@companyhelm/cli 0.0.2 → 0.0.5

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.
Files changed (47) hide show
  1. package/README.md +24 -62
  2. package/RUNTIME_IMAGE_VERSION +1 -1
  3. package/dist/cli.js +29 -1
  4. package/dist/commands/register-commands.js +2 -0
  5. package/dist/commands/root.js +280 -20
  6. package/dist/commands/startup.js +138 -55
  7. package/dist/commands/status.js +32 -0
  8. package/dist/service/app_server.js +23 -9
  9. package/dist/service/docker/app_server_container.js +3 -1
  10. package/dist/service/thread_lifecycle.js +4 -1
  11. package/dist/state/daemon_state.js +83 -0
  12. package/dist/state/schema.js +9 -1
  13. package/dist/templates/app_server_bootstrap.sh.j2 +46 -0
  14. package/dist/templates/runtime_agents.md.j2 +50 -0
  15. package/dist/templates/runtime_bashrc.j2 +19 -0
  16. package/dist/utils/daemon.js +15 -0
  17. package/dist/utils/process.js +22 -0
  18. package/drizzle/0011_actual_lucky.sql +7 -0
  19. package/drizzle/meta/_journal.json +8 -1
  20. package/package.json +6 -3
  21. package/dist/commands/agent/index.js +0 -10
  22. package/dist/commands/agent/list.js +0 -31
  23. package/dist/commands/agent/register-agent-commands.js +0 -10
  24. package/dist/commands/index.js +0 -15
  25. package/dist/commands/sdk/index.js +0 -12
  26. package/dist/commands/thread/index.js +0 -12
  27. package/dist/config/local.js +0 -1
  28. package/dist/config/schema.js +0 -7
  29. package/dist/model.js +0 -22
  30. package/dist/schema.js +0 -47
  31. package/dist/service/docker/docker_provider.js +0 -1
  32. package/dist/service/docker/runtime_container.js +0 -1
  33. package/dist/service/docker/runtime_image.js +0 -40
  34. package/dist/startup.js +0 -166
  35. package/dist/state/service/app_server.js +0 -392
  36. package/dist/state/service/buffered_client_message_sender.js +0 -73
  37. package/dist/state/service/companyhelm_api_client.js +0 -316
  38. package/dist/state/service/docker/app_server_container.js +0 -165
  39. package/dist/state/service/docker/dind.js +0 -114
  40. package/dist/state/service/docker/runtime_app_server_exec.js +0 -95
  41. package/dist/state/service/host.js +0 -15
  42. package/dist/state/service/runtime_shell.js +0 -23
  43. package/dist/state/service/sdk/refresh_models.js +0 -83
  44. package/dist/state/service/thread_lifecycle.js +0 -327
  45. package/dist/state/service/thread_runtime.js +0 -11
  46. package/dist/state/service/thread_turn_state.js +0 -45
  47. package/dist/state/service/workspace_agents.js +0 -115
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DAEMON_LOG_PATH_ENV = exports.DAEMON_CHILD_ENV = void 0;
4
+ exports.resolveDaemonLogPath = resolveDaemonLogPath;
5
+ exports.resolveDaemonLogDirectory = resolveDaemonLogDirectory;
6
+ const node_path_1 = require("node:path");
7
+ const path_js_1 = require("./path.js");
8
+ exports.DAEMON_CHILD_ENV = "COMPANYHELM_DAEMON_CHILD";
9
+ exports.DAEMON_LOG_PATH_ENV = "COMPANYHELM_DAEMON_LOG_PATH";
10
+ function resolveDaemonLogPath(stateDbPath) {
11
+ return (0, node_path_1.join)((0, node_path_1.dirname)((0, path_js_1.expandHome)(stateDbPath)), "daemon.log");
12
+ }
13
+ function resolveDaemonLogDirectory(stateDbPath) {
14
+ return (0, node_path_1.dirname)(resolveDaemonLogPath(stateDbPath));
15
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isProcessRunning = isProcessRunning;
4
+ function isProcessRunning(pid) {
5
+ if (!Number.isInteger(pid) || pid <= 0) {
6
+ return false;
7
+ }
8
+ try {
9
+ process.kill(pid, 0);
10
+ return true;
11
+ }
12
+ catch (error) {
13
+ const code = typeof error === "object" && error && "code" in error ? error.code : undefined;
14
+ if (code === "EPERM") {
15
+ return true;
16
+ }
17
+ if (code === "ESRCH") {
18
+ return false;
19
+ }
20
+ throw error;
21
+ }
22
+ }
@@ -0,0 +1,7 @@
1
+ CREATE TABLE `daemon_state` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `pid` integer,
4
+ `log_path` text,
5
+ `started_at` text NOT NULL,
6
+ `updated_at` text NOT NULL
7
+ );
@@ -78,6 +78,13 @@
78
78
  "when": 1772664695504,
