@alpacakit/agents 0.1.0-beta.39 → 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.
Files changed (134) hide show
  1. package/README.md +142 -1
  2. package/dist/agents/builtin.d.ts +2 -2
  3. package/dist/agents/builtin.d.ts.map +1 -1
  4. package/dist/agents/builtin.js +6 -4
  5. package/dist/agents/claude/cli.d.ts +133 -0
  6. package/dist/agents/claude/cli.d.ts.map +1 -0
  7. package/dist/agents/claude/cli.js +182 -0
  8. package/dist/agents/claude/host.d.ts +14 -0
  9. package/dist/agents/claude/host.d.ts.map +1 -0
  10. package/dist/agents/claude/host.js +319 -0
  11. package/dist/agents/{claude.d.ts → claude/index.d.ts} +11 -11
  12. package/dist/agents/claude/index.d.ts.map +1 -0
  13. package/dist/agents/claude/index.js +134 -0
  14. package/dist/agents/claude/session.d.ts +25 -0
  15. package/dist/agents/claude/session.d.ts.map +1 -0
  16. package/dist/agents/claude/session.js +321 -0
  17. package/dist/agents/codex/cli.d.ts +132 -0
  18. package/dist/agents/codex/cli.d.ts.map +1 -0
  19. package/dist/agents/codex/cli.js +110 -0
  20. package/dist/agents/codex/host.d.ts +14 -0
  21. package/dist/agents/codex/host.d.ts.map +1 -0
  22. package/dist/agents/codex/host.js +221 -0
  23. package/dist/agents/codex/index.d.ts +14 -0
  24. package/dist/agents/codex/index.d.ts.map +1 -0
  25. package/dist/agents/codex/index.js +127 -0
  26. package/dist/agents/codex/session.d.ts +21 -0
  27. package/dist/agents/codex/session.d.ts.map +1 -0
  28. package/dist/agents/codex/session.js +390 -0
  29. package/dist/agents/openai-compatible/fetch-engine.d.ts.map +1 -1
  30. package/dist/agents/openai-compatible/fetch-engine.js +3 -2
  31. package/dist/agents/openai-compatible/pi/engine.js +1 -1
  32. package/dist/agents/openai-compatible/pi/{session.d.ts → run.d.ts} +1 -1
  33. package/dist/agents/openai-compatible/pi/run.d.ts.map +1 -0
  34. package/dist/agents/openai-compatible/pi/sandbox.d.ts.map +1 -1
  35. package/dist/auth/login-probe.d.ts +6 -4
  36. package/dist/auth/login-probe.d.ts.map +1 -1
  37. package/dist/auth/login-probe.js +19 -13
  38. package/dist/auth/material.d.ts +1 -1
  39. package/dist/auth/material.d.ts.map +1 -1
  40. package/dist/codex/app-server.d.ts +50 -1
  41. package/dist/codex/app-server.d.ts.map +1 -1
  42. package/dist/codex/app-server.js +140 -66
  43. package/dist/codex/index.d.ts +3 -2
  44. package/dist/codex/index.d.ts.map +1 -1
  45. package/dist/codex/index.js +2 -1
  46. package/dist/codex/protocol.d.ts +101 -0
  47. package/dist/codex/protocol.d.ts.map +1 -1
  48. package/dist/codex/protocol.js +78 -0
  49. package/dist/config/agent-config-validation.d.ts +1 -1
  50. package/dist/config/agent-config-validation.d.ts.map +1 -1
  51. package/dist/config/agent-configs.d.ts.map +1 -1
  52. package/dist/config/agent-configs.js +3 -3
  53. package/dist/config/compose.d.ts.map +1 -1
  54. package/dist/config/config.d.ts +1 -1
  55. package/dist/config/config.d.ts.map +1 -1
  56. package/dist/config/index.d.ts +2 -2
  57. package/dist/config/index.d.ts.map +1 -1
  58. package/dist/config/index.js +1 -1
  59. package/dist/config/model.d.ts +0 -1
  60. package/dist/config/model.d.ts.map +1 -1
  61. package/dist/config/schema.d.ts.map +1 -1
  62. package/dist/config/schema.js +1 -1
  63. package/dist/config/store.d.ts.map +1 -1
  64. package/dist/config/store.js +6 -24
  65. package/dist/config/support.d.ts +0 -1
  66. package/dist/config/support.d.ts.map +1 -1
  67. package/dist/config/support.js +0 -9
  68. package/dist/core/cli-child.d.ts +56 -0
  69. package/dist/core/cli-child.d.ts.map +1 -0
  70. package/dist/core/cli-child.js +105 -0
  71. package/dist/core/fs.d.ts +1 -1
  72. package/dist/core/fs.d.ts.map +1 -1
  73. package/dist/core/fs.js +10 -2
  74. package/dist/core/node-ports.d.ts.map +1 -1
  75. package/dist/core/node-ports.js +1 -5
  76. package/dist/core/session.d.ts +104 -0
  77. package/dist/core/session.d.ts.map +1 -0
  78. package/dist/core/session.js +29 -0
  79. package/dist/fleet/store.d.ts.map +1 -1
  80. package/dist/fleet/store.js +4 -3
  81. package/dist/host/availability.d.ts +2 -1
  82. package/dist/host/availability.d.ts.map +1 -1
  83. package/dist/host/github-dir.d.ts.map +1 -1
  84. package/dist/host/github-dir.js +2 -1
  85. package/dist/host/mcp-list.d.ts.map +1 -1
  86. package/dist/host/mcp-list.js +5 -6
  87. package/dist/host/run-command.d.ts +2 -1
  88. package/dist/host/run-command.d.ts.map +1 -1
  89. package/dist/host/run-command.js +10 -19
  90. package/dist/host/session-files.d.ts +23 -0
  91. package/dist/host/session-files.d.ts.map +1 -0
  92. package/dist/host/session-files.js +92 -0
  93. package/dist/index.d.ts +9 -4
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +5 -2
  96. package/dist/internal/controlled-process/supervisor-runtime.js +27 -1
  97. package/dist/kernel/classify.d.ts +1 -2
  98. package/dist/kernel/classify.d.ts.map +1 -1
  99. package/dist/kernel/classify.js +1 -1
  100. package/dist/kernel/cli-agent.d.ts.map +1 -1
  101. package/dist/kernel/cli-agent.js +26 -85
  102. package/dist/kernel/cli-login.d.ts.map +1 -1
  103. package/dist/kernel/cli-login.js +9 -30
  104. package/dist/kernel/definition.d.ts +11 -2
  105. package/dist/kernel/definition.d.ts.map +1 -1
  106. package/dist/kernel/facets.d.ts +38 -1
  107. package/dist/kernel/facets.d.ts.map +1 -1
  108. package/dist/kernel/facets.js +20 -0
  109. package/dist/kernel/login.d.ts.map +1 -1
  110. package/dist/kernel/login.js +2 -1
  111. package/dist/kernel/options.d.ts +1 -1
  112. package/dist/kernel/options.d.ts.map +1 -1
  113. package/dist/kernel/run.d.ts.map +1 -1
  114. package/dist/kernel/run.js +2 -1
  115. package/dist/kernel/runtime.d.ts +10 -6
  116. package/dist/kernel/runtime.d.ts.map +1 -1
  117. package/dist/kernel/runtime.js +4 -1
  118. package/dist/kernel/session.d.ts +104 -0
  119. package/dist/kernel/session.d.ts.map +1 -0
  120. package/dist/kernel/session.js +314 -0
  121. package/dist/testing/fake-exec.d.ts +10 -5
  122. package/dist/testing/fake-exec.d.ts.map +1 -1
  123. package/dist/testing/fake-exec.js +17 -2
  124. package/dist/testing/index.d.ts +1 -1
  125. package/dist/testing/index.d.ts.map +1 -1
  126. package/dist/testing/index.js +1 -1
  127. package/package.json +2 -2
  128. package/dist/agents/claude.d.ts.map +0 -1
  129. package/dist/agents/claude.js +0 -543
  130. package/dist/agents/codex.d.ts +0 -19
  131. package/dist/agents/codex.d.ts.map +0 -1
  132. package/dist/agents/codex.js +0 -377
  133. package/dist/agents/openai-compatible/pi/session.d.ts.map +0 -1
  134. /package/dist/agents/openai-compatible/pi/{session.js → run.js} +0 -0
