@getpaseo/server 0.1.75 → 0.1.77
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/dist/server/client/daemon-client.d.ts +14 -2
- package/dist/server/client/daemon-client.d.ts.map +1 -1
- package/dist/server/client/daemon-client.js +37 -0
- package/dist/server/client/daemon-client.js.map +1 -1
- package/dist/server/server/agent/agent-manager.d.ts +2 -1
- package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
- package/dist/server/server/agent/agent-manager.js +21 -10
- package/dist/server/server/agent/agent-manager.js.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.d.ts +5 -0
- package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
- package/dist/server/server/agent/agent-sdk-types.js +7 -0
- package/dist/server/server/agent/agent-sdk-types.js.map +1 -1
- package/dist/server/server/agent/import-sessions.d.ts.map +1 -1
- package/dist/server/server/agent/import-sessions.js +6 -2
- package/dist/server/server/agent/import-sessions.js.map +1 -1
- package/dist/server/server/agent/mcp-server.d.ts.map +1 -1
- package/dist/server/server/agent/mcp-server.js +227 -4
- package/dist/server/server/agent/mcp-server.js.map +1 -1
- package/dist/server/server/agent/provider-history-timestamps.d.ts +2 -0
- package/dist/server/server/agent/provider-history-timestamps.d.ts.map +1 -0
- package/dist/server/server/agent/provider-history-timestamps.js +16 -0
- package/dist/server/server/agent/provider-history-timestamps.js.map +1 -0
- package/dist/server/server/agent/provider-manifest.d.ts +1 -1
- package/dist/server/server/agent/provider-manifest.d.ts.map +1 -1
- package/dist/server/server/agent/provider-manifest.js +14 -0
- package/dist/server/server/agent/provider-manifest.js.map +1 -1
- package/dist/server/server/agent/provider-registry.d.ts.map +1 -1
- package/dist/server/server/agent/provider-registry.js +53 -27
- package/dist/server/server/agent/provider-registry.js.map +1 -1
- package/dist/server/server/agent/provider-snapshot-manager.d.ts +2 -6
- package/dist/server/server/agent/provider-snapshot-manager.d.ts.map +1 -1
- package/dist/server/server/agent/provider-snapshot-manager.js +43 -32
- package/dist/server/server/agent/provider-snapshot-manager.js.map +1 -1
- package/dist/server/server/agent/providers/acp-agent.d.ts +3 -1
- package/dist/server/server/agent/providers/acp-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/acp-agent.js +61 -14
- package/dist/server/server/agent/providers/acp-agent.js.map +1 -1
- package/dist/server/server/agent/providers/claude/agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/agent.js +111 -38
- package/dist/server/server/agent/providers/claude/agent.js.map +1 -1
- package/dist/server/server/agent/providers/claude/models.d.ts +2 -0
- package/dist/server/server/agent/providers/claude/models.d.ts.map +1 -1
- package/dist/server/server/agent/providers/claude/models.js +78 -0
- package/dist/server/server/agent/providers/claude/models.js.map +1 -1
- package/dist/server/server/agent/providers/codex/app-server-transport.d.ts +1 -0
- package/dist/server/server/agent/providers/codex/app-server-transport.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex/app-server-transport.js +14 -10
- package/dist/server/server/agent/providers/codex/app-server-transport.js.map +1 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +15 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/codex-app-server-agent.js +372 -69
- package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
- package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +21 -0
- package/dist/server/server/agent/providers/cursor-acp-agent.d.ts.map +1 -0
- package/dist/server/server/agent/providers/cursor-acp-agent.js +85 -0
- package/dist/server/server/agent/providers/cursor-acp-agent.js.map +1 -0
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts +13 -0
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/generic-acp-agent.js +209 -2
- package/dist/server/server/agent/providers/generic-acp-agent.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/server-manager.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/server-manager.js +2 -1
- package/dist/server/server/agent/providers/opencode/server-manager.js.map +1 -1
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts +7 -0
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js +50 -1
- package/dist/server/server/agent/providers/opencode/test-utils/test-opencode-runtime.js.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.d.ts +11 -7
- package/dist/server/server/agent/providers/opencode-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/opencode-agent.js +307 -346
- package/dist/server/server/agent/providers/opencode-agent.js.map +1 -1
- package/dist/server/server/agent/providers/pi-direct-agent.d.ts +1 -1
- package/dist/server/server/agent/providers/pi-direct-agent.d.ts.map +1 -1
- package/dist/server/server/agent/providers/pi-direct-agent.js +14 -0
- package/dist/server/server/agent/providers/pi-direct-agent.js.map +1 -1
- package/dist/server/server/agent/providers/pi-session-recovery-policy.d.ts +22 -0
- package/dist/server/server/agent/providers/pi-session-recovery-policy.d.ts.map +1 -0
- package/dist/server/server/agent/providers/pi-session-recovery-policy.js +51 -0
- package/dist/server/server/agent/providers/pi-session-recovery-policy.js.map +1 -0
- package/dist/server/server/agent/providers/tool-call-detail-primitives.d.ts.map +1 -1
- package/dist/server/server/agent/timeline-projection.d.ts.map +1 -1
- package/dist/server/server/agent/timeline-projection.js +9 -0
- package/dist/server/server/agent/timeline-projection.js.map +1 -1
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +40 -0
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts.map +1 -0
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +80 -0
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.js.map +1 -0
- package/dist/server/server/auto-archive-on-merge/index.d.ts +8 -0
- package/dist/server/server/auto-archive-on-merge/index.d.ts.map +1 -0
- package/dist/server/server/auto-archive-on-merge/index.js +15 -0
- package/dist/server/server/auto-archive-on-merge/index.js.map +1 -0
- package/dist/server/server/bootstrap.d.ts +2 -0
- package/dist/server/server/bootstrap.d.ts.map +1 -1
- package/dist/server/server/bootstrap.js +82 -40
- package/dist/server/server/bootstrap.js.map +1 -1
- package/dist/server/server/checkout/status-projection.d.ts.map +1 -1
- package/dist/server/server/checkout/status-projection.js +5 -1
- package/dist/server/server/checkout/status-projection.js.map +1 -1
- package/dist/server/server/config.d.ts.map +1 -1
- package/dist/server/server/config.js +13 -5
- package/dist/server/server/config.js.map +1 -1
- package/dist/server/server/daemon-config-store.js +1 -0
- package/dist/server/server/daemon-config-store.js.map +1 -1
- package/dist/server/server/loop/rpc-schemas.d.ts +96 -96
- package/dist/server/server/loop-service.d.ts +18 -18
- package/dist/server/server/pairing-offer.d.ts +1 -0
- package/dist/server/server/pairing-offer.d.ts.map +1 -1
- package/dist/server/server/pairing-offer.js +2 -1
- package/dist/server/server/pairing-offer.js.map +1 -1
- package/dist/server/server/paseo-worktree-service.d.ts +3 -1
- package/dist/server/server/paseo-worktree-service.d.ts.map +1 -1
- package/dist/server/server/paseo-worktree-service.js +55 -18
- package/dist/server/server/paseo-worktree-service.js.map +1 -1
- package/dist/server/server/persisted-config.d.ts +16 -0
- package/dist/server/server/persisted-config.d.ts.map +1 -1
- package/dist/server/server/persisted-config.js +11 -3
- package/dist/server/server/persisted-config.js.map +1 -1
- package/dist/server/server/relay-transport.d.ts +2 -1
- package/dist/server/server/relay-transport.d.ts.map +1 -1
- package/dist/server/server/relay-transport.js +26 -4
- package/dist/server/server/relay-transport.js.map +1 -1
- package/dist/server/server/session.d.ts +6 -0
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +195 -34
- package/dist/server/server/session.js.map +1 -1
- package/dist/server/server/utils/diff-highlighter.d.ts.map +1 -1
- package/dist/server/server/utils/diff-highlighter.js +30 -9
- package/dist/server/server/utils/diff-highlighter.js.map +1 -1
- package/dist/server/server/websocket-server.d.ts.map +1 -1
- package/dist/server/server/websocket-server.js +5 -0
- package/dist/server/server/websocket-server.js.map +1 -1
- package/dist/server/server/workspace-git-service.d.ts +6 -1
- package/dist/server/server/workspace-git-service.d.ts.map +1 -1
- package/dist/server/server/workspace-git-service.js +27 -4
- package/dist/server/server/workspace-git-service.js.map +1 -1
- package/dist/server/server/workspace-reconciliation-service.d.ts +4 -2
- package/dist/server/server/workspace-reconciliation-service.d.ts.map +1 -1
- package/dist/server/server/workspace-reconciliation-service.js +112 -14
- package/dist/server/server/workspace-reconciliation-service.js.map +1 -1
- package/dist/server/server/workspace-registry.d.ts +6 -1
- package/dist/server/server/workspace-registry.d.ts.map +1 -1
- package/dist/server/server/workspace-registry.js +11 -0
- package/dist/server/server/workspace-registry.js.map +1 -1
- package/dist/server/server/worktree-session.d.ts.map +1 -1
- package/dist/server/server/worktree-session.js +1 -0
- package/dist/server/server/worktree-session.js.map +1 -1
- package/dist/server/services/github-service.d.ts +46 -0
- package/dist/server/services/github-service.d.ts.map +1 -1
- package/dist/server/services/github-service.js +274 -5
- package/dist/server/services/github-service.js.map +1 -1
- package/dist/server/shared/messages.d.ts +3443 -290
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +94 -3
- package/dist/server/shared/messages.js.map +1 -1
- package/dist/server/shared/terminal-input-mode.d.ts +26 -0
- package/dist/server/shared/terminal-input-mode.d.ts.map +1 -0
- package/dist/server/shared/terminal-input-mode.js +151 -0
- package/dist/server/shared/terminal-input-mode.js.map +1 -0
- package/dist/server/terminal/terminal-session-controller.d.ts.map +1 -1
- package/dist/server/terminal/terminal-session-controller.js +12 -2
- package/dist/server/terminal/terminal-session-controller.js.map +1 -1
- package/dist/server/terminal/terminal.d.ts +1 -0
- package/dist/server/terminal/terminal.d.ts.map +1 -1
- package/dist/server/terminal/terminal.js +16 -3
- package/dist/server/terminal/terminal.js.map +1 -1
- package/dist/server/terminal/worker-terminal-manager.d.ts.map +1 -1
- package/dist/server/terminal/worker-terminal-manager.js +8 -0
- package/dist/server/terminal/worker-terminal-manager.js.map +1 -1
- package/dist/server/utils/checkout-git.d.ts +4 -1
- package/dist/server/utils/checkout-git.d.ts.map +1 -1
- package/dist/server/utils/checkout-git.js +85 -29
- package/dist/server/utils/checkout-git.js.map +1 -1
- package/dist/server/utils/directory-suggestions.d.ts +2 -0
- package/dist/server/utils/directory-suggestions.d.ts.map +1 -1
- package/dist/server/utils/directory-suggestions.js +87 -14
- package/dist/server/utils/directory-suggestions.js.map +1 -1
- package/dist/server/utils/executable.d.ts.map +1 -1
- package/dist/server/utils/executable.js +6 -3
- package/dist/server/utils/executable.js.map +1 -1
- package/dist/server/utils/path.d.ts +10 -0
- package/dist/server/utils/path.d.ts.map +1 -1
- package/dist/server/utils/path.js +65 -1
- package/dist/server/utils/path.js.map +1 -1
- package/dist/server/utils/run-git-command.d.ts +2 -0
- package/dist/server/utils/run-git-command.d.ts.map +1 -1
- package/dist/server/utils/run-git-command.js +41 -1
- package/dist/server/utils/run-git-command.js.map +1 -1
- package/dist/server/utils/worktree.js +1 -1
- package/dist/server/utils/worktree.js.map +1 -1
- package/dist/src/server/agent/agent-sdk-types.js +7 -0
- package/dist/src/server/agent/agent-sdk-types.js.map +1 -1
- package/dist/src/server/agent/provider-manifest.js +14 -0
- package/dist/src/server/agent/provider-manifest.js.map +1 -1
- package/dist/src/server/persisted-config.js +11 -3
- package/dist/src/server/persisted-config.js.map +1 -1
- package/dist/src/shared/messages.js +94 -3
- package/dist/src/shared/messages.js.map +1 -1
- package/dist/src/utils/executable.js +6 -3
- package/dist/src/utils/executable.js.map +1 -1
- package/package.json +3 -3
|
@@ -11,11 +11,13 @@ import { curateAgentActivity } from "../activity-curator.js";
|
|
|
11
11
|
import { mapCodexRolloutToolCall, mapCodexToolCallFromThreadItem, } from "./codex/tool-call-mapper.js";
|
|
12
12
|
import { createProviderEnv, createProviderEnvSpec, resolveProviderCommandPrefix, } from "../provider-launch-config.js";
|
|
13
13
|
import { findExecutable, isCommandAvailable } from "../../../utils/executable.js";
|
|
14
|
+
import { createPathEquivalenceMatcher } from "../../../utils/path.js";
|
|
14
15
|
import { spawnProcess } from "../../../utils/spawn.js";
|
|
15
16
|
import { extractCodexTerminalSessionId, nonEmptyString } from "./tool-call-mapper-utils.js";
|
|
16
17
|
import { buildCodexFeatures, codexModelSupportsFastMode } from "./codex-feature-definitions.js";
|
|
17
18
|
import { CodexAppServerClient, } from "./codex/app-server-transport.js";
|
|
18
19
|
import { renderProviderImageOutputAsAssistantMarkdown, } from "./provider-image-output.js";
|
|
20
|
+
import { normalizeProviderReplayTimestamp } from "../provider-history-timestamps.js";
|
|
19
21
|
import { formatDiagnosticStatus, formatProviderDiagnostic, formatProviderDiagnosticError, resolveBinaryVersion, toDiagnosticErrorMessage, } from "./diagnostic-utils.js";
|
|
20
22
|
import { runProviderTurn } from "./provider-runner.js";
|
|
21
23
|
function assertChildWithPipes(child) {
|
|
@@ -38,11 +40,13 @@ const CODEX_TOOL_THREAD_ITEM_TYPES = new Set([
|
|
|
38
40
|
"webSearch",
|
|
39
41
|
"collabAgentToolCall",
|
|
40
42
|
]);
|
|
43
|
+
const CODEX_CONTEXT_COMPACTION_TYPE = "contextCompaction";
|
|
41
44
|
const CODEX_PLAN_IMPLEMENTATION_PROMPT_PREFIX = "The user approved the plan. Implement it now. Do not restate or revise the plan unless blocked.";
|
|
42
45
|
// Codex's experimental `goals` feature ships in 0.128.0+. Older binaries reject
|
|
43
46
|
// `--enable goals` at launch, so we gate by version and silently skip the flag
|
|
44
47
|
// (and the /goal slash command) when the binary is too old.
|
|
45
48
|
const CODEX_GOALS_MIN_VERSION = [0, 128, 0];
|
|
49
|
+
const CODEX_AUTO_REVIEW_MIN_VERSION = [0, 115, 0];
|
|
46
50
|
function parseCodexVersion(versionOutput) {
|
|
47
51
|
const match = versionOutput.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
48
52
|
if (!match)
|
|
@@ -91,6 +95,11 @@ const CODEX_MODES = [
|
|
|
91
95
|
label: "Default Permissions",
|
|
92
96
|
description: "Edit files and run commands with Codex's default approval flow.",
|
|
93
97
|
},
|
|
98
|
+
{
|
|
99
|
+
id: "auto-review",
|
|
100
|
+
label: "Auto-review",
|
|
101
|
+
description: "Same workspace-write permissions as Default, but eligible `on-request` approvals are routed through the auto-reviewer subagent.",
|
|
102
|
+
},
|
|
94
103
|
{
|
|
95
104
|
id: "full-access",
|
|
96
105
|
label: "Full Access",
|
|
@@ -107,12 +116,30 @@ const MODE_PRESETS = {
|
|
|
107
116
|
approvalPolicy: "on-request",
|
|
108
117
|
sandbox: "workspace-write",
|
|
109
118
|
},
|
|
119
|
+
"auto-review": {
|
|
120
|
+
approvalPolicy: "on-request",
|
|
121
|
+
sandbox: "workspace-write",
|
|
122
|
+
approvalsReviewer: "auto_review",
|
|
123
|
+
},
|
|
110
124
|
"full-access": {
|
|
111
125
|
approvalPolicy: "never",
|
|
112
126
|
sandbox: "danger-full-access",
|
|
113
127
|
networkAccess: true,
|
|
114
128
|
},
|
|
115
129
|
};
|
|
130
|
+
function isAutoReviewReviewer(value) {
|
|
131
|
+
return value === "auto_review" || value === "guardian_subagent";
|
|
132
|
+
}
|
|
133
|
+
function applyApprovalsReviewerParam(params, preset) {
|
|
134
|
+
if (preset.approvalsReviewer) {
|
|
135
|
+
params.approvalsReviewer = preset.approvalsReviewer;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function shouldPromoteThreadResponseToAutoReview(params) {
|
|
139
|
+
return (isAutoReviewReviewer(params.approvalsReviewer) &&
|
|
140
|
+
params.approvalPolicy === "on-request" &&
|
|
141
|
+
params.sandbox === "workspace-write");
|
|
142
|
+
}
|
|
116
143
|
function validateCodexMode(modeId) {
|
|
117
144
|
if (!(modeId in MODE_PRESETS)) {
|
|
118
145
|
const validModes = Object.keys(MODE_PRESETS).join(", ");
|
|
@@ -484,7 +511,8 @@ function filterCodexThreadsByCwd(threads, cwd) {
|
|
|
484
511
|
// falls back to process.cwd() if the field is missing, so we only match
|
|
485
512
|
// here when the row genuinely carries a cwd string — otherwise threads
|
|
486
513
|
// with no cwd would falsely match the daemon's own cwd.
|
|
487
|
-
|
|
514
|
+
const matchesCwd = createPathEquivalenceMatcher(cwd);
|
|
515
|
+
return threads.filter((thread) => typeof thread.cwd === "string" && matchesCwd(thread.cwd));
|
|
488
516
|
}
|
|
489
517
|
function toAgentUsage(tokenUsage) {
|
|
490
518
|
const usage = toObjectRecord(tokenUsage);
|
|
@@ -1070,6 +1098,29 @@ function firstStringField(record, fields) {
|
|
|
1070
1098
|
}
|
|
1071
1099
|
return null;
|
|
1072
1100
|
}
|
|
1101
|
+
function readCodexHistoryTimestamp(item) {
|
|
1102
|
+
const record = toObjectRecord(item);
|
|
1103
|
+
if (!record) {
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
return (normalizeProviderReplayTimestamp(record.timestamp) ??
|
|
1107
|
+
normalizeProviderReplayTimestamp(record.createdAt) ??
|
|
1108
|
+
normalizeProviderReplayTimestamp(record.created_at));
|
|
1109
|
+
}
|
|
1110
|
+
function readCodexTurnHistoryTimestamp(turn, timelineItem) {
|
|
1111
|
+
const record = toObjectRecord(turn);
|
|
1112
|
+
if (!record) {
|
|
1113
|
+
return null;
|
|
1114
|
+
}
|
|
1115
|
+
const startedAt = normalizeProviderReplayTimestamp(record.startedAt) ??
|
|
1116
|
+
normalizeProviderReplayTimestamp(record.started_at);
|
|
1117
|
+
const completedAt = normalizeProviderReplayTimestamp(record.completedAt) ??
|
|
1118
|
+
normalizeProviderReplayTimestamp(record.completed_at);
|
|
1119
|
+
if (timelineItem.type === "user_message") {
|
|
1120
|
+
return startedAt ?? completedAt;
|
|
1121
|
+
}
|
|
1122
|
+
return completedAt ?? startedAt;
|
|
1123
|
+
}
|
|
1073
1124
|
function codexImageOutputFromResult(result) {
|
|
1074
1125
|
if (typeof result === "string") {
|
|
1075
1126
|
const trimmed = result.trim();
|
|
@@ -1139,15 +1190,23 @@ function threadItemToTimeline(item, options) {
|
|
|
1139
1190
|
switch (normalizedType) {
|
|
1140
1191
|
case "userMessage":
|
|
1141
1192
|
return mapCodexThreadUserMessageItem(normalizedItem, includeUserMessage);
|
|
1142
|
-
case "agentMessage":
|
|
1193
|
+
case "agentMessage": {
|
|
1194
|
+
const messageId = nonEmptyString(normalizedItem.id);
|
|
1143
1195
|
return {
|
|
1144
1196
|
type: "assistant_message",
|
|
1145
1197
|
text: typeof normalizedItem.text === "string" ? normalizedItem.text : "",
|
|
1198
|
+
...(messageId ? { messageId } : {}),
|
|
1146
1199
|
};
|
|
1200
|
+
}
|
|
1147
1201
|
case "plan":
|
|
1148
1202
|
return mapCodexThreadPlanItem(normalizedItem);
|
|
1149
1203
|
case "reasoning":
|
|
1150
1204
|
return mapCodexThreadReasoningItem(normalizedItem);
|
|
1205
|
+
case CODEX_CONTEXT_COMPACTION_TYPE:
|
|
1206
|
+
return {
|
|
1207
|
+
type: "compaction",
|
|
1208
|
+
status: "completed",
|
|
1209
|
+
};
|
|
1151
1210
|
default:
|
|
1152
1211
|
return null;
|
|
1153
1212
|
}
|
|
@@ -1179,7 +1238,11 @@ async function loadCodexThreadHistoryTimeline(params) {
|
|
|
1179
1238
|
for (const item of turn.items) {
|
|
1180
1239
|
const timelineItem = threadItemToTimeline(item, { cwd: params.cwd });
|
|
1181
1240
|
if (timelineItem) {
|
|
1182
|
-
|
|
1241
|
+
const timestamp = readCodexHistoryTimestamp(item) ?? readCodexTurnHistoryTimestamp(turn, timelineItem);
|
|
1242
|
+
timeline.push({
|
|
1243
|
+
item: timelineItem,
|
|
1244
|
+
timestamp: timestamp ?? undefined,
|
|
1245
|
+
});
|
|
1183
1246
|
}
|
|
1184
1247
|
}
|
|
1185
1248
|
}
|
|
@@ -1296,6 +1359,12 @@ const ItemLifecycleNotificationSchema = z
|
|
|
1296
1359
|
.passthrough(),
|
|
1297
1360
|
})
|
|
1298
1361
|
.passthrough();
|
|
1362
|
+
const ContextCompactedNotificationSchema = z
|
|
1363
|
+
.object({
|
|
1364
|
+
threadId: z.string(),
|
|
1365
|
+
turnId: z.string().optional(),
|
|
1366
|
+
})
|
|
1367
|
+
.passthrough();
|
|
1299
1368
|
const CodexEventTurnAbortedNotificationSchema = z
|
|
1300
1369
|
.object({
|
|
1301
1370
|
msg: z
|
|
@@ -1511,6 +1580,18 @@ const CodexNotificationSchema = z.union([
|
|
|
1511
1580
|
method,
|
|
1512
1581
|
params,
|
|
1513
1582
|
})),
|
|
1583
|
+
z
|
|
1584
|
+
.object({ method: z.literal("thread/compacted"), params: ContextCompactedNotificationSchema })
|
|
1585
|
+
.transform(({ params }) => ({
|
|
1586
|
+
kind: "context_compacted",
|
|
1587
|
+
threadId: params.threadId,
|
|
1588
|
+
turnId: params.turnId ?? null,
|
|
1589
|
+
})),
|
|
1590
|
+
z.object({ method: z.literal("thread/compacted"), params: z.unknown() }).transform(({ method, params }) => ({
|
|
1591
|
+
kind: "invalid_payload",
|
|
1592
|
+
method,
|
|
1593
|
+
params,
|
|
1594
|
+
})),
|
|
1514
1595
|
z
|
|
1515
1596
|
.object({
|
|
1516
1597
|
method: z.literal("item/agentMessage/delta"),
|
|
@@ -1952,12 +2033,13 @@ function buildCodexCustomProviderConfig(runtimeSettings, customProvider) {
|
|
|
1952
2033
|
};
|
|
1953
2034
|
}
|
|
1954
2035
|
class CodexAppServerAgentSession {
|
|
1955
|
-
constructor(config, resumeHandle, logger, spawnAppServer, deps = {}, ephemeral = false, goalsEnabled = false, agentId) {
|
|
2036
|
+
constructor(config, resumeHandle, logger, spawnAppServer, deps = {}, ephemeral = false, goalsEnabled = false, autoReviewEnabled = false, agentId) {
|
|
1956
2037
|
this.resumeHandle = resumeHandle;
|
|
1957
2038
|
this.spawnAppServer = spawnAppServer;
|
|
1958
2039
|
this.deps = deps;
|
|
1959
2040
|
this.ephemeral = ephemeral;
|
|
1960
2041
|
this.goalsEnabled = goalsEnabled;
|
|
2042
|
+
this.autoReviewEnabled = autoReviewEnabled;
|
|
1961
2043
|
this.agentId = agentId;
|
|
1962
2044
|
this.provider = CODEX_PROVIDER;
|
|
1963
2045
|
this.capabilities = CODEX_APP_SERVER_CAPABILITIES;
|
|
@@ -1993,6 +2075,12 @@ class CodexAppServerAgentSession {
|
|
|
1993
2075
|
this.warnedInvalidNotificationPayloads = new Set();
|
|
1994
2076
|
this.warnedIncompleteEditToolCallIds = new Set();
|
|
1995
2077
|
this.latestPlanResult = null;
|
|
2078
|
+
this.pendingManualCompactionStarts = 0;
|
|
2079
|
+
this.compactionTriggerByItemId = new Map();
|
|
2080
|
+
// Codex can report one completed compaction through both channels:
|
|
2081
|
+
// `thread/compacted` and a completed `contextCompaction` item.
|
|
2082
|
+
this.unpairedCompactionNotificationCompletions = 0;
|
|
2083
|
+
this.unpairedCompactionItemCompletions = 0;
|
|
1996
2084
|
this.connected = false;
|
|
1997
2085
|
this.collaborationModes = [];
|
|
1998
2086
|
this.resolvedCollaborationMode = null;
|
|
@@ -2009,7 +2097,7 @@ class CodexAppServerAgentSession {
|
|
|
2009
2097
|
this.currentMode = config.modeId;
|
|
2010
2098
|
this.config = config;
|
|
2011
2099
|
this.config.thinkingOptionId = normalizeCodexThinkingOptionId(this.config.thinkingOptionId);
|
|
2012
|
-
if (this.config.featureValues?.fast_mode) {
|
|
2100
|
+
if (this.config.featureValues?.fast_mode && codexModelSupportsFastMode(this.config.model)) {
|
|
2013
2101
|
this.serviceTier = "fast";
|
|
2014
2102
|
}
|
|
2015
2103
|
if (this.config.featureValues?.plan_mode) {
|
|
@@ -2094,7 +2182,7 @@ class CodexAppServerAgentSession {
|
|
|
2094
2182
|
cwd: [this.config.cwd],
|
|
2095
2183
|
}));
|
|
2096
2184
|
const entries = Array.isArray(response?.data) ? response.data : [];
|
|
2097
|
-
const
|
|
2185
|
+
const skillsByName = new Map();
|
|
2098
2186
|
for (const entry of entries) {
|
|
2099
2187
|
const entryRecord = toObjectRecord(entry);
|
|
2100
2188
|
const list = Array.isArray(entryRecord?.skills) ? entryRecord.skills : [];
|
|
@@ -2102,14 +2190,16 @@ class CodexAppServerAgentSession {
|
|
|
2102
2190
|
const skillRecord = toObjectRecord(skill);
|
|
2103
2191
|
if (typeof skillRecord?.name !== "string" || typeof skillRecord?.path !== "string")
|
|
2104
2192
|
continue;
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2193
|
+
if (!skillsByName.has(skillRecord.name)) {
|
|
2194
|
+
skillsByName.set(skillRecord.name, {
|
|
2195
|
+
name: skillRecord.name,
|
|
2196
|
+
description: resolveSkillDescription(skillRecord),
|
|
2197
|
+
path: skillRecord.path,
|
|
2198
|
+
});
|
|
2199
|
+
}
|
|
2110
2200
|
}
|
|
2111
2201
|
}
|
|
2112
|
-
this.cachedSkills =
|
|
2202
|
+
this.cachedSkills = Array.from(skillsByName.values());
|
|
2113
2203
|
}
|
|
2114
2204
|
catch (error) {
|
|
2115
2205
|
this.logger.trace({
|
|
@@ -2330,56 +2420,18 @@ class CodexAppServerAgentSession {
|
|
|
2330
2420
|
}
|
|
2331
2421
|
const skill = this.cachedSkills.find((entry) => entry.name === commandName);
|
|
2332
2422
|
if (skill) {
|
|
2423
|
+
const trimmedArgs = args?.trim() ?? "";
|
|
2424
|
+
const text = trimmedArgs ? `$${skill.name} ${trimmedArgs}` : `$${skill.name}`;
|
|
2333
2425
|
const input = [
|
|
2334
2426
|
{ type: "skill", name: skill.name, path: skill.path },
|
|
2427
|
+
{ type: "text", text },
|
|
2335
2428
|
];
|
|
2336
|
-
if (args && args.trim().length > 0) {
|
|
2337
|
-
input.push({ type: "text", text: args.trim() });
|
|
2338
|
-
}
|
|
2339
|
-
else {
|
|
2340
|
-
input.push({ type: "text", text: `$${skill.name}` });
|
|
2341
|
-
}
|
|
2342
2429
|
return input;
|
|
2343
2430
|
}
|
|
2344
2431
|
return args ? `$${commandName} ${args}` : `$${commandName}`;
|
|
2345
2432
|
}
|
|
2346
|
-
async
|
|
2347
|
-
|
|
2348
|
-
prompt,
|
|
2349
|
-
runOptions: options,
|
|
2350
|
-
startTurn: (p, o) => this.startTurn(p, o),
|
|
2351
|
-
subscribe: (callback) => this.subscribe(callback),
|
|
2352
|
-
getSessionId: async () => (await this.getRuntimeInfo()).sessionId ?? "",
|
|
2353
|
-
reduceFinalText: ({ current, item }) => {
|
|
2354
|
-
if (item.type === "assistant_message") {
|
|
2355
|
-
return item.text;
|
|
2356
|
-
}
|
|
2357
|
-
if (item.type === "tool_call" && item.detail.type === "plan") {
|
|
2358
|
-
return item.detail.text;
|
|
2359
|
-
}
|
|
2360
|
-
return current;
|
|
2361
|
-
},
|
|
2362
|
-
});
|
|
2363
|
-
}
|
|
2364
|
-
async startTurn(prompt, options) {
|
|
2365
|
-
if (this.activeForegroundTurnId) {
|
|
2366
|
-
throw new Error("A foreground turn is already active");
|
|
2367
|
-
}
|
|
2368
|
-
await this.connect();
|
|
2369
|
-
if (!this.client) {
|
|
2370
|
-
throw new Error("Codex client not initialized");
|
|
2371
|
-
}
|
|
2372
|
-
const slashCommand = await this.resolveSlashCommandInvocation(prompt);
|
|
2373
|
-
const effectivePrompt = slashCommand
|
|
2374
|
-
? await this.buildCommandPromptInput(slashCommand.commandName, slashCommand.args)
|
|
2375
|
-
: prompt;
|
|
2376
|
-
if (this.currentThreadId) {
|
|
2377
|
-
await this.ensureThreadLoaded();
|
|
2378
|
-
}
|
|
2379
|
-
else {
|
|
2380
|
-
await this.ensureThread();
|
|
2381
|
-
}
|
|
2382
|
-
const input = await this.buildUserInput(effectivePrompt);
|
|
2433
|
+
async buildTurnStartParams(prompt, options) {
|
|
2434
|
+
const input = await this.buildUserInput(prompt);
|
|
2383
2435
|
const preset = MODE_PRESETS[this.currentMode] ?? MODE_PRESETS[DEFAULT_CODEX_MODE_ID];
|
|
2384
2436
|
const approvalPolicy = this.config.approvalPolicy ?? preset.approvalPolicy;
|
|
2385
2437
|
const sandboxPolicyType = this.config.sandboxMode ?? preset.sandbox;
|
|
@@ -2391,6 +2443,7 @@ class CodexAppServerAgentSession {
|
|
|
2391
2443
|
? this.config.networkAccess
|
|
2392
2444
|
: preset.networkAccess),
|
|
2393
2445
|
};
|
|
2446
|
+
applyApprovalsReviewerParam(params, preset);
|
|
2394
2447
|
if (this.config.model) {
|
|
2395
2448
|
params.model = this.config.model;
|
|
2396
2449
|
}
|
|
@@ -2420,10 +2473,81 @@ class CodexAppServerAgentSession {
|
|
|
2420
2473
|
if (codexConfig) {
|
|
2421
2474
|
params.config = codexConfig;
|
|
2422
2475
|
}
|
|
2476
|
+
return {
|
|
2477
|
+
params,
|
|
2478
|
+
thinkingOptionId,
|
|
2479
|
+
approvalPolicy,
|
|
2480
|
+
sandboxPolicyType,
|
|
2481
|
+
hasOutputSchema: Boolean(options?.outputSchema),
|
|
2482
|
+
hasCodexConfig: Boolean(codexConfig),
|
|
2483
|
+
};
|
|
2484
|
+
}
|
|
2485
|
+
logTurnStartSummary({ turnId, thinkingOptionId, approvalPolicy, sandboxPolicyType, hasOutputSchema, hasCodexConfig, }) {
|
|
2486
|
+
this.logger.info({
|
|
2487
|
+
turnId,
|
|
2488
|
+
threadId: this.currentThreadId,
|
|
2489
|
+
model: this.config.model ?? null,
|
|
2490
|
+
modeId: this.currentMode ?? null,
|
|
2491
|
+
effort: thinkingOptionId ?? null,
|
|
2492
|
+
serviceTier: this.serviceTier,
|
|
2493
|
+
cwd: this.config.cwd ?? null,
|
|
2494
|
+
approvalPolicy,
|
|
2495
|
+
sandboxPolicyType,
|
|
2496
|
+
hasCollaborationMode: Boolean(this.resolvedCollaborationMode),
|
|
2497
|
+
hasOutputSchema,
|
|
2498
|
+
hasDeveloperInstructions: Boolean(this.config.systemPrompt?.trim()),
|
|
2499
|
+
hasCodexConfig,
|
|
2500
|
+
}, "Starting Codex app-server turn");
|
|
2501
|
+
}
|
|
2502
|
+
async run(prompt, options) {
|
|
2503
|
+
return runProviderTurn({
|
|
2504
|
+
prompt,
|
|
2505
|
+
runOptions: options,
|
|
2506
|
+
startTurn: (p, o) => this.startTurn(p, o),
|
|
2507
|
+
subscribe: (callback) => this.subscribe(callback),
|
|
2508
|
+
getSessionId: async () => (await this.getRuntimeInfo()).sessionId ?? "",
|
|
2509
|
+
reduceFinalText: ({ current, item }) => {
|
|
2510
|
+
if (item.type === "assistant_message") {
|
|
2511
|
+
return item.text;
|
|
2512
|
+
}
|
|
2513
|
+
if (item.type === "tool_call" && item.detail.type === "plan") {
|
|
2514
|
+
return item.detail.text;
|
|
2515
|
+
}
|
|
2516
|
+
return current;
|
|
2517
|
+
},
|
|
2518
|
+
});
|
|
2519
|
+
}
|
|
2520
|
+
async startTurn(prompt, options) {
|
|
2521
|
+
if (this.activeForegroundTurnId) {
|
|
2522
|
+
throw new Error("A foreground turn is already active");
|
|
2523
|
+
}
|
|
2524
|
+
await this.connect();
|
|
2525
|
+
if (!this.client) {
|
|
2526
|
+
throw new Error("Codex client not initialized");
|
|
2527
|
+
}
|
|
2528
|
+
const slashCommand = await this.resolveSlashCommandInvocation(prompt);
|
|
2529
|
+
const effectivePrompt = slashCommand
|
|
2530
|
+
? await this.buildCommandPromptInput(slashCommand.commandName, slashCommand.args)
|
|
2531
|
+
: prompt;
|
|
2532
|
+
if (this.currentThreadId) {
|
|
2533
|
+
await this.ensureThreadLoaded();
|
|
2534
|
+
}
|
|
2535
|
+
else {
|
|
2536
|
+
await this.ensureThread();
|
|
2537
|
+
}
|
|
2538
|
+
const turnStart = await this.buildTurnStartParams(effectivePrompt, options);
|
|
2423
2539
|
const turnId = this.createTurnId();
|
|
2424
2540
|
this.activeForegroundTurnId = turnId;
|
|
2425
2541
|
try {
|
|
2426
|
-
|
|
2542
|
+
this.logTurnStartSummary({
|
|
2543
|
+
turnId,
|
|
2544
|
+
thinkingOptionId: turnStart.thinkingOptionId,
|
|
2545
|
+
approvalPolicy: turnStart.approvalPolicy,
|
|
2546
|
+
sandboxPolicyType: turnStart.sandboxPolicyType,
|
|
2547
|
+
hasOutputSchema: turnStart.hasOutputSchema,
|
|
2548
|
+
hasCodexConfig: turnStart.hasCodexConfig,
|
|
2549
|
+
});
|
|
2550
|
+
await this.client.request("turn/start", turnStart.params, TURN_START_TIMEOUT_MS);
|
|
2427
2551
|
}
|
|
2428
2552
|
catch (error) {
|
|
2429
2553
|
this.activeForegroundTurnId = null;
|
|
@@ -2444,8 +2568,13 @@ class CodexAppServerAgentSession {
|
|
|
2444
2568
|
const history = this.persistedHistory;
|
|
2445
2569
|
this.persistedHistory = [];
|
|
2446
2570
|
this.historyPending = false;
|
|
2447
|
-
for (const
|
|
2448
|
-
yield {
|
|
2571
|
+
for (const entry of history) {
|
|
2572
|
+
yield {
|
|
2573
|
+
type: "timeline",
|
|
2574
|
+
provider: CODEX_PROVIDER,
|
|
2575
|
+
item: entry.item,
|
|
2576
|
+
timestamp: entry.timestamp,
|
|
2577
|
+
};
|
|
2449
2578
|
}
|
|
2450
2579
|
}
|
|
2451
2580
|
async getRuntimeInfo() {
|
|
@@ -2471,7 +2600,10 @@ class CodexAppServerAgentSession {
|
|
|
2471
2600
|
return { ...info };
|
|
2472
2601
|
}
|
|
2473
2602
|
async getAvailableModes() {
|
|
2474
|
-
|
|
2603
|
+
if (this.autoReviewEnabled) {
|
|
2604
|
+
return CODEX_MODES;
|
|
2605
|
+
}
|
|
2606
|
+
return CODEX_MODES.filter((mode) => mode.id !== "auto-review");
|
|
2475
2607
|
}
|
|
2476
2608
|
async getCurrentMode() {
|
|
2477
2609
|
return this.currentMode ?? null;
|
|
@@ -2496,6 +2628,9 @@ class CodexAppServerAgentSession {
|
|
|
2496
2628
|
}
|
|
2497
2629
|
async setFeature(featureId, value) {
|
|
2498
2630
|
if (featureId === "fast_mode") {
|
|
2631
|
+
if (Boolean(value) && !codexModelSupportsFastMode(this.config.model)) {
|
|
2632
|
+
throw new Error(`Codex fast mode is not available for model '${this.config.model ?? "default"}'`);
|
|
2633
|
+
}
|
|
2499
2634
|
this.applyFeatureValue("fast_mode", Boolean(value));
|
|
2500
2635
|
return;
|
|
2501
2636
|
}
|
|
@@ -2700,7 +2835,13 @@ class CodexAppServerAgentSession {
|
|
|
2700
2835
|
const fallbackSkills = appServerSkills.length === 0
|
|
2701
2836
|
? await listCodexSkills(this.config.cwd, this.deps.workspaceGitService)
|
|
2702
2837
|
: [];
|
|
2703
|
-
const builtin = [
|
|
2838
|
+
const builtin = [
|
|
2839
|
+
{
|
|
2840
|
+
name: "compact",
|
|
2841
|
+
description: "Summarize conversation to prevent hitting the context limit",
|
|
2842
|
+
argumentHint: "",
|
|
2843
|
+
},
|
|
2844
|
+
];
|
|
2704
2845
|
if (this.goalsEnabled) {
|
|
2705
2846
|
builtin.push({
|
|
2706
2847
|
name: "goal",
|
|
@@ -2711,12 +2852,26 @@ class CodexAppServerAgentSession {
|
|
|
2711
2852
|
return [...builtin, ...appServerSkills, ...fallbackSkills, ...prompts].sort((a, b) => a.name.localeCompare(b.name));
|
|
2712
2853
|
}
|
|
2713
2854
|
tryHandleOutOfBand(prompt) {
|
|
2714
|
-
if (!this.goalsEnabled)
|
|
2715
|
-
return null;
|
|
2716
2855
|
if (typeof prompt !== "string")
|
|
2717
2856
|
return null;
|
|
2718
2857
|
const parsed = this.parseSlashCommandInput(prompt);
|
|
2719
|
-
if (!parsed
|
|
2858
|
+
if (!parsed)
|
|
2859
|
+
return null;
|
|
2860
|
+
if (parsed.commandName === "compact") {
|
|
2861
|
+
return {
|
|
2862
|
+
run: async ({ emit }) => {
|
|
2863
|
+
const error = await this.executeCompactCommand();
|
|
2864
|
+
if (error) {
|
|
2865
|
+
emit({
|
|
2866
|
+
type: "timeline",
|
|
2867
|
+
provider: CODEX_PROVIDER,
|
|
2868
|
+
item: { type: "assistant_message", text: formatOutOfBandStatusMessage(error) },
|
|
2869
|
+
});
|
|
2870
|
+
}
|
|
2871
|
+
},
|
|
2872
|
+
};
|
|
2873
|
+
}
|
|
2874
|
+
if (!this.goalsEnabled || parsed.commandName !== "goal")
|
|
2720
2875
|
return null;
|
|
2721
2876
|
const subcommand = parseGoalSubcommand(parsed.args);
|
|
2722
2877
|
return {
|
|
@@ -2730,6 +2885,35 @@ class CodexAppServerAgentSession {
|
|
|
2730
2885
|
},
|
|
2731
2886
|
};
|
|
2732
2887
|
}
|
|
2888
|
+
async executeCompactCommand() {
|
|
2889
|
+
try {
|
|
2890
|
+
await this.connect();
|
|
2891
|
+
if (this.currentThreadId) {
|
|
2892
|
+
await this.ensureThreadLoaded();
|
|
2893
|
+
}
|
|
2894
|
+
else {
|
|
2895
|
+
await this.ensureThread();
|
|
2896
|
+
}
|
|
2897
|
+
if (!this.client || !this.currentThreadId) {
|
|
2898
|
+
throw new Error("Codex thread is not available");
|
|
2899
|
+
}
|
|
2900
|
+
this.pendingManualCompactionStarts += 1;
|
|
2901
|
+
try {
|
|
2902
|
+
await this.client.request("thread/compact/start", {
|
|
2903
|
+
threadId: this.currentThreadId,
|
|
2904
|
+
});
|
|
2905
|
+
}
|
|
2906
|
+
catch (error) {
|
|
2907
|
+
this.pendingManualCompactionStarts = Math.max(0, this.pendingManualCompactionStarts - 1);
|
|
2908
|
+
throw error;
|
|
2909
|
+
}
|
|
2910
|
+
return null;
|
|
2911
|
+
}
|
|
2912
|
+
catch (error) {
|
|
2913
|
+
const message = error instanceof Error ? error.message : "unknown error";
|
|
2914
|
+
return `Failed to compact context: ${message}`;
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2733
2917
|
async executeGoalSubcommand(subcommand) {
|
|
2734
2918
|
if (subcommand.kind === "usage") {
|
|
2735
2919
|
return "Usage: /goal <objective>|pause|resume|clear";
|
|
@@ -2841,7 +3025,7 @@ class CodexAppServerAgentSession {
|
|
|
2841
3025
|
const approvalPolicy = this.config.approvalPolicy ?? preset.approvalPolicy;
|
|
2842
3026
|
const sandbox = this.config.sandboxMode ?? preset.sandbox;
|
|
2843
3027
|
const innerConfig = this.buildCodexInnerConfig();
|
|
2844
|
-
const
|
|
3028
|
+
const params = {
|
|
2845
3029
|
model,
|
|
2846
3030
|
cwd: this.config.cwd ?? null,
|
|
2847
3031
|
approvalPolicy,
|
|
@@ -2851,13 +3035,24 @@ class CodexAppServerAgentSession {
|
|
|
2851
3035
|
: {}),
|
|
2852
3036
|
...(innerConfig ? { config: innerConfig } : {}),
|
|
2853
3037
|
...(this.ephemeral ? { ephemeral: true } : {}),
|
|
2854
|
-
}
|
|
3038
|
+
};
|
|
3039
|
+
applyApprovalsReviewerParam(params, preset);
|
|
3040
|
+
const rawResponse = await this.client.request("thread/start", params);
|
|
2855
3041
|
const response = toObjectRecord(rawResponse);
|
|
2856
3042
|
const threadRecord = toObjectRecord(response?.thread);
|
|
2857
3043
|
const threadId = typeof threadRecord?.id === "string" ? threadRecord.id : undefined;
|
|
2858
3044
|
if (!threadId) {
|
|
2859
3045
|
throw new Error("Codex app-server did not return thread id");
|
|
2860
3046
|
}
|
|
3047
|
+
const responseApprovalsReviewer = typeof response?.approvalsReviewer === "string" ? response.approvalsReviewer : undefined;
|
|
3048
|
+
if (shouldPromoteThreadResponseToAutoReview({
|
|
3049
|
+
approvalsReviewer: responseApprovalsReviewer,
|
|
3050
|
+
approvalPolicy,
|
|
3051
|
+
sandbox,
|
|
3052
|
+
})) {
|
|
3053
|
+
this.currentMode = "auto-review";
|
|
3054
|
+
this.cachedRuntimeInfo = null;
|
|
3055
|
+
}
|
|
2861
3056
|
this.currentThreadId = threadId;
|
|
2862
3057
|
}
|
|
2863
3058
|
buildCodexInnerConfig() {
|
|
@@ -2932,6 +3127,9 @@ class CodexAppServerAgentSession {
|
|
|
2932
3127
|
case "token_usage_updated":
|
|
2933
3128
|
this.handleTokenUsageUpdatedNotification(parsed);
|
|
2934
3129
|
return;
|
|
3130
|
+
case "context_compacted":
|
|
3131
|
+
this.handleContextCompactedNotification(parsed);
|
|
3132
|
+
return;
|
|
2935
3133
|
case "agent_message_delta":
|
|
2936
3134
|
case "reasoning_delta":
|
|
2937
3135
|
case "exec_command_output_delta":
|
|
@@ -3085,6 +3283,7 @@ class CodexAppServerAgentSession {
|
|
|
3085
3283
|
if (subAgentCallId) {
|
|
3086
3284
|
this.upsertSubAgentChildItem(subAgentCallId, parsed.itemId, {
|
|
3087
3285
|
type: "assistant_message",
|
|
3286
|
+
messageId: parsed.itemId,
|
|
3088
3287
|
text,
|
|
3089
3288
|
});
|
|
3090
3289
|
this.emitSubAgentActivityUpdate(subAgentCallId, "running");
|
|
@@ -3096,6 +3295,7 @@ class CodexAppServerAgentSession {
|
|
|
3096
3295
|
provider: CODEX_PROVIDER,
|
|
3097
3296
|
item: {
|
|
3098
3297
|
type: "assistant_message",
|
|
3298
|
+
messageId: parsed.itemId,
|
|
3099
3299
|
text: isFirstDeltaForItem && this.pendingAssistantMessageBoundary
|
|
3100
3300
|
? `${ASSISTANT_MESSAGE_BOUNDARY_MARKDOWN}${parsed.delta}`
|
|
3101
3301
|
: parsed.delta,
|
|
@@ -3200,6 +3400,8 @@ class CodexAppServerAgentSession {
|
|
|
3200
3400
|
this.pendingFileChangeOutputDeltas.clear();
|
|
3201
3401
|
this.pendingAssistantMessageBoundary = false;
|
|
3202
3402
|
this.warnedIncompleteEditToolCallIds.clear();
|
|
3403
|
+
this.unpairedCompactionNotificationCompletions = 0;
|
|
3404
|
+
this.unpairedCompactionItemCompletions = 0;
|
|
3203
3405
|
}
|
|
3204
3406
|
handlePlanUpdatedNotification(parsed) {
|
|
3205
3407
|
const timelineItem = mapCodexPlanToToolCall({
|
|
@@ -3230,6 +3432,55 @@ class CodexAppServerAgentSession {
|
|
|
3230
3432
|
});
|
|
3231
3433
|
}
|
|
3232
3434
|
}
|
|
3435
|
+
resolveContextCompactionTrigger(itemId) {
|
|
3436
|
+
if (itemId) {
|
|
3437
|
+
const known = this.compactionTriggerByItemId.get(itemId);
|
|
3438
|
+
if (known) {
|
|
3439
|
+
return known;
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
if (this.pendingManualCompactionStarts > 0) {
|
|
3443
|
+
this.pendingManualCompactionStarts -= 1;
|
|
3444
|
+
return "manual";
|
|
3445
|
+
}
|
|
3446
|
+
return undefined;
|
|
3447
|
+
}
|
|
3448
|
+
createContextCompactionTimelineItem(status, itemId) {
|
|
3449
|
+
const trigger = this.resolveContextCompactionTrigger(itemId);
|
|
3450
|
+
if (itemId && trigger) {
|
|
3451
|
+
if (status === "loading") {
|
|
3452
|
+
this.compactionTriggerByItemId.set(itemId, trigger);
|
|
3453
|
+
}
|
|
3454
|
+
else {
|
|
3455
|
+
this.compactionTriggerByItemId.delete(itemId);
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
return {
|
|
3459
|
+
type: "compaction",
|
|
3460
|
+
status,
|
|
3461
|
+
...(trigger ? { trigger } : {}),
|
|
3462
|
+
};
|
|
3463
|
+
}
|
|
3464
|
+
isContextCompactionItem(item) {
|
|
3465
|
+
return (normalizeCodexThreadItemType(typeof item.type === "string" ? item.type : undefined) ===
|
|
3466
|
+
CODEX_CONTEXT_COMPACTION_TYPE);
|
|
3467
|
+
}
|
|
3468
|
+
handleContextCompactedNotification(parsed) {
|
|
3469
|
+
if (parsed.threadId !== this.currentThreadId) {
|
|
3470
|
+
return;
|
|
3471
|
+
}
|
|
3472
|
+
if (this.unpairedCompactionItemCompletions > 0) {
|
|
3473
|
+
this.unpairedCompactionItemCompletions -= 1;
|
|
3474
|
+
return;
|
|
3475
|
+
}
|
|
3476
|
+
this.unpairedCompactionNotificationCompletions += 1;
|
|
3477
|
+
this.emitEvent({
|
|
3478
|
+
type: "timeline",
|
|
3479
|
+
provider: CODEX_PROVIDER,
|
|
3480
|
+
item: this.createContextCompactionTimelineItem("completed"),
|
|
3481
|
+
...(parsed.turnId ? { turnId: parsed.turnId } : {}),
|
|
3482
|
+
});
|
|
3483
|
+
}
|
|
3233
3484
|
handleExecCommandStartedNotification(parsed) {
|
|
3234
3485
|
if (parsed.callId) {
|
|
3235
3486
|
this.emittedExecCommandStartedCallIds.add(parsed.callId);
|
|
@@ -3326,6 +3577,19 @@ class CodexAppServerAgentSession {
|
|
|
3326
3577
|
if (parsed.source === "codex_event") {
|
|
3327
3578
|
return;
|
|
3328
3579
|
}
|
|
3580
|
+
if (this.isContextCompactionItem(parsed.item)) {
|
|
3581
|
+
if (this.unpairedCompactionNotificationCompletions > 0) {
|
|
3582
|
+
this.unpairedCompactionNotificationCompletions -= 1;
|
|
3583
|
+
return;
|
|
3584
|
+
}
|
|
3585
|
+
this.emitEvent({
|
|
3586
|
+
type: "timeline",
|
|
3587
|
+
provider: CODEX_PROVIDER,
|
|
3588
|
+
item: this.createContextCompactionTimelineItem("completed", parsed.item.id),
|
|
3589
|
+
});
|
|
3590
|
+
this.unpairedCompactionItemCompletions += 1;
|
|
3591
|
+
return;
|
|
3592
|
+
}
|
|
3329
3593
|
const timelineItem = threadItemToTimeline(parsed.item, {
|
|
3330
3594
|
includeUserMessage: false,
|
|
3331
3595
|
cwd: this.config.cwd ?? null,
|
|
@@ -3407,7 +3671,13 @@ class CodexAppServerAgentSession {
|
|
|
3407
3671
|
this.emitEvent({
|
|
3408
3672
|
type: "timeline",
|
|
3409
3673
|
provider: CODEX_PROVIDER,
|
|
3410
|
-
item:
|
|
3674
|
+
item: timelineItem.type === "assistant_message"
|
|
3675
|
+
? {
|
|
3676
|
+
type: timelineItem.type,
|
|
3677
|
+
text: suffix,
|
|
3678
|
+
...(timelineItem.messageId ? { messageId: timelineItem.messageId } : {}),
|
|
3679
|
+
}
|
|
3680
|
+
: { type: timelineItem.type, text: suffix },
|
|
3411
3681
|
});
|
|
3412
3682
|
}
|
|
3413
3683
|
applyBufferedDeltaTextToTimelineItem(timelineItem, itemId) {
|
|
@@ -3432,6 +3702,14 @@ class CodexAppServerAgentSession {
|
|
|
3432
3702
|
if (parsed.source === "codex_event") {
|
|
3433
3703
|
return;
|
|
3434
3704
|
}
|
|
3705
|
+
if (this.isContextCompactionItem(parsed.item)) {
|
|
3706
|
+
this.emitEvent({
|
|
3707
|
+
type: "timeline",
|
|
3708
|
+
provider: CODEX_PROVIDER,
|
|
3709
|
+
item: this.createContextCompactionTimelineItem("loading", parsed.item.id),
|
|
3710
|
+
});
|
|
3711
|
+
return;
|
|
3712
|
+
}
|
|
3435
3713
|
const timelineItem = threadItemToTimeline(parsed.item, {
|
|
3436
3714
|
includeUserMessage: false,
|
|
3437
3715
|
cwd: this.config.cwd ?? null,
|
|
@@ -3711,6 +3989,7 @@ export class CodexAppServerAgentClient {
|
|
|
3711
3989
|
this.provider = CODEX_PROVIDER;
|
|
3712
3990
|
this.capabilities = CODEX_APP_SERVER_CAPABILITIES;
|
|
3713
3991
|
this.goalsEnabledPromise = null;
|
|
3992
|
+
this.autoReviewEnabledPromise = null;
|
|
3714
3993
|
}
|
|
3715
3994
|
sessionDeps() {
|
|
3716
3995
|
return {
|
|
@@ -3740,6 +4019,28 @@ export class CodexAppServerAgentClient {
|
|
|
3740
4019
|
}
|
|
3741
4020
|
return this.goalsEnabledPromise;
|
|
3742
4021
|
}
|
|
4022
|
+
resolveAutoReviewEnabled() {
|
|
4023
|
+
if (!this.autoReviewEnabledPromise) {
|
|
4024
|
+
this.autoReviewEnabledPromise = (async () => {
|
|
4025
|
+
try {
|
|
4026
|
+
const launchPrefix = await resolveCodexLaunchPrefix(this.runtimeSettings);
|
|
4027
|
+
const versionOutput = await resolveBinaryVersion(launchPrefix.command);
|
|
4028
|
+
const enabled = codexVersionAtLeast(versionOutput, CODEX_AUTO_REVIEW_MIN_VERSION);
|
|
4029
|
+
this.logger.trace({
|
|
4030
|
+
provider: CODEX_PROVIDER,
|
|
4031
|
+
versionOutput,
|
|
4032
|
+
enabled,
|
|
4033
|
+
}, "provider.codex.config.auto_review_resolved");
|
|
4034
|
+
return enabled;
|
|
4035
|
+
}
|
|
4036
|
+
catch (error) {
|
|
4037
|
+
this.logger.warn({ err: error }, "Failed to probe codex version for auto-review gate");
|
|
4038
|
+
return false;
|
|
4039
|
+
}
|
|
4040
|
+
})();
|
|
4041
|
+
}
|
|
4042
|
+
return this.autoReviewEnabledPromise;
|
|
4043
|
+
}
|
|
3743
4044
|
async spawnAppServer(launchEnv, options) {
|
|
3744
4045
|
const launchPrefix = await resolveCodexLaunchPrefix(this.runtimeSettings);
|
|
3745
4046
|
const args = [...launchPrefix.args, "app-server"];
|
|
@@ -3771,7 +4072,8 @@ export class CodexAppServerAgentClient {
|
|
|
3771
4072
|
}
|
|
3772
4073
|
const sessionConfig = { ...config, provider: CODEX_PROVIDER };
|
|
3773
4074
|
const goalsEnabled = await this.resolveGoalsEnabled();
|
|
3774
|
-
const
|
|
4075
|
+
const autoReviewEnabled = await this.resolveAutoReviewEnabled();
|
|
4076
|
+
const session = new CodexAppServerAgentSession(sessionConfig, null, this.logger, () => this.spawnAppServer(launchContext?.env, { goalsEnabled, agentId: launchContext?.agentId }), this.sessionDeps(), options?.persistSession === false, goalsEnabled, autoReviewEnabled, launchContext?.agentId);
|
|
3775
4077
|
await session.connect();
|
|
3776
4078
|
return session;
|
|
3777
4079
|
}
|
|
@@ -3784,7 +4086,8 @@ export class CodexAppServerAgentClient {
|
|
|
3784
4086
|
cwd: overrides?.cwd ?? storedConfig.cwd ?? process.cwd(),
|
|
3785
4087
|
};
|
|
3786
4088
|
const goalsEnabled = await this.resolveGoalsEnabled();
|
|
3787
|
-
const
|
|
4089
|
+
const autoReviewEnabled = await this.resolveAutoReviewEnabled();
|
|
4090
|
+
const session = new CodexAppServerAgentSession(merged, handle, this.logger, () => this.spawnAppServer(launchContext?.env, { goalsEnabled, agentId: launchContext?.agentId }), this.sessionDeps(), false, goalsEnabled, autoReviewEnabled, launchContext?.agentId);
|
|
3788
4091
|
await session.connect();
|
|
3789
4092
|
return session;
|
|
3790
4093
|
}
|
|
@@ -3840,7 +4143,7 @@ export class CodexAppServerAgentClient {
|
|
|
3840
4143
|
threadId,
|
|
3841
4144
|
},
|
|
3842
4145
|
},
|
|
3843
|
-
timeline,
|
|
4146
|
+
timeline: timeline.map((entry) => entry.item),
|
|
3844
4147
|
};
|
|
3845
4148
|
}));
|
|
3846
4149
|
return descriptors;
|