dsh-packycode-api 1.2.0 → 1.2.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.1
4
+
5
+ - **Generated image visible only inside tool details.** DSH 0.2 treats custom Turn/Step nodes as foldable process content, so the chat gallery disappeared when completed work was collapsed. PTC also logs successful child images as `tool/ptc-dispatch` without root presentation metadata, which the gallery previously ignored. The gallery now recognizes this plugin's successful native/PTC/CLI results and renders a Session-level card anchored beside its owning answer, independent of process folding. Stored conversations replay the same image references; no log rewrite or paid regeneration is needed. Duplicate results for the same call are projected once. Tool instructions also tell models to use automatic image presentation instead of inventing Markdown image links to host paths or attachment IDs.
6
+ - Added regressions using DSH's real 0.1.5/0.2.0 conversation assemblers, the 0.2.0 chat grouping policy, native PTC ToolRuntime output and the built browser gallery/preview/viewer. The minimal reproduction showed a valid image in tool details with no main-chat card, plus an existing native gallery incorrectly classified as a collapsed process group; both now remain standalone visible image cards.
7
+ - **Claude CLI image generation and editing.** CLI-backed Claude model turns and `claude_code` delegation can call a temporary MCP image tool backed by the existing host Images API service. Saved image model/quality, all three image engines, separate image credentials, original PNG storage and image-balance invalidation are shared with the native DSH tool. Only session-scoped image handles cross the input seam; neither keys nor arbitrary file/URL references are accepted. Generated images can be edited again within the same invocation.
8
+ - The CLI's exact per-run image tool is allowed alongside search without widening shell permissions or changing user MCP configuration. Plan mode and titles expose no image tool. Requests are cancellable, bounded to five minutes and four attempts per invocation, with one active image request. Native MCP previews stay below 1 MiB and never duplicate base64 in textual results or DSH events.
9
+ - Successful images are emitted as real assistant image blocks (or delegation tool image results), persisted by DSH, and projected into the chat gallery on replay. A later CLI failure preserves completed images and reports the failure instead of silently repeating paid work. The Create image button remains visible for Claude conversations.
10
+ - Added service, transport, credential-isolation, composition, message assembly and replay regressions, plus `scripts/cli-image-check.mjs`. Its default checks run the real official CLI with local model/image fixtures across read-only/edit/full/plan/title modes; `--live` makes one real low-quality generation and one reference edit with the stored image key while Claude replies remain local fixtures.
11
+ - Delegation output now declares the runner's token accounting fields, so DSH's actual output validator accepts both text and image results. PTC image forwarding uses the host's existing mechanism once, avoiding duplicate image contexts.
12
+ - Validation, 2026-10-15: 377 offline tests, both bundles and the 1.2.1 tarball, including the built browser gallery and real DSH 0.1.5/0.2.0 replay/grouping regressions. Official CLI 2.1.295 passed image MCP fixtures in all five modes and existing search checks. A real `claude-haiku-5-5` upstream turn generated a blue teapot using Sunburst `low`, edited the generated reference to orange, and persisted both 1024×1024 images through DSH's message assembler in 33.078s; visual review confirmed preserved composition/background. A separate real-image/local-Claude check passed in 24.887s. Native and PTC ToolRuntime output validation/replay passed. The general gateway check passed five HTTP models; Astra first hit the script's 90-second deadline, then its focused repeat passed. No running desktop conversation was created or restarted for this verification; a physical Intel Mac retest is still needed.
13
+
3
14
  ## 1.2.0
4
15
 
5
16
  - **New-image argument compatibility.** A desktop model repeatedly sent `referenceImages: []` with an unused, zero-valued mask reference for a new image. Treating field presence as an edit produced `PackyCode image edits require 1-16 reference images` before reaching the gateway. Empty arrays now mean no references, and only an entirely zero-valued empty/all-zero-ID mask placeholder is treated as absent. Nonempty reference/mask errors still fail; explicit `operation: edit` always requires references and explicit generation rejects real references. `model` and `quality` also accept `settings` to follow saved preferences rather than filling arbitrary defaults. Added tool-execution regressions from the actual desktop argument shape; a replay through the built tool with a public test prompt, a real image key and a local attachment adapter made exactly one generation request and returned a PNG in 12.267s.
