@rallycry/conveyor-agent 4.10.2 → 5.0.1

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/cli.js CHANGED
@@ -1,12 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  AgentRunner,
4
- ProjectRunner
5
- } from "./chunk-VJRAWAWQ.js";
4
+ ProjectRunner,
5
+ createServiceLogger,
6
+ errorMeta
7
+ } from "./chunk-JI4AW4WX.js";
6
8
 
7
9
  // src/cli.ts
8
10
  import { readFileSync, existsSync } from "fs";
9
- import { join } from "path";
11
+ import { join, dirname } from "path";
12
+ import { fileURLToPath } from "url";
13
+ if (process.argv.includes("--version")) {
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const pkgPath = join(__dirname, "..", "package.json");
16
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
17
+ process.stdout.write(pkg.version + "\n");
18
+ process.exit(0);
19
+ }
20
+ var logger = createServiceLogger("CLI");
10
21
  function loadConveyorEnvFile(workspaceDir) {
11
22
  const envPath = join(workspaceDir, ".conveyor", "env");
12
23
  if (!existsSync(envPath)) return;
@@ -21,16 +32,16 @@ function loadConveyorEnvFile(workspaceDir) {
21
32
  const value = trimmed.slice(eqIdx + 1);
22
33
  process.env[key] = value;
23
34
  }
24
- console.log("[conveyor-agent] Loaded env overrides from .conveyor/env");
35
+ logger.info("Loaded env overrides from .conveyor/env");
25
36
  } catch {
26
37
  }
27
38
  }
