devez-vibe 1.7.63 → 1.7.65
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/bin/dvz.exe +0 -0
- package/bridge/claude-agent-sdk-bridge.mjs +66 -0
- package/package.json +1 -1
package/bin/dvz.exe
CHANGED
|
Binary file
|
|
@@ -122,6 +122,9 @@ function sanitizedEnvironment() {
|
|
|
122
122
|
delete env.ANTHROPIC_API_KEY;
|
|
123
123
|
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
124
124
|
env.CLAUDE_AGENT_SDK_CLIENT_APP = `dvz/${VERSION}`;
|
|
125
|
+
// Claude Code leaves the Artifact tool off for SDK hosts unless asked; the
|
|
126
|
+
// account flag and admin policy still decide whether it actually appears.
|
|
127
|
+
env.CLAUDE_CODE_ARTIFACT ??= "1";
|
|
125
128
|
return env;
|
|
126
129
|
}
|
|
127
130
|
|
|
@@ -2486,6 +2489,14 @@ function processUser(session, message) {
|
|
|
2486
2489
|
finishSubagentTask(session, firstLine(pending.input?.task_id || "", 80));
|
|
2487
2490
|
}
|
|
2488
2491
|
if (!pending) continue;
|
|
2492
|
+
if (pending.name === "Artifact" && typeof message.tool_use_result?.url === "string") {
|
|
2493
|
+
notify("turn/artifact/published", {
|
|
2494
|
+
threadId: session.id,
|
|
2495
|
+
url: message.tool_use_result.url,
|
|
2496
|
+
title: String(message.tool_use_result.title || ""),
|
|
2497
|
+
path: String(message.tool_use_result.path || pending.input?.file_path || ""),
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2489
2500
|
pending.toolUseId = block.tool_use_id;
|
|
2490
2501
|
if (pending.suppressed) {
|
|
2491
2502
|
updatePlanFromToolResult(session, pending, message);
|
|
@@ -3135,11 +3146,45 @@ function transcriptEntries(raw) {
|
|
|
3135
3146
|
if (seen.has(entry.uuid)) continue;
|
|
3136
3147
|
seen.add(entry.uuid);
|
|
3137
3148
|
}
|
|
3149
|
+
// The transcript file spells the SDK's tool_use_result as toolUseResult.
|
|
3150
|
+
if (entry.tool_use_result === undefined && entry.toolUseResult !== undefined) entry.tool_use_result = entry.toolUseResult;
|
|
3138
3151
|
messages.push(entry);
|
|
3139
3152
|
}
|
|
3140
3153
|
return messages;
|
|
3141
3154
|
}
|
|
3142
3155
|
|
|
3156
|
+
// Pages the transcript published with the Artifact tool, oldest first and each
|
|
3157
|
+
// URL at its latest publish, so a resumed session gets its row under the status
|
|
3158
|
+
// line back the way the CLI rehydrates its own footer.
|
|
3159
|
+
function publishedArtifacts(messages) {
|
|
3160
|
+
const inputs = new Map();
|
|
3161
|
+
const artifacts = new Map();
|
|
3162
|
+
for (const message of messages) {
|
|
3163
|
+
for (const block of contentBlocks(message.message)) {
|
|
3164
|
+
if (block.type === "tool_use" && block.name === "Artifact") inputs.set(block.id, block.input || {});
|
|
3165
|
+
if (block.type !== "tool_result" || !inputs.has(block.tool_use_id)) continue;
|
|
3166
|
+
const result = message.tool_use_result;
|
|
3167
|
+
if (typeof result?.url !== "string") continue;
|
|
3168
|
+
artifacts.delete(result.url);
|
|
3169
|
+
artifacts.set(result.url, {
|
|
3170
|
+
url: result.url,
|
|
3171
|
+
title: String(result.title || ""),
|
|
3172
|
+
path: String(result.path || inputs.get(block.tool_use_id).file_path || ""),
|
|
3173
|
+
});
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
return [...artifacts.values()];
|
|
3177
|
+
}
|
|
3178
|
+
|
|
3179
|
+
// Sent after the resume reply, which the host has already cleared its row for.
|
|
3180
|
+
function restoreArtifacts(id, messages) {
|
|
3181
|
+
const artifacts = publishedArtifacts(messages);
|
|
3182
|
+
if (!artifacts.length) return;
|
|
3183
|
+
setImmediate(() => {
|
|
3184
|
+
for (const artifact of artifacts) notify("turn/artifact/published", { threadId: id, ...artifact });
|
|
3185
|
+
});
|
|
3186
|
+
}
|
|
3187
|
+
|
|
3143
3188
|
async function transcriptMessagesAt(path) {
|
|
3144
3189
|
let raw;
|
|
3145
3190
|
try {
|
|
@@ -3370,6 +3415,7 @@ async function dispatch(method, params = {}) {
|
|
|
3370
3415
|
if (existing) {
|
|
3371
3416
|
const messages = await sessionMessages(id, existing.cwd);
|
|
3372
3417
|
if (!existing.tasks.size) existing.tasks = historyState(messages).tasks;
|
|
3418
|
+
restoreArtifacts(id, messages);
|
|
3373
3419
|
return {
|
|
3374
3420
|
id,
|
|
3375
3421
|
thread: { id, turns: [] },
|
|
@@ -3403,6 +3449,7 @@ async function dispatch(method, params = {}) {
|
|
|
3403
3449
|
session.lastContextUsage = tokenUsage?.last || null;
|
|
3404
3450
|
session.lastContextWindow = tokenUsage?.modelContextWindow || 0;
|
|
3405
3451
|
session.tasks = historyState(messages).tasks;
|
|
3452
|
+
restoreArtifacts(id, messages);
|
|
3406
3453
|
return {
|
|
3407
3454
|
id,
|
|
3408
3455
|
thread: { id, turns: [] },
|
|
@@ -3633,6 +3680,25 @@ async function runSelfTest() {
|
|
|
3633
3680
|
|| JSON.stringify(restoredPrompts) !== JSON.stringify(["compact 이전 질문", "compact 이후 질문"])) {
|
|
3634
3681
|
throw new Error(`Claude compacted transcript self-test failed: ${JSON.stringify({ restored: restored.length, restoredPrompts })}`);
|
|
3635
3682
|
}
|
|
3683
|
+
// A resumed transcript lists its Artifact pages once each at their latest
|
|
3684
|
+
// publish, read through the file's toolUseResult spelling.
|
|
3685
|
+
const artifactTranscript = [
|
|
3686
|
+
JSON.stringify({ type: "assistant", uuid: "art-1", message: { role: "assistant", content: [{ type: "tool_use", id: "toolu_a1", name: "Artifact", input: { file_path: "C:\\tmp\\first.html" } }] } }),
|
|
3687
|
+
JSON.stringify({ type: "user", uuid: "art-1r", message: { role: "user", content: [{ type: "tool_result", tool_use_id: "toolu_a1", content: "ok" }] }, toolUseResult: { url: "https://claude.ai/code/artifact/one", title: "One" } }),
|
|
3688
|
+
JSON.stringify({ type: "assistant", uuid: "art-2", message: { role: "assistant", content: [{ type: "tool_use", id: "toolu_a2", name: "Artifact", input: { file_path: "C:\\tmp\\second.html" } }] } }),
|
|
3689
|
+
JSON.stringify({ type: "user", uuid: "art-2r", message: { role: "user", content: [{ type: "tool_result", tool_use_id: "toolu_a2", content: "ok" }] }, toolUseResult: { url: "https://claude.ai/code/artifact/two", path: "C:\\tmp\\second.html", title: "Two" } }),
|
|
3690
|
+
JSON.stringify({ type: "assistant", uuid: "art-3", message: { role: "assistant", content: [{ type: "tool_use", id: "toolu_a3", name: "Artifact", input: { action: "read", url: "https://claude.ai/code/artifact/one" } }] } }),
|
|
3691
|
+
JSON.stringify({ type: "user", uuid: "art-3r", message: { role: "user", content: [{ type: "tool_result", tool_use_id: "toolu_a3", content: "<html>" }] }, toolUseResult: { content: "<html>" } }),
|
|
3692
|
+
JSON.stringify({ type: "assistant", uuid: "art-4", message: { role: "assistant", content: [{ type: "tool_use", id: "toolu_a4", name: "Artifact", input: { file_path: "C:\\tmp\\first.html" } }] } }),
|
|
3693
|
+
JSON.stringify({ type: "user", uuid: "art-4r", message: { role: "user", content: [{ type: "tool_result", tool_use_id: "toolu_a4", content: "ok" }] }, toolUseResult: { url: "https://claude.ai/code/artifact/one", path: "C:\\tmp\\first.html", title: "One", updated: true } }),
|
|
3694
|
+
].join("\n");
|
|
3695
|
+
const restoredArtifacts = publishedArtifacts(transcriptEntries(artifactTranscript));
|
|
3696
|
+
if (JSON.stringify(restoredArtifacts) !== JSON.stringify([
|
|
3697
|
+
{ url: "https://claude.ai/code/artifact/two", title: "Two", path: "C:\\tmp\\second.html" },
|
|
3698
|
+
{ url: "https://claude.ai/code/artifact/one", title: "One", path: "C:\\tmp\\first.html" },
|
|
3699
|
+
])) {
|
|
3700
|
+
throw new Error(`Claude artifact resume self-test failed: ${JSON.stringify(restoredArtifacts)}`);
|
|
3701
|
+
}
|
|
3636
3702
|
// A model that left the CLI's list resolves to its family's newest entry, so a
|
|
3637
3703
|
// Fable 5 transcript resumes on Fable 5.1 instead of the host's default.
|
|
3638
3704
|
const successorModels = [
|