package/README.en.md CHANGED
@@ -51,7 +51,7 @@ Open the desktop application's **Plugins** page, click **Add plugin**, and enter
51
51
  dsh-packycode-api
52
52
  ```
53
53
 
54
- Choose the **official** install source, then click **Install**. To pin a version, enter `dsh-packycode-api@1.2.0`.
54
+ Choose the **official** install source, then click **Install**. To pin a version, enter `dsh-packycode-api@1.2.1`.
55
55
 
56
56
  A **first install requires no DSH restart**: open **Settings → PackyCode** and add a key immediately. When updating an already loaded older version, follow the restart guidance in the **Plugin version** card.
57
57
 
@@ -70,7 +70,7 @@ Choose a model from the `PackyCode` group. `deepseek-flash`, `gpt-6.1-sol`, `gpt
70
70
 
71
71
  The **Plugins** page shows the installed state and version, and is also where you enable, disable, or uninstall.
72
72
 
73
- **For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.2.0`. Do not use it for `desktop` — the CLI refuses it (`profile "desktop" is managed exclusively by the Electron application`).
73
+ **For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.2.1`. Do not use it for `desktop` — the CLI refuses it (`profile "desktop" is managed exclusively by the Electron application`).
74
74
 
75
75
  For a local checkout, keep the `link:` prefix: `dsh plugin --profile <name> add link:/path/to/dsh-packycode-api`. **Do not pass a bare path or `file:`** — that install copies the whole checkout, `node_modules` included, into the profile, where it then shadows the packages the DSH installation itself provides and the plugin looks uninstalled; see the FAQ. If you already installed that way, uninstall first and reinstall as above.
76
76
 
@@ -146,7 +146,11 @@ Add the dedicated key under **Settings → PackyCode → Image generation and ed
146
146
 
147
147
  The image card shows each image key's remaining/used quota, limits when supplied, reset period, usage bar and separate totals. It refreshes every minute or with **Refresh**, preserving a dated last-good reading when a refresh fails. Image key changes and successful generation invalidate the independent balance cache. Only image key quotas are queried; account-wide billing and conversation key totals are kept separate.
148
148
 
149
- Choose the image model and quality, then click **Create image** in a PackyCode conversation or explicitly request `packycode_image_generate`. Attach references and describe changes to use `/v1/images/edits`; new images use `/v1/images/generations`. The image model is independent of the conversation model and other image plugins can coexist. CLI-backed Claude main turns currently bridge web search only; use an API conversation model supporting DSH tool calls for images.
149
+ Choose the image model and quality, then click **Create image** in a PackyCode conversation or explicitly request `packycode_image_generate`. Attach references and describe changes to use `/v1/images/edits`; new images use `/v1/images/generations`. The image model is independent of the conversation model and other image plugins can coexist.
150
+
151
+ All three CLI-backed Claude models and the `claude_code` delegation tool also support generation and editing through a temporary MCP image tool: `Claude Code CLI → local MCP → host image service → PackyCode Images API`. It shares the image preferences, dedicated image key and balance cache; the image key never reaches the CLI. References use host-scoped session handles (`referenceIds` / optional `maskId`), including images generated earlier in the same run. Successful images are persisted in DSH messages for chat replay, with original PNG files saved separately. Each run allows at most four image attempts, one at a time; cancellation aborts image work. Plan mode and session titles do not expose the paid image tool. **Create image** remains available in Claude conversations.
152
+
153
+ **Image visible in tool details but unavailable in the final answer:** a standalone main-chat gallery remains visible when reasoning/tool details are collapsed, including PTC child calls. Reopening an existing conversation restores the gallery from its saved attachments without regenerating or spending image quota. An old invalid Markdown image link to a host path does not affect this gallery.
150
154
 
