remote-codex 0.1.10 → 0.11.0
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/apps/supervisor-api/dist/index.js +11159 -27875
- package/apps/supervisor-web/dist/assets/{highlighted-body-OFNGDK62-CyMcatlD.js → highlighted-body-OFNGDK62-ChrwAL9u.js} +1 -1
- package/apps/supervisor-web/dist/assets/index-DHf2HOXx.js +381 -0
- package/apps/supervisor-web/dist/assets/index-DpWxXCgt.css +32 -0
- package/apps/supervisor-web/dist/assets/{xterm-DbYWMNQ0.js → xterm-D4sevve4.js} +1 -1
- package/apps/supervisor-web/dist/index.html +2 -2
- package/package.json +2 -3
- package/packages/agent-runtime/src/index.ts +4 -0
- package/packages/agent-runtime/src/management-errors.ts +11 -0
- package/packages/agent-runtime/src/model-pricing.ts +312 -0
- package/packages/agent-runtime/src/registry.ts +19 -4
- package/packages/agent-runtime/src/runtime-errors.ts +97 -0
- package/packages/agent-runtime/src/types.ts +36 -3
- package/packages/agent-runtime/src/unavailable-runtime.ts +169 -0
- package/packages/claude/src/runtimeAdapter.test.ts +95 -6
- package/packages/claude/src/runtimeAdapter.ts +421 -65
- package/packages/codex/src/historyItems.test.ts +110 -0
- package/packages/codex/src/historyItems.ts +96 -15
- package/packages/codex/src/hookHistory.test.ts +59 -0
- package/packages/codex/src/index.ts +7 -0
- package/packages/codex/src/local-session-store.ts +390 -0
- package/packages/codex/src/management/codex-management-service.ts +454 -0
- package/packages/codex/src/management/codexHostConfig.test.ts +88 -0
- package/packages/codex/src/management/codexHostConfig.ts +188 -0
- package/packages/codex/src/management/errors.ts +20 -0
- package/packages/codex/src/modelPricing.test.ts +184 -0
- package/packages/codex/src/modelPricing.ts +9 -0
- package/packages/codex/src/runtime-errors.test.ts +72 -0
- package/packages/codex/src/runtime-errors.ts +37 -0
- package/packages/codex/src/runtimeAdapter.ts +15 -0
- package/packages/codex/src/thread-title.ts +1 -0
- package/packages/opencode/src/historyItems.test.ts +504 -0
- package/packages/opencode/src/historyItems.ts +896 -0
- package/packages/opencode/src/index.ts +2 -0
- package/packages/opencode/src/runtimeAdapter.test.ts +1355 -0
- package/packages/opencode/src/runtimeAdapter.ts +1469 -0
- package/packages/shared/src/agent-providers.ts +56 -0
- package/packages/shared/src/index.ts +170 -35
- package/apps/supervisor-web/dist/assets/index-BlAhoIuq.js +0 -379
- package/apps/supervisor-web/dist/assets/index-DI0NRNgr.css +0 -32
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
markTransientAgentHistoryItem,
|
|
5
|
+
type AgentHistoryItem,
|
|
6
|
+
} from '../../agent-runtime/src/index';
|
|
7
|
+
import {
|
|
8
|
+
agentTurnToThreadTurnDto,
|
|
9
|
+
codexTurnToAgentTurn,
|
|
10
|
+
liveCodexItemToHistoryItem,
|
|
11
|
+
shouldPersistLiveHistoryItem,
|
|
12
|
+
shouldPersistRuntimeFinalHistoryItem,
|
|
13
|
+
} from './historyItems';
|
|
14
|
+
|
|
15
|
+
describe('codex history item persistence policy', () => {
|
|
16
|
+
it('keeps streamed assistant text out of live history persistence', () => {
|
|
17
|
+
expect(
|
|
18
|
+
shouldPersistLiveHistoryItem({
|
|
19
|
+
id: 'agent-live-1',
|
|
20
|
+
kind: 'agentMessage',
|
|
21
|
+
text: 'Streaming draft',
|
|
22
|
+
}),
|
|
23
|
+
).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('keeps transient streamed assistant text out of final runtime persistence', () => {
|
|
27
|
+
const transientMessage = markTransientAgentHistoryItem<AgentHistoryItem>({
|
|
28
|
+
id: 'agent-live-1',
|
|
29
|
+
kind: 'agentMessage',
|
|
30
|
+
text: 'Streaming draft',
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
expect(shouldPersistRuntimeFinalHistoryItem(transientMessage, [transientMessage])).toBe(
|
|
34
|
+
false,
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('hides transient streamed assistant text once a final assistant message exists', () => {
|
|
39
|
+
const transientMessage = markTransientAgentHistoryItem<AgentHistoryItem>({
|
|
40
|
+
id: 'agent-live-1',
|
|
41
|
+
kind: 'agentMessage',
|
|
42
|
+
text: 'Streaming draft',
|
|
43
|
+
});
|
|
44
|
+
const finalMessage: AgentHistoryItem = {
|
|
45
|
+
id: 'agent-final-1',
|
|
46
|
+
kind: 'agentMessage',
|
|
47
|
+
text: 'Final answer',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
expect(
|
|
51
|
+
agentTurnToThreadTurnDto({
|
|
52
|
+
providerTurnId: 'turn-1',
|
|
53
|
+
status: 'completed',
|
|
54
|
+
error: null,
|
|
55
|
+
items: [transientMessage, finalMessage],
|
|
56
|
+
}).items,
|
|
57
|
+
).toEqual([finalMessage]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('maps Codex collab agent tool calls to dedicated agent tool call items', () => {
|
|
61
|
+
const turn = codexTurnToAgentTurn({
|
|
62
|
+
id: 'turn-1',
|
|
63
|
+
status: 'inProgress',
|
|
64
|
+
error: null,
|
|
65
|
+
items: [
|
|
66
|
+
{
|
|
67
|
+
id: 'agent-tool-1',
|
|
68
|
+
type: 'collabAgentToolCall',
|
|
69
|
+
status: 'running',
|
|
70
|
+
action: {
|
|
71
|
+
name: 'Review checkout flow',
|
|
72
|
+
input: {
|
|
73
|
+
prompt: 'Inspect checkout UI regressions.',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
expect(turn.items[0]).toMatchObject({
|
|
81
|
+
id: 'agent-tool-1',
|
|
82
|
+
kind: 'agentToolCall',
|
|
83
|
+
text: 'Agent: Review checkout flow',
|
|
84
|
+
previewText: 'Agent',
|
|
85
|
+
status: 'running',
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('keeps Codex collab agent tool calls visible while running', () => {
|
|
90
|
+
expect(
|
|
91
|
+
liveCodexItemToHistoryItem(
|
|
92
|
+
{
|
|
93
|
+
id: 'agent-tool-1',
|
|
94
|
+
type: 'collabAgentToolCall',
|
|
95
|
+
status: 'running',
|
|
96
|
+
action: {
|
|
97
|
+
name: 'Inspect backend runtime boundaries',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
'started',
|
|
101
|
+
),
|
|
102
|
+
).toMatchObject({
|
|
103
|
+
id: 'agent-tool-1',
|
|
104
|
+
kind: 'agentToolCall',
|
|
105
|
+
text: 'Agent: Inspect backend runtime boundaries',
|
|
106
|
+
previewText: 'Agent',
|
|
107
|
+
status: 'running',
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
CodexTurnItem,
|
|
4
4
|
} from './types';
|
|
5
5
|
import type { AgentTurn } from '../../agent-runtime/src/index';
|
|
6
|
+
import { isTransientAgentHistoryItem } from '../../agent-runtime/src/index';
|
|
6
7
|
import type {
|
|
7
8
|
ThreadHistoryItemDetailDto,
|
|
8
9
|
ThreadHistoryItemDto,
|
|
@@ -13,6 +14,7 @@ import { parseCodexHookPromptText } from './hookHistory';
|
|
|
13
14
|
|
|
14
15
|
const DEFERRED_COMMAND_DETAIL_TITLE = 'Command Output';
|
|
15
16
|
const DEFERRED_TOOL_DETAIL_TITLE = 'Tool Call Details';
|
|
17
|
+
const DEFERRED_AGENT_TOOL_DETAIL_TITLE = 'Agent Details';
|
|
16
18
|
|
|
17
19
|
export type TurnItemOrderSnapshot = Map<string, Map<string, number>>;
|
|
18
20
|
|
|
@@ -213,14 +215,19 @@ function formatCommandHistoryItem(
|
|
|
213
215
|
}
|
|
214
216
|
|
|
215
217
|
function deferToolCallHistoryItem(
|
|
216
|
-
item: ThreadHistoryItemDto & { kind: 'toolCall' },
|
|
218
|
+
item: ThreadHistoryItemDto & { kind: 'toolCall' | 'agentToolCall' | 'skillToolCall' },
|
|
217
219
|
deferredDetails: Map<string, ThreadHistoryItemDetailDto>,
|
|
218
220
|
): ThreadHistoryItemDto {
|
|
219
221
|
const fullText = item.detailText?.trim() || item.text || 'Tool call';
|
|
220
222
|
deferredDetails.set(item.id, {
|
|
221
223
|
id: item.id,
|
|
222
224
|
kind: item.kind,
|
|
223
|
-
title:
|
|
225
|
+
title:
|
|
226
|
+
item.kind === 'agentToolCall'
|
|
227
|
+
? DEFERRED_AGENT_TOOL_DETAIL_TITLE
|
|
228
|
+
: item.kind === 'skillToolCall'
|
|
229
|
+
? 'Skill Details'
|
|
230
|
+
: DEFERRED_TOOL_DETAIL_TITLE,
|
|
224
231
|
text: fullText,
|
|
225
232
|
});
|
|
226
233
|
|
|
@@ -267,6 +274,7 @@ function valueFromNestedRecords(
|
|
|
267
274
|
function formatToolCallHistoryItem(
|
|
268
275
|
item: CodexTurnItem,
|
|
269
276
|
deferredDetails?: Map<string, ThreadHistoryItemDetailDto>,
|
|
277
|
+
kind: 'toolCall' | 'agentToolCall' | 'skillToolCall' = 'toolCall',
|
|
270
278
|
): ThreadHistoryItemDto {
|
|
271
279
|
const { action, result, input, output } = extractToolCallRecords(item);
|
|
272
280
|
const nestedRecords = [item, action, result, input, output];
|
|
@@ -295,14 +303,18 @@ function formatToolCallHistoryItem(
|
|
|
295
303
|
const summaryLine = serverName && toolName
|
|
296
304
|
? `${serverName}/${toolName}`
|
|
297
305
|
: toolName ?? serverName ?? stringOrNull(item.text) ?? item.type;
|
|
306
|
+
const displaySummary =
|
|
307
|
+
kind === 'agentToolCall' && !/^agent\b/i.test(summaryLine)
|
|
308
|
+
? `Agent: ${summaryLine}`
|
|
309
|
+
: summaryLine;
|
|
298
310
|
|
|
299
|
-
const detailLines = [
|
|
311
|
+
const detailLines = [displaySummary];
|
|
300
312
|
if (status) {
|
|
301
313
|
detailLines.push(`Status: ${status}`);
|
|
302
314
|
}
|
|
303
315
|
|
|
304
316
|
const text = stringOrNull(item.text);
|
|
305
|
-
if (text && text !== summaryLine) {
|
|
317
|
+
if (text && text !== summaryLine && text !== displaySummary) {
|
|
306
318
|
detailLines.push('', text);
|
|
307
319
|
}
|
|
308
320
|
|
|
@@ -320,9 +332,9 @@ function formatToolCallHistoryItem(
|
|
|
320
332
|
|
|
321
333
|
const historyItem: ThreadHistoryItemDto = {
|
|
322
334
|
id: item.id,
|
|
323
|
-
kind
|
|
324
|
-
text:
|
|
325
|
-
previewText:
|
|
335
|
+
kind,
|
|
336
|
+
text: displaySummary,
|
|
337
|
+
previewText: kind === 'agentToolCall' ? 'Agent' : displaySummary,
|
|
326
338
|
detailText: detailLines.join('\n'),
|
|
327
339
|
status,
|
|
328
340
|
};
|
|
@@ -334,7 +346,9 @@ function formatToolCallHistoryItem(
|
|
|
334
346
|
(historyItem.detailText?.length ?? 0) > 240)
|
|
335
347
|
) {
|
|
336
348
|
return deferToolCallHistoryItem(
|
|
337
|
-
historyItem as ThreadHistoryItemDto & {
|
|
349
|
+
historyItem as ThreadHistoryItemDto & {
|
|
350
|
+
kind: 'toolCall' | 'agentToolCall' | 'skillToolCall';
|
|
351
|
+
},
|
|
338
352
|
deferredDetails,
|
|
339
353
|
);
|
|
340
354
|
}
|
|
@@ -355,8 +369,12 @@ export function deferLargeHistoryItemDetails(
|
|
|
355
369
|
deferredDetails,
|
|
356
370
|
)
|
|
357
371
|
: item.kind === 'toolCall'
|
|
372
|
+
|| item.kind === 'agentToolCall'
|
|
373
|
+
|| item.kind === 'skillToolCall'
|
|
358
374
|
? deferToolCallHistoryItem(
|
|
359
|
-
item as ThreadHistoryItemDto & {
|
|
375
|
+
item as ThreadHistoryItemDto & {
|
|
376
|
+
kind: 'toolCall' | 'agentToolCall' | 'skillToolCall';
|
|
377
|
+
},
|
|
360
378
|
deferredDetails,
|
|
361
379
|
)
|
|
362
380
|
: item,
|
|
@@ -366,15 +384,45 @@ export function deferLargeHistoryItemDetails(
|
|
|
366
384
|
|
|
367
385
|
export function shouldPersistLiveHistoryItem(item: ThreadHistoryItemDto) {
|
|
368
386
|
return (
|
|
369
|
-
item.kind === 'agentMessage' ||
|
|
370
387
|
item.kind === 'commandExecution' ||
|
|
371
388
|
item.kind === 'fileChange' ||
|
|
389
|
+
item.kind === 'fileRead' ||
|
|
372
390
|
item.kind === 'hook' ||
|
|
391
|
+
item.kind === 'agentToolCall' ||
|
|
392
|
+
item.kind === 'skillToolCall' ||
|
|
373
393
|
item.kind === 'toolCall' ||
|
|
374
394
|
item.kind === 'webSearch'
|
|
375
395
|
);
|
|
376
396
|
}
|
|
377
397
|
|
|
398
|
+
export function shouldPersistFinalHistoryItem(item: ThreadHistoryItemDto) {
|
|
399
|
+
return item.kind === 'agentMessage' || shouldPersistLiveHistoryItem(item);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export function shouldPersistRuntimeFinalHistoryItem(
|
|
403
|
+
item: ThreadHistoryItemDto,
|
|
404
|
+
allItems: ThreadHistoryItemDto[],
|
|
405
|
+
) {
|
|
406
|
+
if (item.kind === 'agentMessage' && isTransientAgentHistoryItem(item)) {
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return shouldPersistFinalHistoryItem(item);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function visibleRuntimeTurnItems(items: ThreadHistoryItemDto[]) {
|
|
414
|
+
const hasFinalAgentMessage = items.some(
|
|
415
|
+
(item) => item.kind === 'agentMessage' && !isTransientAgentHistoryItem(item),
|
|
416
|
+
);
|
|
417
|
+
if (!hasFinalAgentMessage) {
|
|
418
|
+
return items;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
return items.filter(
|
|
422
|
+
(item) => !(item.kind === 'agentMessage' && isTransientAgentHistoryItem(item)),
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
|
|
378
426
|
export function parseStoredHistoryItem(value: string): ThreadHistoryItemDto | null {
|
|
379
427
|
try {
|
|
380
428
|
const parsed = JSON.parse(value);
|
|
@@ -562,6 +610,24 @@ function copyPersistedSequence(
|
|
|
562
610
|
return item.sequence === sequence ? item : { ...item, sequence };
|
|
563
611
|
}
|
|
564
612
|
|
|
613
|
+
function shouldAppendPersistedMissingItem(
|
|
614
|
+
turn: ThreadTurnDto,
|
|
615
|
+
item: ThreadHistoryItemDto,
|
|
616
|
+
) {
|
|
617
|
+
if (item.kind !== 'agentMessage') {
|
|
618
|
+
return true;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Older builds persisted streaming assistant drafts. Once the provider
|
|
622
|
+
// transcript has final assistant text, do not resurrect those draft rows.
|
|
623
|
+
const isCrossTurnProjection = Boolean(item.sourceTurnId && item.sourceTurnId !== turn.id);
|
|
624
|
+
return !(
|
|
625
|
+
turn.status === 'completed' &&
|
|
626
|
+
turn.items.some((turnItem) => turnItem.kind === 'agentMessage') &&
|
|
627
|
+
!isCrossTurnProjection
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
|
|
565
631
|
export function mergePersistedHistoryItemsIntoTurns(
|
|
566
632
|
turns: ThreadTurnDto[],
|
|
567
633
|
persistedItemsByTurnId: Map<string, ThreadHistoryItemDto[]>,
|
|
@@ -596,7 +662,12 @@ export function mergePersistedHistoryItemsIntoTurns(
|
|
|
596
662
|
changed = true;
|
|
597
663
|
}
|
|
598
664
|
|
|
599
|
-
if (
|
|
665
|
+
if (
|
|
666
|
+
persistedItem.kind === 'commandExecution' ||
|
|
667
|
+
persistedItem.kind === 'toolCall' ||
|
|
668
|
+
persistedItem.kind === 'agentToolCall' ||
|
|
669
|
+
persistedItem.kind === 'skillToolCall'
|
|
670
|
+
) {
|
|
600
671
|
const existingText = item.detailText?.trim() || item.text.trim();
|
|
601
672
|
const persistedText = persistedItem.detailText?.trim() || persistedItem.text.trim();
|
|
602
673
|
if (persistedText.length > existingText.length) {
|
|
@@ -607,7 +678,9 @@ export function mergePersistedHistoryItemsIntoTurns(
|
|
|
607
678
|
deferredDetails,
|
|
608
679
|
)
|
|
609
680
|
: deferToolCallHistoryItem(
|
|
610
|
-
persistedItem as ThreadHistoryItemDto & {
|
|
681
|
+
persistedItem as ThreadHistoryItemDto & {
|
|
682
|
+
kind: 'toolCall' | 'agentToolCall' | 'skillToolCall';
|
|
683
|
+
},
|
|
611
684
|
deferredDetails,
|
|
612
685
|
);
|
|
613
686
|
}
|
|
@@ -619,6 +692,7 @@ export function mergePersistedHistoryItemsIntoTurns(
|
|
|
619
692
|
const existingItemIds = new Set(nextItems.map((item) => item.id));
|
|
620
693
|
const missingItems = [...persistedItemsById.values()]
|
|
621
694
|
.filter((item) => !existingItemIds.has(item.id))
|
|
695
|
+
.filter((item) => shouldAppendPersistedMissingItem(turn, item))
|
|
622
696
|
.map((item) =>
|
|
623
697
|
item.kind === 'commandExecution'
|
|
624
698
|
? deferCommandHistoryItem(
|
|
@@ -626,8 +700,12 @@ export function mergePersistedHistoryItemsIntoTurns(
|
|
|
626
700
|
deferredDetails,
|
|
627
701
|
)
|
|
628
702
|
: item.kind === 'toolCall'
|
|
703
|
+
|| item.kind === 'agentToolCall'
|
|
704
|
+
|| item.kind === 'skillToolCall'
|
|
629
705
|
? deferToolCallHistoryItem(
|
|
630
|
-
item as ThreadHistoryItemDto & {
|
|
706
|
+
item as ThreadHistoryItemDto & {
|
|
707
|
+
kind: 'toolCall' | 'agentToolCall' | 'skillToolCall';
|
|
708
|
+
},
|
|
631
709
|
deferredDetails,
|
|
632
710
|
)
|
|
633
711
|
: item,
|
|
@@ -1175,8 +1253,9 @@ function itemToHistoryItem(
|
|
|
1175
1253
|
return formatFileChangeHistoryItem(item);
|
|
1176
1254
|
case 'mcpToolCall':
|
|
1177
1255
|
case 'dynamicToolCall':
|
|
1178
|
-
case 'collabAgentToolCall':
|
|
1179
1256
|
return formatToolCallHistoryItem(item, deferredDetails);
|
|
1257
|
+
case 'collabAgentToolCall':
|
|
1258
|
+
return formatToolCallHistoryItem(item, deferredDetails, 'agentToolCall');
|
|
1180
1259
|
default:
|
|
1181
1260
|
return {
|
|
1182
1261
|
id: item.id,
|
|
@@ -1195,6 +1274,8 @@ export function liveCodexItemToHistoryItem(
|
|
|
1195
1274
|
if (
|
|
1196
1275
|
historyItem.kind !== 'commandExecution' &&
|
|
1197
1276
|
historyItem.kind !== 'toolCall' &&
|
|
1277
|
+
historyItem.kind !== 'agentToolCall' &&
|
|
1278
|
+
historyItem.kind !== 'skillToolCall' &&
|
|
1198
1279
|
historyItem.kind !== 'fileChange' &&
|
|
1199
1280
|
historyItem.kind !== 'webSearch'
|
|
1200
1281
|
) {
|
|
@@ -1218,7 +1299,7 @@ export function agentTurnToThreadTurnDto(
|
|
|
1218
1299
|
startedAt: turn.startedAt ?? parseUuidV7Timestamp(turn.providerTurnId),
|
|
1219
1300
|
status: turn.status,
|
|
1220
1301
|
error: turn.error?.message ?? null,
|
|
1221
|
-
items: turn.items,
|
|
1302
|
+
items: visibleRuntimeTurnItems(turn.items),
|
|
1222
1303
|
};
|
|
1223
1304
|
|
|
1224
1305
|
return deferredDetails ? deferLargeHistoryItemDetails(baseTurn, deferredDetails) : baseTurn;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
codexHookRunToHistoryItem,
|
|
5
|
+
parseCodexHookPromptText,
|
|
6
|
+
} from './index';
|
|
7
|
+
|
|
8
|
+
describe('codex hook history mapping', () => {
|
|
9
|
+
it('parses hook prompt XML emitted as assistant text', () => {
|
|
10
|
+
expect(
|
|
11
|
+
parseCodexHookPromptText(
|
|
12
|
+
'<hook_prompt hook_run_id="stop:0:/tmp/demo/.codex/hooks.json">remote-codex hook ran</hook_prompt>',
|
|
13
|
+
),
|
|
14
|
+
).toMatchObject({
|
|
15
|
+
hookRunId: 'stop:0:/tmp/demo/.codex/hooks.json',
|
|
16
|
+
output: 'remote-codex hook ran',
|
|
17
|
+
eventName: 'stop',
|
|
18
|
+
eventLabel: 'Stop',
|
|
19
|
+
sourcePath: '/tmp/demo/.codex/hooks.json',
|
|
20
|
+
outputEntries: [{ kind: 'warning', text: 'remote-codex hook ran' }],
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('maps Codex hook runs into provider-neutral history items', () => {
|
|
25
|
+
expect(
|
|
26
|
+
codexHookRunToHistoryItem({
|
|
27
|
+
id: 'run-1',
|
|
28
|
+
eventName: 'preToolUse',
|
|
29
|
+
handlerType: 'command',
|
|
30
|
+
executionMode: 'blocking',
|
|
31
|
+
scope: 'project',
|
|
32
|
+
sourcePath: '/tmp/demo/.codex/hooks.json',
|
|
33
|
+
source: 'project',
|
|
34
|
+
status: 'completed',
|
|
35
|
+
statusMessage: 'Checking Bash',
|
|
36
|
+
durationMs: 42,
|
|
37
|
+
outputEntries: [{ kind: 'context', text: 'allowed' }],
|
|
38
|
+
stderr: 'diagnostic',
|
|
39
|
+
}),
|
|
40
|
+
).toMatchObject({
|
|
41
|
+
id: 'hook:run-1',
|
|
42
|
+
kind: 'hook',
|
|
43
|
+
text: 'PreToolUse hook',
|
|
44
|
+
previewText: 'Checking Bash',
|
|
45
|
+
status: 'Completed',
|
|
46
|
+
hookEventName: 'preToolUse',
|
|
47
|
+
hookEventLabel: 'PreToolUse',
|
|
48
|
+
hookHandlerType: 'command',
|
|
49
|
+
hookScope: 'project',
|
|
50
|
+
hookSource: 'project',
|
|
51
|
+
hookSourcePath: '/tmp/demo/.codex/hooks.json',
|
|
52
|
+
hookStatusMessage: 'Checking Bash',
|
|
53
|
+
hookOutputEntries: [
|
|
54
|
+
{ kind: 'context', text: 'allowed' },
|
|
55
|
+
{ kind: 'warning', text: 'diagnostic' },
|
|
56
|
+
],
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -2,5 +2,12 @@ export * from './appServerManager';
|
|
|
2
2
|
export * from './historyItems';
|
|
3
3
|
export * from './hookHistory';
|
|
4
4
|
export * from './jsonrpc';
|
|
5
|
+
export * from './local-session-store';
|
|
6
|
+
export * from './management/codex-management-service';
|
|
7
|
+
export * from './management/codexHostConfig';
|
|
8
|
+
export * from './management/errors';
|
|
9
|
+
export * from './modelPricing';
|
|
10
|
+
export * from './runtime-errors';
|
|
5
11
|
export * from './runtimeAdapter';
|
|
12
|
+
export * from './thread-title';
|
|
6
13
|
export * from './types';
|