remote-codex 0.1.10 → 0.11.1

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 (46) hide show
  1. package/apps/supervisor-api/dist/chunk-6M32PPHZ.js +24507 -0
  2. package/apps/supervisor-api/dist/chunk-7AA2MFXK.js +24499 -0
  3. package/apps/supervisor-api/dist/chunk-HKBFCPHH.js +24511 -0
  4. package/apps/supervisor-api/dist/index.js +12525 -28436
  5. package/apps/supervisor-api/dist/worker-index.d.ts +2 -0
  6. package/apps/supervisor-api/dist/worker-index.js +33 -0
  7. package/apps/supervisor-web/dist/assets/{highlighted-body-OFNGDK62-CyMcatlD.js → highlighted-body-OFNGDK62-p31aS0f0.js} +1 -1
  8. package/apps/supervisor-web/dist/assets/index-BiuFei_K.css +32 -0
  9. package/apps/supervisor-web/dist/assets/index-D1R9CUnx.js +2161 -0
  10. package/apps/supervisor-web/dist/assets/{xterm-DbYWMNQ0.js → xterm-D92BViLH.js} +1 -1
  11. package/apps/supervisor-web/dist/index.html +2 -2
  12. package/package.json +2 -3
  13. package/packages/agent-runtime/src/index.ts +4 -0
  14. package/packages/agent-runtime/src/management-errors.ts +11 -0
  15. package/packages/agent-runtime/src/model-pricing.ts +325 -0
  16. package/packages/agent-runtime/src/registry.ts +19 -4
  17. package/packages/agent-runtime/src/runtime-errors.ts +97 -0
  18. package/packages/agent-runtime/src/types.ts +36 -3
  19. package/packages/agent-runtime/src/unavailable-runtime.ts +169 -0
  20. package/packages/claude/src/historyItems.ts +41 -5
  21. package/packages/claude/src/runtimeAdapter.test.ts +117 -6
  22. package/packages/claude/src/runtimeAdapter.ts +421 -65
  23. package/packages/codex/src/historyItems.test.ts +137 -0
  24. package/packages/codex/src/historyItems.ts +135 -17
  25. package/packages/codex/src/hookHistory.test.ts +59 -0
  26. package/packages/codex/src/index.ts +7 -0
  27. package/packages/codex/src/local-session-store.ts +390 -0
  28. package/packages/codex/src/management/codex-management-service.ts +454 -0
  29. package/packages/codex/src/management/codexHostConfig.test.ts +88 -0
  30. package/packages/codex/src/management/codexHostConfig.ts +188 -0
  31. package/packages/codex/src/management/errors.ts +20 -0
  32. package/packages/codex/src/modelPricing.test.ts +235 -0
  33. package/packages/codex/src/modelPricing.ts +9 -0
  34. package/packages/codex/src/runtime-errors.test.ts +72 -0
  35. package/packages/codex/src/runtime-errors.ts +37 -0
  36. package/packages/codex/src/runtimeAdapter.ts +15 -0
  37. package/packages/codex/src/thread-title.ts +1 -0
  38. package/packages/opencode/src/historyItems.test.ts +504 -0
  39. package/packages/opencode/src/historyItems.ts +896 -0
  40. package/packages/opencode/src/index.ts +2 -0
  41. package/packages/opencode/src/runtimeAdapter.test.ts +1444 -0
  42. package/packages/opencode/src/runtimeAdapter.ts +1473 -0
  43. package/packages/shared/src/agent-providers.ts +56 -0
  44. package/packages/shared/src/index.ts +240 -35
  45. package/apps/supervisor-web/dist/assets/index-BlAhoIuq.js +0 -379
  46. package/apps/supervisor-web/dist/assets/index-DI0NRNgr.css +0 -32