151
155
  Tool callers can set `model` and `quality` to `settings` to follow the saved preferences; `auto` is an explicit API quality. New images may omit `referenceImages` or pass an empty array. Explicit `operation: edit` requires valid references, and invalid real references are never discarded in favor of new-image generation.
152
156
 
@@ -264,6 +268,8 @@ pnpm run check
264
268
 
265
269
  `node scripts/cli-search-check.mjs` runs the real CLI against a local test gateway and MCP bridge; Claude responses and search data are mocked by default, with no quota consumed. It checks all three permission modes, native-search exclusion and temporary-resource cleanup. `--live --backend deepseek` or `--live --backend gpt` sends the read-only mode's one search to the real backend (edit/full remain mocked). This does not verify actual Claude upstream turns or a running DSH integration.
266
270
 
271
+ `node scripts/cli-image-check.mjs` checks the real official CLI generating an image, editing its result, and persisting both through DSH's message assembler. Default model/image responses are local fixtures, covering read-only/edit/full/plan/title modes and temporary-config cleanup. `--live` makes one real Sunburst low-quality generation and one edit using the stored image key, while Claude replies remain local fixtures. `--with-claude` additionally uses a real Claude upstream turn (Haiku by default), consuming conversation quota too. Outputs go under `.artifacts/`; neither option starts DSH or claims a running desktop conversation was tested.
272
+
267
273
  `node scripts/cli-plan-check.mjs` checks plan mode with the real CLI and a local fake gateway: stdio handoff, concurrent plan ownership, invocation-only file fallback, stale-plan exclusion, actual denial limits and cleanup. It reads no real credentials, spends no quota and starts no DSH instance.
268
274
 
269
275
  `node scripts/install-check.mjs` diagnoses an installed plugin that never appears: it reads one profile, lists any host package shadowed by a leftover `node_modules` inside an installed package (with versions) plus the recovery steps, and exits 1 when it finds one. `--profile <name>`, `--home <dir>`, and `--json` are available.
package/README.md CHANGED
@@ -51,7 +51,7 @@
51
51
  dsh-packycode-api
