orkestrate 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +47 -56
- package/dist/cli.js.map +1 -1
- package/dist/mcp-entry.js +19 -17
- package/dist/mcp-entry.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -639,19 +639,19 @@ function detectTools(projectDir = process.cwd()) {
|
|
|
639
639
|
return tools;
|
|
640
640
|
}
|
|
641
641
|
async function configureTool(tool, projectDir = process.cwd()) {
|
|
642
|
-
const
|
|
643
|
-
const mcpUrl = `${
|
|
642
|
+
const bridge = resolveMcpBridge(projectDir);
|
|
643
|
+
const mcpUrl = `${getServerUrl()}/api/mcp`;
|
|
644
644
|
switch (tool) {
|
|
645
645
|
case "claude":
|
|
646
|
-
return configureClaudeCode(
|
|
646
|
+
return configureClaudeCode(bridge);
|
|
647
647
|
case "opencode":
|
|
648
|
-
return configureOpenCode(join(projectDir, "opencode.json"),
|
|
648
|
+
return configureOpenCode(join(projectDir, "opencode.json"), bridge);
|
|
649
649
|
case "cursor":
|
|
650
|
-
return configureMcpServersJson("Cursor", join(projectDir, ".cursor", "mcp.json"),
|
|
650
|
+
return configureMcpServersJson("Cursor", join(projectDir, ".cursor", "mcp.json"), bridge);
|
|
651
651
|
case "windsurf":
|
|
652
|
-
return configureMcpServersJson("Windsurf", join(projectDir, ".windsurf", "mcp.json"),
|
|
652
|
+
return configureMcpServersJson("Windsurf", join(projectDir, ".windsurf", "mcp.json"), bridge);
|
|
653
653
|
case "codex":
|
|
654
|
-
return configureCodex(projectDir,
|
|
654
|
+
return configureCodex(projectDir, bridge);
|
|
655
655
|
default:
|
|
656
656
|
return { success: false, message: `Unknown tool: ${tool}` };
|
|
657
657
|
}
|
|
@@ -696,73 +696,62 @@ function getNodePath() {
|
|
|
696
696
|
return "node";
|
|
697
697
|
}
|
|
698
698
|
}
|
|
699
|
-
function configureClaudeCode(
|
|
700
|
-
if (!isCommandAvailable("claude")) {
|
|
701
|
-
return {
|
|
702
|
-
success: false,
|
|
703
|
-
message: "Claude Code CLI not found."
|
|
704
|
-
};
|
|
705
|
-
}
|
|
699
|
+
function configureClaudeCode(bridge) {
|
|
700
|
+
if (!isCommandAvailable("claude")) return { success: false, message: "Claude Code CLI not found." };
|
|
706
701
|
try {
|
|
707
|
-
const bridge = resolveMcpBridge(process.cwd());
|
|
708
702
|
const bridgeCmd = `"${bridge.command}" ${bridge.args.map((a) => `"${a}"`).join(" ")}`;
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
return {
|
|
715
|
-
success: true,
|
|
716
|
-
message: "MCP added to Claude Code via local proxy."
|
|
717
|
-
};
|
|
718
|
-
} catch {
|
|
719
|
-
execSync(
|
|
720
|
-
`claude mcp add --transport http --scope project Orkestrate "${mcpUrl}"`,
|
|
721
|
-
{ stdio: "pipe", encoding: "utf-8" }
|
|
722
|
-
);
|
|
723
|
-
return { success: true, message: "MCP added to Claude Code via HTTP." };
|
|
724
|
-
}
|
|
703
|
+
execSync(
|
|
704
|
+
`claude mcp add --transport stdio --scope project Orkestrate ${bridgeCmd}`,
|
|
705
|
+
{ stdio: "pipe", encoding: "utf-8" }
|
|
706
|
+
);
|
|
707
|
+
return { success: true, message: "MCP added to Claude Code." };
|
|
725
708
|
} catch (err) {
|
|
726
709
|
return { success: false, message: `Claude config failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
727
710
|
}
|
|
728
711
|
}
|
|
729
|
-
function configureOpenCode(configPath,
|
|
712
|
+
function configureOpenCode(configPath, bridge) {
|
|
730
713
|
try {
|
|
731
714
|
let config2 = existsSync(configPath) ? JSON.parse(readFileSync(configPath, "utf-8")) : {};
|
|
732
715
|
if (!config2.mcp || typeof config2.mcp !== "object") config2.mcp = {};
|
|
733
|
-
config2.mcp["Orkestrate"] = {
|
|
716
|
+
config2.mcp["Orkestrate"] = {
|
|
717
|
+
type: "local",
|
|
718
|
+
command: [bridge.command, ...bridge.args],
|
|
719
|
+
enabled: true
|
|
720
|
+
};
|
|
734
721
|
writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
735
722
|
return { success: true, message: `Configured OpenCode at ${configPath}` };
|
|
736
723
|
} catch (err) {
|
|
737
724
|
return { success: false, message: `OpenCode config failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
738
725
|
}
|
|
739
726
|
}
|
|
740
|
-
function configureMcpServersJson(displayName, configPath,
|
|
727
|
+
function configureMcpServersJson(displayName, configPath, bridge) {
|
|
741
728
|
try {
|
|
742
729
|
const dir = join(configPath, "..");
|
|
743
730
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
744
731
|
let config2 = existsSync(configPath) ? JSON.parse(readFileSync(configPath, "utf-8")) : {};
|
|
745
732
|
if (!config2.mcpServers || typeof config2.mcpServers !== "object") config2.mcpServers = {};
|
|
746
|
-
config2.mcpServers["Orkestrate"] = {
|
|
733
|
+
config2.mcpServers["Orkestrate"] = {
|
|
734
|
+
command: bridge.command,
|
|
735
|
+
args: bridge.args
|
|
736
|
+
};
|
|
747
737
|
writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
748
738
|
return { success: true, message: `Configured ${displayName} at ${configPath}` };
|
|
749
739
|
} catch (err) {
|
|
750
740
|
return { success: false, message: `${displayName} config failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
751
741
|
}
|
|
752
742
|
}
|
|
753
|
-
function configureCodex(projectDir,
|
|
743
|
+
function configureCodex(projectDir, bridge) {
|
|
754
744
|
const home = homedir();
|
|
755
745
|
const codexDir = join(home, ".codex");
|
|
756
746
|
const configPath = join(codexDir, "config.toml");
|
|
757
747
|
try {
|
|
758
748
|
if (!existsSync(codexDir)) mkdirSync(codexDir, { recursive: true });
|
|
759
|
-
const bridge = resolveMcpBridge(projectDir);
|
|
760
749
|
let content = existsSync(configPath) ? readFileSync(configPath, "utf-8") : "[mcp_servers]\n";
|
|
761
|
-
const sectionRegex = /\[mcp_servers\.Orkestrate\]\s*\n(?:(?!\[)[^\n]*\n?)*/;
|
|
762
750
|
const proxySection = `[mcp_servers.Orkestrate]
|
|
763
751
|
command = "${bridge.command}"
|
|
764
752
|
args = [${bridge.args.map((a) => `"${a}"`).join(", ")}]
|
|
765
753
|
`;
|
|
754
|
+
const sectionRegex = /\[mcp_servers\.Orkestrate\]\s*\n(?:(?!\[)[^\n]*\n?)*/;
|
|
766
755
|
if (sectionRegex.test(content)) {
|
|
767
756
|
content = content.replace(sectionRegex, proxySection);
|
|
768
757
|
} else {
|
|
@@ -776,7 +765,7 @@ args = [${bridge.args.map((a) => `"${a}"`).join(", ")}]
|
|
|
776
765
|
}
|
|
777
766
|
}
|
|
778
767
|
writeFileSync(configPath, content, "utf-8");
|
|
779
|
-
return { success: true, message: `Configured Codex
|
|
768
|
+
return { success: true, message: `Configured Codex.` };
|
|
780
769
|
} catch (err) {
|
|
781
770
|
return { success: false, message: `Codex config failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
782
771
|
}
|
|
@@ -1259,10 +1248,19 @@ async function mcpCommand() {
|
|
|
1259
1248
|
}
|
|
1260
1249
|
}
|
|
1261
1250
|
async function processLine(line, mcpUrl) {
|
|
1251
|
+
let payload;
|
|
1252
|
+
try {
|
|
1253
|
+
payload = JSON.parse(line);
|
|
1254
|
+
} catch {
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
const isNotification = !Object.prototype.hasOwnProperty.call(payload, "id");
|
|
1258
|
+
const requestId = payload.id;
|
|
1262
1259
|
try {
|
|
1263
|
-
const payload = JSON.parse(line);
|
|
1264
|
-
const isNotification = !Object.prototype.hasOwnProperty.call(payload, "id");
|
|
1265
1260
|
const token = await getValidToken();
|
|
1261
|
+
if (!token) {
|
|
1262
|
+
throw new Error("NOT_LOGGED_IN: Please run 'orkestrate login' to authenticate.");
|
|
1263
|
+
}
|
|
1266
1264
|
const res = await fetch(mcpUrl, {
|
|
1267
1265
|
method: "POST",
|
|
1268
1266
|
headers: {
|
|
@@ -1278,22 +1276,15 @@ async function processLine(line, mcpUrl) {
|
|
|
1278
1276
|
process.stdout.write(responseBody + "\n");
|
|
1279
1277
|
}
|
|
1280
1278
|
} catch (err) {
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
code: -32603,
|
|
1289
|
-
message: `Orkestrate Proxy Error: ${err instanceof Error ? err.message : String(err)}`
|
|
1290
|
-
}
|
|
1291
|
-
}) + "\n");
|
|
1279
|
+
if (isNotification) return;
|
|
1280
|
+
process.stdout.write(JSON.stringify({
|
|
1281
|
+
jsonrpc: "2.0",
|
|
1282
|
+
id: requestId,
|
|
1283
|
+
error: {
|
|
1284
|
+
code: -32603,
|
|
1285
|
+
message: err instanceof Error ? err.message : String(err)
|
|
1292
1286
|
}
|
|
1293
|
-
}
|
|
1294
|
-
process.stderr.write(`[Orkestrate] Internal error: ${err}
|
|
1295
|
-
`);
|
|
1296
|
-
}
|
|
1287
|
+
}) + "\n");
|
|
1297
1288
|
}
|
|
1298
1289
|
}
|
|
1299
1290
|
var init_mcp = __esm({
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/ui.ts","../src/lib/config.ts","../src/lib/auth.ts","../src/lib/api.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/lib/detect.ts","../src/commands/connect.ts","../src/commands/status.ts","../src/commands/workspace.ts","../src/lib/git.ts","../src/commands/init.ts","../src/commands/mcp.ts","../src/commands/whoami.ts","../src/cli.ts"],"sourcesContent":["/**\n * Orkestrate CLI — Terminal UI Helpers\n *\n * Pretty output formatting for the terminal.\n */\n\nimport pc from \"picocolors\";\n\nexport const ui = {\n // Status icons\n success: (msg: string) => console.log(` ${pc.green(\"✓\")} ${msg}`),\n error: (msg: string) => console.log(` ${pc.red(\"✗\")} ${msg}`),\n info: (msg: string) => console.log(` ${pc.blue(\"→\")} ${msg}`),\n warn: (msg: string) => console.log(` ${pc.yellow(\"!\")} ${msg}`),\n dim: (msg: string) => console.log(` ${pc.dim(msg)}`),\n\n // Headers\n header: (msg: string) => {\n console.log();\n console.log(` ${pc.bold(pc.white(msg))}`);\n console.log();\n },\n\n // Blank line\n blank: () => console.log(),\n\n // Indented line\n line: (msg: string) => console.log(` ${msg}`),\n\n // Key-value pair\n kv: (key: string, value: string) => {\n console.log(` ${pc.dim(key + \":\")} ${value}`);\n },\n\n // Table\n table: (headers: string[], rows: string[][]) => {\n const colWidths = headers.map((h, i) => {\n const maxContent = Math.max(h.length, ...rows.map((r) => (r[i] || \"\").length));\n return Math.min(maxContent, 40);\n });\n\n const separator = \"─\";\n const pad = (s: string, w: number) => s.padEnd(w).slice(0, w);\n\n // Top border\n console.log(\n ` ┌${colWidths.map((w) => separator.repeat(w + 2)).join(\"┬\")}┐`,\n );\n\n // Header row\n console.log(\n ` │${headers.map((h, i) => ` ${pc.bold(pad(h, colWidths[i]))} `).join(\"│\")}│`,\n );\n\n // Header separator\n console.log(\n ` ├${colWidths.map((w) => separator.repeat(w + 2)).join(\"┼\")}┤`,\n );\n\n // Data rows\n for (const row of rows) {\n console.log(\n ` │${row.map((c, i) => ` ${pad(c || \"\", colWidths[i])} `).join(\"│\")}│`,\n );\n }\n\n // Bottom border\n console.log(\n ` └${colWidths.map((w) => separator.repeat(w + 2)).join(\"┴\")}┘`,\n );\n },\n\n // Colored status badge\n statusBadge: (status: string): string => {\n switch (status) {\n case \"active\":\n return pc.green(\"● active\");\n case \"idle\":\n return pc.dim(\"○ idle\");\n case \"blocked\":\n return pc.red(\"■ blocked\");\n case \"planning\":\n return pc.blue(\"◆ planning\");\n case \"handoff\":\n return pc.yellow(\"⇄ handoff\");\n case \"done\":\n return pc.dim(\"✓ done\");\n default:\n return pc.dim(status);\n }\n },\n\n // Banner\n banner: () => {\n console.log();\n console.log(pc.bold(pc.cyan(\" ⬡ orkestrate\")));\n console.log(pc.dim(\" the coordination layer for AI coding agents\"));\n console.log();\n },\n};\n","/**\n * Orkestrate CLI — Configuration Management\n *\n * Stores credentials and preferences in the user's home directory.\n * Uses the `conf` package for cross-platform config storage.\n */\n\nimport Conf from \"conf\";\n\nexport interface StoredCredentials {\n clientId: string;\n accessToken: string;\n refreshToken: string;\n expiresAt: number; // epoch seconds\n userId: string;\n scope: string;\n}\n\nexport interface CliConfig {\n credentials: StoredCredentials | null;\n activeWorkspaceId: string | null;\n activeWorkspaceName: string | null;\n serverUrl: string;\n}\n\nconst config = new Conf<CliConfig>({\n projectName: \"orkestrate\",\n projectSuffix: \"\",\n defaults: {\n credentials: null,\n activeWorkspaceId: null,\n activeWorkspaceName: null,\n serverUrl: \"https://orkestrate.space\",\n },\n});\n\nexport function getConfig(): CliConfig {\n return {\n credentials: config.get(\"credentials\"),\n activeWorkspaceId: config.get(\"activeWorkspaceId\"),\n activeWorkspaceName: config.get(\"activeWorkspaceName\"),\n serverUrl: config.get(\"serverUrl\"),\n };\n}\n\nexport function getServerUrl(): string {\n return config.get(\"serverUrl\");\n}\n\nexport function setCredentials(creds: StoredCredentials): void {\n config.set(\"credentials\", creds);\n}\n\nexport function getCredentials(): StoredCredentials | null {\n return config.get(\"credentials\");\n}\n\nexport function clearCredentials(): void {\n config.set(\"credentials\", null);\n}\n\nexport function setActiveWorkspace(id: string, name: string): void {\n config.set(\"activeWorkspaceId\", id);\n config.set(\"activeWorkspaceName\", name);\n}\n\nexport function getActiveWorkspace(): { id: string | null; name: string | null } {\n return {\n id: config.get(\"activeWorkspaceId\"),\n name: config.get(\"activeWorkspaceName\"),\n };\n}\n\nexport function setServerUrl(url: string): void {\n config.set(\"serverUrl\", url);\n}\n\nexport function clearAll(): void {\n config.clear();\n}\n\nexport function getConfigPath(): string {\n return config.path;\n}\n","/**\n * Orkestrate CLI — OAuth Authentication\n *\n * Implements the full OAuth 2.0 + PKCE flow:\n * 1. Dynamic client registration\n * 2. Open browser for consent\n * 3. Local HTTP callback server\n * 4. Token exchange\n * 5. Credential storage\n */\n\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport {\n getServerUrl,\n setCredentials,\n getCredentials,\n type StoredCredentials,\n} from \"./config.js\";\n\nfunction randomToken(bytes = 32): string {\n return randomBytes(bytes).toString(\"base64url\");\n}\n\nfunction pkceS256(verifier: string): string {\n return createHash(\"sha256\").update(verifier).digest(\"base64url\");\n}\n\ninterface TokenResponse {\n token_type: string;\n access_token: string;\n expires_in: number;\n refresh_token: string;\n scope: string;\n}\n\n/**\n * Step 1: Register this CLI instance as an OAuth client.\n */\nasync function registerClient(\n serverUrl: string,\n redirectUri: string,\n): Promise<{ clientId: string }> {\n const res = await fetch(`${serverUrl}/api/oauth/register`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_name: \"Orkestrate CLI\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n }),\n });\n\n if (!res.ok) {\n const body = await res.text();\n throw new Error(`Client registration failed (${res.status}): ${body}`);\n }\n\n const data = (await res.json()) as { client_id: string };\n return { clientId: data.client_id };\n}\n\n/**\n * Step 2 & 3: Open browser and wait for the OAuth callback.\n */\nfunction waitForCallback(\n port: number,\n): Promise<{ code: string; state: string }> {\n return new Promise((resolve, reject) => {\n let timeoutHandle: ReturnType<typeof setTimeout>;\n\n function cleanup() {\n clearTimeout(timeoutHandle);\n server.close();\n }\n\n const server = createServer((req: IncomingMessage, res: ServerResponse) => {\n const url = new URL(req.url || \"/\", `http://localhost:${port}`);\n\n if (url.pathname !== \"/callback\") {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n const error = url.searchParams.get(\"error\");\n const state = url.searchParams.get(\"state\") || \"\";\n\n if (error) {\n const description = url.searchParams.get(\"error_description\") || error;\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(buildErrorPage(description));\n cleanup();\n reject(new Error(`OAuth error: ${description}`));\n return;\n }\n\n if (!code) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(buildErrorPage(\"No authorization code received.\"));\n cleanup();\n reject(new Error(\"No authorization code received\"));\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(buildSuccessPage());\n cleanup();\n resolve({ code, state });\n });\n\n server.listen(port, \"127.0.0.1\", () => {\n // Server ready\n });\n\n server.on(\"error\", (err: Error) => {\n clearTimeout(timeoutHandle);\n reject(new Error(`Could not start local server: ${err.message}`));\n });\n\n // Timeout after 5 minutes — unref so it doesn't block process exit\n timeoutHandle = setTimeout(() => {\n server.close();\n reject(new Error(\"Authentication timed out (5 minutes). Please try again.\"));\n }, 5 * 60 * 1000);\n timeoutHandle.unref();\n });\n}\n\n/**\n * Step 4: Exchange authorization code for tokens.\n */\nasync function exchangeCodeForTokens(\n serverUrl: string,\n code: string,\n clientId: string,\n codeVerifier: string,\n redirectUri: string,\n): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n code_verifier: codeVerifier,\n client_id: clientId,\n redirect_uri: redirectUri,\n });\n\n const res = await fetch(`${serverUrl}/api/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Token exchange failed (${res.status}): ${text}`);\n }\n\n return (await res.json()) as TokenResponse;\n}\n\n/**\n * Refresh an expired access token.\n */\nexport async function refreshAccessToken(): Promise<StoredCredentials | null> {\n const creds = getCredentials();\n if (!creds?.refreshToken) return null;\n\n const serverUrl = getServerUrl();\n const body = new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: creds.refreshToken,\n client_id: creds.clientId,\n });\n\n const res = await fetch(`${serverUrl}/api/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!res.ok) return null;\n\n const tokens = (await res.json()) as TokenResponse;\n const now = Math.floor(Date.now() / 1000);\n\n const newCreds: StoredCredentials = {\n clientId: creds.clientId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: now + tokens.expires_in,\n userId: creds.userId,\n scope: tokens.scope,\n };\n\n setCredentials(newCreds);\n return newCreds;\n}\n\n/**\n * Get a valid access token, refreshing if needed.\n */\nexport async function getValidToken(): Promise<string | null> {\n const creds = getCredentials();\n if (!creds) return null;\n\n const now = Math.floor(Date.now() / 1000);\n\n // Refresh if expired or expiring within 60 seconds\n if (creds.expiresAt <= now + 60) {\n const refreshed = await refreshAccessToken();\n return refreshed?.accessToken || null;\n }\n\n return creds.accessToken;\n}\n\n/**\n * Run the full OAuth login flow.\n */\nexport async function performLogin(): Promise<{\n clientId: string;\n userId: string;\n accessToken: string;\n}> {\n const serverUrl = getServerUrl();\n const port = 19274; // \"ork\" on a phone keypad, roughly\n const redirectUri = `http://127.0.0.1:${port}/callback`;\n\n // Step 1: Register client\n const { clientId } = await registerClient(serverUrl, redirectUri);\n\n // Step 2: Prepare PKCE\n const codeVerifier = randomToken(48);\n const codeChallenge = pkceS256(codeVerifier);\n const state = randomToken(16);\n\n // Step 3: Build authorization URL\n const authUrl = new URL(`${serverUrl}/api/oauth/authorize`);\n authUrl.searchParams.set(\"response_type\", \"code\");\n authUrl.searchParams.set(\"client_id\", clientId);\n authUrl.searchParams.set(\"redirect_uri\", redirectUri);\n authUrl.searchParams.set(\"code_challenge\", codeChallenge);\n authUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authUrl.searchParams.set(\"scope\", \"mcp:read mcp:write\");\n authUrl.searchParams.set(\"state\", state);\n\n // Step 4: Start callback server + open browser\n const callbackPromise = waitForCallback(port);\n\n // Dynamic import to handle ESM-only `open` package\n const { default: openBrowser } = await import(\"open\");\n await openBrowser(authUrl.toString());\n\n // Step 5: Wait for callback\n const { code, state: returnedState } = await callbackPromise;\n\n if (returnedState !== state) {\n throw new Error(\"OAuth state mismatch — possible CSRF attack. Aborting.\");\n }\n\n // Step 6: Exchange code for tokens\n const tokens = await exchangeCodeForTokens(\n serverUrl,\n code,\n clientId,\n codeVerifier,\n redirectUri,\n );\n\n const now = Math.floor(Date.now() / 1000);\n\n // We don't get user_id from the token response directly.\n // We'll extract it from the MCP endpoint or store a placeholder.\n // For now, use clientId as a proxy until first API call resolves it.\n const credentials: StoredCredentials = {\n clientId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: now + tokens.expires_in,\n userId: \"\", // Will be resolved on first API call\n scope: tokens.scope,\n };\n\n setCredentials(credentials);\n\n return {\n clientId,\n userId: credentials.userId,\n accessToken: tokens.access_token,\n };\n}\n\n// --- HTML pages for the local callback server ---\n\nfunction buildSuccessPage(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Orkestrate — Authenticated</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n text-align: center;\n padding: 3rem;\n border: 1px solid #262626;\n border-radius: 12px;\n background: #111;\n max-width: 420px;\n }\n .icon { font-size: 3rem; margin-bottom: 1rem; }\n h1 { font-size: 1.5rem; margin-bottom: 0.5rem; color: #fff; }\n p { color: #a3a3a3; line-height: 1.6; }\n .hint { margin-top: 1.5rem; font-size: 0.85rem; color: #525252; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">✓</div>\n <h1>Authenticated</h1>\n <p>You're now logged in to Orkestrate. You can close this tab and return to your terminal.</p>\n <p class=\"hint\">This window will close automatically.</p>\n </div>\n <script>setTimeout(() => window.close(), 3000);</script>\n</body>\n</html>`;\n}\n\nfunction buildErrorPage(message: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Orkestrate — Error</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n text-align: center;\n padding: 3rem;\n border: 1px solid #371717;\n border-radius: 12px;\n background: #1a0a0a;\n max-width: 420px;\n }\n .icon { font-size: 3rem; margin-bottom: 1rem; }\n h1 { font-size: 1.5rem; margin-bottom: 0.5rem; color: #fca5a5; }\n p { color: #a3a3a3; line-height: 1.6; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">✗</div>\n <h1>Authentication Failed</h1>\n <p>${message}</p>\n </div>\n</body>\n</html>`;\n}\n","/**\n * Orkestrate CLI — API Client\n *\n * Authenticated HTTP client for the Orkestrate web API.\n * All requests use the stored OAuth bearer token.\n */\n\nimport { getServerUrl } from \"./config.js\";\nimport { getValidToken } from \"./auth.js\";\n\nexport class ApiError extends Error {\n constructor(\n public status: number,\n message: string,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\nasync function authHeaders(): Promise<Record<string, string>> {\n const token = await getValidToken();\n if (!token) {\n throw new ApiError(401, \"Not authenticated. Run `orkestrate login` first.\");\n }\n return {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n };\n}\n\nasync function request<T>(\n method: string,\n path: string,\n body?: unknown,\n): Promise<T> {\n const serverUrl = getServerUrl();\n const headers = await authHeaders();\n\n const res = await fetch(`${serverUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, `API error (${res.status}): ${text}`);\n }\n\n return res.json();\n}\n\n// --- Workspace API ---\n\nexport interface Workspace {\n id: string;\n name: string;\n ownerId: string;\n repoUrl: string | null;\n defaultBranch: string | null;\n isActive: boolean;\n createdAt: string;\n}\n\nexport async function listWorkspaces(): Promise<Workspace[]> {\n const data = await request<{ workspaces: Workspace[] }>(\"GET\", \"/api/workspaces\");\n return data.workspaces || [];\n}\n\nexport async function switchWorkspace(workspaceId: string): Promise<void> {\n await request(\"POST\", \"/api/workspaces\", {\n action: \"switch\",\n workspaceId,\n });\n}\n\nexport async function createWorkspace(\n name: string,\n repoUrl: string,\n defaultBranch: string,\n): Promise<Workspace> {\n const data = await request<{ workspace: Workspace }>(\"POST\", \"/api/workspaces\", {\n action: \"create\",\n name,\n repoUrl,\n defaultBranch,\n });\n return data.workspace;\n}\n\n// --- Agent Status API ---\n\nexport interface AgentState {\n scopedAgentId: string;\n agentId: string;\n toolName: string | null;\n status: string;\n objective: string;\n claimedPaths: string[];\n plan: string[];\n notes: string;\n updatedAt: string;\n}\n\nexport async function getTeamStatus(): Promise<{\n agents: AgentState[];\n stateHash: string;\n}> {\n // Use the MCP endpoint with a read_team_state RPC call\n const serverUrl = getServerUrl();\n const token = await getValidToken();\n if (!token) {\n throw new ApiError(401, \"Not authenticated. Run `orkestrate login` first.\");\n }\n\n const res = await fetch(`${serverUrl}/api/mcp`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: {\n name: \"read_team_state\",\n arguments: {},\n },\n }),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, `MCP error (${res.status}): ${text}`);\n }\n\n const rpcResult = await res.json();\n\n // Parse the MCP response to extract team state\n if (rpcResult.error) {\n throw new ApiError(400, rpcResult.error.message || \"MCP call failed\");\n }\n\n const content = rpcResult.result?.content || [];\n const textContent = content\n .filter((c: { type: string }) => c.type === \"text\")\n .map((c: { text: string }) => c.text)\n .join(\"\\n\");\n\n try {\n const parsed = JSON.parse(textContent);\n return {\n agents: parsed.agents || parsed.states || [],\n stateHash: parsed.stateHash || \"\",\n };\n } catch {\n return { agents: [], stateHash: \"\" };\n }\n}\n\n// --- Health Check ---\n\nexport async function checkHealth(): Promise<boolean> {\n const serverUrl = getServerUrl();\n try {\n const res = await fetch(`${serverUrl}/api/health`, { method: \"GET\" });\n return res.ok;\n } catch {\n return false;\n }\n}\n","/**\n * orkestrate login\n *\n * Authenticate with Orkestrate via OAuth browser flow.\n */\n\nimport { performLogin } from \"../lib/auth.js\";\nimport { getCredentials, getConfigPath } from \"../lib/config.js\";\nimport { listWorkspaces } from \"../lib/api.js\";\nimport { setActiveWorkspace } from \"../lib/config.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function loginCommand(): Promise<void> {\n // Check if already logged in\n const existing = getCredentials();\n if (existing?.accessToken) {\n ui.warn(\"You are already logged in.\");\n ui.dim(`Config: ${getConfigPath()}`);\n ui.dim(\"Run `orkestrate logout` to sign out first.\");\n ui.blank();\n return;\n }\n\n ui.info(\"Opening browser for authentication...\");\n ui.dim(\"If the browser doesn't open, check your terminal for the URL.\");\n ui.blank();\n\n try {\n const result = await performLogin();\n\n ui.success(\"Authenticated successfully!\");\n ui.blank();\n\n // Try to fetch and display workspaces\n try {\n const workspaces = await listWorkspaces();\n if (workspaces.length > 0) {\n const active = workspaces.find((w) => w.isActive) || workspaces[0];\n setActiveWorkspace(active.id, active.name);\n ui.kv(\"Workspace\", active.name);\n ui.kv(\"Workspace ID\", active.id);\n\n if (workspaces.length > 1) {\n ui.dim(`${workspaces.length - 1} other workspace(s) available. Use \\`orkestrate workspace list\\` to see all.`);\n }\n } else {\n ui.dim(\"No workspaces found. Create one at orkestrate.space or run `orkestrate workspace create`.\");\n }\n } catch {\n // Non-fatal — user is still authenticated\n ui.dim(\"Could not fetch workspaces. You can do this later with `orkestrate workspace list`.\");\n }\n\n ui.blank();\n ui.dim(`Credentials stored at: ${getConfigPath()}`);\n ui.blank();\n ui.info(\"Next step: run `orkestrate connect claude` to wire up your AI tool.\");\n } catch (err) {\n ui.error(`Login failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n","/**\n * orkestrate logout\n *\n * Clear stored credentials.\n */\n\nimport { clearCredentials, getCredentials, getConfigPath } from \"../lib/config.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport function logoutCommand(): void {\n const existing = getCredentials();\n\n if (!existing?.accessToken) {\n ui.dim(\"Not currently logged in.\");\n return;\n }\n\n clearCredentials();\n ui.success(\"Logged out. Credentials cleared.\");\n ui.dim(`Config: ${getConfigPath()}`);\n}\n","/**\n * Orkestrate CLI — Tool Detection & MCP Configuration\n *\n * Detects installed AI coding tools and writes MCP configuration\n * to connect them to the Orkestrate coordination server.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { execSync } from \"node:child_process\";\nimport { getServerUrl } from \"./config.js\";\n\nexport type ToolName = \"claude\" | \"opencode\" | \"cursor\" | \"windsurf\" | \"codex\";\n\nexport interface DetectedTool {\n name: ToolName;\n displayName: string;\n detected: boolean;\n configPath?: string;\n}\n\n/**\n * Detect which AI coding tools are available on this system.\n */\nexport function detectTools(projectDir: string = process.cwd()): DetectedTool[] {\n const tools: DetectedTool[] = [];\n\n // Claude Code\n tools.push({\n name: \"claude\",\n displayName: \"Claude Code\",\n detected: isCommandAvailable(\"claude\"),\n });\n\n // OpenCode\n const opencodeConfig = join(projectDir, \"opencode.json\");\n tools.push({\n name: \"opencode\",\n displayName: \"OpenCode\",\n detected: existsSync(opencodeConfig) || isCommandAvailable(\"opencode\"),\n configPath: opencodeConfig,\n });\n\n // Cursor\n const cursorConfig = join(projectDir, \".cursor\", \"mcp.json\");\n tools.push({\n name: \"cursor\",\n displayName: \"Cursor\",\n detected: existsSync(join(projectDir, \".cursor\")) || existsSync(cursorConfig),\n configPath: cursorConfig,\n });\n\n // Windsurf\n const windsurfConfig = join(projectDir, \".windsurf\", \"mcp.json\");\n tools.push({\n name: \"windsurf\",\n displayName: \"Windsurf\",\n detected: existsSync(join(projectDir, \".windsurf\")) || existsSync(windsurfConfig),\n configPath: windsurfConfig,\n });\n\n // Codex\n const codexDir = join(homedir(), \".codex\");\n tools.push({\n name: \"codex\",\n displayName: \"Codex CLI\",\n detected: isCommandAvailable(\"codex\") || existsSync(codexDir),\n });\n\n return tools;\n}\n\n/**\n * Configure MCP for a specific tool.\n */\nexport async function configureTool(\n tool: ToolName,\n projectDir: string = process.cwd(),\n): Promise<{ success: boolean; message: string }> {\n const serverUrl = getServerUrl();\n const mcpUrl = `${serverUrl}/api/mcp`;\n\n switch (tool) {\n case \"claude\":\n return configureClaudeCode(mcpUrl);\n case \"opencode\":\n return configureOpenCode(join(projectDir, \"opencode.json\"), mcpUrl);\n case \"cursor\":\n return configureMcpServersJson(\"Cursor\", join(projectDir, \".cursor\", \"mcp.json\"), mcpUrl);\n case \"windsurf\":\n return configureMcpServersJson(\"Windsurf\", join(projectDir, \".windsurf\", \"mcp.json\"), mcpUrl);\n case \"codex\":\n return configureCodex(projectDir, mcpUrl);\n default:\n return { success: false, message: `Unknown tool: ${tool}` };\n }\n}\n\n/**\n * Resolves the best way to run the Orkestrate MCP bridge.\n * Returns { command: string, args: string[] }\n */\nfunction resolveMcpBridge(projectDir: string): { command: string, args: string[] } {\n const isWindows = process.platform === \"win32\";\n const nodePath = getNodePath();\n\n // 1. Check if we're in the Agentalk source repo (dev mode)\n const devMcpEntry = join(projectDir, \"dist\", \"mcp-entry.js\");\n const pkgJsonPath = join(projectDir, \"package.json\");\n \n if (existsSync(devMcpEntry) && existsSync(pkgJsonPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, \"utf-8\"));\n if (pkg.name === \"orkestrate\") {\n return {\n command: nodePath,\n args: [devMcpEntry.replace(/\\\\/g, \"/\")]\n };\n }\n } catch { /* ignore */ }\n }\n\n // 2. Check for global installation (bun/npm)\n const home = homedir();\n const globalMcpEntry = join(home, \".bun\", \"install\", \"global\", \"node_modules\", \"orkestrate\", \"dist\", \"mcp-entry.js\");\n if (existsSync(globalMcpEntry)) {\n return {\n command: nodePath,\n args: [globalMcpEntry.replace(/\\\\/g, \"/\")]\n };\n }\n\n // 3. Last fallback: use the global command\n return {\n command: isWindows ? \"orkestrate.cmd\" : \"orkestrate\",\n args: [\"mcp\"]\n };\n}\n\nfunction getNodePath(): string {\n try {\n const isWindows = process.platform === \"win32\";\n const cmd = isWindows ? \"where node\" : \"which node\";\n const result = execSync(cmd, { stdio: \"pipe\" }).toString().trim().split(\"\\n\")[0].trim();\n return result.replace(/\\\\/g, \"/\");\n } catch {\n return \"node\";\n }\n}\n\n// ──────────────────────────────────────────────\n// Tool Specific Configs\n// ──────────────────────────────────────────────\n\nfunction configureClaudeCode(mcpUrl: string): { success: boolean; message: string } {\n if (!isCommandAvailable(\"claude\")) {\n return {\n success: false,\n message: \"Claude Code CLI not found.\",\n };\n }\n\n try {\n const bridge = resolveMcpBridge(process.cwd());\n const bridgeCmd = `\"${bridge.command}\" ${bridge.args.map(a => `\"${a}\"`).join(\" \")}`;\n \n try {\n execSync(\n `claude mcp add --transport stdio --scope project Orkestrate ${bridgeCmd}`,\n { stdio: \"pipe\", encoding: \"utf-8\" },\n );\n return {\n success: true,\n message: \"MCP added to Claude Code via local proxy.\",\n };\n } catch {\n execSync(\n `claude mcp add --transport http --scope project Orkestrate \"${mcpUrl}\"`,\n { stdio: \"pipe\", encoding: \"utf-8\" },\n );\n return { success: true, message: \"MCP added to Claude Code via HTTP.\" };\n }\n } catch (err) {\n return { success: false, message: `Claude config failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n}\n\nfunction configureOpenCode(configPath: string, mcpUrl: string): { success: boolean; message: string } {\n try {\n let config = existsSync(configPath) ? JSON.parse(readFileSync(configPath, \"utf-8\")) : {};\n if (!config.mcp || typeof config.mcp !== \"object\") config.mcp = {};\n\n config.mcp[\"Orkestrate\"] = { type: \"remote\", url: mcpUrl, oauth: {} };\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n\n return { success: true, message: `Configured OpenCode at ${configPath}` };\n } catch (err) {\n return { success: false, message: `OpenCode config failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n}\n\nfunction configureMcpServersJson(displayName: string, configPath: string, mcpUrl: string): { success: boolean; message: string } {\n try {\n const dir = join(configPath, \"..\");\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n\n let config = existsSync(configPath) ? JSON.parse(readFileSync(configPath, \"utf-8\")) : {};\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") config.mcpServers = {};\n\n config.mcpServers[\"Orkestrate\"] = { url: mcpUrl, type: \"http\" };\n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n\n return { success: true, message: `Configured ${displayName} at ${configPath}` };\n } catch (err) {\n return { success: false, message: `${displayName} config failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n}\n\nfunction configureCodex(projectDir: string, mcpUrl: string): { success: boolean; message: string } {\n const home = homedir();\n const codexDir = join(home, \".codex\");\n const configPath = join(codexDir, \"config.toml\");\n\n try {\n if (!existsSync(codexDir)) mkdirSync(codexDir, { recursive: true });\n\n const bridge = resolveMcpBridge(projectDir);\n let content = existsSync(configPath) ? readFileSync(configPath, \"utf-8\") : \"[mcp_servers]\\n\";\n\n const sectionRegex = /\\[mcp_servers\\.Orkestrate\\]\\s*\\n(?:(?!\\[)[^\\n]*\\n?)*/;\n const proxySection = `[mcp_servers.Orkestrate]\\ncommand = \"${bridge.command}\"\\nargs = [${bridge.args.map(a => `\"${a}\"`).join(\", \")}]\\n`;\n\n if (sectionRegex.test(content)) {\n content = content.replace(sectionRegex, proxySection);\n } else {\n const mcpServersIdx = content.indexOf(\"[mcp_servers]\");\n if (mcpServersIdx !== -1) {\n const lineEnd = content.indexOf(\"\\n\", mcpServersIdx);\n const insertPos = lineEnd !== -1 ? lineEnd + 1 : content.length;\n content = content.slice(0, insertPos) + \"\\n\" + proxySection + content.slice(insertPos);\n } else {\n content = content.trimEnd() + \"\\n\\n[mcp_servers]\\n\\n\" + proxySection;\n }\n }\n\n writeFileSync(configPath, content, \"utf-8\");\n return { success: true, message: `Configured Codex (bridge: ${bridge.command}).` };\n } catch (err) {\n return { success: false, message: `Codex config failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n}\n\nfunction isCommandAvailable(command: string): boolean {\n try {\n const isWindows = process.platform === \"win32\";\n const checkCmd = isWindows ? `where ${command}` : `which ${command}`;\n execSync(checkCmd, { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function getToolNames(): ToolName[] {\n return [\"claude\", \"opencode\", \"cursor\", \"windsurf\", \"codex\"];\n}\n","/**\n * orkestrate connect <tool>\n *\n * Auto-configure MCP endpoint for a specific AI coding tool.\n */\n\nimport { getCredentials } from \"../lib/config.js\";\nimport {\n configureTool,\n detectTools,\n getToolNames,\n type ToolName,\n} from \"../lib/detect.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function connectCommand(toolName?: string): Promise<void> {\n // Require authentication\n const creds = getCredentials();\n if (!creds?.accessToken) {\n ui.error(\"Not authenticated. Run `orkestrate login` first.\");\n process.exit(1);\n }\n\n const validTools = getToolNames();\n\n // If no tool specified, detect and list available tools\n if (!toolName) {\n ui.header(\"Detected Tools\");\n\n const detected = detectTools();\n const found = detected.filter((t) => t.detected);\n\n if (found.length === 0) {\n ui.dim(\"No supported AI coding tools detected in this environment.\");\n ui.blank();\n ui.info(\"Supported tools:\");\n for (const name of validTools) {\n ui.line(` • ${name}`);\n }\n ui.blank();\n ui.info(\"Usage: orkestrate connect <tool>\");\n return;\n }\n\n for (const tool of detected) {\n if (tool.detected) {\n ui.success(`${tool.displayName} — detected`);\n } else {\n ui.dim(`${tool.displayName} — not found`);\n }\n }\n\n ui.blank();\n ui.info(\"Run `orkestrate connect <tool>` to configure. Example:\");\n ui.line(` orkestrate connect ${found[0].name}`);\n return;\n }\n\n // Validate tool name\n const tool = toolName.toLowerCase() as ToolName;\n if (!validTools.includes(tool)) {\n ui.error(`Unknown tool: ${toolName}`);\n ui.blank();\n ui.info(\"Supported tools:\");\n for (const name of validTools) {\n ui.line(` • ${name}`);\n }\n process.exit(1);\n }\n\n // Configure\n ui.info(`Configuring MCP for ${toolName}...`);\n\n const result = await configureTool(tool);\n\n if (result.success) {\n ui.success(result.message);\n ui.blank();\n ui.info(\"Your AI tool can now connect to Orkestrate.\");\n ui.dim(\"Restart your tool if it's currently running.\");\n } else {\n ui.error(result.message);\n process.exit(1);\n }\n}\n","/**\n * orkestrate status\n *\n * Display current team coordination state in the terminal.\n */\n\nimport { getCredentials, getActiveWorkspace } from \"../lib/config.js\";\nimport { getTeamStatus, listWorkspaces, checkHealth } from \"../lib/api.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function statusCommand(): Promise<void> {\n const creds = getCredentials();\n if (!creds?.accessToken) {\n ui.error(\"Not authenticated. Run `orkestrate login` first.\");\n process.exit(1);\n }\n\n // Check server health\n const healthy = await checkHealth();\n if (!healthy) {\n ui.error(\"Cannot reach Orkestrate server. Check your connection.\");\n process.exit(1);\n }\n\n const workspace = getActiveWorkspace();\n\n ui.header(\"Orkestrate Status\");\n\n // Show workspace info\n if (workspace.name) {\n ui.kv(\"Workspace\", workspace.name);\n }\n if (workspace.id) {\n ui.kv(\"ID\", workspace.id);\n }\n ui.blank();\n\n try {\n const { agents, stateHash } = await getTeamStatus();\n\n if (agents.length === 0) {\n ui.dim(\"No active agents in this workspace.\");\n ui.blank();\n ui.info(\"Connect an agent with `orkestrate connect <tool>` to get started.\");\n return;\n }\n\n // Build table\n const rows = agents.map((agent) => [\n agent.agentId || agent.scopedAgentId,\n agent.toolName || \"—\",\n agent.status,\n truncate(agent.objective, 35),\n ]);\n\n ui.table(\n [\"Agent\", \"Tool\", \"Status\", \"Objective\"],\n rows,\n );\n\n // Show claimed paths summary\n const agentsWithClaims = agents.filter(\n (a) => a.claimedPaths && a.claimedPaths.length > 0,\n );\n if (agentsWithClaims.length > 0) {\n ui.blank();\n ui.line(pc_bold(\"Active Scope Claims:\"));\n for (const agent of agentsWithClaims) {\n ui.line(` ${agent.agentId}: ${agent.claimedPaths.join(\", \")}`);\n }\n }\n\n ui.blank();\n ui.dim(`State hash: ${stateHash}`);\n ui.dim(`${agents.length} agent(s) connected`);\n } catch (err) {\n ui.error(\n `Failed to fetch status: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exit(1);\n }\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1) + \"…\";\n}\n\n// Inline bold since we don't want to import picocolors at top level just for one use\nfunction pc_bold(s: string): string {\n return `\\x1b[1m${s}\\x1b[22m`;\n}\n","/**\n * orkestrate workspace [list|switch|create]\n *\n * Manage workspaces from the CLI.\n */\n\nimport { getCredentials, setActiveWorkspace, getActiveWorkspace } from \"../lib/config.js\";\nimport {\n listWorkspaces,\n switchWorkspace as apiSwitchWorkspace,\n createWorkspace as apiCreateWorkspace,\n} from \"../lib/api.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function workspaceCommand(\n action?: string,\n nameOrId?: string,\n extra?: string,\n): Promise<void> {\n const creds = getCredentials();\n if (!creds?.accessToken) {\n ui.error(\"Not authenticated. Run `orkestrate login` first.\");\n process.exit(1);\n }\n\n const subcommand = (action || \"list\").toLowerCase();\n\n switch (subcommand) {\n case \"list\":\n case \"ls\":\n return workspaceList();\n\n case \"switch\":\n case \"use\":\n if (!nameOrId) {\n ui.error(\"Usage: orkestrate workspace switch <workspace-id-or-name>\");\n process.exit(1);\n }\n return workspaceSwitch(nameOrId);\n\n case \"create\":\n case \"new\":\n if (!nameOrId) {\n ui.error(\"Usage: orkestrate workspace create <name> <repo-url> [branch]\");\n process.exit(1);\n }\n return workspaceCreate(nameOrId, extra);\n\n default:\n ui.error(`Unknown subcommand: ${action}`);\n ui.blank();\n ui.info(\"Available subcommands:\");\n ui.line(\" list — Show all workspaces\");\n ui.line(\" switch — Switch active workspace\");\n ui.line(\" create — Create a new workspace\");\n process.exit(1);\n }\n}\n\nasync function workspaceList(): Promise<void> {\n ui.header(\"Workspaces\");\n\n try {\n const workspaces = await listWorkspaces();\n const active = getActiveWorkspace();\n\n if (workspaces.length === 0) {\n ui.dim(\"No workspaces found.\");\n ui.info(\"Create one at orkestrate.space or run `orkestrate workspace create`.\");\n return;\n }\n\n for (const ws of workspaces) {\n const isActive = ws.id === active.id || ws.isActive;\n const marker = isActive ? \" ← active\" : \"\";\n const name = ws.name || \"Unnamed\";\n\n if (isActive) {\n ui.success(`${name} (${ws.id})${marker}`);\n } else {\n ui.line(` ${name} (${ws.id})`);\n }\n\n if (ws.repoUrl) {\n ui.dim(` repo: ${ws.repoUrl}`);\n }\n }\n\n ui.blank();\n ui.dim(`${workspaces.length} workspace(s)`);\n } catch (err) {\n ui.error(`Failed to list workspaces: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n\nasync function workspaceSwitch(nameOrId: string): Promise<void> {\n try {\n const workspaces = await listWorkspaces();\n\n // Find by exact ID or name match\n const target = workspaces.find(\n (ws) =>\n ws.id === nameOrId ||\n ws.name.toLowerCase() === nameOrId.toLowerCase(),\n );\n\n if (!target) {\n ui.error(`Workspace not found: ${nameOrId}`);\n ui.blank();\n ui.info(\"Available workspaces:\");\n for (const ws of workspaces) {\n ui.line(` ${ws.name} (${ws.id})`);\n }\n process.exit(1);\n }\n\n await apiSwitchWorkspace(target.id);\n setActiveWorkspace(target.id, target.name);\n ui.success(`Switched to workspace: ${target.name}`);\n } catch (err) {\n ui.error(`Failed to switch workspace: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n\nasync function workspaceCreate(name: string, repoUrl?: string): Promise<void> {\n if (!repoUrl) {\n ui.error(\"Repository URL is required.\");\n ui.info(\"Usage: orkestrate workspace create <name> <repo-url>\");\n process.exit(1);\n }\n\n try {\n const workspace = await apiCreateWorkspace(name, repoUrl, \"main\");\n setActiveWorkspace(workspace.id, workspace.name || name);\n ui.success(`Created workspace: ${workspace.name || name}`);\n ui.kv(\"ID\", workspace.id);\n ui.kv(\"Repo\", repoUrl);\n } catch (err) {\n ui.error(`Failed to create workspace: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n","/**\n * Orkestrate CLI — Git Context Detection\n *\n * Reads git metadata from the current working directory.\n */\n\nimport { execSync } from \"node:child_process\";\n\nexport interface GitContext {\n remote: string;\n repoRoot: string;\n branch: string;\n headSha: string;\n dirty: boolean;\n collectedAt: string;\n}\n\nfunction git(cmd: string, cwd: string): string {\n try {\n return execSync(`git ${cmd}`, {\n cwd,\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n } catch {\n return \"\";\n }\n}\n\nexport function detectGitContext(cwd: string = process.cwd()): GitContext | null {\n const repoRoot = git(\"rev-parse --show-toplevel\", cwd);\n if (!repoRoot) return null;\n\n const remote = git(\"remote get-url origin\", cwd);\n const branch = git(\"rev-parse --abbrev-ref HEAD\", cwd);\n const headSha = git(\"rev-parse HEAD\", cwd);\n const status = git(\"status --porcelain\", cwd);\n\n return {\n remote: remote || \"\",\n repoRoot,\n branch: branch || \"unknown\",\n headSha: headSha || \"\",\n dirty: status.length > 0,\n collectedAt: new Date().toISOString(),\n };\n}\n","/**\n * orkestrate init\n *\n * Initialize Orkestrate in the current project directory.\n * Detects git context and binds to the matching workspace.\n */\n\nimport { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getCredentials, getActiveWorkspace, setActiveWorkspace } from \"../lib/config.js\";\nimport { detectGitContext } from \"../lib/git.js\";\nimport { listWorkspaces } from \"../lib/api.js\";\nimport { detectTools } from \"../lib/detect.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function initCommand(): Promise<void> {\n const creds = getCredentials();\n if (!creds?.accessToken) {\n ui.error(\"Not authenticated. Run `orkestrate login` first.\");\n process.exit(1);\n }\n\n const cwd = process.cwd();\n\n ui.header(\"Initializing Orkestrate\");\n\n // Step 1: Detect git context\n const git = detectGitContext(cwd);\n if (git) {\n ui.success(`Git repository detected`);\n ui.kv(\"Remote\", git.remote || \"(no remote)\");\n ui.kv(\"Branch\", git.branch);\n ui.kv(\"HEAD\", git.headSha.slice(0, 8));\n ui.kv(\"Dirty\", git.dirty ? \"yes\" : \"clean\");\n } else {\n ui.warn(\"No git repository detected in current directory.\");\n ui.dim(\"Orkestrate works best with a git repository.\");\n }\n\n ui.blank();\n\n // Step 2: Match to workspace\n try {\n const workspaces = await listWorkspaces();\n let matched = false;\n\n if (git?.remote && workspaces.length > 0) {\n // Try to match by repo URL\n const normalizedRemote = normalizeGitUrl(git.remote);\n const match = workspaces.find((ws) => {\n if (!ws.repoUrl) return false;\n return normalizeGitUrl(ws.repoUrl) === normalizedRemote;\n });\n\n if (match) {\n setActiveWorkspace(match.id, match.name);\n ui.success(`Matched to workspace: ${match.name}`);\n ui.kv(\"Workspace ID\", match.id);\n matched = true;\n }\n }\n\n if (!matched) {\n const active = getActiveWorkspace();\n if (active.id) {\n ui.info(`Using current workspace: ${active.name || active.id}`);\n } else if (workspaces.length > 0) {\n const first = workspaces[0];\n setActiveWorkspace(first.id, first.name);\n ui.info(`Using workspace: ${first.name}`);\n } else {\n ui.warn(\"No workspaces available. Create one at orkestrate.space\");\n }\n }\n } catch {\n ui.dim(\"Could not fetch workspaces. Skipping workspace matching.\");\n }\n\n ui.blank();\n\n // Step 3: Detect available tools\n const tools = detectTools(cwd);\n const found = tools.filter((t) => t.detected);\n\n if (found.length > 0) {\n ui.info(\"Detected AI tools:\");\n for (const tool of found) {\n ui.line(` • ${tool.displayName}`);\n }\n ui.blank();\n ui.info(`Run \\`orkestrate connect ${found[0].name}\\` to configure MCP.`);\n } else {\n ui.dim(\"No AI coding tools detected. Install one and run `orkestrate connect <tool>`.\");\n }\n\n // Step 4: Write .orkestrate.json (project marker)\n const configFile = join(cwd, \".orkestrate.json\");\n if (!existsSync(configFile)) {\n const activeWs = getActiveWorkspace();\n const projectConfig = {\n $schema: \"https://orkestrate.space/schema/project.json\",\n workspaceId: activeWs.id || null,\n server: \"https://orkestrate.space\",\n initialized: new Date().toISOString(),\n };\n\n writeFileSync(configFile, JSON.stringify(projectConfig, null, 2) + \"\\n\", \"utf-8\");\n ui.blank();\n ui.success(`Created .orkestrate.json`);\n ui.dim(\"Add this file to your repository so collaborators can auto-detect the workspace.\");\n } else {\n ui.dim(\".orkestrate.json already exists — skipping.\");\n }\n\n ui.blank();\n}\n\n/**\n * Normalize a git remote URL for comparison.\n * Handles https://, git@, and .git suffix variations.\n */\nfunction normalizeGitUrl(url: string): string {\n let normalized = url.trim().toLowerCase();\n\n // Remove trailing .git\n normalized = normalized.replace(/\\.git$/, \"\");\n\n // Convert SSH to HTTPS format for comparison\n // git@github.com:user/repo → github.com/user/repo\n const sshMatch = normalized.match(/^git@([^:]+):(.+)$/);\n if (sshMatch) {\n normalized = `${sshMatch[1]}/${sshMatch[2]}`;\n }\n\n // Remove protocol\n normalized = normalized.replace(/^https?:\\/\\//, \"\");\n normalized = normalized.replace(/^ssh:\\/\\//, \"\");\n\n // Remove trailing slash\n normalized = normalized.replace(/\\/$/, \"\");\n\n return normalized;\n}\n","\nimport { getServerUrl } from \"../lib/config.js\";\nimport { getValidToken } from \"../lib/auth.js\";\n\n/**\n * Orkestrate MCP Proxy\n * \n * Acts as a local MCP server (stdio) that forwards all requests to the \n * Orkestrate cloud MCP endpoint (HTTP), injecting the local auth token.\n */\nexport async function mcpCommand() {\n try {\n const serverUrl = getServerUrl();\n const mcpUrl = `${serverUrl}/api/mcp`;\n\n process.stdin.setEncoding(\"utf-8\");\n let buffer = \"\";\n \n process.stdin.on(\"data\", async (chunk) => {\n const rawChunk = String(chunk);\n buffer += rawChunk;\n \n let lineEndIndex;\n while ((lineEndIndex = buffer.indexOf(\"\\n\")) >= 0) {\n let line = buffer.slice(0, lineEndIndex).trim();\n buffer = buffer.slice(lineEndIndex + 1);\n \n if (!line) continue;\n \n // Handle back-to-back JSON objects missing newlines\n if (line.includes(\"}{\")) {\n const parts = line.split(\"}{\");\n processLine(parts[0] + \"}\", mcpUrl);\n for (let i = 1; i < parts.length - 1; i++) {\n processLine(\"{\" + parts[i] + \"}\", mcpUrl);\n }\n processLine(\"{\" + parts[parts.length - 1], mcpUrl);\n } else {\n processLine(line, mcpUrl);\n }\n }\n });\n\n process.stdin.on(\"end\", () => {\n process.exit(0);\n });\n\n // Stay alive\n await new Promise(() => {});\n } catch (err) {\n process.stderr.write(`[Orkestrate] Fatal error: ${err}\\n`);\n process.exit(1);\n }\n}\n\nasync function processLine(line: string, mcpUrl: string) {\n try {\n const payload = JSON.parse(line);\n const isNotification = !Object.prototype.hasOwnProperty.call(payload, \"id\");\n \n const token = await getValidToken();\n const res = await fetch(mcpUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${token}`,\n \"User-Agent\": \"Orkestrate-CLI-Proxy\"\n },\n body: line\n });\n\n // Notifications MUST NOT be responded to on stdout\n if (isNotification) return;\n\n const responseBody = await res.text();\n if (responseBody) {\n process.stdout.write(responseBody + \"\\n\");\n }\n } catch (err) {\n try {\n const payload = JSON.parse(line);\n if (payload.id !== undefined) {\n process.stdout.write(JSON.stringify({\n jsonrpc: \"2.0\",\n id: payload.id,\n error: {\n code: -32603,\n message: `Orkestrate Proxy Error: ${err instanceof Error ? err.message : String(err)}`\n }\n }) + \"\\n\");\n }\n } catch { \n process.stderr.write(`[Orkestrate] Internal error: ${err}\\n`);\n }\n }\n}\n","/**\n * orkestrate whoami\n *\n * Show current authentication and configuration state.\n */\n\nimport { getCredentials, getActiveWorkspace, getServerUrl, getConfigPath } from \"../lib/config.js\";\nimport { checkHealth } from \"../lib/api.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function whoamiCommand(): Promise<void> {\n ui.header(\"Orkestrate Configuration\");\n\n const creds = getCredentials();\n const workspace = getActiveWorkspace();\n const serverUrl = getServerUrl();\n\n ui.kv(\"Server\", serverUrl);\n ui.kv(\"Config\", getConfigPath());\n ui.blank();\n\n if (creds?.accessToken) {\n ui.success(\"Authenticated\");\n ui.kv(\"Client ID\", creds.clientId);\n if (creds.userId) {\n ui.kv(\"User ID\", creds.userId);\n }\n\n const expiresIn = creds.expiresAt - Math.floor(Date.now() / 1000);\n if (expiresIn > 0) {\n const minutes = Math.floor(expiresIn / 60);\n ui.kv(\"Token expires\", `in ${minutes} minute(s)`);\n } else {\n ui.warn(\"Access token expired — will auto-refresh on next API call.\");\n }\n } else {\n ui.error(\"Not authenticated. Run `orkestrate login`.\");\n }\n\n ui.blank();\n\n if (workspace.id) {\n ui.kv(\"Active workspace\", workspace.name || \"—\");\n ui.kv(\"Workspace ID\", workspace.id);\n } else {\n ui.dim(\"No active workspace set.\");\n }\n\n ui.blank();\n\n // Server health check\n ui.info(\"Checking server health...\");\n const healthy = await checkHealth();\n if (healthy) {\n ui.success(\"Server is reachable\");\n } else {\n ui.error(\"Server is unreachable\");\n }\n}\n","/**\n * Orkestrate CLI\n *\n * The coordination layer for autonomous AI coding agents.\n * https://orkestrate.space\n */\n\nimport { Command } from \"commander\";\nimport { ui } from \"./lib/ui.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"orkestrate\")\n .description(\"The coordination layer for autonomous AI coding agents\")\n .version(\"0.1.0\")\n .hook(\"preAction\", () => {\n // Show banner on all commands\n });\n\n// --- login ---\nprogram\n .command(\"login\")\n .description(\"Authenticate with Orkestrate via browser OAuth\")\n .action(async () => {\n const { loginCommand } = await import(\"./commands/login.js\");\n await loginCommand();\n });\n\n// --- logout ---\nprogram\n .command(\"logout\")\n .description(\"Clear stored credentials\")\n .action(async () => {\n const { logoutCommand } = await import(\"./commands/logout.js\");\n logoutCommand();\n });\n\n// --- connect ---\nprogram\n .command(\"connect [tool]\")\n .description(\"Configure MCP endpoint for an AI coding tool (claude, opencode, cursor, windsurf, codex)\")\n .action(async (tool?: string) => {\n const { connectCommand } = await import(\"./commands/connect.js\");\n await connectCommand(tool);\n });\n\n// --- status ---\nprogram\n .command(\"status\")\n .alias(\"s\")\n .description(\"Show current team coordination state\")\n .action(async () => {\n const { statusCommand } = await import(\"./commands/status.js\");\n await statusCommand();\n });\n\n// --- workspace ---\nprogram\n .command(\"workspace [action] [name] [extra]\")\n .alias(\"ws\")\n .description(\"Manage workspaces (list, switch, create)\")\n .action(async (action?: string, name?: string, extra?: string) => {\n const { workspaceCommand } = await import(\"./commands/workspace.js\");\n await workspaceCommand(action, name, extra);\n });\n\n// --- init ---\nprogram\n .command(\"init\")\n .description(\"Initialize Orkestrate in the current project\")\n .action(async () => {\n const { initCommand } = await import(\"./commands/init.js\");\n await initCommand();\n });\n\n// --- mcp ---\nprogram\n .command(\"mcp\")\n .description(\"Run as a local MCP server (stdio bridge to Orkestrate Cloud)\")\n .action(async () => {\n try {\n const { mcpCommand } = await import(\"./commands/mcp.js\");\n await mcpCommand();\n } catch (err) {\n process.stderr.write(`[Orkestrate-MCP] ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n });\n\n// --- whoami ---\nprogram\n .command(\"whoami\")\n .description(\"Show current authentication and configuration\")\n .action(async () => {\n const { whoamiCommand } = await import(\"./commands/whoami.js\");\n await whoamiCommand();\n });\n\n// --- Default: show banner + help ---\nprogram.action(() => {\n ui.banner();\n program.help();\n});\n\n// Run\nprogram.parseAsync(process.argv).catch((err) => {\n ui.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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","names":["config","tool","execSync","existsSync","writeFileSync","join","git","loginCommand","logoutCommand","connectCommand","statusCommand","workspaceCommand","initCommand","mcpCommand","whoamiCommand"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/ui.ts","../src/lib/config.ts","../src/lib/auth.ts","../src/lib/api.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/lib/detect.ts","../src/commands/connect.ts","../src/commands/status.ts","../src/commands/workspace.ts","../src/lib/git.ts","../src/commands/init.ts","../src/commands/mcp.ts","../src/commands/whoami.ts","../src/cli.ts"],"sourcesContent":["/**\n * Orkestrate CLI — Terminal UI Helpers\n *\n * Pretty output formatting for the terminal.\n */\n\nimport pc from \"picocolors\";\n\nexport const ui = {\n // Status icons\n success: (msg: string) => console.log(` ${pc.green(\"✓\")} ${msg}`),\n error: (msg: string) => console.log(` ${pc.red(\"✗\")} ${msg}`),\n info: (msg: string) => console.log(` ${pc.blue(\"→\")} ${msg}`),\n warn: (msg: string) => console.log(` ${pc.yellow(\"!\")} ${msg}`),\n dim: (msg: string) => console.log(` ${pc.dim(msg)}`),\n\n // Headers\n header: (msg: string) => {\n console.log();\n console.log(` ${pc.bold(pc.white(msg))}`);\n console.log();\n },\n\n // Blank line\n blank: () => console.log(),\n\n // Indented line\n line: (msg: string) => console.log(` ${msg}`),\n\n // Key-value pair\n kv: (key: string, value: string) => {\n console.log(` ${pc.dim(key + \":\")} ${value}`);\n },\n\n // Table\n table: (headers: string[], rows: string[][]) => {\n const colWidths = headers.map((h, i) => {\n const maxContent = Math.max(h.length, ...rows.map((r) => (r[i] || \"\").length));\n return Math.min(maxContent, 40);\n });\n\n const separator = \"─\";\n const pad = (s: string, w: number) => s.padEnd(w).slice(0, w);\n\n // Top border\n console.log(\n ` ┌${colWidths.map((w) => separator.repeat(w + 2)).join(\"┬\")}┐`,\n );\n\n // Header row\n console.log(\n ` │${headers.map((h, i) => ` ${pc.bold(pad(h, colWidths[i]))} `).join(\"│\")}│`,\n );\n\n // Header separator\n console.log(\n ` ├${colWidths.map((w) => separator.repeat(w + 2)).join(\"┼\")}┤`,\n );\n\n // Data rows\n for (const row of rows) {\n console.log(\n ` │${row.map((c, i) => ` ${pad(c || \"\", colWidths[i])} `).join(\"│\")}│`,\n );\n }\n\n // Bottom border\n console.log(\n ` └${colWidths.map((w) => separator.repeat(w + 2)).join(\"┴\")}┘`,\n );\n },\n\n // Colored status badge\n statusBadge: (status: string): string => {\n switch (status) {\n case \"active\":\n return pc.green(\"● active\");\n case \"idle\":\n return pc.dim(\"○ idle\");\n case \"blocked\":\n return pc.red(\"■ blocked\");\n case \"planning\":\n return pc.blue(\"◆ planning\");\n case \"handoff\":\n return pc.yellow(\"⇄ handoff\");\n case \"done\":\n return pc.dim(\"✓ done\");\n default:\n return pc.dim(status);\n }\n },\n\n // Banner\n banner: () => {\n console.log();\n console.log(pc.bold(pc.cyan(\" ⬡ orkestrate\")));\n console.log(pc.dim(\" the coordination layer for AI coding agents\"));\n console.log();\n },\n};\n","/**\n * Orkestrate CLI — Configuration Management\n *\n * Stores credentials and preferences in the user's home directory.\n * Uses the `conf` package for cross-platform config storage.\n */\n\nimport Conf from \"conf\";\n\nexport interface StoredCredentials {\n clientId: string;\n accessToken: string;\n refreshToken: string;\n expiresAt: number; // epoch seconds\n userId: string;\n scope: string;\n}\n\nexport interface CliConfig {\n credentials: StoredCredentials | null;\n activeWorkspaceId: string | null;\n activeWorkspaceName: string | null;\n serverUrl: string;\n}\n\nconst config = new Conf<CliConfig>({\n projectName: \"orkestrate\",\n projectSuffix: \"\",\n defaults: {\n credentials: null,\n activeWorkspaceId: null,\n activeWorkspaceName: null,\n serverUrl: \"https://orkestrate.space\",\n },\n});\n\nexport function getConfig(): CliConfig {\n return {\n credentials: config.get(\"credentials\"),\n activeWorkspaceId: config.get(\"activeWorkspaceId\"),\n activeWorkspaceName: config.get(\"activeWorkspaceName\"),\n serverUrl: config.get(\"serverUrl\"),\n };\n}\n\nexport function getServerUrl(): string {\n return config.get(\"serverUrl\");\n}\n\nexport function setCredentials(creds: StoredCredentials): void {\n config.set(\"credentials\", creds);\n}\n\nexport function getCredentials(): StoredCredentials | null {\n return config.get(\"credentials\");\n}\n\nexport function clearCredentials(): void {\n config.set(\"credentials\", null);\n}\n\nexport function setActiveWorkspace(id: string, name: string): void {\n config.set(\"activeWorkspaceId\", id);\n config.set(\"activeWorkspaceName\", name);\n}\n\nexport function getActiveWorkspace(): { id: string | null; name: string | null } {\n return {\n id: config.get(\"activeWorkspaceId\"),\n name: config.get(\"activeWorkspaceName\"),\n };\n}\n\nexport function setServerUrl(url: string): void {\n config.set(\"serverUrl\", url);\n}\n\nexport function clearAll(): void {\n config.clear();\n}\n\nexport function getConfigPath(): string {\n return config.path;\n}\n","/**\n * Orkestrate CLI — OAuth Authentication\n *\n * Implements the full OAuth 2.0 + PKCE flow:\n * 1. Dynamic client registration\n * 2. Open browser for consent\n * 3. Local HTTP callback server\n * 4. Token exchange\n * 5. Credential storage\n */\n\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport {\n getServerUrl,\n setCredentials,\n getCredentials,\n type StoredCredentials,\n} from \"./config.js\";\n\nfunction randomToken(bytes = 32): string {\n return randomBytes(bytes).toString(\"base64url\");\n}\n\nfunction pkceS256(verifier: string): string {\n return createHash(\"sha256\").update(verifier).digest(\"base64url\");\n}\n\ninterface TokenResponse {\n token_type: string;\n access_token: string;\n expires_in: number;\n refresh_token: string;\n scope: string;\n}\n\n/**\n * Step 1: Register this CLI instance as an OAuth client.\n */\nasync function registerClient(\n serverUrl: string,\n redirectUri: string,\n): Promise<{ clientId: string }> {\n const res = await fetch(`${serverUrl}/api/oauth/register`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_name: \"Orkestrate CLI\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n }),\n });\n\n if (!res.ok) {\n const body = await res.text();\n throw new Error(`Client registration failed (${res.status}): ${body}`);\n }\n\n const data = (await res.json()) as { client_id: string };\n return { clientId: data.client_id };\n}\n\n/**\n * Step 2 & 3: Open browser and wait for the OAuth callback.\n */\nfunction waitForCallback(\n port: number,\n): Promise<{ code: string; state: string }> {\n return new Promise((resolve, reject) => {\n let timeoutHandle: ReturnType<typeof setTimeout>;\n\n function cleanup() {\n clearTimeout(timeoutHandle);\n server.close();\n }\n\n const server = createServer((req: IncomingMessage, res: ServerResponse) => {\n const url = new URL(req.url || \"/\", `http://localhost:${port}`);\n\n if (url.pathname !== \"/callback\") {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n const error = url.searchParams.get(\"error\");\n const state = url.searchParams.get(\"state\") || \"\";\n\n if (error) {\n const description = url.searchParams.get(\"error_description\") || error;\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(buildErrorPage(description));\n cleanup();\n reject(new Error(`OAuth error: ${description}`));\n return;\n }\n\n if (!code) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(buildErrorPage(\"No authorization code received.\"));\n cleanup();\n reject(new Error(\"No authorization code received\"));\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(buildSuccessPage());\n cleanup();\n resolve({ code, state });\n });\n\n server.listen(port, \"127.0.0.1\", () => {\n // Server ready\n });\n\n server.on(\"error\", (err: Error) => {\n clearTimeout(timeoutHandle);\n reject(new Error(`Could not start local server: ${err.message}`));\n });\n\n // Timeout after 5 minutes — unref so it doesn't block process exit\n timeoutHandle = setTimeout(() => {\n server.close();\n reject(new Error(\"Authentication timed out (5 minutes). Please try again.\"));\n }, 5 * 60 * 1000);\n timeoutHandle.unref();\n });\n}\n\n/**\n * Step 4: Exchange authorization code for tokens.\n */\nasync function exchangeCodeForTokens(\n serverUrl: string,\n code: string,\n clientId: string,\n codeVerifier: string,\n redirectUri: string,\n): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n code_verifier: codeVerifier,\n client_id: clientId,\n redirect_uri: redirectUri,\n });\n\n const res = await fetch(`${serverUrl}/api/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Token exchange failed (${res.status}): ${text}`);\n }\n\n return (await res.json()) as TokenResponse;\n}\n\n/**\n * Refresh an expired access token.\n */\nexport async function refreshAccessToken(): Promise<StoredCredentials | null> {\n const creds = getCredentials();\n if (!creds?.refreshToken) return null;\n\n const serverUrl = getServerUrl();\n const body = new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: creds.refreshToken,\n client_id: creds.clientId,\n });\n\n const res = await fetch(`${serverUrl}/api/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!res.ok) return null;\n\n const tokens = (await res.json()) as TokenResponse;\n const now = Math.floor(Date.now() / 1000);\n\n const newCreds: StoredCredentials = {\n clientId: creds.clientId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: now + tokens.expires_in,\n userId: creds.userId,\n scope: tokens.scope,\n };\n\n setCredentials(newCreds);\n return newCreds;\n}\n\n/**\n * Get a valid access token, refreshing if needed.\n */\nexport async function getValidToken(): Promise<string | null> {\n const creds = getCredentials();\n if (!creds) return null;\n\n const now = Math.floor(Date.now() / 1000);\n\n // Refresh if expired or expiring within 60 seconds\n if (creds.expiresAt <= now + 60) {\n const refreshed = await refreshAccessToken();\n return refreshed?.accessToken || null;\n }\n\n return creds.accessToken;\n}\n\n/**\n * Run the full OAuth login flow.\n */\nexport async function performLogin(): Promise<{\n clientId: string;\n userId: string;\n accessToken: string;\n}> {\n const serverUrl = getServerUrl();\n const port = 19274; // \"ork\" on a phone keypad, roughly\n const redirectUri = `http://127.0.0.1:${port}/callback`;\n\n // Step 1: Register client\n const { clientId } = await registerClient(serverUrl, redirectUri);\n\n // Step 2: Prepare PKCE\n const codeVerifier = randomToken(48);\n const codeChallenge = pkceS256(codeVerifier);\n const state = randomToken(16);\n\n // Step 3: Build authorization URL\n const authUrl = new URL(`${serverUrl}/api/oauth/authorize`);\n authUrl.searchParams.set(\"response_type\", \"code\");\n authUrl.searchParams.set(\"client_id\", clientId);\n authUrl.searchParams.set(\"redirect_uri\", redirectUri);\n authUrl.searchParams.set(\"code_challenge\", codeChallenge);\n authUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authUrl.searchParams.set(\"scope\", \"mcp:read mcp:write\");\n authUrl.searchParams.set(\"state\", state);\n\n // Step 4: Start callback server + open browser\n const callbackPromise = waitForCallback(port);\n\n // Dynamic import to handle ESM-only `open` package\n const { default: openBrowser } = await import(\"open\");\n await openBrowser(authUrl.toString());\n\n // Step 5: Wait for callback\n const { code, state: returnedState } = await callbackPromise;\n\n if (returnedState !== state) {\n throw new Error(\"OAuth state mismatch — possible CSRF attack. Aborting.\");\n }\n\n // Step 6: Exchange code for tokens\n const tokens = await exchangeCodeForTokens(\n serverUrl,\n code,\n clientId,\n codeVerifier,\n redirectUri,\n );\n\n const now = Math.floor(Date.now() / 1000);\n\n // We don't get user_id from the token response directly.\n // We'll extract it from the MCP endpoint or store a placeholder.\n // For now, use clientId as a proxy until first API call resolves it.\n const credentials: StoredCredentials = {\n clientId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: now + tokens.expires_in,\n userId: \"\", // Will be resolved on first API call\n scope: tokens.scope,\n };\n\n setCredentials(credentials);\n\n return {\n clientId,\n userId: credentials.userId,\n accessToken: tokens.access_token,\n };\n}\n\n// --- HTML pages for the local callback server ---\n\nfunction buildSuccessPage(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Orkestrate — Authenticated</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n text-align: center;\n padding: 3rem;\n border: 1px solid #262626;\n border-radius: 12px;\n background: #111;\n max-width: 420px;\n }\n .icon { font-size: 3rem; margin-bottom: 1rem; }\n h1 { font-size: 1.5rem; margin-bottom: 0.5rem; color: #fff; }\n p { color: #a3a3a3; line-height: 1.6; }\n .hint { margin-top: 1.5rem; font-size: 0.85rem; color: #525252; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">✓</div>\n <h1>Authenticated</h1>\n <p>You're now logged in to Orkestrate. You can close this tab and return to your terminal.</p>\n <p class=\"hint\">This window will close automatically.</p>\n </div>\n <script>setTimeout(() => window.close(), 3000);</script>\n</body>\n</html>`;\n}\n\nfunction buildErrorPage(message: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Orkestrate — Error</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n text-align: center;\n padding: 3rem;\n border: 1px solid #371717;\n border-radius: 12px;\n background: #1a0a0a;\n max-width: 420px;\n }\n .icon { font-size: 3rem; margin-bottom: 1rem; }\n h1 { font-size: 1.5rem; margin-bottom: 0.5rem; color: #fca5a5; }\n p { color: #a3a3a3; line-height: 1.6; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">✗</div>\n <h1>Authentication Failed</h1>\n <p>${message}</p>\n </div>\n</body>\n</html>`;\n}\n","/**\n * Orkestrate CLI — API Client\n *\n * Authenticated HTTP client for the Orkestrate web API.\n * All requests use the stored OAuth bearer token.\n */\n\nimport { getServerUrl } from \"./config.js\";\nimport { getValidToken } from \"./auth.js\";\n\nexport class ApiError extends Error {\n constructor(\n public status: number,\n message: string,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\nasync function authHeaders(): Promise<Record<string, string>> {\n const token = await getValidToken();\n if (!token) {\n throw new ApiError(401, \"Not authenticated. Run `orkestrate login` first.\");\n }\n return {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n };\n}\n\nasync function request<T>(\n method: string,\n path: string,\n body?: unknown,\n): Promise<T> {\n const serverUrl = getServerUrl();\n const headers = await authHeaders();\n\n const res = await fetch(`${serverUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, `API error (${res.status}): ${text}`);\n }\n\n return res.json();\n}\n\n// --- Workspace API ---\n\nexport interface Workspace {\n id: string;\n name: string;\n ownerId: string;\n repoUrl: string | null;\n defaultBranch: string | null;\n isActive: boolean;\n createdAt: string;\n}\n\nexport async function listWorkspaces(): Promise<Workspace[]> {\n const data = await request<{ workspaces: Workspace[] }>(\"GET\", \"/api/workspaces\");\n return data.workspaces || [];\n}\n\nexport async function switchWorkspace(workspaceId: string): Promise<void> {\n await request(\"POST\", \"/api/workspaces\", {\n action: \"switch\",\n workspaceId,\n });\n}\n\nexport async function createWorkspace(\n name: string,\n repoUrl: string,\n defaultBranch: string,\n): Promise<Workspace> {\n const data = await request<{ workspace: Workspace }>(\"POST\", \"/api/workspaces\", {\n action: \"create\",\n name,\n repoUrl,\n defaultBranch,\n });\n return data.workspace;\n}\n\n// --- Agent Status API ---\n\nexport interface AgentState {\n scopedAgentId: string;\n agentId: string;\n toolName: string | null;\n status: string;\n objective: string;\n claimedPaths: string[];\n plan: string[];\n notes: string;\n updatedAt: string;\n}\n\nexport async function getTeamStatus(): Promise<{\n agents: AgentState[];\n stateHash: string;\n}> {\n // Use the MCP endpoint with a read_team_state RPC call\n const serverUrl = getServerUrl();\n const token = await getValidToken();\n if (!token) {\n throw new ApiError(401, \"Not authenticated. Run `orkestrate login` first.\");\n }\n\n const res = await fetch(`${serverUrl}/api/mcp`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: {\n name: \"read_team_state\",\n arguments: {},\n },\n }),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, `MCP error (${res.status}): ${text}`);\n }\n\n const rpcResult = await res.json();\n\n // Parse the MCP response to extract team state\n if (rpcResult.error) {\n throw new ApiError(400, rpcResult.error.message || \"MCP call failed\");\n }\n\n const content = rpcResult.result?.content || [];\n const textContent = content\n .filter((c: { type: string }) => c.type === \"text\")\n .map((c: { text: string }) => c.text)\n .join(\"\\n\");\n\n try {\n const parsed = JSON.parse(textContent);\n return {\n agents: parsed.agents || parsed.states || [],\n stateHash: parsed.stateHash || \"\",\n };\n } catch {\n return { agents: [], stateHash: \"\" };\n }\n}\n\n// --- Health Check ---\n\nexport async function checkHealth(): Promise<boolean> {\n const serverUrl = getServerUrl();\n try {\n const res = await fetch(`${serverUrl}/api/health`, { method: \"GET\" });\n return res.ok;\n } catch {\n return false;\n }\n}\n","/**\n * orkestrate login\n *\n * Authenticate with Orkestrate via OAuth browser flow.\n */\n\nimport { performLogin } from \"../lib/auth.js\";\nimport { getCredentials, getConfigPath } from \"../lib/config.js\";\nimport { listWorkspaces } from \"../lib/api.js\";\nimport { setActiveWorkspace } from \"../lib/config.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function loginCommand(): Promise<void> {\n // Check if already logged in\n const existing = getCredentials();\n if (existing?.accessToken) {\n ui.warn(\"You are already logged in.\");\n ui.dim(`Config: ${getConfigPath()}`);\n ui.dim(\"Run `orkestrate logout` to sign out first.\");\n ui.blank();\n return;\n }\n\n ui.info(\"Opening browser for authentication...\");\n ui.dim(\"If the browser doesn't open, check your terminal for the URL.\");\n ui.blank();\n\n try {\n const result = await performLogin();\n\n ui.success(\"Authenticated successfully!\");\n ui.blank();\n\n // Try to fetch and display workspaces\n try {\n const workspaces = await listWorkspaces();\n if (workspaces.length > 0) {\n const active = workspaces.find((w) => w.isActive) || workspaces[0];\n setActiveWorkspace(active.id, active.name);\n ui.kv(\"Workspace\", active.name);\n ui.kv(\"Workspace ID\", active.id);\n\n if (workspaces.length > 1) {\n ui.dim(`${workspaces.length - 1} other workspace(s) available. Use \\`orkestrate workspace list\\` to see all.`);\n }\n } else {\n ui.dim(\"No workspaces found. Create one at orkestrate.space or run `orkestrate workspace create`.\");\n }\n } catch {\n // Non-fatal — user is still authenticated\n ui.dim(\"Could not fetch workspaces. You can do this later with `orkestrate workspace list`.\");\n }\n\n ui.blank();\n ui.dim(`Credentials stored at: ${getConfigPath()}`);\n ui.blank();\n ui.info(\"Next step: run `orkestrate connect claude` to wire up your AI tool.\");\n } catch (err) {\n ui.error(`Login failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n","/**\n * orkestrate logout\n *\n * Clear stored credentials.\n */\n\nimport { clearCredentials, getCredentials, getConfigPath } from \"../lib/config.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport function logoutCommand(): void {\n const existing = getCredentials();\n\n if (!existing?.accessToken) {\n ui.dim(\"Not currently logged in.\");\n return;\n }\n\n clearCredentials();\n ui.success(\"Logged out. Credentials cleared.\");\n ui.dim(`Config: ${getConfigPath()}`);\n}\n","/**\n * Orkestrate CLI — Tool Detection & MCP Configuration\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { execSync } from \"node:child_process\";\nimport { getServerUrl } from \"./config.js\";\n\nexport type ToolName = \"claude\" | \"opencode\" | \"cursor\" | \"windsurf\" | \"codex\";\n\nexport interface DetectedTool {\n name: ToolName;\n displayName: string;\n detected: boolean;\n configPath?: string;\n}\n\n/**\n * Detect which AI coding tools are available on this system.\n */\nexport function detectTools(projectDir: string = process.cwd()): DetectedTool[] {\n const tools: DetectedTool[] = [];\n\n // Claude Code\n tools.push({\n name: \"claude\",\n displayName: \"Claude Code\",\n detected: isCommandAvailable(\"claude\"),\n });\n\n // OpenCode\n const opencodeConfig = join(projectDir, \"opencode.json\");\n tools.push({\n name: \"opencode\",\n displayName: \"OpenCode\",\n detected: existsSync(opencodeConfig) || isCommandAvailable(\"opencode\"),\n configPath: opencodeConfig,\n });\n\n // Cursor\n const cursorConfig = join(projectDir, \".cursor\", \"mcp.json\");\n tools.push({\n name: \"cursor\",\n displayName: \"Cursor\",\n detected: existsSync(join(projectDir, \".cursor\")) || existsSync(cursorConfig),\n configPath: cursorConfig,\n });\n\n // Windsurf\n const windsurfConfig = join(projectDir, \".windsurf\", \"mcp.json\");\n tools.push({\n name: \"windsurf\",\n displayName: \"Windsurf\",\n detected: existsSync(join(projectDir, \".windsurf\")) || existsSync(windsurfConfig),\n configPath: windsurfConfig,\n });\n\n // Codex\n const codexDir = join(homedir(), \".codex\");\n tools.push({\n name: \"codex\",\n displayName: \"Codex CLI\",\n detected: isCommandAvailable(\"codex\") || existsSync(codexDir),\n });\n\n return tools;\n}\n\n/**\n * Configure MCP for a specific tool.\n */\nexport async function configureTool(\n tool: ToolName,\n projectDir: string = process.cwd(),\n): Promise<{ success: boolean; message: string }> {\n const bridge = resolveMcpBridge(projectDir);\n const mcpUrl = `${getServerUrl()}/api/mcp`;\n\n switch (tool) {\n case \"claude\":\n return configureClaudeCode(bridge);\n case \"opencode\":\n return configureOpenCode(join(projectDir, \"opencode.json\"), bridge);\n case \"cursor\":\n return configureMcpServersJson(\"Cursor\", join(projectDir, \".cursor\", \"mcp.json\"), bridge);\n case \"windsurf\":\n return configureMcpServersJson(\"Windsurf\", join(projectDir, \".windsurf\", \"mcp.json\"), bridge);\n case \"codex\":\n return configureCodex(projectDir, bridge);\n default:\n return { success: false, message: `Unknown tool: ${tool}` };\n }\n}\n\n/**\n * Resolves the best way to run the Orkestrate MCP bridge.\n * Returns { command: string, args: string[] }\n */\nfunction resolveMcpBridge(projectDir: string): { command: string, args: string[] } {\n const isWindows = process.platform === \"win32\";\n const nodePath = getNodePath();\n\n // 1. Check if we're in the Agentalk source repo (dev mode)\n const devMcpEntry = join(projectDir, \"dist\", \"mcp-entry.js\");\n const pkgJsonPath = join(projectDir, \"package.json\");\n \n if (existsSync(devMcpEntry) && existsSync(pkgJsonPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, \"utf-8\"));\n if (pkg.name === \"orkestrate\") {\n return {\n command: nodePath,\n args: [devMcpEntry.replace(/\\\\/g, \"/\")]\n };\n }\n } catch { /* ignore */ }\n }\n\n // 2. Check for global installation (bun/npm)\n const home = homedir();\n const globalMcpEntry = join(home, \".bun\", \"install\", \"global\", \"node_modules\", \"orkestrate\", \"dist\", \"mcp-entry.js\");\n if (existsSync(globalMcpEntry)) {\n return {\n command: nodePath,\n args: [globalMcpEntry.replace(/\\\\/g, \"/\")]\n };\n }\n\n // 3. Last fallback: use the global command\n return {\n command: isWindows ? \"orkestrate.cmd\" : \"orkestrate\",\n args: [\"mcp\"]\n };\n}\n\nfunction getNodePath(): string {\n try {\n const isWindows = process.platform === \"win32\";\n const cmd = isWindows ? \"where node\" : \"which node\";\n const result = execSync(cmd, { stdio: \"pipe\" }).toString().trim().split(\"\\n\")[0].trim();\n return result.replace(/\\\\/g, \"/\");\n } catch {\n return \"node\";\n }\n}\n\n// ──────────────────────────────────────────────\n// Tool Specific Configs (All use Stdio Proxy now)\n// ──────────────────────────────────────────────\n\nfunction configureClaudeCode(bridge: { command: string, args: string[] }): { success: boolean; message: string } {\n if (!isCommandAvailable(\"claude\")) return { success: false, message: \"Claude Code CLI not found.\" };\n\n try {\n const bridgeCmd = `\"${bridge.command}\" ${bridge.args.map(a => `\"${a}\"`).join(\" \")}`;\n execSync(\n `claude mcp add --transport stdio --scope project Orkestrate ${bridgeCmd}`,\n { stdio: \"pipe\", encoding: \"utf-8\" },\n );\n return { success: true, message: \"MCP added to Claude Code.\" };\n } catch (err) {\n return { success: false, message: `Claude config failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n}\n\nfunction configureOpenCode(configPath: string, bridge: { command: string, args: string[] }): { success: boolean; message: string } {\n try {\n let config = existsSync(configPath) ? JSON.parse(readFileSync(configPath, \"utf-8\")) : {};\n if (!config.mcp || typeof config.mcp !== \"object\") config.mcp = {};\n\n config.mcp[\"Orkestrate\"] = {\n type: \"local\",\n command: [bridge.command, ...bridge.args],\n enabled: true\n };\n \n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n return { success: true, message: `Configured OpenCode at ${configPath}` };\n } catch (err) {\n return { success: false, message: `OpenCode config failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n}\n\nfunction configureMcpServersJson(displayName: string, configPath: string, bridge: { command: string, args: string[] }): { success: boolean; message: string } {\n try {\n const dir = join(configPath, \"..\");\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n\n let config = existsSync(configPath) ? JSON.parse(readFileSync(configPath, \"utf-8\")) : {};\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") config.mcpServers = {};\n\n config.mcpServers[\"Orkestrate\"] = {\n command: bridge.command,\n args: bridge.args\n };\n \n writeFileSync(configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n return { success: true, message: `Configured ${displayName} at ${configPath}` };\n } catch (err) {\n return { success: false, message: `${displayName} config failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n}\n\nfunction configureCodex(projectDir: string, bridge: { command: string, args: string[] }): { success: boolean; message: string } {\n const home = homedir();\n const codexDir = join(home, \".codex\");\n const configPath = join(codexDir, \"config.toml\");\n\n try {\n if (!existsSync(codexDir)) mkdirSync(codexDir, { recursive: true });\n\n let content = existsSync(configPath) ? readFileSync(configPath, \"utf-8\") : \"[mcp_servers]\\n\";\n const proxySection = `[mcp_servers.Orkestrate]\\ncommand = \"${bridge.command}\"\\nargs = [${bridge.args.map(a => `\"${a}\"`).join(\", \")}]\\n`;\n\n const sectionRegex = /\\[mcp_servers\\.Orkestrate\\]\\s*\\n(?:(?!\\[)[^\\n]*\\n?)*/;\n if (sectionRegex.test(content)) {\n content = content.replace(sectionRegex, proxySection);\n } else {\n const mcpServersIdx = content.indexOf(\"[mcp_servers]\");\n if (mcpServersIdx !== -1) {\n const lineEnd = content.indexOf(\"\\n\", mcpServersIdx);\n const insertPos = lineEnd !== -1 ? lineEnd + 1 : content.length;\n content = content.slice(0, insertPos) + \"\\n\" + proxySection + content.slice(insertPos);\n } else {\n content = content.trimEnd() + \"\\n\\n[mcp_servers]\\n\\n\" + proxySection;\n }\n }\n\n writeFileSync(configPath, content, \"utf-8\");\n return { success: true, message: `Configured Codex.` };\n } catch (err) {\n return { success: false, message: `Codex config failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n}\n\nfunction isCommandAvailable(command: string): boolean {\n try {\n const isWindows = process.platform === \"win32\";\n const checkCmd = isWindows ? `where ${command}` : `which ${command}`;\n execSync(checkCmd, { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function getToolNames(): ToolName[] {\n return [\"claude\", \"opencode\", \"cursor\", \"windsurf\", \"codex\"];\n}\n","/**\n * orkestrate connect <tool>\n *\n * Auto-configure MCP endpoint for a specific AI coding tool.\n */\n\nimport { getCredentials } from \"../lib/config.js\";\nimport {\n configureTool,\n detectTools,\n getToolNames,\n type ToolName,\n} from \"../lib/detect.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function connectCommand(toolName?: string): Promise<void> {\n // Require authentication\n const creds = getCredentials();\n if (!creds?.accessToken) {\n ui.error(\"Not authenticated. Run `orkestrate login` first.\");\n process.exit(1);\n }\n\n const validTools = getToolNames();\n\n // If no tool specified, detect and list available tools\n if (!toolName) {\n ui.header(\"Detected Tools\");\n\n const detected = detectTools();\n const found = detected.filter((t) => t.detected);\n\n if (found.length === 0) {\n ui.dim(\"No supported AI coding tools detected in this environment.\");\n ui.blank();\n ui.info(\"Supported tools:\");\n for (const name of validTools) {\n ui.line(` • ${name}`);\n }\n ui.blank();\n ui.info(\"Usage: orkestrate connect <tool>\");\n return;\n }\n\n for (const tool of detected) {\n if (tool.detected) {\n ui.success(`${tool.displayName} — detected`);\n } else {\n ui.dim(`${tool.displayName} — not found`);\n }\n }\n\n ui.blank();\n ui.info(\"Run `orkestrate connect <tool>` to configure. Example:\");\n ui.line(` orkestrate connect ${found[0].name}`);\n return;\n }\n\n // Validate tool name\n const tool = toolName.toLowerCase() as ToolName;\n if (!validTools.includes(tool)) {\n ui.error(`Unknown tool: ${toolName}`);\n ui.blank();\n ui.info(\"Supported tools:\");\n for (const name of validTools) {\n ui.line(` • ${name}`);\n }\n process.exit(1);\n }\n\n // Configure\n ui.info(`Configuring MCP for ${toolName}...`);\n\n const result = await configureTool(tool);\n\n if (result.success) {\n ui.success(result.message);\n ui.blank();\n ui.info(\"Your AI tool can now connect to Orkestrate.\");\n ui.dim(\"Restart your tool if it's currently running.\");\n } else {\n ui.error(result.message);\n process.exit(1);\n }\n}\n","/**\n * orkestrate status\n *\n * Display current team coordination state in the terminal.\n */\n\nimport { getCredentials, getActiveWorkspace } from \"../lib/config.js\";\nimport { getTeamStatus, listWorkspaces, checkHealth } from \"../lib/api.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function statusCommand(): Promise<void> {\n const creds = getCredentials();\n if (!creds?.accessToken) {\n ui.error(\"Not authenticated. Run `orkestrate login` first.\");\n process.exit(1);\n }\n\n // Check server health\n const healthy = await checkHealth();\n if (!healthy) {\n ui.error(\"Cannot reach Orkestrate server. Check your connection.\");\n process.exit(1);\n }\n\n const workspace = getActiveWorkspace();\n\n ui.header(\"Orkestrate Status\");\n\n // Show workspace info\n if (workspace.name) {\n ui.kv(\"Workspace\", workspace.name);\n }\n if (workspace.id) {\n ui.kv(\"ID\", workspace.id);\n }\n ui.blank();\n\n try {\n const { agents, stateHash } = await getTeamStatus();\n\n if (agents.length === 0) {\n ui.dim(\"No active agents in this workspace.\");\n ui.blank();\n ui.info(\"Connect an agent with `orkestrate connect <tool>` to get started.\");\n return;\n }\n\n // Build table\n const rows = agents.map((agent) => [\n agent.agentId || agent.scopedAgentId,\n agent.toolName || \"—\",\n agent.status,\n truncate(agent.objective, 35),\n ]);\n\n ui.table(\n [\"Agent\", \"Tool\", \"Status\", \"Objective\"],\n rows,\n );\n\n // Show claimed paths summary\n const agentsWithClaims = agents.filter(\n (a) => a.claimedPaths && a.claimedPaths.length > 0,\n );\n if (agentsWithClaims.length > 0) {\n ui.blank();\n ui.line(pc_bold(\"Active Scope Claims:\"));\n for (const agent of agentsWithClaims) {\n ui.line(` ${agent.agentId}: ${agent.claimedPaths.join(\", \")}`);\n }\n }\n\n ui.blank();\n ui.dim(`State hash: ${stateHash}`);\n ui.dim(`${agents.length} agent(s) connected`);\n } catch (err) {\n ui.error(\n `Failed to fetch status: ${err instanceof Error ? err.message : String(err)}`,\n );\n process.exit(1);\n }\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1) + \"…\";\n}\n\n// Inline bold since we don't want to import picocolors at top level just for one use\nfunction pc_bold(s: string): string {\n return `\\x1b[1m${s}\\x1b[22m`;\n}\n","/**\n * orkestrate workspace [list|switch|create]\n *\n * Manage workspaces from the CLI.\n */\n\nimport { getCredentials, setActiveWorkspace, getActiveWorkspace } from \"../lib/config.js\";\nimport {\n listWorkspaces,\n switchWorkspace as apiSwitchWorkspace,\n createWorkspace as apiCreateWorkspace,\n} from \"../lib/api.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function workspaceCommand(\n action?: string,\n nameOrId?: string,\n extra?: string,\n): Promise<void> {\n const creds = getCredentials();\n if (!creds?.accessToken) {\n ui.error(\"Not authenticated. Run `orkestrate login` first.\");\n process.exit(1);\n }\n\n const subcommand = (action || \"list\").toLowerCase();\n\n switch (subcommand) {\n case \"list\":\n case \"ls\":\n return workspaceList();\n\n case \"switch\":\n case \"use\":\n if (!nameOrId) {\n ui.error(\"Usage: orkestrate workspace switch <workspace-id-or-name>\");\n process.exit(1);\n }\n return workspaceSwitch(nameOrId);\n\n case \"create\":\n case \"new\":\n if (!nameOrId) {\n ui.error(\"Usage: orkestrate workspace create <name> <repo-url> [branch]\");\n process.exit(1);\n }\n return workspaceCreate(nameOrId, extra);\n\n default:\n ui.error(`Unknown subcommand: ${action}`);\n ui.blank();\n ui.info(\"Available subcommands:\");\n ui.line(\" list — Show all workspaces\");\n ui.line(\" switch — Switch active workspace\");\n ui.line(\" create — Create a new workspace\");\n process.exit(1);\n }\n}\n\nasync function workspaceList(): Promise<void> {\n ui.header(\"Workspaces\");\n\n try {\n const workspaces = await listWorkspaces();\n const active = getActiveWorkspace();\n\n if (workspaces.length === 0) {\n ui.dim(\"No workspaces found.\");\n ui.info(\"Create one at orkestrate.space or run `orkestrate workspace create`.\");\n return;\n }\n\n for (const ws of workspaces) {\n const isActive = ws.id === active.id || ws.isActive;\n const marker = isActive ? \" ← active\" : \"\";\n const name = ws.name || \"Unnamed\";\n\n if (isActive) {\n ui.success(`${name} (${ws.id})${marker}`);\n } else {\n ui.line(` ${name} (${ws.id})`);\n }\n\n if (ws.repoUrl) {\n ui.dim(` repo: ${ws.repoUrl}`);\n }\n }\n\n ui.blank();\n ui.dim(`${workspaces.length} workspace(s)`);\n } catch (err) {\n ui.error(`Failed to list workspaces: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n\nasync function workspaceSwitch(nameOrId: string): Promise<void> {\n try {\n const workspaces = await listWorkspaces();\n\n // Find by exact ID or name match\n const target = workspaces.find(\n (ws) =>\n ws.id === nameOrId ||\n ws.name.toLowerCase() === nameOrId.toLowerCase(),\n );\n\n if (!target) {\n ui.error(`Workspace not found: ${nameOrId}`);\n ui.blank();\n ui.info(\"Available workspaces:\");\n for (const ws of workspaces) {\n ui.line(` ${ws.name} (${ws.id})`);\n }\n process.exit(1);\n }\n\n await apiSwitchWorkspace(target.id);\n setActiveWorkspace(target.id, target.name);\n ui.success(`Switched to workspace: ${target.name}`);\n } catch (err) {\n ui.error(`Failed to switch workspace: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n\nasync function workspaceCreate(name: string, repoUrl?: string): Promise<void> {\n if (!repoUrl) {\n ui.error(\"Repository URL is required.\");\n ui.info(\"Usage: orkestrate workspace create <name> <repo-url>\");\n process.exit(1);\n }\n\n try {\n const workspace = await apiCreateWorkspace(name, repoUrl, \"main\");\n setActiveWorkspace(workspace.id, workspace.name || name);\n ui.success(`Created workspace: ${workspace.name || name}`);\n ui.kv(\"ID\", workspace.id);\n ui.kv(\"Repo\", repoUrl);\n } catch (err) {\n ui.error(`Failed to create workspace: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n}\n","/**\n * Orkestrate CLI — Git Context Detection\n *\n * Reads git metadata from the current working directory.\n */\n\nimport { execSync } from \"node:child_process\";\n\nexport interface GitContext {\n remote: string;\n repoRoot: string;\n branch: string;\n headSha: string;\n dirty: boolean;\n collectedAt: string;\n}\n\nfunction git(cmd: string, cwd: string): string {\n try {\n return execSync(`git ${cmd}`, {\n cwd,\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n } catch {\n return \"\";\n }\n}\n\nexport function detectGitContext(cwd: string = process.cwd()): GitContext | null {\n const repoRoot = git(\"rev-parse --show-toplevel\", cwd);\n if (!repoRoot) return null;\n\n const remote = git(\"remote get-url origin\", cwd);\n const branch = git(\"rev-parse --abbrev-ref HEAD\", cwd);\n const headSha = git(\"rev-parse HEAD\", cwd);\n const status = git(\"status --porcelain\", cwd);\n\n return {\n remote: remote || \"\",\n repoRoot,\n branch: branch || \"unknown\",\n headSha: headSha || \"\",\n dirty: status.length > 0,\n collectedAt: new Date().toISOString(),\n };\n}\n","/**\n * orkestrate init\n *\n * Initialize Orkestrate in the current project directory.\n * Detects git context and binds to the matching workspace.\n */\n\nimport { existsSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getCredentials, getActiveWorkspace, setActiveWorkspace } from \"../lib/config.js\";\nimport { detectGitContext } from \"../lib/git.js\";\nimport { listWorkspaces } from \"../lib/api.js\";\nimport { detectTools } from \"../lib/detect.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function initCommand(): Promise<void> {\n const creds = getCredentials();\n if (!creds?.accessToken) {\n ui.error(\"Not authenticated. Run `orkestrate login` first.\");\n process.exit(1);\n }\n\n const cwd = process.cwd();\n\n ui.header(\"Initializing Orkestrate\");\n\n // Step 1: Detect git context\n const git = detectGitContext(cwd);\n if (git) {\n ui.success(`Git repository detected`);\n ui.kv(\"Remote\", git.remote || \"(no remote)\");\n ui.kv(\"Branch\", git.branch);\n ui.kv(\"HEAD\", git.headSha.slice(0, 8));\n ui.kv(\"Dirty\", git.dirty ? \"yes\" : \"clean\");\n } else {\n ui.warn(\"No git repository detected in current directory.\");\n ui.dim(\"Orkestrate works best with a git repository.\");\n }\n\n ui.blank();\n\n // Step 2: Match to workspace\n try {\n const workspaces = await listWorkspaces();\n let matched = false;\n\n if (git?.remote && workspaces.length > 0) {\n // Try to match by repo URL\n const normalizedRemote = normalizeGitUrl(git.remote);\n const match = workspaces.find((ws) => {\n if (!ws.repoUrl) return false;\n return normalizeGitUrl(ws.repoUrl) === normalizedRemote;\n });\n\n if (match) {\n setActiveWorkspace(match.id, match.name);\n ui.success(`Matched to workspace: ${match.name}`);\n ui.kv(\"Workspace ID\", match.id);\n matched = true;\n }\n }\n\n if (!matched) {\n const active = getActiveWorkspace();\n if (active.id) {\n ui.info(`Using current workspace: ${active.name || active.id}`);\n } else if (workspaces.length > 0) {\n const first = workspaces[0];\n setActiveWorkspace(first.id, first.name);\n ui.info(`Using workspace: ${first.name}`);\n } else {\n ui.warn(\"No workspaces available. Create one at orkestrate.space\");\n }\n }\n } catch {\n ui.dim(\"Could not fetch workspaces. Skipping workspace matching.\");\n }\n\n ui.blank();\n\n // Step 3: Detect available tools\n const tools = detectTools(cwd);\n const found = tools.filter((t) => t.detected);\n\n if (found.length > 0) {\n ui.info(\"Detected AI tools:\");\n for (const tool of found) {\n ui.line(` • ${tool.displayName}`);\n }\n ui.blank();\n ui.info(`Run \\`orkestrate connect ${found[0].name}\\` to configure MCP.`);\n } else {\n ui.dim(\"No AI coding tools detected. Install one and run `orkestrate connect <tool>`.\");\n }\n\n // Step 4: Write .orkestrate.json (project marker)\n const configFile = join(cwd, \".orkestrate.json\");\n if (!existsSync(configFile)) {\n const activeWs = getActiveWorkspace();\n const projectConfig = {\n $schema: \"https://orkestrate.space/schema/project.json\",\n workspaceId: activeWs.id || null,\n server: \"https://orkestrate.space\",\n initialized: new Date().toISOString(),\n };\n\n writeFileSync(configFile, JSON.stringify(projectConfig, null, 2) + \"\\n\", \"utf-8\");\n ui.blank();\n ui.success(`Created .orkestrate.json`);\n ui.dim(\"Add this file to your repository so collaborators can auto-detect the workspace.\");\n } else {\n ui.dim(\".orkestrate.json already exists — skipping.\");\n }\n\n ui.blank();\n}\n\n/**\n * Normalize a git remote URL for comparison.\n * Handles https://, git@, and .git suffix variations.\n */\nfunction normalizeGitUrl(url: string): string {\n let normalized = url.trim().toLowerCase();\n\n // Remove trailing .git\n normalized = normalized.replace(/\\.git$/, \"\");\n\n // Convert SSH to HTTPS format for comparison\n // git@github.com:user/repo → github.com/user/repo\n const sshMatch = normalized.match(/^git@([^:]+):(.+)$/);\n if (sshMatch) {\n normalized = `${sshMatch[1]}/${sshMatch[2]}`;\n }\n\n // Remove protocol\n normalized = normalized.replace(/^https?:\\/\\//, \"\");\n normalized = normalized.replace(/^ssh:\\/\\//, \"\");\n\n // Remove trailing slash\n normalized = normalized.replace(/\\/$/, \"\");\n\n return normalized;\n}\n","\nimport { getServerUrl } from \"../lib/config.js\";\nimport { getValidToken } from \"../lib/auth.js\";\n\n/**\n * Orkestrate MCP Proxy\n * \n * Acts as a local MCP server (stdio) that forwards all requests to the \n * Orkestrate cloud MCP endpoint (HTTP), injecting the local auth token.\n */\nexport async function mcpCommand() {\n try {\n const serverUrl = getServerUrl();\n const mcpUrl = `${serverUrl}/api/mcp`;\n\n process.stdin.setEncoding(\"utf-8\");\n let buffer = \"\";\n \n process.stdin.on(\"data\", async (chunk) => {\n const rawChunk = String(chunk);\n buffer += rawChunk;\n \n let lineEndIndex;\n while ((lineEndIndex = buffer.indexOf(\"\\n\")) >= 0) {\n let line = buffer.slice(0, lineEndIndex).trim();\n buffer = buffer.slice(lineEndIndex + 1);\n \n if (!line) continue;\n \n // Handle back-to-back JSON objects missing newlines\n if (line.includes(\"}{\")) {\n const parts = line.split(\"}{\");\n processLine(parts[0] + \"}\", mcpUrl);\n for (let i = 1; i < parts.length - 1; i++) {\n processLine(\"{\" + parts[i] + \"}\", mcpUrl);\n }\n processLine(\"{\" + parts[parts.length - 1], mcpUrl);\n } else {\n processLine(line, mcpUrl);\n }\n }\n });\n\n process.stdin.on(\"end\", () => {\n process.exit(0);\n });\n\n // Stay alive\n await new Promise(() => {});\n } catch (err) {\n process.stderr.write(`[Orkestrate] Fatal error: ${err}\\n`);\n process.exit(1);\n }\n}\n\nasync function processLine(line: string, mcpUrl: string) {\n let payload: any;\n try {\n payload = JSON.parse(line);\n } catch { return; }\n\n const isNotification = !Object.prototype.hasOwnProperty.call(payload, \"id\");\n const requestId = payload.id;\n\n try {\n const token = await getValidToken();\n \n if (!token) {\n throw new Error(\"NOT_LOGGED_IN: Please run 'orkestrate login' to authenticate.\");\n }\n\n const res = await fetch(mcpUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${token}`,\n \"User-Agent\": \"Orkestrate-CLI-Proxy\"\n },\n body: line\n });\n\n // Notifications MUST NOT be responded to on stdout\n if (isNotification) return;\n\n const responseBody = await res.text();\n if (responseBody) {\n process.stdout.write(responseBody + \"\\n\");\n }\n } catch (err) {\n if (isNotification) return;\n\n process.stdout.write(JSON.stringify({\n jsonrpc: \"2.0\",\n id: requestId,\n error: {\n code: -32603,\n message: err instanceof Error ? err.message : String(err)\n }\n }) + \"\\n\");\n }\n}\n","/**\n * orkestrate whoami\n *\n * Show current authentication and configuration state.\n */\n\nimport { getCredentials, getActiveWorkspace, getServerUrl, getConfigPath } from \"../lib/config.js\";\nimport { checkHealth } from \"../lib/api.js\";\nimport { ui } from \"../lib/ui.js\";\n\nexport async function whoamiCommand(): Promise<void> {\n ui.header(\"Orkestrate Configuration\");\n\n const creds = getCredentials();\n const workspace = getActiveWorkspace();\n const serverUrl = getServerUrl();\n\n ui.kv(\"Server\", serverUrl);\n ui.kv(\"Config\", getConfigPath());\n ui.blank();\n\n if (creds?.accessToken) {\n ui.success(\"Authenticated\");\n ui.kv(\"Client ID\", creds.clientId);\n if (creds.userId) {\n ui.kv(\"User ID\", creds.userId);\n }\n\n const expiresIn = creds.expiresAt - Math.floor(Date.now() / 1000);\n if (expiresIn > 0) {\n const minutes = Math.floor(expiresIn / 60);\n ui.kv(\"Token expires\", `in ${minutes} minute(s)`);\n } else {\n ui.warn(\"Access token expired — will auto-refresh on next API call.\");\n }\n } else {\n ui.error(\"Not authenticated. Run `orkestrate login`.\");\n }\n\n ui.blank();\n\n if (workspace.id) {\n ui.kv(\"Active workspace\", workspace.name || \"—\");\n ui.kv(\"Workspace ID\", workspace.id);\n } else {\n ui.dim(\"No active workspace set.\");\n }\n\n ui.blank();\n\n // Server health check\n ui.info(\"Checking server health...\");\n const healthy = await checkHealth();\n if (healthy) {\n ui.success(\"Server is reachable\");\n } else {\n ui.error(\"Server is unreachable\");\n }\n}\n","/**\n * Orkestrate CLI\n *\n * The coordination layer for autonomous AI coding agents.\n * https://orkestrate.space\n */\n\nimport { Command } from \"commander\";\nimport { ui } from \"./lib/ui.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"orkestrate\")\n .description(\"The coordination layer for autonomous AI coding agents\")\n .version(\"0.1.0\")\n .hook(\"preAction\", () => {\n // Show banner on all commands\n });\n\n// --- login ---\nprogram\n .command(\"login\")\n .description(\"Authenticate with Orkestrate via browser OAuth\")\n .action(async () => {\n const { loginCommand } = await import(\"./commands/login.js\");\n await loginCommand();\n });\n\n// --- logout ---\nprogram\n .command(\"logout\")\n .description(\"Clear stored credentials\")\n .action(async () => {\n const { logoutCommand } = await import(\"./commands/logout.js\");\n logoutCommand();\n });\n\n// --- connect ---\nprogram\n .command(\"connect [tool]\")\n .description(\"Configure MCP endpoint for an AI coding tool (claude, opencode, cursor, windsurf, codex)\")\n .action(async (tool?: string) => {\n const { connectCommand } = await import(\"./commands/connect.js\");\n await connectCommand(tool);\n });\n\n// --- status ---\nprogram\n .command(\"status\")\n .alias(\"s\")\n .description(\"Show current team coordination state\")\n .action(async () => {\n const { statusCommand } = await import(\"./commands/status.js\");\n await statusCommand();\n });\n\n// --- workspace ---\nprogram\n .command(\"workspace [action] [name] [extra]\")\n .alias(\"ws\")\n .description(\"Manage workspaces (list, switch, create)\")\n .action(async (action?: string, name?: string, extra?: string) => {\n const { workspaceCommand } = await import(\"./commands/workspace.js\");\n await workspaceCommand(action, name, extra);\n });\n\n// --- init ---\nprogram\n .command(\"init\")\n .description(\"Initialize Orkestrate in the current project\")\n .action(async () => {\n const { initCommand } = await import(\"./commands/init.js\");\n await initCommand();\n });\n\n// --- mcp ---\nprogram\n .command(\"mcp\")\n .description(\"Run as a local MCP server (stdio bridge to Orkestrate Cloud)\")\n .action(async () => {\n try {\n const { mcpCommand } = await import(\"./commands/mcp.js\");\n await mcpCommand();\n } catch (err) {\n process.stderr.write(`[Orkestrate-MCP] ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n });\n\n// --- whoami ---\nprogram\n .command(\"whoami\")\n .description(\"Show current authentication and configuration\")\n .action(async () => {\n const { whoamiCommand } = await import(\"./commands/whoami.js\");\n await whoamiCommand();\n });\n\n// --- Default: show banner + help ---\nprogram.action(() => {\n ui.banner();\n program.help();\n});\n\n// Run\nprogram.parseAsync(process.argv).catch((err) => {\n ui.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"],"mappings":"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","names":["config","tool","execSync","existsSync","writeFileSync","join","git","loginCommand","logoutCommand","connectCommand","statusCommand","workspaceCommand","initCommand","mcpCommand","whoamiCommand"]}
|
package/dist/mcp-entry.js
CHANGED
|
@@ -103,10 +103,19 @@ async function mcpCommand() {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
async function processLine(line, mcpUrl) {
|
|
106
|
+
let payload;
|
|
107
|
+
try {
|
|
108
|
+
payload = JSON.parse(line);
|
|
109
|
+
} catch {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const isNotification = !Object.prototype.hasOwnProperty.call(payload, "id");
|
|
113
|
+
const requestId = payload.id;
|
|
106
114
|
try {
|
|
107
|
-
const payload = JSON.parse(line);
|
|
108
|
-
const isNotification = !Object.prototype.hasOwnProperty.call(payload, "id");
|
|
109
115
|
const token = await getValidToken();
|
|
116
|
+
if (!token) {
|
|
117
|
+
throw new Error("NOT_LOGGED_IN: Please run 'orkestrate login' to authenticate.");
|
|
118
|
+
}
|
|
110
119
|
const res = await fetch(mcpUrl, {
|
|
111
120
|
method: "POST",
|
|
112
121
|
headers: {
|
|
@@ -122,22 +131,15 @@ async function processLine(line, mcpUrl) {
|
|
|
122
131
|
process.stdout.write(responseBody + "\n");
|
|
123
132
|
}
|
|
124
133
|
} catch (err) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
code: -32603,
|
|
133
|
-
message: `Orkestrate Proxy Error: ${err instanceof Error ? err.message : String(err)}`
|
|
134
|
-
}
|
|
135
|
-
}) + "\n");
|
|
134
|
+
if (isNotification) return;
|
|
135
|
+
process.stdout.write(JSON.stringify({
|
|
136
|
+
jsonrpc: "2.0",
|
|
137
|
+
id: requestId,
|
|
138
|
+
error: {
|
|
139
|
+
code: -32603,
|
|
140
|
+
message: err instanceof Error ? err.message : String(err)
|
|
136
141
|
}
|
|
137
|
-
}
|
|
138
|
-
process.stderr.write(`[Orkestrate] Internal error: ${err}
|
|
139
|
-
`);
|
|
140
|
-
}
|
|
142
|
+
}) + "\n");
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
145
|
|
package/dist/mcp-entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/config.ts","../src/lib/auth.ts","../src/commands/mcp.ts","../src/mcp-entry.ts"],"sourcesContent":["/**\n * Orkestrate CLI — Configuration Management\n *\n * Stores credentials and preferences in the user's home directory.\n * Uses the `conf` package for cross-platform config storage.\n */\n\nimport Conf from \"conf\";\n\nexport interface StoredCredentials {\n clientId: string;\n accessToken: string;\n refreshToken: string;\n expiresAt: number; // epoch seconds\n userId: string;\n scope: string;\n}\n\nexport interface CliConfig {\n credentials: StoredCredentials | null;\n activeWorkspaceId: string | null;\n activeWorkspaceName: string | null;\n serverUrl: string;\n}\n\nconst config = new Conf<CliConfig>({\n projectName: \"orkestrate\",\n projectSuffix: \"\",\n defaults: {\n credentials: null,\n activeWorkspaceId: null,\n activeWorkspaceName: null,\n serverUrl: \"https://orkestrate.space\",\n },\n});\n\nexport function getConfig(): CliConfig {\n return {\n credentials: config.get(\"credentials\"),\n activeWorkspaceId: config.get(\"activeWorkspaceId\"),\n activeWorkspaceName: config.get(\"activeWorkspaceName\"),\n serverUrl: config.get(\"serverUrl\"),\n };\n}\n\nexport function getServerUrl(): string {\n return config.get(\"serverUrl\");\n}\n\nexport function setCredentials(creds: StoredCredentials): void {\n config.set(\"credentials\", creds);\n}\n\nexport function getCredentials(): StoredCredentials | null {\n return config.get(\"credentials\");\n}\n\nexport function clearCredentials(): void {\n config.set(\"credentials\", null);\n}\n\nexport function setActiveWorkspace(id: string, name: string): void {\n config.set(\"activeWorkspaceId\", id);\n config.set(\"activeWorkspaceName\", name);\n}\n\nexport function getActiveWorkspace(): { id: string | null; name: string | null } {\n return {\n id: config.get(\"activeWorkspaceId\"),\n name: config.get(\"activeWorkspaceName\"),\n };\n}\n\nexport function setServerUrl(url: string): void {\n config.set(\"serverUrl\", url);\n}\n\nexport function clearAll(): void {\n config.clear();\n}\n\nexport function getConfigPath(): string {\n return config.path;\n}\n","/**\n * Orkestrate CLI — OAuth Authentication\n *\n * Implements the full OAuth 2.0 + PKCE flow:\n * 1. Dynamic client registration\n * 2. Open browser for consent\n * 3. Local HTTP callback server\n * 4. Token exchange\n * 5. Credential storage\n */\n\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport {\n getServerUrl,\n setCredentials,\n getCredentials,\n type StoredCredentials,\n} from \"./config.js\";\n\nfunction randomToken(bytes = 32): string {\n return randomBytes(bytes).toString(\"base64url\");\n}\n\nfunction pkceS256(verifier: string): string {\n return createHash(\"sha256\").update(verifier).digest(\"base64url\");\n}\n\ninterface TokenResponse {\n token_type: string;\n access_token: string;\n expires_in: number;\n refresh_token: string;\n scope: string;\n}\n\n/**\n * Step 1: Register this CLI instance as an OAuth client.\n */\nasync function registerClient(\n serverUrl: string,\n redirectUri: string,\n): Promise<{ clientId: string }> {\n const res = await fetch(`${serverUrl}/api/oauth/register`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_name: \"Orkestrate CLI\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n }),\n });\n\n if (!res.ok) {\n const body = await res.text();\n throw new Error(`Client registration failed (${res.status}): ${body}`);\n }\n\n const data = (await res.json()) as { client_id: string };\n return { clientId: data.client_id };\n}\n\n/**\n * Step 2 & 3: Open browser and wait for the OAuth callback.\n */\nfunction waitForCallback(\n port: number,\n): Promise<{ code: string; state: string }> {\n return new Promise((resolve, reject) => {\n let timeoutHandle: ReturnType<typeof setTimeout>;\n\n function cleanup() {\n clearTimeout(timeoutHandle);\n server.close();\n }\n\n const server = createServer((req: IncomingMessage, res: ServerResponse) => {\n const url = new URL(req.url || \"/\", `http://localhost:${port}`);\n\n if (url.pathname !== \"/callback\") {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n const error = url.searchParams.get(\"error\");\n const state = url.searchParams.get(\"state\") || \"\";\n\n if (error) {\n const description = url.searchParams.get(\"error_description\") || error;\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(buildErrorPage(description));\n cleanup();\n reject(new Error(`OAuth error: ${description}`));\n return;\n }\n\n if (!code) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(buildErrorPage(\"No authorization code received.\"));\n cleanup();\n reject(new Error(\"No authorization code received\"));\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(buildSuccessPage());\n cleanup();\n resolve({ code, state });\n });\n\n server.listen(port, \"127.0.0.1\", () => {\n // Server ready\n });\n\n server.on(\"error\", (err: Error) => {\n clearTimeout(timeoutHandle);\n reject(new Error(`Could not start local server: ${err.message}`));\n });\n\n // Timeout after 5 minutes — unref so it doesn't block process exit\n timeoutHandle = setTimeout(() => {\n server.close();\n reject(new Error(\"Authentication timed out (5 minutes). Please try again.\"));\n }, 5 * 60 * 1000);\n timeoutHandle.unref();\n });\n}\n\n/**\n * Step 4: Exchange authorization code for tokens.\n */\nasync function exchangeCodeForTokens(\n serverUrl: string,\n code: string,\n clientId: string,\n codeVerifier: string,\n redirectUri: string,\n): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n code_verifier: codeVerifier,\n client_id: clientId,\n redirect_uri: redirectUri,\n });\n\n const res = await fetch(`${serverUrl}/api/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Token exchange failed (${res.status}): ${text}`);\n }\n\n return (await res.json()) as TokenResponse;\n}\n\n/**\n * Refresh an expired access token.\n */\nexport async function refreshAccessToken(): Promise<StoredCredentials | null> {\n const creds = getCredentials();\n if (!creds?.refreshToken) return null;\n\n const serverUrl = getServerUrl();\n const body = new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: creds.refreshToken,\n client_id: creds.clientId,\n });\n\n const res = await fetch(`${serverUrl}/api/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!res.ok) return null;\n\n const tokens = (await res.json()) as TokenResponse;\n const now = Math.floor(Date.now() / 1000);\n\n const newCreds: StoredCredentials = {\n clientId: creds.clientId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: now + tokens.expires_in,\n userId: creds.userId,\n scope: tokens.scope,\n };\n\n setCredentials(newCreds);\n return newCreds;\n}\n\n/**\n * Get a valid access token, refreshing if needed.\n */\nexport async function getValidToken(): Promise<string | null> {\n const creds = getCredentials();\n if (!creds) return null;\n\n const now = Math.floor(Date.now() / 1000);\n\n // Refresh if expired or expiring within 60 seconds\n if (creds.expiresAt <= now + 60) {\n const refreshed = await refreshAccessToken();\n return refreshed?.accessToken || null;\n }\n\n return creds.accessToken;\n}\n\n/**\n * Run the full OAuth login flow.\n */\nexport async function performLogin(): Promise<{\n clientId: string;\n userId: string;\n accessToken: string;\n}> {\n const serverUrl = getServerUrl();\n const port = 19274; // \"ork\" on a phone keypad, roughly\n const redirectUri = `http://127.0.0.1:${port}/callback`;\n\n // Step 1: Register client\n const { clientId } = await registerClient(serverUrl, redirectUri);\n\n // Step 2: Prepare PKCE\n const codeVerifier = randomToken(48);\n const codeChallenge = pkceS256(codeVerifier);\n const state = randomToken(16);\n\n // Step 3: Build authorization URL\n const authUrl = new URL(`${serverUrl}/api/oauth/authorize`);\n authUrl.searchParams.set(\"response_type\", \"code\");\n authUrl.searchParams.set(\"client_id\", clientId);\n authUrl.searchParams.set(\"redirect_uri\", redirectUri);\n authUrl.searchParams.set(\"code_challenge\", codeChallenge);\n authUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authUrl.searchParams.set(\"scope\", \"mcp:read mcp:write\");\n authUrl.searchParams.set(\"state\", state);\n\n // Step 4: Start callback server + open browser\n const callbackPromise = waitForCallback(port);\n\n // Dynamic import to handle ESM-only `open` package\n const { default: openBrowser } = await import(\"open\");\n await openBrowser(authUrl.toString());\n\n // Step 5: Wait for callback\n const { code, state: returnedState } = await callbackPromise;\n\n if (returnedState !== state) {\n throw new Error(\"OAuth state mismatch — possible CSRF attack. Aborting.\");\n }\n\n // Step 6: Exchange code for tokens\n const tokens = await exchangeCodeForTokens(\n serverUrl,\n code,\n clientId,\n codeVerifier,\n redirectUri,\n );\n\n const now = Math.floor(Date.now() / 1000);\n\n // We don't get user_id from the token response directly.\n // We'll extract it from the MCP endpoint or store a placeholder.\n // For now, use clientId as a proxy until first API call resolves it.\n const credentials: StoredCredentials = {\n clientId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: now + tokens.expires_in,\n userId: \"\", // Will be resolved on first API call\n scope: tokens.scope,\n };\n\n setCredentials(credentials);\n\n return {\n clientId,\n userId: credentials.userId,\n accessToken: tokens.access_token,\n };\n}\n\n// --- HTML pages for the local callback server ---\n\nfunction buildSuccessPage(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Orkestrate — Authenticated</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n text-align: center;\n padding: 3rem;\n border: 1px solid #262626;\n border-radius: 12px;\n background: #111;\n max-width: 420px;\n }\n .icon { font-size: 3rem; margin-bottom: 1rem; }\n h1 { font-size: 1.5rem; margin-bottom: 0.5rem; color: #fff; }\n p { color: #a3a3a3; line-height: 1.6; }\n .hint { margin-top: 1.5rem; font-size: 0.85rem; color: #525252; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">✓</div>\n <h1>Authenticated</h1>\n <p>You're now logged in to Orkestrate. You can close this tab and return to your terminal.</p>\n <p class=\"hint\">This window will close automatically.</p>\n </div>\n <script>setTimeout(() => window.close(), 3000);</script>\n</body>\n</html>`;\n}\n\nfunction buildErrorPage(message: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Orkestrate — Error</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n text-align: center;\n padding: 3rem;\n border: 1px solid #371717;\n border-radius: 12px;\n background: #1a0a0a;\n max-width: 420px;\n }\n .icon { font-size: 3rem; margin-bottom: 1rem; }\n h1 { font-size: 1.5rem; margin-bottom: 0.5rem; color: #fca5a5; }\n p { color: #a3a3a3; line-height: 1.6; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">✗</div>\n <h1>Authentication Failed</h1>\n <p>${message}</p>\n </div>\n</body>\n</html>`;\n}\n","\nimport { getServerUrl } from \"../lib/config.js\";\nimport { getValidToken } from \"../lib/auth.js\";\n\n/**\n * Orkestrate MCP Proxy\n * \n * Acts as a local MCP server (stdio) that forwards all requests to the \n * Orkestrate cloud MCP endpoint (HTTP), injecting the local auth token.\n */\nexport async function mcpCommand() {\n try {\n const serverUrl = getServerUrl();\n const mcpUrl = `${serverUrl}/api/mcp`;\n\n process.stdin.setEncoding(\"utf-8\");\n let buffer = \"\";\n \n process.stdin.on(\"data\", async (chunk) => {\n const rawChunk = String(chunk);\n buffer += rawChunk;\n \n let lineEndIndex;\n while ((lineEndIndex = buffer.indexOf(\"\\n\")) >= 0) {\n let line = buffer.slice(0, lineEndIndex).trim();\n buffer = buffer.slice(lineEndIndex + 1);\n \n if (!line) continue;\n \n // Handle back-to-back JSON objects missing newlines\n if (line.includes(\"}{\")) {\n const parts = line.split(\"}{\");\n processLine(parts[0] + \"}\", mcpUrl);\n for (let i = 1; i < parts.length - 1; i++) {\n processLine(\"{\" + parts[i] + \"}\", mcpUrl);\n }\n processLine(\"{\" + parts[parts.length - 1], mcpUrl);\n } else {\n processLine(line, mcpUrl);\n }\n }\n });\n\n process.stdin.on(\"end\", () => {\n process.exit(0);\n });\n\n // Stay alive\n await new Promise(() => {});\n } catch (err) {\n process.stderr.write(`[Orkestrate] Fatal error: ${err}\\n`);\n process.exit(1);\n }\n}\n\nasync function processLine(line: string, mcpUrl: string) {\n try {\n const payload = JSON.parse(line);\n const isNotification = !Object.prototype.hasOwnProperty.call(payload, \"id\");\n \n const token = await getValidToken();\n const res = await fetch(mcpUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${token}`,\n \"User-Agent\": \"Orkestrate-CLI-Proxy\"\n },\n body: line\n });\n\n // Notifications MUST NOT be responded to on stdout\n if (isNotification) return;\n\n const responseBody = await res.text();\n if (responseBody) {\n process.stdout.write(responseBody + \"\\n\");\n }\n } catch (err) {\n try {\n const payload = JSON.parse(line);\n if (payload.id !== undefined) {\n process.stdout.write(JSON.stringify({\n jsonrpc: \"2.0\",\n id: payload.id,\n error: {\n code: -32603,\n message: `Orkestrate Proxy Error: ${err instanceof Error ? err.message : String(err)}`\n }\n }) + \"\\n\");\n }\n } catch { \n process.stderr.write(`[Orkestrate] Internal error: ${err}\\n`);\n }\n }\n}\n","\nimport { mcpCommand } from \"./commands/mcp.js\";\n\n// Standalone MCP bridge entry point. \n// DO NOT PRINT TO STDOUT ANY NON-JSON DATA.\nmcpCommand().catch(err => {\n process.stderr.write(`[Orkestrate-MCP] Fatal: ${err}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/config.ts","../src/lib/auth.ts","../src/commands/mcp.ts","../src/mcp-entry.ts"],"sourcesContent":["/**\n * Orkestrate CLI — Configuration Management\n *\n * Stores credentials and preferences in the user's home directory.\n * Uses the `conf` package for cross-platform config storage.\n */\n\nimport Conf from \"conf\";\n\nexport interface StoredCredentials {\n clientId: string;\n accessToken: string;\n refreshToken: string;\n expiresAt: number; // epoch seconds\n userId: string;\n scope: string;\n}\n\nexport interface CliConfig {\n credentials: StoredCredentials | null;\n activeWorkspaceId: string | null;\n activeWorkspaceName: string | null;\n serverUrl: string;\n}\n\nconst config = new Conf<CliConfig>({\n projectName: \"orkestrate\",\n projectSuffix: \"\",\n defaults: {\n credentials: null,\n activeWorkspaceId: null,\n activeWorkspaceName: null,\n serverUrl: \"https://orkestrate.space\",\n },\n});\n\nexport function getConfig(): CliConfig {\n return {\n credentials: config.get(\"credentials\"),\n activeWorkspaceId: config.get(\"activeWorkspaceId\"),\n activeWorkspaceName: config.get(\"activeWorkspaceName\"),\n serverUrl: config.get(\"serverUrl\"),\n };\n}\n\nexport function getServerUrl(): string {\n return config.get(\"serverUrl\");\n}\n\nexport function setCredentials(creds: StoredCredentials): void {\n config.set(\"credentials\", creds);\n}\n\nexport function getCredentials(): StoredCredentials | null {\n return config.get(\"credentials\");\n}\n\nexport function clearCredentials(): void {\n config.set(\"credentials\", null);\n}\n\nexport function setActiveWorkspace(id: string, name: string): void {\n config.set(\"activeWorkspaceId\", id);\n config.set(\"activeWorkspaceName\", name);\n}\n\nexport function getActiveWorkspace(): { id: string | null; name: string | null } {\n return {\n id: config.get(\"activeWorkspaceId\"),\n name: config.get(\"activeWorkspaceName\"),\n };\n}\n\nexport function setServerUrl(url: string): void {\n config.set(\"serverUrl\", url);\n}\n\nexport function clearAll(): void {\n config.clear();\n}\n\nexport function getConfigPath(): string {\n return config.path;\n}\n","/**\n * Orkestrate CLI — OAuth Authentication\n *\n * Implements the full OAuth 2.0 + PKCE flow:\n * 1. Dynamic client registration\n * 2. Open browser for consent\n * 3. Local HTTP callback server\n * 4. Token exchange\n * 5. Credential storage\n */\n\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport {\n getServerUrl,\n setCredentials,\n getCredentials,\n type StoredCredentials,\n} from \"./config.js\";\n\nfunction randomToken(bytes = 32): string {\n return randomBytes(bytes).toString(\"base64url\");\n}\n\nfunction pkceS256(verifier: string): string {\n return createHash(\"sha256\").update(verifier).digest(\"base64url\");\n}\n\ninterface TokenResponse {\n token_type: string;\n access_token: string;\n expires_in: number;\n refresh_token: string;\n scope: string;\n}\n\n/**\n * Step 1: Register this CLI instance as an OAuth client.\n */\nasync function registerClient(\n serverUrl: string,\n redirectUri: string,\n): Promise<{ clientId: string }> {\n const res = await fetch(`${serverUrl}/api/oauth/register`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_name: \"Orkestrate CLI\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n }),\n });\n\n if (!res.ok) {\n const body = await res.text();\n throw new Error(`Client registration failed (${res.status}): ${body}`);\n }\n\n const data = (await res.json()) as { client_id: string };\n return { clientId: data.client_id };\n}\n\n/**\n * Step 2 & 3: Open browser and wait for the OAuth callback.\n */\nfunction waitForCallback(\n port: number,\n): Promise<{ code: string; state: string }> {\n return new Promise((resolve, reject) => {\n let timeoutHandle: ReturnType<typeof setTimeout>;\n\n function cleanup() {\n clearTimeout(timeoutHandle);\n server.close();\n }\n\n const server = createServer((req: IncomingMessage, res: ServerResponse) => {\n const url = new URL(req.url || \"/\", `http://localhost:${port}`);\n\n if (url.pathname !== \"/callback\") {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n const error = url.searchParams.get(\"error\");\n const state = url.searchParams.get(\"state\") || \"\";\n\n if (error) {\n const description = url.searchParams.get(\"error_description\") || error;\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(buildErrorPage(description));\n cleanup();\n reject(new Error(`OAuth error: ${description}`));\n return;\n }\n\n if (!code) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(buildErrorPage(\"No authorization code received.\"));\n cleanup();\n reject(new Error(\"No authorization code received\"));\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(buildSuccessPage());\n cleanup();\n resolve({ code, state });\n });\n\n server.listen(port, \"127.0.0.1\", () => {\n // Server ready\n });\n\n server.on(\"error\", (err: Error) => {\n clearTimeout(timeoutHandle);\n reject(new Error(`Could not start local server: ${err.message}`));\n });\n\n // Timeout after 5 minutes — unref so it doesn't block process exit\n timeoutHandle = setTimeout(() => {\n server.close();\n reject(new Error(\"Authentication timed out (5 minutes). Please try again.\"));\n }, 5 * 60 * 1000);\n timeoutHandle.unref();\n });\n}\n\n/**\n * Step 4: Exchange authorization code for tokens.\n */\nasync function exchangeCodeForTokens(\n serverUrl: string,\n code: string,\n clientId: string,\n codeVerifier: string,\n redirectUri: string,\n): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n code_verifier: codeVerifier,\n client_id: clientId,\n redirect_uri: redirectUri,\n });\n\n const res = await fetch(`${serverUrl}/api/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Token exchange failed (${res.status}): ${text}`);\n }\n\n return (await res.json()) as TokenResponse;\n}\n\n/**\n * Refresh an expired access token.\n */\nexport async function refreshAccessToken(): Promise<StoredCredentials | null> {\n const creds = getCredentials();\n if (!creds?.refreshToken) return null;\n\n const serverUrl = getServerUrl();\n const body = new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: creds.refreshToken,\n client_id: creds.clientId,\n });\n\n const res = await fetch(`${serverUrl}/api/oauth/token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: body.toString(),\n });\n\n if (!res.ok) return null;\n\n const tokens = (await res.json()) as TokenResponse;\n const now = Math.floor(Date.now() / 1000);\n\n const newCreds: StoredCredentials = {\n clientId: creds.clientId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: now + tokens.expires_in,\n userId: creds.userId,\n scope: tokens.scope,\n };\n\n setCredentials(newCreds);\n return newCreds;\n}\n\n/**\n * Get a valid access token, refreshing if needed.\n */\nexport async function getValidToken(): Promise<string | null> {\n const creds = getCredentials();\n if (!creds) return null;\n\n const now = Math.floor(Date.now() / 1000);\n\n // Refresh if expired or expiring within 60 seconds\n if (creds.expiresAt <= now + 60) {\n const refreshed = await refreshAccessToken();\n return refreshed?.accessToken || null;\n }\n\n return creds.accessToken;\n}\n\n/**\n * Run the full OAuth login flow.\n */\nexport async function performLogin(): Promise<{\n clientId: string;\n userId: string;\n accessToken: string;\n}> {\n const serverUrl = getServerUrl();\n const port = 19274; // \"ork\" on a phone keypad, roughly\n const redirectUri = `http://127.0.0.1:${port}/callback`;\n\n // Step 1: Register client\n const { clientId } = await registerClient(serverUrl, redirectUri);\n\n // Step 2: Prepare PKCE\n const codeVerifier = randomToken(48);\n const codeChallenge = pkceS256(codeVerifier);\n const state = randomToken(16);\n\n // Step 3: Build authorization URL\n const authUrl = new URL(`${serverUrl}/api/oauth/authorize`);\n authUrl.searchParams.set(\"response_type\", \"code\");\n authUrl.searchParams.set(\"client_id\", clientId);\n authUrl.searchParams.set(\"redirect_uri\", redirectUri);\n authUrl.searchParams.set(\"code_challenge\", codeChallenge);\n authUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authUrl.searchParams.set(\"scope\", \"mcp:read mcp:write\");\n authUrl.searchParams.set(\"state\", state);\n\n // Step 4: Start callback server + open browser\n const callbackPromise = waitForCallback(port);\n\n // Dynamic import to handle ESM-only `open` package\n const { default: openBrowser } = await import(\"open\");\n await openBrowser(authUrl.toString());\n\n // Step 5: Wait for callback\n const { code, state: returnedState } = await callbackPromise;\n\n if (returnedState !== state) {\n throw new Error(\"OAuth state mismatch — possible CSRF attack. Aborting.\");\n }\n\n // Step 6: Exchange code for tokens\n const tokens = await exchangeCodeForTokens(\n serverUrl,\n code,\n clientId,\n codeVerifier,\n redirectUri,\n );\n\n const now = Math.floor(Date.now() / 1000);\n\n // We don't get user_id from the token response directly.\n // We'll extract it from the MCP endpoint or store a placeholder.\n // For now, use clientId as a proxy until first API call resolves it.\n const credentials: StoredCredentials = {\n clientId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: now + tokens.expires_in,\n userId: \"\", // Will be resolved on first API call\n scope: tokens.scope,\n };\n\n setCredentials(credentials);\n\n return {\n clientId,\n userId: credentials.userId,\n accessToken: tokens.access_token,\n };\n}\n\n// --- HTML pages for the local callback server ---\n\nfunction buildSuccessPage(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Orkestrate — Authenticated</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n text-align: center;\n padding: 3rem;\n border: 1px solid #262626;\n border-radius: 12px;\n background: #111;\n max-width: 420px;\n }\n .icon { font-size: 3rem; margin-bottom: 1rem; }\n h1 { font-size: 1.5rem; margin-bottom: 0.5rem; color: #fff; }\n p { color: #a3a3a3; line-height: 1.6; }\n .hint { margin-top: 1.5rem; font-size: 0.85rem; color: #525252; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">✓</div>\n <h1>Authenticated</h1>\n <p>You're now logged in to Orkestrate. You can close this tab and return to your terminal.</p>\n <p class=\"hint\">This window will close automatically.</p>\n </div>\n <script>setTimeout(() => window.close(), 3000);</script>\n</body>\n</html>`;\n}\n\nfunction buildErrorPage(message: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Orkestrate — Error</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #0a0a0a;\n color: #e5e5e5;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n }\n .card {\n text-align: center;\n padding: 3rem;\n border: 1px solid #371717;\n border-radius: 12px;\n background: #1a0a0a;\n max-width: 420px;\n }\n .icon { font-size: 3rem; margin-bottom: 1rem; }\n h1 { font-size: 1.5rem; margin-bottom: 0.5rem; color: #fca5a5; }\n p { color: #a3a3a3; line-height: 1.6; }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"icon\">✗</div>\n <h1>Authentication Failed</h1>\n <p>${message}</p>\n </div>\n</body>\n</html>`;\n}\n","\nimport { getServerUrl } from \"../lib/config.js\";\nimport { getValidToken } from \"../lib/auth.js\";\n\n/**\n * Orkestrate MCP Proxy\n * \n * Acts as a local MCP server (stdio) that forwards all requests to the \n * Orkestrate cloud MCP endpoint (HTTP), injecting the local auth token.\n */\nexport async function mcpCommand() {\n try {\n const serverUrl = getServerUrl();\n const mcpUrl = `${serverUrl}/api/mcp`;\n\n process.stdin.setEncoding(\"utf-8\");\n let buffer = \"\";\n \n process.stdin.on(\"data\", async (chunk) => {\n const rawChunk = String(chunk);\n buffer += rawChunk;\n \n let lineEndIndex;\n while ((lineEndIndex = buffer.indexOf(\"\\n\")) >= 0) {\n let line = buffer.slice(0, lineEndIndex).trim();\n buffer = buffer.slice(lineEndIndex + 1);\n \n if (!line) continue;\n \n // Handle back-to-back JSON objects missing newlines\n if (line.includes(\"}{\")) {\n const parts = line.split(\"}{\");\n processLine(parts[0] + \"}\", mcpUrl);\n for (let i = 1; i < parts.length - 1; i++) {\n processLine(\"{\" + parts[i] + \"}\", mcpUrl);\n }\n processLine(\"{\" + parts[parts.length - 1], mcpUrl);\n } else {\n processLine(line, mcpUrl);\n }\n }\n });\n\n process.stdin.on(\"end\", () => {\n process.exit(0);\n });\n\n // Stay alive\n await new Promise(() => {});\n } catch (err) {\n process.stderr.write(`[Orkestrate] Fatal error: ${err}\\n`);\n process.exit(1);\n }\n}\n\nasync function processLine(line: string, mcpUrl: string) {\n let payload: any;\n try {\n payload = JSON.parse(line);\n } catch { return; }\n\n const isNotification = !Object.prototype.hasOwnProperty.call(payload, \"id\");\n const requestId = payload.id;\n\n try {\n const token = await getValidToken();\n \n if (!token) {\n throw new Error(\"NOT_LOGGED_IN: Please run 'orkestrate login' to authenticate.\");\n }\n\n const res = await fetch(mcpUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${token}`,\n \"User-Agent\": \"Orkestrate-CLI-Proxy\"\n },\n body: line\n });\n\n // Notifications MUST NOT be responded to on stdout\n if (isNotification) return;\n\n const responseBody = await res.text();\n if (responseBody) {\n process.stdout.write(responseBody + \"\\n\");\n }\n } catch (err) {\n if (isNotification) return;\n\n process.stdout.write(JSON.stringify({\n jsonrpc: \"2.0\",\n id: requestId,\n error: {\n code: -32603,\n message: err instanceof Error ? err.message : String(err)\n }\n }) + \"\\n\");\n }\n}\n","\nimport { mcpCommand } from \"./commands/mcp.js\";\n\n// Standalone MCP bridge entry point. \n// DO NOT PRINT TO STDOUT ANY NON-JSON DATA.\nmcpCommand().catch(err => {\n process.stderr.write(`[Orkestrate-MCP] Fatal: ${err}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
|