fix(keys): snippets survive being pasted into real zsh
The copyable text opened with a "# hint" line — but default interactive zsh has interactivecomments off, so the line was parsed as a command, and the "!" inside «(перезапишет!)» fired history expansion: pasting the OpenCode snippet died with "zsh: event not found: )" before doing anything. Hints now live in the UI above the snippet; the clipboard gets commands only. Verified by piping the actual rendered snippet through an interactive zsh: the config file lands intact.
This commit is contained in:
Vendored
+22
-16
@@ -62,14 +62,12 @@ export async function renderKeys() {
|
||||
// Harness auto-setup scripts first (the gateway speaks OpenAI at /v1/* and
|
||||
// Anthropic at /v1/messages, so Claude Code connects natively), SDKs after.
|
||||
const buildSnips = (osKind) => osKind === "ps" ? {
|
||||
"Claude Code": `# ${t("keys.h.claude")}
|
||||
$env:ANTHROPIC_BASE_URL = "${origin}"
|
||||
"Claude Code": `$env:ANTHROPIC_BASE_URL = "${origin}"
|
||||
$env:ANTHROPIC_AUTH_TOKEN = "${key}"
|
||||
$env:ANTHROPIC_MODEL = "cortiq-auto"
|
||||
|
||||
claude`,
|
||||
Codex: `# ${t("keys.h.codex")}
|
||||
New-Item -ItemType Directory -Force "$HOME\\.codex" | Out-Null
|
||||
Codex: `New-Item -ItemType Directory -Force "$HOME\\.codex" | Out-Null
|
||||
Add-Content "$HOME\\.codex\\config.toml" @'
|
||||
model = "cortiq-auto"
|
||||
model_provider = "cortiq"
|
||||
@@ -83,8 +81,7 @@ wire_api = "chat"
|
||||
$env:CORTIQ_API_KEY = "${key}"
|
||||
|
||||
codex`,
|
||||
OpenCode: `# ${t("keys.h.opencode")}
|
||||
New-Item -ItemType Directory -Force "$HOME\\.config\\opencode" | Out-Null
|
||||
OpenCode: `New-Item -ItemType Directory -Force "$HOME\\.config\\opencode" | Out-Null
|
||||
Set-Content "$HOME\\.config\\opencode\\opencode.json" @'
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
@@ -100,8 +97,7 @@ Set-Content "$HOME\\.config\\opencode\\opencode.json" @'
|
||||
'@
|
||||
|
||||
opencode`,
|
||||
Continue: `# ${t("keys.h.continue")}
|
||||
New-Item -ItemType Directory -Force "$HOME\\.continue" | Out-Null
|
||||
Continue: `New-Item -ItemType Directory -Force "$HOME\\.continue" | Out-Null
|
||||
Add-Content "$HOME\\.continue\\config.yaml" @'
|
||||
models:
|
||||
- name: Cortiq Auto
|
||||
@@ -122,14 +118,12 @@ ${t("keys.h.cline2")}`,
|
||||
-H "Content-Type: application/json" \`
|
||||
-d '{"model":"cortiq-auto","messages":[{"role":"user","content":"Привет!"}]}'`,
|
||||
} : {
|
||||
"Claude Code": `# ${t("keys.h.claude")}
|
||||
export ANTHROPIC_BASE_URL="${origin}"
|
||||
"Claude Code": `export ANTHROPIC_BASE_URL="${origin}"
|
||||
export ANTHROPIC_AUTH_TOKEN="${key}"
|
||||
export ANTHROPIC_MODEL="cortiq-auto"
|
||||
|
||||
claude`,
|
||||
Codex: `# ${t("keys.h.codex")}
|
||||
mkdir -p ~/.codex && cat >> ~/.codex/config.toml <<'EOF'
|
||||
Codex: `mkdir -p ~/.codex && cat >> ~/.codex/config.toml <<'EOF'
|
||||
model = "cortiq-auto"
|
||||
model_provider = "cortiq"
|
||||
|
||||
@@ -142,8 +136,7 @@ EOF
|
||||
export CORTIQ_API_KEY="${key}"
|
||||
|
||||
codex`,
|
||||
OpenCode: `# ${t("keys.h.opencode")}
|
||||
mkdir -p ~/.config/opencode && cat > ~/.config/opencode/opencode.json <<'EOF'
|
||||
OpenCode: `mkdir -p ~/.config/opencode && cat > ~/.config/opencode/opencode.json <<'EOF'
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"provider": {
|
||||
@@ -158,8 +151,7 @@ mkdir -p ~/.config/opencode && cat > ~/.config/opencode/opencode.json <<'EOF'
|
||||
EOF
|
||||
|
||||
opencode`,
|
||||
Continue: `# ${t("keys.h.continue")}
|
||||
mkdir -p ~/.continue && cat >> ~/.continue/config.yaml <<'EOF'
|
||||
Continue: `mkdir -p ~/.continue && cat >> ~/.continue/config.yaml <<'EOF'
|
||||
models:
|
||||
- name: Cortiq Auto
|
||||
provider: openai
|
||||
@@ -205,7 +197,19 @@ console.log(resp.choices[0].message.content);`,
|
||||
}
|
||||
rebuildSnips();
|
||||
let cur = "Claude Code";
|
||||
// per-harness hint lives OUTSIDE the copyable text: a leading "# comment"
|
||||
// in a pasted snippet is not a comment in default interactive zsh, and a
|
||||
// "!" inside it triggers history expansion ("event not found")
|
||||
const HINTS = {
|
||||
"Claude Code": () => t("keys.h.claude"),
|
||||
Codex: () => t("keys.h.codex"),
|
||||
OpenCode: () => t("keys.h.opencode"),
|
||||
Continue: () => t("keys.h.continue"),
|
||||
};
|
||||
const hintHost = h("div", { class: "muted small", style: "margin-bottom:6px" });
|
||||
const paintHint = () => { hintHost.textContent = HINTS[cur] ? HINTS[cur]() : ""; };
|
||||
const pre = h("pre", { class: "conv-log snippet" }, snips[cur]);
|
||||
paintHint();
|
||||
const seg = h(
|
||||
"div",
|
||||
{ class: "seg" },
|
||||
@@ -213,6 +217,7 @@ console.log(resp.choices[0].message.content);`,
|
||||
h("button", { class: (i === 0 ? "active" : "") + (["curl", "python", "javascript"].includes(k) ? " sdk" : ""), "data-snip": k, onClick: (e) => {
|
||||
cur = k;
|
||||
pre.textContent = snips[k];
|
||||
paintHint();
|
||||
protoWarn.style.display = k === "Claude Code" && protoWarn.childNodes.length ? "" : "none";
|
||||
paintStatus();
|
||||
seg.querySelectorAll("button").forEach((b) => b.classList.remove("active"));
|
||||
@@ -321,6 +326,7 @@ console.log(resp.choices[0].message.content);`,
|
||||
h("div", { class: "muted small", style: "margin-bottom:8px" },
|
||||
lastCreatedKey ? t("keys.snip.withKey") : openMode ? t("keys.snip.openMode") : t("keys.snip.hint")),
|
||||
h("div", { class: "flex", style: "gap:8px; margin-bottom:8px; flex-wrap:wrap" }, seg, h("div", { class: "grow" }), keyIn, applyBtn, osSeg, copy),
|
||||
hintHost,
|
||||
pre,
|
||||
statusHost,
|
||||
protoWarn,
|
||||
|
||||
Reference in New Issue
Block a user