52
52
  ```
53
53
 
54
- 在**安装源**中选择**官方源**,然后点击**安装**。需要固定版本时填入 `dsh-packycode-api@1.2.0`。
54
+ 在**安装源**中选择**官方源**,然后点击**安装**。需要固定版本时填入 `dsh-packycode-api@1.2.1`。
55
55
 
56
56
  首次安装后**无需重启 DSH**,可直接打开**设置 → PackyCode** 添加 Key。更新已加载的旧版时,按「插件版本」卡片的重启提示操作。
57
57
 
@@ -70,7 +70,7 @@ dsh-packycode-api
70
70
 
71
71
  桌面应用的**插件**页可以看到已安装状态与版本,也可以在那里启用、停用或卸载。
72
72
 
73
- **仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.2.0`。不要对 `desktop` 使用它 —— CLI 会直接拒绝(`profile "desktop" is managed exclusively by the Electron application`)。
73
+ **仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.2.1`。不要对 `desktop` 使用它 —— CLI 会直接拒绝(`profile "desktop" is managed exclusively by the Electron application`)。
74
74
 
75
75
  本地开发要加 `link:` 前缀:`dsh plugin --profile <name> add link:/path/to/dsh-packycode-api`。**不要直接写路径(或 `file:`)** —— 那样的安装会把整个仓库目录(连同 `node_modules`)复制进 profile,之后它会在 profile 内部挡住 DSH 自带的包,插件看起来像没装,见「常见问题」。已经那样装过的话,先卸载再按上面的方式重装。
76
76
 
@@ -146,7 +146,11 @@ Claude Code CLI → 本机临时 MCP web_search → 插件选定的 DeepSeek/GPT
146
146
 
147
147
  图片卡片会显示每个图片 Key 的剩余、已用、限额(接口有提供时)、重置周期和使用进度,并单独汇总图片额度。余额每分钟更新,也可点卡片右上角的「刷新」;读取失败时保留上次余额并标出时间。图片 Key 变更或生图成功后会清理图片余额缓存。仅查询专用图片 Key 的额度,不叠加账户级账单,也不混入对话 Key 的合计。
148
148
 
149
- 选择请求型号与质量后,可在 PackyCode 对话里点 **创建图片** 补充描述,或明确要求使用 `packycode_image_generate`。上传参考图后描述修改要求会调用 `/v1/images/edits`;新图调用 `/v1/images/generations`。图片型号独立于对话型号,其他插件的图片工具仍可并存。CLI 执行的 Claude 主回合目前仅桥接网页搜索,生图请在支持 DSH 工具调用的 API 模型对话中使用。
149
+ 选择请求型号与质量后,可在 PackyCode 对话里点 **创建图片** 补充描述,或明确要求使用 `packycode_image_generate`。上传参考图后描述修改要求会调用 `/v1/images/edits`;新图调用 `/v1/images/generations`。图片型号独立于对话型号,其他插件的图片工具仍可并存。
150
+
151
+ 三个 Claude 模型走本机官方 CLI 时,以及 `claude_code` 委派时,均可通过临时 MCP 图片工具生图和编辑:`Claude Code CLI → 本机 MCP → 插件图片服务 → PackyCode Images API`。它复用同一份图片设置、独立图片 Key 和余额缓存;图片 Key 不会交给 CLI。CLI 只使用宿主提供的本会话图片句柄(`referenceIds` / 可选 `maskId`),可以继续编辑本轮刚生成的图片。成功结果作为图片保存进 DSH 会话,聊天重放也能展示,PNG 原图另存本机。每轮最多四次图片尝试、同一时间一张;请求取消时一并停止图片请求。计划模式和标题生成不开放生图工具。创建图片按钮在 Claude 对话中保留。
152
+
153
+ **详情里有图、主聊天却显示「图片无法预览」:** 图片结果会在主聊天单独展示,收起思维链或工具详情时仍可见,包括 PTC 嵌套调用。修复版重新打开历史对话也会用已保存的附件补出图片卡片,无需再次生图;模型回复里遗留的无效本机路径图片链接不影响这张卡片。
150
154
 
151
155
  工具调用可将 `model` 和 `quality` 设为 `settings` 来跟随已保存的图片设置;`auto` 是一个明确的 API 质量档位。新图可省略 `referenceImages` 或传空数组;显式指定 `operation: edit` 时必须提供有效参考图,错误的真实参考图不会被丢弃后改生成新图。
152
156
 
@@ -264,6 +268,8 @@ pnpm run check
264
268
 
265
269
  Claude CLI 的 MCP 接口验证用 `node scripts/cli-search-check.mjs`:运行真实 CLI,普通 Claude 响应和搜索数据默认由本地测试服务模拟,不消费额度;会检查三种权限模式、原生搜索禁用和临时资源清理。加 `--live --backend deepseek` 或 `--live --backend gpt` 会让只读模式的那一次搜索走真实后端(其它两种模式仍模拟)。这不等于验证了真实 Claude 上游对话或运行中的 DSH 集成。
266
270
 
271
+ 图片 MCP 验证用 `node scripts/cli-image-check.mjs`:真实官方 CLI 依次生图、用生成结果编辑,并经 DSH 消息组装器验证持久化图片;默认 Claude 和图片网关响应均在本地模拟,同时检查只读/编辑/完全权限、计划模式、标题和临时配置清理。加 `--live` 会用已保存的独立图片 Key 向真实图片网关发出一次 Sunburst `low` 生图与一次编辑,结果写入 `.artifacts/`;Claude 回复仍由本地模拟网关提供。加 `--with-claude` 则连 Claude 也走真实网关,默认 Haiku,另消费对话额度;两者都不启动或重启 DSH,也不等于验证了运行中桌面会话。
272
+
267
273
  计划模式另用 `node scripts/cli-plan-check.mjs` 验证:真实 CLI 对接本地模拟网关,检查 stdio 计划提交、并发计划归属、本轮文件回退、旧计划隔离、实际拒绝次数上限和清理;不读取真实凭据、不消费额度、不启动 DSH。
268
274
 
269
275
  排查「装了却看不到插件」用 `node scripts/install-check.mjs`:它只读当前 profile,列出被包内残留 `node_modules` 挡住的宿主包(含版本)和对应的修复步骤,发现问题时以退出码 1 结束;`--profile <name>`、`--home <dir>` 可指定其它 profile,`--json` 输出结构化结果。
package/lib/client.js CHANGED
@@ -493,7 +493,27 @@ window.__ModuleLoader__.load({
493
493
  //#region src/image-conversation.js
494
494
  /** Project this plugin's durable image results into chat without duplicating context. */
495
495
  const IMAGE_CHAT_KIND = "packycode-image-output";
496
- const successfulImages = (event) => event?.type === "tool/result" && event.data?.meta?.kind === "packycode-image" ? (event.data.message?.content ?? []).filter((block) => block.type === "tool-result" && !block.isError && block.content?.some((part) => part.type === "image" && part.attachment)) : [];
496
+ const IMAGE_TOOLS = /* @__PURE__ */ new Set(["packycode_image_generate", "claude_code"]);
497
+ const hasImage = (content) => Array.isArray(content) && content.some((part) => part.type === "image" && part.attachment);
498
+ function successfulImages(event) {
499
+ if (event?.type === "tool/result" && event.data?.meta?.kind === "packycode-image") return (event.data.message?.content ?? []).filter((block) => block.type === "tool-result" && !block.isError && hasImage(block.content)).map((block) => ({
500
+ ...block,
501
+ meta: event.data.meta
502
+ }));
503
+ if (event?.type === "tool/ptc-dispatch" && IMAGE_TOOLS.has(event.data?.name) && event.data.isError === false && typeof event.data.subCallId === "string" && hasImage(event.data.content)) return [{
504
+ type: "tool-result",
505
+ toolCallId: event.data.subCallId,
506
+ content: event.data.content,
507
+ meta: { kind: "packycode-image" }
508
+ }];
509
+ const source = event?.data?.message?.source;
510
+ if (event?.type !== "assistant/message" || source?.kind !== "model" || source.provider !== "packycode" || !/^claude-/u.test(source.model ?? "")) return [];
511
+ return (event.data.message.content ?? []).flatMap((block, index) => block.type === "image" && block.attachment ? [{
512
+ type: "tool-result",
513
+ toolCallId: `packycode-cli-image-${event.seq}-${index}`,
514
+ content: [block]
515
+ }] : []);
516
+ }
497
517
  const imageConversationNode = {
498
518
  kind: IMAGE_CHAT_KIND,
499
519
  target: "chat",
@@ -510,11 +530,10 @@ window.__ModuleLoader__.load({
510
530
  if (finished === void 0) return null;
511
531
  const results = context.matches.filter((match) => successfulImages(match.event).length > 0);
512
532
  if (results.length === 0) return null;
513
- const blocks = results.flatMap(({ event }) => successfulImages(event).map((block) => ({
533
+ const blocks = [...new Map(results.flatMap(({ event }) => successfulImages(event).map((block) => [block.toolCallId, {
514
534
  ...block,
515
- kind: "tool-result",
516
- meta: event.data.meta
517
- })));
535
+ kind: "tool-result"
536
+ }]))).values()];
518
537
  const answerSeq = finished.location.turn?.steps?.at(-1)?.data.get("assistant-step")?.finalNode?.seq;
519
538
  const lastImageSeq = Math.max(...results.map((match) => match.event.seq));
520
539
  return {
@@ -522,10 +541,13 @@ window.__ModuleLoader__.load({
522
541
  id: context.id,
523
542
  kind: IMAGE_CHAT_KIND,
524
543
  target: "chat",
525
- location: finished.location,
544
+ location: { kind: "session" },
526
545
  visibility: "visible",
527
546
  anchorSeq: answerSeq > lastImageSeq ? answerSeq + .025 : finished.event.seq - .025,
528
- data: { blocks }
547
+ data: {
548
+ turn: finished.event.data.turn,
549
+ blocks
550
+ }
529
551
  };
530
552
  }
531
553
  };