@jentrix/runner 0.5.19 → 0.5.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/chunk-UN63BYMS.js +7 -0
- package/dist/{chunk-HJ2AADN6.js.map → chunk-UN63BYMS.js.map} +1 -1
- package/dist/runner-cli.js +2 -2
- package/dist/{session-host-NJF6CRET.js → session-host-L6XF4T2P.js} +255 -24
- package/dist/session-host-L6XF4T2P.js.map +7 -0
- package/dist/workflow-runner.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-HJ2AADN6.js +0 -7
- package/dist/session-host-NJF6CRET.js.map +0 -7
package/README.md
CHANGED
|
@@ -132,10 +132,10 @@ Setup:
|
|
|
132
132
|
|
|
133
133
|
| Context loaded up front | Bytes | ≈ Tokens |
|
|
134
134
|
| --- | --- | --- |
|
|
135
|
-
| MCP agent — all 242 tool definitions |
|
|
135
|
+
| MCP agent — all 242 tool definitions | 375 KB | ~101k |
|
|
136
136
|
| CLI agent — `CLI_STANDUP_SYSTEM_PROMPT` only | 2 KB | ~510 |
|
|
137
137
|
|
|
138
|
-
That is a **~
|
|
138
|
+
That is a **~199× smaller** Jentrix-specific up-front context.
|
|
139
139
|
<!-- END GENERATED: mcp-tool-count:agent-token-cost -->
|
|
140
140
|
|
|
141
141
|
Reproduce the two numbers directly:
|
package/dist/runner-cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
RUNNER_VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UN63BYMS.js";
|
|
5
5
|
|
|
6
6
|
// runner-cli.ts
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
@@ -219,7 +219,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
219
219
|
return runConfiguredRunner(args.includes("--once"));
|
|
220
220
|
}
|
|
221
221
|
if (command === "session-run" && (args.includes("--plan-stdin") || args.includes("--plan-file"))) {
|
|
222
|
-
const { runSessionHost } = await import("./session-host-
|
|
222
|
+
const { runSessionHost } = await import("./session-host-L6XF4T2P.js");
|
|
223
223
|
let raw;
|
|
224
224
|
const planFile = valueAfter(args, "--plan-file");
|
|
225
225
|
if (planFile) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
RUNNER_VERSION
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UN63BYMS.js";
|
|
4
4
|
import {
|
|
5
5
|
appendHookEvent,
|
|
6
6
|
readHookLines,
|
|
@@ -180,6 +180,126 @@ function serializeSessionEvent(event) {
|
|
|
180
180
|
`;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
// lib/session-skeleton.ts
|
|
184
|
+
var SKELETON_VERSION = 1;
|
|
185
|
+
var MAX_SKELETON_BYTES = 32 * 1024;
|
|
186
|
+
var MAX_DISTINCT_TOOLS = 100;
|
|
187
|
+
var MAX_TRACKED_FILES = 300;
|
|
188
|
+
var MAX_HOURLY_BUCKETS = 500;
|
|
189
|
+
var MAX_PATH_CHARS = 300;
|
|
190
|
+
var PATH_KEYS = ["file_path", "path", "notebook_path", "filePath"];
|
|
191
|
+
function pathOf(value) {
|
|
192
|
+
if (typeof value !== "string") return null;
|
|
193
|
+
const trimmed = value.trim();
|
|
194
|
+
if (!trimmed || /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)) return null;
|
|
195
|
+
return trimmed.slice(0, MAX_PATH_CHARS);
|
|
196
|
+
}
|
|
197
|
+
var SessionSkeleton = class {
|
|
198
|
+
constructor(provider) {
|
|
199
|
+
this.provider = provider;
|
|
200
|
+
}
|
|
201
|
+
provider;
|
|
202
|
+
turns = 0;
|
|
203
|
+
firstEventAt = null;
|
|
204
|
+
lastEventAt = null;
|
|
205
|
+
eventCounts = /* @__PURE__ */ new Map();
|
|
206
|
+
toolCounts = /* @__PURE__ */ new Map();
|
|
207
|
+
files = /* @__PURE__ */ new Set();
|
|
208
|
+
filesOverflow = 0;
|
|
209
|
+
hourly = /* @__PURE__ */ new Map();
|
|
210
|
+
coalesced = false;
|
|
211
|
+
get observedAnything() {
|
|
212
|
+
return this.firstEventAt !== null;
|
|
213
|
+
}
|
|
214
|
+
/** Feed one REDACTED observed event. Pure accumulation, never throws. */
|
|
215
|
+
observe(event) {
|
|
216
|
+
this.eventCounts.set(
|
|
217
|
+
event.kind,
|
|
218
|
+
(this.eventCounts.get(event.kind) ?? 0) + 1
|
|
219
|
+
);
|
|
220
|
+
if (event.kind === "user_message") this.turns += 1;
|
|
221
|
+
if (this.firstEventAt === null) this.firstEventAt = event.at;
|
|
222
|
+
this.lastEventAt = event.at;
|
|
223
|
+
const hour = event.at.slice(0, 13);
|
|
224
|
+
if (this.hourly.has(hour) || this.hourly.size < MAX_HOURLY_BUCKETS) {
|
|
225
|
+
this.hourly.set(hour, (this.hourly.get(hour) ?? 0) + 1);
|
|
226
|
+
} else {
|
|
227
|
+
this.coalesced = true;
|
|
228
|
+
}
|
|
229
|
+
const payload = event.payload ?? {};
|
|
230
|
+
if (event.kind === "tool_call") {
|
|
231
|
+
const name = typeof payload.name === "string" && payload.name.trim() ? payload.name.trim().slice(0, 120) : "(unnamed)";
|
|
232
|
+
if (this.toolCounts.has(name) || this.toolCounts.size < MAX_DISTINCT_TOOLS) {
|
|
233
|
+
this.toolCounts.set(name, (this.toolCounts.get(name) ?? 0) + 1);
|
|
234
|
+
} else {
|
|
235
|
+
this.coalesced = true;
|
|
236
|
+
this.toolCounts.set(
|
|
237
|
+
"(other)",
|
|
238
|
+
(this.toolCounts.get("(other)") ?? 0) + 1
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
const input = payload.input;
|
|
242
|
+
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
243
|
+
for (const key of PATH_KEYS) {
|
|
244
|
+
const path = pathOf(input[key]);
|
|
245
|
+
if (path) this.touch(path);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (event.kind === "file_change") {
|
|
250
|
+
const changes = payload.changes;
|
|
251
|
+
if (Array.isArray(changes)) {
|
|
252
|
+
for (const change of changes) {
|
|
253
|
+
const path = pathOf(change?.path);
|
|
254
|
+
if (path) this.touch(path);
|
|
255
|
+
}
|
|
256
|
+
} else if (changes && typeof changes === "object") {
|
|
257
|
+
for (const key of Object.keys(changes)) {
|
|
258
|
+
const path = pathOf(key);
|
|
259
|
+
if (path) this.touch(path);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
touch(path) {
|
|
265
|
+
if (this.files.has(path)) return;
|
|
266
|
+
if (this.files.size >= MAX_TRACKED_FILES) {
|
|
267
|
+
this.filesOverflow += 1;
|
|
268
|
+
this.coalesced = true;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
this.files.add(path);
|
|
272
|
+
}
|
|
273
|
+
/** The bounded v1 JSON. ≤ 32 KB serialized — file-list tail drops first. */
|
|
274
|
+
snapshot() {
|
|
275
|
+
const build = (paths2, listTruncated2) => ({
|
|
276
|
+
version: SKELETON_VERSION,
|
|
277
|
+
provider: this.provider,
|
|
278
|
+
turns: this.turns,
|
|
279
|
+
firstEventAt: this.firstEventAt,
|
|
280
|
+
lastEventAt: this.lastEventAt,
|
|
281
|
+
eventCounts: Object.fromEntries(this.eventCounts),
|
|
282
|
+
toolCounts: Object.fromEntries(this.toolCounts),
|
|
283
|
+
filesTouched: {
|
|
284
|
+
total: this.files.size + this.filesOverflow,
|
|
285
|
+
paths: paths2,
|
|
286
|
+
...listTruncated2 ? { listTruncated: true } : {}
|
|
287
|
+
},
|
|
288
|
+
hourlyBuckets: Object.fromEntries(this.hourly),
|
|
289
|
+
...this.coalesced || listTruncated2 ? { truncated: true } : {}
|
|
290
|
+
});
|
|
291
|
+
let paths = [...this.files];
|
|
292
|
+
let listTruncated = this.filesOverflow > 0;
|
|
293
|
+
let skeleton = build(paths, listTruncated);
|
|
294
|
+
while (Buffer.byteLength(JSON.stringify(skeleton), "utf8") > MAX_SKELETON_BYTES && paths.length > 0) {
|
|
295
|
+
paths = paths.slice(0, Math.max(0, Math.floor(paths.length / 2)));
|
|
296
|
+
listTruncated = true;
|
|
297
|
+
skeleton = build(paths, listTruncated);
|
|
298
|
+
}
|
|
299
|
+
return skeleton;
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
183
303
|
// lib/session-usage.ts
|
|
184
304
|
function insideOneRange(ranges, from, to) {
|
|
185
305
|
return ranges.some((r) => r.from <= from && to <= r.to);
|
|
@@ -362,6 +482,7 @@ var HEARTBEAT_MIN_INTERVAL_MS = 3e4;
|
|
|
362
482
|
var SessionBridge = class {
|
|
363
483
|
constructor(deps) {
|
|
364
484
|
this.deps = deps;
|
|
485
|
+
this.skeleton = deps.collectSkeleton === false ? null : new SessionSkeleton(deps.provider);
|
|
365
486
|
}
|
|
366
487
|
deps;
|
|
367
488
|
sequence = 0;
|
|
@@ -393,6 +514,13 @@ var SessionBridge = class {
|
|
|
393
514
|
* session keeps its telemetry and loses what it actually concluded).
|
|
394
515
|
*/
|
|
395
516
|
lastAssistantMessage = null;
|
|
517
|
+
/**
|
|
518
|
+
* Session evidence floor (PRD §4): the v1 activity skeleton, accumulated
|
|
519
|
+
* from every REDACTED event this bridge records — capture-off included —
|
|
520
|
+
* and submitted on the existing heartbeats plus the forced beat at close.
|
|
521
|
+
* Null when the operator opted out at align (D3).
|
|
522
|
+
*/
|
|
523
|
+
skeleton;
|
|
396
524
|
/**
|
|
397
525
|
* True after a heartbeat came back 409 SESSION_NOT_ACTIVE — the session is
|
|
398
526
|
* terminal server-side. The watch host uses this as its end signal when no
|
|
@@ -463,6 +591,7 @@ var SessionBridge = class {
|
|
|
463
591
|
this.deps.redactor.text(serializeSessionEvent(full))
|
|
464
592
|
);
|
|
465
593
|
}
|
|
594
|
+
this.skeleton?.observe(full);
|
|
466
595
|
if (full.kind === "assistant_message") {
|
|
467
596
|
const text2 = full.payload?.text;
|
|
468
597
|
if (typeof text2 === "string" && text2.trim().length > 0) {
|
|
@@ -601,7 +730,12 @@ var SessionBridge = class {
|
|
|
601
730
|
// Sent only once a receipt has actually been observed — an empty
|
|
602
731
|
// rollup would overwrite the session's totals with nulls and
|
|
603
732
|
// report UNAVAILABLE for a session that had already reported.
|
|
604
|
-
...this.receipts.length > 0 ? { usage: this.usageRollup() } : {}
|
|
733
|
+
...this.receipts.length > 0 ? { usage: this.usageRollup() } : {},
|
|
734
|
+
// Evidence floor (PRD §4/D2): the bounded activity skeleton rides
|
|
735
|
+
// the same beat (tolerant server parse — an old server strips the
|
|
736
|
+
// unknown key). Sent only once something was observed: null column
|
|
737
|
+
// means "never observed", never an empty object.
|
|
738
|
+
...this.skeleton?.observedAnything ? { activitySkeleton: this.skeleton.snapshot() } : {}
|
|
605
739
|
})
|
|
606
740
|
}
|
|
607
741
|
);
|
|
@@ -801,6 +935,7 @@ var SessionBridge = class {
|
|
|
801
935
|
*/
|
|
802
936
|
async complete(opts) {
|
|
803
937
|
const { pending } = await this.flushParts();
|
|
938
|
+
await this.flushUsageNow().catch(() => false);
|
|
804
939
|
const finalResponseArtifactId = await this.pushFinalResponse();
|
|
805
940
|
const rollup = this.usageRollup();
|
|
806
941
|
const current = await this.deps.callTool("get_agent_session", {
|
|
@@ -1152,39 +1287,90 @@ function mapCodexThreadEvent(raw) {
|
|
|
1152
1287
|
return { event: null, unrecognized: true };
|
|
1153
1288
|
}
|
|
1154
1289
|
}
|
|
1290
|
+
var CODEX_INJECTED_USER_CONTEXT = [
|
|
1291
|
+
"<recommended_plugins>",
|
|
1292
|
+
"# AGENTS.md instructions",
|
|
1293
|
+
"<environment_context>"
|
|
1294
|
+
];
|
|
1295
|
+
function codexOpeningPromptOf(rollout) {
|
|
1296
|
+
for (const rawLine of rollout.split("\n")) {
|
|
1297
|
+
try {
|
|
1298
|
+
const line = JSON.parse(rawLine);
|
|
1299
|
+
if (line.type !== "response_item" || line.payload?.type !== "message" || line.payload.role !== "user") {
|
|
1300
|
+
continue;
|
|
1301
|
+
}
|
|
1302
|
+
const text2 = (line.payload.content ?? []).filter((block) => block.type === "input_text").map((block) => block.text?.trim() ?? "").filter(
|
|
1303
|
+
(block) => block && !CODEX_INJECTED_USER_CONTEXT.some(
|
|
1304
|
+
(prefix) => block.startsWith(prefix)
|
|
1305
|
+
)
|
|
1306
|
+
);
|
|
1307
|
+
if (text2.length > 0) return text2.join("\n\n");
|
|
1308
|
+
} catch {
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
return null;
|
|
1312
|
+
}
|
|
1155
1313
|
function reportedToken(value) {
|
|
1156
1314
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
1157
1315
|
}
|
|
1158
|
-
function
|
|
1316
|
+
function mapCodexRolloutLine(rawLine) {
|
|
1159
1317
|
try {
|
|
1160
1318
|
const line = JSON.parse(rawLine);
|
|
1319
|
+
const modelId = line.payload?.model?.trim() || null;
|
|
1320
|
+
const turnId = line.payload?.turn_id?.trim() || null;
|
|
1321
|
+
const at = Date.parse(line.timestamp ?? "");
|
|
1322
|
+
if (line.type === "turn_context") {
|
|
1323
|
+
return { event: null, modelId, turn: null };
|
|
1324
|
+
}
|
|
1325
|
+
if (line.type === "event_msg" && turnId && Number.isFinite(at) && (line.payload?.type === "task_started" || line.payload?.type === "task_complete")) {
|
|
1326
|
+
return {
|
|
1327
|
+
event: null,
|
|
1328
|
+
modelId: null,
|
|
1329
|
+
turn: {
|
|
1330
|
+
id: turnId,
|
|
1331
|
+
phase: line.payload.type === "task_started" ? "started" : "completed",
|
|
1332
|
+
at
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1161
1336
|
const usage = line.payload?.info?.last_token_usage;
|
|
1162
1337
|
const inputTokens = reportedToken(usage?.input_tokens);
|
|
1163
1338
|
const outputTokens = reportedToken(usage?.output_tokens);
|
|
1164
1339
|
if (line.type !== "event_msg" || line.payload?.type !== "token_count" || inputTokens === null || outputTokens === null) {
|
|
1165
|
-
return null;
|
|
1340
|
+
return { event: null, modelId: null, turn: null };
|
|
1166
1341
|
}
|
|
1167
1342
|
const cacheReadTokens = reportedToken(usage?.cached_input_tokens);
|
|
1168
1343
|
const cacheCreationTokens = reportedToken(usage?.cache_write_input_tokens);
|
|
1169
1344
|
const reasoningOutputTokens = reportedToken(usage?.reasoning_output_tokens);
|
|
1170
1345
|
return {
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1346
|
+
event: {
|
|
1347
|
+
...make(
|
|
1348
|
+
"usage",
|
|
1349
|
+
{
|
|
1350
|
+
kind: "delta",
|
|
1351
|
+
inputTokens,
|
|
1352
|
+
outputTokens,
|
|
1353
|
+
...cacheReadTokens !== null ? { cacheReadTokens } : {},
|
|
1354
|
+
...cacheCreationTokens !== null ? { cacheCreationTokens } : {},
|
|
1355
|
+
...reasoningOutputTokens !== null ? { reasoningOutputTokens } : {}
|
|
1356
|
+
},
|
|
1357
|
+
typeof line.ordinal === "number" ? `rollout:${line.ordinal}` : line.timestamp
|
|
1358
|
+
),
|
|
1359
|
+
...line.timestamp ? { at: line.timestamp } : {}
|
|
1360
|
+
},
|
|
1361
|
+
modelId: null,
|
|
1362
|
+
turn: null
|
|
1184
1363
|
};
|
|
1185
1364
|
} catch {
|
|
1186
|
-
return null;
|
|
1365
|
+
return { event: null, modelId: null, turn: null };
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
function lastCodexRolloutModelOf(rollout) {
|
|
1369
|
+
let modelId = null;
|
|
1370
|
+
for (const rawLine of rollout.split("\n")) {
|
|
1371
|
+
modelId = mapCodexRolloutLine(rawLine).modelId ?? modelId;
|
|
1187
1372
|
}
|
|
1373
|
+
return modelId;
|
|
1188
1374
|
}
|
|
1189
1375
|
|
|
1190
1376
|
// lib/session-codex-hooks.ts
|
|
@@ -1620,6 +1806,7 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1620
1806
|
callTool: deps.callTool ?? sessionCallTool(plan.mcpUrl, bearerSource, plan.sessionId),
|
|
1621
1807
|
fetchImpl: deps.fetchImpl,
|
|
1622
1808
|
traceCapture,
|
|
1809
|
+
collectSkeleton: plan.collectSkeleton !== false,
|
|
1623
1810
|
log
|
|
1624
1811
|
});
|
|
1625
1812
|
bridge.recordCapabilities(
|
|
@@ -1680,6 +1867,9 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1680
1867
|
}
|
|
1681
1868
|
let transcriptPath = watch ? plan.transcriptPath ?? null : null;
|
|
1682
1869
|
let transcriptOffset = 0;
|
|
1870
|
+
let codexTurnId = null;
|
|
1871
|
+
let codexModelId = null;
|
|
1872
|
+
const codexRolloutTurnStarts = /* @__PURE__ */ new Map();
|
|
1683
1873
|
const timing = new ClaudeTimingTracker();
|
|
1684
1874
|
let transcriptSeen = false;
|
|
1685
1875
|
let transcriptWarned = false;
|
|
@@ -1690,16 +1880,26 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1690
1880
|
markHostTranscript(sessionDir, true, transcriptPath ?? void 0);
|
|
1691
1881
|
}
|
|
1692
1882
|
};
|
|
1883
|
+
const observePriorCodexModel = (path) => {
|
|
1884
|
+
if (plan.provider !== "codex" || plan.importHistory) return;
|
|
1885
|
+
try {
|
|
1886
|
+
const modelId = lastCodexRolloutModelOf(readFileSync3(path, "utf8"));
|
|
1887
|
+
if (modelId) {
|
|
1888
|
+
codexModelId = modelId;
|
|
1889
|
+
bridge.observeModel(modelId);
|
|
1890
|
+
}
|
|
1891
|
+
} catch {
|
|
1892
|
+
}
|
|
1893
|
+
};
|
|
1693
1894
|
if (watch && transcriptPath && !plan.importHistory) {
|
|
1694
1895
|
try {
|
|
1695
1896
|
transcriptOffset = statSync2(transcriptPath).size;
|
|
1897
|
+
observePriorCodexModel(transcriptPath);
|
|
1696
1898
|
noteTranscriptSeen();
|
|
1697
1899
|
} catch {
|
|
1698
1900
|
}
|
|
1699
1901
|
}
|
|
1700
1902
|
let bound = watch;
|
|
1701
|
-
let codexTurnId = null;
|
|
1702
|
-
let codexModelId = null;
|
|
1703
1903
|
let sessionEnded = false;
|
|
1704
1904
|
let lastPeriodicFlushAt = 0;
|
|
1705
1905
|
let lastPromptAttemptAt = 0;
|
|
@@ -1715,13 +1915,14 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1715
1915
|
}
|
|
1716
1916
|
return;
|
|
1717
1917
|
}
|
|
1718
|
-
if (!transcriptPath
|
|
1918
|
+
if (!transcriptPath) return;
|
|
1719
1919
|
const nowMs = Date.now();
|
|
1720
1920
|
if (nowMs - lastPromptAttemptAt < 3e4) return;
|
|
1721
1921
|
lastPromptAttemptAt = nowMs;
|
|
1722
1922
|
let prompt = null;
|
|
1723
1923
|
try {
|
|
1724
|
-
|
|
1924
|
+
const transcript = readFileSync3(transcriptPath, "utf8");
|
|
1925
|
+
prompt = plan.provider === "claude" ? openingPromptOf(transcript) : codexOpeningPromptOf(transcript);
|
|
1725
1926
|
} catch {
|
|
1726
1927
|
return;
|
|
1727
1928
|
}
|
|
@@ -1795,6 +1996,7 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1795
1996
|
transcriptPath = hookTranscript;
|
|
1796
1997
|
try {
|
|
1797
1998
|
transcriptOffset = plan.importHistory ? 0 : statSync2(transcriptPath).size;
|
|
1999
|
+
observePriorCodexModel(transcriptPath);
|
|
1798
2000
|
noteTranscriptSeen();
|
|
1799
2001
|
} catch {
|
|
1800
2002
|
transcriptOffset = 0;
|
|
@@ -1876,7 +2078,32 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1876
2078
|
transcriptOffset = tail.offset;
|
|
1877
2079
|
if (tail.body) {
|
|
1878
2080
|
for (const rawLine of tail.body.split("\n").filter(Boolean)) {
|
|
1879
|
-
const
|
|
2081
|
+
const mapped = mapCodexRolloutLine(rawLine);
|
|
2082
|
+
if (mapped.modelId) {
|
|
2083
|
+
codexModelId = mapped.modelId;
|
|
2084
|
+
bridge.observeModel(mapped.modelId);
|
|
2085
|
+
}
|
|
2086
|
+
if (mapped.turn?.phase === "started") {
|
|
2087
|
+
codexTurnId = mapped.turn.id;
|
|
2088
|
+
codexRolloutTurnStarts.set(mapped.turn.id, mapped.turn.at);
|
|
2089
|
+
} else if (mapped.turn?.phase === "completed") {
|
|
2090
|
+
const startedAt = codexRolloutTurnStarts.get(mapped.turn.id);
|
|
2091
|
+
if (startedAt !== void 0) {
|
|
2092
|
+
if (mapped.turn.at >= startedAt) {
|
|
2093
|
+
bridge.recordInterval({
|
|
2094
|
+
kind: "turn",
|
|
2095
|
+
id: mapped.turn.id,
|
|
2096
|
+
startedAt,
|
|
2097
|
+
endedAt: mapped.turn.at
|
|
2098
|
+
});
|
|
2099
|
+
} else {
|
|
2100
|
+
bridge.recordUnclosedInterval("turn", mapped.turn.id);
|
|
2101
|
+
}
|
|
2102
|
+
codexRolloutTurnStarts.delete(mapped.turn.id);
|
|
2103
|
+
}
|
|
2104
|
+
if (codexTurnId === mapped.turn.id) codexTurnId = null;
|
|
2105
|
+
}
|
|
2106
|
+
const event = mapped.event;
|
|
1880
2107
|
if (!event) continue;
|
|
1881
2108
|
bridge.record({
|
|
1882
2109
|
...event,
|
|
@@ -1946,6 +2173,9 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1946
2173
|
for (const id of timing.unclosedToolIds()) {
|
|
1947
2174
|
bridge.recordUnclosedInterval("tool", id);
|
|
1948
2175
|
}
|
|
2176
|
+
for (const id of codexRolloutTurnStarts.keys()) {
|
|
2177
|
+
bridge.recordUnclosedInterval("turn", id);
|
|
2178
|
+
}
|
|
1949
2179
|
const end = await endRepoState(plan.repoRoot);
|
|
1950
2180
|
const result = await bridge.complete({
|
|
1951
2181
|
outcome: exitCode === 0 ? "COMPLETED" : "INTERRUPTED",
|
|
@@ -1989,6 +2219,7 @@ async function runCodexSessionHost(plan, deps = {}) {
|
|
|
1989
2219
|
redactor: createSessionRedactor({ homedir: homedir() }),
|
|
1990
2220
|
callTool: sessionCallTool(plan.mcpUrl, codexBearerSource, plan.sessionId),
|
|
1991
2221
|
fetchImpl: deps.fetchImpl,
|
|
2222
|
+
collectSkeleton: plan.collectSkeleton !== false,
|
|
1992
2223
|
log
|
|
1993
2224
|
});
|
|
1994
2225
|
bridge.recordCapabilities({
|
|
@@ -2127,4 +2358,4 @@ export {
|
|
|
2127
2358
|
safeParse,
|
|
2128
2359
|
sessionCallTool
|
|
2129
2360
|
};
|
|
2130
|
-
//# sourceMappingURL=session-host-
|
|
2361
|
+
//# sourceMappingURL=session-host-L6XF4T2P.js.map
|