@astrosheep/keiyaku 2.8.4 → 2.9.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/README.md +35 -15
- package/build/.tsbuildinfo +1 -1
- package/build/agents/{call-terms_v2.js → call-terms.js} +12 -8
- package/build/agents/harness/control-types.js +1 -0
- package/build/agents/harness/execution-handle.js +23 -3
- package/build/agents/harness/index.js +6 -607
- package/build/agents/harness/outcome.js +141 -0
- package/build/agents/harness/projection.js +310 -0
- package/build/agents/harness/router.js +201 -0
- package/build/agents/harness/runtime.js +2 -1
- package/build/agents/{launch-snapshot_v2.js → launch-snapshot/model.js} +69 -74
- package/build/agents/launch-snapshot/resolve.js +72 -0
- package/build/agents/opencode-sdk.js +24 -3
- package/build/agents/providers/{claude-agent-sdk.js → claude-agent-sdk/adapter.js} +46 -368
- package/build/agents/providers/claude-agent-sdk/events.js +218 -0
- package/build/agents/providers/claude-agent-sdk/session.js +158 -0
- package/build/agents/providers/codex-app-server/adapter.js +347 -0
- package/build/agents/providers/codex-app-server/events.js +352 -0
- package/build/agents/providers/codex-app-server/session.js +266 -0
- package/build/agents/providers/codex-sdk.js +23 -5
- package/build/agents/providers/opencode-sdk/adapter.js +344 -0
- package/build/agents/providers/opencode-sdk/events.js +354 -0
- package/build/agents/providers/opencode-sdk/session.js +180 -0
- package/build/agents/providers/pi/adapter.js +269 -0
- package/build/agents/providers/pi/checkpoint.js +41 -0
- package/build/agents/providers/pi/events.js +282 -0
- package/build/agents/{selector_v2.js → selector.js} +8 -6
- package/build/cli/commands/akuma/akuma/handler.js +4 -0
- package/build/cli/commands/akuma/akuma/meta.js +16 -0
- package/build/cli/commands/akuma/catalog.js +8 -0
- package/build/cli/commands/akuma/list/handler.js +15 -0
- package/build/cli/commands/akuma/list/meta-ls.js +9 -0
- package/build/cli/commands/akuma/view/handler.js +34 -0
- package/build/cli/commands/akuma/view/meta.js +8 -0
- package/build/cli/commands/akuma.js +1 -1
- package/build/cli/commands/contract/amend/handler.js +10 -0
- package/build/cli/commands/contract/amend/meta.js +12 -0
- package/build/cli/commands/contract/arc/handler.js +9 -0
- package/build/cli/commands/contract/arc/meta.js +26 -0
- package/build/cli/commands/contract/bind/handler.js +23 -0
- package/build/cli/commands/contract/bind/meta.js +30 -0
- package/build/cli/commands/contract/catalog.js +16 -0
- package/build/cli/commands/contract/forfeit/handler.js +13 -0
- package/build/cli/commands/contract/forfeit/meta.js +12 -0
- package/build/cli/commands/contract/log/handler.js +12 -0
- package/build/cli/commands/contract/log/meta.js +12 -0
- package/build/cli/commands/contract/petition/handler.js +26 -0
- package/build/cli/commands/contract/petition/meta.js +23 -0
- package/build/cli/commands/contract/renew/handler.js +10 -0
- package/build/cli/commands/contract/renew/meta.js +17 -0
- package/build/cli/commands/projection/call/handler.js +39 -0
- package/build/cli/commands/projection/call/meta.js +9 -0
- package/build/cli/commands/projection/catalog.js +14 -0
- package/build/cli/commands/projection/kill/handler.js +35 -0
- package/build/cli/commands/projection/kill/meta.js +11 -0
- package/build/cli/commands/projection/revive/handler.js +53 -0
- package/build/cli/commands/projection/revive/meta.js +9 -0
- package/build/cli/commands/projection/status/handler.js +23 -0
- package/build/cli/commands/projection/status/meta.js +9 -0
- package/build/cli/commands/projection/tell/handler.js +34 -0
- package/build/cli/commands/projection/tell/meta.js +9 -0
- package/build/cli/commands/projection/wait/handler.js +21 -0
- package/build/cli/commands/projection/wait/meta.js +11 -0
- package/build/cli/commands/registry.js +100 -0
- package/build/cli/commands/shared.js +71 -0
- package/build/cli/commands/skills/catalog.js +6 -0
- package/build/cli/commands/skills/install/handler.js +10 -0
- package/build/cli/commands/skills/install/meta.js +9 -0
- package/build/cli/commands/skills/skills/handler.js +4 -0
- package/build/cli/commands/skills/skills/meta.js +10 -0
- package/build/cli/commands/system/catalog.js +8 -0
- package/build/cli/commands/system/completion/handler.js +10 -0
- package/build/cli/commands/system/completion/meta.js +9 -0
- package/build/cli/commands/system/dump-env/handler.js +3 -0
- package/build/cli/commands/system/dump-env/meta.js +10 -0
- package/build/cli/commands/system/guide/handler.js +4 -0
- package/build/cli/commands/system/guide/meta.js +9 -0
- package/build/cli/commands/task/add/handler.js +21 -0
- package/build/cli/commands/task/add/meta.js +8 -0
- package/build/cli/commands/task/catalog.js +22 -0
- package/build/cli/commands/task/doctor/handler.js +4 -0
- package/build/cli/commands/task/doctor/meta.js +8 -0
- package/build/cli/commands/task/done/handler.js +17 -0
- package/build/cli/commands/task/done/meta.js +8 -0
- package/build/cli/commands/task/drop/handler.js +6 -0
- package/build/cli/commands/task/drop/meta.js +8 -0
- package/build/cli/commands/task/ls/handler.js +13 -0
- package/build/cli/commands/task/ls/meta.js +8 -0
- package/build/cli/commands/task/shared.js +131 -0
- package/build/cli/commands/task/start/handler.js +6 -0
- package/build/cli/commands/task/start/meta.js +8 -0
- package/build/cli/commands/task/stop/handler.js +17 -0
- package/build/cli/commands/task/stop/meta.js +8 -0
- package/build/cli/commands/task/task/handler.js +5 -0
- package/build/cli/commands/task/task/meta.js +11 -0
- package/build/cli/commands/task/update/handler.js +18 -0
- package/build/cli/commands/task/update/meta.js +8 -0
- package/build/cli/commands/task/view/handler.js +14 -0
- package/build/cli/commands/task/view/meta.js +8 -0
- package/build/cli/completion.js +26 -27
- package/build/cli/flags.js +79 -2
- package/build/cli/help.js +27 -49
- package/build/cli/index.js +121 -374
- package/build/cli/output-stream-error-policy.js +17 -0
- package/build/cli/parse.js +159 -72
- package/build/cli/projection-address.js +5 -0
- package/build/cli/render/arc.js +1 -1
- package/build/cli/render/errors.js +4 -3
- package/build/cli/render/format.js +14 -0
- package/build/cli/render/kanshi.js +106 -0
- package/build/cli/render/petition.js +24 -1
- package/build/cli/render/projection-activity.js +5 -1
- package/build/cli/render/shared.js +2 -2
- package/build/cli/render/status.js +79 -13
- package/build/cli/render/task.js +113 -0
- package/build/cli/render/wait.js +23 -3
- package/build/cli/types.js +1 -1
- package/build/config/{akuma-loader_v2.js → akuma-loader.js} +2 -2
- package/build/config/env.js +9 -4
- package/build/config/settings/disease.js +26 -0
- package/build/config/settings/knobs.js +8 -0
- package/build/config/settings/loader.js +244 -0
- package/build/config/settings/schema.js +276 -0
- package/build/core/addressing.js +1 -1
- package/build/core/amend.js +3 -3
- package/build/core/arc.js +5 -4
- package/build/core/bind-workspace.js +123 -0
- package/build/core/bind.js +75 -155
- package/build/core/call/call.js +224 -0
- package/build/core/call/context.js +238 -0
- package/build/core/call/execution.js +217 -0
- package/build/core/call/prompt.js +42 -0
- package/build/core/call/reference.js +24 -0
- package/build/core/call-persist.js +1 -1
- package/build/core/claim-delivery.js +247 -0
- package/build/core/claim.js +39 -277
- package/build/core/context.js +2 -1
- package/build/core/{render.js → contract-view.js} +12 -140
- package/build/core/draft.js +107 -9
- package/build/core/entry.js +9 -1
- package/build/core/execution-coordinate.js +4 -20
- package/build/core/execution-pact.js +16 -31
- package/build/core/forfeit.js +35 -22
- package/build/core/hints.js +2 -2
- package/build/core/log.js +2 -2
- package/build/core/petition-claim-gates.js +8 -6
- package/build/core/petition-preview.js +97 -0
- package/build/core/petition-run.js +3 -2
- package/build/core/petition.js +39 -26
- package/build/core/projection/generation/database.js +306 -0
- package/build/core/projection/generation/identity.js +84 -0
- package/build/core/projection/generation/model.js +201 -0
- package/build/core/projection/generation/store.js +73 -0
- package/build/core/projection/generation/transitions.js +258 -0
- package/build/core/projection/heart.js +0 -307
- package/build/core/projection/tell/database.js +109 -0
- package/build/core/projection/tell/model.js +97 -0
- package/build/core/{projection-tells.js → projection/tell/store.js} +3 -158
- package/build/core/projection-activity.js +23 -2
- package/build/core/projection-core.js +2 -1
- package/build/core/projection-execution-observer.js +259 -0
- package/build/core/projection-generation-continuation.js +1 -1
- package/build/core/projection-generation-execution.js +90 -20
- package/build/core/projection-generation-launcher.js +1 -1
- package/build/core/projection-generation-runner.js +198 -4
- package/build/core/projection-identity.js +1 -1
- package/build/core/projection-kill.js +50 -17
- package/build/core/projection-life-observer.js +1 -1
- package/build/core/projection-life-protocol.js +10 -0
- package/build/core/projection-mint.js +1 -1
- package/build/core/projection-status.js +45 -32
- package/build/core/projection-wait.js +12 -2
- package/build/core/projection-wake.js +5 -2
- package/build/core/{queue_v2.js → queue.js} +2 -1
- package/build/core/registry.js +1 -1
- package/build/core/renew.js +7 -7
- package/build/core/response-artifact-catalog-sqlite.js +112 -0
- package/build/core/response-artifact-catalog.js +7 -0
- package/build/core/seal.js +44 -16
- package/build/core/status/board.js +286 -0
- package/build/core/status/drift.js +99 -0
- package/build/core/status/lifecycle.js +84 -0
- package/build/core/status/reconciliation.js +131 -0
- package/build/core/stored-agent-event.js +28 -4
- package/build/core/target-ref.js +10 -0
- package/build/core/task/board.js +175 -0
- package/build/core/task/commands.js +211 -0
- package/build/core/task/document.js +189 -0
- package/build/core/task/model.js +1 -0
- package/build/core/task/settlement-git.js +207 -0
- package/build/core/task/settlement-policy.js +82 -0
- package/build/core/task/source-board.js +84 -0
- package/build/core/task/source-model.js +1 -0
- package/build/core/task/validation.js +44 -0
- package/build/core/task-contract.js +224 -0
- package/build/core/task-doctor.js +14 -0
- package/build/core/task-git-actor.js +38 -0
- package/build/core/task-git-runtime.js +34 -0
- package/build/core/task-git-store.js +375 -0
- package/build/core/task-repository.js +1 -0
- package/build/core/task-store-repository.js +86 -0
- package/build/core/task-store.js +1 -0
- package/build/core/task-worktree.js +51 -0
- package/build/core/task.js +4 -0
- package/build/core/transcripts.js +138 -56
- package/build/core/validation.js +17 -0
- package/build/core/verdict.js +2 -2
- package/build/core/worktree-path.js +24 -6
- package/build/flow-error.js +3 -2
- package/build/generated/version.js +1 -1
- package/build/git/commits.js +3 -0
- package/build/git/diff/parsers.js +0 -94
- package/build/index.js +2 -0
- package/build/keiyaku-constants.js +2 -0
- package/build/keiyaku.js +4 -3
- package/package.json +3 -2
- package/skills/keiyaku/SKILL.md +1 -1
- package/skills/keiyaku-akuma/SKILL.md +11 -6
- package/build/agents/harness/pump.js +0 -158
- package/build/agents/providers/codex-app-server.js +0 -864
- package/build/agents/providers/opencode-sdk.js +0 -363
- package/build/agents/providers/pi.js +0 -557
- package/build/config/settings.js +0 -533
- package/build/core/call.js +0 -686
- package/build/core/projection/generation.js +0 -412
- package/build/core/projection/identity.js +0 -81
- package/build/core/projection/mint.js +0 -174
- package/build/core/projection-generation-store.js +0 -707
- package/build/core/status.js +0 -539
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { activityCallFromNamedTool, boundActivityExcerpt } from "../../harness/activity-values.js";
|
|
2
|
+
import { coerceString } from "../../harness/runtime.js";
|
|
3
|
+
import { AGENT_PLAN_ITEM_TEXT_MAX_CHARS, AGENT_PLAN_MAX_ITEMS, AGENT_THOUGHT_TEXT_MAX_CHARS, } from "../../harness/events.js";
|
|
4
|
+
import { CLAUDE_AGENT_SDK_PROVIDER } from "./session.js";
|
|
5
|
+
const CLAUDE_MAPPED = new Set(["assistant", "user", "result", "system", "fallback"]);
|
|
6
|
+
const CLAUDE_ACKNOWLEDGED_UNPERSISTED = new Set([
|
|
7
|
+
"stream_event",
|
|
8
|
+
"rate_limit_event",
|
|
9
|
+
"control_cancel_request",
|
|
10
|
+
"control_request",
|
|
11
|
+
"control_response",
|
|
12
|
+
"conversation_reset",
|
|
13
|
+
"keep_alive",
|
|
14
|
+
"local",
|
|
15
|
+
"prompt_suggestion",
|
|
16
|
+
"tool_progress",
|
|
17
|
+
"tool_use_summary",
|
|
18
|
+
"auth_status",
|
|
19
|
+
]);
|
|
20
|
+
export function claudeIngressDisposition(type) {
|
|
21
|
+
if (CLAUDE_MAPPED.has(type))
|
|
22
|
+
return "mapped";
|
|
23
|
+
if (CLAUDE_ACKNOWLEDGED_UNPERSISTED.has(type))
|
|
24
|
+
return "acknowledged-unpersisted";
|
|
25
|
+
return "unknown";
|
|
26
|
+
}
|
|
27
|
+
function extractMessageText(content) {
|
|
28
|
+
if (!Array.isArray(content))
|
|
29
|
+
return undefined;
|
|
30
|
+
const text = content
|
|
31
|
+
.map((block) => {
|
|
32
|
+
if (typeof block !== "object" || block === null || !("text" in block))
|
|
33
|
+
return "";
|
|
34
|
+
const candidate = block.text;
|
|
35
|
+
return typeof candidate === "string" ? candidate : "";
|
|
36
|
+
})
|
|
37
|
+
.join("")
|
|
38
|
+
.trim();
|
|
39
|
+
return text || undefined;
|
|
40
|
+
}
|
|
41
|
+
export function extractAssistantMessage(event) {
|
|
42
|
+
return extractMessageText(event.message.content);
|
|
43
|
+
}
|
|
44
|
+
export function extractAssistantMessageId(event) {
|
|
45
|
+
const id = coerceString(event.message.id)?.trim();
|
|
46
|
+
if (!id) {
|
|
47
|
+
throw Object.assign(new Error(`${CLAUDE_AGENT_SDK_PROVIDER} assistant event lacked nonblank message.id`), { name: "ClaudeAssistantMessageIdError" });
|
|
48
|
+
}
|
|
49
|
+
return id;
|
|
50
|
+
}
|
|
51
|
+
export function extractAssistantMessageModel(event) {
|
|
52
|
+
return coerceString(event.message.model);
|
|
53
|
+
}
|
|
54
|
+
function claudeActivityCall(name, input) {
|
|
55
|
+
if (!isRecord(input))
|
|
56
|
+
return { kind: "other", display: name };
|
|
57
|
+
return activityCallFromNamedTool(name, {
|
|
58
|
+
...(typeof input.command === "string" ? { command: input.command } : {}),
|
|
59
|
+
...(typeof input.description === "string" ? { description: input.description } : {}),
|
|
60
|
+
...(typeof input.file_path === "string" ? { path: input.file_path } : {}),
|
|
61
|
+
...(typeof input.offset === "number" && Number.isFinite(input.offset) ? { offset: input.offset } : {}),
|
|
62
|
+
...(typeof input.limit === "number" && Number.isFinite(input.limit) ? { limit: input.limit } : {}),
|
|
63
|
+
...(typeof input.query === "string" ? { query: input.query } : {}),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function claudeResultMessage(content) {
|
|
67
|
+
if (typeof content === "string")
|
|
68
|
+
return content ? boundActivityExcerpt(content) : undefined;
|
|
69
|
+
if (!Array.isArray(content))
|
|
70
|
+
return undefined;
|
|
71
|
+
const text = content.flatMap((entry) => {
|
|
72
|
+
if (!isRecord(entry) || entry.type !== "text" || typeof entry.text !== "string")
|
|
73
|
+
return [];
|
|
74
|
+
return [entry.text];
|
|
75
|
+
}).join("\n");
|
|
76
|
+
return text ? boundActivityExcerpt(text) : undefined;
|
|
77
|
+
}
|
|
78
|
+
export function emitClaudeToolStarts(builder, event, seenToolUses) {
|
|
79
|
+
if (!Array.isArray(event.message.content))
|
|
80
|
+
return;
|
|
81
|
+
for (const block of event.message.content) {
|
|
82
|
+
if (!isRecord(block) || block.type !== "tool_use")
|
|
83
|
+
continue;
|
|
84
|
+
const id = coerceString(block.id);
|
|
85
|
+
const name = coerceString(block.name);
|
|
86
|
+
if (!id || !name)
|
|
87
|
+
continue;
|
|
88
|
+
const call = claudeActivityCall(name, block.input);
|
|
89
|
+
seenToolUses.set(id, { tool: name, call });
|
|
90
|
+
builder.emit({
|
|
91
|
+
type: "activity",
|
|
92
|
+
phase: "started",
|
|
93
|
+
id,
|
|
94
|
+
tool: name,
|
|
95
|
+
call,
|
|
96
|
+
});
|
|
97
|
+
if (name === "TodoWrite" && isRecord(block.input) && Array.isArray(block.input.todos)) {
|
|
98
|
+
const items = block.input.todos.slice(0, AGENT_PLAN_MAX_ITEMS).flatMap((todo) => {
|
|
99
|
+
if (!isRecord(todo) || typeof todo.content !== "string" || typeof todo.status !== "string") {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
return [{
|
|
103
|
+
text: todo.content.slice(0, AGENT_PLAN_ITEM_TEXT_MAX_CHARS),
|
|
104
|
+
done: todo.status === "completed",
|
|
105
|
+
...(todo.status === "in_progress" ? { active: true } : {}),
|
|
106
|
+
}];
|
|
107
|
+
});
|
|
108
|
+
builder.emit({ type: "plan", id, items });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export function emitClaudeThoughts(builder, event) {
|
|
113
|
+
if (!Array.isArray(event.message.content))
|
|
114
|
+
return;
|
|
115
|
+
event.message.content.forEach((block, blockIndex) => {
|
|
116
|
+
if (!isRecord(block) || block.type !== "thinking" || typeof block.thinking !== "string")
|
|
117
|
+
return;
|
|
118
|
+
const truncated = block.thinking.length > AGENT_THOUGHT_TEXT_MAX_CHARS;
|
|
119
|
+
builder.emit({
|
|
120
|
+
type: "thought",
|
|
121
|
+
id: `${event.uuid}:${blockIndex}`,
|
|
122
|
+
text: block.thinking.slice(0, AGENT_THOUGHT_TEXT_MAX_CHARS),
|
|
123
|
+
final: true,
|
|
124
|
+
...(truncated ? { truncated: true } : {}),
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
export function emitClaudeToolResults(builder, event, seenToolUses) {
|
|
129
|
+
const content = event.message.content;
|
|
130
|
+
if (!Array.isArray(content))
|
|
131
|
+
return;
|
|
132
|
+
for (const block of content) {
|
|
133
|
+
if (!isRecord(block) || block.type !== "tool_result")
|
|
134
|
+
continue;
|
|
135
|
+
const id = coerceString(block.tool_use_id);
|
|
136
|
+
if (!id)
|
|
137
|
+
continue;
|
|
138
|
+
const observed = seenToolUses.get(id);
|
|
139
|
+
if (!observed)
|
|
140
|
+
continue;
|
|
141
|
+
seenToolUses.delete(id);
|
|
142
|
+
const message = claudeResultMessage(block.content);
|
|
143
|
+
builder.emit({
|
|
144
|
+
type: "activity",
|
|
145
|
+
phase: "completed",
|
|
146
|
+
id,
|
|
147
|
+
tool: observed.tool,
|
|
148
|
+
call: observed.call,
|
|
149
|
+
result: {
|
|
150
|
+
status: block.is_error === true ? "error" : "ok",
|
|
151
|
+
...(message ? { message } : {}),
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export function emitClaudeUsage(builder, event, model) {
|
|
157
|
+
const usage = event.usage;
|
|
158
|
+
builder.emit({
|
|
159
|
+
type: "usage",
|
|
160
|
+
inputTokens: usage.input_tokens,
|
|
161
|
+
outputTokens: usage.output_tokens,
|
|
162
|
+
cachedInputTokens: usage.cache_read_input_tokens,
|
|
163
|
+
...(typeof event.total_cost_usd === "number" ? { costUsd: event.total_cost_usd } : {}),
|
|
164
|
+
...(model ? { model } : {}),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function isRecord(value) {
|
|
168
|
+
return typeof value === "object" && value !== null;
|
|
169
|
+
}
|
|
170
|
+
export function isClaudeModelRefusalFallbackEvent(event) {
|
|
171
|
+
return event.type === "system" && event.subtype === "model_refusal_fallback";
|
|
172
|
+
}
|
|
173
|
+
export function isClaudeModelRefusalNoFallbackEvent(event) {
|
|
174
|
+
return event.type === "system" && event.subtype === "model_refusal_no_fallback";
|
|
175
|
+
}
|
|
176
|
+
export function isClaudeApiRetryEvent(event) {
|
|
177
|
+
return event.type === "system" && event.subtype === "api_retry";
|
|
178
|
+
}
|
|
179
|
+
export function mapClaudeApiRetryWarning(event) {
|
|
180
|
+
return {
|
|
181
|
+
reason: "retry",
|
|
182
|
+
attempt: event.attempt,
|
|
183
|
+
maxRetries: event.max_retries,
|
|
184
|
+
retryDelayMs: event.retry_delay_ms,
|
|
185
|
+
errorStatus: event.error_status,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function extractFallbackRequestId(value) {
|
|
189
|
+
if (value === null)
|
|
190
|
+
return null;
|
|
191
|
+
return coerceString(value);
|
|
192
|
+
}
|
|
193
|
+
export function extractOverloadFallbackWarning(event) {
|
|
194
|
+
if (!isRecord(event) || event.type !== "fallback") {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
const originalModel = coerceString(event.original_model);
|
|
198
|
+
const fallbackModel = coerceString(event.fallback_model);
|
|
199
|
+
const direction = coerceString(event.direction);
|
|
200
|
+
const requestId = extractFallbackRequestId(event.request_id);
|
|
201
|
+
return {
|
|
202
|
+
reason: "overload",
|
|
203
|
+
...(originalModel ? { originalModel } : {}),
|
|
204
|
+
...(fallbackModel ? { fallbackModel } : {}),
|
|
205
|
+
...(direction ? { direction } : {}),
|
|
206
|
+
...(requestId !== undefined ? { requestId } : {}),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
export function extractResumeToken(event) {
|
|
210
|
+
return coerceString(event.session_id);
|
|
211
|
+
}
|
|
212
|
+
export function extractResultText(event) {
|
|
213
|
+
if (event.subtype === "success") {
|
|
214
|
+
return coerceString(event.result);
|
|
215
|
+
}
|
|
216
|
+
const errorText = event.errors.join("\n").trim();
|
|
217
|
+
return errorText || undefined;
|
|
218
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
export const CLAUDE_AGENT_SDK_PROVIDER = "claude-agent-sdk";
|
|
2
|
+
/** Sentinel for IteratorResult<SDKUserMessage> done=true returns.
|
|
3
|
+
* The SDK's AsyncIterator protocol requires the value field even when done=true.
|
|
4
|
+
* Consumers never read it, but TypeScript needs the type to match. */
|
|
5
|
+
const DONE_SENTINEL = undefined;
|
|
6
|
+
function createMessageAck() {
|
|
7
|
+
let resolve;
|
|
8
|
+
let reject;
|
|
9
|
+
const promise = new Promise((res, rej) => {
|
|
10
|
+
resolve = res;
|
|
11
|
+
reject = rej;
|
|
12
|
+
});
|
|
13
|
+
// Prevent unhandled rejection if nobody awaits before reject-on-end.
|
|
14
|
+
promise.catch(() => undefined);
|
|
15
|
+
const ack = {
|
|
16
|
+
settled: false,
|
|
17
|
+
settleResolve() {
|
|
18
|
+
if (ack.settled)
|
|
19
|
+
return;
|
|
20
|
+
ack.settled = true;
|
|
21
|
+
resolve();
|
|
22
|
+
},
|
|
23
|
+
settleReject(error) {
|
|
24
|
+
if (ack.settled)
|
|
25
|
+
return;
|
|
26
|
+
ack.settled = true;
|
|
27
|
+
reject(error);
|
|
28
|
+
},
|
|
29
|
+
wait() {
|
|
30
|
+
return promise;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
return ack;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Long-lived push source for Claude Query.
|
|
37
|
+
* Submitted fence is per-yield: entering next() first acknowledges the previously
|
|
38
|
+
* yielded message, then yields the next item. That next-entry after a yield is the
|
|
39
|
+
* post-yield ack (transport.write completed for the prior yield).
|
|
40
|
+
*/
|
|
41
|
+
export function createPushableUserMessageStream(onYield) {
|
|
42
|
+
const queue = [];
|
|
43
|
+
const waiters = [];
|
|
44
|
+
/** Ack for the message most recently yielded; resolved on the subsequent next() entry. */
|
|
45
|
+
let pendingYieldAck;
|
|
46
|
+
let closed = false;
|
|
47
|
+
let failure;
|
|
48
|
+
let pullCount = 0;
|
|
49
|
+
const terminalError = (error) => error ?? new Error(`${CLAUDE_AGENT_SDK_PROVIDER} input stream ended before submitted ack`);
|
|
50
|
+
const rejectUnresolvedAcks = (error) => {
|
|
51
|
+
const err = terminalError(error);
|
|
52
|
+
if (pendingYieldAck) {
|
|
53
|
+
pendingYieldAck.settleReject(err);
|
|
54
|
+
pendingYieldAck = undefined;
|
|
55
|
+
}
|
|
56
|
+
while (queue.length > 0) {
|
|
57
|
+
queue.shift().ack.settleReject(err);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
/** First action on every next() entry: post-yield ack for the prior yield. */
|
|
61
|
+
const acknowledgePreviousYield = () => {
|
|
62
|
+
if (!pendingYieldAck)
|
|
63
|
+
return;
|
|
64
|
+
pendingYieldAck.settleResolve();
|
|
65
|
+
pendingYieldAck = undefined;
|
|
66
|
+
};
|
|
67
|
+
const yieldQueued = (entry) => {
|
|
68
|
+
pullCount += 1;
|
|
69
|
+
pendingYieldAck = entry.ack;
|
|
70
|
+
onYield?.(entry.message);
|
|
71
|
+
return { value: entry.message, done: false };
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
get pullCount() {
|
|
75
|
+
return pullCount;
|
|
76
|
+
},
|
|
77
|
+
get queueLength() {
|
|
78
|
+
return queue.length;
|
|
79
|
+
},
|
|
80
|
+
push(message) {
|
|
81
|
+
const ack = createMessageAck();
|
|
82
|
+
if (closed || failure !== undefined) {
|
|
83
|
+
ack.settleReject(terminalError(failure));
|
|
84
|
+
return { waitSubmitted: () => ack.wait() };
|
|
85
|
+
}
|
|
86
|
+
const waiter = waiters.shift();
|
|
87
|
+
if (waiter) {
|
|
88
|
+
// Consumer is already inside next() (previous yield already acked at entry).
|
|
89
|
+
pullCount += 1;
|
|
90
|
+
pendingYieldAck = ack;
|
|
91
|
+
onYield?.(message);
|
|
92
|
+
waiter.resolve({ value: message, done: false });
|
|
93
|
+
return { waitSubmitted: () => ack.wait() };
|
|
94
|
+
}
|
|
95
|
+
queue.push({ message, ack });
|
|
96
|
+
return { waitSubmitted: () => ack.wait() };
|
|
97
|
+
},
|
|
98
|
+
end(error) {
|
|
99
|
+
if (closed)
|
|
100
|
+
return;
|
|
101
|
+
closed = true;
|
|
102
|
+
if (error !== undefined) {
|
|
103
|
+
failure = error;
|
|
104
|
+
// Failure: reject every unresolved ack (yielded + still queued) so enqueue cannot hang.
|
|
105
|
+
rejectUnresolvedAcks(error);
|
|
106
|
+
while (waiters.length > 0) {
|
|
107
|
+
waiters.shift().reject(failure);
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Clean end: leave queued messages readable for a late consumer drain.
|
|
112
|
+
// Only reject a yielded-but-not-post-acked message (no further next() will ack it
|
|
113
|
+
// if the consumer has already stopped). If a consumer is parked, they get done
|
|
114
|
+
// after any remaining queue is taken on subsequent next() calls — parked waiters
|
|
115
|
+
// here mean queue is empty, so resolve done.
|
|
116
|
+
if (pendingYieldAck) {
|
|
117
|
+
pendingYieldAck.settleReject(terminalError());
|
|
118
|
+
pendingYieldAck = undefined;
|
|
119
|
+
}
|
|
120
|
+
while (waiters.length > 0) {
|
|
121
|
+
waiters.shift().resolve({ value: DONE_SENTINEL, done: true });
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
iterable: {
|
|
125
|
+
[Symbol.asyncIterator]() {
|
|
126
|
+
return {
|
|
127
|
+
next() {
|
|
128
|
+
// Per-yield submitted fence: next entry acks the previously yielded message.
|
|
129
|
+
acknowledgePreviousYield();
|
|
130
|
+
if (queue.length > 0) {
|
|
131
|
+
return Promise.resolve(yieldQueued(queue.shift()));
|
|
132
|
+
}
|
|
133
|
+
if (failure !== undefined) {
|
|
134
|
+
return Promise.reject(failure);
|
|
135
|
+
}
|
|
136
|
+
if (closed) {
|
|
137
|
+
return Promise.resolve({ value: DONE_SENTINEL, done: true });
|
|
138
|
+
}
|
|
139
|
+
return new Promise((resolve, reject) => {
|
|
140
|
+
waiters.push({ resolve, reject });
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
export function toClaudeUserMessage(text) {
|
|
149
|
+
return {
|
|
150
|
+
type: "user",
|
|
151
|
+
message: {
|
|
152
|
+
role: "user",
|
|
153
|
+
content: text,
|
|
154
|
+
},
|
|
155
|
+
parent_tool_use_id: null,
|
|
156
|
+
session_id: "",
|
|
157
|
+
};
|
|
158
|
+
}
|