dsh-packycode-api 1.2.11 → 1.3.0

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.
package/SECURITY.md CHANGED
@@ -11,16 +11,14 @@
11
11
  ## Network
12
12
 
13
13
  - Balance requests carry a timeout (`AbortSignal.timeout`) and `redirect: 'error'`, and go only to the configured hosts plus the PackyAPI fallback host.
14
- - Model traffic goes to the configured model host through the host's own pi-ai adapter, with the harness attribution headers, exactly like a configured provider route.
14
+ - Model traffic goes to the configured model host through the plugin's pi-ai adapter. Protocol-specific compatibility headers are applied host-side; credentials remain scoped to the selected plugin key.
15
15
 
16
- ## Claude CLI MCP search bridge
16
+ ## Native Claude requests
17
17
 
18
- - Each CLI invocation owns a temporary HTTP MCP server bound exclusively to `127.0.0.1` on a random port. Every method requires an independent cryptographically random capability; Host/Origin validation rejects rebinding and cross-origin browser requests. No CORS access is granted.
19
- - The owner-only temporary MCP config (private directory, file mode 0600 on POSIX) contains only this local capability. The search API keys remain in the host's key ring and are never placed in MCP configuration, argv, schemas, tool results or raw diagnostics. Result/CLI redaction handles escaped keys and secrets split across text deltas.
20
- - The endpoint offers only bounded `web_search`; models cannot supply backend, API host, credentials, session IDs, shell commands or arbitrary fetch requests. Input size, query size, concurrency, search count, output size and an end-to-end timeout are bounded. Run stop and tool cancellation abort the provider.
21
- - Native CLI WebSearch is denied even in full mode. Read-only/edit modes add only the exact MCP search tool to their auto-approval lists. Existing MCP/settings and user/managed deny rules remain effective; `--allowedTools` is not an exclusive whitelist. Hooks, other trusted MCP servers and full-permission commands remain part of the CLI's existing trust boundary.
22
- - The local capability and owner-only files reduce accidental exposure; they do **not** isolate the service from a compromised process or customization running as the same OS user. Do not run the delegated CLI in an untrusted workspace with hostile hooks/MCP configuration.
23
- - Startup cancellation also revokes an already-bound listener while filesystem setup is pending. Completed/failed/abandoned invocations and plugin unload close the server and clean up only their own temporary config directory.
18
+ - Claude uses the plugin's HTTP Messages route. The plugin has no Claude CLI runner, installer, delegation tool or local MCP bridge. Existing standalone Claude Code installations and configuration are untouched.
19
+ - The compatibility headers and session metadata do not load a CLI login or external configuration. Bearer authentication uses only the plugin's selected conversation key; images keep their separate credential record.
20
+ - DSH owns tool execution, permissions, plan mode, attachments and history. Wire tool aliases are restored only for tools offered on that request; unknown aliases are not decoded into host tools. Saved images from older CLI-backed sessions remain readable without executing their old tools.
21
+ - Captured client-policy refusals do not disable keys or switch providers. The specific pre-stream anomalies covered by the native transport may replay the exact bytes and credential once; ordinary policy refusals, HTTP 429 and accepted streams are excluded. Cancellation aborts the replay.
24
22
 
25
23
  ## Reporting
26
24
 
