@contextgraph/agent 0.4.15 → 0.4.17
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/index.js +14 -157
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -975,7 +975,7 @@ var LogTransportService = class {
|
|
|
975
975
|
/**
|
|
976
976
|
* Create a new run for an action
|
|
977
977
|
* @param actionId - The action ID this run is executing
|
|
978
|
-
* @param purpose - The purpose of this run: 'execute' | 'prepare' | '
|
|
978
|
+
* @param purpose - The purpose of this run: 'execute' | 'prepare' | 'review'
|
|
979
979
|
* @param metadata - Optional metadata for the run (e.g., startingCommit)
|
|
980
980
|
* @returns The created run ID
|
|
981
981
|
*/
|
|
@@ -1050,7 +1050,7 @@ var LogTransportService = class {
|
|
|
1050
1050
|
if (!this.runId) {
|
|
1051
1051
|
throw new Error("No run ID set. Call createRun() first.");
|
|
1052
1052
|
}
|
|
1053
|
-
if (state === "executing" || state === "preparing" || state === "running"
|
|
1053
|
+
if (state === "executing" || state === "preparing" || state === "running") {
|
|
1054
1054
|
await this.startRun();
|
|
1055
1055
|
} else if (state === "completed" || state === "failed") {
|
|
1056
1056
|
const outcome = state === "completed" ? "success" : "error";
|
|
@@ -1500,102 +1500,6 @@ ${errorText}`);
|
|
|
1500
1500
|
}
|
|
1501
1501
|
}
|
|
1502
1502
|
|
|
1503
|
-
// src/workflows/learn.ts
|
|
1504
|
-
var API_BASE_URL3 = "https://www.contextgraph.dev";
|
|
1505
|
-
async function runLearn(actionId, options) {
|
|
1506
|
-
const credentials = await loadCredentials();
|
|
1507
|
-
if (!credentials) {
|
|
1508
|
-
console.error("\u274C Not authenticated. Run authentication first.");
|
|
1509
|
-
process.exit(1);
|
|
1510
|
-
}
|
|
1511
|
-
if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {
|
|
1512
|
-
console.error("\u274C Token expired. Re-authenticate to continue.");
|
|
1513
|
-
process.exit(1);
|
|
1514
|
-
}
|
|
1515
|
-
const logTransport = new LogTransportService(API_BASE_URL3, credentials.clerkToken);
|
|
1516
|
-
let runId;
|
|
1517
|
-
let heartbeatManager;
|
|
1518
|
-
let logBuffer;
|
|
1519
|
-
try {
|
|
1520
|
-
console.log("[Log Streaming] Creating run for learn phase...");
|
|
1521
|
-
runId = await logTransport.createRun(actionId, "learn", {
|
|
1522
|
-
startingCommit: options?.startingCommit
|
|
1523
|
-
});
|
|
1524
|
-
console.log(`[Log Streaming] Run created: ${runId}`);
|
|
1525
|
-
console.log(`Fetching learning instructions for action ${actionId}...
|
|
1526
|
-
`);
|
|
1527
|
-
const response = await fetchWithRetry(
|
|
1528
|
-
`${API_BASE_URL3}/api/prompts/learn`,
|
|
1529
|
-
{
|
|
1530
|
-
method: "POST",
|
|
1531
|
-
headers: {
|
|
1532
|
-
"Authorization": `Bearer ${credentials.clerkToken}`,
|
|
1533
|
-
"Content-Type": "application/json"
|
|
1534
|
-
},
|
|
1535
|
-
body: JSON.stringify({ actionId, runId })
|
|
1536
|
-
}
|
|
1537
|
-
);
|
|
1538
|
-
if (!response.ok) {
|
|
1539
|
-
const errorText = await response.text();
|
|
1540
|
-
throw new Error(`Failed to fetch learn prompt: ${response.statusText}
|
|
1541
|
-
${errorText}`);
|
|
1542
|
-
}
|
|
1543
|
-
const { prompt } = await response.json();
|
|
1544
|
-
await logTransport.updateRunState("learning");
|
|
1545
|
-
heartbeatManager = new HeartbeatManager(API_BASE_URL3, credentials.clerkToken, runId);
|
|
1546
|
-
heartbeatManager.start();
|
|
1547
|
-
console.log("[Log Streaming] Heartbeat started");
|
|
1548
|
-
logBuffer = new LogBuffer(logTransport);
|
|
1549
|
-
logBuffer.start();
|
|
1550
|
-
console.log("Spawning Claude for learning extraction...\n");
|
|
1551
|
-
const claudeResult = await executeClaude({
|
|
1552
|
-
prompt,
|
|
1553
|
-
cwd: options?.cwd || process.cwd(),
|
|
1554
|
-
authToken: credentials.clerkToken,
|
|
1555
|
-
...options?.model ? { model: options.model } : {},
|
|
1556
|
-
onLogEvent: (event) => {
|
|
1557
|
-
logBuffer.push(event);
|
|
1558
|
-
}
|
|
1559
|
-
});
|
|
1560
|
-
if (claudeResult.exitCode === 0) {
|
|
1561
|
-
await logTransport.finishRun("success", {
|
|
1562
|
-
exitCode: claudeResult.exitCode,
|
|
1563
|
-
cost: claudeResult.cost,
|
|
1564
|
-
usage: claudeResult.usage
|
|
1565
|
-
});
|
|
1566
|
-
console.log("\n\u2705 Learning extraction complete");
|
|
1567
|
-
} else {
|
|
1568
|
-
await logTransport.finishRun("error", {
|
|
1569
|
-
exitCode: claudeResult.exitCode,
|
|
1570
|
-
errorMessage: `Claude learning extraction failed with exit code ${claudeResult.exitCode}`
|
|
1571
|
-
});
|
|
1572
|
-
console.error(`
|
|
1573
|
-
\u274C Claude learning extraction failed with exit code ${claudeResult.exitCode}`);
|
|
1574
|
-
process.exit(1);
|
|
1575
|
-
}
|
|
1576
|
-
} catch (error) {
|
|
1577
|
-
if (runId) {
|
|
1578
|
-
try {
|
|
1579
|
-
await logTransport.finishRun("error", {
|
|
1580
|
-
errorMessage: error instanceof Error ? error.message : String(error)
|
|
1581
|
-
});
|
|
1582
|
-
} catch (stateError) {
|
|
1583
|
-
console.error("[Log Streaming] Failed to update run state:", stateError);
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
throw error;
|
|
1587
|
-
} finally {
|
|
1588
|
-
if (heartbeatManager) {
|
|
1589
|
-
heartbeatManager.stop();
|
|
1590
|
-
console.log("[Log Streaming] Heartbeat stopped");
|
|
1591
|
-
}
|
|
1592
|
-
if (logBuffer) {
|
|
1593
|
-
await logBuffer.stop();
|
|
1594
|
-
console.log("[Log Streaming] Logs flushed");
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
1503
|
// src/workflows/agent.ts
|
|
1600
1504
|
import { randomUUID } from "crypto";
|
|
1601
1505
|
import { readFileSync } from "fs";
|
|
@@ -1607,7 +1511,7 @@ import { dirname, join as join3 } from "path";
|
|
|
1607
1511
|
// package.json
|
|
1608
1512
|
var package_default = {
|
|
1609
1513
|
name: "@contextgraph/agent",
|
|
1610
|
-
version: "0.4.
|
|
1514
|
+
version: "0.4.16",
|
|
1611
1515
|
description: "Autonomous agent for contextgraph action execution",
|
|
1612
1516
|
type: "module",
|
|
1613
1517
|
bin: {
|
|
@@ -1767,9 +1671,9 @@ import { spawn as spawn2 } from "child_process";
|
|
|
1767
1671
|
import { mkdtemp, rm } from "fs/promises";
|
|
1768
1672
|
import { tmpdir } from "os";
|
|
1769
1673
|
import { join as join2 } from "path";
|
|
1770
|
-
var
|
|
1674
|
+
var API_BASE_URL3 = "https://www.contextgraph.dev";
|
|
1771
1675
|
async function fetchGitHubCredentials(authToken) {
|
|
1772
|
-
const response = await fetchWithRetry(`${
|
|
1676
|
+
const response = await fetchWithRetry(`${API_BASE_URL3}/api/cli/credentials`, {
|
|
1773
1677
|
headers: {
|
|
1774
1678
|
"x-authorization": `Bearer ${authToken}`,
|
|
1775
1679
|
"Content-Type": "application/json"
|
|
@@ -1887,7 +1791,6 @@ var apiClient = null;
|
|
|
1887
1791
|
var stats = {
|
|
1888
1792
|
startTime: Date.now(),
|
|
1889
1793
|
prepared: 0,
|
|
1890
|
-
learned: 0,
|
|
1891
1794
|
executed: 0,
|
|
1892
1795
|
errors: 0
|
|
1893
1796
|
};
|
|
@@ -1904,8 +1807,8 @@ function formatDuration(ms) {
|
|
|
1904
1807
|
}
|
|
1905
1808
|
function printStatus() {
|
|
1906
1809
|
const uptime = formatDuration(Date.now() - stats.startTime);
|
|
1907
|
-
const total = stats.prepared + stats.
|
|
1908
|
-
console.log(`Status: ${total} actions (${stats.prepared} prepared, ${stats.
|
|
1810
|
+
const total = stats.prepared + stats.executed;
|
|
1811
|
+
console.log(`Status: ${total} actions (${stats.prepared} prepared, ${stats.executed} executed, ${stats.errors} errors) | Uptime: ${uptime}`);
|
|
1909
1812
|
}
|
|
1910
1813
|
async function cleanupAndExit() {
|
|
1911
1814
|
if (currentClaim && apiClient) {
|
|
@@ -1966,10 +1869,6 @@ async function runLocalAgent(options) {
|
|
|
1966
1869
|
console.log(`\u{1F477} Worker ID: ${workerId}`);
|
|
1967
1870
|
console.log(`\u{1F504} Starting continuous worker loop...
|
|
1968
1871
|
`);
|
|
1969
|
-
if (options?.skipLearning) {
|
|
1970
|
-
console.log(`\u23ED\uFE0F Skipping learning runs (--skip-learning)
|
|
1971
|
-
`);
|
|
1972
|
-
}
|
|
1973
1872
|
console.log(`\u{1F4A1} Press Ctrl+C to gracefully shutdown and release any claimed work
|
|
1974
1873
|
`);
|
|
1975
1874
|
let currentPollInterval = INITIAL_POLL_INTERVAL;
|
|
@@ -2018,7 +1917,6 @@ async function runLocalAgent(options) {
|
|
|
2018
1917
|
continue;
|
|
2019
1918
|
}
|
|
2020
1919
|
currentPollInterval = INITIAL_POLL_INTERVAL;
|
|
2021
|
-
console.log(`Working: ${actionDetail.title}`);
|
|
2022
1920
|
if (actionDetail.claim_id) {
|
|
2023
1921
|
currentClaim = {
|
|
2024
1922
|
actionId: actionDetail.id,
|
|
@@ -2027,17 +1925,12 @@ async function runLocalAgent(options) {
|
|
|
2027
1925
|
};
|
|
2028
1926
|
}
|
|
2029
1927
|
let phase;
|
|
2030
|
-
if (
|
|
2031
|
-
phase = "learn";
|
|
2032
|
-
} else if (!actionDetail.prepared) {
|
|
1928
|
+
if (!actionDetail.prepared) {
|
|
2033
1929
|
phase = "prepare";
|
|
2034
1930
|
} else if (!actionDetail.done) {
|
|
2035
1931
|
phase = "execute";
|
|
2036
1932
|
} else {
|
|
2037
|
-
|
|
2038
|
-
if (!isLearningOnlyAndSkipped) {
|
|
2039
|
-
console.log(`\u23ED\uFE0F Skipping action "${actionDetail.title}" - done but not yet reviewed`);
|
|
2040
|
-
}
|
|
1933
|
+
console.log(`\u23ED\uFE0F Skipping action "${actionDetail.title}" - already completed`);
|
|
2041
1934
|
if (currentClaim && apiClient) {
|
|
2042
1935
|
try {
|
|
2043
1936
|
await apiClient.releaseClaim({
|
|
@@ -2052,12 +1945,13 @@ async function runLocalAgent(options) {
|
|
|
2052
1945
|
currentClaim = null;
|
|
2053
1946
|
continue;
|
|
2054
1947
|
}
|
|
1948
|
+
console.log(`Working: ${actionDetail.title}`);
|
|
2055
1949
|
const repoUrl = actionDetail.resolved_repository_url || actionDetail.repository_url;
|
|
2056
1950
|
const branch = actionDetail.resolved_branch || actionDetail.branch;
|
|
2057
1951
|
let workspacePath;
|
|
2058
1952
|
let cleanup;
|
|
2059
1953
|
let startingCommit;
|
|
2060
|
-
const needsRepo =
|
|
1954
|
+
const needsRepo = repoUrl;
|
|
2061
1955
|
try {
|
|
2062
1956
|
if (needsRepo) {
|
|
2063
1957
|
const workspace = await prepareWorkspace(repoUrl, {
|
|
@@ -2068,11 +1962,7 @@ async function runLocalAgent(options) {
|
|
|
2068
1962
|
cleanup = workspace.cleanup;
|
|
2069
1963
|
startingCommit = workspace.startingCommit;
|
|
2070
1964
|
} else {
|
|
2071
|
-
|
|
2072
|
-
console.log(`\u{1F4C2} Learning phase - creating blank workspace`);
|
|
2073
|
-
} else {
|
|
2074
|
-
console.log(`\u{1F4C2} No repository configured - creating blank workspace`);
|
|
2075
|
-
}
|
|
1965
|
+
console.log(`\u{1F4C2} No repository configured - creating blank workspace`);
|
|
2076
1966
|
workspacePath = await mkdtemp2(join3(tmpdir2(), "cg-workspace-"));
|
|
2077
1967
|
console.log(` \u2192 ${workspacePath}`);
|
|
2078
1968
|
cleanup = async () => {
|
|
@@ -2100,30 +1990,6 @@ async function runLocalAgent(options) {
|
|
|
2100
1990
|
currentClaim = null;
|
|
2101
1991
|
continue;
|
|
2102
1992
|
}
|
|
2103
|
-
if (phase === "learn") {
|
|
2104
|
-
try {
|
|
2105
|
-
await runLearn(actionDetail.id, { cwd: workspacePath, startingCommit, model: options?.forceModel });
|
|
2106
|
-
stats.learned++;
|
|
2107
|
-
console.log(`Learning extracted: ${actionDetail.title}`);
|
|
2108
|
-
} catch (learnError) {
|
|
2109
|
-
stats.errors++;
|
|
2110
|
-
console.error(`Error during learning: ${learnError.message}. Continuing...`);
|
|
2111
|
-
} finally {
|
|
2112
|
-
if (currentClaim && apiClient) {
|
|
2113
|
-
try {
|
|
2114
|
-
await apiClient.releaseClaim({
|
|
2115
|
-
action_id: currentClaim.actionId,
|
|
2116
|
-
worker_id: currentClaim.workerId,
|
|
2117
|
-
claim_id: currentClaim.claimId
|
|
2118
|
-
});
|
|
2119
|
-
} catch (releaseError) {
|
|
2120
|
-
console.error("\u26A0\uFE0F Failed to release claim:", releaseError.message);
|
|
2121
|
-
}
|
|
2122
|
-
}
|
|
2123
|
-
currentClaim = null;
|
|
2124
|
-
}
|
|
2125
|
-
continue;
|
|
2126
|
-
}
|
|
2127
1993
|
try {
|
|
2128
1994
|
await runExecute(actionDetail.id, { cwd: workspacePath, startingCommit, model: options?.forceModel });
|
|
2129
1995
|
stats.executed++;
|
|
@@ -2178,11 +2044,10 @@ var packageJson2 = JSON.parse(
|
|
|
2178
2044
|
);
|
|
2179
2045
|
var program = new Command();
|
|
2180
2046
|
program.name("contextgraph-agent").description("Autonomous agent for contextgraph action execution").version(packageJson2.version);
|
|
2181
|
-
program.command("run").description("Run continuous worker loop (claims and executes actions until Ctrl+C)").option("--force-haiku", "Force all workflows to use claude-haiku-4-5 instead of default models").
|
|
2047
|
+
program.command("run").description("Run continuous worker loop (claims and executes actions until Ctrl+C)").option("--force-haiku", "Force all workflows to use claude-haiku-4-5 instead of default models").action(async (options) => {
|
|
2182
2048
|
try {
|
|
2183
2049
|
await runLocalAgent({
|
|
2184
|
-
forceModel: options.forceHaiku ? "claude-haiku-4-5-20251001" : void 0
|
|
2185
|
-
skipLearning: options.skipLearning || false
|
|
2050
|
+
forceModel: options.forceHaiku ? "claude-haiku-4-5-20251001" : void 0
|
|
2186
2051
|
});
|
|
2187
2052
|
} catch (error) {
|
|
2188
2053
|
if (error instanceof Error) {
|
|
@@ -2221,14 +2086,6 @@ program.command("execute").argument("<action-id>", "Action ID to execute").descr
|
|
|
2221
2086
|
process.exit(1);
|
|
2222
2087
|
}
|
|
2223
2088
|
});
|
|
2224
|
-
program.command("learn").argument("<action-id>", "Action ID to learn from").description("Extract learnings from a completed action").action(async (actionId) => {
|
|
2225
|
-
try {
|
|
2226
|
-
await runLearn(actionId);
|
|
2227
|
-
} catch (error) {
|
|
2228
|
-
console.error("Error learning from action:", error instanceof Error ? error.message : error);
|
|
2229
|
-
process.exit(1);
|
|
2230
|
-
}
|
|
2231
|
-
});
|
|
2232
2089
|
program.command("whoami").description("Show current authentication status").action(async () => {
|
|
2233
2090
|
try {
|
|
2234
2091
|
const credentials = await loadCredentials();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/index.ts","../src/callback-server.ts","../src/credentials.ts","../src/auth-flow.ts","../src/workflows/auth.ts","../src/claude-sdk.ts","../src/plugin-setup.ts","../src/sdk-event-transformer.ts","../src/fetch-with-retry.ts","../src/log-transport.ts","../src/log-buffer.ts","../src/heartbeat-manager.ts","../src/workflows/prepare.ts","../src/workflows/execute.ts","../src/workflows/learn.ts","../src/workflows/agent.ts","../package.json","../src/api-client.ts","../src/workspace-prep.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { runAuth } from '../workflows/auth.js';\nimport { runPrepare } from '../workflows/prepare.js';\nimport { runExecute } from '../workflows/execute.js';\nimport { runLearn } from '../workflows/learn.js';\nimport { runLocalAgent } from '../workflows/agent.js';\nimport { loadCredentials, isExpired, isTokenExpired } from '../credentials.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8')\n);\n\nconst program = new Command();\n\nprogram\n .name('contextgraph-agent')\n .description('Autonomous agent for contextgraph action execution')\n .version(packageJson.version);\n\nprogram\n .command('run')\n .description('Run continuous worker loop (claims and executes actions until Ctrl+C)')\n .option('--force-haiku', 'Force all workflows to use claude-haiku-4-5 instead of default models')\n .option('--skip-learning', 'Skip learning runs and only do preparation and execution')\n .action(async (options) => {\n try {\n await runLocalAgent({\n forceModel: options.forceHaiku ? 'claude-haiku-4-5-20251001' : undefined,\n skipLearning: options.skipLearning || false,\n });\n } catch (error) {\n if (error instanceof Error) {\n console.error('Error running agent:', error.message || '(no message)');\n if (error.stack) {\n console.error('\\nStack trace:');\n console.error(error.stack);\n }\n } else {\n console.error('Error running agent:', error);\n }\n process.exit(1);\n }\n });\n\nprogram\n .command('auth')\n .description('Authenticate with contextgraph.dev')\n .action(async () => {\n try {\n await runAuth();\n } catch (error) {\n console.error('Error during authentication:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('prepare')\n .argument('<action-id>', 'Action ID to prepare')\n .description('Prepare a single action')\n .action(async (actionId: string) => {\n try {\n await runPrepare(actionId);\n } catch (error) {\n console.error('Error preparing action:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('execute')\n .argument('<action-id>', 'Action ID to execute')\n .description('Execute a single action')\n .action(async (actionId: string) => {\n try {\n await runExecute(actionId);\n } catch (error) {\n console.error('Error executing action:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('learn')\n .argument('<action-id>', 'Action ID to learn from')\n .description('Extract learnings from a completed action')\n .action(async (actionId: string) => {\n try {\n await runLearn(actionId);\n } catch (error) {\n console.error('Error learning from action:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('whoami')\n .description('Show current authentication status')\n .action(async () => {\n try {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n console.log('Not authenticated. Run `contextgraph-agent auth` to authenticate.');\n process.exit(1);\n }\n\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n console.log('⚠️ Token expired. Run `contextgraph-agent auth` to re-authenticate.');\n console.log(`User ID: ${credentials.userId}`);\n console.log(`Expired at: ${credentials.expiresAt}`);\n process.exit(1);\n }\n\n console.log('✅ Authenticated');\n console.log(`User ID: ${credentials.userId}`);\n console.log(`Expires at: ${credentials.expiresAt}`);\n } catch (error) {\n console.error('Error checking authentication:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import http from 'http';\nimport { URL } from 'url';\nimport type { CallbackResult } from './types/actions.js';\n\nexport type CallbackServerResult = {\n port: number;\n waitForCallback: () => Promise<CallbackResult>;\n close: () => Promise<void>;\n};\n\nconst MIN_PORT = 3000;\nconst MAX_PORT = 3100;\n\nasync function findFreePort(): Promise<number> {\n for (let port = MIN_PORT; port <= MAX_PORT; port++) {\n const isAvailable = await checkPortAvailable(port);\n if (isAvailable) {\n return port;\n }\n }\n\n throw new Error(`No free ports found between ${MIN_PORT} and ${MAX_PORT}`);\n}\n\nfunction checkPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = http.createServer();\n\n server.once('error', () => {\n resolve(false);\n });\n\n server.once('listening', () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n}\n\nexport async function startCallbackServer(): Promise<CallbackServerResult> {\n const port = await findFreePort();\n\n let callbackResolve: ((result: CallbackResult) => void) | null = null;\n const connections = new Set<import('net').Socket>();\n\n const server = http.createServer((req, res) => {\n const url = new URL(req.url || '/', `http://localhost:${port}`);\n\n if (url.pathname === '/callback') {\n const token = url.searchParams.get('token');\n const userId = url.searchParams.get('userId');\n\n if (!token) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getErrorPage('Missing token parameter'));\n return;\n }\n\n if (!userId) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getErrorPage('Missing userId parameter'));\n return;\n }\n\n if (callbackResolve) {\n callbackResolve({ token, userId });\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getSuccessPage());\n } else {\n res.writeHead(404, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getNotFoundPage());\n }\n });\n\n // Track connections so we can destroy them on close\n server.on('connection', (socket) => {\n connections.add(socket);\n socket.on('close', () => {\n connections.delete(socket);\n });\n });\n\n await new Promise<void>((resolve) => {\n server.listen(port, resolve);\n });\n\n return {\n port,\n waitForCallback: () => {\n return new Promise((resolve) => {\n callbackResolve = resolve;\n });\n },\n close: () => {\n return new Promise<void>((resolve, reject) => {\n // Destroy all active connections to ensure server closes immediately\n for (const socket of connections) {\n socket.destroy();\n }\n connections.clear();\n\n server.close((err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n },\n };\n}\n\nfunction getSuccessPage(): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authentication Successful</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link href=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap\" rel=\"stylesheet\">\n <style>\n :root {\n --bg: hsl(0 0% 8%);\n --tile-bg: hsl(0 0% 12%);\n --cream: hsl(45 30% 85%);\n --orange: hsl(30 95% 55%);\n --subtitle: hsl(0 0% 55%);\n --border: hsl(0 0% 20%);\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: var(--bg);\n padding: 1rem;\n }\n\n .container {\n background: var(--tile-bg);\n padding: 3rem;\n border-radius: 0.75rem;\n border: 1px solid var(--border);\n text-align: center;\n max-width: 400px;\n width: 100%;\n }\n\n .icon-container {\n width: 80px;\n height: 80px;\n margin: 0 auto 1.5rem;\n background: hsl(145 50% 12%);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid hsl(145 50% 25%);\n }\n\n .icon {\n width: 40px;\n height: 40px;\n stroke: hsl(145 70% 55%);\n stroke-width: 3;\n fill: none;\n }\n\n h1 {\n color: var(--cream);\n margin: 0 0 0.75rem 0;\n font-size: 1.25rem;\n font-weight: 500;\n letter-spacing: -0.02em;\n }\n\n p {\n color: var(--subtitle);\n margin: 0;\n font-size: 0.875rem;\n line-height: 1.6;\n }\n\n .brand {\n margin-top: 2rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--border);\n }\n\n .brand-text {\n color: var(--orange);\n font-size: 0.75rem;\n font-weight: 500;\n letter-spacing: 0.05em;\n }\n\n @keyframes check-draw {\n 0% {\n stroke-dashoffset: 24;\n }\n 100% {\n stroke-dashoffset: 0;\n }\n }\n\n .icon polyline {\n stroke-dasharray: 24;\n stroke-dashoffset: 24;\n animation: check-draw 0.4s ease-out 0.2s forwards;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"icon-container\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\">\n <polyline points=\"4 12 10 18 20 6\"></polyline>\n </svg>\n </div>\n <h1>Authentication successful</h1>\n <p>You can close this window and return to your terminal.</p>\n <div class=\"brand\">\n <span class=\"brand-text\">CONTEXTGRAPH</span>\n </div>\n </div>\n</body>\n</html>\n `.trim();\n}\n\nfunction getErrorPage(message: string): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authentication Error</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link href=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap\" rel=\"stylesheet\">\n <style>\n :root {\n --bg: hsl(0 0% 8%);\n --tile-bg: hsl(0 0% 12%);\n --red: hsl(0 80% 60%);\n --red-dim: hsl(0 50% 12%);\n --red-border: hsl(0 50% 25%);\n --cream: hsl(45 30% 85%);\n --orange: hsl(30 95% 55%);\n --subtitle: hsl(0 0% 55%);\n --border: hsl(0 0% 20%);\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: var(--bg);\n padding: 1rem;\n }\n\n .container {\n background: var(--tile-bg);\n padding: 3rem;\n border-radius: 0.75rem;\n border: 1px solid var(--border);\n text-align: center;\n max-width: 400px;\n width: 100%;\n }\n\n .icon-container {\n width: 80px;\n height: 80px;\n margin: 0 auto 1.5rem;\n background: var(--red-dim);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--red-border);\n }\n\n .icon {\n width: 40px;\n height: 40px;\n stroke: var(--red);\n stroke-width: 3;\n fill: none;\n }\n\n h1 {\n color: var(--red);\n margin: 0 0 0.75rem 0;\n font-size: 1.25rem;\n font-weight: 500;\n letter-spacing: -0.02em;\n }\n\n p {\n color: var(--subtitle);\n margin: 0;\n font-size: 0.875rem;\n line-height: 1.6;\n }\n\n .brand {\n margin-top: 2rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--border);\n }\n\n .brand-text {\n color: var(--orange);\n font-size: 0.75rem;\n font-weight: 500;\n letter-spacing: 0.05em;\n }\n\n @keyframes x-draw {\n 0% {\n stroke-dashoffset: 34;\n }\n 100% {\n stroke-dashoffset: 0;\n }\n }\n\n .icon line {\n stroke-dasharray: 17;\n stroke-dashoffset: 17;\n }\n\n .icon line:first-child {\n animation: x-draw 0.3s ease-out 0.2s forwards;\n }\n\n .icon line:last-child {\n animation: x-draw 0.3s ease-out 0.35s forwards;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"icon-container\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n </svg>\n </div>\n <h1>Authentication error</h1>\n <p>${message}</p>\n <div class=\"brand\">\n <span class=\"brand-text\">CONTEXTGRAPH</span>\n </div>\n </div>\n</body>\n</html>\n `.trim();\n}\n\nfunction getNotFoundPage(): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Not Found</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link href=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap\" rel=\"stylesheet\">\n <style>\n :root {\n --bg: hsl(0 0% 8%);\n --tile-bg: hsl(0 0% 12%);\n --cream: hsl(45 30% 85%);\n --orange: hsl(30 95% 55%);\n --subtitle: hsl(0 0% 55%);\n --border: hsl(0 0% 20%);\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: var(--bg);\n padding: 1rem;\n }\n\n .container {\n background: var(--tile-bg);\n padding: 3rem;\n border-radius: 0.75rem;\n border: 1px solid var(--border);\n text-align: center;\n max-width: 400px;\n width: 100%;\n }\n\n .code {\n color: var(--orange);\n font-size: 3rem;\n font-weight: 700;\n margin: 0 0 0.5rem 0;\n letter-spacing: -0.02em;\n }\n\n h1 {\n color: var(--cream);\n margin: 0;\n font-size: 1rem;\n font-weight: 400;\n }\n\n .brand {\n margin-top: 2rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--border);\n }\n\n .brand-text {\n color: var(--orange);\n font-size: 0.75rem;\n font-weight: 500;\n letter-spacing: 0.05em;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"code\">404</div>\n <h1>Not Found</h1>\n <div class=\"brand\">\n <span class=\"brand-text\">CONTEXTGRAPH</span>\n </div>\n </div>\n</body>\n</html>\n `.trim();\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\nimport type { Credentials } from './types/actions.js';\n\nfunction getCredentialsDir(): string {\n return process.env.CONTEXTGRAPH_CREDENTIALS_DIR || path.join(os.homedir(), '.contextgraph');\n}\n\nfunction getCredentialsPath(): string {\n return path.join(getCredentialsDir(), 'credentials.json');\n}\n\nexport const CREDENTIALS_DIR = getCredentialsDir();\nexport const CREDENTIALS_PATH = getCredentialsPath();\n\nexport async function saveCredentials(credentials: Credentials): Promise<void> {\n const dir = getCredentialsDir();\n const filePath = getCredentialsPath();\n\n await fs.mkdir(dir, { recursive: true, mode: 0o700 });\n\n const content = JSON.stringify(credentials, null, 2);\n await fs.writeFile(filePath, content, { mode: 0o600 });\n}\n\nexport async function loadCredentials(): Promise<Credentials | null> {\n // Check for API token in environment variable first\n const apiToken = process.env.CONTEXTGRAPH_API_TOKEN;\n if (apiToken) {\n // Create credentials from API token\n // API tokens don't expire in the same way, set a far future date\n const farFuture = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(); // 1 year\n return {\n clerkToken: apiToken,\n userId: 'api-token-user', // Placeholder - server will resolve actual user\n expiresAt: farFuture,\n createdAt: new Date().toISOString(),\n };\n }\n\n // Fall back to file-based credentials\n const filePath = getCredentialsPath();\n\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as Credentials;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n\n console.error('Error loading credentials:', error);\n return null;\n }\n}\n\nexport async function deleteCredentials(): Promise<void> {\n const filePath = getCredentialsPath();\n\n try {\n await fs.unlink(filePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n}\n\nexport function isExpired(credentials: Credentials): boolean {\n return new Date(credentials.expiresAt) <= new Date();\n}\n\nexport function isTokenExpired(token: string): boolean {\n try {\n // API tokens (non-JWT format) don't expire - check with server\n // API tokens typically start with a prefix like \"cg_\" or similar\n const parts = token.split('.');\n if (parts.length !== 3) {\n // Not a JWT - assume it's an API token that doesn't expire\n return false;\n }\n\n // Decode JWT to check actual token expiration\n const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());\n const now = Math.floor(Date.now() / 1000);\n\n // Token without exp claim is considered expired\n if (!payload.exp) {\n return true;\n }\n\n // Check if token has expired (including exactly now)\n if (payload.exp <= now) {\n return true;\n }\n\n // Check if token is not yet valid\n if (payload.nbf && payload.nbf > now) {\n return true;\n }\n\n return false;\n } catch {\n // If we can't decode it as JWT, assume it's an API token\n return false;\n }\n}\n\nexport function getTokenExpiration(token: string): Date | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return null;\n }\n\n const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());\n if (payload.exp) {\n return new Date(payload.exp * 1000);\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get an authenticated fetch function that includes the Clerk token\n *\n * This loads the credentials from disk and returns a fetch function\n * that automatically includes the x-authorization header (workaround for Vercel stripping Authorization).\n *\n * Throws an error if credentials are not found or expired.\n */\nexport async function getAuthenticatedFetch(): Promise<typeof fetch> {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n throw new Error(\n 'No credentials found. Please run authentication first.'\n );\n }\n\n if (isTokenExpired(credentials.clerkToken)) {\n throw new Error(\n 'Your credentials have expired. Please re-authenticate.'\n );\n }\n\n // Return a fetch function that includes the x-authorization header\n // Use x-authorization instead of Authorization because Vercel strips Authorization header\n return async (url: string | URL | Request, init?: RequestInit) => {\n const headers = new Headers(init?.headers);\n headers.set('x-authorization', `Bearer ${credentials.clerkToken}`);\n\n return fetch(url, {\n ...init,\n headers,\n });\n };\n}\n","import { startCallbackServer } from './callback-server.js';\nimport { saveCredentials } from './credentials.js';\n\ntype AuthenticationResult =\n | {\n success: true;\n credentials: {\n token: string;\n userId: string;\n };\n }\n | {\n success: false;\n error: string;\n };\n\ntype AuthenticationOptions = {\n baseUrl?: string;\n timeout?: number;\n openBrowser?: (url: string) => Promise<void>;\n};\n\nconst DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_BASE_URL = 'https://www.contextgraph.dev';\n\nasync function defaultOpenBrowser(url: string): Promise<void> {\n const open = (await import('open')).default;\n await open(url);\n}\n\nexport async function authenticateAgent(\n options: AuthenticationOptions = {}\n): Promise<AuthenticationResult> {\n const {\n baseUrl = DEFAULT_BASE_URL,\n timeout = DEFAULT_TIMEOUT,\n openBrowser = defaultOpenBrowser,\n } = options;\n\n let server;\n\n try {\n server = await startCallbackServer();\n const { port, waitForCallback, close } = server;\n\n const authUrl = `${baseUrl}/auth/cli-callback?port=${port}`;\n\n console.log(`Opening browser to: ${authUrl}`);\n await openBrowser(authUrl);\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('Authentication timeout')), timeout);\n });\n\n const result = await Promise.race([waitForCallback(), timeoutPromise]);\n\n const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(); // 24 hours\n\n await saveCredentials({\n clerkToken: result.token,\n userId: result.userId,\n expiresAt,\n createdAt: new Date().toISOString(),\n });\n\n await close();\n\n return {\n success: true,\n credentials: {\n token: result.token,\n userId: result.userId,\n },\n };\n } catch (error) {\n if (server) {\n await server.close();\n }\n\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n}\n","import { authenticateAgent } from '../auth-flow.js';\n\nexport async function runAuth(): Promise<void> {\n console.log('Starting authentication flow...\\n');\n\n const result = await authenticateAgent();\n\n if (result.success) {\n console.log('\\n✅ Authentication successful!');\n console.log(`User ID: ${result.credentials.userId}`);\n process.exit(0);\n } else {\n console.error('\\n❌ Authentication failed:', result.error);\n process.exit(1);\n }\n}\n\n","import { query, type SDKMessage, type SDKAssistantMessage, type SDKResultMessage } from '@anthropic-ai/claude-agent-sdk';\nimport type { ClaudeResult, SpawnClaudeOptions } from './types/actions.js';\nimport { ensurePlugin } from './plugin-setup.js';\nimport { transformSDKMessage } from './sdk-event-transformer.js';\nimport type { LogEvent } from './log-transport.js';\n\n// Constants for timeouts and truncation\nconst EXECUTION_TIMEOUT_MS = 20 * 60 * 1000; // 20 minutes\nconst THINKING_TRUNCATE_LENGTH = 100;\nconst COMMAND_TRUNCATE_LENGTH = 60;\n\n// Helper types for SDK message content\ntype ToolInput =\n | { file_path: string; old_string?: string; new_string?: string } // Read, Edit, Write\n | { command: string; description?: string; timeout?: number } // Bash\n | { pattern: string; glob?: string; type?: string; output_mode?: string } // Grep\n | { pattern: string; path?: string } // Glob\n | Record<string, unknown>; // Other tools\n\ntype SDKMessageContent = {\n type: string;\n text?: string;\n name?: string;\n input?: ToolInput;\n thinking?: string;\n};\n\n/**\n * Format tool use for console output\n */\nfunction formatToolUse(content: SDKMessageContent): string {\n if (content.type === 'tool_use') {\n const name = content.name || 'unknown';\n const summary = formatToolInput(name, content.input);\n return ` 🔧 ${name}${summary}`;\n }\n if (content.type === 'thinking' && content.thinking) {\n const truncated = content.thinking.length > THINKING_TRUNCATE_LENGTH\n ? content.thinking.substring(0, THINKING_TRUNCATE_LENGTH) + '...'\n : content.thinking;\n return ` 💭 ${truncated}`;\n }\n return '';\n}\n\n/**\n * Format tool input parameters for display\n */\nfunction formatToolInput(toolName: string, input: any): string {\n if (!input) return '';\n\n switch (toolName) {\n case 'Read':\n return `: ${input.file_path}`;\n case 'Edit':\n case 'Write':\n return `: ${input.file_path}`;\n case 'Bash':\n const cmd = input.command || '';\n const truncated = cmd.length > COMMAND_TRUNCATE_LENGTH\n ? cmd.substring(0, COMMAND_TRUNCATE_LENGTH) + '...'\n : cmd;\n return `: ${truncated}`;\n case 'Grep':\n return `: \"${input.pattern}\"`;\n case 'Glob':\n return `: ${input.pattern}`;\n default:\n return '';\n }\n}\n\n/**\n * Format assistant message content for display\n */\nfunction formatAssistantMessage(content: Array<SDKMessageContent>): string {\n const lines: string[] = [];\n\n for (const item of content) {\n if (item.type === 'text' && item.text) {\n lines.push(` ${item.text}`);\n } else if (item.type === 'tool_use' || item.type === 'thinking') {\n const formatted = formatToolUse(item);\n if (formatted) lines.push(formatted);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Format SDK message for console output\n */\nfunction formatMessage(message: SDKMessage): string | null {\n switch (message.type) {\n case 'system':\n if (message.subtype === 'init') {\n return '🚀 Claude session initialized';\n }\n return null;\n\n case 'assistant':\n const assistantMsg = message as SDKAssistantMessage;\n if (assistantMsg.message?.content && Array.isArray(assistantMsg.message.content)) {\n return formatAssistantMessage(assistantMsg.message.content as Array<SDKMessageContent>);\n }\n return null;\n\n case 'result':\n const resultMsg = message as SDKResultMessage;\n if (resultMsg.subtype === 'success') {\n const duration = resultMsg.duration_ms ? `${(resultMsg.duration_ms / 1000).toFixed(1)}s` : 'unknown';\n return `✅ Completed in ${duration}`;\n } else if (resultMsg.subtype.startsWith('error_')) {\n return '❌ Execution failed';\n }\n return null;\n\n default:\n return null;\n }\n}\n\n/**\n * Extended options for executeClaude with log streaming support\n */\nexport interface ExecuteClaudeOptions extends SpawnClaudeOptions {\n /** Callback for log events - called for each SDK message transformed into a LogEvent */\n onLogEvent?: (event: LogEvent) => void;\n /** Optional model to use (e.g., 'claude-opus-4-5-20251101'). If not specified, uses SDK default (Sonnet). */\n model?: string;\n}\n\n/**\n * Execute Claude using the Agent SDK\n *\n * This is a drop-in replacement for spawnClaude() that uses the SDK instead of spawning a CLI process.\n * It matches the same interface (SpawnClaudeOptions) and returns the same result type (ClaudeResult).\n *\n * Optionally accepts onLogEvent callback for real-time log streaming.\n */\nexport async function executeClaude(\n options: ExecuteClaudeOptions\n): Promise<ClaudeResult> {\n let sessionId: string | undefined;\n let totalCost = 0;\n let usage: any;\n\n // Create abort controller for timeout\n const abortController = new AbortController();\n const timeout = setTimeout(() => {\n abortController.abort();\n }, EXECUTION_TIMEOUT_MS);\n\n try {\n // Ensure the contextgraph plugin is available (clones from GitHub if missing)\n const pluginPath = await ensurePlugin();\n console.log('[Agent SDK] Loading plugin from:', pluginPath);\n console.log('[Agent SDK] Auth token available:', !!options.authToken);\n console.log('[Agent SDK] Anthropic API key available:', !!process.env.ANTHROPIC_API_KEY);\n console.log('[Agent SDK] Claude OAuth token available:', !!process.env.CLAUDE_CODE_OAUTH_TOKEN);\n\n // Create the query with SDK using the plugin\n const iterator = query({\n prompt: options.prompt,\n options: {\n ...(options.model ? { model: options.model } : {}),\n cwd: options.cwd,\n abortController,\n permissionMode: 'bypassPermissions', // Allow MCP tools to execute automatically\n maxTurns: 100, // Reasonable limit\n env: {\n ...process.env,\n // Pass auth token through environment for MCP server\n CONTEXTGRAPH_AUTH_TOKEN: options.authToken || '',\n // Pass Anthropic API key for SDK authentication\n ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || '',\n // Pass Claude OAuth token for SDK authentication (alternative to API key)\n CLAUDE_CODE_OAUTH_TOKEN: process.env.CLAUDE_CODE_OAUTH_TOKEN || '',\n },\n // Load the contextgraph plugin (provides MCP server URL and other config)\n plugins: [\n {\n type: 'local',\n path: pluginPath,\n }\n ]\n // Note: Auth is passed via CONTEXTGRAPH_AUTH_TOKEN environment variable above\n }\n });\n\n // Iterate through messages\n for await (const message of iterator) {\n // Capture session ID from first message\n if (!sessionId && message.session_id) {\n sessionId = message.session_id;\n }\n\n // Format and display the message (preserved console output)\n const formatted = formatMessage(message);\n if (formatted) {\n console.log(formatted);\n }\n\n // Transform and emit log event if callback is provided\n if (options.onLogEvent) {\n try {\n const logEvent = transformSDKMessage(message);\n if (logEvent) {\n options.onLogEvent(logEvent);\n }\n } catch (error) {\n // Log transformation errors but don't block execution\n console.error('[Log Transform]', error instanceof Error ? error.message : String(error));\n }\n }\n\n // Capture result metadata\n if (message.type === 'result') {\n const resultMsg = message as SDKResultMessage;\n totalCost = resultMsg.total_cost_usd || 0;\n usage = resultMsg.usage;\n\n // Check for errors\n if (resultMsg.subtype.startsWith('error_')) {\n clearTimeout(timeout);\n return {\n exitCode: 1,\n sessionId,\n usage,\n cost: totalCost,\n };\n }\n }\n }\n\n clearTimeout(timeout);\n\n // Return successful result\n return {\n exitCode: 0,\n sessionId,\n usage,\n cost: totalCost,\n };\n\n } catch (error) {\n clearTimeout(timeout);\n\n // Handle abort/timeout\n if (abortController.signal.aborted) {\n const timeoutMinutes = EXECUTION_TIMEOUT_MS / (60 * 1000);\n throw new Error(`Claude SDK execution timed out after ${timeoutMinutes} minutes`);\n }\n\n // Handle other errors\n throw new Error(`Failed to execute Claude SDK: ${(error as Error).message}`);\n }\n}\n","import { spawn } from 'child_process';\nimport { access, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nconst PLUGIN_REPO = 'https://github.com/contextgraph/claude-code-plugin.git';\nconst PLUGIN_DIR = join(homedir(), '.contextgraph', 'claude-code-plugin');\nconst PLUGIN_PATH = join(PLUGIN_DIR, 'plugins', 'contextgraph');\n\n/**\n * Get the path to the contextgraph plugin, cloning it if necessary\n */\nexport async function ensurePlugin(): Promise<string> {\n // Check if plugin already exists\n try {\n await access(PLUGIN_PATH);\n console.log(`📦 Using plugin: ${PLUGIN_PATH}`);\n return PLUGIN_PATH;\n } catch {\n // Plugin path doesn't exist, check if repo dir exists\n }\n\n // Check if repo directory exists but plugin path is missing (incomplete clone or wrong structure)\n let repoDirExists = false;\n try {\n await access(PLUGIN_DIR);\n repoDirExists = true;\n } catch {\n // Directory doesn't exist, will need to clone\n }\n\n if (repoDirExists) {\n // Directory exists but plugin path doesn't - try pulling latest\n console.log('📦 Plugin directory exists but incomplete, pulling latest...');\n await runCommand('git', ['pull'], PLUGIN_DIR);\n\n // Check again after pull\n try {\n await access(PLUGIN_PATH);\n console.log(`📦 Plugin ready: ${PLUGIN_PATH}`);\n return PLUGIN_PATH;\n } catch {\n throw new Error(`Plugin not found at ${PLUGIN_PATH} even after git pull. Check repository structure.`);\n }\n }\n\n console.log(`📦 Cloning plugin from ${PLUGIN_REPO}...`);\n\n // Ensure parent directory exists\n const contextgraphDir = join(homedir(), '.contextgraph');\n try {\n await mkdir(contextgraphDir, { recursive: true });\n } catch {\n // Directory might already exist\n }\n\n // Clone the repository\n await runCommand('git', ['clone', PLUGIN_REPO, PLUGIN_DIR]);\n\n // Verify plugin exists after clone\n try {\n await access(PLUGIN_PATH);\n console.log(`📦 Plugin installed: ${PLUGIN_PATH}`);\n return PLUGIN_PATH;\n } catch {\n throw new Error(`Plugin clone succeeded but plugin path not found at ${PLUGIN_PATH}`);\n }\n}\n\n/**\n * Update the plugin to latest version\n */\nexport async function updatePlugin(): Promise<void> {\n try {\n await access(PLUGIN_DIR);\n } catch {\n throw new Error('Plugin not installed. Run the agent first to auto-install.');\n }\n\n console.log('[Plugin Setup] Updating plugin...');\n await runCommand('git', ['pull'], PLUGIN_DIR);\n console.log('[Plugin Setup] Plugin updated');\n}\n\n/**\n * Get the plugin path (without ensuring it exists)\n */\nexport function getPluginPath(): string {\n return PLUGIN_PATH;\n}\n\nfunction runCommand(command: string, args: string[], cwd?: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, { cwd, stdio: 'inherit' });\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`${command} ${args[0]} failed with exit code ${code}`));\n }\n });\n\n proc.on('error', (err) => {\n reject(new Error(`Failed to spawn ${command}: ${err.message}`));\n });\n });\n}\n","/**\n * SDK Event Transformer - Transforms Claude SDK messages into agentLog event format\n *\n * This module provides a pure transformation function that converts SDK messages\n * into LogEvent objects for the log streaming infrastructure.\n *\n * IMPORTANT: Events are emitted in the same format as the Vercel sandbox agents\n * to ensure compatibility with the AgentEventMessage component. The full SDK\n * message is preserved in the `data` field without truncation.\n */\n\nimport type { LogEvent } from './log-transport.js';\nimport type { SDKMessage, SDKAssistantMessage, SDKResultMessage } from '@anthropic-ai/claude-agent-sdk';\n\n/**\n * Transform an SDK message into a LogEvent\n *\n * The transformation preserves the full SDK message in the `data` field,\n * matching the Vercel sandbox format for UI compatibility.\n *\n * @param message - The SDK message to transform\n * @returns A LogEvent or null if the message should be skipped\n */\nexport function transformSDKMessage(message: SDKMessage): LogEvent | null {\n const timestamp = new Date().toISOString();\n\n switch (message.type) {\n case 'system':\n return transformSystemMessage(message, timestamp);\n\n case 'assistant':\n return transformAssistantMessage(message as SDKAssistantMessage, timestamp);\n\n case 'result':\n return transformResultMessage(message as SDKResultMessage, timestamp);\n\n case 'user':\n // User messages with tool results\n return transformUserMessage(message, timestamp);\n\n default:\n // Skip unknown message types\n return null;\n }\n}\n\n/**\n * Transform a system message (initialization, etc.)\n */\nfunction transformSystemMessage(\n message: SDKMessage & { subtype?: string; content?: string },\n timestamp: string\n): LogEvent {\n // Emit in the format expected by AgentEventMessage\n return {\n eventType: 'claude_message',\n content: message.content || `System: ${message.subtype || 'initialization'}`,\n data: {\n type: 'system',\n subtype: message.subtype,\n content: message.content,\n session_id: message.session_id,\n },\n timestamp,\n };\n}\n\n/**\n * Transform an assistant message (text, tool use, thinking)\n *\n * Preserves the full SDK message in the data field for UI rendering.\n * This matches the Vercel sandbox format where the entire SDK JSON\n * is stored in event.data.\n */\nfunction transformAssistantMessage(\n message: SDKAssistantMessage,\n timestamp: string\n): LogEvent | null {\n const content = message.message?.content;\n if (!content || !Array.isArray(content)) {\n return null;\n }\n\n // Generate a human-readable summary for the content field\n const contentSummary = generateContentSummary(content);\n\n // Emit the full SDK message structure in data for UI compatibility\n // This matches sandbox-execution.ts line 512-522\n return {\n eventType: 'claude_message',\n content: contentSummary,\n data: {\n type: 'assistant',\n message: message.message,\n session_id: message.session_id,\n parent_tool_use_id: message.parent_tool_use_id,\n },\n timestamp,\n };\n}\n\n/**\n * Transform a result message (completion status)\n *\n * Emits as claude_message with type='result' to match sandbox format.\n */\nfunction transformResultMessage(\n message: SDKResultMessage,\n timestamp: string\n): LogEvent {\n const isSuccess = message.subtype === 'success';\n const durationSec = message.duration_ms\n ? (message.duration_ms / 1000).toFixed(1)\n : 'unknown';\n\n return {\n eventType: 'claude_message',\n content: isSuccess\n ? `Completed successfully in ${durationSec}s`\n : `Execution ${message.subtype}: ${durationSec}s`,\n data: {\n type: 'result',\n subtype: message.subtype,\n duration_ms: message.duration_ms,\n total_cost_usd: message.total_cost_usd,\n num_turns: message.num_turns,\n usage: message.usage,\n session_id: message.session_id,\n },\n timestamp,\n };\n}\n\n/**\n * Transform a user message (typically contains tool results)\n *\n * Preserves full tool result content for UI rendering.\n */\nfunction transformUserMessage(\n message: SDKMessage & { message?: { content?: unknown } },\n timestamp: string\n): LogEvent | null {\n const content = message.message?.content;\n if (!content || !Array.isArray(content)) {\n return null;\n }\n\n // Check if this contains tool results\n const hasToolResults = content.some(\n (block: any) => block.type === 'tool_result'\n );\n\n if (!hasToolResults) {\n return null;\n }\n\n // Generate summary for content field\n const summaries = content\n .filter((block: any) => block.type === 'tool_result')\n .map((block: any) => {\n const prefix = block.is_error ? '❌' : '✓';\n const resultText = extractToolResultText(block.content);\n return `${prefix} ${resultText.substring(0, 100)}${resultText.length > 100 ? '...' : ''}`;\n });\n\n // Emit full message structure in data for UI rendering\n return {\n eventType: 'claude_message',\n content: summaries.join('\\n'),\n data: {\n type: 'user',\n message: message.message,\n session_id: message.session_id,\n },\n timestamp,\n };\n}\n\n/**\n * Generate a human-readable summary from message content blocks\n */\nfunction generateContentSummary(content: unknown[]): string {\n const parts: string[] = [];\n\n for (const block of content as any[]) {\n if (block.type === 'text' && block.text) {\n // Include first 200 chars of text in summary\n const text = block.text.length > 200\n ? block.text.substring(0, 200) + '...'\n : block.text;\n parts.push(text);\n } else if (block.type === 'tool_use') {\n parts.push(`🔧 ${block.name}`);\n } else if (block.type === 'thinking') {\n parts.push('💭 [thinking]');\n }\n }\n\n return parts.join(' | ') || '[no content]';\n}\n\n/**\n * Extract text content from a tool result for summary purposes\n */\nfunction extractToolResultText(\n content: string | Array<{ type: string; text?: string }> | undefined\n): string {\n if (!content) return '';\n\n if (typeof content === 'string') {\n return content;\n }\n\n if (Array.isArray(content)) {\n return content\n .filter(block => block.type === 'text' && block.text)\n .map(block => block.text)\n .join('\\n');\n }\n\n return '';\n}\n\n/**\n * Batch transform multiple SDK messages\n * Useful for processing message arrays from SDK iterations\n *\n * @param messages - Array of SDK messages\n * @returns Array of LogEvents (excluding nulls)\n */\nexport function transformSDKMessages(messages: SDKMessage[]): LogEvent[] {\n return messages\n .map(transformSDKMessage)\n .filter((event): event is LogEvent => event !== null);\n}\n","export interface RetryOptions {\n maxRetries?: number;\n baseDelayMs?: number;\n maxDelayMs?: number;\n /** If true, will log retry attempts */\n verbose?: boolean;\n}\n\nexport async function fetchWithRetry(\n url: string,\n options: RequestInit,\n retryOptions: RetryOptions = {}\n): Promise<Response> {\n const { maxRetries = 3, baseDelayMs = 1000, maxDelayMs = 10000 } = retryOptions;\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await fetch(url, options);\n // Don't retry on client errors (4xx), only on server/network errors\n if (response.ok || (response.status >= 400 && response.status < 500)) {\n return response;\n }\n // Server error (5xx) - will retry\n lastError = new Error(`HTTP ${response.status}`);\n } catch (error) {\n // Network error - will retry\n lastError = error instanceof Error ? error : new Error(String(error));\n }\n\n if (attempt < maxRetries) {\n // Exponential backoff with jitter\n const delay = Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs);\n const jitter = delay * 0.1 * Math.random();\n await new Promise((resolve) => setTimeout(resolve, delay + jitter));\n }\n }\n\n throw lastError ?? new Error('Request failed after retries');\n}\n","/**\n * LogTransportService - Handles sending log events to the platform API\n *\n * This service manages:\n * - Creating and updating runs\n * - Sending batches of log events\n * - Retry logic with exponential backoff\n */\n\n/**\n * Log event types supported by the platform\n */\nexport type LogEventType =\n | 'stdout'\n | 'stderr'\n | 'claude_message'\n | 'tool_use'\n | 'tool_result'\n | 'system';\n\n/**\n * A log event to be sent to the platform\n */\nexport interface LogEvent {\n eventType: LogEventType;\n content: string;\n data?: Record<string, unknown>;\n timestamp: string;\n}\n\n/**\n * Response from creating a run\n */\nexport interface CreateRunResponse {\n runId: string;\n}\n\n/**\n * Response from batch send\n */\nexport interface BatchSendResponse {\n success: boolean;\n eventsReceived?: number;\n}\n\n/**\n * Configuration for retry behavior\n */\nexport interface RetryConfig {\n maxRetries: number;\n initialDelayMs: number;\n backoffFactor: number;\n}\n\nconst DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n initialDelayMs: 100,\n backoffFactor: 2,\n};\n\n/**\n * Service for sending log events to the platform API\n */\nexport class LogTransportService {\n private runId: string | null = null;\n private retryConfig: RetryConfig;\n\n constructor(\n private baseUrl: string,\n private authToken: string,\n runId?: string,\n retryConfig?: Partial<RetryConfig>\n ) {\n this.runId = runId ?? null;\n this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...retryConfig };\n }\n\n /**\n * Get the current run ID\n */\n getRunId(): string | null {\n return this.runId;\n }\n\n /**\n * Create a new run for an action\n * @param actionId - The action ID this run is executing\n * @param purpose - The purpose of this run: 'execute' | 'prepare' | 'learn' | 'review'\n * @param metadata - Optional metadata for the run (e.g., startingCommit)\n * @returns The created run ID\n */\n async createRun(\n actionId: string,\n purpose: 'execute' | 'prepare' | 'learn' | 'review',\n metadata?: { startingCommit?: string }\n ): Promise<string> {\n const response = await this.makeRequest('/api/runs', {\n method: 'POST',\n body: JSON.stringify({\n actionId,\n state: 'queued',\n purpose,\n ...(metadata?.startingCommit && { startingCommit: metadata.startingCommit }),\n }),\n });\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'Failed to create run');\n }\n\n this.runId = result.data.runId;\n return this.runId;\n }\n\n /**\n * Start the run (transition to running state)\n * Called when execution begins\n */\n async startRun(): Promise<void> {\n if (!this.runId) {\n throw new Error('No run ID set. Call createRun() first.');\n }\n\n const response = await this.makeRequest(`/api/runs/${this.runId}/start`, {\n method: 'POST',\n body: JSON.stringify({}),\n });\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'Failed to start run');\n }\n }\n\n /**\n * Finish the run with an outcome\n * @param outcome - 'success' | 'error' | 'timeout' | 'incomplete'\n * @param metadata - Optional metadata (exitCode, errorMessage, cost, usage)\n */\n async finishRun(\n outcome: 'success' | 'error' | 'timeout' | 'incomplete',\n metadata?: {\n exitCode?: number;\n errorMessage?: string;\n cost?: number;\n usage?: Record<string, unknown>;\n }\n ): Promise<void> {\n if (!this.runId) {\n throw new Error('No run ID set. Call createRun() first.');\n }\n\n const response = await this.makeRequest(`/api/runs/${this.runId}/finish`, {\n method: 'POST',\n body: JSON.stringify({\n outcome,\n exitCode: metadata?.exitCode?.toString(),\n errorMessage: metadata?.errorMessage,\n }),\n });\n\n const result = await response.json();\n\n if (!result.success) {\n // If the run is already in a finishing state (summarizing, finished),\n // this is not an error - the server is already handling completion\n const error = result.error || 'Failed to finish run';\n if (error.includes('summarizing') || error.includes('finished')) {\n console.log('[LogTransport] Run is already being finished by server, skipping client finish');\n return;\n }\n throw new Error(error);\n }\n }\n\n /**\n * Update the state of the current run\n * @deprecated Use startRun() and finishRun() instead\n * @param state - New state for the run\n * @param metadata - Optional metadata to include with the state update\n */\n async updateRunState(\n state: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n if (!this.runId) {\n throw new Error('No run ID set. Call createRun() first.');\n }\n\n // Map state to appropriate endpoint\n if (state === 'executing' || state === 'preparing' || state === 'running' || state === 'learning') {\n await this.startRun();\n } else if (state === 'completed' || state === 'failed') {\n const outcome = state === 'completed' ? 'success' : 'error';\n await this.finishRun(outcome, {\n exitCode: metadata?.exitCode as number | undefined,\n errorMessage: metadata?.error as string | undefined,\n cost: metadata?.cost as number | undefined,\n usage: metadata?.usage as Record<string, unknown> | undefined,\n });\n } else {\n // For unknown states, just log a warning\n console.warn(`[LogTransport] Unknown state '${state}' - no API call made`);\n }\n }\n\n /**\n * Send a batch of log events to the platform\n * @param events - Array of log events to send\n * @param workerId - Optional worker ID\n * @returns Success status and number of events received\n */\n async sendBatch(\n events: LogEvent[],\n workerId?: string\n ): Promise<BatchSendResponse> {\n if (!this.runId) {\n throw new Error('No run ID set. Call createRun() first.');\n }\n\n if (events.length === 0) {\n return { success: true, eventsReceived: 0 };\n }\n\n const response = await this.makeRequest('/api/agents/log/event', {\n method: 'POST',\n body: JSON.stringify({\n runId: this.runId,\n events,\n ...(workerId && { workerId }),\n }),\n });\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'Failed to send log batch');\n }\n\n return {\n success: true,\n eventsReceived: result.data?.eventsReceived ?? events.length,\n };\n }\n\n /**\n * Make an HTTP request with retry logic\n */\n private async makeRequest(\n path: string,\n options: RequestInit\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n const headers = {\n 'x-authorization': `Bearer ${this.authToken}`,\n 'Content-Type': 'application/json',\n };\n\n let lastError: Error | null = null;\n let delay = this.retryConfig.initialDelayMs;\n\n for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n ...headers,\n ...(options.headers || {}),\n },\n });\n\n // Don't retry on client errors (4xx) - these won't succeed on retry\n if (response.status >= 400 && response.status < 500) {\n return response;\n }\n\n // Retry on server errors (5xx) or network issues\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Don't wait after the last attempt\n if (attempt < this.retryConfig.maxRetries) {\n await this.sleep(delay);\n delay *= this.retryConfig.backoffFactor;\n }\n }\n }\n\n throw new Error(\n `Request failed after ${this.retryConfig.maxRetries + 1} attempts: ${lastError?.message}`\n );\n }\n\n /**\n * Sleep for a given number of milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","/**\n * LogBuffer - Manages buffered, non-blocking log transmission\n *\n * Collects log events and flushes them periodically to avoid\n * blocking the main Claude execution flow.\n */\n\nimport { LogTransportService, type LogEvent } from './log-transport.js';\n\n// Buffer configuration for log streaming\nconst LOG_BUFFER_FLUSH_INTERVAL_MS = 500;\nconst LOG_BUFFER_MAX_SIZE = 50;\nconst LOG_BUFFER_MAX_QUEUE_SIZE = 1000;\n\nexport class LogBuffer {\n private buffer: LogEvent[] = [];\n private flushIntervalId: ReturnType<typeof setInterval> | null = null;\n private isFlushing = false;\n\n constructor(\n private transport: LogTransportService,\n private flushIntervalMs: number = LOG_BUFFER_FLUSH_INTERVAL_MS,\n private maxBufferSize: number = LOG_BUFFER_MAX_SIZE,\n private maxQueueSize: number = LOG_BUFFER_MAX_QUEUE_SIZE\n ) {}\n\n /**\n * Add an event to the buffer (fire-and-forget)\n * Handles backpressure by dropping oldest events if queue is full.\n */\n push(event: LogEvent): void {\n // Backpressure: drop oldest events if queue is too large\n if (this.buffer.length >= this.maxQueueSize) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n\n // Trigger immediate flush if buffer is at max size\n if (this.buffer.length >= this.maxBufferSize) {\n this.flushAsync();\n }\n }\n\n /**\n * Start periodic flushing\n */\n start(): void {\n if (this.flushIntervalId !== null) return;\n\n this.flushIntervalId = setInterval(() => {\n this.flushAsync();\n }, this.flushIntervalMs);\n }\n\n /**\n * Stop periodic flushing and flush remaining events\n */\n async stop(): Promise<void> {\n if (this.flushIntervalId !== null) {\n clearInterval(this.flushIntervalId);\n this.flushIntervalId = null;\n }\n\n // Final flush of remaining events\n await this.flush();\n }\n\n /**\n * Async flush (fire-and-forget, non-blocking)\n */\n private flushAsync(): void {\n // Don't start a new flush if one is in progress\n if (this.isFlushing || this.buffer.length === 0) return;\n\n // Fire and forget - don't await\n this.flush().catch((error) => {\n console.error('[LogBuffer] Flush error:', error instanceof Error ? error.message : String(error));\n });\n }\n\n /**\n * Flush current buffer contents to transport\n */\n private async flush(): Promise<void> {\n if (this.isFlushing || this.buffer.length === 0) return;\n\n this.isFlushing = true;\n const eventsToSend = [...this.buffer];\n this.buffer = [];\n\n try {\n await this.transport.sendBatch(eventsToSend);\n } catch (error) {\n // Log errors but don't re-queue (to avoid infinite growth)\n console.error('[LogBuffer] Failed to send batch:', error instanceof Error ? error.message : String(error));\n } finally {\n this.isFlushing = false;\n }\n }\n}\n","/**\n * HeartbeatManager - Sends periodic liveness signals during execution\n *\n * This service manages:\n * - Periodic heartbeat signals to the platform\n * - Phase/progress updates without blocking execution\n * - Graceful error handling (log, don't throw)\n */\n\n/**\n * Execution phases for heartbeat reporting\n */\nexport type HeartbeatPhase = 'executing' | 'reading' | 'writing' | 'thinking';\n\n/**\n * Heartbeat payload sent to the platform\n */\nexport interface HeartbeatPayload {\n phase: HeartbeatPhase;\n progress?: number;\n timestamp: string;\n}\n\n/**\n * HeartbeatManager - Self-managing heartbeat service\n *\n * Sends periodic liveness signals to keep the platform informed\n * of worker status without blocking the main execution flow.\n */\nexport class HeartbeatManager {\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private currentPhase: HeartbeatPhase = 'executing';\n private currentProgress: number | undefined = undefined;\n\n constructor(\n private baseUrl: string,\n private authToken: string,\n private runId: string\n ) {}\n\n /**\n * Start sending periodic heartbeats\n * @param intervalMs - Time between heartbeats in milliseconds (default: 30000)\n */\n start(intervalMs: number = 30000): void {\n // Clear any existing interval\n this.stop();\n\n // Send initial heartbeat immediately\n this.sendHeartbeat();\n\n // Set up periodic heartbeats\n this.intervalId = setInterval(() => {\n this.sendHeartbeat();\n }, intervalMs);\n }\n\n /**\n * Stop sending heartbeats\n */\n stop(): void {\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n }\n\n /**\n * Update the current phase and optional progress\n * @param phase - Current execution phase\n * @param progress - Optional progress percentage (0-100)\n */\n updatePhase(phase: HeartbeatPhase, progress?: number): void {\n this.currentPhase = phase;\n this.currentProgress = progress;\n }\n\n /**\n * Check if heartbeat manager is currently running\n */\n isRunning(): boolean {\n return this.intervalId !== null;\n }\n\n /**\n * Send a heartbeat to the platform (internal method)\n * Errors are logged but not thrown to avoid blocking execution.\n * Includes one retry attempt for transient network failures.\n */\n private async sendHeartbeat(): Promise<void> {\n const payload: HeartbeatPayload = {\n phase: this.currentPhase,\n timestamp: new Date().toISOString(),\n };\n\n if (this.currentProgress !== undefined) {\n payload.progress = this.currentProgress;\n }\n\n const url = `${this.baseUrl}/api/runs/${this.runId}/heartbeat`;\n const requestOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'x-authorization': `Bearer ${this.authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n };\n\n // Try up to 2 times (initial + 1 retry)\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n const response = await fetch(url, requestOptions);\n\n if (response.ok) {\n return; // Success\n }\n\n // Don't retry client errors (4xx)\n if (response.status >= 400 && response.status < 500) {\n console.error(\n `Heartbeat failed: HTTP ${response.status} ${response.statusText}`\n );\n return;\n }\n\n // Server error - will retry\n if (attempt === 0) {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n } catch (error) {\n // Network error - retry once\n if (attempt === 0) {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n } else {\n // Log on final failure\n console.error(\n 'Heartbeat error:',\n error instanceof Error ? error.message : String(error)\n );\n }\n }\n }\n }\n}\n","import { loadCredentials, isExpired, isTokenExpired } from '../credentials.js';\nimport { executeClaude } from '../claude-sdk.js';\nimport { fetchWithRetry } from '../fetch-with-retry.js';\nimport { LogTransportService } from '../log-transport.js';\nimport { LogBuffer } from '../log-buffer.js';\nimport { HeartbeatManager } from '../heartbeat-manager.js';\n\nconst API_BASE_URL = 'https://www.contextgraph.dev';\n\nexport interface WorkflowOptions {\n cwd?: string;\n startingCommit?: string;\n model?: string;\n}\n\nexport async function runPrepare(actionId: string, options?: WorkflowOptions): Promise<void> {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n console.error('❌ Not authenticated. Run authentication first.');\n process.exit(1);\n }\n\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n console.error('❌ Token expired. Re-authenticate to continue.');\n process.exit(1);\n }\n\n // Initialize log streaming infrastructure\n const logTransport = new LogTransportService(API_BASE_URL, credentials.clerkToken);\n let runId: string | undefined;\n let heartbeatManager: HeartbeatManager | undefined;\n let logBuffer: LogBuffer | undefined;\n\n try {\n // Create run for this preparation phase FIRST so we have runId for the prompt\n console.log('[Log Streaming] Creating run for prepare phase...');\n runId = await logTransport.createRun(actionId, 'prepare', {\n startingCommit: options?.startingCommit,\n });\n console.log(`[Log Streaming] Run created: ${runId}`);\n\n // Now fetch preparation instructions with runId included\n console.log(`Fetching preparation instructions for action ${actionId}...\\n`);\n\n const response = await fetchWithRetry(\n `${API_BASE_URL}/api/prompts/prepare`,\n {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${credentials.clerkToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ actionId, runId }),\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to fetch prepare prompt: ${response.statusText}\\n${errorText}`);\n }\n\n const { prompt } = await response.json();\n\n // Update run state to preparing\n await logTransport.updateRunState('preparing');\n\n // Start heartbeat manager\n heartbeatManager = new HeartbeatManager(API_BASE_URL, credentials.clerkToken, runId);\n heartbeatManager.start();\n console.log('[Log Streaming] Heartbeat started');\n\n // Set up log buffer for non-blocking transmission\n logBuffer = new LogBuffer(logTransport);\n logBuffer.start();\n\n console.log('Spawning Claude for preparation...\\n');\n\n const claudeResult = await executeClaude({\n prompt,\n cwd: options?.cwd || process.cwd(),\n authToken: credentials.clerkToken,\n model: options?.model || 'claude-opus-4-5-20251101',\n onLogEvent: (event) => {\n logBuffer!.push(event);\n },\n });\n\n // Update run state based on execution result\n if (claudeResult.exitCode === 0) {\n await logTransport.finishRun('success', {\n exitCode: claudeResult.exitCode,\n cost: claudeResult.cost,\n usage: claudeResult.usage,\n });\n console.log('\\n✅ Preparation complete');\n } else {\n await logTransport.finishRun('error', {\n exitCode: claudeResult.exitCode,\n errorMessage: `Claude preparation failed with exit code ${claudeResult.exitCode}`,\n });\n console.error(`\\n❌ Claude preparation failed with exit code ${claudeResult.exitCode}`);\n process.exit(1);\n }\n\n } catch (error) {\n // Update run state to failed if we have a run\n if (runId) {\n try {\n await logTransport.finishRun('error', {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n } catch (stateError) {\n console.error('[Log Streaming] Failed to update run state:', stateError);\n }\n }\n throw error;\n\n } finally {\n // Cleanup: stop heartbeat and flush remaining logs\n if (heartbeatManager) {\n heartbeatManager.stop();\n console.log('[Log Streaming] Heartbeat stopped');\n }\n\n if (logBuffer) {\n await logBuffer.stop();\n console.log('[Log Streaming] Logs flushed');\n }\n }\n}\n","import { loadCredentials, isExpired, isTokenExpired } from '../credentials.js';\nimport { executeClaude } from '../claude-sdk.js';\nimport { fetchWithRetry } from '../fetch-with-retry.js';\nimport { LogTransportService } from '../log-transport.js';\nimport { LogBuffer } from '../log-buffer.js';\nimport { HeartbeatManager } from '../heartbeat-manager.js';\n\nconst API_BASE_URL = 'https://www.contextgraph.dev';\n\nexport interface WorkflowOptions {\n cwd?: string;\n startingCommit?: string;\n model?: string;\n}\n\nexport async function runExecute(actionId: string, options?: WorkflowOptions): Promise<void> {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n console.error('❌ Not authenticated. Run authentication first.');\n process.exit(1);\n }\n\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n console.error('❌ Token expired. Re-authenticate to continue.');\n process.exit(1);\n }\n\n // Initialize log streaming infrastructure\n const logTransport = new LogTransportService(API_BASE_URL, credentials.clerkToken);\n let runId: string | undefined;\n let heartbeatManager: HeartbeatManager | undefined;\n let logBuffer: LogBuffer | undefined;\n\n try {\n // Create run for this execution FIRST so we have runId for the prompt\n console.log('[Log Streaming] Creating run...');\n runId = await logTransport.createRun(actionId, 'execute', {\n startingCommit: options?.startingCommit,\n });\n console.log(`[Log Streaming] Run created: ${runId}`);\n\n // Now fetch execution instructions with runId included\n console.log(`Fetching execution instructions for action ${actionId}...\\n`);\n\n const response = await fetchWithRetry(\n `${API_BASE_URL}/api/prompts/execute`,\n {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${credentials.clerkToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ actionId, runId }),\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to fetch execute prompt: ${response.statusText}\\n${errorText}`);\n }\n\n const { prompt } = await response.json();\n\n // Update run state to executing\n await logTransport.updateRunState('executing');\n\n // Start heartbeat manager\n heartbeatManager = new HeartbeatManager(API_BASE_URL, credentials.clerkToken, runId);\n heartbeatManager.start();\n console.log('[Log Streaming] Heartbeat started');\n\n // Set up log buffer for non-blocking transmission\n logBuffer = new LogBuffer(logTransport);\n logBuffer.start();\n\n console.log('Spawning Claude for execution...\\n');\n\n const claudeResult = await executeClaude({\n prompt,\n cwd: options?.cwd || process.cwd(),\n authToken: credentials.clerkToken,\n ...(options?.model ? { model: options.model } : {}),\n onLogEvent: (event) => {\n logBuffer!.push(event);\n },\n });\n\n // Update run state based on execution result\n if (claudeResult.exitCode === 0) {\n await logTransport.finishRun('success', {\n exitCode: claudeResult.exitCode,\n cost: claudeResult.cost,\n usage: claudeResult.usage,\n });\n console.log('\\n✅ Execution complete');\n } else {\n await logTransport.finishRun('error', {\n exitCode: claudeResult.exitCode,\n errorMessage: `Claude execution failed with exit code ${claudeResult.exitCode}`,\n });\n throw new Error(`Claude execution failed with exit code ${claudeResult.exitCode}`);\n }\n\n } catch (error) {\n // Update run state to failed if we have a run\n if (runId) {\n try {\n await logTransport.finishRun('error', {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n } catch (stateError) {\n console.error('[Log Streaming] Failed to update run state:', stateError);\n }\n }\n throw error;\n\n } finally {\n // Cleanup: stop heartbeat and flush remaining logs\n if (heartbeatManager) {\n heartbeatManager.stop();\n console.log('[Log Streaming] Heartbeat stopped');\n }\n\n if (logBuffer) {\n await logBuffer.stop();\n console.log('[Log Streaming] Logs flushed');\n }\n }\n}\n","import { loadCredentials, isExpired, isTokenExpired } from '../credentials.js';\nimport { executeClaude } from '../claude-sdk.js';\nimport { fetchWithRetry } from '../fetch-with-retry.js';\nimport { LogTransportService } from '../log-transport.js';\nimport { LogBuffer } from '../log-buffer.js';\nimport { HeartbeatManager } from '../heartbeat-manager.js';\n\nconst API_BASE_URL = 'https://www.contextgraph.dev';\n\nexport interface WorkflowOptions {\n cwd?: string;\n startingCommit?: string;\n model?: string;\n}\n\nexport async function runLearn(actionId: string, options?: WorkflowOptions): Promise<void> {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n console.error('❌ Not authenticated. Run authentication first.');\n process.exit(1);\n }\n\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n console.error('❌ Token expired. Re-authenticate to continue.');\n process.exit(1);\n }\n\n // Initialize log streaming infrastructure\n const logTransport = new LogTransportService(API_BASE_URL, credentials.clerkToken);\n let runId: string | undefined;\n let heartbeatManager: HeartbeatManager | undefined;\n let logBuffer: LogBuffer | undefined;\n\n try {\n // Create run for this learning phase FIRST so we have runId for the prompt\n console.log('[Log Streaming] Creating run for learn phase...');\n runId = await logTransport.createRun(actionId, 'learn', {\n startingCommit: options?.startingCommit,\n });\n console.log(`[Log Streaming] Run created: ${runId}`);\n\n // Now fetch learning instructions with runId included\n console.log(`Fetching learning instructions for action ${actionId}...\\n`);\n\n const response = await fetchWithRetry(\n `${API_BASE_URL}/api/prompts/learn`,\n {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${credentials.clerkToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ actionId, runId }),\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to fetch learn prompt: ${response.statusText}\\n${errorText}`);\n }\n\n const { prompt } = await response.json();\n\n // Update run state to learning\n await logTransport.updateRunState('learning');\n\n // Start heartbeat manager\n heartbeatManager = new HeartbeatManager(API_BASE_URL, credentials.clerkToken, runId);\n heartbeatManager.start();\n console.log('[Log Streaming] Heartbeat started');\n\n // Set up log buffer for non-blocking transmission\n logBuffer = new LogBuffer(logTransport);\n logBuffer.start();\n\n console.log('Spawning Claude for learning extraction...\\n');\n\n const claudeResult = await executeClaude({\n prompt,\n cwd: options?.cwd || process.cwd(),\n authToken: credentials.clerkToken,\n ...(options?.model ? { model: options.model } : {}),\n onLogEvent: (event) => {\n logBuffer!.push(event);\n },\n });\n\n // Update run state based on execution result\n if (claudeResult.exitCode === 0) {\n await logTransport.finishRun('success', {\n exitCode: claudeResult.exitCode,\n cost: claudeResult.cost,\n usage: claudeResult.usage,\n });\n console.log('\\n✅ Learning extraction complete');\n } else {\n await logTransport.finishRun('error', {\n exitCode: claudeResult.exitCode,\n errorMessage: `Claude learning extraction failed with exit code ${claudeResult.exitCode}`,\n });\n console.error(`\\n❌ Claude learning extraction failed with exit code ${claudeResult.exitCode}`);\n process.exit(1);\n }\n\n } catch (error) {\n // Update run state to failed if we have a run\n if (runId) {\n try {\n await logTransport.finishRun('error', {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n } catch (stateError) {\n console.error('[Log Streaming] Failed to update run state:', stateError);\n }\n }\n throw error;\n\n } finally {\n // Cleanup: stop heartbeat and flush remaining logs\n if (heartbeatManager) {\n heartbeatManager.stop();\n console.log('[Log Streaming] Heartbeat stopped');\n }\n\n if (logBuffer) {\n await logBuffer.stop();\n console.log('[Log Streaming] Logs flushed');\n }\n }\n}\n","import { randomUUID } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { mkdtemp, rm } from 'fs/promises';\nimport { tmpdir } from 'os';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { ApiClient } from '../api-client.js';\nimport type { ActionNode, ActionMetadata } from '../types/actions.js';\nimport { findNextLeaf, type FindNextLeafResult } from '../next-action.js';\nimport { runPrepare } from './prepare.js';\nimport { runExecute } from './execute.js';\nimport { runLearn } from './learn.js';\nimport { prepareWorkspace } from '../workspace-prep.js';\nimport { loadCredentials, isExpired, isTokenExpired } from '../credentials.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n// When built, this file is in dist/, so package.json is one level up\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8')\n);\n\n// Polling configuration from environment variables\nconst INITIAL_POLL_INTERVAL = parseInt(process.env.WORKER_INITIAL_POLL_INTERVAL || '2000', 10); // 2 seconds default\nconst MAX_POLL_INTERVAL = parseInt(process.env.WORKER_MAX_POLL_INTERVAL || '5000', 10); // 5 seconds default\nconst BACKOFF_MULTIPLIER = 1.5;\nconst STATUS_INTERVAL_MS = 30000; // Show status every 30 seconds when idle\n\n// Retry configuration for transient API errors\n// For extended outages, we wait indefinitely with a ceiling on delay\nconst MAX_API_RETRIES = Infinity; // Never give up on transient errors\nconst INITIAL_RETRY_DELAY = 1000; // 1 second\nconst MAX_RETRY_DELAY = 60000; // 1 minute ceiling\nconst OUTAGE_WARNING_THRESHOLD = 5; // Warn user after this many retries\n\n// Module-scope state for graceful shutdown\nlet running = true;\nlet currentClaim: { actionId: string; claimId: string; workerId: string } | null = null;\nlet apiClient: ApiClient | null = null;\n\n// Stats tracking\nconst stats = {\n startTime: Date.now(),\n prepared: 0,\n learned: 0,\n executed: 0,\n errors: 0,\n};\n\nfunction formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) {\n return `${hours}h ${minutes % 60}m`;\n } else if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n }\n return `${seconds}s`;\n}\n\nfunction printStatus(): void {\n const uptime = formatDuration(Date.now() - stats.startTime);\n const total = stats.prepared + stats.learned + stats.executed;\n console.log(`Status: ${total} actions (${stats.prepared} prepared, ${stats.learned} learned, ${stats.executed} executed, ${stats.errors} errors) | Uptime: ${uptime}`);\n}\n\n/**\n * Get the next action to work on, handling tree depth truncation.\n * If the tree is truncated (children exist beyond depth limit), this function\n * will recursively re-fetch the tree starting from the truncated node.\n */\nasync function getNextAction(\n apiClient: ApiClient,\n rootId: string,\n depth: number = 0\n): Promise<ActionNode | null> {\n // Prevent infinite recursion in case of malformed data\n const maxDepth = 20;\n if (depth >= maxDepth) {\n console.error(`❌ Tree traversal exceeded maximum depth (${maxDepth}). Possible cycle or malformed data.`);\n return null;\n }\n\n const tree = await apiClient.fetchTree(rootId, false);\n\n if (tree.done) {\n if (depth === 0) {\n console.log('✅ Root action is already complete');\n }\n return null;\n }\n\n // Use local findNextLeaf to traverse tree and find next action\n const result = findNextLeaf(tree);\n\n // If we found an action, return it\n if (result.action) {\n return result.action;\n }\n\n // If tree was truncated, re-fetch starting from the truncated node\n if (result.truncatedAt) {\n console.log(`📊 Tree depth limit reached at action ${result.truncatedAt}. Fetching deeper...`);\n return getNextAction(apiClient, result.truncatedAt, depth + 1);\n }\n\n // No action found and no truncation - tree is complete or blocked\n return null;\n}\n\n/**\n * Clean up any claimed work and exit gracefully\n */\nasync function cleanupAndExit(): Promise<void> {\n if (currentClaim && apiClient) {\n try {\n console.log(`\\n🧹 Releasing claim on action ${currentClaim.actionId}...`);\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n console.log('✅ Claim released successfully');\n } catch (error) {\n console.error('⚠️ Failed to release claim:', (error as Error).message);\n }\n }\n console.log('👋 Shutdown complete');\n process.exit(0);\n}\n\n/**\n * Set up signal handlers for graceful shutdown\n */\nfunction setupSignalHandlers(): void {\n process.on('SIGINT', async () => {\n console.log('\\n\\n⚠️ Received SIGINT (Ctrl+C). Shutting down gracefully...');\n running = false;\n await cleanupAndExit();\n });\n\n process.on('SIGTERM', async () => {\n console.log('\\n\\n⚠️ Received SIGTERM. Shutting down gracefully...');\n running = false;\n await cleanupAndExit();\n });\n}\n\n/**\n * Sleep for the specified number of milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Check if an error is likely transient and worth retrying\n */\nfunction isRetryableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n // Retry on server errors (5xx), network errors, and timeouts\n return (\n message.includes('api error 5') ||\n message.includes('500') ||\n message.includes('502') ||\n message.includes('503') ||\n message.includes('504') ||\n message.includes('network') ||\n message.includes('timeout') ||\n message.includes('econnreset') ||\n message.includes('econnrefused') ||\n message.includes('socket hang up') ||\n message.includes('failed query') // Database query failures\n );\n}\n\nexport async function runLocalAgent(options?: { forceModel?: string; skipLearning?: boolean }): Promise<void> {\n // Initialize module-scope apiClient for signal handlers\n apiClient = new ApiClient();\n\n // Set up graceful shutdown handlers\n setupSignalHandlers();\n\n // Load and validate credentials upfront\n const credentials = await loadCredentials();\n if (!credentials) {\n console.error('❌ Not authenticated.');\n console.error(' Set CONTEXTGRAPH_API_TOKEN environment variable or run `contextgraph-agent auth`');\n process.exit(1);\n }\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n console.error('❌ Token expired. Run `contextgraph-agent auth` to re-authenticate.');\n process.exit(1);\n }\n\n // Show authentication method\n const usingApiToken = !!process.env.CONTEXTGRAPH_API_TOKEN;\n if (usingApiToken) {\n console.log('🔐 Authenticated via CONTEXTGRAPH_API_TOKEN');\n }\n\n // Generate unique worker ID for this session\n const workerId = randomUUID();\n\n console.log(`🤖 ContextGraph Agent v${packageJson.version}`);\n console.log(`👷 Worker ID: ${workerId}`);\n console.log(`🔄 Starting continuous worker loop...\\n`);\n if (options?.skipLearning) {\n console.log(`⏭️ Skipping learning runs (--skip-learning)\\n`);\n }\n console.log(`💡 Press Ctrl+C to gracefully shutdown and release any claimed work\\n`);\n\n let currentPollInterval = INITIAL_POLL_INTERVAL;\n let lastStatusTime = Date.now();\n let consecutiveApiErrors = 0;\n let apiRetryDelay = INITIAL_RETRY_DELAY;\n\n while (running) {\n\n // Claim next action from worker queue with retry logic\n let actionDetail;\n try {\n actionDetail = await apiClient.claimNextAction(workerId);\n // Reset error tracking on success\n consecutiveApiErrors = 0;\n apiRetryDelay = INITIAL_RETRY_DELAY;\n } catch (error) {\n const err = error as Error;\n\n if (isRetryableError(err)) {\n consecutiveApiErrors++;\n\n // Show extended outage warning once\n if (consecutiveApiErrors === OUTAGE_WARNING_THRESHOLD) {\n console.warn(`\\n⚠️ API appears to be experiencing an outage.`);\n console.warn(` Will continue retrying indefinitely (every ${MAX_RETRY_DELAY / 1000}s max).`);\n console.warn(` Press Ctrl+C to stop.\\n`);\n }\n\n if (consecutiveApiErrors < OUTAGE_WARNING_THRESHOLD) {\n console.warn(`⚠️ API error (attempt ${consecutiveApiErrors}): ${err.message}`);\n } else if (consecutiveApiErrors % 10 === 0) {\n // Only log every 10th retry during extended outage to reduce noise\n console.warn(`⚠️ Still retrying... (attempt ${consecutiveApiErrors}, last error: ${err.message})`);\n }\n\n const delaySeconds = Math.round(apiRetryDelay / 1000);\n if (consecutiveApiErrors < OUTAGE_WARNING_THRESHOLD) {\n console.warn(` Retrying in ${delaySeconds}s...`);\n }\n\n await sleep(apiRetryDelay);\n apiRetryDelay = Math.min(apiRetryDelay * 2, MAX_RETRY_DELAY);\n continue;\n }\n\n // Non-retryable error - re-throw\n throw err;\n }\n\n if (!actionDetail) {\n // Show periodic status while waiting\n if (Date.now() - lastStatusTime >= STATUS_INTERVAL_MS) {\n printStatus();\n lastStatusTime = Date.now();\n }\n await sleep(currentPollInterval);\n currentPollInterval = Math.min(currentPollInterval * BACKOFF_MULTIPLIER, MAX_POLL_INTERVAL);\n continue;\n }\n\n // Reset poll interval on successful claim\n currentPollInterval = INITIAL_POLL_INTERVAL;\n\n console.log(`Working: ${actionDetail.title}`);\n\n // Track current claim for graceful shutdown\n if (actionDetail.claim_id) {\n currentClaim = {\n actionId: actionDetail.id,\n claimId: actionDetail.claim_id,\n workerId,\n };\n }\n\n // Determine which phase this action needs\n // Check learning eligibility first - some actions were executed without being prepared\n let phase: 'prepare' | 'learn' | 'execute';\n if (actionDetail.done && actionDetail.reviewed && !actionDetail.learned && !options?.skipLearning) {\n phase = 'learn';\n } else if (!actionDetail.prepared) {\n phase = 'prepare';\n } else if (!actionDetail.done) {\n phase = 'execute';\n } else {\n // Action is done but not reviewed yet, or learning is disabled - nothing to do\n // Only log if this isn't a learning-only scenario being skipped\n const isLearningOnlyAndSkipped = actionDetail.done && actionDetail.reviewed && !actionDetail.learned && options?.skipLearning;\n if (!isLearningOnlyAndSkipped) {\n console.log(`⏭️ Skipping action \"${actionDetail.title}\" - done but not yet reviewed`);\n }\n if (currentClaim && apiClient) {\n try {\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n } catch (releaseError) {\n console.error('⚠️ Failed to release claim:', (releaseError as Error).message);\n }\n }\n currentClaim = null;\n continue;\n }\n\n // Prepare workspace based on phase and repo availability\n const repoUrl = actionDetail.resolved_repository_url || actionDetail.repository_url;\n const branch = actionDetail.resolved_branch || actionDetail.branch;\n\n let workspacePath: string;\n let cleanup: (() => Promise<void>) | undefined;\n let startingCommit: string | undefined;\n\n // Determine if we need to clone the repository\n // - Learning phase: never needs repo (works via API/MCP tools)\n // - Prepare/Execute: need repo if available, blank workspace otherwise\n const needsRepo = phase !== 'learn' && repoUrl;\n\n try {\n if (needsRepo) {\n // Clone repository into workspace\n const workspace = await prepareWorkspace(repoUrl, {\n branch: branch || undefined,\n authToken: credentials.clerkToken,\n });\n workspacePath = workspace.path;\n cleanup = workspace.cleanup;\n startingCommit = workspace.startingCommit;\n } else {\n // Create a blank temp directory (learning phase, or no repo configured)\n if (phase === 'learn') {\n console.log(`📂 Learning phase - creating blank workspace`);\n } else {\n console.log(`📂 No repository configured - creating blank workspace`);\n }\n workspacePath = await mkdtemp(join(tmpdir(), 'cg-workspace-'));\n console.log(` → ${workspacePath}`);\n cleanup = async () => {\n try {\n await rm(workspacePath, { recursive: true, force: true });\n } catch (error) {\n console.error(`Warning: Failed to cleanup workspace at ${workspacePath}:`, error);\n }\n };\n }\n\n if (phase === 'prepare') {\n await runPrepare(actionDetail.id, { cwd: workspacePath, startingCommit, model: options?.forceModel });\n stats.prepared++;\n\n // Release claim after preparation\n if (currentClaim && apiClient) {\n try {\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n } catch (releaseError) {\n console.error('⚠️ Failed to release claim after preparation:', (releaseError as Error).message);\n }\n }\n currentClaim = null;\n continue;\n }\n\n if (phase === 'learn') {\n try {\n await runLearn(actionDetail.id, { cwd: workspacePath, startingCommit, model: options?.forceModel });\n stats.learned++;\n console.log(`Learning extracted: ${actionDetail.title}`);\n } catch (learnError) {\n stats.errors++;\n console.error(`Error during learning: ${(learnError as Error).message}. Continuing...`);\n } finally {\n // Release claim after learning completes (success or failure)\n if (currentClaim && apiClient) {\n try {\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n } catch (releaseError) {\n console.error('⚠️ Failed to release claim:', (releaseError as Error).message);\n }\n }\n currentClaim = null;\n }\n continue;\n }\n\n try {\n await runExecute(actionDetail.id, { cwd: workspacePath, startingCommit, model: options?.forceModel });\n stats.executed++;\n console.log(`Completed: ${actionDetail.title}`);\n } catch (executeError) {\n stats.errors++;\n console.error(`Error: ${(executeError as Error).message}. Continuing...`);\n } finally {\n // Release claim after execution completes (success or failure)\n if (currentClaim && apiClient) {\n try {\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n } catch (releaseError) {\n console.error('⚠️ Failed to release claim:', (releaseError as Error).message);\n }\n }\n currentClaim = null;\n }\n } catch (workspaceError) {\n // Handle workspace preparation or other errors\n stats.errors++;\n console.error(`Error preparing workspace: ${(workspaceError as Error).message}. Continuing...`);\n\n // Release claim on workspace/preparation failure\n if (currentClaim && apiClient) {\n try {\n console.log(`🧹 Releasing claim due to workspace error...`);\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n console.log('✅ Claim released');\n } catch (releaseError) {\n console.error('⚠️ Failed to release claim:', (releaseError as Error).message);\n }\n }\n currentClaim = null;\n } finally {\n if (cleanup) {\n await cleanup();\n }\n }\n }\n\n}\n\n","{\n \"name\": \"@contextgraph/agent\",\n \"version\": \"0.4.14\",\n \"description\": \"Autonomous agent for contextgraph action execution\",\n \"type\": \"module\",\n \"bin\": {\n \"contextgraph-agent\": \"dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"jest\"\n },\n \"keywords\": [\n \"contextgraph\",\n \"agent\",\n \"autonomous\",\n \"cli\"\n ],\n \"author\": \"contextgraph\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/contextgraph/agent.git\"\n },\n \"homepage\": \"https://github.com/contextgraph/agent#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/contextgraph/agent/issues\"\n },\n \"dependencies\": {\n \"@anthropic-ai/claude-agent-sdk\": \"^0.1.50\",\n \"commander\": \"^11.0.0\",\n \"open\": \"^10.0.0\"\n },\n \"devDependencies\": {\n \"@jest/globals\": \"^30.2.0\",\n \"@types/jest\": \"^30.0.0\",\n \"@types/node\": \"^20.0.0\",\n \"jest\": \"^30.2.0\",\n \"ts-jest\": \"^29.4.5\",\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n}\n","import { loadCredentials, isExpired, isTokenExpired } from './credentials.js';\nimport { fetchWithRetry } from './fetch-with-retry.js';\nimport type { ActionDetailResource, ActionNode } from './types/actions.js';\nimport packageJson from '../package.json' assert { type: 'json' };\n\nexport class ApiClient {\n constructor(\n private baseUrl: string = 'https://www.contextgraph.dev'\n ) {}\n\n private async getAuthToken(): Promise<string> {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n throw new Error('Not authenticated. Run authentication first.');\n }\n\n // Check both the stored metadata and the actual JWT expiration\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n throw new Error('Token expired. Re-authenticate to continue.');\n }\n\n return credentials.clerkToken;\n }\n\n async getActionDetail(actionId: string): Promise<ActionDetailResource> {\n const token = await this.getAuthToken();\n\n // Use both x-authorization header and query param for Vercel compatibility\n const response = await fetchWithRetry(\n `${this.baseUrl}/api/actions/${actionId}?token=${encodeURIComponent(token)}`,\n {\n headers: {\n 'x-authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n }\n );\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error);\n }\n\n return result.data;\n }\n\n async fetchTree(rootActionId: string, includeCompleted: boolean = false): Promise<ActionNode> {\n const token = await this.getAuthToken();\n\n // Use both x-authorization header and query param for Vercel compatibility\n const response = await fetchWithRetry(\n `${this.baseUrl}/api/tree/${rootActionId}?includeCompleted=${includeCompleted}&token=${encodeURIComponent(token)}`,\n {\n headers: {\n 'x-authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to fetch tree: ${response.status} ${errorText}`);\n }\n\n const result = await response.json();\n if (!result.success) {\n throw new Error('Failed to fetch tree: API returned unsuccessful response');\n }\n\n // If no root actions, the tree is complete (all actions done)\n if (!result.data.rootActions?.[0]) {\n return { id: rootActionId, title: '', done: true, dependencies: [], children: [] };\n }\n\n return result.data.rootActions[0];\n }\n\n async claimNextAction(workerId: string): Promise<ActionDetailResource | null> {\n const token = await this.getAuthToken();\n\n const response = await fetchWithRetry(\n `${this.baseUrl}/api/worker/next?token=${encodeURIComponent(token)}`,\n {\n method: 'POST',\n headers: {\n 'x-authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n worker_id: workerId,\n agent_version: packageJson.version\n }),\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error ${response.status}: ${errorText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'API returned unsuccessful response');\n }\n\n // API returns null when no work is available\n return result.data;\n }\n\n async releaseClaim(params: { action_id: string; worker_id: string; claim_id: string }): Promise<void> {\n const token = await this.getAuthToken();\n\n const response = await fetchWithRetry(\n `${this.baseUrl}/api/worker/release?token=${encodeURIComponent(token)}`,\n {\n method: 'POST',\n headers: {\n 'x-authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(params),\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error ${response.status}: ${errorText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'API returned unsuccessful response');\n }\n }\n}\n","import { spawn } from 'child_process';\nimport { mkdtemp, rm } from 'fs/promises';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { fetchWithRetry } from './fetch-with-retry.js';\nimport type { GitHubCredentials } from './types/actions.js';\n\nconst API_BASE_URL = 'https://www.contextgraph.dev';\n\nexport interface WorkspaceResult {\n path: string;\n startingCommit: string;\n cleanup: () => Promise<void>;\n}\n\nexport interface PrepareWorkspaceOptions {\n branch?: string;\n authToken: string;\n}\n\nasync function fetchGitHubCredentials(authToken: string): Promise<GitHubCredentials> {\n const response = await fetchWithRetry(`${API_BASE_URL}/api/cli/credentials`, {\n headers: {\n 'x-authorization': `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (response.status === 401) {\n throw new Error('Authentication failed. Please re-authenticate.');\n }\n\n if (response.status === 404) {\n throw new Error(\n 'GitHub not connected. Please connect your GitHub account at https://contextgraph.dev/settings.'\n );\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to fetch GitHub credentials: ${response.statusText}\\n${errorText}`);\n }\n\n return response.json() as Promise<GitHubCredentials>;\n}\n\nfunction runGitCommand(args: string[], cwd?: string): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n const proc = spawn('git', args, { cwd });\n let stdout = '';\n let stderr = '';\n\n proc.stdout.on('data', (data) => {\n stdout += data.toString();\n });\n\n proc.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolve({ stdout, stderr });\n } else {\n reject(new Error(`git ${args[0]} failed (exit ${code}): ${stderr || stdout}`));\n }\n });\n\n proc.on('error', (err) => {\n reject(new Error(`Failed to spawn git: ${err.message}`));\n });\n });\n}\n\nfunction buildAuthenticatedUrl(repoUrl: string, token: string): string {\n // Handle https://github.com/... URLs\n if (repoUrl.startsWith('https://github.com/')) {\n return repoUrl.replace('https://github.com/', `https://${token}@github.com/`);\n }\n\n // Handle https://github.com URLs without trailing slash\n if (repoUrl.startsWith('https://github.com')) {\n return repoUrl.replace('https://github.com', `https://${token}@github.com`);\n }\n\n // For other URLs, return as-is (might be SSH or other provider)\n return repoUrl;\n}\n\nexport async function prepareWorkspace(\n repoUrl: string,\n options: PrepareWorkspaceOptions\n): Promise<WorkspaceResult> {\n const { branch, authToken } = options;\n\n // Fetch GitHub credentials\n const credentials = await fetchGitHubCredentials(authToken);\n\n // Create temp directory\n const workspacePath = await mkdtemp(join(tmpdir(), 'cg-workspace-'));\n\n const cleanup = async () => {\n try {\n await rm(workspacePath, { recursive: true, force: true });\n } catch (error) {\n console.error(`Warning: Failed to cleanup workspace at ${workspacePath}:`, error);\n }\n };\n\n try {\n // Build authenticated clone URL\n const cloneUrl = buildAuthenticatedUrl(repoUrl, credentials.githubToken);\n\n // Clone the repository\n console.log(`📂 Cloning ${repoUrl}`);\n console.log(` → ${workspacePath}`);\n await runGitCommand(['clone', cloneUrl, workspacePath]);\n console.log(`✅ Repository cloned`);\n\n // Configure git identity if we have the info\n if (credentials.githubUsername) {\n await runGitCommand(['config', 'user.name', credentials.githubUsername], workspacePath);\n }\n if (credentials.githubEmail) {\n await runGitCommand(['config', 'user.email', credentials.githubEmail], workspacePath);\n }\n\n // Handle branch checkout if specified\n if (branch) {\n // Check if branch exists remotely\n const { stdout } = await runGitCommand(\n ['ls-remote', '--heads', 'origin', branch],\n workspacePath\n );\n\n const branchExists = stdout.trim().length > 0;\n\n if (branchExists) {\n // Checkout existing branch\n console.log(`🌿 Checking out branch: ${branch}`);\n await runGitCommand(['checkout', branch], workspacePath);\n } else {\n // Create new branch\n console.log(`🌱 Creating new branch: ${branch}`);\n await runGitCommand(['checkout', '-b', branch], workspacePath);\n }\n }\n\n // Capture starting commit for historical accuracy\n const { stdout: commitHash } = await runGitCommand(['rev-parse', 'HEAD'], workspacePath);\n const startingCommit = commitHash.trim();\n\n return { path: workspacePath, startingCommit, cleanup };\n } catch (error) {\n // Cleanup on failure\n await cleanup();\n throw error;\n }\n}\n"],"mappings":"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","names":["readFileSync","fileURLToPath","dirname","join","path","API_BASE_URL","API_BASE_URL","mkdtemp","rm","tmpdir","join","spawn","join","API_BASE_URL","spawn","join","__filename","__dirname","join","mkdtemp","join","tmpdir","rm","__filename","fileURLToPath","__dirname","dirname","packageJson","readFileSync","join"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/index.ts","../src/callback-server.ts","../src/credentials.ts","../src/auth-flow.ts","../src/workflows/auth.ts","../src/claude-sdk.ts","../src/plugin-setup.ts","../src/sdk-event-transformer.ts","../src/fetch-with-retry.ts","../src/log-transport.ts","../src/log-buffer.ts","../src/heartbeat-manager.ts","../src/workflows/prepare.ts","../src/workflows/execute.ts","../src/workflows/agent.ts","../package.json","../src/api-client.ts","../src/workspace-prep.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { runAuth } from '../workflows/auth.js';\nimport { runPrepare } from '../workflows/prepare.js';\nimport { runExecute } from '../workflows/execute.js';\nimport { runLocalAgent } from '../workflows/agent.js';\nimport { loadCredentials, isExpired, isTokenExpired } from '../credentials.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8')\n);\n\nconst program = new Command();\n\nprogram\n .name('contextgraph-agent')\n .description('Autonomous agent for contextgraph action execution')\n .version(packageJson.version);\n\nprogram\n .command('run')\n .description('Run continuous worker loop (claims and executes actions until Ctrl+C)')\n .option('--force-haiku', 'Force all workflows to use claude-haiku-4-5 instead of default models')\n .action(async (options) => {\n try {\n await runLocalAgent({\n forceModel: options.forceHaiku ? 'claude-haiku-4-5-20251001' : undefined,\n });\n } catch (error) {\n if (error instanceof Error) {\n console.error('Error running agent:', error.message || '(no message)');\n if (error.stack) {\n console.error('\\nStack trace:');\n console.error(error.stack);\n }\n } else {\n console.error('Error running agent:', error);\n }\n process.exit(1);\n }\n });\n\nprogram\n .command('auth')\n .description('Authenticate with contextgraph.dev')\n .action(async () => {\n try {\n await runAuth();\n } catch (error) {\n console.error('Error during authentication:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('prepare')\n .argument('<action-id>', 'Action ID to prepare')\n .description('Prepare a single action')\n .action(async (actionId: string) => {\n try {\n await runPrepare(actionId);\n } catch (error) {\n console.error('Error preparing action:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('execute')\n .argument('<action-id>', 'Action ID to execute')\n .description('Execute a single action')\n .action(async (actionId: string) => {\n try {\n await runExecute(actionId);\n } catch (error) {\n console.error('Error executing action:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram\n .command('whoami')\n .description('Show current authentication status')\n .action(async () => {\n try {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n console.log('Not authenticated. Run `contextgraph-agent auth` to authenticate.');\n process.exit(1);\n }\n\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n console.log('⚠️ Token expired. Run `contextgraph-agent auth` to re-authenticate.');\n console.log(`User ID: ${credentials.userId}`);\n console.log(`Expired at: ${credentials.expiresAt}`);\n process.exit(1);\n }\n\n console.log('✅ Authenticated');\n console.log(`User ID: ${credentials.userId}`);\n console.log(`Expires at: ${credentials.expiresAt}`);\n } catch (error) {\n console.error('Error checking authentication:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import http from 'http';\nimport { URL } from 'url';\nimport type { CallbackResult } from './types/actions.js';\n\nexport type CallbackServerResult = {\n port: number;\n waitForCallback: () => Promise<CallbackResult>;\n close: () => Promise<void>;\n};\n\nconst MIN_PORT = 3000;\nconst MAX_PORT = 3100;\n\nasync function findFreePort(): Promise<number> {\n for (let port = MIN_PORT; port <= MAX_PORT; port++) {\n const isAvailable = await checkPortAvailable(port);\n if (isAvailable) {\n return port;\n }\n }\n\n throw new Error(`No free ports found between ${MIN_PORT} and ${MAX_PORT}`);\n}\n\nfunction checkPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = http.createServer();\n\n server.once('error', () => {\n resolve(false);\n });\n\n server.once('listening', () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n}\n\nexport async function startCallbackServer(): Promise<CallbackServerResult> {\n const port = await findFreePort();\n\n let callbackResolve: ((result: CallbackResult) => void) | null = null;\n const connections = new Set<import('net').Socket>();\n\n const server = http.createServer((req, res) => {\n const url = new URL(req.url || '/', `http://localhost:${port}`);\n\n if (url.pathname === '/callback') {\n const token = url.searchParams.get('token');\n const userId = url.searchParams.get('userId');\n\n if (!token) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getErrorPage('Missing token parameter'));\n return;\n }\n\n if (!userId) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getErrorPage('Missing userId parameter'));\n return;\n }\n\n if (callbackResolve) {\n callbackResolve({ token, userId });\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getSuccessPage());\n } else {\n res.writeHead(404, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getNotFoundPage());\n }\n });\n\n // Track connections so we can destroy them on close\n server.on('connection', (socket) => {\n connections.add(socket);\n socket.on('close', () => {\n connections.delete(socket);\n });\n });\n\n await new Promise<void>((resolve) => {\n server.listen(port, resolve);\n });\n\n return {\n port,\n waitForCallback: () => {\n return new Promise((resolve) => {\n callbackResolve = resolve;\n });\n },\n close: () => {\n return new Promise<void>((resolve, reject) => {\n // Destroy all active connections to ensure server closes immediately\n for (const socket of connections) {\n socket.destroy();\n }\n connections.clear();\n\n server.close((err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n },\n };\n}\n\nfunction getSuccessPage(): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authentication Successful</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link href=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap\" rel=\"stylesheet\">\n <style>\n :root {\n --bg: hsl(0 0% 8%);\n --tile-bg: hsl(0 0% 12%);\n --cream: hsl(45 30% 85%);\n --orange: hsl(30 95% 55%);\n --subtitle: hsl(0 0% 55%);\n --border: hsl(0 0% 20%);\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: var(--bg);\n padding: 1rem;\n }\n\n .container {\n background: var(--tile-bg);\n padding: 3rem;\n border-radius: 0.75rem;\n border: 1px solid var(--border);\n text-align: center;\n max-width: 400px;\n width: 100%;\n }\n\n .icon-container {\n width: 80px;\n height: 80px;\n margin: 0 auto 1.5rem;\n background: hsl(145 50% 12%);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid hsl(145 50% 25%);\n }\n\n .icon {\n width: 40px;\n height: 40px;\n stroke: hsl(145 70% 55%);\n stroke-width: 3;\n fill: none;\n }\n\n h1 {\n color: var(--cream);\n margin: 0 0 0.75rem 0;\n font-size: 1.25rem;\n font-weight: 500;\n letter-spacing: -0.02em;\n }\n\n p {\n color: var(--subtitle);\n margin: 0;\n font-size: 0.875rem;\n line-height: 1.6;\n }\n\n .brand {\n margin-top: 2rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--border);\n }\n\n .brand-text {\n color: var(--orange);\n font-size: 0.75rem;\n font-weight: 500;\n letter-spacing: 0.05em;\n }\n\n @keyframes check-draw {\n 0% {\n stroke-dashoffset: 24;\n }\n 100% {\n stroke-dashoffset: 0;\n }\n }\n\n .icon polyline {\n stroke-dasharray: 24;\n stroke-dashoffset: 24;\n animation: check-draw 0.4s ease-out 0.2s forwards;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"icon-container\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\">\n <polyline points=\"4 12 10 18 20 6\"></polyline>\n </svg>\n </div>\n <h1>Authentication successful</h1>\n <p>You can close this window and return to your terminal.</p>\n <div class=\"brand\">\n <span class=\"brand-text\">CONTEXTGRAPH</span>\n </div>\n </div>\n</body>\n</html>\n `.trim();\n}\n\nfunction getErrorPage(message: string): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Authentication Error</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link href=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap\" rel=\"stylesheet\">\n <style>\n :root {\n --bg: hsl(0 0% 8%);\n --tile-bg: hsl(0 0% 12%);\n --red: hsl(0 80% 60%);\n --red-dim: hsl(0 50% 12%);\n --red-border: hsl(0 50% 25%);\n --cream: hsl(45 30% 85%);\n --orange: hsl(30 95% 55%);\n --subtitle: hsl(0 0% 55%);\n --border: hsl(0 0% 20%);\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: var(--bg);\n padding: 1rem;\n }\n\n .container {\n background: var(--tile-bg);\n padding: 3rem;\n border-radius: 0.75rem;\n border: 1px solid var(--border);\n text-align: center;\n max-width: 400px;\n width: 100%;\n }\n\n .icon-container {\n width: 80px;\n height: 80px;\n margin: 0 auto 1.5rem;\n background: var(--red-dim);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid var(--red-border);\n }\n\n .icon {\n width: 40px;\n height: 40px;\n stroke: var(--red);\n stroke-width: 3;\n fill: none;\n }\n\n h1 {\n color: var(--red);\n margin: 0 0 0.75rem 0;\n font-size: 1.25rem;\n font-weight: 500;\n letter-spacing: -0.02em;\n }\n\n p {\n color: var(--subtitle);\n margin: 0;\n font-size: 0.875rem;\n line-height: 1.6;\n }\n\n .brand {\n margin-top: 2rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--border);\n }\n\n .brand-text {\n color: var(--orange);\n font-size: 0.75rem;\n font-weight: 500;\n letter-spacing: 0.05em;\n }\n\n @keyframes x-draw {\n 0% {\n stroke-dashoffset: 34;\n }\n 100% {\n stroke-dashoffset: 0;\n }\n }\n\n .icon line {\n stroke-dasharray: 17;\n stroke-dashoffset: 17;\n }\n\n .icon line:first-child {\n animation: x-draw 0.3s ease-out 0.2s forwards;\n }\n\n .icon line:last-child {\n animation: x-draw 0.3s ease-out 0.35s forwards;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"icon-container\">\n <svg class=\"icon\" viewBox=\"0 0 24 24\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n </svg>\n </div>\n <h1>Authentication error</h1>\n <p>${message}</p>\n <div class=\"brand\">\n <span class=\"brand-text\">CONTEXTGRAPH</span>\n </div>\n </div>\n</body>\n</html>\n `.trim();\n}\n\nfunction getNotFoundPage(): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>Not Found</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link href=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap\" rel=\"stylesheet\">\n <style>\n :root {\n --bg: hsl(0 0% 8%);\n --tile-bg: hsl(0 0% 12%);\n --cream: hsl(45 30% 85%);\n --orange: hsl(30 95% 55%);\n --subtitle: hsl(0 0% 55%);\n --border: hsl(0 0% 20%);\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n font-family: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n background: var(--bg);\n padding: 1rem;\n }\n\n .container {\n background: var(--tile-bg);\n padding: 3rem;\n border-radius: 0.75rem;\n border: 1px solid var(--border);\n text-align: center;\n max-width: 400px;\n width: 100%;\n }\n\n .code {\n color: var(--orange);\n font-size: 3rem;\n font-weight: 700;\n margin: 0 0 0.5rem 0;\n letter-spacing: -0.02em;\n }\n\n h1 {\n color: var(--cream);\n margin: 0;\n font-size: 1rem;\n font-weight: 400;\n }\n\n .brand {\n margin-top: 2rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--border);\n }\n\n .brand-text {\n color: var(--orange);\n font-size: 0.75rem;\n font-weight: 500;\n letter-spacing: 0.05em;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"code\">404</div>\n <h1>Not Found</h1>\n <div class=\"brand\">\n <span class=\"brand-text\">CONTEXTGRAPH</span>\n </div>\n </div>\n</body>\n</html>\n `.trim();\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\nimport type { Credentials } from './types/actions.js';\n\nfunction getCredentialsDir(): string {\n return process.env.CONTEXTGRAPH_CREDENTIALS_DIR || path.join(os.homedir(), '.contextgraph');\n}\n\nfunction getCredentialsPath(): string {\n return path.join(getCredentialsDir(), 'credentials.json');\n}\n\nexport const CREDENTIALS_DIR = getCredentialsDir();\nexport const CREDENTIALS_PATH = getCredentialsPath();\n\nexport async function saveCredentials(credentials: Credentials): Promise<void> {\n const dir = getCredentialsDir();\n const filePath = getCredentialsPath();\n\n await fs.mkdir(dir, { recursive: true, mode: 0o700 });\n\n const content = JSON.stringify(credentials, null, 2);\n await fs.writeFile(filePath, content, { mode: 0o600 });\n}\n\nexport async function loadCredentials(): Promise<Credentials | null> {\n // Check for API token in environment variable first\n const apiToken = process.env.CONTEXTGRAPH_API_TOKEN;\n if (apiToken) {\n // Create credentials from API token\n // API tokens don't expire in the same way, set a far future date\n const farFuture = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(); // 1 year\n return {\n clerkToken: apiToken,\n userId: 'api-token-user', // Placeholder - server will resolve actual user\n expiresAt: farFuture,\n createdAt: new Date().toISOString(),\n };\n }\n\n // Fall back to file-based credentials\n const filePath = getCredentialsPath();\n\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as Credentials;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n\n console.error('Error loading credentials:', error);\n return null;\n }\n}\n\nexport async function deleteCredentials(): Promise<void> {\n const filePath = getCredentialsPath();\n\n try {\n await fs.unlink(filePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n}\n\nexport function isExpired(credentials: Credentials): boolean {\n return new Date(credentials.expiresAt) <= new Date();\n}\n\nexport function isTokenExpired(token: string): boolean {\n try {\n // API tokens (non-JWT format) don't expire - check with server\n // API tokens typically start with a prefix like \"cg_\" or similar\n const parts = token.split('.');\n if (parts.length !== 3) {\n // Not a JWT - assume it's an API token that doesn't expire\n return false;\n }\n\n // Decode JWT to check actual token expiration\n const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());\n const now = Math.floor(Date.now() / 1000);\n\n // Token without exp claim is considered expired\n if (!payload.exp) {\n return true;\n }\n\n // Check if token has expired (including exactly now)\n if (payload.exp <= now) {\n return true;\n }\n\n // Check if token is not yet valid\n if (payload.nbf && payload.nbf > now) {\n return true;\n }\n\n return false;\n } catch {\n // If we can't decode it as JWT, assume it's an API token\n return false;\n }\n}\n\nexport function getTokenExpiration(token: string): Date | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return null;\n }\n\n const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());\n if (payload.exp) {\n return new Date(payload.exp * 1000);\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get an authenticated fetch function that includes the Clerk token\n *\n * This loads the credentials from disk and returns a fetch function\n * that automatically includes the x-authorization header (workaround for Vercel stripping Authorization).\n *\n * Throws an error if credentials are not found or expired.\n */\nexport async function getAuthenticatedFetch(): Promise<typeof fetch> {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n throw new Error(\n 'No credentials found. Please run authentication first.'\n );\n }\n\n if (isTokenExpired(credentials.clerkToken)) {\n throw new Error(\n 'Your credentials have expired. Please re-authenticate.'\n );\n }\n\n // Return a fetch function that includes the x-authorization header\n // Use x-authorization instead of Authorization because Vercel strips Authorization header\n return async (url: string | URL | Request, init?: RequestInit) => {\n const headers = new Headers(init?.headers);\n headers.set('x-authorization', `Bearer ${credentials.clerkToken}`);\n\n return fetch(url, {\n ...init,\n headers,\n });\n };\n}\n","import { startCallbackServer } from './callback-server.js';\nimport { saveCredentials } from './credentials.js';\n\ntype AuthenticationResult =\n | {\n success: true;\n credentials: {\n token: string;\n userId: string;\n };\n }\n | {\n success: false;\n error: string;\n };\n\ntype AuthenticationOptions = {\n baseUrl?: string;\n timeout?: number;\n openBrowser?: (url: string) => Promise<void>;\n};\n\nconst DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_BASE_URL = 'https://www.contextgraph.dev';\n\nasync function defaultOpenBrowser(url: string): Promise<void> {\n const open = (await import('open')).default;\n await open(url);\n}\n\nexport async function authenticateAgent(\n options: AuthenticationOptions = {}\n): Promise<AuthenticationResult> {\n const {\n baseUrl = DEFAULT_BASE_URL,\n timeout = DEFAULT_TIMEOUT,\n openBrowser = defaultOpenBrowser,\n } = options;\n\n let server;\n\n try {\n server = await startCallbackServer();\n const { port, waitForCallback, close } = server;\n\n const authUrl = `${baseUrl}/auth/cli-callback?port=${port}`;\n\n console.log(`Opening browser to: ${authUrl}`);\n await openBrowser(authUrl);\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('Authentication timeout')), timeout);\n });\n\n const result = await Promise.race([waitForCallback(), timeoutPromise]);\n\n const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(); // 24 hours\n\n await saveCredentials({\n clerkToken: result.token,\n userId: result.userId,\n expiresAt,\n createdAt: new Date().toISOString(),\n });\n\n await close();\n\n return {\n success: true,\n credentials: {\n token: result.token,\n userId: result.userId,\n },\n };\n } catch (error) {\n if (server) {\n await server.close();\n }\n\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n}\n","import { authenticateAgent } from '../auth-flow.js';\n\nexport async function runAuth(): Promise<void> {\n console.log('Starting authentication flow...\\n');\n\n const result = await authenticateAgent();\n\n if (result.success) {\n console.log('\\n✅ Authentication successful!');\n console.log(`User ID: ${result.credentials.userId}`);\n process.exit(0);\n } else {\n console.error('\\n❌ Authentication failed:', result.error);\n process.exit(1);\n }\n}\n\n","import { query, type SDKMessage, type SDKAssistantMessage, type SDKResultMessage } from '@anthropic-ai/claude-agent-sdk';\nimport type { ClaudeResult, SpawnClaudeOptions } from './types/actions.js';\nimport { ensurePlugin } from './plugin-setup.js';\nimport { transformSDKMessage } from './sdk-event-transformer.js';\nimport type { LogEvent } from './log-transport.js';\n\n// Constants for timeouts and truncation\nconst EXECUTION_TIMEOUT_MS = 20 * 60 * 1000; // 20 minutes\nconst THINKING_TRUNCATE_LENGTH = 100;\nconst COMMAND_TRUNCATE_LENGTH = 60;\n\n// Helper types for SDK message content\ntype ToolInput =\n | { file_path: string; old_string?: string; new_string?: string } // Read, Edit, Write\n | { command: string; description?: string; timeout?: number } // Bash\n | { pattern: string; glob?: string; type?: string; output_mode?: string } // Grep\n | { pattern: string; path?: string } // Glob\n | Record<string, unknown>; // Other tools\n\ntype SDKMessageContent = {\n type: string;\n text?: string;\n name?: string;\n input?: ToolInput;\n thinking?: string;\n};\n\n/**\n * Format tool use for console output\n */\nfunction formatToolUse(content: SDKMessageContent): string {\n if (content.type === 'tool_use') {\n const name = content.name || 'unknown';\n const summary = formatToolInput(name, content.input);\n return ` 🔧 ${name}${summary}`;\n }\n if (content.type === 'thinking' && content.thinking) {\n const truncated = content.thinking.length > THINKING_TRUNCATE_LENGTH\n ? content.thinking.substring(0, THINKING_TRUNCATE_LENGTH) + '...'\n : content.thinking;\n return ` 💭 ${truncated}`;\n }\n return '';\n}\n\n/**\n * Format tool input parameters for display\n */\nfunction formatToolInput(toolName: string, input: any): string {\n if (!input) return '';\n\n switch (toolName) {\n case 'Read':\n return `: ${input.file_path}`;\n case 'Edit':\n case 'Write':\n return `: ${input.file_path}`;\n case 'Bash':\n const cmd = input.command || '';\n const truncated = cmd.length > COMMAND_TRUNCATE_LENGTH\n ? cmd.substring(0, COMMAND_TRUNCATE_LENGTH) + '...'\n : cmd;\n return `: ${truncated}`;\n case 'Grep':\n return `: \"${input.pattern}\"`;\n case 'Glob':\n return `: ${input.pattern}`;\n default:\n return '';\n }\n}\n\n/**\n * Format assistant message content for display\n */\nfunction formatAssistantMessage(content: Array<SDKMessageContent>): string {\n const lines: string[] = [];\n\n for (const item of content) {\n if (item.type === 'text' && item.text) {\n lines.push(` ${item.text}`);\n } else if (item.type === 'tool_use' || item.type === 'thinking') {\n const formatted = formatToolUse(item);\n if (formatted) lines.push(formatted);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Format SDK message for console output\n */\nfunction formatMessage(message: SDKMessage): string | null {\n switch (message.type) {\n case 'system':\n if (message.subtype === 'init') {\n return '🚀 Claude session initialized';\n }\n return null;\n\n case 'assistant':\n const assistantMsg = message as SDKAssistantMessage;\n if (assistantMsg.message?.content && Array.isArray(assistantMsg.message.content)) {\n return formatAssistantMessage(assistantMsg.message.content as Array<SDKMessageContent>);\n }\n return null;\n\n case 'result':\n const resultMsg = message as SDKResultMessage;\n if (resultMsg.subtype === 'success') {\n const duration = resultMsg.duration_ms ? `${(resultMsg.duration_ms / 1000).toFixed(1)}s` : 'unknown';\n return `✅ Completed in ${duration}`;\n } else if (resultMsg.subtype.startsWith('error_')) {\n return '❌ Execution failed';\n }\n return null;\n\n default:\n return null;\n }\n}\n\n/**\n * Extended options for executeClaude with log streaming support\n */\nexport interface ExecuteClaudeOptions extends SpawnClaudeOptions {\n /** Callback for log events - called for each SDK message transformed into a LogEvent */\n onLogEvent?: (event: LogEvent) => void;\n /** Optional model to use (e.g., 'claude-opus-4-5-20251101'). If not specified, uses SDK default (Sonnet). */\n model?: string;\n}\n\n/**\n * Execute Claude using the Agent SDK\n *\n * This is a drop-in replacement for spawnClaude() that uses the SDK instead of spawning a CLI process.\n * It matches the same interface (SpawnClaudeOptions) and returns the same result type (ClaudeResult).\n *\n * Optionally accepts onLogEvent callback for real-time log streaming.\n */\nexport async function executeClaude(\n options: ExecuteClaudeOptions\n): Promise<ClaudeResult> {\n let sessionId: string | undefined;\n let totalCost = 0;\n let usage: any;\n\n // Create abort controller for timeout\n const abortController = new AbortController();\n const timeout = setTimeout(() => {\n abortController.abort();\n }, EXECUTION_TIMEOUT_MS);\n\n try {\n // Ensure the contextgraph plugin is available (clones from GitHub if missing)\n const pluginPath = await ensurePlugin();\n console.log('[Agent SDK] Loading plugin from:', pluginPath);\n console.log('[Agent SDK] Auth token available:', !!options.authToken);\n console.log('[Agent SDK] Anthropic API key available:', !!process.env.ANTHROPIC_API_KEY);\n console.log('[Agent SDK] Claude OAuth token available:', !!process.env.CLAUDE_CODE_OAUTH_TOKEN);\n\n // Create the query with SDK using the plugin\n const iterator = query({\n prompt: options.prompt,\n options: {\n ...(options.model ? { model: options.model } : {}),\n cwd: options.cwd,\n abortController,\n permissionMode: 'bypassPermissions', // Allow MCP tools to execute automatically\n maxTurns: 100, // Reasonable limit\n env: {\n ...process.env,\n // Pass auth token through environment for MCP server\n CONTEXTGRAPH_AUTH_TOKEN: options.authToken || '',\n // Pass Anthropic API key for SDK authentication\n ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || '',\n // Pass Claude OAuth token for SDK authentication (alternative to API key)\n CLAUDE_CODE_OAUTH_TOKEN: process.env.CLAUDE_CODE_OAUTH_TOKEN || '',\n },\n // Load the contextgraph plugin (provides MCP server URL and other config)\n plugins: [\n {\n type: 'local',\n path: pluginPath,\n }\n ]\n // Note: Auth is passed via CONTEXTGRAPH_AUTH_TOKEN environment variable above\n }\n });\n\n // Iterate through messages\n for await (const message of iterator) {\n // Capture session ID from first message\n if (!sessionId && message.session_id) {\n sessionId = message.session_id;\n }\n\n // Format and display the message (preserved console output)\n const formatted = formatMessage(message);\n if (formatted) {\n console.log(formatted);\n }\n\n // Transform and emit log event if callback is provided\n if (options.onLogEvent) {\n try {\n const logEvent = transformSDKMessage(message);\n if (logEvent) {\n options.onLogEvent(logEvent);\n }\n } catch (error) {\n // Log transformation errors but don't block execution\n console.error('[Log Transform]', error instanceof Error ? error.message : String(error));\n }\n }\n\n // Capture result metadata\n if (message.type === 'result') {\n const resultMsg = message as SDKResultMessage;\n totalCost = resultMsg.total_cost_usd || 0;\n usage = resultMsg.usage;\n\n // Check for errors\n if (resultMsg.subtype.startsWith('error_')) {\n clearTimeout(timeout);\n return {\n exitCode: 1,\n sessionId,\n usage,\n cost: totalCost,\n };\n }\n }\n }\n\n clearTimeout(timeout);\n\n // Return successful result\n return {\n exitCode: 0,\n sessionId,\n usage,\n cost: totalCost,\n };\n\n } catch (error) {\n clearTimeout(timeout);\n\n // Handle abort/timeout\n if (abortController.signal.aborted) {\n const timeoutMinutes = EXECUTION_TIMEOUT_MS / (60 * 1000);\n throw new Error(`Claude SDK execution timed out after ${timeoutMinutes} minutes`);\n }\n\n // Handle other errors\n throw new Error(`Failed to execute Claude SDK: ${(error as Error).message}`);\n }\n}\n","import { spawn } from 'child_process';\nimport { access, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nconst PLUGIN_REPO = 'https://github.com/contextgraph/claude-code-plugin.git';\nconst PLUGIN_DIR = join(homedir(), '.contextgraph', 'claude-code-plugin');\nconst PLUGIN_PATH = join(PLUGIN_DIR, 'plugins', 'contextgraph');\n\n/**\n * Get the path to the contextgraph plugin, cloning it if necessary\n */\nexport async function ensurePlugin(): Promise<string> {\n // Check if plugin already exists\n try {\n await access(PLUGIN_PATH);\n console.log(`📦 Using plugin: ${PLUGIN_PATH}`);\n return PLUGIN_PATH;\n } catch {\n // Plugin path doesn't exist, check if repo dir exists\n }\n\n // Check if repo directory exists but plugin path is missing (incomplete clone or wrong structure)\n let repoDirExists = false;\n try {\n await access(PLUGIN_DIR);\n repoDirExists = true;\n } catch {\n // Directory doesn't exist, will need to clone\n }\n\n if (repoDirExists) {\n // Directory exists but plugin path doesn't - try pulling latest\n console.log('📦 Plugin directory exists but incomplete, pulling latest...');\n await runCommand('git', ['pull'], PLUGIN_DIR);\n\n // Check again after pull\n try {\n await access(PLUGIN_PATH);\n console.log(`📦 Plugin ready: ${PLUGIN_PATH}`);\n return PLUGIN_PATH;\n } catch {\n throw new Error(`Plugin not found at ${PLUGIN_PATH} even after git pull. Check repository structure.`);\n }\n }\n\n console.log(`📦 Cloning plugin from ${PLUGIN_REPO}...`);\n\n // Ensure parent directory exists\n const contextgraphDir = join(homedir(), '.contextgraph');\n try {\n await mkdir(contextgraphDir, { recursive: true });\n } catch {\n // Directory might already exist\n }\n\n // Clone the repository\n await runCommand('git', ['clone', PLUGIN_REPO, PLUGIN_DIR]);\n\n // Verify plugin exists after clone\n try {\n await access(PLUGIN_PATH);\n console.log(`📦 Plugin installed: ${PLUGIN_PATH}`);\n return PLUGIN_PATH;\n } catch {\n throw new Error(`Plugin clone succeeded but plugin path not found at ${PLUGIN_PATH}`);\n }\n}\n\n/**\n * Update the plugin to latest version\n */\nexport async function updatePlugin(): Promise<void> {\n try {\n await access(PLUGIN_DIR);\n } catch {\n throw new Error('Plugin not installed. Run the agent first to auto-install.');\n }\n\n console.log('[Plugin Setup] Updating plugin...');\n await runCommand('git', ['pull'], PLUGIN_DIR);\n console.log('[Plugin Setup] Plugin updated');\n}\n\n/**\n * Get the plugin path (without ensuring it exists)\n */\nexport function getPluginPath(): string {\n return PLUGIN_PATH;\n}\n\nfunction runCommand(command: string, args: string[], cwd?: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, { cwd, stdio: 'inherit' });\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`${command} ${args[0]} failed with exit code ${code}`));\n }\n });\n\n proc.on('error', (err) => {\n reject(new Error(`Failed to spawn ${command}: ${err.message}`));\n });\n });\n}\n","/**\n * SDK Event Transformer - Transforms Claude SDK messages into agentLog event format\n *\n * This module provides a pure transformation function that converts SDK messages\n * into LogEvent objects for the log streaming infrastructure.\n *\n * IMPORTANT: Events are emitted in the same format as the Vercel sandbox agents\n * to ensure compatibility with the AgentEventMessage component. The full SDK\n * message is preserved in the `data` field without truncation.\n */\n\nimport type { LogEvent } from './log-transport.js';\nimport type { SDKMessage, SDKAssistantMessage, SDKResultMessage } from '@anthropic-ai/claude-agent-sdk';\n\n/**\n * Transform an SDK message into a LogEvent\n *\n * The transformation preserves the full SDK message in the `data` field,\n * matching the Vercel sandbox format for UI compatibility.\n *\n * @param message - The SDK message to transform\n * @returns A LogEvent or null if the message should be skipped\n */\nexport function transformSDKMessage(message: SDKMessage): LogEvent | null {\n const timestamp = new Date().toISOString();\n\n switch (message.type) {\n case 'system':\n return transformSystemMessage(message, timestamp);\n\n case 'assistant':\n return transformAssistantMessage(message as SDKAssistantMessage, timestamp);\n\n case 'result':\n return transformResultMessage(message as SDKResultMessage, timestamp);\n\n case 'user':\n // User messages with tool results\n return transformUserMessage(message, timestamp);\n\n default:\n // Skip unknown message types\n return null;\n }\n}\n\n/**\n * Transform a system message (initialization, etc.)\n */\nfunction transformSystemMessage(\n message: SDKMessage & { subtype?: string; content?: string },\n timestamp: string\n): LogEvent {\n // Emit in the format expected by AgentEventMessage\n return {\n eventType: 'claude_message',\n content: message.content || `System: ${message.subtype || 'initialization'}`,\n data: {\n type: 'system',\n subtype: message.subtype,\n content: message.content,\n session_id: message.session_id,\n },\n timestamp,\n };\n}\n\n/**\n * Transform an assistant message (text, tool use, thinking)\n *\n * Preserves the full SDK message in the data field for UI rendering.\n * This matches the Vercel sandbox format where the entire SDK JSON\n * is stored in event.data.\n */\nfunction transformAssistantMessage(\n message: SDKAssistantMessage,\n timestamp: string\n): LogEvent | null {\n const content = message.message?.content;\n if (!content || !Array.isArray(content)) {\n return null;\n }\n\n // Generate a human-readable summary for the content field\n const contentSummary = generateContentSummary(content);\n\n // Emit the full SDK message structure in data for UI compatibility\n // This matches sandbox-execution.ts line 512-522\n return {\n eventType: 'claude_message',\n content: contentSummary,\n data: {\n type: 'assistant',\n message: message.message,\n session_id: message.session_id,\n parent_tool_use_id: message.parent_tool_use_id,\n },\n timestamp,\n };\n}\n\n/**\n * Transform a result message (completion status)\n *\n * Emits as claude_message with type='result' to match sandbox format.\n */\nfunction transformResultMessage(\n message: SDKResultMessage,\n timestamp: string\n): LogEvent {\n const isSuccess = message.subtype === 'success';\n const durationSec = message.duration_ms\n ? (message.duration_ms / 1000).toFixed(1)\n : 'unknown';\n\n return {\n eventType: 'claude_message',\n content: isSuccess\n ? `Completed successfully in ${durationSec}s`\n : `Execution ${message.subtype}: ${durationSec}s`,\n data: {\n type: 'result',\n subtype: message.subtype,\n duration_ms: message.duration_ms,\n total_cost_usd: message.total_cost_usd,\n num_turns: message.num_turns,\n usage: message.usage,\n session_id: message.session_id,\n },\n timestamp,\n };\n}\n\n/**\n * Transform a user message (typically contains tool results)\n *\n * Preserves full tool result content for UI rendering.\n */\nfunction transformUserMessage(\n message: SDKMessage & { message?: { content?: unknown } },\n timestamp: string\n): LogEvent | null {\n const content = message.message?.content;\n if (!content || !Array.isArray(content)) {\n return null;\n }\n\n // Check if this contains tool results\n const hasToolResults = content.some(\n (block: any) => block.type === 'tool_result'\n );\n\n if (!hasToolResults) {\n return null;\n }\n\n // Generate summary for content field\n const summaries = content\n .filter((block: any) => block.type === 'tool_result')\n .map((block: any) => {\n const prefix = block.is_error ? '❌' : '✓';\n const resultText = extractToolResultText(block.content);\n return `${prefix} ${resultText.substring(0, 100)}${resultText.length > 100 ? '...' : ''}`;\n });\n\n // Emit full message structure in data for UI rendering\n return {\n eventType: 'claude_message',\n content: summaries.join('\\n'),\n data: {\n type: 'user',\n message: message.message,\n session_id: message.session_id,\n },\n timestamp,\n };\n}\n\n/**\n * Generate a human-readable summary from message content blocks\n */\nfunction generateContentSummary(content: unknown[]): string {\n const parts: string[] = [];\n\n for (const block of content as any[]) {\n if (block.type === 'text' && block.text) {\n // Include first 200 chars of text in summary\n const text = block.text.length > 200\n ? block.text.substring(0, 200) + '...'\n : block.text;\n parts.push(text);\n } else if (block.type === 'tool_use') {\n parts.push(`🔧 ${block.name}`);\n } else if (block.type === 'thinking') {\n parts.push('💭 [thinking]');\n }\n }\n\n return parts.join(' | ') || '[no content]';\n}\n\n/**\n * Extract text content from a tool result for summary purposes\n */\nfunction extractToolResultText(\n content: string | Array<{ type: string; text?: string }> | undefined\n): string {\n if (!content) return '';\n\n if (typeof content === 'string') {\n return content;\n }\n\n if (Array.isArray(content)) {\n return content\n .filter(block => block.type === 'text' && block.text)\n .map(block => block.text)\n .join('\\n');\n }\n\n return '';\n}\n\n/**\n * Batch transform multiple SDK messages\n * Useful for processing message arrays from SDK iterations\n *\n * @param messages - Array of SDK messages\n * @returns Array of LogEvents (excluding nulls)\n */\nexport function transformSDKMessages(messages: SDKMessage[]): LogEvent[] {\n return messages\n .map(transformSDKMessage)\n .filter((event): event is LogEvent => event !== null);\n}\n","export interface RetryOptions {\n maxRetries?: number;\n baseDelayMs?: number;\n maxDelayMs?: number;\n /** If true, will log retry attempts */\n verbose?: boolean;\n}\n\nexport async function fetchWithRetry(\n url: string,\n options: RequestInit,\n retryOptions: RetryOptions = {}\n): Promise<Response> {\n const { maxRetries = 3, baseDelayMs = 1000, maxDelayMs = 10000 } = retryOptions;\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await fetch(url, options);\n // Don't retry on client errors (4xx), only on server/network errors\n if (response.ok || (response.status >= 400 && response.status < 500)) {\n return response;\n }\n // Server error (5xx) - will retry\n lastError = new Error(`HTTP ${response.status}`);\n } catch (error) {\n // Network error - will retry\n lastError = error instanceof Error ? error : new Error(String(error));\n }\n\n if (attempt < maxRetries) {\n // Exponential backoff with jitter\n const delay = Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs);\n const jitter = delay * 0.1 * Math.random();\n await new Promise((resolve) => setTimeout(resolve, delay + jitter));\n }\n }\n\n throw lastError ?? new Error('Request failed after retries');\n}\n","/**\n * LogTransportService - Handles sending log events to the platform API\n *\n * This service manages:\n * - Creating and updating runs\n * - Sending batches of log events\n * - Retry logic with exponential backoff\n */\n\n/**\n * Log event types supported by the platform\n */\nexport type LogEventType =\n | 'stdout'\n | 'stderr'\n | 'claude_message'\n | 'tool_use'\n | 'tool_result'\n | 'system';\n\n/**\n * A log event to be sent to the platform\n */\nexport interface LogEvent {\n eventType: LogEventType;\n content: string;\n data?: Record<string, unknown>;\n timestamp: string;\n}\n\n/**\n * Response from creating a run\n */\nexport interface CreateRunResponse {\n runId: string;\n}\n\n/**\n * Response from batch send\n */\nexport interface BatchSendResponse {\n success: boolean;\n eventsReceived?: number;\n}\n\n/**\n * Configuration for retry behavior\n */\nexport interface RetryConfig {\n maxRetries: number;\n initialDelayMs: number;\n backoffFactor: number;\n}\n\nconst DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 3,\n initialDelayMs: 100,\n backoffFactor: 2,\n};\n\n/**\n * Service for sending log events to the platform API\n */\nexport class LogTransportService {\n private runId: string | null = null;\n private retryConfig: RetryConfig;\n\n constructor(\n private baseUrl: string,\n private authToken: string,\n runId?: string,\n retryConfig?: Partial<RetryConfig>\n ) {\n this.runId = runId ?? null;\n this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...retryConfig };\n }\n\n /**\n * Get the current run ID\n */\n getRunId(): string | null {\n return this.runId;\n }\n\n /**\n * Create a new run for an action\n * @param actionId - The action ID this run is executing\n * @param purpose - The purpose of this run: 'execute' | 'prepare' | 'review'\n * @param metadata - Optional metadata for the run (e.g., startingCommit)\n * @returns The created run ID\n */\n async createRun(\n actionId: string,\n purpose: 'execute' | 'prepare' | 'review',\n metadata?: { startingCommit?: string }\n ): Promise<string> {\n const response = await this.makeRequest('/api/runs', {\n method: 'POST',\n body: JSON.stringify({\n actionId,\n state: 'queued',\n purpose,\n ...(metadata?.startingCommit && { startingCommit: metadata.startingCommit }),\n }),\n });\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'Failed to create run');\n }\n\n this.runId = result.data.runId;\n return this.runId;\n }\n\n /**\n * Start the run (transition to running state)\n * Called when execution begins\n */\n async startRun(): Promise<void> {\n if (!this.runId) {\n throw new Error('No run ID set. Call createRun() first.');\n }\n\n const response = await this.makeRequest(`/api/runs/${this.runId}/start`, {\n method: 'POST',\n body: JSON.stringify({}),\n });\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'Failed to start run');\n }\n }\n\n /**\n * Finish the run with an outcome\n * @param outcome - 'success' | 'error' | 'timeout' | 'incomplete'\n * @param metadata - Optional metadata (exitCode, errorMessage, cost, usage)\n */\n async finishRun(\n outcome: 'success' | 'error' | 'timeout' | 'incomplete',\n metadata?: {\n exitCode?: number;\n errorMessage?: string;\n cost?: number;\n usage?: Record<string, unknown>;\n }\n ): Promise<void> {\n if (!this.runId) {\n throw new Error('No run ID set. Call createRun() first.');\n }\n\n const response = await this.makeRequest(`/api/runs/${this.runId}/finish`, {\n method: 'POST',\n body: JSON.stringify({\n outcome,\n exitCode: metadata?.exitCode?.toString(),\n errorMessage: metadata?.errorMessage,\n }),\n });\n\n const result = await response.json();\n\n if (!result.success) {\n // If the run is already in a finishing state (summarizing, finished),\n // this is not an error - the server is already handling completion\n const error = result.error || 'Failed to finish run';\n if (error.includes('summarizing') || error.includes('finished')) {\n console.log('[LogTransport] Run is already being finished by server, skipping client finish');\n return;\n }\n throw new Error(error);\n }\n }\n\n /**\n * Update the state of the current run\n * @deprecated Use startRun() and finishRun() instead\n * @param state - New state for the run\n * @param metadata - Optional metadata to include with the state update\n */\n async updateRunState(\n state: string,\n metadata?: Record<string, unknown>\n ): Promise<void> {\n if (!this.runId) {\n throw new Error('No run ID set. Call createRun() first.');\n }\n\n // Map state to appropriate endpoint\n if (state === 'executing' || state === 'preparing' || state === 'running') {\n await this.startRun();\n } else if (state === 'completed' || state === 'failed') {\n const outcome = state === 'completed' ? 'success' : 'error';\n await this.finishRun(outcome, {\n exitCode: metadata?.exitCode as number | undefined,\n errorMessage: metadata?.error as string | undefined,\n cost: metadata?.cost as number | undefined,\n usage: metadata?.usage as Record<string, unknown> | undefined,\n });\n } else {\n // For unknown states, just log a warning\n console.warn(`[LogTransport] Unknown state '${state}' - no API call made`);\n }\n }\n\n /**\n * Send a batch of log events to the platform\n * @param events - Array of log events to send\n * @param workerId - Optional worker ID\n * @returns Success status and number of events received\n */\n async sendBatch(\n events: LogEvent[],\n workerId?: string\n ): Promise<BatchSendResponse> {\n if (!this.runId) {\n throw new Error('No run ID set. Call createRun() first.');\n }\n\n if (events.length === 0) {\n return { success: true, eventsReceived: 0 };\n }\n\n const response = await this.makeRequest('/api/agents/log/event', {\n method: 'POST',\n body: JSON.stringify({\n runId: this.runId,\n events,\n ...(workerId && { workerId }),\n }),\n });\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'Failed to send log batch');\n }\n\n return {\n success: true,\n eventsReceived: result.data?.eventsReceived ?? events.length,\n };\n }\n\n /**\n * Make an HTTP request with retry logic\n */\n private async makeRequest(\n path: string,\n options: RequestInit\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n const headers = {\n 'x-authorization': `Bearer ${this.authToken}`,\n 'Content-Type': 'application/json',\n };\n\n let lastError: Error | null = null;\n let delay = this.retryConfig.initialDelayMs;\n\n for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n ...options,\n headers: {\n ...headers,\n ...(options.headers || {}),\n },\n });\n\n // Don't retry on client errors (4xx) - these won't succeed on retry\n if (response.status >= 400 && response.status < 500) {\n return response;\n }\n\n // Retry on server errors (5xx) or network issues\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Don't wait after the last attempt\n if (attempt < this.retryConfig.maxRetries) {\n await this.sleep(delay);\n delay *= this.retryConfig.backoffFactor;\n }\n }\n }\n\n throw new Error(\n `Request failed after ${this.retryConfig.maxRetries + 1} attempts: ${lastError?.message}`\n );\n }\n\n /**\n * Sleep for a given number of milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","/**\n * LogBuffer - Manages buffered, non-blocking log transmission\n *\n * Collects log events and flushes them periodically to avoid\n * blocking the main Claude execution flow.\n */\n\nimport { LogTransportService, type LogEvent } from './log-transport.js';\n\n// Buffer configuration for log streaming\nconst LOG_BUFFER_FLUSH_INTERVAL_MS = 500;\nconst LOG_BUFFER_MAX_SIZE = 50;\nconst LOG_BUFFER_MAX_QUEUE_SIZE = 1000;\n\nexport class LogBuffer {\n private buffer: LogEvent[] = [];\n private flushIntervalId: ReturnType<typeof setInterval> | null = null;\n private isFlushing = false;\n\n constructor(\n private transport: LogTransportService,\n private flushIntervalMs: number = LOG_BUFFER_FLUSH_INTERVAL_MS,\n private maxBufferSize: number = LOG_BUFFER_MAX_SIZE,\n private maxQueueSize: number = LOG_BUFFER_MAX_QUEUE_SIZE\n ) {}\n\n /**\n * Add an event to the buffer (fire-and-forget)\n * Handles backpressure by dropping oldest events if queue is full.\n */\n push(event: LogEvent): void {\n // Backpressure: drop oldest events if queue is too large\n if (this.buffer.length >= this.maxQueueSize) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n\n // Trigger immediate flush if buffer is at max size\n if (this.buffer.length >= this.maxBufferSize) {\n this.flushAsync();\n }\n }\n\n /**\n * Start periodic flushing\n */\n start(): void {\n if (this.flushIntervalId !== null) return;\n\n this.flushIntervalId = setInterval(() => {\n this.flushAsync();\n }, this.flushIntervalMs);\n }\n\n /**\n * Stop periodic flushing and flush remaining events\n */\n async stop(): Promise<void> {\n if (this.flushIntervalId !== null) {\n clearInterval(this.flushIntervalId);\n this.flushIntervalId = null;\n }\n\n // Final flush of remaining events\n await this.flush();\n }\n\n /**\n * Async flush (fire-and-forget, non-blocking)\n */\n private flushAsync(): void {\n // Don't start a new flush if one is in progress\n if (this.isFlushing || this.buffer.length === 0) return;\n\n // Fire and forget - don't await\n this.flush().catch((error) => {\n console.error('[LogBuffer] Flush error:', error instanceof Error ? error.message : String(error));\n });\n }\n\n /**\n * Flush current buffer contents to transport\n */\n private async flush(): Promise<void> {\n if (this.isFlushing || this.buffer.length === 0) return;\n\n this.isFlushing = true;\n const eventsToSend = [...this.buffer];\n this.buffer = [];\n\n try {\n await this.transport.sendBatch(eventsToSend);\n } catch (error) {\n // Log errors but don't re-queue (to avoid infinite growth)\n console.error('[LogBuffer] Failed to send batch:', error instanceof Error ? error.message : String(error));\n } finally {\n this.isFlushing = false;\n }\n }\n}\n","/**\n * HeartbeatManager - Sends periodic liveness signals during execution\n *\n * This service manages:\n * - Periodic heartbeat signals to the platform\n * - Phase/progress updates without blocking execution\n * - Graceful error handling (log, don't throw)\n */\n\n/**\n * Execution phases for heartbeat reporting\n */\nexport type HeartbeatPhase = 'executing' | 'reading' | 'writing' | 'thinking';\n\n/**\n * Heartbeat payload sent to the platform\n */\nexport interface HeartbeatPayload {\n phase: HeartbeatPhase;\n progress?: number;\n timestamp: string;\n}\n\n/**\n * HeartbeatManager - Self-managing heartbeat service\n *\n * Sends periodic liveness signals to keep the platform informed\n * of worker status without blocking the main execution flow.\n */\nexport class HeartbeatManager {\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private currentPhase: HeartbeatPhase = 'executing';\n private currentProgress: number | undefined = undefined;\n\n constructor(\n private baseUrl: string,\n private authToken: string,\n private runId: string\n ) {}\n\n /**\n * Start sending periodic heartbeats\n * @param intervalMs - Time between heartbeats in milliseconds (default: 30000)\n */\n start(intervalMs: number = 30000): void {\n // Clear any existing interval\n this.stop();\n\n // Send initial heartbeat immediately\n this.sendHeartbeat();\n\n // Set up periodic heartbeats\n this.intervalId = setInterval(() => {\n this.sendHeartbeat();\n }, intervalMs);\n }\n\n /**\n * Stop sending heartbeats\n */\n stop(): void {\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n }\n\n /**\n * Update the current phase and optional progress\n * @param phase - Current execution phase\n * @param progress - Optional progress percentage (0-100)\n */\n updatePhase(phase: HeartbeatPhase, progress?: number): void {\n this.currentPhase = phase;\n this.currentProgress = progress;\n }\n\n /**\n * Check if heartbeat manager is currently running\n */\n isRunning(): boolean {\n return this.intervalId !== null;\n }\n\n /**\n * Send a heartbeat to the platform (internal method)\n * Errors are logged but not thrown to avoid blocking execution.\n * Includes one retry attempt for transient network failures.\n */\n private async sendHeartbeat(): Promise<void> {\n const payload: HeartbeatPayload = {\n phase: this.currentPhase,\n timestamp: new Date().toISOString(),\n };\n\n if (this.currentProgress !== undefined) {\n payload.progress = this.currentProgress;\n }\n\n const url = `${this.baseUrl}/api/runs/${this.runId}/heartbeat`;\n const requestOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'x-authorization': `Bearer ${this.authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n };\n\n // Try up to 2 times (initial + 1 retry)\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n const response = await fetch(url, requestOptions);\n\n if (response.ok) {\n return; // Success\n }\n\n // Don't retry client errors (4xx)\n if (response.status >= 400 && response.status < 500) {\n console.error(\n `Heartbeat failed: HTTP ${response.status} ${response.statusText}`\n );\n return;\n }\n\n // Server error - will retry\n if (attempt === 0) {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n } catch (error) {\n // Network error - retry once\n if (attempt === 0) {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n } else {\n // Log on final failure\n console.error(\n 'Heartbeat error:',\n error instanceof Error ? error.message : String(error)\n );\n }\n }\n }\n }\n}\n","import { loadCredentials, isExpired, isTokenExpired } from '../credentials.js';\nimport { executeClaude } from '../claude-sdk.js';\nimport { fetchWithRetry } from '../fetch-with-retry.js';\nimport { LogTransportService } from '../log-transport.js';\nimport { LogBuffer } from '../log-buffer.js';\nimport { HeartbeatManager } from '../heartbeat-manager.js';\n\nconst API_BASE_URL = 'https://www.contextgraph.dev';\n\nexport interface WorkflowOptions {\n cwd?: string;\n startingCommit?: string;\n model?: string;\n}\n\nexport async function runPrepare(actionId: string, options?: WorkflowOptions): Promise<void> {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n console.error('❌ Not authenticated. Run authentication first.');\n process.exit(1);\n }\n\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n console.error('❌ Token expired. Re-authenticate to continue.');\n process.exit(1);\n }\n\n // Initialize log streaming infrastructure\n const logTransport = new LogTransportService(API_BASE_URL, credentials.clerkToken);\n let runId: string | undefined;\n let heartbeatManager: HeartbeatManager | undefined;\n let logBuffer: LogBuffer | undefined;\n\n try {\n // Create run for this preparation phase FIRST so we have runId for the prompt\n console.log('[Log Streaming] Creating run for prepare phase...');\n runId = await logTransport.createRun(actionId, 'prepare', {\n startingCommit: options?.startingCommit,\n });\n console.log(`[Log Streaming] Run created: ${runId}`);\n\n // Now fetch preparation instructions with runId included\n console.log(`Fetching preparation instructions for action ${actionId}...\\n`);\n\n const response = await fetchWithRetry(\n `${API_BASE_URL}/api/prompts/prepare`,\n {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${credentials.clerkToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ actionId, runId }),\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to fetch prepare prompt: ${response.statusText}\\n${errorText}`);\n }\n\n const { prompt } = await response.json();\n\n // Update run state to preparing\n await logTransport.updateRunState('preparing');\n\n // Start heartbeat manager\n heartbeatManager = new HeartbeatManager(API_BASE_URL, credentials.clerkToken, runId);\n heartbeatManager.start();\n console.log('[Log Streaming] Heartbeat started');\n\n // Set up log buffer for non-blocking transmission\n logBuffer = new LogBuffer(logTransport);\n logBuffer.start();\n\n console.log('Spawning Claude for preparation...\\n');\n\n const claudeResult = await executeClaude({\n prompt,\n cwd: options?.cwd || process.cwd(),\n authToken: credentials.clerkToken,\n model: options?.model || 'claude-opus-4-5-20251101',\n onLogEvent: (event) => {\n logBuffer!.push(event);\n },\n });\n\n // Update run state based on execution result\n if (claudeResult.exitCode === 0) {\n await logTransport.finishRun('success', {\n exitCode: claudeResult.exitCode,\n cost: claudeResult.cost,\n usage: claudeResult.usage,\n });\n console.log('\\n✅ Preparation complete');\n } else {\n await logTransport.finishRun('error', {\n exitCode: claudeResult.exitCode,\n errorMessage: `Claude preparation failed with exit code ${claudeResult.exitCode}`,\n });\n console.error(`\\n❌ Claude preparation failed with exit code ${claudeResult.exitCode}`);\n process.exit(1);\n }\n\n } catch (error) {\n // Update run state to failed if we have a run\n if (runId) {\n try {\n await logTransport.finishRun('error', {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n } catch (stateError) {\n console.error('[Log Streaming] Failed to update run state:', stateError);\n }\n }\n throw error;\n\n } finally {\n // Cleanup: stop heartbeat and flush remaining logs\n if (heartbeatManager) {\n heartbeatManager.stop();\n console.log('[Log Streaming] Heartbeat stopped');\n }\n\n if (logBuffer) {\n await logBuffer.stop();\n console.log('[Log Streaming] Logs flushed');\n }\n }\n}\n","import { loadCredentials, isExpired, isTokenExpired } from '../credentials.js';\nimport { executeClaude } from '../claude-sdk.js';\nimport { fetchWithRetry } from '../fetch-with-retry.js';\nimport { LogTransportService } from '../log-transport.js';\nimport { LogBuffer } from '../log-buffer.js';\nimport { HeartbeatManager } from '../heartbeat-manager.js';\n\nconst API_BASE_URL = 'https://www.contextgraph.dev';\n\nexport interface WorkflowOptions {\n cwd?: string;\n startingCommit?: string;\n model?: string;\n}\n\nexport async function runExecute(actionId: string, options?: WorkflowOptions): Promise<void> {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n console.error('❌ Not authenticated. Run authentication first.');\n process.exit(1);\n }\n\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n console.error('❌ Token expired. Re-authenticate to continue.');\n process.exit(1);\n }\n\n // Initialize log streaming infrastructure\n const logTransport = new LogTransportService(API_BASE_URL, credentials.clerkToken);\n let runId: string | undefined;\n let heartbeatManager: HeartbeatManager | undefined;\n let logBuffer: LogBuffer | undefined;\n\n try {\n // Create run for this execution FIRST so we have runId for the prompt\n console.log('[Log Streaming] Creating run...');\n runId = await logTransport.createRun(actionId, 'execute', {\n startingCommit: options?.startingCommit,\n });\n console.log(`[Log Streaming] Run created: ${runId}`);\n\n // Now fetch execution instructions with runId included\n console.log(`Fetching execution instructions for action ${actionId}...\\n`);\n\n const response = await fetchWithRetry(\n `${API_BASE_URL}/api/prompts/execute`,\n {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${credentials.clerkToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ actionId, runId }),\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to fetch execute prompt: ${response.statusText}\\n${errorText}`);\n }\n\n const { prompt } = await response.json();\n\n // Update run state to executing\n await logTransport.updateRunState('executing');\n\n // Start heartbeat manager\n heartbeatManager = new HeartbeatManager(API_BASE_URL, credentials.clerkToken, runId);\n heartbeatManager.start();\n console.log('[Log Streaming] Heartbeat started');\n\n // Set up log buffer for non-blocking transmission\n logBuffer = new LogBuffer(logTransport);\n logBuffer.start();\n\n console.log('Spawning Claude for execution...\\n');\n\n const claudeResult = await executeClaude({\n prompt,\n cwd: options?.cwd || process.cwd(),\n authToken: credentials.clerkToken,\n ...(options?.model ? { model: options.model } : {}),\n onLogEvent: (event) => {\n logBuffer!.push(event);\n },\n });\n\n // Update run state based on execution result\n if (claudeResult.exitCode === 0) {\n await logTransport.finishRun('success', {\n exitCode: claudeResult.exitCode,\n cost: claudeResult.cost,\n usage: claudeResult.usage,\n });\n console.log('\\n✅ Execution complete');\n } else {\n await logTransport.finishRun('error', {\n exitCode: claudeResult.exitCode,\n errorMessage: `Claude execution failed with exit code ${claudeResult.exitCode}`,\n });\n throw new Error(`Claude execution failed with exit code ${claudeResult.exitCode}`);\n }\n\n } catch (error) {\n // Update run state to failed if we have a run\n if (runId) {\n try {\n await logTransport.finishRun('error', {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n } catch (stateError) {\n console.error('[Log Streaming] Failed to update run state:', stateError);\n }\n }\n throw error;\n\n } finally {\n // Cleanup: stop heartbeat and flush remaining logs\n if (heartbeatManager) {\n heartbeatManager.stop();\n console.log('[Log Streaming] Heartbeat stopped');\n }\n\n if (logBuffer) {\n await logBuffer.stop();\n console.log('[Log Streaming] Logs flushed');\n }\n }\n}\n","import { randomUUID } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { mkdtemp, rm } from 'fs/promises';\nimport { tmpdir } from 'os';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { ApiClient } from '../api-client.js';\nimport type { ActionNode, ActionMetadata } from '../types/actions.js';\nimport { findNextLeaf, type FindNextLeafResult } from '../next-action.js';\nimport { runPrepare } from './prepare.js';\nimport { runExecute } from './execute.js';\nimport { prepareWorkspace } from '../workspace-prep.js';\nimport { loadCredentials, isExpired, isTokenExpired } from '../credentials.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n// When built, this file is in dist/, so package.json is one level up\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8')\n);\n\n// Polling configuration from environment variables\nconst INITIAL_POLL_INTERVAL = parseInt(process.env.WORKER_INITIAL_POLL_INTERVAL || '2000', 10); // 2 seconds default\nconst MAX_POLL_INTERVAL = parseInt(process.env.WORKER_MAX_POLL_INTERVAL || '5000', 10); // 5 seconds default\nconst BACKOFF_MULTIPLIER = 1.5;\nconst STATUS_INTERVAL_MS = 30000; // Show status every 30 seconds when idle\n\n// Retry configuration for transient API errors\n// For extended outages, we wait indefinitely with a ceiling on delay\nconst MAX_API_RETRIES = Infinity; // Never give up on transient errors\nconst INITIAL_RETRY_DELAY = 1000; // 1 second\nconst MAX_RETRY_DELAY = 60000; // 1 minute ceiling\nconst OUTAGE_WARNING_THRESHOLD = 5; // Warn user after this many retries\n\n// Module-scope state for graceful shutdown\nlet running = true;\nlet currentClaim: { actionId: string; claimId: string; workerId: string } | null = null;\nlet apiClient: ApiClient | null = null;\n\n// Stats tracking\nconst stats = {\n startTime: Date.now(),\n prepared: 0,\n executed: 0,\n errors: 0,\n};\n\nfunction formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) {\n return `${hours}h ${minutes % 60}m`;\n } else if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n }\n return `${seconds}s`;\n}\n\nfunction printStatus(): void {\n const uptime = formatDuration(Date.now() - stats.startTime);\n const total = stats.prepared + stats.executed;\n console.log(`Status: ${total} actions (${stats.prepared} prepared, ${stats.executed} executed, ${stats.errors} errors) | Uptime: ${uptime}`);\n}\n\n/**\n * Get the next action to work on, handling tree depth truncation.\n * If the tree is truncated (children exist beyond depth limit), this function\n * will recursively re-fetch the tree starting from the truncated node.\n */\nasync function getNextAction(\n apiClient: ApiClient,\n rootId: string,\n depth: number = 0\n): Promise<ActionNode | null> {\n // Prevent infinite recursion in case of malformed data\n const maxDepth = 20;\n if (depth >= maxDepth) {\n console.error(`❌ Tree traversal exceeded maximum depth (${maxDepth}). Possible cycle or malformed data.`);\n return null;\n }\n\n const tree = await apiClient.fetchTree(rootId, false);\n\n if (tree.done) {\n if (depth === 0) {\n console.log('✅ Root action is already complete');\n }\n return null;\n }\n\n // Use local findNextLeaf to traverse tree and find next action\n const result = findNextLeaf(tree);\n\n // If we found an action, return it\n if (result.action) {\n return result.action;\n }\n\n // If tree was truncated, re-fetch starting from the truncated node\n if (result.truncatedAt) {\n console.log(`📊 Tree depth limit reached at action ${result.truncatedAt}. Fetching deeper...`);\n return getNextAction(apiClient, result.truncatedAt, depth + 1);\n }\n\n // No action found and no truncation - tree is complete or blocked\n return null;\n}\n\n/**\n * Clean up any claimed work and exit gracefully\n */\nasync function cleanupAndExit(): Promise<void> {\n if (currentClaim && apiClient) {\n try {\n console.log(`\\n🧹 Releasing claim on action ${currentClaim.actionId}...`);\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n console.log('✅ Claim released successfully');\n } catch (error) {\n console.error('⚠️ Failed to release claim:', (error as Error).message);\n }\n }\n console.log('👋 Shutdown complete');\n process.exit(0);\n}\n\n/**\n * Set up signal handlers for graceful shutdown\n */\nfunction setupSignalHandlers(): void {\n process.on('SIGINT', async () => {\n console.log('\\n\\n⚠️ Received SIGINT (Ctrl+C). Shutting down gracefully...');\n running = false;\n await cleanupAndExit();\n });\n\n process.on('SIGTERM', async () => {\n console.log('\\n\\n⚠️ Received SIGTERM. Shutting down gracefully...');\n running = false;\n await cleanupAndExit();\n });\n}\n\n/**\n * Sleep for the specified number of milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * Check if an error is likely transient and worth retrying\n */\nfunction isRetryableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n // Retry on server errors (5xx), network errors, and timeouts\n return (\n message.includes('api error 5') ||\n message.includes('500') ||\n message.includes('502') ||\n message.includes('503') ||\n message.includes('504') ||\n message.includes('network') ||\n message.includes('timeout') ||\n message.includes('econnreset') ||\n message.includes('econnrefused') ||\n message.includes('socket hang up') ||\n message.includes('failed query') // Database query failures\n );\n}\n\nexport async function runLocalAgent(options?: { forceModel?: string }): Promise<void> {\n // Initialize module-scope apiClient for signal handlers\n apiClient = new ApiClient();\n\n // Set up graceful shutdown handlers\n setupSignalHandlers();\n\n // Load and validate credentials upfront\n const credentials = await loadCredentials();\n if (!credentials) {\n console.error('❌ Not authenticated.');\n console.error(' Set CONTEXTGRAPH_API_TOKEN environment variable or run `contextgraph-agent auth`');\n process.exit(1);\n }\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n console.error('❌ Token expired. Run `contextgraph-agent auth` to re-authenticate.');\n process.exit(1);\n }\n\n // Show authentication method\n const usingApiToken = !!process.env.CONTEXTGRAPH_API_TOKEN;\n if (usingApiToken) {\n console.log('🔐 Authenticated via CONTEXTGRAPH_API_TOKEN');\n }\n\n // Generate unique worker ID for this session\n const workerId = randomUUID();\n\n console.log(`🤖 ContextGraph Agent v${packageJson.version}`);\n console.log(`👷 Worker ID: ${workerId}`);\n console.log(`🔄 Starting continuous worker loop...\\n`);\n console.log(`💡 Press Ctrl+C to gracefully shutdown and release any claimed work\\n`);\n\n let currentPollInterval = INITIAL_POLL_INTERVAL;\n let lastStatusTime = Date.now();\n let consecutiveApiErrors = 0;\n let apiRetryDelay = INITIAL_RETRY_DELAY;\n\n while (running) {\n\n // Claim next action from worker queue with retry logic\n let actionDetail;\n try {\n actionDetail = await apiClient.claimNextAction(workerId);\n // Reset error tracking on success\n consecutiveApiErrors = 0;\n apiRetryDelay = INITIAL_RETRY_DELAY;\n } catch (error) {\n const err = error as Error;\n\n if (isRetryableError(err)) {\n consecutiveApiErrors++;\n\n // Show extended outage warning once\n if (consecutiveApiErrors === OUTAGE_WARNING_THRESHOLD) {\n console.warn(`\\n⚠️ API appears to be experiencing an outage.`);\n console.warn(` Will continue retrying indefinitely (every ${MAX_RETRY_DELAY / 1000}s max).`);\n console.warn(` Press Ctrl+C to stop.\\n`);\n }\n\n if (consecutiveApiErrors < OUTAGE_WARNING_THRESHOLD) {\n console.warn(`⚠️ API error (attempt ${consecutiveApiErrors}): ${err.message}`);\n } else if (consecutiveApiErrors % 10 === 0) {\n // Only log every 10th retry during extended outage to reduce noise\n console.warn(`⚠️ Still retrying... (attempt ${consecutiveApiErrors}, last error: ${err.message})`);\n }\n\n const delaySeconds = Math.round(apiRetryDelay / 1000);\n if (consecutiveApiErrors < OUTAGE_WARNING_THRESHOLD) {\n console.warn(` Retrying in ${delaySeconds}s...`);\n }\n\n await sleep(apiRetryDelay);\n apiRetryDelay = Math.min(apiRetryDelay * 2, MAX_RETRY_DELAY);\n continue;\n }\n\n // Non-retryable error - re-throw\n throw err;\n }\n\n if (!actionDetail) {\n // Show periodic status while waiting\n if (Date.now() - lastStatusTime >= STATUS_INTERVAL_MS) {\n printStatus();\n lastStatusTime = Date.now();\n }\n await sleep(currentPollInterval);\n currentPollInterval = Math.min(currentPollInterval * BACKOFF_MULTIPLIER, MAX_POLL_INTERVAL);\n continue;\n }\n\n // Reset poll interval on successful claim\n currentPollInterval = INITIAL_POLL_INTERVAL;\n\n // Track current claim for graceful shutdown\n if (actionDetail.claim_id) {\n currentClaim = {\n actionId: actionDetail.id,\n claimId: actionDetail.claim_id,\n workerId,\n };\n }\n\n // Determine which phase this action needs\n let phase: 'prepare' | 'execute';\n if (!actionDetail.prepared) {\n phase = 'prepare';\n } else if (!actionDetail.done) {\n phase = 'execute';\n } else {\n // Action is already done - nothing to do\n console.log(`⏭️ Skipping action \"${actionDetail.title}\" - already completed`);\n if (currentClaim && apiClient) {\n try {\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n } catch (releaseError) {\n console.error('⚠️ Failed to release claim:', (releaseError as Error).message);\n }\n }\n currentClaim = null;\n continue;\n }\n\n // Only print \"Working\" once we've determined there's actual work to do\n console.log(`Working: ${actionDetail.title}`);\n\n // Prepare workspace based on phase and repo availability\n const repoUrl = actionDetail.resolved_repository_url || actionDetail.repository_url;\n const branch = actionDetail.resolved_branch || actionDetail.branch;\n\n let workspacePath: string;\n let cleanup: (() => Promise<void>) | undefined;\n let startingCommit: string | undefined;\n\n // Determine if we need to clone the repository\n // - Prepare/Execute: need repo if available, blank workspace otherwise\n const needsRepo = repoUrl;\n\n try {\n if (needsRepo) {\n // Clone repository into workspace\n const workspace = await prepareWorkspace(repoUrl, {\n branch: branch || undefined,\n authToken: credentials.clerkToken,\n });\n workspacePath = workspace.path;\n cleanup = workspace.cleanup;\n startingCommit = workspace.startingCommit;\n } else {\n // Create a blank temp directory (no repo configured)\n console.log(`📂 No repository configured - creating blank workspace`);\n workspacePath = await mkdtemp(join(tmpdir(), 'cg-workspace-'));\n console.log(` → ${workspacePath}`);\n cleanup = async () => {\n try {\n await rm(workspacePath, { recursive: true, force: true });\n } catch (error) {\n console.error(`Warning: Failed to cleanup workspace at ${workspacePath}:`, error);\n }\n };\n }\n\n if (phase === 'prepare') {\n await runPrepare(actionDetail.id, { cwd: workspacePath, startingCommit, model: options?.forceModel });\n stats.prepared++;\n\n // Release claim after preparation\n if (currentClaim && apiClient) {\n try {\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n } catch (releaseError) {\n console.error('⚠️ Failed to release claim after preparation:', (releaseError as Error).message);\n }\n }\n currentClaim = null;\n continue;\n }\n\n try {\n await runExecute(actionDetail.id, { cwd: workspacePath, startingCommit, model: options?.forceModel });\n stats.executed++;\n console.log(`Completed: ${actionDetail.title}`);\n } catch (executeError) {\n stats.errors++;\n console.error(`Error: ${(executeError as Error).message}. Continuing...`);\n } finally {\n // Release claim after execution completes (success or failure)\n if (currentClaim && apiClient) {\n try {\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n } catch (releaseError) {\n console.error('⚠️ Failed to release claim:', (releaseError as Error).message);\n }\n }\n currentClaim = null;\n }\n } catch (workspaceError) {\n // Handle workspace preparation or other errors\n stats.errors++;\n console.error(`Error preparing workspace: ${(workspaceError as Error).message}. Continuing...`);\n\n // Release claim on workspace/preparation failure\n if (currentClaim && apiClient) {\n try {\n console.log(`🧹 Releasing claim due to workspace error...`);\n await apiClient.releaseClaim({\n action_id: currentClaim.actionId,\n worker_id: currentClaim.workerId,\n claim_id: currentClaim.claimId,\n });\n console.log('✅ Claim released');\n } catch (releaseError) {\n console.error('⚠️ Failed to release claim:', (releaseError as Error).message);\n }\n }\n currentClaim = null;\n } finally {\n if (cleanup) {\n await cleanup();\n }\n }\n }\n\n}\n\n","{\n \"name\": \"@contextgraph/agent\",\n \"version\": \"0.4.16\",\n \"description\": \"Autonomous agent for contextgraph action execution\",\n \"type\": \"module\",\n \"bin\": {\n \"contextgraph-agent\": \"dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"jest\"\n },\n \"keywords\": [\n \"contextgraph\",\n \"agent\",\n \"autonomous\",\n \"cli\"\n ],\n \"author\": \"contextgraph\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/contextgraph/agent.git\"\n },\n \"homepage\": \"https://github.com/contextgraph/agent#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/contextgraph/agent/issues\"\n },\n \"dependencies\": {\n \"@anthropic-ai/claude-agent-sdk\": \"^0.1.50\",\n \"commander\": \"^11.0.0\",\n \"open\": \"^10.0.0\"\n },\n \"devDependencies\": {\n \"@jest/globals\": \"^30.2.0\",\n \"@types/jest\": \"^30.0.0\",\n \"@types/node\": \"^20.0.0\",\n \"jest\": \"^30.2.0\",\n \"ts-jest\": \"^29.4.5\",\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n }\n}\n","import { loadCredentials, isExpired, isTokenExpired } from './credentials.js';\nimport { fetchWithRetry } from './fetch-with-retry.js';\nimport type { ActionDetailResource, ActionNode } from './types/actions.js';\nimport packageJson from '../package.json' assert { type: 'json' };\n\nexport class ApiClient {\n constructor(\n private baseUrl: string = 'https://www.contextgraph.dev'\n ) {}\n\n private async getAuthToken(): Promise<string> {\n const credentials = await loadCredentials();\n\n if (!credentials) {\n throw new Error('Not authenticated. Run authentication first.');\n }\n\n // Check both the stored metadata and the actual JWT expiration\n if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {\n throw new Error('Token expired. Re-authenticate to continue.');\n }\n\n return credentials.clerkToken;\n }\n\n async getActionDetail(actionId: string): Promise<ActionDetailResource> {\n const token = await this.getAuthToken();\n\n // Use both x-authorization header and query param for Vercel compatibility\n const response = await fetchWithRetry(\n `${this.baseUrl}/api/actions/${actionId}?token=${encodeURIComponent(token)}`,\n {\n headers: {\n 'x-authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n }\n );\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error);\n }\n\n return result.data;\n }\n\n async fetchTree(rootActionId: string, includeCompleted: boolean = false): Promise<ActionNode> {\n const token = await this.getAuthToken();\n\n // Use both x-authorization header and query param for Vercel compatibility\n const response = await fetchWithRetry(\n `${this.baseUrl}/api/tree/${rootActionId}?includeCompleted=${includeCompleted}&token=${encodeURIComponent(token)}`,\n {\n headers: {\n 'x-authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to fetch tree: ${response.status} ${errorText}`);\n }\n\n const result = await response.json();\n if (!result.success) {\n throw new Error('Failed to fetch tree: API returned unsuccessful response');\n }\n\n // If no root actions, the tree is complete (all actions done)\n if (!result.data.rootActions?.[0]) {\n return { id: rootActionId, title: '', done: true, dependencies: [], children: [] };\n }\n\n return result.data.rootActions[0];\n }\n\n async claimNextAction(workerId: string): Promise<ActionDetailResource | null> {\n const token = await this.getAuthToken();\n\n const response = await fetchWithRetry(\n `${this.baseUrl}/api/worker/next?token=${encodeURIComponent(token)}`,\n {\n method: 'POST',\n headers: {\n 'x-authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n worker_id: workerId,\n agent_version: packageJson.version\n }),\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error ${response.status}: ${errorText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'API returned unsuccessful response');\n }\n\n // API returns null when no work is available\n return result.data;\n }\n\n async releaseClaim(params: { action_id: string; worker_id: string; claim_id: string }): Promise<void> {\n const token = await this.getAuthToken();\n\n const response = await fetchWithRetry(\n `${this.baseUrl}/api/worker/release?token=${encodeURIComponent(token)}`,\n {\n method: 'POST',\n headers: {\n 'x-authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(params),\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error ${response.status}: ${errorText}`);\n }\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || 'API returned unsuccessful response');\n }\n }\n}\n","import { spawn } from 'child_process';\nimport { mkdtemp, rm } from 'fs/promises';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport { fetchWithRetry } from './fetch-with-retry.js';\nimport type { GitHubCredentials } from './types/actions.js';\n\nconst API_BASE_URL = 'https://www.contextgraph.dev';\n\nexport interface WorkspaceResult {\n path: string;\n startingCommit: string;\n cleanup: () => Promise<void>;\n}\n\nexport interface PrepareWorkspaceOptions {\n branch?: string;\n authToken: string;\n}\n\nasync function fetchGitHubCredentials(authToken: string): Promise<GitHubCredentials> {\n const response = await fetchWithRetry(`${API_BASE_URL}/api/cli/credentials`, {\n headers: {\n 'x-authorization': `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (response.status === 401) {\n throw new Error('Authentication failed. Please re-authenticate.');\n }\n\n if (response.status === 404) {\n throw new Error(\n 'GitHub not connected. Please connect your GitHub account at https://contextgraph.dev/settings.'\n );\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to fetch GitHub credentials: ${response.statusText}\\n${errorText}`);\n }\n\n return response.json() as Promise<GitHubCredentials>;\n}\n\nfunction runGitCommand(args: string[], cwd?: string): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n const proc = spawn('git', args, { cwd });\n let stdout = '';\n let stderr = '';\n\n proc.stdout.on('data', (data) => {\n stdout += data.toString();\n });\n\n proc.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolve({ stdout, stderr });\n } else {\n reject(new Error(`git ${args[0]} failed (exit ${code}): ${stderr || stdout}`));\n }\n });\n\n proc.on('error', (err) => {\n reject(new Error(`Failed to spawn git: ${err.message}`));\n });\n });\n}\n\nfunction buildAuthenticatedUrl(repoUrl: string, token: string): string {\n // Handle https://github.com/... URLs\n if (repoUrl.startsWith('https://github.com/')) {\n return repoUrl.replace('https://github.com/', `https://${token}@github.com/`);\n }\n\n // Handle https://github.com URLs without trailing slash\n if (repoUrl.startsWith('https://github.com')) {\n return repoUrl.replace('https://github.com', `https://${token}@github.com`);\n }\n\n // For other URLs, return as-is (might be SSH or other provider)\n return repoUrl;\n}\n\nexport async function prepareWorkspace(\n repoUrl: string,\n options: PrepareWorkspaceOptions\n): Promise<WorkspaceResult> {\n const { branch, authToken } = options;\n\n // Fetch GitHub credentials\n const credentials = await fetchGitHubCredentials(authToken);\n\n // Create temp directory\n const workspacePath = await mkdtemp(join(tmpdir(), 'cg-workspace-'));\n\n const cleanup = async () => {\n try {\n await rm(workspacePath, { recursive: true, force: true });\n } catch (error) {\n console.error(`Warning: Failed to cleanup workspace at ${workspacePath}:`, error);\n }\n };\n\n try {\n // Build authenticated clone URL\n const cloneUrl = buildAuthenticatedUrl(repoUrl, credentials.githubToken);\n\n // Clone the repository\n console.log(`📂 Cloning ${repoUrl}`);\n console.log(` → ${workspacePath}`);\n await runGitCommand(['clone', cloneUrl, workspacePath]);\n console.log(`✅ Repository cloned`);\n\n // Configure git identity if we have the info\n if (credentials.githubUsername) {\n await runGitCommand(['config', 'user.name', credentials.githubUsername], workspacePath);\n }\n if (credentials.githubEmail) {\n await runGitCommand(['config', 'user.email', credentials.githubEmail], workspacePath);\n }\n\n // Handle branch checkout if specified\n if (branch) {\n // Check if branch exists remotely\n const { stdout } = await runGitCommand(\n ['ls-remote', '--heads', 'origin', branch],\n workspacePath\n );\n\n const branchExists = stdout.trim().length > 0;\n\n if (branchExists) {\n // Checkout existing branch\n console.log(`🌿 Checking out branch: ${branch}`);\n await runGitCommand(['checkout', branch], workspacePath);\n } else {\n // Create new branch\n console.log(`🌱 Creating new branch: ${branch}`);\n await runGitCommand(['checkout', '-b', branch], workspacePath);\n }\n }\n\n // Capture starting commit for historical accuracy\n const { stdout: commitHash } = await runGitCommand(['rev-parse', 'HEAD'], workspacePath);\n const startingCommit = commitHash.trim();\n\n return { path: workspacePath, startingCommit, cleanup };\n } catch (error) {\n // Cleanup on failure\n await cleanup();\n throw error;\n }\n}\n"],"mappings":"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","names":["readFileSync","fileURLToPath","dirname","join","path","API_BASE_URL","mkdtemp","rm","tmpdir","join","spawn","join","API_BASE_URL","spawn","join","__filename","__dirname","join","mkdtemp","join","tmpdir","rm","__filename","fileURLToPath","__dirname","dirname","packageJson","readFileSync","join"]}
|