@gkorepanov/ccodex 0.4.16 → 0.4.18
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/agents/codex-wrapper.md +40 -0
- package/config/compatibility.json +1 -1
- package/dist/claude/inputMapper.js +9 -0
- package/dist/claude/inputMapper.js.map +1 -1
- package/dist/claude/session/codexRollout.d.ts +26 -0
- package/dist/claude/session/codexRollout.js +139 -0
- package/dist/claude/session/codexRollout.js.map +1 -0
- package/dist/claude/session/commands.d.ts +9 -0
- package/dist/claude/session/session.d.ts +10 -1
- package/dist/claude/session/session.js +164 -2
- package/dist/claude/session/session.js.map +1 -1
- package/dist/daemon/probe.js +3 -0
- package/dist/daemon/probe.js.map +1 -1
- package/dist/gateway/threadList.js +4 -1
- package/dist/gateway/threadList.js.map +1 -1
- package/dist/handoff/service.js +6 -1
- package/dist/handoff/service.js.map +1 -1
- package/dist/management/setup.js +13 -0
- package/dist/management/setup.js.map +1 -1
- package/dist/store/sqliteStore.js +2 -0
- package/dist/store/sqliteStore.js.map +1 -1
- package/package.json +8 -4
- package/scripts/install-claude-stack.sh +28 -0
- package/skills/workforce/SKILL.md +35 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: codex-wrapper
|
|
3
|
+
description: Interactive wrapper around OpenAI Codex. Use when the caller wants to delegate work to Codex, discuss a task with Codex, continue an existing Codex thread, ask Codex to implement/review/debug/research something, or use Codex as a general-purpose subagent.
|
|
4
|
+
tools: mcp__codex__*
|
|
5
|
+
mcpServers:
|
|
6
|
+
- codex:
|
|
7
|
+
type: stdio
|
|
8
|
+
command: codex
|
|
9
|
+
args: ["mcp-server"]
|
|
10
|
+
model: sonnet
|
|
11
|
+
effort: low
|
|
12
|
+
permissionMode: bypassPermissions
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
You are codex-wrapper.
|
|
16
|
+
|
|
17
|
+
Codex is a full general-purpose subagent. Your job is to communicate with Codex interactively through the Codex MCP server and report the useful results back to the caller.
|
|
18
|
+
|
|
19
|
+
Core behavior:
|
|
20
|
+
- For a new Codex conversation, call the `codex` MCP tool.
|
|
21
|
+
- For follow-ups, call `codex-reply` with the existing `threadId`.
|
|
22
|
+
- Always use `danger-full-access` for Codex sandbox/access mode.
|
|
23
|
+
- Keep the Codex conversation stateful. Preserve and reuse `threadId` whenever continuing the same task.
|
|
24
|
+
- Pass the caller's context to Codex as fully as possible, preferably word-for-word.
|
|
25
|
+
- Do not summarize, reinterpret, or compress the caller's task before sending it to Codex.
|
|
26
|
+
- If the caller asks you to continue a prior Codex discussion and gives a `threadId`, use `codex-reply`.
|
|
27
|
+
|
|
28
|
+
Interaction loop:
|
|
29
|
+
- Talk to Codex for as many turns as needed (e.g. when codex asks permission or stopped mid task, ask it to continue)
|
|
30
|
+
- But do not apply your own judgement if codex is stuck. Report to the caller and wait for next requests from caller.
|
|
31
|
+
|
|
32
|
+
Reporting:
|
|
33
|
+
- Report Codex's result to the caller clearly and fully.
|
|
34
|
+
- Include the active `threadId` in your final response.
|
|
35
|
+
- Preserve important Codex claims, objections, commands, file paths, and proposed changes.
|
|
36
|
+
- Distinguish what Codex said from your own coordination notes when that matters.
|
|
37
|
+
|
|
38
|
+
Codex model to use:
|
|
39
|
+
- `gpt-5.6-sol` with `high` reasoning unless asked otherwise by caller.
|
|
40
|
+
- Reasoning effort is set via the `config` parameter of the `codex` MCP tool: `config: {"model_reasoning_effort": "high"}`. Supported values: `minimal`/`low`/`medium`/`high`/`xhigh`/`max`.
|
|
@@ -9,6 +9,7 @@ const mediaTypes = {
|
|
|
9
9
|
".png": "image/png",
|
|
10
10
|
".webp": "image/webp",
|
|
11
11
|
};
|
|
12
|
+
const dataImageUrl = /^data:(image\/[a-z+.-]+);base64,([\s\S]*)$/i;
|
|
12
13
|
async function allowedImagePath(path, context) {
|
|
13
14
|
const candidate = await realpath(isAbsolute(path) ? path : resolve(context.cwd, path));
|
|
14
15
|
const sandbox = context.sandboxPolicy && typeof context.sandboxPolicy === "object" && "type" in context.sandboxPolicy
|
|
@@ -43,6 +44,14 @@ export async function mapUserInput(input, uuid, context) {
|
|
|
43
44
|
throw invalidParams("Codex skills are not available in Claude threads.");
|
|
44
45
|
}
|
|
45
46
|
else if (item.type === "image") {
|
|
47
|
+
const inline = dataImageUrl.exec(item.url);
|
|
48
|
+
if (inline) {
|
|
49
|
+
const mediaType = inline[1].toLocaleLowerCase();
|
|
50
|
+
if (!Object.values(mediaTypes).includes(mediaType))
|
|
51
|
+
throw invalidParams(`Unsupported Claude image type '${mediaType}'.`);
|
|
52
|
+
content.push({ type: "image", source: { type: "base64", media_type: mediaType, data: inline[2].replace(/\s+/g, "") } });
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
46
55
|
const url = new URL(item.url);
|
|
47
56
|
if (url.protocol !== "https:" && url.protocol !== "http:")
|
|
48
57
|
throw invalidParams(`Unsupported Claude image URL scheme '${url.protocol}'.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputMapper.js","sourceRoot":"","sources":["../../src/claude/inputMapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGnE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,UAAU,GAA2B;IACzC,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;CACtB,CAAC;
|
|
1
|
+
{"version":3,"file":"inputMapper.js","sourceRoot":"","sources":["../../src/claude/inputMapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const CODEX_MCP_TOOLS: Set<string>;
|
|
2
|
+
export declare const CODEX_MCP_PROMPT_LABEL = "\u25C6 CCodex \u2502 Codex MCP prompt";
|
|
3
|
+
export declare const CODEX_MCP_MESSAGE_LABEL = "\u25C6 CCodex \u2502 Codex MCP message";
|
|
4
|
+
export declare const CODEX_MCP_REASONING_LABEL = "\u25C6 CCodex \u2502 Codex MCP reasoning";
|
|
5
|
+
export type CodexRolloutEvent = {
|
|
6
|
+
readonly kind: "message";
|
|
7
|
+
readonly text: string;
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: "reasoning";
|
|
10
|
+
readonly text: string;
|
|
11
|
+
} | {
|
|
12
|
+
readonly kind: "turnComplete";
|
|
13
|
+
};
|
|
14
|
+
/** Locates the rollout journal for a codex MCP call; injectable for tests. */
|
|
15
|
+
export interface CodexRolloutLocator {
|
|
16
|
+
/** Journal of an existing codex thread (codex-reply), by thread id. */
|
|
17
|
+
byThreadId(threadId: string): string | undefined;
|
|
18
|
+
/** Journal of a fresh MCP-sourced codex session started at or after `notBeforeMs`, excluding `claimed` paths. */
|
|
19
|
+
freshMcpSession(notBeforeMs: number, claimed: ReadonlySet<string>): string | undefined;
|
|
20
|
+
}
|
|
21
|
+
export declare function defaultCodexRolloutLocator(sessionsDir?: string): CodexRolloutLocator;
|
|
22
|
+
/** Consumes complete journal lines from `buffer` + `chunk`, returning mapped events and the unparsed tail. */
|
|
23
|
+
export declare function parseRolloutChunk(buffer: string, chunk: string): {
|
|
24
|
+
rest: string;
|
|
25
|
+
events: CodexRolloutEvent[];
|
|
26
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { closeSync, openSync, readSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
export const CODEX_MCP_TOOLS = new Set(["mcp__codex__codex", "mcp__codex__codex-reply"]);
|
|
5
|
+
export const CODEX_MCP_PROMPT_LABEL = "◆ CCodex │ Codex MCP prompt";
|
|
6
|
+
export const CODEX_MCP_MESSAGE_LABEL = "◆ CCodex │ Codex MCP message";
|
|
7
|
+
export const CODEX_MCP_REASONING_LABEL = "◆ CCodex │ Codex MCP reasoning";
|
|
8
|
+
function codexSessionsDir() {
|
|
9
|
+
return join(process.env.CODEX_HOME ?? join(homedir(), ".codex"), "sessions");
|
|
10
|
+
}
|
|
11
|
+
function dayDirsNewestFirst(root, limit) {
|
|
12
|
+
const numericDesc = (values) => values.filter((value) => /^\d+$/.test(value)).sort((a, b) => Number(b) - Number(a));
|
|
13
|
+
const days = [];
|
|
14
|
+
let entries;
|
|
15
|
+
try {
|
|
16
|
+
entries = readdirSync(root);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
for (const year of numericDesc(entries)) {
|
|
22
|
+
for (const month of numericDesc(readdirSync(join(root, year)))) {
|
|
23
|
+
for (const day of numericDesc(readdirSync(join(root, year, month)))) {
|
|
24
|
+
days.push(join(root, year, month, day));
|
|
25
|
+
if (days.length >= limit)
|
|
26
|
+
return days;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return days;
|
|
31
|
+
}
|
|
32
|
+
function sessionMeta(path) {
|
|
33
|
+
// The session_meta line embeds the full codex base instructions, so it can be
|
|
34
|
+
// tens of kilobytes long — read a bounded head and require a complete line.
|
|
35
|
+
let head;
|
|
36
|
+
try {
|
|
37
|
+
const buffer = Buffer.alloc(262_144);
|
|
38
|
+
const fd = openSync(path, "r");
|
|
39
|
+
try {
|
|
40
|
+
head = buffer.subarray(0, readSync(fd, buffer, 0, buffer.length, 0)).toString("utf8");
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
closeSync(fd);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
const end = head.indexOf("\n");
|
|
50
|
+
if (end === -1)
|
|
51
|
+
return undefined;
|
|
52
|
+
const line = head.slice(0, end);
|
|
53
|
+
try {
|
|
54
|
+
const parsed = JSON.parse(line);
|
|
55
|
+
if (parsed.type !== "session_meta")
|
|
56
|
+
return undefined;
|
|
57
|
+
const timestamp = parsed.payload?.timestamp ? Date.parse(parsed.payload.timestamp) : Number.NaN;
|
|
58
|
+
return {
|
|
59
|
+
...(parsed.payload?.source === undefined ? {} : { source: parsed.payload.source }),
|
|
60
|
+
...(Number.isNaN(timestamp) ? {} : { timestampMs: timestamp }),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function defaultCodexRolloutLocator(sessionsDir = codexSessionsDir()) {
|
|
68
|
+
return {
|
|
69
|
+
byThreadId(threadId) {
|
|
70
|
+
const suffix = `-${threadId}.jsonl`;
|
|
71
|
+
for (const day of dayDirsNewestFirst(sessionsDir, 366)) {
|
|
72
|
+
for (const entry of readdirSync(day)) {
|
|
73
|
+
if (entry.endsWith(suffix))
|
|
74
|
+
return join(day, entry);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
},
|
|
79
|
+
freshMcpSession(notBeforeMs, claimed) {
|
|
80
|
+
const candidates = [];
|
|
81
|
+
for (const day of dayDirsNewestFirst(sessionsDir, 2)) {
|
|
82
|
+
for (const entry of readdirSync(day)) {
|
|
83
|
+
if (!entry.endsWith(".jsonl"))
|
|
84
|
+
continue;
|
|
85
|
+
const path = join(day, entry);
|
|
86
|
+
if (claimed.has(path))
|
|
87
|
+
continue;
|
|
88
|
+
try {
|
|
89
|
+
if (statSync(path).mtimeMs < notBeforeMs - 5_000)
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const meta = sessionMeta(path);
|
|
96
|
+
if (meta?.source !== "mcp")
|
|
97
|
+
continue;
|
|
98
|
+
if (meta.timestampMs === undefined || meta.timestampMs < notBeforeMs - 5_000)
|
|
99
|
+
continue;
|
|
100
|
+
candidates.push({ path, timestampMs: meta.timestampMs });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return candidates.sort((a, b) => a.timestampMs - b.timestampMs)[0]?.path;
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** Consumes complete journal lines from `buffer` + `chunk`, returning mapped events and the unparsed tail. */
|
|
108
|
+
export function parseRolloutChunk(buffer, chunk) {
|
|
109
|
+
const combined = buffer + chunk;
|
|
110
|
+
const boundary = combined.lastIndexOf("\n");
|
|
111
|
+
if (boundary === -1)
|
|
112
|
+
return { rest: combined, events: [] };
|
|
113
|
+
const events = [];
|
|
114
|
+
for (const line of combined.slice(0, boundary).split("\n")) {
|
|
115
|
+
if (!line.trim())
|
|
116
|
+
continue;
|
|
117
|
+
let parsed;
|
|
118
|
+
try {
|
|
119
|
+
parsed = JSON.parse(line);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (parsed.type !== "event_msg")
|
|
125
|
+
continue;
|
|
126
|
+
const payload = parsed.payload;
|
|
127
|
+
if (payload?.type === "agent_message" && typeof payload.message === "string" && payload.message) {
|
|
128
|
+
events.push({ kind: "message", text: payload.message });
|
|
129
|
+
}
|
|
130
|
+
else if (payload?.type === "agent_reasoning" && typeof payload.text === "string" && payload.text) {
|
|
131
|
+
events.push({ kind: "reasoning", text: payload.text });
|
|
132
|
+
}
|
|
133
|
+
else if (payload?.type === "task_complete") {
|
|
134
|
+
events.push({ kind: "turnComplete" });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return { rest: combined.slice(boundary + 1), events };
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=codexRollout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexRollout.js","sourceRoot":"","sources":["../../../src/claude/session/codexRollout.ts"],"names":[],"mappings":"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"}
|
|
@@ -110,6 +110,9 @@ export type MainStreamFact = {
|
|
|
110
110
|
} | {
|
|
111
111
|
readonly kind: "instantAgent";
|
|
112
112
|
readonly text: string;
|
|
113
|
+
} | {
|
|
114
|
+
readonly kind: "instantReasoning";
|
|
115
|
+
readonly text: string;
|
|
113
116
|
} | {
|
|
114
117
|
readonly kind: "settle";
|
|
115
118
|
readonly phase: "commentary" | "final_answer";
|
|
@@ -727,6 +730,12 @@ export type ClaudeSessionCommand = {
|
|
|
727
730
|
readonly type: "captureToolFileAfter";
|
|
728
731
|
readonly runtimeGeneration: number;
|
|
729
732
|
readonly providerId: string;
|
|
733
|
+
} | {
|
|
734
|
+
readonly type: "codexMcpCallBegin";
|
|
735
|
+
readonly runtimeGeneration: number;
|
|
736
|
+
readonly providerId: string;
|
|
737
|
+
readonly ownerProviderId?: string;
|
|
738
|
+
readonly input: Record<string, unknown>;
|
|
730
739
|
} | {
|
|
731
740
|
readonly type: "hook";
|
|
732
741
|
readonly runtimeGeneration: number;
|
|
@@ -6,6 +6,7 @@ import type { ClaudeOutputAdapter } from "./outputAdapter.js";
|
|
|
6
6
|
import { type ClaudeSessionRepository } from "./repository.js";
|
|
7
7
|
import { ShellRunner } from "./shellRunner.js";
|
|
8
8
|
import { type BackgroundOutputReader } from "./backgroundOutput.js";
|
|
9
|
+
import { type CodexRolloutLocator } from "./codexRollout.js";
|
|
9
10
|
import type { TurnStartParams } from "../../codex/generated/v2/TurnStartParams.js";
|
|
10
11
|
import type { TurnSteerParams } from "../../codex/generated/v2/TurnSteerParams.js";
|
|
11
12
|
import type { ThreadBackgroundTerminal } from "../../codex/generated/v2/ThreadBackgroundTerminal.js";
|
|
@@ -47,6 +48,7 @@ export declare class ClaudeSession implements ClaudeSessionHandle<ClaudeSessionC
|
|
|
47
48
|
private readonly shellRunner;
|
|
48
49
|
private readonly backgroundOutputReader;
|
|
49
50
|
private readonly runtimeDependencies?;
|
|
51
|
+
private readonly codexRolloutLocator;
|
|
50
52
|
private readonly mailbox;
|
|
51
53
|
private readonly consumer;
|
|
52
54
|
private runtimeLineage;
|
|
@@ -63,6 +65,8 @@ export declare class ClaudeSession implements ClaudeSessionHandle<ClaudeSessionC
|
|
|
63
65
|
private runtimeGeneration;
|
|
64
66
|
private readonly scopes;
|
|
65
67
|
private readonly tasks;
|
|
68
|
+
private readonly codexMcpTailers;
|
|
69
|
+
private readonly codexRolloutClaims;
|
|
66
70
|
private compaction;
|
|
67
71
|
private automaticCompaction;
|
|
68
72
|
private readonly compactionActions;
|
|
@@ -93,7 +97,7 @@ export declare class ClaudeSession implements ClaudeSessionHandle<ClaudeSessionC
|
|
|
93
97
|
private hookDisplayOrder;
|
|
94
98
|
private adminOperation;
|
|
95
99
|
private shell;
|
|
96
|
-
constructor(threadId: string, repository: ClaudeSessionRepository, output: ClaudeOutputAdapter, capacity?: number, metrics?: MetricsRegistry, onLifecycle?: (update: SessionLifecycleUpdate) => void, onChildCreated?: (threadId: string) => void, onChildRemoved?: (threadId: string) => void, shellRunner?: ShellRunner, backgroundOutputReader?: BackgroundOutputReader, runtimeDependencies?: ClaudeSessionRuntimeDependencies | undefined);
|
|
100
|
+
constructor(threadId: string, repository: ClaudeSessionRepository, output: ClaudeOutputAdapter, capacity?: number, metrics?: MetricsRegistry, onLifecycle?: (update: SessionLifecycleUpdate) => void, onChildCreated?: (threadId: string) => void, onChildRemoved?: (threadId: string) => void, shellRunner?: ShellRunner, backgroundOutputReader?: BackgroundOutputReader, runtimeDependencies?: ClaudeSessionRuntimeDependencies | undefined, codexRolloutLocator?: CodexRolloutLocator);
|
|
97
101
|
submit<Result>(command: ClaudeSessionCommand): Promise<Result>;
|
|
98
102
|
private submitLineage;
|
|
99
103
|
private submitRuntimeEffect;
|
|
@@ -262,6 +266,11 @@ export declare class ClaudeSession implements ClaudeSessionHandle<ClaudeSessionC
|
|
|
262
266
|
private findTool;
|
|
263
267
|
private toolOwner;
|
|
264
268
|
private captureToolFileBefore;
|
|
269
|
+
private codexMcpCallBegin;
|
|
270
|
+
private ensureCodexRolloutTailer;
|
|
271
|
+
private drainCodexRollout;
|
|
272
|
+
private finishCodexRolloutTailer;
|
|
273
|
+
private stopCodexRolloutTailer;
|
|
265
274
|
private captureToolFileAfter;
|
|
266
275
|
private acceptHook;
|
|
267
276
|
private syncInteractionStatus;
|
|
@@ -17,7 +17,9 @@ import { bindGoalTurn, consumeGoalContinuation, dispatchGoal, finishGoalTurn, go
|
|
|
17
17
|
import { ShellRunner } from "./shellRunner.js";
|
|
18
18
|
import { diffFile, snapshotFile } from "../fileSnapshots.js";
|
|
19
19
|
import { appendHookProgress, completeHookRun, startHookRun } from "../hookMapper.js";
|
|
20
|
+
import { stat } from "node:fs/promises";
|
|
20
21
|
import { readBackgroundOutput } from "./backgroundOutput.js";
|
|
22
|
+
import { CODEX_MCP_MESSAGE_LABEL, CODEX_MCP_PROMPT_LABEL, CODEX_MCP_REASONING_LABEL, CODEX_MCP_TOOLS, defaultCodexRolloutLocator, parseRolloutChunk, } from "./codexRollout.js";
|
|
21
23
|
import { createGoalMcpServer } from "../goalTools.js";
|
|
22
24
|
import { mapUserInput } from "../inputMapper.js";
|
|
23
25
|
import { bashCommandActions } from "../commandActions.js";
|
|
@@ -118,6 +120,7 @@ export class ClaudeSession {
|
|
|
118
120
|
shellRunner;
|
|
119
121
|
backgroundOutputReader;
|
|
120
122
|
runtimeDependencies;
|
|
123
|
+
codexRolloutLocator;
|
|
121
124
|
mailbox;
|
|
122
125
|
consumer;
|
|
123
126
|
runtimeLineage = { state: "absent" };
|
|
@@ -134,6 +137,8 @@ export class ClaudeSession {
|
|
|
134
137
|
runtimeGeneration;
|
|
135
138
|
scopes = new Map();
|
|
136
139
|
tasks = new Map();
|
|
140
|
+
codexMcpTailers = new Map();
|
|
141
|
+
codexRolloutClaims = new Set();
|
|
137
142
|
compaction;
|
|
138
143
|
automaticCompaction;
|
|
139
144
|
compactionActions = [];
|
|
@@ -164,7 +169,7 @@ export class ClaudeSession {
|
|
|
164
169
|
hookDisplayOrder = 0;
|
|
165
170
|
adminOperation;
|
|
166
171
|
shell;
|
|
167
|
-
constructor(threadId, repository, output, capacity, metrics = new MetricsRegistry(), onLifecycle = () => undefined, onChildCreated = () => undefined, onChildRemoved = () => undefined, shellRunner = new ShellRunner(), backgroundOutputReader = readBackgroundOutput, runtimeDependencies) {
|
|
172
|
+
constructor(threadId, repository, output, capacity, metrics = new MetricsRegistry(), onLifecycle = () => undefined, onChildCreated = () => undefined, onChildRemoved = () => undefined, shellRunner = new ShellRunner(), backgroundOutputReader = readBackgroundOutput, runtimeDependencies, codexRolloutLocator = defaultCodexRolloutLocator()) {
|
|
168
173
|
this.threadId = threadId;
|
|
169
174
|
this.repository = repository;
|
|
170
175
|
this.output = output;
|
|
@@ -175,6 +180,7 @@ export class ClaudeSession {
|
|
|
175
180
|
this.shellRunner = shellRunner;
|
|
176
181
|
this.backgroundOutputReader = backgroundOutputReader;
|
|
177
182
|
this.runtimeDependencies = runtimeDependencies;
|
|
183
|
+
this.codexRolloutLocator = codexRolloutLocator;
|
|
178
184
|
this.mailbox = new ClaudeMailbox(capacity);
|
|
179
185
|
this.consumer = this.run();
|
|
180
186
|
}
|
|
@@ -2089,6 +2095,15 @@ export class ClaudeSession {
|
|
|
2089
2095
|
toolName: input.tool_name,
|
|
2090
2096
|
input: toolInput,
|
|
2091
2097
|
});
|
|
2098
|
+
if (CODEX_MCP_TOOLS.has(input.tool_name)) {
|
|
2099
|
+
await this.submitProviderProjection(runtimeGeneration, {
|
|
2100
|
+
type: "codexMcpCallBegin",
|
|
2101
|
+
runtimeGeneration,
|
|
2102
|
+
providerId: toolUseId,
|
|
2103
|
+
...(input.agent_id ? { ownerProviderId: input.agent_id } : {}),
|
|
2104
|
+
input: toolInput,
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2092
2107
|
}
|
|
2093
2108
|
if (policy.decision === "defer" || policy.decision === "ask")
|
|
2094
2109
|
return { continue: true };
|
|
@@ -2284,6 +2299,9 @@ export class ClaudeSession {
|
|
|
2284
2299
|
const backgroundId = backgroundTaskId(message);
|
|
2285
2300
|
const itemIds = [];
|
|
2286
2301
|
for (const result of toolResults(message)) {
|
|
2302
|
+
if (this.codexMcpTailers.has(result.toolUseId)) {
|
|
2303
|
+
await this.finishCodexRolloutTailer(result.toolUseId);
|
|
2304
|
+
}
|
|
2287
2305
|
const outputFile = backgroundOutputFile(result.output);
|
|
2288
2306
|
const projected = backgroundId
|
|
2289
2307
|
? await this.applyProviderMainStream(projection, runtimeGeneration, {
|
|
@@ -4248,6 +4266,8 @@ export class ClaudeSession {
|
|
|
4248
4266
|
}
|
|
4249
4267
|
case "captureToolFileBefore":
|
|
4250
4268
|
return this.captureToolFileBefore(command);
|
|
4269
|
+
case "codexMcpCallBegin":
|
|
4270
|
+
return this.codexMcpCallBegin(command);
|
|
4251
4271
|
case "captureToolFileAfter":
|
|
4252
4272
|
return this.captureToolFileAfter(command.runtimeGeneration, command.providerId);
|
|
4253
4273
|
case "hook":
|
|
@@ -5995,6 +6015,131 @@ export class ClaudeSession {
|
|
|
5995
6015
|
tool.fileSnapshot = snapshot;
|
|
5996
6016
|
return true;
|
|
5997
6017
|
}
|
|
6018
|
+
codexMcpCallBegin(command) {
|
|
6019
|
+
if (command.runtimeGeneration !== this.runtimeGeneration || this.interruptFence || this.dropLateFacts)
|
|
6020
|
+
return false;
|
|
6021
|
+
let owner = this.toolOwner(command.providerId);
|
|
6022
|
+
if (!owner && command.ownerProviderId) {
|
|
6023
|
+
owner = this.toolOwner(command.ownerProviderId);
|
|
6024
|
+
const task = [...this.tasks.values()].find((candidate) => taskUsesProvider(candidate, command.ownerProviderId) || candidate.taskId === command.ownerProviderId);
|
|
6025
|
+
if (task?.childThreadId)
|
|
6026
|
+
owner = this.scopes.get(task.childThreadId);
|
|
6027
|
+
}
|
|
6028
|
+
owner ??= this.scopes.get(this.threadId);
|
|
6029
|
+
if (!owner)
|
|
6030
|
+
return false;
|
|
6031
|
+
const prompt = typeof command.input.prompt === "string" ? command.input.prompt : "";
|
|
6032
|
+
if (prompt) {
|
|
6033
|
+
this.projectMainStream(owner.ownerThreadId, {
|
|
6034
|
+
kind: "instantAgent",
|
|
6035
|
+
text: `${CODEX_MCP_PROMPT_LABEL}\n\n${prompt}`,
|
|
6036
|
+
}, nullSource);
|
|
6037
|
+
}
|
|
6038
|
+
this.ensureCodexRolloutTailer(command.providerId, owner.ownerThreadId, typeof command.input.threadId === "string" ? command.input.threadId : undefined);
|
|
6039
|
+
return true;
|
|
6040
|
+
}
|
|
6041
|
+
ensureCodexRolloutTailer(providerId, ownerThreadId, codexThreadId) {
|
|
6042
|
+
if (this.codexMcpTailers.has(providerId))
|
|
6043
|
+
return;
|
|
6044
|
+
const runtimeGeneration = this.runtimeGeneration;
|
|
6045
|
+
if (runtimeGeneration === undefined)
|
|
6046
|
+
return;
|
|
6047
|
+
const tailer = {
|
|
6048
|
+
runtimeGeneration, ownerThreadId, codexThreadId,
|
|
6049
|
+
notBeforeMs: Date.now(), offset: 0, buffer: "",
|
|
6050
|
+
decoder: new TextDecoder(),
|
|
6051
|
+
timer: setInterval(() => { void this.drainCodexRollout(providerId).catch(() => undefined); }, 250),
|
|
6052
|
+
stopped: false, sawTurnComplete: false,
|
|
6053
|
+
};
|
|
6054
|
+
tailer.timer.unref();
|
|
6055
|
+
this.codexMcpTailers.set(providerId, tailer);
|
|
6056
|
+
void this.drainCodexRollout(providerId).catch(() => undefined);
|
|
6057
|
+
}
|
|
6058
|
+
async drainCodexRollout(providerId, final = false) {
|
|
6059
|
+
const tailer = this.codexMcpTailers.get(providerId);
|
|
6060
|
+
if (!tailer || tailer.stopped)
|
|
6061
|
+
return;
|
|
6062
|
+
if (tailer.reading) {
|
|
6063
|
+
const reading = tailer.reading;
|
|
6064
|
+
await reading;
|
|
6065
|
+
if (tailer.reading === reading)
|
|
6066
|
+
tailer.reading = undefined;
|
|
6067
|
+
if (final)
|
|
6068
|
+
await this.drainCodexRollout(providerId, true);
|
|
6069
|
+
return;
|
|
6070
|
+
}
|
|
6071
|
+
const reading = (async () => {
|
|
6072
|
+
if (!tailer.file) {
|
|
6073
|
+
if (tailer.codexThreadId) {
|
|
6074
|
+
// Continuation of an existing codex thread: the journal already holds
|
|
6075
|
+
// prior turns, so start from its current end.
|
|
6076
|
+
const file = this.codexRolloutLocator.byThreadId(tailer.codexThreadId);
|
|
6077
|
+
if (!file)
|
|
6078
|
+
return;
|
|
6079
|
+
tailer.offset = await stat(file).then((info) => info.size, () => 0);
|
|
6080
|
+
tailer.file = file;
|
|
6081
|
+
}
|
|
6082
|
+
else {
|
|
6083
|
+
const file = this.codexRolloutLocator.freshMcpSession(tailer.notBeforeMs, this.codexRolloutClaims);
|
|
6084
|
+
if (!file)
|
|
6085
|
+
return;
|
|
6086
|
+
tailer.file = file;
|
|
6087
|
+
}
|
|
6088
|
+
this.codexRolloutClaims.add(tailer.file);
|
|
6089
|
+
}
|
|
6090
|
+
tailer.offset = await this.backgroundOutputReader(tailer.file, tailer.offset, async (bytes) => {
|
|
6091
|
+
if (tailer.stopped)
|
|
6092
|
+
return;
|
|
6093
|
+
const { rest, events } = parseRolloutChunk(tailer.buffer, tailer.decoder.decode(bytes, { stream: true }));
|
|
6094
|
+
tailer.buffer = rest;
|
|
6095
|
+
for (const event of events) {
|
|
6096
|
+
if (event.kind === "turnComplete") {
|
|
6097
|
+
tailer.sawTurnComplete = true;
|
|
6098
|
+
continue;
|
|
6099
|
+
}
|
|
6100
|
+
await this.submit({
|
|
6101
|
+
type: "mainStream",
|
|
6102
|
+
runtimeGeneration: tailer.runtimeGeneration,
|
|
6103
|
+
ownerThreadId: tailer.ownerThreadId,
|
|
6104
|
+
source: { providerEventId: null, providerEventType: "codex_rollout" },
|
|
6105
|
+
fact: event.kind === "message"
|
|
6106
|
+
? { kind: "instantAgent", text: `${CODEX_MCP_MESSAGE_LABEL}\n\n${event.text}` }
|
|
6107
|
+
: { kind: "instantReasoning", text: `${CODEX_MCP_REASONING_LABEL}\n\n${event.text}` },
|
|
6108
|
+
});
|
|
6109
|
+
}
|
|
6110
|
+
});
|
|
6111
|
+
})();
|
|
6112
|
+
tailer.reading = reading;
|
|
6113
|
+
try {
|
|
6114
|
+
await reading;
|
|
6115
|
+
}
|
|
6116
|
+
finally {
|
|
6117
|
+
if (tailer.reading === reading)
|
|
6118
|
+
tailer.reading = undefined;
|
|
6119
|
+
}
|
|
6120
|
+
}
|
|
6121
|
+
async finishCodexRolloutTailer(providerId) {
|
|
6122
|
+
const tailer = this.codexMcpTailers.get(providerId);
|
|
6123
|
+
if (!tailer)
|
|
6124
|
+
return;
|
|
6125
|
+
for (let attempt = 0; attempt < 3 && !tailer.stopped; attempt += 1) {
|
|
6126
|
+
await this.drainCodexRollout(providerId, true).catch(() => undefined);
|
|
6127
|
+
if (tailer.sawTurnComplete)
|
|
6128
|
+
break;
|
|
6129
|
+
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
6130
|
+
}
|
|
6131
|
+
this.stopCodexRolloutTailer(providerId);
|
|
6132
|
+
}
|
|
6133
|
+
stopCodexRolloutTailer(providerId) {
|
|
6134
|
+
const tailer = this.codexMcpTailers.get(providerId);
|
|
6135
|
+
if (!tailer)
|
|
6136
|
+
return;
|
|
6137
|
+
tailer.stopped = true;
|
|
6138
|
+
clearInterval(tailer.timer);
|
|
6139
|
+
if (tailer.file)
|
|
6140
|
+
this.codexRolloutClaims.delete(tailer.file);
|
|
6141
|
+
this.codexMcpTailers.delete(providerId);
|
|
6142
|
+
}
|
|
5998
6143
|
async captureToolFileAfter(runtimeGeneration, providerId) {
|
|
5999
6144
|
if (runtimeGeneration !== this.runtimeGeneration || this.interruptFence || this.dropLateFacts)
|
|
6000
6145
|
return false;
|
|
@@ -6299,6 +6444,19 @@ export class ClaudeSession {
|
|
|
6299
6444
|
itemIds = [item.id];
|
|
6300
6445
|
break;
|
|
6301
6446
|
}
|
|
6447
|
+
case "instantReasoning": {
|
|
6448
|
+
const item = { type: "reasoning", id: uuidv7(), summary: [fact.text], content: [] };
|
|
6449
|
+
turn.items.push(item);
|
|
6450
|
+
this.publishTurn(turn, "item/started", {
|
|
6451
|
+
item, threadId: state.ownerThreadId, turnId: turn.id, startedAtMs: Date.now(),
|
|
6452
|
+
}, source);
|
|
6453
|
+
this.publishTurn(turn, "item/reasoning/summaryTextDelta", {
|
|
6454
|
+
threadId: state.ownerThreadId, turnId: turn.id, itemId: item.id, delta: fact.text, summaryIndex: 0,
|
|
6455
|
+
}, source);
|
|
6456
|
+
this.completeStreamItem(turn, state, item.id, source);
|
|
6457
|
+
itemIds = [item.id];
|
|
6458
|
+
break;
|
|
6459
|
+
}
|
|
6302
6460
|
case "settle":
|
|
6303
6461
|
this.settleAgentMessages(turn, state, fact.phase, source);
|
|
6304
6462
|
break;
|
|
@@ -6431,8 +6589,10 @@ export class ClaudeSession {
|
|
|
6431
6589
|
if (itemIds.has(id))
|
|
6432
6590
|
state.blockItems.delete(index);
|
|
6433
6591
|
for (const [id, candidate] of state.tools)
|
|
6434
|
-
if (itemIds.has(candidate.itemId))
|
|
6592
|
+
if (itemIds.has(candidate.itemId)) {
|
|
6435
6593
|
state.tools.delete(id);
|
|
6594
|
+
this.stopCodexRolloutTailer(id);
|
|
6595
|
+
}
|
|
6436
6596
|
for (const [id, task] of this.tasks)
|
|
6437
6597
|
if (itemIds.has(task.itemId)) {
|
|
6438
6598
|
this.stopBackgroundTailer(task);
|
|
@@ -6535,6 +6695,8 @@ export class ClaudeSession {
|
|
|
6535
6695
|
disposeRuntimeOperations() {
|
|
6536
6696
|
for (const task of this.tasks.values())
|
|
6537
6697
|
this.stopBackgroundTailer(task);
|
|
6698
|
+
for (const providerId of [...this.codexMcpTailers.keys()])
|
|
6699
|
+
this.stopCodexRolloutTailer(providerId);
|
|
6538
6700
|
for (const state of this.scopes.values()) {
|
|
6539
6701
|
for (const tool of state.tools.values())
|
|
6540
6702
|
delete tool.fileSnapshot;
|