@@ -0,0 +1,321 @@
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_OWNER_KIND, TURN_OUTCOME, } from "../../core/session.js";
26
+ import { fileExists, readDirectoryNames, readJsonFile, scanJsonlFirstLast, } from "../../host/session-files.js";
27
+ import { assertHostSessionId, SessionProcess, driveSession, sessionStateError, } from "../../kernel/session.js";
28
+ import { CLAUDE, CLAUDE_PERMISSION_MODE, parseClaudeRecord, permissionModeArgs, } from "./cli.js";
29
+ const CONTROL_RESPONSE_TIMEOUT_MS = 30_000;
30
+ const DECLINED_MESSAGE = "Declined by the session owner";
31
+ function sessionArgs(permissions, target, options) {
32
+ return [
33
+ CLAUDE.cli.prompt,
34
+ CLAUDE.cli.inputFormat,
35
+ CLAUDE.cli.streamJson,
36
+ CLAUDE.cli.outputFormat,
37
+ CLAUDE.cli.streamJson,
38
+ CLAUDE.cli.verbose,
39
+ ...permissionModeArgs(permissions.mode),
40
+ CLAUDE.cli.permissionPromptTool,
41
+ CLAUDE.cli.stdio,
42
+ // A session's whole point is the recorded conversation, so `disabled`
43
+ // drops only the customization flags, never `--no-session-persistence`.
44
+ ...(options.customizations === "disabled"
45
+ ? [CLAUDE.cli.safeMode, CLAUDE.cli.strictMcpConfig]
46
+ : []),
47
+ target.kind === "resume" ? CLAUDE.cli.resume : CLAUDE.cli.sessionId,
48
+ target.sessionId,
49
+ ];
50
+ }
51
+ /**
52
+ * The Claude side of a Session: user lines and control requests out,
53
+ * stream-json records in. Control responses are correlated here (they
54
+ * answer this protocol's own requests); everything else is decoded into
55
+ * the driver's sink. Claude's stream carries no turn id, so the turn id
56
+ * is a per-session counter.
57
+ */
58
+ class ClaudeProtocol {
59
+ process;
60
+ ctx;
61
+ pendingControls = new Map();
62
+ turnCount = 0;
63
+ interruptRequested = false;
64
+ incoming;
65
+ constructor(process, ctx) {
66
+ this.process = process;
67
+ this.ctx = ctx;
68
+ this.incoming = this.records();
69
+ }
70
+ get exit() {
71
+ return this.process.exit;
72
+ }
73
+ get stderrTail() {
74
+ return this.process.stderr;
75
+ }
76
+ async startTurn(text) {
77
+ this.turnCount += 1;
78
+ this.writeUserLine(text);
79
+ return String(this.turnCount);
80
+ }
81
+ async steer(_turnId, text) {
82
+ this.writeUserLine(text);
83
+ }
84
+ async interrupt() {
85
+ const requestId = randomUUID();
86
+ this.interruptRequested = true;
87
+ const answered = this.awaitControlResponse(requestId);
88
+ this.process.writeLine(JSON.stringify({
89
+ type: CLAUDE.json.type.controlRequest,
90
+ [CLAUDE.json.field.requestId]: requestId,
91
+ request: { subtype: CLAUDE.json.subtype.interrupt },
92
+ }));
93
+ try {
94
+ await answered;
95
+ }
96
+ catch (error) {
97
+ // An unanswered interrupt must not color the next turn's outcome.
98
+ this.interruptRequested = false;
99
+ throw error;
100
+ }
101
+ }
102
+ respond(approval, decision) {
103
+ const response = decision === APPROVAL_DECISION.accept
104
+ ? {
105
+ behavior: CLAUDE.json.behavior.allow,
106
+ updatedInput: approval.input,
107
+ }
108
+ : {
109
+ behavior: CLAUDE.json.behavior.deny,
110
+ message: DECLINED_MESSAGE,
111
+ };
112
+ this.process.writeLine(JSON.stringify({
113
+ type: CLAUDE.json.type.controlResponse,
114
+ response: {
115
+ subtype: CLAUDE.json.subtype.success,
116
+ [CLAUDE.json.field.requestId]: approval.requestId,
117
+ response,
118
+ },
119
+ }));
120
+ }
121
+ async close() {
122
+ await this.process.close();
123
+ }
124
+ decode(record, sink) {
125
+ const type = readString(record, CLAUDE.json.field.type);
126
+ if (type === CLAUDE.json.type.assistant) {
127
+ for (const event of parseClaudeRecord(record)) {
128
+ if (event.type === AGENT_EVENT_TYPE.message) {
129
+ sink.message(event.text);
130
+ }
131
+ else if (event.type === AGENT_EVENT_TYPE.tool) {
132
+ sink.tool(event.name);
133
+ }
134
+ }
135
+ return;
136
+ }
137
+ if (type === CLAUDE.json.type.result) {
138
+ const isError = record[CLAUDE.json.field.isError] === true;
139
+ const outcome = this.interruptRequested
140
+ ? TURN_OUTCOME.interrupted
141
+ : isError
142
+ ? TURN_OUTCOME.failed
143
+ : TURN_OUTCOME.completed;
144
+ this.interruptRequested = false;
145
+ sink.endTurn(outcome, readString(record, CLAUDE.json.field.result));
146
+ return;
147
+ }
148
+ if (type === CLAUDE.json.type.controlRequest) {
149
+ this.decodeControlRequest(record, sink);
150
+ }
151
+ }
152
+ writeUserLine(text) {
153
+ this.process.writeLine(JSON.stringify({
154
+ type: CLAUDE.json.type.user,
155
+ message: { role: CLAUDE.json.type.user, content: text },
156
+ }));
157
+ }
158
+ awaitControlResponse(requestId) {
159
+ return new Promise((resolve, reject) => {
160
+ const cancelTimeout = this.ctx.clock.setTimeout(() => {
161
+ this.pendingControls.delete(requestId);
162
+ reject(new AgentError({
163
+ code: AGENT_ERROR_CODE.timeout,
164
+ classification: AgentError.agentFailure(AGENT_ERROR_CODE.timeout),
165
+ message: "Claude did not answer the control request in time",
166
+ data: {
167
+ kind: TIMEOUT_KIND.total,
168
+ limitMs: CONTROL_RESPONSE_TIMEOUT_MS,
169
+ },
170
+ agentId: CLAUDE.id,
171
+ }));
172
+ }, CONTROL_RESPONSE_TIMEOUT_MS);
173
+ this.pendingControls.set(requestId, { resolve, reject, cancelTimeout });
174
+ });
175
+ }
176
+ /** stdout records minus the control responses, which are answered here; settles waiters when the child is gone. */
177
+ async *records() {
178
+ try {
179
+ for await (const line of this.process.lines()) {
180
+ const record = readJsonRecord(line);
181
+ if (record === null) {
182
+ continue;
183
+ }
184
+ if (readString(record, CLAUDE.json.field.type) ===
185
+ CLAUDE.json.type.controlResponse) {
186
+ this.handleControlResponse(record);
187
+ continue;
188
+ }
189
+ yield record;
190
+ }
191
+ }
192
+ finally {
193
+ for (const pending of this.pendingControls.values()) {
194
+ pending.cancelTimeout();
195
+ pending.reject(sessionStateError(CLAUDE.id, "session process exited"));
196
+ }
197
+ this.pendingControls.clear();
198
+ this.interruptRequested = false;
199
+ }
200
+ }
201
+ decodeControlRequest(record, sink) {
202
+ const requestId = readString(record, CLAUDE.json.field.requestId);
203
+ const request = readRecord(record, CLAUDE.json.field.request);
204
+ const subtype = request === null ? null : readString(request, CLAUDE.json.field.subtype);
205
+ if (requestId === null || request === null) {
206
+ return;
207
+ }
208
+ if (subtype !== CLAUDE.json.subtype.canUseTool) {
209
+ this.ctx.logger.log("warn", `ignoring unsupported claude control request "${subtype ?? "?"}"`);
210
+ return;
211
+ }
212
+ const toolName = readString(request, CLAUDE.json.field.toolName) ?? "";
213
+ const description = readString(request, CLAUDE.json.field.description);
214
+ sink.approvalRequested(requestId, description === null ? toolName : `${toolName} ${description}`, { requestId, input: request[CLAUDE.json.field.input] });
215
+ }
216
+ handleControlResponse(record) {
217
+ const response = readRecord(record, CLAUDE.json.field.response);
218
+ const requestId = response === null
219
+ ? null
220
+ : readString(response, CLAUDE.json.field.requestId);
221
+ if (response === null || requestId === null) {
222
+ return;
223
+ }
224
+ const pending = this.pendingControls.get(requestId);
225
+ if (pending === undefined) {
226
+ return;
227
+ }
228
+ this.pendingControls.delete(requestId);
229
+ pending.cancelTimeout();
230
+ if (readString(response, CLAUDE.json.field.subtype) ===
231
+ CLAUDE.json.subtype.error) {
232
+ pending.reject(sessionStateError(CLAUDE.id, redactSecrets(readString(response, CLAUDE.json.field.error) ??
233
+ "control request failed")));
234
+ return;
235
+ }
236
+ pending.resolve();
237
+ }
238
+ }
239
+ async function openClaudeSession(target, options, ctx, sessionOptions) {
240
+ const process = await SessionProcess.spawn({
241
+ command: CLAUDE.command,
242
+ args: sessionArgs(options.permissions, target, sessionOptions),
243
+ cwd: options.workspace,
244
+ ctx,
245
+ agentId: CLAUDE.id,
246
+ });
247
+ return driveSession({
248
+ id: target.sessionId,
249
+ agentId: CLAUDE.id,
250
+ protocol: new ClaudeProtocol(process, ctx),
251
+ logger: ctx.logger,
252
+ });
253
+ }
254
+ function claudeRoot(ctx, ...segments) {
255
+ return path.join(ctx.location.homeDir, CLAUDE.files.root, ...segments);
256
+ }
257
+ /** `~/.claude/projects/<encoded cwd>/<id>.jsonl` — the project directory name is not derivable, so scan. */
258
+ async function findClaudeTranscript(ctx, id) {
259
+ const root = claudeRoot(ctx, CLAUDE.files.projects);
260
+ for (const project of await readDirectoryNames(root)) {
261
+ const candidate = path.join(root, project, `${id}${CLAUDE.files.transcriptExtension}`);
262
+ if (await fileExists(candidate)) {
263
+ return candidate;
264
+ }
265
+ }
266
+ return null;
267
+ }
268
+ /** `~/.claude/sessions/<pid>.json` — one file per live CLI process, keyed by pid. */
269
+ async function claudeRegistryOwner(ctx, id) {
270
+ const root = claudeRoot(ctx, CLAUDE.files.sessions);
271
+ for (const name of await readDirectoryNames(root)) {
272
+ if (!name.endsWith(CLAUDE.files.registryExtension)) {
273
+ continue;
274
+ }
275
+ const entry = await readJsonFile(path.join(root, name));
276
+ if (entry === null || readString(entry, CLAUDE.files.sessionId) !== id) {
277
+ continue;
278
+ }
279
+ return {
280
+ kind: SESSION_OWNER_KIND.process,
281
+ pid: readNumber(entry, CLAUDE.files.pid),
282
+ entrypoint: readString(entry, CLAUDE.files.entrypoint),
283
+ };
284
+ }
285
+ return { kind: SESSION_OWNER_KIND.none };
286
+ }
287
+ function permissionModeFrom(value) {
288
+ return value !== null &&
289
+ Object.values(CLAUDE_PERMISSION_MODE).includes(value)
290
+ ? value
291
+ : null;
292
+ }
293
+ async function inspectClaudeSession(id, ctx) {
294
+ assertHostSessionId(id, CLAUDE.id);
295
+ const transcript = await findClaudeTranscript(ctx, id);
296
+ if (transcript === null) {
297
+ return null;
298
+ }
299
+ const cwd = await scanJsonlFirstLast(transcript, (record) => readString(record, CLAUDE.files.cwd));
300
+ if (cwd.first === null) {
301
+ return null;
302
+ }
303
+ const modes = await scanJsonlFirstLast(transcript, (record) => readString(record, CLAUDE.files.permissionMode));
304
+ const mode = permissionModeFrom(modes.last);
305
+ return {
306
+ workspace: cwd.first,
307
+ lastPermissions: mode === null ? null : { mode },
308
+ owner: await claudeRegistryOwner(ctx, id),
309
+ archived: false,
310
+ };
311
+ }
312
+ export function claudeSessions(options) {
313
+ return {
314
+ open: (resolved, ctx) => openClaudeSession({ kind: "new", sessionId: randomUUID() }, resolved, ctx, options),
315
+ resume: async (id, resolved, ctx) => {
316
+ assertHostSessionId(id, CLAUDE.id);
317
+ return openClaudeSession({ kind: "resume", sessionId: id }, resolved, ctx, options);
318
+ },
319
+ inspect: inspectClaudeSession,
320
+ };
321
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * The Codex vocabulary, spelled once: the `codex exec` flags, the app-server
3
+ * notification and file fields the session reads, the permission words, and
4
+ * the host's own file names. The run adapter (`index.ts`), the session
5
+ * adapter (`session.ts`), and the host plane (`host.ts`) all read from here;
6
+ * JSON-RPC method names and sandbox words come from `codex/protocol.ts`.
7
+ */
8
+ import type { CODEX_SANDBOX_MODE } from "../../codex/protocol.js";
9
+ export declare const CODEX_HOME_ENV_VAR = "CODEX_HOME";
10
+ export declare const CODEX_API_KEY_ENV_VAR = "OPENAI_API_KEY";
11
+ export declare const CODEX: {
12
+ readonly id: "codex";
13
+ readonly command: "codex";
14
+ readonly cli: {
15
+ readonly exec: "exec";
16
+ readonly model: "--model";
17
+ readonly config: "-c";
18
+ readonly reasoningEffortConfigKey: "model_reasoning_effort";
19
+ readonly json: "--json";
20
+ readonly skipGitRepoCheck: "--skip-git-repo-check";
21
+ readonly sandbox: "--sandbox";
22
+ readonly workspace: "-C";
23
+ };
24
+ readonly auth: {
25
+ readonly statusArgs: readonly ["login", "status"];
26
+ readonly oauthLoginArgs: readonly ["login"];
27
+ readonly deviceLoginArgs: readonly ["login", "--device-auth"];
28
+ };
29
+ readonly json: {
30
+ readonly field: {
31
+ readonly type: "type";
32
+ readonly text: "text";
33
+ readonly item: "item";
34
+ };
35
+ readonly event: {
36
+ readonly turnCompleted: "turn.completed";
37
+ readonly agentMessage: "agent_message";
38
+ readonly itemCompleted: "item.completed";
39
+ };
40
+ };
41
+ readonly mcp: {
42
+ readonly add: "add";
43
+ readonly env: "--env";
44
+ readonly executableSeparator: "--";
45
+ readonly mcp: "mcp";
46
+ readonly remove: "remove";
47
+ };
48
+ readonly notification: {
49
+ readonly threadId: "threadId";
50
+ readonly turnId: "turnId";
51
+ readonly turn: "turn";
52
+ readonly item: "item";
53
+ readonly id: "id";
54
+ readonly type: "type";
55
+ readonly text: "text";
56
+ readonly status: "status";
57
+ readonly items: "items";
58
+ readonly phase: "phase";
59
+ readonly finalAnswer: "final_answer";
60
+ readonly agentMessage: "agentMessage";
61
+ readonly userMessage: "userMessage";
62
+ readonly reasoning: "reasoning";
63
+ readonly command: "command";
64
+ readonly reason: "reason";
65
+ };
66
+ readonly turnStatus: {
67
+ readonly completed: "completed";
68
+ readonly interrupted: "interrupted";
69
+ readonly failed: "failed";
70
+ };
71
+ readonly decision: {
72
+ readonly accept: "accept";
73
+ readonly decline: "decline";
74
+ };
75
+ readonly error: {
76
+ readonly archived: "is archived";
77
+ readonly methodNotFound: -32601;
78
+ readonly unsupported: "unsupported server request";
79
+ };
80
+ readonly files: {
81
+ readonly root: ".codex";
82
+ readonly sessions: "sessions";
83
+ readonly archivedSessions: "archived_sessions";
84
+ readonly writerLocks: "thread-writer-locks";
85
+ readonly lockExtension: ".lock";
86
+ readonly rolloutExtension: ".jsonl";
87
+ readonly type: "type";
88
+ readonly payload: "payload";
89
+ readonly sessionMeta: "session_meta";
90
+ readonly turnContext: "turn_context";
91
+ readonly cwd: "cwd";
92
+ readonly approvalPolicy: "approval_policy";
93
+ readonly approvalsReviewer: "approvals_reviewer";
94
+ readonly sandboxPolicy: "sandbox_policy";
95
+ readonly writableRoots: "writable_roots";
96
+ readonly networkAccess: "network_access";
97
+ readonly excludeTmpdirEnvVar: "exclude_tmpdir_env_var";
98
+ readonly excludeSlashTmp: "exclude_slash_tmp";
99
+ };
100
+ };
101
+ /** `approval_policy` words (codex 0.153.4 `AskForApproval`; the granular object form is not modeled). */
102
+ export declare const CODEX_APPROVAL_POLICY: {
103
+ readonly untrusted: "untrusted";
104
+ readonly onRequest: "on-request";
105
+ readonly never: "never";
106
+ };
107
+ export type CodexApprovalPolicy = (typeof CODEX_APPROVAL_POLICY)[keyof typeof CODEX_APPROVAL_POLICY];
108
+ export declare const CODEX_APPROVALS_REVIEWER: {
109
+ readonly user: "user";
110
+ readonly autoReview: "auto_review";
111
+ readonly guardianSubagent: "guardian_subagent";
112
+ };
113
+ export type CodexApprovalsReviewer = (typeof CODEX_APPROVALS_REVIEWER)[keyof typeof CODEX_APPROVALS_REVIEWER];
114
+ /** Spelled as the rollout's `turn_context.sandbox_policy` records it. */
115
+ export type { CodexSandboxMode } from "../../codex/protocol.js";
116
+ export type CodexSandboxPolicy = {
117
+ readonly type: typeof CODEX_SANDBOX_MODE.readOnly;
118
+ } | {
119
+ readonly type: typeof CODEX_SANDBOX_MODE.dangerFullAccess;
120
+ } | {
121
+ readonly type: typeof CODEX_SANDBOX_MODE.workspaceWrite;
122
+ readonly writableRoots: readonly string[];
123
+ readonly networkAccess: boolean;
124
+ readonly excludeTmpdirEnvVar: boolean;
125
+ readonly excludeSlashTmp: boolean;
126
+ };
127
+ export type CodexSessionPermissions = {
128
+ readonly approvalPolicy: CodexApprovalPolicy;
129
+ readonly approvalsReviewer: CodexApprovalsReviewer;
130
+ readonly sandbox: CodexSandboxPolicy;
131
+ };
132
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/agents/codex/cli.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAC/C,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AAEtD,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyFR,CAAC;AAEX,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,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,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"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * The Codex vocabulary, spelled once: the `codex exec` flags, the app-server
3
+ * notification and file fields the session reads, the permission words, and
4
+ * the host's own file names. The run adapter (`index.ts`), the session
5
+ * adapter (`session.ts`), and the host plane (`host.ts`) all read from here;
6
+ * JSON-RPC method names and sandbox words come from `codex/protocol.ts`.
7
+ */
8
+ export const CODEX_HOME_ENV_VAR = "CODEX_HOME";
9
+ export const CODEX_API_KEY_ENV_VAR = "OPENAI_API_KEY";
10
+ export const CODEX = {
11
+ id: "codex",
12
+ command: "codex",
13
+ cli: {
14
+ exec: "exec",
15
+ model: "--model",
16
+ config: "-c",
17
+ reasoningEffortConfigKey: "model_reasoning_effort",
18
+ json: "--json",
19
+ skipGitRepoCheck: "--skip-git-repo-check",
20
+ sandbox: "--sandbox",
21
+ workspace: "-C",
22
+ },
23
+ auth: {
24
+ // Exit-code-only login probe (E12): `codex login status` exits 0 when a
25
+ // credential is present, nonzero otherwise. The output format is not
26
+ // parsed — only the exit code decides valid/invalid, like claude's.
27
+ statusArgs: ["login", "status"],
28
+ oauthLoginArgs: ["login"],
29
+ deviceLoginArgs: ["login", "--device-auth"],
30
+ },
31
+ json: {
32
+ field: {
33
+ type: "type",
34
+ text: "text",
35
+ item: "item",
36
+ },
37
+ event: {
38
+ turnCompleted: "turn.completed",
39
+ agentMessage: "agent_message",
40
+ itemCompleted: "item.completed",
41
+ },
42
+ },
43
+ mcp: {
44
+ add: "add",
45
+ env: "--env",
46
+ executableSeparator: "--",
47
+ mcp: "mcp",
48
+ remove: "remove",
49
+ },
50
+ notification: {
51
+ threadId: "threadId",
52
+ turnId: "turnId",
53
+ turn: "turn",
54
+ item: "item",
55
+ id: "id",
56
+ type: "type",
57
+ text: "text",
58
+ status: "status",
59
+ items: "items",
60
+ phase: "phase",
61
+ finalAnswer: "final_answer",
62
+ agentMessage: "agentMessage",
63
+ userMessage: "userMessage",
64
+ reasoning: "reasoning",
65
+ command: "command",
66
+ reason: "reason",
67
+ },
68
+ turnStatus: {
69
+ completed: "completed",
70
+ interrupted: "interrupted",
71
+ failed: "failed",
72
+ },
73
+ decision: { accept: "accept", decline: "decline" },
74
+ error: {
75
+ archived: "is archived",
76
+ methodNotFound: -32601,
77
+ unsupported: "unsupported server request",
78
+ },
79
+ files: {
80
+ root: ".codex",
81
+ sessions: "sessions",
82
+ archivedSessions: "archived_sessions",
83
+ writerLocks: "thread-writer-locks",
84
+ lockExtension: ".lock",
85
+ rolloutExtension: ".jsonl",
86
+ type: "type",
87
+ payload: "payload",
88
+ sessionMeta: "session_meta",
89
+ turnContext: "turn_context",
90
+ cwd: "cwd",
91
+ approvalPolicy: "approval_policy",
92
+ approvalsReviewer: "approvals_reviewer",
93
+ sandboxPolicy: "sandbox_policy",
94
+ writableRoots: "writable_roots",
95
+ networkAccess: "network_access",
96
+ excludeTmpdirEnvVar: "exclude_tmpdir_env_var",
97
+ excludeSlashTmp: "exclude_slash_tmp",
98
+ },
99
+ };
100
+ /** `approval_policy` words (codex 0.153.4 `AskForApproval`; the granular object form is not modeled). */
101
+ export const CODEX_APPROVAL_POLICY = {
102
+ untrusted: "untrusted",
103
+ onRequest: "on-request",
104
+ never: "never",
105
+ };
106
+ export const CODEX_APPROVALS_REVIEWER = {
107
+ user: "user",
108
+ autoReview: "auto_review",
109
+ guardianSubagent: "guardian_subagent",
110
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The codex host plane: auth materials and sign-in, skills and plugins
3
+ * through a short-lived app-server client, and MCP registration through
4
+ * the CLI. Outside a run and a session; every path comes from
5
+ * `HostContext.location`, never `os.homedir()`.
6
+ */
7
+ import { type LoginCapability } from "../../auth/login.js";
8
+ import type { MaterialHandlers } from "../../auth/material.js";
9
+ import { type McpCapability, type SkillsCapability } from "../../host/capabilities.js";
10
+ export declare const codexAuth: MaterialHandlers;
11
+ export declare const codexLogin: LoginCapability;
12
+ export declare const codexSkills: SkillsCapability;
13
+ export declare const codexMcp: McpCapability;
14
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../../src/agents/codex/host.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAmB/D,OAAO,EAOL,KAAK,aAAa,EAKlB,KAAK,gBAAgB,EAEtB,MAAM,4BAA4B,CAAC;AAkOpC,eAAO,MAAM,SAAS,EAAE,gBAqBvB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,eAKxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,gBAKzB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,aAMtB,CAAC"}