@companyhelm/runner 0.0.18 → 0.0.21
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/commands/root.js
CHANGED
|
@@ -42,7 +42,6 @@ exports.isNoActiveTurnSteerError = isNoActiveTurnSteerError;
|
|
|
42
42
|
exports.isNoRunningTurnInterruptError = isNoRunningTurnInterruptError;
|
|
43
43
|
exports.normalizeThreadAgentApiUrlForRuntime = normalizeThreadAgentApiUrlForRuntime;
|
|
44
44
|
exports.extractThreadNameUpdateFromNotification = extractThreadNameUpdateFromNotification;
|
|
45
|
-
exports.extractServerMessageRequestId = extractServerMessageRequestId;
|
|
46
45
|
exports.runCommandLoop = runCommandLoop;
|
|
47
46
|
exports.isInternalDaemonChildProcess = isInternalDaemonChildProcess;
|
|
48
47
|
exports.runDetachedDaemonProcess = runDetachedDaemonProcess;
|
|
@@ -445,80 +444,6 @@ function extractThreadNameUpdateFromNotification(notification) {
|
|
|
445
444
|
normalizeNonEmptyString(params.thread_name);
|
|
446
445
|
return { sdkThreadId, threadName };
|
|
447
446
|
}
|
|
448
|
-
function isByte(value) {
|
|
449
|
-
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 255;
|
|
450
|
-
}
|
|
451
|
-
function decodeLengthDelimitedPayload(bytes) {
|
|
452
|
-
let index = 0;
|
|
453
|
-
let shift = 0;
|
|
454
|
-
let length = 0;
|
|
455
|
-
while (index < bytes.length) {
|
|
456
|
-
const current = bytes[index];
|
|
457
|
-
length |= (current & 0x7f) << shift;
|
|
458
|
-
index += 1;
|
|
459
|
-
if ((current & 0x80) === 0) {
|
|
460
|
-
break;
|
|
461
|
-
}
|
|
462
|
-
shift += 7;
|
|
463
|
-
if (shift > 28) {
|
|
464
|
-
return null;
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
if (index === 0) {
|
|
468
|
-
return null;
|
|
469
|
-
}
|
|
470
|
-
if (index + length !== bytes.length) {
|
|
471
|
-
return null;
|
|
472
|
-
}
|
|
473
|
-
return bytes.subarray(index);
|
|
474
|
-
}
|
|
475
|
-
function toUint8Array(data) {
|
|
476
|
-
if (data instanceof Uint8Array) {
|
|
477
|
-
return data;
|
|
478
|
-
}
|
|
479
|
-
if (Buffer.isBuffer(data)) {
|
|
480
|
-
return new Uint8Array(data);
|
|
481
|
-
}
|
|
482
|
-
if (Array.isArray(data) && data.every(isByte)) {
|
|
483
|
-
return Uint8Array.from(data);
|
|
484
|
-
}
|
|
485
|
-
if (data &&
|
|
486
|
-
typeof data === "object" &&
|
|
487
|
-
"type" in data &&
|
|
488
|
-
data.type === "Buffer" &&
|
|
489
|
-
"data" in data &&
|
|
490
|
-
Array.isArray(data.data)) {
|
|
491
|
-
const values = data.data;
|
|
492
|
-
if (values.every(isByte)) {
|
|
493
|
-
return Uint8Array.from(values);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
return null;
|
|
497
|
-
}
|
|
498
|
-
function extractServerMessageRequestId(serverMessage) {
|
|
499
|
-
if (!serverMessage || typeof serverMessage !== "object") {
|
|
500
|
-
return undefined;
|
|
501
|
-
}
|
|
502
|
-
const typedMessage = serverMessage;
|
|
503
|
-
if (typeof typedMessage.requestId === "string" && typedMessage.requestId.length > 0) {
|
|
504
|
-
return typedMessage.requestId;
|
|
505
|
-
}
|
|
506
|
-
if (!Array.isArray(typedMessage.$unknown)) {
|
|
507
|
-
return undefined;
|
|
508
|
-
}
|
|
509
|
-
for (const field of typedMessage.$unknown) {
|
|
510
|
-
if (field?.no !== 1 || field.wireType !== 2) {
|
|
511
|
-
continue;
|
|
512
|
-
}
|
|
513
|
-
const bytes = toUint8Array(field.data);
|
|
514
|
-
if (!bytes || bytes.length === 0) {
|
|
515
|
-
continue;
|
|
516
|
-
}
|
|
517
|
-
const payload = decodeLengthDelimitedPayload(bytes) ?? bytes;
|
|
518
|
-
return Buffer.from(payload).toString("utf8");
|
|
519
|
-
}
|
|
520
|
-
return undefined;
|
|
521
|
-
}
|
|
522
447
|
function isGrpcServiceError(error) {
|
|
523
448
|
return Boolean(error && typeof error === "object" && "code" in error);
|
|
524
449
|
}
|
|
@@ -1724,6 +1649,9 @@ async function resolveThreadAuthMode(cfg) {
|
|
|
1724
1649
|
if (!codexSdk) {
|
|
1725
1650
|
throw new Error("Codex SDK is not configured.");
|
|
1726
1651
|
}
|
|
1652
|
+
if (codexSdk.authentication === "api-key") {
|
|
1653
|
+
return "dedicated";
|
|
1654
|
+
}
|
|
1727
1655
|
if (codexSdk.authentication !== "host" && codexSdk.authentication !== "dedicated") {
|
|
1728
1656
|
throw new Error(`Unsupported Codex authentication mode '${codexSdk.authentication}' for thread creation.`);
|
|
1729
1657
|
}
|
|
@@ -2415,7 +2343,7 @@ async function handleCodexConfigurationRequest(cfg, commandChannel, request, req
|
|
|
2415
2343
|
}
|
|
2416
2344
|
async function runCommandLoop(cfg, commandChannel, commandMessageSink, apiClient, apiCallOptions, logger) {
|
|
2417
2345
|
for await (const serverMessage of commandChannel) {
|
|
2418
|
-
const requestId =
|
|
2346
|
+
const requestId = serverMessage.requestId ?? undefined;
|
|
2419
2347
|
switch (serverMessage.request.case) {
|
|
2420
2348
|
case "createThreadRequest":
|
|
2421
2349
|
await handleCreateThreadRequest(cfg, commandMessageSink, serverMessage.request.value, requestId, apiClient, apiCallOptions, logger);
|
|
@@ -40,6 +40,9 @@ exports.defaultUseDedicatedCodexAuthDependencies = {
|
|
|
40
40
|
spawnCommand: node_child_process_1.spawn,
|
|
41
41
|
spawnSyncCommand: node_child_process_1.spawnSync,
|
|
42
42
|
};
|
|
43
|
+
function isDedicatedCodexAuthentication(authentication) {
|
|
44
|
+
return authentication === "dedicated" || authentication === "api-key";
|
|
45
|
+
}
|
|
43
46
|
function resolveContainerPath(pathValue, containerHome) {
|
|
44
47
|
if (pathValue === "~") {
|
|
45
48
|
return containerHome;
|
|
@@ -279,14 +282,26 @@ async function ensureCodexRunnerStartState(cfg, overrides = {}) {
|
|
|
279
282
|
const { db, client } = await deps.initDbFn(cfg.state_db_path);
|
|
280
283
|
try {
|
|
281
284
|
const existingSdk = await db.select().from(schema_js_1.agentSdks).where((0, drizzle_orm_1.eq)(schema_js_1.agentSdks.name, "codex")).get();
|
|
285
|
+
const hostInfo = deps.getHostInfoFn(cfg.codex.codex_auth_path);
|
|
286
|
+
const dedicatedAuthPath = (0, node_path_1.join)((0, path_js_1.expandHome)(cfg.config_directory), cfg.codex.codex_auth_file_path);
|
|
287
|
+
const dedicatedAuthInfo = deps.getHostInfoFn(dedicatedAuthPath);
|
|
282
288
|
if (deps.useDedicatedAuth) {
|
|
283
|
-
if (existingSdk?.
|
|
289
|
+
if (existingSdk?.status === "configured" &&
|
|
290
|
+
isDedicatedCodexAuthentication(existingSdk.authentication) &&
|
|
291
|
+
dedicatedAuthInfo.codexAuthExists) {
|
|
284
292
|
return;
|
|
285
293
|
}
|
|
286
294
|
await setCodexUnconfiguredInDb(db);
|
|
287
295
|
return;
|
|
288
296
|
}
|
|
289
|
-
|
|
297
|
+
if (existingSdk?.status === "configured") {
|
|
298
|
+
if (existingSdk.authentication === "host" && hostInfo.codexAuthExists) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (isDedicatedCodexAuthentication(existingSdk.authentication) && dedicatedAuthInfo.codexAuthExists) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
290
305
|
if (hostInfo.codexAuthExists) {
|
|
291
306
|
deps.logInfo(`Detected Codex host auth at ${(0, path_js_1.expandHome)(cfg.codex.codex_auth_path)}; using host auth automatically.`);
|
|
292
307
|
await setCodexHostAuthInDb(db);
|
package/dist/commands/shell.js
CHANGED
|
@@ -51,16 +51,6 @@ const terminal_js_1 = require("../utils/terminal.js");
|
|
|
51
51
|
const path_js_1 = require("../utils/path.js");
|
|
52
52
|
const NON_OVERRIDABLE_DAEMON_OPTION_NAMES = new Set(["daemon", "serverUrl", "secret", "help"]);
|
|
53
53
|
const SHELL_PROMPT = "companyhelm db> ";
|
|
54
|
-
const SHELL_HELP_TEXT = [
|
|
55
|
-
"Available commands:",
|
|
56
|
-
" help Show this help.",
|
|
57
|
-
" list threads List full thread rows from the state DB.",
|
|
58
|
-
" thread status <id> Show the full thread row for one thread.",
|
|
59
|
-
" list containers List thread container fields from the state DB.",
|
|
60
|
-
" thread docker <id> Docker exec bash into the selected thread runtime container.",
|
|
61
|
-
" show daemon Show the daemon_state row from the state DB.",
|
|
62
|
-
" exit Exit the shell.",
|
|
63
|
-
].join("\n");
|
|
64
54
|
function resolveDaemonOptionValue(option, values) {
|
|
65
55
|
const explicit = values[option.name];
|
|
66
56
|
if (explicit !== undefined) {
|
|
@@ -115,6 +105,64 @@ function buildShellDaemonOverrideArgs(options, values) {
|
|
|
115
105
|
}
|
|
116
106
|
return args;
|
|
117
107
|
}
|
|
108
|
+
const SHELL_TABLES = [
|
|
109
|
+
{
|
|
110
|
+
key: "threads",
|
|
111
|
+
label: "Threads",
|
|
112
|
+
menuLabel: "List threads",
|
|
113
|
+
menuHint: "Full rows from the threads table",
|
|
114
|
+
commandAliases: ["threads", "thread"],
|
|
115
|
+
loadRows: async (db) => (await db.select().from(schema_js_1.threads).orderBy(schema_js_1.threads.id).all()),
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
key: "agent-sdks",
|
|
119
|
+
label: "Agent SDKs",
|
|
120
|
+
menuLabel: "List SDKs",
|
|
121
|
+
menuHint: "Full rows from the agent_sdks table",
|
|
122
|
+
commandAliases: ["sdks", "sdk", "agent-sdks"],
|
|
123
|
+
loadRows: async (db) => (await db.select().from(schema_js_1.agentSdks).orderBy(schema_js_1.agentSdks.name).all()),
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
key: "llm-models",
|
|
127
|
+
label: "LLM models",
|
|
128
|
+
menuLabel: "List models",
|
|
129
|
+
menuHint: "Full rows from the llm_models table",
|
|
130
|
+
commandAliases: ["models", "model", "llm-models"],
|
|
131
|
+
loadRows: async (db) => (await db.select().from(schema_js_1.llmModels).orderBy(schema_js_1.llmModels.sdkName, schema_js_1.llmModels.name).all()),
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
key: "thread-user-message-request-store",
|
|
135
|
+
label: "Thread user message request store",
|
|
136
|
+
menuLabel: "List requests",
|
|
137
|
+
menuHint: "Full rows from the thread_user_message_request_store table",
|
|
138
|
+
commandAliases: ["requests", "request", "message-requests", "user-message-requests"],
|
|
139
|
+
loadRows: async (db) => (await db.select().from(schema_js_1.threadUserMessageRequestStore).orderBy(schema_js_1.threadUserMessageRequestStore.id).all()),
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
key: "daemon-state",
|
|
143
|
+
label: "Daemon state table",
|
|
144
|
+
menuLabel: "List daemon rows",
|
|
145
|
+
menuHint: "Full rows from the daemon_state table",
|
|
146
|
+
commandAliases: ["daemon", "daemons", "daemon-state"],
|
|
147
|
+
loadRows: async (db) => (await db.select().from(schema_js_1.daemonState).orderBy(schema_js_1.daemonState.id).all()),
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
const SHELL_TABLE_BY_KEY = new Map(SHELL_TABLES.map((table) => [table.key, table]));
|
|
151
|
+
const SHELL_TABLE_BY_ALIAS = new Map(SHELL_TABLES.flatMap((table) => table.commandAliases.map((alias) => [alias, table])));
|
|
152
|
+
const SHELL_HELP_TEXT = [
|
|
153
|
+
"Available commands:",
|
|
154
|
+
" help Show this help.",
|
|
155
|
+
" list threads List full thread rows from the threads table.",
|
|
156
|
+
" list sdks List full rows from the agent_sdks table.",
|
|
157
|
+
" list models List full rows from the llm_models table.",
|
|
158
|
+
" list requests List full rows from the thread_user_message_request_store table.",
|
|
159
|
+
" list daemon List full rows from the daemon_state table.",
|
|
160
|
+
" thread status <id> Show the full thread row for one thread.",
|
|
161
|
+
" list containers List thread container fields from the state DB.",
|
|
162
|
+
" thread docker <id> Docker exec bash into the selected thread runtime container.",
|
|
163
|
+
" show daemon Show the daemon_state row from the state DB.",
|
|
164
|
+
" exit Exit the shell.",
|
|
165
|
+
].join("\n");
|
|
118
166
|
function jsonReplacer(_key, value) {
|
|
119
167
|
return typeof value === "bigint" ? value.toString() : value;
|
|
120
168
|
}
|
|
@@ -137,6 +185,9 @@ function printRow(label, row) {
|
|
|
137
185
|
console.log(JSON.stringify(row, jsonReplacer, 2));
|
|
138
186
|
console.log();
|
|
139
187
|
}
|
|
188
|
+
function resolveShellTableByAlias(alias) {
|
|
189
|
+
return SHELL_TABLE_BY_ALIAS.get(alias.toLowerCase());
|
|
190
|
+
}
|
|
140
191
|
function parseShellCommand(input) {
|
|
141
192
|
const trimmed = input.trim();
|
|
142
193
|
if (!trimmed) {
|
|
@@ -150,7 +201,16 @@ function parseShellCommand(input) {
|
|
|
150
201
|
case "?":
|
|
151
202
|
return { type: "help" };
|
|
152
203
|
case "threads":
|
|
153
|
-
return { type: "list-threads" };
|
|
204
|
+
return { type: "list-table", tableKey: "threads" };
|
|
205
|
+
case "sdks":
|
|
206
|
+
case "sdk":
|
|
207
|
+
return { type: "list-table", tableKey: "agent-sdks" };
|
|
208
|
+
case "models":
|
|
209
|
+
case "model":
|
|
210
|
+
return { type: "list-table", tableKey: "llm-models" };
|
|
211
|
+
case "requests":
|
|
212
|
+
case "request":
|
|
213
|
+
return { type: "list-table", tableKey: "thread-user-message-request-store" };
|
|
154
214
|
case "containers":
|
|
155
215
|
return { type: "list-containers" };
|
|
156
216
|
case "daemon":
|
|
@@ -163,12 +223,15 @@ function parseShellCommand(input) {
|
|
|
163
223
|
}
|
|
164
224
|
}
|
|
165
225
|
if (normalized.length === 2) {
|
|
166
|
-
if (normalized[0] === "list" && normalized[1] === "threads") {
|
|
167
|
-
return { type: "list-threads" };
|
|
168
|
-
}
|
|
169
226
|
if (normalized[0] === "list" && normalized[1] === "containers") {
|
|
170
227
|
return { type: "list-containers" };
|
|
171
228
|
}
|
|
229
|
+
if (normalized[0] === "list") {
|
|
230
|
+
const table = resolveShellTableByAlias(normalized[1]);
|
|
231
|
+
if (table) {
|
|
232
|
+
return { type: "list-table", tableKey: table.key };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
172
235
|
if (normalized[0] === "show" && normalized[1] === "daemon") {
|
|
173
236
|
return { type: "show-daemon" };
|
|
174
237
|
}
|
|
@@ -215,7 +278,7 @@ async function promptShellAction() {
|
|
|
215
278
|
const action = await p.select({
|
|
216
279
|
message: "Choose shell action",
|
|
217
280
|
options: [
|
|
218
|
-
{ value: "list-
|
|
281
|
+
{ value: "list-table", label: "Inspect runner tables", hint: "Threads, SDKs, models, requests, daemon state" },
|
|
219
282
|
{ value: "thread-status", label: "Thread status" },
|
|
220
283
|
{ value: "list-containers", label: "List containers" },
|
|
221
284
|
{ value: "thread-docker-shell", label: "Thread docker shell (bash)" },
|
|
@@ -226,6 +289,17 @@ async function promptShellAction() {
|
|
|
226
289
|
});
|
|
227
290
|
return p.isCancel(action) ? null : action;
|
|
228
291
|
}
|
|
292
|
+
async function promptShellTable() {
|
|
293
|
+
const selection = await p.select({
|
|
294
|
+
message: "Choose table to list",
|
|
295
|
+
options: SHELL_TABLES.map((table) => ({
|
|
296
|
+
value: table.key,
|
|
297
|
+
label: table.menuLabel,
|
|
298
|
+
hint: table.menuHint,
|
|
299
|
+
})),
|
|
300
|
+
});
|
|
301
|
+
return p.isCancel(selection) ? null : selection;
|
|
302
|
+
}
|
|
229
303
|
async function runClackShell(db, stateDbPath) {
|
|
230
304
|
p.intro(`CompanyHelm DB shell\n${(0, path_js_1.expandHome)(stateDbPath)}`);
|
|
231
305
|
try {
|
|
@@ -240,9 +314,14 @@ async function runClackShell(db, stateDbPath) {
|
|
|
240
314
|
case "help":
|
|
241
315
|
console.log(SHELL_HELP_TEXT);
|
|
242
316
|
break;
|
|
243
|
-
case "list-
|
|
244
|
-
|
|
317
|
+
case "list-table": {
|
|
318
|
+
const tableKey = await promptShellTable();
|
|
319
|
+
if (!tableKey) {
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
await runParsedShellCommand(db, { type: "list-table", tableKey });
|
|
245
323
|
break;
|
|
324
|
+
}
|
|
246
325
|
case "thread-status": {
|
|
247
326
|
const threadId = await selectThreadId(db, "Select thread");
|
|
248
327
|
if (!threadId) {
|
|
@@ -284,9 +363,14 @@ async function runParsedShellCommand(db, command) {
|
|
|
284
363
|
case "help":
|
|
285
364
|
console.log(SHELL_HELP_TEXT);
|
|
286
365
|
return false;
|
|
287
|
-
case "list-
|
|
288
|
-
const
|
|
289
|
-
|
|
366
|
+
case "list-table": {
|
|
367
|
+
const table = SHELL_TABLE_BY_KEY.get(command.tableKey);
|
|
368
|
+
if (!table) {
|
|
369
|
+
console.log(`Unknown table key: ${command.tableKey}`);
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
const rows = await table.loadRows(db);
|
|
373
|
+
printRows(table.label, rows);
|
|
290
374
|
return false;
|
|
291
375
|
}
|
|
292
376
|
case "thread-status": {
|
|
@@ -219,7 +219,7 @@ class AppServerContainerService {
|
|
|
219
219
|
const hostAuthPath = (0, path_js_1.expandHome)(cfg.codex.codex_auth_path);
|
|
220
220
|
const hostDedicatedAuthPath = `${(0, path_js_1.expandHome)(cfg.config_directory)}/${cfg.codex.codex_auth_file_path}`;
|
|
221
221
|
const mountArgs = [];
|
|
222
|
-
if (codexAuthMode === "dedicated") {
|
|
222
|
+
if (codexAuthMode === "dedicated" || codexAuthMode === "api-key") {
|
|
223
223
|
if (!(0, host_js_1.getHostInfo)(hostDedicatedAuthPath).codexAuthExists) {
|
|
224
224
|
throw new Error(`Dedicated Codex auth file was not found at ${hostDedicatedAuthPath}`);
|
|
225
225
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@companyhelm/runner",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"description": "Run the CompanyHelm runner in fully isolated Docker sandboxes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@bufbuild/protobuf": "^2.11.0",
|
|
34
34
|
"@clack/prompts": "^1.0.1",
|
|
35
|
-
"@companyhelm/protos": "^0.5.
|
|
35
|
+
"@companyhelm/protos": "^0.5.20",
|
|
36
36
|
"@grpc/grpc-js": "^1.14.3",
|
|
37
37
|
"@libsql/client": "^0.17.0",
|
|
38
38
|
"commander": "^14.0.0",
|