@companyhelm/runner 0.0.15 → 0.0.18
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/register-commands.js +5 -0
- package/dist/commands/root.js +16 -8
- package/dist/commands/runner/start.js +23 -21
- package/dist/commands/sdk/codex/auth.js +103 -13
- package/dist/commands/sdk/codex/use-dedicated-auth.js +1 -0
- package/dist/commands/sdk/codex/use-host-auth.js +1 -0
- package/dist/commands/startup.js +1 -0
- package/dist/service/docker/app_server_container.js +7 -0
- package/dist/service/thread_lifecycle.js +1 -1
- package/package.json +2 -1
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerCommands = registerCommands;
|
|
4
|
+
const common_js_1 = require("./runner/common.js");
|
|
4
5
|
const register_runner_commands_js_1 = require("./runner/register-runner-commands.js");
|
|
6
|
+
const start_js_1 = require("./runner/start.js");
|
|
5
7
|
const shell_js_1 = require("./shell.js");
|
|
6
8
|
const register_sdk_commands_js_1 = require("./sdk/register-sdk-commands.js");
|
|
7
9
|
const status_js_1 = require("./status.js");
|
|
8
10
|
const register_thread_commands_js_1 = require("./thread/register-thread-commands.js");
|
|
9
11
|
function registerCommands(program) {
|
|
12
|
+
(0, common_js_1.addRunnerStartOptions)(program
|
|
13
|
+
.command("companyhelm-runner")
|
|
14
|
+
.description("Alias for starting the local CompanyHelm runner.")).action(start_js_1.runRunnerStartCommand);
|
|
10
15
|
(0, register_runner_commands_js_1.registerRunnerCommands)(program);
|
|
11
16
|
(0, status_js_1.registerStatusCommand)(program);
|
|
12
17
|
(0, register_thread_commands_js_1.registerThreadCommands)(program);
|
package/dist/commands/root.js
CHANGED
|
@@ -1661,15 +1661,17 @@ async function countSdkModels(cfg, sdkName) {
|
|
|
1661
1661
|
client.close();
|
|
1662
1662
|
}
|
|
1663
1663
|
}
|
|
1664
|
-
async function
|
|
1664
|
+
async function loadCodexSdkState(cfg) {
|
|
1665
1665
|
const { db, client } = await (0, db_js_1.initDb)(cfg.state_db_path);
|
|
1666
|
-
let codexSdk;
|
|
1667
1666
|
try {
|
|
1668
|
-
|
|
1667
|
+
return await db.select().from(schema_js_1.agentSdks).where((0, drizzle_orm_1.eq)(schema_js_1.agentSdks.name, "codex")).get() ?? undefined;
|
|
1669
1668
|
}
|
|
1670
1669
|
finally {
|
|
1671
1670
|
client.close();
|
|
1672
1671
|
}
|
|
1672
|
+
}
|
|
1673
|
+
async function refreshCodexModelsForRegistration(cfg, logger) {
|
|
1674
|
+
const codexSdk = await loadCodexSdkState(cfg);
|
|
1673
1675
|
if (!codexSdk || codexSdk.status !== "configured" || codexSdk.authentication === "unauthenticated") {
|
|
1674
1676
|
logger.info("Codex is not configured; registering runner with unconfigured Codex SDK state.");
|
|
1675
1677
|
return null;
|
|
@@ -2004,18 +2006,18 @@ async function deleteThreadWithCleanup(cfg, request) {
|
|
|
2004
2006
|
}
|
|
2005
2007
|
return { kind: "deleted" };
|
|
2006
2008
|
}
|
|
2007
|
-
async function handleDeleteThreadRequest(cfg, commandChannel, request, logger) {
|
|
2009
|
+
async function handleDeleteThreadRequest(cfg, commandChannel, request, requestId, logger) {
|
|
2008
2010
|
const deleteResult = await deleteThreadWithCleanup(cfg, request);
|
|
2009
2011
|
if (deleteResult.kind === "not_found") {
|
|
2010
2012
|
logger.warn(`Delete requested for missing thread '${request.threadId}'. Treating as deleted.`);
|
|
2011
|
-
await sendThreadUpdate(commandChannel, request.threadId, protos_1.ThreadStatus.DELETED);
|
|
2013
|
+
await sendThreadUpdate(commandChannel, request.threadId, protos_1.ThreadStatus.DELETED, requestId);
|
|
2012
2014
|
return;
|
|
2013
2015
|
}
|
|
2014
2016
|
if (deleteResult.kind === "error") {
|
|
2015
|
-
await sendRequestError(commandChannel, deleteResult.message);
|
|
2017
|
+
await sendRequestError(commandChannel, deleteResult.message, requestId);
|
|
2016
2018
|
return;
|
|
2017
2019
|
}
|
|
2018
|
-
await sendThreadUpdate(commandChannel, request.threadId, protos_1.ThreadStatus.DELETED);
|
|
2020
|
+
await sendThreadUpdate(commandChannel, request.threadId, protos_1.ThreadStatus.DELETED, requestId);
|
|
2019
2021
|
}
|
|
2020
2022
|
async function reportNoRunningInterruptAsReady(cfg, commandChannel, request, threadState, logger, logMessage) {
|
|
2021
2023
|
try {
|
|
@@ -2394,6 +2396,12 @@ async function handleCodexConfigurationRequest(cfg, commandChannel, request, req
|
|
|
2394
2396
|
await sendRequestError(commandChannel, "Unsupported Codex auth type.", requestId);
|
|
2395
2397
|
return;
|
|
2396
2398
|
}
|
|
2399
|
+
const codexSdk = await loadCodexSdkState(cfg);
|
|
2400
|
+
if (!codexSdk || codexSdk.status !== "configured" || codexSdk.authentication === "unauthenticated") {
|
|
2401
|
+
const sdkUpdate = await buildCodexAgentSdkUpdate(cfg, logger, protos_1.AgentSdkStatus.UNCONFIGURED);
|
|
2402
|
+
await sendAgentSdkUpdate(commandChannel, sdkUpdate, requestId);
|
|
2403
|
+
return;
|
|
2404
|
+
}
|
|
2397
2405
|
const codexRefreshErrorMessage = await refreshCodexModelsForRegistration(cfg, logger);
|
|
2398
2406
|
const sdkUpdate = await buildCodexAgentSdkUpdate(cfg, logger, codexRefreshErrorMessage ? protos_1.AgentSdkStatus.ERROR : protos_1.AgentSdkStatus.READY, codexRefreshErrorMessage ?? undefined);
|
|
2399
2407
|
await sendAgentSdkUpdate(commandChannel, sdkUpdate, requestId);
|
|
@@ -2413,7 +2421,7 @@ async function runCommandLoop(cfg, commandChannel, commandMessageSink, apiClient
|
|
|
2413
2421
|
await handleCreateThreadRequest(cfg, commandMessageSink, serverMessage.request.value, requestId, apiClient, apiCallOptions, logger);
|
|
2414
2422
|
break;
|
|
2415
2423
|
case "deleteThreadRequest":
|
|
2416
|
-
await handleDeleteThreadRequest(cfg, commandMessageSink, serverMessage.request.value, logger);
|
|
2424
|
+
await handleDeleteThreadRequest(cfg, commandMessageSink, serverMessage.request.value, requestId, logger);
|
|
2417
2425
|
break;
|
|
2418
2426
|
case "createUserMessageRequest":
|
|
2419
2427
|
void handleCreateUserMessageRequest(cfg, commandMessageSink, serverMessage.request.value, requestId, logger).catch((error) => {
|
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runRunnerStartCommand = runRunnerStartCommand;
|
|
3
4
|
exports.registerRunnerStartCommand = registerRunnerStartCommand;
|
|
4
5
|
const root_js_1 = require("../root.js");
|
|
5
6
|
const common_js_1 = require("./common.js");
|
|
7
|
+
async function runRunnerStartCommand(options) {
|
|
8
|
+
if (options.daemon && !(0, root_js_1.isInternalDaemonChildProcess)()) {
|
|
9
|
+
await (0, root_js_1.runDetachedDaemonProcess)(options);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
await (0, root_js_1.runRootCommand)(options, (0, root_js_1.isInternalDaemonChildProcess)()
|
|
14
|
+
? {
|
|
15
|
+
onDaemonReady: () => {
|
|
16
|
+
(0, root_js_1.sendDaemonParentMessage)({ type: "daemon-ready" });
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
: undefined);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
if ((0, root_js_1.isInternalDaemonChildProcess)()) {
|
|
23
|
+
(0, root_js_1.sendDaemonParentMessage)({ type: "daemon-error", message: (0, root_js_1.toErrorMessage)(error) });
|
|
24
|
+
}
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
6
28
|
function registerRunnerStartCommand(runnerCommand) {
|
|
7
29
|
(0, common_js_1.addRunnerStartOptions)(runnerCommand
|
|
8
30
|
.command("start")
|
|
9
|
-
.description("Start the local CompanyHelm runner daemon.")).action(
|
|
10
|
-
if (options.daemon && !(0, root_js_1.isInternalDaemonChildProcess)()) {
|
|
11
|
-
await (0, root_js_1.runDetachedDaemonProcess)(options);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
try {
|
|
15
|
-
await (0, root_js_1.runRootCommand)(options, (0, root_js_1.isInternalDaemonChildProcess)()
|
|
16
|
-
? {
|
|
17
|
-
onDaemonReady: () => {
|
|
18
|
-
(0, root_js_1.sendDaemonParentMessage)({ type: "daemon-ready" });
|
|
19
|
-
},
|
|
20
|
-
}
|
|
21
|
-
: undefined);
|
|
22
|
-
}
|
|
23
|
-
catch (error) {
|
|
24
|
-
if ((0, root_js_1.isInternalDaemonChildProcess)()) {
|
|
25
|
-
(0, root_js_1.sendDaemonParentMessage)({ type: "daemon-error", message: (0, root_js_1.toErrorMessage)(error) });
|
|
26
|
-
}
|
|
27
|
-
throw error;
|
|
28
|
-
}
|
|
29
|
-
});
|
|
31
|
+
.description("Start the local CompanyHelm runner daemon.")).action(runRunnerStartCommand);
|
|
30
32
|
}
|
|
@@ -40,12 +40,90 @@ exports.defaultUseDedicatedCodexAuthDependencies = {
|
|
|
40
40
|
spawnCommand: node_child_process_1.spawn,
|
|
41
41
|
spawnSyncCommand: node_child_process_1.spawnSync,
|
|
42
42
|
};
|
|
43
|
+
function resolveContainerPath(pathValue, containerHome) {
|
|
44
|
+
if (pathValue === "~") {
|
|
45
|
+
return containerHome;
|
|
46
|
+
}
|
|
47
|
+
if (pathValue.startsWith("~/")) {
|
|
48
|
+
return `${containerHome}${pathValue.slice(1)}`;
|
|
49
|
+
}
|
|
50
|
+
return pathValue;
|
|
51
|
+
}
|
|
52
|
+
function shellQuote(value) {
|
|
53
|
+
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
54
|
+
}
|
|
55
|
+
function buildCodexLoginShellCommand(cfg, loginCommand) {
|
|
56
|
+
const hostInfo = (0, host_js_1.getHostInfo)(cfg.codex.codex_auth_path);
|
|
57
|
+
const containerAuthPath = resolveContainerPath(cfg.codex.codex_auth_path, cfg.agent_home_directory);
|
|
58
|
+
return [
|
|
59
|
+
`AGENT_USER=${shellQuote(cfg.agent_user)}`,
|
|
60
|
+
`AGENT_HOME=${shellQuote(cfg.agent_home_directory)}`,
|
|
61
|
+
`AGENT_UID=${shellQuote(String(hostInfo.uid))}`,
|
|
62
|
+
`AGENT_GID=${shellQuote(String(hostInfo.gid))}`,
|
|
63
|
+
`CODEX_AUTH_PATH=${shellQuote(containerAuthPath)}`,
|
|
64
|
+
`CODEX_LOGIN_COMMAND=${shellQuote(`source "$NVM_DIR/nvm.sh"; ${loginCommand}`)}`,
|
|
65
|
+
'EXISTING_UID_USER=""',
|
|
66
|
+
'if getent passwd "$AGENT_UID" >/dev/null 2>&1; then',
|
|
67
|
+
' EXISTING_UID_USER="$(getent passwd "$AGENT_UID" | cut -d: -f1)"',
|
|
68
|
+
' AGENT_USER="$EXISTING_UID_USER"',
|
|
69
|
+
'fi',
|
|
70
|
+
'AGENT_GROUP="$AGENT_USER"',
|
|
71
|
+
'if getent group "$AGENT_GID" >/dev/null 2>&1; then',
|
|
72
|
+
' AGENT_GROUP="$(getent group "$AGENT_GID" | cut -d: -f1)"',
|
|
73
|
+
'elif getent group "$AGENT_USER" >/dev/null 2>&1; then',
|
|
74
|
+
' groupmod -g "$AGENT_GID" "$AGENT_USER"',
|
|
75
|
+
' AGENT_GROUP="$AGENT_USER"',
|
|
76
|
+
'else',
|
|
77
|
+
' groupadd -g "$AGENT_GID" "$AGENT_USER"',
|
|
78
|
+
' AGENT_GROUP="$AGENT_USER"',
|
|
79
|
+
'fi',
|
|
80
|
+
'if id -u "$AGENT_USER" >/dev/null 2>&1; then',
|
|
81
|
+
' usermod -u "$AGENT_UID" -g "$AGENT_GROUP" -d "$AGENT_HOME" -s /bin/bash "$AGENT_USER" || true',
|
|
82
|
+
'else',
|
|
83
|
+
' useradd -m -d "$AGENT_HOME" -u "$AGENT_UID" -g "$AGENT_GROUP" -s /bin/bash "$AGENT_USER"',
|
|
84
|
+
'fi',
|
|
85
|
+
'mkdir -p "$AGENT_HOME" "$(dirname "$CODEX_AUTH_PATH")"',
|
|
86
|
+
'chown -R "$AGENT_UID:$AGENT_GID" "$AGENT_HOME" "$(dirname "$CODEX_AUTH_PATH")" || true',
|
|
87
|
+
'export HOME="$AGENT_HOME"',
|
|
88
|
+
'exec sudo -n -E -H -u "$AGENT_USER" bash -lc "$CODEX_LOGIN_COMMAND"',
|
|
89
|
+
].join("\n");
|
|
90
|
+
}
|
|
43
91
|
function isErrnoException(error) {
|
|
44
92
|
return error instanceof Error && "code" in error;
|
|
45
93
|
}
|
|
46
94
|
function buildDockerMissingError() {
|
|
47
95
|
return new Error("Docker is not installed or not available on PATH. Install Docker and retry.");
|
|
48
96
|
}
|
|
97
|
+
function readSpawnSyncText(output) {
|
|
98
|
+
if (typeof output === "string") {
|
|
99
|
+
return output.trim();
|
|
100
|
+
}
|
|
101
|
+
if (Buffer.isBuffer(output)) {
|
|
102
|
+
return output.toString("utf8").trim();
|
|
103
|
+
}
|
|
104
|
+
return "";
|
|
105
|
+
}
|
|
106
|
+
function describeSpawnSyncFailure(command, args, result) {
|
|
107
|
+
if (isErrnoException(result.error)) {
|
|
108
|
+
return `${command} ${args.join(" ")} failed to start: ${result.error.message}`;
|
|
109
|
+
}
|
|
110
|
+
const parts = [`${command} ${args.join(" ")}`];
|
|
111
|
+
if (typeof result.status === "number") {
|
|
112
|
+
parts.push(`exit code ${result.status}`);
|
|
113
|
+
}
|
|
114
|
+
if (result.signal) {
|
|
115
|
+
parts.push(`signal ${result.signal}`);
|
|
116
|
+
}
|
|
117
|
+
const stderr = readSpawnSyncText(result.stderr);
|
|
118
|
+
if (stderr.length > 0) {
|
|
119
|
+
parts.push(`stderr: ${stderr}`);
|
|
120
|
+
}
|
|
121
|
+
const stdout = readSpawnSyncText(result.stdout);
|
|
122
|
+
if (stdout.length > 0) {
|
|
123
|
+
parts.push(`stdout: ${stdout}`);
|
|
124
|
+
}
|
|
125
|
+
return parts.join(", ");
|
|
126
|
+
}
|
|
49
127
|
function ensureDockerAvailable(spawnSyncCommand) {
|
|
50
128
|
const result = spawnSyncCommand("docker", ["--version"], { stdio: "ignore" });
|
|
51
129
|
if (isErrnoException(result.error) && result.error.code === "ENOENT") {
|
|
@@ -64,9 +142,10 @@ async function runContainerizedCodexLogin(cfg, deps, options) {
|
|
|
64
142
|
(0, node_fs_1.mkdirSync)(configDir, { recursive: true });
|
|
65
143
|
}
|
|
66
144
|
const destPath = (0, node_path_1.join)(configDir, cfg.codex.codex_auth_file_path);
|
|
67
|
-
const containerAuthPath = cfg.codex.codex_auth_path;
|
|
145
|
+
const containerAuthPath = resolveContainerPath(cfg.codex.codex_auth_path, cfg.agent_home_directory);
|
|
68
146
|
let authCopied = false;
|
|
69
147
|
let combinedOutput = "";
|
|
148
|
+
let lastCopyFailure = null;
|
|
70
149
|
await new Promise((resolve, reject) => {
|
|
71
150
|
let settled = false;
|
|
72
151
|
let poll;
|
|
@@ -77,19 +156,17 @@ async function runContainerizedCodexLogin(cfg, deps, options) {
|
|
|
77
156
|
deps.spawnSyncCommand("docker", ["rm", "-f", options.containerName], { stdio: "ignore" });
|
|
78
157
|
};
|
|
79
158
|
const tryCopyAuthFile = () => {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
const cpResult = deps.spawnSyncCommand("docker", ["cp", `${options.containerName}:${containerAuthPath}`, destPath], {
|
|
87
|
-
stdio: "ignore",
|
|
159
|
+
const cpArgs = ["cp", `${options.containerName}:${containerAuthPath}`, destPath];
|
|
160
|
+
const cpResult = deps.spawnSyncCommand("docker", cpArgs, {
|
|
161
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
162
|
+
encoding: "utf8",
|
|
88
163
|
});
|
|
89
164
|
if (cpResult.status !== 0) {
|
|
165
|
+
lastCopyFailure = describeSpawnSyncFailure("docker", cpArgs, cpResult);
|
|
90
166
|
return false;
|
|
91
167
|
}
|
|
92
168
|
authCopied = true;
|
|
169
|
+
lastCopyFailure = null;
|
|
93
170
|
cleanup();
|
|
94
171
|
return true;
|
|
95
172
|
};
|
|
@@ -141,7 +218,14 @@ async function runContainerizedCodexLogin(cfg, deps, options) {
|
|
|
141
218
|
resolveOnce();
|
|
142
219
|
return;
|
|
143
220
|
}
|
|
144
|
-
|
|
221
|
+
const details = [];
|
|
222
|
+
if (lastCopyFailure) {
|
|
223
|
+
details.push(`Auth file copy failed from ${containerAuthPath}: ${lastCopyFailure}`);
|
|
224
|
+
}
|
|
225
|
+
if (combinedOutput.trim().length > 0) {
|
|
226
|
+
details.push(`Output: ${combinedOutput.trim()}`);
|
|
227
|
+
}
|
|
228
|
+
rejectOnce(new Error(`Codex login failed or was cancelled.${details.length > 0 ? ` ${details.join(" ")}` : ""}`));
|
|
145
229
|
});
|
|
146
230
|
});
|
|
147
231
|
return destPath;
|
|
@@ -232,6 +316,8 @@ async function runSetCodexHostAuth(cfg, overrides = {}) {
|
|
|
232
316
|
}
|
|
233
317
|
async function runDedicatedCodexAuth(cfg, db, deps) {
|
|
234
318
|
const containerName = `companyhelm-codex-auth-${Date.now()}`;
|
|
319
|
+
ensureDockerAvailable(deps.spawnSyncCommand);
|
|
320
|
+
const loginCommand = buildCodexLoginShellCommand(cfg, "codex login --device-auth");
|
|
235
321
|
deps.logInfo("Starting Codex login inside a container...");
|
|
236
322
|
deps.logInfo("A browser URL and device code will appear -- open it to complete authentication.");
|
|
237
323
|
const destPath = await runContainerizedCodexLogin(cfg, deps, {
|
|
@@ -244,7 +330,7 @@ async function runDedicatedCodexAuth(cfg, db, deps) {
|
|
|
244
330
|
"bash",
|
|
245
331
|
cfg.runtime_image,
|
|
246
332
|
"-lc",
|
|
247
|
-
|
|
333
|
+
loginCommand,
|
|
248
334
|
],
|
|
249
335
|
});
|
|
250
336
|
await setCodexDedicatedAuthInDb(db);
|
|
@@ -257,6 +343,8 @@ async function runCodexApiKeyAuth(cfg, apiKey, overrides = {}) {
|
|
|
257
343
|
try {
|
|
258
344
|
deps.logInfo("Starting Codex API key login inside a container...");
|
|
259
345
|
const containerName = `companyhelm-codex-auth-${Date.now()}`;
|
|
346
|
+
ensureDockerAvailable(deps.spawnSyncCommand);
|
|
347
|
+
const loginCommand = buildCodexLoginShellCommand(cfg, 'printf \'%s\\n\' "$CODEX_API_KEY" | codex login --with-api-key');
|
|
260
348
|
const destPath = await runContainerizedCodexLogin(cfg, deps, {
|
|
261
349
|
containerName,
|
|
262
350
|
dockerArgs: [
|
|
@@ -269,7 +357,7 @@ async function runCodexApiKeyAuth(cfg, apiKey, overrides = {}) {
|
|
|
269
357
|
"bash",
|
|
270
358
|
cfg.runtime_image,
|
|
271
359
|
"-lc",
|
|
272
|
-
|
|
360
|
+
loginCommand,
|
|
273
361
|
],
|
|
274
362
|
});
|
|
275
363
|
await setCodexApiKeyAuthInDb(db);
|
|
@@ -288,6 +376,8 @@ async function runCodexDeviceCodeAuth(cfg, onDeviceCode, overrides = {}) {
|
|
|
288
376
|
let onDeviceCodePromise = Promise.resolve();
|
|
289
377
|
deps.logInfo("Starting Codex device login inside a container...");
|
|
290
378
|
const containerName = `companyhelm-codex-auth-${Date.now()}`;
|
|
379
|
+
ensureDockerAvailable(deps.spawnSyncCommand);
|
|
380
|
+
const loginCommand = buildCodexLoginShellCommand(cfg, "codex login --device-auth");
|
|
291
381
|
const destPath = await runContainerizedCodexLogin(cfg, deps, {
|
|
292
382
|
containerName,
|
|
293
383
|
dockerArgs: [
|
|
@@ -298,7 +388,7 @@ async function runCodexDeviceCodeAuth(cfg, onDeviceCode, overrides = {}) {
|
|
|
298
388
|
"bash",
|
|
299
389
|
cfg.runtime_image,
|
|
300
390
|
"-lc",
|
|
301
|
-
|
|
391
|
+
loginCommand,
|
|
302
392
|
],
|
|
303
393
|
onOutput: (output) => {
|
|
304
394
|
const deviceCode = extractCodexDeviceCodeFromOutput(output);
|
|
@@ -5,6 +5,7 @@ exports.registerSdkCodexUseDedicatedAuthCommand = registerSdkCodexUseDedicatedAu
|
|
|
5
5
|
const config_js_1 = require("../../../config.js");
|
|
6
6
|
const auth_js_1 = require("./auth.js");
|
|
7
7
|
async function runSdkCodexUseDedicatedAuthCommand(cfg = config_js_1.config.parse({}), overrides = {}) {
|
|
8
|
+
cfg = config_js_1.config.parse(cfg);
|
|
8
9
|
const deps = { ...auth_js_1.defaultUseDedicatedCodexAuthDependencies, ...overrides };
|
|
9
10
|
await (0, auth_js_1.runUseDedicatedCodexAuth)(cfg, deps);
|
|
10
11
|
}
|
|
@@ -5,6 +5,7 @@ exports.registerSdkCodexUseHostAuthCommand = registerSdkCodexUseHostAuthCommand;
|
|
|
5
5
|
const config_js_1 = require("../../../config.js");
|
|
6
6
|
const auth_js_1 = require("./auth.js");
|
|
7
7
|
async function runSdkCodexUseHostAuthCommand(cfg = config_js_1.config.parse({}), overrides = {}) {
|
|
8
|
+
cfg = config_js_1.config.parse(cfg);
|
|
8
9
|
const deps = { ...auth_js_1.defaultSetCodexHostAuthDependencies, ...overrides };
|
|
9
10
|
const authPath = await (0, auth_js_1.runSetCodexHostAuth)(cfg, deps);
|
|
10
11
|
console.log(`Codex SDK configured with host authentication using ${authPath}.`);
|
package/dist/commands/startup.js
CHANGED
|
@@ -96,6 +96,7 @@ async function selectStartupAuthMode(options, deps) {
|
|
|
96
96
|
return authMode;
|
|
97
97
|
}
|
|
98
98
|
async function startup(cfg = config_js_1.config.parse({}), overrides = {}) {
|
|
99
|
+
cfg = config_js_1.config.parse(cfg);
|
|
99
100
|
const deps = { ...defaultStartupDependencies, ...overrides };
|
|
100
101
|
banner();
|
|
101
102
|
const s = deps.promptApi.spinner();
|
|
@@ -216,6 +216,7 @@ class AppServerContainerService {
|
|
|
216
216
|
const hostInfo = (0, host_js_1.getHostInfo)(cfg.codex.codex_auth_path);
|
|
217
217
|
const containerHome = cfg.agent_home_directory;
|
|
218
218
|
const containerAuthPath = resolveContainerPath(cfg.codex.codex_auth_path, containerHome);
|
|
219
|
+
const hostAuthPath = (0, path_js_1.expandHome)(cfg.codex.codex_auth_path);
|
|
219
220
|
const hostDedicatedAuthPath = `${(0, path_js_1.expandHome)(cfg.config_directory)}/${cfg.codex.codex_auth_file_path}`;
|
|
220
221
|
const mountArgs = [];
|
|
221
222
|
if (codexAuthMode === "dedicated") {
|
|
@@ -224,6 +225,12 @@ class AppServerContainerService {
|
|
|
224
225
|
}
|
|
225
226
|
mountArgs.push("--mount", `type=bind,src=${hostDedicatedAuthPath},dst=${containerAuthPath}`);
|
|
226
227
|
}
|
|
228
|
+
else if (codexAuthMode === "host") {
|
|
229
|
+
if (!hostInfo.codexAuthExists) {
|
|
230
|
+
throw new Error(`Codex host auth file was not found at ${hostAuthPath}`);
|
|
231
|
+
}
|
|
232
|
+
mountArgs.push("--mount", `type=bind,src=${hostAuthPath},dst=${containerAuthPath}`);
|
|
233
|
+
}
|
|
227
234
|
this.containerName = `companyhelm-codex-app-server-${Date.now()}`;
|
|
228
235
|
const bootstrapTemplate = (0, node_fs_1.readFileSync)(resolveTemplatePath(), "utf8");
|
|
229
236
|
const bootstrapScript = renderJinjaTemplate(bootstrapTemplate, {
|
|
@@ -108,7 +108,7 @@ function buildSharedThreadMounts(options) {
|
|
|
108
108
|
mounts.push({
|
|
109
109
|
Type: "bind",
|
|
110
110
|
Source: hostAuthPath,
|
|
111
|
-
Target:
|
|
111
|
+
Target: resolveContainerPath(options.codexAuthPath, options.containerHomeDirectory),
|
|
112
112
|
});
|
|
113
113
|
return mounts;
|
|
114
114
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@companyhelm/runner",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Run the CompanyHelm runner in fully isolated Docker sandboxes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"test": "npm run build && vitest run",
|
|
25
25
|
"test:unit": "npm run build && vitest run tests/unit",
|
|
26
26
|
"test:integration": "npm run build && vitest run tests/integration",
|
|
27
|
+
"test:system:device-auth": "npm run build && COMPANYHELM_RUN_MANUAL_DEVICE_AUTH_TEST=1 vitest run --reporter=verbose tests/system/codex-device-auth.system.test.ts",
|
|
27
28
|
"db:generate": "drizzle-kit generate",
|
|
28
29
|
"db:migrate": "drizzle-kit migrate",
|
|
29
30
|
"generate:codex-app-server": "docker run --rm --user \"$(id -u):$(id -g)\" -e CODEX_HOME=/workspace/node_modules/.cache/codex -v \"$PWD:/workspace\" -w /workspace companyhelm/runner:$(tr -d '[:space:]' < RUNTIME_IMAGE_VERSION) bash -lc 'mkdir -p /workspace/node_modules/.cache/codex; source \"$NVM_DIR/nvm.sh\"; codex app-server generate-ts --out src/generated/codex-app-server'"
|