dsh-packycode-api 1.2.0 → 1.2.2
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 +17 -0
- package/README.en.md +9 -3
- package/README.md +9 -3
- package/lib/client.js +41 -16
- package/lib/index.js +990 -622
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.2
|
|
4
|
+
|
|
5
|
+
- Fixed the remaining missing-gallery bug in 1.2.1. Real native `tool/result` and nested `tool/ptc-dispatch` records do not have `data.turn`; keying image contexts by that missing field separated image evidence from the actual `turn/end` context. Image contexts now use the tool call ID (or CLI message sequence) and obtain the owning turn and completion boundary from DSH's engine-provided Match Location. Results appear as soon as available and stay visible when history later supplies missing boundaries.
|
|
6
|
+
- Removed fabricated turn/step fields from the runtime regression fixture. Added the real DSH 0.2 Chat snapshot builder and grouping to the built-client path, plus multi-turn, interleaved-session and older-page-prepend regressions. A React/ReactDOM browser replay (`scripts/image-preview-check.mjs`) reproduces the published 1.2.1 bundle showing zero main-chat images while tool details can load the PNG; the corrected build displays both native/PTC image cards with details collapsed and retains them after history reload. No new paid generation or existing-session modification is needed.
|
|
7
|
+
- Validation, 2026-10-15: 381 offline tests, both bundles and the 1.2.2 tarball. Browser comparison used the published 1.2.1 client and the corrected client against the same raw native/PTC events and real DSH 0.2.0-rc.2 Chat assembly/grouping: the old client rendered zero main-chat images with a loadable tool-detail image; the new client rendered both PNGs with details collapsed and after history reload. The final browser replay uses React, ReactDOM and the JSX runtime with no console errors. The colleague's physical Intel Mac still needs an update-and-retest; no DSH process was restarted and no paid image request was made for this verification.
|
|
8
|
+
|
|
9
|
+
## 1.2.1
|
|
10
|
+
|
|
11
|
+
- **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.
|
|
12
|
+
- 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.
|
|
13
|
+
- **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.
|
|
14
|
+
- 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.
|
|
15
|
+
- 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.
|
|
16
|
+
- 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.
|
|
17
|
+
- 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.
|
|
18
|
+
- 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.
|
|
19
|
+
|
|
3
20
|
## 1.2.0
|
|
4
21
|
|
|
5
22
|
- **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.
|
|
54
|
+
Choose the **official** install source, then click **Install**. To pin a version, enter `dsh-packycode-api@1.2.2`.
|
|
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.
|
|
73
|
+
**For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.2.2`. 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.
|
|
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.
|
|
54
|
+
在**安装源**中选择**官方源**,然后点击**安装**。需要固定版本时填入 `dsh-packycode-api@1.2.2`。
|
|
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.
|
|
73
|
+
**仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.2.2`。不要对 `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`。图片型号独立于对话型号,其他插件的图片工具仍可并存。
|
|
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,39 +493,64 @@ 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
|
|
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",
|
|
500
520
|
match(event) {
|
|
501
|
-
|
|
502
|
-
|
|
521
|
+
const images = successfulImages(event);
|
|
522
|
+
if (images.length === 0) return null;
|
|
523
|
+
const id = event.type === "assistant/message" ? `cli:${event.seq}` : event.data?.subCallId ?? event.data?.message?.source?.callId ?? images[0].toolCallId ?? `event:${event.seq}`;
|
|
524
|
+
return {
|
|
525
|
+
id: String(id),
|
|
503
526
|
role: "update"
|
|
504
|
-
}
|
|
527
|
+
};
|
|
505
528
|
},
|
|
506
|
-
start: () =>
|
|
507
|
-
update: (context) => context.state,
|
|
529
|
+
start: () => ({}),
|
|
530
|
+
update: (context) => context.state ?? {},
|
|
508
531
|
buildViewNode(context) {
|
|
509
|
-
const finished = context.matches.find((match) => match.event.type === "turn/end");
|
|
510
|
-
if (finished === void 0) return null;
|
|
511
532
|
const results = context.matches.filter((match) => successfulImages(match.event).length > 0);
|
|
512
533
|
if (results.length === 0) return null;
|
|
513
|
-
const
|
|
534
|
+
const turn = (results.find((match) => match.location?.kind === "turn" || match.location?.kind === "step")?.location)?.turn;
|
|
535
|
+
const finished = turn?.end;
|
|
536
|
+
const blocks = [...new Map(results.flatMap(({ event }) => successfulImages(event).map((block) => [block.toolCallId, {
|
|
514
537
|
...block,
|
|
515
|
-
kind: "tool-result"
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const answerSeq = finished.location.turn?.steps?.at(-1)?.data.get("assistant-step")?.finalNode?.seq;
|
|
538
|
+
kind: "tool-result"
|
|
539
|
+
}]))).values()];
|
|
540
|
+
const answerSeq = turn?.steps?.at(-1)?.data.get("assistant-step")?.finalNode?.seq;
|
|
519
541
|
const lastImageSeq = Math.max(...results.map((match) => match.event.seq));
|
|
520
542
|
return {
|
|
521
543
|
key: context.key,
|
|
522
544
|
id: context.id,
|
|
523
545
|
kind: IMAGE_CHAT_KIND,
|
|
524
546
|
target: "chat",
|
|
525
|
-
location:
|
|
547
|
+
location: { kind: "session" },
|
|
526
548
|
visibility: "visible",
|
|
527
|
-
anchorSeq: answerSeq > lastImageSeq ? answerSeq + .025 : finished.
|
|
528
|
-
data: {
|
|
549
|
+
anchorSeq: answerSeq > lastImageSeq ? answerSeq + .025 : finished === void 0 ? lastImageSeq + .025 : finished.seq - .025,
|
|
550
|
+
data: {
|
|
551
|
+
...turn === void 0 ? {} : { turn: turn.turn },
|
|
552
|
+
blocks
|
|
553
|
+
}
|
|
529
554
|
};
|
|
530
555
|
}
|
|
531
556
|
};
|