feat(keys): paste-your-key field — snippets carry the real key instantly
Next to the copy button: a key input and an «Insert key» button (Enter works too). The pasted key substitutes into every harness/SDK snippet immediately and survives tab and OS switches; a freshly created key pre-fills the field. No more copying a snippet and then hand-editing the placeholder. 2 strings ×7 languages.
This commit is contained in:
Vendored
+2
@@ -644,4 +644,6 @@ export default {
|
|||||||
"keys.budgetOf": "Budget {b}/Mon.",
|
"keys.budgetOf": "Budget {b}/Mon.",
|
||||||
"dash.kpi.orBalance": "OpenRouter-Guthaben",
|
"dash.kpi.orBalance": "OpenRouter-Guthaben",
|
||||||
"keys.h.install": "Installieren:",
|
"keys.h.install": "Installieren:",
|
||||||
|
"keys.snip.keyInputPh": "API-Schlüssel einfügen",
|
||||||
|
"keys.snip.apply": "Schlüssel einsetzen",
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+2
@@ -637,4 +637,6 @@ export default {
|
|||||||
"keys.budgetOf": "budget {b}/mo",
|
"keys.budgetOf": "budget {b}/mo",
|
||||||
"dash.kpi.orBalance": "OpenRouter balance",
|
"dash.kpi.orBalance": "OpenRouter balance",
|
||||||
"keys.h.install": "Install:",
|
"keys.h.install": "Install:",
|
||||||
|
"keys.snip.keyInputPh": "paste your API key",
|
||||||
|
"keys.snip.apply": "Insert key",
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+2
@@ -644,4 +644,6 @@ export default {
|
|||||||
"keys.budgetOf": "presupuesto {b}/mes",
|
"keys.budgetOf": "presupuesto {b}/mes",
|
||||||
"dash.kpi.orBalance": "Saldo OpenRouter",
|
"dash.kpi.orBalance": "Saldo OpenRouter",
|
||||||
"keys.h.install": "Instalar:",
|
"keys.h.install": "Instalar:",
|
||||||
|
"keys.snip.keyInputPh": "pega tu clave API",
|
||||||
|
"keys.snip.apply": "Insertar clave",
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+2
@@ -644,4 +644,6 @@ export default {
|
|||||||
"keys.budgetOf": "budget {b}/mois",
|
"keys.budgetOf": "budget {b}/mois",
|
||||||
"dash.kpi.orBalance": "Solde OpenRouter",
|
"dash.kpi.orBalance": "Solde OpenRouter",
|
||||||
"keys.h.install": "Installer :",
|
"keys.h.install": "Installer :",
|
||||||
|
"keys.snip.keyInputPh": "collez votre clé API",
|
||||||
|
"keys.snip.apply": "Insérer la clé",
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+2
@@ -636,4 +636,6 @@ export default {
|
|||||||
"keys.budgetOf": "бюджет {b}/мес",
|
"keys.budgetOf": "бюджет {b}/мес",
|
||||||
"dash.kpi.orBalance": "Баланс OpenRouter",
|
"dash.kpi.orBalance": "Баланс OpenRouter",
|
||||||
"keys.h.install": "Установить:",
|
"keys.h.install": "Установить:",
|
||||||
|
"keys.snip.keyInputPh": "вставьте ваш API-ключ",
|
||||||
|
"keys.snip.apply": "Вставить ключ",
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+2
@@ -644,4 +644,6 @@ export default {
|
|||||||
"keys.budgetOf": "bütçe {b}/ay",
|
"keys.budgetOf": "bütçe {b}/ay",
|
||||||
"dash.kpi.orBalance": "OpenRouter bakiyesi",
|
"dash.kpi.orBalance": "OpenRouter bakiyesi",
|
||||||
"keys.h.install": "Kurulum:",
|
"keys.h.install": "Kurulum:",
|
||||||
|
"keys.snip.keyInputPh": "API anahtarınızı yapıştırın",
|
||||||
|
"keys.snip.apply": "Anahtarı ekle",
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+2
@@ -644,4 +644,6 @@ export default {
|
|||||||
"keys.budgetOf": "预算 {b}/月",
|
"keys.budgetOf": "预算 {b}/月",
|
||||||
"dash.kpi.orBalance": "OpenRouter 余额",
|
"dash.kpi.orBalance": "OpenRouter 余额",
|
||||||
"keys.h.install": "安装:",
|
"keys.h.install": "安装:",
|
||||||
|
"keys.snip.keyInputPh": "粘贴你的 API 密钥",
|
||||||
|
"keys.snip.apply": "插入密钥",
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+22
-8
@@ -54,7 +54,7 @@ export async function renderKeys() {
|
|||||||
function snippetsCard(openMode) {
|
function snippetsCard(openMode) {
|
||||||
const origin = location.origin;
|
const origin = location.origin;
|
||||||
const base = origin + "/v1";
|
const base = origin + "/v1";
|
||||||
const key = lastCreatedKey || (openMode ? "sk-anything" : "<" + t("keys.snip.keyPh") + ">");
|
let key = lastCreatedKey || (openMode ? "sk-anything" : "<" + t("keys.snip.keyPh") + ">");
|
||||||
// Every scripty snippet exists in two OS flavors: bash heredocs for
|
// Every scripty snippet exists in two OS flavors: bash heredocs for
|
||||||
// Linux/macOS and PowerShell here-strings for Windows. SDK snippets
|
// Linux/macOS and PowerShell here-strings for Windows. SDK snippets
|
||||||
// (python/js) and GUI instructions are OS-independent.
|
// (python/js) and GUI instructions are OS-independent.
|
||||||
@@ -195,11 +195,15 @@ const resp = await client.chat.completions.create({
|
|||||||
});
|
});
|
||||||
console.log(resp.choices[0].message.content);`,
|
console.log(resp.choices[0].message.content);`,
|
||||||
};
|
};
|
||||||
const shSnips = buildSnips("sh");
|
let shSnips, psSnips, snips;
|
||||||
const psSnips = buildSnips("ps");
|
function rebuildSnips() {
|
||||||
// python/js/Cline одинаковы — дополняем ps-набор из sh
|
shSnips = buildSnips("sh");
|
||||||
for (const k of Object.keys(shSnips)) if (!psSnips[k]) psSnips[k] = shSnips[k];
|
psSnips = buildSnips("ps");
|
||||||
let snips = os === "ps" ? psSnips : shSnips;
|
// python/js/Cline одинаковы — дополняем ps-набор из sh
|
||||||
|
for (const k of Object.keys(shSnips)) if (!psSnips[k]) psSnips[k] = shSnips[k];
|
||||||
|
snips = os === "ps" ? psSnips : shSnips;
|
||||||
|
}
|
||||||
|
rebuildSnips();
|
||||||
let cur = "Claude Code";
|
let cur = "Claude Code";
|
||||||
const pre = h("pre", { class: "conv-log snippet" }, snips[cur]);
|
const pre = h("pre", { class: "conv-log snippet" }, snips[cur]);
|
||||||
const seg = h(
|
const seg = h(
|
||||||
@@ -289,12 +293,22 @@ console.log(resp.choices[0].message.content);`,
|
|||||||
osSeg.querySelectorAll("button").forEach((b, i) =>
|
osSeg.querySelectorAll("button").forEach((b, i) =>
|
||||||
b.addEventListener("click", () => {
|
b.addEventListener("click", () => {
|
||||||
os = i === 0 ? "sh" : "ps";
|
os = i === 0 ? "sh" : "ps";
|
||||||
snips = os === "ps" ? psSnips : shSnips;
|
rebuildSnips();
|
||||||
osSeg.querySelectorAll("button").forEach((x, j) => x.classList.toggle("active", j === (os === "sh" ? 0 : 1)));
|
osSeg.querySelectorAll("button").forEach((x, j) => x.classList.toggle("active", j === (os === "sh" ? 0 : 1)));
|
||||||
pre.textContent = snips[cur];
|
pre.textContent = snips[cur];
|
||||||
paintStatus();
|
paintStatus();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// paste-your-key: substitutes the key into every snippet immediately
|
||||||
|
const keyIn = h("input", { class: "mono", placeholder: t("keys.snip.keyInputPh"), style: "max-width:230px; font-size:12px", value: lastCreatedKey || "" });
|
||||||
|
const applyKey = () => {
|
||||||
|
key = keyIn.value.trim() || (openMode ? "sk-anything" : "<" + t("keys.snip.keyPh") + ">");
|
||||||
|
rebuildSnips();
|
||||||
|
pre.textContent = snips[cur];
|
||||||
|
};
|
||||||
|
const applyBtn = h("button", { class: "btn ghost sm", onClick: applyKey }, "⤵ " + t("keys.snip.apply"));
|
||||||
|
keyIn.addEventListener("keydown", (e) => { if (e.key === "Enter") applyKey(); });
|
||||||
|
|
||||||
const copy = h("button", { class: "btn ghost sm" }, "⧉ " + t("common.copy"));
|
const copy = h("button", { class: "btn ghost sm" }, "⧉ " + t("common.copy"));
|
||||||
copy.addEventListener("click", async () => {
|
copy.addEventListener("click", async () => {
|
||||||
await navigator.clipboard.writeText(pre.textContent);
|
await navigator.clipboard.writeText(pre.textContent);
|
||||||
@@ -306,7 +320,7 @@ console.log(resp.choices[0].message.content);`,
|
|||||||
h("div", { class: "card-title" }, "🔌 " + t("keys.snip.title")),
|
h("div", { class: "card-title" }, "🔌 " + t("keys.snip.title")),
|
||||||
h("div", { class: "muted small", style: "margin-bottom:8px" },
|
h("div", { class: "muted small", style: "margin-bottom:8px" },
|
||||||
lastCreatedKey ? t("keys.snip.withKey") : openMode ? t("keys.snip.openMode") : t("keys.snip.hint")),
|
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" }), osSeg, copy),
|
h("div", { class: "flex", style: "gap:8px; margin-bottom:8px; flex-wrap:wrap" }, seg, h("div", { class: "grow" }), keyIn, applyBtn, osSeg, copy),
|
||||||
pre,
|
pre,
|
||||||
statusHost,
|
statusHost,
|
||||||
protoWarn,
|
protoWarn,
|
||||||
|
|||||||
Reference in New Issue
Block a user