@getpaseo/server 0.1.75 → 0.1.76

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