28
39
  async function bootstrapFromCodespace(apiUrl) {
29
- console.log(`[conveyor-agent] Bootstrapping from codespace ${process.env.CODESPACE_NAME}...`);
40
+ logger.info("Bootstrapping from codespace", { codespace: process.env.CODESPACE_NAME });
30
41
  const response = await fetch(`${apiUrl}/api/codespace/bootstrap/${process.env.CODESPACE_NAME}`);
31
42
  if (!response.ok) {
32
43
  const errorText = await response.text();
33
- console.error(`Bootstrap failed (${response.status}): ${errorText}`);
44
+ logger.error("Bootstrap failed", { status: response.status, body: errorText });
34
45
  process.exit(1);
35
46
  }
36
47
  const config = await response.json();
@@ -40,26 +51,33 @@ async function bootstrapFromCodespace(apiUrl) {
40
51
  if (config.mode === "project") {
41
52
  process.env.CONVEYOR_PROJECT_TOKEN = config.projectToken;
42
53
  process.env.CONVEYOR_PROJECT_ID = config.projectId;
43
- console.log(`[conveyor-agent] Bootstrap complete, project ${config.projectId}`);
54
+ if (config.workspaceBranch) {
55
+ process.env.CONVEYOR_WORKSPACE_BRANCH = config.workspaceBranch;
56
+ }
57
+ logger.info("Bootstrap complete", { projectId: config.projectId });
44
58
  } else {
45
59
  process.env.CONVEYOR_TASK_ID = config.taskId;
46
60
  process.env.CONVEYOR_TASK_TOKEN = config.taskToken;
47
61
  process.env.CONVEYOR_AGENT_MODE = config.agentMode;
48
62
  process.env.CONVEYOR_IS_AUTO = config.isAuto;
49
- if (config.pullBranch) {
50
- process.env.CONVEYOR_PULL_BRANCH = config.pullBranch;
63
+ if (config.taskBranch) {
64
+ process.env.CONVEYOR_TASK_BRANCH = config.taskBranch;
51
65
  }
52
- console.log(`[conveyor-agent] Bootstrap complete, task ${config.taskId}`);
66
+ logger.info("Bootstrap complete", { taskId: config.taskId });
53
67
  }
54
68
  }
55
69
  process.on("uncaughtException", (err) => {
56
70
  if (err.code === "EPIPE") return;
57
- console.error("Uncaught exception:", err);
71
+ logger.error("Uncaught exception", { error: err.message, code: err.code });
58
72
  process.exit(1);
59
73
  });
60
74
  loadConveyorEnvFile(process.env.CONVEYOR_WORKSPACE ?? process.cwd());
61
75
  var conveyorApiUrl = process.env.CONVEYOR_API_URL;
62
76
  if (process.env.CODESPACE_NAME && !process.env.CONVEYOR_TASK_TOKEN && !process.env.CONVEYOR_PROJECT_TOKEN) {
77
+ if (!conveyorApiUrl) {
78
+ logger.error("CONVEYOR_API_URL is required for codespace bootstrap");
79
+ process.exit(1);
80
+ }
63
81
  await bootstrapFromCodespace(conveyorApiUrl);
64
82
  conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;
65
83
  }
@@ -67,13 +85,13 @@ var CONVEYOR_PROJECT_TOKEN = process.env.CONVEYOR_PROJECT_TOKEN;
67
85
  var CONVEYOR_PROJECT_ID = process.env.CONVEYOR_PROJECT_ID;
68
86
  if (CONVEYOR_PROJECT_TOKEN && CONVEYOR_PROJECT_ID) {
69
87
  const projectRunner = new ProjectRunner({
70
- conveyorApiUrl,
88
+ conveyorApiUrl: conveyorApiUrl ?? "",
71
89
  projectToken: CONVEYOR_PROJECT_TOKEN,
72
90
  projectId: CONVEYOR_PROJECT_ID,
73
91
  projectDir: process.env.CONVEYOR_WORKSPACE ?? process.cwd()
74
92
  });
75
93
  projectRunner.start().catch((error) => {
76
- console.error("Project runner failed:", error);
94
+ logger.error("Project runner failed", errorMeta(error));
77
95
  process.exit(1);
78
96
  });
79
97
  } else {
@@ -86,30 +104,30 @@ if (CONVEYOR_PROJECT_TOKEN && CONVEYOR_PROJECT_ID) {
86
104
  const CONVEYOR_AGENT_MODE = process.env.CONVEYOR_AGENT_MODE || void 0;
87
105
  const CONVEYOR_IS_AUTO = CONVEYOR_AGENT_MODE ? CONVEYOR_AGENT_MODE === "auto" : process.env.CONVEYOR_IS_AUTO === "true";
88
106
  if (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {
89
- console.error("Missing required environment variables:");
90
- console.error(" CONVEYOR_TASK_TOKEN - JWT token for task authentication");
91
- console.error(" CONVEYOR_TASK_ID - ID of the task to execute");
92
- console.error("");
93
- console.error("CONVEYOR_API_URL is provided via codespace secret or bootstrap.");
94
- console.error("");
95
- console.error("Optional:");
96
- console.error(" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'");
97
- console.error(" CONVEYOR_MODEL - Claude model to use");
98
- console.error(" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)");
99
- console.error("");
100
- console.error("Project runner mode:");
101
- console.error(" CONVEYOR_PROJECT_TOKEN - Project token for project runner");
102
- console.error(" CONVEYOR_PROJECT_ID - Project ID for project runner");
107
+ logger.error("Missing required environment variables");
108
+ logger.error(" CONVEYOR_TASK_TOKEN - JWT token for task authentication");
109
+ logger.error(" CONVEYOR_TASK_ID - ID of the task to execute");
110
+ logger.error("");
111
+ logger.error("CONVEYOR_API_URL is provided via codespace secret or bootstrap.");
112
+ logger.error("");
113
+ logger.error("Optional:");
114
+ logger.error(" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'");
115
+ logger.error(" CONVEYOR_MODEL - Claude model to use");
116
+ logger.error(" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)");
117
+ logger.error("");
118
+ logger.error("Project runner mode:");
119
+ logger.error(" CONVEYOR_PROJECT_TOKEN - Project token for project runner");
120
+ logger.error(" CONVEYOR_PROJECT_ID - Project ID for project runner");
103
121
  process.exit(1);
104
122
  }
105
123
  if (CONVEYOR_MODE !== "task" && CONVEYOR_MODE !== "pm") {
106
- console.error(`Invalid CONVEYOR_MODE: "${CONVEYOR_MODE}". Must be "task" or "pm".`);
124
+ logger.error("Invalid CONVEYOR_MODE", { mode: CONVEYOR_MODE, expected: ["task", "pm"] });
107
125
  process.exit(1);
108
126
  }
109
- console.log(`[conveyor-agent] Starting in ${CONVEYOR_MODE} mode`);
127
+ logger.info("Starting agent", { mode: CONVEYOR_MODE });
110
128
  const runner = new AgentRunner(
111
129
  {
112
- conveyorApiUrl,
130
+ conveyorApiUrl: conveyorApiUrl ?? "",
113
131
  taskToken: CONVEYOR_TASK_TOKEN,
114
132
  taskId: CONVEYOR_TASK_ID,
115
133
  model: CONVEYOR_MODEL,
@@ -121,23 +139,23 @@ if (CONVEYOR_PROJECT_TOKEN && CONVEYOR_PROJECT_ID) {
121
139
  {
122
140
  onEvent: (event) => {
123
141
  const detail = "message" in event ? event.message : "content" in event ? event.content : "summary" in event ? event.summary : "";
124
- console.log(`[${event.type}] ${detail}`);
142
+ logger.info(detail, { eventType: event.type });
125
143
  },
126
144
  onStatusChange: (status) => {
127
- console.log(`[status] ${status}`);
145
+ logger.info("Status changed", { status });
128
146
  }
129
147
  }
130
148
  );
131
149
  process.on("SIGTERM", () => {
132
- console.log("Received SIGTERM, stopping agent...");
150
+ logger.info("Received SIGTERM, stopping agent");
133
151
  runner.stop();
134
152
  });
135
153
  process.on("SIGINT", () => {
136
- console.log("Received SIGINT, stopping agent...");
154
+ logger.info("Received SIGINT, stopping agent");
137
155
  runner.stop();
138
156
  });
139
157
  runner.start().catch((error) => {
140
- console.error("Agent runner failed:", error);
158
+ logger.error("Agent runner failed", errorMeta(error));
141
159
  process.exit(1);
142
160
  });
143
161
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/* oxlint-disable no-console */\n\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { AgentRunner } from \"./runner/index.js\";\nimport { ProjectRunner } from \"./runner/index.js\";\nimport type { AgentEvent, AgentRunnerStatus, RunnerMode } from \"./types.js\";\n\nfunction loadConveyorEnvFile(workspaceDir: string): void {\n const envPath = join(workspaceDir, \".conveyor\", \"env\");\n if (!existsSync(envPath)) return;\n try {\n const content = readFileSync(envPath, \"utf-8\");\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx < 1) continue;\n const key = trimmed.slice(0, eqIdx);\n const value = trimmed.slice(eqIdx + 1);\n process.env[key] = value;\n }\n console.log(\"[conveyor-agent] Loaded env overrides from .conveyor/env\");\n } catch {\n // File unreadable — fall through to containerEnv / defaults\n }\n}\n\nasync function bootstrapFromCodespace(apiUrl: string): Promise<void> {\n console.log(`[conveyor-agent] Bootstrapping from codespace ${process.env.CODESPACE_NAME}...`);\n const response = await fetch(`${apiUrl}/api/codespace/bootstrap/${process.env.CODESPACE_NAME}`);\n if (!response.ok) {\n const errorText = await response.text();\n console.error(`Bootstrap failed (${response.status}): ${errorText}`);\n process.exit(1);\n }\n const config = (await response.json()) as {\n mode?: \"task\" | \"project\";\n taskId?: string;\n taskToken?: string;\n agentMode?: string;\n isAuto?: string;\n pullBranch?: string;\n projectId?: string;\n projectToken?: string;\n apiUrl?: string;\n envVars: Record<string, string>;\n };\n\n // Apply shared env vars first\n for (const [key, value] of Object.entries(config.envVars ?? {})) {\n process.env[key] = value;\n }\n\n if (config.mode === \"project\") {\n // Project codespace → set project runner env vars\n process.env.CONVEYOR_PROJECT_TOKEN = config.projectToken;\n process.env.CONVEYOR_PROJECT_ID = config.projectId;\n console.log(`[conveyor-agent] Bootstrap complete, project ${config.projectId}`);\n } else {\n // Task codespace → existing behavior\n process.env.CONVEYOR_TASK_ID = config.taskId;\n process.env.CONVEYOR_TASK_TOKEN = config.taskToken;\n process.env.CONVEYOR_AGENT_MODE = config.agentMode;\n process.env.CONVEYOR_IS_AUTO = config.isAuto;\n if (config.pullBranch) {\n process.env.CONVEYOR_PULL_BRANCH = config.pullBranch;\n }\n console.log(`[conveyor-agent] Bootstrap complete, task ${config.taskId}`);\n }\n}\n\nprocess.on(\"uncaughtException\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EPIPE\") return;\n console.error(\"Uncaught exception:\", err);\n process.exit(1);\n});\n\n// Load .conveyor/env overrides (e.g. CONVEYOR_API_URL) before reading env vars.\n// This file is committed to the task branch by the Conveyor API and lets the\n// agent reach the correct API without modifying devcontainer.json (which would\n// invalidate GitHub prebuild caches).\nloadConveyorEnvFile(process.env.CONVEYOR_WORKSPACE ?? process.cwd());\n\nlet conveyorApiUrl = process.env.CONVEYOR_API_URL;\n\n// Step 1: Codespace bootstrap (before project runner check)\n// Bootstrap runs when in a codespace and neither token is already set.\n// This allows the bootstrap endpoint to return either task or project credentials.\nif (\n process.env.CODESPACE_NAME &&\n !process.env.CONVEYOR_TASK_TOKEN &&\n !process.env.CONVEYOR_PROJECT_TOKEN\n) {\n await bootstrapFromCodespace(conveyorApiUrl!);\n conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;\n}\n\n// Step 2: Re-read env vars (bootstrap may have set them)\nconst CONVEYOR_PROJECT_TOKEN = process.env.CONVEYOR_PROJECT_TOKEN;\nconst CONVEYOR_PROJECT_ID = process.env.CONVEYOR_PROJECT_ID;\n\n// Step 3: Branch on mode\nif (CONVEYOR_PROJECT_TOKEN && CONVEYOR_PROJECT_ID) {\n // Project runner mode: connect once, auto-handle tasks\n const projectRunner = new ProjectRunner({\n conveyorApiUrl: conveyorApiUrl!,\n projectToken: CONVEYOR_PROJECT_TOKEN,\n projectId: CONVEYOR_PROJECT_ID,\n projectDir: process.env.CONVEYOR_WORKSPACE ?? process.cwd(),\n });\n\n projectRunner.start().catch((error: unknown) => {\n console.error(\"Project runner failed:\", error);\n process.exit(1);\n });\n} else {\n // Standard per-task agent mode\n const CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\n const CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\n const CONVEYOR_MODEL = process.env.CONVEYOR_MODEL ?? \"claude-sonnet-4-20250514\";\n const CONVEYOR_INSTRUCTIONS = process.env.CONVEYOR_INSTRUCTIONS ?? \"\";\n const CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\n const CONVEYOR_MODE = (process.env.CONVEYOR_MODE ?? \"task\") as RunnerMode;\n const CONVEYOR_AGENT_MODE = process.env.CONVEYOR_AGENT_MODE || undefined;\n const CONVEYOR_IS_AUTO = CONVEYOR_AGENT_MODE\n ? CONVEYOR_AGENT_MODE === \"auto\"\n : process.env.CONVEYOR_IS_AUTO === \"true\";\n\n if (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {\n console.error(\"Missing required environment variables:\");\n console.error(\" CONVEYOR_TASK_TOKEN - JWT token for task authentication\");\n console.error(\" CONVEYOR_TASK_ID - ID of the task to execute\");\n console.error(\"\");\n console.error(\"CONVEYOR_API_URL is provided via codespace secret or bootstrap.\");\n console.error(\"\");\n console.error(\"Optional:\");\n console.error(\" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'\");\n console.error(\" CONVEYOR_MODEL - Claude model to use\");\n console.error(\" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)\");\n console.error(\"\");\n console.error(\"Project runner mode:\");\n console.error(\" CONVEYOR_PROJECT_TOKEN - Project token for project runner\");\n console.error(\" CONVEYOR_PROJECT_ID - Project ID for project runner\");\n process.exit(1);\n }\n\n if (CONVEYOR_MODE !== \"task\" && CONVEYOR_MODE !== \"pm\") {\n console.error(`Invalid CONVEYOR_MODE: \"${CONVEYOR_MODE}\". Must be \"task\" or \"pm\".`);\n process.exit(1);\n }\n\n console.log(`[conveyor-agent] Starting in ${CONVEYOR_MODE} mode`);\n\n const runner = new AgentRunner(\n {\n conveyorApiUrl: conveyorApiUrl!,\n taskToken: CONVEYOR_TASK_TOKEN,\n taskId: CONVEYOR_TASK_ID,\n model: CONVEYOR_MODEL,\n instructions: CONVEYOR_INSTRUCTIONS,\n workspaceDir: CONVEYOR_WORKSPACE,\n mode: CONVEYOR_MODE,\n isAuto: CONVEYOR_IS_AUTO,\n },\n {\n onEvent: (event: AgentEvent) => {\n const detail =\n \"message\" in event\n ? event.message\n : \"content\" in event\n ? event.content\n : \"summary\" in event\n ? event.summary\n : \"\";\n console.log(`[${event.type}] ${detail}`);\n },\n onStatusChange: (status: AgentRunnerStatus) => {\n console.log(`[status] ${status}`);\n },\n },\n );\n\n process.on(\"SIGTERM\", () => {\n console.log(\"Received SIGTERM, stopping agent...\");\n runner.stop();\n });\n\n process.on(\"SIGINT\", () => {\n console.log(\"Received SIGINT, stopping agent...\");\n runner.stop();\n });\n\n runner.start().catch((error: unknown) => {\n console.error(\"Agent runner failed:\", error);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { AgentRunner } from \"./runner/index.js\";\nimport { ProjectRunner } from \"./runner/index.js\";\nimport type { AgentEvent, AgentRunnerStatus, RunnerMode } from \"./types.js\";\nimport { createServiceLogger, errorMeta } from \"./utils/logger.js\";\n\n// Handle --version flag before any other initialization\nif (process.argv.includes(\"--version\")) {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n process.stdout.write(pkg.version + \"\\n\");\n process.exit(0);\n}\n\nconst logger = createServiceLogger(\"CLI\");\n\nfunction loadConveyorEnvFile(workspaceDir: string): void {\n const envPath = join(workspaceDir, \".conveyor\", \"env\");\n if (!existsSync(envPath)) return;\n try {\n const content = readFileSync(envPath, \"utf-8\");\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx < 1) continue;\n const key = trimmed.slice(0, eqIdx);\n const value = trimmed.slice(eqIdx + 1);\n process.env[key] = value;\n }\n logger.info(\"Loaded env overrides from .conveyor/env\");\n } catch {\n // File unreadable — fall through to containerEnv / defaults\n }\n}\n\nasync function bootstrapFromCodespace(apiUrl: string): Promise<void> {\n logger.info(\"Bootstrapping from codespace\", { codespace: process.env.CODESPACE_NAME });\n const response = await fetch(`${apiUrl}/api/codespace/bootstrap/${process.env.CODESPACE_NAME}`);\n if (!response.ok) {\n const errorText = await response.text();\n logger.error(\"Bootstrap failed\", { status: response.status, body: errorText });\n process.exit(1);\n }\n const config = (await response.json()) as {\n mode?: \"task\" | \"project\";\n taskId?: string;\n taskToken?: string;\n agentMode?: string;\n isAuto?: string;\n taskBranch?: string;\n projectId?: string;\n projectToken?: string;\n apiUrl?: string;\n workspaceBranch?: string;\n envVars: Record<string, string>;\n };\n\n // Apply shared env vars first\n for (const [key, value] of Object.entries(config.envVars ?? {})) {\n process.env[key] = value;\n }\n\n if (config.mode === \"project\") {\n // Project codespace → set project runner env vars\n process.env.CONVEYOR_PROJECT_TOKEN = config.projectToken;\n process.env.CONVEYOR_PROJECT_ID = config.projectId;\n if (config.workspaceBranch) {\n process.env.CONVEYOR_WORKSPACE_BRANCH = config.workspaceBranch;\n }\n logger.info(\"Bootstrap complete\", { projectId: config.projectId });\n } else {\n // Task codespace → existing behavior\n process.env.CONVEYOR_TASK_ID = config.taskId;\n process.env.CONVEYOR_TASK_TOKEN = config.taskToken;\n process.env.CONVEYOR_AGENT_MODE = config.agentMode;\n process.env.CONVEYOR_IS_AUTO = config.isAuto;\n if (config.taskBranch) {\n process.env.CONVEYOR_TASK_BRANCH = config.taskBranch;\n }\n logger.info(\"Bootstrap complete\", { taskId: config.taskId });\n }\n}\n\nprocess.on(\"uncaughtException\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EPIPE\") return;\n logger.error(\"Uncaught exception\", { error: err.message, code: err.code });\n process.exit(1);\n});\n\n// Load .conveyor/env overrides (e.g. CONVEYOR_API_URL) before reading env vars.\n// This file is committed to the task branch by the Conveyor API and lets the\n// agent reach the correct API without modifying devcontainer.json (which would\n// invalidate GitHub prebuild caches).\nloadConveyorEnvFile(process.env.CONVEYOR_WORKSPACE ?? process.cwd());\n\nlet conveyorApiUrl = process.env.CONVEYOR_API_URL;\n\n// Step 1: Codespace bootstrap (before project runner check)\n// Bootstrap runs when in a codespace and neither token is already set.\n// This allows the bootstrap endpoint to return either task or project credentials.\nif (\n process.env.CODESPACE_NAME &&\n !process.env.CONVEYOR_TASK_TOKEN &&\n !process.env.CONVEYOR_PROJECT_TOKEN\n) {\n if (!conveyorApiUrl) {\n logger.error(\"CONVEYOR_API_URL is required for codespace bootstrap\");\n process.exit(1);\n }\n await bootstrapFromCodespace(conveyorApiUrl);\n conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;\n}\n\n// Step 2: Re-read env vars (bootstrap may have set them)\nconst CONVEYOR_PROJECT_TOKEN = process.env.CONVEYOR_PROJECT_TOKEN;\nconst CONVEYOR_PROJECT_ID = process.env.CONVEYOR_PROJECT_ID;\n\n// Step 3: Branch on mode\nif (CONVEYOR_PROJECT_TOKEN && CONVEYOR_PROJECT_ID) {\n // Project runner mode: connect once, auto-handle tasks\n const projectRunner = new ProjectRunner({\n conveyorApiUrl: conveyorApiUrl ?? \"\",\n projectToken: CONVEYOR_PROJECT_TOKEN,\n projectId: CONVEYOR_PROJECT_ID,\n projectDir: process.env.CONVEYOR_WORKSPACE ?? process.cwd(),\n });\n\n projectRunner.start().catch((error: unknown) => {\n logger.error(\"Project runner failed\", errorMeta(error));\n process.exit(1);\n });\n} else {\n // Standard per-task agent mode\n const CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\n const CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\n const CONVEYOR_MODEL = process.env.CONVEYOR_MODEL ?? \"claude-sonnet-4-20250514\";\n const CONVEYOR_INSTRUCTIONS = process.env.CONVEYOR_INSTRUCTIONS ?? \"\";\n const CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\n const CONVEYOR_MODE = (process.env.CONVEYOR_MODE ?? \"task\") as RunnerMode;\n const CONVEYOR_AGENT_MODE = process.env.CONVEYOR_AGENT_MODE || undefined;\n const CONVEYOR_IS_AUTO = CONVEYOR_AGENT_MODE\n ? CONVEYOR_AGENT_MODE === \"auto\"\n : process.env.CONVEYOR_IS_AUTO === \"true\";\n\n if (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {\n logger.error(\"Missing required environment variables\");\n logger.error(\" CONVEYOR_TASK_TOKEN - JWT token for task authentication\");\n logger.error(\" CONVEYOR_TASK_ID - ID of the task to execute\");\n logger.error(\"\");\n logger.error(\"CONVEYOR_API_URL is provided via codespace secret or bootstrap.\");\n logger.error(\"\");\n logger.error(\"Optional:\");\n logger.error(\" CONVEYOR_MODE - Runner mode: 'task' (default) or 'pm'\");\n logger.error(\" CONVEYOR_MODEL - Claude model to use\");\n logger.error(\" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)\");\n logger.error(\"\");\n logger.error(\"Project runner mode:\");\n logger.error(\" CONVEYOR_PROJECT_TOKEN - Project token for project runner\");\n logger.error(\" CONVEYOR_PROJECT_ID - Project ID for project runner\");\n process.exit(1);\n }\n\n if (CONVEYOR_MODE !== \"task\" && CONVEYOR_MODE !== \"pm\") {\n logger.error(\"Invalid CONVEYOR_MODE\", { mode: CONVEYOR_MODE, expected: [\"task\", \"pm\"] });\n process.exit(1);\n }\n\n logger.info(\"Starting agent\", { mode: CONVEYOR_MODE });\n\n const runner = new AgentRunner(\n {\n conveyorApiUrl: conveyorApiUrl ?? \"\",\n taskToken: CONVEYOR_TASK_TOKEN,\n taskId: CONVEYOR_TASK_ID,\n model: CONVEYOR_MODEL,\n instructions: CONVEYOR_INSTRUCTIONS,\n workspaceDir: CONVEYOR_WORKSPACE,\n mode: CONVEYOR_MODE,\n isAuto: CONVEYOR_IS_AUTO,\n },\n {\n onEvent: (event: AgentEvent) => {\n const detail =\n \"message\" in event\n ? event.message\n : \"content\" in event\n ? event.content\n : \"summary\" in event\n ? event.summary\n : \"\";\n logger.info(detail, { eventType: event.type });\n },\n onStatusChange: (status: AgentRunnerStatus) => {\n logger.info(\"Status changed\", { status });\n },\n },\n );\n\n process.on(\"SIGTERM\", () => {\n logger.info(\"Received SIGTERM, stopping agent\");\n runner.stop();\n });\n\n process.on(\"SIGINT\", () => {\n logger.info(\"Received SIGINT, stopping agent\");\n runner.stop();\n });\n\n runner.start().catch((error: unknown) => {\n logger.error(\"Agent runner failed\", errorMeta(error));\n process.exit(1);\n });\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -90,6 +90,7 @@ declare class ProjectRunner {
90
90
  private stopping;
91
91
  private resolveLifecycle;
92
92
  constructor(config: ProjectRunnerConfig);
93
+ private checkoutWorkspaceBranch;
93
94
  start(): Promise<void>;
94
95
  private handleAssignment;
95
96
  private handleStopTask;
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  removeWorktree,
10
10
  runSetupCommand,
11
11
  runStartCommand
12
- } from "./chunk-VJRAWAWQ.js";
12
+ } from "./chunk-JI4AW4WX.js";
13
13
  export {
14
14
  AgentRunner,
15
15
  ConveyorConnection,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-agent",
3
- "version": "4.10.2",
3
+ "version": "5.0.1",
4
4
  "description": "Conveyor cloud build agent runner - executes task plans inside GitHub Codespaces",
5
5
  "keywords": [
6
6
  "agent",