package/lib/client.js CHANGED
@@ -144,29 +144,6 @@ window.__ModuleLoader__.load({
144
144
  composerUnread: "余额读取失败",
145
145
  composerStale: "上次读取于 {time},本次读取失败",
146
146
  quotaReadAt: "更新于 {time}",
147
- cliTitle: "Claude Code CLI",
148
- cliChecking: "正在检测本机的 Claude Code CLI…",
149
- cliInstalled: "已安装",
150
- cliVersion: "版本",
151
- cliPath: "位置",
152
- cliRecheck: "重新检测",
153
- cliMissing: "未检测到 Claude Code CLI",
154
- cliMissingHint: "不安装将无法正常使用 Claude 模型(claude-opus-5-5、claude-sonnet-5-5、claude-haiku-5-5):PackyCode 只把 Claude 模型提供给官方 Claude Code CLI,插件需要调用本机的 CLI 来运行它。其它模型不受影响。",
155
- cliConfiguredMissing: "设置里指定的 CLI 路径不存在:{path}",
156
- cliBroken: "找到了 CLI,但无法运行",
157
- cliInstall: "安装 Claude Code CLI",
158
- cliReinstall: "重新安装",
159
- cliInstalling: "正在安装…(通常需要一两分钟,请勿关闭 DSH)",
160
- cliInstallCommand: "将在本机执行:{command}(需要 Node.js 18 或更高版本)",
161
- cliInstallSucceeded: "安装完成。",
162
- cliInstallFailed: "安装失败",
163
- cliNpmMissing: "没有找到 npm。请先从 https://nodejs.org 安装 Node.js(18 或更高版本),然后再点安装。",
164
- cliPermission: "npm 没有权限写入全局目录。请在终端执行 sudo {command},或把 npm 的全局目录改到用户目录后重试。",
165
- cliPermissionWindows: "npm 没有权限写入全局目录。请以管理员身份打开终端执行 {command},然后点「重新检测」。",
166
- cliNetwork: "下载失败,请检查网络或 npm 镜像设置后重试。",
167
- cliTimeout: "安装超时,请检查网络后重试。",
168
- cliNotFoundAfterInstall: "npm 显示安装完成,但仍找不到 claude 命令。请在终端执行 claude --version 确认,然后点「重新检测」。",
169
- cliWindowsNote: "Windows 上 Claude Code 还需要 Git for Windows(https://git-scm.com/downloads/win)。",
170
147
  versionTitle: "插件版本",
171
148
  versionCurrent: "当前版本",
172
149
  versionLatest: "最新版本",
@@ -202,8 +179,7 @@ window.__ModuleLoader__.load({
202
179
  diagError: "生成诊断信息失败",
203
180
  searchTitle: "网页搜索",
204
181
  searchScope: "DSH 全局设置",
205
- searchIntro: "DSH 的 web_search 和 Claude CLI 的 MCP 搜索可使用这里选择的 DeepSeek/GPT 后端。每次搜索是独立的模型调用,用插件保存的 Key 计费。",
206
- searchCliHint: "Claude CLI 始终通过 MCP 使用这里的搜索后端,原生 WebSearch 已禁用。下面的路由选项只控制 DSH 全局搜索,不影响 CLI。",
182
+ searchIntro: "DSH 的 web_search 可使用这里选择的 DeepSeek/GPT 后端,Claude 与其它模型遵循相同的路由设置。每次搜索是独立的模型调用,用插件保存的 Key 计费。",
207
183
  searchChecking: "正在读取搜索设置…",
208
184
  searchLoadFailed: "搜索设置读取或保存失败",
209
185
  searchModeTitle: "DSH 路由",
@@ -223,7 +199,7 @@ window.__ModuleLoader__.load({
223
199
  searchApplyFailed: "写入搜索补丁失败:{error}",
224
200
  searchForeign: "检测到 {names} 订阅插件:它们接管的模型仍按各自的搜索设置,其余请求才会到达这里的选择。",
225
201
  searchOverridden: "基础搜索现在是 {base},不是 PackyCode:可能还在热加载,或被其他插件的补丁覆盖。",
226
- searchUnavailable: "当前运行环境没有 DSH 网页搜索服务,全局路由暂不生效;Claude CLI 的 MCP 搜索不受影响。",
202
+ searchUnavailable: "当前运行环境没有 DSH 网页搜索服务,搜索路由暂不生效。",
227
203
  searchNotWritable: "当前 profile 不允许写入设置。",
228
204
  searchUnknown: "未知"
229
205
  };
@@ -336,29 +312,6 @@ window.__ModuleLoader__.load({
336
312
  composerUnread: "Balance unavailable",
337
313
  composerStale: "Last read at {time}; this read failed",
338
314
  quotaReadAt: "Updated at {time}",
339
- cliTitle: "Claude Code CLI",
340
- cliChecking: "Checking this device for the Claude Code CLI…",
341
- cliInstalled: "Installed",
342
- cliVersion: "Version",
343
- cliPath: "Location",
344
- cliRecheck: "Check again",
345
- cliMissing: "Claude Code CLI not found",
346
- cliMissingHint: "Without it the Claude models (claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5) cannot work: PackyCode serves Claude models only to the official Claude Code CLI, so the plugin runs the CLI on this device. Other models are unaffected.",
347
- cliConfiguredMissing: "The CLI path set in settings does not exist: {path}",
348
- cliBroken: "The CLI was found but could not run",
349
- cliInstall: "Install Claude Code CLI",
350
- cliReinstall: "Reinstall",
351
- cliInstalling: "Installing… (usually a minute or two; keep DSH open)",
352
- cliInstallCommand: "Runs on this device: {command} (requires Node.js 18 or later)",
353
- cliInstallSucceeded: "Installed.",
354
- cliInstallFailed: "Install failed",
355
- cliNpmMissing: "npm was not found. Install Node.js 18 or later from https://nodejs.org, then click Install again.",
356
- cliPermission: "npm cannot write its global directory. Run sudo {command} in a terminal, or point npm’s global prefix at a folder you own, then retry.",
357
- cliPermissionWindows: "npm cannot write its global directory. Open a terminal as administrator, run {command}, then click Check again.",
358
- cliNetwork: "The download failed. Check your network or npm registry settings and retry.",
359
- cliTimeout: "The install timed out. Check your network and retry.",
360
- cliNotFoundAfterInstall: "npm reported success, but the claude command still cannot be found. Run claude --version in a terminal, then click Check again.",
361
- cliWindowsNote: "On Windows, Claude Code also needs Git for Windows (https://git-scm.com/downloads/win).",
362
315
  versionTitle: "Plugin version",
363
316
  versionCurrent: "Current version",
364
317
  versionLatest: "Latest version",
@@ -394,8 +347,7 @@ window.__ModuleLoader__.load({
394
347
  diagError: "Could not generate diagnostics",
395
348
  searchTitle: "Web search",
396
349
  searchScope: "DSH-wide setting",
397
- searchIntro: "DSH’s web_search and Claude CLI’s MCP search can use the DeepSeek/GPT backend selected here. Each search is a separate model call billed to the plugin-stored keys.",
398
- searchCliHint: "Claude CLI always uses this backend through MCP; native WebSearch is disabled. The routing options below only control DSH-wide search, not CLI search.",
350
+ searchIntro: "DSH’s web_search can use the DeepSeek/GPT backend selected here. Claude follows the same routing settings as other models. Each search is a separate model call billed to the plugin-stored keys.",
399
351
  searchChecking: "Reading the search preference…",
400
352
  searchLoadFailed: "Could not read or save the search preference",
401
353
  searchModeTitle: "DSH routing",
@@ -415,7 +367,7 @@ window.__ModuleLoader__.load({
415
367
  searchApplyFailed: "Could not write the search patch: {error}",
416
368
  searchForeign: "{names} subscription plugin detected: the models it routes keep its own search choice; only the other requests reach the choice made here.",
417
369
  searchOverridden: "The base search is {base}, not PackyCode: the reload may still be running, or another plugin’s patch overrides it.",
418
- searchUnavailable: "This runtime has no DSH web search service; global routing has no effect. Claude CLI’s MCP search is unaffected.",
370
+ searchUnavailable: "This runtime has no DSH web search service; search routing has no effect.",
419
371
  searchNotWritable: "This profile does not allow settings writes.",
420
372
  searchUnknown: "unknown"
421
373
  };
@@ -1936,7 +1888,6 @@ window.__ModuleLoader__.load({
1936
1888
  const REFRESH_MS = 6e4;
1937
1889
  /** PackyCode registration through the author's invite link, offered only until a key is stored. */
1938
1890
  const INVITE_URL = "https://www.packyapi.ai/register?aff=Im3l";
1939
- const INSTALL_POLL_MS = 2e3;
1940
1891
  /** How long after a search change the panel re-reads what DSH applied (the patch hot-reloads). */
1941
1892
  const SEARCH_SETTLE_MS = 1500;
1942
1893
  const OWN_SEARCH_IDS = {
@@ -2521,10 +2472,6 @@ window.__ModuleLoader__.load({
2521
2472
  className: "pkc-note",
2522
2473
  children: t("searchIntro")
2523
2474
  }),
2524
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2525
- className: "pkc-note",
2526
- children: t("searchCliHint")
2527
- }),
2528
2475
  state === void 0 && error === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2529
2476
  className: "pkc-note",
2530
2477
  role: "status",
@@ -2629,157 +2576,6 @@ window.__ModuleLoader__.load({
2629
2576
  ]
2630
2577
  });
2631
2578
  }
2632
- const INSTALL_FAILURES = {
2633
- "npm-missing": () => "cliNpmMissing",
2634
- permission: (cli) => cli.platform === "win32" ? "cliPermissionWindows" : "cliPermission",
2635
- network: () => "cliNetwork",
2636
- timeout: () => "cliTimeout",
2637
- "not-found-after-install": () => "cliNotFoundAfterInstall"
2638
- };
2639
- /** The sentence explaining a failed install, by the code the host classified. */
2640
- function installFailure(cli, t) {
2641
- const key = INSTALL_FAILURES[cli.install?.code]?.(cli);
2642
- return key === void 0 ? void 0 : fill(t(key), { command: cli.command ?? "" });
2643
- }
2644
- /**
2645
- * Whether this device has the Claude Code CLI, which version, and — when it
2646
- * has none — a button that installs it with npm.
2647
- */
2648
- function ClaudeCliCard({ call, t }) {
2649
- const [cli, setCli] = react.useState();
2650
- const [checking, setChecking] = react.useState(false);
2651
- const [error, setError] = react.useState();
2652
- const check = react.useCallback((force = false) => {
2653
- setChecking(true);
2654
- setError(void 0);
2655
- return call("claude-cli/status", { force }).then(setCli).catch((failure) => setError(clearMessage(failure))).finally(() => setChecking(false));
2656
- }, [call]);
2657
- react.useEffect(() => {
2658
- check(false);
2659
- }, [check]);
2660
- const running = cli?.install?.state === "running";
2661
- react.useEffect(() => {
2662
- if (!running) return void 0;
2663
- let live = true;
2664
- const timer = window.setInterval(() => {
2665
- call("claude-cli/status").then((value) => {
2666
- if (live) setCli(value);
2667
- }).catch(() => void 0);
2668
- }, INSTALL_POLL_MS);
2669
- return () => {
2670
- live = false;
2671
- window.clearInterval(timer);
2672
- };
2673
- }, [call, running]);
2674
- const install = () => {
2675
- setError(void 0);
2676
- call("claude-cli/install").then(setCli).catch((failure) => setError(clearMessage(failure)));
2677
- };
2678
- const usable = cli?.installed === true && cli.version !== void 0;
2679
- const failed = cli?.install?.state === "failed";
2680
- const failure = cli === void 0 ? void 0 : installFailure(cli, t);
2681
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Card, {
2682
- title: t("cliTitle"),
2683
- aside: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
2684
- disabled: checking || running,
2685
- onClick: () => check(true),
2686
- children: checking ? t("refreshing") : t("cliRecheck")
2687
- }),
2688
- children: [
2689
- cli === void 0 && error === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2690
- className: "pkc-note",
2691
- children: t("cliChecking")
2692
- }),
2693
- usable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
2694
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2695
- className: "pkc-status",
2696
- children: [
2697
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2698
- className: "pkc-dot",
2699
- "data-tone": "success"
2700
- }),
2701
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("cliInstalled") }),
2702
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: `${t("cliVersion")} ${cli.version}` })
2703
- ]
2704
- }),
2705
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2706
- className: "pkc-meta",
2707
- children: [
2708
- t("cliPath"),
2709
- " ",
2710
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2711
- className: "pkc-mono",
2712
- children: cli.path
2713
- })
2714
- ]
2715
- }),
2716
- cli.install?.state === "succeeded" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2717
- className: "pkc-note",
2718
- children: t("cliInstallSucceeded")
2719
- })
2720
- ] }),
2721
- cli !== void 0 && !usable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2722
- className: "pkc-callout",
2723
- children: [
2724
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2725
- className: "pkc-status",
2726
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2727
- className: "pkc-dot",
2728
- "data-tone": cli.installed ? "danger" : "warn"
2729
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: cli.installed ? t("cliBroken") : t("cliMissing") })]
2730
- }),
2731
- cli.installed && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2732
- className: "pkc-meta",
2733
- children: [
2734
- t("cliPath"),
2735
- " ",
2736
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2737
- className: "pkc-mono",
2738
- children: cli.path
2739
- })
2740
- ]
2741
- }), cli.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
2742
- className: "pkc-detail",
2743
- children: cli.error
2744
- })] }),
2745
- cli.configuredPath !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2746
- className: "pkc-note",
2747
- children: fill(t("cliConfiguredMissing"), { path: cli.configuredPath })
2748
- }),
2749
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2750
- className: "pkc-note",
2751
- children: t("cliMissingHint")
2752
- }),
2753
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2754
- className: "pkc-split",
2755
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
2756
- variant: "primary",
2757
- size: "md",
2758
- disabled: running || checking,
2759
- onClick: install,
2760
- children: running ? t("cliInstalling") : cli.installed ? t("cliReinstall") : t("cliInstall")
2761
- })
2762
- }),
2763
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
2764
- className: "pkc-note",
2765
- children: [fill(t("cliInstallCommand"), { command: cli.command ?? "" }), cli.platform === "win32" && ` ${t("cliWindowsNote")}`]
2766
- })
2767
- ]
2768
- }),
2769
- failed && !usable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2770
- className: "pkc-error",
2771
- children: failure === void 0 ? t("cliInstallFailed") : `${t("cliInstallFailed")} · ${failure}`
2772
- }), cli.install.detail !== void 0 && cli.install.detail !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
2773
- className: "pkc-detail",
2774
- children: cli.install.detail
2775
- })] }),
2776
- error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2777
- className: "pkc-error",
2778
- children: `${t("error")}: ${error}`
2779
- })
2780
- ]
2781
- });
2782
- }
2783
2579
  function VersionCard({ call, t }) {
2784
2580
  const [info, setInfo] = react.useState();
2785
2581
  const [loading, setLoading] = react.useState(true);
@@ -2938,10 +2734,6 @@ window.__ModuleLoader__.load({
2938
2734
  call,
2939
2735
  t
2940
2736
  }),
2941
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClaudeCliCard, {
2942
- call,
2943
- t
2944
- }),
2945
2737
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionCard, {
2946
2738
  call,
2947
2739
  t