@bbigbang/agent-node 0.1.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/dist/agentHost.js +483 -0
- package/dist/appVersion.js +14 -0
- package/dist/assetCachePaths.js +35 -0
- package/dist/attachmentInput.js +588 -0
- package/dist/attachmentMaterializer.js +230 -0
- package/dist/bigbangCli.js +17 -0
- package/dist/bigbangMessageSendDetection.js +284 -0
- package/dist/builtinSkillRoots.js +54 -0
- package/dist/claudeConfig.js +32 -0
- package/dist/claudeDirectRuntime.js +1960 -0
- package/dist/claudeSessionControls.js +78 -0
- package/dist/claudeTranscriptFs.js +147 -0
- package/dist/codexAppServerClient.js +188 -0
- package/dist/codexAppServerEnv.js +14 -0
- package/dist/codexAppServerRpc.js +273 -0
- package/dist/codexAppServerRuntime.js +3495 -0
- package/dist/codexBuiltinPrompt.js +117 -0
- package/dist/codexConversationSummarizer.js +76 -0
- package/dist/codexTranscriptFs.js +145 -0
- package/dist/config.js +129 -0
- package/dist/connection.js +151 -0
- package/dist/dispatchQueueStore.js +39 -0
- package/dist/dreamEnv.js +1 -0
- package/dist/dreamMemoryFallback.js +118 -0
- package/dist/dreamToolPolicy.js +293 -0
- package/dist/droidMissionRunner.js +808 -0
- package/dist/executor.js +1078 -0
- package/dist/hostRuntime.js +1 -0
- package/dist/libraryAuthorityFs.js +74 -0
- package/dist/libraryMirror.js +183 -0
- package/dist/main.js +1659 -0
- package/dist/native-worker/native-worker.mjs +475 -0
- package/dist/nativeMissionAgentDispatch.js +463 -0
- package/dist/nativeMissionRunner.js +461 -0
- package/dist/nativeSkillMounts.js +204 -0
- package/dist/nativeWorkerHost.js +142 -0
- package/dist/nodeSink.js +142 -0
- package/dist/panelHttpFetch.js +334 -0
- package/dist/runtimeDrivers.js +62 -0
- package/dist/skillFs.js +229 -0
- package/dist/soloHost.js +165 -0
- package/dist/soloNodeSink.js +138 -0
- package/dist/terminalManager.js +254 -0
- package/dist/workspaceFs.js +1020 -0
- package/dist/workspaceGit.js +694 -0
- package/dist/workspaceInspect.js +22 -0
- package/package.json +49 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { getRuntimeDriver } from '@bbigbang/protocol';
|
|
5
|
+
import { normalizeSkillRootsWithBuiltins } from './builtinSkillRoots.js';
|
|
6
|
+
import { buildCodexAppServerInitializeParams, CodexAppServerClient } from './codexAppServerClient.js';
|
|
7
|
+
import { buildCodexAppServerChildEnv } from './codexAppServerEnv.js';
|
|
8
|
+
const TRANSIENT_REQUEST_TIMEOUT_MS = 30_000;
|
|
9
|
+
export class CodexAppServerRpc {
|
|
10
|
+
config;
|
|
11
|
+
spawnImpl;
|
|
12
|
+
constructor(params) {
|
|
13
|
+
this.config = params.config;
|
|
14
|
+
this.spawnImpl = params.spawnImpl ?? spawn;
|
|
15
|
+
}
|
|
16
|
+
async listModels(params) {
|
|
17
|
+
const workspaceRoot = this.resolveWorkspaceRoot(params.workspaceRoot);
|
|
18
|
+
return await this.withClient(workspaceRoot, async (client) => {
|
|
19
|
+
const response = await client.request('model/list', {
|
|
20
|
+
...(params.cursor ? { cursor: params.cursor } : {}),
|
|
21
|
+
...(typeof params.limit === 'number' ? { limit: params.limit } : {}),
|
|
22
|
+
...(typeof params.includeHidden === 'boolean' ? { includeHidden: params.includeHidden } : {}),
|
|
23
|
+
}, TRANSIENT_REQUEST_TIMEOUT_MS);
|
|
24
|
+
return normalizeModelListResponse(response);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async listSkills(params) {
|
|
28
|
+
const workspaceRoot = this.resolveWorkspaceRoot(params.workspaceRoot);
|
|
29
|
+
const skillRoots = normalizeSkillRootsWithBuiltins(normalizeStringArray(params.skillRoots));
|
|
30
|
+
const allowedSkillRoots = [workspaceRoot, ...skillRoots];
|
|
31
|
+
return await this.withClient(workspaceRoot, async (client) => {
|
|
32
|
+
const response = await client.request('skills/list', {
|
|
33
|
+
cwds: [workspaceRoot],
|
|
34
|
+
...(params.forceReload === true ? { forceReload: true } : {}),
|
|
35
|
+
perCwdExtraUserRoots: skillRoots.length > 0
|
|
36
|
+
? [{ cwd: workspaceRoot, extraUserRoots: skillRoots }]
|
|
37
|
+
: [],
|
|
38
|
+
}, TRANSIENT_REQUEST_TIMEOUT_MS);
|
|
39
|
+
return normalizeSkillListResponse(response, workspaceRoot, allowedSkillRoots);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async listThreads(params) {
|
|
43
|
+
const workspaceRoot = this.resolveWorkspaceRoot(params.workspaceRoot);
|
|
44
|
+
return await this.withClient(workspaceRoot, async (client) => {
|
|
45
|
+
const response = await client.request('thread/list', {
|
|
46
|
+
cwd: workspaceRoot,
|
|
47
|
+
...(params.cursor ? { cursor: params.cursor } : {}),
|
|
48
|
+
...(typeof params.limit === 'number' ? { limit: params.limit } : {}),
|
|
49
|
+
...(typeof params.archived === 'boolean' ? { archived: params.archived } : {}),
|
|
50
|
+
...(params.searchTerm ? { searchTerm: params.searchTerm } : {}),
|
|
51
|
+
...(params.useStateDbOnly === true ? { useStateDbOnly: true } : {}),
|
|
52
|
+
}, TRANSIENT_REQUEST_TIMEOUT_MS);
|
|
53
|
+
return normalizeThreadListResponse(response, workspaceRoot);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async readThread(params) {
|
|
57
|
+
const workspaceRoot = this.resolveWorkspaceRoot(params.workspaceRoot);
|
|
58
|
+
return await this.withClient(workspaceRoot, async (client) => {
|
|
59
|
+
const response = await client.request('thread/read', {
|
|
60
|
+
threadId: params.threadId,
|
|
61
|
+
includeTurns: params.includeTurns ?? true,
|
|
62
|
+
}, TRANSIENT_REQUEST_TIMEOUT_MS);
|
|
63
|
+
const result = normalizeThreadReadResponse(response);
|
|
64
|
+
if (normalizePathForCompare(result.thread.cwd) !== normalizePathForCompare(workspaceRoot)) {
|
|
65
|
+
throw new Error('Codex thread belongs to a different workspace.');
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async withClient(workspaceRoot, fn) {
|
|
71
|
+
this.assertCodexAppServerAvailable();
|
|
72
|
+
fs.mkdirSync(workspaceRoot, { recursive: true });
|
|
73
|
+
const driver = getRuntimeDriver('codex_app_server');
|
|
74
|
+
const child = this.spawnImpl(driver.command, [...driver.args], {
|
|
75
|
+
cwd: workspaceRoot,
|
|
76
|
+
env: buildCodexAppServerChildEnv(process.env, driver.defaultEnv ?? {}),
|
|
77
|
+
detached: process.platform !== 'win32',
|
|
78
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
79
|
+
});
|
|
80
|
+
const client = new CodexAppServerClient({
|
|
81
|
+
child,
|
|
82
|
+
requestTimeoutMs: TRANSIENT_REQUEST_TIMEOUT_MS,
|
|
83
|
+
});
|
|
84
|
+
try {
|
|
85
|
+
await client.request('initialize', buildCodexAppServerInitializeParams(), TRANSIENT_REQUEST_TIMEOUT_MS);
|
|
86
|
+
client.notify('initialized', {});
|
|
87
|
+
return await fn(client);
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
await client.dispose().catch(() => { });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
resolveWorkspaceRoot(workspaceRoot) {
|
|
94
|
+
const normalized = normalizeOptionalString(workspaceRoot) ?? this.config.workspaceRoot;
|
|
95
|
+
return path.resolve(normalized);
|
|
96
|
+
}
|
|
97
|
+
assertCodexAppServerAvailable() {
|
|
98
|
+
if (this.config.runtimeDrivers.some((driver) => driver.agentType === 'codex_app_server'))
|
|
99
|
+
return;
|
|
100
|
+
throw new Error('codex_app_server runtime is not available on this node.');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function normalizeModelListResponse(value) {
|
|
104
|
+
const payload = value;
|
|
105
|
+
const models = (Array.isArray(payload?.data) ? payload.data : [])
|
|
106
|
+
.map(normalizeModel)
|
|
107
|
+
.filter(Boolean);
|
|
108
|
+
const defaultModel = models.find((model) => model.isDefault)?.model ?? models[0]?.model ?? null;
|
|
109
|
+
return {
|
|
110
|
+
models,
|
|
111
|
+
nextCursor: normalizeOptionalString(payload?.nextCursor),
|
|
112
|
+
defaultModel,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function normalizeModel(value) {
|
|
116
|
+
if (!value || typeof value !== 'object')
|
|
117
|
+
return null;
|
|
118
|
+
const model = value;
|
|
119
|
+
const id = normalizeOptionalString(model.id) ?? normalizeOptionalString(model.model);
|
|
120
|
+
const modelValue = normalizeOptionalString(model.model) ?? id;
|
|
121
|
+
if (!id || !modelValue)
|
|
122
|
+
return null;
|
|
123
|
+
return {
|
|
124
|
+
id,
|
|
125
|
+
model: modelValue,
|
|
126
|
+
displayName: normalizeOptionalString(model.displayName) ?? modelValue,
|
|
127
|
+
...(normalizeOptionalString(model.description) ? { description: normalizeOptionalString(model.description) } : {}),
|
|
128
|
+
hidden: model.hidden === true,
|
|
129
|
+
supportedReasoningEfforts: normalizeReasoningEfforts(model.supportedReasoningEfforts),
|
|
130
|
+
defaultReasoningEffort: normalizeReasoningEffort(model.defaultReasoningEffort),
|
|
131
|
+
additionalSpeedTiers: normalizeStringArray(model.additionalSpeedTiers),
|
|
132
|
+
isDefault: model.isDefault === true,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function normalizeSkillListResponse(value, workspaceRoot, allowedSkillRoots) {
|
|
136
|
+
const payload = value;
|
|
137
|
+
const data = (Array.isArray(payload?.data) ? payload.data : []).map((entry) => {
|
|
138
|
+
const record = entry;
|
|
139
|
+
const cwd = normalizeOptionalString(record?.cwd) ?? '';
|
|
140
|
+
if (normalizePathForCompare(cwd) !== normalizePathForCompare(workspaceRoot)) {
|
|
141
|
+
throw new Error('Codex skills list included a different workspace.');
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
cwd,
|
|
145
|
+
skills: (Array.isArray(record?.skills) ? record.skills : [])
|
|
146
|
+
.map(normalizeSkill)
|
|
147
|
+
.filter((skill) => Boolean(skill))
|
|
148
|
+
.filter((skill) => isPathUnderAnyRoot(skill.path, allowedSkillRoots, workspaceRoot)),
|
|
149
|
+
errors: Array.isArray(record?.errors) ? record.errors : [],
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
return { data };
|
|
153
|
+
}
|
|
154
|
+
function normalizeSkill(value) {
|
|
155
|
+
if (!value || typeof value !== 'object')
|
|
156
|
+
return null;
|
|
157
|
+
const skill = value;
|
|
158
|
+
const name = normalizeOptionalString(skill.name);
|
|
159
|
+
const description = normalizeOptionalString(skill.description) ?? '';
|
|
160
|
+
const pathValue = normalizeOptionalString(skill.path);
|
|
161
|
+
if (!name || !pathValue)
|
|
162
|
+
return null;
|
|
163
|
+
return {
|
|
164
|
+
name,
|
|
165
|
+
description,
|
|
166
|
+
...(normalizeOptionalString(skill.shortDescription) ? { shortDescription: normalizeOptionalString(skill.shortDescription) } : {}),
|
|
167
|
+
path: pathValue,
|
|
168
|
+
...(normalizeOptionalString(skill.scope) ? { scope: normalizeOptionalString(skill.scope) } : {}),
|
|
169
|
+
enabled: skill.enabled !== false,
|
|
170
|
+
...('interface' in skill ? { interface: skill.interface } : {}),
|
|
171
|
+
...('dependencies' in skill ? { dependencies: skill.dependencies } : {}),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function normalizeThreadListResponse(value, workspaceRoot) {
|
|
175
|
+
const payload = value;
|
|
176
|
+
const threads = (Array.isArray(payload?.data) ? payload.data : [])
|
|
177
|
+
.map(normalizeThread)
|
|
178
|
+
.filter(Boolean);
|
|
179
|
+
if (threads.some((thread) => normalizePathForCompare(thread.cwd) !== normalizePathForCompare(workspaceRoot))) {
|
|
180
|
+
throw new Error('Codex thread list included a different workspace.');
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
threads,
|
|
184
|
+
nextCursor: normalizeOptionalString(payload?.nextCursor),
|
|
185
|
+
backwardsCursor: normalizeOptionalString(payload?.backwardsCursor),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function normalizeThreadReadResponse(value) {
|
|
189
|
+
const payload = value;
|
|
190
|
+
const thread = normalizeThread(payload?.thread);
|
|
191
|
+
if (!thread) {
|
|
192
|
+
throw new Error('Codex app-server did not return a thread.');
|
|
193
|
+
}
|
|
194
|
+
return { thread };
|
|
195
|
+
}
|
|
196
|
+
function normalizeThread(value) {
|
|
197
|
+
if (!value || typeof value !== 'object')
|
|
198
|
+
return null;
|
|
199
|
+
const thread = value;
|
|
200
|
+
const id = normalizeOptionalString(thread.id);
|
|
201
|
+
const cwd = normalizeOptionalString(thread.cwd);
|
|
202
|
+
if (!id || !cwd)
|
|
203
|
+
return null;
|
|
204
|
+
return {
|
|
205
|
+
id,
|
|
206
|
+
forkedFromId: normalizeOptionalString(thread.forkedFromId),
|
|
207
|
+
preview: normalizeOptionalString(thread.preview) ?? '',
|
|
208
|
+
createdAt: numberValue(thread.createdAt) ?? 0,
|
|
209
|
+
updatedAt: numberValue(thread.updatedAt) ?? 0,
|
|
210
|
+
status: normalizeOptionalString(thread.status) ?? 'unknown',
|
|
211
|
+
path: normalizeOptionalString(thread.path),
|
|
212
|
+
cwd,
|
|
213
|
+
...(normalizeOptionalString(thread.modelProvider) ? { modelProvider: normalizeOptionalString(thread.modelProvider) } : {}),
|
|
214
|
+
...('source' in thread ? { source: thread.source } : {}),
|
|
215
|
+
name: normalizeOptionalString(thread.name),
|
|
216
|
+
turns: Array.isArray(thread.turns) ? thread.turns : [],
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function normalizeOptionalString(value) {
|
|
220
|
+
if (typeof value !== 'string')
|
|
221
|
+
return null;
|
|
222
|
+
const normalized = value.trim();
|
|
223
|
+
return normalized ? normalized : null;
|
|
224
|
+
}
|
|
225
|
+
function normalizeStringArray(value) {
|
|
226
|
+
if (!Array.isArray(value))
|
|
227
|
+
return [];
|
|
228
|
+
return value
|
|
229
|
+
.map((item) => normalizeOptionalString(item))
|
|
230
|
+
.filter((item) => Boolean(item));
|
|
231
|
+
}
|
|
232
|
+
function normalizeReasoningEfforts(value) {
|
|
233
|
+
if (!Array.isArray(value))
|
|
234
|
+
return [];
|
|
235
|
+
return value
|
|
236
|
+
.map((item) => {
|
|
237
|
+
if (typeof item === 'string')
|
|
238
|
+
return normalizeReasoningEffort(item);
|
|
239
|
+
return normalizeReasoningEffort(item?.reasoningEffort);
|
|
240
|
+
})
|
|
241
|
+
.filter((item) => Boolean(item));
|
|
242
|
+
}
|
|
243
|
+
function normalizeReasoningEffort(value) {
|
|
244
|
+
const normalized = normalizeOptionalString(value);
|
|
245
|
+
if (normalized === 'none'
|
|
246
|
+
|| normalized === 'minimal'
|
|
247
|
+
|| normalized === 'low'
|
|
248
|
+
|| normalized === 'medium'
|
|
249
|
+
|| normalized === 'high'
|
|
250
|
+
|| normalized === 'xhigh') {
|
|
251
|
+
return normalized;
|
|
252
|
+
}
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
function numberValue(value) {
|
|
256
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
257
|
+
}
|
|
258
|
+
function normalizePathForCompare(value) {
|
|
259
|
+
return path.resolve(value);
|
|
260
|
+
}
|
|
261
|
+
function isPathUnderAnyRoot(pathValue, roots, workspaceRoot) {
|
|
262
|
+
const candidate = path.isAbsolute(pathValue)
|
|
263
|
+
? path.resolve(pathValue)
|
|
264
|
+
: path.resolve(workspaceRoot, pathValue);
|
|
265
|
+
return roots.some((root) => isPathUnderRoot(candidate, root, workspaceRoot));
|
|
266
|
+
}
|
|
267
|
+
function isPathUnderRoot(candidate, root, workspaceRoot) {
|
|
268
|
+
const resolvedRoot = path.isAbsolute(root)
|
|
269
|
+
? path.resolve(root)
|
|
270
|
+
: path.resolve(workspaceRoot, root);
|
|
271
|
+
const relative = path.relative(resolvedRoot, candidate);
|
|
272
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
273
|
+
}
|