@abitat_reece/host-daemon 0.1.21 → 0.1.23

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.
@@ -1 +1 @@
1
- {"version":3,"file":"codex-bridge.d.ts","sourceRoot":"","sources":["../../src/local-control/codex-bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex-bridge.d.ts","sourceRoot":"","sources":["../../src/local-control/codex-bridge.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAEV,gBAAgB,EAGhB,iBAAiB,EAGlB,MAAM,aAAa,CAAC;AACrB,OAAO,EAKL,KAAK,8BAA8B,EACpC,MAAM,sBAAsB,CAAC;AA+B9B,UAAU,6BAA6B;IACrC,WAAW,CAAC,EAAE,8BAA8B,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,oBAAoB,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAEnG,KAAK,iBAAiB,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,EAAE,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAgBpD,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,KAAK,kBAAkB,GACnB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1E;IACE,IAAI,EAAE,kBAAkB,CAAC;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAmED,qBAAa,+BAAgC,SAAQ,KAAK;IACxD,QAAQ,CAAC,UAAU,OAAO;;CAQ3B;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,6BAAkC,GAC1C,gBAAgB,CAkwBlB;AA2sCD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,EACtB,cAAc,SAAyC,EACvD,WAAW,CAAC,EAAE,8BAA8B,GAC3C,iBAAiB,EAAE,CAgFrB"}
@@ -18,7 +18,13 @@ const THREAD_LIST_CACHE_TTL_MS = 2_500;
18
18
  const LOCAL_STARTED_TURN_MATERIALIZATION_GRACE_MS = 5 * 60_000;
19
19
  const MAX_CODEX_MESSAGE_CONTENT_LENGTH = 12_000;
20
20
  const MAX_CONTEXT_SYNC_TURNS_WITHOUT_CURSOR = 6;
21
- const HIDDEN_CODEX_ITEM_TYPES = new Set(["reasoning"]);
21
+ const HIDDEN_CODEX_ITEM_TYPES = new Set([
22
+ "contextCompaction",
23
+ "enteredReviewMode",
24
+ "exitedReviewMode",
25
+ "reasoning"
26
+ ]);
27
+ const MAX_CODEX_ITEM_SUMMARY_LENGTH = 240;
22
28
  const PHONE_FULL_ACCESS_TURN_OPTIONS = {
23
29
  approvalPolicy: "never",
24
30
  sandboxPolicy: { type: "dangerFullAccess" }
@@ -42,6 +48,7 @@ export function createLocalCodexBridge(options = {}) {
42
48
  const queuedTurnsByThread = new Map();
43
49
  const queueDrainTimers = new Map();
44
50
  const threadListCache = new Map();
51
+ const conversationStatusCache = new Map();
45
52
  const messageHistoryCache = new Map();
46
53
  const modelContextSyncedTurnIds = new Map();
47
54
  const locallyStartedTurnsByThread = new Map();
@@ -67,6 +74,10 @@ export function createLocalCodexBridge(options = {}) {
67
74
  }
68
75
  return tracked;
69
76
  }
77
+ if (shouldClearMissingLocalStartedTurn(thread, tracked)) {
78
+ locallyStartedTurnsByThread.delete(thread.id);
79
+ return null;
80
+ }
70
81
  if (Date.now() - tracked.startedAtMs > LOCAL_STARTED_TURN_MATERIALIZATION_GRACE_MS) {
71
82
  locallyStartedTurnsByThread.delete(thread.id);
72
83
  return null;
@@ -263,6 +274,7 @@ export function createLocalCodexBridge(options = {}) {
263
274
  return true;
264
275
  }
265
276
  function invalidateMessageHistoryCache(threadId) {
277
+ conversationStatusCache.delete(threadId);
266
278
  messageHistoryCache.delete(threadId);
267
279
  }
268
280
  function scheduleQueueDrain(threadId, delayMs = QUEUED_TURN_POLL_INTERVAL_MS) {
@@ -324,6 +336,18 @@ export function createLocalCodexBridge(options = {}) {
324
336
  rememberModelContextSyncedTurn(threadId, started.turn.id);
325
337
  rememberLocallyStartedTurn(threadId, started.turn.id);
326
338
  }
339
+ async function readThreadForContinuation(threadId) {
340
+ try {
341
+ return await client.readThread(threadId, true);
342
+ }
343
+ catch (error) {
344
+ logDiagnostics(diagnostics, "warn", "codex.thread_continue.full_read_unavailable", {
345
+ error: errorDiagnostics(error),
346
+ threadId
347
+ });
348
+ return client.readThread(threadId, false);
349
+ }
350
+ }
327
351
  return {
328
352
  async bootstrap() {
329
353
  try {
@@ -343,7 +367,7 @@ export function createLocalCodexBridge(options = {}) {
343
367
  },
344
368
  async continueConversation(conversationId, input) {
345
369
  const threadId = toCodexThreadId(conversationId);
346
- const thread = await client.readThread(threadId, true);
370
+ const thread = await readThreadForContinuation(threadId);
347
371
  const delivery = input.delivery ?? "queue";
348
372
  const locallyStartedTurn = locallyStartedTurnForThread(thread);
349
373
  if (isCodexThreadBusy(thread) || locallyStartedTurn) {
@@ -403,8 +427,12 @@ export function createLocalCodexBridge(options = {}) {
403
427
  updated
404
428
  };
405
429
  },
406
- async listCompletionStates() {
407
- const threads = await readThreadsWithTurns(await loadAllThreads());
430
+ async listCompletionStates(completionOptions = {}) {
431
+ const threads = await hydrateConversationStatusThreads(await loadAllThreads(), {
432
+ hydrateCompletionTransitions: true,
433
+ hydrateIdleSummariesSince: completionOptions.hydrateIdleSummariesSince,
434
+ hydrateIdleSummaries: false
435
+ });
408
436
  const states = threads.map((thread) => codexThreadToCompletionState(thread, workspaceId, {
409
437
  forceRunning: Boolean(locallyStartedTurnForThread(thread))
410
438
  }));
@@ -453,7 +481,9 @@ export function createLocalCodexBridge(options = {}) {
453
481
  },
454
482
  async listProjectConversations(projectId) {
455
483
  const cwd = await resolveProjectCwd(projectId);
456
- const threads = await hydrateConversationStatusThreads(await listAllThreads({ cwd }));
484
+ const threads = await hydrateConversationStatusThreads(await listAllThreads({ cwd }), {
485
+ hydrateIdleSummaries: true
486
+ });
457
487
  return threads
458
488
  .filter((thread) => externalCodexProjectId(thread.cwd) === projectId)
459
489
  .sort((left, right) => right.updatedAt - left.updatedAt)
@@ -483,19 +513,24 @@ export function createLocalCodexBridge(options = {}) {
483
513
  };
484
514
  }
485
515
  };
486
- async function readThreadsWithTurns(threads) {
487
- return Promise.all(threads.map(async (thread) => {
488
- const readThread = await client.readThread(thread.id, true).catch(() => thread);
489
- return mergeCodexThreadSnapshots(readThread, thread);
490
- }));
491
- }
492
- async function hydrateConversationStatusThreads(threads) {
516
+ async function hydrateConversationStatusThreads(threads, options) {
493
517
  return Promise.all(threads.map(async (thread) => {
494
- if (!needsConversationStatusHydration(thread)) {
518
+ const cached = conversationStatusCache.get(thread.id);
519
+ if (cached && canUseCachedConversationStatusThread(cached, thread)) {
520
+ return mergeCodexThreadSnapshots(cached.thread, thread);
521
+ }
522
+ if (!needsConversationStatusHydration(thread, options) &&
523
+ !needsCompletionTransitionHydration(thread, cached, options)) {
495
524
  return thread;
496
525
  }
497
526
  const readThread = await client.readThread(thread.id, true).catch(() => thread);
498
- return mergeCodexThreadSnapshots(readThread, thread);
527
+ const mergedThread = mergeCodexThreadSnapshots(readThread, thread);
528
+ conversationStatusCache.set(thread.id, {
529
+ summaryStatusType: threadStatusType(thread.status),
530
+ summaryUpdatedAt: safeSeconds(thread.updatedAt, thread.createdAt),
531
+ thread: mergedThread
532
+ });
533
+ return mergedThread;
499
534
  }));
500
535
  }
501
536
  async function readCachedThreadMessages(threadId, options) {
@@ -525,6 +560,10 @@ export function createLocalCodexBridge(options = {}) {
525
560
  cached.statusType === threadStatusType(summary.status) &&
526
561
  cached.updatedAt === safeSeconds(summary.updatedAt, summary.createdAt));
527
562
  }
563
+ function canUseCachedConversationStatusThread(cached, summary) {
564
+ return (cached.summaryStatusType === threadStatusType(summary.status) &&
565
+ cached.summaryUpdatedAt === safeSeconds(summary.updatedAt, summary.createdAt));
566
+ }
528
567
  async function isThreadLoaded(threadId) {
529
568
  try {
530
569
  return (await client.listLoadedThreads()).includes(threadId);
@@ -1400,10 +1439,44 @@ function isThreadListActivitySummaryStatus(status) {
1400
1439
  const statusType = threadStatusType(status);
1401
1440
  return statusType === "idle" || statusType === "notLoaded";
1402
1441
  }
1403
- function needsConversationStatusHydration(thread) {
1442
+ function needsConversationStatusHydration(thread, options) {
1404
1443
  return (thread.turns.length === 0 &&
1405
- (isThreadListActivitySummaryStatus(thread.status) ||
1406
- threadStatusType(thread.status) === "active"));
1444
+ (threadStatusType(thread.status) === "active" ||
1445
+ thread.abitatLoadedFromAppServer === true ||
1446
+ (options.hydrateIdleSummaries && isThreadListActivitySummaryStatus(thread.status))));
1447
+ }
1448
+ function needsCompletionTransitionHydration(thread, cached, options) {
1449
+ if (!options.hydrateCompletionTransitions ||
1450
+ thread.turns.length > 0 ||
1451
+ !isThreadListActivitySummaryStatus(thread.status)) {
1452
+ return false;
1453
+ }
1454
+ return (Boolean(cached && isCodexThreadBusy(cached.thread)) ||
1455
+ summaryUpdatedAfter(thread, options.hydrateIdleSummariesSince));
1456
+ }
1457
+ function summaryUpdatedAfter(thread, timestampMs) {
1458
+ if (typeof timestampMs !== "number" || !Number.isFinite(timestampMs)) {
1459
+ return false;
1460
+ }
1461
+ return safeSeconds(thread.updatedAt, thread.createdAt) * 1000 >= timestampMs;
1462
+ }
1463
+ function shouldClearMissingLocalStartedTurn(thread, tracked) {
1464
+ const latestTurn = thread.turns.at(-1) ?? null;
1465
+ if (latestTurn &&
1466
+ latestTurn.id !== tracked.turnId &&
1467
+ isTurnTerminal(latestTurn) &&
1468
+ turnEndedAfterLocalStart(thread, latestTurn, tracked)) {
1469
+ return true;
1470
+ }
1471
+ const statusType = threadStatusType(thread.status);
1472
+ return statusType !== "active" && threadUpdatedAfterLocalStart(thread, tracked);
1473
+ }
1474
+ function turnEndedAfterLocalStart(thread, turn, tracked) {
1475
+ return (safeSeconds(turn.completedAt, thread.updatedAt, thread.createdAt) * 1000 >=
1476
+ tracked.startedAtMs);
1477
+ }
1478
+ function threadUpdatedAfterLocalStart(thread, tracked) {
1479
+ return safeSeconds(thread.updatedAt, thread.createdAt) * 1000 >= tracked.startedAtMs;
1407
1480
  }
1408
1481
  function threadListActivitySeconds(thread) {
1409
1482
  const currentActivity = thread.turns.length === 0 &&
@@ -1474,8 +1547,9 @@ export function flattenThreadMessages(thread, conversationId = externalCodexConv
1474
1547
  itemTypeCounts.set(item.type, (itemTypeCounts.get(item.type) ?? 0) + 1);
1475
1548
  const flattened = threadItemToMessageContent(item);
1476
1549
  if (!flattened) {
1477
- if (!HIDDEN_CODEX_ITEM_TYPES.has(item.type) && !isKnownCodexItemType(item.type)) {
1478
- unknownItemTypes.add(item.type);
1550
+ if (!HIDDEN_CODEX_ITEM_TYPES.has(item.type) &&
1551
+ !isKnownCodexItemType(item.type) &&
1552
+ !unknownItemTypes.has(item.type)) {
1479
1553
  logDiagnostics(diagnostics, "warn", "codex.thread_item.unknown", {
1480
1554
  codexItemId: item.id,
1481
1555
  codexItemType: item.type,
@@ -1483,6 +1557,7 @@ export function flattenThreadMessages(thread, conversationId = externalCodexConv
1483
1557
  threadId: thread.id,
1484
1558
  turnId: turn.id
1485
1559
  });
1560
+ unknownItemTypes.add(item.type);
1486
1561
  }
1487
1562
  continue;
1488
1563
  }
@@ -1588,6 +1663,27 @@ function stringField(value, key) {
1588
1663
  const field = value[key];
1589
1664
  return typeof field === "string" && field.trim() ? field.trim() : null;
1590
1665
  }
1666
+ function recordField(value, key) {
1667
+ if (!value || typeof value !== "object") {
1668
+ return null;
1669
+ }
1670
+ const field = value[key];
1671
+ return field && typeof field === "object" ? field : null;
1672
+ }
1673
+ function summarizedStringField(value, key) {
1674
+ if (!value || typeof value !== "object") {
1675
+ return null;
1676
+ }
1677
+ const field = stringField(value, key);
1678
+ return field ? summarizeInlineContent(field) : null;
1679
+ }
1680
+ function summarizeInlineContent(content) {
1681
+ const normalized = content.replace(/\s+/gu, " ").trim();
1682
+ if (normalized.length <= MAX_CODEX_ITEM_SUMMARY_LENGTH) {
1683
+ return normalized;
1684
+ }
1685
+ return `${normalized.slice(0, MAX_CODEX_ITEM_SUMMARY_LENGTH)}...`;
1686
+ }
1591
1687
  function mimeTypeForPath(path) {
1592
1688
  switch (extname(path).toLowerCase()) {
1593
1689
  case ".html":
@@ -1702,6 +1798,36 @@ function threadItemToMessageContent(item) {
1702
1798
  role: "runtime"
1703
1799
  };
1704
1800
  }
1801
+ if (item.type === "imageGeneration") {
1802
+ return {
1803
+ content: imageGenerationSummary(item),
1804
+ role: "assistant"
1805
+ };
1806
+ }
1807
+ if (item.type === "webSearch") {
1808
+ return {
1809
+ content: webSearchSummary(item),
1810
+ role: "runtime"
1811
+ };
1812
+ }
1813
+ if (item.type === "imageView") {
1814
+ return {
1815
+ content: "Viewed an image.",
1816
+ role: "runtime"
1817
+ };
1818
+ }
1819
+ if (item.type === "mcpToolCall" || item.type === "dynamicToolCall") {
1820
+ return {
1821
+ content: toolCallSummary(item),
1822
+ role: "runtime"
1823
+ };
1824
+ }
1825
+ if (item.type === "collabAgentToolCall") {
1826
+ return {
1827
+ content: collabAgentToolCallSummary(item),
1828
+ role: "runtime"
1829
+ };
1830
+ }
1705
1831
  return null;
1706
1832
  }
1707
1833
  function isKnownCodexItemType(type) {
@@ -1710,8 +1836,53 @@ function isKnownCodexItemType(type) {
1710
1836
  type === "plan" ||
1711
1837
  type === "commandExecution" ||
1712
1838
  type === "fileChange" ||
1839
+ type === "imageGeneration" ||
1840
+ type === "imageView" ||
1841
+ type === "webSearch" ||
1842
+ type === "mcpToolCall" ||
1843
+ type === "dynamicToolCall" ||
1844
+ type === "collabAgentToolCall" ||
1713
1845
  HIDDEN_CODEX_ITEM_TYPES.has(type));
1714
1846
  }
1847
+ function imageGenerationSummary(item) {
1848
+ const prompt = summarizedStringField(item, "prompt") ?? summarizedStringField(item, "userPrompt");
1849
+ const savedPath = summarizedStringField(item, "savedPath") ??
1850
+ summarizedStringField(item, "saved_path") ??
1851
+ summarizedStringField(item, "path");
1852
+ if (prompt && savedPath) {
1853
+ return `Generated an image: ${prompt}. Saved to ${savedPath}.`;
1854
+ }
1855
+ if (prompt) {
1856
+ return `Generated an image: ${prompt}.`;
1857
+ }
1858
+ if (savedPath) {
1859
+ return `Generated an image: ${savedPath}.`;
1860
+ }
1861
+ return "Generated an image.";
1862
+ }
1863
+ function webSearchSummary(item) {
1864
+ const action = recordField(item, "action");
1865
+ const query = summarizedStringField(item, "query") ??
1866
+ summarizedStringField(action, "query") ??
1867
+ summarizedStringField(item, "url") ??
1868
+ summarizedStringField(action, "url");
1869
+ return query ? `Searched the web: ${query}.` : "Searched the web.";
1870
+ }
1871
+ function toolCallSummary(item) {
1872
+ const toolName = summarizedStringField(item, "name") ??
1873
+ summarizedStringField(item, "toolName") ??
1874
+ summarizedStringField(item, "tool_name") ??
1875
+ summarizedStringField(item, "serverName") ??
1876
+ summarizedStringField(item, "server_name");
1877
+ return toolName ? `Used tool: ${toolName}.` : "Used a tool.";
1878
+ }
1879
+ function collabAgentToolCallSummary(item) {
1880
+ const name = summarizedStringField(item, "name") ??
1881
+ summarizedStringField(item, "toolName") ??
1882
+ summarizedStringField(item, "agentPath") ??
1883
+ summarizedStringField(item, "agent_path");
1884
+ return name ? `Used collaboration tool: ${name}.` : "Used a collaboration tool.";
1885
+ }
1715
1886
  function filterThreadMessages(messages, options) {
1716
1887
  const filtered = options.includeRuntime
1717
1888
  ? messages