@@ -0,0 +1,504 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import {
4
+ openCodeMessagesToTurns,
5
+ openCodeMessageToHistoryItems,
6
+ openCodeMessagesToPlanUpdate,
7
+ } from './historyItems';
8
+
9
+ describe('OpenCode history item mapping', () => {
10
+ it('maps projected OpenCode message kinds to timeline items', () => {
11
+ const messages = [
12
+ {
13
+ id: 'user-1',
14
+ type: 'user',
15
+ text: 'Implement the feature',
16
+ time: { created: 1_700_000_000_000 },
17
+ },
18
+ {
19
+ id: 'assistant-1',
20
+ type: 'assistant',
21
+ time: { created: 1_700_000_001_000 },
22
+ agent: 'build',
23
+ model: { id: 'gpt-5', providerID: 'openai', variant: 'default' },
24
+ content: [
25
+ { type: 'reasoning', id: 'reasoning-1', text: 'Need to inspect files.' },
26
+ { type: 'text', text: 'I will update the module.' },
27
+ {
28
+ type: 'tool',
29
+ id: 'tool-1',
30
+ name: 'bash',
31
+ state: {
32
+ status: 'completed',
33
+ input: { command: 'pnpm test' },
34
+ content: [{ type: 'text', text: 'ok' }],
35
+ structured: {},
36
+ },
37
+ },
38
+ ],
39
+ },
40
+ {
41
+ id: 'shell-1',
42
+ type: 'shell',
43
+ command: 'git status',
44
+ output: 'clean',
45
+ time: { created: 1_700_000_002_000, completed: 1_700_000_003_000 },
46
+ },
47
+ {
48
+ id: 'synthetic-1',
49
+ type: 'synthetic',
50
+ text: 'System note',
51
+ time: { created: 1_700_000_004_000 },
52
+ },
53
+ {
54
+ id: 'agent-1',
55
+ type: 'agent-switched',
56
+ agent: 'review',
57
+ time: { created: 1_700_000_005_000 },
58
+ },
59
+ {
60
+ id: 'model-1',
61
+ type: 'model-switched',
62
+ model: { id: 'claude-sonnet', providerID: 'anthropic', variant: 'default' },
63
+ time: { created: 1_700_000_006_000 },
64
+ },
65
+ {
66
+ id: 'compact-1',
67
+ type: 'compaction',
68
+ reason: 'manual',
69
+ summary: 'Summary text',
70
+ time: { created: 1_700_000_007_000 },
71
+ },
72
+ ];
73
+
74
+ const turns = openCodeMessagesToTurns(messages);
75
+ expect(turns).toHaveLength(1);
76
+ expect(turns[0]!.items.map((item) => item.kind)).toEqual([
77
+ 'userMessage',
78
+ 'reasoning',
79
+ 'agentMessage',
80
+ 'commandExecution',
81
+ 'commandExecution',
82
+ 'other',
83
+ 'other',
84
+ 'other',
85
+ 'contextCompaction',
86
+ ]);
87
+ });
88
+
89
+ it('maps tool state variants without dropping bubbles', () => {
90
+ const toolStates = ['pending', 'running', 'completed', 'error'].map((status, index) => ({
91
+ id: `assistant-${index}`,
92
+ type: 'assistant',
93
+ content: [
94
+ {
95
+ type: 'tool',
96
+ id: `tool-${index}`,
97
+ name: index === 0 ? 'read' : index === 1 ? 'web_search' : index === 2 ? 'edit' : 'custom',
98
+ state: {
99
+ status,
100
+ input: { path: 'src/index.ts', query: 'docs' },
101
+ content: [{ type: 'text', text: 'result' }],
102
+ structured: {},
103
+ error: status === 'error' ? { message: 'failed' } : undefined,
104
+ },
105
+ },
106
+ ],
107
+ }));
108
+
109
+ const items = toolStates.flatMap((message) => openCodeMessageToHistoryItems(message));
110
+ expect(items.map((item) => item.kind)).toEqual([
111
+ 'fileRead',
112
+ 'webSearch',
113
+ 'fileChange',
114
+ 'toolCall',
115
+ ]);
116
+ expect(items.map((item) => item.status)).toEqual([
117
+ 'running',
118
+ 'running',
119
+ 'completed',
120
+ 'failed',
121
+ ]);
122
+ });
123
+
124
+ it('summarizes bash tools with the command instead of the description', () => {
125
+ const items = openCodeMessageToHistoryItems({
126
+ id: 'assistant-bash',
127
+ type: 'assistant',
128
+ content: [
129
+ {
130
+ type: 'tool',
131
+ id: 'bash-1',
132
+ tool: 'bash',
133
+ state: {
134
+ status: 'completed',
135
+ input: {
136
+ command: 'npx tsx --test packages/frontend/src/tokenUsage.test.ts',
137
+ description: 'Runs TypeScript token usage tests',
138
+ timeout: 120000,
139
+ workdir: '/home/u/dev/ElAgente/graphchat',
140
+ },
141
+ output: 'ok',
142
+ },
143
+ },
144
+ ],
145
+ });
146
+
147
+ expect(items).toEqual([
148
+ expect.objectContaining({
149
+ id: 'bash-1',
150
+ kind: 'commandExecution',
151
+ text: 'npx tsx --test packages/frontend/src/tokenUsage.test.ts',
152
+ previewText: 'npx tsx --test packages/frontend/src/tokenUsage.test.ts',
153
+ }),
154
+ ]);
155
+ });
156
+
157
+ it('maps OpenCode todo tools to plan updates and apply_patch tools to useful bubbles', () => {
158
+ const message = {
159
+ id: 'assistant-tools',
160
+ type: 'assistant',
161
+ content: [
162
+ {
163
+ type: 'tool',
164
+ id: 'todo-1',
165
+ tool: 'todowrite',
166
+ state: {
167
+ status: 'completed',
168
+ input: {
169
+ todos: [
170
+ { content: 'Inspect code', status: 'in_progress', priority: 'high' },
171
+ { content: 'Patch code', status: 'pending', priority: 'high' },
172
+ ],
173
+ },
174
+ output: '[]',
175
+ title: '2 todos',
176
+ metadata: {},
177
+ },
178
+ },
179
+ {
180
+ type: 'tool',
181
+ id: 'patch-1',
182
+ name: 'apply_patch',
183
+ state: {
184
+ status: 'completed',
185
+ input: {
186
+ patchText: [
187
+ '*** Begin Patch',
188
+ '*** Update File: /tmp/project/src/index.ts',
189
+ '@@',
190
+ '+const ok = true;',
191
+ '-const ok = false;',
192
+ '*** End Patch',
193
+ ].join('\n'),
194
+ },
195
+ output: 'Success. Updated the following files:\nM src/index.ts',
196
+ title: 'Success. Updated the following files',
197
+ metadata: {
198
+ files: [
199
+ {
200
+ filePath: '/tmp/project/src/index.ts',
201
+ type: 'update',
202
+ additions: 1,
203
+ deletions: 1,
204
+ },
205
+ ],
206
+ },
207
+ },
208
+ },
209
+ ],
210
+ };
211
+ const items = openCodeMessageToHistoryItems({
212
+ ...message,
213
+ });
214
+
215
+ expect(items).toEqual([
216
+ expect.objectContaining({
217
+ id: 'patch-1',
218
+ kind: 'fileChange',
219
+ text: '/tmp/project/src/index.ts',
220
+ previewText: '/tmp/project/src/index.ts',
221
+ changedFiles: 1,
222
+ addedLines: 1,
223
+ removedLines: 1,
224
+ }),
225
+ ]);
226
+ expect(openCodeMessagesToPlanUpdate([message])).toEqual({
227
+ explanation: null,
228
+ plan: [
229
+ { step: 'Inspect code', status: 'in_progress' },
230
+ { step: 'Patch code', status: 'pending' },
231
+ ],
232
+ });
233
+ });
234
+
235
+ it('extracts file read paths and suppresses empty pending apply_patch tools', () => {
236
+ const items = openCodeMessageToHistoryItems({
237
+ id: 'assistant-read-patch',
238
+ type: 'assistant',
239
+ content: [
240
+ {
241
+ type: 'tool',
242
+ id: 'read-1',
243
+ name: 'read',
244
+ state: {
245
+ status: 'completed',
246
+ input: {
247
+ filePath: '/tmp/project/src/tokenUsage.ts',
248
+ limit: 260,
249
+ offset: 1,
250
+ },
251
+ output: '<path>/tmp/project/src/tokenUsage.ts</path>',
252
+ },
253
+ },
254
+ {
255
+ type: 'tool',
256
+ id: 'patch-pending-1',
257
+ name: 'apply_patch',
258
+ state: {
259
+ status: 'pending',
260
+ input: {},
261
+ raw: '',
262
+ },
263
+ },
264
+ ],
265
+ });
266
+
267
+ expect(items).toEqual([
268
+ expect.objectContaining({
269
+ id: 'read-1',
270
+ kind: 'fileRead',
271
+ text: '/tmp/project/src/tokenUsage.ts',
272
+ previewText: '/tmp/project/src/tokenUsage.ts',
273
+ }),
274
+ ]);
275
+ });
276
+
277
+ it('uses workspace-relative paths for file bubbles and keeps external absolute paths', () => {
278
+ const items = openCodeMessageToHistoryItems({
279
+ id: 'assistant-paths',
280
+ type: 'assistant',
281
+ content: [
282
+ {
283
+ type: 'tool',
284
+ id: 'read-in-root',
285
+ name: 'read',
286
+ state: {
287
+ status: 'completed',
288
+ input: {
289
+ filePath: '/tmp/project/src/tokenUsage.ts',
290
+ },
291
+ output: '',
292
+ },
293
+ },
294
+ {
295
+ type: 'tool',
296
+ id: 'read-outside-root',
297
+ name: 'read',
298
+ state: {
299
+ status: 'completed',
300
+ input: {
301
+ filePath: '/tmp/other/src/tokenUsage.ts',
302
+ },
303
+ output: '',
304
+ },
305
+ },
306
+ {
307
+ type: 'tool',
308
+ id: 'patch-in-root',
309
+ name: 'apply_patch',
310
+ state: {
311
+ status: 'completed',
312
+ input: {},
313
+ metadata: {
314
+ files: [
315
+ {
316
+ filePath: '/tmp/project/src/index.ts',
317
+ additions: 2,
318
+ deletions: 1,
319
+ },
320
+ ],
321
+ },
322
+ },
323
+ },
324
+ ],
325
+ }, {
326
+ workspacePath: '/tmp/project',
327
+ });
328
+
329
+ expect(items).toEqual([
330
+ expect.objectContaining({
331
+ id: 'read-in-root',
332
+ kind: 'fileRead',
333
+ text: 'src/tokenUsage.ts',
334
+ previewText: 'src/tokenUsage.ts',
335
+ }),
336
+ expect.objectContaining({
337
+ id: 'read-outside-root',
338
+ kind: 'fileRead',
339
+ text: '/tmp/other/src/tokenUsage.ts',
340
+ previewText: '/tmp/other/src/tokenUsage.ts',
341
+ }),
342
+ expect.objectContaining({
343
+ id: 'patch-in-root',
344
+ kind: 'fileChange',
345
+ text: 'src/index.ts',
346
+ previewText: 'src/index.ts',
347
+ }),
348
+ ]);
349
+ });
350
+
351
+ it('maps OpenCode SDK part variants without falling back to raw JSON', () => {
352
+ const items = openCodeMessageToHistoryItems({
353
+ id: 'assistant-parts',
354
+ type: 'assistant',
355
+ content: [
356
+ {
357
+ id: 'file-1',
358
+ type: 'file',
359
+ filename: 'src/index.ts',
360
+ mime: 'text/typescript',
361
+ url: 'file:///tmp/project/src/index.ts',
362
+ source: {
363
+ type: 'file',
364
+ path: 'src/index.ts',
365
+ text: { value: 'export {}', start: 0, end: 9 },
366
+ },
367
+ },
368
+ {
369
+ id: 'patch-part-1',
370
+ type: 'patch',
371
+ hash: 'abc',
372
+ files: ['src/index.ts', 'src/app.ts'],
373
+ },
374
+ {
375
+ id: 'step-start-1',
376
+ type: 'step-start',
377
+ },
378
+ {
379
+ id: 'step-finish-1',
380
+ type: 'step-finish',
381
+ reason: 'stop',
382
+ cost: 0.01,
383
+ tokens: {
384
+ input: 10,
385
+ output: 5,
386
+ reasoning: 2,
387
+ cache: { read: 1, write: 0 },
388
+ },
389
+ },
390
+ {
391
+ id: 'agent-1',
392
+ type: 'agent',
393
+ name: 'build',
394
+ source: { value: 'Use build agent', start: 0, end: 15 },
395
+ },
396
+ {
397
+ id: 'subtask-1',
398
+ type: 'subtask',
399
+ prompt: 'Inspect files',
400
+ description: 'Inspect repository',
401
+ agent: 'build',
402
+ },
403
+ {
404
+ id: 'retry-1',
405
+ type: 'retry',
406
+ attempt: 2,
407
+ error: { message: 'rate limited' },
408
+ time: { created: 1 },
409
+ },
410
+ {
411
+ id: 'compact-1',
412
+ type: 'compaction',
413
+ auto: true,
414
+ },
415
+ ],
416
+ });
417
+
418
+ expect(items.map((item) => item.kind)).toEqual([
419
+ 'fileRead',
420
+ 'fileChange',
421
+ 'agentToolCall',
422
+ 'agentToolCall',
423
+ 'other',
424
+ 'contextCompaction',
425
+ ]);
426
+ expect(items[0]).toMatchObject({
427
+ text: 'src/index.ts',
428
+ detailText: 'export {}',
429
+ });
430
+ expect(items[1]).toMatchObject({
431
+ text: 'src/index.ts\nsrc/app.ts',
432
+ changedFiles: 2,
433
+ });
434
+ expect(items[4]).toMatchObject({
435
+ text: 'Retry 2: rate limited',
436
+ status: 'failed',
437
+ });
438
+ });
439
+
440
+ it('maps legacy SDK message wrappers to timeline items', () => {
441
+ const turns = openCodeMessagesToTurns([
442
+ {
443
+ info: {
444
+ id: 'user-1',
445
+ role: 'user',
446
+ time: { created: 1_700_000_000_000 },
447
+ },
448
+ parts: [{ type: 'text', text: 'hi' }],
449
+ },
450
+ {
451
+ info: {
452
+ id: 'assistant-1',
453
+ role: 'assistant',
454
+ time: { created: 1_700_000_001_000, completed: 1_700_000_002_000 },
455
+ providerID: 'openai',
456
+ modelID: 'gpt-5.5',
457
+ },
458
+ parts: [
459
+ { id: 'text-1', type: 'text', text: 'hello' },
460
+ {
461
+ id: 'tool-1',
462
+ type: 'tool',
463
+ tool: 'bash',
464
+ state: {
465
+ status: 'completed',
466
+ input: { command: 'pwd' },
467
+ output: '/tmp/project',
468
+ },
469
+ },
470
+ ],
471
+ },
472
+ ]);
473
+
474
+ expect(turns).toHaveLength(1);
475
+ expect(turns[0]!.items.map((item) => item.kind)).toEqual([
476
+ 'userMessage',
477
+ 'agentMessage',
478
+ 'commandExecution',
479
+ ]);
480
+ expect(turns[0]!.items[1]).toMatchObject({
481
+ kind: 'agentMessage',
482
+ text: 'hello',
483
+ });
484
+ });
485
+
486
+ it('keeps user-only legacy turns in progress', () => {
487
+ const turns = openCodeMessagesToTurns([
488
+ {
489
+ info: {
490
+ id: 'user-1',
491
+ role: 'user',
492
+ time: { created: 1_700_000_000_000 },
493
+ },
494
+ parts: [{ type: 'text', text: 'hi' }],
495
+ },
496
+ ]);
497
+
498
+ expect(turns).toHaveLength(1);
499
+ expect(turns[0]).toMatchObject({
500
+ status: 'inProgress',
501
+ items: [{ kind: 'userMessage', text: 'hi' }],
502
+ });
503
+ });
504
+ });