@companyhelm/cli 0.0.6 → 0.0.8
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 +2 -2
- package/dist/commands/root.js +13 -41
- package/dist/commands/runner/common.js +16 -0
- package/dist/commands/runner/register-runner-commands.js +12 -0
- package/dist/commands/runner/start.js +30 -0
- package/dist/commands/runner/stop.js +55 -0
- package/dist/commands/sdk/refresh-models.js +8 -1
- package/dist/commands/shell.js +3 -1
- package/dist/service/docker/app_server_container.js +52 -3
- package/dist/service/sdk/refresh_models.js +8 -0
- package/dist/templates/app_server_bootstrap.sh.j2 +7 -1
- package/package.json +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerCommands = registerCommands;
|
|
4
|
-
const
|
|
4
|
+
const register_runner_commands_js_1 = require("./runner/register-runner-commands.js");
|
|
5
5
|
const shell_js_1 = require("./shell.js");
|
|
6
6
|
const register_sdk_commands_js_1 = require("./sdk/register-sdk-commands.js");
|
|
7
7
|
const status_js_1 = require("./status.js");
|
|
8
8
|
const register_thread_commands_js_1 = require("./thread/register-thread-commands.js");
|
|
9
9
|
function registerCommands(program) {
|
|
10
|
-
(0,
|
|
10
|
+
(0, register_runner_commands_js_1.registerRunnerCommands)(program);
|
|
11
11
|
(0, status_js_1.registerStatusCommand)(program);
|
|
12
12
|
(0, register_thread_commands_js_1.registerThreadCommands)(program);
|
|
13
13
|
(0, shell_js_1.registerShellCommand)(program);
|
package/dist/commands/root.js
CHANGED
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.toErrorMessage = toErrorMessage;
|
|
36
37
|
exports.isRetryableApiConnectionError = isRetryableApiConnectionError;
|
|
37
38
|
exports.formatApiConnectionFailureMessage = formatApiConnectionFailureMessage;
|
|
38
39
|
exports.formatApiConnectionFailureDiagnostics = formatApiConnectionFailureDiagnostics;
|
|
@@ -42,9 +43,11 @@ exports.isNoRunningTurnInterruptError = isNoRunningTurnInterruptError;
|
|
|
42
43
|
exports.normalizeThreadAgentApiUrlForRuntime = normalizeThreadAgentApiUrlForRuntime;
|
|
43
44
|
exports.extractThreadNameUpdateFromNotification = extractThreadNameUpdateFromNotification;
|
|
44
45
|
exports.extractServerMessageRequestId = extractServerMessageRequestId;
|
|
46
|
+
exports.isInternalDaemonChildProcess = isInternalDaemonChildProcess;
|
|
47
|
+
exports.runDetachedDaemonProcess = runDetachedDaemonProcess;
|
|
48
|
+
exports.sendDaemonParentMessage = sendDaemonParentMessage;
|
|
45
49
|
exports.runRootCommand = runRootCommand;
|
|
46
50
|
exports.buildRootConfig = buildRootConfig;
|
|
47
|
-
exports.registerRootCommand = registerRootCommand;
|
|
48
51
|
const protobuf_1 = require("@bufbuild/protobuf");
|
|
49
52
|
const protos_1 = require("@companyhelm/protos");
|
|
50
53
|
const drizzle_orm_1 = require("drizzle-orm");
|
|
@@ -1464,10 +1467,11 @@ async function hasConfiguredSdks(cfg) {
|
|
|
1464
1467
|
client.close();
|
|
1465
1468
|
}
|
|
1466
1469
|
}
|
|
1467
|
-
async function
|
|
1470
|
+
async function countSdkModels(cfg, sdkName) {
|
|
1468
1471
|
const { db, client } = await (0, db_js_1.initDb)(cfg.state_db_path);
|
|
1469
1472
|
try {
|
|
1470
|
-
await db.
|
|
1473
|
+
const models = await db.select({ name: schema_js_1.llmModels.name }).from(schema_js_1.llmModels).where((0, drizzle_orm_1.eq)(schema_js_1.llmModels.sdkName, sdkName)).all();
|
|
1474
|
+
return models.length;
|
|
1471
1475
|
}
|
|
1472
1476
|
finally {
|
|
1473
1477
|
client.close();
|
|
@@ -1480,9 +1484,12 @@ async function refreshCodexModelsForRegistration(cfg, logger) {
|
|
|
1480
1484
|
logger.info(`Refreshed Codex models from container app-server (${modelCount} models).`);
|
|
1481
1485
|
}
|
|
1482
1486
|
catch (error) {
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1487
|
+
const cachedModelCount = await countSdkModels(cfg, "codex");
|
|
1488
|
+
const failureMessage = (0, refresh_models_js_1.formatSdkModelRefreshFailure)("codex", error);
|
|
1489
|
+
if (cachedModelCount === 0) {
|
|
1490
|
+
throw new Error(`${failureMessage} Runner startup aborted because no cached Codex models are available; refusing to register zero models.`);
|
|
1491
|
+
}
|
|
1492
|
+
logger.warn(`${failureMessage} Using ${cachedModelCount} cached Codex model(s) from local state instead of registering zero models.`);
|
|
1486
1493
|
}
|
|
1487
1494
|
}
|
|
1488
1495
|
async function resolveThreadAuthMode(cfg) {
|
|
@@ -2361,38 +2368,3 @@ function buildRootConfig(options) {
|
|
|
2361
2368
|
thread_git_skills_directory: options.threadGitSkillsDirectory,
|
|
2362
2369
|
});
|
|
2363
2370
|
}
|
|
2364
|
-
function registerRootCommand(program) {
|
|
2365
|
-
program
|
|
2366
|
-
.option("--config-path <path>", "Config directory override (defaults to ~/.config/companyhelm).")
|
|
2367
|
-
.option("--server-url <url>", "CompanyHelm gRPC API URL override.")
|
|
2368
|
-
.option("--agent-api-url <url>", "Agent gRPC API URL for companyhelm-agent in runtime containers (localhost is rewritten to http://host.docker.internal).")
|
|
2369
|
-
.option("--secret <secret>", "Bearer secret used as gRPC Authorization header.")
|
|
2370
|
-
.option("--state-db-path <path>", "State database path override (defaults to ~/.local/share/companyhelm/state.db).")
|
|
2371
|
-
.option("--use-host-docker-runtime", "Mount host Docker socket into runtime containers instead of creating DinD sidecars.")
|
|
2372
|
-
.option("--host-docker-path <path>", "Host Docker endpoint when --use-host-docker-runtime is enabled (unix:///<socket-path> or tcp://localhost:<port>).")
|
|
2373
|
-
.option("--thread-git-skills-directory <path>", "Container path where thread git skill repositories are cloned before linking into ~/.codex/skills.")
|
|
2374
|
-
.option("-d, --daemon", "Run in daemon mode and fail fast when no SDK is configured.")
|
|
2375
|
-
.option("--log-level <level>", "Log level (DEBUG, INFO, WARN, ERROR).", "INFO")
|
|
2376
|
-
.action(async () => {
|
|
2377
|
-
const options = program.opts();
|
|
2378
|
-
if (options.daemon && !isInternalDaemonChildProcess()) {
|
|
2379
|
-
await runDetachedDaemonProcess(options);
|
|
2380
|
-
return;
|
|
2381
|
-
}
|
|
2382
|
-
try {
|
|
2383
|
-
await runRootCommand(options, isInternalDaemonChildProcess()
|
|
2384
|
-
? {
|
|
2385
|
-
onDaemonReady: () => {
|
|
2386
|
-
sendDaemonParentMessage({ type: "daemon-ready" });
|
|
2387
|
-
},
|
|
2388
|
-
}
|
|
2389
|
-
: undefined);
|
|
2390
|
-
}
|
|
2391
|
-
catch (error) {
|
|
2392
|
-
if (isInternalDaemonChildProcess()) {
|
|
2393
|
-
sendDaemonParentMessage({ type: "daemon-error", message: toErrorMessage(error) });
|
|
2394
|
-
}
|
|
2395
|
-
throw error;
|
|
2396
|
-
}
|
|
2397
|
-
});
|
|
2398
|
-
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addRunnerStartOptions = addRunnerStartOptions;
|
|
4
|
+
function addRunnerStartOptions(command) {
|
|
5
|
+
return command
|
|
6
|
+
.option("--config-path <path>", "Config directory override (defaults to ~/.config/companyhelm).")
|
|
7
|
+
.option("--server-url <url>", "CompanyHelm gRPC API URL override.")
|
|
8
|
+
.option("--agent-api-url <url>", "Agent gRPC API URL for companyhelm-agent in runtime containers (localhost is rewritten to http://host.docker.internal).")
|
|
9
|
+
.option("--secret <secret>", "Bearer secret used as gRPC Authorization header.")
|
|
10
|
+
.option("--state-db-path <path>", "State database path override (defaults to ~/.local/share/companyhelm/state.db).")
|
|
11
|
+
.option("--use-host-docker-runtime", "Mount host Docker socket into runtime containers instead of creating DinD sidecars.")
|
|
12
|
+
.option("--host-docker-path <path>", "Host Docker endpoint when --use-host-docker-runtime is enabled (unix:///<socket-path> or tcp://localhost:<port>).")
|
|
13
|
+
.option("--thread-git-skills-directory <path>", "Container path where thread git skill repositories are cloned before linking into ~/.codex/skills.")
|
|
14
|
+
.option("-d, --daemon", "Run in daemon mode and fail fast when no SDK is configured.")
|
|
15
|
+
.option("--log-level <level>", "Log level (DEBUG, INFO, WARN, ERROR).", "INFO");
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerRunnerCommands = registerRunnerCommands;
|
|
4
|
+
const start_js_1 = require("./start.js");
|
|
5
|
+
const stop_js_1 = require("./stop.js");
|
|
6
|
+
function registerRunnerCommands(program) {
|
|
7
|
+
const runnerCommand = program
|
|
8
|
+
.command("runner")
|
|
9
|
+
.description("Manage the local CompanyHelm runner daemon.");
|
|
10
|
+
(0, start_js_1.registerRunnerStartCommand)(runnerCommand);
|
|
11
|
+
(0, stop_js_1.registerRunnerStopCommand)(runnerCommand);
|
|
12
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerRunnerStartCommand = registerRunnerStartCommand;
|
|
4
|
+
const root_js_1 = require("../root.js");
|
|
5
|
+
const common_js_1 = require("./common.js");
|
|
6
|
+
function registerRunnerStartCommand(runnerCommand) {
|
|
7
|
+
(0, common_js_1.addRunnerStartOptions)(runnerCommand
|
|
8
|
+
.command("start")
|
|
9
|
+
.description("Start the local CompanyHelm runner daemon.")).action(async (options) => {
|
|
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
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runRunnerStopCommand = runRunnerStopCommand;
|
|
4
|
+
exports.registerRunnerStopCommand = registerRunnerStopCommand;
|
|
5
|
+
const config_js_1 = require("../../config.js");
|
|
6
|
+
const daemon_state_js_1 = require("../../state/daemon_state.js");
|
|
7
|
+
const process_js_1 = require("../../utils/process.js");
|
|
8
|
+
const root_js_1 = require("../root.js");
|
|
9
|
+
const RUNNER_STOP_TIMEOUT_MS = 15000;
|
|
10
|
+
async function waitForProcessExit(pid, timeoutMs) {
|
|
11
|
+
const deadline = Date.now() + timeoutMs;
|
|
12
|
+
while (Date.now() < deadline) {
|
|
13
|
+
if (!(0, process_js_1.isProcessRunning)(pid)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
17
|
+
}
|
|
18
|
+
return !(0, process_js_1.isProcessRunning)(pid);
|
|
19
|
+
}
|
|
20
|
+
async function runRunnerStopCommand(options) {
|
|
21
|
+
const cfg = config_js_1.config.parse({
|
|
22
|
+
state_db_path: options.stateDbPath,
|
|
23
|
+
});
|
|
24
|
+
const state = await (0, daemon_state_js_1.readCurrentDaemonState)(cfg.state_db_path);
|
|
25
|
+
if (!state?.pid) {
|
|
26
|
+
console.log("CompanyHelm runner is not running.");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!(0, process_js_1.isProcessRunning)(state.pid)) {
|
|
30
|
+
await (0, daemon_state_js_1.clearCurrentDaemonState)(cfg.state_db_path, state.pid);
|
|
31
|
+
console.log(`CompanyHelm runner was not running. Cleared stale pid ${state.pid}.`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
process.kill(state.pid, "SIGTERM");
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
throw new Error(`Failed to stop CompanyHelm runner pid ${state.pid}: ${(0, root_js_1.toErrorMessage)(error)}`);
|
|
39
|
+
}
|
|
40
|
+
const stopped = await waitForProcessExit(state.pid, RUNNER_STOP_TIMEOUT_MS);
|
|
41
|
+
if (!stopped) {
|
|
42
|
+
throw new Error(`Timed out waiting for CompanyHelm runner pid ${state.pid} to stop.`);
|
|
43
|
+
}
|
|
44
|
+
await (0, daemon_state_js_1.clearCurrentDaemonState)(cfg.state_db_path, state.pid);
|
|
45
|
+
console.log(`CompanyHelm runner stopped (pid ${state.pid}).`);
|
|
46
|
+
}
|
|
47
|
+
function registerRunnerStopCommand(runnerCommand) {
|
|
48
|
+
runnerCommand
|
|
49
|
+
.command("stop")
|
|
50
|
+
.description("Stop the local CompanyHelm runner daemon.")
|
|
51
|
+
.option("--state-db-path <path>", "State database path override (defaults to ~/.local/share/companyhelm/state.db).")
|
|
52
|
+
.action(async (options) => {
|
|
53
|
+
await runRunnerStopCommand(options);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -4,7 +4,14 @@ exports.runSdkRefreshModelsCommand = runSdkRefreshModelsCommand;
|
|
|
4
4
|
exports.registerSdkRefreshModelsCommand = registerSdkRefreshModelsCommand;
|
|
5
5
|
const refresh_models_js_1 = require("../../service/sdk/refresh_models.js");
|
|
6
6
|
async function runSdkRefreshModelsCommand(options) {
|
|
7
|
-
|
|
7
|
+
let results;
|
|
8
|
+
try {
|
|
9
|
+
results = await (0, refresh_models_js_1.refreshSdkModels)({ sdk: options.sdk });
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
const sdkName = options.sdk ?? "configured";
|
|
13
|
+
throw new Error((0, refresh_models_js_1.formatSdkModelRefreshFailure)(sdkName, error));
|
|
14
|
+
}
|
|
8
15
|
for (const result of results) {
|
|
9
16
|
console.log(`Refreshed ${result.modelCount} models for SDK '${result.sdk}'.`);
|
|
10
17
|
}
|
package/dist/commands/shell.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.registerShellCommand = registerShellCommand;
|
|
|
7
7
|
const config_js_1 = require("../config.js");
|
|
8
8
|
const db_js_1 = require("../state/db.js");
|
|
9
9
|
const schema_js_1 = require("../state/schema.js");
|
|
10
|
+
const common_js_1 = require("./runner/common.js");
|
|
10
11
|
const NON_OVERRIDABLE_DAEMON_OPTION_NAMES = new Set(["daemon", "serverUrl", "secret", "help"]);
|
|
11
12
|
function resolveDaemonOptionValue(option, values) {
|
|
12
13
|
const explicit = values[option.name];
|
|
@@ -22,7 +23,8 @@ function resolveDaemonOptionValue(option, values) {
|
|
|
22
23
|
return undefined;
|
|
23
24
|
}
|
|
24
25
|
function getShellConfigurableDaemonOptions(program) {
|
|
25
|
-
|
|
26
|
+
const runnerStartCommand = (0, common_js_1.addRunnerStartOptions)(program.createCommand("start"));
|
|
27
|
+
return runnerStartCommand.options
|
|
26
28
|
.filter((option) => {
|
|
27
29
|
if (!option.long || option.hidden) {
|
|
28
30
|
return false;
|
|
@@ -56,12 +56,46 @@ class AppServerContainerService {
|
|
|
56
56
|
this.child = null;
|
|
57
57
|
this.containerName = null;
|
|
58
58
|
this.running = false;
|
|
59
|
+
this.recentStderrLines = [];
|
|
60
|
+
this.lastExitCode = null;
|
|
61
|
+
this.lastExitSignal = null;
|
|
59
62
|
this.docker = options?.docker ?? new dockerode_1.default();
|
|
60
63
|
this.imageStatusReporter = options?.imageStatusReporter;
|
|
61
64
|
}
|
|
62
65
|
reportImageStatus(message) {
|
|
63
66
|
this.imageStatusReporter?.(message);
|
|
64
67
|
}
|
|
68
|
+
recordStderr(chunk) {
|
|
69
|
+
const lines = chunk
|
|
70
|
+
.split(/\r?\n/)
|
|
71
|
+
.map((line) => line.trim())
|
|
72
|
+
.filter((line) => line.length > 0);
|
|
73
|
+
if (lines.length === 0) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this.recentStderrLines.push(...lines);
|
|
77
|
+
if (this.recentStderrLines.length > 8) {
|
|
78
|
+
this.recentStderrLines.splice(0, this.recentStderrLines.length - 8);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
buildContainerStoppedErrorMessage() {
|
|
82
|
+
const details = [];
|
|
83
|
+
if (this.containerName) {
|
|
84
|
+
details.push(`container ${this.containerName}`);
|
|
85
|
+
}
|
|
86
|
+
if (this.lastExitCode !== null) {
|
|
87
|
+
details.push(`exit code ${this.lastExitCode}`);
|
|
88
|
+
}
|
|
89
|
+
else if (this.lastExitSignal) {
|
|
90
|
+
details.push(`signal ${this.lastExitSignal}`);
|
|
91
|
+
}
|
|
92
|
+
if (this.recentStderrLines.length > 0) {
|
|
93
|
+
details.push(`stderr: ${this.recentStderrLines.join(" | ")}`);
|
|
94
|
+
}
|
|
95
|
+
return details.length > 0
|
|
96
|
+
? `App server container is not running (${details.join(", ")})`
|
|
97
|
+
: "App server container is not running";
|
|
98
|
+
}
|
|
65
99
|
static isImageNotFound(error) {
|
|
66
100
|
if (typeof error !== "object" || error === null) {
|
|
67
101
|
return false;
|
|
@@ -159,6 +193,9 @@ class AppServerContainerService {
|
|
|
159
193
|
if (this.running) {
|
|
160
194
|
throw new Error("App server container is already running");
|
|
161
195
|
}
|
|
196
|
+
this.recentStderrLines = [];
|
|
197
|
+
this.lastExitCode = null;
|
|
198
|
+
this.lastExitSignal = null;
|
|
162
199
|
const cfg = config_js_1.config.parse({});
|
|
163
200
|
await this.ensureImageAvailable(cfg.runtime_image);
|
|
164
201
|
const { db, client } = await (0, db_js_1.initDb)(cfg.state_db_path);
|
|
@@ -218,15 +255,27 @@ class AppServerContainerService {
|
|
|
218
255
|
this.messageQueue.push({ type: "stdout", payload: chunk });
|
|
219
256
|
});
|
|
220
257
|
child.stderr.on("data", (chunk) => {
|
|
221
|
-
|
|
258
|
+
const payload = chunk.toString("utf8");
|
|
259
|
+
this.recordStderr(payload);
|
|
260
|
+
this.messageQueue.push({ type: "stderr", payload });
|
|
222
261
|
});
|
|
223
262
|
child.on("error", (err) => {
|
|
263
|
+
this.recordStderr(err.message);
|
|
224
264
|
this.messageQueue.push({ type: "error", reason: `docker process error: ${err.message}` });
|
|
225
265
|
this.running = false;
|
|
226
266
|
this.messageQueue.close();
|
|
227
267
|
});
|
|
228
|
-
child.on("exit", () => {
|
|
268
|
+
child.on("exit", (code, signal) => {
|
|
269
|
+
const wasRunning = this.running;
|
|
270
|
+
this.lastExitCode = code;
|
|
271
|
+
this.lastExitSignal = signal;
|
|
229
272
|
this.running = false;
|
|
273
|
+
if (wasRunning) {
|
|
274
|
+
this.messageQueue.push({
|
|
275
|
+
type: "error",
|
|
276
|
+
reason: this.buildContainerStoppedErrorMessage(),
|
|
277
|
+
});
|
|
278
|
+
}
|
|
230
279
|
this.messageQueue.close();
|
|
231
280
|
});
|
|
232
281
|
this.child = child;
|
|
@@ -253,7 +302,7 @@ class AppServerContainerService {
|
|
|
253
302
|
}
|
|
254
303
|
async sendRaw(payload) {
|
|
255
304
|
if (!this.running || !this.child || !this.child.stdin) {
|
|
256
|
-
throw new Error(
|
|
305
|
+
throw new Error(this.buildContainerStoppedErrorMessage());
|
|
257
306
|
}
|
|
258
307
|
this.child.stdin.write(payload);
|
|
259
308
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatSdkModelRefreshFailure = formatSdkModelRefreshFailure;
|
|
3
4
|
exports.refreshSdkModels = refreshSdkModels;
|
|
4
5
|
const drizzle_orm_1 = require("drizzle-orm");
|
|
5
6
|
const config_js_1 = require("../../config.js");
|
|
@@ -7,6 +8,13 @@ const db_js_1 = require("../../state/db.js");
|
|
|
7
8
|
const schema_js_1 = require("../../state/schema.js");
|
|
8
9
|
const app_server_js_1 = require("../app_server.js");
|
|
9
10
|
const app_server_container_js_1 = require("../docker/app_server_container.js");
|
|
11
|
+
function toErrorMessage(error) {
|
|
12
|
+
return error instanceof Error ? error.message : String(error);
|
|
13
|
+
}
|
|
14
|
+
function formatSdkModelRefreshFailure(sdk, error) {
|
|
15
|
+
return (`Failed to refresh ${sdk} models from the local Codex app-server: ${toErrorMessage(error)}. ` +
|
|
16
|
+
"Verify the runner image can start Codex app-server with valid auth, then retry.");
|
|
17
|
+
}
|
|
10
18
|
async function fetchCodexModelsFromAppServer(clientName, logger, imageStatusReporter) {
|
|
11
19
|
const transport = new app_server_container_js_1.AppServerContainerService({ imageStatusReporter });
|
|
12
20
|
const appServer = new app_server_js_1.AppServerService(transport, clientName, logger);
|
|
@@ -6,6 +6,12 @@ AGENT_UID={{ agent_uid }}
|
|
|
6
6
|
AGENT_GID={{ agent_gid }}
|
|
7
7
|
CODEX_AUTH_PATH={{ codex_auth_path }}
|
|
8
8
|
APP_SERVER_COMMAND={{ app_server_command }}
|
|
9
|
+
EXISTING_UID_USER=""
|
|
10
|
+
|
|
11
|
+
if getent passwd "$AGENT_UID" >/dev/null 2>&1; then
|
|
12
|
+
EXISTING_UID_USER="$(getent passwd "$AGENT_UID" | cut -d: -f1)"
|
|
13
|
+
AGENT_USER="$EXISTING_UID_USER"
|
|
14
|
+
fi
|
|
9
15
|
|
|
10
16
|
AGENT_GROUP="$AGENT_USER"
|
|
11
17
|
if getent group "$AGENT_GID" >/dev/null 2>&1; then
|
|
@@ -19,7 +25,7 @@ else
|
|
|
19
25
|
fi
|
|
20
26
|
|
|
21
27
|
if id -u "$AGENT_USER" >/dev/null 2>&1; then
|
|
22
|
-
usermod -u "$AGENT_UID" -g "$AGENT_GROUP" -d "$AGENT_HOME" "$AGENT_USER" || true
|
|
28
|
+
usermod -u "$AGENT_UID" -g "$AGENT_GROUP" -d "$AGENT_HOME" -s /bin/bash "$AGENT_USER" || true
|
|
23
29
|
else
|
|
24
30
|
useradd -m -d "$AGENT_HOME" -u "$AGENT_UID" -g "$AGENT_GROUP" -s /bin/bash "$AGENT_USER"
|
|
25
31
|
fi
|