@crazyhappyone/dsh-tui 0.1.0-alpha.10 → 0.1.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +71 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -76135,7 +76135,7 @@ function SettingsPane({
76135
76135
  visible.map((row, index2) => {
76136
76136
  const absolute = start + index2;
76137
76137
  const selected = absolute === selectedIndex;
76138
- const localized = row.namespace === "tui" && (row.field === "reasoning" || row.field === "scrollbar" || row.field === "statusDetails" || row.field === "locale") ? `${row.field} \xB7 ${tuiCopy(row.field, locale)}` : row.field;
76138
+ const localized = row.namespace === "tui" && (row.field === "reasoning" || row.field === "scrollbar" || row.field === "statusDetails" || row.field === "locale") ? `${row.field} \xB7 ${tuiCopy(row.field, locale)}` : row.field === "apiKeyEnv" ? `${row.field} \xB7 \u73AF\u5883\u53D8\u91CF\u540D` : row.field;
76139
76139
  const label = `${row.namespace} \xB7 ${localized}`;
76140
76140
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Box_default, { width: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Text, { children: paintRow(fieldRow(label, row.value, selected, width)) }) }, `${row.namespace}:${row.field}`);
76141
76141
  }),
@@ -79521,6 +79521,27 @@ function projectAssistantBlocks(blocks) {
79521
79521
  function contentText(content3, kind) {
79522
79522
  return content3.filter((item) => item.kind === kind).map((item) => item.text).join("");
79523
79523
  }
79524
+ function formatTurnError(error51) {
79525
+ const rawMessage = error51.message || "\u672A\u77E5\u9519\u8BEF";
79526
+ const code2 = error51.code;
79527
+ const status = error51.status;
79528
+ if (rawMessage.includes("sk-") && (rawMessage.includes("apiKeyEnv") || rawMessage.includes("store sk-") || rawMessage.includes("export sk-"))) {
79529
+ return "\u26A0\uFE0F **\u914D\u7F6E\u9519\u8BEF**\uFF1A\u68C0\u6D4B\u5230 `apiKeyEnv` \u4E2D\u8BEF\u586B\u4E86\u660E\u6587\u5BC6\u94A5\u3002`apiKeyEnv` \u5FC5\u987B\u662F\u73AF\u5883\u53D8\u91CF\u540D\u79F0\uFF08\u5982 `DEEPSEEK_API_KEY`\uFF09\u3002\u8BF7\u5728 `/settings` \u4E2D\u66F4\u6B63\u6216\u68C0\u67E5 `~/.dsh/settings.yaml`\uFF0C\u5E76\u4F7F\u7528 `/key` \u547D\u4EE4\u914D\u7F6E\u5BC6\u94A5\u3002";
79530
+ }
79531
+ if (code2 === "MISSING_CREDENTIAL" || rawMessage.includes("DEEPSEEK_API_KEY") || rawMessage.includes("MISSING_CREDENTIAL") || rawMessage.includes("no API key")) {
79532
+ return '\u26A0\uFE0F **API \u5BC6\u94A5\u7F3A\u5931**\uFF1A\u672A\u68C0\u6D4B\u5230\u6709\u6548\u5BC6\u94A5\u3002\u8BF7\u5728\u7EC8\u7AEF\u6267\u884C `export DEEPSEEK_API_KEY="sk-..."` \u6216\u8F93\u5165 `/key` \u547D\u4EE4\u8FDB\u884C\u914D\u7F6E\u3002';
79533
+ }
79534
+ if (status === 401 || code2 === "AUTH" || rawMessage.includes("401") || rawMessage.toLowerCase().includes("authentication fails") || rawMessage.toLowerCase().includes("invalid api key") || rawMessage.toLowerCase().includes("unauthorized")) {
79535
+ return `\u26A0\uFE0F **API \u8BA4\u8BC1\u5931\u8D25\uFF08HTTP 401\uFF09**\uFF1AAPI Key \u65E0\u6548\u6216\u672A\u6388\u6743\uFF08${rawMessage}\uFF09\u3002\u8BF7\u68C0\u67E5\u5BC6\u94A5\u662F\u5426\u6B63\u786E\uFF0C\u6216\u4F7F\u7528 \`/key\` \u91CD\u65B0\u914D\u7F6E\u3002`;
79536
+ }
79537
+ if (status === 429 || code2 === "RATE_LIMIT" || rawMessage.includes("429") || rawMessage.toLowerCase().includes("quota") || rawMessage.toLowerCase().includes("rate limit")) {
79538
+ return `\u26A0\uFE0F **\u8BF7\u6C42\u53D7\u9650\uFF08HTTP 429\uFF09**\uFF1A\u8BF7\u6C42\u9891\u7387\u8D85\u9650\u6216\u8D26\u6237\u4F59\u989D\u4E0D\u8DB3\uFF08${rawMessage}\uFF09\u3002\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u68C0\u67E5\u8D26\u6237\u989D\u5EA6\u3002`;
79539
+ }
79540
+ if (rawMessage.includes("ECONNREFUSED") || rawMessage.includes("ETIMEDOUT") || rawMessage.includes("ENOTFOUND") || rawMessage.includes("fetch failed")) {
79541
+ return `\u26A0\uFE0F **\u7F51\u7EDC\u8FDE\u63A5\u5931\u8D25**\uFF1A\u65E0\u6CD5\u8FDE\u63A5\u5230\u6A21\u578B\u670D\u52A1\uFF08${rawMessage}\uFF09\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u6216\u4EE3\u7406\u914D\u7F6E\u3002`;
79542
+ }
79543
+ return `\u26A0\uFE0F **\u6A21\u578B\u8BF7\u6C42\u5931\u8D25**\uFF1A${rawMessage}`;
79544
+ }
79524
79545
  function createProjector() {
79525
79546
  const history = [];
79526
79547
  const compactionDividers = [];
@@ -79723,8 +79744,7 @@ function createProjector() {
79723
79744
  let text4 = activeTurn.assistantText;
79724
79745
  const content3 = activeTurn.content.map((item) => ({ ...item }));
79725
79746
  if (reason.kind === "error") {
79726
- const rawMessage = reason.error.message || "\u672A\u77E5\u9519\u8BEF";
79727
- const formattedError = rawMessage.includes("DEEPSEEK_API_KEY") || reason.error.code === "MISSING_CREDENTIAL" ? '\u26A0\uFE0F **API \u5BC6\u94A5\u7F3A\u5931**\uFF1A\u672A\u68C0\u6D4B\u5230 `DEEPSEEK_API_KEY`\u3002\u8BF7\u5728\u7EC8\u7AEF\u6267\u884C `export DEEPSEEK_API_KEY="sk-..."` \u6216\u5728 `~/.dsh/.credentials.yaml` \u4E2D\u914D\u7F6E\u5BC6\u94A5\u3002' : `\u26A0\uFE0F **\u6A21\u578B\u8BF7\u6C42\u5931\u8D25**\uFF1A${rawMessage}`;
79747
+ const formattedError = formatTurnError(reason.error);
79728
79748
  if (text4.trim() === "") {
79729
79749
  text4 = formattedError;
79730
79750
  content3.push({ kind: "text", text: formattedError });
@@ -80096,6 +80116,16 @@ function parseSettingsFieldValue(namespace, field, current, draft) {
80096
80116
  if (draft === "auto" || draft === "on" || draft === "off") return draft;
80097
80117
  throw new TypeError("\u9700\u8981 \u81EA\u52A8\u3001\u5F00\u542F \u6216 \u5173\u95ED");
80098
80118
  }
80119
+ if (field === "apiKeyEnv" || field === "secretEnv" || field.endsWith("Env") || field.endsWith("Ref")) {
80120
+ const trimmed = draft.trim();
80121
+ if (trimmed.startsWith("sk-") || trimmed.startsWith("ghp_") || trimmed.startsWith("Bearer ") || trimmed.length > 50) {
80122
+ throw new TypeError(`${field} \u662F\u73AF\u5883\u53D8\u91CF\u540D\uFF08\u5982 DEEPSEEK_API_KEY\uFF09\uFF0C\u8BF7\u52FF\u8F93\u5165\u771F\u5B9E\u5BC6\u94A5\u3002\u8BF7\u4F7F\u7528 /key \u914D\u7F6E\u5BC6\u94A5`);
80123
+ }
80124
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(trimmed)) {
80125
+ throw new TypeError(`${field} \u9700\u8981\u5408\u6CD5\u7684\u73AF\u5883\u53D8\u91CF\u540D\uFF08\u4F8B\u5982 DEEPSEEK_API_KEY\uFF09`);
80126
+ }
80127
+ return trimmed;
80128
+ }
80099
80129
  return parseSettingValue(current, draft);
80100
80130
  }
80101
80131
  function settingsRowsFromDescribe(descriptors, read) {
@@ -80438,6 +80468,8 @@ var SEARCH_DEBOUNCE_MS = 120;
80438
80468
  var LOCAL_COMMANDS = [
80439
80469
  { name: "export", description: "Export this session to a Markdown file" },
80440
80470
  { name: "help", description: "Show command help and key bindings" },
80471
+ { name: "key", description: "Set or update API key" },
80472
+ { name: "login", description: "Set or update API key" },
80441
80473
  { name: "model", description: "Switch the active model" },
80442
80474
  { name: "reload", description: "Relaunch this process and resume the session" },
80443
80475
  { name: "resume", description: "Switch or resume a session" },
@@ -83438,6 +83470,18 @@ var RuntimeController = class _RuntimeController {
83438
83470
  this.openHelpPane();
83439
83471
  return;
83440
83472
  }
83473
+ if (query === "key" || query === "key " || query === "login" || query === "login ") {
83474
+ if (this.blockingHead() !== void 0) return;
83475
+ this.openApiKeyPane();
83476
+ return;
83477
+ }
83478
+ if (query.startsWith("key ") || query.startsWith("login ")) {
83479
+ const token = query.replace(/^(?:key|login)\s+/, "").trim();
83480
+ if (token.length > 0) {
83481
+ this.applyOnboardingKey(ONBOARDING_KEY, token);
83482
+ return;
83483
+ }
83484
+ }
83441
83485
  if (query === "model") {
83442
83486
  this.openModelPane();
83443
83487
  return;
@@ -83708,6 +83752,13 @@ var RuntimeController = class _RuntimeController {
83708
83752
  try {
83709
83753
  await credentials.set(credentialRef(field), value);
83710
83754
  if (this.closed) return;
83755
+ const settings = this.ctx.get("settings");
83756
+ if (settings !== void 0) {
83757
+ const ds = settings.get("llm-deepseek");
83758
+ if (typeof ds?.apiKeyEnv === "string" && ds.apiKeyEnv.startsWith("sk-")) {
83759
+ await settings.update("llm-deepseek", { apiKeyEnv: "DEEPSEEK_API_KEY" });
83760
+ }
83761
+ }
83711
83762
  this.settingsOnboarding = false;
83712
83763
  this.settingsOpen = false;
83713
83764
  this.settingsEditing = false;
@@ -83776,6 +83827,23 @@ var RuntimeController = class _RuntimeController {
83776
83827
  });
83777
83828
  });
83778
83829
  }
83830
+ /**
83831
+ * Open the API-key configuration overlay directly from /key or /login.
83832
+ */
83833
+ openApiKeyPane() {
83834
+ this.closeOtherPanels();
83835
+ this.settingsOnboarding = true;
83836
+ this.settingsEditing = true;
83837
+ this.settingsUpdateError = void 0;
83838
+ this.settingsRows = [{
83839
+ namespace: "credentials",
83840
+ field: ONBOARDING_KEY,
83841
+ value: ""
83842
+ }];
83843
+ this.settingsSelectedIndex = 0;
83844
+ this.settingsOpen = true;
83845
+ this.emit();
83846
+ }
83779
83847
  /**
83780
83848
  * Open the first-run API-key overlay when idle boot has no configured
83781
83849
  * `DEEPSEEK_API_KEY`. Approval or ask-user already open skips (K2′).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crazyhappyone/dsh-tui",
3
- "version": "0.1.0-alpha.10",
3
+ "version": "0.1.0-alpha.11",
4
4
  "description": "Source-runtime launcher for the DeepSeek Harness terminal interface",
5
5
  "type": "module",
6
6
  "license": "MIT",