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.
- package/apps/supervisor-api/dist/chunk-6M32PPHZ.js +24507 -0
- package/apps/supervisor-api/dist/chunk-7AA2MFXK.js +24499 -0
- package/apps/supervisor-api/dist/chunk-HKBFCPHH.js +24511 -0
- package/apps/supervisor-api/dist/index.js +12525 -28436
- package/apps/supervisor-api/dist/worker-index.d.ts +2 -0
- package/apps/supervisor-api/dist/worker-index.js +33 -0
- package/apps/supervisor-web/dist/assets/{highlighted-body-OFNGDK62-CyMcatlD.js → highlighted-body-OFNGDK62-p31aS0f0.js} +1 -1
- package/apps/supervisor-web/dist/assets/index-BiuFei_K.css +32 -0
- package/apps/supervisor-web/dist/assets/index-D1R9CUnx.js +2161 -0
- package/apps/supervisor-web/dist/assets/{xterm-DbYWMNQ0.js → xterm-D92BViLH.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 +325 -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/historyItems.ts +41 -5
- package/packages/claude/src/runtimeAdapter.test.ts +117 -6
- package/packages/claude/src/runtimeAdapter.ts +421 -65
- package/packages/codex/src/historyItems.test.ts +137 -0
- package/packages/codex/src/historyItems.ts +135 -17
- 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 +235 -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 +1444 -0
- package/packages/opencode/src/runtimeAdapter.ts +1473 -0
- package/packages/shared/src/agent-providers.ts +56 -0
- package/packages/shared/src/index.ts +240 -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,169 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
agentBackendMetadata,
|
|
5
|
+
} from '../../shared/src/index';
|
|
6
|
+
import type {
|
|
7
|
+
AgentBackendInstallationDto,
|
|
8
|
+
} from '../../shared/src/index';
|
|
9
|
+
import type {
|
|
10
|
+
AgentSessionDetail,
|
|
11
|
+
AgentTurn,
|
|
12
|
+
AgentProviderId,
|
|
13
|
+
AgentProviderCapabilities,
|
|
14
|
+
AgentRuntime,
|
|
15
|
+
AgentRuntimeManagementSchema,
|
|
16
|
+
AgentRuntimeStatus,
|
|
17
|
+
InterruptAgentTurnInput,
|
|
18
|
+
ReadAgentSessionOptions,
|
|
19
|
+
ResumeAgentSessionInput,
|
|
20
|
+
StartAgentSessionInput,
|
|
21
|
+
StartAgentSessionResult,
|
|
22
|
+
StartAgentTurnInput,
|
|
23
|
+
} from './types';
|
|
24
|
+
import { AgentRuntimeError } from './types';
|
|
25
|
+
|
|
26
|
+
const unavailableCapabilities: AgentProviderCapabilities = {
|
|
27
|
+
sessions: {
|
|
28
|
+
list: false,
|
|
29
|
+
read: false,
|
|
30
|
+
resume: false,
|
|
31
|
+
importLocal: false,
|
|
32
|
+
},
|
|
33
|
+
turns: {
|
|
34
|
+
start: false,
|
|
35
|
+
streamInput: false,
|
|
36
|
+
steer: false,
|
|
37
|
+
interrupt: false,
|
|
38
|
+
compact: false,
|
|
39
|
+
},
|
|
40
|
+
branching: {
|
|
41
|
+
fork: false,
|
|
42
|
+
hardRollback: false,
|
|
43
|
+
resumeAt: false,
|
|
44
|
+
rewindFiles: false,
|
|
45
|
+
},
|
|
46
|
+
controls: {
|
|
47
|
+
planMode: false,
|
|
48
|
+
permissionRequests: false,
|
|
49
|
+
sandboxMode: false,
|
|
50
|
+
performanceMode: false,
|
|
51
|
+
goals: false,
|
|
52
|
+
},
|
|
53
|
+
management: {
|
|
54
|
+
models: false,
|
|
55
|
+
mcpStatus: false,
|
|
56
|
+
skills: false,
|
|
57
|
+
hooks: false,
|
|
58
|
+
hookTrust: false,
|
|
59
|
+
hostConfigFiles: false,
|
|
60
|
+
providerSettings: false,
|
|
61
|
+
},
|
|
62
|
+
usage: {
|
|
63
|
+
contextWindow: false,
|
|
64
|
+
tokenUsage: false,
|
|
65
|
+
costUsd: false,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const unavailableManagementSchema: AgentRuntimeManagementSchema = {
|
|
70
|
+
hostConfigFiles: [],
|
|
71
|
+
toolboxItems: [],
|
|
72
|
+
hookCommandTemplates: [],
|
|
73
|
+
providerConfigFormat: 'none',
|
|
74
|
+
mcpConfigFormat: 'none',
|
|
75
|
+
configArchives: false,
|
|
76
|
+
buildRestart: false,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export interface UnavailableRuntimeOptions {
|
|
80
|
+
provider: AgentProviderId;
|
|
81
|
+
reason: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export class UnavailableRuntimeAdapter extends EventEmitter implements AgentRuntime {
|
|
85
|
+
readonly provider: AgentProviderId;
|
|
86
|
+
readonly displayName: string;
|
|
87
|
+
readonly description: string;
|
|
88
|
+
readonly capabilities = unavailableCapabilities;
|
|
89
|
+
readonly managementSchema = unavailableManagementSchema;
|
|
90
|
+
readonly installation: AgentBackendInstallationDto;
|
|
91
|
+
|
|
92
|
+
private readonly status: AgentRuntimeStatus;
|
|
93
|
+
|
|
94
|
+
constructor(options: UnavailableRuntimeOptions) {
|
|
95
|
+
super();
|
|
96
|
+
const metadata = agentBackendMetadata[options.provider];
|
|
97
|
+
this.provider = options.provider;
|
|
98
|
+
this.displayName = metadata.displayName;
|
|
99
|
+
this.description = metadata.description;
|
|
100
|
+
this.installation = {
|
|
101
|
+
packageName: null,
|
|
102
|
+
installed: false,
|
|
103
|
+
installedVersion: null,
|
|
104
|
+
latestVersion: null,
|
|
105
|
+
installCommand: null,
|
|
106
|
+
updateCommand: null,
|
|
107
|
+
busy: false,
|
|
108
|
+
lastError: options.reason,
|
|
109
|
+
};
|
|
110
|
+
this.status = {
|
|
111
|
+
state: 'stopped',
|
|
112
|
+
transport: metadata.defaultTransport,
|
|
113
|
+
lastStartedAt: null,
|
|
114
|
+
lastError: options.reason,
|
|
115
|
+
restartCount: 0,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
getStatus(): AgentRuntimeStatus {
|
|
120
|
+
return { ...this.status };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async start() {}
|
|
124
|
+
|
|
125
|
+
async stop() {}
|
|
126
|
+
|
|
127
|
+
async listModels() {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async listSessions() {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async listLoadedSessions() {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async readSession(
|
|
140
|
+
_providerSessionId: string,
|
|
141
|
+
_options?: ReadAgentSessionOptions,
|
|
142
|
+
): Promise<AgentSessionDetail> {
|
|
143
|
+
throw this.unavailableError();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async startSession(_input: StartAgentSessionInput): Promise<StartAgentSessionResult> {
|
|
147
|
+
throw this.unavailableError();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async resumeSession(_input: ResumeAgentSessionInput): Promise<StartAgentSessionResult> {
|
|
151
|
+
throw this.unavailableError();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async startTurn(_input: StartAgentTurnInput): Promise<AgentTurn> {
|
|
155
|
+
throw this.unavailableError();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async interruptTurn(_input: InterruptAgentTurnInput): Promise<AgentTurn | null> {
|
|
159
|
+
throw this.unavailableError();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private unavailableError() {
|
|
163
|
+
return new AgentRuntimeError(
|
|
164
|
+
this.status.lastError ?? `${this.displayName} is not available.`,
|
|
165
|
+
this.provider,
|
|
166
|
+
'provider_unavailable',
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -104,6 +104,40 @@ function readableToolName(toolName: string) {
|
|
|
104
104
|
return toolName;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
function projectRelativePathLabel(value: string | null | undefined) {
|
|
108
|
+
const normalized = value?.trim();
|
|
109
|
+
if (!normalized) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const slashNormalized = normalized.replace(/\\/g, '/');
|
|
114
|
+
if (!slashNormalized.startsWith('/')) {
|
|
115
|
+
return slashNormalized.replace(/^\.\//, '');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const markers = [
|
|
119
|
+
'/apps/',
|
|
120
|
+
'/packages/',
|
|
121
|
+
'/src/',
|
|
122
|
+
'/test/',
|
|
123
|
+
'/tests/',
|
|
124
|
+
'/docs/',
|
|
125
|
+
'/config/',
|
|
126
|
+
'/scripts/',
|
|
127
|
+
'/e2e/',
|
|
128
|
+
'/.agents/',
|
|
129
|
+
'/.codex/',
|
|
130
|
+
];
|
|
131
|
+
for (const marker of markers) {
|
|
132
|
+
const markerIndex = slashNormalized.indexOf(marker);
|
|
133
|
+
if (markerIndex >= 0) {
|
|
134
|
+
return slashNormalized.slice(markerIndex + 1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return slashNormalized;
|
|
139
|
+
}
|
|
140
|
+
|
|
107
141
|
function commandFromInput(input: unknown) {
|
|
108
142
|
if (!isRecord(input)) {
|
|
109
143
|
return null;
|
|
@@ -115,11 +149,13 @@ function pathFromInput(input: unknown) {
|
|
|
115
149
|
if (!isRecord(input)) {
|
|
116
150
|
return null;
|
|
117
151
|
}
|
|
118
|
-
return (
|
|
119
|
-
stringValue(input.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
152
|
+
return projectRelativePathLabel(
|
|
153
|
+
stringValue(input.relative_path) ??
|
|
154
|
+
stringValue(input.relativePath) ??
|
|
155
|
+
stringValue(input.file_path) ??
|
|
156
|
+
stringValue(input.filePath) ??
|
|
157
|
+
stringValue(input.path) ??
|
|
158
|
+
stringValue(input.notebook_path),
|
|
123
159
|
);
|
|
124
160
|
}
|
|
125
161
|
|
|
@@ -2,17 +2,21 @@ import { describe, expect, it } from 'vitest';
|
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import type {
|
|
6
|
-
Query,
|
|
7
|
-
SDKMessage,
|
|
8
|
-
SDKSessionInfo,
|
|
9
|
-
SessionMessage,
|
|
10
|
-
} from '@anthropic-ai/claude-agent-sdk';
|
|
11
5
|
|
|
12
6
|
import { ClaudeRuntimeAdapter } from './runtimeAdapter';
|
|
13
7
|
import { hiddenInitPrompt } from './historyItems';
|
|
14
8
|
import type { AgentRuntimeEvent } from '../../agent-runtime/src/index';
|
|
15
9
|
|
|
10
|
+
type SDKMessage = Record<string, any>;
|
|
11
|
+
type SDKSessionInfo = Record<string, any>;
|
|
12
|
+
type SessionMessage = Record<string, any>;
|
|
13
|
+
interface Query extends AsyncIterable<SDKMessage> {
|
|
14
|
+
close(): void;
|
|
15
|
+
interrupt(): Promise<void>;
|
|
16
|
+
supportedModels(): Promise<any[]>;
|
|
17
|
+
mcpServerStatus(): Promise<any[]>;
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
function wait(ms = 0) {
|
|
17
21
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
22
|
}
|
|
@@ -229,6 +233,23 @@ describe('ClaudeRuntimeAdapter', () => {
|
|
|
229
233
|
expect(sdkOptions[0]?.pathToClaudeCodeExecutable).toBe('claude');
|
|
230
234
|
});
|
|
231
235
|
|
|
236
|
+
it('does not pass an empty tool list to Claude session initialization', async () => {
|
|
237
|
+
const sdkOptions: Record<string, unknown>[] = [];
|
|
238
|
+
const adapter = makeAdapter((_prompt, options) => {
|
|
239
|
+
sdkOptions.push(options);
|
|
240
|
+
return [systemInit(), result()];
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
await adapter.startSession({
|
|
244
|
+
cwd: '/tmp/workspace',
|
|
245
|
+
model: 'sonnet',
|
|
246
|
+
approvalMode: 'guarded',
|
|
247
|
+
sandboxMode: 'workspace-write',
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
expect(sdkOptions[0]).not.toHaveProperty('tools');
|
|
251
|
+
});
|
|
252
|
+
|
|
232
253
|
it('maps thread sandbox modes to Claude permission and sandbox settings', async () => {
|
|
233
254
|
const turnOptions: Record<string, unknown>[] = [];
|
|
234
255
|
const adapter = makeAdapter((_prompt, options) => {
|
|
@@ -436,6 +457,74 @@ describe('ClaudeRuntimeAdapter', () => {
|
|
|
436
457
|
});
|
|
437
458
|
});
|
|
438
459
|
|
|
460
|
+
it('keeps image blocks visible when reading Claude session history', async () => {
|
|
461
|
+
const workspace = await fs.mkdtemp(path.join(os.tmpdir(), 'claude-history-image-'));
|
|
462
|
+
const adapter = new ClaudeRuntimeAdapter({
|
|
463
|
+
home: '/tmp/claude-home',
|
|
464
|
+
command: 'claude',
|
|
465
|
+
query: (() => new FakeQuery([systemInit(), result()])) as any,
|
|
466
|
+
listSessions: (async () => [] satisfies SDKSessionInfo[]) as any,
|
|
467
|
+
getSessionInfo: (async () => ({
|
|
468
|
+
sessionId: 'claude-session-1',
|
|
469
|
+
summary: 'Existing session',
|
|
470
|
+
lastModified: 1_772_000_000_000,
|
|
471
|
+
createdAt: 1_771_000_000_000,
|
|
472
|
+
cwd: workspace,
|
|
473
|
+
})) as any,
|
|
474
|
+
getSessionMessages: (async () => [
|
|
475
|
+
{
|
|
476
|
+
type: 'user',
|
|
477
|
+
uuid: '019e4657-bd3c-72d1-b59d-324ed8a4b1ec',
|
|
478
|
+
session_id: 'claude-session-1',
|
|
479
|
+
message: {
|
|
480
|
+
role: 'user',
|
|
481
|
+
content: [
|
|
482
|
+
{ type: 'text', text: 'What number is in the screenshot? ' },
|
|
483
|
+
{
|
|
484
|
+
type: 'image',
|
|
485
|
+
source: {
|
|
486
|
+
type: 'base64',
|
|
487
|
+
media_type: 'image/png',
|
|
488
|
+
data: 'ZmFrZS1wbmc=',
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
],
|
|
492
|
+
},
|
|
493
|
+
parent_tool_use_id: null,
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
type: 'assistant',
|
|
497
|
+
uuid: '019e4657-bd3c-72d1-b59d-324ed8a4b1ed',
|
|
498
|
+
session_id: 'claude-session-1',
|
|
499
|
+
message: {
|
|
500
|
+
role: 'assistant',
|
|
501
|
+
content: [{ type: 'text', text: 'The number is 9.' }],
|
|
502
|
+
},
|
|
503
|
+
parent_tool_use_id: null,
|
|
504
|
+
},
|
|
505
|
+
] satisfies SessionMessage[]) as any,
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
const session = await adapter.readSession('claude-session-1', {
|
|
509
|
+
localThreadId: 'thread-1',
|
|
510
|
+
workspacePath: workspace,
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
expect(session.turns[0]?.items[0]).toMatchObject({
|
|
514
|
+
kind: 'userMessage',
|
|
515
|
+
text: 'What number is in the screenshot? \n[PHOTO ./.temp/threads/thread-1/claude-history-019e4657-bd3c-72d1-b59d-324ed8a4b1ec-1.png]',
|
|
516
|
+
});
|
|
517
|
+
await expect(
|
|
518
|
+
fs.readFile(
|
|
519
|
+
path.join(
|
|
520
|
+
workspace,
|
|
521
|
+
'.temp/threads/thread-1/claude-history-019e4657-bd3c-72d1-b59d-324ed8a4b1ec-1.png',
|
|
522
|
+
),
|
|
523
|
+
'utf8',
|
|
524
|
+
),
|
|
525
|
+
).resolves.toBe('fake-png');
|
|
526
|
+
});
|
|
527
|
+
|
|
439
528
|
it('starts a session from the Claude init message and hides the synthetic prompt', async () => {
|
|
440
529
|
const adapter = makeAdapter((prompt) => {
|
|
441
530
|
expect(prompt).toBe(hiddenInitPrompt());
|
|
@@ -1933,6 +2022,16 @@ describe('ClaudeRuntimeAdapter', () => {
|
|
|
1933
2022
|
file_path: 'packages/claude/src/runtimeAdapter.ts',
|
|
1934
2023
|
},
|
|
1935
2024
|
},
|
|
2025
|
+
{
|
|
2026
|
+
type: 'tool_use',
|
|
2027
|
+
id: 'toolu_edit',
|
|
2028
|
+
name: 'Edit',
|
|
2029
|
+
input: {
|
|
2030
|
+
file_path: '/home/u/dev/remoteCodex/apps/supervisor-api/src/thread-service.ts',
|
|
2031
|
+
old_string: 'before',
|
|
2032
|
+
new_string: 'after',
|
|
2033
|
+
},
|
|
2034
|
+
},
|
|
1936
2035
|
{
|
|
1937
2036
|
type: 'tool_use',
|
|
1938
2037
|
id: 'toolu_skill',
|
|
@@ -1980,6 +2079,11 @@ describe('ClaudeRuntimeAdapter', () => {
|
|
|
1980
2079
|
tool_use_id: 'toolu_read',
|
|
1981
2080
|
content: 'export class ClaudeRuntimeAdapter {}',
|
|
1982
2081
|
},
|
|
2082
|
+
{
|
|
2083
|
+
type: 'tool_result',
|
|
2084
|
+
tool_use_id: 'toolu_edit',
|
|
2085
|
+
content: 'File updated.',
|
|
2086
|
+
},
|
|
1983
2087
|
{
|
|
1984
2088
|
type: 'tool_result',
|
|
1985
2089
|
tool_use_id: 'toolu_skill',
|
|
@@ -2025,6 +2129,13 @@ describe('ClaudeRuntimeAdapter', () => {
|
|
|
2025
2129
|
text: 'Read file: packages/claude/src/runtimeAdapter.ts',
|
|
2026
2130
|
status: 'completed',
|
|
2027
2131
|
}),
|
|
2132
|
+
expect.objectContaining({
|
|
2133
|
+
id: 'toolu_edit',
|
|
2134
|
+
kind: 'fileChange',
|
|
2135
|
+
text: 'apps/supervisor-api/src/thread-service.ts',
|
|
2136
|
+
previewText: 'Edit file: apps/supervisor-api/src/thread-service.ts',
|
|
2137
|
+
status: 'completed',
|
|
2138
|
+
}),
|
|
2028
2139
|
expect.objectContaining({
|
|
2029
2140
|
id: 'toolu_skill',
|
|
2030
2141
|
kind: 'skillToolCall',
|