@alpacakit/agents 0.2.0-beta.2 → 0.2.0-beta.3
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 +21 -0
- package/dist/agents/builtin.d.ts +2 -2
- package/dist/agents/builtin.d.ts.map +1 -1
- package/dist/agents/builtin.js +6 -4
- package/dist/agents/claude/cli.d.ts +133 -0
- package/dist/agents/claude/cli.d.ts.map +1 -0
- package/dist/agents/{claude-stream.js → claude/cli.js} +81 -10
- package/dist/agents/claude/host.d.ts +14 -0
- package/dist/agents/claude/host.d.ts.map +1 -0
- package/dist/agents/{claude.js → claude/host.js} +51 -174
- package/dist/agents/{claude.d.ts → claude/index.d.ts} +10 -11
- package/dist/agents/claude/index.d.ts.map +1 -0
- package/dist/agents/claude/index.js +134 -0
- package/dist/agents/{claude-session.d.ts → claude/session.d.ts} +3 -15
- package/dist/agents/claude/session.d.ts.map +1 -0
- package/dist/agents/claude/session.js +321 -0
- package/dist/agents/codex/cli.d.ts +132 -0
- package/dist/agents/codex/cli.d.ts.map +1 -0
- package/dist/agents/codex/cli.js +110 -0
- package/dist/agents/codex/host.d.ts +14 -0
- package/dist/agents/codex/host.d.ts.map +1 -0
- package/dist/agents/codex/host.js +221 -0
- package/dist/agents/codex/index.d.ts +14 -0
- package/dist/agents/codex/index.d.ts.map +1 -0
- package/dist/agents/codex/index.js +127 -0
- package/dist/agents/codex/session.d.ts +21 -0
- package/dist/agents/codex/session.d.ts.map +1 -0
- package/dist/agents/codex/session.js +390 -0
- package/dist/agents/openai-compatible/fetch-engine.d.ts.map +1 -1
- package/dist/agents/openai-compatible/fetch-engine.js +3 -2
- package/dist/agents/openai-compatible/pi/engine.js +1 -1
- package/dist/agents/openai-compatible/pi/{session.d.ts → run.d.ts} +1 -1
- package/dist/agents/openai-compatible/pi/run.d.ts.map +1 -0
- package/dist/agents/openai-compatible/pi/sandbox.d.ts.map +1 -1
- package/dist/auth/login-probe.d.ts +6 -4
- package/dist/auth/login-probe.d.ts.map +1 -1
- package/dist/auth/login-probe.js +19 -13
- package/dist/auth/material.d.ts +1 -1
- package/dist/auth/material.d.ts.map +1 -1
- package/dist/codex/app-server.d.ts.map +1 -1
- package/dist/codex/app-server.js +13 -42
- package/dist/codex/index.d.ts +1 -1
- package/dist/codex/index.d.ts.map +1 -1
- package/dist/config/agent-config-validation.d.ts +1 -1
- package/dist/config/agent-config-validation.d.ts.map +1 -1
- package/dist/config/agent-configs.d.ts.map +1 -1
- package/dist/config/agent-configs.js +3 -3
- package/dist/config/compose.d.ts.map +1 -1
- package/dist/config/config.d.ts +1 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/model.d.ts +0 -1
- package/dist/config/model.d.ts.map +1 -1
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +1 -1
- package/dist/config/store.d.ts.map +1 -1
- package/dist/config/store.js +6 -24
- package/dist/config/support.d.ts +0 -1
- package/dist/config/support.d.ts.map +1 -1
- package/dist/config/support.js +0 -9
- package/dist/core/cli-child.d.ts +56 -0
- package/dist/core/cli-child.d.ts.map +1 -0
- package/dist/core/cli-child.js +105 -0
- package/dist/core/fs.d.ts +1 -1
- package/dist/core/fs.d.ts.map +1 -1
- package/dist/core/fs.js +10 -2
- package/dist/core/node-ports.d.ts.map +1 -1
- package/dist/core/node-ports.js +1 -5
- package/dist/core/session.d.ts +4 -0
- package/dist/core/session.d.ts.map +1 -1
- package/dist/fleet/store.d.ts.map +1 -1
- package/dist/fleet/store.js +4 -3
- package/dist/host/availability.d.ts +2 -1
- package/dist/host/availability.d.ts.map +1 -1
- package/dist/host/github-dir.d.ts.map +1 -1
- package/dist/host/github-dir.js +2 -1
- package/dist/host/mcp-list.d.ts.map +1 -1
- package/dist/host/mcp-list.js +5 -6
- package/dist/host/run-command.d.ts +2 -1
- package/dist/host/run-command.d.ts.map +1 -1
- package/dist/host/run-command.js +10 -19
- package/dist/host/session-files.d.ts +2 -1
- package/dist/host/session-files.d.ts.map +1 -1
- package/dist/host/session-files.js +2 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/kernel/classify.d.ts +1 -2
- package/dist/kernel/classify.d.ts.map +1 -1
- package/dist/kernel/classify.js +1 -1
- package/dist/kernel/cli-agent.d.ts.map +1 -1
- package/dist/kernel/cli-agent.js +26 -85
- package/dist/kernel/cli-login.d.ts.map +1 -1
- package/dist/kernel/cli-login.js +9 -30
- package/dist/kernel/facets.d.ts +1 -1
- package/dist/kernel/facets.d.ts.map +1 -1
- package/dist/kernel/login.d.ts.map +1 -1
- package/dist/kernel/login.js +2 -1
- package/dist/kernel/options.d.ts +1 -1
- package/dist/kernel/options.d.ts.map +1 -1
- package/dist/kernel/run.d.ts.map +1 -1
- package/dist/kernel/run.js +2 -1
- package/dist/kernel/session.d.ts +46 -39
- package/dist/kernel/session.d.ts.map +1 -1
- package/dist/kernel/session.js +128 -69
- package/dist/testing/fake-exec.d.ts +9 -10
- package/dist/testing/fake-exec.d.ts.map +1 -1
- package/dist/testing/fake-exec.js +14 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -1
- package/package.json +2 -2
- package/dist/agents/claude-session.d.ts.map +0 -1
- package/dist/agents/claude-session.js +0 -419
- package/dist/agents/claude-stream.d.ts +0 -65
- package/dist/agents/claude-stream.d.ts.map +0 -1
- package/dist/agents/claude.d.ts.map +0 -1
- package/dist/agents/codex-session.d.ts +0 -52
- package/dist/agents/codex-session.d.ts.map +0 -1
- package/dist/agents/codex-session.js +0 -495
- package/dist/agents/codex.d.ts +0 -20
- package/dist/agents/codex.d.ts.map +0 -1
- package/dist/agents/codex.js +0 -379
- package/dist/agents/openai-compatible/pi/session.d.ts.map +0 -1
- package/dist/core/process-close.d.ts +0 -11
- package/dist/core/process-close.d.ts.map +0 -1
- package/dist/core/process-close.js +0 -27
- /package/dist/agents/openai-compatible/pi/{session.js → run.js} +0 -0
|
@@ -1,419 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude session adapter: one `claude -p --input-format stream-json
|
|
3
|
-
* --output-format stream-json` process held open across turns.
|
|
4
|
-
*
|
|
5
|
-
* Protocol facts (claude 2.1.270, T52 / T61 lab runs):
|
|
6
|
-
* - a turn is one user line `{"type":"user","message":{"role":"user","content":…}}`
|
|
7
|
-
* and ends with the `result` line; a user line written mid-turn is absorbed
|
|
8
|
-
* into the running turn at its next tool boundary (`steer`);
|
|
9
|
-
* - `{"type":"control_request","request_id":…,"request":{"subtype":"interrupt"}}`
|
|
10
|
-
* is answered by a `control_response`, and the turn then ends with
|
|
11
|
-
* `is_error: true` / `terminal_reason: "aborted_tools"`;
|
|
12
|
-
* - approval prompts reach stdout only with `--permission-prompt-tool stdio`, as
|
|
13
|
-
* `control_request` / `can_use_tool`, and are answered with a
|
|
14
|
-
* `control_response` whose `behavior` is `allow` (+ `updatedInput`) or `deny`;
|
|
15
|
-
* - `--session-id <uuid>` fixes the id before the first turn (no `init` line
|
|
16
|
-
* is emitted until then), `--resume <id>` continues a recorded one;
|
|
17
|
-
* - the child needs `USER` in its env: without it the CLI reports "Not logged in".
|
|
18
|
-
*/
|
|
19
|
-
import { randomUUID } from "node:crypto";
|
|
20
|
-
import path from "node:path";
|
|
21
|
-
import { AGENT_ERROR_CODE, AgentError, TIMEOUT_KIND } from "../core/error.js";
|
|
22
|
-
import { readJsonRecord, readNumber, readRecord, readString, } from "../core/json.js";
|
|
23
|
-
import { redactSecrets } from "../core/redact.js";
|
|
24
|
-
import { AGENT_EVENT_TYPE } from "../core/run.js";
|
|
25
|
-
import { APPROVAL_DECISION, SESSION_EVENT_TYPE, SESSION_OWNER_KIND, TURN_OUTCOME, } from "../core/session.js";
|
|
26
|
-
import { fileExists, readDirectoryNames, readJsonFile, scanJsonlFirstLast, } from "../host/session-files.js";
|
|
27
|
-
import { assertHostSessionId, SessionProcess, SessionState, sessionStateError, } from "../kernel/session.js";
|
|
28
|
-
import { CLAUDE, parseClaudeLine } from "./claude-stream.js";
|
|
29
|
-
export const CLAUDE_PERMISSION_MODE = {
|
|
30
|
-
default: "default",
|
|
31
|
-
acceptEdits: "acceptEdits",
|
|
32
|
-
auto: "auto",
|
|
33
|
-
bypassPermissions: "bypassPermissions",
|
|
34
|
-
dontAsk: "dontAsk",
|
|
35
|
-
plan: "plan",
|
|
36
|
-
};
|
|
37
|
-
const CLAUDE_SESSION = {
|
|
38
|
-
cli: {
|
|
39
|
-
inputFormat: "--input-format",
|
|
40
|
-
permissionPromptTool: "--permission-prompt-tool",
|
|
41
|
-
stdio: "stdio",
|
|
42
|
-
resume: "--resume",
|
|
43
|
-
sessionId: "--session-id",
|
|
44
|
-
allowDangerouslySkipPermissions: "--allow-dangerously-skip-permissions",
|
|
45
|
-
/** The CLI spells the transcript's `default` mode `manual` on its flag. */
|
|
46
|
-
manualPermissionMode: "manual",
|
|
47
|
-
},
|
|
48
|
-
stream: {
|
|
49
|
-
type: {
|
|
50
|
-
user: "user",
|
|
51
|
-
assistant: "assistant",
|
|
52
|
-
result: "result",
|
|
53
|
-
controlRequest: "control_request",
|
|
54
|
-
controlResponse: "control_response",
|
|
55
|
-
},
|
|
56
|
-
field: {
|
|
57
|
-
type: "type",
|
|
58
|
-
message: "message",
|
|
59
|
-
role: "role",
|
|
60
|
-
content: "content",
|
|
61
|
-
request: "request",
|
|
62
|
-
requestId: "request_id",
|
|
63
|
-
response: "response",
|
|
64
|
-
subtype: "subtype",
|
|
65
|
-
error: "error",
|
|
66
|
-
toolName: "tool_name",
|
|
67
|
-
description: "description",
|
|
68
|
-
input: "input",
|
|
69
|
-
isError: "is_error",
|
|
70
|
-
result: "result",
|
|
71
|
-
behavior: "behavior",
|
|
72
|
-
updatedInput: "updatedInput",
|
|
73
|
-
},
|
|
74
|
-
subtype: {
|
|
75
|
-
interrupt: "interrupt",
|
|
76
|
-
canUseTool: "can_use_tool",
|
|
77
|
-
success: "success",
|
|
78
|
-
error: "error",
|
|
79
|
-
},
|
|
80
|
-
behavior: { allow: "allow", deny: "deny" },
|
|
81
|
-
},
|
|
82
|
-
files: {
|
|
83
|
-
root: ".claude",
|
|
84
|
-
projects: "projects",
|
|
85
|
-
sessions: "sessions",
|
|
86
|
-
transcriptExtension: ".jsonl",
|
|
87
|
-
registryExtension: ".json",
|
|
88
|
-
cwd: "cwd",
|
|
89
|
-
permissionMode: "permissionMode",
|
|
90
|
-
sessionId: "sessionId",
|
|
91
|
-
pid: "pid",
|
|
92
|
-
entrypoint: "entrypoint",
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
const CONTROL_RESPONSE_TIMEOUT_MS = 30_000;
|
|
96
|
-
const DECLINED_MESSAGE = "Declined by the session owner";
|
|
97
|
-
const CLAUDE_APPROVAL_DECISIONS = [
|
|
98
|
-
APPROVAL_DECISION.accept,
|
|
99
|
-
APPROVAL_DECISION.decline,
|
|
100
|
-
];
|
|
101
|
-
function sessionArgs(permissions, target, options) {
|
|
102
|
-
const mode = permissions.mode === CLAUDE_PERMISSION_MODE.default
|
|
103
|
-
? CLAUDE_SESSION.cli.manualPermissionMode
|
|
104
|
-
: permissions.mode;
|
|
105
|
-
return [
|
|
106
|
-
CLAUDE.cli.prompt,
|
|
107
|
-
CLAUDE_SESSION.cli.inputFormat,
|
|
108
|
-
CLAUDE.cli.streamJson,
|
|
109
|
-
CLAUDE.cli.outputFormat,
|
|
110
|
-
CLAUDE.cli.streamJson,
|
|
111
|
-
CLAUDE.cli.verbose,
|
|
112
|
-
CLAUDE.cli.permissionMode,
|
|
113
|
-
mode,
|
|
114
|
-
...(permissions.mode === CLAUDE_PERMISSION_MODE.bypassPermissions
|
|
115
|
-
? [CLAUDE_SESSION.cli.allowDangerouslySkipPermissions]
|
|
116
|
-
: []),
|
|
117
|
-
CLAUDE_SESSION.cli.permissionPromptTool,
|
|
118
|
-
CLAUDE_SESSION.cli.stdio,
|
|
119
|
-
// A session's whole point is the recorded conversation, so `disabled`
|
|
120
|
-
// drops only the customization flags, never `--no-session-persistence`.
|
|
121
|
-
...(options.customizations === "disabled"
|
|
122
|
-
? [CLAUDE.cli.safeMode, CLAUDE.cli.strictMcpConfig]
|
|
123
|
-
: []),
|
|
124
|
-
target.kind === "resume"
|
|
125
|
-
? CLAUDE_SESSION.cli.resume
|
|
126
|
-
: CLAUDE_SESSION.cli.sessionId,
|
|
127
|
-
target.sessionId,
|
|
128
|
-
];
|
|
129
|
-
}
|
|
130
|
-
class ClaudeSession {
|
|
131
|
-
id;
|
|
132
|
-
process;
|
|
133
|
-
ctx;
|
|
134
|
-
state = new SessionState(CLAUDE.id);
|
|
135
|
-
pendingApprovals = new Map();
|
|
136
|
-
pendingControls = new Map();
|
|
137
|
-
reading;
|
|
138
|
-
turnCount = 0;
|
|
139
|
-
interruptRequested = false;
|
|
140
|
-
constructor(id, process, ctx) {
|
|
141
|
-
this.id = id;
|
|
142
|
-
this.process = process;
|
|
143
|
-
this.ctx = ctx;
|
|
144
|
-
this.reading = this.read();
|
|
145
|
-
}
|
|
146
|
-
get events() {
|
|
147
|
-
return this.state.events;
|
|
148
|
-
}
|
|
149
|
-
async send(text) {
|
|
150
|
-
this.state.requireIdle();
|
|
151
|
-
this.turnCount += 1;
|
|
152
|
-
const turn = this.state.beginTurn(String(this.turnCount));
|
|
153
|
-
this.writeUserLine(text);
|
|
154
|
-
return turn;
|
|
155
|
-
}
|
|
156
|
-
async steer(text) {
|
|
157
|
-
this.state.requireActive();
|
|
158
|
-
this.writeUserLine(text);
|
|
159
|
-
}
|
|
160
|
-
async interrupt() {
|
|
161
|
-
this.state.requireActive();
|
|
162
|
-
const requestId = randomUUID();
|
|
163
|
-
this.interruptRequested = true;
|
|
164
|
-
const answered = this.awaitControlResponse(requestId);
|
|
165
|
-
this.process.writeLine(JSON.stringify({
|
|
166
|
-
type: CLAUDE_SESSION.stream.type.controlRequest,
|
|
167
|
-
[CLAUDE_SESSION.stream.field.requestId]: requestId,
|
|
168
|
-
request: { subtype: CLAUDE_SESSION.stream.subtype.interrupt },
|
|
169
|
-
}));
|
|
170
|
-
try {
|
|
171
|
-
await answered;
|
|
172
|
-
}
|
|
173
|
-
catch (error) {
|
|
174
|
-
// An unanswered interrupt must not color the next turn's outcome.
|
|
175
|
-
this.interruptRequested = false;
|
|
176
|
-
throw error;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
async respond(requestId, decision) {
|
|
180
|
-
this.state.requireOpen();
|
|
181
|
-
if (!this.pendingApprovals.has(requestId)) {
|
|
182
|
-
throw sessionStateError(CLAUDE.id, `no pending approval request "${requestId}"`);
|
|
183
|
-
}
|
|
184
|
-
const input = this.pendingApprovals.get(requestId);
|
|
185
|
-
this.pendingApprovals.delete(requestId);
|
|
186
|
-
const response = decision === APPROVAL_DECISION.accept
|
|
187
|
-
? {
|
|
188
|
-
behavior: CLAUDE_SESSION.stream.behavior.allow,
|
|
189
|
-
updatedInput: input,
|
|
190
|
-
}
|
|
191
|
-
: {
|
|
192
|
-
behavior: CLAUDE_SESSION.stream.behavior.deny,
|
|
193
|
-
message: DECLINED_MESSAGE,
|
|
194
|
-
};
|
|
195
|
-
this.process.writeLine(JSON.stringify({
|
|
196
|
-
type: CLAUDE_SESSION.stream.type.controlResponse,
|
|
197
|
-
response: {
|
|
198
|
-
subtype: CLAUDE_SESSION.stream.subtype.success,
|
|
199
|
-
[CLAUDE_SESSION.stream.field.requestId]: requestId,
|
|
200
|
-
response,
|
|
201
|
-
},
|
|
202
|
-
}));
|
|
203
|
-
}
|
|
204
|
-
async close() {
|
|
205
|
-
await this.process.close();
|
|
206
|
-
await this.reading;
|
|
207
|
-
}
|
|
208
|
-
writeUserLine(text) {
|
|
209
|
-
this.process.writeLine(JSON.stringify({
|
|
210
|
-
type: CLAUDE_SESSION.stream.type.user,
|
|
211
|
-
message: { role: CLAUDE_SESSION.stream.type.user, content: text },
|
|
212
|
-
}));
|
|
213
|
-
}
|
|
214
|
-
awaitControlResponse(requestId) {
|
|
215
|
-
return new Promise((resolve, reject) => {
|
|
216
|
-
const cancelTimeout = this.ctx.clock.setTimeout(() => {
|
|
217
|
-
this.pendingControls.delete(requestId);
|
|
218
|
-
reject(new AgentError({
|
|
219
|
-
code: AGENT_ERROR_CODE.timeout,
|
|
220
|
-
classification: AgentError.agentFailure(AGENT_ERROR_CODE.timeout),
|
|
221
|
-
message: "Claude did not answer the control request in time",
|
|
222
|
-
data: {
|
|
223
|
-
kind: TIMEOUT_KIND.total,
|
|
224
|
-
limitMs: CONTROL_RESPONSE_TIMEOUT_MS,
|
|
225
|
-
},
|
|
226
|
-
agentId: CLAUDE.id,
|
|
227
|
-
}));
|
|
228
|
-
}, CONTROL_RESPONSE_TIMEOUT_MS);
|
|
229
|
-
this.pendingControls.set(requestId, { resolve, reject, cancelTimeout });
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
async read() {
|
|
233
|
-
try {
|
|
234
|
-
for await (const line of this.process.lines()) {
|
|
235
|
-
const record = readJsonRecord(line);
|
|
236
|
-
if (record !== null) {
|
|
237
|
-
this.handleRecord(record, line);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
catch (error) {
|
|
242
|
-
this.ctx.logger.log("error", "claude session reader failed", error);
|
|
243
|
-
}
|
|
244
|
-
finally {
|
|
245
|
-
// Whatever happened above, the stream must end so `events` consumers
|
|
246
|
-
// and `close()` are released.
|
|
247
|
-
const exit = await this.process.exit;
|
|
248
|
-
for (const pending of this.pendingControls.values()) {
|
|
249
|
-
pending.cancelTimeout();
|
|
250
|
-
pending.reject(sessionStateError(CLAUDE.id, "session process exited"));
|
|
251
|
-
}
|
|
252
|
-
this.pendingControls.clear();
|
|
253
|
-
this.pendingApprovals.clear();
|
|
254
|
-
this.interruptRequested = false;
|
|
255
|
-
this.state.end(exit, this.process.stderr);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
handleRecord(record, line) {
|
|
259
|
-
const type = readString(record, CLAUDE_SESSION.stream.field.type);
|
|
260
|
-
if (type === CLAUDE_SESSION.stream.type.assistant) {
|
|
261
|
-
for (const event of parseClaudeLine(line)) {
|
|
262
|
-
if (event.type === AGENT_EVENT_TYPE.message) {
|
|
263
|
-
this.state.message(event.text);
|
|
264
|
-
}
|
|
265
|
-
else if (event.type === AGENT_EVENT_TYPE.tool) {
|
|
266
|
-
this.state.emit({ type: SESSION_EVENT_TYPE.tool, name: event.name });
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
if (type === CLAUDE_SESSION.stream.type.result) {
|
|
272
|
-
this.handleResult(record);
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
if (type === CLAUDE_SESSION.stream.type.controlRequest) {
|
|
276
|
-
this.handleControlRequest(record);
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
if (type === CLAUDE_SESSION.stream.type.controlResponse) {
|
|
280
|
-
this.handleControlResponse(record);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
handleResult(record) {
|
|
284
|
-
const isError = record[CLAUDE_SESSION.stream.field.isError] === true;
|
|
285
|
-
const outcome = this.interruptRequested
|
|
286
|
-
? TURN_OUTCOME.interrupted
|
|
287
|
-
: isError
|
|
288
|
-
? TURN_OUTCOME.failed
|
|
289
|
-
: TURN_OUTCOME.completed;
|
|
290
|
-
this.interruptRequested = false;
|
|
291
|
-
// Approval requests belong to the turn that raised them.
|
|
292
|
-
this.pendingApprovals.clear();
|
|
293
|
-
this.state.endTurn(outcome, readString(record, CLAUDE_SESSION.stream.field.result));
|
|
294
|
-
}
|
|
295
|
-
handleControlRequest(record) {
|
|
296
|
-
const requestId = readString(record, CLAUDE_SESSION.stream.field.requestId);
|
|
297
|
-
const request = readRecord(record, CLAUDE_SESSION.stream.field.request);
|
|
298
|
-
const subtype = request === null
|
|
299
|
-
? null
|
|
300
|
-
: readString(request, CLAUDE_SESSION.stream.field.subtype);
|
|
301
|
-
if (requestId === null || request === null) {
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
if (subtype !== CLAUDE_SESSION.stream.subtype.canUseTool) {
|
|
305
|
-
this.ctx.logger.log("warn", `ignoring unsupported claude control request "${subtype ?? "?"}"`);
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
this.pendingApprovals.set(requestId, request[CLAUDE_SESSION.stream.field.input]);
|
|
309
|
-
const toolName = readString(request, CLAUDE_SESSION.stream.field.toolName) ?? "";
|
|
310
|
-
const description = readString(request, CLAUDE_SESSION.stream.field.description);
|
|
311
|
-
this.state.emit({
|
|
312
|
-
type: SESSION_EVENT_TYPE.approvalRequested,
|
|
313
|
-
requestId,
|
|
314
|
-
summary: description === null ? toolName : `${toolName} ${description}`,
|
|
315
|
-
decisions: CLAUDE_APPROVAL_DECISIONS,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
handleControlResponse(record) {
|
|
319
|
-
const response = readRecord(record, CLAUDE_SESSION.stream.field.response);
|
|
320
|
-
const requestId = response === null
|
|
321
|
-
? null
|
|
322
|
-
: readString(response, CLAUDE_SESSION.stream.field.requestId);
|
|
323
|
-
if (response === null || requestId === null) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
const pending = this.pendingControls.get(requestId);
|
|
327
|
-
if (pending === undefined) {
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
this.pendingControls.delete(requestId);
|
|
331
|
-
pending.cancelTimeout();
|
|
332
|
-
if (readString(response, CLAUDE_SESSION.stream.field.subtype) ===
|
|
333
|
-
CLAUDE_SESSION.stream.subtype.error) {
|
|
334
|
-
pending.reject(sessionStateError(CLAUDE.id, redactSecrets(readString(response, CLAUDE_SESSION.stream.field.error) ??
|
|
335
|
-
"control request failed")));
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
pending.resolve();
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
async function openClaudeSession(target, options, ctx, sessionOptions) {
|
|
342
|
-
const process = await SessionProcess.spawn({
|
|
343
|
-
command: CLAUDE.command,
|
|
344
|
-
args: sessionArgs(options.permissions, target, sessionOptions),
|
|
345
|
-
cwd: options.workspace,
|
|
346
|
-
ctx,
|
|
347
|
-
agentId: CLAUDE.id,
|
|
348
|
-
});
|
|
349
|
-
return new ClaudeSession(target.sessionId, process, ctx);
|
|
350
|
-
}
|
|
351
|
-
function claudeRoot(ctx, ...segments) {
|
|
352
|
-
return path.join(ctx.location.homeDir, CLAUDE_SESSION.files.root, ...segments);
|
|
353
|
-
}
|
|
354
|
-
/** `~/.claude/projects/<encoded cwd>/<id>.jsonl` — the project directory name is not derivable, so scan. */
|
|
355
|
-
async function findClaudeTranscript(ctx, id) {
|
|
356
|
-
const root = claudeRoot(ctx, CLAUDE_SESSION.files.projects);
|
|
357
|
-
for (const project of await readDirectoryNames(root)) {
|
|
358
|
-
const candidate = path.join(root, project, `${id}${CLAUDE_SESSION.files.transcriptExtension}`);
|
|
359
|
-
if (await fileExists(candidate)) {
|
|
360
|
-
return candidate;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
return null;
|
|
364
|
-
}
|
|
365
|
-
/** `~/.claude/sessions/<pid>.json` — one file per live CLI process, keyed by pid. */
|
|
366
|
-
async function claudeRegistryOwner(ctx, id) {
|
|
367
|
-
const root = claudeRoot(ctx, CLAUDE_SESSION.files.sessions);
|
|
368
|
-
for (const name of await readDirectoryNames(root)) {
|
|
369
|
-
if (!name.endsWith(CLAUDE_SESSION.files.registryExtension)) {
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
const entry = await readJsonFile(path.join(root, name));
|
|
373
|
-
if (entry === null ||
|
|
374
|
-
readString(entry, CLAUDE_SESSION.files.sessionId) !== id) {
|
|
375
|
-
continue;
|
|
376
|
-
}
|
|
377
|
-
return {
|
|
378
|
-
kind: SESSION_OWNER_KIND.process,
|
|
379
|
-
pid: readNumber(entry, CLAUDE_SESSION.files.pid),
|
|
380
|
-
entrypoint: readString(entry, CLAUDE_SESSION.files.entrypoint),
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
return { kind: SESSION_OWNER_KIND.none };
|
|
384
|
-
}
|
|
385
|
-
function permissionModeFrom(value) {
|
|
386
|
-
return value !== null &&
|
|
387
|
-
Object.values(CLAUDE_PERMISSION_MODE).includes(value)
|
|
388
|
-
? value
|
|
389
|
-
: null;
|
|
390
|
-
}
|
|
391
|
-
async function inspectClaudeSession(id, ctx) {
|
|
392
|
-
assertHostSessionId(id, CLAUDE.id);
|
|
393
|
-
const transcript = await findClaudeTranscript(ctx, id);
|
|
394
|
-
if (transcript === null) {
|
|
395
|
-
return null;
|
|
396
|
-
}
|
|
397
|
-
const cwd = await scanJsonlFirstLast(transcript, (record) => readString(record, CLAUDE_SESSION.files.cwd));
|
|
398
|
-
if (cwd.first === null) {
|
|
399
|
-
return null;
|
|
400
|
-
}
|
|
401
|
-
const modes = await scanJsonlFirstLast(transcript, (record) => readString(record, CLAUDE_SESSION.files.permissionMode));
|
|
402
|
-
const mode = permissionModeFrom(modes.last);
|
|
403
|
-
return {
|
|
404
|
-
workspace: cwd.first,
|
|
405
|
-
lastPermissions: mode === null ? null : { mode },
|
|
406
|
-
owner: await claudeRegistryOwner(ctx, id),
|
|
407
|
-
archived: false,
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
export function claudeSessions(options) {
|
|
411
|
-
return {
|
|
412
|
-
open: (resolved, ctx) => openClaudeSession({ kind: "new", sessionId: randomUUID() }, resolved, ctx, options),
|
|
413
|
-
resume: async (id, resolved, ctx) => {
|
|
414
|
-
assertHostSessionId(id, CLAUDE.id);
|
|
415
|
-
return openClaudeSession({ kind: "resume", sessionId: id }, resolved, ctx, options);
|
|
416
|
-
},
|
|
417
|
-
inspect: inspectClaudeSession,
|
|
418
|
-
};
|
|
419
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude CLI stream-json vocabulary and line readers, shared by the
|
|
3
|
-
* one-shot run adapter (`claude.ts`) and the long-lived session adapter
|
|
4
|
-
* (`claude-session.ts`): one place spells the CLI's flags and the NDJSON
|
|
5
|
-
* field names both of them read.
|
|
6
|
-
*/
|
|
7
|
-
import type { AgentEvent } from "../core/run.js";
|
|
8
|
-
import type { CliResultCapture } from "../kernel/cli-agent.js";
|
|
9
|
-
export declare const CLAUDE: {
|
|
10
|
-
readonly id: "claude";
|
|
11
|
-
readonly command: "claude";
|
|
12
|
-
readonly cli: {
|
|
13
|
-
readonly prompt: "-p";
|
|
14
|
-
readonly model: "--model";
|
|
15
|
-
readonly effort: "--effort";
|
|
16
|
-
readonly outputFormat: "--output-format";
|
|
17
|
-
readonly streamJson: "stream-json";
|
|
18
|
-
readonly permissionMode: "--permission-mode";
|
|
19
|
-
readonly bypassPermissions: "bypassPermissions";
|
|
20
|
-
readonly defaultPermissionMode: "default";
|
|
21
|
-
readonly verbose: "--verbose";
|
|
22
|
-
readonly tools: "--tools";
|
|
23
|
-
readonly allowedTools: "--allowedTools";
|
|
24
|
-
readonly safeMode: "--safe-mode";
|
|
25
|
-
readonly strictMcpConfig: "--strict-mcp-config";
|
|
26
|
-
readonly noSessionPersistence: "--no-session-persistence";
|
|
27
|
-
};
|
|
28
|
-
readonly auth: {
|
|
29
|
-
readonly statusArgs: readonly ["auth", "status", "--json"];
|
|
30
|
-
readonly loginArgs: readonly ["auth", "login", "--claudeai"];
|
|
31
|
-
};
|
|
32
|
-
readonly mcp: {
|
|
33
|
-
readonly addJson: "add-json";
|
|
34
|
-
readonly mcp: "mcp";
|
|
35
|
-
readonly remove: "remove";
|
|
36
|
-
readonly scope: "--scope";
|
|
37
|
-
};
|
|
38
|
-
readonly plugin: {
|
|
39
|
-
readonly plugin: "plugin";
|
|
40
|
-
readonly install: "install";
|
|
41
|
-
};
|
|
42
|
-
readonly json: {
|
|
43
|
-
readonly field: {
|
|
44
|
-
readonly type: "type";
|
|
45
|
-
readonly message: "message";
|
|
46
|
-
readonly content: "content";
|
|
47
|
-
readonly text: "text";
|
|
48
|
-
readonly name: "name";
|
|
49
|
-
readonly usage: "usage";
|
|
50
|
-
readonly result: "result";
|
|
51
|
-
readonly inputTokens: "input_tokens";
|
|
52
|
-
readonly outputTokens: "output_tokens";
|
|
53
|
-
readonly totalCost: "total_cost_usd";
|
|
54
|
-
};
|
|
55
|
-
readonly type: {
|
|
56
|
-
readonly assistant: "assistant";
|
|
57
|
-
readonly result: "result";
|
|
58
|
-
readonly text: "text";
|
|
59
|
-
readonly toolUse: "tool_use";
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
export declare function parseClaudeLine(line: string): AgentEvent[];
|
|
64
|
-
export declare function parseClaudeResult(line: string): CliResultCapture | null;
|
|
65
|
-
//# sourceMappingURL=claude-stream.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-stream.d.ts","sourceRoot":"","sources":["../../src/agents/claude-stream.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EAAE,UAAU,EAAY,MAAM,gBAAgB,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDT,CAAC;AAEX,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CAkC1D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAkBvE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4CH,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EACL,KAAK,wBAAwB,EAE9B,MAAM,qBAAqB,CAAC;AAG7B,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAC7D,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAwD1D;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI,cAAc,CA0CvD;AA6TD,MAAM,MAAM,aAAa,GAAG;IAC1B;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CAClD,CAAC;AAEF,wBAAgB,MAAM,CACpB,OAAO,GAAE,aAAkB,GAC1B,eAAe,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAiFrD"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Codex session adapter: one `codex app-server` process holding one thread.
|
|
3
|
-
*
|
|
4
|
-
* Protocol facts (codex 0.153.4, T53 / T57 / T61 lab runs):
|
|
5
|
-
* - `thread/start {cwd, sandbox, approvalPolicy, approvalsReviewer}` creates
|
|
6
|
-
* the thread and takes its writer lock; with a writable sandbox Codex also
|
|
7
|
-
* appends a `trust_level` entry for `cwd` to `~/.codex/config.toml`;
|
|
8
|
-
* - `thread/resume` must repeat the permissions — without `sandbox` the
|
|
9
|
-
* resumed turns ran as danger-full-access; it answers -32600 "already has
|
|
10
|
-
* an active writer" while another process holds the thread and -32600
|
|
11
|
-
* "… is archived" for an archived one (`thread/unarchive` first, opt-in);
|
|
12
|
-
* - `turn/start` answers the turn id at once; `turn/steer {expectedTurnId}`
|
|
13
|
-
* appends to it; `turn/interrupt` ends it with `turn/completed`
|
|
14
|
-
* status `interrupted` (the command's own `item/completed` may trail by ~36 s);
|
|
15
|
-
* - `item/commandExecution/requestApproval` is a server request answered by
|
|
16
|
-
* `{"decision": "accept" | "decline"}`; closing stdin releases the lock.
|
|
17
|
-
*/
|
|
18
|
-
import { CODEX_SANDBOX_MODE } from "../codex/protocol.js";
|
|
19
|
-
export type { CodexSandboxMode } from "../codex/protocol.js";
|
|
20
|
-
import { type SessionCapability } from "../kernel/session.js";
|
|
21
|
-
/** `approval_policy` words (codex 0.153.4 `AskForApproval`; the granular object form is not modeled). */
|
|
22
|
-
export declare const CODEX_APPROVAL_POLICY: {
|
|
23
|
-
readonly untrusted: "untrusted";
|
|
24
|
-
readonly onRequest: "on-request";
|
|
25
|
-
readonly never: "never";
|
|
26
|
-
};
|
|
27
|
-
export type CodexApprovalPolicy = (typeof CODEX_APPROVAL_POLICY)[keyof typeof CODEX_APPROVAL_POLICY];
|
|
28
|
-
export declare const CODEX_APPROVALS_REVIEWER: {
|
|
29
|
-
readonly user: "user";
|
|
30
|
-
readonly autoReview: "auto_review";
|
|
31
|
-
readonly guardianSubagent: "guardian_subagent";
|
|
32
|
-
};
|
|
33
|
-
export type CodexApprovalsReviewer = (typeof CODEX_APPROVALS_REVIEWER)[keyof typeof CODEX_APPROVALS_REVIEWER];
|
|
34
|
-
/** Spelled as the rollout's `turn_context.sandbox_policy` records it. */
|
|
35
|
-
export type CodexSandboxPolicy = {
|
|
36
|
-
readonly type: typeof CODEX_SANDBOX_MODE.readOnly;
|
|
37
|
-
} | {
|
|
38
|
-
readonly type: typeof CODEX_SANDBOX_MODE.dangerFullAccess;
|
|
39
|
-
} | {
|
|
40
|
-
readonly type: typeof CODEX_SANDBOX_MODE.workspaceWrite;
|
|
41
|
-
readonly writableRoots: readonly string[];
|
|
42
|
-
readonly networkAccess: boolean;
|
|
43
|
-
readonly excludeTmpdirEnvVar: boolean;
|
|
44
|
-
readonly excludeSlashTmp: boolean;
|
|
45
|
-
};
|
|
46
|
-
export type CodexSessionPermissions = {
|
|
47
|
-
readonly approvalPolicy: CodexApprovalPolicy;
|
|
48
|
-
readonly approvalsReviewer: CodexApprovalsReviewer;
|
|
49
|
-
readonly sandbox: CodexSandboxPolicy;
|
|
50
|
-
};
|
|
51
|
-
export declare function codexSessions(): SessionCapability<CodexSessionPermissions>;
|
|
52
|
-
//# sourceMappingURL=codex-session.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codex-session.d.ts","sourceRoot":"","sources":["../../src/agents/codex-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH,OAAO,EAGL,kBAAkB,EAGnB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AA2B7D,OAAO,EAIL,KAAK,iBAAiB,EAIvB,MAAM,sBAAsB,CAAC;AAK9B,yGAAyG;AACzG,eAAO,MAAM,qBAAqB;;;;CAIxB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAC7B,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,OAAO,qBAAqB,CAAC,CAAC;AAErE,eAAO,MAAM,wBAAwB;;;;CAI3B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAChC,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,OAAO,wBAAwB,CAAC,CAAC;AAE3E,yEAAyE;AACzE,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,kBAAkB,CAAC,QAAQ,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,kBAAkB,CAAC,gBAAgB,CAAA;CAAE,GAC7D;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,kBAAkB,CAAC,cAAc,CAAC;IACxD,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC,CAAC;AAEN,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,cAAc,EAAE,mBAAmB,CAAC;IAC7C,QAAQ,CAAC,iBAAiB,EAAE,sBAAsB,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;CACtC,CAAC;AAkkBF,wBAAgB,aAAa,IAAI,iBAAiB,CAAC,uBAAuB,CAAC,CAM1E"}
|