@rallycry/conveyor-agent 7.3.8 → 7.3.9
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/{chunk-RX7NQCWK.js → chunk-Y6IHF32X.js} +709 -145
- package/dist/chunk-Y6IHF32X.js.map +1 -0
- package/dist/cli.js +16 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-RX7NQCWK.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
loadForwardPorts,
|
|
8
8
|
runSetupCommand,
|
|
9
9
|
runStartCommand
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-Y6IHF32X.js";
|
|
11
11
|
import "./chunk-FDWECEDJ.js";
|
|
12
12
|
import {
|
|
13
13
|
createServiceLogger
|
|
@@ -54,8 +54,14 @@ if (process.argv.includes("--version")) {
|
|
|
54
54
|
}
|
|
55
55
|
var logger = createServiceLogger("CLI");
|
|
56
56
|
async function bootstrapFromCodespace(apiUrl, instanceName) {
|
|
57
|
-
logger.info("Bootstrapping from codespace", { codespace: instanceName });
|
|
58
57
|
const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;
|
|
58
|
+
const apiUrlFromEnv = Boolean(process.env.CONVEYOR_API_URL);
|
|
59
|
+
logger.info("Bootstrapping from codespace", {
|
|
60
|
+
codespace: instanceName,
|
|
61
|
+
apiUrl,
|
|
62
|
+
apiUrlFromEnv,
|
|
63
|
+
bootstrapTokenPresent: Boolean(bootstrapToken)
|
|
64
|
+
});
|
|
59
65
|
const headers = {};
|
|
60
66
|
if (bootstrapToken) {
|
|
61
67
|
headers["x-codespace-token"] = bootstrapToken;
|
|
@@ -63,7 +69,14 @@ async function bootstrapFromCodespace(apiUrl, instanceName) {
|
|
|
63
69
|
const response = await fetch(`${apiUrl}/api/codespace/bootstrap/${instanceName}`, { headers });
|
|
64
70
|
if (!response.ok) {
|
|
65
71
|
const errorText = await response.text();
|
|
66
|
-
logger.error("Bootstrap failed", {
|
|
72
|
+
logger.error("Bootstrap failed", {
|
|
73
|
+
status: response.status,
|
|
74
|
+
body: errorText.slice(0, 500),
|
|
75
|
+
apiUrl,
|
|
76
|
+
apiUrlFromEnv,
|
|
77
|
+
bootstrapTokenPresent: Boolean(bootstrapToken),
|
|
78
|
+
hint: apiUrlFromEnv ? "Verify the codespace was created by this Conveyor deployment and that the bootstrap token is current." : "CONVEYOR_API_URL was not set as a codespace secret \u2014 agent fell back to the built-in default. Re-create the codespace, or push CONVEYOR_API_URL via project settings."
|
|
79
|
+
});
|
|
67
80
|
process.exit(1);
|
|
68
81
|
}
|
|
69
82
|
const config = await response.json();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/utils/session-identity.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { SessionRunner } from \"./runner/session-runner.js\";\nimport { ProjectRunner } from \"./runner/project-runner.js\";\nimport type { AgentRunnerStatus, RunnerMode } from \"@project/shared\";\nimport { createServiceLogger } from \"./utils/logger.js\";\nimport { buildSessionPreviewPorts, loadConveyorConfig, loadForwardPorts } from \"./setup/config.js\";\nimport { runSetupCommand, runStartCommand } from \"./setup/commands.js\";\nimport { checkSessionTaskIdentity } from \"./utils/session-identity.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\nasync function bootstrapFromCodespace(apiUrl: string, instanceName: string): Promise<void> {\n logger.info(\"Bootstrapping from codespace\", { codespace: instanceName });\n const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;\n const headers: Record<string, string> = {};\n if (bootstrapToken) {\n headers[\"x-codespace-token\"] = bootstrapToken;\n }\n const response = await fetch(`${apiUrl}/api/codespace/bootstrap/${instanceName}`, { headers });\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 sessionId?: string;\n taskToken?: string;\n runnerMode?: 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 for (const [key, value] of Object.entries(config.envVars ?? {})) {\n process.env[key] = value;\n }\n\n if (config.mode === \"project\") {\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 (project mode)\", { projectId: config.projectId });\n } else {\n process.env.CONVEYOR_TASK_ID = config.taskId;\n if (config.sessionId) {\n process.env.CONVEYOR_SESSION_ID = config.sessionId;\n }\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.runnerMode) {\n process.env.CONVEYOR_MODE = config.runnerMode;\n }\n if (config.taskBranch) {\n process.env.CONVEYOR_TASK_BRANCH = config.taskBranch;\n }\n logger.info(\"Bootstrap complete\", { taskId: config.taskId });\n }\n}\n\n// Helper to detect expected abort errors from SDK cleanup\nfunction isExpectedAbortError(error: Error | NodeJS.ErrnoException): boolean {\n const message = error.message || \"\";\n const hasAbortMessage = /operation aborted/i.test(message) || /abort/i.test(message);\n const hasAbortCode = !(\"code\" in error) || error.code === undefined || error.code === \"ABORT_ERR\";\n return hasAbortMessage && hasAbortCode;\n}\n\nprocess.on(\"uncaughtException\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EPIPE\") return;\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort after shutdown\", { error: err.message, code: err.code });\n return;\n }\n\n logger.error(\"Uncaught exception\", { error: err.message, code: err.code });\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", (reason: unknown) => {\n const err = reason instanceof Error ? reason : new Error(String(reason));\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort rejection after shutdown\", { error: err.message });\n return;\n }\n\n logger.error(\"Unhandled rejection\", { error: err.message });\n process.exit(1);\n});\n\nconst DEFAULT_CONVEYOR_API_URL = \"https://api.conveyor.rallycryapp.com\";\nlet conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;\n\n// Step 1: Codespace bootstrap\nconst INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;\nif (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN && !process.env.CONVEYOR_PROJECT_TOKEN) {\n if (!conveyorApiUrl) {\n logger.error(\"Could not resolve CONVEYOR_API_URL for codespace bootstrap\");\n process.exit(1);\n }\n await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);\n conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;\n}\n\n// Step 2: 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 const CONVEYOR_PROJECT_DIR = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\n\n if (!conveyorApiUrl) {\n logger.error(\"Could not resolve CONVEYOR_API_URL for project runner mode\");\n process.exit(1);\n }\n\n logger.info(\"Starting project runner\", { projectId: CONVEYOR_PROJECT_ID });\n\n const runner = new ProjectRunner({\n conveyorApiUrl,\n projectToken: CONVEYOR_PROJECT_TOKEN,\n projectId: CONVEYOR_PROJECT_ID,\n projectDir: CONVEYOR_PROJECT_DIR,\n });\n\n process.on(\"SIGTERM\", () => {\n logger.info(\"Received SIGTERM, stopping project runner\");\n void runner.stop();\n setTimeout(() => {\n logger.warn(\"Forcing exit after SIGTERM timeout\");\n process.exit(1);\n }, 40_000).unref();\n });\n\n process.on(\"SIGINT\", () => {\n logger.info(\"Received SIGINT, stopping project runner\");\n void runner.stop();\n setTimeout(() => {\n logger.warn(\"Forcing exit after SIGINT timeout\");\n process.exit(1);\n }, 40_000).unref();\n });\n\n runner.start().catch((error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(\"Project runner failed\", { error: msg });\n process.exit(1);\n });\n} else {\n const CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\n const CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\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_WORKSPACE - Working directory (defaults to cwd)\");\n process.exit(1);\n }\n\n if (CONVEYOR_MODE !== \"task\" && CONVEYOR_MODE !== \"pm\" && CONVEYOR_MODE !== \"code-review\") {\n logger.error(\"Invalid CONVEYOR_MODE\", {\n mode: CONVEYOR_MODE,\n expected: [\"task\", \"pm\", \"code-review\"],\n });\n process.exit(1);\n }\n\n logger.info(\"Starting agent\", { mode: CONVEYOR_MODE });\n\n // Claudespace pods: longer idle timeout to stay alive for incoming messages\n const lifecycleOverrides = process.env.CLAUDESPACE_NAME\n ? { idleTimeoutMs: 60 * 60 * 1000 }\n : undefined;\n\n const runner = new SessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: CONVEYOR_TASK_TOKEN,\n // CONVEYOR_SESSION_ID is the CodespaceSession ID for BaseService ACL.\n // Falls back to CONVEYOR_TASK_ID for backward compat (codespace bootstrap sets only task ID).\n sessionId: process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID,\n runnerMode: CONVEYOR_MODE,\n },\n runnerMode: CONVEYOR_MODE,\n isAuto: CONVEYOR_IS_AUTO,\n workspaceDir: CONVEYOR_WORKSPACE,\n agentMode: CONVEYOR_AGENT_MODE as import(\"@project/shared\").AgentMode | undefined,\n lifecycle: lifecycleOverrides,\n },\n {\n onStatusChange: (status: AgentRunnerStatus) => {\n logger.info(\"Status changed\", { status });\n },\n onEvent: (event: Record<string, unknown>) => {\n const detail =\n (event.message as string) ?? (event.content as string) ?? (event.summary as string) ?? \"\";\n if (detail) {\n logger.info(detail, { eventType: event.type as string });\n }\n },\n },\n );\n\n const shutdownAgent = (signal: \"SIGTERM\" | \"SIGINT\") => {\n logger.info(`Received ${signal}, flushing git and stopping agent`);\n // Flush WIP commit + push BEFORE stop() tears down the connection, since\n // the token-refresh RPC needs a live socket. Then stop the runner.\n void (async () => {\n try {\n await runner.flushGitOnShutdown();\n } finally {\n runner.stop();\n }\n })();\n setTimeout(() => {\n logger.warn(`Forcing exit after ${signal} timeout`);\n process.exit(1);\n }, 45_000).unref();\n };\n\n process.on(\"SIGTERM\", () => shutdownAgent(\"SIGTERM\"));\n process.on(\"SIGINT\", () => shutdownAgent(\"SIGINT\"));\n\n // Connect first so setup/start output is forwarded to the API\n await runner.connect();\n\n // Defense-in-depth: warn loudly if CONVEYOR_SESSION_ID decodes to a different\n // task than CONVEYOR_TASK_ID. Authoritative checks are server-side\n // (requireTaskAuth + partial-unique index on active CodespaceSessions). This\n // is a visibility net in case those regress — see SEC-9 postmortem in\n // .claude/rules/agent-codespace.md.\n void checkSessionTaskIdentity({\n sessionId: process.env.CONVEYOR_SESSION_ID,\n taskId: CONVEYOR_TASK_ID,\n fetchSessionTaskId: async (sessionId) => {\n const ctx = await runner.connection.call(\"getTaskContext\", { sessionId });\n return ctx.id;\n },\n logger,\n });\n\n // Run setup + start commands in the background so the agent can start\n // fetching context and thinking immediately. The dev environment will be\n // ready by the time the agent needs to actually execute anything in it.\n // Start command still runs after setup (install must finish before `bun\n // run dev` works), but both are decoupled from runner.run().\n //\n // INVARIANT: failures inside this IIFE are NON-FATAL. Any throw or non-zero\n // exit from setup/start must surface as a chat event, never as process.exit.\n // The agent continues so the user can still interact with it and debug.\n const conveyorConfig = loadConveyorConfig();\n if (conveyorConfig) {\n void (async () => {\n const logOutput = (stream: \"stdout\" | \"stderr\", data: string) => {\n runner.connection.sendEvent({ type: \"setup_output\", stream, data });\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n };\n if (conveyorConfig.setupCommand) {\n logger.info(\"Running setup command (background)\", {\n command: conveyorConfig.setupCommand,\n });\n try {\n await runSetupCommand(conveyorConfig.setupCommand, CONVEYOR_WORKSPACE, logOutput);\n logger.info(\"Setup command completed\");\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Setup command failed\";\n logger.error(\"Setup command failed\", { error: msg });\n runner.connection.sendEvent({ type: \"setup_error\", message: msg });\n }\n }\n\n let startCommandRunning = false;\n if (conveyorConfig.startCommand) {\n logger.info(\"Running start command\", { command: conveyorConfig.startCommand });\n const child = runStartCommand(\n conveyorConfig.startCommand,\n CONVEYOR_WORKSPACE,\n (stream, data) => {\n runner.connection.sendEvent({ type: \"start_command_output\", stream, data });\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n },\n );\n startCommandRunning = true;\n child.on(\"exit\", (code, signal) => {\n logger.info(\"Start command exited\", { code, signal });\n runner.connection.sendEvent({\n type: \"start_command_exited\",\n code,\n signal,\n message: `start command exited${code === null ? \"\" : ` with code ${code}`}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n // Surface non-zero exits as a loud chat message too, so users know\n // their dev server crashed and the agent may hit tool-use failures.\n if (code !== null && code !== 0) {\n runner.connection.sendEvent({\n type: \"start_command_error\",\n message: `start command exited with code ${code}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n }\n });\n child.on(\"error\", (err) => {\n logger.error(\"Start command error\", { error: err.message });\n runner.connection.sendEvent({ type: \"start_command_error\", message: err.message });\n });\n }\n\n const forwardPorts = await loadForwardPorts(CONVEYOR_WORKSPACE);\n const previewPorts = buildSessionPreviewPorts(forwardPorts);\n runner.connection.sendEvent({\n type: \"setup_complete\",\n startCommandRunning,\n previewPort: conveyorConfig.previewPort,\n ...(previewPorts.length > 0 ? { previewPorts } : {}),\n });\n })();\n }\n\n // Start the main agent lifecycle immediately in parallel with setup\n // (context fetch, mode resolution, core loop).\n runner\n .run()\n .then(() => {\n // Exit with code 0 for clean shutdown (entrypoint won't restart),\n // code 1 for errors (entrypoint will restart).\n process.exit(runner.finalState === \"error\" ? 1 : 0);\n })\n .catch((error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(\"Agent runner failed\", { error: msg });\n process.exit(1);\n });\n}\n","// Defense-in-depth startup check. The authoritative guarantee that a session is\n// bound to the right task lives server-side (requireTaskAuth + the Postgres\n// partial-unique index on active CodespaceSessions). This check exists so that\n// if those invariants ever regress, a human sees a loud WARN immediately\n// instead of the symptoms SEC-9 produced (multiple agents silently clobbering\n// the same branch).\nexport interface SessionIdentityLogger {\n warn(message: string, data?: Record<string, unknown>): void;\n info?(message: string, data?: Record<string, unknown>): void;\n}\n\nexport interface CheckSessionTaskIdentityParams {\n sessionId: string | undefined;\n taskId: string;\n fetchSessionTaskId: (sessionId: string) => Promise<string>;\n logger: SessionIdentityLogger;\n}\n\nexport async function checkSessionTaskIdentity(\n params: CheckSessionTaskIdentityParams,\n): Promise<\"match\" | \"mismatch\" | \"skipped\" | \"error\"> {\n const { sessionId, taskId, fetchSessionTaskId, logger } = params;\n if (!sessionId || sessionId === taskId) return \"skipped\";\n let sessionTaskId: string;\n try {\n sessionTaskId = await fetchSessionTaskId(sessionId);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.warn(\"Could not verify session/task identity — continuing (defense-in-depth only)\", {\n sessionId,\n taskId,\n error: message,\n });\n return \"error\";\n }\n if (sessionTaskId !== taskId) {\n logger.warn(\n \"!!! CONVEYOR_SESSION_ID is bound to a different task than CONVEYOR_TASK_ID — server-side guards should still block mutations, but this indicates a misconfiguration or replayed token.\",\n { sessionId, envTaskId: taskId, sessionTaskId },\n );\n return \"mismatch\";\n }\n return \"match\";\n}\n"],"mappings":"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","names":["logger"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/utils/session-identity.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { SessionRunner } from \"./runner/session-runner.js\";\nimport { ProjectRunner } from \"./runner/project-runner.js\";\nimport type { AgentRunnerStatus, RunnerMode } from \"@project/shared\";\nimport { createServiceLogger } from \"./utils/logger.js\";\nimport { buildSessionPreviewPorts, loadConveyorConfig, loadForwardPorts } from \"./setup/config.js\";\nimport { runSetupCommand, runStartCommand } from \"./setup/commands.js\";\nimport { checkSessionTaskIdentity } from \"./utils/session-identity.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\nasync function bootstrapFromCodespace(apiUrl: string, instanceName: string): Promise<void> {\n const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;\n const apiUrlFromEnv = Boolean(process.env.CONVEYOR_API_URL);\n logger.info(\"Bootstrapping from codespace\", {\n codespace: instanceName,\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n });\n const headers: Record<string, string> = {};\n if (bootstrapToken) {\n headers[\"x-codespace-token\"] = bootstrapToken;\n }\n const response = await fetch(`${apiUrl}/api/codespace/bootstrap/${instanceName}`, { headers });\n if (!response.ok) {\n const errorText = await response.text();\n logger.error(\"Bootstrap failed\", {\n status: response.status,\n body: errorText.slice(0, 500),\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n hint: apiUrlFromEnv\n ? \"Verify the codespace was created by this Conveyor deployment and that the bootstrap token is current.\"\n : \"CONVEYOR_API_URL was not set as a codespace secret — agent fell back to the built-in default. Re-create the codespace, or push CONVEYOR_API_URL via project settings.\",\n });\n process.exit(1);\n }\n const config = (await response.json()) as {\n mode?: \"task\" | \"project\";\n taskId?: string;\n sessionId?: string;\n taskToken?: string;\n runnerMode?: 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 for (const [key, value] of Object.entries(config.envVars ?? {})) {\n process.env[key] = value;\n }\n\n if (config.mode === \"project\") {\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 (project mode)\", { projectId: config.projectId });\n } else {\n process.env.CONVEYOR_TASK_ID = config.taskId;\n if (config.sessionId) {\n process.env.CONVEYOR_SESSION_ID = config.sessionId;\n }\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.runnerMode) {\n process.env.CONVEYOR_MODE = config.runnerMode;\n }\n if (config.taskBranch) {\n process.env.CONVEYOR_TASK_BRANCH = config.taskBranch;\n }\n logger.info(\"Bootstrap complete\", { taskId: config.taskId });\n }\n}\n\n// Helper to detect expected abort errors from SDK cleanup\nfunction isExpectedAbortError(error: Error | NodeJS.ErrnoException): boolean {\n const message = error.message || \"\";\n const hasAbortMessage = /operation aborted/i.test(message) || /abort/i.test(message);\n const hasAbortCode = !(\"code\" in error) || error.code === undefined || error.code === \"ABORT_ERR\";\n return hasAbortMessage && hasAbortCode;\n}\n\nprocess.on(\"uncaughtException\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EPIPE\") return;\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort after shutdown\", { error: err.message, code: err.code });\n return;\n }\n\n logger.error(\"Uncaught exception\", { error: err.message, code: err.code });\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", (reason: unknown) => {\n const err = reason instanceof Error ? reason : new Error(String(reason));\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort rejection after shutdown\", { error: err.message });\n return;\n }\n\n logger.error(\"Unhandled rejection\", { error: err.message });\n process.exit(1);\n});\n\nconst DEFAULT_CONVEYOR_API_URL = \"https://api.conveyor.rallycryapp.com\";\nlet conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;\n\n// Step 1: Codespace bootstrap\nconst INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;\nif (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN && !process.env.CONVEYOR_PROJECT_TOKEN) {\n if (!conveyorApiUrl) {\n logger.error(\"Could not resolve CONVEYOR_API_URL for codespace bootstrap\");\n process.exit(1);\n }\n await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);\n conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;\n}\n\n// Step 2: 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 const CONVEYOR_PROJECT_DIR = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\n\n if (!conveyorApiUrl) {\n logger.error(\"Could not resolve CONVEYOR_API_URL for project runner mode\");\n process.exit(1);\n }\n\n logger.info(\"Starting project runner\", { projectId: CONVEYOR_PROJECT_ID });\n\n const runner = new ProjectRunner({\n conveyorApiUrl,\n projectToken: CONVEYOR_PROJECT_TOKEN,\n projectId: CONVEYOR_PROJECT_ID,\n projectDir: CONVEYOR_PROJECT_DIR,\n });\n\n process.on(\"SIGTERM\", () => {\n logger.info(\"Received SIGTERM, stopping project runner\");\n void runner.stop();\n setTimeout(() => {\n logger.warn(\"Forcing exit after SIGTERM timeout\");\n process.exit(1);\n }, 40_000).unref();\n });\n\n process.on(\"SIGINT\", () => {\n logger.info(\"Received SIGINT, stopping project runner\");\n void runner.stop();\n setTimeout(() => {\n logger.warn(\"Forcing exit after SIGINT timeout\");\n process.exit(1);\n }, 40_000).unref();\n });\n\n runner.start().catch((error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(\"Project runner failed\", { error: msg });\n process.exit(1);\n });\n} else {\n const CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\n const CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\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_WORKSPACE - Working directory (defaults to cwd)\");\n process.exit(1);\n }\n\n if (CONVEYOR_MODE !== \"task\" && CONVEYOR_MODE !== \"pm\" && CONVEYOR_MODE !== \"code-review\") {\n logger.error(\"Invalid CONVEYOR_MODE\", {\n mode: CONVEYOR_MODE,\n expected: [\"task\", \"pm\", \"code-review\"],\n });\n process.exit(1);\n }\n\n logger.info(\"Starting agent\", { mode: CONVEYOR_MODE });\n\n // Claudespace pods: longer idle timeout to stay alive for incoming messages\n const lifecycleOverrides = process.env.CLAUDESPACE_NAME\n ? { idleTimeoutMs: 60 * 60 * 1000 }\n : undefined;\n\n const runner = new SessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: CONVEYOR_TASK_TOKEN,\n // CONVEYOR_SESSION_ID is the CodespaceSession ID for BaseService ACL.\n // Falls back to CONVEYOR_TASK_ID for backward compat (codespace bootstrap sets only task ID).\n sessionId: process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID,\n runnerMode: CONVEYOR_MODE,\n },\n runnerMode: CONVEYOR_MODE,\n isAuto: CONVEYOR_IS_AUTO,\n workspaceDir: CONVEYOR_WORKSPACE,\n agentMode: CONVEYOR_AGENT_MODE as import(\"@project/shared\").AgentMode | undefined,\n lifecycle: lifecycleOverrides,\n },\n {\n onStatusChange: (status: AgentRunnerStatus) => {\n logger.info(\"Status changed\", { status });\n },\n onEvent: (event: Record<string, unknown>) => {\n const detail =\n (event.message as string) ?? (event.content as string) ?? (event.summary as string) ?? \"\";\n if (detail) {\n logger.info(detail, { eventType: event.type as string });\n }\n },\n },\n );\n\n const shutdownAgent = (signal: \"SIGTERM\" | \"SIGINT\") => {\n logger.info(`Received ${signal}, flushing git and stopping agent`);\n // Flush WIP commit + push BEFORE stop() tears down the connection, since\n // the token-refresh RPC needs a live socket. Then stop the runner.\n void (async () => {\n try {\n await runner.flushGitOnShutdown();\n } finally {\n runner.stop();\n }\n })();\n setTimeout(() => {\n logger.warn(`Forcing exit after ${signal} timeout`);\n process.exit(1);\n }, 45_000).unref();\n };\n\n process.on(\"SIGTERM\", () => shutdownAgent(\"SIGTERM\"));\n process.on(\"SIGINT\", () => shutdownAgent(\"SIGINT\"));\n\n // Connect first so setup/start output is forwarded to the API\n await runner.connect();\n\n // Defense-in-depth: warn loudly if CONVEYOR_SESSION_ID decodes to a different\n // task than CONVEYOR_TASK_ID. Authoritative checks are server-side\n // (requireTaskAuth + partial-unique index on active CodespaceSessions). This\n // is a visibility net in case those regress — see SEC-9 postmortem in\n // .claude/rules/agent-codespace.md.\n void checkSessionTaskIdentity({\n sessionId: process.env.CONVEYOR_SESSION_ID,\n taskId: CONVEYOR_TASK_ID,\n fetchSessionTaskId: async (sessionId) => {\n const ctx = await runner.connection.call(\"getTaskContext\", { sessionId });\n return ctx.id;\n },\n logger,\n });\n\n // Run setup + start commands in the background so the agent can start\n // fetching context and thinking immediately. The dev environment will be\n // ready by the time the agent needs to actually execute anything in it.\n // Start command still runs after setup (install must finish before `bun\n // run dev` works), but both are decoupled from runner.run().\n //\n // INVARIANT: failures inside this IIFE are NON-FATAL. Any throw or non-zero\n // exit from setup/start must surface as a chat event, never as process.exit.\n // The agent continues so the user can still interact with it and debug.\n const conveyorConfig = loadConveyorConfig();\n if (conveyorConfig) {\n void (async () => {\n const logOutput = (stream: \"stdout\" | \"stderr\", data: string) => {\n runner.connection.sendEvent({ type: \"setup_output\", stream, data });\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n };\n if (conveyorConfig.setupCommand) {\n logger.info(\"Running setup command (background)\", {\n command: conveyorConfig.setupCommand,\n });\n try {\n await runSetupCommand(conveyorConfig.setupCommand, CONVEYOR_WORKSPACE, logOutput);\n logger.info(\"Setup command completed\");\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Setup command failed\";\n logger.error(\"Setup command failed\", { error: msg });\n runner.connection.sendEvent({ type: \"setup_error\", message: msg });\n }\n }\n\n let startCommandRunning = false;\n if (conveyorConfig.startCommand) {\n logger.info(\"Running start command\", { command: conveyorConfig.startCommand });\n const child = runStartCommand(\n conveyorConfig.startCommand,\n CONVEYOR_WORKSPACE,\n (stream, data) => {\n runner.connection.sendEvent({ type: \"start_command_output\", stream, data });\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n },\n );\n startCommandRunning = true;\n child.on(\"exit\", (code, signal) => {\n logger.info(\"Start command exited\", { code, signal });\n runner.connection.sendEvent({\n type: \"start_command_exited\",\n code,\n signal,\n message: `start command exited${code === null ? \"\" : ` with code ${code}`}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n // Surface non-zero exits as a loud chat message too, so users know\n // their dev server crashed and the agent may hit tool-use failures.\n if (code !== null && code !== 0) {\n runner.connection.sendEvent({\n type: \"start_command_error\",\n message: `start command exited with code ${code}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n }\n });\n child.on(\"error\", (err) => {\n logger.error(\"Start command error\", { error: err.message });\n runner.connection.sendEvent({ type: \"start_command_error\", message: err.message });\n });\n }\n\n const forwardPorts = await loadForwardPorts(CONVEYOR_WORKSPACE);\n const previewPorts = buildSessionPreviewPorts(forwardPorts);\n runner.connection.sendEvent({\n type: \"setup_complete\",\n startCommandRunning,\n previewPort: conveyorConfig.previewPort,\n ...(previewPorts.length > 0 ? { previewPorts } : {}),\n });\n })();\n }\n\n // Start the main agent lifecycle immediately in parallel with setup\n // (context fetch, mode resolution, core loop).\n runner\n .run()\n .then(() => {\n // Exit with code 0 for clean shutdown (entrypoint won't restart),\n // code 1 for errors (entrypoint will restart).\n process.exit(runner.finalState === \"error\" ? 1 : 0);\n })\n .catch((error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(\"Agent runner failed\", { error: msg });\n process.exit(1);\n });\n}\n","// Defense-in-depth startup check. The authoritative guarantee that a session is\n// bound to the right task lives server-side (requireTaskAuth + the Postgres\n// partial-unique index on active CodespaceSessions). This check exists so that\n// if those invariants ever regress, a human sees a loud WARN immediately\n// instead of the symptoms SEC-9 produced (multiple agents silently clobbering\n// the same branch).\nexport interface SessionIdentityLogger {\n warn(message: string, data?: Record<string, unknown>): void;\n info?(message: string, data?: Record<string, unknown>): void;\n}\n\nexport interface CheckSessionTaskIdentityParams {\n sessionId: string | undefined;\n taskId: string;\n fetchSessionTaskId: (sessionId: string) => Promise<string>;\n logger: SessionIdentityLogger;\n}\n\nexport async function checkSessionTaskIdentity(\n params: CheckSessionTaskIdentityParams,\n): Promise<\"match\" | \"mismatch\" | \"skipped\" | \"error\"> {\n const { sessionId, taskId, fetchSessionTaskId, logger } = params;\n if (!sessionId || sessionId === taskId) return \"skipped\";\n let sessionTaskId: string;\n try {\n sessionTaskId = await fetchSessionTaskId(sessionId);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.warn(\"Could not verify session/task identity — continuing (defense-in-depth only)\", {\n sessionId,\n taskId,\n error: message,\n });\n return \"error\";\n }\n if (sessionTaskId !== taskId) {\n logger.warn(\n \"!!! CONVEYOR_SESSION_ID is bound to a different task than CONVEYOR_TASK_ID — server-side guards should still block mutations, but this indicates a misconfiguration or replayed token.\",\n { sessionId, envTaskId: taskId, sessionTaskId },\n );\n return \"mismatch\";\n }\n return \"match\";\n}\n"],"mappings":"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","names":["logger"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -395,6 +395,9 @@ interface IncomingChatMessage {
|
|
|
395
395
|
userId: string;
|
|
396
396
|
chatId?: string;
|
|
397
397
|
projectId: string;
|
|
398
|
+
/** When set, only the runner whose session matches should react. Other
|
|
399
|
+
* runners on the same project room must ignore the message. */
|
|
400
|
+
targetSessionId?: string | null;
|
|
398
401
|
timestamp: string;
|
|
399
402
|
}
|
|
400
403
|
interface SwitchBranchRequest {
|
|
@@ -457,6 +460,10 @@ declare class ProjectRunner {
|
|
|
457
460
|
private stopping;
|
|
458
461
|
private resolveLifecycle;
|
|
459
462
|
private chatSessionIds;
|
|
463
|
+
/** ProjectCodespaceSession id assigned at register time. Used to filter
|
|
464
|
+
* targeted incoming chat messages so we only react to ones addressed
|
|
465
|
+
* to this specific runner. */
|
|
466
|
+
private projectSessionId;
|
|
460
467
|
private startCmd;
|
|
461
468
|
private setupComplete;
|
|
462
469
|
private branchSwitchCommand;
|
package/dist/index.js
CHANGED