79
79
  "tag": "0010_wealthy_dorian_gray",
80
80
  "breakpoints": true
81
+ },
82
+ {
83
+ "idx": 11,
84
+ "version": "6",
85
+ "when": 1772775000000,
86
+ "tag": "0011_actual_lucky",
87
+ "breakpoints": true
81
88
  }
82
89
  ]
83
- }
90
+ }
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@companyhelm/cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
4
4
  "description": "Run coding agents in fully isolated Docker sandboxes, locally.",
5
5
  "license": "Apache-2.0",
6
- "engines": {
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/CompanyHelm/companyhelm-cli"
9
+ }, "engines": {
7
10
  "node": ">=24"
8
11
  },
9
12
  "bin": {
@@ -15,7 +18,7 @@
15
18
  "RUNTIME_IMAGE_VERSION"
16
19
  ],
17
20
  "scripts": {
18
- "build": "tsc -p tsconfig.json",
21
+ "build": "tsc -p tsconfig.json && node scripts/copy-templates.js",
19
22
  "start": "npm run build && node dist/cli.js",
20
23
  "test": "npm run build && vitest run",
21
24
  "test:unit": "npm run build && vitest run tests/unit",
@@ -1,10 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerAgentCommands = registerAgentCommands;
4
- const list_js_1 = require("./list.js");
5
- function registerAgentCommands(program) {
6
- const agentCommand = program
7
- .command("agent")
8
- .description("Manage agents stored in the local state database.");
9
- (0, list_js_1.registerAgentListCommand)(agentCommand);
10
- }
@@ -1,31 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runAgentListCommand = runAgentListCommand;
4
- exports.registerAgentListCommand = registerAgentListCommand;
5
- const config_js_1 = require("../../config.js");
6
- const db_js_1 = require("../../state/db.js");
7
- const schema_js_1 = require("../../state/schema.js");
8
- async function runAgentListCommand() {
9
- const cfg = config_js_1.config.parse({});
10
- const { db, client } = await (0, db_js_1.initDb)(cfg.state_db_path);
11
- try {
12
- const rows = await db.select().from(schema_js_1.agents).orderBy(schema_js_1.agents.id).all();
13
- if (rows.length === 0) {
14
- console.log("No agents found.");
15
- return;
16
- }
17
- console.log("Agents:");
18
- for (const row of rows) {
19
- console.log(`- id: ${row.id}, name: ${row.name}, sdk: ${row.sdk}`);
20
- }
21
- }
22
- finally {
23
- client.close();
24
- }
25
- }
26
- function registerAgentListCommand(agentCommand) {
27
- agentCommand
28
- .command("list")
29
- .description("List all agents stored in the local state database.")
30
- .action(runAgentListCommand);
31
- }
@@ -1,10 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerAgentCommands = registerAgentCommands;
4
- const list_js_1 = require("./list.js");
5
- function registerAgentCommands(program) {
6
- const agentCommand = program
7
- .command("agent")
8
- .description("Manage agents stored in the local state database.");
9
- (0, list_js_1.registerAgentListCommand)(agentCommand);
10
- }
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerCommands = registerCommands;
4
- const index_js_1 = require("./agent/index.js");
5
- const root_js_1 = require("./root.js");
6
- const shell_js_1 = require("./shell.js");
7
- const index_js_2 = require("./sdk/index.js");
8
- const index_js_3 = require("./thread/index.js");
9
- function registerCommands(program) {
10
- (0, root_js_1.registerRootCommand)(program);
11
- (0, index_js_1.registerAgentCommands)(program);
12
- (0, index_js_3.registerThreadCommands)(program);
13
- (0, shell_js_1.registerShellCommand)(program);
14
- (0, index_js_2.registerSdkCommands)(program);
15
- }
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerSdkCommands = registerSdkCommands;
4
- const list_js_1 = require("./list.js");
5
- const refresh_models_js_1 = require("./refresh-models.js");
6
- function registerSdkCommands(program) {
7
- const sdkCommand = program
8
- .command("sdk")
9
- .description("Manage configured SDKs and their model capabilities.");
10
- (0, list_js_1.registerSdkListCommand)(sdkCommand);
11
- (0, refresh_models_js_1.registerSdkRefreshModelsCommand)(sdkCommand);
12
- }
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerThreadCommands = registerThreadCommands;
4
- const docker_js_1 = require("./docker.js");
5
- const list_js_1 = require("./list.js");
6
- function registerThreadCommands(program) {
7
- const threadCommand = program
8
- .command("thread")
9
- .description("Manage threads stored in the local state database.");
10
- (0, list_js_1.registerThreadListCommand)(threadCommand);
11
- (0, docker_js_1.registerThreadDockerCommand)(threadCommand);
12
- }
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const zod_1 = require("zod");
4
- const schema = zod_1.z.object({
5
- agent_home: zod_1.z.string().describe("The home directory for the agent.").default("/home/agent"),
6
- });
7
- exports.default = schema;
package/dist/model.js DELETED
@@ -1,22 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CodexModel = exports.LLMModel = exports.AgentModel = void 0;
4
- const zod_1 = require("zod");
5
- exports.AgentModel = zod_1.z.object({
6
- id: zod_1.z.uuid().describe("The ID of the agent."),
7
- name: zod_1.z.string().describe("The name of the agent."),
8
- sdk: zod_1.z.enum(["codex"]).describe("The SDK to use for the agent."),
9
- model: zod_1.z.string().describe("The model to use for the agent."),
10
- reasoning_level: zod_1.z.string().describe("The reasoning level to use for the agent. Model specific."),
11
- workspace: zod_1.z.string().describe("The workspace path in use by the agent."),
12
- runtime_container: zod_1.z.string().describe("The runtime container to use for the agent."),
13
- dind_container: zod_1.z.string().describe("The DIND container to use for the agent."),
14
- });
15
- exports.LLMModel = zod_1.z.object({
16
- name: zod_1.z.string().describe("The name of the model."),
17
- reasoning_level: zod_1.z.array(zod_1.z.string()).describe("The reasoning levels to use for the model. Model specific.").optional(),
18
- });
19
- exports.CodexModel = zod_1.z.object({
20
- authentication: zod_1.z.enum(["unauthenticated", "host", "dedicated"]).describe("Whether to use the host's authentication or a dedicated authentication."),
21
- models: zod_1.z.array(exports.LLMModel).describe("The models to use for the Codex agent."),
22
- });
package/dist/schema.js DELETED
@@ -1,47 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.codexConfigModels = exports.codexConfigs = exports.agents = exports.llmModels = exports.agentSdks = void 0;
4
- const sqlite_core_1 = require("drizzle-orm/sqlite-core");
5
- // ── agent_sdks ──────────────────────────────────────────────────────────────
6
- exports.agentSdks = (0, sqlite_core_1.sqliteTable)("agent_sdks", {
7
- name: (0, sqlite_core_1.text)("name").primaryKey(),
8
- });
9
- // ── llm_models ──────────────────────────────────────────────────────────────
10
- exports.llmModels = (0, sqlite_core_1.sqliteTable)("llm_models", {
11
- name: (0, sqlite_core_1.text)("name").primaryKey(),
12
- sdkName: (0, sqlite_core_1.text)("sdk_name")
13
- .notNull()
14
- .references(() => exports.agentSdks.name),
15
- reasoningLevels: (0, sqlite_core_1.text)("reasoning_levels", { mode: "json" })
16
- .$type(),
17
- });
18
- // ── agents ──────────────────────────────────────────────────────────────────
19
- exports.agents = (0, sqlite_core_1.sqliteTable)("agents", {
20
- id: (0, sqlite_core_1.text)("id")
21
- .primaryKey()
22
- .$defaultFn(() => crypto.randomUUID()),
23
- name: (0, sqlite_core_1.text)("name").notNull(),
24
- sdk: (0, sqlite_core_1.text)("sdk", { enum: ["codex"] }).notNull(),
25
- model: (0, sqlite_core_1.text)("model").notNull(),
26
- reasoningLevel: (0, sqlite_core_1.text)("reasoning_level").notNull(),
27
- workspace: (0, sqlite_core_1.text)("workspace").notNull(),
28
- runtimeContainer: (0, sqlite_core_1.text)("runtime_container").notNull(),
29
- dindContainer: (0, sqlite_core_1.text)("dind_container").notNull(),
30
- });
31
- // ── codex_configs ───────────────────────────────────────────────────────────
32
- exports.codexConfigs = (0, sqlite_core_1.sqliteTable)("codex_configs", {
33
- id: (0, sqlite_core_1.text)("id")
34
- .primaryKey()
35
- .$defaultFn(() => crypto.randomUUID()),
36
- authentication: (0, sqlite_core_1.text)("authentication", {
37
- enum: ["unauthenticated", "host", "dedicated"],
38
- }).notNull(),
39
- });
40
- exports.codexConfigModels = (0, sqlite_core_1.sqliteTable)("codex_config_models", {
41
- configId: (0, sqlite_core_1.text)("config_id")
42
- .notNull()
43
- .references(() => exports.codexConfigs.id),
44
- modelName: (0, sqlite_core_1.text)("model_name")
45
- .notNull()
46
- .references(() => exports.llmModels.name),
47
- });
@@ -1 +0,0 @@
1
- "use strict";
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,40 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ensureRuntimeImage = ensureRuntimeImage;
7
- const dockerode_1 = __importDefault(require("dockerode"));
8
- const DOCKERFILE = "Dockerfile-runtime";
9
- /**
10
- * Ensures the runtime image exists in Docker.
11
- *
12
- * If an image named {@link imageName} is already present locally, returns
13
- * immediately. Otherwise, builds it from `Dockerfile-runtime` in
14
- * {@link contextDir} and tags it with {@link imageName}.
15
- *
16
- * @param imageName - Docker image name to check / build (e.g. "yolodock/runtime").
17
- * @param contextDir - Absolute path to the directory that contains Dockerfile-runtime.
18
- * @param docker - Optional Dockerode instance (defaults to the local daemon).
19
- * @returns The verified image name.
20
- */
21
- async function ensureRuntimeImage(imageName, contextDir, docker) {
22
- const d = docker ?? new dockerode_1.default();
23
- if (await imageExists(d, imageName)) {
24
- return imageName;
25
- }
26
- const stream = await d.buildImage({ context: contextDir, src: ["."] }, { dockerfile: DOCKERFILE, t: imageName });
27
- await new Promise((resolve, reject) => {
28
- d.modem.followProgress(stream, (err) => (err ? reject(err) : resolve()));
29
- });
30
- return imageName;
31
- }
32
- async function imageExists(docker, name) {
33
- try {
34
- await docker.getImage(name).inspect();
35
- return true;
36
- }
37
- catch {
38
- return false;
39
- }
40
- }
package/dist/startup.js DELETED
@@ -1,166 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.startup = startup;
40
- const node_fs_1 = require("node:fs");
41
- const node_path_1 = require("node:path");
42
- const node_child_process_1 = require("node:child_process");
43
- const p = __importStar(require("@clack/prompts"));
44
- const figlet_1 = __importDefault(require("figlet"));
45
- const config_js_1 = require("./config.js");
46
- const db_js_1 = require("./state/db.js");
47
- const schema_js_1 = require("./state/schema.js");
48
- const host_js_1 = require("./service/host.js");
49
- const path_js_1 = require("./utils/path.js");
50
- function banner() {
51
- console.log();
52
- console.log(figlet_1.default.textSync("CompanyHelm", { font: "Small" }));
53
- console.log();
54
- }
55
- async function dedicatedAuth(cfg, db) {
56
- const port = cfg.codex.codex_auth_port;
57
- const socatPort = port + 1; // socat listens on a separate port to avoid conflicting with codex
58
- const containerName = `companyhelm-codex-auth-${Date.now()}`;
59
- p.log.info("Starting Codex login inside a container...");
60
- p.log.info("A browser URL will appear -- open it to complete authentication.");
61
- const configDir = (0, path_js_1.expandHome)(cfg.config_directory);
62
- if (!(0, node_fs_1.existsSync)(configDir)) {
63
- (0, node_fs_1.mkdirSync)(configDir, { recursive: true });
64
- }
65
- const destPath = (0, node_path_1.join)(configDir, cfg.codex.codex_auth_file_path);
66
- // Start codex interactively (full TTY passthrough so user can interact)
67
- // Host:port → container:socatPort (socat) → container:127.0.0.1:port (codex)
68
- const child = (0, node_child_process_1.spawn)("docker", [
69
- "run",
70
- "-it",
71
- "--name", containerName,
72
- "-p", `${port}:${socatPort}`,
73
- "--entrypoint", "bash",
74
- cfg.runtime_image,
75
- "-c",
76
- `source "$NVM_DIR/nvm.sh"; socat TCP-LISTEN:${socatPort},fork,bind=0.0.0.0,reuseaddr TCP:127.0.0.1:${port} 2>/dev/null & codex`,
77
- ], { stdio: "inherit" });
78
- // Poll for auth file inside the container — once it exists, login succeeded
79
- let authCopied = false;
80
- await new Promise((resolve, reject) => {
81
- const poll = setInterval(() => {
82
- // Use sh -c so ~ is expanded by the container's shell
83
- const check = (0, node_child_process_1.spawnSync)("docker", ["exec", containerName, "sh", "-c", `test -f ${cfg.codex.codex_auth_path}`], { stdio: "ignore" });
84
- if (check.status === 0) {
85
- clearInterval(poll);
86
- // Resolve ~ inside the container to get the absolute path for docker cp
87
- const resolveResult = (0, node_child_process_1.spawnSync)("docker", ["exec", containerName, "sh", "-c", `echo ${cfg.codex.codex_auth_path}`], { encoding: "utf-8" });
88
- const containerAuthAbsPath = resolveResult.stdout.trim();
89
- // Copy auth file from container to host
90
- const cpResult = (0, node_child_process_1.spawnSync)("docker", ["cp", `${containerName}:${containerAuthAbsPath}`, destPath], { stdio: "ignore" });
91
- if (cpResult.status !== 0) {
92
- (0, node_child_process_1.spawnSync)("docker", ["rm", "-f", containerName], { stdio: "ignore" });
93
- reject(new Error("Failed to extract auth file from container."));
94
- return;
95
- }
96
- // Mark success before killing container to avoid race with exit handler
97
- authCopied = true;
98
- (0, node_child_process_1.spawnSync)("docker", ["rm", "-f", containerName], { stdio: "ignore" });
99
- resolve();
100
- }
101
- }, 1000);
102
- // If codex exits before auth file appeared, user cancelled
103
- child.on("exit", () => {
104
- clearInterval(poll);
105
- if (!authCopied) {
106
- (0, node_child_process_1.spawnSync)("docker", ["rm", "-f", containerName], { stdio: "ignore" });
107
- reject(new Error("Codex login failed or was cancelled."));
108
- }
109
- });
110
- });
111
- await db.insert(schema_js_1.agentSdks).values({ name: "codex", authentication: "dedicated" });
112
- p.log.success(`Codex auth saved to ${destPath}`);
113
- }
114
- async function startup() {
115
- banner();
116
- const cfg = config_js_1.config.parse({});
117
- const s = p.spinner();
118
- s.start("Initializing state database");
119
- const { db } = await (0, db_js_1.initDb)(cfg.state_db_path);
120
- s.stop("State database ready.");
121
- // Check if any agent SDK is configured
122
- const sdks = await db.select().from(schema_js_1.agentSdks).all();
123
- if (sdks.length > 0) {
124
- p.log.success(`Agent SDK configured: ${sdks.map((s) => s.name).join(", ")}`);
125
- return;
126
- }
127
- // No SDK configured -- offer auth options
128
- p.intro("No agent SDK configured. Let's set up Codex authentication.");
129
- const hostInfo = (0, host_js_1.getHostInfo)(cfg.codex.codex_auth_path);
130
- const options = [
131
- {
132
- value: "dedicated",
133
- label: "Dedicated",
134
- hint: "recommended -- runs Codex login inside a container",
135
- },
136
- ];
137
- if (hostInfo.codexAuthExists) {
138
- options.push({
139
- value: "host",
140
- label: "Host",
141
- hint: `reuse existing credentials from ${cfg.codex.codex_auth_path}`,
142
- });
143
- }
144
- const authMode = await p.select({
145
- message: "How would you like to authenticate Codex?",
146
- options,
147
- });
148
- if (p.isCancel(authMode)) {
149
- p.cancel("Setup cancelled.");
150
- process.exit(0);
151
- }
152
- if (authMode === "host") {
153
- await db.insert(schema_js_1.agentSdks).values({ name: "codex", authentication: "host" });
154
- p.outro("Codex SDK configured with host authentication.");
155
- return;
156
- }
157
- // Dedicated auth flow
158
- try {
159
- await dedicatedAuth(cfg, db);
160
- p.outro("Codex login successful!");
161
- }
162
- catch (err) {
163
- p.cancel(err.message ?? "Codex login failed or was cancelled.");
164
- process.exit(1);
165
- }
166
- }