@appchy/jarvis 0.1.21 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/bin.js +7914 -4828
  2. package/dist/bin.js.map +1 -1
  3. package/package.json +3 -1
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/cli.ts","../../../packages/logger/src/logger.ts","../../../providers/anthropic/src/anthropic.provider.ts","../../../providers/anthropic/src/anthropic.models.ts","../../../packages/types/src/agents/llm.types.ts","../../../packages/types/src/agents/tool.types.ts","../../../packages/types/src/media/tts.types.ts","../../../providers/anthropic/src/claude-code.provider.ts","../../../packages/sdk/src/agents/tools/tools.ts","../../../packages/sdk/src/agents/tools/plan.tool.ts","../../../packages/sdk/src/agents/tools/ask-user.tool.ts","../../../packages/sdk/src/agents/tools/think.tool.ts","../../../packages/sdk/src/agents/tools/plan-mode.tool.ts","../../../packages/sdk/src/agents/tools/agent.tools.ts","../../../packages/sdk/src/agents/skills/skills.ts","../../../packages/sdk/src/agents/prompts/mustache.ts","../../../packages/sdk/src/agents/references/reference.ts","../../../packages/sdk/src/data/tables.ts","../../../packages/sdk/src/data/connectors.ts","../../../packages/agent/src/tools/edit.tool.ts","../../../packages/agent/src/tools/bash.tool.ts","../../../packages/agent/src/tools/write.tool.ts","../../../packages/agent/src/tools/read.tool.ts","../../../packages/agent/src/tools/glob.tool.ts","../../../packages/agent/src/tools/grep.tool.ts","../../../packages/agent/src/tools/index.ts","../../../packages/agent/src/format.ts","../../../packages/agent/src/worktree.ts","../src/progress.ts","../src/attachments.ts","../src/agent.ts","../src/files.ts","../src/git.ts","../src/server.ts","../src/upstream.ts","../src/start.ts","../src/tui/chat.ts","../src/tui/settings.ts","../src/tui/app.tsx","../src/tui/hooks/use-agent-client.ts","../src/tui/hooks/use-messages.ts","../src/tui/hooks/use-task.ts","../src/tui/hooks/use-settings.ts","../src/tui/utils/slash-commands.ts","../src/tui/utils/auto-approve.ts","../src/tui/components/welcome-header.tsx","../src/tui/theme.ts","../src/tui/components/user-message.tsx","../src/tui/components/spinner.tsx","../src/tui/components/divider.tsx","../src/tui/hooks/use-terminal.ts","../src/tui/components/prompt-input.tsx","../src/tui/components/suggestions.tsx","../src/tui/components/file-picker.tsx","../src/tui/components/status-bar.tsx","../src/tui/utils/format-tokens.ts","../src/tui/components/permission-dialog.tsx","../src/tui/components/plan-review.tsx","../src/tui/components/max-iterations.tsx","../src/tui/components/help-menu.tsx","../src/tui/components/status-display.tsx","../src/tui/components/model-picker.tsx","../src/tui/components/mode-picker.tsx","../src/tui/components/thinking-picker.tsx","../src/tui/components/settings-dialog.tsx","../src/tui/components/notification.tsx","../src/tui/components/markdown-text.tsx","../src/service.ts","../src/bin.ts"],"sourcesContent":["/**\n * Agent Config\n *\n * Manages ~/.jarvis/config.json — saved by `jarvis connect <token>`,\n * read on `jarvis start`.\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\nimport { fileURLToPath } from \"url\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface AgentConfig {\n /** Cloud WS API URL (from connect token) */\n apiUrl?: string;\n /** JWT auth token (from connect token) */\n token?: string;\n /** Long-lived refresh token for obtaining new access tokens */\n refreshToken?: string;\n /** User ID */\n userId: string;\n /** Environment ID */\n envId?: string;\n /** Workspace root path for repo operations */\n workspacePath?: string;\n /** Web app URL for browser-based auth */\n appUrl?: string;\n /** Anthropic API key (for local-only use without cloud) */\n anthropicApiKey?: string;\n /** Use Anthropic subscription instead of API key */\n useSubscription?: boolean;\n /** Local WS server port */\n port?: number;\n /** When the config was last updated */\n connectedAt?: string;\n}\n\nexport interface ConnectToken {\n apiUrl: string;\n jwt: string;\n refreshToken: string;\n userId: string;\n envId: string;\n}\n\n// =============================================================================\n// Paths\n// =============================================================================\n\n// =============================================================================\n// Environment (single source of truth)\n// =============================================================================\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/** Single source of truth for dev vs prod.\n * Reads env.json relative to the CLI package root.\n * Dev: apps/cli/env.json has { \"env\": \"development\" }\n * Prod: dist/env.json has { \"env\": \"production\" } (written by tsup build) */\nexport function isDev(): boolean {\n try {\n const envFile = path.join(__dirname, \"..\", \"env.json\");\n const data = JSON.parse(fs.readFileSync(envFile, \"utf-8\"));\n return data.env === \"development\";\n } catch {\n return false;\n }\n}\n\nconst PROD_APP_URL = \"https://jarvis.appchy.com\";\nconst DEV_APP_URL = \"http://localhost:3000\";\n\n/** App URL for the current environment. */\nexport function getDefaultAppUrl(): string {\n return isDev() ? (process.env.APP_URL || DEV_APP_URL) : PROD_APP_URL;\n}\n\n// =============================================================================\n// Config directory\n// =============================================================================\n\n/** Determine config directory.\n * - JARVIS_CONFIG_DIR env var takes priority (escape hatch for CI/testing)\n * - dev → ~/.jarvis/dev/\n * - prod → ~/.jarvis/ */\nfunction resolveConfigDir(): string {\n if (process.env.JARVIS_CONFIG_DIR) return process.env.JARVIS_CONFIG_DIR;\n const base = path.join(os.homedir(), \".jarvis\");\n return isDev() ? path.join(base, \"dev\") : base;\n}\n\nconst CONFIG_DIR = resolveConfigDir();\nconst CONFIG_FILE = path.join(CONFIG_DIR, \"config.json\");\n\n// =============================================================================\n// Operations\n// =============================================================================\n\nexport function loadConfig(): AgentConfig | null {\n try {\n const raw = fs.readFileSync(CONFIG_FILE, \"utf-8\");\n return JSON.parse(raw) as AgentConfig;\n } catch {\n return null;\n }\n}\n\nexport function saveConfig(config: AgentConfig): void {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\nexport function clearConfig(): void {\n try {\n fs.unlinkSync(CONFIG_FILE);\n } catch {}\n}\n\nexport function parseConnectToken(token: string): ConnectToken {\n try {\n const decoded = Buffer.from(token, \"base64\").toString(\"utf-8\");\n const parsed = JSON.parse(decoded);\n if (!parsed.apiUrl || !parsed.jwt || !parsed.userId) {\n throw new Error(\"Invalid token: missing required fields (apiUrl, jwt, userId)\");\n }\n return parsed as ConnectToken;\n } catch (err) {\n if (err instanceof SyntaxError) {\n throw new Error(\"Invalid token: not valid base64-encoded JSON\");\n }\n throw err;\n }\n}\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n","/**\n * Agent CLI\n *\n * Commands:\n * (default) — Interactive TUI (auto-setup on first run)\n * connect <token> — Save cloud connection config\n * start — Start the agent (daemon by default, auto-setup on first run)\n * stop — Stop the running agent\n * restart — Restart the agent\n * logs — Tail agent logs\n * status — Show config and connection status\n * install — Install as OS service (auto-start + crash recovery)\n * uninstall — Remove OS service\n * logout — Clear saved config\n */\n\nimport { Command } from \"commander\";\nimport { spawn, execSync } from \"child_process\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\nimport { loadConfig, saveConfig, clearConfig, parseConnectToken, getConfigPath, getDefaultAppUrl, isDev } from \"./config\";\nimport { startAgent } from \"./start\";\nimport { isPortInUse } from \"./server\";\nimport { launchChat, type ChatOptions } from \"./tui/chat\";\nimport { createServiceManager } from \"./service\";\n\nimport { createRequire } from \"module\";\nconst _require = createRequire(import.meta.url);\nconst PKG_VERSION: string = _require(\"../package.json\").version ?? \"dev\";\n\nconst LOG_DIR = path.join(os.homedir(), \".jarvis\");\nconst LOG_FILE = path.join(LOG_DIR, \"agent.log\");\nconst PID_FILE = path.join(LOG_DIR, \"agent.pid\");\n\n// =============================================================================\n// PID helpers\n// =============================================================================\n\nfunction readPid(): number | null {\n try {\n const pid = parseInt(fs.readFileSync(PID_FILE, \"utf-8\").trim(), 10);\n if (isNaN(pid)) return null;\n // Check if process is alive\n try {\n process.kill(pid, 0);\n return pid;\n } catch {\n // Process not running, clean up stale PID\n fs.unlinkSync(PID_FILE);\n return null;\n }\n } catch {\n return null;\n }\n}\n\nfunction clearPid(): void {\n try {\n fs.unlinkSync(PID_FILE);\n } catch {}\n}\n\n// =============================================================================\n// Interactive setup (runs when no config exists)\n// =============================================================================\n\n/**\n * Start a temporary HTTP server to receive the auth callback from the browser.\n * Returns the connect token when the callback is received.\n */\nasync function waitForBrowserAuth(port: number): Promise<string> {\n const http = await import(\"http\");\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n server.close();\n reject(new Error(\"Browser authentication timed out (2 minutes)\"));\n }, 120_000);\n\n const server = http.createServer((req, res) => {\n const url = new URL(req.url ?? \"/\", `http://127.0.0.1:${port}`);\n\n if (url.pathname === \"/callback\") {\n const token = url.searchParams.get(\"token\");\n // Allow CORS from the web app\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET\");\n\n if (token) {\n res.writeHead(200, { \"Content-Type\": \"text/plain\" });\n res.end(\"OK\");\n clearTimeout(timeout);\n server.close();\n resolve(token);\n } else {\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\n res.end(\"Missing token\");\n }\n return;\n }\n\n res.writeHead(404);\n res.end();\n });\n\n server.listen(port, \"127.0.0.1\");\n });\n}\n\n/** Find a free port for the auth callback server */\nasync function findFreePort(): Promise<number> {\n const net = await import(\"net\");\n return new Promise((resolve, reject) => {\n const server = net.createServer();\n server.listen(0, \"127.0.0.1\", () => {\n const addr = server.address();\n const port = typeof addr === \"object\" && addr ? addr.port : 0;\n server.close(() => resolve(port));\n });\n server.on(\"error\", reject);\n });\n}\n\nasync function browserAuth(appUrl: string): Promise<boolean> {\n const config = loadConfig();\n const callbackPort = await findFreePort();\n const loginUrl = `${appUrl}/auth/cli?port=${callbackPort}`;\n\n console.log();\n console.log(\"Opening browser for sign in...\");\n console.log(` If it doesn't open, visit: ${loginUrl}`);\n console.log();\n\n // Open browser\n const { exec } = await import(\"child_process\");\n const platform = process.platform;\n const openCmd = platform === \"darwin\" ? \"open\" : platform === \"win32\" ? \"start\" : \"xdg-open\";\n exec(`${openCmd} \"${loginUrl}\"`);\n\n console.log(\"Waiting for authentication...\");\n\n try {\n const token = await waitForBrowserAuth(callbackPort);\n const parsed = parseConnectToken(token);\n saveConfig({\n ...config,\n apiUrl: parsed.apiUrl,\n token: parsed.jwt,\n refreshToken: parsed.refreshToken,\n userId: parsed.userId,\n envId: parsed.envId,\n connectedAt: new Date().toISOString(),\n });\n console.log();\n console.log(`Signed in as ${parsed.userId}`);\n return true;\n } catch (err) {\n console.error(`Authentication failed: ${err instanceof Error ? err.message : err}`);\n return false;\n }\n}\n\n/** Resolve app URL for browser auth.\n * Uses config.appUrl if set (from a previous connect), otherwise the build-time default.\n * Dev (tsx) → localhost:3000, Prod (tsup bundle) → jarvis.appchy.com. */\nfunction getAppUrl(): string {\n const config = loadConfig();\n return config?.appUrl ?? getDefaultAppUrl();\n}\n\n/**\n * Ensure the agent is configured with a valid, fresh token.\n * Always re-authenticates via browser to guarantee correct userId and WS URL.\n * Only skips auth for API key / subscription mode.\n */\nasync function ensureSetup(): Promise<boolean> {\n const config = loadConfig();\n\n // API key or subscription mode — no token management needed\n if (config?.anthropicApiKey || config?.useSubscription) {\n return true;\n }\n\n // Always re-authenticate to guarantee fresh token with correct userId + WS URL.\n // This handles: expired tokens, wrong userId, wrong WS URL, stale config, etc.\n clearConfig();\n return browserAuth(getAppUrl());\n}\n\n// =============================================================================\n// Auto-register repo\n// =============================================================================\n\n/**\n * Parse owner/name from a git remote URL.\n * Supports: git@github.com:owner/name.git, https://github.com/owner/name.git\n */\nfunction parseGitRemote(url: string): { owner: string; name: string } | null {\n // SSH: git@github.com:owner/name.git\n const sshMatch = url.match(/[:\\/]([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n if (sshMatch) return { owner: sshMatch[1], name: sshMatch[2] };\n return null;\n}\n\n/**\n * Auto-register the workspace repo in environment settings.\n * Detects the git remote and PATCHes user preferences with the repo path mapping.\n * Silent on failure — never blocks startup.\n */\nasync function autoRegisterRepo(\n workspacePath: string,\n config: ReturnType<typeof loadConfig>,\n): Promise<void> {\n try {\n const remoteUrl = execSync(\"git config --get remote.origin.url\", {\n cwd: workspacePath,\n encoding: \"utf-8\",\n timeout: 5000,\n }).trim();\n if (!remoteUrl) return;\n\n const parsed = parseGitRemote(remoteUrl);\n if (!parsed) return;\n\n const slug = `${parsed.owner}/${parsed.name}`;\n const appUrl = config?.appUrl ?? getDefaultAppUrl();\n const token = config?.token;\n if (!token) return;\n\n console.log(`Registering repo ${slug} → ${workspacePath}`);\n\n const envId = config?.envId ?? \"local\";\n const res = await fetch(`${appUrl}/api/v1/settings/preferences/repos?envId=${envId}`, {\n method: \"PATCH\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ [slug]: workspacePath }),\n });\n\n if (res.ok) {\n console.log(` Repo registered`);\n } else {\n const body = await res.text().catch(() => \"\");\n console.error(` Failed to register repo (${res.status}): ${body}`);\n }\n } catch (err) {\n console.error(` Failed to register repo: ${err instanceof Error ? err.message : err}`);\n }\n}\n\n// =============================================================================\n// CLI\n// =============================================================================\n\nexport function createCli(): Command {\n const program = new Command()\n .name(\"jarvis\")\n .description(\"Jarvis local agent — runs Claude Code on your machine\")\n .version(PKG_VERSION);\n\n // ---------------------------------------------------------------------------\n // Default action (no subcommand) — launch interactive chat\n // ---------------------------------------------------------------------------\n\n // Default action handled after subcommand definitions (see bottom)\n\n // ---------------------------------------------------------------------------\n // connect <token>\n // ---------------------------------------------------------------------------\n\n program\n .command(\"connect <token>\")\n .description(\"Connect to Jarvis cloud using a token from the web UI\")\n .option(\"-w, --workspace <path>\", \"Workspace root path for repo operations\")\n .action((token: string, opts: { workspace?: string }) => {\n try {\n const parsed = parseConnectToken(token);\n const existing = loadConfig();\n\n saveConfig({\n ...existing,\n apiUrl: parsed.apiUrl,\n token: parsed.jwt,\n refreshToken: parsed.refreshToken,\n userId: parsed.userId,\n envId: parsed.envId,\n ...(opts.workspace ? { workspacePath: opts.workspace } : {}),\n connectedAt: new Date().toISOString(),\n });\n\n console.log(`Connected to Jarvis cloud`);\n console.log(` User: ${parsed.userId}`);\n console.log(` Env: ${parsed.envId}`);\n console.log(` API: ${parsed.apiUrl}`);\n console.log(` Config: ${getConfigPath()}`);\n console.log();\n console.log(`Run 'jarvis start' to begin.`);\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n // ---------------------------------------------------------------------------\n // start\n // ---------------------------------------------------------------------------\n\n program\n .command(\"start\")\n .description(\"Start the local agent (authenticates, cleans up stale processes, starts fresh)\")\n .option(\"-p, --port <port>\", \"Local WS server port\", \"7862\")\n .option(\"-w, --workspace <path>\", \"Workspace root path\")\n .option(\"--api-key <key>\", \"Anthropic API key (for local-only use)\")\n .option(\"--no-upstream\", \"Don't connect to cloud (local-only mode)\")\n .option(\"--foreground\", \"Run in foreground (don't daemonize)\")\n .action(\n async (opts: {\n port: string;\n workspace?: string;\n apiKey?: string;\n upstream: boolean;\n foreground?: boolean;\n }) => {\n // Skip interactive setup in foreground mode (used by daemon child & E2E tests)\n if (!opts.foreground) {\n const ok = await ensureSetup();\n if (!ok) {\n console.error(\"Setup failed. Cannot start agent.\");\n process.exit(1);\n }\n }\n const config = loadConfig();\n const port = parseInt(opts.port, 10);\n\n const workspacePath = opts.workspace ?? config?.workspacePath ?? process.cwd();\n const userId = config?.userId ?? process.env.JARVIS_USER_ID ?? \"local\";\n\n // Auto-register this repo in environment settings\n if (!opts.foreground) {\n await autoRegisterRepo(workspacePath, config);\n }\n\n // Default: use subscription (Claude Max / Pro plan)\n // Only use API key if explicitly passed via --api-key flag or config\n const explicitApiKey = opts.apiKey ?? config?.anthropicApiKey;\n const useSubscription = !explicitApiKey;\n const anthropicApiKey = explicitApiKey;\n\n // Foreground mode — run directly (used by daemon child, OS service, & E2E tests)\n if (opts.foreground) {\n // Strip API key from env when using subscription to prevent SDK from picking it up\n if (useSubscription && process.env.ANTHROPIC_API_KEY) {\n delete process.env.ANTHROPIC_API_KEY;\n }\n await startAgent({\n port,\n workspacePath,\n anthropicApiKey,\n useSubscription,\n userId,\n upstream: (() => {\n const apiUrl = process.env.JARVIS_UPSTREAM_URL ?? config?.apiUrl;\n const token = process.env.JARVIS_UPSTREAM_TOKEN ?? config?.token;\n if (opts.upstream && apiUrl && token) {\n const appUrl = getAppUrl();\n return {\n apiUrl,\n token,\n refreshToken: config?.refreshToken,\n onAuthExhausted: async () => {\n console.log(\"\\n[Auth] Token expired — re-authenticating...\");\n const ok = await browserAuth(appUrl);\n if (!ok) return null;\n const fresh = loadConfig();\n if (!fresh?.token) return null;\n return { token: fresh.token, refreshToken: fresh.refreshToken };\n },\n };\n }\n return undefined;\n })(),\n });\n return;\n }\n\n // -----------------------------------------------------------------------\n // Clean start: nuke everything, then install fresh\n // -----------------------------------------------------------------------\n\n const service = createServiceManager();\n\n // 1. Unload the OS service first (stops KeepAlive respawning)\n if (service.isInstalled()) {\n try {\n service.uninstall();\n } catch {}\n }\n\n // 2. Kill stale daemon process\n const stalePid = readPid();\n if (stalePid) {\n try { process.kill(stalePid, \"SIGTERM\"); } catch {}\n clearPid();\n }\n\n // 3. Force-kill anything on our port (orphans, stale processes)\n const killPort = async (p: number) => {\n try {\n const output = execSync(`lsof -ti :${p}`, { encoding: \"utf-8\" }).trim();\n if (output) {\n for (const pid of output.split(\"\\n\")) {\n try { process.kill(parseInt(pid, 10), \"SIGTERM\"); } catch {}\n }\n }\n } catch {}\n // Wait for graceful shutdown\n await new Promise((r) => setTimeout(r, 1000));\n // Force kill if still alive\n if (await isPortInUse(p)) {\n try {\n const output = execSync(`lsof -ti :${p}`, { encoding: \"utf-8\" }).trim();\n if (output) {\n for (const pid of output.split(\"\\n\")) {\n try { process.kill(parseInt(pid, 10), \"SIGKILL\"); } catch {}\n }\n }\n } catch {}\n await new Promise((r) => setTimeout(r, 1000));\n }\n };\n\n await killPort(port);\n\n // Resolve the entry point — dev uses source (tsx), prod uses dist build\n const binPath = process.argv[1]!;\n const cliRoot = path.resolve(path.dirname(binPath), \"..\");\n const distEntry = path.join(cliRoot, \"dist\", \"bin.js\");\n const srcEntry = path.join(cliRoot, \"src\", \"bin.ts\");\n const useSrc = isDev() && fs.existsSync(srcEntry);\n const entryPath = useSrc ? srcEntry : (fs.existsSync(distEntry) ? distEntry : binPath);\n const tsxBin = path.join(cliRoot, \"node_modules\", \".bin\", \"tsx\");\n const nodePath = useSrc && fs.existsSync(tsxBin) ? tsxBin : process.execPath;\n\n // Propagate override vars to the OS service\n const serviceEnv: Record<string, string> = {};\n if (process.env.JARVIS_CONFIG_DIR) serviceEnv.JARVIS_CONFIG_DIR = process.env.JARVIS_CONFIG_DIR;\n if (process.env.JARVIS_USER_ID) serviceEnv.JARVIS_USER_ID = process.env.JARVIS_USER_ID;\n if (process.env.JARVIS_ENV_ID) serviceEnv.JARVIS_ENV_ID = process.env.JARVIS_ENV_ID;\n\n // Install (or re-install) and start the OS service\n service.install({\n port,\n workspacePath,\n nodePath,\n entryPath,\n upstream: opts.upstream,\n ...(Object.keys(serviceEnv).length > 0 ? { env: serviceEnv } : {}),\n });\n\n // Wait for the agent to actually start and connect\n const startTime = Date.now();\n let agentReady = false;\n while (Date.now() - startTime < 15_000) {\n if (await isPortInUse(port)) {\n agentReady = true;\n break;\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n\n if (!agentReady) {\n console.error(\"Agent failed to start. Check logs:\");\n console.error(` ${LOG_FILE}`);\n process.exit(1);\n }\n\n const status = service.status();\n console.log(`Jarvis agent started`);\n console.log(` Local: ws://127.0.0.1:${port}`);\n console.log(` Workspace: ${workspacePath}`);\n console.log(` Logs: ${LOG_FILE}`);\n if (config?.apiUrl) {\n console.log(` Cloud: ${config.apiUrl}`);\n }\n if (status.os) {\n console.log(` Service: ${status.os} (auto-start on login, crash recovery)`);\n }\n },\n );\n\n // ---------------------------------------------------------------------------\n // stop\n // ---------------------------------------------------------------------------\n\n program\n .command(\"stop\")\n .description(\"Stop the running agent\")\n .action(async () => {\n const service = createServiceManager();\n if (service.isInstalled()) {\n service.stop();\n clearPid();\n console.log(\"Agent stopped via OS service.\");\n console.log(\"Use 'jarvis start' to re-enable, or 'jarvis uninstall' to remove auto-start.\");\n return;\n }\n\n const pid = readPid();\n if (pid) {\n try {\n process.kill(pid, \"SIGTERM\");\n clearPid();\n console.log(`Agent stopped (PID: ${pid})`);\n } catch {\n clearPid();\n console.log(\"Agent process not found. Cleaned up PID file.\");\n }\n return;\n }\n\n // Fallback: check if port is in use\n const running = await isPortInUse(7862);\n if (running) {\n // Try to find the process by port\n try {\n const output = execSync(\"lsof -ti :7862\", { encoding: \"utf-8\" }).trim();\n if (output) {\n const pids = output.split(\"\\n\");\n for (const p of pids) {\n try {\n process.kill(parseInt(p, 10), \"SIGTERM\");\n } catch {}\n }\n console.log(\"Agent stopped.\");\n return;\n }\n } catch {}\n }\n\n console.log(\"No agent is running.\");\n });\n\n // ---------------------------------------------------------------------------\n // restart\n // ---------------------------------------------------------------------------\n\n program\n .command(\"restart\")\n .description(\"Restart the agent (alias for start — start always does a clean restart)\")\n .action(async () => {\n // start already handles: auth → kill stale → start fresh\n await program.parseAsync([\"node\", \"jarvis\", \"start\"]);\n });\n\n // ---------------------------------------------------------------------------\n // logs\n // ---------------------------------------------------------------------------\n\n program\n .command(\"logs\")\n .description(\"View agent logs\")\n .option(\"-f, --follow\", \"Follow log output (like tail -f)\", true)\n .option(\"-n, --lines <n>\", \"Number of lines to show\", \"50\")\n .action((opts: { follow?: boolean; lines: string }) => {\n if (!fs.existsSync(LOG_FILE)) {\n console.log(\"No log file found. Start the agent first: jarvis start\");\n return;\n }\n\n if (opts.follow) {\n // Tail -f mode\n const tail = spawn(\"tail\", [\"-f\", \"-n\", opts.lines, LOG_FILE], {\n stdio: \"inherit\",\n });\n process.on(\"SIGINT\", () => {\n tail.kill();\n process.exit(0);\n });\n tail.on(\"exit\", () => process.exit(0));\n } else {\n // Show last N lines\n const content = execSync(`tail -n ${opts.lines} \"${LOG_FILE}\"`, { encoding: \"utf-8\" });\n process.stdout.write(content);\n }\n });\n\n // ---------------------------------------------------------------------------\n // status\n // ---------------------------------------------------------------------------\n\n program\n .command(\"status\")\n .description(\"Show agent configuration and connection status\")\n .action(async () => {\n const config = loadConfig();\n const pid = readPid();\n const port = config?.port ?? 7862;\n const running = await isPortInUse(port);\n\n console.log(`Jarvis Agent v${PKG_VERSION}:`);\n console.log(\n ` Status: ${running ? `\\x1b[32mrunning\\x1b[0m` : `\\x1b[31mstopped\\x1b[0m`}${pid ? ` (PID: ${pid})` : \"\"}`,\n );\n console.log(` Port: ${port}`);\n console.log(` Config: ${getConfigPath()}`);\n\n if (config) {\n console.log(` User: ${config.userId}`);\n console.log(` Env: ${config.envId ?? \"local\"}`);\n console.log(` Workspace: ${config.workspacePath ?? \"(cwd)\"}`);\n console.log(` Cloud: ${config.apiUrl ?? \"(not connected)\"}`);\n if (config.connectedAt) {\n console.log(` Connected: ${config.connectedAt}`);\n }\n } else {\n console.log(` Config: Not set up. Run 'jarvis connect <token>'`);\n }\n\n const svc = createServiceManager();\n const svcStatus = svc.status();\n if (svcStatus.installed) {\n const label = svcStatus.os ?? \"unknown\";\n const state = svcStatus.running\n ? `\\x1b[32minstalled & running\\x1b[0m (${label})`\n : `\\x1b[33minstalled, stopped\\x1b[0m (${label})`;\n console.log(` Service: ${state}`);\n } else {\n console.log(` Service: not installed (run 'jarvis install' for always-on)`);\n }\n\n console.log(` Logs: ${LOG_FILE}`);\n });\n\n // ---------------------------------------------------------------------------\n // install\n // ---------------------------------------------------------------------------\n\n program\n .command(\"install\")\n .description(\"Install as OS service for auto-start on login and crash recovery\")\n .option(\"-p, --port <port>\", \"Local WS server port\", \"7862\")\n .option(\"-w, --workspace <path>\", \"Workspace root path\")\n .option(\"--no-upstream\", \"Don't connect to cloud\")\n .action(async (opts: { port: string; workspace?: string; upstream: boolean }) => {\n await ensureSetup();\n const config = loadConfig();\n const port = parseInt(opts.port, 10);\n const workspacePath = opts.workspace ?? config?.workspacePath ?? process.cwd();\n const service = createServiceManager();\n\n // Resolve entry point (same logic as start command)\n const binPath = process.argv[1]!;\n const cliRoot = path.resolve(path.dirname(binPath), \"..\");\n const distEntry = path.join(cliRoot, \"dist\", \"bin.js\");\n const srcEntry = path.join(cliRoot, \"src\", \"bin.ts\");\n const useSrc = isDev() && fs.existsSync(srcEntry);\n const entryPath = useSrc ? srcEntry : (fs.existsSync(distEntry) ? distEntry : binPath);\n const tsxBin = path.join(cliRoot, \"node_modules\", \".bin\", \"tsx\");\n const nodePath = useSrc && fs.existsSync(tsxBin) ? tsxBin : process.execPath;\n\n // Kill any existing detached daemon — service takes over\n const pid = readPid();\n if (pid) {\n try {\n process.kill(pid, \"SIGTERM\");\n } catch {}\n clearPid();\n }\n\n // Propagate override vars to the OS service\n const installEnv: Record<string, string> = {};\n if (process.env.JARVIS_CONFIG_DIR) installEnv.JARVIS_CONFIG_DIR = process.env.JARVIS_CONFIG_DIR;\n if (process.env.JARVIS_USER_ID) installEnv.JARVIS_USER_ID = process.env.JARVIS_USER_ID;\n if (process.env.JARVIS_ENV_ID) installEnv.JARVIS_ENV_ID = process.env.JARVIS_ENV_ID;\n\n try {\n service.install({\n port,\n workspacePath,\n nodePath,\n entryPath,\n upstream: opts.upstream,\n ...(Object.keys(installEnv).length > 0 ? { env: installEnv } : {}),\n });\n } catch (err) {\n console.error(`Failed to install service: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n\n const status = service.status();\n console.log(`Jarvis agent installed as OS service`);\n console.log(` Platform: ${status.os}`);\n console.log(` Port: ${port}`);\n console.log(` Workspace: ${workspacePath}`);\n console.log(` Auto-start on login: \\x1b[32menabled\\x1b[0m`);\n console.log(` Crash recovery: \\x1b[32menabled\\x1b[0m`);\n console.log();\n console.log(`Commands:`);\n console.log(` jarvis status — Check service status`);\n console.log(` jarvis uninstall — Remove OS service`);\n });\n\n // ---------------------------------------------------------------------------\n // uninstall\n // ---------------------------------------------------------------------------\n\n program\n .command(\"uninstall\")\n .description(\"Remove OS service (stops auto-start and crash recovery)\")\n .action(() => {\n const service = createServiceManager();\n if (!service.isInstalled()) {\n console.log(\"No service is installed. Nothing to do.\");\n return;\n }\n\n try {\n service.stop();\n } catch {}\n service.uninstall();\n clearPid();\n console.log(\"Jarvis OS service removed.\");\n console.log(\"The agent will no longer auto-start on login or restart on crash.\");\n });\n\n // ---------------------------------------------------------------------------\n // logout\n // ---------------------------------------------------------------------------\n\n program\n .command(\"logout\")\n .description(\"Clear saved configuration\")\n .action(() => {\n clearConfig();\n console.log(\"Configuration cleared.\");\n });\n\n // ---------------------------------------------------------------------------\n // Default action (no subcommand) — launch interactive chat\n // Must be defined AFTER subcommands so Commander routes subcommands first\n // ---------------------------------------------------------------------------\n\n program\n .command(\"chat\", { isDefault: true, hidden: true })\n .description(\"Interactive TUI\")\n .option(\"--model <id>\", \"Model (e.g., claude-opus-4-20250514)\")\n .option(\"--mode <mode>\", \"Permission mode: supervised|auto|plan|yolo\")\n .option(\"--thinking <config>\", \"Thinking: adaptive|enabled|disabled\")\n .option(\"--thinking-budget <n>\", \"Token budget when thinking=enabled\")\n .option(\"--max-turns <n>\", \"Max turns per task\")\n .option(\"-p, --port <port>\", \"Agent server port\", \"7862\")\n .option(\"-w, --workspace <path>\", \"Workspace root path\")\n .option(\"--no-server\", \"Connect to existing server, don't auto-start\")\n .action(async (opts: ChatOptions) => {\n await ensureSetup();\n await launchChat(opts);\n });\n\n return program;\n}\n","/**\n * Logger Singleton\n *\n * Provider-agnostic logger with console default.\n * Call logger.init({ provider }) to set a real provider (e.g., pinoProvider).\n *\n * Usage:\n * ```typescript\n * import { logger } from \"@jarvis/logger\";\n * import { pinoProvider } from \"@jarvis/pino\";\n *\n * logger.init({ provider: pinoProvider({ name: \"worker\" }) });\n * logger.info(ctx, \"Hello\", { key: \"value\" });\n * logger.sys.info(\"System startup\");\n * Runtime.install({ logger: logger.runtime() });\n * ```\n */\n\nimport type { Context, LogProvider, LogMetadata, AuditEvent } from \"@jarvis/types\";\n\n// =============================================================================\n// Error resolving — handles Error objects in metadata\n// =============================================================================\n\nfunction resolveError(meta?: LogMetadata): LogMetadata {\n if (!meta) return {};\n const { error, ...rest } = meta;\n if (error === undefined) return meta;\n if (error instanceof Error) {\n return { ...rest, error: error.message, ...(error.stack ? { errorStack: error.stack } : {}) };\n }\n return { ...rest, error: typeof error === \"string\" ? error : String(error) };\n}\n\n// =============================================================================\n// Console default provider\n// =============================================================================\n\nfunction consoleProvider(): LogProvider {\n const log =\n (level: \"debug\" | \"info\" | \"warn\" | \"error\") =>\n (_ctx: Context, message: string, meta?: LogMetadata): void => {\n const fn = level === \"error\" ? console.error : level === \"warn\" ? console.warn : level === \"debug\" ? console.debug : console.info;\n fn(`[${level.toUpperCase()}]`, message, resolveError(meta));\n };\n\n return {\n debug: log(\"debug\"),\n info: log(\"info\"),\n warn: log(\"warn\"),\n error: log(\"error\"),\n audit: (_ctx, event) => console.info(\"[AUDIT]\", event.action, event.result),\n };\n}\n\n// =============================================================================\n// Console runtime logger (fallback for Temporal Runtime.install())\n// =============================================================================\n\ninterface RuntimeLogger {\n log(level: string, message: string, meta?: Record<string | symbol, unknown>): void;\n trace(message: string, meta?: Record<string | symbol, unknown>): void;\n debug(message: string, meta?: Record<string | symbol, unknown>): void;\n info(message: string, meta?: Record<string | symbol, unknown>): void;\n warn(message: string, meta?: Record<string | symbol, unknown>): void;\n error(message: string, meta?: Record<string | symbol, unknown>): void;\n}\n\nconst LEVEL_MAP: Record<string, \"debug\" | \"info\" | \"warn\" | \"error\"> = {\n TRACE: \"debug\",\n DEBUG: \"debug\",\n INFO: \"info\",\n WARN: \"warn\",\n ERROR: \"error\",\n};\n\nfunction consoleRuntimeLogger(): RuntimeLogger {\n const log = (level: string, message: string, meta?: Record<string | symbol, unknown>) => {\n const fn = console[LEVEL_MAP[level] ?? \"info\"];\n fn(message, meta ? Object.fromEntries(Object.entries(meta as Record<string, unknown>)) : \"\");\n };\n return {\n log: (level, msg, meta) => log(level, msg, meta),\n trace: (msg, meta) => log(\"TRACE\", msg, meta),\n debug: (msg, meta) => log(\"DEBUG\", msg, meta),\n info: (msg, meta) => log(\"INFO\", msg, meta),\n warn: (msg, meta) => log(\"WARN\", msg, meta),\n error: (msg, meta) => log(\"ERROR\", msg, meta),\n };\n}\n\n// =============================================================================\n// Singleton state\n// =============================================================================\n\nconst SYS_CTX: Context = { userId: \"system\" } as Context;\n\nlet _provider: LogProvider = consoleProvider();\nlet _runtimeFactory: (() => RuntimeLogger) | null = null;\n\n// =============================================================================\n// Logger singleton\n// =============================================================================\n\nexport type LogProviderWithRuntime = LogProvider & {\n runtime?: () => RuntimeLogger;\n};\n\nexport const logger = {\n /** Set the active logging provider */\n init(config: { provider: LogProviderWithRuntime }) {\n _provider = config.provider;\n _runtimeFactory = config.provider.runtime ?? null;\n },\n\n // Logging — delegates to current provider (resolves Error objects in meta)\n debug(ctx: Context, message: string, meta?: LogMetadata) { _provider.debug(ctx, message, resolveError(meta)); },\n info(ctx: Context, message: string, meta?: LogMetadata) { _provider.info(ctx, message, resolveError(meta)); },\n warn(ctx: Context, message: string, meta?: LogMetadata) { _provider.warn(ctx, message, resolveError(meta)); },\n error(ctx: Context, message: string, meta?: LogMetadata) { _provider.error(ctx, message, resolveError(meta)); },\n audit(ctx: Context, event: AuditEvent) { _provider.audit(ctx, event); },\n\n /** System-scoped shorthand (no ctx required) */\n sys: {\n debug(message: string, meta?: LogMetadata) { _provider.debug(SYS_CTX, message, meta); },\n info(message: string, meta?: LogMetadata) { _provider.info(SYS_CTX, message, meta); },\n warn(message: string, meta?: LogMetadata) { _provider.warn(SYS_CTX, message, meta); },\n error(message: string, meta?: LogMetadata) { _provider.error(SYS_CTX, message, meta); },\n },\n\n /** Get a Temporal Runtime.install() logger. Uses provider's runtime() if available, console fallback. */\n runtime(): RuntimeLogger {\n if (_runtimeFactory) return _runtimeFactory();\n return consoleRuntimeLogger();\n },\n};\n","/**\n * Anthropic provider implementation\n * Provides LLM capabilities (query, stream) using the Anthropic Messages API\n *\n * Ported from @gluoe/anthropic with @jarvis/* imports\n */\n\nimport Anthropic from \"@anthropic-ai/sdk\";\nimport type { MessageParam } from \"@anthropic-ai/sdk/resources/messages\";\n\nimport { anthropicModels } from \"./anthropic.models\";\nimport type {\n Context,\n QueryLLMRequest,\n QueryLLMResponse,\n LLMProvider,\n LLMQueryOptions,\n Model,\n Message,\n MultimodalMessage,\n ContentPart,\n TextContentPart,\n ImageContentPart,\n} from \"@jarvis/types\";\n\nexport interface Config {\n apiKey?: string;\n baseURL?: string;\n}\n\nexport type AnthropicProvider = LLMProvider;\n\nexport function provider(config?: Config): AnthropicProvider {\n const finalConfig = {\n apiKey: config?.apiKey ?? process.env.ANTHROPIC_API_KEY,\n baseURL: config?.baseURL ?? process.env.ANTHROPIC_BASE_URL,\n };\n\n if (!finalConfig.apiKey) {\n throw new Error(\n \"Anthropic API key is required. Provide it via config.apiKey or ANTHROPIC_API_KEY environment variable\",\n );\n }\n\n const client = new Anthropic({\n apiKey: finalConfig.apiKey,\n baseURL: finalConfig.baseURL,\n });\n\n // =========================================================================\n // LLM METHODS\n // =========================================================================\n\n async function query(\n _ctx: Context,\n request: QueryLLMRequest,\n _options?: LLMQueryOptions,\n ): Promise<QueryLLMResponse> {\n try {\n const startTime = Date.now();\n const systemMessage = request.messages.find((m) => m.role === \"system\");\n\n const options = {\n max_tokens: request.options?.maxTokens ?? 4096,\n temperature: request.options?.temperature,\n top_p: request.options?.topP,\n };\n\n // Check if webSearch tool is present and convert to native web search\n const hasWebSearch = request.tools?.some((t) => t.name === \"webSearch\");\n const otherTools =\n request.tools?.filter((t) => t.name !== \"webSearch\") || [];\n\n // If structured output is requested, use tool calling approach\n const tools = request.output?.schema\n ? [\n {\n name: \"structured_output\",\n description: \"Respond with a structured JSON object\",\n input_schema: request.output.schema,\n },\n ...(hasWebSearch\n ? [\n {\n type: \"web_search_20250305\" as const,\n name: \"web_search\",\n max_uses: 5,\n },\n ]\n : []),\n ...(otherTools.length > 0 ? convertTools(otherTools) : []),\n ]\n : hasWebSearch\n ? [\n {\n type: \"web_search_20250305\" as const,\n name: \"web_search\",\n max_uses: 5,\n },\n ...(otherTools.length > 0 ? convertTools(otherTools) : []),\n ]\n : otherTools.length > 0\n ? convertTools(otherTools)\n : undefined;\n\n const tool_choice = request.output?.schema\n ? {\n type: \"tool\" as const,\n name: \"structured_output\",\n disable_parallel_tool_use: true,\n }\n : undefined;\n\n // Map ThinkingConfig to Anthropic thinking parameter\n const thinking_param = request.thinking?.type === \"disabled\"\n ? undefined\n : request.thinking?.type === \"enabled\" && request.thinking.budgetTokens\n ? { type: \"enabled\" as const, budget_tokens: request.thinking.budgetTokens }\n : request.thinking?.type === \"adaptive\"\n ? { type: \"enabled\" as const, budget_tokens: options.max_tokens - 1 }\n : undefined;\n\n const response = await client.messages.create({\n model: request.model,\n max_tokens: options.max_tokens,\n temperature: options.temperature,\n top_p: options.top_p,\n system: systemMessage?.content,\n messages: convertMessages(request.messages),\n tools,\n tool_choice,\n ...(thinking_param && { thinking: thinking_param }),\n } as any); // Type assertion needed for web_search_20250305\n\n const duration = Date.now() - startTime;\n\n let content = \"\";\n let thinking = \"\";\n let toolCalls: any[] | undefined;\n\n // Handle multiple content blocks\n for (const block of response.content) {\n if (block.type === \"text\") {\n content += block.text;\n } else if ((block as any).type === \"thinking\") {\n thinking += (block as any).thinking ?? \"\";\n } else if (block.type === \"tool_use\") {\n // If this is the structured output tool, extract content from it\n if (block.name === \"structured_output\" && request.output?.schema) {\n content = JSON.stringify(block.input || {});\n } else {\n // Regular tool call\n if (!toolCalls) toolCalls = [];\n toolCalls.push({\n id: block.id,\n name: block.name,\n args: JSON.stringify(block.input || {}),\n status: \"pending\" as const,\n });\n }\n }\n }\n\n return {\n content,\n thinking: thinking || undefined,\n toolCalls,\n metadata: {\n usage: {\n inputTokens: response.usage?.input_tokens || 0,\n outputTokens: response.usage?.output_tokens || 0,\n totalTokens:\n (response.usage?.input_tokens || 0) +\n (response.usage?.output_tokens || 0),\n cachedTokens: (response.usage as any)?.cache_read_input_tokens || 0,\n },\n model: request.model,\n options,\n duration,\n provider: \"anthropic\",\n },\n };\n } catch (error) {\n throw new Error(\n `Anthropic API error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n\n async function* stream(\n _ctx: Context,\n request: QueryLLMRequest,\n _options?: LLMQueryOptions,\n ): AsyncGenerator<QueryLLMResponse> {\n try {\n const options = {\n max_tokens: request.options?.maxTokens ?? 4096,\n temperature: request.options?.temperature,\n top_p: request.options?.topP,\n };\n\n const startTime = Date.now();\n\n const systemMessage = request.messages.find((m) => m.role === \"system\");\n\n // Check if webSearch tool is present and convert to native web search\n const hasWebSearch = request.tools?.some((t) => t.name === \"webSearch\");\n const otherTools =\n request.tools?.filter((t) => t.name !== \"webSearch\") || [];\n\n // If structured output is requested, use tool calling approach\n const tools = request.output?.schema\n ? [\n {\n name: \"structured_output\",\n description: \"Respond with a structured JSON object\",\n input_schema: request.output.schema,\n },\n ...(hasWebSearch\n ? [\n {\n type: \"web_search_20250305\" as const,\n name: \"web_search\",\n max_uses: 5,\n },\n ]\n : []),\n ...(otherTools.length > 0 ? convertTools(otherTools) : []),\n ]\n : hasWebSearch\n ? [\n {\n type: \"web_search_20250305\" as const,\n name: \"web_search\",\n max_uses: 5,\n },\n ...(otherTools.length > 0 ? convertTools(otherTools) : []),\n ]\n : otherTools.length > 0\n ? convertTools(otherTools)\n : undefined;\n\n const tool_choice = request.output?.schema\n ? {\n type: \"tool\" as const,\n name: \"structured_output\",\n disable_parallel_tool_use: true,\n }\n : undefined;\n\n // Map ThinkingConfig to Anthropic thinking parameter\n const thinking_param = request.thinking?.type === \"disabled\"\n ? undefined\n : request.thinking?.type === \"enabled\" && request.thinking.budgetTokens\n ? { type: \"enabled\" as const, budget_tokens: request.thinking.budgetTokens }\n : request.thinking?.type === \"adaptive\"\n ? { type: \"enabled\" as const, budget_tokens: options.max_tokens - 1 }\n : undefined;\n\n const streamResponse = client.messages.stream({\n model: request.model,\n max_tokens: options.max_tokens,\n temperature: options.temperature,\n top_p: options.top_p,\n system: systemMessage?.content,\n messages: convertMessages(request.messages),\n tools: tools as any, // Type assertion needed for web_search_20250305\n tool_choice,\n ...(thinking_param && { thinking: thinking_param }),\n });\n\n let usage = {\n input_tokens: 0,\n output_tokens: 0,\n };\n const toolCalls: any[] = [];\n let currentToolUse: {\n id: string;\n name: string;\n inputJson: string;\n } | null = null;\n\n for await (const chunk of streamResponse) {\n // Update usage from message_delta events\n if (chunk.type === \"message_delta\" && (chunk as any).usage) {\n usage = (chunk as any).usage;\n }\n\n // Track content block starts (tool_use)\n if (\n chunk.type === \"content_block_start\" &&\n (chunk as any).content_block?.type === \"tool_use\"\n ) {\n const block = (chunk as any).content_block;\n currentToolUse = {\n id: block.id,\n name: block.name,\n inputJson: \"\",\n };\n }\n\n // Handle content block deltas\n if (chunk.type === \"content_block_delta\") {\n const deltaType = (chunk.delta as any)?.type;\n\n if (deltaType === \"text_delta\") {\n // Yield text chunks\n yield {\n content: (chunk.delta as any).text || \"\",\n metadata: {\n usage: {\n inputTokens: usage.input_tokens || 0,\n outputTokens: usage.output_tokens || 0,\n totalTokens:\n (usage.input_tokens || 0) + (usage.output_tokens || 0),\n },\n model: request.model,\n options,\n duration: Date.now() - startTime,\n provider: \"anthropic\",\n },\n };\n } else if (deltaType === \"thinking_delta\") {\n // Yield thinking chunks\n yield {\n content: \"\",\n thinking: (chunk.delta as any).thinking || \"\",\n metadata: {\n usage: {\n inputTokens: usage.input_tokens || 0,\n outputTokens: usage.output_tokens || 0,\n totalTokens:\n (usage.input_tokens || 0) + (usage.output_tokens || 0),\n },\n model: request.model,\n options,\n duration: Date.now() - startTime,\n provider: \"anthropic\",\n },\n };\n } else if (deltaType === \"input_json_delta\" && currentToolUse) {\n currentToolUse.inputJson += (chunk.delta as any).partial_json || \"\";\n }\n // signature_delta — ignored\n }\n\n // Finalize tool call on content_block_stop\n if (chunk.type === \"content_block_stop\" && currentToolUse) {\n toolCalls.push({\n id: currentToolUse.id,\n name: currentToolUse.name,\n args: currentToolUse.inputJson || \"{}\",\n status: \"pending\" as const,\n });\n currentToolUse = null;\n }\n }\n\n // Yield final chunk with tool calls if any were accumulated\n if (toolCalls.length > 0) {\n yield {\n content: \"\",\n toolCalls,\n metadata: {\n usage: {\n inputTokens: usage.input_tokens || 0,\n outputTokens: usage.output_tokens || 0,\n totalTokens:\n (usage.input_tokens || 0) + (usage.output_tokens || 0),\n },\n model: request.model,\n options,\n duration: Date.now() - startTime,\n provider: \"anthropic\",\n },\n };\n }\n } catch (error) {\n throw new Error(\n `Anthropic streaming error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n\n async function getModels(): Promise<Model[]> {\n return anthropicModels.list();\n }\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n\n function parseToolArgs(str: string): Record<string, unknown> {\n if (!str || str.trim() === \"\") return {};\n try {\n return JSON.parse(str);\n } catch (err) {\n console.warn(\"Failed to parse tool call args:\", err);\n return {};\n }\n }\n\n function convertMessages(\n messages: (Message | MultimodalMessage)[],\n ): MessageParam[] {\n return (\n messages\n ?.filter((msg) => msg.role !== \"system\") // Anthropic handles system messages separately\n ?.map((msg): MessageParam => {\n switch (msg.role) {\n case \"user\":\n if (msg.content && Array.isArray(msg.content)) {\n return {\n role: \"user\",\n content: msg.content\n .filter(\n (\n part: ContentPart,\n ): part is TextContentPart | ImageContentPart =>\n part.type === \"text\" || part.type === \"image\",\n )\n .map((part: TextContentPart | ImageContentPart) => {\n if (part.type === \"image\") {\n return {\n type: \"image\" as const,\n source: {\n type: \"base64\" as const,\n media_type: part.mimeType as\n | \"image/jpeg\"\n | \"image/png\"\n | \"image/gif\"\n | \"image/webp\",\n data: part.data,\n },\n };\n }\n return {\n type: \"text\" as const,\n text: part.text,\n };\n }),\n };\n } else {\n return {\n role: \"user\",\n content: msg.content || \"\",\n };\n }\n\n case \"assistant\": {\n const assistantMsg = msg as any;\n\n // Check if there are tool calls\n if (assistantMsg.toolCalls && assistantMsg.toolCalls.length > 0) {\n const content: any[] = [];\n if (assistantMsg.content) {\n content.push({\n type: \"text\" as const,\n text: assistantMsg.content,\n });\n }\n for (const tc of assistantMsg.toolCalls) {\n content.push({\n type: \"tool_use\" as const,\n id: tc.id,\n name: tc.name,\n input:\n typeof tc.args === \"string\"\n ? parseToolArgs(tc.args)\n : tc.args || {},\n });\n }\n return { role: \"assistant\", content };\n }\n\n return {\n role: \"assistant\",\n content: assistantMsg.content || \"\",\n };\n }\n\n case \"tool\": {\n // Anthropic expects tool results in user messages with tool_result content blocks\n const toolMsg = msg as any;\n return {\n role: \"user\",\n content: [\n {\n type: \"tool_result\" as const,\n tool_use_id: toolMsg.toolCallId,\n content: toolMsg.content,\n },\n ],\n };\n }\n\n default:\n throw new Error(`Unsupported message role: ${(msg as any).role}`);\n }\n }) || []\n );\n }\n\n function convertTools(tools: any[]): any[] {\n return (\n tools?.map((tool) => ({\n name: tool.name,\n description: tool.description,\n input_schema: tool.input,\n })) || []\n );\n }\n\n function configure(overrides: Record<string, unknown>): AnthropicProvider {\n return provider({ ...finalConfig, ...overrides } as Config);\n }\n\n return {\n name: \"anthropic\",\n query,\n stream,\n getModels,\n configure,\n };\n}\n","/**\n * Anthropic model definitions\n */\n\nimport type { Model } from \"@jarvis/types\";\n\nexport const claude3Haiku: Model = {\n id: \"claude-3-haiku-20240307\",\n name: \"Claude 3 Haiku\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 4096 },\n cost: { multiplier: 8, inputTokens: 0.25, outputTokens: 1.25 },\n};\n\nexport const claude37Sonnet: Model = {\n id: \"claude-3-7-sonnet-20241022\",\n name: \"Claude 3.7 Sonnet\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: { multiplier: 20, inputTokens: 3.00, outputTokens: 15.00 },\n options: {\n temperature: 0.4,\n topP: 0.95,\n },\n};\n\nexport const claude35Haiku: Model = {\n id: \"claude-3-5-haiku-20241022\",\n name: \"Claude 3.5 Haiku\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: { multiplier: 8, inputTokens: 0.80, outputTokens: 4.00 },\n};\n\nexport const claude4Sonnet: Model = {\n id: \"claude-sonnet-4-20250514\",\n name: \"Claude 4 Sonnet\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: { multiplier: 20, inputTokens: 3.00, outputTokens: 15.00 },\n};\n\nexport const claude4Opus: Model = {\n id: \"claude-opus-4-20250514\",\n name: \"Claude 4 Opus\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: { multiplier: 50, inputTokens: 15.00, outputTokens: 75.00 },\n};\n\nexport const claudeSonnet45: Model = {\n id: \"claude-sonnet-4-5-20250929\",\n name: \"Claude Sonnet 4.5\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: { multiplier: 20, inputTokens: 3.00, outputTokens: 15.00 },\n};\n\nexport const claudeOpus41: Model = {\n id: \"claude-opus-4-1-20250514\",\n name: \"Claude Opus 4.1\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: { multiplier: 50, inputTokens: 15.00, outputTokens: 75.00 },\n};\n\nexport const claudeHaiku45: Model = {\n id: \"claude-haiku-4-5-20251001\",\n name: \"Claude Haiku 4.5\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: { multiplier: 8, inputTokens: 1.00, outputTokens: 5.00 },\n};\n\nexport const claudeOpus46: Model = {\n id: \"claude-opus-4-6-20250515\",\n name: \"Claude Opus 4.6\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 16384 },\n cost: { multiplier: 50, inputTokens: 5.00, outputTokens: 25.00 },\n};\n\n// Claude Code models (routed via \"claude-code\" provider tag, not model ID)\nexport const claudeCodeSonnet: Model = {\n id: \"claude-sonnet-4-5-20250929\",\n name: \"Claude Code (Sonnet)\",\n provider: \"claude-code\",\n maxTokens: { input: 200_000, output: 16384 },\n cost: { multiplier: 20, inputTokens: 3.00, outputTokens: 15.00 },\n};\n\nexport const claudeCodeOpus: Model = {\n id: \"claude-opus-4-6-20250515\",\n name: \"Claude Code (Opus)\",\n provider: \"claude-code\",\n maxTokens: { input: 200_000, output: 16384 },\n cost: { multiplier: 50, inputTokens: 5.00, outputTokens: 25.00 },\n};\n\n// All Anthropic models\nexport const anthropicModels = {\n claude3Haiku,\n claude37Sonnet,\n claude35Haiku,\n claude4Sonnet,\n claude4Opus,\n claudeSonnet45,\n claudeOpus41,\n claudeHaiku45,\n claudeOpus46,\n\n list: (): Model[] => [\n claude3Haiku,\n claude37Sonnet,\n claude35Haiku,\n claude4Sonnet,\n claude4Opus,\n claudeSonnet45,\n claudeOpus41,\n claudeHaiku45,\n claudeOpus46,\n ],\n};\n\n// Claude Code models registry\nexport const claudeCodeModels = {\n claudeCodeSonnet,\n claudeCodeOpus,\n\n list: (): Model[] => [claudeCodeSonnet, claudeCodeOpus],\n};\n","/**\n * LLM (Large Language Model) related types\n */\n\nimport type {\n TTSVoice,\n TTSModel,\n TTSResponseFormat,\n} from \"../media/tts.types\";\n\nimport type { Message, MultimodalMessage } from \"./message.types\";\nimport type { Usage } from \"./usage.types\";\nimport { Context } from \"../core/context.types\";\nimport {\n Model,\n ResolveModelRequest,\n ResolveModelResponse,\n} from \"./model.types\";\nimport { Provider } from \"../core/provider.types\";\nimport { Schema } from \"../core/schema.types\";\nimport { ToolCall, Tool } from \"./tool.types\";\n\n// Re-export message types for backward compatibility\nexport type {\n MessageRole,\n Message,\n MultimodalMessage,\n BaseMessage,\n UserMessage,\n AssistantMessage,\n SystemMessage,\n ToolMessage,\n ContentPart,\n TextContentPart,\n AudioContentPart,\n ImageContentPart,\n} from \"./message.types\";\n\n// =============================================================================\n// OUTPUT CONFIGURATION\n// =============================================================================\n\n/** Output format types — what the response should include */\nexport type OutputFormat = \"text\" | \"audio\" | \"json\";\n\n/** Audio-specific output configuration */\nexport interface AudioOutputConfig {\n /** TTS voice (defaults to \"nova\") */\n voice?: TTSVoice;\n /** TTS model (defaults to \"tts-1\") */\n model?: TTSModel;\n /** Audio response format (defaults to \"mp3\") */\n format?: TTSResponseFormat;\n}\n\n/**\n * Output configuration for LLM response delivery.\n *\n * Controls both LLM output format (json with schema) and\n * response delivery formats (text, audio).\n *\n * Valid format combinations:\n * - `[\"text\"]` — text only (default)\n * - `[\"text\", \"audio\"]` — text + audio (voice mode)\n * - `[\"json\"]` — JSON structured output (standalone, requires schema)\n *\n * @example Text only (default)\n * ```typescript\n * { formats: [\"text\"] }\n * ```\n *\n * @example Text + audio (voice mode)\n * ```typescript\n * { formats: [\"text\", \"audio\"], audio: { voice: \"nova\" } }\n * ```\n *\n * @example JSON structured output\n * ```typescript\n * { formats: [\"json\"], schema: mySchema }\n * ```\n */\nexport interface LLMQueryOutput {\n /**\n * Which formats to include in the response. Defaults to [\"text\"].\n * Valid: [\"text\"], [\"text\", \"audio\"], or [\"json\"].\n */\n formats?: [\"text\"] | [\"text\", \"audio\"] | [\"json\"];\n /** JSON schema — required when formats is [\"json\"] */\n schema?: Schema;\n /** Audio-specific settings — used when \"audio\" is in formats */\n audio?: AudioOutputConfig;\n}\n\n/** Check if an output config includes a specific format */\nexport function hasOutputFormat(\n output: LLMQueryOutput | undefined,\n format: OutputFormat,\n): boolean {\n return (output?.formats as string[] | undefined)?.includes(format) ?? false;\n}\n\n// =============================================================================\n// THINKING CONFIG\n// =============================================================================\n\n/**\n * Thinking/reasoning configuration — provider-agnostic.\n *\n * Providers map this to their native format:\n * - Anthropic: adaptive → `thinking: { type: \"enabled\" }`, enabled → `thinking: { budget_tokens }`\n * - Gemini: maps to `thinkingConfig.thinkingLevel` or `thinkingBudget`\n * - OpenAI: maps to `reasoning_effort`\n * - Providers without support: ignore the field\n */\nexport interface ThinkingConfig {\n /** Thinking mode */\n type: \"adaptive\" | \"enabled\" | \"disabled\";\n /** Token budget for thinking (only used with type: \"enabled\") */\n budgetTokens?: number;\n}\n\n// =============================================================================\n// LLM QUERY TYPES\n// =============================================================================\n\nexport interface QueryLLMRequest {\n model: string;\n messages: (Message | MultimodalMessage)[];\n tools?: Tool[];\n output?: LLMQueryOutput;\n thinking?: ThinkingConfig;\n options?: {\n temperature?: number;\n maxTokens?: number;\n topP?: number;\n };\n}\n\nexport interface LLMQueryOptions {\n /** Override provider selection (bypass model-based routing) */\n provider?: string;\n /** Set false to suppress Redis token streaming (for internal LLM calls like query understanding) */\n stream?: boolean;\n}\n\nexport interface QueryLLMResponse {\n content: string;\n /** JSON structured output (when output format is \"json\" and SDK returns structured_output) */\n json?: string;\n /** Error from the SDK (e.g. error_max_turns, error_max_budget_usd) */\n error?: string;\n thinking?: string;\n toolCalls?: ToolCall[];\n metadata?: QueryLLMMetadata;\n /** Claude Code session ID from the SDK (for session resume support) */\n sessionId?: string;\n /** Why the LLM stopped generating — populated by providers from API response */\n stopReason?: StopReason;\n}\n\n/** Why the LLM stopped generating */\nexport type StopReason =\n | \"end_turn\"\n | \"max_tokens\"\n | \"tool_use\"\n | \"stop_sequence\"\n | \"content_filter\";\n\nexport interface QueryLLMMetadata {\n model: string;\n usage: Usage;\n options?: {\n temperature?: number;\n maxTokens?: number;\n topP?: number;\n };\n duration: number;\n provider: string;\n}\n\n// LLM Client interface\nexport interface LLMProvider extends Provider {\n query(\n ctx: Context,\n req: QueryLLMRequest,\n options?: LLMQueryOptions,\n ): Promise<QueryLLMResponse>;\n stream(\n ctx: Context,\n req: QueryLLMRequest,\n options?: LLMQueryOptions,\n ): AsyncGenerator<QueryLLMResponse>;\n getModels?(): Promise<Model[]>;\n /** Create a new instance with different config (e.g., different API key for BYOK) */\n configure?(config: Record<string, unknown>): LLMProvider;\n /** Optional provider-specific request validation. Called by the router before query/stream. */\n validateQuery?(ctx: Context, req: QueryLLMRequest): QueryLLMRequest;\n}\n\n// ============================================================================\n// LLM Resolvers\n// ============================================================================\n\nexport interface ResolveLLMProviderRequest {\n providerName?: string;\n providers: LLMProvider[];\n}\n\nexport interface ResolveLLMProviderResponse {\n provider: LLMProvider;\n}\n\nexport interface LLMProviderResolver extends Provider {\n resolve(\n request: ResolveLLMProviderRequest,\n ): Promise<ResolveLLMProviderResponse>;\n}\n\nexport interface ModelResolver extends Provider {\n resolve(request: ResolveModelRequest): Promise<ResolveModelResponse>;\n}\n\nexport interface ResolveOptionsRequest {\n requestOptions?: QueryLLMRequest[\"options\"];\n modelOptions?: QueryLLMRequest[\"options\"];\n}\n\nexport interface ResolveOptionsResponse {\n options?: QueryLLMRequest[\"options\"];\n}\n\nexport interface OptionsResolver extends Provider {\n resolve(request: ResolveOptionsRequest): Promise<ResolveOptionsResponse>;\n}\n","import type { Context } from \"../core/context.types\";\nimport type { TranslateFn } from \"../core/translation.types\";\nimport { Schema } from \"../core/schema.types\";\nimport type { Usage } from \"./usage.types\";\n\n// =============================================================================\n// Tool UI (Unified — MCP iframe OR chat component)\n// =============================================================================\n\n/**\n * ToolUi — discriminated union for rich rendering.\n *\n * Component variant: renders in chat via artifact router\n * Resource variant: renders as MCP iframe via ui:// resource\n */\nexport type ToolUi = ToolUiComponent | ToolUiResource;\n\nexport interface ToolUiComponent {\n /** MCP-style URI: \"ui://appId/componentType\" (e.g., \"ui://chef/recipe\") */\n uri: string;\n /** Display title for the component card */\n title: string;\n /** Data payload — auto-populated from tool output when omitted in after hook */\n data?: unknown;\n /** Preferred height in pixels */\n height?: number;\n}\n\nexport interface ToolUiResource {\n /** URI of the MCP UI resource (e.g., \"ui://server/dashboard\") */\n resourceUri: string;\n /** Title override for the artifact card */\n title?: string;\n /** Preferred iframe height in pixels */\n height?: number;\n /** Extra data passed to the rendering component (e.g., html, serverName) */\n data?: unknown;\n}\n\n// =============================================================================\n// Tool Permissions (Declarative Access Control)\n// =============================================================================\n\n/**\n * Declarative permissions for a tool.\n * Combines RBAC (roles/tiers) with risk classification.\n */\nexport interface ToolPermissions {\n /** Required roles (checked vs ctx.access.role) */\n roles?: string[];\n /** Required tiers (checked vs ctx.access.tier) */\n tiers?: string[];\n /**\n * Risk level — drives permission mode behavior:\n * - \"safe\": auto-allow (read, search, list)\n * - \"moderate\": allow by default, log (create, update)\n * - \"dangerous\": ask user first (delete, send, execute)\n */\n risk?: \"safe\" | \"moderate\" | \"dangerous\";\n /**\n * When to ask for user approval (if applicable based on risk + mode).\n * - \"before\": ask BEFORE execution (default)\n * - \"after\": execute first, then ask for confirmation\n * Only applies when the harness auto-asks (no custom hook defined).\n */\n ask?: \"before\" | \"after\";\n /** Can run in parallel with other tools (default: true) */\n concurrent?: boolean;\n /** Resource scopes (future: OAuth/MCP) */\n scopes?: string[];\n}\n\n// =============================================================================\n// Tool Metadata (all display, permissions, and provider config)\n// =============================================================================\n\n/** Context provided to metadata describe function */\nexport interface ToolMetadataContext {\n toolName: string;\n toolCallId: string;\n}\n\n/** Request passed to the describe function */\nexport interface DescribeToolRequest {\n status: ToolCallStatus;\n input: Record<string, unknown>;\n output?: unknown;\n error?: string;\n durationMs?: number;\n}\n\n/** Options passed as 3rd argument to metadata.describe() */\nexport interface DescribeToolOptions {\n t: TranslateFn;\n}\n\n/**\n * Tool metadata — all display, permissions, UI, and provider configuration.\n */\nexport interface ToolMetadata {\n /** Human-readable tool name for UI display (e.g., \"Create Recipe\") */\n label?: string;\n\n /** Generate phase description for the tool message UI */\n describe?: (\n ctx: ToolMetadataContext,\n req: DescribeToolRequest,\n options?: DescribeToolOptions,\n ) => string | undefined;\n\n /**\n * When true, tool calls are not displayed in the conversation UI.\n * The tool still runs normally — it's just invisible to the user.\n */\n hidden?: boolean;\n\n /**\n * Native provider that handles lifecycle.\n * When set, the tool is handled by the named provider's internal loop\n * rather than by callTool().\n */\n provider?: string;\n\n /** Declarative permissions — RBAC + risk classification */\n permissions?: ToolPermissions;\n\n /** UI component config — MCP iframe or chat component */\n ui?: ToolUi;\n\n /** Max tool output size in characters before truncation (default: 50000) */\n maxOutputSize?: number;\n}\n\n// =============================================================================\n// Tool Definition\n// =============================================================================\n\n/**\n * Tool definition — serializable schema + optional execution fields.\n *\n * Core fields (name, description, input, output) are always serializable.\n * Execution fields (call, hooks, metadata, build) are added by the SDK\n * `tool()` factory and used by the agent runner.\n */\nexport interface Tool {\n name: string;\n description: string;\n input: Schema;\n output: Schema;\n\n // === Execution ===\n\n /** Function to execute the tool */\n call?: CallTool;\n\n /**\n * Schema-only builder — called by buildTools() at the start of each iteration\n * to produce a tool with state-dependent schemas (e.g., dynamic enum values).\n */\n build?: (ctx: Context, req: { tool: Tool; state: unknown }) => Tool;\n\n // === Configuration ===\n\n /** All display, permissions, UI, and provider configuration */\n metadata?: ToolMetadata;\n\n // === Lifecycle Hooks ===\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n hooks?: ToolHooks<any>;\n}\n\n/**\n * Tool handler function.\n *\n * Signature: (ctx, input, options?) => output\n * ctx from runner, options pre-bound by buildTools.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type CallTool = (...args: any[]) => Promise<any>;\n\n// =============================================================================\n// Ask User (human-in-the-loop)\n// =============================================================================\n\n/** User's response action */\nexport type UserInputAction = \"allow\" | \"deny\" | \"modify\";\n\nexport interface UserInputResponse {\n action: UserInputAction;\n data?: Record<string, unknown>;\n feedback?: string;\n}\n\n/** User input with correlation ID */\nexport interface UserInput extends UserInputResponse {\n id: string;\n}\n\n/**\n * Request for user input — raw data preview, rich UI component, or reason-only.\n */\nexport type UserInputRequest =\n | { reason?: string; data: unknown; ui?: never }\n | { reason?: string; data?: never; ui: ToolUi };\n\n/**\n * Options passed to tool hooks (third argument)\n */\nexport interface ToolHookOptions {\n /** Request user input (human-in-the-loop). Pauses until user responds. */\n askUser: (req?: UserInputRequest) => Promise<UserInputResponse | null>;\n /** Current agent mode — hooks can use this to decide behavior per mode. */\n mode: string;\n}\n\n// =============================================================================\n// Tool Hook Types\n// =============================================================================\n\n/**\n * Hook called before tool execution.\n *\n * Return values:\n * - `{ action: \"allow\" }` — proceed (optionally with modified input)\n * - `{ action: \"deny\", reason }` — reject execution\n */\nexport type BeforeToolHook<TState = unknown> = (\n ctx: Context,\n req: {\n toolName: string;\n input: unknown;\n toolCallId: string;\n state: TState;\n },\n options: ToolHookOptions,\n) => Promise<{ action: \"allow\"; input?: unknown } | { action: \"deny\"; reason: string }>;\n\n/** Unified tool call status */\nexport type ToolCallStatus = \"running\" | \"completed\" | \"modify\" | \"denied\" | \"error\";\n\n/**\n * Hook called after tool execution.\n */\nexport type AfterToolHook<TState = unknown> = (\n ctx: Context,\n req: {\n toolName: string;\n input: unknown;\n output: unknown;\n toolCallId: string;\n state: TState;\n ui?: ToolUi;\n },\n options: ToolHookOptions,\n) => Promise<{\n /** Lightweight context for LLM */\n context: unknown;\n /** State update (partial merge) */\n state?: Partial<TState>;\n /** UI override — if omitted and metadata.ui exists, auto-generated from tool output */\n ui?: ToolUi;\n /** Tool call result status */\n status?: ToolCallStatus;\n /** Human-readable message */\n message?: string;\n /** Pruning instructions */\n prune?: {\n removeTools?: string[];\n keepRecent?: number;\n };\n /** Resource usage */\n usage?: Usage;\n}>;\n\n/** Tool hooks container */\nexport interface ToolHooks<TState = unknown> {\n before?: BeforeToolHook<TState>;\n after?: AfterToolHook<TState>;\n}\n\n// =============================================================================\n// Hook Identity Functions (type narrowing without generics on tool())\n// =============================================================================\n\nexport function before<TState>(fn: BeforeToolHook<TState>): BeforeToolHook<TState> {\n return fn;\n}\n\nexport function after<TState>(fn: AfterToolHook<TState>): AfterToolHook<TState> {\n return fn;\n}\n\n// =============================================================================\n// Tool Call Types\n// =============================================================================\n\nexport interface CallToolRequest {\n tool: Tool;\n args: unknown;\n}\n\nexport interface CallToolResponse {\n output: string;\n}\n\nexport interface ToolCallError {\n tool: string;\n error: string;\n args?: string;\n}\n\nexport interface ToolCall {\n id: string;\n name: string;\n args: string;\n status: \"pending\" | \"completed\" | \"failed\";\n output?: string;\n error?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ResolveToolRequest {\n tool: string | Tool;\n available: Tool[];\n}\n\nexport interface ResolveToolResponse {\n tool: Tool;\n}\n","/**\n * TTS (Text-to-Speech) related types\n *\n * Provider-agnostic TTS interface. Voice and model are opaque strings —\n * each provider interprets them in its own context (e.g., OpenAI \"nova\"\n * vs ElevenLabs voice IDs like \"cgSgspJ2msm6clMCkdW9\").\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { ModelCost } from \"../agents/model.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// VOICE, MODEL, FORMAT\n// =============================================================================\n\n/** Provider-agnostic voice identifier (string — each provider defines its own) */\nexport type TTSVoice = string;\n\n/** Provider-agnostic model identifier */\nexport type TTSModel = string;\n\n/** Audio output format — shared across providers */\nexport type TTSResponseFormat = \"mp3\" | \"opus\" | \"aac\" | \"flac\" | \"wav\" | \"pcm\";\n\n// OpenAI-specific convenience constants\nexport const OPENAI_TTS_VOICES = [\"alloy\", \"echo\", \"fable\", \"onyx\", \"nova\", \"shimmer\"] as const;\nexport type OpenAITTSVoice = (typeof OPENAI_TTS_VOICES)[number];\n\nexport const OPENAI_TTS_MODELS = [\"tts-1\", \"tts-1-hd\"] as const;\nexport type OpenAITTSModel = (typeof OPENAI_TTS_MODELS)[number];\n\n// Backwards-compatible runtime constants (used by OpenAI provider validation)\nexport const TTS_VOICES: string[] = [...OPENAI_TTS_VOICES];\nexport const TTS_MODELS: string[] = [...OPENAI_TTS_MODELS];\nexport const TTS_FORMATS: TTSResponseFormat[] = [\"mp3\", \"opus\", \"aac\", \"flac\", \"wav\", \"pcm\"];\n\n// =============================================================================\n// REQUEST / RESPONSE\n// =============================================================================\n\nexport interface TTSRequest {\n /** The text to convert to speech */\n text: string;\n /** The voice to use for speech synthesis */\n voice?: TTSVoice;\n /** The model to use for speech synthesis */\n model?: TTSModel;\n /** Speed of the generated audio (0.25 to 4.0) */\n speed?: number;\n /** The format of the audio output */\n responseFormat?: TTSResponseFormat;\n /** Explicit provider routing (e.g., \"openai\", \"elevenlabs\") */\n provider?: string;\n /** Provider-specific voice settings (stability, similarity_boost, etc.) */\n voiceSettings?: Record<string, unknown>;\n}\n\nexport interface TTSResponse {\n /** Raw audio buffer */\n audioBuffer: Buffer;\n /** Base64-encoded audio data */\n audioBase64: string;\n /** MIME type of the audio */\n mimeType: string;\n}\n\n// =============================================================================\n// MODEL / VOICE DEFINITIONS\n// =============================================================================\n\n/** TTS model definition — follows the same pattern as Model in model.types.ts */\nexport interface TTSModelDef {\n /** Model identifier (e.g., \"tts-1\", \"eleven_turbo_v2\") */\n id: string;\n /** Human-readable name (e.g., \"TTS-1\", \"Eleven Turbo v2\") */\n name: string;\n /** Provider name (e.g., \"openai\", \"elevenlabs\") */\n provider: string;\n /** Provider-specific options */\n options?: Record<string, unknown>;\n /** Cost configuration for billing and estimation */\n cost: ModelCost;\n}\n\n/** TTS voice definition — a named voice with provider and default settings */\nexport interface TTSVoiceDef {\n /** Voice identifier (e.g., \"nova\", \"cgSgspJ2msm6clMCkdW9\") */\n id: string;\n /** Human-readable name (e.g., \"Nova\", \"Scarlett\") */\n name: string;\n /** Provider name (e.g., \"openai\", \"elevenlabs\") */\n provider: string;\n /** Default voice settings (e.g., { stability: 0.5, similarityBoost: 0.8 }) */\n options?: Record<string, unknown>;\n}\n\n// =============================================================================\n// TTS PROVIDER\n// =============================================================================\n\n/**\n * TTSProvider — platform-provided text-to-speech.\n *\n * Implementations: OpenAI (`@jarvis/openai`), ElevenLabs (`@jarvis/elevenlabs`).\n * Multi-provider routing: `@jarvis/tts`.\n */\nexport interface TTSProvider extends Provider {\n /** Convert text to speech audio */\n speech(ctx: Context, request: TTSRequest): Promise<TTSResponse>;\n /** List available TTS models for this provider */\n getModels?(): TTSModelDef[];\n /** List available voices for this provider */\n getVoices?(): TTSVoiceDef[];\n /** Create a new instance with different config (e.g., different API key for BYOK) */\n configure?(config: Record<string, unknown>): TTSProvider;\n}\n","/**\n * Claude Code provider\n *\n * Wraps the @anthropic-ai/claude-agent-sdk. Returns { content, toolCalls: undefined }\n * so the orchestrator exits after 1 iteration — Claude Code handles its own tool loop internally.\n *\n * Routing is by provider (\"claude-code\"), not model ID. The model ID passed in\n * (e.g. \"claude-sonnet-4-5-20250929\") goes straight to the SDK.\n *\n * Tool interception (canUseTool):\n * - When `onUserInput` is provided, every SDK tool call is converted to a PendingUserInput\n * and forwarded to the consumer via the callback. The consumer decides per-tool what to do.\n * - Tools with hooks.before: Provider invokes the hook, which calls wait() with artifact data.\n * The wait() creates an enriched PendingUserInput and routes through onUserInput.\n * - AskUserQuestion: Specific converter → structured questions format for AskUserPanel\n * - All other tools: Generic converter → raw toolName + input\n * - When no `onUserInput` is provided, falls back to bypassPermissions (backwards compatible)\n *\n * After-hook invocation:\n * - When a \"user\" message arrives (tool_result), the provider invokes after hooks for tracked tools.\n * - Artifacts from after hooks are attached to the message as `_toolUi` map.\n * - The worker reads `_toolUi` when creating tool completion messages.\n */\n\nimport { logger } from \"@jarvis/logger\";\nimport { claudeCodeModels } from \"./anthropic.models\";\nimport { context as createContext } from \"@jarvis/sdk\";\nimport type {\n Context,\n QueryLLMRequest,\n QueryLLMResponse,\n LLMProvider,\n LLMQueryOptions,\n Model,\n PendingUserInput,\n ToolUiData,\n UserInputResponse,\n ToolHookOptions,\n} from \"@jarvis/types\";\nimport { hasOutputFormat } from \"@jarvis/types\";\n\nimport type { ClaudeCodeConfig, ProviderTool } from \"./claude-code.types\";\n\n// SDK types imported dynamically; declare the shapes we need for canUseTool.\n// Note: SDK Zod validation requires updatedInput on the \"allow\" variant.\ntype PermissionResult =\n | {\n behavior: \"allow\";\n updatedInput: Record<string, unknown>;\n toolUseID?: string;\n }\n | {\n behavior: \"deny\";\n message: string;\n interrupt?: boolean;\n toolUseID?: string;\n };\n\nlet _idCounter = 0;\nfunction generateId(): string {\n return `pui-${Date.now()}-${++_idCounter}`;\n}\n\n/**\n * Convert AskUserQuestion tool call to a PendingUserInput\n * with structured questions format matching AskUserPanel expectations.\n */\nfunction convertAskUserQuestion(\n input: Record<string, unknown>,\n toolUseID: string,\n): PendingUserInput {\n return {\n id: generateId(),\n type: \"tool\",\n toolName: \"askUser\",\n toolCallId: toolUseID,\n output: {\n questions: input.questions,\n },\n timing: \"before\",\n };\n}\n\n/**\n * Convert any other tool call to a generic PendingUserInput.\n * The consumer (worker) decides what to do based on toolName.\n */\nfunction convertGenericTool(\n toolName: string,\n input: Record<string, unknown>,\n toolUseID: string,\n): PendingUserInput {\n return {\n id: generateId(),\n type: \"tool\",\n toolName,\n toolCallId: toolUseID,\n input,\n timing: \"before\",\n };\n}\n\n/**\n * Convert a UserInputResponse from the consumer back to an SDK PermissionResult.\n * For AskUserQuestion, the response data contains answers that need to flow back.\n */\nfunction toPermissionResult(\n toolName: string,\n originalInput: Record<string, unknown>,\n response: UserInputResponse,\n toolUseID: string,\n): PermissionResult {\n if (response.action === \"deny\") {\n return {\n behavior: \"deny\",\n message: response.feedback || \"User denied the tool call\",\n toolUseID,\n };\n }\n\n // For AskUserQuestion, pass answers back as updatedInput so the SDK\n // receives them as the tool's \"result\"\n if (toolName === \"AskUserQuestion\" && response.data) {\n return {\n behavior: \"allow\",\n updatedInput: {\n answers: response.data,\n },\n toolUseID,\n };\n }\n\n // SDK Zod schema requires updatedInput for the \"allow\" variant —\n // pass the original input through unchanged.\n return { behavior: \"allow\", updatedInput: originalInput, toolUseID };\n}\n\n// =============================================================================\n// Shared permission + hook infrastructure\n// =============================================================================\n\ninterface PermissionOptions {\n opts: Record<string, unknown>;\n toolMap: Map<string, ProviderTool>;\n toolInputTracker: Map<\n string,\n { toolName: string; input: Record<string, unknown> }\n >;\n}\n\n/**\n * Build permission options shared by both query() and stream().\n * When tools with hooks are provided, canUseTool invokes the before hook.\n */\nfunction buildPermissionOptions(\n ctx: Context,\n config: ClaudeCodeConfig,\n): PermissionOptions {\n const toolMap = new Map<string, ProviderTool>();\n for (const t of config.tools ?? []) toolMap.set(t.name, t);\n\n const toolInputTracker = new Map<\n string,\n { toolName: string; input: Record<string, unknown> }\n >();\n\n if (!config.onUserInput) {\n return {\n opts: {\n permissionMode: \"bypassPermissions\" as const,\n allowDangerouslySkipPermissions: true,\n },\n toolMap,\n toolInputTracker,\n };\n }\n\n const canUseTool = async (\n toolName: string,\n input: Record<string, unknown>,\n options: { toolUseID: string; signal: AbortSignal },\n ): Promise<PermissionResult> => {\n // Track tool input for after-hook invocation\n toolInputTracker.set(options.toolUseID, { toolName, input });\n\n const t = toolMap.get(toolName);\n\n // If tool has a before hook, invoke it — the hook creates the PendingUserInput\n // with artifact data via wait()\n if (t?.hooks?.before) {\n const req = {\n toolName,\n input,\n toolCallId: options.toolUseID,\n state: {} as unknown,\n };\n const hookOptions: ToolHookOptions = {\n mode: config.permissionMode ?? \"default\",\n askUser: async (waitOpts?) => {\n const pendingInput: PendingUserInput = {\n id: generateId(),\n type: \"tool\" as const,\n toolName,\n toolCallId: options.toolUseID,\n input,\n timing: \"before\" as const,\n ...(waitOpts?.data\n ? { output: waitOpts.data }\n : waitOpts?.ui\n ? { output: waitOpts.ui }\n : {}),\n reason: waitOpts?.reason,\n };\n return config.onUserInput!(pendingInput);\n },\n };\n\n const result = await t.hooks.before(ctx, req, hookOptions);\n if (result.action === \"deny\") {\n return {\n behavior: \"deny\",\n message: (result as { reason?: string }).reason ?? \"Denied\",\n toolUseID: options.toolUseID,\n };\n }\n return {\n behavior: \"allow\",\n updatedInput:\n ((result as { input?: unknown }).input as Record<string, unknown>) ||\n input,\n toolUseID: options.toolUseID,\n };\n }\n\n // No before hook — use specific converters for known tools, generic for others\n const pendingInput =\n toolName === \"AskUserQuestion\"\n ? convertAskUserQuestion(input, options.toolUseID)\n : convertGenericTool(toolName, input, options.toolUseID);\n\n const response = await config.onUserInput!(pendingInput);\n return toPermissionResult(toolName, input, response, options.toolUseID);\n };\n\n return {\n opts: {\n permissionMode: (config.permissionMode ?? \"default\") as\n | \"default\"\n | \"plan\",\n canUseTool,\n },\n toolMap,\n toolInputTracker,\n };\n}\n\n/**\n * Process after hooks for a \"user\" message (tool_result).\n * Returns a map of toolUseId → ToolUiData for enrichment.\n */\nasync function processAfterHooks(\n ctx: Context,\n req: {\n message: any;\n config: ClaudeCodeConfig;\n toolMap: Map<string, ProviderTool>;\n toolInputTracker: Map<\n string,\n { toolName: string; input: Record<string, unknown> }\n >;\n },\n): Promise<Record<string, ToolUiData> | null> {\n const { message, config, toolInputTracker, toolMap } = req;\n if (message.type !== \"user\" || !Array.isArray(message.message?.content))\n return null;\n\n const artifactMap: Record<string, ToolUiData> = {};\n let hasArtifacts = false;\n\n for (const block of message.message.content) {\n const toolUseId = block?.tool_use_id;\n if (!toolUseId) continue;\n\n const tracked = toolInputTracker.get(toolUseId);\n const t = tracked ? toolMap.get(tracked.toolName) : null;\n\n if (t?.hooks?.after) {\n try {\n const afterResult = await t.hooks.after(\n ctx,\n {\n toolName: tracked!.toolName,\n input: tracked!.input,\n output: block.content ?? block.output,\n toolCallId: toolUseId,\n state: {} as unknown,\n },\n { mode: config.permissionMode ?? \"default\", askUser: async () => ({ action: \"allow\" as const }) },\n );\n\n // Bridge ToolUi → ToolUiData for chat messages\n if (afterResult.ui && \"uri\" in afterResult.ui) {\n const { uri, title, data } = afterResult.ui as {\n uri: string;\n title: string;\n data?: unknown;\n };\n const match = uri.match(/^ui:\\/\\/([^/]+)\\/(.+)$/);\n artifactMap[toolUseId] = {\n type: match?.[2] || uri,\n title,\n data,\n };\n hasArtifacts = true;\n }\n } catch (err) {\n logger.sys.error(`After hook error for ${tracked!.toolName}`, {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n toolInputTracker.delete(toolUseId);\n }\n\n return hasArtifacts ? artifactMap : null;\n}\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nexport function claudeCodeProvider(config: ClaudeCodeConfig = {}): LLMProvider {\n const useSubscription = config.useSubscription ?? false;\n const apiKey = useSubscription\n ? undefined\n : (config.apiKey ?? process.env.ANTHROPIC_API_KEY);\n\n async function query(\n ctx: Context,\n req: QueryLLMRequest,\n _options?: LLMQueryOptions,\n ): Promise<QueryLLMResponse> {\n const { query: claudeQuery } =\n await import(\"@anthropic-ai/claude-agent-sdk\");\n if (!apiKey && !useSubscription) {\n throw new Error(\n \"Anthropic API key is required. \" +\n \"Provide it via config.apiKey, ANTHROPIC_API_KEY env var, or set useSubscription: true.\",\n );\n }\n\n const startTime = Date.now();\n\n // Extract user message and system prompt\n const userMessage = [...req.messages]\n .reverse()\n .find((m) => m.role === \"user\");\n const prompt = userMessage?.content ?? \"\";\n const systemMessage = req.messages.find((m) => m.role === \"system\");\n const systemPrompt = config.systemPrompt ?? systemMessage?.content ?? \"\";\n\n let aggregatedContent = \"\";\n let lastAssistantContent = \"\";\n let json: string | undefined;\n let sdkError: string | undefined;\n let inputTokens = 0;\n let outputTokens = 0;\n let resultSessionId: string | undefined;\n\n // When resuming, skip setting systemPrompt — SDK uses the original session's prompt\n const isResuming = !!config.session?.resume;\n const systemPromptOption = isResuming\n ? undefined\n : systemPrompt\n ? {\n type: \"preset\" as const,\n preset: \"claude_code\" as const,\n append: typeof systemPrompt === \"string\" ? systemPrompt : \"\",\n }\n : undefined;\n\n // Build permission options (shared helper — hook-aware when tools provided)\n const {\n opts: permissionOptions,\n toolMap,\n toolInputTracker,\n } = buildPermissionOptions(ctx, config);\n\n logger.info(ctx, \"[ClaudeCode] Starting query\", {\n model: req.model,\n hasApiKey: !!apiKey,\n promptLength: typeof prompt === \"string\" ? prompt.length : 0,\n cwd: config.workingDirectory,\n mcpServers: Object.keys(config.mcpServers || {}),\n });\n\n let messageCount = 0;\n try {\n for await (const message of claudeQuery({\n prompt: typeof prompt === \"string\" ? prompt : JSON.stringify(prompt),\n options: {\n model: req.model,\n systemPrompt: systemPromptOption,\n ...(config.maxTurns ? { maxTurns: config.maxTurns } : {}),\n ...permissionOptions,\n ...(config.mcpServers ? { mcpServers: config.mcpServers } : {}),\n ...(config.workingDirectory ? { cwd: config.workingDirectory } : {}),\n ...(hasOutputFormat(config.output, \"json\") && config.output?.schema\n ? {\n outputFormat: {\n type: \"json_schema\" as const,\n schema: config.output.schema,\n },\n }\n : {}),\n ...(config.disallowedTools?.length\n ? { disallowedTools: config.disallowedTools }\n : {}),\n ...(config.abortController\n ? { abortController: config.abortController }\n : {}),\n ...(config.thinking ? { thinking: config.thinking } : {}),\n // Session resume/persistence options\n ...(config.session?.sessionId\n ? { sessionId: config.session.sessionId }\n : {}),\n ...(config.session?.resume ? { resume: config.session.resume } : {}),\n ...(config.session?.persistSession !== undefined\n ? { persistSession: config.session.persistSession }\n : {}),\n ...(config.session?.forkSession\n ? { forkSession: config.session.forkSession }\n : {}),\n env: {\n ...(apiKey ? { ANTHROPIC_API_KEY: apiKey } : {}),\n ...(useSubscription ? {} : { IS_SANDBOX: \"1\" }),\n HOME: process.env.HOME ?? \"\",\n PATH: process.env.PATH ?? \"\",\n TMPDIR: process.env.TMPDIR ?? \"\",\n NODE_ENV: process.env.NODE_ENV ?? \"\",\n },\n debugFile: \"/tmp/claude-code-debug.log\",\n stderr: (data: string) =>\n logger.error(ctx, \"[ClaudeCode stderr]\", { data }),\n },\n })) {\n messageCount++;\n logger.info(ctx, \"[ClaudeCode] SDK message\", {\n count: messageCount,\n type: message.type,\n });\n\n // Skip replayed messages during session resume — they're old history.\n // Still heartbeat so the activity stays alive during replay.\n if ((message as any).isReplay) {\n if (config.heartbeat) config.heartbeat();\n continue;\n }\n\n if (config.heartbeat) {\n config.heartbeat();\n }\n\n // Track tool inputs from \"assistant\" messages for safe tools that bypass canUseTool\n // (SDK auto-approves Read, Glob, Grep without calling canUseTool in default mode)\n if (\n message.type === \"assistant\" &&\n Array.isArray(message.message?.content)\n ) {\n for (const block of message.message.content) {\n if (block?.type === \"tool_use\" && block.id && block.name) {\n if (!toolInputTracker.has(block.id)) {\n toolInputTracker.set(block.id, {\n toolName: block.name,\n input: (block.input || {}) as Record<string, unknown>,\n });\n }\n }\n }\n }\n\n // Process after hooks for tool_result messages — enrich with artifacts\n const artifacts = await processAfterHooks(ctx, {\n message,\n config,\n toolMap,\n toolInputTracker,\n });\n if (artifacts) {\n (message as any)._toolUi = artifacts;\n }\n\n // Forward all SDK messages for rich progress tracking\n if (config.onProgress) {\n await config.onProgress(message);\n // Heartbeat after async progress handling — may take time\n if (config.heartbeat) config.heartbeat();\n }\n\n if (message.type === \"assistant\" && message.message?.content) {\n lastAssistantContent = \"\";\n for (const block of message.message.content) {\n if (typeof block === \"string\") {\n lastAssistantContent += block;\n aggregatedContent += block;\n if (config.onChunk) config.onChunk(block);\n } else if (block.type === \"text\") {\n lastAssistantContent += block.text;\n aggregatedContent += block.text;\n if (config.onChunk) config.onChunk(block.text);\n }\n }\n }\n\n if (message.type === \"result\") {\n // Detect SDK error results (max_turns, budget, etc.)\n const subtype = (message as any).subtype;\n if (subtype && subtype !== \"success\") {\n const errors = (message as any).errors as string[] | undefined;\n sdkError = `Agent ${subtype}${errors?.length ? `: ${errors.join(\", \")}` : \"\"}`;\n }\n\n // Keep structured output separate — don't overwrite text content\n const structuredOutput = (message as any).structured_output;\n if (\n structuredOutput !== undefined &&\n hasOutputFormat(config.output, \"json\")\n ) {\n json =\n typeof structuredOutput === \"string\"\n ? structuredOutput\n : JSON.stringify(structuredOutput);\n }\n\n // Text result from SDK — use as content if we have no assistant text yet\n if (\"result\" in message && !aggregatedContent) {\n aggregatedContent = (message as any).result;\n }\n\n if (\"usage\" in message) {\n const usage = (message as any).usage;\n inputTokens = usage?.input_tokens ?? 0;\n outputTokens = usage?.output_tokens ?? 0;\n }\n\n // Extract session ID for resume support\n resultSessionId = (message as any).session_id;\n }\n }\n } catch (error) {\n logger.error(ctx, \"[ClaudeCode] Query error\", {\n error: error instanceof Error ? error.message : String(error),\n model: req.model,\n apiKeyPresent: !!apiKey,\n cwd: config.workingDirectory,\n mcpServers: Object.keys(config.mcpServers || {}),\n });\n throw error;\n }\n\n logger.info(ctx, \"[ClaudeCode] Query complete\", { messageCount });\n\n return {\n content: lastAssistantContent || aggregatedContent,\n json,\n error: sdkError,\n toolCalls: undefined,\n sessionId: resultSessionId,\n metadata: {\n model: req.model,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n duration: Date.now() - startTime,\n provider: \"claude-code\",\n },\n };\n }\n\n async function* stream(\n ctx: Context,\n req: QueryLLMRequest,\n _options?: LLMQueryOptions,\n ): AsyncGenerator<QueryLLMResponse> {\n const { query: claudeQuery } =\n await import(\"@anthropic-ai/claude-agent-sdk\");\n if (!apiKey && !useSubscription) {\n throw new Error(\n \"Anthropic API key is required. \" +\n \"Provide it via config.apiKey, ANTHROPIC_API_KEY env var, or set useSubscription: true.\",\n );\n }\n\n const startTime = Date.now();\n\n const userMessage = [...req.messages]\n .reverse()\n .find((m) => m.role === \"user\");\n const prompt = userMessage?.content ?? \"\";\n const systemMessage = req.messages.find((m) => m.role === \"system\");\n const systemPrompt = config.systemPrompt ?? systemMessage?.content ?? \"\";\n\n let inputTokens = 0;\n let outputTokens = 0;\n\n // When resuming, skip setting systemPrompt — SDK uses the original session's prompt\n const isResuming = !!config.session?.resume;\n const streamSystemPromptOption = isResuming\n ? undefined\n : systemPrompt\n ? {\n type: \"preset\" as const,\n preset: \"claude_code\" as const,\n append: typeof systemPrompt === \"string\" ? systemPrompt : \"\",\n }\n : undefined;\n\n // Build permission options (shared helper — hook-aware when tools provided)\n const {\n opts: permissionOptions,\n toolMap,\n toolInputTracker,\n } = buildPermissionOptions(ctx, config);\n\n logger.info(ctx, \"[ClaudeCode] Starting stream\", {\n model: req.model,\n hasApiKey: !!apiKey,\n promptLength: typeof prompt === \"string\" ? prompt.length : 0,\n cwd: config.workingDirectory,\n mcpServers: Object.keys(config.mcpServers || {}),\n });\n\n let messageCount = 0;\n try {\n for await (const message of claudeQuery({\n prompt: typeof prompt === \"string\" ? prompt : JSON.stringify(prompt),\n options: {\n model: req.model,\n systemPrompt: streamSystemPromptOption,\n ...(config.maxTurns ? { maxTurns: config.maxTurns } : {}),\n ...permissionOptions,\n ...(config.mcpServers ? { mcpServers: config.mcpServers } : {}),\n ...(config.workingDirectory ? { cwd: config.workingDirectory } : {}),\n ...(hasOutputFormat(config.output, \"json\") && config.output?.schema\n ? {\n outputFormat: {\n type: \"json_schema\" as const,\n schema: config.output.schema,\n },\n }\n : {}),\n ...(config.disallowedTools?.length\n ? { disallowedTools: config.disallowedTools }\n : {}),\n ...(config.abortController\n ? { abortController: config.abortController }\n : {}),\n ...(config.thinking ? { thinking: config.thinking } : {}),\n // Session resume/persistence options\n ...(config.session?.sessionId\n ? { sessionId: config.session.sessionId }\n : {}),\n ...(config.session?.resume ? { resume: config.session.resume } : {}),\n ...(config.session?.persistSession !== undefined\n ? { persistSession: config.session.persistSession }\n : {}),\n ...(config.session?.forkSession\n ? { forkSession: config.session.forkSession }\n : {}),\n env: {\n ...(apiKey ? { ANTHROPIC_API_KEY: apiKey } : {}),\n ...(useSubscription ? {} : { IS_SANDBOX: \"1\" }),\n HOME: process.env.HOME ?? \"\",\n PATH: process.env.PATH ?? \"\",\n TMPDIR: process.env.TMPDIR ?? \"\",\n NODE_ENV: process.env.NODE_ENV ?? \"\",\n },\n debugFile: \"/tmp/claude-code-debug.log\",\n stderr: (data: string) =>\n logger.error(ctx, \"[ClaudeCode stderr]\", { data }),\n },\n })) {\n messageCount++;\n logger.info(ctx, \"[ClaudeCode] SDK message\", {\n count: messageCount,\n type: message.type,\n });\n\n // Skip replayed messages during session resume — they're old history.\n // Still heartbeat so the activity stays alive during replay.\n if ((message as any).isReplay) {\n if (config.heartbeat) config.heartbeat();\n continue;\n }\n\n if (config.heartbeat) config.heartbeat();\n\n // Track tool inputs from \"assistant\" messages for safe tools that bypass canUseTool\n if (\n message.type === \"assistant\" &&\n Array.isArray(message.message?.content)\n ) {\n for (const block of message.message.content) {\n if (block?.type === \"tool_use\" && block.id && block.name) {\n if (!toolInputTracker.has(block.id)) {\n toolInputTracker.set(block.id, {\n toolName: block.name,\n input: (block.input || {}) as Record<string, unknown>,\n });\n }\n }\n }\n }\n\n // Process after hooks for tool_result messages — enrich with artifacts\n const artifacts = await processAfterHooks(ctx, {\n message,\n config,\n toolMap,\n toolInputTracker,\n });\n if (artifacts) {\n (message as any)._toolUi = artifacts;\n }\n\n if (config.onProgress) {\n await config.onProgress(message);\n if (config.heartbeat) config.heartbeat();\n }\n\n // Yield incremental text chunks as Claude Code produces them\n if (message.type === \"assistant\" && message.message?.content) {\n for (const block of message.message.content) {\n const text =\n typeof block === \"string\"\n ? block\n : block.type === \"text\"\n ? block.text\n : \"\";\n if (text) {\n if (config.onChunk) config.onChunk(text);\n yield {\n content: text,\n metadata: {\n model: req.model,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n duration: Date.now() - startTime,\n provider: \"claude-code\",\n },\n };\n }\n }\n }\n\n if (message.type === \"result\") {\n if (\"usage\" in message) {\n const usage = (message as any).usage;\n inputTokens = usage?.input_tokens ?? 0;\n outputTokens = usage?.output_tokens ?? 0;\n }\n // Keep structured output separate from text content\n const structuredOutput = (message as any).structured_output;\n const sc =\n structuredOutput !== undefined &&\n hasOutputFormat(config.output, \"json\")\n ? typeof structuredOutput === \"string\"\n ? structuredOutput\n : JSON.stringify(structuredOutput)\n : undefined;\n // Final yield with updated usage metadata\n yield {\n content: \"\", // Text already yielded incrementally\n json: sc,\n metadata: {\n model: req.model,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n duration: Date.now() - startTime,\n provider: \"claude-code\",\n },\n };\n }\n }\n } catch (error) {\n logger.error(ctx, \"[ClaudeCode] Stream error\", {\n error: error instanceof Error ? error.message : String(error),\n model: req.model,\n apiKeyPresent: !!apiKey,\n cwd: config.workingDirectory,\n mcpServers: Object.keys(config.mcpServers || {}),\n });\n throw error;\n }\n\n logger.info(ctx, \"[ClaudeCode] Stream complete\", { messageCount });\n }\n\n async function getModels(): Promise<Model[]> {\n return claudeCodeModels.list();\n }\n\n return {\n name: \"claude-code\",\n query,\n stream,\n getModels,\n };\n}\n","/**\n * Tools Domain\n * Pure functions for creating and calling tools\n */\nimport type {\n CallTool,\n Context,\n ToolHooks,\n BeforeToolHook,\n AfterToolHook,\n Tool,\n ToolMetadata,\n Schema,\n ToolHookOptions,\n} from \"@jarvis/types\";\n\n// Re-export hook identity functions from types\nexport { before, after } from \"@jarvis/types\";\n\n// =============================================================================\n// extractHooks() - Extract hooks from tools for agent creation\n// =============================================================================\n\nexport function extractHooks<TState = unknown>(\n tools: Tool[],\n): {\n before: Record<string, BeforeToolHook<TState>>;\n after: Record<string, AfterToolHook<TState>>;\n} {\n const before: Record<string, BeforeToolHook<TState>> = {};\n const after: Record<string, AfterToolHook<TState>> = {};\n\n for (const t of tools) {\n if (t.hooks?.before) {\n before[t.name] = t.hooks.before as BeforeToolHook<TState>;\n }\n if (t.hooks?.after) {\n after[t.name] = t.hooks.after as AfterToolHook<TState>;\n }\n }\n\n return { before, after };\n}\n\n// =============================================================================\n// tool() Factory\n// =============================================================================\n\n/**\n * Create a tool with optional colocated hooks.\n *\n * @example\n * ```typescript\n * const myTool = tool({\n * name: \"createGoal\",\n * description: \"Create a new goal\",\n * schema: {\n * input: { type: \"object\", properties: { title: { type: \"string\" } } },\n * output: { type: \"object\", properties: { goalId: { type: \"string\" } } },\n * },\n * call: async (ctx, input) => ({ goalId: \"g-123\" }),\n * metadata: {\n * label: \"Create Goal\",\n * permissions: { roles: [\"editor\"], risk: \"moderate\" },\n * ui: { component: \"goals\", title: \"Goals\" },\n * },\n * hooks: {\n * before: before<MyState>(async (ctx, req, { askUser }) => ({ action: \"allow\" })),\n * after: after<MyState>(async (ctx, req) => ({\n * context: { created: true },\n * state: { goals: [...req.state.goals, req.output] },\n * })),\n * },\n * });\n * ```\n */\nexport function tool<TState = unknown>(config: {\n name: string;\n description: string;\n schema: { input: Schema; output: Schema };\n call?: CallTool;\n hooks?: ToolHooks<TState>;\n metadata?: ToolMetadata;\n build?: (ctx: unknown, req: { tool: Tool; state: TState }) => Tool;\n}): Tool {\n return {\n name: config.name,\n description: config.description,\n input: config.schema.input,\n output: config.schema.output,\n call: config.call,\n hooks: config.hooks,\n metadata: config.metadata,\n build: config.build as Tool[\"build\"],\n };\n}\n\n// =============================================================================\n// buildTools() - Apply build() to tools with current state\n// =============================================================================\n\n/**\n * Build tools by applying schema builders and pre-binding options.\n *\n * Three phases per tool:\n * 1. Apply permissions check via before hook (if metadata.permissions is set)\n * 2. Apply `build()` for schema-only changes (dynamic enums from state)\n * 3. Wrap `call()` to pre-bind options (if call has >= 2 params)\n * 4. Wrap hooks to spread app options flat into hook options\n */\nexport function buildTools(\n ctx: Context,\n req: { tools: Tool[]; state: unknown },\n options?: unknown,\n): Tool[] {\n return req.tools.map((t) => {\n // Phase 0: If tool has permissions, inject a before hook that checks roles/tiers\n const permissions = t.metadata?.permissions;\n if (permissions?.roles?.length || permissions?.tiers?.length) {\n const existingBefore = t.hooks?.before;\n t = {\n ...t,\n hooks: {\n ...t.hooks,\n before: async (hookCtx: Context, hookReq: { toolName: string; input: unknown; toolCallId: string; state: unknown }, hookOpts: ToolHookOptions) => {\n const access = (hookCtx as Context & { access?: { role?: string; tier?: string } }).access;\n const role = access?.role ?? \"\";\n const tier = access?.tier ?? \"free\";\n if (permissions.roles?.length && !permissions.roles.includes(role)) {\n return { action: \"deny\" as const, reason: \"Access denied: insufficient role\" };\n }\n if (permissions.tiers?.length && !permissions.tiers.includes(tier)) {\n return { action: \"deny\" as const, reason: \"Access denied: insufficient tier\" };\n }\n if (existingBefore) return existingBefore(hookCtx, hookReq, hookOpts);\n return { action: \"allow\" as const };\n },\n },\n };\n }\n\n // Phase 1: Apply build (schema-only, no options)\n const built = t.build ? t.build(ctx, { tool: t, state: req.state }) : t;\n if (options == null) return built;\n\n const result = { ...built };\n\n // Phase 2: Wrap call to pre-bind options (if call has >= 2 params)\n if (result.call && result.call.length >= 2) {\n const baseCall = result.call as (\n ctx: Context,\n input: unknown,\n options?: unknown,\n ) => Promise<unknown>;\n result.call = ((ctxArg: Context, input: unknown) =>\n baseCall(ctxArg, input, options)) as CallTool;\n }\n\n // Phase 3: Wrap hooks to spread app options flat into hook options\n if (result.hooks) {\n const baseHooks = result.hooks;\n result.hooks = {\n before: baseHooks.before\n ? async (ctx: Context, req: { toolName: string; input: unknown; toolCallId: string; state: unknown }, hookOpts: ToolHookOptions) =>\n baseHooks.before!(ctx, req, {\n ...hookOpts,\n ...(options as object),\n } as ToolHookOptions)\n : undefined,\n after: baseHooks.after\n ? async (ctx: Context, req: unknown, hookOpts: ToolHookOptions) =>\n baseHooks.after!(ctx, req as Parameters<NonNullable<typeof baseHooks.after>>[1], {\n ...hookOpts,\n ...(options as object),\n } as ToolHookOptions)\n : undefined,\n };\n }\n\n return result;\n });\n}\n\n/**\n * Call a tool directly (for testing or simple invocation).\n */\nexport async function call(req: { tool: Tool; input: unknown }): Promise<unknown> {\n if (!req.tool.call) {\n throw new Error(\n `Tool ${req.tool.name} has no call function.`,\n );\n }\n return await req.tool.call(req.input);\n}\n","/**\n * Plan Tool\n * Platform-level tool for presenting plans to users for approval\n *\n * This tool allows agents to present a plan (list of steps) to the user\n * and wait for approval/modification before proceeding.\n *\n * @example\n * ```typescript\n * import { planTool } from \"@jarvis/sdk\";\n *\n * const tools = [planTool, ...otherTools];\n *\n * // Agent can now use the plan tool:\n * // LLM: \"I'll create a plan for you to review\"\n * // Tool call: plan({ title: \"...\", steps: [...], reasoning: \"...\" })\n * // → User sees PlanPanel in UI\n * // → User approves/modifies/rejects\n * // → Agent continues based on user response\n * ```\n */\nimport { Context } from \"@jarvis/types\";\nimport { tool } from \"./tools\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * A single step in a plan\n */\nexport interface PlanStep {\n /** Unique identifier for the step */\n id: string;\n /** Step title (brief description) */\n title: string;\n /** Optional detailed description */\n description?: string;\n /** Optional category for grouping/styling */\n category?: string;\n}\n\n/**\n * Input for the plan tool\n */\nexport interface PlanInput {\n /** Plan title shown in the header */\n title: string;\n /** List of steps in the plan */\n steps: PlanStep[];\n /** Optional reasoning explaining why this plan */\n reasoning?: string;\n}\n\n/**\n * Output from the plan tool\n */\nexport interface PlanOutput {\n /** Plan title */\n title: string;\n /** Plan items (steps mapped to items) */\n items: PlanStep[];\n /** Optional reasoning */\n reasoning?: string;\n}\n\n// =============================================================================\n// SCHEMA\n// =============================================================================\n\nconst planInputSchema = {\n type: \"object\" as const,\n properties: {\n title: {\n type: \"string\",\n description: \"A brief title for the plan\",\n },\n steps: {\n type: \"array\",\n description: \"The steps in the plan\",\n items: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Unique identifier for this step\",\n },\n title: {\n type: \"string\",\n description: \"Brief title for the step\",\n },\n description: {\n type: \"string\",\n description: \"Detailed description of what this step involves\",\n },\n category: {\n type: \"string\",\n description:\n \"Optional category for grouping (e.g., 'setup', 'implementation', 'testing')\",\n },\n },\n required: [\"id\", \"title\"],\n },\n },\n reasoning: {\n type: \"string\",\n description: \"Explanation of why this plan was chosen\",\n },\n },\n required: [\"title\", \"steps\"],\n};\n\nconst planOutputSchema = {\n type: \"object\" as const,\n properties: {\n title: { type: \"string\" },\n items: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n id: { type: \"string\" },\n title: { type: \"string\" },\n description: { type: \"string\" },\n category: { type: \"string\" },\n },\n },\n },\n reasoning: { type: \"string\" },\n },\n};\n\n// =============================================================================\n// TOOL\n// =============================================================================\n\n/**\n * Plan tool for presenting plans to users\n *\n * Usage:\n * - Agent calls this tool to present a plan\n * - Tool output is shown in PlanPanel UI component\n * - User can approve, reject, or modify the plan\n * - Agent receives user's response via the after hook\n */\nexport const planTool = tool({\n name: \"plan\",\n description:\n \"Present a plan to the user for approval before executing. Use this when you need user confirmation before proceeding with a multi-step task. The user can approve, reject, or suggest modifications to the plan.\",\n schema: {\n input: planInputSchema,\n output: planOutputSchema,\n },\n // The call function simply passes through the input as output\n // The actual plan review happens in the after hook via wait()\n call: async (_ctx: Context, input: PlanInput): Promise<PlanOutput> => ({\n title: input.title,\n items: input.steps,\n reasoning: input.reasoning,\n }),\n // Hooks handle the human-in-the-loop approval flow\n hooks: {\n // After hook waits for user approval\n after: async (ctx, req, options) => {\n const planOutput = req.output as PlanOutput;\n\n // Wait for user input (shows PlanPanel in UI)\n const userInput = await options.askUser({\n reason: planOutput.title,\n data: planOutput,\n });\n\n // Handle user response\n if (!userInput || userInput.action === \"deny\") {\n return {\n context: {\n status: \"denied\",\n message: userInput?.feedback || \"Plan was rejected by user\",\n },\n status: \"denied\",\n message: userInput?.feedback || \"Plan was rejected by user\",\n };\n }\n\n if (userInput.action === \"modify\") {\n return {\n context: {\n status: \"modify\",\n userFeedback: userInput.feedback,\n originalPlan: planOutput,\n },\n status: \"modify\",\n message: userInput.feedback || \"User requested modifications\",\n };\n }\n\n // Approved\n return {\n context: {\n status: \"approved\",\n plan: planOutput,\n message: \"Plan approved by user. Proceed with execution.\",\n },\n ui: {\n uri: \"ui://sdk/plan\",\n title: planOutput.title,\n data: planOutput,\n },\n };\n },\n },\n // Metadata for UI display\n metadata: {\n describe: (ctx, req) => {\n const input = req.input as unknown as PlanInput;\n if (req.status === \"running\") {\n return `Creating plan: ${input.title}`;\n }\n if (req.status === \"completed\") {\n return `Plan \"${input.title}\" ready for review`;\n }\n return undefined;\n },\n },\n});\n","/**\n * Ask User Tool\n * Platform-level tool for asking users structured questions\n *\n * This tool allows agents to ask clarifying questions with predefined options,\n * pausing execution until the user responds. Each question appears as a tab\n * with selectable options and an \"Other\" free-text input.\n *\n * @example\n * ```typescript\n * import { askUserTool } from \"@jarvis/sdk\";\n *\n * const tools = [askUserTool, ...otherTools];\n *\n * // Agent can now use the askUser tool:\n * // LLM: \"I need to understand your preference\"\n * // Tool call: askUser({ questions: [{ header: \"Approach\", question: \"...\", options: [...] }] })\n * // → User sees AskUserPanel in UI\n * // → User selects options or types custom answer\n * // → Agent continues with user's answers\n * ```\n */\nimport { tool } from \"./tools\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * A single option within a question\n */\nexport interface AskUserOption {\n /** Display label for the option */\n label: string;\n /** Optional description explaining the option */\n description?: string;\n}\n\n/**\n * A single question with options\n */\nexport interface AskUserQuestion {\n /** Short label displayed as tab header (max ~12 chars) */\n header: string;\n /** Full question text */\n question: string;\n /** Available options (2-4) */\n options: AskUserOption[];\n /** Whether user can select multiple options (default: false) */\n multiSelect?: boolean;\n}\n\n/**\n * Input for the askUser tool\n */\nexport interface AskUserInput {\n /** Questions to ask (1-4) */\n questions: AskUserQuestion[];\n}\n\n/**\n * A single answer from the user\n */\nexport interface AskUserAnswer {\n /** Header of the question being answered */\n header: string;\n /** Selected option label(s) */\n selected: string[];\n /** Custom text if user chose \"Other\" */\n customText?: string;\n}\n\n/**\n * Output from the askUser tool\n */\nexport interface AskUserOutput {\n /** The questions that were asked */\n questions: AskUserQuestion[];\n /** User's answers (populated after user responds) */\n answers?: AskUserAnswer[];\n}\n\n// =============================================================================\n// SCHEMA\n// =============================================================================\n\nconst askUserInputSchema = {\n type: \"object\" as const,\n properties: {\n questions: {\n type: \"array\",\n description: \"Questions to ask the user (1-4 questions)\",\n minItems: 1,\n maxItems: 4,\n items: {\n type: \"object\",\n properties: {\n header: {\n type: \"string\",\n description:\n \"Short label for the tab header (e.g., 'Approach', 'Priority')\",\n },\n question: {\n type: \"string\",\n description: \"The full question to ask the user\",\n },\n options: {\n type: \"array\",\n description:\n \"Available options (2-4). User always has an 'Other' free-text option automatically.\",\n minItems: 2,\n maxItems: 4,\n items: {\n type: \"object\",\n properties: {\n label: {\n type: \"string\",\n description: \"Option display label\",\n },\n description: {\n type: \"string\",\n description: \"Optional explanation of this option\",\n },\n },\n required: [\"label\"],\n },\n },\n multiSelect: {\n type: \"boolean\",\n description:\n \"Whether user can select multiple options (default: false)\",\n },\n },\n required: [\"header\", \"question\", \"options\"],\n },\n },\n },\n required: [\"questions\"],\n};\n\nconst askUserOutputSchema = {\n type: \"object\" as const,\n properties: {\n questions: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n header: { type: \"string\" },\n question: { type: \"string\" },\n options: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n label: { type: \"string\" },\n description: { type: \"string\" },\n },\n },\n },\n multiSelect: { type: \"boolean\" },\n },\n },\n },\n answers: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n header: { type: \"string\" },\n selected: { type: \"array\", items: { type: \"string\" } },\n customText: { type: \"string\" },\n },\n },\n },\n },\n};\n\n// =============================================================================\n// TOOL\n// =============================================================================\n\n/**\n * Ask User tool for structured questions\n *\n * Usage:\n * - Agent calls this tool to ask the user questions\n * - Tool output is shown in AskUserPanel UI component\n * - User can select options or type custom answers\n * - Agent receives user's answers via the after hook\n */\nexport const askUserTool = tool({\n name: \"askUser\",\n description: `Ask the user clarifying questions when you need their input to proceed. Use this when the request is ambiguous, you need a preference between approaches, or the scope/priority is unclear. Each question has predefined options plus a free-text 'Other' option. Do NOT use this for plan approval (use exitPlanMode instead) or internal reasoning (use think instead).\n\nGuidelines:\n- Do NOT ask questions you can resolve using available tools\n- Prefer making reasonable defaults over asking — only ask when the choice genuinely matters\n- Keep header labels concise (1-4 words like 'Approach', 'Priority')\n- Mark the recommended option with '(Recommended)' suffix\n- In plan mode, questions should relate to the plan being developed`,\n schema: {\n input: askUserInputSchema,\n output: askUserOutputSchema,\n },\n // Pass-through: returns questions as output for UI rendering\n call: async (_ctx, input: AskUserInput): Promise<AskUserOutput> => ({\n questions: input.questions,\n }),\n // After hook waits for user answers\n hooks: {\n after: async (ctx, req, options) => {\n const output = req.output as AskUserOutput;\n\n // Wait for user input (shows AskUserPanel in UI)\n const userInput = await options.askUser({\n reason:\n output.questions.length === 1\n ? output.questions[0]!.question\n : `${output.questions.length} questions to answer`,\n data: output,\n });\n\n // Handle user skip/cancel\n if (!userInput || userInput.action === \"deny\") {\n return {\n context: {\n status: \"skipped\",\n message:\n userInput?.feedback ||\n \"User skipped the questions. Proceed with your best judgment.\",\n },\n status: \"denied\",\n message: userInput?.feedback || \"User skipped the questions\",\n };\n }\n\n // Extract answers from user response\n const answers = (userInput.data as { answers?: AskUserAnswer[] })\n ?.answers;\n\n if (!answers || answers.length === 0) {\n return {\n context: {\n status: \"skipped\",\n message: \"No answers provided. Proceed with your best judgment.\",\n },\n status: \"denied\",\n message: \"No answers provided\",\n };\n }\n\n // Format answers for LLM context\n const formattedAnswers = answers\n .map((a) => {\n const selection =\n a.selected.length > 0\n ? a.selected.join(\", \")\n : a.customText || \"No selection\";\n return `${a.header}: ${selection}`;\n })\n .join(\"\\n\");\n\n return {\n context: {\n status: \"answered\",\n answers,\n summary: formattedAnswers,\n message: `User answered:\\n${formattedAnswers}`,\n },\n ui: {\n uri: \"ui://sdk/ask-user\",\n title: \"User Answers\",\n data: { questions: output.questions, answers },\n },\n };\n },\n },\n // Metadata for UI display\n metadata: {\n permissions: { risk: \"safe\" },\n describe: (ctx, req) => {\n const input = req.input as unknown as AskUserInput;\n if (req.status === \"running\") {\n return input.questions?.length === 1\n ? `Asking: ${input.questions[0]!.header}`\n : `Asking ${input.questions?.length || 0} questions`;\n }\n if (req.status === \"completed\") {\n const output = req.output as AskUserOutput;\n if (output?.answers) {\n return `Answered ${output.answers.length} question${output.answers.length !== 1 ? \"s\" : \"\"}`;\n }\n return \"Questions skipped\";\n }\n return undefined;\n },\n },\n});\n","/**\n * Think Tool\n *\n * Platform-level internal reasoning tool. No side effects.\n * The agent uses this to organize thoughts, reflect, and plan\n * before taking action. Hidden from conversation UI.\n */\n\nimport { Context } from \"@jarvis/types\";\n\nimport { tool } from \"./tools\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface ThinkInput {\n thought: string;\n}\n\nexport interface ThinkOutput {\n acknowledged: boolean;\n}\n\n// =============================================================================\n// Schemas\n// =============================================================================\n\nconst thinkInputSchema = {\n type: \"object\" as const,\n properties: {\n thought: {\n type: \"string\",\n description: \"Your internal reasoning, reflection, or planning\",\n },\n },\n required: [\"thought\"],\n};\n\nconst thinkOutputSchema = {\n type: \"object\" as const,\n properties: {\n acknowledged: { type: \"boolean\" },\n },\n};\n\n// =============================================================================\n// Tool\n// =============================================================================\n\n/**\n * Internal reasoning tool — no side effects, hidden from UI.\n * Use for organizing thoughts before acting.\n */\nexport const thinkTool = tool({\n name: \"think\",\n description: `Use this tool for internal reasoning, reflection, and planning your next steps. No side effects — output is never shown to the user.\n\nGood uses:\n- Breaking down complex problems into steps\n- Evaluating trade-offs between approaches\n- Synthesizing information from multiple tool results\n- Planning multi-step operations before acting\n\nThis consumes tokens like any other tool call. Use for genuinely complex reasoning, not simple decisions.`,\n schema: {\n input: thinkInputSchema,\n output: thinkOutputSchema,\n },\n call: async (_ctx: Context, _input: ThinkInput) => ({ acknowledged: true }),\n metadata: { hidden: true },\n});\n","/**\n * Plan Mode Tools\n *\n * enterPlanMode / exitPlanMode — explicit plan-first mode.\n * When active, only non-destructive + safe tools are available.\n */\n\nimport type { AgentMode } from \"@jarvis/types\";\nimport { tool, after } from \"./tools\";\n\n// =============================================================================\n// enterPlanMode\n// =============================================================================\n\nexport const enterPlanModeTool = tool({\n name: \"enterPlanMode\",\n description: `Enter planning mode to research and design before taking action. Only non-destructive and safe tools are available until exitPlanMode is called.\n\nWhen to use:\n- Complex tasks with multiple steps or approaches\n- Ambiguous requirements needing exploration\n- Tasks where the user's preference between approaches matters\n- Unfamiliar domains requiring research first\n\nWhen NOT to use:\n- Simple, direct requests with clear intent\n- Follow-up actions on an already-agreed plan\n- Quick questions or lookups\n\nDecision rule: If you're unsure how to approach the task, enter plan mode. The cost of unnecessary planning is low; the cost of a wrong approach is high.`,\n schema: {\n input: { type: \"object\" as const, properties: {} },\n output: {\n type: \"object\" as const,\n properties: { mode: { type: \"string\" } },\n },\n },\n call: async () => ({ mode: \"plan\" as AgentMode }),\n hooks: {\n after: after<{ mode?: AgentMode; previousMode?: AgentMode }>(async (_ctx, _req) => ({\n context: {\n mode: \"plan\",\n message: `Plan mode is now active. Only non-destructive tools are available.\nYour next steps:\n1. Research the task using available tools\n2. Understand the current state and constraints\n3. Identify the best approach\n4. Draft a step-by-step plan\n5. Present the plan to the user\n6. Call exitPlanMode when the plan is approved`,\n },\n state: { mode: \"plan\" as AgentMode, previousMode: \"auto\" as AgentMode },\n })),\n },\n metadata: {\n label: \"Enter Plan Mode\",\n permissions: { risk: \"safe\" },\n },\n});\n\n// =============================================================================\n// exitPlanMode\n// =============================================================================\n\nexport const exitPlanModeTool = tool({\n name: \"exitPlanMode\",\n description: `Exit planning mode and signal the plan is ready for execution. All tools become available after exit.\n\nBefore calling this:\n- You should have researched and understood the task\n- You should have presented a clear plan to the user\n- The user should have had a chance to review or adjust\n\nAfter exit: Execute the plan step by step.`,\n schema: {\n input: { type: \"object\" as const, properties: {} },\n output: {\n type: \"object\" as const,\n properties: { mode: { type: \"string\" } },\n },\n },\n call: async () => ({ mode: \"auto\" as AgentMode }),\n hooks: {\n after: after<{ mode?: AgentMode; previousMode?: AgentMode }>(async (_ctx, _req) => ({\n context: {\n mode: \"auto\",\n message: \"Plan mode exited. All tools are now available. Execute the plan you presented, working through it step by step.\",\n },\n state: { mode: \"auto\" as AgentMode, previousMode: undefined },\n })),\n },\n metadata: {\n label: \"Exit Plan Mode\",\n permissions: { risk: \"safe\" },\n },\n});\n","/**\n * Agent Tool\n *\n * Tool for spawning a sub-agent of the current agent with a different task.\n * The sub-agent runs with the same agent config but can have filtered tools.\n */\n\nimport type { SubAgentRequest, SubAgentResponse, SubAgentFn } from \"./agent.tools.types\";\nimport { tool } from \"./tools\";\n\n// =============================================================================\n// agentTool — spawn a sub-agent of self\n// =============================================================================\n\n/**\n * Spawn a sub-agent with a task and optional tool filtering.\n *\n * @example\n * ```typescript\n * import { agentTool, buildTools } from \"@jarvis/sdk\";\n *\n * const tools = buildTools(ctx, {\n * tools: [agentTool, ...otherTools],\n * state: currentState,\n * }, {\n * spawnSubAgent: async (task, context, options) => {\n * return { message: \"Done\", success: true, requestCount: 0 };\n * },\n * });\n * ```\n */\nexport const agentTool = tool({\n name: \"agent\",\n description: `Spawn a sub-agent to handle a task independently.\n\nGuidelines:\n- Use filters.tools to restrict tools for focused tasks\n- Use model override for cost optimization: smaller model for simple tasks, larger for complex reasoning\n- Provide complete context in the task description — the sub-agent doesn't share your conversation history\n- After the sub-agent completes, synthesize its findings before acting — don't just pass through results`,\n schema: {\n input: {\n type: \"object\",\n properties: {\n task: {\n type: \"string\",\n description: \"The task to delegate. Be specific and include all relevant context.\",\n },\n context: {\n type: \"object\",\n description: \"Additional context to pass to the sub-agent\",\n },\n model: {\n type: \"string\",\n description:\n \"Override model ID for the sub-agent (e.g., 'claude-sonnet-4-20250514', 'gpt-4o')\",\n },\n filters: {\n type: \"object\",\n description: \"Filters for the sub-agent\",\n properties: {\n tools: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Restrict which tools the sub-agent can use (whitelist by tool name)\",\n },\n },\n },\n },\n required: [\"task\"],\n },\n output: {\n type: \"object\",\n properties: {\n message: { type: \"string\" },\n success: { type: \"boolean\" },\n requestCount: { type: \"number\" },\n ui: { type: \"object\" },\n },\n },\n },\n\n call: async (_ctx: unknown, input: unknown, options?: Record<string, unknown>) => {\n const { task, context, model, filters } = input as SubAgentRequest;\n const spawnSubAgent = options?.spawnSubAgent as SubAgentFn | undefined;\n if (!spawnSubAgent) {\n throw new Error(\"spawnSubAgent callback not provided via buildTools options\");\n }\n return spawnSubAgent(task, context, { model, filters });\n },\n\n hooks: {\n before: async (_ctx: unknown, req: { input: unknown }) => ({\n action: \"allow\" as const,\n input: req.input,\n }),\n after: async (_ctx: unknown, req: { input: unknown; output: unknown }) => {\n const output = req.output as SubAgentResponse;\n return {\n context: {\n message: output.message,\n success: output.success,\n requestCount: output.requestCount,\n },\n ui: output.ui,\n };\n },\n },\n});\n","/**\n * Skills Domain\n * Factory function for creating skills with collection and import methods.\n *\n * The skill() factory is both a creator and a namespace:\n * - skill({...}) — create a skill inline\n * - skill.add(s) — add a skill to the registry\n * - skill.list() — get all registered skills\n * - skill.get(id) — get a skill by ID\n */\n\nimport type { Skill, Prompt, SkillHooks } from \"@jarvis/types\";\n\nimport type { Tool } from \"@jarvis/types\"; // Used by SkillConfig\n\n// =============================================================================\n// skillHooks() Factory\n// =============================================================================\n\n/**\n * Create a skill hooks container (type-safe factory).\n * Mirrors the hooks() factory for tools.\n *\n * @example\n * ```typescript\n * import { skill, skillHooks } from \"@jarvis/sdk\";\n * import type { OrchestratorState } from \"./orchestrator.types\";\n *\n * const mySkill = skill({\n * id: \"my-skill\",\n * // ...\n * hooks: skillHooks<OrchestratorState>({\n * before: async (ctx, req, options) => ({\n * action: \"allow\",\n * messages: [{ role: \"system\", content: `State: ${JSON.stringify(ctx.state)}` }],\n * }),\n * after: async (ctx, req, options) => ({\n * context: { message: req.message },\n * state: req.skillState,\n * }),\n * }),\n * });\n * ```\n */\nexport function skillHooks<TState = unknown>(\n config: SkillHooks<TState>\n): SkillHooks<TState> {\n return config;\n}\n\n// =============================================================================\n// Internal Registry\n// =============================================================================\n\nconst registry = new Map<string, Skill>();\n\n// =============================================================================\n// skill() Factory + Namespace\n// =============================================================================\n\ninterface SkillConfig {\n id: string;\n name: string;\n description: string;\n prompt: Prompt;\n tools: Tool[];\n maxIterations?: number;\n version?: string;\n author?: string;\n tags?: string[];\n hooks?: SkillHooks<unknown>;\n}\n\n/**\n * Create a skill with typed configuration\n *\n * Skills are procedural knowledge - prompts and methodology that transform\n * general-purpose agents into specialists.\n *\n * @example\n * ```typescript\n * import { skill, tool, prompt } from \"@jarvis/sdk\";\n *\n * // Inline definition\n * export const codeReviewSkill = skill({\n * id: \"code-review\",\n * name: \"Code Review\",\n * description: \"Systematic code review\",\n * prompt: codeReviewPrompt,\n * tools: [analyzeCodeTool],\n * maxIterations: 5,\n * });\n *\n * // Import from directory\n * const analyticsSkill = await skill.fromDir(\"./skills/analytics\");\n *\n * // Add to registry\n * skill.add(codeReviewSkill);\n *\n * // Load (fromDir + add)\n * await skill.load(\"./skills/research\");\n *\n * // Query registry\n * skill.list(); // -> Skill[]\n * skill.get(\"code-review\"); // -> Skill | undefined\n * ```\n */\nfunction createSkill(config: SkillConfig): Skill {\n return {\n id: config.id,\n name: config.name,\n description: config.description,\n prompt: config.prompt,\n tools: config.tools,\n maxIterations: config.maxIterations,\n version: config.version,\n author: config.author,\n tags: config.tags,\n hooks: config.hooks,\n };\n}\n\n// =============================================================================\n// Collection Methods\n// =============================================================================\n\n/**\n * Add a skill to the internal registry.\n */\nfunction add(s: Skill): Skill {\n registry.set(s.id, s);\n return s;\n}\n\n/**\n * Get all registered skills.\n */\nfunction list(): Skill[] {\n return [...registry.values()];\n}\n\n/**\n * Get a registered skill by ID.\n */\nfunction get(id: string): Skill | undefined {\n return registry.get(id);\n}\n\n// =============================================================================\n// Export: skill as callable + namespace\n// =============================================================================\n\nexport const skill = Object.assign(createSkill, {\n add,\n list,\n get,\n});\n","/**\n * Mustache Renderer\n * Simple mustache-style template renderer for prompts\n */\n\nimport type {\n PromptRenderer,\n RenderPromptRequest,\n RenderPromptResponse,\n ValidatePromptRequest,\n ValidatePromptResponse,\n Message,\n} from \"@jarvis/types\";\n\n/**\n * Render a mustache template string with variables\n * Supports:\n * - Simple variables: {{variable}}\n * - Conditional sections: {{#variable}}content{{/variable}} - render if truthy\n * - Inverted sections: {{^variable}}content{{/variable}} - render if falsy\n */\nexport function renderTemplate(template: string, args: Record<string, unknown>): string {\n let result = template;\n\n // 1. Handle inverted sections {{^variable}}...{{/variable}} (render if falsy)\n result = result.replace(\n /\\{\\{\\^(\\w+)\\}\\}([\\s\\S]*?)\\{\\{\\/\\1\\}\\}/g,\n (_match, key, content) => {\n const value = args[key];\n // Render content if value is falsy or empty array/string\n if (!value || (Array.isArray(value) && value.length === 0) || value === \"\") {\n return renderTemplate(content, args);\n }\n return \"\";\n }\n );\n\n // 2. Handle conditional sections {{#variable}}...{{/variable}}\n result = result.replace(\n /\\{\\{#(\\w+)\\}\\}([\\s\\S]*?)\\{\\{\\/\\1\\}\\}/g,\n (_match, key, content) => {\n const value = args[key];\n // Skip if value is falsy or empty array/string\n if (!value || (Array.isArray(value) && value.length === 0) || value === \"\") {\n return \"\";\n }\n // Render content with variables substituted\n return renderTemplate(content, args);\n }\n );\n\n // 3. Handle simple variables {{variable}}\n result = result.replace(/\\{\\{(\\w+)\\}\\}/g, (_match, key) => {\n const value = args[key];\n if (value === undefined || value === null) {\n return \"\";\n }\n return String(value);\n });\n\n return result;\n}\n\n/**\n * Render a message with mustache variables\n */\nfunction renderMessage(message: Message, args: Record<string, unknown>): Message {\n const content = typeof message.content === \"string\"\n ? renderTemplate(message.content, args)\n : message.content ?? \"\";\n\n return {\n ...message,\n content,\n } as Message;\n}\n\n/**\n * Create a mustache renderer instance\n */\nexport function mustacheRenderer(): PromptRenderer {\n return {\n name: \"mustache\",\n\n async render(request: RenderPromptRequest): Promise<RenderPromptResponse> {\n const { prompt, args } = request;\n\n // If prompt has messages, render each message\n if (prompt.messages && prompt.messages.length > 0) {\n const messages = prompt.messages.map((msg) => renderMessage(msg, args));\n return {\n messages,\n output: prompt.output,\n metadata: {\n promptId: prompt.id,\n promptName: prompt.name,\n version: prompt.version || \"1.0.0\",\n provider: \"mustache\",\n },\n };\n }\n\n // If prompt has content, render as a single system message\n if (prompt.content) {\n const renderedContent = renderTemplate(prompt.content, args);\n return {\n messages: [{ role: \"system\", content: renderedContent }],\n output: prompt.output,\n metadata: {\n promptId: prompt.id,\n promptName: prompt.name,\n version: prompt.version || \"1.0.0\",\n provider: \"mustache\",\n },\n };\n }\n\n // No content to render\n return {\n messages: [],\n output: prompt.output,\n metadata: {\n promptId: prompt.id,\n promptName: prompt.name,\n version: prompt.version || \"1.0.0\",\n provider: \"mustache\",\n },\n };\n },\n\n async validate(request: ValidatePromptRequest): Promise<ValidatePromptResponse> {\n const { prompt, args } = request;\n\n // Check if all required variables are provided\n if (prompt.input && prompt.input.properties) {\n const required: string[] = Array.isArray(prompt.input.required)\n ? prompt.input.required\n : [];\n for (const key of required) {\n if (args[key] === undefined) {\n return {\n valid: false,\n message: `Missing required variable: ${key}`,\n };\n }\n }\n }\n\n return { valid: true };\n },\n };\n}\n\n/**\n * Default mustache renderer instance\n */\nexport const defaultMustacheRenderer = mustacheRenderer();\n","/**\n * Reference Factory\n *\n * Factory for defining reference types with metadata and creation logic.\n * Follows the same config pattern as entity(), resolver(), tool(), etc.\n *\n * @example\n * ```typescript\n * import { ref } from \"@jarvis/sdk\";\n * import type { DateReference } from \"@jarvis/types\";\n *\n * export const dateReference = ref<DateReference>({\n * type: \"date\",\n * label: \"Date\",\n * icon: \"calendar\",\n * color: \"purple\",\n * displayName: (input) => formatDateStr(input.date),\n * });\n *\n * // Usage:\n * const myDate = dateReference.create({ date: \"2024-01-01\" });\n * ```\n */\n\nimport type {\n Reference,\n ReferenceType,\n RefConfig,\n Ref,\n EntityReference,\n DateReference,\n DateRangeReference,\n FileReference,\n UrlReference,\n TextReference,\n ResolvedReference,\n Resolver,\n} from \"@jarvis/types\";\n\n// =============================================================================\n// Internal Helpers\n// =============================================================================\n\nfunction formatDateStr(date: string): string {\n return new Date(date).toLocaleDateString(undefined, {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** Format a date for LLM context display */\nfunction formatDateOnly(dateStr: unknown): string {\n if (!dateStr) return \"N/A\";\n try {\n const d = new Date(dateStr as string);\n return d.toLocaleDateString(\"en-US\", {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n } catch {\n return String(dateStr);\n }\n}\n\n/** Fallback formatter — selective JSON (exclude noisy fields) */\nfunction formatGeneric(name: string, type: string, data: unknown): string {\n const lines = [`### ${type}: ${name}`];\n\n if (data && typeof data === \"object\") {\n const cleanData = { ...(data as Record<string, unknown>) };\n delete cleanData.id;\n delete cleanData.userId;\n delete cleanData.createdAt;\n delete cleanData.updatedAt;\n delete cleanData.deletedAt;\n\n lines.push(\"```json\");\n lines.push(JSON.stringify(cleanData, null, 2));\n lines.push(\"```\");\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Define a reference type with metadata and creation logic.\n *\n * Returns a Ref definition with `.create()` for instantiation\n * and metadata fields (label, icon, color, format) for UI/LLM use.\n */\nexport function ref<T extends Reference>(config: RefConfig<T>): Ref<T> {\n return {\n type: config.type,\n label: config.label,\n icon: config.icon,\n color: config.color,\n format: config.format,\n create: (input) => {\n const displayName =\n input.displayName || config.displayName?.(input) || \"\";\n return {\n id: Math.random().toString(36).substring(2, 10),\n type: config.type,\n displayName,\n createdAt: new Date().toISOString(),\n ...input,\n } as T;\n },\n };\n}\n\n// =============================================================================\n// Reference Definitions\n// =============================================================================\n\nexport const entityReference = ref<EntityReference>({\n type: \"entity\",\n label: \"Entity\",\n icon: \"box\",\n color: \"blue\",\n format: (displayName: string, data: unknown) => {\n const d = data as Record<string, unknown>;\n const lines = [`### Entity: ${displayName}`];\n if (d.id) lines.push(`- **Entity ID**: \\`${d.id}\\``);\n if (d.entityType) lines.push(`- **Entity Type**: ${d.entityType}`);\n\n const cleanData = { ...d };\n delete cleanData.id;\n delete cleanData.userId;\n delete cleanData.createdAt;\n delete cleanData.updatedAt;\n delete cleanData.deletedAt;\n delete cleanData.entityType;\n\n if (Object.keys(cleanData).length > 0) {\n lines.push(\"```json\");\n lines.push(JSON.stringify(cleanData, null, 2));\n lines.push(\"```\");\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n },\n});\n\nexport const dateReference = ref<DateReference>({\n type: \"date\",\n label: \"Date\",\n icon: \"calendar\",\n color: \"purple\",\n displayName: (input) => formatDateStr(input.date),\n format: (name: string, data: unknown) => {\n const d = data as Record<string, unknown>;\n const lines = [`### Date: ${name}`];\n\n if (d.date) lines.push(`- **Date**: ${formatDateOnly(d.date)}`);\n if (d.events && Array.isArray(d.events))\n lines.push(`- **Events on this date**: ${d.events.length}`);\n if (d.tasks && Array.isArray(d.tasks))\n lines.push(`- **Tasks due**: ${d.tasks.length}`);\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n },\n});\n\nexport const dateRangeReference = ref<DateRangeReference>({\n type: \"dateRange\",\n label: \"Date Range\",\n icon: \"calendar\",\n color: \"purple\",\n displayName: (input) =>\n `${formatDateStr(input.startDate)} - ${formatDateStr(input.endDate)}`,\n});\n\nexport const fileReference = ref<FileReference>({\n type: \"file\",\n label: \"File\",\n icon: \"file\",\n color: \"gray\",\n displayName: (input) => input.path.split(\"/\").pop() || input.path,\n});\n\nexport const urlReference = ref<UrlReference>({\n type: \"url\",\n label: \"URL\",\n icon: \"link\",\n color: \"cyan\",\n displayName: (input) => new URL(input.url).hostname,\n});\n\nexport const textReference = ref<TextReference>({\n type: \"text\",\n label: \"Text\",\n icon: \"text\",\n color: \"gray\",\n displayName: (input) =>\n input.content.length > 30\n ? input.content.slice(0, 30) + \"...\"\n : input.content,\n});\n\n// =============================================================================\n// Collection\n// =============================================================================\n\nconst allRefs: Ref<Reference>[] = [\n entityReference as Ref<Reference>,\n dateReference as Ref<Reference>,\n dateRangeReference as Ref<Reference>,\n fileReference as Ref<Reference>,\n urlReference as Ref<Reference>,\n textReference as Ref<Reference>,\n];\n\nexport const references = {\n // Definitions\n entity: entityReference,\n date: dateReference,\n dateRange: dateRangeReference,\n file: fileReference,\n url: urlReference,\n text: textReference,\n\n /** Format reference for display */\n format: (r: Reference): string => {\n const meta = references.get(r.type);\n return meta ? `[${meta.icon}] ${r.displayName}` : r.displayName;\n },\n\n /** List all ref definitions */\n list: (): Ref<Reference>[] => allRefs,\n\n /** Get ref definition by type */\n get: (type: ReferenceType): Ref<Reference> | undefined =>\n allRefs.find((r) => r.type === type),\n\n /**\n * Format resolved references for LLM context.\n * Priority: resolver format → ref definition format → generic JSON fallback.\n */\n \n formatResolved: (\n resolved: ResolvedReference[],\n resolverDefs?: Resolver<Reference, unknown>[],\n ): string => {\n if (resolved.length === 0) return \"\";\n\n const sections: string[] = [\"## Referenced Context\\n\"];\n\n for (const r of resolved) {\n if (!r.resolved || !r.data) {\n sections.push(\n `### ${r.reference.displayName} (${r.reference.type}) - NOT FOUND`,\n );\n sections.push(`> ${r.error || \"Could not resolve this reference\"}`);\n sections.push(\n \"*Ask the user how to proceed or if they want to select a different item.*\\n\",\n );\n continue;\n }\n\n // Priority 1: Resolver-level format (e.g. entity.format for entity resolvers)\n const entityType =\n r.reference.type === \"entity\"\n ? (r.reference as EntityReference).entityType\n : undefined;\n const def = resolverDefs?.find(\n (d) =>\n d.type === r.reference.type &&\n (!entityType || d.entityType === entityType),\n );\n\n if (def?.format) {\n sections.push(def.format(r.reference.displayName, r.data));\n continue;\n }\n\n // Priority 2: Ref definition format\n const refDef = references.get(r.reference.type);\n if (refDef?.format) {\n sections.push(refDef.format(r.reference.displayName, r.data));\n continue;\n }\n\n // Priority 3: Generic fallback\n sections.push(\n formatGeneric(r.reference.displayName, r.reference.type, r.data),\n );\n }\n\n return sections.join(\"\\n\");\n },\n};\n","/**\n * Table Factory, Field Helpers, and Index Helpers\n *\n * table<T>() creates a pure schema definition — no CRUD methods.\n * CRUD is handled by the DatabaseProvider directly:\n * db.find(ctx, { table: usersTable, filter: { email } })\n *\n * Every column is explicit — what you declare is what the DB gets.\n * No implicit system columns.\n */\n\nimport type { Table, TableConfig } from \"@jarvis/types\";\nimport type { FieldConfig, FieldType, IndexConfig, JsonFieldSchema } from \"@jarvis/types\";\n\n// =============================================================================\n// UTILITIES\n// =============================================================================\n\n/** Convert camelCase to snake_case */\nexport function toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n// =============================================================================\n// table<T>() FACTORY — Pure schema definition\n// =============================================================================\n\n/**\n * Create a typed table schema definition.\n *\n * Returns a Table<T> with name, columns, indexes — no CRUD methods.\n * CRUD is handled by the DatabaseProvider.\n *\n * @example\n * ```typescript\n * import { table, field, index } from \"@jarvis/sdk\";\n *\n * export const usersTable = table<User>({\n * name: \"users\",\n * columns: {\n * id: field.uuid({ primary: true }),\n * userId: field.string({ required: true }),\n * email: field.string({ required: true, unique: true }),\n * name: field.string({ nullable: true }),\n * preferences: field.json({ default: {} }),\n * createdAt: field.timestamp({ auto: \"create\" }),\n * updatedAt: field.timestamp({ auto: \"update\" }),\n * },\n * });\n *\n * // Usage — CRUD via db provider:\n * const result = await db.find<User>(ctx, { table: usersTable, filter: { email } });\n * ```\n */\nexport function table<T = Record<string, unknown>>(\n config: TableConfig<T>,\n): Table<T> {\n if (!config.name) {\n throw new Error(\"Table must have a name\");\n }\n if (!/^[a-z][a-z0-9_]*$/.test(config.name)) {\n throw new Error(\n `Invalid table name \"${config.name}\". Must be lowercase with underscores.`,\n );\n }\n\n const columns = config.columns;\n const indexes = config.indexes ?? [];\n\n // Collect searchable field names\n const searchableFields: string[] = [];\n for (const [fname, fconfig] of Object.entries(columns)) {\n if (fconfig.searchable) {\n searchableFields.push(fname);\n }\n if (fconfig.type === \"json\" && fconfig.schema) {\n for (const [innerName, innerConfig] of Object.entries(fconfig.schema)) {\n if (innerConfig.searchable) {\n searchableFields.push(`${fname}.${innerName}`);\n }\n }\n }\n }\n\n return {\n kind: \"table\" as const,\n name: config.name,\n columns,\n indexes,\n access: config.access,\n searchableFields,\n } as Table<T>;\n}\n\n// =============================================================================\n// FIELD HELPERS\n// =============================================================================\n\n/**\n * Field helper functions for defining column types.\n *\n * @example\n * ```typescript\n * import { field } from \"@jarvis/sdk\";\n *\n * const columns = {\n * id: field.uuid({ primary: true }),\n * name: field.string({ required: true }),\n * email: field.string({ required: true, unique: true }),\n * age: field.integer({ default: 0 }),\n * isActive: field.boolean({ default: true }),\n * bio: field.text(),\n * metadata: field.json({ default: {} }),\n * createdAt: field.timestamp({ auto: \"create\" }),\n * updatedAt: field.timestamp({ auto: \"update\" }),\n * };\n * ```\n */\nexport const field = {\n string: (options?: {\n required?: boolean;\n nullable?: boolean;\n unique?: boolean;\n default?: string;\n searchable?: boolean;\n secret?: boolean;\n }): FieldConfig => ({\n type: \"string\" as FieldType,\n required: options?.required,\n nullable: options?.nullable,\n unique: options?.unique,\n default: options?.default,\n searchable: options?.searchable,\n secret: options?.secret,\n }),\n\n text: (options?: {\n required?: boolean;\n nullable?: boolean;\n default?: string;\n searchable?: boolean;\n }): FieldConfig => ({\n type: \"text\" as FieldType,\n required: options?.required,\n nullable: options?.nullable,\n default: options?.default,\n searchable: options?.searchable,\n }),\n\n integer: (options?: {\n required?: boolean;\n default?: number;\n unique?: boolean;\n }): FieldConfig => ({\n type: \"integer\" as FieldType,\n required: options?.required,\n default: options?.default,\n unique: options?.unique,\n }),\n\n boolean: (options?: { default?: boolean }): FieldConfig => ({\n type: \"boolean\" as FieldType,\n default: options?.default,\n }),\n\n timestamp: (options?: {\n required?: boolean;\n nullable?: boolean;\n default?: string | Date;\n auto?: \"create\" | \"update\";\n }): FieldConfig => ({\n type: \"timestamp\" as FieldType,\n required: options?.required,\n nullable: options?.nullable,\n default: options?.default,\n auto: options?.auto,\n }),\n\n json: <TJ = unknown>(options?: {\n default?: TJ;\n schema?: Record<string, JsonFieldSchema>;\n }): FieldConfig => ({\n type: \"json\" as FieldType,\n default: options?.default,\n schema: options?.schema,\n }),\n\n uuid: (options?: {\n primary?: boolean;\n required?: boolean;\n unique?: boolean;\n auto?: true;\n }): FieldConfig => ({\n type: \"uuid\" as FieldType,\n primary: options?.primary,\n required: options?.required,\n unique: options?.unique,\n auto: options?.auto,\n }),\n\n enum: (values: string[], options?: { default?: string }): FieldConfig => ({\n type: \"string\" as FieldType,\n default: options?.default ?? values[0],\n }),\n\n vector: (options?: { dimensions?: number }): FieldConfig => ({\n type: \"vector\" as FieldType,\n dimensions: options?.dimensions ?? 1536,\n }),\n\n number: (options?: {\n required?: boolean;\n nullable?: boolean;\n default?: number;\n unique?: boolean;\n }): FieldConfig => ({\n type: \"integer\" as FieldType,\n required: options?.required,\n nullable: options?.nullable,\n default: options?.default,\n unique: options?.unique,\n }),\n};\n\n// =============================================================================\n// INDEX HELPERS\n// =============================================================================\n\n/**\n * Create an index configuration\n *\n * @example\n * ```typescript\n * import { index } from \"@jarvis/sdk\";\n *\n * const indexes = [\n * index(\"goals_status_idx\", [\"userId\", \"status\"]),\n * index(\"goals_email_unique\", [\"email\"], { unique: true }),\n * ];\n * ```\n */\nexport function index(\n name: string,\n columns: string[],\n options?: { unique?: boolean },\n): IndexConfig {\n return {\n name,\n columns,\n unique: options?.unique,\n };\n}\n","/**\n * Connector Factory + Registry\n *\n * Provides the connector() factory for creating external service connector definitions,\n * and a registry for aggregating all platform connectors.\n *\n * Auth is handled by platform providers. Sync via Temporal workflows.\n */\n\nimport type {\n Connector,\n ConnectorConfig,\n ConnectorInstance,\n} from \"@jarvis/types\";\n\nimport { table, field, index } from \"./tables\";\n\n// =============================================================================\n// SHARED CONNECTORS TABLE\n// =============================================================================\n\n/** Shared connectors table — persistent storage for connection tracking */\nexport const connectorsTable = table<Connector>({\n name: \"connectors\",\n columns: {\n id: field.uuid({ primary: true }),\n userId: field.string({ required: true }),\n type: field.string({ required: true }),\n accountId: field.string(),\n displayName: field.string(),\n status: field.string({ default: \"disconnected\" }),\n lastSyncedAt: field.timestamp({ nullable: true }),\n syncState: field.json(),\n metadata: field.json(),\n createdAt: field.timestamp({ auto: \"create\" }),\n updatedAt: field.timestamp({ auto: \"update\" }),\n },\n indexes: [index(\"connectors_type_idx\", [\"userId\", \"type\"])],\n});\n\n// =============================================================================\n// CONNECTOR FACTORY\n// =============================================================================\n\n/**\n * Create an external service connector definition.\n *\n * Returns a ConnectorInstance with:\n * - .configure() — app-level sync config\n * - .connect() — initiate auth (OAuth redirect, API key store, token store)\n * - .exchangeCode() — OAuth callback code exchange\n * - .disconnect() — clear credentials\n *\n * @example\n * ```typescript\n * // Platform defines:\n * export const googleCalendarConnector = connector({\n * type: \"google_calendar\",\n * name: \"Google Calendar\",\n * auth: { type: \"oauth\", providerId: \"google\", scopes: [...] },\n * });\n *\n * // App configures sync:\n * export default googleCalendarConnector.configure({\n * sync: { pull: \"./workflows/pull.workflow\", cron: \"...\" },\n * });\n * ```\n */\nexport function connector(config: ConnectorConfig): ConnectorInstance {\n if (!config.type) throw new Error(\"Connector must have a type\");\n if (!config.name) throw new Error(\"Connector must have a name\");\n\n return {\n ...config,\n\n configure(configureConfig) {\n // Merge additional scopes with base auth if provided\n let auth = config.auth;\n if (configureConfig.auth?.scopes && auth?.type === \"oauth\") {\n const merged = [\n ...new Set([...auth.scopes, ...configureConfig.auth.scopes]),\n ];\n auth = { ...auth, scopes: merged };\n }\n\n return {\n type: config.type,\n name: configureConfig.name ?? config.name,\n icon: config.icon,\n color: config.color,\n description: configureConfig.description ?? config.description,\n version: config.version,\n sync: configureConfig.sync,\n auth,\n };\n },\n\n async connect(ctx, req, deps) {\n const auth = this.auth;\n\n // OAuth: return redirect URL\n if (auth?.type === \"oauth\" && auth.provider) {\n return {\n action: \"redirect\",\n ...auth.provider.buildAuthUrl(req.state ?? \"\"),\n };\n }\n\n // API key / token: validate + store credential\n if (\n (auth?.type === \"apiKey\" || auth?.type === \"token\") &&\n req.credential\n ) {\n if (auth.type === \"apiKey\" && \"validate\" in auth && auth.validate) {\n const error = await auth.validate(req.credential);\n if (error) return { action: \"error\", message: error };\n }\n\n await deps.secrets.set(ctx, {\n scope: config.type,\n type: auth.type,\n value: req.credential,\n });\n\n await deps.onConnect?.();\n return { action: \"connected\" };\n }\n\n return { action: \"error\", message: \"Unsupported auth type\" };\n },\n\n async exchangeCode(ctx, req, deps) {\n const auth = this.auth;\n if (auth?.type !== \"oauth\" || !auth.provider) {\n throw new Error(`${config.type}: no OAuth provider`);\n }\n\n const { tokens, profile, metadata } = await auth.provider.exchangeCode(\n req.code,\n req.codeVerifier,\n );\n\n const scope = auth.providerId ?? config.type;\n\n await deps.secrets.set(ctx, {\n scope,\n type: \"oauth\",\n value: {\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken ?? null,\n expiresAt: tokens.expiresAt\n ? new Date(tokens.expiresAt).toISOString()\n : null,\n tokenScope: tokens.scopes.join(\" \"),\n ...(tokens.extra ?? {}),\n },\n metadata: {\n accountId: profile?.accountId ?? null,\n displayName: profile?.displayName ?? null,\n },\n });\n\n await deps.onConnect?.({\n accountId: profile?.accountId,\n displayName: profile?.displayName,\n ...profile?.metadata,\n ...metadata,\n });\n },\n\n async disconnect(ctx, _req, deps) {\n const auth = this.auth;\n const scope =\n auth?.type === \"oauth\" ? (auth.providerId ?? config.type) : config.type;\n\n await deps.secrets.delete(ctx, { scope });\n await deps.onDisconnect?.();\n },\n };\n}\n\n// =============================================================================\n// CONNECTORS COLLECTION\n// =============================================================================\n\nconst all: ConnectorInstance[] = [];\n\nexport const connectors = {\n /** List all registered connectors */\n list: () => [...all],\n\n /** Find a connector by type */\n get: (type: string) => all.find((c) => c.type === type),\n\n /** Register a connector instance */\n add: (instance: ConnectorInstance) => {\n all.push(instance);\n },\n};\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface EditToolInput {\n file_path: string;\n old_string: string;\n new_string: string;\n replace_all?: boolean;\n}\n\nexport const editTool = tool({\n name: \"Edit\",\n description: \"Edit file contents with string replacement\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\" },\n old_string: { type: \"string\" },\n new_string: { type: \"string\" },\n replace_all: { type: \"boolean\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Edit File\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<EditToolInput>;\n const fileName = input.file_path?.split(\"/\").pop() || \"file\";\n if (req.status === \"running\") return `Editing ${fileName}...`;\n if (req.status === \"completed\") return `Edited ${fileName}`;\n return `Failed to edit ${fileName}`;\n },\n },\n hooks: {\n before: async (_ctx, req, options) => {\n const input = req.input as EditToolInput;\n const response = await options.askUser({\n ui: {\n uri: \"ui://devenv/diff\",\n title: input.file_path,\n data: {\n filePath: input.file_path,\n oldString: input.old_string,\n newString: input.new_string,\n replaceAll: input.replace_all,\n },\n },\n });\n if (response?.action === \"deny\") {\n return { action: \"deny\", reason: response.feedback || \"User denied edit\" };\n }\n return { action: \"allow\" };\n },\n after: async (_ctx, req) => {\n const input = req.input as EditToolInput;\n return {\n context: { edited: input.file_path },\n ui: {\n uri: \"ui://devenv/diff\",\n title: input.file_path,\n data: {\n filePath: input.file_path,\n oldString: input.old_string,\n newString: input.new_string,\n replaceAll: input.replace_all,\n },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface BashToolInput {\n command: string;\n description?: string;\n timeout?: number;\n}\n\nexport const bashTool = tool({\n name: \"Bash\",\n description: \"Execute a bash command\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n command: { type: \"string\" },\n description: { type: \"string\" },\n timeout: { type: \"number\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Run Command\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<BashToolInput>;\n if (input.description) return input.description;\n const shortCmd =\n input.command && input.command.length > 50\n ? input.command.slice(0, 47) + \"...\"\n : input.command || \"command\";\n if (req.status === \"running\") return `Running: ${shortCmd}`;\n if (req.status === \"completed\") return `Ran: ${shortCmd}`;\n return `Failed: ${shortCmd}`;\n },\n },\n hooks: {\n before: async (_ctx, req, options) => {\n const input = req.input as BashToolInput;\n const response = await options.askUser({\n ui: {\n uri: \"ui://devenv/command\",\n title: input.description || input.command,\n data: { command: input.command, description: input.description },\n },\n });\n if (response?.action === \"deny\") {\n return { action: \"deny\", reason: response.feedback || \"User denied command\" };\n }\n return { action: \"allow\" };\n },\n after: async (_ctx, req) => {\n const input = req.input as BashToolInput;\n const output = req.output as { stdout?: string; stderr?: string; exitCode?: number } | string | undefined;\n const outputText = typeof output === \"string\"\n ? output\n : output\n ? [output.stdout, output.stderr].filter(Boolean).join(\"\\n\")\n : undefined;\n const exitCode = typeof output === \"object\" && output ? output.exitCode : undefined;\n return {\n context: { command: input.command, exitCode },\n ui: {\n uri: \"ui://devenv/command\",\n title: input.description || input.command,\n data: { command: input.command, description: input.description, output: outputText, exitCode },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface WriteToolInput {\n file_path: string;\n content: string;\n}\n\nfunction detectLanguage(filePath: string): string | undefined {\n const ext = filePath.split(\".\").pop()?.toLowerCase();\n const langMap: Record<string, string> = {\n ts: \"typescript\", tsx: \"typescript\", js: \"javascript\", jsx: \"javascript\",\n py: \"python\", rs: \"rust\", go: \"go\", rb: \"ruby\", java: \"java\",\n css: \"css\", scss: \"scss\", html: \"html\", json: \"json\",\n yaml: \"yaml\", yml: \"yaml\", toml: \"toml\", xml: \"xml\",\n md: \"markdown\", sql: \"sql\", sh: \"shell\", bash: \"shell\",\n };\n return ext ? langMap[ext] : undefined;\n}\n\nexport const writeTool = tool({\n name: \"Write\",\n description: \"Write content to a file\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\" },\n content: { type: \"string\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Write File\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<WriteToolInput>;\n const fileName = input.file_path?.split(\"/\").pop() || \"file\";\n if (req.status === \"running\") return `Writing ${fileName}...`;\n if (req.status === \"completed\") return `Wrote ${fileName}`;\n return `Failed to write ${fileName}`;\n },\n },\n hooks: {\n before: async (_ctx, req, options) => {\n const input = req.input as WriteToolInput;\n const language = detectLanguage(input.file_path);\n const response = await options.askUser({\n ui: {\n uri: \"ui://devenv/file\",\n title: input.file_path,\n data: { filePath: input.file_path, content: input.content, language },\n },\n });\n if (response?.action === \"deny\") {\n return { action: \"deny\", reason: response.feedback || \"User denied write\" };\n }\n return { action: \"allow\" };\n },\n after: async (_ctx, req) => {\n const input = req.input as WriteToolInput;\n const language = detectLanguage(input.file_path);\n return {\n context: { wrote: input.file_path },\n ui: {\n uri: \"ui://devenv/file\",\n title: input.file_path,\n data: { filePath: input.file_path, content: input.content, language },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface ReadToolInput {\n file_path: string;\n offset?: number;\n limit?: number;\n}\n\nfunction stripLineNumbers(text: string): string {\n return text.replace(/^\\s*\\d+[\\t→]/gm, \"\");\n}\n\nfunction detectLanguage(filePath: string): string | undefined {\n const ext = filePath.split(\".\").pop()?.toLowerCase();\n const langMap: Record<string, string> = {\n ts: \"typescript\", tsx: \"typescript\", js: \"javascript\", jsx: \"javascript\",\n py: \"python\", rs: \"rust\", go: \"go\", rb: \"ruby\", java: \"java\",\n css: \"css\", scss: \"scss\", html: \"html\", json: \"json\",\n yaml: \"yaml\", yml: \"yaml\", toml: \"toml\", xml: \"xml\",\n md: \"markdown\", sql: \"sql\", sh: \"shell\", bash: \"shell\",\n };\n return ext ? langMap[ext] : undefined;\n}\n\nexport const readTool = tool({\n name: \"Read\",\n description: \"Read file contents\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\" },\n offset: { type: \"number\" },\n limit: { type: \"number\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Read File\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<ReadToolInput>;\n const fileName = input.file_path?.split(\"/\").pop() || \"file\";\n if (req.status === \"running\") return `Reading ${fileName}...`;\n if (req.status === \"completed\") return `Read ${fileName}`;\n return `Failed to read ${fileName}`;\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n const input = req.input as ReadToolInput;\n const language = detectLanguage(input.file_path);\n const rawOutput = typeof req.output === \"string\"\n ? req.output\n : JSON.stringify(req.output, null, 2);\n const content = stripLineNumbers(rawOutput);\n return {\n context: { read: input.file_path },\n ui: {\n uri: \"ui://devenv/file\",\n title: input.file_path,\n data: { filePath: input.file_path, content, language, startLine: (input.offset ?? 0) + 1 },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface GlobToolInput {\n pattern: string;\n path?: string;\n}\n\nexport const globTool = tool({\n name: \"Glob\",\n description: \"Search for files by pattern\",\n schema: {\n input: {\n type: \"object\",\n properties: { pattern: { type: \"string\" }, path: { type: \"string\" } },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Find Files\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<GlobToolInput>;\n const pattern = input.pattern || \"files\";\n if (req.status === \"running\") return `Finding ${pattern}...`;\n if (req.status === \"completed\") return `Found files matching ${pattern}`;\n return `Failed to find ${pattern}`;\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n const input = req.input as GlobToolInput;\n const output = typeof req.output === \"string\" ? req.output : JSON.stringify(req.output, null, 2);\n return {\n context: { searched: input.pattern },\n ui: {\n uri: \"ui://devenv/command\",\n title: `Find: ${input.pattern}`,\n data: {\n command: `glob ${input.pattern}${input.path ? ` in ${input.path}` : \"\"}`,\n description: `Find files matching ${input.pattern}`,\n output,\n },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface GrepToolInput {\n pattern: string;\n path?: string;\n glob?: string;\n output_mode?: string;\n}\n\nexport const grepTool = tool({\n name: \"Grep\",\n description: \"Search file contents by pattern\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n pattern: { type: \"string\" },\n path: { type: \"string\" },\n glob: { type: \"string\" },\n output_mode: { type: \"string\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Search Code\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<GrepToolInput>;\n const pattern = input.pattern || \"\";\n if (req.status === \"running\") return `Searching for \"${pattern}\"...`;\n if (req.status === \"completed\") return `Searched for \"${pattern}\"`;\n return `Failed to search for \"${pattern}\"`;\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n const input = req.input as GrepToolInput;\n const output = typeof req.output === \"string\" ? req.output : JSON.stringify(req.output, null, 2);\n return {\n context: { searched: input.pattern },\n ui: {\n uri: \"ui://devenv/command\",\n title: `Search: \"${input.pattern}\"`,\n data: {\n command: `grep \"${input.pattern}\"${input.path ? ` in ${input.path}` : \"\"}${input.glob ? ` (${input.glob})` : \"\"}`,\n description: `Search for \"${input.pattern}\"`,\n output,\n },\n },\n };\n },\n },\n});\n","export { editTool } from \"./edit.tool\";\nexport { bashTool } from \"./bash.tool\";\nexport { writeTool } from \"./write.tool\";\nexport { readTool } from \"./read.tool\";\nexport { globTool } from \"./glob.tool\";\nexport { grepTool } from \"./grep.tool\";\n\nimport { bashTool } from \"./bash.tool\";\nimport { editTool } from \"./edit.tool\";\nimport { globTool } from \"./glob.tool\";\nimport { grepTool } from \"./grep.tool\";\nimport { readTool } from \"./read.tool\";\nimport { writeTool } from \"./write.tool\";\n\n/** All Claude Code native tools with hooks */\nexport const claudeCodeTools = [editTool, bashTool, writeTool, readTool, globTool, grepTool];\n","/**\n * Tool Description Formatter\n *\n * Human-readable descriptions for tool calls in progress messages.\n */\n\nexport function formatToolDescription(toolName: string, input?: Record<string, unknown>): string {\n if (!input) return toolName;\n switch (toolName) {\n case \"Read\":\n return `Reading ${input.file_path || \"file\"}`;\n case \"Edit\":\n return `Editing ${input.file_path || \"file\"}`;\n case \"Write\":\n return `Writing to ${input.file_path || \"file\"}`;\n case \"Bash\":\n return typeof input.command === \"string\"\n ? input.command.length > 80\n ? input.command.slice(0, 80) + \"\\u2026\"\n : input.command\n : \"Running command\";\n case \"Glob\":\n return `Searching for ${input.pattern || \"files\"}`;\n case \"Grep\":\n return `Searching for \"${input.pattern || \"\"}\"`;\n default:\n return toolName;\n }\n}\n","/**\n * Git Worktree Utilities\n *\n * Per-task isolation using git worktrees.\n * Default location: ~/.jarvis/worktrees/\n */\n\nimport { exec as execCb } from \"child_process\";\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport { promisify } from \"util\";\n\nconst exec = promisify(execCb);\n\nconst DEFAULT_WORKTREE_DIR = path.join(os.homedir(), \".jarvis\", \"worktrees\");\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CreateWorktreeRequest {\n repoPath: string;\n taskId: string;\n branch?: string;\n /** Base directory for worktrees (default: ~/.jarvis/worktrees) */\n worktreeDir?: string;\n}\n\nexport interface CreateWorktreeResponse {\n worktreePath: string;\n branchName: string;\n}\n\nexport interface RemoveWorktreeRequest {\n repoPath: string;\n taskId: string;\n /** Base directory for worktrees (default: ~/.jarvis/worktrees) */\n worktreeDir?: string;\n}\n\nexport interface ListWorktreesRequest {\n repoPath: string;\n}\n\nexport interface WorktreeInfo {\n taskId: string;\n path: string;\n branch: string;\n}\n\nexport interface WorktreeExistsRequest {\n taskId: string;\n /** Base directory for worktrees (default: ~/.jarvis/worktrees) */\n worktreeDir?: string;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction resolveDir(worktreeDir?: string): string {\n if (!worktreeDir) return DEFAULT_WORKTREE_DIR;\n return worktreeDir.replace(/^~/, os.homedir());\n}\n\n// =============================================================================\n// Functions\n// =============================================================================\n\nexport async function createWorktree(req: CreateWorktreeRequest): Promise<CreateWorktreeResponse> {\n const branchName = `jarvis/task-${req.taskId}`;\n const baseDir = resolveDir(req.worktreeDir);\n const worktreePath = path.join(baseDir, `task-${req.taskId}`);\n\n await fs.mkdir(path.dirname(worktreePath), { recursive: true });\n\n if (await worktreeExists({ taskId: req.taskId, worktreeDir: req.worktreeDir })) {\n return { worktreePath, branchName };\n }\n\n const startPoint = req.branch ?? \"HEAD\";\n await exec(`git worktree add -b \"${branchName}\" \"${worktreePath}\" \"${startPoint}\"`, {\n cwd: req.repoPath,\n });\n\n return { worktreePath, branchName };\n}\n\nexport async function removeWorktree(req: RemoveWorktreeRequest): Promise<void> {\n const branchName = `jarvis/task-${req.taskId}`;\n const baseDir = resolveDir(req.worktreeDir);\n const worktreePath = path.join(baseDir, `task-${req.taskId}`);\n\n try {\n await exec(`git worktree remove --force \"${worktreePath}\"`, { cwd: req.repoPath });\n } catch {\n await fs.rm(worktreePath, { recursive: true, force: true });\n await exec(\"git worktree prune\", { cwd: req.repoPath }).catch(() => {});\n }\n\n await exec(`git branch -D \"${branchName}\"`, { cwd: req.repoPath }).catch(() => {});\n}\n\nexport async function listWorktrees(req: ListWorktreesRequest): Promise<WorktreeInfo[]> {\n const { stdout } = await exec(\"git worktree list --porcelain\", { cwd: req.repoPath });\n const worktrees: WorktreeInfo[] = [];\n\n let currentPath = \"\";\n let currentBranch = \"\";\n\n for (const line of stdout.split(\"\\n\")) {\n if (line.startsWith(\"worktree \")) {\n currentPath = line.slice(9);\n } else if (line.startsWith(\"branch refs/heads/\")) {\n currentBranch = line.slice(18);\n if (currentBranch.startsWith(\"jarvis/task-\")) {\n worktrees.push({\n taskId: currentBranch.replace(\"jarvis/task-\", \"\"),\n path: currentPath,\n branch: currentBranch,\n });\n }\n }\n }\n\n return worktrees;\n}\n\nexport async function worktreeExists(req: WorktreeExistsRequest): Promise<boolean> {\n const baseDir = resolveDir(req.worktreeDir);\n const worktreePath = path.join(baseDir, `task-${req.taskId}`);\n try {\n await fs.access(worktreePath);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * WS Progress Handlers\n *\n * Same logic as workflows/devenv/src/progress.ts but publishes\n * over WebSocket instead of Redis pub/sub + Temporal signals.\n *\n * The handleProgress() and handleUserInput() functions are identical\n * in behavior — only the transport (publish/signal → ws.send) changes.\n */\n\nimport crypto from \"crypto\";\n\nimport { formatToolDescription } from \"@jarvis/agent\";\nimport type {\n ChatMessage,\n PendingUserInput,\n ToolCallData,\n ToolUi,\n ToolUiData,\n UserInputResponse,\n} from \"@jarvis/types\";\n\nimport type { OutboundMessage } from \"./protocol\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface WsProgressHandlersDeps {\n /** Send a message to all connected clients (local + upstream) */\n broadcast: (msg: OutboundMessage) => void;\n /** Send input request and wait for user response */\n requestInput: (taskId: string, input: PendingUserInput) => Promise<UserInputResponse>;\n /** Task ID for message routing */\n taskId: string;\n /** Chat ID for usage events */\n chatId: string;\n}\n\nexport interface WsProgressHandlers {\n onMessage: (msg: ChatMessage) => Promise<void>;\n completeTools: () => Promise<void>;\n waitForInput: (pendingInput: PendingUserInput) => Promise<UserInputResponse>;\n handleUserInput: (input: PendingUserInput) => Promise<UserInputResponse>;\n handleProgress: (message: unknown) => Promise<void>;\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\nexport function createWsProgressHandlers(deps: WsProgressHandlersDeps): WsProgressHandlers {\n const { broadcast, requestInput, taskId, chatId } = deps;\n const toolIds = new Map<string, string>();\n let currentThinkingId: string | null = null;\n let currentTextId: string | null = null;\n let currentTextContent = \"\";\n // Track plan file content written during plan mode\n let planFileContent: string | null = null;\n let planFilePath: string | null = null;\n\n // ---------------------------------------------------------------------------\n // Transport: single WS broadcast replaces Redis pub/sub + Temporal signal\n // ---------------------------------------------------------------------------\n\n async function onMessage(msg: ChatMessage): Promise<void> {\n broadcast({ type: \"agent:onMessage\", taskId, message: msg });\n }\n\n // ---------------------------------------------------------------------------\n // Tool lifecycle\n // ---------------------------------------------------------------------------\n\n async function completeTools(): Promise<void> {\n const now = new Date().toISOString();\n for (const [toolId, toolName] of toolIds) {\n const msg: ChatMessage = {\n id: `tool-${toolId}`,\n role: \"assistant\",\n type: \"tool\",\n content: \"\",\n toolCall: { toolName, toolCallId: toolId, status: \"completed\" },\n isPartial: false,\n createdAt: now,\n };\n await onMessage(msg);\n }\n toolIds.clear();\n }\n\n // ---------------------------------------------------------------------------\n // User input (tool approval, plan review)\n // ---------------------------------------------------------------------------\n\n async function waitForInput(pendingInput: PendingUserInput): Promise<UserInputResponse> {\n return requestInput(taskId, pendingInput);\n }\n\n async function handleUserInput(input: PendingUserInput): Promise<UserInputResponse> {\n const toolName = input.toolName ?? \"\";\n const now = new Date().toISOString();\n\n if (toolName === \"askUser\") return waitForInput(input);\n\n if (toolName === \"ExitPlanMode\") {\n const now = new Date().toISOString();\n // Broadcast plan artifact for side panel rendering\n if (planFileContent) {\n await onMessage({\n id: `plan-${crypto.randomUUID()}`,\n role: \"assistant\",\n type: \"ui\",\n content: planFileContent,\n ui: {\n uri: \"ui://agent/plan\",\n title: \"Plan\",\n data: { content: planFileContent, path: planFilePath },\n },\n isPartial: false,\n createdAt: now,\n });\n }\n return waitForInput({\n ...input,\n type: \"plan\",\n reason: (input.input?.allowedPrompts as string) || \"Plan ready for review\",\n output: planFileContent\n ? { content: planFileContent, path: planFilePath }\n : input.output,\n });\n }\n\n if (toolName === \"EnterPlanMode\") {\n await onMessage({\n id: `status-plan-${crypto.randomUUID()}`,\n role: \"assistant\",\n type: \"status\",\n content: \"Planning\",\n isPartial: true,\n createdAt: now,\n });\n return { action: \"allow\" };\n }\n\n if (toolName === \"TodoWrite\") {\n const todos =\n (input.input?.todos as Array<{ content: string; status: string; activeForm: string }>) ??\n [];\n await onMessage({\n id: \"todo-progress\",\n role: \"assistant\",\n type: \"status\",\n content: JSON.stringify({ type: \"todo\", todos }),\n isPartial: true,\n createdAt: now,\n });\n return { action: \"allow\" };\n }\n\n // Tools with UI artifact → forward for approval\n if (input.ui) return waitForInput(input);\n\n // All other tools → auto-approve\n return { action: \"allow\" };\n }\n\n // ---------------------------------------------------------------------------\n // SDK message → ChatMessage conversion (identical to devenv/progress.ts)\n // ---------------------------------------------------------------------------\n\n async function handleProgress(message: unknown): Promise<void> {\n const raw = message as {\n type?: string;\n message?: { content?: Array<Record<string, unknown>> };\n usage?: { input_tokens?: number; output_tokens?: number };\n model?: string;\n _toolUi?: Record<string, ToolUiData>;\n };\n if (!raw?.type) return;\n\n const now = new Date().toISOString();\n\n // --- Assistant messages: thinking, text, tool_use blocks ---\n if (raw.type === \"assistant\" && Array.isArray(raw.message?.content)) {\n for (const block of raw.message!.content) {\n // Thinking blocks — reuse stable ID within a turn\n if (block.type === \"thinking\" && block.thinking) {\n if (!currentThinkingId) currentThinkingId = `thinking-${crypto.randomUUID()}`;\n const msg: ChatMessage = {\n id: currentThinkingId,\n role: \"assistant\",\n type: \"thinking\",\n content: block.thinking as string,\n isPartial: true,\n createdAt: now,\n };\n await onMessage(msg);\n continue;\n }\n\n // Non-thinking block resets the thinking ID\n currentThinkingId = null;\n\n // Text blocks → stream as tokens with stable messageId\n if (block.type === \"text\" && block.text) {\n if (!currentTextId) currentTextId = `text-${crypto.randomUUID()}`;\n currentTextContent += block.text as string;\n\n // Broadcast incremental token event (content is accumulated snapshot)\n broadcast({\n type: \"agent:onToken\",\n taskId,\n messageId: currentTextId,\n content: currentTextContent,\n isComplete: false,\n });\n }\n\n // Track plan file writes (Write tool targeting .md files during plan mode)\n if (\n block.type === \"tool_use\" &&\n block.name === \"Write\" &&\n typeof (block.input as Record<string, unknown>)?.file_path === \"string\" &&\n ((block.input as Record<string, unknown>).file_path as string).endsWith(\".md\")\n ) {\n const input = block.input as { file_path: string; content: string };\n planFileContent = input.content ?? null;\n planFilePath = input.file_path ?? null;\n }\n\n // Tool use blocks — finalize any in-progress text stream first\n if (block.type === \"tool_use\" && block.id && block.name) {\n if (currentTextId) {\n broadcast({\n type: \"agent:onToken\",\n taskId,\n messageId: currentTextId,\n content: currentTextContent,\n isComplete: true,\n isFinal: false, // More content may follow after tool execution\n });\n currentTextId = null;\n currentTextContent = \"\";\n }\n const blockId = block.id as string;\n const blockName = block.name as string;\n toolIds.set(blockId, blockName);\n\n const toolCall: ToolCallData = {\n toolName: blockName,\n toolCallId: blockId,\n status: \"running\",\n input: block.input as Record<string, unknown>,\n };\n\n const msg: ChatMessage = {\n id: `tool-${blockId}`,\n role: \"assistant\",\n type: \"tool\",\n content: formatToolDescription(blockName, block.input as Record<string, unknown>),\n toolCall,\n isPartial: true,\n createdAt: now,\n };\n await onMessage(msg);\n }\n }\n }\n\n // Tool results reset thinking ID and finalize text stream\n currentThinkingId = null;\n if (currentTextId) {\n broadcast({\n type: \"agent:onToken\",\n taskId,\n messageId: currentTextId,\n content: currentTextContent,\n isComplete: true,\n });\n currentTextId = null;\n currentTextContent = \"\";\n }\n\n // --- User messages (tool results): mark tools completed ---\n if (raw.type === \"user\" && Array.isArray(raw.message?.content)) {\n for (const block of raw.message!.content) {\n if (!block.tool_use_id) continue;\n\n const toolUseId = block.tool_use_id as string;\n const output =\n typeof block.content === \"string\" ? block.content : JSON.stringify(block.content);\n const truncated = output && output.length > 1000 ? output.slice(0, 1000) + \"...\" : output;\n\n const toolUiData = raw._toolUi?.[toolUseId];\n const toolUi: ToolUi | undefined = toolUiData\n ? {\n uri: `ui://devenv/${toolUiData.type}`,\n title: toolUiData.title ?? \"\",\n data: toolUiData.data,\n }\n : undefined;\n\n const toolCall: ToolCallData = {\n toolName: toolIds.get(toolUseId) ?? \"\",\n toolCallId: toolUseId,\n status: block.is_error ? \"error\" : \"completed\",\n output: truncated,\n error: block.is_error ? (truncated ?? undefined) : undefined,\n };\n\n const msg: ChatMessage = {\n id: `tool-${toolUseId}`,\n role: \"assistant\",\n type: \"tool\",\n content: truncated ?? \"\",\n toolCall,\n ...(toolUi ? { ui: toolUi } : {}),\n isPartial: false,\n createdAt: now,\n };\n await onMessage(msg);\n toolIds.delete(toolUseId);\n }\n }\n\n // --- Result: complete remaining tools + publish usage ---\n if (raw.type === \"result\") {\n await completeTools();\n\n if (raw.usage) {\n const inputTokens = raw.usage.input_tokens ?? 0;\n const outputTokens = raw.usage.output_tokens ?? 0;\n broadcast({\n type: \"agent:onUsage\",\n taskId,\n chatId,\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n model: raw.model ?? \"unknown\",\n });\n }\n }\n }\n\n return { onMessage, completeTools, waitForInput, handleUserInput, handleProgress };\n}\n","/**\n * Attachment Resolver\n *\n * Downloads file attachments from storage and converts them into\n * content that can be included in Claude Code messages.\n *\n * - Images: saved to workspace, path referenced in message\n * - Text/code files: content inlined in message\n * - Other files: saved to workspace, path referenced in message\n */\n\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nimport { logger } from \"@jarvis/logger\";\nimport { getDefaultAppUrl } from \"./config\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\ninterface Attachment {\n key: string;\n url: string;\n fileName: string;\n mimeType: string;\n size: number;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nconst TEXT_MIME_PREFIXES = [\"text/\", \"application/json\", \"application/xml\", \"application/javascript\"];\nconst IMAGE_MIME_PREFIXES = [\"image/\"];\n\nfunction isTextFile(mimeType: string): boolean {\n return TEXT_MIME_PREFIXES.some((p) => mimeType.startsWith(p));\n}\n\nfunction isImageFile(mimeType: string): boolean {\n return IMAGE_MIME_PREFIXES.some((p) => mimeType.startsWith(p));\n}\n\n/**\n * Resolve a relative storage URL to an absolute URL using the web app origin.\n * Storage URLs from the UI are relative (e.g., /api/v1/storage/read/...).\n */\nfunction resolveUrl(url: string, baseUrl?: string): string {\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) return url;\n const origin = baseUrl || getDefaultAppUrl();\n return `${origin}${url}`;\n}\n\n// =============================================================================\n// Main\n// =============================================================================\n\n/**\n * Process attachments and return additional context to prepend to the user message.\n * Downloads files to workspace as needed.\n */\nexport async function resolveAttachments(\n attachments: Attachment[],\n workspacePath: string,\n baseUrl?: string,\n): Promise<string> {\n if (!attachments.length) return \"\";\n\n const parts: string[] = [];\n const uploadDir = path.join(workspacePath, \".jarvis-uploads\");\n\n for (const att of attachments) {\n try {\n const fullUrl = resolveUrl(att.url, baseUrl);\n\n if (isTextFile(att.mimeType)) {\n // Inline text content\n const res = await fetch(fullUrl);\n if (!res.ok) {\n logger.sys.warn(\"[Attachments] Failed to fetch text file\", {\n fileName: att.fileName,\n status: res.status,\n });\n continue;\n }\n const text = await res.text();\n parts.push(`<file name=\"${att.fileName}\">\\n${text}\\n</file>`);\n } else if (isImageFile(att.mimeType)) {\n // Save image to workspace so Claude Code can view it with its Read tool\n await fs.mkdir(uploadDir, { recursive: true });\n const localPath = path.join(uploadDir, att.fileName);\n const res = await fetch(fullUrl);\n if (!res.ok) {\n logger.sys.warn(\"[Attachments] Failed to fetch image\", {\n fileName: att.fileName,\n status: res.status,\n });\n continue;\n }\n const buffer = Buffer.from(await res.arrayBuffer());\n await fs.writeFile(localPath, buffer);\n parts.push(`[Image attached: ${localPath}]`);\n } else {\n // Save binary file to workspace\n await fs.mkdir(uploadDir, { recursive: true });\n const localPath = path.join(uploadDir, att.fileName);\n const res = await fetch(fullUrl);\n if (!res.ok) {\n logger.sys.warn(\"[Attachments] Failed to fetch file\", {\n fileName: att.fileName,\n status: res.status,\n });\n continue;\n }\n const buffer = Buffer.from(await res.arrayBuffer());\n await fs.writeFile(localPath, buffer);\n parts.push(`[File attached: ${localPath}]`);\n }\n } catch (err) {\n logger.sys.warn(\"[Attachments] Error processing attachment\", {\n fileName: att.fileName,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return parts.length ? parts.join(\"\\n\\n\") : \"\";\n}\n","/**\n * Agent Core\n *\n * Same execution logic as workflows/devenv/src/activities.ts\n * but without Temporal dependencies. Uses WS callbacks for progress.\n */\n\nimport { claudeCodeProvider } from \"@jarvis/anthropic\";\nimport { claudeCodeTools } from \"@jarvis/agent\";\nimport type {\n Context as AppContext,\n Message,\n PendingUserInput,\n UserInputResponse,\n} from \"@jarvis/types\";\n\nimport { createWsProgressHandlers } from \"./progress\";\nimport { resolveAttachments } from \"./attachments\";\nimport { getDefaultAppUrl } from \"./config\";\nimport type { OutboundMessage, AgentDispatchMessage } from \"./protocol\";\n\nimport { logger } from \"@jarvis/logger\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface AgentDeps {\n workspacePath: string;\n anthropicApiKey?: string;\n useSubscription?: boolean;\n userId: string;\n broadcast: (msg: OutboundMessage) => void;\n requestInput: (taskId: string, input: PendingUserInput) => Promise<UserInputResponse>;\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\nexport function createAgent(deps: AgentDeps) {\n const activeTasks = new Map<string, AbortController>();\n\n async function runTask(msg: AgentDispatchMessage): Promise<void> {\n const { taskId, chatId } = msg;\n const abortController = new AbortController();\n activeTasks.set(taskId, abortController);\n\n deps.broadcast({ type: \"agent:status\", status: \"busy\", taskId });\n\n const handlers = createWsProgressHandlers({\n broadcast: deps.broadcast,\n requestInput: deps.requestInput,\n taskId,\n chatId,\n });\n\n try {\n const wsPath = msg.worktreePath || deps.workspacePath;\n const systemMsg = msg.messages.find((m) => m.role === \"system\");\n const nonSystemMessages = msg.messages.filter((m) => m.role !== \"system\");\n\n // Resolve file attachments — download and inline/save to workspace\n if (msg.attachments?.length) {\n const attachmentContext = await resolveAttachments(msg.attachments, wsPath, getDefaultAppUrl());\n if (attachmentContext) {\n // Prepend attachment context to the last user message\n let lastUserIdx = -1;\n for (let i = nonSystemMessages.length - 1; i >= 0; i--) {\n if (nonSystemMessages[i].role === \"user\") {\n lastUserIdx = i;\n break;\n }\n }\n if (lastUserIdx >= 0) {\n const orig = nonSystemMessages[lastUserIdx];\n nonSystemMessages[lastUserIdx] = {\n ...orig,\n content: `${attachmentContext}\\n\\n${orig.content}`,\n };\n }\n }\n }\n\n logger.sys.info(\"[Agent] Running task\", {\n taskId,\n model: msg.model,\n worktreePath: wsPath,\n messageCount: msg.messages.length,\n });\n\n // Same claudeCodeProvider call as devenv activities.ts\n // Just different callbacks: WS broadcast instead of Redis/Temporal\n // Ask mode: block write tools to enforce read-only behavior\n const askModeTools =\n msg.permissionMode === \"ask\"\n ? [\"Edit\", \"Write\", \"MultiEdit\", \"NotebookEdit\"]\n : [];\n const allDisallowed = [...(msg.disallowedTools ?? []), ...askModeTools];\n\n const provider = claudeCodeProvider({\n ...(deps.useSubscription ? { useSubscription: true } : { apiKey: deps.anthropicApiKey }),\n systemPrompt: (systemMsg?.content as string) ?? \"\",\n workingDirectory: wsPath,\n tools: claudeCodeTools,\n ...(msg.maxTurns ? { maxTurns: msg.maxTurns } : {}),\n userId: deps.userId,\n abortController,\n heartbeat: () => {}, // No Temporal heartbeat — WS ping/pong handles liveness\n onProgress: handlers.handleProgress,\n onUserInput: handlers.handleUserInput,\n permissionMode: msg.permissionMode === \"plan\" ? (\"plan\" as const) : (\"default\" as const),\n ...(allDisallowed.length ? { disallowedTools: allDisallowed } : {}),\n ...(msg.thinking ? { thinking: msg.thinking } : {}),\n ...(msg.session ? { session: msg.session } : {}),\n });\n\n const ctx = { requestId: taskId, userId: deps.userId } as AppContext;\n let response = await provider.query(ctx, {\n model: msg.model ?? \"claude-sonnet-4-20250514\",\n messages: nonSystemMessages as Message[],\n });\n\n // If resume failed, retry with fresh session (same as devenv activities)\n if (response.error && msg.session?.resume) {\n const resumeError = response.error.toLowerCase();\n if (\n resumeError.includes(\"session\") ||\n resumeError.includes(\"resume\") ||\n resumeError.includes(\"not found\")\n ) {\n logger.sys.warn(\"[Agent] Resume failed, retrying with fresh session\", {\n error: response.error,\n });\n const { resume: _, forkSession: __, ...fallbackSession } = msg.session;\n const fallbackProvider = claudeCodeProvider({\n ...(deps.useSubscription\n ? { useSubscription: true }\n : { apiKey: deps.anthropicApiKey }),\n workingDirectory: wsPath,\n tools: claudeCodeTools,\n ...(msg.maxTurns ? { maxTurns: msg.maxTurns } : {}),\n userId: deps.userId,\n abortController,\n heartbeat: () => {},\n onProgress: handlers.handleProgress,\n onUserInput: handlers.handleUserInput,\n ...(Object.keys(fallbackSession).length > 0 ? { session: fallbackSession } : {}),\n });\n response = await fallbackProvider.query(ctx, {\n model: msg.model ?? \"claude-sonnet-4-20250514\",\n messages: nonSystemMessages as Message[],\n });\n }\n }\n\n logger.sys.info(\"[Agent] Task completed\", {\n taskId,\n success: !response.error,\n sessionId: response.sessionId,\n });\n\n deps.broadcast({\n type: \"agent:output\",\n taskId,\n output: {\n success: !response.error,\n content: response.content ?? \"\",\n json: response.json,\n error: response.error,\n sessionId: response.sessionId,\n },\n });\n } catch (err) {\n if (abortController.signal.aborted) {\n logger.sys.info(\"[Agent] Task interrupted\", { taskId });\n deps.broadcast({\n type: \"agent:output\",\n taskId,\n output: {\n success: false,\n content: \"\",\n error: \"Interrupted\",\n interrupted: true,\n sessionId: msg.session?.resume,\n },\n });\n } else {\n const error = err instanceof Error ? err.message : String(err);\n logger.sys.error(\"[Agent] Task failed\", { taskId, error });\n deps.broadcast({\n type: \"agent:output\",\n taskId,\n output: { success: false, content: \"\", error },\n });\n }\n } finally {\n activeTasks.delete(taskId);\n deps.broadcast({ type: \"agent:status\", status: \"idle\" });\n }\n }\n\n function cancelTask(taskId: string): void {\n const controller = activeTasks.get(taskId);\n if (controller) {\n logger.sys.info(\"[Agent] Cancelling task\", { taskId });\n controller.abort();\n }\n }\n\n function isRunning(taskId: string): boolean {\n return activeTasks.has(taskId);\n }\n\n function activeTaskCount(): number {\n return activeTasks.size;\n }\n\n return { runTask, cancelTask, isRunning, activeTaskCount };\n}\n\nexport type Agent = ReturnType<typeof createAgent>;\n","/**\n * File Search\n *\n * Searches workspace files by name/path, respecting .gitignore.\n * Used by the \"@\" mention system in the chat UI.\n */\n\nimport { execFile } from \"child_process\";\nimport { promisify } from \"util\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\n\nimport { logger } from \"@jarvis/logger\";\n\nconst execFileAsync = promisify(execFile);\n\nconst MAX_RESULTS = 50;\n\ninterface FileResult {\n path: string;\n name: string;\n type: \"file\" | \"directory\";\n}\n\n/**\n * Search for files in the workspace matching a query.\n * Uses `git ls-files` to respect .gitignore, falls back to basic fs scan.\n */\nexport async function searchFiles(workspacePath: string, query: string): Promise<FileResult[]> {\n try {\n // Use git ls-files for .gitignore-aware listing\n const { stdout } = await execFileAsync(\"git\", [\"ls-files\", \"--cached\", \"--others\", \"--exclude-standard\"], {\n cwd: workspacePath,\n maxBuffer: 1024 * 1024,\n });\n\n const allFiles = stdout.split(\"\\n\").filter(Boolean);\n\n // Extract unique directories from file paths\n const dirSet = new Set<string>();\n for (const f of allFiles) {\n const parts = f.split(\"/\");\n for (let i = 1; i < parts.length; i++) {\n dirSet.add(parts.slice(0, i).join(\"/\"));\n }\n }\n\n // Build combined list: directories + files\n const allEntries: FileResult[] = [\n ...[...dirSet].map((d) => ({ path: d, name: path.basename(d), type: \"directory\" as const })),\n ...allFiles.map((f) => ({ path: f, name: path.basename(f), type: \"file\" as const })),\n ];\n\n // If no query, return top entries (sorted by depth — shallower first, dirs before files)\n if (!query.trim()) {\n const sorted = [...allEntries].sort((a, b) => {\n const depthA = a.path.split(\"/\").length;\n const depthB = b.path.split(\"/\").length;\n if (depthA !== depthB) return depthA - depthB;\n if (a.type !== b.type) return a.type === \"directory\" ? -1 : 1;\n return a.path.localeCompare(b.path);\n });\n return sorted.slice(0, MAX_RESULTS);\n }\n\n const lowerQuery = query.toLowerCase();\n\n // Filter by query — match name or path\n const matched = allEntries\n .filter((e) => e.path.toLowerCase().includes(lowerQuery))\n .sort((a, b) => {\n // Prefer exact name matches\n const aExact = a.name.toLowerCase() === lowerQuery ? 0 : 1;\n const bExact = b.name.toLowerCase() === lowerQuery ? 0 : 1;\n if (aExact !== bExact) return aExact - bExact;\n // Dirs before files\n if (a.type !== b.type) return a.type === \"directory\" ? -1 : 1;\n return a.path.localeCompare(b.path);\n })\n .slice(0, MAX_RESULTS);\n\n return matched;\n } catch (err) {\n logger.sys.warn(\"[Files] git ls-files failed, falling back to fs scan\", {\n error: err instanceof Error ? err.message : String(err),\n });\n return fallbackSearch(workspacePath, query);\n }\n}\n\n/**\n * Fallback file search using fs when git is not available.\n */\nasync function fallbackSearch(workspacePath: string, query: string): Promise<FileResult[]> {\n const results: FileResult[] = [];\n const lowerQuery = query.toLowerCase();\n\n async function walk(dir: string, depth: number) {\n if (depth > 4 || results.length >= MAX_RESULTS) return;\n\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (results.length >= MAX_RESULTS) break;\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n\n const relPath = path.relative(workspacePath, path.join(dir, entry.name));\n\n if (relPath.toLowerCase().includes(lowerQuery)) {\n results.push({\n path: relPath,\n name: entry.name,\n type: entry.isDirectory() ? \"directory\" : \"file\",\n });\n }\n\n if (entry.isDirectory()) {\n await walk(path.join(dir, entry.name), depth + 1);\n }\n }\n } catch {\n // Skip unreadable directories\n }\n }\n\n await walk(workspacePath, 0);\n return results;\n}\n","/**\n * Git Operations\n *\n * Handles git operations dispatched via WS (resolveRepo, createWorktree, commit, diffStats).\n * Same logic as workflows/devenv/src/activities.ts but without Temporal dependencies.\n */\n\nimport { exec as execCb } from \"child_process\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { promisify } from \"util\";\n\nimport { createWorktree, listWorktrees } from \"@jarvis/agent\";\nimport { logger } from \"@jarvis/logger\";\nimport type { InboundMessage, OutboundMessage } from \"@jarvis/types\";\n\nconst exec = promisify(execCb);\n\nexport function createGitHandler(\n workspacePath: string,\n broadcast: (msg: OutboundMessage) => void,\n) {\n async function handle(msg: InboundMessage): Promise<boolean> {\n switch (msg.type) {\n case \"git:resolveRepo\":\n await handleResolveRepo(msg);\n return true;\n case \"git:createWorktree\":\n await handleCreateWorktree(msg);\n return true;\n case \"git:commit\":\n await handleCommit(msg);\n return true;\n case \"git:diffStats\":\n await handleDiffStats(msg);\n return true;\n case \"git:listWorktrees\":\n await handleListWorktrees(msg);\n return true;\n case \"git:browseDir\":\n await handleBrowseDir(msg);\n return true;\n default:\n return false;\n }\n }\n\n function respond(requestId: string, result: unknown, error?: string) {\n broadcast({ type: \"git:response\", requestId, result, error });\n }\n\n async function hasGitDir(dir: string): Promise<boolean> {\n return fs\n .access(path.join(dir, \".git\"))\n .then(() => true)\n .catch(() => false);\n }\n\n async function fetchAndCheckout(repoDir: string, branch: string) {\n await exec(\"git fetch origin\", { cwd: repoDir, timeout: 120000 });\n try {\n await exec(`git checkout \"${branch}\"`, { cwd: repoDir });\n } catch {\n await exec(`git checkout -b \"${branch}\" \"origin/${branch}\"`, { cwd: repoDir });\n }\n await exec(\"git pull --ff-only\", { cwd: repoDir }).catch(() => {});\n }\n\n async function handleResolveRepo(msg: Extract<InboundMessage, { type: \"git:resolveRepo\" }>) {\n try {\n // Fallback chain: explicit path → {workspace}/{name} → {workspace}/{owner}/{name} → clone\n\n // 1. Explicit path from user preferences\n if (msg.repoPath && (await hasGitDir(msg.repoPath))) {\n logger.sys.info(\"[Git] Using explicit repo path\", { repoPath: msg.repoPath });\n await fetchAndCheckout(msg.repoPath, msg.branch);\n respond(msg.requestId, { repoPath: msg.repoPath });\n return;\n }\n\n // 2. {workspace}/{name} (common for monorepos / simple layouts)\n const byName = path.join(workspacePath, msg.name);\n if (await hasGitDir(byName)) {\n logger.sys.info(\"[Git] Found repo by name\", { repoPath: byName });\n await fetchAndCheckout(byName, msg.branch);\n respond(msg.requestId, { repoPath: byName });\n return;\n }\n\n // 3. {workspace}/{owner}/{name} (default layout)\n const byOwnerName = path.join(workspacePath, msg.owner, msg.name);\n if (await hasGitDir(byOwnerName)) {\n logger.sys.info(\"[Git] Found repo by owner/name\", { repoPath: byOwnerName });\n await fetchAndCheckout(byOwnerName, msg.branch);\n respond(msg.requestId, { repoPath: byOwnerName });\n return;\n }\n\n // 4. Clone to {workspace}/{owner}/{name}\n logger.sys.info(\"[Git] Cloning repo...\", { repoDir: byOwnerName });\n await fs.mkdir(path.join(workspacePath, msg.owner), { recursive: true });\n const cloneUrl = `git@github.com:${msg.owner}/${msg.name}.git`;\n await exec(`git clone \"${cloneUrl}\" \"${byOwnerName}\"`, { timeout: 300000 });\n await fetchAndCheckout(byOwnerName, msg.branch);\n respond(msg.requestId, { repoPath: byOwnerName });\n } catch (err) {\n respond(msg.requestId, null, err instanceof Error ? err.message : String(err));\n }\n }\n\n async function handleCreateWorktree(msg: Extract<InboundMessage, { type: \"git:createWorktree\" }>) {\n try {\n const result = await createWorktree({ repoPath: msg.repoPath, taskId: msg.taskId, branch: msg.branch });\n respond(msg.requestId, result);\n } catch (err) {\n respond(msg.requestId, null, err instanceof Error ? err.message : String(err));\n }\n }\n\n async function handleCommit(msg: Extract<InboundMessage, { type: \"git:commit\" }>) {\n try {\n const cwd = msg.worktreePath;\n await exec(\"git add -A\", { cwd });\n const { stdout: status } = await exec(\"git status --porcelain\", { cwd });\n if (!status.trim()) {\n respond(msg.requestId, { success: true, output: \"Nothing to commit\" });\n return;\n }\n const title = msg.title.replace(/\"/g, '\\\\\"');\n const { stdout } = await exec(`git commit -m \"jarvis: ${title}\"`, { cwd });\n respond(msg.requestId, { success: true, output: stdout });\n } catch (err) {\n respond(msg.requestId, { success: false, output: \"\", error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n async function handleDiffStats(msg: Extract<InboundMessage, { type: \"git:diffStats\" }>) {\n try {\n const cwd = msg.worktreePath;\n const { stdout } = await exec(\"git diff --numstat HEAD~1\", { cwd });\n const files: Array<{ file: string; additions: number; deletions: number }> = [];\n let totalAdditions = 0;\n let totalDeletions = 0;\n\n for (const line of stdout.trim().split(\"\\n\")) {\n if (!line.trim()) continue;\n const [add, del, file] = line.split(\"\\t\");\n const additions = add === \"-\" ? 0 : parseInt(add, 10) || 0;\n const deletions = del === \"-\" ? 0 : parseInt(del, 10) || 0;\n files.push({ file, additions, deletions });\n totalAdditions += additions;\n totalDeletions += deletions;\n }\n\n respond(msg.requestId, { files, additions: totalAdditions, deletions: totalDeletions });\n } catch {\n respond(msg.requestId, { files: [], additions: 0, deletions: 0 });\n }\n }\n\n async function handleListWorktrees(msg: Extract<InboundMessage, { type: \"git:listWorktrees\" }>) {\n try {\n const worktrees = await listWorktrees({ repoPath: msg.repoPath });\n respond(msg.requestId, worktrees);\n } catch (err) {\n respond(msg.requestId, null, err instanceof Error ? err.message : String(err));\n }\n }\n\n async function handleBrowseDir(msg: Extract<InboundMessage, { type: \"git:browseDir\" }>) {\n try {\n // Use osascript on macOS to open native folder picker\n const { stdout } = await exec(\n `osascript -e 'set theFolder to POSIX path of (choose folder with prompt \"Select worktree directory\")' -e 'return theFolder'`,\n { timeout: 60000 },\n );\n const selectedPath = stdout.trim();\n respond(msg.requestId, { path: selectedPath });\n } catch (err) {\n // User cancelled or osascript not available\n respond(msg.requestId, null, err instanceof Error ? err.message : String(err));\n }\n }\n\n return { handle };\n}\n","/**\n * Local WS Server\n *\n * Listens on 127.0.0.1 only — for VSCode extension and CLI clients.\n * No auth needed (localhost-only, same user).\n *\n * Supports multiple concurrent clients (TUI, VSCode, web — all receive broadcasts).\n */\n\nimport { WebSocketServer, WebSocket } from \"ws\";\n\nimport type { InboundMessage, OutboundMessage } from \"./protocol\";\n\n/**\n * Check if the agent port is already in use (another agent is running).\n */\nexport async function isPortInUse(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const ws = new WebSocket(`ws://127.0.0.1:${port}`);\n const timeout = setTimeout(() => {\n ws.close();\n resolve(false);\n }, 1000);\n\n ws.on(\"open\", () => {\n clearTimeout(timeout);\n ws.send(JSON.stringify({ type: \"ping\" }));\n ws.on(\"message\", () => {\n ws.close();\n resolve(true);\n });\n });\n\n ws.on(\"error\", () => {\n clearTimeout(timeout);\n resolve(false);\n });\n });\n}\n\nexport function createLocalServer(port: number) {\n const clients = new Set<WebSocket>();\n const wss = new WebSocketServer({ host: \"127.0.0.1\", port });\n\n // Handle port already in use\n wss.on(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") {\n console.error(\n `\\nError: Port ${port} is already in use.` +\n `\\nAnother Jarvis agent is already running on this port.` +\n `\\nClients (jarvis chat, VSCode) can connect to the existing agent.` +\n `\\nTo use a different port: jarvis start --port <port>\\n`,\n );\n process.exit(1);\n }\n throw err;\n });\n\n wss.on(\"connection\", (ws) => {\n clients.add(ws);\n ws.on(\"close\", () => clients.delete(ws));\n ws.on(\"error\", () => clients.delete(ws));\n });\n\n /** Broadcast an outbound message to all connected local clients */\n function broadcast(msg: OutboundMessage): void {\n const data = JSON.stringify(msg);\n for (const ws of clients) {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(data);\n }\n }\n }\n\n /** Register a handler for inbound messages from local clients */\n function onMessage(handler: (msg: InboundMessage, ws: WebSocket) => void): void {\n wss.on(\"connection\", (ws) => {\n ws.on(\"message\", (raw) => {\n try {\n const msg = JSON.parse(raw.toString()) as InboundMessage;\n if (msg.type === \"ping\") {\n ws.send(JSON.stringify({ type: \"pong\" }));\n return;\n }\n handler(msg, ws);\n } catch {\n // Ignore malformed messages\n }\n });\n });\n }\n\n /** Number of connected clients */\n function clientCount(): number {\n return clients.size;\n }\n\n function close(): void {\n for (const ws of clients) ws.close();\n wss.close();\n }\n\n return { broadcast, onMessage, clientCount, close };\n}\n","/**\n * Upstream WS Client\n *\n * Connects to the cloud API so web/mobile can dispatch tasks\n * and receive progress from this local agent.\n */\n\nimport WebSocket from \"ws\";\n\nimport { logger } from \"@jarvis/logger\";\n\nimport type { InboundMessage, OutboundMessage } from \"./protocol\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface UpstreamConfig {\n apiUrl: string;\n token: string;\n refreshToken?: string;\n /** HTTP base URL for the WS server (derived from apiUrl if not set) */\n refreshUrl?: string;\n /** Called when auth fails after all retries — return a new token to reconnect, or null to give up */\n onAuthExhausted?: () => Promise<{ token: string; refreshToken?: string } | null>;\n}\n\n// =============================================================================\n// Client\n// =============================================================================\n\nexport function createUpstreamClient(config: UpstreamConfig) {\n let ws: WebSocket | null = null;\n let messageHandler: ((msg: InboundMessage) => void) | null = null;\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n let closed = false;\n let authFailures = 0;\n let retries = 0;\n let currentToken = config.token;\n const MAX_AUTH_RETRIES = 3;\n const MAX_RETRIES = 3;\n /** Refresh 5 minutes before expiry */\n const REFRESH_BUFFER_MS = 5 * 60 * 1000;\n\n /** Derive HTTP URL from WS URL for refresh endpoint */\n function getRefreshUrl(): string | null {\n if (config.refreshUrl) return config.refreshUrl;\n if (!config.refreshToken) return null;\n // wss://host/ws → https://host/ws/refresh\n return config.apiUrl.replace(/^wss:/, \"https:\").replace(/^ws:/, \"http:\") + \"/refresh\";\n }\n\n /** Decode token expiry (seconds since epoch) without full verification.\n * Supports both JWE (5-part, encrypted) and legacy JWT (3-part, base64) formats. */\n function getTokenExpiry(token: string): number | null {\n try {\n const parts = token.split(\".\");\n if (parts.length === 5) {\n // JWE: header is readable, but payload is encrypted.\n // Parse the protected header to confirm it's a JWE, then\n // decode the token properly to get exp.\n // For scheduling purposes, assume 1 hour if we can't read exp.\n return Math.floor(Date.now() / 1000) + 3600;\n }\n // Legacy JWT: payload is base64-encoded JSON\n const payload = JSON.parse(Buffer.from(parts[1]!, \"base64\").toString());\n return payload.exp ?? null;\n } catch {\n return null;\n }\n }\n\n /** Schedule a token refresh before the current token expires */\n function scheduleRefresh(): void {\n if (refreshTimer) clearTimeout(refreshTimer);\n if (!config.refreshToken) return;\n\n const exp = getTokenExpiry(currentToken);\n if (!exp) return;\n\n const msUntilExpiry = exp * 1000 - Date.now();\n const refreshIn = Math.max(msUntilExpiry - REFRESH_BUFFER_MS, 0);\n\n logger.sys.info(\"[Upstream] Token refresh scheduled\", {\n expiresIn: `${Math.round(msUntilExpiry / 1000)}s`,\n refreshIn: `${Math.round(refreshIn / 1000)}s`,\n });\n\n refreshTimer = setTimeout(refreshToken, refreshIn);\n }\n\n /** Refresh the access token using the refresh token */\n async function refreshToken(): Promise<boolean> {\n const url = getRefreshUrl();\n if (!url || !config.refreshToken) return false;\n\n try {\n logger.sys.info(\"[Upstream] Refreshing token...\");\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken: config.refreshToken }),\n });\n\n if (!res.ok) {\n logger.sys.error(\"[Upstream] Token refresh failed\", { status: res.status });\n return false;\n }\n\n const { token } = (await res.json()) as { token: string };\n currentToken = token;\n logger.sys.info(\"[Upstream] Token refreshed successfully\");\n\n // Reconnect with new token\n ws?.close();\n scheduleRefresh();\n return true;\n } catch (err) {\n logger.sys.error(\"[Upstream] Token refresh error\", {\n error: err instanceof Error ? err.message : String(err),\n });\n return false;\n }\n }\n\n /** Auth exhausted — try re-authenticating from scratch via browser */\n function attemptReauth(): void {\n if (!config.onAuthExhausted) {\n logger.sys.error(\"[Upstream] Auth failed after max retries, giving up\");\n return;\n }\n logger.sys.info(\"[Upstream] Auth exhausted, attempting re-authentication...\");\n config.onAuthExhausted().then((result) => {\n if (!result) {\n logger.sys.error(\"[Upstream] Re-authentication failed, giving up\");\n return;\n }\n currentToken = result.token;\n if (result.refreshToken) config.refreshToken = result.refreshToken;\n authFailures = 0;\n retries = 0;\n logger.sys.info(\"[Upstream] Re-authenticated, reconnecting...\");\n reconnectTimer = setTimeout(connect, 1000);\n }).catch((err) => {\n logger.sys.error(\"[Upstream] Re-authentication error\", {\n error: err instanceof Error ? err.message : String(err),\n });\n });\n }\n\n function connect(): void {\n if (closed) return;\n\n ws = new WebSocket(config.apiUrl, {\n headers: { authorization: `Bearer ${currentToken}` },\n });\n\n ws.on(\"open\", () => {\n authFailures = 0;\n retries = 0;\n logger.sys.info(\"[Upstream] Connected to cloud\", { apiUrl: config.apiUrl });\n scheduleRefresh();\n });\n\n ws.on(\"message\", (raw) => {\n try {\n const msg = JSON.parse(raw.toString()) as InboundMessage;\n if (msg.type === \"ping\") {\n ws?.send(JSON.stringify({ type: \"pong\" }));\n return;\n }\n messageHandler?.(msg);\n } catch {\n // Ignore malformed messages\n }\n });\n\n ws.on(\"close\", (code) => {\n console.error(\"[Upstream] Connection closed, code:\", code);\n if (closed) return;\n\n // Auth failures (4001=missing token, 4003=invalid/expired token)\n if (code === 4001 || code === 4003) {\n // Try refreshing the token before counting as a failure\n if (config.refreshToken) {\n refreshToken().then((ok) => {\n if (ok) {\n reconnectTimer = setTimeout(connect, 1000);\n } else {\n authFailures++;\n if (authFailures >= MAX_AUTH_RETRIES) {\n attemptReauth();\n return;\n }\n reconnectTimer = setTimeout(connect, 3000);\n }\n });\n return;\n }\n\n authFailures++;\n if (authFailures >= MAX_AUTH_RETRIES) {\n attemptReauth();\n return;\n }\n logger.sys.warn(\"[Upstream] Auth failed, retrying...\", {\n code,\n attempt: authFailures,\n maxRetries: MAX_AUTH_RETRIES,\n });\n reconnectTimer = setTimeout(connect, 3000);\n return;\n }\n\n retries++;\n if (retries >= MAX_RETRIES) {\n logger.sys.error(\"[Upstream] Max reconnect attempts reached, giving up\", {\n attempts: retries,\n });\n return;\n }\n\n logger.sys.info(\"[Upstream] Disconnected, reconnecting in 3s...\", {\n code,\n attempt: retries,\n maxRetries: MAX_RETRIES,\n });\n reconnectTimer = setTimeout(connect, 3000);\n });\n\n ws.on(\"error\", (err) => {\n console.error(\"[Upstream] Connection error:\", err.message);\n logger.sys.error(\"[Upstream] Connection error\", {\n error: err.message,\n });\n });\n }\n\n function send(msg: OutboundMessage): void {\n if (ws?.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(msg));\n }\n }\n\n function onMessage(handler: (msg: InboundMessage) => void): void {\n messageHandler = handler;\n }\n\n function isConnected(): boolean {\n return ws?.readyState === WebSocket.OPEN;\n }\n\n function close(): void {\n closed = true;\n if (reconnectTimer) clearTimeout(reconnectTimer);\n if (refreshTimer) clearTimeout(refreshTimer);\n ws?.close();\n }\n\n return { connect, send, onMessage, isConnected, close };\n}\n\nexport type UpstreamClient = ReturnType<typeof createUpstreamClient>;\n","/**\n * Agent Start\n *\n * Pure WS agent — no Temporal on the user's machine.\n *\n * 1. Local WS server (VSCode/CLI clients connect here)\n * 2. Upstream WS client (cloud hub — receives dispatches from Temporal workflow)\n * 3. Runs Claude Code locally, streams progress via WS\n *\n * The Temporal workflow dispatches to this agent through the WS hub.\n * Temporal stays in the cloud as source of truth for session state.\n */\n\nimport type { InboundMessage, OutboundMessage, UserInputResponse } from \"@jarvis/types\";\n\nimport { logger } from \"@jarvis/logger\";\nimport { createAgent } from \"./agent\";\nimport { searchFiles } from \"./files\";\nimport { createGitHandler } from \"./git\";\nimport { createLocalServer } from \"./server\";\nimport { createUpstreamClient, type UpstreamConfig } from \"./upstream\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface StartAgentOptions {\n port: number;\n workspacePath: string;\n anthropicApiKey?: string;\n useSubscription?: boolean;\n userId: string;\n upstream?: UpstreamConfig;\n}\n\n// =============================================================================\n// Start\n// =============================================================================\n\nexport async function startAgent(options: StartAgentOptions): Promise<void> {\n // Pending input requests: inputId → resolve function\n const pendingInputs = new Map<string, (response: UserInputResponse) => void>();\n\n // --- Local WS server (VSCode, CLI) ---\n const server = createLocalServer(options.port);\n\n // --- Upstream WS client (cloud — optional) ---\n const upstream = options.upstream ? createUpstreamClient(options.upstream) : null;\n\n // --- Broadcast to ALL clients (local + upstream) ---\n function broadcast(msg: OutboundMessage): void {\n server.broadcast(msg);\n upstream?.send(msg);\n }\n\n // --- Input request/response flow ---\n function requestInput(taskId: string, input: import(\"@jarvis/types\").PendingUserInput): Promise<UserInputResponse> {\n return new Promise((resolve) => {\n pendingInputs.set(input.id, resolve);\n broadcast({ type: \"agent:onUserInputRequest\", taskId, input });\n });\n }\n\n // --- Git handler ---\n const git = createGitHandler(options.workspacePath, broadcast);\n\n // --- Create the agent ---\n const agent = createAgent({\n workspacePath: options.workspacePath,\n anthropicApiKey: options.anthropicApiKey,\n useSubscription: options.useSubscription,\n userId: options.userId,\n broadcast,\n requestInput,\n });\n\n // --- Handle inbound messages (from any source — local or upstream) ---\n function handleMessage(msg: InboundMessage): void {\n // Try git operations first\n if (msg.type.startsWith(\"git:\")) {\n git.handle(msg);\n return;\n }\n\n switch (msg.type) {\n case \"agent:dispatch\":\n agent.runTask(msg);\n break;\n\n case \"agent:abort\":\n agent.cancelTask(msg.taskId);\n break;\n\n case \"agent:userInput\": {\n const response: UserInputResponse = {\n action: msg.action as UserInputResponse[\"action\"],\n data: msg.data,\n feedback: msg.feedback,\n };\n const resolve = pendingInputs.get(msg.inputId);\n if (resolve) {\n resolve(response);\n pendingInputs.delete(msg.inputId);\n }\n break;\n }\n\n case \"files:search\": {\n const filesMsg = msg as import(\"@jarvis/types\").FilesSearchMessage;\n searchFiles(options.workspacePath, filesMsg.query)\n .then((files) => {\n broadcast({ type: \"files:response\", requestId: filesMsg.requestId, files });\n })\n .catch((err) => {\n logger.sys.error(\"[Agent] File search failed\", {\n error: err instanceof Error ? err.message : String(err),\n });\n broadcast({ type: \"files:response\", requestId: filesMsg.requestId, files: [] });\n });\n break;\n }\n\n case \"ping\":\n // Handled at transport level\n break;\n }\n }\n\n // Wire up message handlers\n server.onMessage((msg) => handleMessage(msg));\n upstream?.onMessage(handleMessage);\n\n // Connect upstream if configured\n upstream?.connect();\n\n // --- Status output ---\n console.log();\n console.log(`Jarvis Agent v0.0.0`);\n console.log(` Local: ws://127.0.0.1:${options.port}`);\n console.log(` Workspace: ${options.workspacePath}`);\n console.log(` User: ${options.userId}`);\n if (upstream) {\n console.log(` Cloud: ${options.upstream!.apiUrl}`);\n }\n console.log();\n console.log(\"Waiting for tasks...\");\n console.log();\n\n // --- Graceful shutdown ---\n const shutdown = () => {\n console.log(\"\\nShutting down...\");\n server.close();\n upstream?.close();\n process.exit(0);\n };\n\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n}\n","/**\n * Chat Entry Point\n *\n * Launches the interactive TUI:\n * 1. Load settings (file + CLI flags)\n * 2. Auto-start agent server as a detached child process (silent)\n * 3. Render Ink app — owns stdout/stderr exclusively\n */\n\nimport React from \"react\";\nimport { render } from \"ink\";\nimport { spawn, type ChildProcess } from \"child_process\";\nimport { fileURLToPath } from \"url\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport os from \"os\";\nimport WebSocket from \"ws\";\n\nimport { loadSettings, mergeCliFlags, type TuiSettings } from \"./settings\";\nimport { loadConfig } from \"../config\";\nimport { App } from \"./app\";\n\n/** Agent child process — killed on TUI exit */\nlet agentChild: ChildProcess | null = null;\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface ChatOptions {\n model?: string;\n mode?: string;\n thinking?: string;\n thinkingBudget?: string;\n maxTurns?: string;\n port: string;\n server: boolean; // --no-server sets to false\n workspace?: string;\n}\n\n// =============================================================================\n// Launch\n// =============================================================================\n\nexport async function launchChat(opts: ChatOptions): Promise<void> {\n const port = parseInt(opts.port, 10);\n const config = loadConfig();\n\n // Load and merge settings\n const fileSettings = loadSettings();\n const settings: TuiSettings = mergeCliFlags(fileSettings, {\n model: opts.model,\n mode: opts.mode,\n thinking: opts.thinking,\n thinkingBudget: opts.thinkingBudget,\n maxTurns: opts.maxTurns,\n });\n\n const workspacePath = opts.workspace ?? config?.workspacePath ?? process.cwd();\n\n // Auto-start agent server if --no-server wasn't passed\n let weSpawnedAgent = false;\n if (opts.server) {\n const isRunning = await checkAgentRunning(port);\n if (!isRunning) {\n spawnAgentProcess(port, workspacePath);\n weSpawnedAgent = true;\n await waitForAgent(port);\n }\n }\n\n // Kill agent on exit if we spawned it\n const cleanup = () => {\n if (weSpawnedAgent && agentChild && !agentChild.killed) {\n agentChild.kill(\"SIGTERM\");\n agentChild = null;\n }\n };\n\n process.on(\"exit\", cleanup);\n process.on(\"SIGINT\", () => {\n cleanup();\n process.exit(0);\n });\n process.on(\"SIGTERM\", () => {\n cleanup();\n process.exit(0);\n });\n process.on(\"SIGHUP\", () => {\n cleanup();\n process.exit(0);\n });\n\n // Render the TUI — Ink owns stdout/stderr from here\n const { waitUntilExit } = render(\n React.createElement(App, {\n initialSettings: settings,\n port,\n workspacePath,\n }),\n );\n\n await waitUntilExit();\n cleanup();\n}\n\n// =============================================================================\n// Agent Process (child, killed on TUI exit)\n// =============================================================================\n\n/**\n * Spawn `jarvis start` as a child process.\n * stdout/stderr → ~/.jarvis/agent.log (TUI owns the terminal).\n * NOT detached — dies when the TUI process exits.\n */\nfunction spawnAgentProcess(port: number, workspacePath: string): void {\n const config = loadConfig();\n\n // Log file for agent output\n const logDir = path.join(os.homedir(), \".jarvis\");\n fs.mkdirSync(logDir, { recursive: true });\n const logFile = path.join(logDir, \"agent.log\");\n const logFd = fs.openSync(logFile, \"a\");\n\n // Find the bin entry point (same binary the user invoked)\n const __filename = fileURLToPath(import.meta.url);\n const cliRoot = path.resolve(path.dirname(__filename), \"../..\");\n const binPath = path.join(cliRoot, \"bin\", \"jarvis.mjs\");\n\n // Build args for `jarvis start`\n const args = [\"start\", \"--port\", String(port), \"--workspace\", workspacePath];\n\n if (config?.apiUrl && config?.token) {\n // upstream is auto-detected from config\n } else {\n args.push(\"--no-upstream\");\n }\n\n const apiKey = config?.anthropicApiKey ?? process.env.ANTHROPIC_API_KEY;\n if (apiKey) {\n args.push(\"--api-key\", apiKey);\n }\n\n agentChild = spawn(process.execPath, [binPath, ...args], {\n stdio: [\"ignore\", logFd, logFd],\n cwd: workspacePath,\n env: { ...process.env },\n });\n\n fs.closeSync(logFd);\n}\n\n// =============================================================================\n// Agent Health Check\n// =============================================================================\n\nasync function checkAgentRunning(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n const ws = new WebSocket(`ws://127.0.0.1:${port}`);\n const timeout = setTimeout(() => {\n ws.close();\n resolve(false);\n }, 1000);\n\n ws.on(\"open\", () => {\n clearTimeout(timeout);\n ws.send(JSON.stringify({ type: \"ping\" }));\n ws.on(\"message\", () => {\n ws.close();\n resolve(true);\n });\n });\n\n ws.on(\"error\", () => {\n clearTimeout(timeout);\n resolve(false);\n });\n } catch {\n resolve(false);\n }\n });\n}\n\nasync function waitForAgent(port: number, maxAttempts = 30): Promise<void> {\n for (let i = 0; i < maxAttempts; i++) {\n const running = await checkAgentRunning(port);\n if (running) return;\n await new Promise((r) => setTimeout(r, 250));\n }\n // Don't console.log here — TUI will show connection status in status bar\n}\n","/**\n * TUI Settings\n *\n * Load/save/merge ~/.jarvis/settings.json — user preferences for the TUI.\n * These are TUI-local and applied per agent:dispatch message.\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\n\nimport type { ThinkingConfig } from \"@jarvis/types\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type PermissionMode = \"supervised\" | \"auto\" | \"plan\" | \"yolo\";\n\nexport interface TuiSettings {\n model: string;\n thinking: ThinkingConfig;\n permissionMode: PermissionMode;\n maxTurns: number;\n theme: \"dark\" | \"light\";\n disallowedTools: string[];\n}\n\n// =============================================================================\n// Defaults\n// =============================================================================\n\nexport const DEFAULT_SETTINGS: TuiSettings = {\n model: \"claude-sonnet-4-20250514\",\n thinking: { type: \"adaptive\" },\n permissionMode: \"supervised\",\n maxTurns: 25,\n theme: \"dark\",\n disallowedTools: [],\n};\n\n// =============================================================================\n// Paths\n// =============================================================================\n\nconst SETTINGS_DIR = path.join(os.homedir(), \".jarvis\");\nconst SETTINGS_FILE = path.join(SETTINGS_DIR, \"settings.json\");\n\n// =============================================================================\n// Operations\n// =============================================================================\n\nexport function loadSettings(): TuiSettings {\n try {\n const raw = fs.readFileSync(SETTINGS_FILE, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<TuiSettings>;\n return { ...DEFAULT_SETTINGS, ...parsed };\n } catch {\n return { ...DEFAULT_SETTINGS };\n }\n}\n\nexport function saveSettings(settings: TuiSettings): void {\n fs.mkdirSync(SETTINGS_DIR, { recursive: true });\n fs.writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2) + \"\\n\");\n}\n\n/**\n * Merge CLI flags into loaded settings.\n * Only non-undefined flags override.\n */\nexport function mergeCliFlags(\n settings: TuiSettings,\n flags: {\n model?: string;\n mode?: string;\n thinking?: string;\n thinkingBudget?: string;\n maxTurns?: string;\n },\n): TuiSettings {\n const merged = { ...settings };\n\n if (flags.model) merged.model = flags.model;\n if (flags.mode) merged.permissionMode = flags.mode as PermissionMode;\n if (flags.maxTurns) merged.maxTurns = parseInt(flags.maxTurns, 10);\n\n if (flags.thinking) {\n const type = flags.thinking as ThinkingConfig[\"type\"];\n merged.thinking = { type };\n if (type === \"enabled\" && flags.thinkingBudget) {\n merged.thinking.budgetTokens = parseInt(flags.thinkingBudget, 10);\n }\n }\n\n return merged;\n}\n\nexport function getSettingsPath(): string {\n return SETTINGS_FILE;\n}\n","/**\n * Jarvis TUI App\n *\n * Rendering strategy — zero dynamic content above the input bar:\n * - ALL messages go into <Static> (rendered once, never re-rendered)\n * - Streaming text is committed to <Static> only when finalized\n * - The ONLY dynamic elements are: spinner + overlays + input bar + footer\n * - This eliminates all jumpiness during streaming\n */\n\nimport React, { useState, useCallback, useRef, useEffect } from \"react\";\nimport { Box, Static, Text, useApp, useInput } from \"ink\";\n\nimport type { OutboundMessage, AgentOnTokenEvent } from \"@jarvis/types\";\n\nimport type { TuiSettings } from \"./settings\";\nimport { useAgentClient } from \"./hooks/use-agent-client\";\nimport { useMessages, type DisplayMessage } from \"./hooks/use-messages\";\nimport { useTask } from \"./hooks/use-task\";\nimport { useSettings } from \"./hooks/use-settings\";\nimport { parseSlashCommand } from \"./utils/slash-commands\";\nimport { shouldAutoApprove } from \"./utils/auto-approve\";\n\nimport { WelcomeHeader } from \"./components/welcome-header\";\nimport { UserMessage } from \"./components/user-message\";\nimport { Spinner } from \"./components/spinner\";\nimport { Divider } from \"./components/divider\";\nimport { PromptInput } from \"./components/prompt-input\";\nimport { StatusBar } from \"./components/status-bar\";\nimport { PermissionDialog } from \"./components/permission-dialog\";\nimport { PlanReview } from \"./components/plan-review\";\nimport { MaxIterations } from \"./components/max-iterations\";\nimport { HelpMenu } from \"./components/help-menu\";\nimport { StatusDisplay } from \"./components/status-display\";\nimport { ModelPicker } from \"./components/model-picker\";\nimport { ModePicker } from \"./components/mode-picker\";\nimport { ThinkingPicker } from \"./components/thinking-picker\";\nimport { SettingsDialog } from \"./components/settings-dialog\";\nimport { Notification } from \"./components/notification\";\nimport { MarkdownText } from \"./components/markdown-text\";\nimport { t } from \"./theme\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\ntype Overlay = \"none\" | \"help\" | \"status\" | \"config\" | \"model\" | \"mode\" | \"thinking\";\n\ninterface AppProps {\n initialSettings: TuiSettings;\n port: number;\n workspacePath: string;\n}\n\ninterface StaticItem {\n key: string;\n node: React.ReactNode;\n}\n\n// =============================================================================\n// App\n// =============================================================================\n\nexport function App({ initialSettings, port, workspacePath }: AppProps) {\n const { exit } = useApp();\n const [overlay, setOverlay] = useState<Overlay>(\"none\");\n const [notification, setNotification] = useState<string | null>(null);\n\n const { settings, setModel, setThinking, setPermissionMode, cyclePermissionMode, setMaxTurns } =\n useSettings(initialSettings);\n\n const {\n messages,\n streamingTextContent: _streamingTextContent,\n addUserMessage,\n handleChatMessage,\n handleTokenEvent,\n clearMessages,\n } = useMessages();\n\n // ==========================================================================\n // Static output — append-only list rendered by <Static>\n // ==========================================================================\n\n const [staticItems, setStaticItems] = useState<StaticItem[]>([\n {\n key: \"welcome\",\n node: <WelcomeHeader settings={settings} workspacePath={workspacePath} />,\n },\n ]);\n const committedIdsRef = useRef(new Set<string>());\n\n // Commit finalized messages to static.\n // Thinking messages are always isPartial=true (never finalized by the agent),\n // so we commit them when a newer message appears after them (thinking is over).\n useEffect(() => {\n const newItems: StaticItem[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]!;\n if (committedIdsRef.current.has(msg.id)) continue;\n\n // Non-partial → commit immediately\n if (!msg.isPartial) {\n committedIdsRef.current.add(msg.id);\n newItems.push({ key: msg.id, node: renderMessage(msg) });\n continue;\n }\n\n // Partial thinking → commit if a later message exists (thinking phase is over)\n if (msg.type === \"thinking\" && i < messages.length - 1) {\n committedIdsRef.current.add(msg.id);\n newItems.push({ key: msg.id, node: renderMessage(msg) });\n continue;\n }\n }\n\n if (newItems.length > 0) {\n setStaticItems((prev) => [...prev, ...newItems]);\n }\n }, [messages]);\n\n // ==========================================================================\n // WS handler\n // ==========================================================================\n\n const handleWsMessage = useCallback(\n (msg: OutboundMessage) => {\n switch (msg.type) {\n case \"agent:onMessage\":\n handleChatMessage(msg.message);\n break;\n case \"agent:onToken\":\n handleTokenEvent(msg as AgentOnTokenEvent);\n break;\n case \"agent:onUsage\":\n task.addTokens(msg.totalTokens);\n break;\n case \"agent:onUserInputRequest\": {\n if (shouldAutoApprove(settings.permissionMode, msg.input)) {\n task.setPendingInput(msg.input);\n setTimeout(() => {\n if (task.currentTaskId) {\n client.respondToInput(task.currentTaskId, msg.input.id, \"allow\");\n task.setPendingInput(null);\n task.setAgentState(\"busy\");\n }\n }, 0);\n } else {\n task.setPendingInput(msg.input);\n task.setAgentState(\"awaiting-input\");\n }\n break;\n }\n case \"agent:output\":\n task.setAgentState(\"idle\");\n if (msg.output.sessionId) task.setSessionId(msg.output.sessionId);\n break;\n case \"agent:status\":\n if (msg.status === \"idle\") task.setAgentState(\"idle\");\n break;\n }\n },\n [settings.permissionMode],\n );\n\n const client = useAgentClient(port, handleWsMessage);\n const task = useTask(client, settings);\n\n // ==========================================================================\n // Keybindings\n // ==========================================================================\n\n useInput((_input, key) => {\n if (key.ctrl && _input === \"c\") {\n if (task.agentState === \"busy\") task.abort();\n else exit();\n return;\n }\n if (key.ctrl && _input === \"d\") { exit(); return; }\n if (key.shift && key.tab) {\n setNotification(`Mode: ${cyclePermissionMode()}`);\n return;\n }\n });\n\n const handleEscape = useCallback(() => {\n if (overlay !== \"none\") setOverlay(\"none\");\n else if (task.agentState === \"busy\" || task.agentState === \"awaiting-input\") task.abort();\n }, [overlay, task]);\n\n const handleHelp = useCallback(() => {\n setOverlay((prev) => (prev === \"help\" ? \"none\" : \"help\"));\n }, []);\n\n const handleSubmit = useCallback(\n (value: string) => {\n const cmd = parseSlashCommand(value);\n if (cmd) {\n switch (cmd.command) {\n case \"help\": setOverlay(\"help\"); return;\n case \"config\": setOverlay(\"config\"); return;\n case \"model\":\n if (cmd.arg) { setModel(cmd.arg); setNotification(`Model: ${cmd.arg}`); }\n else setOverlay(\"model\");\n return;\n case \"mode\":\n if (cmd.arg) { setPermissionMode(cmd.arg as TuiSettings[\"permissionMode\"]); setNotification(`Mode: ${cmd.arg}`); }\n else setOverlay(\"mode\");\n return;\n case \"thinking\":\n if (cmd.arg) {\n const tp = cmd.arg as \"adaptive\" | \"enabled\" | \"disabled\";\n setThinking({ type: tp, ...(tp === \"enabled\" ? { budgetTokens: 32768 } : {}) });\n setNotification(`Thinking: ${cmd.arg}`);\n } else setOverlay(\"thinking\");\n return;\n case \"status\": setOverlay(\"status\"); return;\n case \"clear\":\n clearMessages();\n committedIdsRef.current.clear();\n setStaticItems([{\n key: `welcome-${Date.now()}`,\n node: <WelcomeHeader settings={settings} workspacePath={workspacePath} />,\n }]);\n setNotification(\"Conversation cleared\");\n return;\n case \"compact\": setNotification(\"Compact not yet implemented\"); return;\n case \"exit\": exit(); return;\n }\n }\n addUserMessage(value);\n task.dispatch(value);\n },\n [addUserMessage, task, setModel, setThinking, setPermissionMode, clearMessages, exit, settings, workspacePath],\n );\n\n const closeOverlay = useCallback(() => setOverlay(\"none\"), []);\n\n // ==========================================================================\n // Render\n // ==========================================================================\n\n return (\n <Box flexDirection=\"column\">\n {/* All committed output — rendered once, scrolls naturally in terminal */}\n <Static items={staticItems}>\n {(item) => (\n <Box key={item.key} flexDirection=\"column\">\n {item.node}\n </Box>\n )}\n </Static>\n\n {/* === Everything below is the ONLY dynamic area === */}\n\n {/* Spinner (shown while agent is working) */}\n {task.agentState === \"busy\" && <Spinner />}\n\n {/* Overlays */}\n {overlay === \"help\" && <HelpMenu onClose={closeOverlay} />}\n {overlay === \"status\" && (\n <StatusDisplay settings={settings} connected={client.connected} port={port} sessionId={task.sessionId} totalTokens={task.totalTokens} workspacePath={workspacePath} onClose={closeOverlay} />\n )}\n {overlay === \"config\" && (\n <SettingsDialog settings={settings} onUpdateModel={setModel} onUpdateThinking={setThinking} onUpdateMode={setPermissionMode} onUpdateMaxTurns={setMaxTurns} onClose={closeOverlay} />\n )}\n {overlay === \"model\" && (\n <ModelPicker currentModel={settings.model} onSelect={setModel} onClose={closeOverlay} />\n )}\n {overlay === \"mode\" && (\n <ModePicker currentMode={settings.permissionMode} onSelect={setPermissionMode} onClose={closeOverlay} />\n )}\n {overlay === \"thinking\" && (\n <ThinkingPicker current={settings.thinking} onSelect={setThinking} onClose={closeOverlay} />\n )}\n\n {/* Permission dialogs */}\n {task.pendingInput && task.agentState === \"awaiting-input\" && (\n <>\n {task.pendingInput.type === \"tool\" && (\n <PermissionDialog input={task.pendingInput} onRespond={task.respondToInput} />\n )}\n {task.pendingInput.type === \"plan\" && (\n <PlanReview input={task.pendingInput} onRespond={task.respondToInput} />\n )}\n {task.pendingInput.type === \"max_iterations\" && (\n <MaxIterations input={task.pendingInput} onRespond={task.respondToInput} />\n )}\n </>\n )}\n\n {/* Notification */}\n <Notification message={notification} />\n\n {/* Bottom bar */}\n <Divider />\n <Box paddingX={0} marginY={0}>\n <PromptInput\n onSubmit={handleSubmit}\n onEscape={handleEscape}\n onHelp={handleHelp}\n onSlashCommand={handleSubmit}\n isLoading={task.agentState !== \"idle\"}\n workspacePath={workspacePath}\n />\n </Box>\n <Divider />\n <StatusBar\n mode={settings.permissionMode}\n model={settings.model}\n thinking={settings.thinking}\n agentState={task.agentState}\n totalTokens={task.totalTokens}\n connected={client.connected}\n sessionId={task.sessionId}\n workspacePath={workspacePath}\n />\n </Box>\n );\n}\n\n// =============================================================================\n// Message renderer — creates the React node for a committed message\n// =============================================================================\n\nfunction renderMessage(m: DisplayMessage): React.ReactNode {\n // User messages — gold arrow, extra spacing above\n if (m.type === \"user\") {\n return (\n <Box marginTop={1}>\n <UserMessage content={m.content} />\n </Box>\n );\n }\n\n // Tool calls — colored dot + tool name + description\n if (m.type === \"tool\") {\n const status = m.toolCall?.status ?? \"running\";\n const dot = status === \"completed\" ? t.toolSuccess : status === \"error\" ? t.toolError : t.toolRunning;\n const desc = getToolDesc(m.toolCall);\n return (\n <Box>\n <Box width={2} flexShrink={0}><Text color={dot}>●</Text></Box>\n <Text bold>{m.toolCall?.toolName ?? \"Tool\"}</Text>\n {desc && <Text color={t.dim}> {desc}</Text>}\n {m.toolCall?.error && <Text color={t.toolError}> {truncate(m.toolCall.error, 60)}</Text>}\n </Box>\n );\n }\n\n // Thinking — dim dot + muted content, spacing above\n if (m.type === \"thinking\") {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Box>\n <Box width={2} flexShrink={0}><Text color={t.dim}>●</Text></Box>\n <Text color={t.dim} underline>Thinking</Text>\n </Box>\n {m.content && (\n <Box paddingLeft={2}>\n <Text color={t.dim}>{m.content}</Text>\n </Box>\n )}\n </Box>\n );\n }\n\n // Assistant text — green dot + markdown, spacing above\n if (m.type === \"assistant-text\") {\n return (\n <Box flexDirection=\"row\" marginTop={1}>\n <Box width={2} flexShrink={0}><Text color={t.toolSuccess}>●</Text></Box>\n <Box flexDirection=\"column\" flexGrow={1}>\n <MarkdownText content={m.content} />\n </Box>\n </Box>\n );\n }\n\n return null;\n}\n\nfunction getToolDesc(toolCall?: DisplayMessage[\"toolCall\"]): string {\n if (!toolCall) return \"\";\n const { toolName, input, output } = toolCall;\n if (toolCall.status === \"completed\" && output != null) {\n const out = String(output);\n if (out.length < 50 && !out.includes(\"\\n\")) return out;\n }\n if (!input) return \"\";\n switch (toolName) {\n case \"Read\": return String(input.file_path ?? \"\");\n case \"Write\": return String(input.file_path ?? \"\");\n case \"Edit\": return String(input.file_path ?? \"\");\n case \"Bash\": return truncate(String(input.command ?? \"\"), 50);\n case \"Glob\": return String(input.pattern ?? \"\");\n case \"Grep\": return String(input.pattern ?? \"\");\n case \"Agent\": return String(input.description ?? \"\");\n default: return \"\";\n }\n}\n\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + \"…\";\n}\n","/**\n * useAgentClient Hook\n *\n * WS client hook that mirrors AgentClient from apps/vscode/src/agent.client.ts.\n * Connects to the local agent server on 127.0.0.1:PORT.\n */\n\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport WebSocket from \"ws\";\n\nimport type {\n InboundMessage,\n OutboundMessage,\n AgentDispatchMessage,\n} from \"@jarvis/types\";\n\nexport interface AgentClientState {\n connected: boolean;\n send: (msg: InboundMessage) => void;\n dispatchTask: (task: AgentDispatchMessage) => void;\n abortTask: (taskId: string, reason?: string) => void;\n respondToInput: (\n taskId: string,\n inputId: string,\n action: string,\n data?: Record<string, unknown>,\n feedback?: string,\n ) => void;\n}\n\nexport function useAgentClient(\n port: number,\n onMessage: (msg: OutboundMessage) => void,\n): AgentClientState {\n const [connected, setConnected] = useState(false);\n const wsRef = useRef<WebSocket | null>(null);\n const closedRef = useRef(false);\n const onMessageRef = useRef(onMessage);\n onMessageRef.current = onMessage;\n\n useEffect(() => {\n closedRef.current = false;\n\n function tryConnect() {\n if (closedRef.current) return;\n\n try {\n const ws = new WebSocket(`ws://127.0.0.1:${port}`);\n wsRef.current = ws;\n\n ws.on(\"open\", () => setConnected(true));\n\n ws.on(\"message\", (raw) => {\n try {\n const msg = JSON.parse(raw.toString()) as OutboundMessage;\n if (msg.type === \"pong\") return;\n onMessageRef.current(msg);\n } catch {\n // Ignore malformed\n }\n });\n\n ws.on(\"close\", () => {\n setConnected(false);\n if (!closedRef.current) {\n setTimeout(tryConnect, 3000);\n }\n });\n\n ws.on(\"error\", () => {\n // Will trigger close → reconnect\n });\n } catch {\n if (!closedRef.current) {\n setTimeout(tryConnect, 3000);\n }\n }\n }\n\n tryConnect();\n\n return () => {\n closedRef.current = true;\n wsRef.current?.close();\n wsRef.current = null;\n };\n }, [port]);\n\n const send = useCallback((msg: InboundMessage) => {\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n wsRef.current.send(JSON.stringify(msg));\n }\n }, []);\n\n const dispatchTask = useCallback(\n (task: AgentDispatchMessage) => send(task),\n [send],\n );\n\n const abortTask = useCallback(\n (taskId: string, reason?: string) =>\n send({ type: \"agent:abort\", taskId, reason }),\n [send],\n );\n\n const respondToInput = useCallback(\n (\n taskId: string,\n inputId: string,\n action: string,\n data?: Record<string, unknown>,\n feedback?: string,\n ) => send({ type: \"agent:userInput\", taskId, inputId, action, data, feedback }),\n [send],\n );\n\n return { connected, send, dispatchTask, abortTask, respondToInput };\n}\n","/**\n * useMessages Hook\n *\n * Manages the message list state from agent:onMessage + agent:onToken events.\n * Messages are keyed by ID — partial messages get replaced when updated.\n * Token events are throttled to prevent excessive re-renders.\n */\n\nimport { useState, useCallback, useRef } from \"react\";\n\nimport type { ChatMessage, AgentOnTokenEvent } from \"@jarvis/types\";\n\nexport interface DisplayMessage {\n id: string;\n type: \"user\" | \"assistant-text\" | \"thinking\" | \"tool\" | \"status\";\n content: string;\n toolCall?: ChatMessage[\"toolCall\"];\n thinking?: ChatMessage[\"thinking\"];\n ui?: ChatMessage[\"ui\"];\n isPartial?: boolean;\n createdAt?: string;\n}\n\nexport interface MessagesState {\n messages: DisplayMessage[];\n streamingTextContent: string | null;\n addUserMessage: (content: string) => void;\n handleChatMessage: (msg: ChatMessage) => void;\n handleTokenEvent: (event: AgentOnTokenEvent) => void;\n clearMessages: () => void;\n}\n\nconst TOKEN_THROTTLE_MS = 80; // ~12fps for streaming text, reduces flicker\n\nexport function useMessages(): MessagesState {\n const [messages, setMessages] = useState<DisplayMessage[]>([]);\n const [streamingTextContent, setStreamingTextContent] = useState<string | null>(null);\n const streamingIdRef = useRef<string | null>(null);\n const throttleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingContentRef = useRef<string | null>(null);\n\n const addUserMessage = useCallback((content: string) => {\n const msg: DisplayMessage = {\n id: `user-${Date.now()}`,\n type: \"user\",\n content,\n createdAt: new Date().toISOString(),\n };\n setMessages((prev) => [...prev, msg]);\n }, []);\n\n const handleChatMessage = useCallback((msg: ChatMessage) => {\n const display: DisplayMessage = {\n id: msg.id,\n type:\n msg.type === \"thinking\"\n ? \"thinking\"\n : msg.type === \"tool\"\n ? \"tool\"\n : msg.type === \"status\"\n ? \"status\"\n : \"assistant-text\",\n content: msg.content,\n toolCall: msg.toolCall,\n thinking: msg.thinking,\n ui: msg.ui,\n isPartial: msg.isPartial,\n createdAt: msg.createdAt,\n };\n\n setMessages((prev) => {\n const idx = prev.findIndex((m) => m.id === msg.id);\n if (idx >= 0) {\n const updated = [...prev];\n updated[idx] = display;\n return updated;\n }\n return [...prev, display];\n });\n }, []);\n\n const flushStreamingContent = useCallback(() => {\n if (pendingContentRef.current !== null) {\n setStreamingTextContent(pendingContentRef.current);\n }\n throttleRef.current = null;\n }, []);\n\n const handleTokenEvent = useCallback((event: AgentOnTokenEvent) => {\n if (event.isComplete) {\n // Finalize: flush any pending content, add as message, clear streaming\n if (throttleRef.current) {\n clearTimeout(throttleRef.current);\n throttleRef.current = null;\n }\n streamingIdRef.current = null;\n pendingContentRef.current = null;\n setStreamingTextContent(null);\n setMessages((prev) => {\n const existing = prev.findIndex((m) => m.id === event.messageId);\n const finalMsg: DisplayMessage = {\n id: event.messageId,\n type: \"assistant-text\",\n content: event.content,\n isPartial: false,\n createdAt: new Date().toISOString(),\n };\n if (existing >= 0) {\n const updated = [...prev];\n updated[existing] = finalMsg;\n return updated;\n }\n return [...prev, finalMsg];\n });\n } else {\n // Streaming: throttle updates to reduce re-renders\n streamingIdRef.current = event.messageId;\n pendingContentRef.current = event.content;\n if (!throttleRef.current) {\n // Immediately show first token, then throttle subsequent ones\n setStreamingTextContent(event.content);\n throttleRef.current = setTimeout(flushStreamingContent, TOKEN_THROTTLE_MS);\n }\n }\n }, [flushStreamingContent]);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n setStreamingTextContent(null);\n streamingIdRef.current = null;\n pendingContentRef.current = null;\n if (throttleRef.current) {\n clearTimeout(throttleRef.current);\n throttleRef.current = null;\n }\n }, []);\n\n return {\n messages,\n streamingTextContent,\n addUserMessage,\n handleChatMessage,\n handleTokenEvent,\n clearMessages,\n };\n}\n","/**\n * useTask Hook\n *\n * Manages task lifecycle: dispatch, abort, user input responses.\n * Constructs agent:dispatch messages from TUI settings.\n */\n\nimport { useState, useCallback, useRef } from \"react\";\nimport crypto from \"crypto\";\n\nimport type { AgentDispatchMessage, PendingUserInput } from \"@jarvis/types\";\n\nimport type { TuiSettings } from \"../settings\";\nimport type { AgentClientState } from \"./use-agent-client\";\n\nexport type AgentState = \"idle\" | \"busy\" | \"awaiting-input\";\n\nexport interface TaskState {\n agentState: AgentState;\n currentTaskId: string | null;\n sessionId: string | null;\n totalTokens: number;\n pendingInput: PendingUserInput | null;\n dispatch: (userMessage: string) => void;\n abort: () => void;\n respondToInput: (\n action: string,\n data?: Record<string, unknown>,\n feedback?: string,\n ) => void;\n setAgentState: (state: AgentState) => void;\n setPendingInput: (input: PendingUserInput | null) => void;\n addTokens: (tokens: number) => void;\n setSessionId: (id: string) => void;\n}\n\nexport function useTask(\n client: AgentClientState,\n settings: TuiSettings,\n): TaskState {\n const [agentState, setAgentState] = useState<AgentState>(\"idle\");\n const [currentTaskId, setCurrentTaskId] = useState<string | null>(null);\n const [sessionId, setSessionId] = useState<string | null>(null);\n const [totalTokens, setTotalTokens] = useState(0);\n const [pendingInput, setPendingInput] = useState<PendingUserInput | null>(null);\n const chatIdRef = useRef(`chat-${crypto.randomUUID()}`);\n\n const dispatch = useCallback(\n (userMessage: string) => {\n const taskId = crypto.randomUUID();\n setCurrentTaskId(taskId);\n setAgentState(\"busy\");\n\n const msg: AgentDispatchMessage = {\n type: \"agent:dispatch\",\n taskId,\n chatId: chatIdRef.current,\n messages: [{ role: \"user\", content: userMessage }],\n model: settings.model,\n maxTurns: settings.maxTurns,\n permissionMode:\n settings.permissionMode === \"yolo\"\n ? \"auto\"\n : settings.permissionMode,\n disallowedTools:\n settings.disallowedTools.length > 0\n ? settings.disallowedTools\n : undefined,\n ...(sessionId\n ? { session: { resume: sessionId, persistSession: true } }\n : { session: { persistSession: true } }),\n };\n\n client.dispatchTask(msg);\n },\n [client, settings, sessionId],\n );\n\n const abort = useCallback(() => {\n if (currentTaskId) {\n client.abortTask(currentTaskId);\n }\n }, [client, currentTaskId]);\n\n const respondToInput = useCallback(\n (\n action: string,\n data?: Record<string, unknown>,\n feedback?: string,\n ) => {\n if (currentTaskId && pendingInput) {\n client.respondToInput(\n currentTaskId,\n pendingInput.id,\n action,\n data,\n feedback,\n );\n setPendingInput(null);\n setAgentState(\"busy\");\n }\n },\n [client, currentTaskId, pendingInput],\n );\n\n const addTokens = useCallback((tokens: number) => {\n setTotalTokens((prev) => prev + tokens);\n }, []);\n\n return {\n agentState,\n currentTaskId,\n sessionId,\n totalTokens,\n pendingInput,\n dispatch,\n abort,\n respondToInput,\n setAgentState,\n setPendingInput,\n addTokens,\n setSessionId,\n };\n}\n","/**\n * useSettings Hook\n *\n * Runtime settings state with persistence to ~/.jarvis/settings.json.\n */\n\nimport { useState, useCallback } from \"react\";\n\nimport type { ThinkingConfig } from \"@jarvis/types\";\n\nimport {\n type TuiSettings,\n type PermissionMode,\n saveSettings,\n} from \"../settings\";\n\nconst MODE_CYCLE: PermissionMode[] = [\"supervised\", \"auto\", \"plan\", \"yolo\"];\n\nexport interface SettingsState {\n settings: TuiSettings;\n setModel: (model: string) => void;\n setThinking: (thinking: ThinkingConfig) => void;\n setPermissionMode: (mode: PermissionMode) => void;\n cyclePermissionMode: () => PermissionMode;\n setMaxTurns: (turns: number) => void;\n setTheme: (theme: \"dark\" | \"light\") => void;\n}\n\nexport function useSettings(initial: TuiSettings): SettingsState {\n const [settings, setSettings] = useState<TuiSettings>(initial);\n\n const update = useCallback((patch: Partial<TuiSettings>) => {\n setSettings((prev) => {\n const next = { ...prev, ...patch };\n saveSettings(next);\n return next;\n });\n }, []);\n\n const setModel = useCallback(\n (model: string) => update({ model }),\n [update],\n );\n\n const setThinking = useCallback(\n (thinking: ThinkingConfig) => update({ thinking }),\n [update],\n );\n\n const setPermissionMode = useCallback(\n (permissionMode: PermissionMode) => update({ permissionMode }),\n [update],\n );\n\n const cyclePermissionMode = useCallback(() => {\n let nextMode: PermissionMode = \"supervised\";\n setSettings((prev) => {\n const idx = MODE_CYCLE.indexOf(prev.permissionMode);\n nextMode = MODE_CYCLE[(idx + 1) % MODE_CYCLE.length]!;\n const next = { ...prev, permissionMode: nextMode };\n saveSettings(next);\n return next;\n });\n return nextMode;\n }, []);\n\n const setMaxTurns = useCallback(\n (maxTurns: number) => update({ maxTurns }),\n [update],\n );\n\n const setTheme = useCallback(\n (theme: \"dark\" | \"light\") => update({ theme }),\n [update],\n );\n\n return {\n settings,\n setModel,\n setThinking,\n setPermissionMode,\n cyclePermissionMode,\n setMaxTurns,\n setTheme,\n };\n}\n","/**\n * Slash Command Parser\n *\n * Parses /command [args] from user input.\n */\n\nexport type SlashCommand =\n | { command: \"help\" }\n | { command: \"config\" }\n | { command: \"model\"; arg?: string }\n | { command: \"mode\"; arg?: string }\n | { command: \"thinking\"; arg?: string }\n | { command: \"status\" }\n | { command: \"clear\" }\n | { command: \"compact\" }\n | { command: \"exit\" };\n\nexport function parseSlashCommand(input: string): SlashCommand | null {\n const trimmed = input.trim();\n if (!trimmed.startsWith(\"/\")) return null;\n\n const parts = trimmed.split(/\\s+/);\n const cmd = parts[0]!.slice(1).toLowerCase();\n const arg = parts.slice(1).join(\" \") || undefined;\n\n switch (cmd) {\n case \"help\":\n case \"h\":\n return { command: \"help\" };\n case \"config\":\n case \"settings\":\n return { command: \"config\" };\n case \"model\":\n case \"m\":\n return { command: \"model\", arg };\n case \"mode\":\n return { command: \"mode\", arg };\n case \"thinking\":\n return { command: \"thinking\", arg };\n case \"status\":\n return { command: \"status\" };\n case \"clear\":\n return { command: \"clear\" };\n case \"compact\":\n return { command: \"compact\" };\n case \"exit\":\n case \"quit\":\n case \"q\":\n return { command: \"exit\" };\n default:\n return null;\n }\n}\n","/**\n * Auto-Approval Logic\n *\n * Determines whether a tool should be auto-approved based on permission mode.\n */\n\nimport type { PendingUserInput } from \"@jarvis/types\";\n\nimport type { PermissionMode } from \"../settings\";\n\n/** Tools considered safe for auto-approval in \"auto\" mode */\nconst SAFE_TOOLS = new Set([\n \"Read\",\n \"Glob\",\n \"Grep\",\n \"WebSearch\",\n \"WebFetch\",\n \"Agent\",\n \"TodoWrite\",\n \"Skill\",\n \"ToolSearch\",\n]);\n\n/**\n * Returns true if the pending input should be auto-approved without showing a dialog.\n */\nexport function shouldAutoApprove(\n mode: PermissionMode,\n input: PendingUserInput,\n): boolean {\n // Plan type always needs review in plan mode, auto-approve otherwise\n if (input.type === \"plan\") {\n return mode !== \"plan\" && mode !== \"supervised\";\n }\n\n // Max iterations: always ask\n if (input.type === \"max_iterations\") {\n return false;\n }\n\n // Yolo mode: approve everything\n if (mode === \"yolo\") return true;\n\n // Auto mode: approve safe tools, ask for dangerous\n if (mode === \"auto\") {\n const toolName = input.toolName ?? \"\";\n return SAFE_TOOLS.has(toolName);\n }\n\n // Supervised/plan: never auto-approve tools\n return false;\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport type { TuiSettings } from \"../settings\";\nimport { t } from \"../theme\";\n\ninterface WelcomeHeaderProps {\n settings: TuiSettings;\n workspacePath: string;\n}\n\nconst LOGO = [\n \" ╦╔═╗╦═╗╦ ╦╦╔═╗\",\n \" ║╠═╣╠╦╝╚╗╔╝║╚═╗\",\n \" ╚╝╩ ╩╩╚═ ╚╝ ╩╚═╝\",\n];\n\nfunction shortModel(model: string): string {\n const m = model.match(/(sonnet|opus|haiku)[- ](\\d+(?:\\.\\d+)?)/i);\n if (m) return `${m[1]![0]!.toUpperCase()}${m[1]!.slice(1)} ${m[2]}`;\n return model;\n}\n\nfunction shortPath(p: string): string {\n const home = process.env.HOME ?? \"\";\n if (home && p.startsWith(home)) return \"~\" + p.slice(home.length);\n return p;\n}\n\nexport function WelcomeHeader({ settings, workspacePath }: WelcomeHeaderProps) {\n return (\n <Box flexDirection=\"column\" paddingTop={1} paddingBottom={0}>\n <Box flexDirection=\"column\" paddingLeft={4}>\n {LOGO.map((line, i) => (\n <Text key={i} color={t.logo} bold>{line}</Text>\n ))}\n </Box>\n <Box flexDirection=\"column\" paddingLeft={4} marginTop={0}>\n <Text>\n <Text color={t.logo} bold>Jarvis</Text>\n <Text color={t.dim}>{\" v0.1.0\"}</Text>\n </Text>\n <Text color={t.dim}>\n {shortModel(settings.model)} · {settings.permissionMode}\n </Text>\n <Text color={t.dim}>\n {shortPath(workspacePath)}\n </Text>\n </Box>\n </Box>\n );\n}\n","/**\n * TUI Theme\n *\n * JARVIS terminal color palette — matches the web app theme:\n * Primary: #FFB800 (gold/amber — Iron Man's gold)\n * Secondary: #DC4545 (soft red — Iron Man's red)\n * Neutral: #1E293B (navy-tinted gray)\n *\n * Only accents/indicators are colorful. Regular text stays default.\n */\n\n// =============================================================================\n// Brand Colors (hex values for Ink's `color` prop)\n// =============================================================================\n\nexport const colors = {\n // Primary — gold\n gold: \"#FFB800\",\n goldDim: \"#B38200\",\n goldBg: \"#3D2E00\",\n\n // Secondary — red\n red: \"#DC4545\",\n redDim: \"#991B1B\",\n\n // Accent — purple (from SDK theme)\n purple: \"#8270DB\",\n\n // Status\n green: \"#22C55E\",\n yellow: \"#FFB800\",\n cyan: \"#06B6D4\",\n\n // Neutral\n navy: \"#1E293B\",\n navyLight: \"#64748B\",\n navyLighter: \"#94A3B8\",\n\n // Foreground\n text: undefined, // default terminal color\n dim: \"#64748B\",\n muted: \"#94A3B8\",\n} as const;\n\n// =============================================================================\n// Semantic tokens — what color each UI element uses\n// =============================================================================\n\nexport const t = {\n // Logo & branding\n logo: colors.gold,\n\n // Prompt\n promptArrow: colors.gold,\n\n // Spinner / working indicator\n spinner: colors.gold,\n\n // Divider\n divider: colors.navyLight,\n\n // Tool icons\n toolSuccess: colors.green,\n toolError: colors.red,\n toolRunning: colors.gold,\n\n // Permission mode indicator\n mode: {\n supervised: colors.green,\n auto: colors.gold,\n plan: colors.purple,\n yolo: colors.red,\n } as Record<string, string>,\n\n // Headings in markdown\n heading: colors.gold,\n\n // Slash commands in help menu\n command: colors.gold,\n\n // Status bar\n hint: colors.dim,\n disconnected: colors.red,\n\n // Overlays — border accents\n dialogBorder: colors.navyLight,\n dialogTitle: colors.gold,\n dialogAction: colors.gold,\n dialogDanger: colors.red,\n\n // Notification flash\n notification: colors.gold,\n\n // Dim / muted text\n dim: colors.dim,\n muted: colors.muted,\n} as const;\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport { t } from \"../theme\";\n\ninterface UserMessageProps {\n content: string;\n}\n\nexport function UserMessage({ content }: UserMessageProps) {\n return (\n <Box marginTop={1}>\n <Text color={t.promptArrow} bold>{\"❯ \"}</Text>\n <Text>{content}</Text>\n </Box>\n );\n}\n","import React, { useState, useEffect, useRef } from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport { t } from \"../theme\";\n\n// =============================================================================\n// Fake word generator (from packages/ui StreamingText)\n// =============================================================================\n\nconst PREFIXES = [\n \"Pro\", \"Re\", \"De\", \"Con\", \"Syn\", \"Meta\", \"Hyper\", \"Trans\",\n \"Neo\", \"Poly\", \"Multi\", \"Sub\", \"Inter\", \"Ultra\", \"Semi\",\n \"Auto\", \"Para\", \"Mono\",\n];\nconst ROOTS = [\n \"cog\", \"flux\", \"morph\", \"lex\", \"graph\", \"lys\", \"gen\", \"struct\",\n \"val\", \"duc\", \"fract\", \"gress\", \"ject\", \"spect\", \"vert\", \"tract\",\n \"form\", \"plex\", \"crypt\", \"volt\", \"quant\", \"phas\", \"nex\", \"fus\",\n];\nconst SUFFIXES = [\n \"izing\", \"ating\", \"ifying\", \"enting\", \"uting\", \"ecting\", \"uming\",\n \"ering\", \"ising\", \"ancing\", \"encing\", \"oring\", \"uring\", \"aling\",\n];\n\nfunction pick<T>(arr: T[]): T {\n return arr[Math.floor(Math.random() * arr.length)]!;\n}\n\nfunction generateWord(): string {\n const usePrefix = Math.random() > 0.3;\n const prefix = usePrefix ? pick(PREFIXES) : \"\";\n const root = pick(ROOTS);\n const suffix = pick(SUFFIXES);\n const word = prefix + root + suffix;\n return word.charAt(0).toUpperCase() + word.slice(1);\n}\n\n// =============================================================================\n// Spinner glyph — Claude Code style: growing/shrinking symbols\n// Wrapped in fixed-width Box to prevent jumpiness\n// =============================================================================\n\nconst GLYPHS =\n process.platform === \"darwin\"\n ? [\"·\", \"✢\", \"✳\", \"✶\", \"✻\", \"✽\"]\n : [\"·\", \"✢\", \"*\", \"✶\", \"✻\", \"✽\"];\n\nconst GLYPH_FRAMES = [...GLYPHS, ...[...GLYPHS].reverse()];\n\n// =============================================================================\n// Component\n// =============================================================================\n\nexport function Spinner() {\n const [glyphFrame, setGlyphFrame] = useState(0);\n const [word, setWord] = useState(generateWord);\n const [overwriteIdx, setOverwriteIdx] = useState(0);\n const [prevWord, setPrevWord] = useState(\"\");\n const [phase, setPhase] = useState<\"display\" | \"transition\">(\"display\");\n const startRef = useRef(Date.now());\n\n // Glyph animation: 120ms per frame\n useEffect(() => {\n const timer = setInterval(\n () => setGlyphFrame((f) => (f + 1) % GLYPH_FRAMES.length),\n 120,\n );\n return () => clearInterval(timer);\n }, []);\n\n // Word transition: overwrite char by char at 50ms\n useEffect(() => {\n if (phase === \"transition\") {\n const totalLen = (prevWord + \"…\").length;\n if (overwriteIdx < totalLen) {\n const timer = setTimeout(() => setOverwriteIdx((i) => i + 1), 50);\n return () => clearTimeout(timer);\n } else {\n setPhase(\"display\");\n }\n }\n }, [overwriteIdx, prevWord, phase]);\n\n // Wait then start next word transition\n useEffect(() => {\n if (phase === \"display\") {\n const timer = setTimeout(() => {\n setPrevWord(word);\n setWord(generateWord());\n setOverwriteIdx(0);\n setPhase(\"transition\");\n }, 2500);\n return () => clearTimeout(timer);\n }\n }, [phase, word]);\n\n const elapsed = Math.floor((Date.now() - startRef.current) / 1000);\n\n // Build display text\n let displayText: string;\n if (phase === \"display\") {\n displayText = word + \"…\";\n } else {\n const oldText = prevWord + \"…\";\n const newText = word + \"…\";\n displayText = newText.slice(0, overwriteIdx) + oldText.slice(overwriteIdx);\n }\n\n return (\n <Box marginTop={1}>\n <Box width={2} flexShrink={0}>\n <Text color={t.spinner}>{GLYPH_FRAMES[glyphFrame]}</Text>\n </Box>\n <Text color={t.spinner}>{displayText}</Text>\n {elapsed > 2 && <Text color={t.dim}> {elapsed}s</Text>}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport { t } from \"../theme\";\nimport { useTerminal } from \"../hooks/use-terminal\";\n\nexport function Divider() {\n const { columns } = useTerminal();\n return (\n <Box>\n <Text color={t.divider}>{\"─\".repeat(columns)}</Text>\n </Box>\n );\n}\n","/**\n * useTerminal Hook\n *\n * Terminal dimensions with resize tracking.\n */\n\nimport { useState, useEffect } from \"react\";\n\nexport interface TerminalSize {\n columns: number;\n rows: number;\n}\n\nexport function useTerminal(): TerminalSize {\n const [size, setSize] = useState<TerminalSize>({\n columns: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n });\n\n useEffect(() => {\n const onResize = () => {\n setSize({\n columns: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n });\n };\n\n process.stdout.on(\"resize\", onResize);\n return () => {\n process.stdout.off(\"resize\", onResize);\n };\n }, []);\n\n return size;\n}\n","/**\n * PromptInput with autocomplete\n *\n * Detects:\n * - `/` at start → slash command suggestions\n * - `@` → file picker suggestions\n * - `?` on empty input → help toggle\n * - Esc → abort/close\n * - Arrow keys → navigate suggestions when open\n * - Enter → select suggestion or submit\n * - Tab → accept suggestion\n */\n\nimport React, { useState, useCallback, useMemo } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport TextInput from \"ink-text-input\";\n\nimport { t } from \"../theme\";\nimport {\n type Suggestion,\n filterSlashCommands,\n Suggestions,\n} from \"./suggestions\";\nimport { filterFiles, FilePicker } from \"./file-picker\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\ntype PickerMode = \"none\" | \"slash\" | \"file\";\n\ninterface PromptInputProps {\n onSubmit: (value: string) => void;\n onEscape: () => void;\n onHelp: () => void;\n onSlashCommand: (command: string) => void;\n isLoading?: boolean;\n workspacePath: string;\n}\n\n// =============================================================================\n// Component\n// =============================================================================\n\nexport function PromptInput({\n onSubmit,\n onEscape,\n onHelp,\n onSlashCommand,\n isLoading,\n workspacePath,\n}: PromptInputProps) {\n const [value, setValue] = useState(\"\");\n const [selectedIdx, setSelectedIdx] = useState(0);\n\n // Detect picker mode from input\n const pickerMode: PickerMode = useMemo(() => {\n if (isLoading) return \"none\";\n if (value.startsWith(\"/\")) return \"slash\";\n // Detect @ at start or after whitespace\n const atMatch = value.match(/(^|\\s)@([^\\s]*)$/);\n if (atMatch) return \"file\";\n return \"none\";\n }, [value, isLoading]);\n\n // Get filtered suggestions\n const suggestions: Suggestion[] = useMemo(() => {\n if (pickerMode === \"slash\") {\n return filterSlashCommands(value.slice(1)); // remove leading /\n }\n if (pickerMode === \"file\") {\n const atMatch = value.match(/(^|\\s)@([^\\s]*)$/);\n const query = atMatch?.[2] ?? \"\";\n return filterFiles(query, workspacePath);\n }\n return [];\n }, [pickerMode, value, workspacePath]);\n\n // Reset selection when suggestions change\n const prevSugLen = React.useRef(suggestions.length);\n if (suggestions.length !== prevSugLen.current) {\n prevSugLen.current = suggestions.length;\n if (selectedIdx >= suggestions.length) {\n setSelectedIdx(Math.max(0, suggestions.length - 1));\n }\n }\n\n const handleMove = useCallback(\n (delta: number) => {\n setSelectedIdx((prev) => {\n const next = prev + delta;\n if (next < 0) return suggestions.length - 1;\n if (next >= suggestions.length) return 0;\n return next;\n });\n },\n [suggestions.length],\n );\n\n const handleSelectSuggestion = useCallback(\n (item: Suggestion) => {\n if (pickerMode === \"slash\") {\n // Execute the slash command directly\n setValue(\"\");\n onSlashCommand(item.value);\n } else if (pickerMode === \"file\") {\n // Replace @query with the file path\n const before = value.replace(/(^|\\s)@[^\\s]*$/, \"$1\");\n setValue(before + item.value + \" \");\n }\n setSelectedIdx(0);\n },\n [pickerMode, value, onSlashCommand],\n );\n\n const handleChange = useCallback(\n (text: string) => {\n if (!isLoading) {\n setValue(text);\n setSelectedIdx(0);\n }\n },\n [isLoading],\n );\n\n useInput((_input, key) => {\n // Escape\n if (key.escape) {\n if (pickerMode !== \"none\") {\n // Close suggestions by clearing the trigger char\n if (pickerMode === \"slash\") setValue(\"\");\n else setValue(value.replace(/(^|\\s)@[^\\s]*$/, \"$1\"));\n setSelectedIdx(0);\n } else {\n onEscape();\n }\n return;\n }\n\n // Arrow keys when suggestions are open\n if (pickerMode !== \"none\") {\n if (key.upArrow) {\n handleMove(-1);\n return;\n }\n if (key.downArrow) {\n handleMove(1);\n return;\n }\n if (key.tab && suggestions[selectedIdx]) {\n handleSelectSuggestion(suggestions[selectedIdx]);\n return;\n }\n }\n\n // ? on empty input → help\n if (_input === \"?\" && value === \"\" && !isLoading) {\n onHelp();\n return;\n }\n\n // Enter\n if (key.return) {\n // If suggestions open and one is selected, pick it\n if (pickerMode === \"slash\" && suggestions[selectedIdx]) {\n handleSelectSuggestion(suggestions[selectedIdx]);\n return;\n }\n // Otherwise submit\n if (value.trim() && !isLoading) {\n const text = value.trim();\n setValue(\"\");\n setSelectedIdx(0);\n onSubmit(text);\n }\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n {/* Suggestions dropdown (above input) */}\n {pickerMode === \"slash\" && suggestions.length > 0 && (\n <Suggestions\n items={suggestions}\n selectedIndex={selectedIdx}\n />\n )}\n {pickerMode === \"file\" && suggestions.length > 0 && (\n <FilePicker\n items={suggestions}\n selectedIndex={selectedIdx}\n />\n )}\n\n {/* Input line */}\n <Box>\n <Text color={isLoading ? t.dim : t.promptArrow} dimColor={isLoading}>\n {\"❯ \"}\n </Text>\n <TextInput\n value={value}\n onChange={handleChange}\n placeholder=\"\"\n showCursor={!isLoading}\n />\n </Box>\n </Box>\n );\n}\n","/**\n * Suggestions Dropdown\n *\n * Renders filtered slash command suggestions.\n * Navigation is handled by PromptInput — this is a pure display component.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport { t } from \"../theme\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface Suggestion {\n id: string;\n icon: string;\n label: string;\n description: string;\n value: string;\n}\n\ninterface SuggestionsProps {\n items: Suggestion[];\n selectedIndex: number;\n maxVisible?: number;\n}\n\n// =============================================================================\n// Slash Commands\n// =============================================================================\n\nexport const SLASH_COMMANDS: Suggestion[] = [\n { id: \"help\", icon: \"?\", label: \"/help\", description: \"Show available commands\", value: \"/help\" },\n { id: \"config\", icon: \"⚙\", label: \"/config\", description: \"Open settings\", value: \"/config\" },\n { id: \"model\", icon: \"◆\", label: \"/model\", description: \"Switch model\", value: \"/model\" },\n { id: \"mode\", icon: \"●\", label: \"/mode\", description: \"Switch permission mode\", value: \"/mode\" },\n { id: \"thinking\", icon: \"▸\", label: \"/thinking\", description: \"Toggle thinking config\", value: \"/thinking\" },\n { id: \"status\", icon: \"ℹ\", label: \"/status\", description: \"Show session info\", value: \"/status\" },\n { id: \"clear\", icon: \"✕\", label: \"/clear\", description: \"Clear conversation\", value: \"/clear\" },\n { id: \"compact\", icon: \"◇\", label: \"/compact\", description: \"Compact old messages\", value: \"/compact\" },\n { id: \"exit\", icon: \"→\", label: \"/exit\", description: \"Exit Jarvis\", value: \"/exit\" },\n];\n\nexport function filterSlashCommands(query: string): Suggestion[] {\n const q = query.toLowerCase();\n if (!q) return SLASH_COMMANDS;\n return SLASH_COMMANDS.filter(\n (cmd) =>\n cmd.label.toLowerCase().includes(q) ||\n cmd.description.toLowerCase().includes(q),\n );\n}\n\n// =============================================================================\n// Component (pure display — no useInput)\n// =============================================================================\n\nexport function Suggestions({\n items,\n selectedIndex,\n maxVisible = 6,\n}: SuggestionsProps) {\n if (items.length === 0) return null;\n\n const half = Math.floor(maxVisible / 2);\n const startIdx = Math.max(\n 0,\n Math.min(selectedIndex - half, items.length - maxVisible),\n );\n const visible = items.slice(startIdx, startIdx + maxVisible);\n\n return (\n <Box flexDirection=\"column\" paddingLeft={2} marginBottom={0}>\n {visible.map((item, i) => {\n const realIdx = startIdx + i;\n const selected = realIdx === selectedIndex;\n return (\n <Box key={item.id}>\n <Text color={selected ? t.dialogTitle : t.dim}>\n {selected ? \"❯ \" : \" \"}\n </Text>\n <Text color={selected ? t.dialogTitle : undefined} bold={selected}>\n {item.icon} {item.label}\n </Text>\n <Text color={t.dim}>{\" \"}{item.description}</Text>\n </Box>\n );\n })}\n </Box>\n );\n}\n","/**\n * File Picker\n *\n * Triggered by @ in the input. Shows files matching the query.\n * Pure display component — navigation handled by PromptInput.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport path from \"path\";\nimport fs from \"fs\";\n\nimport { t } from \"../theme\";\nimport type { Suggestion } from \"./suggestions\";\n\n// =============================================================================\n// File scanning\n// =============================================================================\n\nlet cachedFiles: string[] | null = null;\n\nfunction scanFiles(workspacePath: string): string[] {\n if (cachedFiles) return cachedFiles;\n\n const results: string[] = [];\n const ignoreSet = new Set([\n \"node_modules\", \".git\", \"dist\", \"build\", \".next\", \"coverage\",\n \".turbo\", \".cache\", \"__pycache__\", \".DS_Store\",\n ]);\n\n function walk(dir: string, depth: number) {\n if (depth > 4) return;\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (ignoreSet.has(entry.name) || entry.name.startsWith(\".\")) continue;\n const full = path.join(dir, entry.name);\n const rel = path.relative(workspacePath, full);\n if (entry.isDirectory()) {\n results.push(rel + \"/\");\n walk(full, depth + 1);\n } else {\n results.push(rel);\n }\n if (results.length > 500) return;\n }\n } catch {\n // permission errors\n }\n }\n\n walk(workspacePath, 0);\n cachedFiles = results;\n return results;\n}\n\nexport function filterFiles(query: string, workspacePath: string): Suggestion[] {\n const files = scanFiles(workspacePath);\n const q = query.toLowerCase();\n\n const matches = q\n ? files.filter((f) => f.toLowerCase().includes(q))\n : files.slice(0, 20);\n\n return matches.slice(0, 20).map((f) => ({\n id: `file-${f}`,\n icon: f.endsWith(\"/\") ? \"📁\" : \"📄\",\n label: f,\n description: \"\",\n value: f,\n }));\n}\n\nexport function resetFileCache(): void {\n cachedFiles = null;\n}\n\n// =============================================================================\n// Component (pure display — no useInput)\n// =============================================================================\n\ninterface FilePickerProps {\n items: Suggestion[];\n selectedIndex: number;\n maxVisible?: number;\n}\n\nexport function FilePicker({\n items,\n selectedIndex,\n maxVisible = 8,\n}: FilePickerProps) {\n if (items.length === 0) {\n return (\n <Box paddingLeft={2}>\n <Text color={t.dim}>No files found</Text>\n </Box>\n );\n }\n\n const half = Math.floor(maxVisible / 2);\n const startIdx = Math.max(\n 0,\n Math.min(selectedIndex - half, items.length - maxVisible),\n );\n const visible = items.slice(startIdx, startIdx + maxVisible);\n\n return (\n <Box flexDirection=\"column\" paddingLeft={2} marginBottom={0}>\n {visible.map((item, i) => {\n const realIdx = startIdx + i;\n const selected = realIdx === selectedIndex;\n return (\n <Box key={item.id}>\n <Text color={selected ? t.dialogTitle : t.dim}>\n {selected ? \"❯ \" : \" \"}\n </Text>\n <Text color={selected ? t.dialogTitle : undefined} bold={selected}>\n {item.icon} {item.label}\n </Text>\n </Box>\n );\n })}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport type { PermissionMode } from \"../settings\";\nimport type { AgentState } from \"../hooks/use-task\";\nimport type { ThinkingConfig } from \"@jarvis/types\";\nimport { formatTokens } from \"../utils/format-tokens\";\nimport { useTerminal } from \"../hooks/use-terminal\";\nimport { t } from \"../theme\";\n\ninterface StatusBarProps {\n mode: PermissionMode;\n model: string;\n thinking: ThinkingConfig;\n agentState: AgentState;\n totalTokens: number;\n connected: boolean;\n sessionId: string | null;\n workspacePath: string;\n}\n\nfunction shortModel(model: string): string {\n const m = model.match(/(sonnet|opus|haiku)[- ](\\d)/i);\n if (m) return `${m[1]![0]!.toUpperCase()}${m[1]!.slice(1)} ${m[2]}`;\n return model;\n}\n\nfunction getThinkingLabel(thinking: ThinkingConfig): string {\n if (thinking.type === \"disabled\") return \"\";\n if (thinking.type === \"adaptive\") return \"thinking\";\n return thinking.budgetTokens\n ? `thinking (${Math.round(thinking.budgetTokens / 1024)}k)`\n : \"thinking\";\n}\n\nfunction shortPath(p: string): string {\n const home = process.env.HOME ?? \"\";\n if (home && p.startsWith(home)) return \"~\" + p.slice(home.length);\n return p;\n}\n\nexport function StatusBar({\n mode,\n model,\n thinking,\n agentState,\n totalTokens,\n connected,\n sessionId,\n workspacePath,\n}: StatusBarProps) {\n const { columns } = useTerminal();\n\n // --- Row 1: left hints · right info ---\n\n // Left\n let leftText: string;\n if (agentState === \"awaiting-input\") {\n leftText = \"y/n to respond\";\n } else if (agentState === \"busy\") {\n leftText = \"esc to interrupt\";\n } else {\n leftText = \"? for shortcuts\";\n }\n\n // Right: model · mode · thinking · tokens\n const thinkingLabel = getThinkingLabel(thinking);\n const modelStr = shortModel(model);\n const tokenStr = totalTokens > 0 ? ` · ${formatTokens(totalTokens)} tokens` : \"\";\n const thinkingStr = thinkingLabel ? ` · ${thinkingLabel}` : \"\";\n const rightPlain = `${modelStr} · ${mode}${thinkingStr}${tokenStr}`;\n\n const gap1 = Math.max(1, columns - leftText.length - rightPlain.length - 2);\n\n // --- Row 2: left empty · right context info ---\n const contextParts: string[] = [];\n if (!connected) contextParts.push(\"disconnected\");\n if (sessionId) contextParts.push(`session: ${sessionId.slice(0, 8)}`);\n const row2Right = contextParts.length > 0\n ? contextParts.join(\" · \")\n : shortPath(workspacePath);\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n {/* Row 1 */}\n <Box>\n <Text color={t.hint}>{leftText}</Text>\n <Text>{\" \".repeat(gap1)}</Text>\n {!connected ? (\n <Text color={t.disconnected}>{rightPlain}</Text>\n ) : (\n <Text>\n <Text color={t.hint}>{modelStr} · </Text>\n <Text color={t.mode[mode]}>{mode}</Text>\n {thinkingStr && <Text color={t.hint}>{thinkingStr}</Text>}\n {tokenStr && <Text color={t.hint}>{tokenStr}</Text>}\n </Text>\n )}\n </Box>\n {/* Row 2 */}\n <Box justifyContent=\"flex-end\">\n <Text color={t.hint}>{row2Right}</Text>\n </Box>\n </Box>\n );\n}\n","/**\n * Token formatting utilities\n */\n\nexport function formatTokens(count: number): string {\n if (count === 0) return \"0\";\n return count.toLocaleString(\"en-US\");\n}\n\nexport function formatDuration(startMs: number): string {\n const elapsed = (Date.now() - startMs) / 1000;\n if (elapsed < 60) return `${elapsed.toFixed(1)}s`;\n const mins = Math.floor(elapsed / 60);\n const secs = Math.floor(elapsed % 60);\n return `${mins}m${secs}s`;\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport type { PendingUserInput } from \"@jarvis/types\";\nimport { t } from \"../theme\";\n\ninterface PermissionDialogProps {\n input: PendingUserInput;\n onRespond: (action: string, data?: Record<string, unknown>, feedback?: string) => void;\n}\n\nexport function PermissionDialog({ input, onRespond }: PermissionDialogProps) {\n useInput((char) => {\n switch (char.toLowerCase()) {\n case \"y\": onRespond(\"allow\"); break;\n case \"n\": onRespond(\"deny\"); break;\n case \"a\": onRespond(\"allow\", { always: true }); break;\n }\n });\n\n const toolName = input.toolName ?? \"unknown\";\n const description = getInputDescription(input);\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"╭─ \"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.dialogTitle} bold>Jarvis wants to use: {toolName}</Text>\n </Box>\n {description && (\n <>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n {description.split(\"\\n\").map((line, i) => (\n <Box key={i}>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text>{line}</Text>\n </Box>\n ))}\n </>\n )}\n {input.ui?.data != null && (\n <>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text dimColor>{truncate(JSON.stringify(input.ui.data, null, 2), 500)}</Text>\n </Box>\n </>\n )}\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.toolSuccess} bold>Allow (y)</Text>\n <Text>{\" \"}</Text>\n <Text color={t.dialogDanger} bold>Reject (n)</Text>\n <Text>{\" \"}</Text>\n <Text color={t.dialogAction} bold>Always allow (a)</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"╰─\"}</Text>\n </Box>\n );\n}\n\nfunction getInputDescription(input: PendingUserInput): string | null {\n const toolName = input.toolName ?? \"\";\n const inp = input.input ?? {};\n\n switch (toolName) {\n case \"Bash\":\n return `Command: ${inp.command ?? \"\"}${inp.description ? `\\nDescription: ${inp.description}` : \"\"}`;\n case \"Write\": return `File: ${inp.file_path ?? \"\"}`;\n case \"Edit\": return `File: ${inp.file_path ?? \"\"}`;\n case \"NotebookEdit\": return `Notebook: ${inp.notebook_path ?? \"\"}`;\n default:\n if (input.reason) return input.reason;\n return null;\n }\n}\n\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 3) + \"...\";\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport type { PendingUserInput } from \"@jarvis/types\";\nimport { t } from \"../theme\";\n\ninterface PlanReviewProps {\n input: PendingUserInput;\n onRespond: (action: string, data?: Record<string, unknown>, feedback?: string) => void;\n}\n\nexport function PlanReview({ input, onRespond }: PlanReviewProps) {\n useInput((char) => {\n switch (char.toLowerCase()) {\n case \"y\": onRespond(\"allow\"); break;\n case \"n\": onRespond(\"deny\"); break;\n }\n });\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"╭─ Plan ─\"}</Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n {input.items?.map((item, i) => (\n <Box key={item.id}>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text>{i + 1}. {item.title}</Text>\n </Box>\n ))}\n {input.reason && !input.items?.length && (\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text>{input.reason}</Text>\n </Box>\n )}\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.toolSuccess} bold>Approve plan (y)</Text>\n <Text>{\" \"}</Text>\n <Text color={t.dialogDanger} bold>Reject (n)</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"╰─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport type { PendingUserInput } from \"@jarvis/types\";\nimport { t } from \"../theme\";\n\ninterface MaxIterationsProps {\n input: PendingUserInput;\n onRespond: (action: string, data?: Record<string, unknown>) => void;\n}\n\nexport function MaxIterations({ input, onRespond }: MaxIterationsProps) {\n useInput((char) => {\n switch (char.toLowerCase()) {\n case \"y\": onRespond(\"allow\"); break;\n case \"n\": onRespond(\"deny\"); break;\n }\n });\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"╭─ \"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.dialogTitle} bold>\n Reached {input.iteration ?? \"?\"}/{input.maxIterations ?? \"?\"} turns\n </Text>\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text>Continue for {input.initialMaxIterations ?? input.maxIterations ?? 25} more turns?</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.toolSuccess} bold>Continue (y)</Text>\n <Text>{\" \"}</Text>\n <Text color={t.dialogDanger} bold>Stop (n)</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"╰─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport { t } from \"../theme\";\n\ninterface HelpMenuProps {\n onClose: () => void;\n}\n\nconst COMMANDS: [string, string][] = [\n [\"/config\", \"Open settings (model, thinking, mode)\"],\n [\"/model\", \"Quick model switch\"],\n [\"/mode\", \"Quick permission mode switch\"],\n [\"/thinking\", \"Toggle thinking config\"],\n [\"/status\", \"Show connection & session info\"],\n [\"/clear\", \"Clear conversation history and free up context\"],\n [\"/compact\", \"Compact old messages\"],\n [\"/help\", \"Show this help\"],\n [\"/exit\", \"Exit Jarvis\"],\n];\n\nexport function HelpMenu({ onClose }: HelpMenuProps) {\n useInput((_input, key) => {\n if (key.escape || _input === \"q\" || key.return) onClose();\n });\n\n return (\n <Box flexDirection=\"column\" marginTop={1} paddingLeft={1}>\n {COMMANDS.map(([cmd, desc]) => (\n <Box key={cmd}>\n <Text color={t.command}>{cmd!.padEnd(16)}</Text>\n <Text>{desc}</Text>\n </Box>\n ))}\n <Box marginTop={1}>\n <Text color={t.hint}>Shift+Tab to cycle modes · Ctrl+C to interrupt · Esc to close</Text>\n </Box>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport type { TuiSettings } from \"../settings\";\nimport { formatTokens } from \"../utils/format-tokens\";\nimport { t } from \"../theme\";\n\ninterface StatusDisplayProps {\n settings: TuiSettings;\n connected: boolean;\n port: number;\n sessionId: string | null;\n totalTokens: number;\n workspacePath: string;\n onClose: () => void;\n}\n\nexport function StatusDisplay({\n settings,\n connected,\n port,\n sessionId,\n totalTokens,\n workspacePath,\n onClose,\n}: StatusDisplayProps) {\n useInput((_input, key) => {\n if (key.escape || _input === \"q\") onClose();\n });\n\n const thinkingLabel =\n settings.thinking.type === \"enabled\"\n ? `enabled (${settings.thinking.budgetTokens ?? 32768})`\n : settings.thinking.type;\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>\n {\"┌─ \"}\n <Text color={t.dialogTitle}>Jarvis Status</Text>\n {\" ─\"}\n </Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n {[\n [\"Agent\", `ws://127.0.0.1:${port} (${connected ? \"connected\" : \"disconnected\"})`],\n [\"Session\", sessionId ?? \"none\"],\n [\"Model\", settings.model],\n [\"Mode\", settings.permissionMode],\n [\"Thinking\", thinkingLabel],\n [\"Max turns\", String(settings.maxTurns)],\n [\"Workspace\", workspacePath],\n [\"Tokens used\", `${formatTokens(totalTokens)} (session)`],\n ].map(([label, value]) => (\n <Box key={label}>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold>{label!.padEnd(14)}</Text>\n <Text dimColor>{value}</Text>\n </Box>\n ))}\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>Press Esc or q to close</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"└─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport SelectInput from \"ink-select-input\";\n\nimport { t } from \"../theme\";\n\ninterface ModelPickerProps {\n currentModel: string;\n onSelect: (model: string) => void;\n onClose: () => void;\n}\n\nconst MODELS = [\n { label: \"claude-sonnet-4-20250514\", value: \"claude-sonnet-4-20250514\" },\n { label: \"claude-opus-4-20250514\", value: \"claude-opus-4-20250514\" },\n { label: \"claude-haiku-4-5-20251001\", value: \"claude-haiku-4-5-20251001\" },\n];\n\nexport function ModelPicker({ currentModel, onSelect, onClose }: ModelPickerProps) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"┌─ \"}<Text color={t.dialogTitle}>Model</Text>{\" ─\"}</Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text dimColor>Current: {currentModel}</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box paddingLeft={2}>\n <SelectInput\n items={MODELS}\n initialIndex={MODELS.findIndex((m) => m.value === currentModel)}\n onSelect={(item) => { onSelect(item.value); onClose(); }}\n />\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>↑/↓ select · Enter confirm · Esc cancel</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"└─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport SelectInput from \"ink-select-input\";\n\nimport type { PermissionMode } from \"../settings\";\nimport { t } from \"../theme\";\n\ninterface ModePickerProps {\n currentMode: PermissionMode;\n onSelect: (mode: PermissionMode) => void;\n onClose: () => void;\n}\n\nconst MODES = [\n { label: \"Supervised — Ask before dangerous tools\", value: \"supervised\" as const },\n { label: \"Auto — Auto-approve safe tools\", value: \"auto\" as const },\n { label: \"Plan — Plan first, then execute\", value: \"plan\" as const },\n { label: \"Yolo — Bypass all permissions\", value: \"yolo\" as const },\n];\n\nexport function ModePicker({ currentMode, onSelect, onClose }: ModePickerProps) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"┌─ \"}<Text color={t.dialogTitle}>Permission Mode</Text>{\" ─\"}</Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box paddingLeft={2}>\n <SelectInput\n items={MODES}\n initialIndex={MODES.findIndex((m) => m.value === currentMode)}\n onSelect={(item) => { onSelect(item.value); onClose(); }}\n />\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>↑/↓ select · Enter confirm · Esc cancel</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"└─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport SelectInput from \"ink-select-input\";\n\nimport type { ThinkingConfig } from \"@jarvis/types\";\nimport { t } from \"../theme\";\n\ninterface ThinkingPickerProps {\n current: ThinkingConfig;\n onSelect: (config: ThinkingConfig) => void;\n onClose: () => void;\n}\n\nconst OPTIONS = [\n { label: \"Adaptive — Model decides when to think\", value: \"adaptive\" },\n { label: \"Enabled — Always think (budget: 32768)\", value: \"enabled\" },\n { label: \"Disabled — No extended thinking\", value: \"disabled\" },\n];\n\nexport function ThinkingPicker({ current, onSelect, onClose }: ThinkingPickerProps) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"┌─ \"}<Text color={t.dialogTitle}>Thinking</Text>{\" ─\"}</Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box paddingLeft={2}>\n <SelectInput\n items={OPTIONS}\n initialIndex={OPTIONS.findIndex((o) => o.value === current.type)}\n onSelect={(item) => {\n const config: ThinkingConfig = { type: item.value as ThinkingConfig[\"type\"] };\n if (item.value === \"enabled\") config.budgetTokens = 32768;\n onSelect(config);\n onClose();\n }}\n />\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>↑/↓ select · Enter confirm · Esc cancel</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"└─\"}</Text>\n </Box>\n );\n}\n","import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport SelectInput from \"ink-select-input\";\n\nimport type { ThinkingConfig } from \"@jarvis/types\";\nimport type { PermissionMode, TuiSettings } from \"../settings\";\nimport { t } from \"../theme\";\n\ninterface SettingsDialogProps {\n settings: TuiSettings;\n onUpdateModel: (model: string) => void;\n onUpdateThinking: (thinking: ThinkingConfig) => void;\n onUpdateMode: (mode: PermissionMode) => void;\n onUpdateMaxTurns: (turns: number) => void;\n onClose: () => void;\n}\n\ntype Section = \"model\" | \"thinking\" | \"mode\" | \"maxTurns\";\nconst SECTIONS: Section[] = [\"model\", \"thinking\", \"mode\", \"maxTurns\"];\n\nconst MODELS = [\n { label: \"claude-sonnet-4-20250514\", value: \"claude-sonnet-4-20250514\" },\n { label: \"claude-opus-4-20250514\", value: \"claude-opus-4-20250514\" },\n { label: \"claude-haiku-4-5-20251001\", value: \"claude-haiku-4-5-20251001\" },\n];\n\nconst THINKING_OPTIONS = [\n { label: \"Adaptive — Model decides\", value: \"adaptive\" },\n { label: \"Enabled — Always (32k budget)\", value: \"enabled\" },\n { label: \"Disabled — Never\", value: \"disabled\" },\n];\n\nconst MODE_OPTIONS = [\n { label: \"Supervised\", value: \"supervised\" },\n { label: \"Auto\", value: \"auto\" },\n { label: \"Plan\", value: \"plan\" },\n { label: \"Yolo\", value: \"yolo\" },\n];\n\nconst MAX_TURNS_OPTIONS = [\n { label: \"10\", value: \"10\" },\n { label: \"25 (default)\", value: \"25\" },\n { label: \"50\", value: \"50\" },\n { label: \"100\", value: \"100\" },\n { label: \"200\", value: \"200\" },\n];\n\nexport function SettingsDialog({\n settings,\n onUpdateModel,\n onUpdateThinking,\n onUpdateMode,\n onUpdateMaxTurns,\n onClose,\n}: SettingsDialogProps) {\n const [activeSection, setActiveSection] = useState<Section>(\"model\");\n\n useInput((_input, key) => {\n if (key.escape) onClose();\n if (key.tab) {\n const idx = SECTIONS.indexOf(activeSection);\n setActiveSection(SECTIONS[(idx + 1) % SECTIONS.length]!);\n }\n });\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>\n {\"╭─ \"}\n <Text color={t.dialogTitle}>Settings</Text>\n {\" ─\"}\n </Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n\n {/* Model */}\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold color={activeSection === \"model\" ? t.dialogTitle : undefined}>\n Model\n </Text>\n </Box>\n {activeSection === \"model\" && (\n <Box paddingLeft={4}>\n <SelectInput\n items={MODELS}\n initialIndex={MODELS.findIndex((m) => m.value === settings.model)}\n onSelect={(item) => onUpdateModel(item.value)}\n />\n </Box>\n )}\n\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n\n {/* Thinking */}\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold color={activeSection === \"thinking\" ? t.dialogTitle : undefined}>\n Thinking\n </Text>\n </Box>\n {activeSection === \"thinking\" && (\n <Box paddingLeft={4}>\n <SelectInput\n items={THINKING_OPTIONS}\n initialIndex={THINKING_OPTIONS.findIndex((o) => o.value === settings.thinking.type)}\n onSelect={(item) => {\n const config: ThinkingConfig = { type: item.value as ThinkingConfig[\"type\"] };\n if (item.value === \"enabled\") config.budgetTokens = 32768;\n onUpdateThinking(config);\n }}\n />\n </Box>\n )}\n\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n\n {/* Permission Mode */}\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold color={activeSection === \"mode\" ? t.dialogTitle : undefined}>\n Permission Mode\n </Text>\n </Box>\n {activeSection === \"mode\" && (\n <Box paddingLeft={4}>\n <SelectInput\n items={MODE_OPTIONS}\n initialIndex={MODE_OPTIONS.findIndex((m) => m.value === settings.permissionMode)}\n onSelect={(item) => onUpdateMode(item.value as PermissionMode)}\n />\n </Box>\n )}\n\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n\n {/* Max Turns */}\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold color={activeSection === \"maxTurns\" ? t.dialogTitle : undefined}>\n Max Turns\n </Text>\n </Box>\n {activeSection === \"maxTurns\" && (\n <Box paddingLeft={4}>\n <SelectInput\n items={MAX_TURNS_OPTIONS}\n initialIndex={MAX_TURNS_OPTIONS.findIndex((o) => o.value === String(settings.maxTurns))}\n onSelect={(item) => onUpdateMaxTurns(parseInt(item.value, 10))}\n />\n </Box>\n )}\n\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>Tab to switch section · Esc to close</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"╰─\"}</Text>\n </Box>\n );\n}\n","import React, { useEffect, useState } from \"react\";\nimport { Text } from \"ink\";\n\nimport { t } from \"../theme\";\n\ninterface NotificationProps {\n message: string | null;\n duration?: number;\n}\n\nexport function Notification({ message, duration = 2000 }: NotificationProps) {\n const [visible, setVisible] = useState(false);\n const [text, setText] = useState(\"\");\n\n useEffect(() => {\n if (message) {\n setText(message);\n setVisible(true);\n const timer = setTimeout(() => setVisible(false), duration);\n return () => clearTimeout(timer);\n }\n }, [message, duration]);\n\n if (!visible || !text) return null;\n return <Text color={t.notification}>{text}</Text>;\n}\n","/**\n * Markdown Text Renderer\n *\n * Simple terminal markdown: bold, headers, lists, code blocks, inline code.\n * Matches Claude Code's clean output style.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\ninterface MarkdownTextProps {\n content: string;\n}\n\nexport function MarkdownText({ content }: MarkdownTextProps) {\n if (!content) return null;\n\n const lines = content.split(\"\\n\");\n const elements: React.ReactNode[] = [];\n let inCodeBlock = false;\n let codeLines: string[] = [];\n let codeLanguage = \"\";\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n\n // Code block start/end\n if (line.startsWith(\"```\")) {\n if (inCodeBlock) {\n // End code block\n elements.push(\n <Box key={`code-${i}`} flexDirection=\"column\" marginTop={0} marginBottom={0} paddingLeft={2}>\n {codeLanguage && (\n <Text dimColor>{codeLanguage}</Text>\n )}\n {codeLines.map((cl, j) => (\n <Text key={j} color=\"gray\">{cl}</Text>\n ))}\n </Box>,\n );\n codeLines = [];\n codeLanguage = \"\";\n inCodeBlock = false;\n } else {\n inCodeBlock = true;\n codeLanguage = line.slice(3).trim();\n }\n continue;\n }\n\n if (inCodeBlock) {\n codeLines.push(line);\n continue;\n }\n\n // Empty line\n if (line.trim() === \"\") {\n elements.push(<Text key={`empty-${i}`}>{\"\"}</Text>);\n continue;\n }\n\n // Headers\n const h1 = line.match(/^# (.+)/);\n if (h1) {\n elements.push(\n <Text key={`h1-${i}`} bold color=\"white\">\n {renderInline(h1[1]!)}\n </Text>,\n );\n continue;\n }\n\n const h2 = line.match(/^## (.+)/);\n if (h2) {\n elements.push(\n <Text key={`h2-${i}`} bold>\n {renderInline(h2[1]!)}\n </Text>,\n );\n continue;\n }\n\n const h3 = line.match(/^### (.+)/);\n if (h3) {\n elements.push(\n <Text key={`h3-${i}`} bold dimColor>\n {renderInline(h3[1]!)}\n </Text>,\n );\n continue;\n }\n\n // Unordered list items\n const ul = line.match(/^(\\s*)[-*] (.+)/);\n if (ul) {\n const indent = Math.floor((ul[1]?.length ?? 0) / 2);\n elements.push(\n <Box key={`ul-${i}`} paddingLeft={indent * 2}>\n <Text dimColor>{\"– \"}</Text>\n <Text>{renderInline(ul[2]!)}</Text>\n </Box>,\n );\n continue;\n }\n\n // Ordered list items\n const ol = line.match(/^(\\s*)\\d+\\. (.+)/);\n if (ol) {\n const indent = Math.floor((ol[1]?.length ?? 0) / 2);\n const num = line.match(/^(\\s*)(\\d+)\\./);\n elements.push(\n <Box key={`ol-${i}`} paddingLeft={indent * 2}>\n <Text dimColor>{`${num?.[2]}. `}</Text>\n <Text>{renderInline(ol[2]!)}</Text>\n </Box>,\n );\n continue;\n }\n\n // Horizontal rule\n if (/^---+$/.test(line.trim()) || /^\\*\\*\\*+$/.test(line.trim())) {\n elements.push(\n <Text key={`hr-${i}`} dimColor>{\"─\".repeat(40)}</Text>,\n );\n continue;\n }\n\n // Regular paragraph\n elements.push(\n <Text key={`p-${i}`}>{renderInline(line)}</Text>,\n );\n }\n\n return <Box flexDirection=\"column\">{elements}</Box>;\n}\n\n/**\n * Render inline markdown: **bold**, `code`, *italic*\n * Returns a string with ANSI escape sequences.\n *\n * Note: Ink <Text> doesn't support mixed inline styles easily,\n * so we return plain text with markdown stripped for now.\n * Bold is rendered via chalk-style markup.\n */\nfunction renderInline(text: string): string {\n return text\n // Remove bold markers (Ink doesn't support inline bold mixing easily)\n .replace(/\\*\\*(.+?)\\*\\*/g, \"$1\")\n // Remove italic markers\n .replace(/\\*(.+?)\\*/g, \"$1\")\n // Remove inline code markers\n .replace(/`(.+?)`/g, \"$1\");\n}\n","/**\n * Cross-platform service manager for always-on agent.\n *\n * macOS: LaunchAgent plist (~/.jarvis/LaunchAgents/com.appchy.jarvis.plist)\n * Windows: Task Scheduler XML (schtasks /Create)\n */\n\nimport { execSync, spawn } from \"child_process\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface ServiceOptions {\n port: number;\n workspacePath: string;\n nodePath: string;\n entryPath: string;\n upstream: boolean;\n /** Extra environment variables to propagate to the service child process */\n env?: Record<string, string>;\n}\n\nexport interface ServiceStatus {\n installed: boolean;\n running: boolean;\n pid?: number;\n os?: \"macOS\" | \"windows\" | \"linux\";\n}\n\nexport interface ServiceManager {\n install(opts: ServiceOptions): void;\n uninstall(): void;\n isInstalled(): boolean;\n start(): void;\n stop(): void;\n status(): ServiceStatus;\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\nexport function createServiceManager(): ServiceManager {\n if (process.platform === \"darwin\") return new MacOSService();\n if (process.platform === \"win32\") return new WindowsService();\n if (process.platform === \"linux\") return new LinuxService();\n return new FallbackService();\n}\n\n// =============================================================================\n// macOS — LaunchAgent\n// =============================================================================\n\nconst PLIST_LABEL = \"com.appchy.jarvis\";\nconst PLIST_DIR = path.join(os.homedir(), \"Library\", \"LaunchAgents\");\nconst PLIST_PATH = path.join(PLIST_DIR, `${PLIST_LABEL}.plist`);\n\nfunction escapeXml(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nclass MacOSService implements ServiceManager {\n install(opts: ServiceOptions): void {\n const args = [\n opts.nodePath,\n opts.entryPath,\n \"start\",\n \"--foreground\",\n \"--port\",\n String(opts.port),\n \"--workspace\",\n opts.workspacePath,\n ];\n if (!opts.upstream) {\n args.push(\"--no-upstream\");\n }\n\n const logFile = path.join(os.homedir(), \".jarvis\", \"agent.log\");\n const envPath = process.env.PATH ?? \"/usr/local/bin:/usr/bin:/bin\";\n\n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${PLIST_LABEL}</string>\n\n <key>ProgramArguments</key>\n <array>\n${args.map((a) => ` <string>${escapeXml(a)}</string>`).join(\"\\n\")}\n </array>\n\n <key>WorkingDirectory</key>\n <string>${escapeXml(opts.workspacePath)}</string>\n\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>${escapeXml(envPath)}</string>\n <key>HOME</key>\n <string>${escapeXml(os.homedir())}</string>\n <key>NODE_NO_WARNINGS</key>\n <string>1</string>\n${Object.entries(opts.env ?? {}).map(([k, v]) => ` <key>${escapeXml(k)}</key>\\n <string>${escapeXml(v)}</string>`).join(\"\\n\")}\n </dict>\n\n <key>RunAtLoad</key>\n <true/>\n\n <key>KeepAlive</key>\n <true/>\n\n <key>ProcessType</key>\n <string>Interactive</string>\n\n <key>ThrottleInterval</key>\n <integer>5</integer>\n\n <key>StandardOutPath</key>\n <string>${escapeXml(logFile)}</string>\n\n <key>StandardErrorPath</key>\n <string>${escapeXml(logFile)}</string>\n</dict>\n</plist>\n`;\n\n // Ensure directories exist\n fs.mkdirSync(PLIST_DIR, { recursive: true });\n fs.mkdirSync(path.dirname(logFile), { recursive: true });\n\n // Unload existing service if present (ignore errors)\n if (this.isInstalled()) {\n try {\n execSync(`launchctl unload -w \"${PLIST_PATH}\"`, { stdio: \"ignore\" });\n } catch {}\n }\n\n fs.writeFileSync(PLIST_PATH, plist);\n execSync(`launchctl load -w \"${PLIST_PATH}\"`);\n }\n\n uninstall(): void {\n try {\n execSync(`launchctl unload -w \"${PLIST_PATH}\"`, { stdio: \"ignore\" });\n } catch {}\n try {\n fs.unlinkSync(PLIST_PATH);\n } catch {}\n }\n\n isInstalled(): boolean {\n return fs.existsSync(PLIST_PATH);\n }\n\n start(): void {\n try {\n // load -w both loads and starts the agent\n execSync(`launchctl load -w \"${PLIST_PATH}\"`);\n } catch {\n // Already loaded — just kick it\n execSync(`launchctl start ${PLIST_LABEL}`);\n }\n }\n\n stop(): void {\n try {\n // unload -w stops the process AND prevents KeepAlive from restarting\n execSync(`launchctl unload -w \"${PLIST_PATH}\"`, { stdio: \"ignore\" });\n } catch {}\n }\n\n status(): ServiceStatus {\n const installed = this.isInstalled();\n if (!installed) return { installed: false, running: false };\n\n try {\n const output = execSync(`launchctl list ${PLIST_LABEL}`, {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n // Parse PID from launchctl list output\n const pidMatch = output.match(/\"PID\"\\s*=\\s*(\\d+)/);\n const pid = pidMatch ? parseInt(pidMatch[1], 10) : undefined;\n return { installed: true, running: pid !== undefined, pid, os: \"macOS\" };\n } catch {\n return { installed: true, running: false, os: \"macOS\" };\n }\n }\n}\n\n// =============================================================================\n// Windows — Task Scheduler\n// =============================================================================\n\nconst TASK_NAME = \"JarvisAgent\";\n\nclass WindowsService implements ServiceManager {\n install(opts: ServiceOptions): void {\n const args = [\n opts.entryPath,\n \"start\",\n \"--foreground\",\n \"--port\",\n String(opts.port),\n \"--workspace\",\n `\"${opts.workspacePath}\"`,\n ];\n if (!opts.upstream) {\n args.push(\"--no-upstream\");\n }\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n<Task version=\"1.2\" xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">\n <RegistrationInfo>\n <Description>Jarvis AI Agent — always-on background service</Description>\n </RegistrationInfo>\n <Triggers>\n <LogonTrigger>\n <Enabled>true</Enabled>\n </LogonTrigger>\n </Triggers>\n <Principals>\n <Principal id=\"Author\">\n <LogonType>InteractiveToken</LogonType>\n <RunLevel>LeastPrivilege</RunLevel>\n </Principal>\n </Principals>\n <Settings>\n <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>\n <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>\n <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>\n <AllowHardTerminate>true</AllowHardTerminate>\n <StartWhenAvailable>true</StartWhenAvailable>\n <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>\n <AllowStartOnDemand>true</AllowStartOnDemand>\n <Enabled>true</Enabled>\n <Hidden>false</Hidden>\n <RunOnlyIfIdle>false</RunOnlyIfIdle>\n <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>\n <Priority>7</Priority>\n <RestartOnFailure>\n <Interval>PT1M</Interval>\n <Count>999</Count>\n </RestartOnFailure>\n </Settings>\n <Actions Context=\"Author\">\n <Exec>\n <Command>${escapeXml(opts.nodePath)}</Command>\n <Arguments>${escapeXml(args.join(\" \"))}</Arguments>\n <WorkingDirectory>${escapeXml(opts.workspacePath)}</WorkingDirectory>\n </Exec>\n </Actions>\n</Task>\n`;\n\n // Write XML to temp file\n const tmpDir = os.tmpdir();\n const tmpFile = path.join(tmpDir, `jarvis-task-${Date.now()}.xml`);\n fs.writeFileSync(tmpFile, xml, { encoding: \"utf-16le\" });\n\n try {\n execSync(`schtasks /Create /TN \"${TASK_NAME}\" /XML \"${tmpFile}\" /F`, {\n stdio: \"ignore\",\n });\n } finally {\n try {\n fs.unlinkSync(tmpFile);\n } catch {}\n }\n }\n\n uninstall(): void {\n try {\n execSync(`schtasks /Delete /TN \"${TASK_NAME}\" /F`, { stdio: \"ignore\" });\n } catch {}\n }\n\n isInstalled(): boolean {\n try {\n execSync(`schtasks /Query /TN \"${TASK_NAME}\"`, { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n }\n\n start(): void {\n execSync(`schtasks /Run /TN \"${TASK_NAME}\"`, { stdio: \"ignore\" });\n }\n\n stop(): void {\n execSync(`schtasks /End /TN \"${TASK_NAME}\"`, { stdio: \"ignore\" });\n }\n\n status(): ServiceStatus {\n if (!this.isInstalled()) return { installed: false, running: false };\n\n try {\n const output = execSync(`schtasks /Query /TN \"${TASK_NAME}\" /FO CSV /NH`, {\n encoding: \"utf-8\",\n });\n const running = output.includes(\"Running\");\n return { installed: true, running, os: \"windows\" };\n } catch {\n return { installed: true, running: false, os: \"windows\" };\n }\n }\n}\n\n// =============================================================================\n// Linux — systemd user service\n// =============================================================================\n\nconst SYSTEMD_DIR = path.join(os.homedir(), \".config\", \"systemd\", \"user\");\nconst UNIT_NAME = \"jarvis.service\";\nconst UNIT_PATH = path.join(SYSTEMD_DIR, UNIT_NAME);\n\nclass LinuxService implements ServiceManager {\n install(opts: ServiceOptions): void {\n const args = [\n opts.entryPath,\n \"start\",\n \"--foreground\",\n \"--port\",\n String(opts.port),\n \"--workspace\",\n opts.workspacePath,\n ];\n if (!opts.upstream) {\n args.push(\"--no-upstream\");\n }\n\n const logFile = path.join(os.homedir(), \".jarvis\", \"agent.log\");\n const envPath = process.env.PATH ?? \"/usr/local/bin:/usr/bin:/bin\";\n\n const unit = `[Unit]\nDescription=Jarvis AI Agent\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=${opts.nodePath} ${args.join(\" \")}\nWorkingDirectory=${opts.workspacePath}\nEnvironment=PATH=${envPath}\nEnvironment=HOME=${os.homedir()}\nEnvironment=NODE_NO_WARNINGS=1\nRestart=always\nRestartSec=5\nStandardOutput=append:${logFile}\nStandardError=append:${logFile}\n\n[Install]\nWantedBy=default.target\n`;\n\n // Ensure directories exist\n fs.mkdirSync(SYSTEMD_DIR, { recursive: true });\n fs.mkdirSync(path.dirname(logFile), { recursive: true });\n\n // Stop existing service if running\n if (this.isInstalled()) {\n try {\n execSync(\"systemctl --user stop jarvis.service\", { stdio: \"ignore\" });\n } catch {}\n }\n\n fs.writeFileSync(UNIT_PATH, unit);\n execSync(\"systemctl --user daemon-reload\", { stdio: \"ignore\" });\n execSync(\"systemctl --user enable jarvis.service\", { stdio: \"ignore\" });\n execSync(\"systemctl --user start jarvis.service\", { stdio: \"ignore\" });\n\n // Enable lingering so the service runs even when user is not logged in\n // (equivalent to ProcessType: Interactive on macOS)\n try {\n execSync(`loginctl enable-linger ${os.userInfo().username}`, { stdio: \"ignore\" });\n } catch {\n // May require root — not critical, service still works when logged in\n }\n }\n\n uninstall(): void {\n try {\n execSync(\"systemctl --user stop jarvis.service\", { stdio: \"ignore\" });\n } catch {}\n try {\n execSync(\"systemctl --user disable jarvis.service\", { stdio: \"ignore\" });\n } catch {}\n try {\n fs.unlinkSync(UNIT_PATH);\n } catch {}\n try {\n execSync(\"systemctl --user daemon-reload\", { stdio: \"ignore\" });\n } catch {}\n }\n\n isInstalled(): boolean {\n return fs.existsSync(UNIT_PATH);\n }\n\n start(): void {\n execSync(\"systemctl --user start jarvis.service\");\n }\n\n stop(): void {\n execSync(\"systemctl --user stop jarvis.service\", { stdio: \"ignore\" });\n }\n\n status(): ServiceStatus {\n if (!this.isInstalled()) return { installed: false, running: false };\n\n try {\n const output = execSync(\"systemctl --user show jarvis.service --property=ActiveState,MainPID\", {\n encoding: \"utf-8\",\n });\n const active = output.includes(\"ActiveState=active\");\n const pidMatch = output.match(/MainPID=(\\d+)/);\n const pid = pidMatch ? parseInt(pidMatch[1], 10) : undefined;\n return {\n installed: true,\n running: active && pid !== undefined && pid > 0,\n pid: pid && pid > 0 ? pid : undefined,\n os: \"linux\",\n };\n } catch {\n return { installed: true, running: false, os: \"linux\" };\n }\n }\n}\n\n// =============================================================================\n// Unsupported platform\n// =============================================================================\n\n/**\n * Fallback for unsupported platforms.\n *\n * Uses a detached Node.js child process — the agent runs in the background\n * but won't auto-start on login, survive reboots, or recover from crashes.\n */\nclass FallbackService implements ServiceManager {\n private pidFile = path.join(os.homedir(), \".jarvis\", \"agent.pid\");\n private logFile = path.join(os.homedir(), \".jarvis\", \"agent.log\");\n private markerFile = path.join(os.homedir(), \".jarvis\", \"service-installed\");\n\n install(opts: ServiceOptions): void {\n const jarvisDir = path.join(os.homedir(), \".jarvis\");\n fs.mkdirSync(jarvisDir, { recursive: true });\n\n // Stop existing process if running\n this.stop();\n\n const args = [\n opts.entryPath,\n \"start\",\n \"--foreground\",\n \"--port\",\n String(opts.port),\n \"--workspace\",\n opts.workspacePath,\n ];\n if (!opts.upstream) {\n args.push(\"--no-upstream\");\n }\n\n const logFd = fs.openSync(this.logFile, \"a\");\n const child = spawn(opts.nodePath, args, {\n detached: true,\n stdio: [\"ignore\", logFd, logFd],\n cwd: opts.workspacePath,\n env: { ...process.env, NODE_NO_WARNINGS: \"1\" },\n });\n child.unref();\n fs.closeSync(logFd);\n\n // Save PID and marker\n fs.writeFileSync(this.pidFile, String(child.pid));\n fs.writeFileSync(this.markerFile, JSON.stringify({\n nodePath: opts.nodePath,\n entryPath: opts.entryPath,\n port: opts.port,\n workspacePath: opts.workspacePath,\n upstream: opts.upstream,\n }));\n\n console.log(\n `\\x1b[33mNote:\\x1b[0m OS-level service not available on ${process.platform}.`,\n );\n console.log(\" Agent is running as a background process (PID: \" + child.pid + \").\");\n console.log(\" It will NOT auto-start on reboot or recover from crashes.\");\n }\n\n uninstall(): void {\n this.stop();\n try { fs.unlinkSync(this.markerFile); } catch {}\n }\n\n isInstalled(): boolean {\n return fs.existsSync(this.markerFile);\n }\n\n start(): void {\n if (!this.isInstalled()) {\n throw new Error(\"Service not installed. Run 'jarvis install' first.\");\n }\n // Re-install with saved options to spawn a new process\n const saved = JSON.parse(fs.readFileSync(this.markerFile, \"utf-8\"));\n this.install(saved);\n }\n\n stop(): void {\n try {\n const pid = parseInt(fs.readFileSync(this.pidFile, \"utf-8\").trim(), 10);\n if (!isNaN(pid)) {\n process.kill(pid, \"SIGTERM\");\n }\n } catch {}\n try { fs.unlinkSync(this.pidFile); } catch {}\n }\n\n status(): ServiceStatus {\n if (!this.isInstalled()) return { installed: false, running: false };\n\n try {\n const pid = parseInt(fs.readFileSync(this.pidFile, \"utf-8\").trim(), 10);\n if (isNaN(pid)) return { installed: true, running: false };\n process.kill(pid, 0); // Check if alive\n return { installed: true, running: true, pid };\n } catch {\n return { installed: true, running: false };\n }\n }\n}\n","import { isDev } from \"./config\";\n\n// In dev mode (env.json has \"development\"), load .env so APP_URL etc. are available.\n// In prod mode, skip .env entirely — use production defaults.\nif (isDev()) {\n const dotenv = await import(\"dotenv\");\n const fs = await import(\"fs\");\n const path = await import(\"path\");\n\n let dir = process.cwd();\n while (dir !== path.dirname(dir)) {\n const envPath = path.join(dir, \".env\");\n if (fs.existsSync(envPath)) {\n dotenv.config({ path: envPath });\n break;\n }\n dir = path.dirname(dir);\n }\n}\n\nimport { createCli } from \"./cli\";\n\ncreateCli().parse();\n"],"mappings":"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","names":["spawn","execSync","fs","path","os","t","pendingInput","prompt","context","prompt","detectLanguage","fs","os","path","path","fs","crypto","now","crypto","fs","path","path","fs","provider","promisify","path","fs","promisify","path","fs","execCb","fs","path","promisify","exec","promisify","execCb","fs","path","add","WebSocket","WebSocket","agent","React","render","fileURLToPath","path","fs","os","WebSocket","fs","path","os","useState","useCallback","useRef","useEffect","Box","Text","useInput","WebSocket","useState","useCallback","useRef","useState","useCallback","useRef","crypto","useState","useCallback","useState","useCallback","Box","Text","jsx","jsxs","Box","Text","useState","useEffect","useRef","Box","Text","jsx","jsxs","useState","useRef","useEffect","Box","Text","Box","Text","useState","useEffect","jsx","Box","Text","React","useState","useCallback","Box","Text","Box","Text","jsx","jsxs","Box","Text","Box","Text","path","fs","jsx","jsxs","fs","path","jsx","Box","Text","jsxs","jsx","jsxs","useState","React","useCallback","before","Box","Text","Box","Text","jsx","jsxs","shortModel","shortPath","Box","Text","Box","Text","useInput","jsx","jsxs","useInput","Box","Text","Box","Text","useInput","jsx","jsxs","useInput","Box","Text","Box","Text","useInput","jsx","jsxs","useInput","Box","Text","Box","Text","useInput","jsx","jsxs","useInput","Box","Text","Box","Text","useInput","jsx","jsxs","useInput","Box","Text","Box","Text","jsx","jsxs","Box","Text","Box","Text","SelectInput","jsx","jsxs","Box","Text","SelectInput","Box","Text","SelectInput","jsx","jsxs","Box","Text","SelectInput","useState","Box","Text","useInput","SelectInput","jsx","jsxs","MODELS","useState","useInput","Box","Text","SelectInput","useEffect","useState","Text","jsx","useState","useEffect","Text","Box","Text","jsx","jsxs","Fragment","jsx","jsxs","useState","useRef","useEffect","renderMessage","useCallback","useInput","Box","Text","truncate","render","React","path","os","fs","__filename","fileURLToPath","WebSocket","spawn","fs","path","os","path","os","fs","exec","execSync","spawn","state","fs","path"]}
1
+ {"version":3,"sources":["../../../packages/types/src/agents/agent.types.ts","../../../packages/types/src/agents/chat.types.ts","../../../packages/types/src/agents/input.types.ts","../../../packages/types/src/agents/llm.types.ts","../../../packages/types/src/agents/message.types.ts","../../../packages/types/src/agents/mcp.types.ts","../../../packages/types/src/agents/memories.types.ts","../../../packages/types/src/agents/memory.types.ts","../../../packages/types/src/agents/model.types.ts","../../../packages/types/src/agents/prompt.types.ts","../../../packages/types/src/agents/reference.types.ts","../../../packages/types/src/agents/skill.types.ts","../../../packages/types/src/agents/tool.types.ts","../../../packages/types/src/agents/ui.types.ts","../../../packages/types/src/agents/usage.types.ts","../../../packages/types/src/agents/transport.types.ts","../../../packages/types/src/agents/workflow.types.ts","../../../packages/types/src/agents/sessions.types.ts","../../../packages/types/src/agents/provider.types.ts","../../../packages/types/src/agents/ws.types.ts","../../../packages/types/src/agents/index.ts","../../../packages/types/src/core/color.types.ts","../../../packages/types/src/core/context.types.ts","../../../packages/types/src/core/provider.types.ts","../../../packages/types/src/core/schema.types.ts","../../../packages/types/src/core/translation.types.ts","../../../packages/types/src/core/logger.types.ts","../../../packages/types/src/core/index.ts","../../../packages/types/src/data/cache.types.ts","../../../packages/types/src/data/chat.types.ts","../../../packages/types/src/data/db.types.ts","../../../packages/types/src/data/embedding.types.ts","../../../packages/types/src/data/field.types.ts","../../../packages/types/src/data/notification.types.ts","../../../packages/types/src/data/store.types.ts","../../../packages/types/src/data/sync.types.ts","../../../packages/types/src/data/table.types.ts","../../../packages/types/src/data/task.types.ts","../../../packages/types/src/data/usage.types.ts","../../../packages/types/src/data/user.types.ts","../../../packages/types/src/data/vector.types.ts","../../../packages/types/src/data/group.types.ts","../../../packages/types/src/data/automation.types.ts","../../../packages/types/src/data/workspace.types.ts","../../../packages/types/src/data/index.ts","../../../packages/types/src/stream/channel.types.ts","../../../packages/types/src/stream/event.types.ts","../../../packages/types/src/stream/pubsub.types.ts","../../../packages/types/src/stream/rpc.types.ts","../../../packages/types/src/stream/stream.types.ts","../../../packages/types/src/stream/index.ts","../../../packages/types/src/auth/auth.types.ts","../../../packages/types/src/auth/connector.types.ts","../../../packages/types/src/auth/http.types.ts","../../../packages/types/src/auth/secrets.types.ts","../../../packages/types/src/auth/index.ts","../../../packages/types/src/storage/search.types.ts","../../../packages/types/src/storage/storage.types.ts","../../../packages/types/src/storage/index.ts","../../../packages/types/src/media/audio.types.ts","../../../packages/types/src/media/transcription.types.ts","../../../packages/types/src/media/tts.types.ts","../../../packages/types/src/media/index.ts","../../../packages/types/src/users/users.types.ts","../../../packages/types/src/users/index.ts","../../../packages/types/src/index.ts","../../../packages/logger/src/logger.ts","../../../packages/logger/src/index.ts","../../../providers/anthropic/src/anthropic.models.ts","../../../providers/anthropic/src/anthropic.llm.provider.ts","../../../providers/anthropic/src/claude-code.llm.provider.ts","../../../packages/sdk/src/agents/agents.ts","../../../packages/sdk/src/agents/context.ts","../../../packages/sdk/src/agents/messages/messages.ts","../../../packages/sdk/src/agents/messages/index.ts","../../../packages/sdk/src/agents/tools/tools.ts","../../../packages/sdk/src/agents/tools/plan.tool.ts","../../../packages/sdk/src/agents/tools/ask-user.tool.ts","../../../packages/sdk/src/agents/tools/search.tool.ts","../../../packages/sdk/src/agents/tools/think.tool.ts","../../../packages/sdk/src/agents/tools/plan-mode.tool.ts","../../../packages/sdk/src/agents/tools/agent.tools.ts","../../../packages/sdk/src/agents/tools/index.ts","../../../packages/sdk/src/agents/skills/skills.ts","../../../packages/sdk/src/agents/skills/skill.tool.ts","../../../packages/sdk/src/agents/skills/index.ts","../../../packages/errors/src/errors.ts","../../../packages/errors/src/index.ts","../../../packages/sdk/src/agents/prompts/prompts.ts","../../../packages/sdk/src/agents/prompts/mustache.ts","../../../packages/sdk/src/agents/prompts/index.ts","../../../packages/sdk/src/agents/references/reference.ts","../../../packages/sdk/src/agents/references/resolver.ts","../../../packages/sdk/src/agents/references/index.ts","../../../packages/sdk/src/agents/resources/resources.ts","../../../packages/sdk/src/agents/resources/index.ts","../../../packages/sdk/src/agents/index.ts","../../../packages/sdk/src/data/tables.ts","../../../packages/sdk/src/data/caches.ts","../../../packages/sdk/src/data/ui.ts","../../../packages/sdk/src/data/connectors.ts","../../../packages/sdk/src/data/oauth.ts","../../../packages/sdk/src/data/context.ts","../../../packages/sdk/src/data/state.ts","../../../packages/sdk/src/data/index.ts","../../../packages/sdk/src/index.ts","../../../packages/agent/src/tools/edit.tool.ts","../../../packages/agent/src/tools/bash.tool.ts","../../../packages/agent/src/tools/write.tool.ts","../../../packages/agent/src/tools/read.tool.ts","../../../packages/agent/src/tools/glob.tool.ts","../../../packages/agent/src/tools/grep.tool.ts","../../../packages/agent/src/tools/exit-plan-mode.tool.ts","../../../packages/agent/src/tools/enter-plan-mode.tool.ts","../../../packages/agent/src/tools/todo-write.tool.ts","../../../packages/agent/src/tools/web-search.tool.ts","../../../packages/agent/src/tools/web-fetch.tool.ts","../../../packages/agent/src/tools/agent.tool.ts","../../../packages/agent/src/tools/generic.tool.ts","../../../packages/agent/src/tools/index.ts","../../../packages/agent/src/format.ts","../../../packages/agent/src/worktree.ts","../../../packages/agent/src/index.ts","../../../providers/anthropic/src/attachments.ts","../../../providers/anthropic/src/progress.ts","../../../providers/anthropic/src/claude-code.agent.provider.ts","../../../providers/anthropic/src/index.ts","../src/config.ts","../src/cli.ts","../src/commands/connect.ts","../src/auth.ts","../src/entry.ts","../src/paths.ts","../src/pid.ts","../src/setup.ts","../../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/stringify.js","../../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/rng.js","../../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/native.js","../../../node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm/v4.js","../../../packages/transport/src/rpc.ts","../src/start.ts","../src/agent.ts","../src/pubsub.ts","../src/workspace.ts","../src/rpc/router.ts","../src/rpc/agents.ts","../../../packages/agents/src/routing.ts","../../../packages/agents/src/agents.provider.ts","../../../packages/agents/src/code-agents.provider.ts","../src/chats.ts","../src/rpc/chats.ts","../src/files.ts","../src/rpc/files.ts","../src/git.ts","../src/rpc/git.ts","../src/workdir.ts","../src/rpc/workdir.ts","../src/upstream.ts","../src/service.ts","../src/commands/start.ts","../src/commands/stop.ts","../src/commands/restart.ts","../src/commands/logs.ts","../src/version.ts","../src/commands/status.ts","../src/commands/install.ts","../src/commands/uninstall.ts","../src/commands/logout.ts","../src/tui/chat.ts","../src/tui/settings.ts","../src/tui/app.tsx","../src/tui/hooks/use-agent-client.ts","../src/tui/hooks/use-messages.ts","../src/tui/hooks/use-task.ts","../src/tui/hooks/use-settings.ts","../src/tui/utils/slash-commands.ts","../src/tui/utils/auto-approve.ts","../src/tui/components/welcome-header.tsx","../src/tui/theme.ts","../src/tui/components/user-message.tsx","../src/tui/components/spinner.tsx","../src/tui/components/divider.tsx","../src/tui/hooks/use-terminal.ts","../src/tui/components/prompt-input.tsx","../src/tui/components/suggestions.tsx","../src/tui/components/file-picker.tsx","../src/tui/components/status-bar.tsx","../src/tui/utils/format-tokens.ts","../src/tui/components/permission-dialog.tsx","../src/tui/components/plan-review.tsx","../src/tui/components/max-iterations.tsx","../src/tui/components/help-menu.tsx","../src/tui/components/status-display.tsx","../src/tui/components/model-picker.tsx","../src/tui/components/mode-picker.tsx","../src/tui/components/thinking-picker.tsx","../src/tui/components/settings-dialog.tsx","../src/tui/components/notification.tsx","../src/tui/components/markdown-text.tsx","../src/commands/chat.ts","../src/bin.ts"],"sourcesContent":["/**\n * Agent Types\n * Platform-level agentic loop infrastructure + SDK agent types\n */\n\nimport type {\n ChatMessage,\n Message,\n SystemMessage,\n AssistantMessage,\n UserMessage,\n} from \"./message.types\";\nimport type { PendingInputType, PendingUserInput } from \"./input.types\";\nimport type { Usage } from \"./usage.types\";\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\nimport type { TranslateFn } from \"../core/translation.types\";\nimport type { QueryLLMRequest, QueryLLMResponse, StopReason, ThinkingConfig } from \"./llm.types\";\nimport type { McpCapabilities } from \"./mcp.types\";\nimport type { Memory } from \"./memory.types\";\nimport type { Prompt } from \"./prompt.types\";\nimport type {\n Tool,\n ToolCall,\n ToolCallStatus,\n UserInput,\n BeforeToolHook,\n AfterToolHook,\n} from \"./tool.types\";\nimport type { Ui } from \"./ui.types\";\n\n// ============================================================================\n// Legacy Types (kept for backward compatibility with SDK)\n// ============================================================================\n\n/**\n * Agent message type - used by SDK agent configuration\n * Only allow system and assistant messages for agent initialization\n * User messages are passed at query time, not agent creation time\n */\nexport type AgentMessage = SystemMessage | AssistantMessage | UserMessage;\n\n// ============================================================================\n// Agent Status\n// ============================================================================\n\n/**\n * Chat status - for UI status indicator\n */\nexport type AgentStatus = \"active\" | \"processing\" | \"executing\" | \"waiting\" | \"completed\" | \"error\";\n\n// ============================================================================\n// Exit Reason Types\n// ============================================================================\n\n/**\n * Exit reason - why the agent loop stopped\n */\nexport type AgentExitReason =\n | \"completed\" // LLM returned no tool calls (normal completion)\n | \"cancelled\" // User or system cancelled\n | \"max_iterations\" // Hit maxIterations limit\n | \"empty_response\" // LLM returned empty content and no tools\n | \"error\"; // Unhandled error\n\n// ============================================================================\n// User Input Types (Human-in-the-loop)\n// ============================================================================\n\n// PendingInputType and PendingUserInput are defined in chat.types.ts\n// and re-exported here for convenience\nexport type { PendingInputType, PendingUserInput };\n\n// ============================================================================\n// Update Types\n// ============================================================================\n\n/**\n * Update payload - extensible structure for UI updates\n */\n\nexport interface AgentUpdate {\n /** Status update (optional) */\n status?: AgentStatus;\n /**\n * Pending user inputs array for sequential processing of parallel tool calls.\n * UI should show pendingUserInputs[0] with \"1 of N\" counter where N = length.\n * When user responds, first item is removed and next is shown.\n */\n pendingUserInputs?: PendingUserInput[];\n /** Token and credit usage from this iteration */\n usage?: Usage;\n /** Can be extended with more update types */\n [key: string]: unknown;\n}\n\n// ============================================================================\n// Sub-Agent Delegation\n// ============================================================================\n\nexport interface SubAgentRequest {\n task: string;\n context?: Record<string, unknown>;\n /** Override model ID for the sub-agent */\n model?: string;\n /** Filters for the sub-agent */\n filters?: { tools?: string[] };\n}\n\nexport interface SubAgentResponse {\n message: string;\n success: boolean;\n requestCount: number;\n ui?: Ui;\n}\n\nexport type SubAgentFn = (\n task: string,\n context?: Record<string, unknown>,\n options?: { model?: string; filters?: { tools?: string[] } },\n) => Promise<SubAgentResponse>;\n\n/**\n * Tool call request - parameters for callTool\n */\nexport interface ToolCallRequest {\n toolName: string;\n input: Record<string, unknown>;\n toolCallId?: string;\n state: Record<string, unknown>;\n messages: Message[];\n}\n\n/**\n * Agent options - dependency injection and callbacks\n * Following (ctx, request, options) => response pattern\n *\n * All functions are pure (deterministic, workflow-safe):\n * - getPrompt: Returns prompt configuration by ID\n * - resolveTools: Returns available tools based on current state\n * - callTool: Executes a tool and returns response (may use activities internally)\n */\nexport interface AgentOptions {\n /** Get prompt by ID - pure function */\n getPrompt: (promptId: string) => Prompt;\n\n /** Resolve tools from state - pure function */\n resolveTools: (state: Record<string, unknown>) => Tool[];\n\n /**\n * Call tool - pure function that may use activities internally\n * Required - the caller provides tool implementations\n */\n callTool: (ctx: Context, request: ToolCallRequest) => Promise<ToolResponse>;\n\n /** Signal handlers for UI updates */\n signals?: {\n onMessage?: (message: ChatMessage) => Promise<void>;\n onUpdate?: (update: { status?: AgentStatus; [key: string]: unknown }) => Promise<void>;\n };\n}\n\n// ============================================================================\n// Reducer\n// ============================================================================\n\n/**\n * Generic reducer function type - takes current state and returns new state\n * Products can extend this with their own state types\n *\n * @template S - State type (defaults to Record<string, unknown>)\n */\nexport type Reducer<S = Record<string, unknown>> = (state: S) => S;\n\n// ============================================================================\n// Tool Response\n// ============================================================================\n\n/**\n * Tool response - tool handlers return everything needed for UI\n *\n * Tools know their domain, so they decide:\n * - What tool UI to display (if any)\n * - How to update state (reducer)\n */\nexport interface ToolResponse {\n /** Tool output data (for LLM context) */\n output: unknown;\n /** Optional reducer to update agent state */\n reducer?: Reducer;\n /** Optional error message */\n error?: string;\n /** Optional UI component to display in chat */\n ui?: Ui;\n}\n\n// ============================================================================\n// Agent Activities Interface\n// ============================================================================\n\n/**\n * Activities interface - implemented by each product\n * This is the contract between platform workflow and product implementation\n *\n * Note: getPrompt and resolveTools are now pure functions passed via AgentOptions.\n * Only callTool remains as an activity since it may require external I/O.\n *\n * LLM queries are handled via the LLMProvider interface.\n * The worker spreads the LLM provider into activities via `...llmProvider`.\n * The agent workflow uses `proxyActivities<LLMProvider>()` to call the LLM.\n */\nexport interface AgentActivities {\n /**\n * Call tool - product provides its own tool implementations\n * Can return signals to update UI and reducer for state updates\n */\n callTool(request: { toolName: string; input: Record<string, unknown> }): Promise<ToolResponse>;\n}\n\n// ============================================================================\n// SDK Agent Composable Types\n// ============================================================================\n\n/**\n * Response from iterate() - single LLM call\n * Uses ToolCall from @jarvis/types\n */\nexport interface IterateResponse {\n /** LLM response content */\n content: string;\n /** Native thinking/reasoning content from the provider (if supported) */\n thinking?: string;\n /** Tool calls to execute (from platform types) */\n toolCalls?: ToolCall[];\n /** Whether there are tool calls to process */\n shouldContinue: boolean;\n /** Token usage metadata from LLM response */\n metadata?: Usage;\n /** Why the LLM stopped generating */\n stopReason?: StopReason;\n}\n\n/**\n * Output from a single tool call\n */\nexport interface ToolCallOutput {\n /** Tool name */\n toolName: string;\n /** Tool call ID */\n toolCallId: string;\n /** Context to add to LLM messages */\n context: unknown;\n /** State updates to apply */\n state?: unknown;\n /** UI component to display */\n ui?: Ui;\n /** Pruning instructions */\n prune?: { removeTools?: string[]; keepRecent?: number };\n /** Execution duration in milliseconds */\n durationMs: number;\n /** Tool call result status */\n status?: ToolCallStatus;\n /** Human-readable message (error message, feedback, or success message) */\n message?: string;\n /** Resource usage reported by this tool (internal tokens + credits) */\n usage?: Usage;\n}\n\n// ============================================================================\n// Run Types (Agent execution)\n// ============================================================================\n\n/**\n * Request for an agent run. One canonical shape across the codebase:\n * - `RuntimeProvider.run(...)` + `Agent.run(...)` — in-process harness.\n * - `AgentProvider.run(...)` — provider dispatch.\n * - JSON-RPC `agent.run` — cross-process dispatch (hub ↔ CLI runner).\n *\n * In-process callers populate `agent` (AgentConfig — non-serializable).\n * RPC callers leave `agent` unset; the provider resolves its own agent\n * implementation from the `provider` id.\n */\nexport interface RunAgentRequest<TState = unknown> {\n /** Correlation id for this run. Stable across streaming events +\n * the final response; also the signature used by `abort`. */\n runId?: string;\n /** Chat the run is attached to. */\n chatId?: string;\n /** Agent definition — required for in-process harness runs, omitted for\n * RPC dispatches (the provider resolves its own agent). */\n agent?: AgentConfig;\n /** Explicit provider pick when routing through a composed AgentProvider. */\n provider?: string;\n /** Message history (system / user / assistant). */\n messages: Message[];\n /** Initial state (harness only). */\n state?: TState;\n /** Execution mode (auto/ask/plan). */\n mode?: AgentMode;\n /** Override model id. */\n modelId?: string;\n /** Thinking/reasoning configuration. */\n thinking?: ThinkingConfig;\n /** Opaque tool descriptors handed to the provider's runtime. */\n tools?: unknown[];\n /** Stop after this many LLM turns. */\n maxTurns?: number;\n /** Tool-name deny-list (applies to any provider's tool runtime). */\n disallowedTools?: string[];\n /** Provider-native session resume / fork. */\n session?: {\n resume?: string;\n persist?: boolean;\n fork?: boolean;\n sessionId?: string;\n };\n /** File attachments uploaded by the user before dispatch. */\n attachments?: Array<{\n key: string;\n url: string;\n fileName: string;\n mimeType: string;\n size: number;\n }>;\n /** Code-agent-only inputs (CodeAgentProvider runs). */\n code?: {\n /** Directory the agent runs in. Worktree mode → the git-worktree path;\n * direct mode → the user's repo path itself. */\n workdir?: string;\n /** Repo context (git provider + branch) when the run is bound to a repo. */\n repo?: {\n owner: string;\n name: string;\n provider: string;\n branch: string;\n };\n };\n}\n\n/**\n * Response from agent execution\n */\nexport interface RunAgentResponse<TState = unknown> {\n /** Final assistant message content */\n message: string;\n /** Whether the execution completed successfully */\n success: boolean;\n /** Whether the execution was cancelled */\n cancelled: boolean;\n /** Final state after all tool calls */\n state: TState;\n /** Execution metadata */\n metadata: Usage & { iterations: number };\n /** Provider-native session id minted on this turn — runners surface it on\n * `agent.output` so the workflow + UI can correlate. */\n sessionId?: string;\n /** Exit info (present when loop stopped for a reason other than normal completion) */\n exit?: {\n reason: AgentExitReason;\n message: string;\n };\n}\n\n// ============================================================================\n// Hook Types\n// ============================================================================\n\n/**\n * Agent hooks - all callbacks for agent behavior\n * Tool hooks are colocated with tool definitions (tool.hooks)\n * These are fallback/global hooks and control callbacks\n */\nexport interface AgentHooks {\n // === REQUIRED ===\n\n /** LLM query function - required for iterate() */\n onQuery: (request: QueryLLMRequest) => Promise<QueryLLMResponse>;\n\n // === ITERATION LIFECYCLE ===\n\n /**\n * Called before each LLM iteration\n * Can modify messages, tools, and instructions for this iteration\n */\n onIterationStart?: (\n ctx: Context,\n req: { iteration: number; messages: Message[]; tools: Tool[] },\n ) => Promise<void | { messages?: Message[]; tools?: Tool[]; instructions?: string }>;\n\n /**\n * Called after each LLM iteration\n * Useful for logging, metrics, or custom behavior\n */\n onIterationEnd?: (\n ctx: Context,\n req: {\n iteration: number;\n response: IterateResponse;\n toolOutputs?: ToolCallOutput[];\n },\n ) => Promise<void>;\n\n // === TOOL LIFECYCLE (FALLBACK) ===\n\n /**\n * Called before tool execution (fallback for tools without hooks)\n * Tool-specific hooks take precedence\n */\n onBeforeToolCall?: BeforeToolHook;\n\n /**\n * Called after tool execution (fallback for tools without hooks)\n * Tool-specific hooks take precedence\n */\n onAfterToolCall?: AfterToolHook;\n\n // === UI SIGNALS ===\n\n /** Send message to chat UI */\n onMessage?: (message: ChatMessage) => Promise<void>;\n\n /** Send status/workflow update to UI */\n onUpdate?: (update: AgentUpdate) => Promise<void>;\n\n // === CONTROL ===\n\n /**\n * Wait for user input on tool/plan/max_iterations (approve/deny/modify)\n * @param inputId - Unique ID for this pending input (for parallel tool calls)\n * @returns UserInput matching the inputId, or null if cancelled\n */\n onUserInputRequest?: (inputId?: string) => Promise<UserInput | null>;\n\n /** Check if agent should be cancelled */\n onCancelled?: () => boolean;\n\n // === MAX ITERATIONS ===\n\n /**\n * Called when max iterations is reached\n * Return true to continue execution for another batch\n * Return false to stop (default behavior)\n */\n onMaxIterations?: (\n ctx: Context,\n req: {\n iteration: number;\n maxIterations: number;\n /** The initial max iterations value (amount added on each continue) */\n initialMaxIterations: number;\n lastResponse: IterateResponse;\n },\n ) => Promise<boolean>;\n\n // === MEMORY ===\n\n /** Search memories by query — called before first iterate for injection */\n onSearchMemory?: (ctx: Context, req: { query: string; limit?: number }) => Promise<Memory[]>;\n\n /** Extract memories from conversation — called after iterations (fire-and-forget) */\n onExtractMemory?: (ctx: Context, req: { messages: Message[] }) => Promise<void>;\n\n // === DEBUG ===\n\n /**\n * Optional debug logging callback\n * Called with debug info throughout the loop\n */\n onDebug?: (message: string, data?: Record<string, unknown>) => void;\n}\n\n// ============================================================================\n// Agent Config & Interface\n// ============================================================================\n\n/**\n * AgentConfig — pure definition, what users provide.\n * No execution hooks — those are wired by the runtime via RuntimeAgentConfig.\n */\nexport interface AgentConfig {\n /** Unique agent identifier */\n id: string;\n\n /** System instructions — static or dynamic (called each turn with current state) */\n instructions?: string | Message[] | ((ctx: Context, state: unknown) => string | Message[]);\n\n /**\n * Dynamic context — called once per query to inject dynamic content into system prompt.\n * Returns additional system content (e.g., current date, user preferences, recent state).\n */\n context?: (ctx: Context) => string | Message[] | Promise<string | Message[]>;\n\n /**\n * System reminders — contextual hints injected as `<system-reminder>` user messages.\n * Each reminder has a trigger that determines when it's injected.\n */\n reminders?: Reminder[];\n\n /** Tools — static list or dynamic function (called each turn with current state) */\n tools?: Tool[] | ((ctx: Context, state: unknown) => Tool[]);\n\n /** Maximum iterations before stopping (default: 10) */\n maxIterations?: number;\n\n /** Model options */\n options?: {\n temperature?: number;\n maxTokens?: number;\n topP?: number;\n };\n\n /** Source ID for signal routing — identifies this agent so user input responses route directly to it */\n sourceId?: string;\n}\n\n// ============================================================================\n// Agent Modes\n// ============================================================================\n\n/**\n * Agent execution mode — determines tool execution behavior.\n *\n * Built-in modes:\n * - \"ask\" — Prompt user before executing every tool (supervised)\n * - \"auto\" — Auto-approve edits and safe tools; still prompt on dangerous ones\n * - \"plan\" — Only non-destructive/safe tools, research & design before acting\n *\n * Extensible via (string & {}) — apps can define custom modes.\n */\nexport type AgentMode = \"ask\" | \"auto\" | \"plan\" | (string & {});\n\n// ============================================================================\n// Agent State (Base)\n// ============================================================================\n\n/**\n * Base state for all agent workflows.\n * Each implementation extends with domain-specific sub-objects.\n *\n * @example Platform agent\n * ```typescript\n * interface PlatformAgentState extends AgentState {\n * apps: { available: AvailableApp[]; subscribed: AppConfig[]; invocations: AppInvocation[] };\n * }\n * ```\n *\n * @example App agent (e.g., Chef)\n * ```typescript\n * interface ChefState extends AgentState {\n * recipes: Record<string, Recipe>;\n * }\n * ```\n */\nexport interface AgentState {\n /** User ID — from context */\n userId: string;\n /** Resolved language (userPrefs ?? browser header) */\n language?: string;\n /** Resolved timezone (userPrefs ?? browser header) */\n timezone?: string;\n /** User preferences by domain */\n preferences: {\n llm?: { model?: string };\n tts?: { model?: string; voice?: string };\n };\n /** MCP capabilities — available at all levels */\n mcp: {\n capabilities: McpCapabilities[];\n };\n}\n\n// ============================================================================\n// Reminders (Contextual System Hints)\n// ============================================================================\n\n/** A system reminder — contextual hint injected into conversation */\nexport interface Reminder {\n /** Unique identifier */\n id: string;\n /** Content — static string or dynamic function (return null to skip) */\n content: string | ((ctx: Context, state: unknown) => string | null);\n /** When to inject this reminder */\n trigger: ReminderTrigger;\n}\n\n/** When a reminder should be injected */\nexport type ReminderTrigger =\n | { type: \"always\" } // Every iteration\n | { type: \"once\" } // First iteration only\n | { type: \"interval\"; every: number } // Every N iterations\n | { type: \"condition\"; when: (ctx: Context, state: unknown) => boolean }\n | { type: \"after_tool\"; toolName: string } // After specific tool executes\n | { type: \"on_compact\" }; // After context compaction\n\n/**\n * RuntimeAgentConfig — AgentConfig + execution hooks.\n * Created by the runtime (local, temporal, etc.) by merging\n * AgentConfig + AgentHooks from providers/RunOptions.\n * Consumed by harness() in the runner.\n */\nexport interface RuntimeAgentConfig extends AgentConfig {\n /** Execution hooks — provided by the runtime */\n hooks: AgentHooks;\n /** Translation function for UI-facing messages. Identity fallback if not provided. */\n t?: TranslateFn;\n /** Dynamic context function from AgentConfig */\n context?: (ctx: Context) => string | Message[] | Promise<string | Message[]>;\n /** System reminders from AgentConfig */\n reminders?: Reminder[];\n /** Context window management configuration */\n contextWindow?: {\n maxTokens?: number;\n /** Model ID for AI summarization (Level 3 compaction). Use models.defaults.mini.id */\n model?: string;\n keepRecent?: number;\n keepSystem?: boolean;\n maxToolOutputSize?: number;\n };\n /** Budget enforcement configuration */\n budget?: {\n maxTokens?: number;\n maxOutputTokens?: number;\n maxCost?: number;\n maxDuration?: number;\n };\n /** Permission configuration */\n permissions?: {\n mode?: \"default\" | \"strict\" | \"auto\";\n canUseTool?: (\n ctx: Context,\n tool: Tool,\n input: unknown,\n ) => Promise<\n { action: \"allow\" } | { action: \"deny\"; reason: string } | { action: \"ask\"; reason: string }\n >;\n onDenied?: (ctx: Context, toolName: string, reason: string) => void;\n maxConsecutiveDenials?: number;\n };\n}\n\n/**\n * Agent - minimal, clean interface\n *\n * All functions follow (ctx, req) => resp pattern with <verb><noun> naming\n *\n * Usage:\n * ```typescript\n * const output = await myAgent.run(ctx, {\n * agent: planner,\n * messages,\n * state,\n * });\n * ```\n */\nexport interface Agent<TState = unknown> {\n /** Agent configuration */\n readonly config: AgentConfig;\n\n // === EXECUTION ===\n\n /**\n * Run the complete agent loop\n * Handles: iterations, tool calls, state updates, messages, pruning\n * Tool calls run in PARALLEL, state updates applied SYNCHRONOUSLY after\n * Individual tool failures are caught and don't break other calls\n */\n run: (ctx: Context, req: RunAgentRequest<TState>) => Promise<RunAgentResponse<TState>>;\n\n /**\n * Run single LLM iteration (low-level)\n * Use run() for the full loop, or iterate() for manual control\n */\n iterate: (\n ctx: Context,\n req: { messages: Message[]; tools?: Tool[]; modelId?: string },\n ) => Promise<IterateResponse>;\n\n /**\n * Call a tool with full hook orchestration (low-level)\n * Used internally by query(), or for manual control\n */\n callTool: (\n ctx: Context & { state: TState },\n req: { tool: Tool; input: unknown; toolCallId: string },\n ) => Promise<ToolCallOutput>;\n\n // === STATE ===\n\n /**\n * Apply state reducer (pure function)\n * Returns new state without mutation\n */\n reduce: (state: TState, reducer: Reducer<TState>) => TState;\n\n // === UPDATES ===\n\n /**\n * Send message to chat\n * Handles all message types: thinking, tool, status, text, tool UI\n */\n sendMessage: (ctx: Context, message: ChatMessage) => Promise<void>;\n\n /**\n * Send general update\n * Extensible - can send workflow state or other update types\n */\n sendUpdate: (ctx: Context, update: AgentUpdate) => Promise<void>;\n\n // === CONTROL ===\n\n /**\n * Check if cancelled\n */\n isCancelled: () => boolean;\n}\n\n// ============================================================================\n// Context Management Types\n// ============================================================================\n\n/**\n * Options for pruning messages to reduce context size\n */\nexport interface PruneOptions {\n /** Maximum tokens to keep (optional) */\n maxTokens?: number;\n /** Number of recent messages to always keep (default: 10) */\n keepRecent?: number;\n /** Remove all tool calls/responses for these tool names */\n removeTool?: string[];\n /** Remove all messages before this index */\n removeBeforeIndex?: number;\n}\n\n/**\n * Compacted error for context\n */\nexport interface CompactError {\n name: string;\n message: string;\n toolName: string;\n timestamp: string;\n}\n\n// ============================================================================\n// Platform Agent Composable Types (for manual loop control)\n// ============================================================================\n\n/**\n * Response from wait() - human-in-the-loop\n */\nexport interface WaitResponse {\n /** Whether user confirmed */\n confirmed: boolean;\n /** Optional data from user (e.g., modifications) */\n data?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Runtime Provider\n// ============================================================================\n\n/**\n * Runtime provider — pluggable execution backend for running agents.\n *\n * Swappable implementations:\n * - localRuntime() — runs harness in-process\n * - temporalRuntime() — runs harness in a Temporal workflow\n * - claudeRuntime() — runs via Claude API (future)\n * - openaiRuntime() — runs via OpenAI Agents API (future)\n *\n * Transport/channel delivery is the caller's concern — the provider\n * only returns data via run() or yields events via stream().\n */\nexport interface RuntimeProvider extends Provider {\n /** Start execution and wait for completion */\n run<TState = unknown>(\n ctx: Context,\n req: RunAgentRequest<TState>,\n ): Promise<RunAgentResponse<TState>>;\n\n /** Start execution and yield events in real-time */\n stream<TState = unknown>(\n ctx: Context,\n req: RunAgentRequest<TState>,\n options?: { signal?: AbortSignal },\n ): AsyncIterable<RunAgentEvent<TState>>;\n\n /** Start execution without waiting (fire-and-forget). Used when a separate stream handles delivery. */\n start<TState = unknown>(ctx: Context, req: RunAgentRequest<TState>): Promise<void>;\n}\n\n/** Events yielded by AgentProvider.stream() */\nexport type RunAgentEvent<TState = unknown> =\n | { type: \"message\"; message: ChatMessage }\n | { type: \"thinking\"; messageId: string; content: string; isComplete: boolean }\n | {\n type: \"tool_call\";\n toolCall: {\n name: string;\n status: string;\n input?: unknown;\n output?: unknown;\n };\n }\n | { type: \"update\"; update: AgentUpdate }\n | { type: \"iteration\"; iteration: number; tokens: number }\n | { type: \"completed\"; output: RunAgentResponse<TState> }\n | { type: \"error\"; error: Error };\n","/**\n * Chat UI + workflow types.\n *\n * The DB entity `Chat` lives in `data/chat.types.ts` and is the single source\n * of truth for persisted chats — this module stays focused on:\n * - streaming state shared between workflows and the UI (`ChatState`)\n * - plan visualization (`PlanPhase`, `PlanItem`)\n * - audio mode (`AudioState`, `AudioSettings`)\n * - chat signals sent from UI → workflow (`ChatSignal` + payloads)\n *\n * Message + input types are defined in their own files and re-exported here\n * because UI code imports them through `@jarvis/types`.\n */\n\nimport type { AgentMode, AgentStatus } from \"./agent.types\";\nimport type { ChatMessage, FileAttachment } from \"./message.types\";\nimport type { PendingUserInput } from \"./input.types\";\nimport type { LLMQueryOutput } from \"./llm.types\";\nimport type { Reference } from \"./reference.types\";\n\nexport {\n type MessageRole,\n type ChatMessage,\n type ChatMessageType,\n type MessageStatus,\n type FileAttachment,\n type SectionType,\n type Section,\n type SectionMetadata,\n type ErrorMetadata,\n type ChatMessageMetadata,\n type ToolCallData,\n type ThinkingData,\n} from \"./message.types\";\n\nexport { type UiComponentMetadata } from \"./ui.types\";\n\nexport { type PendingInputType, type PendingUserInput } from \"./input.types\";\n\n// =============================================================================\n// Streaming state (shared between workflow queries + UI SSE)\n// =============================================================================\n\nexport interface ChatState {\n chatId: string;\n userId: string;\n mode: string;\n currentAppId: string | null;\n status: AgentStatus;\n messages: ChatMessage[];\n lastActivity: string;\n lastUpdated: number;\n pendingUserInputs: PendingUserInput[];\n childWorkflowId: string | null;\n /** Dev environment server URL (when in build mode). */\n devServerUrl?: string;\n}\n\n// =============================================================================\n// Plan visualization (shared across platform UI)\n// =============================================================================\n\nexport type PlanPhase = \"planning\" | \"confirming\" | \"executing\" | \"completed\";\n\nexport interface PlanItem {\n /** 1-based index. */\n index: number;\n title: string;\n description: string;\n difficulty?: \"beginner\" | \"intermediate\" | \"advanced\";\n completed?: boolean;\n active?: boolean;\n /** Extra data for product-specific needs. */\n data?: unknown;\n}\n\n// =============================================================================\n// Audio mode\n// =============================================================================\n\nexport type AudioState = \"idle\" | \"listening\" | \"speaking\" | \"processing\";\n\nexport interface AudioSettings {\n isActive: boolean;\n onToggle: () => void;\n state: AudioState;\n /** Mic level (0–1). Call in RAF loops. */\n getAudioLevel: () => number;\n interimTranscript?: string;\n spokenText?: string;\n onAbort?: () => void;\n onStopListening?: () => void;\n volume?: number;\n isMuted?: boolean;\n onVolumeChange?: (v: number) => void;\n onToggleMute?: () => void;\n isAwaitingInput?: boolean;\n cancelPendingInput?: () => void;\n onPendingInput?: (input: { id: string; prompt: string } | null) => void;\n}\n\n// =============================================================================\n// Chat signals (UI → workflow)\n// =============================================================================\n\nexport interface SendMessagePayload {\n id: string;\n content: string;\n timestamp: number;\n model?: string;\n mode?: AgentMode;\n thinking?: unknown;\n output?: LLMQueryOutput;\n references?: Reference[];\n attachments?: FileAttachment[];\n mcpServers?: string[];\n /** Session resume config for continuing external agent sessions. */\n session?: {\n resume?: string;\n persist?: boolean;\n };\n /** When the message originates from a modify-permission feedback, this\n * carries the gated tool's tool-call id. It's persisted on the message\n * metadata and used by the timeline renderer to display the message as\n * muted text under the tool's tool UI panel instead of as a top-level\n * user-message bubble. */\n toolCallId?: string;\n}\n\nexport interface UserInputPayload {\n id: string;\n action: string;\n data?: Record<string, unknown>;\n feedback?: string;\n /** Tool-call id of the gated tool. Hub uses this to anchor the synthetic\n * follow-up `sendMessage` on `modify` actions to the right tool's\n * tool UI panel. */\n toolCallId?: string;\n /** Client-generated id for the optimistic feedback message. The hub uses\n * it verbatim when fanning out the `sendMessage` so the streamed server\n * message replaces the optimistic insert in place via id-based dedupe. */\n messageId?: string;\n}\n\nexport interface InterruptPayload {\n reason?: string;\n}\n\nexport type ChatSignal =\n | ({ signal: \"sendMessage\" } & SendMessagePayload)\n | ({ signal: \"userInput\" } & UserInputPayload)\n | ({ signal: \"interrupt\" } & InterruptPayload);\n","/**\n * Input Types\n * Pending user input types for human-in-the-loop flows.\n *\n * This is a leaf module — it only imports from tool.types (for Ui).\n * No circular dependencies.\n */\n\nimport type { Ui } from \"./ui.types\";\n\n// =============================================================================\n// Pending User Input Types (for tool/plan/max_iterations panels)\n// =============================================================================\n\n/**\n * Pending input type - what kind of user input is needed\n */\nexport type PendingInputType = \"tool\" | \"plan\" | \"max_iterations\";\n\n/**\n * Pending user input - awaiting user action\n * Used for tool confirmation, plan approval, and max iterations prompts\n */\nexport interface PendingUserInput<TData = unknown> {\n /** Unique ID for this pending input */\n id: string;\n /** Source ID — identifies the agent/process that should receive the user's response (for direct signal routing) */\n sourceId?: string;\n /** Type of input (tool, plan, or max_iterations) */\n type: PendingInputType;\n /** Tool name (for tool type) */\n toolName?: string;\n /** Tool call ID */\n toolCallId?: string;\n /** Input parameters */\n input?: Record<string, unknown>;\n /** Timing: before or after tool execution */\n timing?: \"before\" | \"after\";\n /** Raw data for basic preview (exclusive with ui) */\n output?: TData;\n /** UI component for rich rendering (exclusive with output) */\n ui?: Ui;\n /** Plan ID (for plan type) */\n planId?: string;\n /** Plan items (for plan type — agent execution steps) */\n items?: Array<{\n id: string;\n title: string;\n status: \"pending\" | \"active\" | \"completed\" | \"skipped\";\n }>;\n /** Current iteration (for max_iterations type) */\n iteration?: number;\n /** Max iterations limit */\n maxIterations?: number;\n /** Initial max iterations value (amount added on each continue) */\n initialMaxIterations?: number;\n /** Human-readable reason for the prompt */\n reason?: string;\n}\n","/**\n * LLM (Large Language Model) related types\n */\n\nimport type {\n TTSVoice,\n TTSModel,\n TTSResponseFormat,\n} from \"../media/tts.types\";\n\nimport type { Message, MultimodalMessage } from \"./message.types\";\nimport type { Usage } from \"./usage.types\";\nimport { Context } from \"../core/context.types\";\nimport {\n Model,\n ResolveModelRequest,\n ResolveModelResponse,\n} from \"./model.types\";\nimport { Provider } from \"../core/provider.types\";\nimport { Schema } from \"../core/schema.types\";\nimport { ToolCall, Tool } from \"./tool.types\";\n\n// Re-export message types for backward compatibility\nexport type {\n MessageRole,\n Message,\n MultimodalMessage,\n BaseMessage,\n UserMessage,\n AssistantMessage,\n SystemMessage,\n ToolMessage,\n ContentPart,\n TextContentPart,\n AudioContentPart,\n ImageContentPart,\n} from \"./message.types\";\n\n// =============================================================================\n// OUTPUT CONFIGURATION\n// =============================================================================\n\n/** Output format types — what the response should include */\nexport type OutputFormat = \"text\" | \"audio\" | \"json\";\n\n/** Audio-specific output configuration */\nexport interface AudioOutputConfig {\n /** TTS voice (defaults to \"nova\") */\n voice?: TTSVoice;\n /** TTS model (defaults to \"tts-1\") */\n model?: TTSModel;\n /** Audio response format (defaults to \"mp3\") */\n format?: TTSResponseFormat;\n}\n\n/**\n * Output configuration for LLM response delivery.\n *\n * Controls both LLM output format (json with schema) and\n * response delivery formats (text, audio).\n *\n * Valid format combinations:\n * - `[\"text\"]` — text only (default)\n * - `[\"text\", \"audio\"]` — text + audio (voice mode)\n * - `[\"json\"]` — JSON structured output (standalone, requires schema)\n *\n * @example Text only (default)\n * ```typescript\n * { formats: [\"text\"] }\n * ```\n *\n * @example Text + audio (voice mode)\n * ```typescript\n * { formats: [\"text\", \"audio\"], audio: { voice: \"nova\" } }\n * ```\n *\n * @example JSON structured output\n * ```typescript\n * { formats: [\"json\"], schema: mySchema }\n * ```\n */\nexport interface LLMQueryOutput {\n /**\n * Which formats to include in the response. Defaults to [\"text\"].\n * Valid: [\"text\"], [\"text\", \"audio\"], or [\"json\"].\n */\n formats?: [\"text\"] | [\"text\", \"audio\"] | [\"json\"];\n /** JSON schema — required when formats is [\"json\"] */\n schema?: Schema;\n /** Audio-specific settings — used when \"audio\" is in formats */\n audio?: AudioOutputConfig;\n}\n\n/** Check if an output config includes a specific format */\nexport function hasOutputFormat(\n output: LLMQueryOutput | undefined,\n format: OutputFormat,\n): boolean {\n return (output?.formats as string[] | undefined)?.includes(format) ?? false;\n}\n\n// =============================================================================\n// THINKING CONFIG\n// =============================================================================\n\n/**\n * Thinking/reasoning configuration — provider-agnostic.\n *\n * Providers map this to their native format:\n * - Anthropic: adaptive → `thinking: { type: \"enabled\" }`, enabled → `thinking: { budget_tokens }`\n * - Gemini: maps to `thinkingConfig.thinkingLevel` or `thinkingBudget`\n * - OpenAI: maps to `reasoning_effort`\n * - Providers without support: ignore the field\n */\nexport interface ThinkingConfig {\n /** Thinking mode */\n type: \"adaptive\" | \"enabled\" | \"disabled\";\n /** Token budget for thinking (only used with type: \"enabled\") */\n budgetTokens?: number;\n}\n\n// =============================================================================\n// LLM QUERY TYPES\n// =============================================================================\n\nexport interface QueryLLMRequest {\n model: string;\n messages: (Message | MultimodalMessage)[];\n tools?: Tool[];\n output?: LLMQueryOutput;\n thinking?: ThinkingConfig;\n options?: {\n temperature?: number;\n maxTokens?: number;\n topP?: number;\n };\n}\n\nexport interface LLMQueryOptions {\n /** Override provider selection (bypass model-based routing) */\n provider?: string;\n /** Set false to suppress Redis token streaming (for internal LLM calls like query understanding) */\n stream?: boolean;\n}\n\nexport interface QueryLLMResponse {\n content: string;\n /** JSON structured output (when output format is \"json\" and SDK returns structured_output) */\n json?: string;\n /** Error from the SDK (e.g. error_max_turns, error_max_budget_usd) */\n error?: string;\n thinking?: string;\n toolCalls?: ToolCall[];\n metadata?: QueryLLMMetadata;\n /** Why the LLM stopped generating — populated by providers from API response */\n stopReason?: StopReason;\n}\n\n/** Why the LLM stopped generating */\nexport type StopReason =\n | \"end_turn\"\n | \"max_tokens\"\n | \"tool_use\"\n | \"stop_sequence\"\n | \"content_filter\";\n\nexport interface QueryLLMMetadata {\n model: string;\n usage: Usage;\n options?: {\n temperature?: number;\n maxTokens?: number;\n topP?: number;\n };\n duration: number;\n provider: string;\n}\n\n// LLM Client interface\nexport interface LLMProvider extends Provider {\n query(\n ctx: Context,\n req: QueryLLMRequest,\n options?: LLMQueryOptions,\n ): Promise<QueryLLMResponse>;\n stream(\n ctx: Context,\n req: QueryLLMRequest,\n options?: LLMQueryOptions,\n ): AsyncGenerator<QueryLLMResponse>;\n getModels?(): Promise<Model[]>;\n /** Create a new instance with different config (e.g., different API key for BYOK) */\n configure?(config: Record<string, unknown>): LLMProvider;\n /** Optional provider-specific request validation. Called by the router before query/stream. */\n validateQuery?(ctx: Context, req: QueryLLMRequest): QueryLLMRequest;\n}\n\n// ============================================================================\n// LLM Resolvers\n// ============================================================================\n\nexport interface ResolveLLMProviderRequest {\n providerName?: string;\n providers: LLMProvider[];\n}\n\nexport interface ResolveLLMProviderResponse {\n provider: LLMProvider;\n}\n\nexport interface LLMProviderResolver extends Provider {\n resolve(\n request: ResolveLLMProviderRequest,\n ): Promise<ResolveLLMProviderResponse>;\n}\n\nexport interface ModelResolver extends Provider {\n resolve(request: ResolveModelRequest): Promise<ResolveModelResponse>;\n}\n\nexport interface ResolveOptionsRequest {\n requestOptions?: QueryLLMRequest[\"options\"];\n modelOptions?: QueryLLMRequest[\"options\"];\n}\n\nexport interface ResolveOptionsResponse {\n options?: QueryLLMRequest[\"options\"];\n}\n\nexport interface OptionsResolver extends Provider {\n resolve(request: ResolveOptionsRequest): Promise<ResolveOptionsResponse>;\n}\n","/**\n * Message Types\n * All message-related types used across agent, chat, and LLM systems.\n *\n * The unified rich-rendering layer (`Ui`, `UiComponent*`) lives in\n * `./ui.types` so messages, tools, and skills can all import it without\n * crossing concerns. We pull in `Ui` here for the `metadata.ui` field\n * on chat messages.\n */\n\nimport type { ToolCallStatus, ToolCall } from \"./tool.types\";\nimport type { Ui } from \"./ui.types\";\n\n// =============================================================================\n// MESSAGE ROLE\n// =============================================================================\n\n/** Message role — matches the DB enum */\nexport type MessageRole = \"system\" | \"user\" | \"assistant\" | \"tool\";\n\n// =============================================================================\n// LLM MESSAGE TYPES\n// =============================================================================\n\nexport interface BaseMessage {\n role: MessageRole;\n content?: string;\n}\n\nexport interface ToolMessage extends BaseMessage {\n role: \"tool\";\n content: string;\n toolCallId: string;\n name?: string;\n}\n\nexport interface UserMessage extends Omit<BaseMessage, \"content\"> {\n role: \"user\";\n content?: string; // Support both text and multimodal\n}\n\nexport interface AssistantMessage extends BaseMessage {\n role: \"assistant\";\n toolCalls?: ToolCall[];\n}\n\nexport interface SystemMessage extends BaseMessage {\n role: \"system\";\n}\n\nexport type Message = UserMessage | AssistantMessage | SystemMessage | ToolMessage;\n\n// Provider-agnostic content types for multimodal messages\nexport type TextContentPart = {\n type: \"text\";\n text: string;\n};\n\nexport type AudioContentPart = {\n type: \"audio\";\n data: string; // Base64 encoded audio\n format: \"wav\" | \"mp3\";\n};\n\nexport type ImageContentPart = {\n type: \"image\";\n /** Base64-encoded image data */\n data: string;\n /** MIME type (image/jpeg, image/png, image/gif, image/webp) */\n mimeType: string;\n};\n\nexport type ContentPart = TextContentPart | AudioContentPart | ImageContentPart;\n\nexport interface MultimodalMessage extends Omit<BaseMessage, \"content\"> {\n role: \"user\";\n content?: ContentPart[]; // Support both text and multimodal\n}\n\n// =============================================================================\n// FILE ATTACHMENTS\n// =============================================================================\n\n/**\n * File attachment metadata — uploaded to storage, referenced by key/URL.\n * Used on chat messages and in the signal pipeline (small payload, no file content).\n */\nexport interface FileAttachment {\n /** Storage key (e.g., \"uploads/userId/uuid.jpg\") */\n key: string;\n /** Accessible URL (e.g., /api/v1/storage/read/uploads/userId/uuid.jpg) */\n url: string;\n /** Original filename */\n fileName: string;\n /** MIME type */\n mimeType: string;\n /** File size in bytes */\n size: number;\n}\n\n// =============================================================================\n// CHAT MESSAGE TYPES\n// =============================================================================\n\n/**\n * Message type discriminator for rendering\n * Claude Code-style transparency - everything visible in chat\n *\n * - text: Regular text message (user or assistant)\n * - thinking: AI reasoning (collapsible, can stream)\n * - tool: Tool call (use toolCall.status for running/completed/error)\n * - ui: Rich visualization (goals, tasks, schedule)\n * - error: Application error (displayed in chat, can have retry)\n */\nexport type ChatMessageType = \"text\" | \"thinking\" | \"tool\" | \"status\" | \"ui\" | \"error\";\n\n/**\n * Message status for streaming/partial updates\n */\nexport type MessageStatus =\n | \"pending\"\n | \"streaming\"\n | \"complete\"\n | \"error\"\n /** User-initiated interrupt (CC-style \"stopped\"). The session is intact\n * and the next message resumes; render this distinctly from \"error\". */\n | \"interrupted\";\n\n/**\n * Selection section type - generic string, products define their own types\n * @example \"courses\" | \"exercises\" | \"songs\" | \"videos\"\n * @example \"tasks\" | \"goals\" | \"habits\"\n */\nexport type SectionType = string;\n\n// =============================================================================\n// Metadata Interfaces\n// =============================================================================\n\n/**\n * Section within a selection message\n */\nexport interface Section<TItem = unknown> {\n type: SectionType;\n title?: string;\n items: TItem[];\n}\n\n/**\n * Metadata for selection messages (welcome, mode-specific lists)\n */\nexport interface SectionMetadata<TItem = unknown> {\n sections: Section<TItem>[];\n}\n\n// Ui rendering types live in `./ui.types`. See that module for `Ui`,\n// `UiComponent`, `UiResource`, `UiComponentConfig`, `UiComponentProps`,\n// `UiComponentMetadata`, `UiComponentAction`, `UiType`, and `McpUiData`.\n\n/**\n * Metadata for error messages (application errors displayed in chat)\n */\nexport interface ErrorMetadata {\n /** Error code for programmatic handling */\n errorCode?: string;\n /** Whether the action can be retried */\n retryable?: boolean;\n /** Original error details (for debugging) */\n details?: unknown;\n}\n\n/**\n * Flat ChatMessage metadata. Top-level `ChatMessage` mirrors the\n * `chat_messages` DB columns; every other field of `ChatMessage` lives here\n * so streaming, persistence, and hydration share the same shape.\n *\n * Legacy artifact / section / error fields from the previous discriminated\n * union are preserved inline so old payloads survive the move.\n */\nexport interface ChatMessageMetadata {\n // Display extras (not yet columns).\n timestamp?: Date | string;\n sender?: string;\n avatar?: string;\n\n // Streaming / lifecycle.\n status?: MessageStatus;\n isPartial?: boolean;\n\n // Tool / thinking / ui — `ui` is the unified tool-UI descriptor (PR #3),\n // valid on any message (system / assistant / tool / user) so any\n // message can carry a rich rendering instead of plain text.\n toolCall?: ToolCallData;\n thinking?: ThinkingData;\n ui?: Ui;\n toolCallId?: string;\n\n // Error payload.\n error?: ErrorMetadata | string;\n\n // User-message attachments.\n attachments?: FileAttachment[];\n\n // Workflow status-message plumbing.\n taskId?: string;\n diffs?: {\n files: Array<{ file: string; additions: number; deletions: number }>;\n additions: number;\n deletions: number;\n };\n\n // Legacy section payload — preserved inline so old payloads survive the\n // move from the old discriminated union.\n sections?: Section[]; // from SectionMetadata\n errorCode?: string; // from ErrorMetadata\n retryable?: boolean; // from ErrorMetadata\n details?: unknown; // from ErrorMetadata\n\n // Open-ended escape hatch — providers / sync may attach extra fields.\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Claude Code-style Message Data (for type=\"tool\" and type=\"thinking\")\n// =============================================================================\n\n/**\n * Tool call data - for type=\"tool\" messages\n * Status determines display: running shows input, completed/error shows output\n */\nexport interface ToolCallData {\n /** Tool name */\n toolName: string;\n /** Tool call ID for correlation */\n toolCallId: string;\n /** Tool execution status */\n status: ToolCallStatus;\n /** Human-readable tool label from metadata (e.g., \"Create Goal\") */\n label?: string;\n /** Tool input parameters (shown when running) */\n input?: Record<string, unknown>;\n /** Tool output (shown when completed) */\n output?: unknown;\n /** Error message (shown when error) */\n error?: string;\n /** Execution duration in milliseconds */\n durationMs?: number;\n}\n\n/**\n * Thinking data - for type=\"thinking\" messages\n * AI reasoning that can be collapsed/expanded\n */\nexport interface ThinkingData {\n /** Thinking status */\n status: \"thinking\" | \"complete\";\n /** Optional title for the thinking block */\n title?: string;\n}\n\n\n// =============================================================================\n// Chat Message\n// =============================================================================\n\n/**\n * Top-level mirrors the `chat_messages` DB columns; every other current\n * field lives under `metadata`. If a field gets a column later, promote it\n * out of `metadata` here and the rest stays.\n */\nexport interface ChatMessage {\n /** Unique message identifier */\n id: string;\n /** User this message belongs to (mirrors the `user_id` column) */\n userId?: string;\n /** Chat ID this message belongs to */\n chatId?: string;\n /** Message role */\n role: MessageRole;\n /** Message type for rendering */\n type: ChatMessageType;\n /** Message content */\n content: string;\n /** Creation timestamp (ISO string) */\n createdAt?: string;\n /**\n * Everything else: status / isPartial / toolCall / thinking / ui / error /\n * attachments / toolCallId / timestamp / sender / avatar / taskId / diffs /\n * legacy artifact + section payloads. Read via `msg.metadata?.<field>`.\n */\n metadata?: ChatMessageMetadata;\n}\n","/**\n * MCP (Model Context Protocol) Types\n * Types for MCP servers, clients, and transports\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Prompt } from \"./prompt.types\";\nimport type { Provider } from \"../core/provider.types\";\nimport type { Tool } from \"./tool.types\";\nimport type { Ui } from \"./ui.types\";\n\n// ============================================================================\n// Authentication Types\n// ============================================================================\n\n/**\n * Authentication context available to MCP handlers after validation\n */\nexport interface AuthContext extends Context {\n scopes: string[];\n expiresAt?: number;\n method?: \"oauth\" | \"token\";\n}\n\n/**\n * OAuth 2.1 authentication configuration for MCP transports\n */\nexport interface McpOAuthConfig {\n issuer: string;\n audience: string;\n validate: (token: string) => Promise<AuthContext>;\n extract: (req: unknown) => string | null | Promise<string | null>;\n resource?: string;\n authorizationServers?: string[];\n}\n\n/**\n * Simple token authentication configuration for MCP transports\n */\nexport interface TokenConfig {\n extract: (req: unknown) => string | null | Promise<string | null>;\n validate: (token: string) => Promise<AuthContext>;\n}\n\n/**\n * Composite authentication configuration\n */\nexport interface Auth {\n oauth?: McpOAuthConfig;\n token?: TokenConfig;\n skip?: boolean;\n exclude?: string[];\n}\n\n/**\n * OAuth 2.1 protected resource metadata (RFC 9728)\n */\nexport interface ProtectedResourceMetadata {\n resource: string;\n authorization_servers: string[];\n bearer_methods_supported?: (\"header\" | \"body\" | \"query\")[];\n resource_documentation?: string;\n}\n\n// ============================================================================\n// MCP Core Types\n// ============================================================================\n\n/**\n * MCP Resource type\n */\nexport interface Resource {\n uri: string;\n name: string;\n description: string;\n mimeType?: string;\n}\n\n/**\n * MCP Transport configuration\n * Supports stdio, HTTP, and SSE transports\n * Can contain ${ENV_VAR} placeholders that are resolved from process.env\n */\nexport interface McpTransport {\n type: \"stdio\" | \"http\" | \"sse\";\n command?: string; // For stdio\n args?: string[]; // For stdio\n env?: Record<string, string>; // For stdio - can contain ${ENV_VAR}\n url?: string; // For http/sse - can contain ${ENV_VAR}\n headers?: Record<string, string>; // For http/sse - can contain ${ENV_VAR}\n}\n\n/**\n * MCP Server Capabilities\n * Collection of tools, prompts, and resources available from a server\n */\nexport interface McpServerCapabilities {\n tools?: Tool[];\n prompts?: Prompt[];\n resources?: Resource[];\n}\n\n/**\n * MCP Server configuration\n * Can be in-memory (with capabilities) or remote (with transport)\n * Auth is optional — when provided, validateAuth runs on every MCP handler.\n */\nexport interface McpServer {\n name: string;\n description?: string;\n version: string;\n capabilities?: McpServerCapabilities;\n transport?: McpTransport;\n auth?: Auth;\n}\n\n// ============================================================================\n// MCP Provider Interface\n// ============================================================================\n\n/**\n * MCP Provider interface\n * Handles both in-memory and remote MCP servers\n */\nexport interface McpProvider extends Provider {\n /**\n * Get capabilities from a server\n */\n getCapabilities(request: {\n server: McpServer;\n }): Promise<{ capabilities: McpServerCapabilities }>;\n\n /**\n * Get tools from a server\n */\n getTools(request: { server: McpServer }): Promise<{ tools: Tool[] }>;\n\n /**\n * Call a tool on a server\n */\n callTool(request: {\n server: McpServer;\n name: string;\n arguments: unknown;\n }): Promise<{ result: unknown }>;\n\n /**\n * Get prompts from a server\n */\n getPrompts(request: { server: McpServer }): Promise<{ prompts: Prompt[] }>;\n\n /**\n * Get a specific prompt from a server\n */\n getPrompt(request: {\n server: McpServer;\n name: string;\n arguments?: unknown;\n }): Promise<{ prompt: Prompt }>;\n\n /**\n * Get resources from a server\n */\n getResources(request: {\n server: McpServer;\n }): Promise<{ resources: Resource[] }>;\n\n /**\n * Get a specific resource from a server\n */\n getResource(request: {\n server: McpServer;\n uri: string;\n }): Promise<{ content: string; mimeType?: string }>;\n}\n\n// ============================================================================\n// MCP Server Installation Types (Marketplace / Phase 4)\n// ============================================================================\n\n/**\n * Input for installing a third-party MCP server\n */\nexport interface InstallServerInput {\n name: string;\n transport: McpTransport;\n description?: string;\n}\n\n/**\n * Input for uninstalling an MCP server\n */\nexport interface UninstallServerInput {\n name: string;\n}\n\n/**\n * Output from resolving all installed servers' capabilities\n */\nexport interface ResolveServersOutput {\n tools: Tool[];\n prompts: Prompt[];\n resources: Resource[];\n}\n\n/**\n * Serializable MCP capability metadata for the orchestrator.\n * Includes tools, prompts, and resources from cached capabilities.\n * No closures — safe to pass across Temporal workflow boundaries.\n */\nexport interface McpCapabilities {\n serverName: string;\n transport: McpTransport;\n tools: McpTool[];\n prompts: McpPrompt[];\n resources: McpResource[];\n}\n\n/**\n * Serializable MCP tool metadata (no closures — returned from activity)\n */\nexport interface McpTool {\n name: string;\n description: string;\n inputSchema: unknown;\n serverName: string;\n transport: McpTransport;\n ui?: Ui;\n}\n\n/**\n * Serializable MCP prompt metadata\n */\nexport interface McpPrompt {\n name: string;\n description?: string;\n serverName: string;\n transport: McpTransport;\n}\n\n/**\n * Serializable MCP resource metadata\n */\nexport interface McpResource {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n serverName: string;\n transport: McpTransport;\n}\n","/**\n * Platform Memory Types\n *\n * Base types for semantic memory storage with pgvector.\n * Products can extend these types with their own memory categories.\n */\n\n// =============================================================================\n// Base Memory Types\n// =============================================================================\n\n/**\n * Base memory types shared across all products.\n * Products can extend with additional types using union types.\n */\nexport type BaseMemoryType = \"fact\" | \"preference\";\n\n// =============================================================================\n// Domain Types\n// =============================================================================\n\n/**\n * Base memory entity.\n * Products can extend this interface for additional fields.\n */\nexport interface BaseMemory {\n id: string;\n userId: string;\n memoryType: string; // string to allow product extensions\n content: string;\n embedding?: number[] | null;\n importance: number;\n metadata: Record<string, unknown>;\n createdAt: Date | string;\n accessCount: number;\n lastAccessedAt?: Date | string | null;\n score?: number; // Similarity score from vector search\n}\n\n// =============================================================================\n// Database Row Types\n// =============================================================================\n\n/**\n * Database row type for memories table.\n * Uses snake_case to match PostgreSQL conventions.\n */\nexport interface DbBaseMemory {\n id: string;\n user_id: string;\n memory_type: string;\n content: string;\n embedding?: number[] | null;\n importance: number;\n metadata: Record<string, unknown> | null;\n created_at: Date | string;\n access_count: number;\n last_accessed_at?: Date | string | null;\n}\n\n// =============================================================================\n// Input Types\n// =============================================================================\n\n/**\n * Input for creating a new memory.\n */\nexport interface CreateMemoryInput {\n id: string;\n userId: string;\n memoryType: string;\n content: string;\n importance?: number;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Input for searching memories.\n */\nexport interface SearchMemoriesInput {\n userId: string;\n query?: string; // Optional text query for semantic search\n types?: string[]; // Filter by memory type(s)\n limit?: number; // Default: 10\n}\n","/**\n * Memory Types\n *\n * Pluggable memory system for agent knowledge persistence.\n * All methods follow (ctx, req, options?) => resp.\n *\n * Pattern: MemoryProvider lives in RuntimeProviders (like LLM, DB, storage).\n * Harness uses hooks (onSearchMemory, onExtractMemory) — never calls provider directly.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Message } from \"./llm.types\";\n\n// =============================================================================\n// MEMORY TYPES\n// =============================================================================\n\n/** Built-in platform memory types */\nexport type PlatformMemoryType =\n | \"user\" // User preferences, role, knowledge\n | \"feedback\" // Corrections, confirmed approaches\n | \"reference\" // External system pointers (URLs, tools, services)\n | \"patterns\"; // Domain workflows, interaction conventions, preferred approaches\n\n/** Extensible memory type — platform types + any app-defined string */\nexport type MemoryType = PlatformMemoryType | (string & {});\n\n/** A single memory record */\nexport interface Memory {\n id: string;\n name: string;\n description: string;\n type: MemoryType;\n content: string;\n scope?: string;\n createdAt: string;\n updatedAt: string;\n}\n\n// =============================================================================\n// REQUEST / OPTIONS TYPES — <Verb><Noun>Request\n// =============================================================================\n\nexport interface SearchMemoryRequest {\n query: string;\n}\n\nexport interface SearchMemoryOptions {\n limit?: number;\n scope?: string;\n type?: MemoryType;\n}\n\nexport interface SaveMemoryRequest {\n memory: Omit<Memory, \"id\" | \"createdAt\" | \"updatedAt\">;\n}\n\nexport interface UpdateMemoryRequest {\n id: string;\n patch: Partial<Pick<Memory, \"name\" | \"description\" | \"type\" | \"content\">>;\n}\n\nexport interface RemoveMemoryRequest {\n id: string;\n}\n\nexport interface ListMemoryRequest {\n type?: MemoryType;\n scope?: string;\n}\n\nexport interface ExtractMemoryRequest {\n messages: Message[];\n}\n\n// =============================================================================\n// MEMORY PROVIDER\n// =============================================================================\n\n/**\n * MemoryProvider — pluggable backend for memory storage and retrieval.\n *\n * All methods follow (ctx, req, options?) => resp.\n *\n * Lives in RuntimeProviders.memory (same pattern as LLM, DB, storage).\n * The runtime wires it into hooks (onSearchMemory, onExtractMemory).\n */\nexport interface MemoryProvider {\n search(ctx: Context, req: SearchMemoryRequest, options?: SearchMemoryOptions): Promise<Memory[]>;\n save(ctx: Context, req: SaveMemoryRequest): Promise<Memory>;\n update(ctx: Context, req: UpdateMemoryRequest): Promise<Memory>;\n remove(ctx: Context, req: RemoveMemoryRequest): Promise<void>;\n list(ctx: Context, req?: ListMemoryRequest): Promise<Memory[]>;\n extract?(ctx: Context, req: ExtractMemoryRequest): Promise<void>;\n}\n","import { Provider } from \"../core/provider.types\";\nimport type { CacheTokens } from \"./usage.types\";\n\n/** Token limits for a model */\nexport interface ModelMaxTokens {\n /** Context window size — total input capacity in tokens */\n input: number;\n /** Max output tokens per response */\n output: number;\n}\n\n/** Cost configuration for credit-based billing and estimation.\n * All token prices are USD per 1M tokens. Each model is the source of truth\n * for its own rates — there is no separate pricing table. */\nexport interface ModelCost {\n /** Credit multiplier. 1 = baseline (cheapest), 0 = free (embeddings, dev models). */\n multiplier: number;\n /** Cost per 1M input tokens in USD (LLM models) */\n inputTokens?: number;\n /** Cost per 1M output tokens in USD (LLM models) */\n outputTokens?: number;\n /** USD-per-1M rates for prompt-cache reads & writes. Same shape as usage-side `CacheTokens`. */\n cacheTokens?: CacheTokens;\n /** Cost per request/generation in USD (music generation, image, etc.) */\n perRequest?: number;\n /** Cost per 1K characters in USD (TTS models) */\n perCharacter?: number;\n /** Cost per minute of audio in USD (transcription models) */\n perMinute?: number;\n}\n\nexport interface Model {\n id: string;\n name: string;\n options?: Record<string, unknown>;\n provider: string;\n /** Token limits for this model (context window + max output) */\n maxTokens?: ModelMaxTokens;\n /** Cost configuration for billing and estimation */\n cost: ModelCost;\n}\n\nexport interface ModelOptions {\n temperature?: number;\n maxTokens?: number;\n topP?: number;\n}\n\n// Find Models\nexport interface SearchModelsRequest {\n provider?: string;\n id?: string;\n}\n\nexport interface SearchModelsResponse {\n models: Model[];\n}\n\nexport interface GetModelRequest {\n id: string;\n}\n\nexport interface GetModelResponse {\n model: Model | null;\n}\n\n// Get Default Model\nexport interface GetDefaultModelRequest {\n provider: string;\n}\n\nexport interface GetDefaultModelResponse {\n modelId: string;\n}\n\n// Resolve Provider\nexport interface ResolveProviderRequest {\n provider?: string;\n fallback?: string;\n}\n\nexport interface ResolveProviderResponse {\n provider: string;\n}\n\nexport interface PartialModel\n extends Pick<Model, \"id\" | \"options\" | \"provider\"> {}\n\n// Resolve Model\nexport interface ResolveModelRequest {\n provider?: string;\n model?: string;\n available?: PartialModel[];\n default?: PartialModel;\n}\n\nexport interface ResolveModelResponse {\n model: PartialModel;\n}\n\n// Merge Options\nexport interface MergeOptionsRequest {\n requestOptions?: ModelOptions;\n modelOptions?: ModelOptions;\n}\n\nexport interface MergeOptionsResponse {\n options?: ModelOptions;\n}\n\n/**\n * Model Provider interface\n * Handles model storage and retrieval operations only\n * Utilities (resolve, merge) are in ModelClient\n */\nexport interface ModelProvider extends Provider {\n /**\n * Find models by optional filters\n */\n search(req: SearchModelsRequest): Promise<SearchModelsResponse>;\n\n /**\n * Find a single model by ID\n */\n get(req: GetModelRequest): Promise<GetModelResponse>;\n\n /**\n * Get the default model for a provider\n */\n getDefault(req: GetDefaultModelRequest): Promise<GetDefaultModelResponse>;\n}\n","import { Message } from \"./llm.types\";\nimport { Model, PartialModel } from \"./model.types\";\nimport { Provider } from \"../core/provider.types\";\nimport { Schema } from \"../core/schema.types\";\nimport { Tool } from \"./tool.types\";\n\n// ============================================================================\n// Tools Context & Dynamic Tools\n// ============================================================================\n\n/**\n * Context passed to tools function for dynamic tool resolution\n */\nexport interface ToolsContext {\n /** Current workflow state (goals, projects, tasks, etc.) */\n state: Record<string, unknown>;\n /** Chat history */\n chatHistory: Message[];\n /** User and chat identifiers */\n userId?: string;\n chatId?: string;\n}\n\n/**\n * Tools can be:\n * - Static array: Tool[]\n * - Dynamic function: (context: ToolsContext) => Tool[] | Promise<Tool[]>\n */\nexport type PromptTools =\n | Tool[]\n | ((context: ToolsContext) => Tool[] | Promise<Tool[]>);\n\n// ============================================================================\n// Prompt\n// ============================================================================\n\nexport interface Prompt {\n id: string;\n name: string;\n description: string;\n version?: string;\n content?: string;\n messages?: Message[];\n format?: PromptFormat;\n /** Input variable schema for template rendering */\n input?: Schema;\n /** Expected output structure schema (for structured outputs) */\n output?: Schema;\n options?: PromptOptions;\n /** Tools available for this prompt - static array OR dynamic function */\n tools?: PromptTools;\n}\n\nexport interface PromptOptions {\n models?: PartialModel[];\n}\n\nexport type PromptFormat = \"mustache\" | \"poml\" | string;\n\nexport type PromptProviderType =\n | \"in-memory\"\n | \"file-system\"\n | \"database\"\n | \"http\"\n | \"mcp\"\n | string;\n\nexport interface RenderPromptRequest {\n prompt: Prompt;\n args: Record<string, unknown>;\n}\n\nexport interface RenderPromptResponse {\n messages: Array<Message>;\n output?: Schema;\n metadata?: {\n promptId: string;\n promptName: string;\n version: string;\n provider: string;\n };\n}\n\nexport interface GetPromptRequest {\n promptId: string;\n version?: string;\n}\n\nexport interface GetPromptsRequest {\n query?: string;\n version?: string;\n}\n\nexport interface GetPromptsResponse {\n prompts: Prompt[];\n}\n\nexport interface GetPromptResponse {\n prompt: Prompt;\n}\n\nexport interface PromptRequest {\n promptId: string;\n version?: string;\n variables?: Record<string, unknown>;\n}\n\nexport interface PromptResponse {\n /** Prompt without messages, content, and format */\n prompt: Exclude<Prompt, \"messages\" | \"content\" | \"format\">;\n /** Rendered messages from the prompt */\n messages: Message[];\n}\n\nexport interface ValidatePromptRequest {\n prompt: Prompt;\n args: Record<string, unknown>;\n}\n\nexport interface ValidatePromptResponse {\n valid: boolean;\n message?: string;\n}\n\nexport interface PromptProvider extends Provider {\n type: PromptProviderType;\n getPrompt(request: GetPromptRequest): Promise<GetPromptResponse>;\n getPrompts(request: GetPromptsRequest): Promise<GetPromptsResponse>;\n}\n\nexport interface InMemoryPromptProvider extends PromptProvider {\n type: \"in-memory\";\n}\n\nexport interface FileSystemPromptProvider extends PromptProvider {\n type: \"file-system\";\n paths: string[];\n}\n\nexport type DatabaseQuery = string | object;\n\nexport interface DatabasePromptProvider extends PromptProvider {\n type: \"database\";\n query: DatabaseQuery;\n}\n\nexport interface HttpPromptProvider extends PromptProvider {\n type: \"http\";\n endpoints: {\n url: string;\n method: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n body?: string;\n }[];\n}\n\nexport interface PromptRenderer extends Provider {\n render(request: RenderPromptRequest): Promise<RenderPromptResponse>;\n validate(request: ValidatePromptRequest): Promise<ValidatePromptResponse>;\n}\n\n// ============================================================================\n// Prompts Resolvers\n// ============================================================================\n\nexport interface ResolvePromptProviderRequest {\n providerName?: string;\n providers: PromptProvider[];\n}\n\nexport interface ResolvePromptProviderResponse {\n provider: PromptProvider;\n}\n\nexport interface PromptProviderResolver extends Provider {\n resolve(request: ResolvePromptProviderRequest): Promise<ResolvePromptProviderResponse>;\n}\n\nexport interface ResolvePromptRendererRequest {\n rendererName?: string;\n format?: PromptFormat;\n renderers: PromptRenderer[];\n defaultFormat?: PromptFormat;\n}\n\nexport interface ResolvePromptRendererResponse {\n renderer: PromptRenderer;\n}\n\nexport interface PromptRendererResolver extends Provider {\n resolve(request: ResolvePromptRendererRequest): Promise<ResolvePromptRendererResponse>;\n}\n","/**\n * Reference Types\n * Types for the reference system - attaching contextual references to chat messages\n */\n\nimport type { Context } from \"../core/context.types\";\n\n// =============================================================================\n// Base Types\n// =============================================================================\n\n/** Discriminator for reference type narrowing */\nexport type ReferenceType =\n | \"entity\" // Generic entity (any app entity type)\n | \"date\" // Specific date/time\n | \"dateRange\" // Date range selection\n | \"file\" // File reference\n | \"url\" // Web URL\n | \"text\" // Raw text/selection\n | \"app\" // Installed app (@mention to delegate)\n | \"skill\" // App skill or MCP prompt (used at app level)\n | \"mcp-resource\"; // MCP server resource\n\n/** Base reference interface */\nexport interface BaseReference {\n /** Unique ID (generated) */\n id: string;\n /** Reference type discriminator */\n type: ReferenceType;\n /** UI tag label */\n displayName: string;\n /** ISO timestamp */\n createdAt: string;\n}\n\n// =============================================================================\n// Concrete Reference Types\n// =============================================================================\n\n/**\n * Generic entity reference — works for any app entity type.\n * Apps use this for all domain-specific entities (events, tasks, goals, etc.)\n */\nexport interface EntityReference extends BaseReference {\n type: \"entity\";\n /** Entity type name (e.g. \"goals\", \"tasks\", \"events\") */\n entityType: string;\n /** Entity ID */\n entityId: string;\n /** Optional entity data snapshot */\n data?: Record<string, unknown>;\n}\n\nexport interface DateReference extends BaseReference {\n type: \"date\";\n /** ISO date (YYYY-MM-DD) */\n date: string;\n /** Optional time (HH:mm) */\n time?: string;\n}\n\nexport interface DateRangeReference extends BaseReference {\n type: \"dateRange\";\n startDate: string;\n endDate: string;\n startTime?: string;\n endTime?: string;\n}\n\nexport interface FileReference extends BaseReference {\n type: \"file\";\n path: string;\n mimeType?: string;\n}\n\nexport interface UrlReference extends BaseReference {\n type: \"url\";\n url: string;\n}\n\nexport interface TextReference extends BaseReference {\n type: \"text\";\n content: string;\n source?: string;\n}\n\n/**\n * App reference — @mention an installed app to delegate a task.\n * Triggers useApp child workflow in the platform orchestrator.\n */\nexport interface AppReference extends BaseReference {\n type: \"app\";\n appId: string;\n}\n\n/**\n * Skill reference — unified for app skills and MCP prompts.\n * Used at app level (inside app orchestrators), not at platform level.\n */\nexport interface SkillReference extends BaseReference {\n type: \"skill\";\n /** Whether this skill comes from an app or an MCP server */\n source: \"app\" | \"mcp\";\n /** App skill fields (when source: \"app\") */\n appId?: string;\n skillId?: string;\n /** MCP prompt fields (when source: \"mcp\") */\n serverName?: string;\n promptName?: string;\n}\n\n/**\n * MCP resource reference — content from an MCP server resource.\n * Fetched and injected as context when referenced.\n */\nexport interface McpResourceReference extends BaseReference {\n type: \"mcp-resource\";\n serverName: string;\n uri: string;\n}\n\n/** Union of all reference types */\nexport type Reference =\n | EntityReference\n | DateReference\n | DateRangeReference\n | FileReference\n | UrlReference\n | TextReference\n | AppReference\n | SkillReference\n | McpResourceReference;\n\n// =============================================================================\n// Resolve Context and Request/Response Types\n// =============================================================================\n\n/** Base resolve request */\nexport interface ResolveReferenceRequest<T extends Reference = Reference> {\n reference: T;\n}\n\n/**\n * Base resolve response\n * Uses existing entity types (Event, Task, Goal, etc.) - not new data types\n */\nexport interface ResolveReferenceResponse<TData = unknown> {\n resolved: boolean;\n /** The actual entity data or null if not found */\n data: TData | null;\n /** Error message (passed to LLM for awareness) */\n error?: string;\n}\n\n// =============================================================================\n// Resolved Data Types (for platform-level, non-entity references)\n// =============================================================================\n\n/** Resolved date data */\nexport interface ResolvedDateData {\n date: string;\n time?: string;\n formatted: string;\n}\n\n/** Resolved date range data */\nexport interface ResolvedDateRangeData {\n startDate: string;\n endDate: string;\n formatted: string;\n}\n\n/** Resolved text data */\nexport interface ResolvedTextData {\n content: string;\n source?: string;\n}\n\n// =============================================================================\n// Type-specific Request/Response pairs\n// =============================================================================\n\nexport interface ResolveDateRequest extends ResolveReferenceRequest<DateReference> {}\nexport interface ResolveDateResponse extends ResolveReferenceResponse<ResolvedDateData> {}\n\nexport interface ResolveDateRangeRequest extends ResolveReferenceRequest<DateRangeReference> {}\nexport interface ResolveDateRangeResponse extends ResolveReferenceResponse<ResolvedDateRangeData> {}\n\nexport interface ResolveTextRequest extends ResolveReferenceRequest<TextReference> {}\nexport interface ResolveTextResponse extends ResolveReferenceResponse<ResolvedTextData> {}\n\n// =============================================================================\n// Resolved Reference Wrapper (for collection results)\n// =============================================================================\n\n/** Resolved reference wrapper with original reference and resolved data */\nexport interface ResolvedReference<\n T extends Reference = Reference,\n TData = unknown,\n> {\n reference: T;\n resolved: boolean;\n data: TData | null;\n error?: string;\n}\n\n// =============================================================================\n// Reference Factory Types\n// =============================================================================\n\n/** Create input — type-specific fields + optional displayName */\nexport type CreateRefInput<T extends Reference> = Omit<\n T,\n \"id\" | \"type\" | \"createdAt\" | \"displayName\"\n> & {\n displayName?: string;\n};\n\n/** Config input for ref() factory */\nexport interface RefConfig<T extends Reference = Reference> {\n type: T[\"type\"];\n label: string;\n icon: string;\n color: string;\n /** Optional LLM formatter — if omitted, uses generic JSON fallback */\n format?: (displayName: string, data: unknown) => string;\n /** Derive displayName from input when not explicitly provided */\n displayName?: (input: CreateRefInput<T>) => string;\n}\n\n/** Output of ref() factory — metadata + create method */\nexport interface Ref<T extends Reference = Reference> {\n type: T[\"type\"];\n label: string;\n icon: string;\n color: string;\n /** Optional LLM formatter */\n format?: (displayName: string, data: unknown) => string;\n /** Create a reference instance */\n create: (input: CreateRefInput<T>) => T;\n}\n\n// =============================================================================\n// Resolver Types\n// =============================================================================\n\n/**\n * Resolver function signature — follows canonical (ctx, ref, options) pattern.\n * Uses Context — app-facing.\n */\nexport type ReferenceResolver<\n T extends Reference = Reference,\n TData = unknown,\n TCtx extends Context = Context,\n> = (\n ctx: TCtx,\n ref: T,\n options: Record<string, unknown>,\n) => Promise<ResolveReferenceResponse<TData>>;\n\n/** Configuration for the resolver() factory */\nexport interface ResolverConfig<\n T extends Reference = Reference,\n TData = unknown,\n TCtx extends Context = Context,\n> {\n /** Reference type discriminator (e.g. \"entity\", \"date\") */\n type: ReferenceType;\n /** For \"entity\" type — matches EntityReference.entityType (e.g. \"goals\", \"tasks\") */\n entityType?: string;\n /** Resolve function: (ctx, ref, options) => response */\n resolve: ReferenceResolver<T, TData, TCtx>;\n /** Optional formatter for LLM context — if omitted, uses generic JSON fallback */\n format?: (displayName: string, data: TData) => string;\n}\n\n/** Resolver definition — output of resolver() and entityResolver() factories */\nexport interface Resolver<T extends Reference = Reference, TData = unknown, TCtx extends Context = Context> {\n type: ReferenceType;\n /** For \"entity\" type — matches EntityReference.entityType */\n entityType?: string;\n resolve: ReferenceResolver<T, TData, TCtx>;\n /** Optional formatter for LLM context */\n format?: (displayName: string, data: unknown) => string;\n}\n\n/** Resolver collection with built-in utilities */\nexport interface ResolverCollection<TCtx extends Context = Context> {\n /** List all registered resolvers */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n list: () => Resolver<any, any, TCtx>[];\n /** Get a specific resolver by type and optional entityType */\n\n get: (\n type: ReferenceType,\n entityType?: string,\n ) => Resolver<any, any, TCtx> | undefined;\n /** Resolve a single reference */\n resolve: <T extends Reference>(\n ctx: TCtx,\n ref: T,\n options: Record<string, unknown>,\n ) => Promise<ResolvedReference<T>>;\n /** Resolve multiple references in parallel */\n resolveAll: (\n ctx: TCtx,\n refs: Reference[],\n options: Record<string, unknown>,\n ) => Promise<ResolvedReference[]>;\n /** Format resolved references for LLM context */\n format: (resolved: ResolvedReference[]) => string;\n /** Bind options, returning a collection where resolve/resolveAll only need (ctx, ref) */\n bind: (options: Record<string, unknown>) => BoundResolverCollection<TCtx>;\n}\n\n/** Resolver collection with options pre-bound (for Temporal activities, etc.) */\nexport interface BoundResolverCollection<TCtx extends Context = Context> {\n /** List all registered resolvers */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n list: () => Resolver<any, any, TCtx>[];\n /** Get a specific resolver by type and optional entityType */\n\n get: (\n type: ReferenceType,\n entityType?: string,\n ) => Resolver<any, any, TCtx> | undefined;\n /** Resolve a single reference (options pre-bound) */\n resolve: <T extends Reference>(\n ctx: TCtx,\n ref: T,\n ) => Promise<ResolvedReference<T>>;\n /** Resolve multiple references in parallel (options pre-bound) */\n resolveAll: (\n ctx: TCtx,\n refs: Reference[],\n ) => Promise<ResolvedReference[]>;\n /** Format resolved references for LLM context */\n format: (resolved: ResolvedReference[]) => string;\n}\n","/**\n * Skill Types\n *\n * Skills are procedural knowledge - prompts and methodology that transform\n * general-purpose agents into specialists. Unlike tools (which execute actions),\n * skills provide \"expertise\" (how to use tools effectively).\n *\n * Skills run as child orchestrator workflows:\n * 1. Orchestrator decides which skill to use via useSkill tool\n * 2. Provides the task with full context\n * 3. Skill executes with its specialized prompt and tools\n * 4. Returns result to orchestrator\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Message } from \"./llm.types\";\nimport type { Prompt } from \"./prompt.types\";\nimport type { Tool, ToolHookOptions } from \"./tool.types\";\nimport type { Ui } from \"./ui.types\";\n\n// =============================================================================\n// Skill Hook Types (mirrors tool hooks pattern)\n// =============================================================================\n\n/**\n * Request passed to skill before hook.\n */\nexport interface BeforeSkillRequest {\n skillId: string;\n task: string;\n /** The user's original request (from orchestrator) */\n userRequest?: string;\n}\n\n/**\n * Response from skill before hook.\n */\nexport type BeforeSkillResponse =\n | {\n action: \"allow\";\n /** Modified skill properties (prompt, tools, etc.) */\n skill?: Partial<Skill>;\n /** Additional messages to prepend to skill conversation */\n messages?: Message[];\n }\n | {\n action: \"deny\";\n reason: string;\n };\n\n/**\n * Hook called before skill execution.\n * - Can modify the skill (prompt, tools, maxIterations)\n * - Can inject context messages\n * - Can reject execution\n * - Can call options.askUser() for human-in-the-loop\n */\nexport type BeforeSkillHook<TState = unknown> = (\n ctx: Context,\n req: BeforeSkillRequest & { state: TState },\n options: ToolHookOptions\n) => Promise<BeforeSkillResponse>;\n\n/**\n * Request passed to skill after hook.\n */\nexport interface AfterSkillRequest {\n skillId: string;\n task: string;\n /** Skill's final message/response */\n message: string;\n /** Whether skill completed successfully */\n success: boolean;\n /** State returned by skill (if any) */\n skillState?: unknown;\n /** Metadata from skill execution */\n metadata?: {\n iterations: number;\n inputTokens?: number;\n outputTokens?: number;\n };\n}\n\n/**\n * Response from skill after hook.\n */\nexport interface AfterSkillResponse<TState = unknown> {\n /** Context for LLM (lightweight summary) */\n context: unknown;\n /** State update (merged into orchestrator state) */\n state?: Partial<TState>;\n /** Optional UI component */\n ui?: Ui;\n}\n\n/**\n * Hook called after skill execution.\n * - Structures output into context for LLM\n * - Updates orchestrator state\n * - Creates tool UIs\n * - Can call options.askUser() for human-in-the-loop\n */\nexport type AfterSkillHook<TState = unknown> = (\n ctx: Context,\n req: AfterSkillRequest & { state: TState },\n options: ToolHookOptions\n) => Promise<AfterSkillResponse<TState>>;\n\n/**\n * Skill hooks container.\n * Mirrors ToolHooks for consistency.\n */\nexport interface SkillHooks<TState = unknown> {\n before?: BeforeSkillHook<TState>;\n after?: AfterSkillHook<TState>;\n}\n\n// =============================================================================\n// Skill Definition\n// =============================================================================\n\n/**\n * Skill - procedural knowledge for specialized tasks\n *\n * Flat structure (no nested metadata) following *.models.ts pattern:\n * - Export individual skills as constants\n * - Export collection object with list() and get() methods\n */\nexport interface Skill {\n /** Unique identifier (e.g., \"code-review\", \"testing\") */\n id: string;\n\n /** Human-readable name (e.g., \"Code Review\", \"Testing\") */\n name: string;\n\n /** What this skill does - shown in useSkill tool description */\n description: string;\n\n /** Prompt providing skill-specific instructions */\n prompt: Prompt;\n\n /** Tools available to this skill */\n tools: Tool[];\n\n /** Maximum iterations for skill execution (default: 5) */\n maxIterations?: number;\n\n /** Version string (optional) */\n version?: string;\n\n /** Author/owner (optional) */\n author?: string;\n\n /** Tags for categorization (optional) */\n tags?: string[];\n\n /**\n * Optional hooks for state transformation.\n * - before: Transform orchestrator state → skill context\n * - after: Transform skill output → orchestrator state update\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n hooks?: SkillHooks<any>;\n}\n\n// =============================================================================\n// useSkill Tool Types\n// =============================================================================\n\n/**\n * Input for the useSkill tool - what orchestrator provides\n */\nexport interface UseSkillInput {\n /** ID of the skill to use */\n skillId: string;\n\n /** Task description for the skill */\n task: string;\n\n /** Additional context data for the skill */\n context?: unknown;\n}\n\n/**\n * Output from skill execution\n */\nexport interface UseSkillOutput {\n /** Response message from the skill */\n message: string;\n\n /** Whether the skill completed successfully */\n success: boolean;\n\n /** Updated state from skill execution (optional) */\n state?: unknown;\n\n /** UI component generated by the skill (optional) */\n ui?: Ui;\n}\n\n// =============================================================================\n// Skill Collection Type\n// =============================================================================\n\n/**\n * Skills collection - following *.models.ts pattern\n *\n * Usage:\n * ```typescript\n * export const plannerSkills = {\n * codeReviewSkill,\n * testingSkill,\n *\n * list: (): Skill[] => [codeReviewSkill, testingSkill],\n *\n * get: (id: string): Skill | undefined =>\n * plannerSkills.list().find((s) => s.id === id),\n * };\n * ```\n */\nexport interface Skills {\n /** Get all skills as array */\n list: () => Skill[];\n\n /** Get skill by ID */\n get: (id: string) => Skill | undefined;\n\n /** Individual skills accessible by name */\n [key: string]: Skill | (() => Skill[]) | ((id: string) => Skill | undefined);\n}\n\n// =============================================================================\n// Skill Factory Type (for the enhanced skill() function)\n// =============================================================================\n\n/**\n * Skill factory with import and collection methods.\n * The skill() function is both a creator and a namespace.\n */\nexport interface SkillFactory {\n /** Create a skill inline */\n (config: {\n id: string;\n name: string;\n description: string;\n prompt: Prompt;\n tools: Tool[];\n maxIterations?: number;\n version?: string;\n author?: string;\n tags?: string[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n hooks?: SkillHooks<any>;\n }): Skill;\n\n /** Import from a convention-based directory */\n fromDir: (dirPath: string) => Promise<Skill>;\n\n /** Import from a config file path */\n fromConfig: (configPath: string) => Promise<Skill>;\n\n /** Import from a URL (future marketplace) */\n fromUrl: (url: string) => Promise<Skill>;\n\n /** Add a skill to the registry */\n add: (s: Skill) => Skill;\n\n /** Load from directory and add to registry */\n load: (dirPath: string) => Promise<Skill>;\n\n /** Get all registered skills */\n list: () => Skill[];\n\n /** Get a registered skill by ID */\n get: (id: string) => Skill | undefined;\n}\n","import type { Context } from \"../core/context.types\";\nimport type { TranslateFn } from \"../core/translation.types\";\nimport { Schema } from \"../core/schema.types\";\nimport type { AgentMode } from \"./agent.types\";\nimport type { Ui } from \"./ui.types\";\nimport type { Usage } from \"./usage.types\";\n\n// =============================================================================\n// Tool Permissions (Declarative Access Control)\n// =============================================================================\n\n/**\n * Declarative permissions for a tool.\n * Combines RBAC (roles/tiers) with risk classification.\n */\nexport interface ToolPermissions {\n /** Required roles (checked vs ctx.access.role) */\n roles?: string[];\n /** Required tiers (checked vs ctx.access.tier) */\n tiers?: string[];\n /**\n * Risk level — drives permission mode behavior:\n * - \"safe\": auto-allow (read, search, list)\n * - \"moderate\": allow by default, log (create, update)\n * - \"dangerous\": ask user first (delete, send, execute)\n */\n risk?: \"safe\" | \"moderate\" | \"dangerous\";\n /**\n * When to ask for user approval (if applicable based on risk + mode).\n * - \"before\": ask BEFORE execution (default)\n * - \"after\": execute first, then ask for confirmation\n * Only applies when the harness auto-asks (no custom hook defined).\n */\n ask?: \"before\" | \"after\";\n /** Can run in parallel with other tools (default: true) */\n concurrent?: boolean;\n /** Resource scopes (future: OAuth/MCP) */\n scopes?: string[];\n}\n\n// =============================================================================\n// Tool Metadata (all display, permissions, and provider config)\n// =============================================================================\n\n/** Context provided to metadata describe function */\nexport interface ToolMetadataContext {\n toolName: string;\n toolCallId: string;\n}\n\n/** Request passed to the describe function */\nexport interface DescribeToolRequest {\n status: ToolCallStatus;\n input: Record<string, unknown>;\n output?: unknown;\n error?: string;\n durationMs?: number;\n}\n\n/** Options passed as 3rd argument to metadata.describe() */\nexport interface DescribeToolOptions {\n t: TranslateFn;\n}\n\n/**\n * Tool metadata — all display, permissions, UI, and provider configuration.\n */\nexport interface ToolMetadata {\n /** Human-readable tool name for UI display (e.g., \"Create Recipe\") */\n label?: string;\n\n /** Generate phase description for the tool message UI */\n describe?: (\n ctx: ToolMetadataContext,\n req: DescribeToolRequest,\n options?: DescribeToolOptions,\n ) => string | undefined;\n\n /**\n * When true, tool calls are not displayed in the conversation UI.\n * The tool still runs normally — it's just invisible to the user.\n */\n hidden?: boolean;\n\n /**\n * Native provider that handles lifecycle.\n * When set, the tool is handled by the named provider's internal loop\n * rather than by callTool().\n */\n provider?: string;\n\n /** Declarative permissions — RBAC + risk classification */\n permissions?: ToolPermissions;\n\n /** UI component config — MCP iframe or chat component */\n ui?: Ui;\n\n /** Max tool output size in characters before truncation (default: 50000) */\n maxOutputSize?: number;\n}\n\n// =============================================================================\n// Tool Definition\n// =============================================================================\n\n/**\n * Tool definition — serializable schema + optional execution fields.\n *\n * Core fields (name, description, input, output) are always serializable.\n * Execution fields (call, hooks, metadata, build) are added by the SDK\n * `tool()` factory and used by the agent runner.\n */\nexport interface Tool {\n name: string;\n description: string;\n input: Schema;\n output: Schema;\n\n // === Execution ===\n\n /** Function to execute the tool */\n call?: CallTool;\n\n /**\n * Schema-only builder — called by buildTools() at the start of each iteration\n * to produce a tool with state-dependent schemas (e.g., dynamic enum values).\n */\n build?: (ctx: Context, req: { tool: Tool; state: unknown }) => Tool;\n\n // === Configuration ===\n\n /** All display, permissions, UI, and provider configuration */\n metadata?: ToolMetadata;\n\n // === Lifecycle Hooks ===\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n hooks?: ToolHooks<any>;\n}\n\n/**\n * Tool handler function.\n *\n * Signature: (ctx, input, options?) => output\n * ctx from runner, options pre-bound by buildTools.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type CallTool = (...args: any[]) => Promise<any>;\n\n// =============================================================================\n// Ask User (human-in-the-loop)\n// =============================================================================\n\n/** User's response action */\nexport type UserInputAction = \"allow\" | \"deny\" | \"modify\";\n\nexport interface UserInputResponse {\n action: UserInputAction;\n data?: Record<string, unknown>;\n feedback?: string;\n /** Agent mode the user picked alongside the response. Used by ExitPlanMode\n * approval to flip the agent's mode for subsequent turns — the hub signals\n * the workflow's `setMode` so `customState.lastMode` updates before the\n * next dispatch. */\n mode?: AgentMode;\n}\n\n/** User input with correlation ID */\nexport interface UserInput extends UserInputResponse {\n id: string;\n}\n\n/**\n * Request for user input — raw data preview, rich UI component, or reason-only.\n */\nexport type UserInputRequest =\n | { reason?: string; data: unknown; ui?: never }\n | { reason?: string; data?: never; ui: Ui };\n\n/**\n * Options passed to tool hooks (third argument)\n */\nexport interface ToolHookOptions {\n /** Request user input (human-in-the-loop). Pauses until user responds. */\n askUser: (req?: UserInputRequest) => Promise<UserInputResponse | null>;\n /** Current agent mode — hooks can use this to decide behavior per mode. */\n mode: string;\n}\n\n// =============================================================================\n// Tool Hook Types\n// =============================================================================\n\n/**\n * Hook called before tool execution.\n *\n * Return values:\n * - `{ action: \"allow\" }` — proceed (optionally with modified input)\n * - `{ action: \"deny\", reason }` — reject execution\n */\nexport type BeforeToolHook<TState = unknown> = (\n ctx: Context,\n req: {\n toolName: string;\n input: unknown;\n toolCallId: string;\n state: TState;\n },\n options: ToolHookOptions,\n) => Promise<{ action: \"allow\"; input?: unknown } | { action: \"deny\"; reason: string }>;\n\n/** Unified tool call status */\nexport type ToolCallStatus = \"running\" | \"completed\" | \"modify\" | \"denied\" | \"error\";\n\n/**\n * Hook called after tool execution.\n */\nexport type AfterToolHook<TState = unknown> = (\n ctx: Context,\n req: {\n toolName: string;\n input: unknown;\n output: unknown;\n toolCallId: string;\n state: TState;\n ui?: Ui;\n },\n options: ToolHookOptions,\n) => Promise<{\n /** Lightweight context for LLM */\n context: unknown;\n /** State update (partial merge) */\n state?: Partial<TState>;\n /** UI override — if omitted and metadata.ui exists, auto-generated from tool output */\n ui?: Ui;\n /** Tool call result status */\n status?: ToolCallStatus;\n /** Human-readable message */\n message?: string;\n /** Pruning instructions */\n prune?: {\n removeTools?: string[];\n keepRecent?: number;\n };\n /** Resource usage */\n usage?: Usage;\n}>;\n\n/** Tool hooks container */\nexport interface ToolHooks<TState = unknown> {\n before?: BeforeToolHook<TState>;\n after?: AfterToolHook<TState>;\n}\n\n// =============================================================================\n// Hook Identity Functions (type narrowing without generics on tool())\n// =============================================================================\n\nexport function before<TState>(fn: BeforeToolHook<TState>): BeforeToolHook<TState> {\n return fn;\n}\n\nexport function after<TState>(fn: AfterToolHook<TState>): AfterToolHook<TState> {\n return fn;\n}\n\n// =============================================================================\n// Tool Call Types\n// =============================================================================\n\nexport interface CallToolRequest {\n tool: Tool;\n args: unknown;\n}\n\nexport interface CallToolResponse {\n output: string;\n}\n\nexport interface ToolCallError {\n tool: string;\n error: string;\n args?: string;\n}\n\nexport interface ToolCall {\n id: string;\n name: string;\n args: string;\n status: \"pending\" | \"completed\" | \"failed\";\n output?: string;\n error?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ResolveToolRequest {\n tool: string | Tool;\n available: Tool[];\n}\n\nexport interface ResolveToolResponse {\n tool: Tool;\n}\n\n// Ui types moved to ./message.types.ts — they describe the unified\n// rich-rendering layer for any chat message (tool or otherwise) and live\n// alongside the message types that own them.\n","/**\n * Ui Types\n *\n * Unified rich-rendering layer for chat. Owned here as a leaf module so\n * messages, tools, skills, and any other surface can refer to it without\n * crossing concern boundaries.\n *\n * - `Ui` — the discriminated union stored at `metadata.ui` (or `ToolMetadata.ui`).\n * - `UiComponent` / `UiResource` — the two variants (registered React\n * component vs MCP iframe resource).\n * - `UiComponentConfig` / `UiComponentProps` — the registry contract used by\n * the `ui()` factory and the chat router.\n * - `UiComponentMetadata` / `UiComponentAction` — internal envelopes used by\n * the router for navigation + action dispatch.\n * - `McpUiData` — payload shape for MCP iframe renderings.\n *\n * Tools register UI via `XTool.tsx`; custom message renderers register via\n * `XMessage.tsx`. Both produce a `UiComponentConfig` and live in the same\n * registry array passed to the chat — the chat code never branches on\n * \"is this a tool\".\n */\n\nimport type { ComponentType, ElementType } from \"react\";\n\nimport type { SemanticColor } from \"../core/color.types\";\nimport type { EntityReference } from \"./reference.types\";\n\n// =============================================================================\n// Ui — discriminated union\n// =============================================================================\n\n/**\n * Ui — discriminated union stored at `metadata.ui` (chat messages) and at\n * `ToolMetadata.ui` (tool definitions). Picks one of two rendering paths:\n *\n * - **Component** variant: a registered renderer (see `UiComponentConfig`).\n * - **Resource** variant: an MCP iframe loaded from a `ui://` resource.\n */\nexport type Ui = UiComponent | UiResource;\n\nexport interface UiComponent {\n /** MCP-style URI: `ui://appId/componentType` (e.g. `ui://chef/recipe`) */\n uri: string;\n /** Display title for the component card */\n title: string;\n /** Data payload — auto-populated from tool output when omitted in after hook */\n data?: unknown;\n /** Preferred height in pixels */\n height?: number;\n}\n\nexport interface UiResource {\n /** URI of the MCP UI resource (e.g. `ui://server/dashboard`) */\n resourceUri: string;\n /** Title override for the UI card */\n title?: string;\n /** Preferred iframe height in pixels */\n height?: number;\n /** Extra data passed to the rendering component (e.g. html, serverName) */\n data?: unknown;\n}\n\n/** Generic URI/type identifier for a registered Ui renderer. */\nexport type UiType = string;\n\n// =============================================================================\n// Router envelopes\n// =============================================================================\n\n/**\n * Metadata passed to the router to identify which renderer to invoke and\n * what data to render. Internal — consumers usually deal with `Ui` directly.\n */\nexport interface UiComponentMetadata<TData = unknown, TStats = unknown> {\n /** URI (e.g. `ui://agent/plan`) or bare type (`plan`) */\n uri: UiType;\n /** Data payload */\n data: TData;\n /** Optional statistics (used by some renderers) */\n statistics?: TStats;\n}\n\n/** Structured action used by the router internally. */\nexport interface UiComponentAction {\n type: string;\n uri: string;\n messageId: string;\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Registry contract — `UiComponentConfig` + `UiComponentProps`\n// =============================================================================\n\n/**\n * Props passed to a registered Ui component. The router extracts `data` from\n * `UiComponentMetadata` and adds the message + lifecycle props.\n */\nexport interface UiComponentProps<TData = unknown> {\n /** Data payload */\n data: TData;\n /** URI identifier */\n uri: string;\n /** Containing message id */\n messageId: string;\n /** Whether the renderer is rendering its expanded form (e.g. side panel) */\n isExpanded?: boolean;\n /** Toggle expand/collapse — only meaningful for renderers that opt in. */\n onToggleExpand?: () => void;\n /** Callback when the user creates a reference */\n onReference?: (ref: EntityReference) => void;\n /** Action channel — renderers fire `onAction(name, payload)` */\n onAction?: (action: string, payload?: unknown) => void;\n /** Navigate to a nested Ui (drilldown) */\n onNavigate?: (metadata: UiComponentMetadata) => void;\n /** Current nested Ui being viewed */\n currentTool?: UiComponentMetadata;\n /** Whether back navigation is available */\n canGoBack?: boolean;\n /** Navigate back in history */\n onGoBack?: () => void;\n}\n\n/**\n * Configuration object returned by the `ui()` factory and passed to the chat\n * for registration. Used by both tool renderers (`XTool.tsx`) and custom\n * message renderers (`XMessage.tsx`).\n */\nexport interface UiComponentConfig<TData = unknown> {\n /** Type identifier (last segment of URI, e.g. `plan`) */\n type: string;\n /** Human-readable label */\n label?: string;\n /** React component that renders the UI */\n Component: ComponentType<UiComponentProps<TData>>;\n /** Skeleton component for loading state */\n Skeleton?: ComponentType;\n /** Icon component */\n icon?: ElementType;\n /** Semantic color for styling */\n color?: SemanticColor;\n /** When `true`, the chat renders this component directly in the timeline\n * with no preview-card chrome and no side-panel expansion. The Component\n * is responsible for its own chrome. Default `false` — the chat wraps in\n * a `<ToolPreview>` and `\"open-ui\"` opens the side panel. */\n inline?: boolean;\n /** Extract a title from data (for headers, breadcrumbs) */\n getTitle?: (data: TData) => string;\n /** Extract a description from data */\n getDescription?: (data: TData) => string | undefined;\n /** Component to render hover actions on the preview card */\n PreviewActions?: ComponentType<{ data: TData }>;\n}\n\n// =============================================================================\n// MCP iframe data\n// =============================================================================\n\n/**\n * Data shape for an `mcp` Ui type. Rendered as a sandboxed iframe via\n * `@mcp-ui/client` AppRenderer.\n */\nexport interface McpUiData {\n /** Self-contained HTML for iframe srcDoc */\n html: string;\n /** Original `ui://` URI */\n resourceUri: string;\n /** MCP server name for attribution */\n serverName?: string;\n /** Preferred iframe height in pixels */\n height?: number;\n /** Structured tool result data */\n structuredContent?: unknown;\n /** Tool name that produced this Ui */\n toolName?: string;\n /** Tool input arguments */\n toolInput?: unknown;\n}\n","/**\n * Usage Types\n *\n * Single source of truth for token and credit usage tracking.\n * Used across LLM responses, agent iterations, tool calls, workflow state,\n * task metrics, and model pricing rates.\n */\n\n/**\n * A read/write pair for prompt-caching tokens. Same shape whether the values\n * are token *counts* (usage) or USD-per-million *rates* (pricing) — context\n * makes the semantics obvious, and sharing one shape keeps everything aligned.\n */\nexport interface CacheTokens {\n /** Prompt cache hit (cheap). */\n read: number;\n /** Prompt cache write/creation (expensive). */\n write: number;\n}\n\n/** Canonical usage shape — token and credit tallies. */\nexport interface Usage {\n inputTokens?: number;\n outputTokens?: number;\n cacheTokens?: CacheTokens;\n totalTokens?: number;\n credits?: number;\n}\n\n/** Total cache tokens across both buckets. */\nexport function totalCacheTokens(c: CacheTokens | undefined | null): number {\n if (!c) return 0;\n return (c.read ?? 0) + (c.write ?? 0);\n}\n\n/** Grand total tokens (input + output + cache read + cache write). */\nexport function totalUsageTokens(u: Usage | undefined | null): number {\n if (!u) return 0;\n return (u.inputTokens ?? 0) + (u.outputTokens ?? 0) + totalCacheTokens(u.cacheTokens);\n}\n","/**\n * Transport Types\n *\n * StreamEvent — canonical event types for real-time streaming.\n * All publishers (workflows, activities, devenv) and all consumers\n * (SSE endpoint, frontend hooks) use this single type.\n *\n * TransportProvider — pluggable streaming delivery mechanism.\n * Implementations: SSE, WebSocket, HTTP stream, Temporal+Redis.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { ChatMessage } from \"./chat.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// STREAM EVENTS (single source of truth)\n// =============================================================================\n\n/**\n * All event types that flow through the streaming system.\n *\n * - \"message\" — discrete ChatMessage (text, thinking, tool, status)\n * - \"token\" — real-time text streaming (accumulated snapshot)\n * - \"thinking\" — real-time thinking streaming (accumulated snapshot)\n * - \"usage\" — token usage metrics after LLM call\n * - \"done\" — workflow/chat finished\n * - \"error\" — something broke\n *\n * All events include an optional `chatId` for per-user channel routing.\n */\nexport type StreamEvent =\n | { type: \"message\"; message: ChatMessage; chatId?: string }\n | { type: \"token\"; messageId: string; content: string; isComplete: boolean; isFinal?: boolean; chatId?: string }\n | { type: \"thinking\"; messageId: string; content: string; isComplete: boolean; chatId?: string }\n | { type: \"usage\"; inputTokens: number; outputTokens: number; totalTokens?: number; cacheTokens?: { read: number; write: number }; model?: string; chatId?: string }\n | { type: \"done\"; status?: string; chatId?: string }\n | { type: \"error\"; message: string; chatId?: string };\n\n// =============================================================================\n// TRANSPORT PROVIDER\n// =============================================================================\n\n/**\n * TransportProvider — pluggable streaming delivery for agent events.\n *\n * Server-side: `publish()` sends events to connected clients.\n * Client-side: `subscribe()` returns an async iterable of events.\n *\n * Implementations:\n * - sseTransport: Server-Sent Events (serverless compatible)\n * - wsTransport: WebSocket (instant delivery, long-lived connections)\n * - httpStreamTransport: Fetch-based streaming (edge compatible)\n * - temporalTransport: Temporal polling + Redis Pub/Sub (platform default)\n */\nexport interface TransportProvider extends Provider {\n /** Publish an event to connected clients (server-side) */\n publish(ctx: Context, req: { event: StreamEvent }): Promise<void>;\n\n /** Subscribe to events (client-side) — returns async iterable */\n subscribe(\n ctx: Context,\n req: { sessionId: string },\n ): AsyncIterable<StreamEvent>;\n\n /** Close the transport connection */\n close(ctx: Context): Promise<void>;\n}\n","/**\n * Workflow Provider Types\n *\n * WorkflowProvider enables starting, signalling, and querying\n * Temporal workflows.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// WORKFLOW PROVIDER\n// =============================================================================\n\n/**\n * WorkflowProvider — start, signal, and query Temporal workflows.\n *\n * Task queue is provided per-request via `req.taskQueue`.\n */\nexport interface WorkflowProvider extends Provider {\n /** Start a workflow and wait for its result */\n execute(\n ctx: Context,\n req: {\n /** Workflow name (must be registered on the worker) */\n workflow: string;\n /** Task queue to route to */\n taskQueue: string;\n /** Optional workflow ID (auto-generated if omitted) */\n workflowId?: string;\n /** Arguments passed to the workflow */\n args?: unknown;\n },\n ): Promise<unknown>;\n\n /** Start a workflow and return immediately */\n start(\n ctx: Context,\n req: {\n /** Workflow name (must be registered on the worker) */\n workflow: string;\n /** Task queue to route to */\n taskQueue: string;\n /** Optional workflow ID (auto-generated if omitted) */\n workflowId?: string;\n /** Arguments passed to the workflow */\n args?: unknown;\n },\n ): Promise<{ workflowId: string; runId: string }>;\n\n /** Send a signal to a running workflow */\n signal(\n ctx: Context,\n req: {\n /** Workflow ID to signal */\n workflowId: string;\n /** Signal name */\n signal: string;\n /** Signal arguments */\n args?: unknown;\n },\n ): Promise<void>;\n\n /** Query a running workflow for its current state */\n query(\n ctx: Context,\n req: {\n /** Workflow ID to query */\n workflowId: string;\n /** Query name */\n query: string;\n /** Query arguments */\n args?: unknown;\n },\n ): Promise<unknown>;\n\n /** Send an update to a running workflow and wait for the result. */\n update(\n ctx: Context,\n req: {\n /** Workflow ID to update */\n workflowId: string;\n /** Update name */\n update: string;\n /** Update arguments */\n args?: unknown;\n },\n ): Promise<unknown>;\n}\n\n// =============================================================================\n// WORKFLOW INPUT\n// =============================================================================\n\n/**\n * Base wrapper for all workflow inputs.\n * Separates identity (ctx) from business logic (req).\n *\n * @typeParam TReq - Business-logic request shape.\n * @typeParam TCtxMeta - Context metadata shape. Workflows that need typed\n * metadata (e.g. `task?: TaskContext`) pass it here so `ctx.metadata` is\n * type-safe without casts.\n */\nexport interface WorkflowInput<TReq = Record<string, unknown>, TCtxMeta = Record<string, unknown>> {\n ctx: Context<TCtxMeta>;\n req: TReq;\n}\n\n// =============================================================================\n// WORKFLOW PROGRESS PROTOCOL\n// =============================================================================\n\nexport interface WorkflowProgress {\n message?: string;\n percent?: number;\n data?: Record<string, unknown>;\n}\n\nexport type WorkflowStatus =\n | \"pending\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\";\n\n// =============================================================================\n// WORKFLOW API\n// =============================================================================\n\nexport interface StartWorkflowRequest {\n taskQueue: string;\n workflowName: string;\n args?: unknown;\n workflowIdSuffix?: string;\n}\n\nexport interface StartWorkflowResponse {\n workflowId: string;\n isNew: boolean;\n}\n\nexport type WorkflowStreamEvent =\n | {\n type: \"progress\";\n status: WorkflowStatus;\n progress: WorkflowProgress | null;\n }\n | { type: \"completed\"; result?: unknown }\n | { type: \"failed\"; error: string }\n | { type: \"error\"; message: string };\n","/**\n * Placeholder — session-era re-exports have been removed. Import `Chat`\n * directly from `@jarvis/types/data` and `AgentProviderId` from\n * `@jarvis/types/agents`.\n */\n\nexport {};\n","/**\n * Agent Provider Types — three-tier taxonomy.\n *\n * `ChatProvider` — messaging surface (web / cli / mobile / whatsapp …)\n * `AgentProvider` — agentic-chat backend (anthropic / openai / jarvis …)\n * `CodeAgentProvider` — AgentProvider with code capabilities (claude-code / cursor / codex / jarvis)\n *\n * All method signatures: `(ctx, req, options?) => response`. No `runner`\n * field — each provider implements `run`/`abort` internally (harness,\n * callRpc, vendor HTTP).\n *\n * Header/metadata projection types (for list screens, detail views) are a\n * frontend concern and live in the UI package — not here. Providers return\n * DB-shaped `Chat` / `ChatMessage` rows; the UI projects them.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Chat } from \"../data/chat.types\";\nimport type { RunAgentRequest, RunAgentResponse } from \"./agent.types\";\nimport type { PendingUserInput } from \"./input.types\";\nimport type { ChatMessage } from \"./message.types\";\nimport type { UserInputResponse } from \"./tool.types\";\nimport type { Usage } from \"./usage.types\";\n\nimport type { OnAgentTokenParams, OnAgentUsageParams } from \"./ws.types\";\n\n// =============================================================================\n// Provider Identity\n// =============================================================================\n\nexport type AgentProviderId = \"claude-code\" | \"codex\" | \"cursor\" | (string & {}); //| \"jarvis\";\n\nexport type ChatProviderId =\n | \"web\"\n | \"cli\"\n | \"vscode\"\n | \"mobile\"\n | \"whatsapp\"\n | \"slack\"\n | \"discord\"\n | \"email\"\n | (string & {});\n\n// =============================================================================\n// File change + tree (used by CodeAgentProvider — server-side projections)\n// =============================================================================\n\nexport interface AgentFileChange {\n file: string;\n additions: number;\n deletions: number;\n /** Unified-diff-ish text. */\n patch: string;\n lastChangedAt: string;\n}\n\nexport interface AgentFileTreeNode {\n name: string;\n path: string;\n type: \"file\" | \"directory\";\n children?: AgentFileTreeNode[];\n}\n\n// =============================================================================\n// Per-turn usage (for metrics projection)\n// =============================================================================\n\nexport interface AgentTurnUsage extends Usage {\n turnIndex: number;\n model: string;\n timestamp: string;\n}\n\n// =============================================================================\n// Request / Response — chat discovery + extraction\n// =============================================================================\n\n/** Cheap lookup against the indexed store (DB / cache). UI sidebars use this.\n * Does NOT walk provider-native storage — use `scanChats` for that. */\nexport interface ListChatsRequest {\n provider?: AgentProviderId;\n repoPaths?: string[];\n cursor?: string;\n limit?: number;\n}\n\nexport interface ListChatsResponse {\n chats: Chat[];\n nextCursor?: string;\n}\n\n/** Expensive walk over provider-native storage (JSONL files, vendor paging).\n * Used by the sync workflow to populate the indexed store. */\nexport interface ScanChatsRequest {\n provider?: AgentProviderId;\n repoPaths?: string[];\n cursor?: string;\n limit?: number;\n /** Backwards-paging window bound used by sync (inclusive). */\n before?: string;\n /** Backwards-paging window bound used by sync (exclusive). */\n after?: string;\n}\n\nexport interface ScanChatsResponse {\n chats: Chat[];\n nextCursor?: string;\n}\n\nexport interface ReadChatRequest {\n provider: AgentProviderId;\n /** Provider-native chat id OR an opaque filePath — provider decides. */\n chatId?: string;\n filePath?: string;\n offset?: number;\n limit?: number;\n}\n\nexport interface ReadChatResponse {\n messages: ChatMessage[];\n total: number;\n hasMore: boolean;\n}\n\nexport interface ExtractChatRequest {\n provider: AgentProviderId;\n chatId?: string;\n filePath?: string;\n}\n\nexport interface ExtractMessagesResponse {\n turns: AgentTurnUsage[];\n}\n\nexport interface ExtractChatMetadataResponse {\n /** The chat as it should be persisted — caller UPSERTs by (userId, provider, externalId). */\n chat: Partial<Chat> & { id: string };\n}\n\nexport interface ExtractFileChangesResponse {\n fileChanges: AgentFileChange[];\n}\n\nexport interface ExtractFileTreeRequest {\n provider: AgentProviderId;\n chatId?: string;\n filePath?: string;\n /** Worktree/cwd override; provider falls back to the chat's own cwd. */\n cwd?: string;\n}\n\nexport interface ExtractFileTreeResponse {\n tree: AgentFileTreeNode[];\n}\n\n// =============================================================================\n// Lifecycle — chat start/stop\n// =============================================================================\n\nexport interface StartChatRequest {\n provider: AgentProviderId;\n prompt: string;\n cwd: string;\n chatId: string;\n model?: string;\n resumeChatId?: string;\n}\n\nexport interface StartChatResponse {\n chatId: string;\n workdir: string;\n}\n\nexport interface StopChatRequest {\n provider: AgentProviderId;\n chatId: string;\n}\n\nexport interface StopChatResponse {\n stopped: boolean;\n}\n\n// =============================================================================\n// Run / Abort\n// =============================================================================\n//\n// `RunAgentRequest` / `RunAgentResponse` live in `agent.types.ts` — the\n// canonical shapes across harness, provider, and JSON-RPC dispatch.\n\nexport interface InterruptAgentRequest {\n runId: string;\n reason?: string;\n}\n\nexport interface RunOptions {\n signal?: AbortSignal;\n /** Streaming handlers — populated by the CLI runner to fan out JSON-RPC\n * events (`agent.onMessage` / `agent.onToken` / `agent.onUsage`)\n * as the provider produces them. */\n onMessage?: (message: ChatMessage) => void;\n onToken?: (params: Omit<OnAgentTokenParams, \"runId\">) => void;\n onUsage?: (params: Omit<OnAgentUsageParams, \"runId\">) => void;\n /** Tool-confirm / plan-review / etc. The provider awaits the returned\n * promise and resumes once the user responds. */\n onUserInputRequest?: (input: PendingUserInput) => Promise<UserInputResponse>;\n [key: string]: unknown;\n}\n\nexport interface InterruptOptions {\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Cost\n// =============================================================================\n\nexport interface EstimateCostRequest {\n provider?: AgentProviderId;\n model: string;\n usage: Usage;\n}\n\nexport interface EstimateCostResponse {\n costUsd: number;\n}\n\n// =============================================================================\n// AgentProvider (base tier)\n// =============================================================================\n\nexport interface AgentProvider {\n id: AgentProviderId;\n name: string;\n kind: \"native\" | \"cloud\" | \"local\";\n models: string[];\n\n run<TState = unknown>(\n ctx: Context,\n req: RunAgentRequest<TState>,\n options?: RunOptions,\n ): Promise<RunAgentResponse<TState>>;\n interrupt(ctx: Context, req: InterruptAgentRequest, options?: InterruptOptions): Promise<void>;\n\n estimateCost(ctx: Context, req: EstimateCostRequest): Promise<EstimateCostResponse>;\n\n /** Cheap — list from the indexed store. UI sidebars use this. */\n listChats?(\n ctx: Context,\n req: ListChatsRequest,\n options?: Record<string, unknown>,\n ): Promise<ListChatsResponse>;\n /** Expensive — walk provider-native storage. Sync workflow uses this. */\n scanChats?(\n ctx: Context,\n req: ScanChatsRequest,\n options?: Record<string, unknown>,\n ): Promise<ScanChatsResponse>;\n readChat?(\n ctx: Context,\n req: ReadChatRequest,\n options?: Record<string, unknown>,\n ): Promise<ReadChatResponse>;\n extractMessages?(ctx: Context, req: ExtractChatRequest): Promise<ExtractMessagesResponse>;\n extractChatMetadata?(ctx: Context, req: ExtractChatRequest): Promise<ExtractChatMetadataResponse>;\n\n startChat?(\n ctx: Context,\n req: StartChatRequest,\n options?: Record<string, unknown>,\n ): Promise<StartChatResponse>;\n stopChat?(\n ctx: Context,\n req: StopChatRequest,\n options?: Record<string, unknown>,\n ): Promise<StopChatResponse>;\n}\n\n// =============================================================================\n// CodeAgentProvider\n// =============================================================================\n\nexport interface CodeAgentProvider extends AgentProvider {\n extractFileChanges(ctx: Context, req: ExtractChatRequest): Promise<ExtractFileChangesResponse>;\n extractFileTree(ctx: Context, req: ExtractFileTreeRequest): Promise<ExtractFileTreeResponse>;\n}\n\n// =============================================================================\n// ChatProvider (messaging surface)\n// =============================================================================\n\nexport interface DeliverMessageRequest {\n chatId: string;\n message: ChatMessage;\n surface?: ChatProviderId;\n}\n\nexport interface DeliverMessageResponse {\n delivered: boolean;\n}\n\nexport interface IngestMessageRequest {\n chatId: string;\n message: ChatMessage;\n surface: ChatProviderId;\n}\n\nexport interface IngestMessageResponse {\n accepted: boolean;\n}\n\nexport interface ChatProvider {\n id: ChatProviderId;\n name: string;\n kind: \"internal\" | \"external\";\n\n deliverMessage(\n ctx: Context,\n req: DeliverMessageRequest,\n options?: Record<string, unknown>,\n ): Promise<DeliverMessageResponse>;\n\n ingestMessage?(\n ctx: Context,\n req: IngestMessageRequest,\n options?: Record<string, unknown>,\n ): Promise<IngestMessageResponse>;\n\n scanChats?(\n ctx: Context,\n req: ScanChatsRequest,\n options?: Record<string, unknown>,\n ): Promise<ScanChatsResponse>;\n\n readChat?(\n ctx: Context,\n req: ReadChatRequest,\n options?: Record<string, unknown>,\n ): Promise<ReadChatResponse>;\n\n extractMessages?(ctx: Context, req: ExtractChatRequest): Promise<ExtractMessagesResponse>;\n}\n","/**\n * JSON-RPC contract for runner + chat traffic.\n *\n * Methods:\n * - `chat.send` → {@link RunAgentRequest} → `{ started: true }`\n * (client → hub: signal/start agentWorkflow)\n * - `agent.run` → {@link RunAgentRequest} → `{ started: true }`\n * (worker → hub → CLI runner: execute one turn)\n * - `agent.interrupt` → {@link InterruptAgentRequest} → `{ interrupted: true }`\n * - `agent.userInput` → {@link UserInput} → `{ received: boolean }`\n *\n * Events (streaming, runner → hub → clients + workflow signals):\n * - `agent.onMessage` — {@link OnAgentMessageParams}\n * - `agent.onToken` — {@link OnAgentTokenParams}\n * - `agent.onUsage` — {@link OnAgentUsageParams}\n * - `agent.onUserInputRequest` — {@link OnAgentUserInputRequestParams}\n * - `agent.output` — {@link AgentOutputParams}\n * - `agent.status` — {@link AgentStatusParams}\n */\n\nimport type { ChatMessage } from \"./chat.types\";\nimport type { PendingUserInput } from \"./input.types\";\n\n// =============================================================================\n// Event params\n// =============================================================================\n\nexport interface OnAgentMessageParams {\n runId: string;\n message: ChatMessage;\n}\n\nexport interface OnAgentTokenParams {\n runId: string;\n messageId: string;\n content: string;\n isComplete: boolean;\n isFinal?: boolean;\n}\n\nexport interface OnAgentUsageParams {\n runId: string;\n chatId: string;\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n model: string;\n}\n\nexport interface OnAgentUserInputRequestParams {\n runId: string;\n input: PendingUserInput;\n}\n\nexport interface AgentOutputParams {\n runId: string;\n output: {\n success: boolean;\n content: string;\n json?: string;\n error?: string;\n interrupted?: boolean;\n };\n}\n\nexport interface AgentStatusParams {\n status: \"idle\" | \"busy\";\n runId?: string;\n}\n\n// =============================================================================\n// Method / event name constants\n// =============================================================================\n\nexport const AGENT_METHODS = {\n run: \"agent.run\",\n interrupt: \"agent.interrupt\",\n userInput: \"agent.userInput\",\n} as const;\n\nexport const CHAT_METHODS = {\n send: \"chat.send\",\n} as const;\n\nexport const AGENT_EVENTS = {\n onMessage: \"agent.onMessage\",\n onToken: \"agent.onToken\",\n onUsage: \"agent.onUsage\",\n onUserInputRequest: \"agent.onUserInputRequest\",\n output: \"agent.output\",\n status: \"agent.status\",\n} as const;\n\nexport type AgentEventName = (typeof AGENT_EVENTS)[keyof typeof AGENT_EVENTS];\n","export * from \"./agent.types\";\nexport * from \"./chat.types\";\nexport * from \"./input.types\";\nexport * from \"./llm.types\";\nexport * from \"./message.types\";\nexport * from \"./mcp.types\";\nexport * from \"./memories.types\";\nexport * from \"./memory.types\";\nexport * from \"./model.types\";\nexport * from \"./prompt.types\";\nexport * from \"./reference.types\";\nexport * from \"./skill.types\";\nexport * from \"./tool.types\";\nexport * from \"./ui.types\";\nexport * from \"./usage.types\";\nexport * from \"./transport.types\";\nexport * from \"./workflow.types\";\nexport * from \"./sessions.types\";\nexport * from \"./provider.types\";\nexport * from \"./ws.types\";\n","/**\n * Semantic Color Types\n *\n * Canonical color type definitions for the platform.\n * Maps to Chakra UI color palettes via the theme configuration.\n */\n\nexport type SemanticColor =\n | \"primary\"\n | \"secondary\"\n | \"positive\"\n | \"negative\"\n | \"warning\"\n | \"neutral\";\n","/**\n * Context types — shared across all operations.\n *\n * Context<TMeta> is the single context type for the SDK.\n * TMeta defaults to Record<string, unknown> so basic usage is just `Context`.\n * Apps can extend metadata by providing a custom TMeta generic parameter.\n */\n\n// =============================================================================\n// CONTEXT\n// =============================================================================\n\n/**\n * Context for all SDK operations.\n *\n * @typeParam TMeta - Custom metadata shape. Defaults to Record<string, unknown>.\n *\n * @example\n * ```typescript\n * // Basic usage — no generic needed\n * const ctx: Context = { userId: \"user-123\", requestId: \"req-1\", timestamp: Date.now() };\n *\n * // With custom metadata\n * interface MyMeta { orgId: string }\n * const ctx: Context<MyMeta> = {\n * userId: \"user-123\",\n * requestId: \"req-1\",\n * timestamp: Date.now(),\n * metadata: { orgId: \"org-1\" },\n * };\n * ```\n */\nexport interface Context<TMetadata = Record<string, unknown>> {\n /** User ID — the one required field */\n userId: string;\n /** Request ID for tracing */\n requestId: string;\n /** Timestamp (ISO string or unix ms) */\n timestamp: string | number;\n /** Active workspace id — resolved at auth time so domain services don't\n * need their own workspace-resolution dependency. */\n workspaceId?: string;\n /** Extensible metadata */\n metadata?: TMetadata & {\n chat?: ChatContextMetadata;\n delegation?: DelegationContextMetadata;\n [key: string]: unknown;\n };\n}\n\n// =============================================================================\n// METADATA CONTAINERS\n// =============================================================================\n\n/** Chat context metadata — routing info for chat sessions.\n *\n * Optional `taskId` / `env` / `repo` fields let the caller (e.g. `/start`\n * route) thread the task config straight to the workflow without forcing it\n * to round-trip through `getTask`. The workflow prefers these over the DB\n * row so the worktree-vs-direct decision can't go stale on a slow read. */\nexport interface ChatContextMetadata {\n chatId: string;\n channelId?: string;\n /** Surface that dispatched the chat (web, cli, test, …) — forwarded to\n * ensureChat so the `chats.source` column reflects the actual origin. */\n source?: string;\n /** Agent provider that will power the chat (claude-code, codex, …). */\n provider?: string;\n /** Task that owns this chat (if any). */\n taskId?: string;\n /** Environment config, surfaced from the task by the start route. */\n env?: { id?: string; worktree?: boolean; config?: Record<string, unknown> };\n /** Repo config, surfaced from the task by the start route. */\n repo?: {\n owner?: string;\n name?: string;\n provider?: string;\n branch?: string;\n path?: string;\n };\n}\n\n/** Delegation context metadata for multi-agent workflows */\nexport interface DelegationContextMetadata {\n depth: number;\n maxDepth: number;\n visited: string[];\n rootWorkflowId: string;\n}\n","import type { Context } from \"./context.types\";\n\nexport interface Provider {\n name: string;\n}\n\n/**\n * Compile-time guard: every async method on a provider must accept\n * `ctx: Context` as its first argument. Sync helpers (extractKey, buildUrl)\n * pass through unchanged since they don't go through RPC.\n *\n * Usage: `ValidProvider<DatabaseProvider>` — turns any async method\n * missing `ctx` to `never`, causing compile errors at every call site.\n */\nexport type ValidProvider<T> = {\n [K in keyof T]: T[K] extends (...args: any[]) => Promise<any>\n ? T[K] extends (ctx: Context, ...rest: any[]) => Promise<any>\n ? T[K]\n : `ERROR: '${K & string}' must accept (ctx: Context, req) signature`\n : T[K];\n};\n","// Schema type - allows for flexible schema definitions\nexport type Schema = Record<string, unknown>;\n","/**\n * i18n Types\n * Shared translation function type for backend tool descriptions\n */\n\n/**\n * Translation function signature.\n * Returns the translated string for the given key, with optional variable interpolation.\n * Falls back to the key itself (English) when no translation is found.\n */\nexport type TranslateFn = (key: string, vars?: Record<string, string | number>) => string;\n","/**\n * Logger Domain Types\n * Pure TypeScript types only - no runtime dependencies\n */\n\nimport type { Context } from \"./context.types\";\n\n// =============================================================================\n// LOG LEVELS & METADATA\n// =============================================================================\n\n/** Log levels in order of severity */\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\n/** Structured metadata for log entries */\nexport interface LogMetadata {\n [key: string]: unknown;\n}\n\n/** Audit event for compliance logging */\nexport interface AuditEvent {\n /** What happened (e.g. \"user.login\", \"entity.delete\") */\n action: string;\n /** What was affected */\n resource?: { type: string; id: string };\n /** Outcome */\n result: \"success\" | \"failure\" | \"denied\";\n /** Why it failed or was denied */\n reason?: string;\n /** Additional context */\n meta?: LogMetadata;\n}\n\n// =============================================================================\n// LOGGER INTERFACE\n// =============================================================================\n\n/**\n * LogProvider — the single logging interface.\n * Implemented by pino, console, temporal, or any custom provider.\n * Used everywhere: request handlers, business logic, providers, lifecycle.\n */\nexport interface LogProvider {\n debug(ctx: Context, message: string, meta?: LogMetadata): void;\n info(ctx: Context, message: string, meta?: LogMetadata): void;\n warn(ctx: Context, message: string, meta?: LogMetadata): void;\n error(ctx: Context, message: string, meta?: LogMetadata): void;\n audit(ctx: Context, event: AuditEvent): void;\n}\n\n/** @deprecated Use LogProvider instead */\nexport type Logger = LogProvider;\n\n// =============================================================================\n// CONFIGURATION\n// =============================================================================\n\n/** Configuration for logger provider implementations (e.g., pino, axiom) */\nexport interface LoggerProviderConfig {\n /** Logger name — defaults to LOGGER_NAME env var or \"app\" */\n name?: string;\n /** Minimum log level (default: \"info\") */\n level?: LogLevel;\n /** Human-readable output for local dev (default: false) */\n pretty?: boolean;\n /** Additional destination streams (e.g., axiomStream from @jarvis/axiom) */\n streams?: import(\"stream\").Writable[];\n}\n\n/** Config for the logger factory in @jarvis/logger */\nexport interface LoggerConfig {\n /** Minimum log level (default: \"info\") */\n level?: LogLevel;\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n}\n","export * from \"./color.types\";\nexport * from \"./context.types\";\nexport * from \"./provider.types\";\nexport * from \"./schema.types\";\nexport * from \"./translation.types\";\nexport * from \"./logger.types\";\n","/**\n * Cache Provider Types\n *\n * Generic key-value and counter operations.\n * Backend-agnostic — can be implemented by Redis, Memcached, etc.\n */\n\nimport { Provider } from \"../core/provider.types\";\n\nexport interface CacheProvider extends Provider {\n get(key: string): Promise<string | null>;\n set(key: string, value: string, options?: { EX?: number }): Promise<void>;\n incr(key: string): Promise<number>;\n expire(key: string, seconds: number): Promise<boolean>;\n ttl(key: string): Promise<number>;\n del(key: string): Promise<number>;\n}\n\n// =============================================================================\n// Rate Limit (fixed-window counter over CacheProvider)\n// =============================================================================\n\nexport interface RateLimitRequest {\n /** Logical bucket name (e.g. `agents.run`, `chats.scan`). */\n action: string;\n /** Optional per-tier bucket (paid users get a higher cap). */\n tier?: string;\n}\n\nexport interface RateLimitResponse {\n allowed: boolean;\n remaining: number;\n limit: number;\n /** ISO timestamp when the current window resets. */\n resetsAt: string;\n}\n","/**\n * Chat Domain Types\n *\n * DB entity types for chats.\n * Note: SDK-level chat message/state types live in agents/chat.types.ts.\n */\n\nimport type { AgentProviderId } from \"../agents/provider.types\";\nimport type { TaskSource } from \"./task.types\";\n\nexport interface Chat {\n id: string;\n userId: string;\n title: string | null;\n status: string;\n /** Where the chat originated — surface that produced it. */\n source: TaskSource;\n /** AgentProvider that powered this chat. Null for native Jarvis chats. */\n provider: AgentProviderId | null;\n /** Provider-native id for imported chats (e.g. Claude Code's JSONL filename\n * stem). Null for native Jarvis chats. Combined with (userId, provider) to\n * make a partial unique key so sync upserts are idempotent. */\n externalId: string | null;\n taskId: string | null;\n model: string | null;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n endedAt: string | null;\n}\n\n","/**\n * Database Types\n * Generic database provider interface\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { FieldConfig, FilterValue } from \"./field.types\";\nimport type { Table } from \"./table.types\";\nimport { Provider } from \"../core/provider.types\";\n\n/** Column schema passed from table to the db provider */\nexport type EntryColumns = Record<string, FieldConfig>;\n\n// =============================================================================\n// Raw SQL (escape hatch for provider-specific operations)\n// =============================================================================\n\nexport interface QueryDbRequest {\n sql: string;\n params?: unknown[];\n}\n\nexport interface QueryDbResponse<T = unknown> {\n rows: T[];\n rowCount: number;\n}\n\n// =============================================================================\n// CRUD Request/Response types — all follow (ctx, req) pattern\n// =============================================================================\n\nexport interface FindRequest {\n table: Table;\n filter?: Record<string, FilterValue>;\n sort?: Record<string, \"asc\" | \"desc\">;\n limit?: number;\n offset?: number;\n}\n\nexport interface FindResponse<T = unknown> {\n items: T[];\n total: number;\n}\n\nexport interface FindOneRequest {\n table: Table;\n id: string;\n}\n\nexport interface CreateRequest<T = unknown> {\n table: Table;\n data: Partial<T>;\n}\n\nexport interface CreateResponse<T = unknown> {\n item: T;\n}\n\nexport interface CreateManyRequest<T = unknown> {\n table: Table;\n items: Partial<T>[];\n}\n\nexport interface CreateManyResponse<T = unknown> {\n items: T[];\n}\n\nexport interface UpdateRequest<T = unknown> {\n table: Table;\n id: string;\n data: Partial<T>;\n}\n\nexport interface UpdateResponse<T = unknown> {\n item: T;\n}\n\nexport interface UpdateManyRequest {\n table: Table;\n filter: Record<string, FilterValue>;\n data: Record<string, unknown>;\n}\n\nexport interface UpdateManyResponse {\n count: number;\n}\n\nexport interface DeleteRequest {\n table: Table;\n id: string;\n}\n\nexport interface DeleteResponse {\n deleted: boolean;\n}\n\nexport interface DeleteManyRequest {\n table: Table;\n filter: Record<string, FilterValue>;\n}\n\nexport interface DeleteManyResponse {\n count: number;\n}\n\nexport interface CountRequest {\n table: Table;\n filter?: Record<string, FilterValue>;\n}\n\nexport interface CountResponse {\n count: number;\n}\n\n// =============================================================================\n// Database Provider\n// =============================================================================\n\nexport interface DatabaseProvider extends Provider {\n /** Raw SQL — escape hatch for provider-specific operations */\n query<T = unknown>(ctx: Context, req: QueryDbRequest): Promise<QueryDbResponse<T>>;\n\n /** Find entries matching filter criteria */\n find?<T = unknown>(ctx: Context, req: FindRequest): Promise<FindResponse<T>>;\n /** Find a single entry by ID */\n findOne?<T = unknown>(ctx: Context, req: FindOneRequest): Promise<T | null>;\n /** Create a new entry */\n create?<T = unknown>(ctx: Context, req: CreateRequest<T>): Promise<CreateResponse<T>>;\n /** Create multiple entries */\n createMany?<T = unknown>(ctx: Context, req: CreateManyRequest<T>): Promise<CreateManyResponse<T>>;\n /** Update a single entry by ID */\n update?<T = unknown>(ctx: Context, req: UpdateRequest<T>): Promise<UpdateResponse<T>>;\n /** Update multiple entries matching filter */\n updateMany?(ctx: Context, req: UpdateManyRequest): Promise<UpdateManyResponse>;\n /** Delete a single entry by ID */\n delete?(ctx: Context, req: DeleteRequest): Promise<DeleteResponse>;\n /** Delete multiple entries matching filter */\n deleteMany?(ctx: Context, req: DeleteManyRequest): Promise<DeleteManyResponse>;\n /** Count entries matching filter */\n count?(ctx: Context, req: CountRequest): Promise<CountResponse>;\n\n connect?(): Promise<void>;\n disconnect?(): Promise<void>;\n}\n\n// =============================================================================\n// Database Config\n// =============================================================================\n\nexport interface DatabaseConfig {\n connectionString?: string;\n host?: string;\n port?: number;\n database?: string;\n username?: string;\n password?: string;\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Legacy aliases (for gradual migration)\n// =============================================================================\n\n/** @deprecated Use FindRequest */\nexport type FindEntryRequest = { table: string; columns: EntryColumns; filter?: Record<string, FilterValue>; sort?: Record<string, \"asc\" | \"desc\">; limit?: number; offset?: number };\n/** @deprecated Use FindResponse */\nexport type FindEntryResponse<T = unknown> = FindResponse<T>;\n/** @deprecated Use FindOneRequest */\nexport type FindOneEntryRequest = { table: string; columns: EntryColumns; id: string };\n/** @deprecated Use CreateRequest */\nexport type CreateEntryRequest<T = unknown> = { table: string; columns: EntryColumns; data: Partial<T> };\n/** @deprecated Use CreateResponse */\nexport type CreateEntryResponse<T = unknown> = CreateResponse<T>;\n/** @deprecated Use CreateManyRequest */\nexport type CreateManyEntryRequest<T = unknown> = { table: string; columns: EntryColumns; items: Partial<T>[] };\n/** @deprecated Use CreateManyResponse */\nexport type CreateManyEntryResponse<T = unknown> = CreateManyResponse<T>;\n/** @deprecated Use UpdateRequest */\nexport type UpdateEntryRequest<T = unknown> = { table: string; columns: EntryColumns; id: string; data: Partial<T> };\n/** @deprecated Use UpdateResponse */\nexport type UpdateEntryResponse<T = unknown> = UpdateResponse<T>;\n/** @deprecated Use UpdateManyRequest */\nexport type UpdateManyEntryRequest = { table: string; columns: EntryColumns; filter: Record<string, FilterValue>; data: Record<string, unknown> };\n/** @deprecated Use UpdateManyResponse */\nexport type UpdateManyEntryResponse = UpdateManyResponse;\n/** @deprecated Use DeleteRequest */\nexport type DeleteEntryRequest = { table: string; id: string };\n/** @deprecated Use DeleteResponse */\nexport type DeleteEntryResponse = DeleteResponse;\n/** @deprecated Use DeleteManyRequest */\nexport type DeleteManyEntryRequest = { table: string; columns: EntryColumns; filter: Record<string, FilterValue> };\n/** @deprecated Use DeleteManyResponse */\nexport type DeleteManyEntryResponse = DeleteManyResponse;\n/** @deprecated Use CountRequest */\nexport type CountEntryRequest = { table: string; columns: EntryColumns; filter?: Record<string, FilterValue> };\n/** @deprecated Use CountResponse */\nexport type CountEntryResponse = CountResponse;\n","/**\n * Embedding related types\n */\n\nimport type { Context } from \"../core/context.types\";\nimport { Provider } from \"../core/provider.types\";\n\n/**\n * Embedding request\n */\nexport interface EmbedRequest {\n text: string | string[];\n model?: string;\n dimensions?: number;\n user?: string;\n}\n\n/**\n * Embedding response\n */\nexport interface EmbedResponse {\n embeddings: number[][];\n model: string;\n usage: {\n promptTokens: number;\n totalTokens: number;\n };\n}\n\n/**\n * Embedding provider interface\n */\nexport interface EmbeddingProvider extends Provider {\n embed(ctx: Context, req: EmbedRequest): Promise<EmbedResponse>;\n}\n","/**\n * Field Types\n * Shared data primitives used across table, entity, store, and db types.\n *\n * This is a leaf module — it only imports from ../core/.\n * No circular dependencies.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// FIELD TYPES\n// =============================================================================\n\n/**\n * Field type for entity/table/cache definitions\n */\nexport type FieldType =\n | \"string\"\n | \"text\"\n | \"integer\"\n | \"numeric\"\n | \"boolean\"\n | \"timestamp\"\n | \"json\"\n | \"uuid\"\n | \"vector\";\n\n/**\n * Schema definition for inner fields of a JSONB column.\n * Used by field.json({ schema }) for type safety and documentation.\n */\nexport interface JsonFieldSchema {\n type: FieldType | \"array\" | \"object\";\n required?: boolean;\n default?: unknown;\n searchable?: boolean;\n /** For array types */\n items?: JsonFieldSchema;\n /** For object types */\n properties?: Record<string, JsonFieldSchema>;\n}\n\n/**\n * Field configuration\n */\nexport interface FieldConfig {\n /** Field data type */\n type: FieldType;\n /** Whether this field is the primary key */\n primary?: boolean;\n /** Whether the field is required */\n required?: boolean;\n /** Whether the field must be unique */\n unique?: boolean;\n /** Default value */\n default?: unknown;\n /** Auto-generate: true for uuid (gen_random_uuid), \"create\"/\"update\" for timestamps */\n auto?: true | \"create\" | \"update\";\n /** Whether the field is nullable */\n nullable?: boolean;\n /** Vector dimensions (for vector fields) */\n dimensions?: number;\n /** Whether this field is included in search (ILIKE matching) */\n searchable?: boolean;\n /** Whether this field contains sensitive data (passwords, tokens, etc.) */\n secret?: boolean;\n /** Schema for JSONB inner fields (for json type only) */\n schema?: Record<string, JsonFieldSchema>;\n}\n\n// =============================================================================\n// INDEX TYPES\n// =============================================================================\n\n/**\n * Index configuration\n */\nexport interface IndexConfig {\n /** Index name */\n name: string;\n /** Columns included in the index */\n columns: string[];\n /** Whether the index enforces uniqueness */\n unique?: boolean;\n /** Partial-index predicate — emitted as `WHERE <expr>` (column names in\n * snake_case, since this is raw SQL). Used for partial unique constraints\n * like `UNIQUE (userId, provider, externalId) WHERE provider IS NOT NULL`. */\n where?: string;\n}\n\n// =============================================================================\n// FILTER TYPES\n// =============================================================================\n\n/**\n * Filter operators for queries\n */\nexport interface FilterOperators {\n $eq?: unknown;\n $ne?: unknown;\n $gt?: unknown;\n $gte?: unknown;\n $lt?: unknown;\n $lte?: unknown;\n $in?: unknown[];\n $nin?: unknown[];\n $like?: string;\n $ilike?: string;\n $isNull?: boolean;\n $contains?: unknown;\n}\n\n/**\n * Filter value — either a direct value (implicit $eq) or operators\n */\nexport type FilterValue = unknown | FilterOperators;\n\n// =============================================================================\n// QUERY TYPES\n// =============================================================================\n\n/** Data scope for queries — extensible for app-specific scopes */\nexport type DataScope = \"private\" | \"public\" | \"shared\" | \"all\" | (string & {});\n\n/**\n * Query parameters for find operations\n */\nexport interface EntityQuery {\n /** Filter conditions: { status: \"active\" } or { age: { $gte: 18 } } */\n filter?: Record<string, FilterValue>;\n /** Sort order: { createdAt: \"desc\", title: \"asc\" } */\n sort?: Record<string, \"asc\" | \"desc\">;\n /** Max results to return */\n limit?: number;\n /** Number of results to skip (for pagination) */\n offset?: number;\n /**\n * Data scope for this query. Only effective if table has `access` config.\n * - \"private\" — only the user's own rows\n * - \"public\" — only rows with visibility='public' from all users\n * - \"shared\" — only records explicitly shared with the current user\n * - \"link\" — only rows with visibility='link' (anyone with the ID)\n * - \"all\" — own + public + shared + link + admin bypass\n */\n scope?: DataScope;\n}\n\n/**\n * Result of a find operation with pagination info\n */\nexport interface FindEntityResponse<T> {\n items: T[];\n total: number;\n}\n","/**\n * Notification Domain Types\n */\n\nexport interface Notification {\n id: string;\n userId: string;\n type: string;\n title: string;\n body: string | null;\n taskId: string | null;\n read: boolean;\n createdAt: string;\n}\n","/**\n * Store Types\n *\n * Types for the cache() storage primitive — ephemeral, TTL-based storage.\n * Used by the cache() factory in @jarvis/sdk.\n *\n * Cache<T> provides the same typed CRUD methods as Table<T> but backed by\n * in-memory storage with automatic TTL expiration. The backing store is\n * swappable via the StoreProvider interface (Redis, PostgreSQL, etc.).\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type {\n DataScope,\n EntityQuery,\n FieldConfig,\n FilterValue,\n FindEntityResponse,\n} from \"./field.types\";\nimport type { LogProvider } from \"../core/logger.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// STORE PROVIDER (swappable backing store)\n// =============================================================================\n\n/**\n * StoreProvider — swappable backing store for cache() primitives.\n *\n * Implementations:\n * - memoryProvider: in-memory Map with TTL (default)\n * - Future: redisStoreProvider, postgresStoreProvider\n */\nexport interface StoreProvider extends Provider {\n /** Get a value by key within a namespace */\n get(\n ctx: Context,\n req: { namespace: string; key: string },\n ): Promise<Record<string, unknown> | null>;\n /** Set a value by key within a namespace, with optional TTL in seconds */\n set(\n ctx: Context,\n req: {\n namespace: string;\n key: string;\n value: Record<string, unknown>;\n ttlSeconds?: number;\n },\n ): Promise<void>;\n /** Delete a value by key within a namespace */\n del(ctx: Context, req: { namespace: string; key: string }): Promise<boolean>;\n /** Find all values in a namespace */\n findAll(\n ctx: Context,\n req: { namespace: string },\n ): Promise<Record<string, unknown>[]>;\n /** Clear all values in a namespace */\n clear(ctx: Context, req: { namespace: string }): Promise<void>;\n /** Count entries in a namespace */\n count(ctx: Context, req: { namespace: string }): Promise<number>;\n}\n\n// =============================================================================\n// CACHE CONFIGURATION\n// =============================================================================\n\n/**\n * Cache configuration input for cache() factory\n */\nexport interface StorageCacheConfig<T = Record<string, unknown>> {\n /** Cache name (lowercase with underscores, e.g. \"insights\", \"album_stats\") */\n name: string;\n /** Field definitions (same as table fields) */\n fields: Record<string, FieldConfig>;\n /** Time-to-live for entries. Supports: \"30s\", \"5m\", \"1h\", \"24h\", \"7d\" */\n ttl?: string;\n /**\n * Data access policy for cache entries.\n * - `\"private\"` (default) — user-scoped namespace only\n * - `\"public\"` — adds shared __public: namespace for cross-user entries\n */\n access?: \"private\" | \"public\";\n}\n\n// =============================================================================\n// CACHE OPTIONS\n// =============================================================================\n\n/**\n * Options for cache CRUD methods.\n */\nexport interface StorageCacheOptions {\n /** Store provider */\n store: StoreProvider;\n /** Optional structured logger */\n logger?: LogProvider;\n}\n\n// =============================================================================\n// CACHE<T> — Ephemeral storage with typed CRUD\n// =============================================================================\n\n/**\n * Cache definition with typed CRUD methods.\n * Returned by cache<T>() factory in @jarvis/sdk.\n *\n * Same CRUD API as Table<T>, but backed by an ephemeral store with TTL.\n * Data auto-expires based on the configured TTL.\n */\nexport interface StorageCache<\n T = Record<string, unknown>,\n> extends StorageCacheConfig<T> {\n /** Storage kind discriminator */\n readonly kind: \"cache\";\n\n /** Parsed TTL in seconds (null = no expiration) */\n ttlSeconds: number | null;\n\n find(\n ctx: Context,\n req: EntityQuery,\n options?: StorageCacheOptions,\n ): Promise<FindEntityResponse<T>>;\n\n findOne(\n ctx: Context,\n req: { id: string; scope?: DataScope },\n options?: StorageCacheOptions,\n ): Promise<T | null>;\n\n create(\n ctx: Context,\n req: Partial<T>,\n options?: StorageCacheOptions,\n ): Promise<T>;\n\n update(\n ctx: Context,\n req: { id: string } & Partial<T>,\n options?: StorageCacheOptions,\n ): Promise<T>;\n\n delete(\n ctx: Context,\n req: { id: string },\n options?: StorageCacheOptions,\n ): Promise<boolean>;\n\n count(\n ctx: Context,\n req: EntityQuery,\n options?: StorageCacheOptions,\n ): Promise<number>;\n\n createMany(\n ctx: Context,\n req: { items: Partial<T>[] },\n options?: StorageCacheOptions,\n ): Promise<T[]>;\n\n updateMany(\n ctx: Context,\n req: { filter: Record<string, FilterValue>; data: Partial<T> },\n options?: StorageCacheOptions,\n ): Promise<number>;\n\n deleteMany(\n ctx: Context,\n req: { filter: Record<string, FilterValue> },\n options?: StorageCacheOptions,\n ): Promise<number>;\n}\n","/**\n * Sync Domain Types\n *\n * Generic sync state — one row per (userId, kind, provider). Tracks the\n * cursor every sync kind needs: newest synced timestamp (delta), oldest\n * synced timestamp (backfill), and a completion flag for backfill.\n */\n\nexport interface SyncRecord<T = Record<string, unknown>> {\n id: string;\n userId: string;\n /** What's being synced — \"chats\" today, \"tasks\" / \"messages\" / ... later. */\n kind: string;\n /** External source — \"claude-code\", \"monday\", ... */\n provider: string;\n /** Most recent source timestamp we've synced — drives delta passes. */\n newestAt: string | null;\n /** Oldest source timestamp we've synced — drives backfill. */\n oldestAt: string | null;\n /** True once backfill reached the oldest source data; nothing more to fetch. */\n completed: boolean;\n /** Kind-specific extras (filters, options, last error, ...). */\n data: T;\n updatedAt: string;\n}\n","/**\n * Table Types\n *\n * Types for defining persistent storage tables.\n * Table<T> is a pure schema definition — no CRUD methods.\n * CRUD is handled by the DatabaseProvider directly.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { FieldConfig, IndexConfig } from \"./field.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// ACCESS POLICY\n// =============================================================================\n\n/** Who is being granted access */\nexport type Principal = \"owner\" | \"public\" | \"shared\" | `role:${string}`;\n\n/** What action is allowed — extensible for app-specific actions */\nexport type Action = \"read\" | \"write\" | \"delete\" | \"*\" | (string & {});\n\n/** A single access grant — who can do what */\nexport interface PolicyRule {\n principal: Principal;\n action: Action;\n}\n\n/** Resolved policy — a set of grant rules */\nexport interface AccessPolicy {\n rules: PolicyRule[];\n}\n\n// =============================================================================\n// ACCESS PROVIDER (data-level enforcement — implemented by platform)\n// =============================================================================\n\n/**\n * Access enforcement provider — platform-specific implementation for\n * applying access policies to storage backends.\n */\nexport interface AccessProvider extends Provider {\n /** Build a scope clause for the given action (e.g., SQL WHERE) */\n buildScope(\n ctx: Context,\n req: {\n tableName: string;\n policy: AccessPolicy;\n action: Action;\n scope?: string;\n },\n ): string;\n\n /** Apply enforcement policies to storage. Idempotent. */\n applyPolicies(\n ctx: Context,\n req: { tableName: string; policy: AccessPolicy },\n ): Promise<void>;\n\n /** Ensure access-related schema exists (visibility columns, shares table, etc.) */\n ensureSchema(\n ctx: Context,\n req: { tableName: string; policy: AccessPolicy },\n ): Promise<void>;\n}\n\n// =============================================================================\n// TABLE CONFIGURATION\n// =============================================================================\n\n/**\n * Table configuration input for table() factory.\n *\n * Every column is explicit — what you write is what the DB gets.\n * Use `primary: true` on a field to mark it as the primary key.\n *\n * @example\n * ```typescript\n * const usersTable = table<User>({\n * name: \"users\",\n * columns: {\n * id: field.uuid({ primary: true }),\n * userId: field.string({ required: true }),\n * email: field.string({ required: true, unique: true }),\n * name: field.string({ nullable: true }),\n * createdAt: field.timestamp({ auto: \"create\" }),\n * updatedAt: field.timestamp({ auto: \"update\" }),\n * },\n * });\n * ```\n */\nexport interface TableConfig<_T = Record<string, unknown>> {\n /** Table name (lowercase with underscores, e.g. \"goals\", \"artist_profiles\") */\n name: string;\n /** Column definitions — 1:1 with actual database columns */\n columns: Record<string, FieldConfig>;\n /** Index definitions */\n indexes?: IndexConfig[];\n /** Access policy. Omit for private (owner-only). */\n access?: AccessPolicy;\n}\n\n// =============================================================================\n// TABLE<T> — Pure schema definition\n// =============================================================================\n\n/**\n * Table definition — pure schema, no CRUD methods.\n * Returned by table<T>() factory in @jarvis/sdk.\n *\n * CRUD is handled by the DatabaseProvider:\n * db.find(ctx, { table: usersTable, filter: { email } })\n */\nexport interface Table<_T = Record<string, unknown>> {\n /** Storage kind discriminator */\n readonly kind: \"table\";\n /** Table name */\n readonly name: string;\n /** Column definitions — 1:1 with actual database columns */\n readonly columns: Record<string, FieldConfig>;\n /** Index definitions */\n readonly indexes: IndexConfig[];\n /** Access policy */\n readonly access?: AccessPolicy;\n /** Searchable field names (fields with searchable: true) */\n readonly searchableFields: string[];\n}\n","import type { AgentProviderId } from \"../agents/provider.types\";\n\n/**\n * Task Domain Types\n *\n * Source of truth for task, repo, env, diff, and metric types.\n */\n\n// =============================================================================\n// Enums / Unions\n// =============================================================================\n\nexport type TaskStatus =\n | \"pending\"\n | \"running\"\n | \"waiting_for_input\"\n | \"reviewing\"\n | \"completed\"\n | \"failed\"\n | \"canceled\"\n | \"archived\";\n\n// =============================================================================\n// Config Types\n// =============================================================================\n\nexport interface RepoConfig {\n owner?: string;\n name?: string;\n provider?: string;\n branch?: string;\n path?: string;\n}\n\nexport interface EnvConfig {\n id?: string;\n config?: Record<string, unknown>;\n worktree?: boolean;\n}\n\n// =============================================================================\n// Diff Types\n// =============================================================================\n\nexport interface FileDiff {\n file: string;\n additions: number;\n deletions: number;\n /** Unified-diff-compatible patch text for inline rendering */\n patch?: string;\n /** ISO timestamp of last edit in this session */\n lastChangedAt?: string;\n /** Git change kind (when known) — drives the A/M/D/R badge in the UI */\n status?: \"added\" | \"modified\" | \"deleted\" | \"renamed\";\n}\n\nexport interface TaskDiff {\n files: FileDiff[];\n additions: number;\n deletions: number;\n}\n\n// =============================================================================\n// File Reference\n// =============================================================================\n\nexport interface TaskFile {\n key: string;\n url: string;\n fileName: string;\n mimeType: string;\n size: number;\n}\n\n// =============================================================================\n// Task Config & State (JSON columns)\n// =============================================================================\n\n/** User-specified configuration at task creation time */\nexport interface TaskConfig {\n repo?: RepoConfig;\n env?: EnvConfig;\n mode?: string;\n /** Model id (e.g. \"claude-sonnet-4-20250514\"). Persisted so the chat\n * resumes with the user's pick across refreshes. */\n model?: string;\n thinking?: {\n type: \"adaptive\" | \"enabled\" | \"disabled\";\n budgetTokens?: number;\n };\n}\n\n/** Runtime state set by the system during task execution */\nexport interface TaskState {\n workflowId?: string;\n /** Directory the agent runs in. Worktree mode → the git-worktree path;\n * direct mode → the user's repo path itself. The mode is implicit:\n * `branchName` set ⇔ a worktree we created. */\n workdir?: string;\n /** Set ONLY in worktree mode (we created the branch via `git worktree add`).\n * Direct mode operates on whatever branch the user already has checked out\n * — we don't own it and don't track it. */\n branchName?: string;\n /** Resolved sha of the worktree's start point at creation time. Frozen for\n * the lifetime of the task — diff scans compute against this ref so they\n * show the cumulative session delta, not just the last commit. */\n baselineRef?: string;\n error?: string;\n diffs?: TaskDiff;\n files?: TaskFile[];\n /** Stable id for the seeded user message. Set when the web surface mints an\n * optimistic user bubble at create time — the workflow reuses it as the\n * user message id so the server-emitted echo dedupes with the optimistic\n * bubble already in the chat thread. */\n messageId?: string;\n}\n\n// =============================================================================\n// Entity Types\n// =============================================================================\n\n/** Task-system providers — external PM tools that originate tasks but don't\n * execute chats. */\nexport type TaskProviderId = \"monday\" | \"jira\" | \"linear\" | \"github\" | (string & {});\n\n/** Where the task/chat originated — which surface produced it.\n * `\"external\"` covers tasks imported from third-party systems — either an\n * agent CLI (Claude Code / Codex / Cursor) or a task-system (Monday / Jira\n * / Linear / GitHub). Always paired with a `provider`. */\nexport type TaskSource =\n | \"web\"\n | \"cli\"\n | \"vscode\"\n | \"mobile\"\n | \"automation\"\n | \"webhook\"\n | \"api\"\n | \"external\"\n | \"test\";\n\nexport interface Task {\n id: string;\n userId: string;\n workspaceId: string | null;\n title: string;\n description: string | null;\n status: TaskStatus;\n chatId: string | null;\n /** Where the task originated — which surface produced it. */\n source: TaskSource;\n /** The system that produced this task — either an AgentProvider\n * (claude-code/codex/cursor) or a task-system provider (monday/jira/…).\n * Null for native Jarvis-authored tasks. */\n provider: AgentProviderId | TaskProviderId | null;\n groupId: string | null;\n /** Position within group. Tasks with the same position can run in parallel. */\n position: number | null;\n config: TaskConfig;\n state: TaskState;\n startedAt: string | null;\n completedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n// =============================================================================\n// Input Types\n// =============================================================================\n\nexport interface CreateTaskRequest {\n title: string;\n description?: string;\n workspaceId?: string;\n config?: TaskConfig;\n groupId?: string;\n position?: number;\n /** Initial files to attach to the task */\n files?: TaskFile[];\n}\n\nexport interface StartTaskRequest {\n chatId: string;\n workflowId: string;\n startedAt: string;\n}\n","/**\n * Usage Domain Types\n *\n * Generic usage record. One row per (kind, owner). The `data` column holds\n * kind-specific payload; for kind=\"tokens\" the payload is `AgentTurnUsage`\n * (extends canonical Usage with turnIndex / model / timestamp).\n *\n * Each kind has one owner type — for \"tokens\", owner is a chat_message id.\n * Chat- and task-level token totals are aggregates: JOIN usage via owner to\n * chat_messages → chats → tasks.\n */\n\nexport interface UsageRecord<T = unknown> {\n id: string;\n userId: string;\n /** What's being measured — \"tokens\" today, \"api\" / ... later. */\n kind: string;\n /** Per-kind owner entity id (for \"tokens\": chat_message id). */\n owner: string;\n data: T;\n createdAt: string;\n}\n","/**\n * App User Entity Type\n *\n * App-specific user record stored in the database.\n * Note: Platform-level BaseUser + UsersProvider live in users/users.types.ts.\n */\n\nexport interface User {\n id: string;\n userId: string;\n email: string;\n name: string | null;\n image: string | null;\n preferences: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n}\n","/**\n * Vector Store Types\n * Vector database provider interface for similarity search\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// Vector Document Types\n// =============================================================================\n\n/**\n * Vector Document - stored in vector database\n */\nexport interface VectorDocument {\n id: string;\n score: number;\n metadata: Record<string, unknown>;\n}\n\n// =============================================================================\n// Entity-Aware Vector Configuration\n// =============================================================================\n\n/**\n * Entity FK column definition for vectors table\n */\nexport interface VectorEntityColumn {\n /** Entity type (e.g., \"task\") */\n entityType: string;\n /** Database column name (e.g., \"task_id\") */\n columnName: string;\n /** Referenced table (e.g., \"tasks\") */\n referencesTable: string;\n /** Referenced column (default: \"id\") */\n referencesColumn?: string;\n}\n\n/**\n * Vectors table configuration\n */\nexport interface VectorsTableConfig {\n /** Table name (default: \"vectors\") */\n tableName?: string;\n /** FK columns for each entity type */\n entityColumns: VectorEntityColumn[];\n}\n\n/**\n * Searchable entity interface - entities implement this for auto-embedding\n */\nexport interface Searchable {\n id: string;\n /** Returns text to embed for semantic search */\n format(): string;\n}\n\n// =============================================================================\n// Request/Response Types\n// =============================================================================\n\n/**\n * Add Document Request\n */\nexport interface AddVectorRequest {\n id: string;\n embedding: number[];\n metadata: Record<string, unknown>;\n /** Entity type (e.g., \"task\", \"project\") */\n entityType?: string;\n /** Entity ID (populates the right FK column) */\n entityId?: string;\n /** Content text for the vector */\n content?: string;\n}\n\nexport interface AddVectorResponse {\n id: string;\n}\n\n/**\n * Search Request\n */\nexport interface SearchVectorRequest {\n embedding: number[];\n limit?: number;\n filter?: Record<string, unknown>;\n /** Filter by entity types */\n entityTypes?: string[];\n}\n\nexport interface SearchVectorResponse {\n documents: VectorDocument[];\n}\n\n/**\n * Remove Document Request\n */\nexport interface RemoveVectorRequest {\n /** Vector ID (optional if entityType + entityId provided) */\n id?: string;\n /** Entity type for targeted removal */\n entityType?: string;\n /** Entity ID for targeted removal */\n entityId?: string;\n}\n\nexport interface RemoveVectorResponse {\n removed: boolean;\n}\n\n/**\n * Get Document Request/Response\n */\nexport interface GetVectorRequest {\n id: string;\n}\n\nexport interface GetVectorResponse {\n id: string;\n content: string;\n metadata: Record<string, unknown>;\n}\n\n// =============================================================================\n// Provider Interface\n// =============================================================================\n\n/**\n * Vector Provider - manages vector storage and similarity search\n *\n * All mutating/querying methods take `ctx: Context` as first arg.\n * The provider resolves identity from ctx internally (platform: via __token,\n * sandbox: via pre-scoped identity) and auto-scopes all operations.\n */\nexport interface VectorProvider extends Provider {\n addVector(ctx: Context, request: AddVectorRequest): Promise<AddVectorResponse>;\n searchVectors(ctx: Context, request: SearchVectorRequest): Promise<SearchVectorResponse>;\n removeVector(ctx: Context, request: RemoveVectorRequest): Promise<RemoveVectorResponse>;\n getVector?(ctx: Context, request: GetVectorRequest): Promise<GetVectorResponse | null>;\n}\n","/**\n * Task Group Domain Types\n *\n * Source of truth for task group types.\n * Groups organize related tasks into features/initiatives that can be executed together.\n */\n\n// =============================================================================\n// Entity Types\n// =============================================================================\n\nexport interface TaskGroup {\n id: string;\n userId: string;\n workspaceId: string;\n name: string;\n description: string | null;\n /** Max tasks to run in parallel when executing group. Default 1 (sequential). */\n parallelism: number;\n createdAt: string;\n updatedAt: string;\n}\n\n// =============================================================================\n// Request Types\n// =============================================================================\n\nexport interface CreateTaskGroupRequest {\n name: string;\n description?: string;\n workspaceId?: string;\n parallelism?: number;\n}\n\nexport interface UpdateTaskGroupRequest {\n name?: string;\n description?: string | null;\n parallelism?: number;\n}\n","/**\n * Automation Domain Types\n *\n * Automations are recurring or event-driven triggers that launch agent tasks.\n * Today only the \"schedule\" type exists (cron-based). Future types may include\n * \"webhook\" or \"event\".\n *\n * The shape of `config` is determined by `type`.\n */\n\nimport type { ThinkingConfig } from \"../agents/llm.types\";\nimport type { RepoConfig } from \"./task.types\";\n\n// =============================================================================\n// Enums / Unions\n// =============================================================================\n\nexport type AutomationType = \"schedule\";\n\nexport type AutomationStatus = \"active\" | \"paused\" | \"error\";\n\n// =============================================================================\n// Config Types — shape depends on AutomationType\n// =============================================================================\n\n/** Config for the \"schedule\" automation type (cron-triggered) */\nexport interface ScheduleAutomationConfig {\n prompt: string;\n cronExpression: string;\n timezone: string;\n repo?: RepoConfig;\n tools?: string[];\n model?: string;\n thinking?: ThinkingConfig;\n [key: string]: unknown;\n}\n\nexport type AutomationConfig = ScheduleAutomationConfig;\n\n// =============================================================================\n// Entity Type\n// =============================================================================\n\nexport interface Automation {\n id: string;\n userId: string;\n workspaceId: string;\n name: string;\n type: AutomationType;\n config: AutomationConfig;\n status: AutomationStatus;\n lastRunAt: string | null;\n nextRunAt: string | null;\n lastError: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n// =============================================================================\n// Workflow context metadata\n// =============================================================================\n\n/** Workflow `ctx.metadata` shape carrying the automation that triggered the\n * run. Workflows check `metadata?.automation` to detect \"this run was\n * triggered automatically\" (e.g. force `mode: auto`, no human approvals). */\nexport interface AutomationContextMetadata {\n automation?: { id: string };\n [key: string]: unknown;\n}\n","/**\n * Workspace Domain Types\n *\n * Source of truth for workspace types.\n * Workspaces organize tasks, connectors, and schedules into project contexts.\n */\n\n// =============================================================================\n// Entity Types\n// =============================================================================\n\nexport interface Workspace {\n id: string;\n userId: string;\n name: string;\n description: string | null;\n icon: string | null;\n color: string | null;\n repos: WorkspaceRepo[];\n settings: WorkspaceSettings;\n createdAt: string;\n updatedAt: string;\n}\n\n// =============================================================================\n// Config Types\n// =============================================================================\n\nexport interface WorkspaceRepo {\n owner: string;\n name: string;\n provider?: string;\n path?: string;\n}\n\nexport interface WorkspaceSettings {\n defaultBranch?: string;\n defaultEnv?: string;\n [key: string]: unknown;\n}\n\n// Request shapes live with the service — see packages/workspaces/src/workspaces.types.ts.\n\n// =============================================================================\n// Member Types\n// =============================================================================\n\nexport type WorkspaceMemberStatus = \"pending\" | \"active\" | \"declined\";\n\nexport interface WorkspaceMember {\n id: string;\n workspaceId: string;\n userId: string | null;\n email: string;\n status: WorkspaceMemberStatus;\n joinedAt: string | null;\n createdAt: string;\n}\n","export * from \"./cache.types\";\nexport * from \"./chat.types\";\nexport * from \"./db.types\";\nexport * from \"./embedding.types\";\nexport * from \"./field.types\";\nexport * from \"./notification.types\";\nexport * from \"./store.types\";\nexport * from \"./sync.types\";\nexport * from \"./table.types\";\nexport * from \"./task.types\";\nexport * from \"./usage.types\";\nexport * from \"./user.types\";\nexport * from \"./vector.types\";\nexport * from \"./group.types\";\nexport * from \"./automation.types\";\nexport * from \"./workspace.types\";\n","/**\n * Channel Types\n *\n * ChannelProvider — low-level messaging API client for a platform\n * (Slack, WhatsApp, CLI, Discord, etc.).\n *\n * Lives in provider packages (e.g., @jarvis/slack), reuses connector auth.\n * Each provider defines its own artifact renderers for platform-native format.\n *\n * Injected via `providers.channel` — same DI pattern as db, llm, storage.\n * Default channel hooks in run() auto-use the provider when present.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// CHANNEL PROVIDER\n// =============================================================================\n\n/**\n * ChannelProvider — low-level API client for a messaging platform.\n *\n * Each implementation knows how to send messages in its platform's format.\n * Artifact renderers convert agent artifacts to platform-native content\n * (Slack blocks, WhatsApp formatted text, Discord embeds, etc.).\n */\nexport interface ChannelProvider extends Provider {\n /** Send a text message */\n sendText(\n ctx: Context,\n req: { text: string },\n ): Promise<void>;\n\n /** Send rich content (blocks, embeds, etc. — platform-native format) */\n sendRich(\n ctx: Context,\n req: { content: unknown },\n ): Promise<void>;\n\n /**\n * Send interactive prompt and wait for user response.\n * Platform decides the UX (Slack buttons, WhatsApp quick replies, CLI readline).\n */\n prompt(\n ctx: Context,\n req: { text: string; actions: string[] },\n ): Promise<string>;\n\n /**\n * Artifact renderers — convert artifact data to platform-native format.\n * Keyed by artifact type (e.g., \"goal\", \"todo-list\").\n * Unknown types fall back to JSON.stringify via default channel hooks.\n */\n artifacts?: {\n renderer: Record<string, (data: unknown) => unknown>;\n };\n}\n","/**\n * Event Types\n *\n * EventProvider enables apps to publish real-time events from fn() functions.\n * Events are scoped to the app (channel auto-prefixed with app:{appId}:)\n * and delivered to clients via SSE or WebSocket.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// EVENT PROVIDER\n// =============================================================================\n\n/**\n * EventProvider — publish real-time events from server-side functions.\n *\n * Channels are auto-scoped to `app:{appId}:` on the Node.js side,\n * so app code only specifies the channel name without the prefix.\n *\n * Implementations:\n * - eventProvider (Redis pub/sub backed)\n */\nexport interface EventProvider extends Provider {\n /** Publish an event to an app-scoped channel */\n publish(\n ctx: Context,\n req: {\n /** Channel name (auto-prefixed with app:{appId}:) */\n channel: string;\n /** Event payload */\n event: Record<string, unknown>;\n },\n ): Promise<void>;\n}\n","/**\n * PubSub Provider Types\n *\n * Generic publish/subscribe message passing.\n * Backend-agnostic — can be implemented by Redis, NATS, etc.\n *\n * All methods follow the canonical `(ctx, req) => resp` signature. Messages\n * on the wire are envelopes `{ ctx, payload }` so subscribers receive the\n * originating user context alongside the data.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n/** Wire-level envelope for every pub/sub message. */\nexport interface PubSubEnvelope<P = unknown> {\n ctx: Context;\n payload: P;\n}\n\nexport interface Publisher {\n publish(ctx: Context, req: { channel: string; payload: unknown }): Promise<void>;\n close(ctx: Context): Promise<void>;\n}\n\n/** Subscriber callback receives the originating ctx + typed payload. */\nexport type SubscribeCallback<P = unknown> = (\n ctx: Context,\n req: { payload: P; channel: string },\n) => void;\n\nexport type SubscribeRequest<P = unknown> =\n | {\n channel: string;\n callback: SubscribeCallback<P>;\n onError?: (error: Error) => void;\n }\n | {\n pattern: string;\n callback: SubscribeCallback<P>;\n onError?: (error: Error) => void;\n };\n\nexport interface Subscriber {\n subscribe<P = unknown>(ctx: Context, req: SubscribeRequest<P>): Promise<void>;\n unsubscribe(ctx: Context, req?: { channel?: string }): Promise<void>;\n close(ctx: Context): Promise<void>;\n}\n\nexport interface PubSubProvider extends Provider {\n /** Singleton publisher (reused across callers) */\n publisher(ctx: Context): Promise<Publisher>;\n /** New subscriber per caller (each consumer gets its own connection) */\n subscriber(ctx: Context): Promise<Subscriber>;\n}\n","/**\n * JSON-RPC 2.0 envelope types + RPC method handler + public client shape.\n *\n * Wire format matches the spec: requests carry an `id`, notifications don't;\n * responses echo the request `id`. Errors use standard codes (-32600..-32603,\n * -32700); the reserved -32000..-32099 range is used for application errors,\n * with domain meaning on `error.data.kind`.\n */\n\nimport type { Context } from \"../core/context.types\";\n\n// =============================================================================\n// JSON-RPC 2.0\n// =============================================================================\n\nexport type JsonRpcId = string | number;\n\n/**\n * A JSON-RPC 2.0 request. Same on-wire shape whether it expects a reply\n * (request — `id` present) or not (event — `id` absent). `ctx` is a\n * non-standard top-level field the platform uses to propagate caller\n * provenance (userId, requestId, timestamp, tracing baggage). The hub\n * NEVER trusts `ctx` for a client-role frame; it's resolved via\n * `requireContext(auth, frame)` at the connection boundary.\n */\nexport interface JsonRpcRequest<TParams = unknown> {\n jsonrpc: \"2.0\";\n id?: JsonRpcId;\n method: string;\n params?: TParams;\n ctx?: Context;\n}\n\nexport interface JsonRpcSuccess<TResult = unknown> {\n jsonrpc: \"2.0\";\n id: JsonRpcId;\n result: TResult;\n}\n\nexport interface JsonRpcError {\n jsonrpc: \"2.0\";\n id: JsonRpcId | null;\n error: { code: number; message: string; data?: unknown };\n}\n\nexport type JsonRpcMessage = JsonRpcRequest | JsonRpcSuccess | JsonRpcError;\n\n// =============================================================================\n// Standard + application error codes\n// =============================================================================\n\nexport const JSON_RPC = {\n // JSON-RPC 2.0 standard\n PARSE_ERROR: -32700,\n INVALID_REQUEST: -32600,\n METHOD_NOT_FOUND: -32601,\n INVALID_PARAMS: -32602,\n INTERNAL_ERROR: -32603,\n\n // Application range (-32000..-32099 reserved by spec for implementations)\n APPLICATION_ERROR: -32000,\n UNAUTHORIZED: -32001,\n FORBIDDEN: -32003,\n RATE_LIMITED: -32009,\n} as const;\n\n/** Application errors carry their domain meaning on `error.data.kind`. */\nexport interface RpcErrorData {\n kind: string; // \"provider_offline\" | \"ask_timeout\" | \"rate_limited\" | …\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Handler signatures\n// =============================================================================\n\nexport type RpcMethodHandler<TReq = unknown, TResp = unknown> = (\n ctx: Context,\n req: TReq,\n options?: { signal?: AbortSignal },\n) => Promise<TResp>;\n\nexport interface RpcMethodDefinition<TReq = unknown, TResp = unknown> {\n name: string;\n /** Runtime validator — return the typed request or throw. Zod isn't a dep\n * yet, so this is a hand-rolled predicate. */\n validate?: (params: unknown) => TReq;\n handler: RpcMethodHandler<TReq, TResp>;\n}\n\n// =============================================================================\n// Public client API\n// =============================================================================\n\nexport interface RpcClient {\n call<TResp = unknown>(\n ctx: Context,\n req: { method: string; params?: unknown },\n options?: { timeoutMs?: number; signal?: AbortSignal },\n ): Promise<TResp>;\n\n subscribe<TPayload = unknown>(\n ctx: Context,\n req: { topic: string },\n options: { onPayload: (payload: TPayload) => void },\n ): () => void;\n}\n","/**\n * Stream types — shared across platform stream features.\n *\n * Used by API routes, stream pages, and hooks.\n */\n\n/** Participant info sent with join signals and shared across peers */\nexport interface StreamParticipant {\n /** Unique per-connection ID (same user can join from multiple devices) */\n peerId: string;\n /** User account ID (may be same across devices) */\n userId?: string;\n /** Device-level stream ID (userId:instanceUUID) — the stream this participant produces */\n deviceId?: string;\n /** Display name */\n displayName: string;\n /** Avatar image URL */\n avatarUrl?: string;\n /** Hex color for waveform visualization (server-assigned, unique per session) */\n color?: string;\n /** Audio source type */\n source?: \"mic\" | \"daw\" | \"system\";\n /** Device type */\n device?: \"web\" | \"mobile\" | \"plugin\";\n}\n\n// ── Signal Message Protocol ──────────────────────────────────────────────────\n// Discriminated union: every message is { type, payload }.\n// Used by WS server, browser hooks, and plugin SignalingClient.\n\nexport interface ReadyPayload {\n color?: string;\n}\n\nexport interface JoinPayload {\n target: string;\n peerId: string;\n participant: StreamParticipant;\n}\n\nexport interface LeavePayload {\n target: string;\n peerId: string;\n}\n\nexport interface OfferPayload {\n target: string;\n peerId: string;\n sdp: string;\n}\n\nexport interface AnswerPayload {\n target: string;\n peerId: string;\n sdp: string;\n}\n\nexport interface IceCandidatePayload {\n target: string;\n peerId: string;\n candidate: { candidate: string; sdpMid?: string | null; sdpMLineIndex?: number | null };\n}\n\nexport interface MetadataUpdatePayload {\n sampleRate: number;\n channels: number;\n bitrate: number;\n}\n\nexport interface StreamEndedPayload {}\n\n/** Admission gate — waiting room protocol */\nexport interface WaitingPayload { position?: number; }\nexport interface AdmittedPayload {}\nexport interface RejectedPayload { reason?: string; }\nexport interface AdmitRequestPayload { peerId: string; displayName: string; }\n\n/** Peer mesh orchestration — jam workflow broadcasts these to coordinate P2P connections */\nexport interface PeerListPayload {\n peers: Array<{ peerId: string; deviceId?: string; displayName: string; color?: string }>;\n}\nexport interface PeerJoinedPayload {\n peerId: string;\n deviceId?: string;\n displayName: string;\n color?: string;\n}\nexport interface PeerLeftPayload {\n peerId: string;\n}\n\ninterface Message<T extends string, P> {\n type: T;\n payload: P;\n}\n\nexport type ReadyMessage = Message<\"ready\", ReadyPayload>;\nexport type JoinMessage = Message<\"join\", JoinPayload>;\nexport type LeaveMessage = Message<\"leave\", LeavePayload>;\nexport type OfferMessage = Message<\"offer\", OfferPayload>;\nexport type AnswerMessage = Message<\"answer\", AnswerPayload>;\nexport type IceCandidateMessage = Message<\"ice-candidate\", IceCandidatePayload>;\nexport type MetadataUpdateMessage = Message<\"metadata-update\", MetadataUpdatePayload>;\nexport type StreamEndedMessage = Message<\"stream-ended\", StreamEndedPayload>;\nexport type WaitingMessage = Message<\"waiting\", WaitingPayload>;\nexport type AdmittedMessage = Message<\"admitted\", AdmittedPayload>;\nexport type RejectedMessage = Message<\"rejected\", RejectedPayload>;\nexport type AdmitRequestMessage = Message<\"admit-request\", AdmitRequestPayload>;\nexport type PeerListMessage = Message<\"peer-list\", PeerListPayload>;\nexport type PeerJoinedMessage = Message<\"peer-joined\", PeerJoinedPayload>;\nexport type PeerLeftMessage = Message<\"peer-left\", PeerLeftPayload>;\n\nexport type SignalMessage =\n | ReadyMessage\n | JoinMessage\n | LeaveMessage\n | OfferMessage\n | AnswerMessage\n | IceCandidateMessage\n | MetadataUpdateMessage\n | StreamEndedMessage\n | WaitingMessage\n | AdmittedMessage\n | RejectedMessage\n | AdmitRequestMessage\n | PeerListMessage\n | PeerJoinedMessage\n | PeerLeftMessage;\n\n// ── Stream Metadata (generic base + per-transport extensions) ────────────────\n\n/** Transport type discriminator */\nexport type StreamTransport = \"webrtc\" | \"sse\" | \"ws\";\n\n/** Generic stream metadata — all streams have these */\nexport interface StreamMetadata {\n streamId: string;\n transport: StreamTransport;\n title: string;\n status: \"active\" | \"completed\";\n access: \"public\" | \"private\";\n userId: string;\n appId?: string;\n token?: string;\n createdAt: string;\n /** App-specific data — anything the app wants to store */\n metadata?: Record<string, unknown>;\n}\n\n/** WebRTC stream — extends with audio parameters */\nexport interface WebRTCStreamMetadata extends StreamMetadata {\n transport: \"webrtc\";\n contentType: string;\n sampleRate?: number;\n channels?: number;\n bitrate?: number;\n}\n\n/** SSE stream */\nexport interface SSEStreamMetadata extends StreamMetadata {\n transport: \"sse\";\n}\n\n/** WebSocket stream */\nexport interface WSStreamMetadata extends StreamMetadata {\n transport: \"ws\";\n}\n\n/** Any stream metadata (union of all transport types) */\nexport type AnyStreamMetadata =\n | WebRTCStreamMetadata\n | SSEStreamMetadata\n | WSStreamMetadata;\n\n// ── Signal Channels — Redis pub/sub (only thing left in Redis) ──────────────\n\nexport const signalChannels = {\n broadcast: (streamId: string) => `signal:${streamId}:broadcast` as const,\n producer: (streamId: string) => `signal:${streamId}:producer` as const,\n consumer: (streamId: string, peerId: string) => `signal:${streamId}:consumer:${peerId}` as const,\n} as const;\n\n// ── Stream Provider ─────────────────────────────────────────────────────────\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n/**\n * StreamProvider — programmatic stream management from fn().\n *\n * Wraps TransportProvider for delivery and Redis for metadata/lifecycle.\n * Apps get a unified API — transport is an implementation detail.\n */\nexport interface StreamProvider extends Provider {\n /** Create a new stream — picks the right transport internally */\n create(\n ctx: Context,\n req: {\n transport: \"webrtc\" | \"sse\" | \"ws\";\n /** Device-level ID (e.g. userId:instanceUUID). Used as streamId when provided. Falls back to ctx.userId. */\n deviceId?: string;\n title?: string;\n access?: \"public\" | \"private\";\n metadata?: Record<string, unknown>;\n /** Audio params (WebRTC streams) */\n contentType?: string;\n sampleRate?: number;\n channels?: number;\n bitrate?: number;\n },\n ): Promise<{ streamId: string; token: string }>;\n\n /** End/complete a stream */\n end(ctx: Context, req: { streamId: string }): Promise<void>;\n\n /** Get stream metadata */\n get(\n ctx: Context,\n req: { streamId: string },\n ): Promise<StreamMetadata | null>;\n\n /** List active streams */\n list(\n ctx: Context,\n req?: {\n transport?: \"webrtc\" | \"sse\" | \"ws\";\n userId?: string;\n },\n ): Promise<StreamMetadata[]>;\n\n /** Publish event to a stream's channel (SSE/WS types) */\n publish(\n ctx: Context,\n req: {\n streamId: string;\n event: Record<string, unknown>;\n },\n ): Promise<void>;\n\n /** Add a participant to a stream */\n addParticipant(\n ctx: Context,\n req: { streamId: string; participant: StreamParticipant },\n ): Promise<void>;\n\n /** Remove a participant from a stream */\n removeParticipant(\n ctx: Context,\n req: { streamId: string; peerId: string },\n ): Promise<void>;\n\n /** Get participants for a stream */\n getParticipants(\n ctx: Context,\n req: { streamId: string },\n ): Promise<StreamParticipant[]>;\n}\n","export * from \"./channel.types\";\nexport * from \"./event.types\";\nexport * from \"./pubsub.types\";\nexport * from \"./rpc.types\";\nexport * from \"./stream.types\";\n","/**\n * Auth Types\n *\n * Pluggable authentication for external service integrations.\n * Decoupled from connectors — can be reused by any subsystem needing auth.\n *\n * Factory implementations: oauth(), token(), apiKey()\n */\n\nimport type { HttpRequestConfig } from \"./http.types\";\n\n// =============================================================================\n// CREDENTIALS\n// =============================================================================\n\n/** Decrypted credentials for authenticating with an external service */\nexport interface AuthCredentials {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string | null;\n extra?: Record<string, string>;\n}\n\n// =============================================================================\n// OAUTH META\n// =============================================================================\n\n/** OAuth flow metadata — used by the platform to identify an OAuth provider */\nexport interface OAuthMetadata {\n provider: string;\n scopes: string[];\n accessType?: string;\n prompt?: string;\n}\n\n// =============================================================================\n// AUTH PROVIDER\n// =============================================================================\n\n/** Pluggable auth provider — created by oauth(), token(), apiKey() factories */\nexport interface AuthProvider {\n readonly type: \"oauth\" | \"token\" | \"apiKey\" | \"custom\";\n readonly baseUrl?: string;\n /** Intercept HTTP requests to inject auth headers/params */\n intercept(\n config: HttpRequestConfig,\n credentials: AuthCredentials,\n ): HttpRequestConfig;\n /** Refresh expired credentials. Returns updated credentials or undefined. */\n refresh?(credentials: AuthCredentials): Promise<AuthCredentials | undefined>;\n /** Check if credentials represent a connected state */\n isConnected(credentials: AuthCredentials): boolean;\n /** OAuth flow metadata — present only for OAuth providers */\n readonly oauth?: OAuthMetadata;\n}\n\n// =============================================================================\n// AUTH FACTORY CONFIGS\n// =============================================================================\n\n/** Config for legacy OAuthProviderConfig factory — OAuth 2.0 providers */\nexport interface OAuthProviderConfig extends OAuthMetadata {\n tokenEndpoint: string;\n clientId: string | (() => string);\n clientSecret: string | (() => string);\n baseUrl?: string;\n /** Override default Bearer token interceptor */\n intercept?: (\n config: HttpRequestConfig,\n creds: AuthCredentials,\n ) => HttpRequestConfig;\n}\n\n/** Config for token() factory — long-lived tokens */\nexport interface TokenProviderConfig {\n baseUrl?: string;\n /** Override default Bearer token interceptor */\n intercept?: (\n config: HttpRequestConfig,\n creds: AuthCredentials,\n ) => HttpRequestConfig;\n}\n\n/** Config for apiKey() factory — API key auth */\nexport interface ApiKeyProviderConfig {\n baseUrl?: string;\n /** Where to place the API key. Default: \"header\" */\n placement?: \"header\" | \"query\";\n /** Header name when placement is \"header\". Default: \"X-API-Key\" */\n headerName?: string;\n /** Query param name when placement is \"query\". Default: \"api_key\" */\n paramName?: string;\n}\n\n// =============================================================================\n// OAUTH (connect-time + runtime unified)\n// =============================================================================\n\n/** Standardized tokens from code exchange */\nexport interface OAuthTokens {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n scopes: string[];\n /** Provider-specific extra fields (e.g., pageAccessToken, igUserId, openId) */\n extra?: Record<string, unknown>;\n}\n\n/** Standardized user profile after OAuth */\nexport interface OAuthProfile {\n accountId: string;\n displayName: string;\n email?: string;\n profileImageUrl?: string;\n /** Provider-specific metadata (e.g., { instagram, facebookPage }) */\n metadata?: Record<string, unknown>;\n}\n\n/** Result of OAuthProvider.exchangeCode() */\nexport interface OAuthExchange {\n tokens: OAuthTokens;\n profile?: OAuthProfile;\n /** Extra metadata from afterExchange hook */\n metadata?: Record<string, unknown>;\n}\n\n/** OAuth configuration — pure data describing a standard OAuth 2.0 provider */\nexport interface OAuthConfig {\n /** Authorization endpoint URL */\n authorizationUrl: string;\n /** Token exchange endpoint URL */\n tokenUrl: string;\n /** Client ID (or client_key for TikTok) */\n clientId: string;\n /** Client secret */\n clientSecret: string;\n /** Redirect URI */\n redirectUri: string;\n /** OAuth scopes */\n scopes: string[];\n}\n\n/** Optional behavior overrides for custom OAuth providers */\nexport interface OAuthOptions {\n /** Override: build authorization URL.\n * Default: standard OAuth 2.0 (client_id, response_type=code, redirect_uri, scope, state).\n * Return codeVerifier if PKCE is used. */\n buildAuthUrl?(state: string): { url: string; codeVerifier?: string };\n\n /** Override: exchange authorization code for tokens.\n * Default: POST to tokenUrl with client_id, client_secret, code, redirect_uri in body. */\n exchangeCode?(code: string, codeVerifier?: string): Promise<OAuthTokens>;\n\n /** Hook: post-exchange processing (e.g., Meta's short→long-lived token swap).\n * Called after exchangeCode, receives tokens, returns updated tokens + optional metadata. */\n afterExchange?(tokens: OAuthTokens): Promise<{ tokens: OAuthTokens; metadata?: Record<string, unknown> }>;\n\n /** Hook: fetch user profile after successful exchange. */\n fetchProfile?(accessToken: string): Promise<OAuthProfile>;\n}\n\n/**\n * OAuth provider — extends AuthProvider with connect-time methods.\n * Returned by oauth() factory. Handles both:\n * - Connect-time: buildAuthUrl, exchangeCode (sign-in ceremony)\n * - Runtime: intercept, refresh, isConnected (HTTP auth + token refresh)\n */\nexport interface OAuthProvider extends AuthProvider {\n /** Build authorization redirect URL. Returns codeVerifier when PKCE is used. */\n buildAuthUrl(state: string): { url: string; codeVerifier?: string };\n /** Exchange authorization code for tokens + profile */\n exchangeCode(code: string, codeVerifier?: string): Promise<OAuthExchange>;\n}\n\n// =============================================================================\n// AUTHORIZATION (RBAC)\n// =============================================================================\n\n/** What is required to access a resource */\nexport interface AuthorizationConfig {\n /** Required roles (user must have at least one). Omit = no role check. */\n roles?: string[];\n /** Required plan tiers (e.g., [\"pro\", \"enterprise\"]). Omit = all tiers allowed. */\n tiers?: string[];\n}\n","/**\n * Connector Types\n *\n * Connectors are external service integrations (Google Calendar, Spotify, etc.).\n * Auth is handled by platform providers. Sync is executed via Temporal workflows.\n *\n * Inspired by:\n * - Nango: syncs vs actions, fully managed auth\n * - Fivetran: cursor state for incremental sync\n * - Airbyte: declarative config, separation of declaration from execution\n */\n\nimport type { OAuthProvider } from \"./auth.types\";\nimport type { SecretsProvider } from \"./secrets.types\";\n\nimport type { Context } from \"../core/context.types\";\nimport type { McpServerCapabilities, McpTransport } from \"../agents/mcp.types\";\n\n// =============================================================================\n// CORE TYPES\n// =============================================================================\n\nexport type ConnectorType =\n | \"google_calendar\"\n | \"meta\"\n | \"youtube\"\n | \"spotify\"\n | \"tiktok\"\n | \"slack\"\n | \"github\"\n | \"openai\"\n | \"anthropic\"\n | \"google_gemini\"\n | string;\n\nexport type ConnectorStatus =\n | \"connected\"\n | \"disconnected\"\n | \"pending\"\n | \"error\";\n\n// =============================================================================\n// AUTH CONFIGURATION\n// =============================================================================\n\n/** How an external connector authenticates with its service */\nexport type ConnectorAuthConfig =\n | {\n type: \"oauth\";\n providerId: string;\n scopes: string[];\n provider?: OAuthProvider;\n }\n | {\n type: \"apiKey\";\n label?: string;\n placeholder?: string;\n validate?: (key: string) => Promise<string | null>;\n }\n | { type: \"token\"; label?: string; placeholder?: string }\n | { type: \"none\" };\n\n// =============================================================================\n// SYNC CONFIGURATION\n// =============================================================================\n\n/** Sync configuration — workflow paths and scheduling */\nexport interface ConnectorSyncConfig {\n /** Pull workflow path — fetches external data into local entities */\n pull?: string;\n /** Push workflow path — sends local changes to external service */\n push?: string;\n /** Cron schedule for automatic sync (e.g., \"0/15 * * * *\") */\n cron?: string;\n}\n\n// =============================================================================\n// CONNECTOR DEPS (DI)\n// =============================================================================\n\n/** Dependencies injected into connector lifecycle methods */\nexport interface ConnectorDeps {\n secrets: SecretsProvider;\n onConnect?(metadata?: Record<string, unknown>): Promise<void>;\n onDisconnect?(): Promise<void>;\n}\n\n/** Unified result from connect() */\nexport type ConnectResult =\n | { action: \"redirect\"; url: string; codeVerifier?: string }\n | { action: \"connected\" }\n | { action: \"error\"; message: string };\n\n// =============================================================================\n// CONNECTOR FACTORY TYPES\n// =============================================================================\n\n/**\n * Configuration input for connector() factory.\n *\n * @example\n * ```typescript\n * connector({ type: \"google_calendar\", name: \"Google Calendar\", auth: { type: \"oauth\", ... } })\n * ```\n */\nexport interface ConnectorConfig {\n /** Unique connector type identifier */\n type: ConnectorType;\n /** Human-readable name */\n name: string;\n /** Lucide icon name */\n icon?: string;\n /** Theme color */\n color?: string;\n /** Description */\n description?: string;\n /** Sync configuration */\n sync?: ConnectorSyncConfig;\n /** Semantic version */\n version?: string;\n /** Auth method (OAuth, API key, token) */\n auth?: ConnectorAuthConfig;\n}\n\n/** Connector definition — the resolved output of connector() or .configure() */\nexport interface ConnectorDefinition {\n type: ConnectorType;\n name: string;\n icon?: string;\n color?: string;\n description?: string;\n sync?: ConnectorSyncConfig;\n version?: string;\n /** Auth method */\n auth?: ConnectorAuthConfig;\n}\n\n// =============================================================================\n// CONNECTOR INSTANCE (rich object with helper methods)\n// =============================================================================\n\n/** Options for .configure() — what an app provides when setting up a connector */\nexport interface ConnectorConfigureConfig {\n /** Override display name */\n name?: string;\n /** Override description */\n description?: string;\n /** Sync configuration — pull/push workflows + cron */\n sync?: ConnectorSyncConfig;\n /** Auth overrides — scopes are merged with base connector scopes */\n auth?: { scopes?: string[] };\n}\n\n/**\n * Rich connector object returned by connector().\n * Extends ConnectorDefinition with lifecycle methods.\n *\n * @example\n * ```typescript\n * // Platform defines:\n * export const googleCalendarConnector = connector({ type: \"google_calendar\", ... });\n *\n * // App configures sync:\n * export default googleCalendarConnector.configure({\n * sync: { pull: \"./workflows/pull.workflow\", push: \"./workflows/push.workflow\", cron: \"...\" },\n * });\n *\n * // Routes call lifecycle methods:\n * await connector.connect(ctx, { state }, deps);\n * await connector.disconnect(ctx, {}, deps);\n * ```\n */\nexport interface ConnectorInstance extends ConnectorDefinition {\n /** Configure sync for an app — returns a ConnectorDefinition for the app's connectors[] array */\n configure(config: ConnectorConfigureConfig): ConnectorDefinition;\n\n /** Initiate auth — OAuth returns redirect, API key/token stores credential */\n connect(\n ctx: Context,\n req: { state?: string; credential?: string },\n deps: ConnectorDeps,\n ): Promise<ConnectResult>;\n\n /** Exchange OAuth authorization code for tokens (OAuth callback) */\n exchangeCode(\n ctx: Context,\n req: { code: string; codeVerifier?: string },\n deps: ConnectorDeps,\n ): Promise<void>;\n\n /** Disconnect — clear credentials and notify */\n disconnect(\n ctx: Context,\n req: Record<string, never>,\n deps: ConnectorDeps,\n ): Promise<void>;\n}\n\n// =============================================================================\n// CONNECTOR SOURCE & SYNC STATUS\n// =============================================================================\n\n/** How the connector integrates — MCP protocol, OAuth API, or raw API */\nexport type ConnectorSource = \"mcp\" | \"oauth\" | \"api\";\n\n/** Capability sync status (for MCP connectors) */\nexport type ConnectorSyncStatus = \"pending\" | \"syncing\" | \"synced\" | \"error\";\n\n// =============================================================================\n// SOURCE-SPECIFIC METADATA\n// =============================================================================\n\n/** MCP connector metadata — transport + cached capabilities */\nexport interface McpConnectorConfig {\n transport: McpTransport;\n capabilities?: McpServerCapabilities;\n syncStatus: ConnectorSyncStatus;\n syncedAt?: string;\n syncError?: string;\n}\n\n/** OAuth connector metadata — auth state + account info */\nexport interface OAuthConnectorConfig {\n authType: \"oauth\";\n accountId?: string;\n displayName?: string;\n status: ConnectorStatus;\n}\n\n/** API connector metadata — auth state */\nexport interface ApiConnectorConfig {\n authType: \"api-key\" | \"token\";\n status: ConnectorStatus;\n}\n\n/** Data sync state (for connectors that pull/push data) */\nexport interface ConnectorSyncState {\n /** Freeform sync state — cursors, page tokens, incremental markers */\n state?: Record<string, unknown>;\n lastSyncedAt?: string;\n}\n\n// =============================================================================\n// CONNECTOR RECORD (unified DB entity)\n// =============================================================================\n\n/**\n * Unified connector record — single entity for MCP servers, OAuth integrations, and API connectors.\n * Source-specific data is grouped into `mcp`, `auth`, and `sync` sub-objects.\n */\nexport interface Connector {\n id: string;\n name: string;\n description?: string;\n source: ConnectorSource;\n enabled: boolean;\n\n /** MCP config — transport, cached capabilities (when source === \"mcp\") */\n mcp?: McpConnectorConfig;\n\n /** Auth config — OAuth/API key state (when source === \"oauth\" | \"api\") */\n auth?: OAuthConnectorConfig | ApiConnectorConfig;\n\n /** Data sync state — cursors, last sync time (when connector syncs data) */\n sync?: ConnectorSyncState;\n\n createdAt: string;\n updatedAt: string;\n}\n","/**\n * HTTP Types\n *\n * HTTP client, request config, and error types.\n * Used by connectors, auth providers, and any subsystem making HTTP calls.\n */\n\nimport type { Context } from \"../core/context.types\";\n\n// =============================================================================\n// HTTP ERROR\n// =============================================================================\n\nexport class HttpError extends Error {\n status: number;\n details?: unknown;\n constructor(status: number, message: string, details?: unknown) {\n super(message);\n this.status = status;\n this.details = details;\n }\n}\n\n// =============================================================================\n// HTTP CONFIG\n// =============================================================================\n\n/** HTTP config passed through interceptor chains */\nexport interface HttpRequestConfig {\n headers: Record<string, string>;\n params?: Record<string, string>;\n}\n\n/** Request object for Http client methods */\nexport interface HttpRequest {\n url: string;\n data?: unknown;\n params?: Record<string, string>;\n}\n\n/** Options for Http client methods */\nexport interface HttpOptions {\n /** Additional headers (merged with interceptor-injected headers) */\n headers?: Record<string, string>;\n}\n\n// =============================================================================\n// HTTP CLIENT\n// =============================================================================\n\n/** Pre-wired HTTP client with (ctx, req, options) signature */\nexport interface HttpProvider {\n get<T = unknown>(\n ctx: Context,\n req: HttpRequest,\n options?: HttpOptions,\n ): Promise<T>;\n post<T = unknown>(\n ctx: Context,\n req: HttpRequest,\n options?: HttpOptions,\n ): Promise<T>;\n put<T = unknown>(\n ctx: Context,\n req: HttpRequest,\n options?: HttpOptions,\n ): Promise<T>;\n patch<T = unknown>(\n ctx: Context,\n req: HttpRequest,\n options?: HttpOptions,\n ): Promise<T>;\n delete<T = unknown>(\n ctx: Context,\n req: HttpRequest,\n options?: HttpOptions,\n ): Promise<T>;\n}\n","/**\n * Secrets Types\n *\n * Type-safe encrypted credential storage.\n * Conceptual model: {scope}.{type} — e.g. google_calendar.oauth, openai.token\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// Secret Types\n// =============================================================================\n\n/** Known secret types — open union allows custom types too */\nexport type SecretType =\n | \"oauth\"\n | \"token\"\n | \"apiKey\"\n | \"password\"\n | \"credential\"\n | (string & {});\n\n/** OAuth credential bundle (stored as encrypted JSON) */\nexport interface OAuthCredentials {\n accessToken: string;\n refreshToken?: string | null;\n expiresAt?: string | null;\n tokenScope?: string | null;\n /** Platform-specific credential fields (e.g., pageAccessToken, igUserId) */\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Request / Response Types\n// =============================================================================\n\n/** Set request — oauth requires OAuthCredentials, everything else is string */\nexport type SetSecretRequest =\n | {\n scope: string;\n type: \"oauth\";\n value: OAuthCredentials;\n metadata?: Record<string, unknown>;\n expiresAt?: Date;\n }\n | {\n scope: string;\n type: Exclude<SecretType, \"oauth\"> | (string & {});\n value: string;\n metadata?: Record<string, unknown>;\n expiresAt?: Date;\n };\n\n/** Get result — oauth returns OAuthCredentials, everything else returns string */\nexport type GetSecretResult<T extends string> = T extends \"oauth\"\n ? OAuthCredentials | null\n : string | null;\n\n/** Metadata for a stored secret (no decrypted value) */\nexport interface SecretMetadata {\n scope: string;\n type: string;\n metadata: Record<string, unknown>;\n expiresAt: string | null;\n}\n\n// =============================================================================\n// Provider\n// =============================================================================\n\n/** Secrets provider — encrypted credential storage with auto-encrypt/decrypt */\nexport interface SecretsProvider extends Provider {\n /** Store a secret (auto-encrypts). Upserts on (user, scope, type). */\n set(ctx: Context, req: SetSecretRequest): Promise<void>;\n\n /** Retrieve a secret (auto-decrypts). OAuth returns OAuthCredentials, others return string. */\n get<T extends SecretType>(\n ctx: Context,\n req: { scope: string; type: T },\n ): Promise<GetSecretResult<T>>;\n\n /** Check if a secret exists. If type omitted, checks any secret for scope. */\n has(ctx: Context, req: { scope: string; type?: SecretType }): Promise<boolean>;\n\n /** Delete secret(s). If type omitted, deletes all for scope. */\n delete(\n ctx: Context,\n req: { scope: string; type?: SecretType },\n ): Promise<void>;\n\n /** Get metadata for secrets (no decryption). If scope omitted, returns all user's secrets. */\n getMeta(ctx: Context, req?: { scope?: string }): Promise<SecretMetadata[]>;\n}\n","export * from \"./auth.types\";\nexport * from \"./connector.types\";\nexport * from \"./http.types\";\nexport * from \"./secrets.types\";\n","/**\n * Unified Search Types\n *\n * Provides a unified interface for all search capabilities:\n * - Web search (Tavily, OpenAI, etc.)\n * - Vector/semantic search (pgvector, etc.)\n * - Entity/metadata search (text matching on entities)\n * - Hybrid search (combining multiple sources with reranking)\n */\n\nimport { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// Unified Search Item (Common result type)\n// =============================================================================\n\n/**\n * Unified search item - common result type across all search types\n */\nexport interface SearchItem {\n /** Unique identifier */\n id: string;\n\n /** Title or heading */\n title: string;\n\n /** Content snippet */\n content: string;\n\n /** Relevance score (0-1) */\n score: number;\n\n /** Source of the result */\n source: \"web\" | \"vector\" | \"metadata\";\n\n /** Entity type (for entity search) */\n entityType?: string;\n\n /** Entity ID (for entity search) */\n entityId?: string;\n\n /** URL (for web search) */\n url?: string;\n\n /** Additional metadata */\n metadata: Record<string, unknown>;\n\n /** Full entity data (for entity search) */\n data?: unknown;\n}\n\n/**\n * Unified search request\n */\nexport interface SearchRequest {\n /** Search query */\n query: string;\n\n /** Filter by entity types (for entity/vector search) */\n entityTypes?: string[];\n\n /** Maximum results to return */\n limit?: number;\n\n /** Pre-computed embedding — skips re-embedding the query */\n embedding?: number[];\n}\n\n/**\n * Unified search response\n */\nexport interface SearchResponse {\n /** Search results */\n items: SearchItem[];\n}\n\n// =============================================================================\n// Web Search Types (Specific)\n// =============================================================================\n\n/**\n * Web search request\n */\nexport interface SearchWebRequest {\n /** The search query */\n query: string;\n\n /** Optional context about why you're searching (helps get better results) */\n context?: string;\n\n /** Search depth - \"basic\" for quick searches, \"advanced\" for comprehensive results */\n searchDepth?: \"basic\" | \"advanced\";\n\n /** Maximum number of results to return */\n maxResults?: number;\n}\n\n/**\n * Web search response\n */\nexport interface SearchWebResponse {\n /** Original query */\n query: string;\n\n /** Synthesized answer/summary (if requested and available) */\n answer?: string;\n\n /** Individual search results */\n items: SearchItem[];\n\n /** Metadata about the search */\n metadata?: SearchWebMetadata;\n}\n\n/**\n * Search metadata\n */\nexport interface SearchWebMetadata {\n /** Provider that performed the search */\n provider: string;\n\n /** Search duration in milliseconds */\n duration?: number;\n\n /** Total results found (may be more than returned) */\n totalResults?: number;\n}\n\n// =============================================================================\n// Reranking Types\n// =============================================================================\n\n/**\n * Rerank request\n */\nexport interface RerankRequest {\n /** Items to rerank */\n items: SearchItem[];\n\n /** Original query for relevance scoring */\n query: string;\n}\n\n/**\n * Rerank response\n */\nexport interface RerankResponse {\n /** Reranked items */\n items: SearchItem[];\n}\n\n/**\n * RerankProvider - reranks search results using various algorithms\n */\nexport interface RerankProvider extends Provider {\n rerank(request: RerankRequest): Promise<RerankResponse>;\n}\n\n// =============================================================================\n// Provider Interfaces\n// =============================================================================\n\n/**\n * Search provider - unified interface for all search capabilities\n *\n * Implementations can provide one or both methods:\n * - search: For entity/metadata/vector search\n * - searchWeb: For web search\n *\n * Entity services can implement focused web search relevant to their domain.\n *\n * @example\n * ```typescript\n * // Web-only provider (e.g., Tavily)\n * export function tavilyProvider(config): SearchProvider {\n * return {\n * name: \"tavily\",\n * async searchWeb(request) {\n * return await tavily.search(request);\n * },\n * };\n * }\n *\n * // Entity service with both search and optional web search\n * export function tasksService(config): TasksService & SearchProvider {\n * return {\n * name: \"tasks\",\n * entityType: \"task\",\n * async search(request) {\n * // Search tasks by title/description\n * return { items: [...] };\n * },\n * async searchWeb(request) {\n * // Optional: focused web search for task-related content\n * return await webSearch({ ...request, context: \"productivity tasks\" });\n * },\n * // ... other service methods\n * };\n * }\n * ```\n */\nexport interface SearchProvider extends Provider {\n /** Optional: The entity type this provider handles (e.g., \"task\", \"goal\") */\n entityType?: string;\n\n /** Optional: Search entities/vectors (metadata + semantic search) */\n search?(request: SearchRequest): Promise<SearchResponse>;\n\n /** Optional: Search the web */\n searchWeb?(request: SearchWebRequest): Promise<SearchWebResponse>;\n}\n\n// =============================================================================\n// Provider Configuration\n// =============================================================================\n\n/**\n * Base configuration for search providers\n */\nexport interface SearchProviderConfig {\n /** API key for the search provider */\n apiKey?: string;\n}\n","/**\n * Storage Provider Types\n *\n * Types for object storage providers (S3, MinIO, etc.)\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n/**\n * Storage configuration options\n */\nexport interface StorageConfig {\n /** Storage provider type — \"minio\" for local dev, \"s3\" for AWS S3 production */\n provider?: \"minio\" | \"s3\";\n /** S3/MinIO endpoint URL (e.g., http://localhost:9000). Omit for AWS S3. */\n endpoint?: string;\n /** AWS region (default: us-east-1) */\n region?: string;\n /** Access key ID. Omit for IAM role auth. */\n accessKeyId?: string;\n /** Secret access key. Omit for IAM role auth. */\n secretAccessKey?: string;\n /** Bucket name */\n bucket?: string;\n /** Force path style (required for MinIO, default: auto based on endpoint) */\n forcePathStyle?: boolean;\n}\n\n/**\n * Result from getObject operation\n */\nexport interface GetObjectResult {\n /** Readable stream of the object body */\n body: ReadableStream<Uint8Array>;\n /** Content type (MIME type) */\n contentType: string | undefined;\n /** Content length in bytes */\n contentLength: number | undefined;\n /** Content-Range header value (e.g. \"bytes 0-1023/2048\") — present on 206 partial responses */\n contentRange?: string;\n /** Accept-Ranges header value (e.g. \"bytes\") */\n acceptRanges?: string;\n}\n\n/**\n * Result from putObject operation\n */\nexport interface PutObjectResult {\n /** The key of the uploaded object */\n key: string;\n /** Full S3 URL of the object */\n url: string;\n}\n\n/**\n * Options for putObject operation\n */\nexport interface PutObjectOptions {\n /** Content type (MIME type) */\n contentType?: string;\n /** Additional metadata */\n metadata?: Record<string, string>;\n}\n\n/**\n * Result from listObjects operation\n */\nexport interface ListObjectsResult {\n /** Array of object keys */\n keys: string[];\n /** Whether there are more results */\n isTruncated: boolean;\n /** Continuation token for pagination */\n continuationToken?: string;\n}\n\n/**\n * Storage provider interface\n *\n * Provides object storage operations (get, put, delete, list)\n * for S3-compatible storage backends.\n *\n * @example\n * ```typescript\n * const storage = storageProvider({ bucket: \"my-bucket\" });\n *\n * // Put an object\n * await storage.putObject(\"path/to/file.txt\", \"Hello World\", {\n * contentType: \"text/plain\"\n * });\n *\n * // Get an object\n * const { body, contentType } = await storage.getObject(\"path/to/file.txt\");\n *\n * // Check existence\n * const exists = await storage.exists(\"path/to/file.txt\");\n *\n * // List objects\n * const { keys } = await storage.listObjects(\"path/to/\");\n * ```\n */\n// =============================================================================\n// STORAGE REQUEST TYPES\n// =============================================================================\n\nexport interface GetObjectRequest {\n key: string;\n /** HTTP Range header value (e.g. \"bytes=0-\") — enables partial content streaming */\n range?: string;\n}\n\nexport interface PutObjectRequest {\n key: string;\n body?: Buffer | string | NodeJS.ReadableStream | ReadableStream<Uint8Array>;\n /** When provided, fetch content from this URL instead of using body */\n url?: string;\n options?: PutObjectOptions;\n}\n\nexport interface DeleteObjectRequest {\n key: string;\n}\n\nexport interface ExistsRequest {\n key: string;\n}\n\nexport interface ListObjectsRequest {\n prefix: string;\n maxKeys?: number;\n}\n\nexport interface PresignedUrlRequest {\n /** Object key */\n key: string;\n /** Expiry in seconds (default: 3600) */\n expiresIn?: number;\n /** HTTP method — GET for downloads, PUT for uploads (default: \"GET\") */\n method?: \"GET\" | \"PUT\";\n /** Content type — required for PUT presigned URLs */\n contentType?: string;\n}\n\nexport interface PresignedUrlResult {\n /** Presigned URL for direct client access */\n url: string;\n /** ISO timestamp when the URL expires */\n expiresAt: string;\n}\n\n// =============================================================================\n// STORAGE PROVIDER\n// =============================================================================\n\nexport interface StorageProvider extends Provider {\n /** Get an object from storage */\n getObject(ctx: Context, req: GetObjectRequest): Promise<GetObjectResult>;\n\n /** Put an object into storage */\n putObject(ctx: Context, req: PutObjectRequest): Promise<PutObjectResult>;\n\n /** Delete an object from storage */\n deleteObject(ctx: Context, req: DeleteObjectRequest): Promise<void>;\n\n /** Check if an object exists */\n exists(ctx: Context, req: ExistsRequest): Promise<boolean>;\n\n /** List objects with a given prefix */\n listObjects(\n ctx: Context,\n req: ListObjectsRequest,\n ): Promise<ListObjectsResult>;\n\n /** Generate a presigned URL for direct client access (upload or download) */\n getPresignedUrl(\n ctx: Context,\n req: PresignedUrlRequest,\n ): Promise<PresignedUrlResult>;\n\n /** Extract S3 key from a path (handles s3:// URLs) — pure sync, no RPC */\n extractKey(path: string): string;\n\n /** Build S3 URL from a key — pure sync, no RPC */\n buildUrl(key: string): string;\n}\n","export * from \"./search.types\";\nexport * from \"./storage.types\";\n","/**\n * Audio Types\n *\n * Types for platform-provided audio processing. AudioProvider is injected\n * into fn() options — apps call options.audio.* from the Deno sandbox.\n *\n * Two backends:\n * - FFmpeg (convert, metadata, lufs, waveform) — in-process via @jarvis/audio\n * - Temporal ML workers (isolate, removeEffects, extractMidi, transcribe, process)\n * — Python workers via @jarvis/sound\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// AUDIO CONVERT\n// =============================================================================\n\nexport interface AudioConvertRequest {\n /** S3 key or URL of the source audio file */\n sourceUrl: string;\n /** Target format */\n format: \"wav\" | \"mp3\" | \"flac\" | \"ogg\" | \"aac\";\n /** Sample rate (default: source) */\n sampleRate?: number;\n /** Number of channels (default: source) */\n channels?: number;\n /** Bitrate for lossy formats (e.g., \"128k\", \"320k\") */\n bitrate?: string;\n}\n\nexport interface AudioConvertResponse {\n /** S3 key of the converted file */\n outputUrl: string;\n /** Duration in seconds */\n durationSeconds: number;\n /** File size in bytes */\n fileSize: number;\n}\n\n// =============================================================================\n// AUDIO METADATA\n// =============================================================================\n\nexport interface AudioMetadataRequest {\n /** S3 key or URL of the audio file */\n sourceUrl: string;\n}\n\nexport interface AudioMetadata {\n /** Duration in seconds */\n durationSeconds: number;\n /** Bitrate in kbps */\n bitrate?: number;\n /** Sample rate in Hz */\n sampleRate?: number;\n /** Number of channels */\n channels?: number;\n /** Codec name */\n codec?: string;\n /** Container format */\n format?: string;\n}\n\n// =============================================================================\n// AUDIO LUFS\n// =============================================================================\n\nexport interface AudioLufsRequest {\n /** S3 key or URL of the audio file */\n sourceUrl: string;\n}\n\nexport interface AudioLufsResponse {\n /** Integrated loudness (LUFS) */\n integratedLufs: number;\n /** Loudness range (LU) */\n loudnessRange: number;\n /** True peak (dBTP) */\n truePeak: number;\n}\n\n// =============================================================================\n// AUDIO WAVEFORM\n// =============================================================================\n\nexport interface AudioWaveformRequest {\n /** S3 key or URL of the audio file */\n sourceUrl: string;\n /** Number of peak samples to return (default: 200) */\n samples?: number;\n}\n\nexport interface AudioWaveformResponse {\n /** Normalized amplitude peaks (0–1) */\n peaks: number[];\n /** Duration in seconds */\n durationSeconds: number;\n}\n\n// =============================================================================\n// AUDIO PROVIDER\n// =============================================================================\n\n/**\n * AudioProvider — platform-provided audio processing.\n *\n * Injected into fn() options as `audio`. Combines two backends:\n * - FFmpeg utilities: convert, metadata, lufs, waveform (in-process)\n * - ML sound processing: isolate, removeEffects, extractMidi, transcribe,\n * process, getProgress (Python Temporal workers)\n *\n * @example\n * ```typescript\n * const analyze = fn<Req, Resp>(async (ctx, req, { audio }) => {\n * const meta = await audio.metadata(ctx, { sourceUrl: req.fileUrl });\n * const { tracks } = await audio.isolate(ctx, { sourceUrl: req.fileUrl });\n * const midi = await audio.extractMidi(ctx, { sourceUrl: tracks.vocals! });\n * return { meta, vocalsUrl: tracks.vocals, midi };\n * });\n * ```\n */\nexport interface AudioProvider extends Provider {\n // ---------------------------------------------------------------------------\n // FFmpeg utilities (in-process)\n // ---------------------------------------------------------------------------\n\n /** Convert audio between formats (FFmpeg) */\n convert(ctx: Context, req: AudioConvertRequest): Promise<AudioConvertResponse>;\n\n /** Extract audio metadata (duration, bitrate, codec, etc.) */\n metadata(ctx: Context, req: AudioMetadataRequest): Promise<AudioMetadata>;\n\n /** Measure LUFS loudness (FFmpeg ebur128 filter) */\n lufs(ctx: Context, req: AudioLufsRequest): Promise<AudioLufsResponse>;\n\n /** Generate waveform peaks for visualization */\n waveform(ctx: Context, req: AudioWaveformRequest): Promise<AudioWaveformResponse>;\n\n}\n","/**\n * Transcription Types\n *\n * Types for platform-provided speech-to-text transcription.\n * TranscriptionProvider is injected into fn() options — apps call\n * options.transcription.transcribe() from the Deno sandbox.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// TRANSCRIBE\n// =============================================================================\n\nexport interface TranscribeRequest {\n /** S3 key or URL of the audio file */\n sourceUrl: string;\n /** Language hint (ISO 639-1, e.g., \"en\") */\n language?: string;\n /** Whether to include word-level timestamps */\n wordTimestamps?: boolean;\n /** Quality hint: \"fast\" (smaller model) vs \"accurate\" (larger model) */\n quality?: \"fast\" | \"accurate\";\n}\n\nexport interface TranscriptionWord {\n /** Word text */\n text: string;\n /** Start time in seconds */\n startTime: number;\n /** End time in seconds */\n endTime: number;\n /** Confidence score (0–1) */\n confidence: number;\n}\n\nexport interface TranscriptionSegment {\n /** Segment text */\n text: string;\n /** Start time in seconds */\n startTime: number;\n /** End time in seconds */\n endTime: number;\n /** Word-level timestamps (when wordTimestamps is true) */\n words?: TranscriptionWord[];\n}\n\nexport interface TranscribeResponse {\n /** Full transcribed text */\n text: string;\n /** Segments with timestamps */\n segments: TranscriptionSegment[];\n /** Detected language (ISO 639-1) */\n language: string;\n /** Duration of audio in seconds */\n durationSeconds: number;\n}\n\n// =============================================================================\n// TRANSCRIPTION PROVIDER\n// =============================================================================\n\n/**\n * TranscriptionProvider — platform-provided speech-to-text.\n *\n * Injected into fn() options as `transcription`. Backed by a platform\n * compute container using Whisper or Deepgram. Apps call transcribe()\n * from the Deno sandbox without needing ML models installed.\n *\n * @example\n * ```typescript\n * const extractLyrics = fn<Req, Resp>(async (ctx, req, { transcription }) => {\n * const result = await transcription.transcribe({\n * sourceUrl: req.audioUrl,\n * wordTimestamps: true,\n * quality: \"accurate\",\n * });\n * return { text: result.text, segments: result.segments };\n * });\n * ```\n */\nexport interface TranscriptionProvider extends Provider {\n /** Transcribe audio to text */\n transcribe(ctx: Context, req: TranscribeRequest): Promise<TranscribeResponse>;\n}\n","/**\n * TTS (Text-to-Speech) related types\n *\n * Provider-agnostic TTS interface. Voice and model are opaque strings —\n * each provider interprets them in its own context (e.g., OpenAI \"nova\"\n * vs ElevenLabs voice IDs like \"cgSgspJ2msm6clMCkdW9\").\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { ModelCost } from \"../agents/model.types\";\nimport type { Provider } from \"../core/provider.types\";\n\n// =============================================================================\n// VOICE, MODEL, FORMAT\n// =============================================================================\n\n/** Provider-agnostic voice identifier (string — each provider defines its own) */\nexport type TTSVoice = string;\n\n/** Provider-agnostic model identifier */\nexport type TTSModel = string;\n\n/** Audio output format — shared across providers */\nexport type TTSResponseFormat = \"mp3\" | \"opus\" | \"aac\" | \"flac\" | \"wav\" | \"pcm\";\n\n// OpenAI-specific convenience constants\nexport const OPENAI_TTS_VOICES = [\"alloy\", \"echo\", \"fable\", \"onyx\", \"nova\", \"shimmer\"] as const;\nexport type OpenAITTSVoice = (typeof OPENAI_TTS_VOICES)[number];\n\nexport const OPENAI_TTS_MODELS = [\"tts-1\", \"tts-1-hd\"] as const;\nexport type OpenAITTSModel = (typeof OPENAI_TTS_MODELS)[number];\n\n// Backwards-compatible runtime constants (used by OpenAI provider validation)\nexport const TTS_VOICES: string[] = [...OPENAI_TTS_VOICES];\nexport const TTS_MODELS: string[] = [...OPENAI_TTS_MODELS];\nexport const TTS_FORMATS: TTSResponseFormat[] = [\"mp3\", \"opus\", \"aac\", \"flac\", \"wav\", \"pcm\"];\n\n// =============================================================================\n// REQUEST / RESPONSE\n// =============================================================================\n\nexport interface TTSRequest {\n /** The text to convert to speech */\n text: string;\n /** The voice to use for speech synthesis */\n voice?: TTSVoice;\n /** The model to use for speech synthesis */\n model?: TTSModel;\n /** Speed of the generated audio (0.25 to 4.0) */\n speed?: number;\n /** The format of the audio output */\n responseFormat?: TTSResponseFormat;\n /** Explicit provider routing (e.g., \"openai\", \"elevenlabs\") */\n provider?: string;\n /** Provider-specific voice settings (stability, similarity_boost, etc.) */\n voiceSettings?: Record<string, unknown>;\n}\n\nexport interface TTSResponse {\n /** Raw audio buffer */\n audioBuffer: Buffer;\n /** Base64-encoded audio data */\n audioBase64: string;\n /** MIME type of the audio */\n mimeType: string;\n}\n\n// =============================================================================\n// MODEL / VOICE DEFINITIONS\n// =============================================================================\n\n/** TTS model definition — follows the same pattern as Model in model.types.ts */\nexport interface TTSModelDef {\n /** Model identifier (e.g., \"tts-1\", \"eleven_turbo_v2\") */\n id: string;\n /** Human-readable name (e.g., \"TTS-1\", \"Eleven Turbo v2\") */\n name: string;\n /** Provider name (e.g., \"openai\", \"elevenlabs\") */\n provider: string;\n /** Provider-specific options */\n options?: Record<string, unknown>;\n /** Cost configuration for billing and estimation */\n cost: ModelCost;\n}\n\n/** TTS voice definition — a named voice with provider and default settings */\nexport interface TTSVoiceDef {\n /** Voice identifier (e.g., \"nova\", \"cgSgspJ2msm6clMCkdW9\") */\n id: string;\n /** Human-readable name (e.g., \"Nova\", \"Scarlett\") */\n name: string;\n /** Provider name (e.g., \"openai\", \"elevenlabs\") */\n provider: string;\n /** Default voice settings (e.g., { stability: 0.5, similarityBoost: 0.8 }) */\n options?: Record<string, unknown>;\n}\n\n// =============================================================================\n// TTS PROVIDER\n// =============================================================================\n\n/**\n * TTSProvider — platform-provided text-to-speech.\n *\n * Implementations: OpenAI (`@jarvis/openai`), ElevenLabs (`@jarvis/elevenlabs`).\n * Multi-provider routing: `@jarvis/tts`.\n */\nexport interface TTSProvider extends Provider {\n /** Convert text to speech audio */\n speech(ctx: Context, request: TTSRequest): Promise<TTSResponse>;\n /** List available TTS models for this provider */\n getModels?(): TTSModelDef[];\n /** List available voices for this provider */\n getVoices?(): TTSVoiceDef[];\n /** Create a new instance with different config (e.g., different API key for BYOK) */\n configure?(config: Record<string, unknown>): TTSProvider;\n}\n","export * from \"./audio.types\";\nexport * from \"./transcription.types\";\nexport * from \"./tts.types\";\n","/**\n * User Types\n *\n * Single source of truth for user types and provider interface.\n */\n\nimport type { Context } from \"../core/context.types\";\nimport type { User } from \"../data/user.types\";\n\n// Re-export User as the canonical type\nexport type { User } from \"../data/user.types\";\n\n/** @deprecated Use User instead */\nexport type BaseUser = User;\n\n// =============================================================================\n// Provider Interface\n// =============================================================================\n\n/** Users provider — follows (ctx, req) => resp convention */\nexport interface UsersProvider<TUser extends User = User> {\n getById(ctx: Context, req: { id: string }): Promise<TUser | null>;\n getByEmail(ctx: Context, req: { email: string }): Promise<TUser | null>;\n create(\n ctx: Context,\n req: { id: string; email: string; name?: string; image?: string },\n ): Promise<TUser>;\n update(\n ctx: Context,\n req: { id: string; name?: string; image?: string; preferences?: Record<string, unknown> },\n ): Promise<void>;\n}\n","export * from \"./users.types\";\n","export * from \"./agents\";\nexport * from \"./core\";\nexport * from \"./data\";\nexport * from \"./stream\";\nexport * from \"./auth\";\nexport * from \"./storage\";\nexport * from \"./media\";\nexport * from \"./users\";\n","/**\n * Logger Singleton\n *\n * Provider-agnostic logger with console default.\n * Call logger.init({ provider }) to set a real provider (e.g., pinoProvider).\n *\n * Usage:\n * ```typescript\n * import { logger } from \"@jarvis/logger\";\n * import { pinoProvider } from \"@jarvis/pino\";\n *\n * logger.init({ provider: pinoProvider({ name: \"worker\" }) });\n * logger.info(ctx, \"Hello\", { key: \"value\" });\n * logger.sys.info(\"System startup\");\n * Runtime.install({ logger: logger.runtime() });\n * ```\n */\n\nimport type { Context, LogProvider, LogMetadata, AuditEvent } from \"@jarvis/types\";\n\n// =============================================================================\n// Error resolving — handles Error objects in metadata\n// =============================================================================\n\nfunction resolveError(meta?: LogMetadata): LogMetadata {\n if (!meta) return {};\n const { error, ...rest } = meta;\n if (error === undefined) return meta;\n if (error instanceof Error) {\n return { ...rest, error: error.message, ...(error.stack ? { errorStack: error.stack } : {}) };\n }\n return { ...rest, error: typeof error === \"string\" ? error : String(error) };\n}\n\n// =============================================================================\n// Console default provider\n// =============================================================================\n\nfunction consoleProvider(): LogProvider {\n const log =\n (level: \"debug\" | \"info\" | \"warn\" | \"error\") =>\n (_ctx: Context, message: string, meta?: LogMetadata): void => {\n const fn = level === \"error\" ? console.error : level === \"warn\" ? console.warn : level === \"debug\" ? console.debug : console.info;\n fn(`[${level.toUpperCase()}]`, message, resolveError(meta));\n };\n\n return {\n debug: log(\"debug\"),\n info: log(\"info\"),\n warn: log(\"warn\"),\n error: log(\"error\"),\n audit: (_ctx, event) => console.info(\"[AUDIT]\", event.action, event.result),\n };\n}\n\n// =============================================================================\n// Console runtime logger (fallback for Temporal Runtime.install())\n// =============================================================================\n\ninterface RuntimeLogger {\n log(level: string, message: string, meta?: Record<string | symbol, unknown>): void;\n trace(message: string, meta?: Record<string | symbol, unknown>): void;\n debug(message: string, meta?: Record<string | symbol, unknown>): void;\n info(message: string, meta?: Record<string | symbol, unknown>): void;\n warn(message: string, meta?: Record<string | symbol, unknown>): void;\n error(message: string, meta?: Record<string | symbol, unknown>): void;\n}\n\nconst LEVEL_MAP: Record<string, \"debug\" | \"info\" | \"warn\" | \"error\"> = {\n TRACE: \"debug\",\n DEBUG: \"debug\",\n INFO: \"info\",\n WARN: \"warn\",\n ERROR: \"error\",\n};\n\nfunction consoleRuntimeLogger(): RuntimeLogger {\n const log = (level: string, message: string, meta?: Record<string | symbol, unknown>) => {\n const fn = console[LEVEL_MAP[level] ?? \"info\"];\n fn(message, meta ? Object.fromEntries(Object.entries(meta as Record<string, unknown>)) : \"\");\n };\n return {\n log: (level, msg, meta) => log(level, msg, meta),\n trace: (msg, meta) => log(\"TRACE\", msg, meta),\n debug: (msg, meta) => log(\"DEBUG\", msg, meta),\n info: (msg, meta) => log(\"INFO\", msg, meta),\n warn: (msg, meta) => log(\"WARN\", msg, meta),\n error: (msg, meta) => log(\"ERROR\", msg, meta),\n };\n}\n\n// =============================================================================\n// Singleton state\n// =============================================================================\n\nconst SYS_CTX: Context = { userId: \"system\" } as Context;\n\nlet _provider: LogProvider = consoleProvider();\nlet _runtimeFactory: (() => RuntimeLogger) | null = null;\n\n// =============================================================================\n// Logger singleton\n// =============================================================================\n\nexport type LogProviderWithRuntime = LogProvider & {\n runtime?: () => RuntimeLogger;\n};\n\nexport const logger = {\n /** Set the active logging provider */\n init(config: { provider: LogProviderWithRuntime }) {\n _provider = config.provider;\n _runtimeFactory = config.provider.runtime ?? null;\n },\n\n // Logging — delegates to current provider (resolves Error objects in meta)\n debug(ctx: Context, message: string, meta?: LogMetadata) { _provider.debug(ctx, message, resolveError(meta)); },\n info(ctx: Context, message: string, meta?: LogMetadata) { _provider.info(ctx, message, resolveError(meta)); },\n warn(ctx: Context, message: string, meta?: LogMetadata) { _provider.warn(ctx, message, resolveError(meta)); },\n error(ctx: Context, message: string, meta?: LogMetadata) { _provider.error(ctx, message, resolveError(meta)); },\n audit(ctx: Context, event: AuditEvent) { _provider.audit(ctx, event); },\n\n /** System-scoped shorthand (no ctx required) */\n sys: {\n debug(message: string, meta?: LogMetadata) { _provider.debug(SYS_CTX, message, meta); },\n info(message: string, meta?: LogMetadata) { _provider.info(SYS_CTX, message, meta); },\n warn(message: string, meta?: LogMetadata) { _provider.warn(SYS_CTX, message, meta); },\n error(message: string, meta?: LogMetadata) { _provider.error(SYS_CTX, message, meta); },\n },\n\n /** Get a Temporal Runtime.install() logger. Uses provider's runtime() if available, console fallback. */\n runtime(): RuntimeLogger {\n if (_runtimeFactory) return _runtimeFactory();\n return consoleRuntimeLogger();\n },\n};\n","export { logger } from \"./logger\";\nexport type { LogProviderWithRuntime } from \"./logger\";\n\n// Re-export types for convenience\nexport type {\n LogProvider,\n Logger,\n LogLevel,\n LogMetadata,\n LoggerConfig,\n LoggerProviderConfig,\n AuditEvent,\n} from \"@jarvis/types\";\n","/**\n * Anthropic model definitions\n *\n * Each entry carries its own cost configuration (USD per 1M tokens). The\n * `cacheTokens.read` / `.write` rates follow Anthropic's public pricing:\n * read = inputTokens × 0.10 (prompt-cache hit)\n * write = inputTokens × 1.25 (prompt-cache creation)\n */\n\nimport type { Model } from \"@jarvis/types\";\n\nexport const claude3Haiku: Model = {\n id: \"claude-3-haiku-20240307\",\n name: \"Claude 3 Haiku\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 4096 },\n cost: {\n multiplier: 8,\n inputTokens: 0.25,\n outputTokens: 1.25,\n cacheTokens: { read: 0.025, write: 0.3125 },\n },\n};\n\n// =============================================================================\n// Claude 4.6 / 4.7 (GA April 2026) — short-alias IDs, 1M context baseline\n// =============================================================================\n\nexport const claudeOpus47: Model = {\n id: \"claude-opus-4-7\",\n name: \"Claude Opus 4.7\",\n provider: \"anthropic\",\n maxTokens: { input: 1_000_000, output: 128_000 },\n cost: {\n multiplier: 25,\n inputTokens: 5.0,\n outputTokens: 25.0,\n cacheTokens: { read: 0.5, write: 6.25 },\n },\n};\n\nexport const claudeSonnet46: Model = {\n id: \"claude-sonnet-4-6\",\n name: \"Claude Sonnet 4.6\",\n provider: \"anthropic\",\n maxTokens: { input: 1_000_000, output: 64_000 },\n cost: {\n multiplier: 20,\n inputTokens: 3.0,\n outputTokens: 15.0,\n cacheTokens: { read: 0.3, write: 3.75 },\n },\n};\n\nexport const claude37Sonnet: Model = {\n id: \"claude-3-7-sonnet-20241022\",\n name: \"Claude 3.7 Sonnet\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: {\n multiplier: 20,\n inputTokens: 3.0,\n outputTokens: 15.0,\n cacheTokens: { read: 0.3, write: 3.75 },\n },\n options: {\n temperature: 0.4,\n topP: 0.95,\n },\n};\n\nexport const claude35Haiku: Model = {\n id: \"claude-3-5-haiku-20241022\",\n name: \"Claude 3.5 Haiku\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: {\n multiplier: 8,\n inputTokens: 0.8,\n outputTokens: 4.0,\n cacheTokens: { read: 0.08, write: 1.0 },\n },\n};\n\nexport const claude4Sonnet: Model = {\n id: \"claude-sonnet-4-20250514\",\n name: \"Claude 4 Sonnet\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: {\n multiplier: 20,\n inputTokens: 3.0,\n outputTokens: 15.0,\n cacheTokens: { read: 0.3, write: 3.75 },\n },\n};\n\nexport const claude4Opus: Model = {\n id: \"claude-opus-4-20250514\",\n name: \"Claude 4 Opus\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: {\n multiplier: 50,\n inputTokens: 15.0,\n outputTokens: 75.0,\n cacheTokens: { read: 1.5, write: 18.75 },\n },\n};\n\nexport const claudeSonnet45: Model = {\n id: \"claude-sonnet-4-5-20250929\",\n name: \"Claude Sonnet 4.5\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 64_000 },\n cost: {\n multiplier: 20,\n inputTokens: 3.0,\n outputTokens: 15.0,\n cacheTokens: { read: 0.3, write: 3.75 },\n },\n};\n\nexport const claudeOpus41: Model = {\n id: \"claude-opus-4-1-20250514\",\n name: \"Claude Opus 4.1\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 8192 },\n cost: {\n multiplier: 50,\n inputTokens: 15.0,\n outputTokens: 75.0,\n cacheTokens: { read: 1.5, write: 18.75 },\n },\n};\n\nexport const claudeHaiku45: Model = {\n id: \"claude-haiku-4-5-20251001\",\n name: \"Claude Haiku 4.5\",\n provider: \"anthropic\",\n maxTokens: { input: 200_000, output: 64_000 },\n cost: {\n multiplier: 8,\n inputTokens: 1.0,\n outputTokens: 5.0,\n cacheTokens: { read: 0.1, write: 1.25 },\n },\n};\n\nexport const claudeOpus46: Model = {\n id: \"claude-opus-4-6\",\n name: \"Claude Opus 4.6\",\n provider: \"anthropic\",\n maxTokens: { input: 1_000_000, output: 64_000 },\n cost: {\n multiplier: 50,\n inputTokens: 5.0,\n outputTokens: 25.0,\n cacheTokens: { read: 0.5, write: 6.25 },\n },\n};\n\n// Claude Code models (same IDs as Anthropic, but routed via \"claude-code\" provider tag)\nexport const claudeCodeOpus47: Model = {\n id: \"claude-opus-4-7\",\n name: \"Claude Opus 4.7\",\n provider: \"claude-code\",\n maxTokens: { input: 1_000_000, output: 128_000 },\n cost: {\n multiplier: 25,\n inputTokens: 5.0,\n outputTokens: 25.0,\n cacheTokens: { read: 0.5, write: 6.25 },\n },\n};\n\nexport const claudeCodeSonnet46: Model = {\n id: \"claude-sonnet-4-6\",\n name: \"Claude Sonnet 4.6\",\n provider: \"claude-code\",\n maxTokens: { input: 1_000_000, output: 64_000 },\n cost: {\n multiplier: 20,\n inputTokens: 3.0,\n outputTokens: 15.0,\n cacheTokens: { read: 0.3, write: 3.75 },\n },\n};\n\nexport const claudeCodeHaiku45: Model = {\n id: \"claude-haiku-4-5\",\n name: \"Claude Haiku 4.5\",\n provider: \"claude-code\",\n maxTokens: { input: 200_000, output: 64_000 },\n cost: {\n multiplier: 8,\n inputTokens: 1.0,\n outputTokens: 5.0,\n cacheTokens: { read: 0.1, write: 1.25 },\n },\n};\n\n// Legacy CC aliases (kept for existing sessions that used these ids)\nexport const claudeCodeSonnet: Model = { ...claudeCodeSonnet46, id: \"claude-sonnet-4-5-20250929\" };\nexport const claudeCodeOpus: Model = { ...claudeCodeOpus47, id: \"claude-opus-4-6\" };\n\n// All Anthropic models\nexport const anthropicModels = {\n claude3Haiku,\n claude37Sonnet,\n claude35Haiku,\n claude4Sonnet,\n claude4Opus,\n claudeSonnet45,\n claudeOpus41,\n claudeHaiku45,\n claudeOpus46,\n claudeSonnet46,\n claudeOpus47,\n\n list: (): Model[] => [\n claude3Haiku,\n claude37Sonnet,\n claude35Haiku,\n claude4Sonnet,\n claude4Opus,\n claudeSonnet45,\n claudeOpus41,\n claudeHaiku45,\n claudeOpus46,\n claudeSonnet46,\n claudeOpus47,\n ],\n};\n\n// Claude Code models registry — order matters for UI (default first)\nexport const claudeCodeModels = {\n claudeCodeOpus47,\n claudeCodeSonnet46,\n claudeCodeHaiku45,\n claudeCodeSonnet,\n claudeCodeOpus,\n\n list: (): Model[] => [claudeCodeOpus47, claudeCodeSonnet46, claudeCodeHaiku45],\n};\n","/**\n * Anthropic provider implementation\n * Provides LLM capabilities (query, stream) using the Anthropic Messages API\n *\n * Ported from @gluoe/anthropic with @jarvis/* imports\n */\n\nimport Anthropic from \"@anthropic-ai/sdk\";\nimport type { MessageParam } from \"@anthropic-ai/sdk/resources/messages\";\n\nimport { anthropicModels } from \"./anthropic.models\";\nimport type {\n Context,\n QueryLLMRequest,\n QueryLLMResponse,\n LLMProvider,\n LLMQueryOptions,\n Model,\n Message,\n MultimodalMessage,\n ContentPart,\n TextContentPart,\n ImageContentPart,\n} from \"@jarvis/types\";\n\nexport interface Config {\n apiKey?: string;\n baseURL?: string;\n}\n\nexport type AnthropicProvider = LLMProvider;\n\nexport function provider(config?: Config): AnthropicProvider {\n const finalConfig = {\n apiKey: config?.apiKey ?? process.env.ANTHROPIC_API_KEY,\n baseURL: config?.baseURL ?? process.env.ANTHROPIC_BASE_URL,\n };\n\n if (!finalConfig.apiKey) {\n throw new Error(\n \"Anthropic API key is required. Provide it via config.apiKey or ANTHROPIC_API_KEY environment variable\",\n );\n }\n\n const client = new Anthropic({\n apiKey: finalConfig.apiKey,\n baseURL: finalConfig.baseURL,\n });\n\n // =========================================================================\n // LLM METHODS\n // =========================================================================\n\n async function query(\n _ctx: Context,\n request: QueryLLMRequest,\n _options?: LLMQueryOptions,\n ): Promise<QueryLLMResponse> {\n try {\n const startTime = Date.now();\n const systemMessage = request.messages.find((m) => m.role === \"system\");\n\n const options = {\n max_tokens: request.options?.maxTokens ?? 4096,\n temperature: request.options?.temperature,\n top_p: request.options?.topP,\n };\n\n // Check if webSearch tool is present and convert to native web search\n const hasWebSearch = request.tools?.some((t) => t.name === \"webSearch\");\n const otherTools =\n request.tools?.filter((t) => t.name !== \"webSearch\") || [];\n\n // If structured output is requested, use tool calling approach\n const tools = request.output?.schema\n ? [\n {\n name: \"structured_output\",\n description: \"Respond with a structured JSON object\",\n input_schema: request.output.schema,\n },\n ...(hasWebSearch\n ? [\n {\n type: \"web_search_20250305\" as const,\n name: \"web_search\",\n max_uses: 5,\n },\n ]\n : []),\n ...(otherTools.length > 0 ? convertTools(otherTools) : []),\n ]\n : hasWebSearch\n ? [\n {\n type: \"web_search_20250305\" as const,\n name: \"web_search\",\n max_uses: 5,\n },\n ...(otherTools.length > 0 ? convertTools(otherTools) : []),\n ]\n : otherTools.length > 0\n ? convertTools(otherTools)\n : undefined;\n\n const tool_choice = request.output?.schema\n ? {\n type: \"tool\" as const,\n name: \"structured_output\",\n disable_parallel_tool_use: true,\n }\n : undefined;\n\n // Map ThinkingConfig to Anthropic thinking parameter\n const thinking_param = request.thinking?.type === \"disabled\"\n ? undefined\n : request.thinking?.type === \"enabled\" && request.thinking.budgetTokens\n ? { type: \"enabled\" as const, budget_tokens: request.thinking.budgetTokens }\n : request.thinking?.type === \"adaptive\"\n ? { type: \"enabled\" as const, budget_tokens: options.max_tokens - 1 }\n : undefined;\n\n const response = await client.messages.create({\n model: request.model,\n max_tokens: options.max_tokens,\n temperature: options.temperature,\n top_p: options.top_p,\n system: systemMessage?.content,\n messages: convertMessages(request.messages),\n tools,\n tool_choice,\n ...(thinking_param && { thinking: thinking_param }),\n } as any); // Type assertion needed for web_search_20250305\n\n const duration = Date.now() - startTime;\n\n let content = \"\";\n let thinking = \"\";\n let toolCalls: any[] | undefined;\n\n // Handle multiple content blocks\n for (const block of response.content) {\n if (block.type === \"text\") {\n content += block.text;\n } else if ((block as any).type === \"thinking\") {\n thinking += (block as any).thinking ?? \"\";\n } else if (block.type === \"tool_use\") {\n // If this is the structured output tool, extract content from it\n if (block.name === \"structured_output\" && request.output?.schema) {\n content = JSON.stringify(block.input || {});\n } else {\n // Regular tool call\n if (!toolCalls) toolCalls = [];\n toolCalls.push({\n id: block.id,\n name: block.name,\n args: JSON.stringify(block.input || {}),\n status: \"pending\" as const,\n });\n }\n }\n }\n\n return {\n content,\n thinking: thinking || undefined,\n toolCalls,\n metadata: {\n usage: {\n inputTokens: response.usage?.input_tokens || 0,\n outputTokens: response.usage?.output_tokens || 0,\n totalTokens:\n (response.usage?.input_tokens || 0) +\n (response.usage?.output_tokens || 0),\n cacheTokens: {\n read: (response.usage as any)?.cache_read_input_tokens || 0,\n write: (response.usage as any)?.cache_creation_input_tokens || 0,\n },\n },\n model: request.model,\n options,\n duration,\n provider: \"anthropic\",\n },\n };\n } catch (error) {\n throw new Error(\n `Anthropic API error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n\n async function* stream(\n _ctx: Context,\n request: QueryLLMRequest,\n _options?: LLMQueryOptions,\n ): AsyncGenerator<QueryLLMResponse> {\n try {\n const options = {\n max_tokens: request.options?.maxTokens ?? 4096,\n temperature: request.options?.temperature,\n top_p: request.options?.topP,\n };\n\n const startTime = Date.now();\n\n const systemMessage = request.messages.find((m) => m.role === \"system\");\n\n // Check if webSearch tool is present and convert to native web search\n const hasWebSearch = request.tools?.some((t) => t.name === \"webSearch\");\n const otherTools =\n request.tools?.filter((t) => t.name !== \"webSearch\") || [];\n\n // If structured output is requested, use tool calling approach\n const tools = request.output?.schema\n ? [\n {\n name: \"structured_output\",\n description: \"Respond with a structured JSON object\",\n input_schema: request.output.schema,\n },\n ...(hasWebSearch\n ? [\n {\n type: \"web_search_20250305\" as const,\n name: \"web_search\",\n max_uses: 5,\n },\n ]\n : []),\n ...(otherTools.length > 0 ? convertTools(otherTools) : []),\n ]\n : hasWebSearch\n ? [\n {\n type: \"web_search_20250305\" as const,\n name: \"web_search\",\n max_uses: 5,\n },\n ...(otherTools.length > 0 ? convertTools(otherTools) : []),\n ]\n : otherTools.length > 0\n ? convertTools(otherTools)\n : undefined;\n\n const tool_choice = request.output?.schema\n ? {\n type: \"tool\" as const,\n name: \"structured_output\",\n disable_parallel_tool_use: true,\n }\n : undefined;\n\n // Map ThinkingConfig to Anthropic thinking parameter\n const thinking_param = request.thinking?.type === \"disabled\"\n ? undefined\n : request.thinking?.type === \"enabled\" && request.thinking.budgetTokens\n ? { type: \"enabled\" as const, budget_tokens: request.thinking.budgetTokens }\n : request.thinking?.type === \"adaptive\"\n ? { type: \"enabled\" as const, budget_tokens: options.max_tokens - 1 }\n : undefined;\n\n const streamResponse = client.messages.stream({\n model: request.model,\n max_tokens: options.max_tokens,\n temperature: options.temperature,\n top_p: options.top_p,\n system: systemMessage?.content,\n messages: convertMessages(request.messages),\n tools: tools as any, // Type assertion needed for web_search_20250305\n tool_choice,\n ...(thinking_param && { thinking: thinking_param }),\n });\n\n let usage = {\n input_tokens: 0,\n output_tokens: 0,\n };\n const toolCalls: any[] = [];\n let currentToolUse: {\n id: string;\n name: string;\n inputJson: string;\n } | null = null;\n\n for await (const chunk of streamResponse) {\n // Update usage from message_delta events\n if (chunk.type === \"message_delta\" && (chunk as any).usage) {\n usage = (chunk as any).usage;\n }\n\n // Track content block starts (tool_use)\n if (\n chunk.type === \"content_block_start\" &&\n (chunk as any).content_block?.type === \"tool_use\"\n ) {\n const block = (chunk as any).content_block;\n currentToolUse = {\n id: block.id,\n name: block.name,\n inputJson: \"\",\n };\n }\n\n // Handle content block deltas\n if (chunk.type === \"content_block_delta\") {\n const deltaType = (chunk.delta as any)?.type;\n\n if (deltaType === \"text_delta\") {\n // Yield text chunks\n yield {\n content: (chunk.delta as any).text || \"\",\n metadata: {\n usage: {\n inputTokens: usage.input_tokens || 0,\n outputTokens: usage.output_tokens || 0,\n totalTokens:\n (usage.input_tokens || 0) + (usage.output_tokens || 0),\n },\n model: request.model,\n options,\n duration: Date.now() - startTime,\n provider: \"anthropic\",\n },\n };\n } else if (deltaType === \"thinking_delta\") {\n // Yield thinking chunks\n yield {\n content: \"\",\n thinking: (chunk.delta as any).thinking || \"\",\n metadata: {\n usage: {\n inputTokens: usage.input_tokens || 0,\n outputTokens: usage.output_tokens || 0,\n totalTokens:\n (usage.input_tokens || 0) + (usage.output_tokens || 0),\n },\n model: request.model,\n options,\n duration: Date.now() - startTime,\n provider: \"anthropic\",\n },\n };\n } else if (deltaType === \"input_json_delta\" && currentToolUse) {\n currentToolUse.inputJson += (chunk.delta as any).partial_json || \"\";\n }\n // signature_delta — ignored\n }\n\n // Finalize tool call on content_block_stop\n if (chunk.type === \"content_block_stop\" && currentToolUse) {\n toolCalls.push({\n id: currentToolUse.id,\n name: currentToolUse.name,\n args: currentToolUse.inputJson || \"{}\",\n status: \"pending\" as const,\n });\n currentToolUse = null;\n }\n }\n\n // Yield final chunk with tool calls if any were accumulated\n if (toolCalls.length > 0) {\n yield {\n content: \"\",\n toolCalls,\n metadata: {\n usage: {\n inputTokens: usage.input_tokens || 0,\n outputTokens: usage.output_tokens || 0,\n totalTokens:\n (usage.input_tokens || 0) + (usage.output_tokens || 0),\n },\n model: request.model,\n options,\n duration: Date.now() - startTime,\n provider: \"anthropic\",\n },\n };\n }\n } catch (error) {\n throw new Error(\n `Anthropic streaming error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n }\n\n async function getModels(): Promise<Model[]> {\n return anthropicModels.list();\n }\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n\n function parseToolArgs(str: string): Record<string, unknown> {\n if (!str || str.trim() === \"\") return {};\n try {\n return JSON.parse(str);\n } catch (err) {\n console.warn(\"Failed to parse tool call args:\", err);\n return {};\n }\n }\n\n function convertMessages(\n messages: (Message | MultimodalMessage)[],\n ): MessageParam[] {\n return (\n messages\n ?.filter((msg) => msg.role !== \"system\") // Anthropic handles system messages separately\n ?.map((msg): MessageParam => {\n switch (msg.role) {\n case \"user\":\n if (msg.content && Array.isArray(msg.content)) {\n return {\n role: \"user\",\n content: msg.content\n .filter(\n (\n part: ContentPart,\n ): part is TextContentPart | ImageContentPart =>\n part.type === \"text\" || part.type === \"image\",\n )\n .map((part: TextContentPart | ImageContentPart) => {\n if (part.type === \"image\") {\n return {\n type: \"image\" as const,\n source: {\n type: \"base64\" as const,\n media_type: part.mimeType as\n | \"image/jpeg\"\n | \"image/png\"\n | \"image/gif\"\n | \"image/webp\",\n data: part.data,\n },\n };\n }\n return {\n type: \"text\" as const,\n text: part.text,\n };\n }),\n };\n } else {\n return {\n role: \"user\",\n content: msg.content || \"\",\n };\n }\n\n case \"assistant\": {\n const assistantMsg = msg as any;\n\n // Check if there are tool calls\n if (assistantMsg.toolCalls && assistantMsg.toolCalls.length > 0) {\n const content: any[] = [];\n if (assistantMsg.content) {\n content.push({\n type: \"text\" as const,\n text: assistantMsg.content,\n });\n }\n for (const tc of assistantMsg.toolCalls) {\n content.push({\n type: \"tool_use\" as const,\n id: tc.id,\n name: tc.name,\n input:\n typeof tc.args === \"string\"\n ? parseToolArgs(tc.args)\n : tc.args || {},\n });\n }\n return { role: \"assistant\", content };\n }\n\n return {\n role: \"assistant\",\n content: assistantMsg.content || \"\",\n };\n }\n\n case \"tool\": {\n // Anthropic expects tool results in user messages with tool_result content blocks\n const toolMsg = msg as any;\n return {\n role: \"user\",\n content: [\n {\n type: \"tool_result\" as const,\n tool_use_id: toolMsg.toolCallId,\n content: toolMsg.content,\n },\n ],\n };\n }\n\n default:\n throw new Error(`Unsupported message role: ${(msg as any).role}`);\n }\n }) || []\n );\n }\n\n function convertTools(tools: any[]): any[] {\n return (\n tools?.map((tool) => ({\n name: tool.name,\n description: tool.description,\n input_schema: tool.input,\n })) || []\n );\n }\n\n function configure(overrides: Record<string, unknown>): AnthropicProvider {\n return provider({ ...finalConfig, ...overrides } as Config);\n }\n\n return {\n name: \"anthropic\",\n query,\n stream,\n getModels,\n configure,\n };\n}\n","/**\n * Claude Code provider\n *\n * Wraps the @anthropic-ai/claude-agent-sdk. Returns { content, toolCalls: undefined }\n * so the orchestrator exits after 1 iteration — Claude Code handles its own tool loop internally.\n *\n * Routing is by provider (\"claude-code\"), not model ID. The model ID passed in\n * (e.g. \"claude-sonnet-4-5-20250929\") goes straight to the SDK.\n *\n * Tool interception (canUseTool):\n * - When `onUserInput` is provided, every SDK tool call is converted to a PendingUserInput\n * and forwarded to the consumer via the callback. The consumer decides per-tool what to do.\n * - Tools with hooks.before: Provider invokes the hook, which calls wait() with artifact data.\n * The wait() creates an enriched PendingUserInput and routes through onUserInput.\n * - AskUserQuestion: Specific converter → structured questions format for AskUserPanel\n * - All other tools: Generic converter → raw toolName + input\n * - When no `onUserInput` is provided, falls back to bypassPermissions (backwards compatible)\n *\n * After-hook invocation:\n * - When a \"user\" message arrives (tool_result), the provider invokes after hooks for tracked tools.\n * - Artifacts from after hooks are attached to the message as `_toolUi` map.\n * - The worker reads `_toolUi` when creating tool completion messages.\n */\n\nimport { logger } from \"@jarvis/logger\";\nimport { claudeCodeModels } from \"./anthropic.models\";\nimport { context as createContext } from \"@jarvis/sdk\";\nimport type {\n Context,\n QueryLLMRequest,\n QueryLLMResponse,\n LLMProvider,\n LLMQueryOptions,\n Model,\n PendingUserInput,\n UserInputResponse,\n ToolHookOptions,\n} from \"@jarvis/types\";\nimport { hasOutputFormat } from \"@jarvis/types\";\n\nimport type { ClaudeCodeConfig, ProviderTool } from \"./claude-code.types\";\n\n/**\n * Internal Claude SDK enrichment shape — same as the local `ToolUiEntry`\n * defined in `progress.ts`. Lifts a tool's UI hint from the SDK before\n * the public `Ui` envelope is constructed downstream.\n */\ninterface ToolUiEntry {\n type: string;\n title?: string;\n data: unknown;\n}\n\n// SDK types imported dynamically; declare the shapes we need for canUseTool.\n// Note: SDK Zod validation requires updatedInput on the \"allow\" variant.\ntype PermissionResult =\n | {\n behavior: \"allow\";\n updatedInput: Record<string, unknown>;\n toolUseID?: string;\n }\n | {\n behavior: \"deny\";\n message: string;\n interrupt?: boolean;\n toolUseID?: string;\n };\n\nlet _idCounter = 0;\nfunction generateId(): string {\n return `pui-${Date.now()}-${++_idCounter}`;\n}\n\n/**\n * Convert AskUserQuestion tool call to a PendingUserInput\n * with structured questions format matching AskUserPanel expectations.\n */\nfunction convertAskUserQuestion(\n input: Record<string, unknown>,\n toolUseID: string,\n): PendingUserInput {\n const questions = input.questions;\n return {\n id: generateId(),\n type: \"tool\",\n toolName: \"askUser\",\n toolCallId: toolUseID,\n output: { questions },\n ui: {\n uri: \"ui://artifact/ask_user\",\n title: \"Question\",\n data: { questions },\n },\n timing: \"before\",\n };\n}\n\n/**\n * Convert any other tool call to a generic PendingUserInput.\n * The consumer (worker) decides what to do based on toolName.\n */\nfunction convertGenericTool(\n toolName: string,\n input: Record<string, unknown>,\n toolUseID: string,\n): PendingUserInput {\n return {\n id: generateId(),\n type: \"tool\",\n toolName,\n toolCallId: toolUseID,\n input,\n timing: \"before\",\n };\n}\n\n/**\n * Convert a UserInputResponse from the consumer back to an SDK PermissionResult.\n * For AskUserQuestion, the response data contains answers that need to flow back.\n */\nfunction toPermissionResult(\n toolName: string,\n originalInput: Record<string, unknown>,\n response: UserInputResponse,\n toolUseID: string,\n): PermissionResult {\n if (response.action === \"deny\") {\n return {\n behavior: \"deny\",\n message: response.feedback || \"User denied the tool call\",\n toolUseID,\n };\n }\n\n // \"modify\" = user wants the agent to STOP and rework based on their\n // feedback. The SDK's `interrupt: true` field on a deny PermissionResult\n // is undocumented and empirically a no-op — the agent loop continues and\n // pivots around the deny. The actual abort happens via the AbortController\n // (the runner calls `interruptTask` immediately after resolving the\n // permission; see apps/cli/src/agent.ts `resolveUserInput`). Returning a\n // plain deny here is enough: the SDK fires `onPermissionResult` synchronously\n // (which emits the gated tool's `status: \"modify\"` UI message), then the\n // explicit abort tears down the query.\n if (response.action === \"modify\") {\n return {\n behavior: \"deny\",\n message: response.feedback || \"User requested changes.\",\n toolUseID,\n };\n }\n\n // For AskUserQuestion, pass answers back as updatedInput so the SDK\n // receives them as the tool's \"result\"\n if (toolName === \"AskUserQuestion\" && response.data) {\n return {\n behavior: \"allow\",\n updatedInput: {\n answers: response.data,\n },\n toolUseID,\n };\n }\n\n // SDK Zod schema requires updatedInput for the \"allow\" variant —\n // pass the original input through unchanged.\n return { behavior: \"allow\", updatedInput: originalInput, toolUseID };\n}\n\n// =============================================================================\n// Shared permission + hook infrastructure\n// =============================================================================\n\ninterface PermissionOptions {\n opts: Record<string, unknown>;\n toolMap: Map<string, ProviderTool>;\n toolInputTracker: Map<string, { toolName: string; input: Record<string, unknown> }>;\n}\n\n/**\n * Build permission options shared by both query() and stream().\n * When tools with hooks are provided, canUseTool invokes the before hook.\n */\nfunction buildPermissionOptions(ctx: Context, config: ClaudeCodeConfig): PermissionOptions {\n const toolMap = new Map<string, ProviderTool>();\n for (const t of config.tools ?? []) toolMap.set(t.name, t);\n\n const toolInputTracker = new Map<string, { toolName: string; input: Record<string, unknown> }>();\n\n if (!config.onUserInput) {\n return {\n opts: {\n permissionMode: \"bypassPermissions\" as const,\n allowDangerouslySkipPermissions: true,\n },\n toolMap,\n toolInputTracker,\n };\n }\n\n const canUseTool = async (\n toolName: string,\n input: Record<string, unknown>,\n options: { toolUseID: string; signal: AbortSignal },\n ): Promise<PermissionResult> => {\n // Track tool input for after-hook invocation\n toolInputTracker.set(options.toolUseID, { toolName, input });\n\n const t = toolMap.get(toolName);\n\n // If tool has a before hook, invoke it — the hook creates the PendingUserInput\n // with artifact data via wait()\n if (t?.hooks?.before) {\n const req = {\n toolName,\n input,\n toolCallId: options.toolUseID,\n state: {} as unknown,\n };\n const hookOptions: ToolHookOptions = {\n mode: config.permissionMode ?? \"default\",\n askUser: async (waitOpts?) => {\n const pendingInput: PendingUserInput = {\n id: generateId(),\n type: \"tool\" as const,\n toolName,\n toolCallId: options.toolUseID,\n input,\n timing: \"before\" as const,\n ...(waitOpts?.data ? { output: waitOpts.data } : {}),\n ...(waitOpts?.ui ? { ui: waitOpts.ui } : {}),\n reason: waitOpts?.reason,\n };\n return config.onUserInput!(pendingInput);\n },\n };\n\n const result = await t.hooks.before(ctx, req, hookOptions);\n if (result.action === \"deny\") {\n return {\n behavior: \"deny\",\n message: (result as { reason?: string }).reason ?? \"Denied\",\n toolUseID: options.toolUseID,\n };\n }\n return {\n behavior: \"allow\",\n updatedInput: ((result as { input?: unknown }).input as Record<string, unknown>) || input,\n toolUseID: options.toolUseID,\n };\n }\n\n // No before hook — use specific converters for known tools, generic for others\n const pendingInput =\n toolName === \"AskUserQuestion\"\n ? convertAskUserQuestion(input, options.toolUseID)\n : convertGenericTool(toolName, input, options.toolUseID);\n\n const response = await config.onUserInput!(pendingInput);\n // Notify the progress layer of the user's decision before returning to\n // the SDK. The SDK may abort (on `interrupt: true`) before emitting any\n // tool_result, so without this the timeline tool message would stay in\n // its last-emitted \"running\" status and render as a gray/green dot.\n config.onPermissionResult?.({\n toolUseId: options.toolUseID,\n toolName,\n action: response.action,\n feedback: response.feedback,\n });\n return toPermissionResult(toolName, input, response, options.toolUseID);\n };\n\n return {\n opts: {\n permissionMode: config.permissionMode ?? \"default\",\n canUseTool,\n },\n toolMap,\n toolInputTracker,\n };\n}\n\n/**\n * Process after hooks for a \"user\" message (tool_result).\n * Returns a map of toolUseId → ToolUiEntry for enrichment.\n */\nasync function processAfterHooks(\n ctx: Context,\n req: {\n message: any;\n config: ClaudeCodeConfig;\n toolMap: Map<string, ProviderTool>;\n toolInputTracker: Map<string, { toolName: string; input: Record<string, unknown> }>;\n },\n): Promise<Record<string, ToolUiEntry> | null> {\n const { message, config, toolInputTracker, toolMap } = req;\n if (message.type !== \"user\" || !Array.isArray(message.message?.content)) return null;\n\n const artifactMap: Record<string, ToolUiEntry> = {};\n let hasArtifacts = false;\n\n for (const block of message.message.content) {\n const toolUseId = block?.tool_use_id;\n if (!toolUseId) continue;\n\n const tracked = toolInputTracker.get(toolUseId);\n const t = tracked ? toolMap.get(tracked.toolName) : null;\n\n if (t?.hooks?.after) {\n try {\n const afterResult = await t.hooks.after(\n ctx,\n {\n toolName: tracked!.toolName,\n input: tracked!.input,\n output: block.content ?? block.output,\n toolCallId: toolUseId,\n state: {} as unknown,\n },\n {\n mode: config.permissionMode ?? \"default\",\n askUser: async () => ({ action: \"allow\" as const }),\n },\n );\n\n // Bridge ToolUi → ToolUiEntry for chat messages\n if (afterResult.ui && \"uri\" in afterResult.ui) {\n const { uri, title, data } = afterResult.ui as {\n uri: string;\n title: string;\n data?: unknown;\n };\n const match = uri.match(/^ui:\\/\\/([^/]+)\\/(.+)$/);\n artifactMap[toolUseId] = {\n type: match?.[2] || uri,\n title,\n data,\n };\n hasArtifacts = true;\n }\n } catch (err) {\n logger.sys.error(`After hook error for ${tracked!.toolName}`, {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n toolInputTracker.delete(toolUseId);\n }\n\n return hasArtifacts ? artifactMap : null;\n}\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nexport function claudeCodeProvider(config: ClaudeCodeConfig = {}): LLMProvider {\n const useSubscription = config.useSubscription ?? false;\n const apiKey = useSubscription ? undefined : (config.apiKey ?? process.env.ANTHROPIC_API_KEY);\n\n async function query(\n ctx: Context,\n req: QueryLLMRequest,\n _options?: LLMQueryOptions,\n ): Promise<QueryLLMResponse> {\n const { query: claudeQuery } = await import(\"@anthropic-ai/claude-agent-sdk\");\n if (!apiKey && !useSubscription) {\n throw new Error(\n \"Anthropic API key is required. \" +\n \"Provide it via config.apiKey, ANTHROPIC_API_KEY env var, or set useSubscription: true.\",\n );\n }\n\n const startTime = Date.now();\n\n // Extract user message and system prompt\n const userMessage = [...req.messages].reverse().find((m) => m.role === \"user\");\n const prompt = userMessage?.content ?? \"\";\n const systemMessage = req.messages.find((m) => m.role === \"system\");\n const systemPrompt = config.systemPrompt ?? systemMessage?.content ?? \"\";\n\n let aggregatedContent = \"\";\n let lastAssistantContent = \"\";\n let json: string | undefined;\n let sdkError: string | undefined;\n let inputTokens = 0;\n let outputTokens = 0;\n\n // When resuming, skip setting systemPrompt — SDK uses the original session's prompt\n const isResuming = !!config.session?.resume;\n const systemPromptOption = isResuming\n ? undefined\n : systemPrompt\n ? {\n type: \"preset\" as const,\n preset: \"claude_code\" as const,\n append: typeof systemPrompt === \"string\" ? systemPrompt : \"\",\n }\n : undefined;\n\n // Build permission options (shared helper — hook-aware when tools provided)\n const {\n opts: permissionOptions,\n toolMap,\n toolInputTracker,\n } = buildPermissionOptions(ctx, config);\n\n logger.info(ctx, \"[ClaudeCode] Starting query\", {\n model: req.model,\n hasApiKey: !!apiKey,\n promptLength: typeof prompt === \"string\" ? prompt.length : 0,\n cwd: config.workingDirectory,\n mcpServers: Object.keys(config.mcpServers || {}),\n });\n\n let messageCount = 0;\n try {\n for await (const message of claudeQuery({\n prompt: typeof prompt === \"string\" ? prompt : JSON.stringify(prompt),\n options: {\n model: req.model,\n systemPrompt: systemPromptOption,\n ...(config.maxTurns ? { maxTurns: config.maxTurns } : {}),\n ...permissionOptions,\n ...(config.mcpServers ? { mcpServers: config.mcpServers } : {}),\n ...(config.workingDirectory ? { cwd: config.workingDirectory } : {}),\n ...(hasOutputFormat(config.output, \"json\") && config.output?.schema\n ? {\n outputFormat: {\n type: \"json_schema\" as const,\n schema: config.output.schema,\n },\n }\n : {}),\n ...(config.disallowedTools?.length ? { disallowedTools: config.disallowedTools } : {}),\n ...(config.abortController ? { abortController: config.abortController } : {}),\n ...(config.thinking ? { thinking: config.thinking } : {}),\n // Session resume/persistence options\n ...(config.session?.sessionId ? { sessionId: config.session.sessionId } : {}),\n ...(config.session?.resume ? { resume: config.session.resume } : {}),\n // SDK API uses persistSession/forkSession — we translate from\n // our internal `persist`/`fork` at this boundary.\n ...(config.session?.persist !== undefined\n ? { persistSession: config.session.persist }\n : {}),\n ...(config.session?.fork ? { forkSession: config.session.fork } : {}),\n env: {\n ...(apiKey ? { ANTHROPIC_API_KEY: apiKey } : {}),\n ...(useSubscription ? {} : { IS_SANDBOX: \"1\" }),\n HOME: process.env.HOME ?? \"\",\n PATH: process.env.PATH ?? \"\",\n TMPDIR: process.env.TMPDIR ?? \"\",\n NODE_ENV: process.env.NODE_ENV ?? \"\",\n },\n debugFile: \"/tmp/claude-code-debug.log\",\n stderr: (data: string) => logger.error(ctx, \"[ClaudeCode stderr]\", { data }),\n },\n })) {\n messageCount++;\n logger.info(ctx, \"[ClaudeCode] SDK message\", {\n count: messageCount,\n type: message.type,\n });\n\n // Skip replayed messages during session resume — they're old history.\n // Still heartbeat so the activity stays alive during replay.\n if ((message as any).isReplay) {\n if (config.heartbeat) config.heartbeat();\n continue;\n }\n\n if (config.heartbeat) {\n config.heartbeat();\n }\n\n // Track tool inputs from \"assistant\" messages for safe tools that bypass canUseTool\n // (SDK auto-approves Read, Glob, Grep without calling canUseTool in default mode)\n if (message.type === \"assistant\" && Array.isArray(message.message?.content)) {\n for (const block of message.message.content) {\n if (block?.type === \"tool_use\" && block.id && block.name) {\n if (!toolInputTracker.has(block.id)) {\n toolInputTracker.set(block.id, {\n toolName: block.name,\n input: (block.input || {}) as Record<string, unknown>,\n });\n }\n }\n }\n }\n\n // Process after hooks for tool_result messages — enrich with artifacts\n const artifacts = await processAfterHooks(ctx, {\n message,\n config,\n toolMap,\n toolInputTracker,\n });\n if (artifacts) {\n (message as any)._toolUi = artifacts;\n }\n\n // Forward all SDK messages for rich progress tracking\n if (config.onProgress) {\n await config.onProgress(message);\n // Heartbeat after async progress handling — may take time\n if (config.heartbeat) config.heartbeat();\n }\n\n if (message.type === \"assistant\" && message.message?.content) {\n lastAssistantContent = \"\";\n for (const block of message.message.content) {\n if (typeof block === \"string\") {\n lastAssistantContent += block;\n aggregatedContent += block;\n if (config.onChunk) config.onChunk(block);\n } else if (block.type === \"text\") {\n lastAssistantContent += block.text;\n aggregatedContent += block.text;\n if (config.onChunk) config.onChunk(block.text);\n }\n }\n }\n\n if (message.type === \"result\") {\n // Detect SDK error results (max_turns, budget, etc.)\n const subtype = (message as any).subtype;\n if (subtype && subtype !== \"success\") {\n const errors = (message as any).errors as string[] | undefined;\n sdkError = `Agent ${subtype}${errors?.length ? `: ${errors.join(\", \")}` : \"\"}`;\n }\n\n // Keep structured output separate — don't overwrite text content\n const structuredOutput = (message as any).structured_output;\n if (structuredOutput !== undefined && hasOutputFormat(config.output, \"json\")) {\n json =\n typeof structuredOutput === \"string\"\n ? structuredOutput\n : JSON.stringify(structuredOutput);\n }\n\n // Text result from SDK — use as content if we have no assistant text yet\n if (\"result\" in message && !aggregatedContent) {\n aggregatedContent = (message as any).result;\n }\n\n if (\"usage\" in message) {\n const usage = (message as any).usage;\n inputTokens = usage?.input_tokens ?? 0;\n outputTokens = usage?.output_tokens ?? 0;\n }\n }\n }\n } catch (error) {\n logger.error(ctx, \"[ClaudeCode] Query error\", {\n error: error instanceof Error ? error.message : String(error),\n model: req.model,\n apiKeyPresent: !!apiKey,\n cwd: config.workingDirectory,\n mcpServers: Object.keys(config.mcpServers || {}),\n });\n throw error;\n }\n\n logger.info(ctx, \"[ClaudeCode] Query complete\", { messageCount });\n\n return {\n content: lastAssistantContent || aggregatedContent,\n json,\n error: sdkError,\n toolCalls: undefined,\n metadata: {\n model: req.model,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n duration: Date.now() - startTime,\n provider: \"claude-code\",\n },\n };\n }\n\n async function* stream(\n ctx: Context,\n req: QueryLLMRequest,\n _options?: LLMQueryOptions,\n ): AsyncGenerator<QueryLLMResponse> {\n const { query: claudeQuery } = await import(\"@anthropic-ai/claude-agent-sdk\");\n if (!apiKey && !useSubscription) {\n throw new Error(\n \"Anthropic API key is required. \" +\n \"Provide it via config.apiKey, ANTHROPIC_API_KEY env var, or set useSubscription: true.\",\n );\n }\n\n const startTime = Date.now();\n\n const userMessage = [...req.messages].reverse().find((m) => m.role === \"user\");\n const prompt = userMessage?.content ?? \"\";\n const systemMessage = req.messages.find((m) => m.role === \"system\");\n const systemPrompt = config.systemPrompt ?? systemMessage?.content ?? \"\";\n\n let inputTokens = 0;\n let outputTokens = 0;\n\n // When resuming, skip setting systemPrompt — SDK uses the original session's prompt\n const isResuming = !!config.session?.resume;\n const streamSystemPromptOption = isResuming\n ? undefined\n : systemPrompt\n ? {\n type: \"preset\" as const,\n preset: \"claude_code\" as const,\n append: typeof systemPrompt === \"string\" ? systemPrompt : \"\",\n }\n : undefined;\n\n // Build permission options (shared helper — hook-aware when tools provided)\n const {\n opts: permissionOptions,\n toolMap,\n toolInputTracker,\n } = buildPermissionOptions(ctx, config);\n\n logger.info(ctx, \"[ClaudeCode] Starting stream\", {\n model: req.model,\n hasApiKey: !!apiKey,\n promptLength: typeof prompt === \"string\" ? prompt.length : 0,\n cwd: config.workingDirectory,\n mcpServers: Object.keys(config.mcpServers || {}),\n });\n\n let messageCount = 0;\n try {\n for await (const message of claudeQuery({\n prompt: typeof prompt === \"string\" ? prompt : JSON.stringify(prompt),\n options: {\n model: req.model,\n systemPrompt: streamSystemPromptOption,\n ...(config.maxTurns ? { maxTurns: config.maxTurns } : {}),\n ...permissionOptions,\n ...(config.mcpServers ? { mcpServers: config.mcpServers } : {}),\n ...(config.workingDirectory ? { cwd: config.workingDirectory } : {}),\n ...(hasOutputFormat(config.output, \"json\") && config.output?.schema\n ? {\n outputFormat: {\n type: \"json_schema\" as const,\n schema: config.output.schema,\n },\n }\n : {}),\n ...(config.disallowedTools?.length ? { disallowedTools: config.disallowedTools } : {}),\n ...(config.abortController ? { abortController: config.abortController } : {}),\n ...(config.thinking ? { thinking: config.thinking } : {}),\n // Session resume/persistence options\n ...(config.session?.sessionId ? { sessionId: config.session.sessionId } : {}),\n ...(config.session?.resume ? { resume: config.session.resume } : {}),\n // SDK API uses persistSession/forkSession — we translate from\n // our internal `persist`/`fork` at this boundary.\n ...(config.session?.persist !== undefined\n ? { persistSession: config.session.persist }\n : {}),\n ...(config.session?.fork ? { forkSession: config.session.fork } : {}),\n env: {\n ...(apiKey ? { ANTHROPIC_API_KEY: apiKey } : {}),\n ...(useSubscription ? {} : { IS_SANDBOX: \"1\" }),\n HOME: process.env.HOME ?? \"\",\n PATH: process.env.PATH ?? \"\",\n TMPDIR: process.env.TMPDIR ?? \"\",\n NODE_ENV: process.env.NODE_ENV ?? \"\",\n },\n debugFile: \"/tmp/claude-code-debug.log\",\n stderr: (data: string) => logger.error(ctx, \"[ClaudeCode stderr]\", { data }),\n },\n })) {\n messageCount++;\n logger.info(ctx, \"[ClaudeCode] SDK message\", {\n count: messageCount,\n type: message.type,\n });\n\n // Skip replayed messages during session resume — they're old history.\n // Still heartbeat so the activity stays alive during replay.\n if ((message as any).isReplay) {\n if (config.heartbeat) config.heartbeat();\n continue;\n }\n\n if (config.heartbeat) config.heartbeat();\n\n // Track tool inputs from \"assistant\" messages for safe tools that bypass canUseTool\n if (message.type === \"assistant\" && Array.isArray(message.message?.content)) {\n for (const block of message.message.content) {\n if (block?.type === \"tool_use\" && block.id && block.name) {\n if (!toolInputTracker.has(block.id)) {\n toolInputTracker.set(block.id, {\n toolName: block.name,\n input: (block.input || {}) as Record<string, unknown>,\n });\n }\n }\n }\n }\n\n // Process after hooks for tool_result messages — enrich with artifacts\n const artifacts = await processAfterHooks(ctx, {\n message,\n config,\n toolMap,\n toolInputTracker,\n });\n if (artifacts) {\n (message as any)._toolUi = artifacts;\n }\n\n if (config.onProgress) {\n await config.onProgress(message);\n if (config.heartbeat) config.heartbeat();\n }\n\n // Yield incremental text chunks as Claude Code produces them\n if (message.type === \"assistant\" && message.message?.content) {\n for (const block of message.message.content) {\n const text =\n typeof block === \"string\" ? block : block.type === \"text\" ? block.text : \"\";\n if (text) {\n if (config.onChunk) config.onChunk(text);\n yield {\n content: text,\n metadata: {\n model: req.model,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n duration: Date.now() - startTime,\n provider: \"claude-code\",\n },\n };\n }\n }\n }\n\n if (message.type === \"result\") {\n if (\"usage\" in message) {\n const usage = (message as any).usage;\n inputTokens = usage?.input_tokens ?? 0;\n outputTokens = usage?.output_tokens ?? 0;\n }\n // Keep structured output separate from text content\n const structuredOutput = (message as any).structured_output;\n const sc =\n structuredOutput !== undefined && hasOutputFormat(config.output, \"json\")\n ? typeof structuredOutput === \"string\"\n ? structuredOutput\n : JSON.stringify(structuredOutput)\n : undefined;\n // Final yield with updated usage metadata\n yield {\n content: \"\", // Text already yielded incrementally\n json: sc,\n metadata: {\n model: req.model,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n duration: Date.now() - startTime,\n provider: \"claude-code\",\n },\n };\n }\n }\n } catch (error) {\n logger.error(ctx, \"[ClaudeCode] Stream error\", {\n error: error instanceof Error ? error.message : String(error),\n model: req.model,\n apiKeyPresent: !!apiKey,\n cwd: config.workingDirectory,\n mcpServers: Object.keys(config.mcpServers || {}),\n });\n throw error;\n }\n\n logger.info(ctx, \"[ClaudeCode] Stream complete\", { messageCount });\n }\n\n async function getModels(): Promise<Model[]> {\n return claudeCodeModels.list();\n }\n\n return {\n name: \"claude-code\",\n query,\n stream,\n getModels,\n };\n}\n","/**\n * Agent Config Factory\n *\n * Pure definition — no execution logic.\n * The runtime (local, temporal, etc.) resolves this into a RuntimeAgentConfig\n * and passes it to harness() in @jarvis/runner.\n *\n * @example\n * ```typescript\n * import { agent } from \"@jarvis/sdk\";\n * import { run, local } from \"@jarvis/runner\";\n *\n * const myAgent = agent({\n * id: \"planner\",\n * instructions: \"You are a planner\",\n * tools: [getGoalsTool, createGoalsTool],\n * maxIterations: 10,\n * });\n *\n * const output = await run(ctx, { agent: myAgent, input: { message: \"Hello\" } }, {\n * runtime: local({ providers: { llm: openai() } }),\n * });\n * ```\n */\n\nimport type { AgentConfig } from \"@jarvis/types\";\n\n/**\n * Create an agent configuration.\n *\n * Returns a frozen AgentConfig — a pure definition with no execution logic.\n */\nexport function agent(config: AgentConfig): AgentConfig {\n return Object.freeze({ ...config });\n}\n","/**\n * Context Management\n *\n * Pure functions for managing LLM context window — token estimation,\n * message pruning, error compaction.\n */\n\nimport type { Message } from \"@jarvis/types\";\n\nimport type { PruneOptions, CompactError } from \"@jarvis/types\";\n\n// =============================================================================\n// TOKEN ESTIMATION\n// =============================================================================\n\n/**\n * Estimate token count for messages.\n * Rough approximation: 1 token ≈ 4 characters.\n */\nexport function estimateTokens(messages: Message[]): number {\n let totalChars = 0;\n\n for (const msg of messages) {\n totalChars += msg.role.length;\n\n if (msg.content) {\n totalChars += msg.content.length;\n }\n\n if (\"toolCalls\" in msg && msg.toolCalls) {\n for (const tc of msg.toolCalls) {\n totalChars += tc.name.length;\n totalChars += tc.args.length;\n }\n }\n\n if (\"toolCallId\" in msg && msg.toolCallId) {\n totalChars += msg.toolCallId.length;\n }\n }\n\n return Math.ceil(totalChars / 4);\n}\n\n// =============================================================================\n// MESSAGE PRUNING\n// =============================================================================\n\n/**\n * Prune messages to reduce context size.\n */\nexport function pruneMessages(\n messages: Message[],\n options: PruneOptions,\n): Message[] {\n const {\n maxTokens,\n keepRecent = 10,\n removeTool = [],\n removeBeforeIndex,\n } = options;\n\n let result = [...messages];\n\n // Step 1: Remove specific tool calls\n if (removeTool.length > 0) {\n const toolCallIdsToRemove = new Set<string>();\n\n for (const msg of result) {\n if (\"toolCalls\" in msg && msg.toolCalls) {\n for (const tc of msg.toolCalls) {\n if (removeTool.includes(tc.name)) {\n toolCallIdsToRemove.add(tc.id);\n }\n }\n }\n }\n\n result = result.filter((msg) => {\n if (\"toolCalls\" in msg && msg.toolCalls) {\n if (msg.toolCalls.some((tc) => toolCallIdsToRemove.has(tc.id)))\n return false;\n }\n if (\"toolCallId\" in msg && msg.toolCallId) {\n if (toolCallIdsToRemove.has(msg.toolCallId)) return false;\n }\n return true;\n });\n }\n\n // Step 2: Remove before index\n if (removeBeforeIndex !== undefined) {\n result = result.filter(\n (msg, idx) => msg.role === \"system\" || idx >= removeBeforeIndex,\n );\n }\n\n // Step 3: Keep only recent messages (preserve system)\n if (result.length > keepRecent) {\n const systemMessages = result.filter((msg) => msg.role === \"system\");\n const nonSystemMessages = result.filter((msg) => msg.role !== \"system\");\n const recentMessages = nonSystemMessages.slice(-keepRecent);\n result = [...systemMessages, ...recentMessages];\n }\n\n // Step 4: Token-based pruning\n if (maxTokens) {\n let currentTokens = estimateTokens(result);\n\n while (currentTokens > maxTokens && result.length > keepRecent) {\n const nonSystemIndex = result.findIndex((msg) => msg.role !== \"system\");\n if (nonSystemIndex === -1) break;\n\n result.splice(nonSystemIndex, 1);\n currentTokens = estimateTokens(result);\n }\n }\n\n return result;\n}\n\n// =============================================================================\n// ERROR COMPACTION\n// =============================================================================\n\n/**\n * Compact error for LLM context — minimal representation.\n */\nexport function compactError(\n error: Error,\n context: { toolName: string },\n): CompactError {\n return {\n name: error.name || \"Error\",\n message: error.message || \"Unknown error\",\n toolName: context.toolName,\n timestamp: new Date().toISOString(),\n };\n}\n","/**\n * Message Helpers\n *\n * Pure functions for creating chat messages (thinking, tool, text, ui).\n * Used by the agent harness in @jarvis/runner and by app code.\n */\n\nimport type {\n ChatMessage,\n ToolCallStatus,\n Ui,\n} from \"@jarvis/types\";\n\n// =============================================================================\n// ID GENERATION\n// =============================================================================\n\nlet messageCounter = 0;\n\nfunction generateId(): string {\n return `msg-${Date.now()}-${++messageCounter}`;\n}\n\n// =============================================================================\n// TOOL DESCRIPTION\n// =============================================================================\n\n/**\n * Generic fallback description generator.\n * Only handles truly generic output patterns (message, success).\n * App-specific descriptions should be provided via tool.metadata.describe().\n * Returns empty string when nothing meaningful can be generated — the UI\n * will hide the subtitle in that case.\n */\nexport function generateToolDescription(\n _toolName: string,\n status: ToolCallStatus,\n _input?: Record<string, unknown>,\n output?: unknown,\n t: (key: string) => string = (k) => k,\n): string {\n if (status !== \"completed\") return \"\";\n\n const out =\n output && typeof output === \"object\"\n ? (output as Record<string, unknown>)\n : {};\n\n // Explicit message in output\n if (\"message\" in out && typeof out.message === \"string\" && out.message) {\n return String(out.message).slice(0, 200);\n }\n\n // Generic success/failure flag\n if (\"success\" in out && typeof out.success === \"boolean\") {\n return out.success ? t(\"Completed successfully\") : t(\"Operation failed\");\n }\n\n return \"\";\n}\n\n// =============================================================================\n// MESSAGE FACTORIES\n// =============================================================================\n\n/**\n * Create a thinking message for the chat.\n */\nexport function thinkingMessage(\n content: string,\n isComplete: boolean,\n messageId: string,\n): ChatMessage {\n return {\n id: messageId,\n role: \"assistant\",\n type: \"thinking\",\n content,\n createdAt: new Date().toISOString(),\n metadata: { thinking: { status: isComplete ? \"complete\" : \"thinking\" } },\n };\n}\n\n/**\n * Create a tool message for the chat.\n */\nexport function toolMessage(\n toolName: string,\n toolCallId: string,\n options: {\n status: ToolCallStatus;\n label?: string;\n input?: Record<string, unknown>;\n output?: unknown;\n error?: string;\n durationMs?: number;\n ui?: Ui;\n description?: string;\n },\n): ChatMessage {\n return {\n id: `tool-${toolCallId}`,\n role: \"assistant\",\n type: \"tool\",\n content:\n options.description ||\n generateToolDescription(\n toolName,\n options.status,\n options.input,\n options.output,\n ),\n createdAt: new Date().toISOString(),\n metadata: {\n toolCall: {\n toolName,\n toolCallId,\n status: options.status,\n label: options.label,\n input: options.input,\n output: options.output,\n error: options.error,\n durationMs: options.durationMs,\n },\n ...(options.ui ? { ui: options.ui } : {}),\n },\n };\n}\n\n/**\n * Create a text message for the chat.\n */\nexport function textMessage(\n content: string,\n role: \"assistant\" | \"user\",\n): ChatMessage {\n return {\n id: generateId(),\n role,\n type: \"text\",\n content,\n createdAt: new Date().toISOString(),\n };\n}\n\n/**\n * Create a UI component message for the chat.\n */\nexport function uiMessage(\n uri: string,\n title: string,\n data: unknown,\n): ChatMessage {\n return {\n id: generateId(),\n role: \"assistant\",\n type: \"ui\",\n content: title,\n createdAt: new Date().toISOString(),\n metadata: { ui: { uri, title, data } },\n };\n}\n","export {\n thinkingMessage,\n toolMessage,\n textMessage,\n uiMessage,\n generateToolDescription,\n} from \"./messages\";\n","/**\n * Tools Domain\n * Pure functions for creating and calling tools\n */\nimport type {\n CallTool,\n Context,\n ToolHooks,\n BeforeToolHook,\n AfterToolHook,\n Tool,\n ToolMetadata,\n Schema,\n ToolHookOptions,\n} from \"@jarvis/types\";\n\n// Re-export hook identity functions from types\nexport { before, after } from \"@jarvis/types\";\n\n// =============================================================================\n// extractHooks() - Extract hooks from tools for agent creation\n// =============================================================================\n\nexport function extractHooks<TState = unknown>(\n tools: Tool[],\n): {\n before: Record<string, BeforeToolHook<TState>>;\n after: Record<string, AfterToolHook<TState>>;\n} {\n const before: Record<string, BeforeToolHook<TState>> = {};\n const after: Record<string, AfterToolHook<TState>> = {};\n\n for (const t of tools) {\n if (t.hooks?.before) {\n before[t.name] = t.hooks.before as BeforeToolHook<TState>;\n }\n if (t.hooks?.after) {\n after[t.name] = t.hooks.after as AfterToolHook<TState>;\n }\n }\n\n return { before, after };\n}\n\n// =============================================================================\n// tool() Factory\n// =============================================================================\n\n/**\n * Create a tool with optional colocated hooks.\n *\n * @example\n * ```typescript\n * const myTool = tool({\n * name: \"createGoal\",\n * description: \"Create a new goal\",\n * schema: {\n * input: { type: \"object\", properties: { title: { type: \"string\" } } },\n * output: { type: \"object\", properties: { goalId: { type: \"string\" } } },\n * },\n * call: async (ctx, input) => ({ goalId: \"g-123\" }),\n * metadata: {\n * label: \"Create Goal\",\n * permissions: { roles: [\"editor\"], risk: \"moderate\" },\n * ui: { component: \"goals\", title: \"Goals\" },\n * },\n * hooks: {\n * before: before<MyState>(async (ctx, req, { askUser }) => ({ action: \"allow\" })),\n * after: after<MyState>(async (ctx, req) => ({\n * context: { created: true },\n * state: { goals: [...req.state.goals, req.output] },\n * })),\n * },\n * });\n * ```\n */\nexport function tool<TState = unknown>(config: {\n name: string;\n description: string;\n schema: { input: Schema; output: Schema };\n call?: CallTool;\n hooks?: ToolHooks<TState>;\n metadata?: ToolMetadata;\n build?: (ctx: unknown, req: { tool: Tool; state: TState }) => Tool;\n}): Tool {\n return {\n name: config.name,\n description: config.description,\n input: config.schema.input,\n output: config.schema.output,\n call: config.call,\n hooks: config.hooks,\n metadata: config.metadata,\n build: config.build as Tool[\"build\"],\n };\n}\n\n// =============================================================================\n// buildTools() - Apply build() to tools with current state\n// =============================================================================\n\n/**\n * Build tools by applying schema builders and pre-binding options.\n *\n * Three phases per tool:\n * 1. Apply permissions check via before hook (if metadata.permissions is set)\n * 2. Apply `build()` for schema-only changes (dynamic enums from state)\n * 3. Wrap `call()` to pre-bind options (if call has >= 2 params)\n * 4. Wrap hooks to spread app options flat into hook options\n */\nexport function buildTools(\n ctx: Context,\n req: { tools: Tool[]; state: unknown },\n options?: unknown,\n): Tool[] {\n return req.tools.map((t) => {\n // Phase 0: If tool has permissions, inject a before hook that checks roles/tiers\n const permissions = t.metadata?.permissions;\n if (permissions?.roles?.length || permissions?.tiers?.length) {\n const existingBefore = t.hooks?.before;\n t = {\n ...t,\n hooks: {\n ...t.hooks,\n before: async (hookCtx: Context, hookReq: { toolName: string; input: unknown; toolCallId: string; state: unknown }, hookOpts: ToolHookOptions) => {\n const access = (hookCtx as Context & { access?: { role?: string; tier?: string } }).access;\n const role = access?.role ?? \"\";\n const tier = access?.tier ?? \"free\";\n if (permissions.roles?.length && !permissions.roles.includes(role)) {\n return { action: \"deny\" as const, reason: \"Access denied: insufficient role\" };\n }\n if (permissions.tiers?.length && !permissions.tiers.includes(tier)) {\n return { action: \"deny\" as const, reason: \"Access denied: insufficient tier\" };\n }\n if (existingBefore) return existingBefore(hookCtx, hookReq, hookOpts);\n return { action: \"allow\" as const };\n },\n },\n };\n }\n\n // Phase 1: Apply build (schema-only, no options)\n const built = t.build ? t.build(ctx, { tool: t, state: req.state }) : t;\n if (options == null) return built;\n\n const result = { ...built };\n\n // Phase 2: Wrap call to pre-bind options (if call has >= 2 params)\n if (result.call && result.call.length >= 2) {\n const baseCall = result.call as (\n ctx: Context,\n input: unknown,\n options?: unknown,\n ) => Promise<unknown>;\n result.call = ((ctxArg: Context, input: unknown) =>\n baseCall(ctxArg, input, options)) as CallTool;\n }\n\n // Phase 3: Wrap hooks to spread app options flat into hook options\n if (result.hooks) {\n const baseHooks = result.hooks;\n result.hooks = {\n before: baseHooks.before\n ? async (ctx: Context, req: { toolName: string; input: unknown; toolCallId: string; state: unknown }, hookOpts: ToolHookOptions) =>\n baseHooks.before!(ctx, req, {\n ...hookOpts,\n ...(options as object),\n } as ToolHookOptions)\n : undefined,\n after: baseHooks.after\n ? async (ctx: Context, req: unknown, hookOpts: ToolHookOptions) =>\n baseHooks.after!(ctx, req as Parameters<NonNullable<typeof baseHooks.after>>[1], {\n ...hookOpts,\n ...(options as object),\n } as ToolHookOptions)\n : undefined,\n };\n }\n\n return result;\n });\n}\n\n/**\n * Call a tool directly (for testing or simple invocation).\n */\nexport async function call(req: { tool: Tool; input: unknown }): Promise<unknown> {\n if (!req.tool.call) {\n throw new Error(\n `Tool ${req.tool.name} has no call function.`,\n );\n }\n return await req.tool.call(req.input);\n}\n","/**\n * Plan Tool\n * Platform-level tool for presenting plans to users for approval\n *\n * This tool allows agents to present a plan (list of steps) to the user\n * and wait for approval/modification before proceeding.\n *\n * @example\n * ```typescript\n * import { planTool } from \"@jarvis/sdk\";\n *\n * const tools = [planTool, ...otherTools];\n *\n * // Agent can now use the plan tool:\n * // LLM: \"I'll create a plan for you to review\"\n * // Tool call: plan({ title: \"...\", steps: [...], reasoning: \"...\" })\n * // → User sees PlanPanel in UI\n * // → User approves/modifies/rejects\n * // → Agent continues based on user response\n * ```\n */\nimport { Context } from \"@jarvis/types\";\nimport { tool } from \"./tools\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * A single step in a plan\n */\nexport interface PlanStep {\n /** Unique identifier for the step */\n id: string;\n /** Step title (brief description) */\n title: string;\n /** Optional detailed description */\n description?: string;\n /** Optional category for grouping/styling */\n category?: string;\n}\n\n/**\n * Input for the plan tool\n */\nexport interface PlanInput {\n /** Plan title shown in the header */\n title: string;\n /** List of steps in the plan */\n steps: PlanStep[];\n /** Optional reasoning explaining why this plan */\n reasoning?: string;\n}\n\n/**\n * Output from the plan tool\n */\nexport interface PlanOutput {\n /** Plan title */\n title: string;\n /** Plan items (steps mapped to items) */\n items: PlanStep[];\n /** Optional reasoning */\n reasoning?: string;\n}\n\n// =============================================================================\n// SCHEMA\n// =============================================================================\n\nconst planInputSchema = {\n type: \"object\" as const,\n properties: {\n title: {\n type: \"string\",\n description: \"A brief title for the plan\",\n },\n steps: {\n type: \"array\",\n description: \"The steps in the plan\",\n items: {\n type: \"object\",\n properties: {\n id: {\n type: \"string\",\n description: \"Unique identifier for this step\",\n },\n title: {\n type: \"string\",\n description: \"Brief title for the step\",\n },\n description: {\n type: \"string\",\n description: \"Detailed description of what this step involves\",\n },\n category: {\n type: \"string\",\n description:\n \"Optional category for grouping (e.g., 'setup', 'implementation', 'testing')\",\n },\n },\n required: [\"id\", \"title\"],\n },\n },\n reasoning: {\n type: \"string\",\n description: \"Explanation of why this plan was chosen\",\n },\n },\n required: [\"title\", \"steps\"],\n};\n\nconst planOutputSchema = {\n type: \"object\" as const,\n properties: {\n title: { type: \"string\" },\n items: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n id: { type: \"string\" },\n title: { type: \"string\" },\n description: { type: \"string\" },\n category: { type: \"string\" },\n },\n },\n },\n reasoning: { type: \"string\" },\n },\n};\n\n// =============================================================================\n// TOOL\n// =============================================================================\n\n/**\n * Plan tool for presenting plans to users\n *\n * Usage:\n * - Agent calls this tool to present a plan\n * - Tool output is shown in PlanPanel UI component\n * - User can approve, reject, or modify the plan\n * - Agent receives user's response via the after hook\n */\nexport const planTool = tool({\n name: \"plan\",\n description:\n \"Present a plan to the user for approval before executing. Use this when you need user confirmation before proceeding with a multi-step task. The user can approve, reject, or suggest modifications to the plan.\",\n schema: {\n input: planInputSchema,\n output: planOutputSchema,\n },\n // The call function simply passes through the input as output\n // The actual plan review happens in the after hook via wait()\n call: async (_ctx: Context, input: PlanInput): Promise<PlanOutput> => ({\n title: input.title,\n items: input.steps,\n reasoning: input.reasoning,\n }),\n // Hooks handle the human-in-the-loop approval flow\n hooks: {\n // After hook waits for user approval\n after: async (ctx, req, options) => {\n const planOutput = req.output as PlanOutput;\n\n // Wait for user input (shows PlanPanel in UI)\n const userInput = await options.askUser({\n reason: planOutput.title,\n data: planOutput,\n });\n\n // Handle user response\n if (!userInput || userInput.action === \"deny\") {\n return {\n context: {\n status: \"denied\",\n message: userInput?.feedback || \"Plan was rejected by user\",\n },\n status: \"denied\",\n message: userInput?.feedback || \"Plan was rejected by user\",\n };\n }\n\n if (userInput.action === \"modify\") {\n return {\n context: {\n status: \"modify\",\n userFeedback: userInput.feedback,\n originalPlan: planOutput,\n },\n status: \"modify\",\n message: userInput.feedback || \"User requested modifications\",\n };\n }\n\n // Approved\n return {\n context: {\n status: \"approved\",\n plan: planOutput,\n message: \"Plan approved by user. Proceed with execution.\",\n },\n ui: {\n uri: \"ui://sdk/plan\",\n title: planOutput.title,\n data: planOutput,\n },\n };\n },\n },\n // Metadata for UI display\n metadata: {\n describe: (ctx, req) => {\n const input = req.input as unknown as PlanInput;\n if (req.status === \"running\") {\n return `Creating plan: ${input.title}`;\n }\n if (req.status === \"completed\") {\n return `Plan \"${input.title}\" ready for review`;\n }\n return undefined;\n },\n },\n});\n","/**\n * Ask User Tool\n * Platform-level tool for asking users structured questions\n *\n * This tool allows agents to ask clarifying questions with predefined options,\n * pausing execution until the user responds. Each question appears as a tab\n * with selectable options and an \"Other\" free-text input.\n *\n * @example\n * ```typescript\n * import { askUserTool } from \"@jarvis/sdk\";\n *\n * const tools = [askUserTool, ...otherTools];\n *\n * // Agent can now use the askUser tool:\n * // LLM: \"I need to understand your preference\"\n * // Tool call: askUser({ questions: [{ header: \"Approach\", question: \"...\", options: [...] }] })\n * // → User sees AskUserPanel in UI\n * // → User selects options or types custom answer\n * // → Agent continues with user's answers\n * ```\n */\nimport { tool } from \"./tools\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * A single option within a question\n */\nexport interface AskUserOption {\n /** Display label for the option */\n label: string;\n /** Optional description explaining the option */\n description?: string;\n}\n\n/**\n * A single question with options\n */\nexport interface AskUserQuestion {\n /** Short label displayed as tab header (max ~12 chars) */\n header: string;\n /** Full question text */\n question: string;\n /** Available options (2-4) */\n options: AskUserOption[];\n /** Whether user can select multiple options (default: false) */\n multiSelect?: boolean;\n}\n\n/**\n * Input for the askUser tool\n */\nexport interface AskUserInput {\n /** Questions to ask (1-4) */\n questions: AskUserQuestion[];\n}\n\n/**\n * A single answer from the user\n */\nexport interface AskUserAnswer {\n /** Header of the question being answered */\n header: string;\n /** Selected option label(s) */\n selected: string[];\n /** Custom text if user chose \"Other\" */\n customText?: string;\n}\n\n/**\n * Output from the askUser tool\n */\nexport interface AskUserOutput {\n /** The questions that were asked */\n questions: AskUserQuestion[];\n /** User's answers (populated after user responds) */\n answers?: AskUserAnswer[];\n}\n\n// =============================================================================\n// SCHEMA\n// =============================================================================\n\nconst askUserInputSchema = {\n type: \"object\" as const,\n properties: {\n questions: {\n type: \"array\",\n description: \"Questions to ask the user (1-4 questions)\",\n minItems: 1,\n maxItems: 4,\n items: {\n type: \"object\",\n properties: {\n header: {\n type: \"string\",\n description:\n \"Short label for the tab header (e.g., 'Approach', 'Priority')\",\n },\n question: {\n type: \"string\",\n description: \"The full question to ask the user\",\n },\n options: {\n type: \"array\",\n description:\n \"Available options (2-4). User always has an 'Other' free-text option automatically.\",\n minItems: 2,\n maxItems: 4,\n items: {\n type: \"object\",\n properties: {\n label: {\n type: \"string\",\n description: \"Option display label\",\n },\n description: {\n type: \"string\",\n description: \"Optional explanation of this option\",\n },\n },\n required: [\"label\"],\n },\n },\n multiSelect: {\n type: \"boolean\",\n description:\n \"Whether user can select multiple options (default: false)\",\n },\n },\n required: [\"header\", \"question\", \"options\"],\n },\n },\n },\n required: [\"questions\"],\n};\n\nconst askUserOutputSchema = {\n type: \"object\" as const,\n properties: {\n questions: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n header: { type: \"string\" },\n question: { type: \"string\" },\n options: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n label: { type: \"string\" },\n description: { type: \"string\" },\n },\n },\n },\n multiSelect: { type: \"boolean\" },\n },\n },\n },\n answers: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n header: { type: \"string\" },\n selected: { type: \"array\", items: { type: \"string\" } },\n customText: { type: \"string\" },\n },\n },\n },\n },\n};\n\n// =============================================================================\n// TOOL\n// =============================================================================\n\n/**\n * Ask User tool for structured questions\n *\n * Usage:\n * - Agent calls this tool to ask the user questions\n * - Tool output is shown in AskUserPanel UI component\n * - User can select options or type custom answers\n * - Agent receives user's answers via the after hook\n */\nexport const askUserTool = tool({\n name: \"askUser\",\n description: `Ask the user clarifying questions when you need their input to proceed. Use this when the request is ambiguous, you need a preference between approaches, or the scope/priority is unclear. Each question has predefined options plus a free-text 'Other' option. Do NOT use this for plan approval (use exitPlanMode instead) or internal reasoning (use think instead).\n\nGuidelines:\n- Do NOT ask questions you can resolve using available tools\n- Prefer making reasonable defaults over asking — only ask when the choice genuinely matters\n- Keep header labels concise (1-4 words like 'Approach', 'Priority')\n- Mark the recommended option with '(Recommended)' suffix\n- In plan mode, questions should relate to the plan being developed`,\n schema: {\n input: askUserInputSchema,\n output: askUserOutputSchema,\n },\n // Pass-through: returns questions as output for UI rendering\n call: async (_ctx, input: AskUserInput): Promise<AskUserOutput> => ({\n questions: input.questions,\n }),\n // After hook waits for user answers\n hooks: {\n after: async (ctx, req, options) => {\n const output = req.output as AskUserOutput;\n\n // Wait for user input (shows AskUserPanel in UI)\n const userInput = await options.askUser({\n reason:\n output.questions.length === 1\n ? output.questions[0]!.question\n : `${output.questions.length} questions to answer`,\n data: output,\n });\n\n // Handle user skip/cancel\n if (!userInput || userInput.action === \"deny\") {\n return {\n context: {\n status: \"skipped\",\n message:\n userInput?.feedback ||\n \"User skipped the questions. Proceed with your best judgment.\",\n },\n status: \"denied\",\n message: userInput?.feedback || \"User skipped the questions\",\n };\n }\n\n // Extract answers from user response\n const answers = (userInput.data as { answers?: AskUserAnswer[] })\n ?.answers;\n\n if (!answers || answers.length === 0) {\n return {\n context: {\n status: \"skipped\",\n message: \"No answers provided. Proceed with your best judgment.\",\n },\n status: \"denied\",\n message: \"No answers provided\",\n };\n }\n\n // Format answers for LLM context\n const formattedAnswers = answers\n .map((a) => {\n const selection =\n a.selected.length > 0\n ? a.selected.join(\", \")\n : a.customText || \"No selection\";\n return `${a.header}: ${selection}`;\n })\n .join(\"\\n\");\n\n return {\n context: {\n status: \"answered\",\n answers,\n summary: formattedAnswers,\n message: `User answered:\\n${formattedAnswers}`,\n },\n ui: {\n uri: \"ui://sdk/ask-user\",\n title: \"User Answers\",\n data: { questions: output.questions, answers },\n },\n };\n },\n },\n // Metadata for UI display\n metadata: {\n permissions: { risk: \"safe\" },\n describe: (ctx, req) => {\n const input = req.input as unknown as AskUserInput;\n if (req.status === \"running\") {\n return input.questions?.length === 1\n ? `Asking: ${input.questions[0]!.header}`\n : `Asking ${input.questions?.length || 0} questions`;\n }\n if (req.status === \"completed\") {\n const output = req.output as AskUserOutput;\n if (output?.answers) {\n return `Answered ${output.answers.length} question${output.answers.length !== 1 ? \"s\" : \"\"}`;\n }\n return \"Questions skipped\";\n }\n return undefined;\n },\n },\n});\n","/**\n * Search Tool\n * Platform-level tool for searching entities using natural language\n *\n * This tool provides a unified interface for hybrid search (semantic + metadata).\n * Products configure it with their search providers.\n *\n * @example\n * ```typescript\n * import { searchTool } from \"@jarvis/sdk\";\n * import { search } from \"@jarvis/search\";\n * import { bm25Provider } from \"@jarvis/rerank\";\n *\n * const searchConfig = {\n * db,\n * providers: [tasksService, goalsService],\n * embeddingProvider: openai,\n * vectorProvider: db,\n * rerankProvider: bm25Provider(),\n * };\n *\n * const tools = [\n * searchTool({\n * search: (request) => search(searchConfig, request),\n * }),\n * ...otherTools,\n * ];\n * ```\n */\nimport type { SearchRequest, SearchResponse } from \"@jarvis/types\";\n\nimport { tool } from \"./tools\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Search tool configuration\n */\nexport interface SearchToolConfig {\n /** Search function implementation */\n search: (request: SearchRequest) => Promise<SearchResponse>;\n}\n\n/**\n * Input for the search tool\n */\nexport interface SearchToolInput {\n /** Natural language search query */\n query: string;\n /** Filter by entity types (e.g., [\"task\", \"goal\"]) */\n entityTypes?: string[];\n /** Maximum results to return */\n limit?: number;\n}\n\n/**\n * Output from the search tool\n */\nexport interface SearchToolOutput {\n /** Search results */\n items: Array<{\n id: string;\n title: string;\n content: string;\n score: number;\n source: \"web\" | \"vector\" | \"metadata\";\n entityType?: string;\n entityId?: string;\n url?: string;\n /** Entity data for rendering in artifacts */\n metadata?: Record<string, unknown>;\n }>;\n /** Original query */\n query: string;\n}\n\n// =============================================================================\n// SCHEMA\n// =============================================================================\n\nconst searchInputSchema = {\n type: \"object\" as const,\n properties: {\n query: {\n type: \"string\",\n description:\n \"Natural language search query (e.g., 'fitness goals', 'project deadlines')\",\n },\n entityTypes: {\n type: \"array\",\n description:\n \"Optional filter by entity types (e.g., ['task', 'goal', 'project'])\",\n items: { type: \"string\" },\n },\n limit: {\n type: \"number\",\n description: \"Maximum number of results to return (default: 10)\",\n },\n },\n required: [\"query\"],\n};\n\nconst searchOutputSchema = {\n type: \"object\" as const,\n properties: {\n items: {\n type: \"array\",\n description: \"Search results ranked by relevance\",\n items: {\n type: \"object\",\n properties: {\n id: { type: \"string\" },\n title: { type: \"string\" },\n content: { type: \"string\" },\n score: { type: \"number\" },\n source: {\n type: \"string\",\n enum: [\"web\", \"vector\", \"metadata\"],\n },\n entityType: { type: \"string\" },\n entityId: { type: \"string\" },\n url: { type: \"string\" },\n metadata: { type: \"object\" },\n },\n },\n },\n query: { type: \"string\" },\n },\n};\n\n// =============================================================================\n// TOOL FACTORY\n// =============================================================================\n\n/**\n * Creates a search tool configured with the provided search function\n *\n * @example\n * ```typescript\n * import { searchTool } from \"@jarvis/sdk\";\n * import { search, SearchConfig } from \"@jarvis/search\";\n *\n * const config: SearchConfig = {\n * db,\n * providers: [tasksService, goalsService, projectsService],\n * embeddingProvider: openai,\n * vectorProvider: db,\n * rerankProvider: bm25Provider({ weight: 0.3 }),\n * };\n *\n * export const mySearchTool = searchTool({\n * search: (request) => search(config, request),\n * });\n * ```\n */\nexport function searchTool(config: SearchToolConfig) {\n return tool({\n name: \"search\",\n description:\n \"Search for entities using natural language. Combines semantic search with metadata matching for comprehensive results. Use this to find tasks, goals, projects, or any other entities.\",\n schema: {\n input: searchInputSchema,\n output: searchOutputSchema,\n },\n call: async (input: SearchToolInput): Promise<SearchToolOutput> => {\n const response = await config.search({\n query: input.query,\n entityTypes: input.entityTypes,\n limit: input.limit,\n });\n\n return {\n items: response.items.map((item) => ({\n id: item.id,\n title: item.title,\n content: item.content,\n score: item.score,\n source: item.source,\n entityType: item.entityType,\n entityId: item.entityId,\n url: item.url,\n metadata: item.metadata,\n })),\n query: input.query,\n };\n },\n metadata: {\n describe: (ctx, req) => {\n const input = req.input as unknown as SearchToolInput;\n if (req.status === \"running\") {\n return `Searching for \"${input.query}\"...`;\n }\n if (req.status === \"completed\") {\n const output = req.output as unknown as SearchToolOutput;\n return `Found ${output?.items?.length ?? 0} results for \"${input.query}\"`;\n }\n return undefined;\n },\n },\n });\n}\n","/**\n * Think Tool\n *\n * Platform-level internal reasoning tool. No side effects.\n * The agent uses this to organize thoughts, reflect, and plan\n * before taking action. Hidden from conversation UI.\n */\n\nimport { Context } from \"@jarvis/types\";\n\nimport { tool } from \"./tools\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface ThinkInput {\n thought: string;\n}\n\nexport interface ThinkOutput {\n acknowledged: boolean;\n}\n\n// =============================================================================\n// Schemas\n// =============================================================================\n\nconst thinkInputSchema = {\n type: \"object\" as const,\n properties: {\n thought: {\n type: \"string\",\n description: \"Your internal reasoning, reflection, or planning\",\n },\n },\n required: [\"thought\"],\n};\n\nconst thinkOutputSchema = {\n type: \"object\" as const,\n properties: {\n acknowledged: { type: \"boolean\" },\n },\n};\n\n// =============================================================================\n// Tool\n// =============================================================================\n\n/**\n * Internal reasoning tool — no side effects, hidden from UI.\n * Use for organizing thoughts before acting.\n */\nexport const thinkTool = tool({\n name: \"think\",\n description: `Use this tool for internal reasoning, reflection, and planning your next steps. No side effects — output is never shown to the user.\n\nGood uses:\n- Breaking down complex problems into steps\n- Evaluating trade-offs between approaches\n- Synthesizing information from multiple tool results\n- Planning multi-step operations before acting\n\nThis consumes tokens like any other tool call. Use for genuinely complex reasoning, not simple decisions.`,\n schema: {\n input: thinkInputSchema,\n output: thinkOutputSchema,\n },\n call: async (_ctx: Context, _input: ThinkInput) => ({ acknowledged: true }),\n metadata: { hidden: true },\n});\n","/**\n * Plan Mode Tools\n *\n * enterPlanMode / exitPlanMode — explicit plan-first mode.\n * When active, only non-destructive + safe tools are available.\n */\n\nimport type { AgentMode } from \"@jarvis/types\";\nimport { tool, after } from \"./tools\";\n\n// =============================================================================\n// enterPlanMode\n// =============================================================================\n\nexport const enterPlanModeTool = tool({\n name: \"enterPlanMode\",\n description: `Enter planning mode to research and design before taking action. Only non-destructive and safe tools are available until exitPlanMode is called.\n\nWhen to use:\n- Complex tasks with multiple steps or approaches\n- Ambiguous requirements needing exploration\n- Tasks where the user's preference between approaches matters\n- Unfamiliar domains requiring research first\n\nWhen NOT to use:\n- Simple, direct requests with clear intent\n- Follow-up actions on an already-agreed plan\n- Quick questions or lookups\n\nDecision rule: If you're unsure how to approach the task, enter plan mode. The cost of unnecessary planning is low; the cost of a wrong approach is high.`,\n schema: {\n input: { type: \"object\" as const, properties: {} },\n output: {\n type: \"object\" as const,\n properties: { mode: { type: \"string\" } },\n },\n },\n call: async () => ({ mode: \"plan\" as AgentMode }),\n hooks: {\n after: after<{ mode?: AgentMode; previousMode?: AgentMode }>(async (_ctx, _req) => ({\n context: {\n mode: \"plan\",\n message: `Plan mode is now active. Only non-destructive tools are available.\nYour next steps:\n1. Research the task using available tools\n2. Understand the current state and constraints\n3. Identify the best approach\n4. Draft a step-by-step plan\n5. Present the plan to the user\n6. Call exitPlanMode when the plan is approved`,\n },\n state: { mode: \"plan\" as AgentMode, previousMode: \"auto\" as AgentMode },\n })),\n },\n metadata: {\n label: \"Enter Plan Mode\",\n permissions: { risk: \"safe\" },\n },\n});\n\n// =============================================================================\n// exitPlanMode\n// =============================================================================\n\nexport const exitPlanModeTool = tool({\n name: \"exitPlanMode\",\n description: `Exit planning mode and signal the plan is ready for execution. All tools become available after exit.\n\nBefore calling this:\n- You should have researched and understood the task\n- You should have presented a clear plan to the user\n- The user should have had a chance to review or adjust\n\nAfter exit: Execute the plan step by step.`,\n schema: {\n input: { type: \"object\" as const, properties: {} },\n output: {\n type: \"object\" as const,\n properties: { mode: { type: \"string\" } },\n },\n },\n call: async () => ({ mode: \"auto\" as AgentMode }),\n hooks: {\n after: after<{ mode?: AgentMode; previousMode?: AgentMode }>(async (_ctx, _req) => ({\n context: {\n mode: \"auto\",\n message: \"Plan mode exited. All tools are now available. Execute the plan you presented, working through it step by step.\",\n },\n state: { mode: \"auto\" as AgentMode, previousMode: undefined },\n })),\n },\n metadata: {\n label: \"Exit Plan Mode\",\n permissions: { risk: \"safe\" },\n },\n});\n","/**\n * Agent Tool\n *\n * Tool for spawning a sub-agent of the current agent with a different task.\n * The sub-agent runs with the same agent config but can have filtered tools.\n */\n\nimport type { SubAgentRequest, SubAgentResponse, SubAgentFn } from \"./agent.tools.types\";\nimport { tool } from \"./tools\";\n\n// =============================================================================\n// agentTool — spawn a sub-agent of self\n// =============================================================================\n\n/**\n * Spawn a sub-agent with a task and optional tool filtering.\n *\n * @example\n * ```typescript\n * import { agentTool, buildTools } from \"@jarvis/sdk\";\n *\n * const tools = buildTools(ctx, {\n * tools: [agentTool, ...otherTools],\n * state: currentState,\n * }, {\n * spawnSubAgent: async (task, context, options) => {\n * return { message: \"Done\", success: true, requestCount: 0 };\n * },\n * });\n * ```\n */\nexport const agentTool = tool({\n name: \"agent\",\n description: `Spawn a sub-agent to handle a task independently.\n\nGuidelines:\n- Use filters.tools to restrict tools for focused tasks\n- Use model override for cost optimization: smaller model for simple tasks, larger for complex reasoning\n- Provide complete context in the task description — the sub-agent doesn't share your conversation history\n- After the sub-agent completes, synthesize its findings before acting — don't just pass through results`,\n schema: {\n input: {\n type: \"object\",\n properties: {\n task: {\n type: \"string\",\n description: \"The task to delegate. Be specific and include all relevant context.\",\n },\n context: {\n type: \"object\",\n description: \"Additional context to pass to the sub-agent\",\n },\n model: {\n type: \"string\",\n description:\n \"Override model ID for the sub-agent (e.g., 'claude-sonnet-4-20250514', 'gpt-4o')\",\n },\n filters: {\n type: \"object\",\n description: \"Filters for the sub-agent\",\n properties: {\n tools: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Restrict which tools the sub-agent can use (whitelist by tool name)\",\n },\n },\n },\n },\n required: [\"task\"],\n },\n output: {\n type: \"object\",\n properties: {\n message: { type: \"string\" },\n success: { type: \"boolean\" },\n requestCount: { type: \"number\" },\n ui: { type: \"object\" },\n },\n },\n },\n\n call: async (_ctx: unknown, input: unknown, options?: Record<string, unknown>) => {\n const { task, context, model, filters } = input as SubAgentRequest;\n const spawnSubAgent = options?.spawnSubAgent as SubAgentFn | undefined;\n if (!spawnSubAgent) {\n throw new Error(\"spawnSubAgent callback not provided via buildTools options\");\n }\n return spawnSubAgent(task, context, { model, filters });\n },\n\n hooks: {\n before: async (_ctx: unknown, req: { input: unknown }) => ({\n action: \"allow\" as const,\n input: req.input,\n }),\n after: async (_ctx: unknown, req: { input: unknown; output: unknown }) => {\n const output = req.output as SubAgentResponse;\n return {\n context: {\n message: output.message,\n success: output.success,\n requestCount: output.requestCount,\n },\n ui: output.ui,\n };\n },\n },\n});\n","/**\n * Tools Domain\n * Re-exports for tools functionality\n */\n\n// Functions\nexport { tool, extractHooks, call, buildTools, before, after } from \"./tools\";\n\n// Pre-built tools\nexport { planTool } from \"./plan.tool\";\nexport type { PlanStep, PlanInput, PlanOutput } from \"./plan.tool\";\n\nexport { askUserTool } from \"./ask-user.tool\";\nexport type {\n AskUserQuestion,\n AskUserOption,\n AskUserInput,\n AskUserAnswer,\n AskUserOutput,\n} from \"./ask-user.tool\";\n\nexport { searchTool } from \"./search.tool\";\nexport type {\n SearchToolConfig,\n SearchToolInput,\n SearchToolOutput,\n} from \"./search.tool\";\n\n// Think tool (internal reasoning - hidden from UI)\nexport { thinkTool } from \"./think.tool\";\nexport type { ThinkInput, ThinkOutput } from \"./think.tool\";\n\n// Plan mode tools\nexport { enterPlanModeTool, exitPlanModeTool } from \"./plan-mode.tool\";\n\n// Agent tool (sub-agent)\nexport { agentTool } from \"./agent.tools\";\nexport type { SubAgentRequest, SubAgentResponse, SubAgentFn } from \"./agent.tools.types\";\n\n// Platform tools - default tools for every orchestrator\nimport { askUserTool } from \"./ask-user.tool\";\nimport { planTool } from \"./plan.tool\";\nimport { thinkTool } from \"./think.tool\";\n\n/** Platform tools that should be included in every orchestrator by default */\nexport const platformTools = [planTool, askUserTool, thinkTool];\n","/**\n * Skills Domain\n * Factory function for creating skills with collection and import methods.\n *\n * The skill() factory is both a creator and a namespace:\n * - skill({...}) — create a skill inline\n * - skill.add(s) — add a skill to the registry\n * - skill.list() — get all registered skills\n * - skill.get(id) — get a skill by ID\n */\n\nimport type { Skill, Prompt, SkillHooks } from \"@jarvis/types\";\n\nimport type { Tool } from \"@jarvis/types\"; // Used by SkillConfig\n\n// =============================================================================\n// skillHooks() Factory\n// =============================================================================\n\n/**\n * Create a skill hooks container (type-safe factory).\n * Mirrors the hooks() factory for tools.\n *\n * @example\n * ```typescript\n * import { skill, skillHooks } from \"@jarvis/sdk\";\n * import type { OrchestratorState } from \"./orchestrator.types\";\n *\n * const mySkill = skill({\n * id: \"my-skill\",\n * // ...\n * hooks: skillHooks<OrchestratorState>({\n * before: async (ctx, req, options) => ({\n * action: \"allow\",\n * messages: [{ role: \"system\", content: `State: ${JSON.stringify(ctx.state)}` }],\n * }),\n * after: async (ctx, req, options) => ({\n * context: { message: req.message },\n * state: req.skillState,\n * }),\n * }),\n * });\n * ```\n */\nexport function skillHooks<TState = unknown>(\n config: SkillHooks<TState>\n): SkillHooks<TState> {\n return config;\n}\n\n// =============================================================================\n// Internal Registry\n// =============================================================================\n\nconst registry = new Map<string, Skill>();\n\n// =============================================================================\n// skill() Factory + Namespace\n// =============================================================================\n\ninterface SkillConfig {\n id: string;\n name: string;\n description: string;\n prompt: Prompt;\n tools: Tool[];\n maxIterations?: number;\n version?: string;\n author?: string;\n tags?: string[];\n hooks?: SkillHooks<unknown>;\n}\n\n/**\n * Create a skill with typed configuration\n *\n * Skills are procedural knowledge - prompts and methodology that transform\n * general-purpose agents into specialists.\n *\n * @example\n * ```typescript\n * import { skill, tool, prompt } from \"@jarvis/sdk\";\n *\n * // Inline definition\n * export const codeReviewSkill = skill({\n * id: \"code-review\",\n * name: \"Code Review\",\n * description: \"Systematic code review\",\n * prompt: codeReviewPrompt,\n * tools: [analyzeCodeTool],\n * maxIterations: 5,\n * });\n *\n * // Import from directory\n * const analyticsSkill = await skill.fromDir(\"./skills/analytics\");\n *\n * // Add to registry\n * skill.add(codeReviewSkill);\n *\n * // Load (fromDir + add)\n * await skill.load(\"./skills/research\");\n *\n * // Query registry\n * skill.list(); // -> Skill[]\n * skill.get(\"code-review\"); // -> Skill | undefined\n * ```\n */\nfunction createSkill(config: SkillConfig): Skill {\n return {\n id: config.id,\n name: config.name,\n description: config.description,\n prompt: config.prompt,\n tools: config.tools,\n maxIterations: config.maxIterations,\n version: config.version,\n author: config.author,\n tags: config.tags,\n hooks: config.hooks,\n };\n}\n\n// =============================================================================\n// Collection Methods\n// =============================================================================\n\n/**\n * Add a skill to the internal registry.\n */\nfunction add(s: Skill): Skill {\n registry.set(s.id, s);\n return s;\n}\n\n/**\n * Get all registered skills.\n */\nfunction list(): Skill[] {\n return [...registry.values()];\n}\n\n/**\n * Get a registered skill by ID.\n */\nfunction get(id: string): Skill | undefined {\n return registry.get(id);\n}\n\n// =============================================================================\n// Export: skill as callable + namespace\n// =============================================================================\n\nexport const skill = Object.assign(createSkill, {\n add,\n list,\n get,\n});\n","/**\n * useSkill Tool Factory\n *\n * Creates a tool that allows the orchestrator to delegate tasks to specialized skills.\n * Skills run as child orchestrator workflows with their own instructions and tools.\n */\n\nimport type { Skill, UseSkillInput, UseSkillOutput } from \"@jarvis/types\";\n\nimport { tool } from \"../tools\";\n\n// =============================================================================\n// useSkillTool() Factory\n// =============================================================================\n\n/**\n * Create a useSkill tool for delegating tasks to specialized skills\n *\n * The tool is created with:\n * - An enum of available skill IDs\n * - Descriptions of each skill for the LLM to choose from\n * - A call function that executes the skill (provided by the consumer)\n *\n * @example\n * ```typescript\n * import { useSkillTool } from \"@jarvis/sdk\";\n * import { executeChild, workflowInfo } from \"@temporalio/workflow\";\n * import { plannerSkills } from \"../skills/planner.skills\";\n *\n * // Create the useSkill tool\n * const skillTool = useSkillTool({\n * skills: plannerSkills.list(),\n * call: async (input) => {\n * const skill = plannerSkills.get(input.skillId);\n * if (!skill) throw new Error(`Skill not found: ${input.skillId}`);\n *\n * // Execute as child orchestrator workflow\n * const result = await executeChild(\"orchestrator\", {\n * args: [{\n * userMessage: input.task,\n * skillId: input.skillId,\n * chatHistory: [],\n * previousState: currentState,\n * userId,\n * chatId,\n * parentWorkflowId: workflowInfo().workflowId,\n * }],\n * workflowId: `skill-${input.skillId}-${Date.now()}`,\n * });\n *\n * return {\n * message: result.message,\n * success: result.success,\n * state: result.state,\n * };\n * },\n * });\n *\n * // Add to orchestrator tools\n * const tools = [...allTools, skillTool];\n * ```\n */\nexport function useSkillTool(config: {\n /** Available skills */\n skills: Skill[];\n /** Function to execute the skill (usually via executeChild) */\n call: (input: UseSkillInput) => Promise<UseSkillOutput>;\n}) {\n const skillEnum = config.skills.map((s) => s.id);\n const skillDescriptions = config.skills\n .map((s) => `- ${s.id}: ${s.description}`)\n .join(\"\\n\");\n\n return tool({\n name: \"skill\",\n description: `Delegate a task to a specialized skill. The skill will execute with its own instructions and tools, then return the result.\n\nAvailable skills:\n${skillDescriptions}`,\n schema: {\n input: {\n type: \"object\",\n properties: {\n skillId: {\n type: \"string\",\n enum: skillEnum,\n description: \"ID of the skill to use\",\n },\n task: {\n type: \"string\",\n description: \"The task to delegate to the skill. Be specific and provide all necessary context.\",\n },\n context: {\n type: \"object\",\n description: \"Additional context data for the skill (optional)\",\n },\n },\n required: [\"skillId\", \"task\"],\n },\n output: {\n type: \"object\",\n properties: {\n message: { type: \"string\", description: \"Response from the skill\" },\n success: { type: \"boolean\", description: \"Whether the skill completed successfully\" },\n },\n },\n },\n call: async (input) => {\n return config.call(input as UseSkillInput);\n },\n });\n}\n","/**\n * Skills Module\n *\n * Provides factories for creating skills and the useSkill tool.\n */\n\nexport { skill, skillHooks } from \"./skills\";\nexport { useSkillTool } from \"./skill.tool\";\n","export class ServiceError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly statusCode: number = 500,\n public readonly context?: Record<string, unknown>,\n ) {\n super(message);\n this.name = \"ServiceError\";\n Error.captureStackTrace?.(this, this.constructor);\n }\n\n toJSON() {\n return {\n error: this.message,\n code: this.code,\n ...(this.context && { details: this.context }),\n };\n }\n}\n\nexport class ValidationError extends ServiceError {\n constructor(message: string, context?: Record<string, unknown>) {\n super(message, \"VALIDATION_ERROR\", 400, context);\n this.name = \"ValidationError\";\n }\n}\n\nexport class UnauthorizedError extends ServiceError {\n constructor(message = \"Unauthorized\", context?: Record<string, unknown>) {\n super(message, \"UNAUTHORIZED\", 401, context);\n this.name = \"UnauthorizedError\";\n }\n}\n\nexport class ForbiddenError extends ServiceError {\n constructor(message = \"Forbidden\", context?: Record<string, unknown>) {\n super(message, \"FORBIDDEN\", 403, context);\n this.name = \"ForbiddenError\";\n }\n}\n\nexport class NotFoundError extends ServiceError {\n constructor(entity: string, id?: string) {\n super(\n id ? `${entity} not found: ${id}` : `${entity} not found`,\n \"NOT_FOUND\",\n 404,\n { entity, ...(id && { id }) },\n );\n this.name = \"NotFoundError\";\n }\n}\n\nexport class ConflictError extends ServiceError {\n constructor(message: string, context?: Record<string, unknown>) {\n super(message, \"CONFLICT\", 409, context);\n this.name = \"ConflictError\";\n }\n}\n\nexport class ConfigurationError extends ServiceError {\n constructor(message: string, field?: string) {\n super(message, \"CONFIGURATION_ERROR\", 500, field ? { field } : undefined);\n this.name = \"ConfigurationError\";\n }\n}\n","export {\n ServiceError,\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n NotFoundError,\n ConflictError,\n ConfigurationError,\n} from \"./errors\";\n","/**\n * Prompts Functions\n * Pure functions mirroring PromptProvider and PromptRenderer interfaces\n */\n\nimport type {\n Prompt,\n PromptTools,\n RenderPromptResponse,\n ValidatePromptResponse,\n PromptProvider,\n PromptRenderer,\n Message,\n Schema,\n PromptOptions,\n} from \"@jarvis/types\";\nimport { ConfigurationError } from \"@jarvis/errors\";\n\nimport type { PromptProviderProxy, PromptRendererProxy } from \"./prompts.types\";\n\n/**\n * Create a prompt definition\n *\n * @example\n * ```typescript\n * import { prompt } from \"@jarvis/sdk\";\n *\n * const greeting = prompt({\n * id: \"greeting\",\n * name: \"Greeting\",\n * description: \"Personalized greeting\",\n * content: \"Hello, {{name}}!\",\n * input: {\n * name: { type: \"string\", description: \"Name to greet\" }\n * }\n * });\n * ```\n */\nexport function prompt(config: {\n id: string;\n name: string;\n description: string;\n content?: string;\n messages?: Message[];\n version?: string;\n format?: string;\n input?: Schema;\n output?: Schema;\n options?: PromptOptions;\n tools?: PromptTools;\n}): Prompt {\n return {\n id: config.id,\n name: config.name,\n description: config.description,\n version: config.version || \"1.0.0\",\n format: config.format || \"text\",\n content: config.content,\n messages: config.messages,\n input: config.input,\n output: config.output,\n options: config.options,\n tools: config.tools,\n };\n}\n\n/**\n * Get a single prompt (internal function mirroring PromptProvider.getPrompt)\n *\n * @internal\n */\nexport async function getPrompt(params: {\n id: string;\n version?: string;\n provider: PromptProvider | PromptProviderProxy;\n}): Promise<{ prompt: Prompt }> {\n return params.provider.getPrompt({\n promptId: params.id,\n version: params.version,\n });\n}\n\n/**\n * Get multiple prompts (internal function mirroring PromptProvider.getPrompts)\n *\n * @internal\n */\nexport async function getPrompts(params: {\n query?: string;\n version?: string;\n provider: PromptProvider | PromptProviderProxy;\n}): Promise<{ prompts: Prompt[] }> {\n return params.provider.getPrompts({\n query: params.query,\n version: params.version,\n });\n}\n\n/**\n * Validate prompt (internal function mirroring PromptRenderer.validate)\n *\n * @internal\n */\nexport async function validate(params: {\n prompt: Prompt;\n args: Record<string, unknown>;\n renderer: PromptRenderer | PromptRendererProxy;\n}): Promise<ValidatePromptResponse> {\n return params.renderer.validate({\n prompt: params.prompt,\n args: params.args,\n });\n}\n\n/**\n * Render prompt (Overload 1: fetch + render with prompt ID)\n *\n * @example\n * ```typescript\n * const { messages } = await render({\n * prompt: \"greeting\",\n * args: { name: \"Alice\" },\n * provider: promptProvider,\n * renderer: mustacheRenderer,\n * });\n * ```\n */\nexport async function render(request: {\n prompt: string;\n args: Record<string, unknown>;\n provider: PromptProvider | PromptProviderProxy;\n renderer: PromptRenderer | PromptRendererProxy;\n version?: string;\n}): Promise<RenderPromptResponse>;\n\n/**\n * Render prompt (Overload 2: render only with Prompt object)\n *\n * @example\n * ```typescript\n * const { messages } = await render({\n * prompt: greetingPrompt,\n * args: { name: \"Alice\" },\n * renderer: mustacheRenderer,\n * });\n * ```\n */\nexport async function render(request: {\n prompt: Prompt;\n args: Record<string, unknown>;\n renderer: PromptRenderer | PromptRendererProxy;\n}): Promise<RenderPromptResponse>;\n\n/**\n * Render implementation\n */\nexport async function render(request: {\n prompt: Prompt | string;\n args: Record<string, unknown>;\n renderer: PromptRenderer | PromptRendererProxy;\n provider?: PromptProvider | PromptProviderProxy;\n version?: string;\n}): Promise<RenderPromptResponse> {\n let prompt: Prompt;\n\n // If prompt is a string ID, fetch it first\n if (typeof request.prompt === \"string\") {\n if (!request.provider) {\n throw new ConfigurationError(\n \"Provider is required when using prompt ID string\",\n );\n }\n\n const { prompt: fetchedPrompt } = await getPrompt({\n id: request.prompt,\n version: request.version,\n provider: request.provider,\n });\n\n prompt = fetchedPrompt;\n } else {\n prompt = request.prompt;\n }\n\n // Render the prompt (mirroring PromptRenderer.render)\n return request.renderer.render({\n prompt,\n args: request.args,\n });\n}\n","/**\n * Mustache Renderer\n * Simple mustache-style template renderer for prompts\n */\n\nimport type {\n PromptRenderer,\n RenderPromptRequest,\n RenderPromptResponse,\n ValidatePromptRequest,\n ValidatePromptResponse,\n Message,\n} from \"@jarvis/types\";\n\n/**\n * Render a mustache template string with variables\n * Supports:\n * - Simple variables: {{variable}}\n * - Conditional sections: {{#variable}}content{{/variable}} - render if truthy\n * - Inverted sections: {{^variable}}content{{/variable}} - render if falsy\n */\nexport function renderTemplate(template: string, args: Record<string, unknown>): string {\n let result = template;\n\n // 1. Handle inverted sections {{^variable}}...{{/variable}} (render if falsy)\n result = result.replace(\n /\\{\\{\\^(\\w+)\\}\\}([\\s\\S]*?)\\{\\{\\/\\1\\}\\}/g,\n (_match, key, content) => {\n const value = args[key];\n // Render content if value is falsy or empty array/string\n if (!value || (Array.isArray(value) && value.length === 0) || value === \"\") {\n return renderTemplate(content, args);\n }\n return \"\";\n }\n );\n\n // 2. Handle conditional sections {{#variable}}...{{/variable}}\n result = result.replace(\n /\\{\\{#(\\w+)\\}\\}([\\s\\S]*?)\\{\\{\\/\\1\\}\\}/g,\n (_match, key, content) => {\n const value = args[key];\n // Skip if value is falsy or empty array/string\n if (!value || (Array.isArray(value) && value.length === 0) || value === \"\") {\n return \"\";\n }\n // Render content with variables substituted\n return renderTemplate(content, args);\n }\n );\n\n // 3. Handle simple variables {{variable}}\n result = result.replace(/\\{\\{(\\w+)\\}\\}/g, (_match, key) => {\n const value = args[key];\n if (value === undefined || value === null) {\n return \"\";\n }\n return String(value);\n });\n\n return result;\n}\n\n/**\n * Render a message with mustache variables\n */\nfunction renderMessage(message: Message, args: Record<string, unknown>): Message {\n const content = typeof message.content === \"string\"\n ? renderTemplate(message.content, args)\n : message.content ?? \"\";\n\n return {\n ...message,\n content,\n } as Message;\n}\n\n/**\n * Create a mustache renderer instance\n */\nexport function mustacheRenderer(): PromptRenderer {\n return {\n name: \"mustache\",\n\n async render(request: RenderPromptRequest): Promise<RenderPromptResponse> {\n const { prompt, args } = request;\n\n // If prompt has messages, render each message\n if (prompt.messages && prompt.messages.length > 0) {\n const messages = prompt.messages.map((msg) => renderMessage(msg, args));\n return {\n messages,\n output: prompt.output,\n metadata: {\n promptId: prompt.id,\n promptName: prompt.name,\n version: prompt.version || \"1.0.0\",\n provider: \"mustache\",\n },\n };\n }\n\n // If prompt has content, render as a single system message\n if (prompt.content) {\n const renderedContent = renderTemplate(prompt.content, args);\n return {\n messages: [{ role: \"system\", content: renderedContent }],\n output: prompt.output,\n metadata: {\n promptId: prompt.id,\n promptName: prompt.name,\n version: prompt.version || \"1.0.0\",\n provider: \"mustache\",\n },\n };\n }\n\n // No content to render\n return {\n messages: [],\n output: prompt.output,\n metadata: {\n promptId: prompt.id,\n promptName: prompt.name,\n version: prompt.version || \"1.0.0\",\n provider: \"mustache\",\n },\n };\n },\n\n async validate(request: ValidatePromptRequest): Promise<ValidatePromptResponse> {\n const { prompt, args } = request;\n\n // Check if all required variables are provided\n if (prompt.input && prompt.input.properties) {\n const required: string[] = Array.isArray(prompt.input.required)\n ? prompt.input.required\n : [];\n for (const key of required) {\n if (args[key] === undefined) {\n return {\n valid: false,\n message: `Missing required variable: ${key}`,\n };\n }\n }\n }\n\n return { valid: true };\n },\n };\n}\n\n/**\n * Default mustache renderer instance\n */\nexport const defaultMustacheRenderer = mustacheRenderer();\n","/**\n * Prompts Domain Exports\n */\n\n// Functions (public)\nexport { render, prompt } from \"./prompts\";\n\n// Renderers\nexport { renderTemplate, mustacheRenderer, defaultMustacheRenderer } from \"./mustache\";\n\n// Types\nexport type * from \"./prompts.types\";\n\n// Internal functions (getPrompt, getPrompts, validate) are NOT exported\n// They are used internally by render() and other SDK functions\n","/**\n * Reference Factory\n *\n * Factory for defining reference types with metadata and creation logic.\n * Follows the same config pattern as entity(), resolver(), tool(), etc.\n *\n * @example\n * ```typescript\n * import { ref } from \"@jarvis/sdk\";\n * import type { DateReference } from \"@jarvis/types\";\n *\n * export const dateReference = ref<DateReference>({\n * type: \"date\",\n * label: \"Date\",\n * icon: \"calendar\",\n * color: \"purple\",\n * displayName: (input) => formatDateStr(input.date),\n * });\n *\n * // Usage:\n * const myDate = dateReference.create({ date: \"2024-01-01\" });\n * ```\n */\n\nimport type {\n Reference,\n ReferenceType,\n RefConfig,\n Ref,\n EntityReference,\n DateReference,\n DateRangeReference,\n FileReference,\n UrlReference,\n TextReference,\n ResolvedReference,\n Resolver,\n} from \"@jarvis/types\";\n\n// =============================================================================\n// Internal Helpers\n// =============================================================================\n\nfunction formatDateStr(date: string): string {\n return new Date(date).toLocaleDateString(undefined, {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n/** Format a date for LLM context display */\nfunction formatDateOnly(dateStr: unknown): string {\n if (!dateStr) return \"N/A\";\n try {\n const d = new Date(dateStr as string);\n return d.toLocaleDateString(\"en-US\", {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n } catch {\n return String(dateStr);\n }\n}\n\n/** Fallback formatter — selective JSON (exclude noisy fields) */\nfunction formatGeneric(name: string, type: string, data: unknown): string {\n const lines = [`### ${type}: ${name}`];\n\n if (data && typeof data === \"object\") {\n const cleanData = { ...(data as Record<string, unknown>) };\n delete cleanData.id;\n delete cleanData.userId;\n delete cleanData.createdAt;\n delete cleanData.updatedAt;\n delete cleanData.deletedAt;\n\n lines.push(\"```json\");\n lines.push(JSON.stringify(cleanData, null, 2));\n lines.push(\"```\");\n }\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Define a reference type with metadata and creation logic.\n *\n * Returns a Ref definition with `.create()` for instantiation\n * and metadata fields (label, icon, color, format) for UI/LLM use.\n */\nexport function ref<T extends Reference>(config: RefConfig<T>): Ref<T> {\n return {\n type: config.type,\n label: config.label,\n icon: config.icon,\n color: config.color,\n format: config.format,\n create: (input) => {\n const displayName =\n input.displayName || config.displayName?.(input) || \"\";\n return {\n id: Math.random().toString(36).substring(2, 10),\n type: config.type,\n displayName,\n createdAt: new Date().toISOString(),\n ...input,\n } as T;\n },\n };\n}\n\n// =============================================================================\n// Reference Definitions\n// =============================================================================\n\nexport const entityReference = ref<EntityReference>({\n type: \"entity\",\n label: \"Entity\",\n icon: \"box\",\n color: \"blue\",\n format: (displayName: string, data: unknown) => {\n const d = data as Record<string, unknown>;\n const lines = [`### Entity: ${displayName}`];\n if (d.id) lines.push(`- **Entity ID**: \\`${d.id}\\``);\n if (d.entityType) lines.push(`- **Entity Type**: ${d.entityType}`);\n\n const cleanData = { ...d };\n delete cleanData.id;\n delete cleanData.userId;\n delete cleanData.createdAt;\n delete cleanData.updatedAt;\n delete cleanData.deletedAt;\n delete cleanData.entityType;\n\n if (Object.keys(cleanData).length > 0) {\n lines.push(\"```json\");\n lines.push(JSON.stringify(cleanData, null, 2));\n lines.push(\"```\");\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n },\n});\n\nexport const dateReference = ref<DateReference>({\n type: \"date\",\n label: \"Date\",\n icon: \"calendar\",\n color: \"purple\",\n displayName: (input) => formatDateStr(input.date),\n format: (name: string, data: unknown) => {\n const d = data as Record<string, unknown>;\n const lines = [`### Date: ${name}`];\n\n if (d.date) lines.push(`- **Date**: ${formatDateOnly(d.date)}`);\n if (d.events && Array.isArray(d.events))\n lines.push(`- **Events on this date**: ${d.events.length}`);\n if (d.tasks && Array.isArray(d.tasks))\n lines.push(`- **Tasks due**: ${d.tasks.length}`);\n\n lines.push(\"\");\n return lines.join(\"\\n\");\n },\n});\n\nexport const dateRangeReference = ref<DateRangeReference>({\n type: \"dateRange\",\n label: \"Date Range\",\n icon: \"calendar\",\n color: \"purple\",\n displayName: (input) =>\n `${formatDateStr(input.startDate)} - ${formatDateStr(input.endDate)}`,\n});\n\nexport const fileReference = ref<FileReference>({\n type: \"file\",\n label: \"File\",\n icon: \"file\",\n color: \"gray\",\n displayName: (input) => input.path.split(\"/\").pop() || input.path,\n});\n\nexport const urlReference = ref<UrlReference>({\n type: \"url\",\n label: \"URL\",\n icon: \"link\",\n color: \"cyan\",\n displayName: (input) => new URL(input.url).hostname,\n});\n\nexport const textReference = ref<TextReference>({\n type: \"text\",\n label: \"Text\",\n icon: \"text\",\n color: \"gray\",\n displayName: (input) =>\n input.content.length > 30\n ? input.content.slice(0, 30) + \"...\"\n : input.content,\n});\n\n// =============================================================================\n// Collection\n// =============================================================================\n\nconst allRefs: Ref<Reference>[] = [\n entityReference as Ref<Reference>,\n dateReference as Ref<Reference>,\n dateRangeReference as Ref<Reference>,\n fileReference as Ref<Reference>,\n urlReference as Ref<Reference>,\n textReference as Ref<Reference>,\n];\n\nexport const references = {\n // Definitions\n entity: entityReference,\n date: dateReference,\n dateRange: dateRangeReference,\n file: fileReference,\n url: urlReference,\n text: textReference,\n\n /** Format reference for display */\n format: (r: Reference): string => {\n const meta = references.get(r.type);\n return meta ? `[${meta.icon}] ${r.displayName}` : r.displayName;\n },\n\n /** List all ref definitions */\n list: (): Ref<Reference>[] => allRefs,\n\n /** Get ref definition by type */\n get: (type: ReferenceType): Ref<Reference> | undefined =>\n allRefs.find((r) => r.type === type),\n\n /**\n * Format resolved references for LLM context.\n * Priority: resolver format → ref definition format → generic JSON fallback.\n */\n \n formatResolved: (\n resolved: ResolvedReference[],\n resolverDefs?: Resolver<Reference, unknown>[],\n ): string => {\n if (resolved.length === 0) return \"\";\n\n const sections: string[] = [\"## Referenced Context\\n\"];\n\n for (const r of resolved) {\n if (!r.resolved || !r.data) {\n sections.push(\n `### ${r.reference.displayName} (${r.reference.type}) - NOT FOUND`,\n );\n sections.push(`> ${r.error || \"Could not resolve this reference\"}`);\n sections.push(\n \"*Ask the user how to proceed or if they want to select a different item.*\\n\",\n );\n continue;\n }\n\n // Priority 1: Resolver-level format (e.g. entity.format for entity resolvers)\n const entityType =\n r.reference.type === \"entity\"\n ? (r.reference as EntityReference).entityType\n : undefined;\n const def = resolverDefs?.find(\n (d) =>\n d.type === r.reference.type &&\n (!entityType || d.entityType === entityType),\n );\n\n if (def?.format) {\n sections.push(def.format(r.reference.displayName, r.data));\n continue;\n }\n\n // Priority 2: Ref definition format\n const refDef = references.get(r.reference.type);\n if (refDef?.format) {\n sections.push(refDef.format(r.reference.displayName, r.data));\n continue;\n }\n\n // Priority 3: Generic fallback\n sections.push(\n formatGeneric(r.reference.displayName, r.reference.type, r.data),\n );\n }\n\n return sections.join(\"\\n\");\n },\n};\n","/**\n * Reference Resolver\n *\n * Factories and helpers for defining and using reference resolvers.\n *\n * Factories:\n * - resolver() — define a resolver with (ctx, ref, options) signature\n * - resolvers() — create a collection with built-in resolve/format/bind utilities\n */\n\nimport type {\n Context,\n Reference,\n ReferenceType,\n EntityReference,\n ResolvedReference,\n ResolverConfig,\n Resolver,\n ResolverCollection,\n BoundResolverCollection,\n ResolveReferenceResponse,\n} from \"@jarvis/types\";\n\nimport { references } from \"./reference\";\n\n// =============================================================================\n// Factories\n// =============================================================================\n\n/**\n * Define a resolver with type-safe (ctx, ref, options) signature.\n */\nexport function resolver<T extends Reference = Reference, TData = unknown>(\n config: ResolverConfig<T, TData>,\n): Resolver<T, TData> {\n return {\n type: config.type,\n entityType: config.entityType,\n resolve: config.resolve,\n format: config.format as Resolver<T, TData>[\"format\"],\n };\n}\n\n/**\n * Create a resolver collection with built-in resolve, format, and bind utilities.\n */\nexport function resolvers(\n input: Resolver<Reference, unknown>[] | { custom?: Resolver<Reference, unknown>[] },\n): ResolverCollection {\n let defs: Resolver<Reference, unknown>[];\n if (Array.isArray(input)) {\n defs = input;\n } else {\n defs = [...(input.custom ?? [])];\n }\n\n const list = () => defs;\n\n const get = (type: ReferenceType, entityType?: string) =>\n defs.find(\n (r) => r.type === type && (!entityType || r.entityType === entityType),\n );\n\n const resolveSingle = async <T extends Reference>(\n ctx: Context,\n ref: T,\n options: Record<string, unknown>,\n ): Promise<ResolvedReference<T>> => {\n const entityType =\n ref.type === \"entity\"\n ? (ref as unknown as EntityReference).entityType\n : undefined;\n const def = get(ref.type, entityType);\n\n if (!def) {\n return {\n reference: ref,\n resolved: false,\n data: null,\n error: `No resolver for ${ref.type}${entityType ? `:${entityType}` : \"\"}`,\n };\n }\n\n try {\n const response = await (def.resolve as (ctx: Context, ref: Reference, options: Record<string, unknown>) => Promise<ResolveReferenceResponse>)(ctx, ref, options);\n return {\n reference: ref,\n resolved: response.resolved,\n data: response.data,\n error: response.error,\n };\n } catch (error) {\n return {\n reference: ref,\n resolved: false,\n data: null,\n error: error instanceof Error ? error.message : \"Resolution failed\",\n };\n }\n };\n\n const resolveAll = (ctx: Context, refs: Reference[], options: Record<string, unknown>) =>\n Promise.all(refs.map((ref) => resolveSingle(ctx, ref, options)));\n\n const format = (resolved: ResolvedReference[]) =>\n references.formatResolved(resolved, defs);\n\n const bind = (options: Record<string, unknown>): BoundResolverCollection => ({\n list,\n get,\n resolve: <T extends Reference>(ctx: Context, ref: T) =>\n resolveSingle(ctx, ref, options),\n resolveAll: (ctx: Context, refs: Reference[]) =>\n resolveAll(ctx, refs, options),\n format,\n });\n\n return { list, get, resolve: resolveSingle, resolveAll, format, bind };\n}\n","/**\n * References Module\n * Factory functions, resolvers, and utilities for the reference system\n */\n\n// Reference factory and definitions\nexport {\n ref,\n entityReference,\n dateReference,\n dateRangeReference,\n fileReference,\n urlReference,\n textReference,\n references,\n} from \"./reference\";\n\n// Resolver factories\nexport {\n resolver,\n resolvers,\n} from \"./resolver\";\n\n// Resolver types (re-exported from @jarvis/types)\nexport type {\n ReferenceResolver,\n ResolverConfig,\n Resolver,\n ResolverCollection,\n BoundResolverCollection,\n} from \"@jarvis/types\";\n","/**\n * Resources Domain\n * Pure functions for creating MCP resources\n */\n\nimport type { Resource } from \"@jarvis/types\";\n\n/**\n * Create a resource definition\n *\n * @example\n * ```typescript\n * const statusResource = resource({\n * uri: \"mcp://server/status\",\n * name: \"Server Status\",\n * description: \"Current server status and statistics\",\n * mimeType: \"application/json\",\n * });\n * ```\n */\nexport function resource(config: {\n uri: string;\n name: string;\n description: string;\n mimeType?: string;\n}): Resource {\n return {\n uri: config.uri,\n name: config.name,\n description: config.description,\n mimeType: config.mimeType || \"application/json\",\n };\n}\n","/**\n * Resources Domain\n * Pure functions for creating MCP resources\n */\n\nexport { resource } from \"./resources\";\nexport type { Resource } from \"@jarvis/types\";\n","/**\n * @jarvis/sdk/agents\n *\n * Agent framework: agents, tools, skills, prompts, messages, references.\n * Everything needed to build AI agents — add this on top of sdk/data.\n *\n * @example\n * ```typescript\n * import { agent, tool, skill, prompt } from \"@jarvis/sdk/agents\";\n * ```\n */\n\n// Agents\nexport { agent } from \"./agents\";\nexport { estimateTokens, pruneMessages, compactError } from \"./context\";\n\n// Messages\nexport {\n thinkingMessage,\n toolMessage,\n textMessage,\n uiMessage,\n generateToolDescription,\n} from \"./messages\";\n\n// Tools\nexport {\n tool,\n extractHooks,\n call,\n buildTools,\n before,\n after,\n planTool,\n askUserTool,\n thinkTool,\n agentTool,\n enterPlanModeTool,\n exitPlanModeTool,\n platformTools,\n} from \"./tools\";\nexport type {\n PlanStep,\n PlanInput,\n PlanOutput,\n AskUserQuestion,\n AskUserOption,\n AskUserInput,\n AskUserAnswer,\n AskUserOutput,\n SearchToolConfig,\n SearchToolInput,\n SearchToolOutput,\n ThinkInput,\n ThinkOutput,\n SubAgentRequest,\n SubAgentResponse,\n SubAgentFn,\n} from \"./tools\";\n\n// Skills\nexport { skill, skillHooks, useSkillTool } from \"./skills\";\n\n// Prompts\nexport {\n render,\n prompt,\n renderTemplate,\n mustacheRenderer,\n defaultMustacheRenderer,\n} from \"./prompts\";\nexport type * from \"./prompts\";\n\n// References\nexport {\n ref,\n entityReference,\n dateReference,\n dateRangeReference,\n fileReference,\n urlReference,\n textReference,\n references,\n resolver,\n resolvers,\n} from \"./references\";\n\n// Resources\nexport { resource } from \"./resources\";\n","/**\n * Table Factory, Field Helpers, and Index Helpers\n *\n * table<T>() creates a pure schema definition — no CRUD methods.\n * CRUD is handled by the DatabaseProvider directly:\n * db.find(ctx, { table: usersTable, filter: { email } })\n *\n * Every column is explicit — what you declare is what the DB gets.\n * No implicit system columns.\n */\n\nimport type { Table, TableConfig } from \"@jarvis/types\";\nimport type { FieldConfig, FieldType, IndexConfig, JsonFieldSchema } from \"@jarvis/types\";\n\n// =============================================================================\n// UTILITIES\n// =============================================================================\n\n/** Convert camelCase to snake_case */\nexport function toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n// =============================================================================\n// table<T>() FACTORY — Pure schema definition\n// =============================================================================\n\n/**\n * Create a typed table schema definition.\n *\n * Returns a Table<T> with name, columns, indexes — no CRUD methods.\n * CRUD is handled by the DatabaseProvider.\n *\n * @example\n * ```typescript\n * import { table, field, index } from \"@jarvis/sdk\";\n *\n * export const usersTable = table<User>({\n * name: \"users\",\n * columns: {\n * id: field.uuid({ primary: true }),\n * userId: field.string({ required: true }),\n * email: field.string({ required: true, unique: true }),\n * name: field.string({ nullable: true }),\n * preferences: field.json({ default: {} }),\n * createdAt: field.timestamp({ auto: \"create\" }),\n * updatedAt: field.timestamp({ auto: \"update\" }),\n * },\n * });\n *\n * // Usage — CRUD via db provider:\n * const result = await db.find<User>(ctx, { table: usersTable, filter: { email } });\n * ```\n */\nexport function table<T = Record<string, unknown>>(\n config: TableConfig<T>,\n): Table<T> {\n if (!config.name) {\n throw new Error(\"Table must have a name\");\n }\n if (!/^[a-z][a-z0-9_]*$/.test(config.name)) {\n throw new Error(\n `Invalid table name \"${config.name}\". Must be lowercase with underscores.`,\n );\n }\n\n const columns = config.columns;\n const indexes = config.indexes ?? [];\n\n // Collect searchable field names\n const searchableFields: string[] = [];\n for (const [fname, fconfig] of Object.entries(columns)) {\n if (fconfig.searchable) {\n searchableFields.push(fname);\n }\n if (fconfig.type === \"json\" && fconfig.schema) {\n for (const [innerName, innerConfig] of Object.entries(fconfig.schema)) {\n if (innerConfig.searchable) {\n searchableFields.push(`${fname}.${innerName}`);\n }\n }\n }\n }\n\n return {\n kind: \"table\" as const,\n name: config.name,\n columns,\n indexes,\n access: config.access,\n searchableFields,\n } as Table<T>;\n}\n\n// =============================================================================\n// FIELD HELPERS\n// =============================================================================\n\n/**\n * Field helper functions for defining column types.\n *\n * @example\n * ```typescript\n * import { field } from \"@jarvis/sdk\";\n *\n * const columns = {\n * id: field.uuid({ primary: true }),\n * name: field.string({ required: true }),\n * email: field.string({ required: true, unique: true }),\n * age: field.integer({ default: 0 }),\n * isActive: field.boolean({ default: true }),\n * bio: field.text(),\n * metadata: field.json({ default: {} }),\n * createdAt: field.timestamp({ auto: \"create\" }),\n * updatedAt: field.timestamp({ auto: \"update\" }),\n * };\n * ```\n */\nexport const field = {\n string: (options?: {\n required?: boolean;\n nullable?: boolean;\n unique?: boolean;\n default?: string;\n searchable?: boolean;\n secret?: boolean;\n }): FieldConfig => ({\n type: \"string\" as FieldType,\n required: options?.required,\n nullable: options?.nullable,\n unique: options?.unique,\n default: options?.default,\n searchable: options?.searchable,\n secret: options?.secret,\n }),\n\n text: (options?: {\n required?: boolean;\n nullable?: boolean;\n default?: string;\n searchable?: boolean;\n }): FieldConfig => ({\n type: \"text\" as FieldType,\n required: options?.required,\n nullable: options?.nullable,\n default: options?.default,\n searchable: options?.searchable,\n }),\n\n integer: (options?: {\n required?: boolean;\n default?: number;\n unique?: boolean;\n }): FieldConfig => ({\n type: \"integer\" as FieldType,\n required: options?.required,\n default: options?.default,\n unique: options?.unique,\n }),\n\n boolean: (options?: { default?: boolean }): FieldConfig => ({\n type: \"boolean\" as FieldType,\n default: options?.default,\n }),\n\n timestamp: (options?: {\n required?: boolean;\n nullable?: boolean;\n default?: string | Date;\n auto?: \"create\" | \"update\";\n }): FieldConfig => ({\n type: \"timestamp\" as FieldType,\n required: options?.required,\n nullable: options?.nullable,\n default: options?.default,\n auto: options?.auto,\n }),\n\n json: <TJ = unknown>(options?: {\n default?: TJ;\n schema?: Record<string, JsonFieldSchema>;\n }): FieldConfig => ({\n type: \"json\" as FieldType,\n default: options?.default,\n schema: options?.schema,\n }),\n\n uuid: (options?: {\n primary?: boolean;\n required?: boolean;\n unique?: boolean;\n auto?: true;\n }): FieldConfig => ({\n type: \"uuid\" as FieldType,\n primary: options?.primary,\n required: options?.required,\n unique: options?.unique,\n auto: options?.auto,\n }),\n\n enum: (values: string[], options?: { default?: string }): FieldConfig => ({\n type: \"string\" as FieldType,\n default: options?.default ?? values[0],\n }),\n\n vector: (options?: { dimensions?: number }): FieldConfig => ({\n type: \"vector\" as FieldType,\n dimensions: options?.dimensions ?? 1536,\n }),\n\n number: (options?: {\n required?: boolean;\n nullable?: boolean;\n default?: number;\n unique?: boolean;\n }): FieldConfig => ({\n type: \"numeric\" as FieldType,\n required: options?.required,\n nullable: options?.nullable,\n default: options?.default,\n unique: options?.unique,\n }),\n};\n\n// =============================================================================\n// INDEX HELPERS\n// =============================================================================\n\n/**\n * Create an index configuration\n *\n * @example\n * ```typescript\n * import { index } from \"@jarvis/sdk\";\n *\n * const indexes = [\n * index(\"goals_status_idx\", [\"userId\", \"status\"]),\n * index(\"goals_email_unique\", [\"email\"], { unique: true }),\n * ];\n * ```\n */\nexport function index(\n name: string,\n columns: string[],\n options?: { unique?: boolean; where?: string },\n): IndexConfig {\n return {\n name,\n columns,\n unique: options?.unique,\n where: options?.where,\n };\n}\n","/**\n * Cache Factory and In-Memory Store Provider\n *\n * Provides the cache<T>() factory for defining ephemeral storage with\n * typed CRUD methods and automatic TTL expiration.\n *\n * Caches have the same CRUD API as tables but are backed by an in-memory\n * store (swappable to Redis, PostgreSQL, etc. via StoreProvider).\n *\n * User scoping is handled by the StoreProvider via identity resolution.\n */\n\nimport type {\n StorageCache,\n StorageCacheConfig,\n StorageCacheOptions,\n StoreProvider,\n} from \"@jarvis/types\";\nimport type {\n DataScope,\n EntityQuery,\n FieldType,\n FilterValue,\n FindEntityResponse,\n Context,\n} from \"@jarvis/types\";\n\n// =============================================================================\n// TTL PARSING\n// =============================================================================\n\n/**\n * Parse a TTL string (e.g., \"30s\", \"5m\", \"1h\", \"24h\", \"7d\") into seconds.\n * Returns null if no TTL specified.\n */\nexport function parseTtl(ttl?: string): number | null {\n if (!ttl) return null;\n\n const match = ttl.match(/^(\\d+)(s|m|h|d)$/);\n if (!match) {\n throw new Error(\n `Invalid TTL format \"${ttl}\". Use: \"30s\", \"5m\", \"1h\", \"24h\", \"7d\"`,\n );\n }\n\n const value = parseInt(match[1]!, 10);\n const unit = match[2]!;\n\n switch (unit) {\n case \"s\":\n return value;\n case \"m\":\n return value * 60;\n case \"h\":\n return value * 3600;\n case \"d\":\n return value * 86400;\n default:\n return null;\n }\n}\n\n// =============================================================================\n// IN-MEMORY STORE PROVIDER\n// =============================================================================\n\ninterface CacheEntry {\n value: Record<string, unknown>;\n expiresAt: number | null; // Unix timestamp in ms, null = no expiration\n}\n\n/**\n * In-memory StoreProvider implementation.\n *\n * Uses a Map<string, Map<string, CacheEntry>> for namespace → key → value.\n * Entries with TTL are lazily cleaned up on access.\n *\n * Accepts an identity provider to resolve user scope from ctx.userId.\n * All namespaces are internally prefixed with `{userId}:{appId}:` for\n * user + app isolation — matching the DB provider's scoping pattern.\n */\nexport function inMemoryStoreProvider(): StoreProvider {\n const store = new Map<string, Map<string, CacheEntry>>();\n\n function resolveScope(ctx: Context): string {\n if (!ctx.userId) {\n throw new Error(\"Store requires identity context (userId)\");\n }\n return ctx.userId;\n }\n\n function scopedNs(ctx: Context, namespace: string): string {\n if (namespace.startsWith(\"__public:\")) {\n return `public:${namespace}`;\n }\n return `${resolveScope(ctx)}:${namespace}`;\n }\n\n function getNamespace(ns: string): Map<string, CacheEntry> {\n let nsMap = store.get(ns);\n if (!nsMap) {\n nsMap = new Map();\n store.set(ns, nsMap);\n }\n return nsMap;\n }\n\n function isExpired(entry: CacheEntry): boolean {\n return entry.expiresAt !== null && Date.now() > entry.expiresAt;\n }\n\n return {\n name: \"memory-store\",\n\n async get(ctx, req) {\n const ns = getNamespace(scopedNs(ctx, req.namespace));\n const entry = ns.get(req.key);\n if (!entry || isExpired(entry)) {\n if (entry) ns.delete(req.key);\n return null;\n }\n return entry.value;\n },\n\n async set(ctx, req) {\n const ns = getNamespace(scopedNs(ctx, req.namespace));\n ns.set(req.key, {\n value: req.value,\n expiresAt: req.ttlSeconds ? Date.now() + req.ttlSeconds * 1000 : null,\n });\n },\n\n async del(ctx, req) {\n const ns = getNamespace(scopedNs(ctx, req.namespace));\n return ns.delete(req.key);\n },\n\n async findAll(ctx, req) {\n const ns = getNamespace(scopedNs(ctx, req.namespace));\n const results: Record<string, unknown>[] = [];\n const toDelete: string[] = [];\n\n for (const [key, entry] of ns) {\n if (isExpired(entry)) {\n toDelete.push(key);\n } else {\n results.push(entry.value);\n }\n }\n\n // Lazy cleanup\n for (const key of toDelete) {\n ns.delete(key);\n }\n\n return results;\n },\n\n async clear(ctx, req) {\n store.delete(scopedNs(ctx, req.namespace));\n },\n\n async count(ctx, req) {\n const ns = getNamespace(scopedNs(ctx, req.namespace));\n let count = 0;\n const toDelete: string[] = [];\n\n for (const [key, entry] of ns) {\n if (isExpired(entry)) {\n toDelete.push(key);\n } else {\n count++;\n }\n }\n\n for (const key of toDelete) {\n ns.delete(key);\n }\n\n return count;\n },\n };\n}\n\n// =============================================================================\n// FILTER HELPERS (in-memory)\n// =============================================================================\n\nfunction matchesFilter(\n item: Record<string, unknown>,\n filter: Record<string, FilterValue> | undefined,\n): boolean {\n if (!filter) return true;\n\n for (const [key, value] of Object.entries(filter)) {\n const itemValue = item[key];\n\n if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n const ops = value as Record<string, unknown>;\n if (ops.$eq !== undefined && itemValue !== ops.$eq) return false;\n if (ops.$ne !== undefined && itemValue === ops.$ne) return false;\n if (ops.$gt !== undefined && !(itemValue! > ops.$gt!)) return false;\n if (ops.$gte !== undefined && !(itemValue! >= ops.$gte!)) return false;\n if (ops.$lt !== undefined && !(itemValue! < ops.$lt!)) return false;\n if (ops.$lte !== undefined && !(itemValue! <= ops.$lte!)) return false;\n if (ops.$in !== undefined && !(ops.$in as unknown[]).includes(itemValue))\n return false;\n if (ops.$nin !== undefined && (ops.$nin as unknown[]).includes(itemValue))\n return false;\n if (ops.$ilike !== undefined) {\n const pattern = (ops.$ilike as string)\n .replace(/%/g, \".*\")\n .replace(/_/g, \".\");\n if (!new RegExp(pattern, \"i\").test(String(itemValue ?? \"\")))\n return false;\n }\n if (ops.$like !== undefined) {\n const pattern = (ops.$like as string)\n .replace(/%/g, \".*\")\n .replace(/_/g, \".\");\n if (!new RegExp(pattern).test(String(itemValue ?? \"\"))) return false;\n }\n if (ops.$isNull !== undefined) {\n if (ops.$isNull && itemValue != null) return false;\n if (!ops.$isNull && itemValue == null) return false;\n }\n } else {\n if (itemValue !== value) return false;\n }\n }\n\n return true;\n}\n\nfunction applySortAndPagination<T>(\n items: T[],\n req: EntityQuery,\n): { items: T[]; total: number } {\n const total = items.length;\n\n // Sort\n if (req.sort) {\n const sortEntries = Object.entries(req.sort);\n items.sort((a, b) => {\n for (const [field, dir] of sortEntries) {\n const aVal = (a as Record<string, unknown>)[field];\n const bVal = (b as Record<string, unknown>)[field];\n if (aVal === bVal) continue;\n if (aVal == null) return dir === \"asc\" ? -1 : 1;\n if (bVal == null) return dir === \"asc\" ? 1 : -1;\n const cmp = aVal < bVal ? -1 : 1;\n return dir === \"asc\" ? cmp : -cmp;\n }\n return 0;\n });\n }\n\n // Pagination\n if (req.offset) items = items.slice(req.offset);\n if (req.limit) items = items.slice(0, req.limit);\n\n return { items, total };\n}\n\n// =============================================================================\n// cache<T>() FACTORY\n// =============================================================================\n\n/**\n * Create a typed cache with CRUD methods and TTL expiration.\n *\n * Returns a Cache<T> with the same CRUD API as Table<T>, backed by\n * an in-memory store (swappable via StoreProvider).\n *\n * @example\n * ```typescript\n * import { cache, field } from \"@jarvis/sdk\";\n *\n * export const insightsCache = cache<Insight>({\n * name: \"insights\",\n * ttl: \"24h\",\n * fields: {\n * type: field.string({ required: true }),\n * title: field.string({ required: true }),\n * content: field.text(),\n * },\n * });\n *\n * // Same CRUD API as table:\n * await insightsCache.create(ctx, { type: \"trend\", title: \"...\" }, options);\n * await insightsCache.find(ctx, { filter: { type: \"trend\" } }, options);\n * ```\n */\nexport function cache<T = Record<string, unknown>>(\n config: StorageCacheConfig<T>,\n): StorageCache<T> {\n if (!config.name) {\n throw new Error(\"Cache must have a name\");\n }\n if (!/^[a-z][a-z0-9_]*$/.test(config.name)) {\n throw new Error(\n `Invalid cache name \"${config.name}\". Must be lowercase with underscores.`,\n );\n }\n\n const name = config.name;\n const fields = config.fields;\n const ttlSeconds = parseTtl(config.ttl);\n\n /** Build namespaced key — platform provides a user-scoped store */\n function ns(scope?: DataScope): string {\n if (config.access === \"public\" && scope === \"public\") {\n return `__public:cache:${name}`;\n }\n return `cache:${name}`;\n }\n\n /** Convert raw store data to typed entity */\n function toEntity(data: Record<string, unknown>): T {\n return data as T;\n }\n\n return {\n kind: \"cache\" as const,\n name,\n fields,\n ttl: config.ttl,\n ttlSeconds,\n\n async find(\n ctx: Context,\n req: EntityQuery,\n options?: StorageCacheOptions,\n ): Promise<FindEntityResponse<T>> {\n const { store } = options!;\n\n if (config.access === \"public\" && req.scope === \"all\") {\n // Merge user-scoped + public entries\n const [userItems, publicItems] = await Promise.all([\n store.findAll(ctx, { namespace: ns(\"private\") }),\n store.findAll(ctx, { namespace: ns(\"public\") }),\n ]);\n const allItems = [...userItems, ...publicItems];\n const filtered = allItems\n .filter((item) => matchesFilter(item, req.filter))\n .map(toEntity);\n return applySortAndPagination(filtered, req);\n }\n\n const all = await store.findAll(ctx, { namespace: ns(req.scope) });\n const filtered = all\n .filter((item) => matchesFilter(item, req.filter))\n .map(toEntity);\n return applySortAndPagination(filtered, req);\n },\n\n async findOne(\n ctx: Context,\n req: { id: string },\n options?: StorageCacheOptions,\n ): Promise<T | null> {\n const { store } = options!;\n const data = await store.get(ctx, { namespace: ns(), key: req.id });\n if (!data) return null;\n return toEntity(data);\n },\n\n async create(\n ctx: Context,\n req: Partial<T>,\n options?: StorageCacheOptions,\n ): Promise<T> {\n const { store } = options!;\n const {\n id: providedId,\n userId: _uid,\n ...dataFields\n } = req as Record<string, unknown>;\n const id = (providedId as string) ?? crypto.randomUUID();\n const now = new Date().toISOString();\n\n const record = {\n id,\n ...dataFields,\n createdAt: now,\n updatedAt: now,\n };\n\n await store.set(ctx, {\n namespace: ns(),\n key: id,\n value: record,\n ttlSeconds: ttlSeconds ?? undefined,\n });\n return toEntity(record);\n },\n\n async update(\n ctx: Context,\n req: { id: string } & Partial<T>,\n options?: StorageCacheOptions,\n ): Promise<T> {\n const { store } = options!;\n const { id, ...updateData } = req as Record<string, unknown> & {\n id: string;\n };\n\n const existing = await store.get(ctx, { namespace: ns(), key: id });\n if (!existing) {\n throw new Error(`Cache entry not found: ${name}/${id}`);\n }\n\n const updated = {\n ...existing,\n ...updateData,\n updatedAt: new Date().toISOString(),\n };\n\n await store.set(ctx, {\n namespace: ns(),\n key: id,\n value: updated,\n ttlSeconds: ttlSeconds ?? undefined,\n });\n return toEntity(updated);\n },\n\n async delete(\n ctx: Context,\n req: { id: string },\n options?: StorageCacheOptions,\n ): Promise<boolean> {\n const { store } = options!;\n return store.del(ctx, { namespace: ns(), key: req.id });\n },\n\n async count(\n ctx: Context,\n req: EntityQuery,\n options?: StorageCacheOptions,\n ): Promise<number> {\n const { store } = options!;\n if (!req.filter || Object.keys(req.filter).length === 0) {\n return store.count(ctx, { namespace: ns() });\n }\n const all = await store.findAll(ctx, { namespace: ns() });\n return all.filter((item) => matchesFilter(item, req.filter)).length;\n },\n\n async createMany(\n ctx: Context,\n req: { items: Partial<T>[] },\n options?: StorageCacheOptions,\n ): Promise<T[]> {\n const { store } = options!;\n const results: T[] = [];\n for (const item of req.items) {\n const { id: providedId, userId: _uid, ...dataFields } = item as Record<string, unknown>;\n const id = (providedId as string) ?? crypto.randomUUID();\n const now = new Date().toISOString();\n const record = { id, ...dataFields, createdAt: now, updatedAt: now };\n await store.set(ctx, { namespace: ns(), key: id, value: record, ttlSeconds: ttlSeconds ?? undefined });\n results.push(toEntity(record));\n }\n return results;\n },\n\n async updateMany(\n ctx: Context,\n req: { filter: Record<string, FilterValue>; data: Partial<T> },\n options?: StorageCacheOptions,\n ): Promise<number> {\n const { store } = options!;\n const all = await store.findAll(ctx, { namespace: ns() });\n const matching = all.filter((item) => matchesFilter(item, req.filter));\n\n let count = 0;\n for (const item of matching) {\n const id = item.id as string;\n if (id) {\n const updated = {\n ...item,\n ...(req.data as Record<string, unknown>),\n updatedAt: new Date().toISOString(),\n };\n await store.set(ctx, {\n namespace: ns(),\n key: id,\n value: updated,\n ttlSeconds: ttlSeconds ?? undefined,\n });\n count++;\n }\n }\n\n return count;\n },\n\n async deleteMany(\n ctx: Context,\n req: { filter: Record<string, FilterValue> },\n options?: StorageCacheOptions,\n ): Promise<number> {\n const { store } = options!;\n const all = await store.findAll(ctx, { namespace: ns() });\n const matching = all.filter((item) => matchesFilter(item, req.filter));\n\n let count = 0;\n for (const item of matching) {\n const id = item.id as string;\n if (id) {\n await store.del(ctx, { namespace: ns(), key: id });\n count++;\n }\n }\n\n return count;\n },\n } as unknown as StorageCache<T>;\n}\n","/**\n * UI Factory\n *\n * Provides the `ui()` factory for defining UI components — React components\n * registered against the chat's `Ui` slot. Used by both tool renderers\n * (`XTool.tsx`) and custom message renderers (`XMessage.tsx`); the chat\n * resolves the right component by URI / type from the registered list.\n */\n\nimport type { UiComponentConfig } from \"@jarvis/types\";\n\n// =============================================================================\n// ui() FACTORY\n// =============================================================================\n\n/**\n * Create a UI component definition for chat rendering.\n *\n * Each UI component renders a specific shape of data into the chat\n * timeline (or side panel). Register one per `metadata.ui.type` your\n * server may emit.\n *\n * @example\n * ```typescript\n * import { ui } from \"@jarvis/sdk\";\n * import type { UiComponentProps } from \"@jarvis/types\";\n *\n * function GoalsUi({ data, isExpanded, onAction }: UiComponentProps<Goal[]>) {\n * return (\n * <Box>\n * {data.map((goal) => (\n * <GoalCard key={goal.id} goal={goal} isExpanded={isExpanded} />\n * ))}\n * </Box>\n * );\n * }\n *\n * export default ui<Goal[]>({\n * type: \"goals\",\n * label: \"Goals\",\n * Component: GoalsUi,\n * });\n * ```\n */\nexport function ui<TData = unknown>(config: UiComponentConfig<TData>): UiComponentConfig<TData> {\n if (!config.type) {\n throw new Error(\"UI config must have a type\");\n }\n if (!config.Component) {\n throw new Error(\"UI config must have a Component\");\n }\n\n return {\n label: config.label ?? config.type,\n ...config,\n };\n}\n","/**\n * Connector Factory + Registry\n *\n * Provides the connector() factory for creating external service connector definitions,\n * and a registry for aggregating all platform connectors.\n *\n * Auth is handled by platform providers. Sync via Temporal workflows.\n */\n\nimport type {\n Connector,\n ConnectorConfig,\n ConnectorInstance,\n} from \"@jarvis/types\";\n\nimport { table, field, index } from \"./tables\";\n\n// =============================================================================\n// SHARED CONNECTORS TABLE\n// =============================================================================\n\n/** Shared connectors table — persistent storage for connection tracking */\nexport const connectorsTable = table<Connector>({\n name: \"connectors\",\n columns: {\n id: field.uuid({ primary: true }),\n userId: field.string({ required: true }),\n type: field.string({ required: true }),\n accountId: field.string(),\n displayName: field.string(),\n status: field.string({ default: \"disconnected\" }),\n lastSyncedAt: field.timestamp({ nullable: true }),\n syncState: field.json(),\n metadata: field.json(),\n createdAt: field.timestamp({ auto: \"create\" }),\n updatedAt: field.timestamp({ auto: \"update\" }),\n },\n indexes: [index(\"connectors_type_idx\", [\"userId\", \"type\"])],\n});\n\n// =============================================================================\n// CONNECTOR FACTORY\n// =============================================================================\n\n/**\n * Create an external service connector definition.\n *\n * Returns a ConnectorInstance with:\n * - .configure() — app-level sync config\n * - .connect() — initiate auth (OAuth redirect, API key store, token store)\n * - .exchangeCode() — OAuth callback code exchange\n * - .disconnect() — clear credentials\n *\n * @example\n * ```typescript\n * // Platform defines:\n * export const googleCalendarConnector = connector({\n * type: \"google_calendar\",\n * name: \"Google Calendar\",\n * auth: { type: \"oauth\", providerId: \"google\", scopes: [...] },\n * });\n *\n * // App configures sync:\n * export default googleCalendarConnector.configure({\n * sync: { pull: \"./workflows/pull.workflow\", cron: \"...\" },\n * });\n * ```\n */\nexport function connector(config: ConnectorConfig): ConnectorInstance {\n if (!config.type) throw new Error(\"Connector must have a type\");\n if (!config.name) throw new Error(\"Connector must have a name\");\n\n return {\n ...config,\n\n configure(configureConfig) {\n // Merge additional scopes with base auth if provided\n let auth = config.auth;\n if (configureConfig.auth?.scopes && auth?.type === \"oauth\") {\n const merged = [\n ...new Set([...auth.scopes, ...configureConfig.auth.scopes]),\n ];\n auth = { ...auth, scopes: merged };\n }\n\n return {\n type: config.type,\n name: configureConfig.name ?? config.name,\n icon: config.icon,\n color: config.color,\n description: configureConfig.description ?? config.description,\n version: config.version,\n sync: configureConfig.sync,\n auth,\n };\n },\n\n async connect(ctx, req, deps) {\n const auth = this.auth;\n\n // OAuth: return redirect URL\n if (auth?.type === \"oauth\" && auth.provider) {\n return {\n action: \"redirect\",\n ...auth.provider.buildAuthUrl(req.state ?? \"\"),\n };\n }\n\n // API key / token: validate + store credential\n if (\n (auth?.type === \"apiKey\" || auth?.type === \"token\") &&\n req.credential\n ) {\n if (auth.type === \"apiKey\" && \"validate\" in auth && auth.validate) {\n const error = await auth.validate(req.credential);\n if (error) return { action: \"error\", message: error };\n }\n\n await deps.secrets.set(ctx, {\n scope: config.type,\n type: auth.type,\n value: req.credential,\n });\n\n await deps.onConnect?.();\n return { action: \"connected\" };\n }\n\n return { action: \"error\", message: \"Unsupported auth type\" };\n },\n\n async exchangeCode(ctx, req, deps) {\n const auth = this.auth;\n if (auth?.type !== \"oauth\" || !auth.provider) {\n throw new Error(`${config.type}: no OAuth provider`);\n }\n\n const { tokens, profile, metadata } = await auth.provider.exchangeCode(\n req.code,\n req.codeVerifier,\n );\n\n const scope = auth.providerId ?? config.type;\n\n await deps.secrets.set(ctx, {\n scope,\n type: \"oauth\",\n value: {\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken ?? null,\n expiresAt: tokens.expiresAt\n ? new Date(tokens.expiresAt).toISOString()\n : null,\n tokenScope: tokens.scopes.join(\" \"),\n ...(tokens.extra ?? {}),\n },\n metadata: {\n accountId: profile?.accountId ?? null,\n displayName: profile?.displayName ?? null,\n },\n });\n\n await deps.onConnect?.({\n accountId: profile?.accountId,\n displayName: profile?.displayName,\n ...profile?.metadata,\n ...metadata,\n });\n },\n\n async disconnect(ctx, _req, deps) {\n const auth = this.auth;\n const scope =\n auth?.type === \"oauth\" ? (auth.providerId ?? config.type) : config.type;\n\n await deps.secrets.delete(ctx, { scope });\n await deps.onDisconnect?.();\n },\n };\n}\n\n// =============================================================================\n// CONNECTORS COLLECTION\n// =============================================================================\n\nconst all: ConnectorInstance[] = [];\n\nexport const connectors = {\n /** List all registered connectors */\n list: () => [...all],\n\n /** Find a connector by type */\n get: (type: string) => all.find((c) => c.type === type),\n\n /** Register a connector instance */\n add: (instance: ConnectorInstance) => {\n all.push(instance);\n },\n};\n","/**\n * OAuth Factory\n *\n * Generic OAuth 2.0 provider factory. Returns an OAuthProvider that handles both:\n * - Connect-time: buildAuthUrl, exchangeCode (sign-in ceremony)\n * - Runtime: intercept, refresh, isConnected (HTTP auth + token refresh)\n *\n * Providers customize behavior via OAuthOptions (second parameter).\n * Default implementations handle standard OAuth 2.0 flows.\n */\n\nimport type {\n OAuthConfig,\n OAuthOptions,\n OAuthProvider,\n OAuthTokens,\n AuthCredentials,\n HttpRequestConfig,\n} from \"@jarvis/types\";\n\n/**\n * Create an OAuth provider from config + optional behavior overrides.\n *\n * @example\n * ```typescript\n * // Standard OAuth 2.0 (no overrides needed)\n * const provider = oauth({\n * authorizationUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n * tokenUrl: \"https://oauth2.googleapis.com/token\",\n * clientId: \"...\",\n * clientSecret: \"...\",\n * redirectUri: \"http://localhost:3000/callback\",\n * scopes: [\"openid\", \"profile\"],\n * });\n *\n * // Custom provider with overrides\n * const provider = oauth(config, {\n * buildAuthUrl(state) { return { url: \"...\" }; },\n * async fetchProfile(accessToken) { return { accountId: \"...\", displayName: \"...\" }; },\n * });\n * ```\n */\nexport function oauth(config: OAuthConfig, options?: OAuthOptions): OAuthProvider {\n return {\n // =========================================================================\n // AuthProvider (runtime)\n // =========================================================================\n\n type: \"oauth\" as const,\n\n intercept(\n reqConfig: HttpRequestConfig,\n creds: AuthCredentials,\n ): HttpRequestConfig {\n if (creds.accessToken) {\n return {\n ...reqConfig,\n headers: {\n ...reqConfig.headers,\n Authorization: `Bearer ${creds.accessToken}`,\n },\n };\n }\n return reqConfig;\n },\n\n isConnected(creds: AuthCredentials): boolean {\n return !!creds.accessToken;\n },\n\n async refresh(\n creds: AuthCredentials,\n ): Promise<AuthCredentials | undefined> {\n if (!creds.refreshToken) return undefined;\n\n const res = await fetch(config.tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: creds.refreshToken,\n client_id: config.clientId,\n client_secret: config.clientSecret,\n }),\n });\n\n if (!res.ok) return undefined;\n\n const data = (await res.json()) as Record<string, unknown>;\n return {\n accessToken: data.access_token as string,\n refreshToken: (data.refresh_token as string) ?? creds.refreshToken,\n expiresAt: data.expires_in\n ? new Date(Date.now() + (data.expires_in as number) * 1000).toISOString()\n : creds.expiresAt,\n };\n },\n\n // =========================================================================\n // OAuthProvider (connect-time)\n // =========================================================================\n\n buildAuthUrl(state: string) {\n if (options?.buildAuthUrl) return options.buildAuthUrl(state);\n\n // Default: standard OAuth 2.0\n const params = new URLSearchParams({\n client_id: config.clientId,\n response_type: \"code\",\n redirect_uri: config.redirectUri,\n scope: config.scopes.join(\" \"),\n state,\n });\n return { url: `${config.authorizationUrl}?${params.toString()}` };\n },\n\n async exchangeCode(code: string, codeVerifier?: string) {\n // Get tokens from provider override or default exchange\n let tokens: OAuthTokens;\n\n if (options?.exchangeCode) {\n tokens = await options.exchangeCode(code, codeVerifier);\n } else {\n // Default: standard POST with credentials in body\n const body: Record<string, string> = {\n grant_type: \"authorization_code\",\n code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n client_secret: config.clientSecret,\n };\n if (codeVerifier) body.code_verifier = codeVerifier;\n\n const res = await fetch(config.tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams(body),\n });\n\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`OAuth token exchange failed: ${err}`);\n }\n\n const data = (await res.json()) as Record<string, unknown>;\n tokens = {\n accessToken: data.access_token as string,\n refreshToken: data.refresh_token as string,\n expiresAt: data.expires_in\n ? Date.now() + (data.expires_in as number) * 1000\n : undefined,\n scopes: ((data.scope as string) || \"\")\n .split(\" \")\n .filter(Boolean),\n };\n }\n\n // Post-exchange hook (e.g., Meta long-lived token swap)\n let metadata: Record<string, unknown> | undefined;\n if (options?.afterExchange) {\n const result = await options.afterExchange(tokens);\n tokens = result.tokens;\n metadata = result.metadata;\n }\n\n // Profile fetch\n const profile = options?.fetchProfile\n ? await options.fetchProfile(tokens.accessToken)\n : undefined;\n\n return { tokens, profile, metadata };\n },\n };\n}\n","/**\n * Context Factory\n *\n * Creates frozen context objects. Auto-generates requestId and timestamp\n * if not provided. If an existing context is passed, inherits its\n * requestId + timestamp (preserves trace chain).\n *\n * @example\n * ```typescript\n * import { context } from \"@jarvis/sdk\";\n *\n * const ctx = context({ userId: \"user-123\" });\n * // ctx.requestId → auto-generated\n * // ctx.timestamp → auto-generated\n *\n * // Inherit trace from existing context\n * const childCtx = context({ userId: \"user-123\" }, parentCtx);\n * // childCtx.requestId === parentCtx.requestId\n * ```\n */\n\nimport type { Context } from \"@jarvis/types\";\n\n// =============================================================================\n// FACTORY\n// =============================================================================\n\nfunction deepFreeze<T extends object>(obj: T): T {\n for (const value of Object.values(obj)) {\n if (value && typeof value === \"object\" && !Object.isFrozen(value)) {\n deepFreeze(value);\n }\n }\n return Object.freeze(obj);\n}\n\nfunction generateId(): string {\n return globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2);\n}\n\n/**\n * Create a frozen Context.\n *\n * - `context({ userId })` → user-scoped context\n * - `context()` → context with userId \"system\"\n * - `context(fields, parentCtx)` → inherits requestId + timestamp from parent\n *\n * requestId and timestamp are auto-generated if not provided and no parent.\n */\nexport function context(\n fields?: Partial<Context>,\n from?: Pick<Context, \"requestId\" | \"timestamp\">,\n): Context {\n return deepFreeze({\n userId: \"system\",\n requestId: from?.requestId ?? generateId(),\n timestamp: from?.timestamp ?? new Date().toISOString(),\n ...fields,\n } as Context);\n}\n","/**\n * State Factory\n *\n * Data-owning state management for agent orchestrators.\n * Adds state filtering, formatting, caching, and identity support.\n *\n * Pure — no Node.js deps — safe for Temporal workflow V8 isolates.\n *\n * @example Data-owning (Temporal workflow)\n * ```typescript\n * const s = state<PlannerState, PlannerQuery>({\n * initial: { goals: {}, tasks: {} },\n * extract: (ctx, req) => extractQuery(ctx.state, req.message),\n * filter: (ctx, req) => filterState(ctx.state, req.query),\n * format: (ctx, req) => formatState(ctx.state, req),\n * });\n *\n * const filtered = await s.filter({ message: \"show goals\" });\n * s.update(current => ({ ...current, goals: newGoals }));\n * s.get(); // current state\n * ```\n *\n * @example With encrypted context\n * ```typescript\n * const ctx = await identity.create({ userId, appId });\n * const s = state(ctx, { initial: { ... }, ...options });\n * // s.userId carries identity\n * ```\n */\n\nimport type { Context } from \"@jarvis/types\";\n\nimport { context } from \"./context\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/** Response from filtering state */\nexport interface FilterStateResponse<TState, TQuery> {\n /** Filtered state */\n state: TState;\n /** Original totals (counts of arrays before filtering) */\n totals: Record<string, number>;\n /** Whether filtering was applied */\n isFiltered: boolean;\n /** The extracted query (product-defined structure) */\n query: TQuery;\n /** Formatted context string for LLM */\n formatted: string;\n}\n\n/** JSON-serializable version of State (for passing to activities or storing) */\nexport interface StateJson<TState, TQuery> extends Partial<Context> {\n lastFilter?: {\n state: TState;\n totals: Record<string, number>;\n isFiltered: boolean;\n query: TQuery;\n formatted: string;\n };\n}\n\n/** Options for the state() factory */\nexport interface StateOptions<TState, TQuery> {\n // --- Data ---\n\n /** Initial state data. Required for data-owning mode (get/set/update/filter without args). */\n initial?: TState;\n\n // --- Callbacks (product-defined) ---\n\n /** Extract query from message */\n extract: (\n ctx: { state: TState },\n req: { message: string },\n ) => Promise<TQuery> | TQuery;\n\n /** Filter state based on extracted query */\n filter: (ctx: { state: TState }, req: { query: TQuery }) => TState;\n\n /** Format state as context string for LLM */\n format: (\n ctx: { state: TState },\n req?: { totals?: Record<string, number>; isFiltered?: boolean },\n ) => string;\n\n /** Check if filtering should be applied. Return false to skip and use full state. */\n shouldFilter?: (ctx: { state: TState }, req: { query: TQuery }) => boolean;\n\n /** Hash query for caching. If not provided, uses JSON.stringify. */\n hashQuery?: (query: TQuery) => string;\n}\n\n/** State instance returned by state() factory. Extends Context with state management. */\nexport interface State<TState, TQuery> extends Context {\n // --- Data access ---\n\n /** Get current state data. Throws if no initial state was provided. */\n get: () => TState;\n\n /** Replace state data + auto-invalidate cache. */\n set: (state: TState) => void;\n\n /** Transform state data via callback + auto-invalidate cache. */\n update: (fn: (current: TState) => TState) => void;\n\n // --- Filtering ---\n\n /** Filter state based on user message. Uses internal state or external ctx. */\n filter: {\n /** Data-owning: filter internal state */\n (req: { message: string }): Promise<FilterStateResponse<TState, TQuery>>;\n /** Legacy: filter external state */\n (\n ctx: { state: TState },\n req: { message: string },\n ): Promise<FilterStateResponse<TState, TQuery>>;\n };\n\n /** Format state as context string. Uses internal state or external ctx. */\n format: {\n (\n req?: { totals?: Record<string, number>; isFiltered?: boolean },\n ): string;\n (\n ctx: { state: TState },\n req?: { totals?: Record<string, number>; isFiltered?: boolean },\n ): string;\n };\n\n /** Compute totals from state (counts arrays). Uses internal state or external ctx. */\n totals: {\n (): Record<string, number>;\n (ctx: { state: TState }): Record<string, number>;\n };\n\n /** Invalidate internal cache (rarely needed — set/update auto-invalidate). */\n invalidate: () => void;\n\n /** Serialize the context + last filter result to JSON (without functions). */\n toJson: () => StateJson<TState, TQuery>;\n}\n\n// =============================================================================\n// FACTORY\n// =============================================================================\n\n/** Options-only — identity and initial state in options */\nexport function state<TState, TQuery = Record<string, unknown>>(\n options: StateOptions<TState, TQuery>,\n): State<TState, TQuery>;\n/** With base context — inherits userId and safe fields */\nexport function state<TState, TQuery = Record<string, unknown>>(\n baseCtx: Context,\n options: StateOptions<TState, TQuery>,\n): State<TState, TQuery>;\nexport function state<TState, TQuery = Record<string, unknown>>(\n ctxOrOptions: Context | StateOptions<TState, TQuery>,\n maybeOptions?: StateOptions<TState, TQuery>,\n): State<TState, TQuery> {\n // Resolve overload: state(options) vs state(ctx, options)\n const explicitCtx = maybeOptions\n ? (ctxOrOptions as Context)\n : undefined;\n const options = maybeOptions ?? (ctxOrOptions as StateOptions<TState, TQuery>);\n\n // Build base context from explicit ctx arg\n const baseCtx = explicitCtx ?? undefined;\n\n // ---------------------------------------------------------------------------\n // Internal mutable state\n // ---------------------------------------------------------------------------\n\n let internalState: TState | undefined = options.initial;\n\n const get = (): TState => {\n if (internalState === undefined) {\n throw new Error(\n \"No state data. Use state({ initial: ... }) or pass state to filter/format.\",\n );\n }\n return internalState;\n };\n\n const set = (newState: TState): void => {\n internalState = newState;\n cache = null; // auto-invalidate\n };\n\n const update = (fn: (current: TState) => TState): void => {\n set(fn(get()));\n };\n\n // ---------------------------------------------------------------------------\n // Cache\n // ---------------------------------------------------------------------------\n\n let cache: {\n stateHash: string;\n queryHash: string;\n result: FilterStateResponse<TState, TQuery>;\n } | null = null;\n\n let lastFilterResult: FilterStateResponse<TState, TQuery> | null = null;\n\n const hashState = (s: TState): string => {\n return JSON.stringify(s).slice(0, 1000);\n };\n\n const hashQuery = (query: TQuery): string => {\n return options.hashQuery ? options.hashQuery(query) : JSON.stringify(query);\n };\n\n const invalidate = (): void => {\n cache = null;\n };\n\n // ---------------------------------------------------------------------------\n // Totals\n // ---------------------------------------------------------------------------\n\n const computeTotals = (s: TState): Record<string, number> => {\n const result: Record<string, number> = {};\n for (const [key, value] of Object.entries(\n s as Record<string, unknown>,\n )) {\n if (Array.isArray(value)) {\n result[key] = value.length;\n }\n }\n return result;\n };\n\n // Overloaded: totals() or totals(ctx)\n const totals = (...args: unknown[]): Record<string, number> => {\n const stateData =\n args.length > 0\n ? (args[0] as { state: TState }).state\n : get();\n return computeTotals(stateData);\n };\n\n // ---------------------------------------------------------------------------\n // Filter (with caching)\n // ---------------------------------------------------------------------------\n\n const filterImpl = async (\n stateData: TState,\n req: { message: string },\n ): Promise<FilterStateResponse<TState, TQuery>> => {\n const ctx = { state: stateData };\n const query = await options.extract(ctx, req);\n\n const shouldFilter = options.shouldFilter?.(ctx, { query }) ?? true;\n\n if (!shouldFilter) {\n const t = computeTotals(stateData);\n const result: FilterStateResponse<TState, TQuery> = {\n state: stateData,\n totals: t,\n isFiltered: false,\n query,\n formatted: options.format(ctx, { totals: t, isFiltered: false }),\n };\n lastFilterResult = result;\n return result;\n }\n\n // Check cache\n const sHash = hashState(stateData);\n const qHash = hashQuery(query);\n\n if (cache && cache.stateHash === sHash && cache.queryHash === qHash) {\n lastFilterResult = cache.result;\n return cache.result;\n }\n\n // Filter state (product-defined)\n const filteredState = options.filter(ctx, { query });\n const t = computeTotals(stateData);\n\n const result: FilterStateResponse<TState, TQuery> = {\n state: filteredState,\n totals: t,\n isFiltered: true,\n query,\n formatted: options.format(\n { state: filteredState },\n { totals: t, isFiltered: true },\n ),\n };\n\n cache = { stateHash: sHash, queryHash: qHash, result };\n lastFilterResult = result;\n\n return result;\n };\n\n // Overloaded: filter(req) or filter(ctx, req)\n const filter = async (...args: [{ message: string }] | [{ state: TState }, { message: string }]) => {\n if (args.length >= 2) {\n // Legacy: filter(ctx, req)\n const [ctx, req] = args as [{ state: TState }, { message: string }];\n return filterImpl(ctx.state, req);\n }\n // Data-owning: filter(req)\n return filterImpl(get(), args[0] as { message: string });\n };\n\n // ---------------------------------------------------------------------------\n // Format\n // ---------------------------------------------------------------------------\n\n // Overloaded: format(req?) or format(ctx, req?)\n const format = (...args: [({ totals?: Record<string, number>; isFiltered?: boolean })?] | [{ state: TState }, ({ totals?: Record<string, number>; isFiltered?: boolean })?]): string => {\n // Detect: is first arg a { state: ... } ctx or a format options object?\n const firstArgIsCtx =\n args.length >= 1 &&\n args[0] != null &&\n typeof args[0] === \"object\" &&\n \"state\" in args[0];\n\n if (firstArgIsCtx) {\n // Legacy: format(ctx, req?)\n const ctx = args[0] as { state: TState };\n const req = args[1] as\n | { totals?: Record<string, number>; isFiltered?: boolean }\n | undefined;\n return options.format(ctx, {\n totals: req?.totals,\n isFiltered: req?.isFiltered ?? false,\n });\n }\n\n // Data-owning: format(req?)\n const req = args[0] as\n | { totals?: Record<string, number>; isFiltered?: boolean }\n | undefined;\n return options.format(\n { state: get() },\n { totals: req?.totals, isFiltered: req?.isFiltered ?? false },\n );\n };\n\n // ---------------------------------------------------------------------------\n // Serialization\n // ---------------------------------------------------------------------------\n\n const toJson = (): StateJson<TState, TQuery> => {\n return {\n userId: baseCtx?.userId,\n requestId: baseCtx?.requestId,\n metadata: baseCtx?.metadata,\n timestamp: baseCtx?.timestamp,\n lastFilter: lastFilterResult\n ? {\n state: lastFilterResult.state,\n totals: lastFilterResult.totals,\n isFiltered: lastFilterResult.isFiltered,\n query: lastFilterResult.query,\n formatted: lastFilterResult.formatted,\n }\n : undefined,\n };\n };\n\n // ---------------------------------------------------------------------------\n // Return\n // ---------------------------------------------------------------------------\n\n return {\n // Spread base context if provided (userId, requestId, timestamp, metadata)\n ...(baseCtx ?? {}),\n // Data access\n get,\n set,\n update,\n // Filtering & formatting\n filter,\n format,\n invalidate,\n totals,\n toJson,\n } as State<TState, TQuery>;\n}\n\n// =============================================================================\n// RESTORE\n// =============================================================================\n\n/**\n * Reconstruct a State from JSON.\n * Use when receiving context from activities or restoring state.\n */\nexport function fromJson<TState, TQuery = Record<string, unknown>>(\n json: StateJson<TState, TQuery>,\n options: StateOptions<TState, TQuery>,\n): State<TState, TQuery> {\n const baseCtx = context({\n userId: json.userId ?? \"\",\n requestId: json.requestId,\n metadata: json.metadata,\n timestamp: json.timestamp,\n });\n\n return state(baseCtx, options);\n}\n","/**\n * Data Domain\n * Re-exports for storage primitives and state management\n */\n\n// Table factory (storage primitive), field helpers, index helpers\nexport { table, field, index, toSnakeCase } from \"./tables\";\n\n// Cache factory (ephemeral storage primitive) and in-memory store provider\nexport { cache, inMemoryStoreProvider, parseTtl } from \"./caches\";\n\n// UI factory (tool UI renderers)\nexport { ui } from \"./ui\";\n\n// Connector factory and collection\nexport {\n connector,\n connectors,\n} from \"./connectors\";\n\n// OAuth factory\nexport { oauth } from \"./oauth\";\n\n// Context factory\nexport { context } from \"./context\";\n\n// State factory (state management — filter, format, cache)\nexport {\n state,\n fromJson,\n type State,\n type StateOptions,\n type StateJson,\n type FilterStateResponse as FilterResult,\n} from \"./state\";\n","export * from \"./agents\";\nexport * from \"./data\";\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface EditToolInput {\n file_path: string;\n old_string: string;\n new_string: string;\n replace_all?: boolean;\n}\n\nexport const editTool = tool({\n name: \"Edit\",\n description: \"Edit file contents with string replacement\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\" },\n old_string: { type: \"string\" },\n new_string: { type: \"string\" },\n replace_all: { type: \"boolean\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Edit File\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<EditToolInput>;\n const fileName = input.file_path?.split(\"/\").pop() || \"file\";\n if (req.status === \"running\") return `Editing ${fileName}...`;\n if (req.status === \"completed\") return `Edited ${fileName}`;\n return `Failed to edit ${fileName}`;\n },\n },\n hooks: {\n before: async (_ctx, req, options) => {\n const input = req.input as EditToolInput;\n const response = await options.askUser({\n ui: {\n uri: \"ui://devenv/diff\",\n title: input.file_path,\n data: {\n filePath: input.file_path,\n oldString: input.old_string,\n newString: input.new_string,\n replaceAll: input.replace_all,\n },\n },\n });\n if (response?.action === \"deny\") {\n return { action: \"deny\", reason: response.feedback || \"User denied edit\" };\n }\n return { action: \"allow\" };\n },\n after: async (_ctx, req) => {\n const input = req.input as EditToolInput;\n return {\n context: { edited: input.file_path },\n ui: {\n uri: \"ui://devenv/diff\",\n title: input.file_path,\n data: {\n filePath: input.file_path,\n oldString: input.old_string,\n newString: input.new_string,\n replaceAll: input.replace_all,\n },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface BashToolInput {\n command: string;\n description?: string;\n timeout?: number;\n}\n\nexport const bashTool = tool({\n name: \"Bash\",\n description: \"Execute a bash command\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n command: { type: \"string\" },\n description: { type: \"string\" },\n timeout: { type: \"number\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Run Command\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<BashToolInput>;\n if (input.description) return input.description;\n const shortCmd =\n input.command && input.command.length > 50\n ? input.command.slice(0, 47) + \"...\"\n : input.command || \"command\";\n if (req.status === \"running\") return `Running: ${shortCmd}`;\n if (req.status === \"completed\") return `Ran: ${shortCmd}`;\n return `Failed: ${shortCmd}`;\n },\n },\n hooks: {\n before: async (_ctx, req, options) => {\n const input = req.input as BashToolInput;\n const response = await options.askUser({\n ui: {\n uri: \"ui://devenv/command\",\n title: input.description || input.command,\n data: { command: input.command, description: input.description },\n },\n });\n if (response?.action === \"deny\") {\n return { action: \"deny\", reason: response.feedback || \"User denied command\" };\n }\n return { action: \"allow\" };\n },\n after: async (_ctx, req) => {\n const input = req.input as BashToolInput;\n const output = req.output as { stdout?: string; stderr?: string; exitCode?: number } | string | undefined;\n const outputText = typeof output === \"string\"\n ? output\n : output\n ? [output.stdout, output.stderr].filter(Boolean).join(\"\\n\")\n : undefined;\n const exitCode = typeof output === \"object\" && output ? output.exitCode : undefined;\n return {\n context: { command: input.command, exitCode },\n ui: {\n uri: \"ui://devenv/command\",\n title: input.description || input.command,\n data: { command: input.command, description: input.description, output: outputText, exitCode },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface WriteToolInput {\n file_path: string;\n content: string;\n}\n\nfunction detectLanguage(filePath: string): string | undefined {\n const ext = filePath.split(\".\").pop()?.toLowerCase();\n const langMap: Record<string, string> = {\n ts: \"typescript\", tsx: \"typescript\", js: \"javascript\", jsx: \"javascript\",\n py: \"python\", rs: \"rust\", go: \"go\", rb: \"ruby\", java: \"java\",\n css: \"css\", scss: \"scss\", html: \"html\", json: \"json\",\n yaml: \"yaml\", yml: \"yaml\", toml: \"toml\", xml: \"xml\",\n md: \"markdown\", sql: \"sql\", sh: \"shell\", bash: \"shell\",\n };\n return ext ? langMap[ext] : undefined;\n}\n\nexport const writeTool = tool({\n name: \"Write\",\n description: \"Write content to a file\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\" },\n content: { type: \"string\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Write File\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<WriteToolInput>;\n const fileName = input.file_path?.split(\"/\").pop() || \"file\";\n if (req.status === \"running\") return `Writing ${fileName}...`;\n if (req.status === \"completed\") return `Wrote ${fileName}`;\n return `Failed to write ${fileName}`;\n },\n },\n hooks: {\n before: async (_ctx, req, options) => {\n const input = req.input as WriteToolInput;\n const language = detectLanguage(input.file_path);\n const response = await options.askUser({\n ui: {\n uri: \"ui://devenv/file\",\n title: input.file_path,\n data: { filePath: input.file_path, content: input.content, language },\n },\n });\n if (response?.action === \"deny\") {\n return { action: \"deny\", reason: response.feedback || \"User denied write\" };\n }\n return { action: \"allow\" };\n },\n after: async (_ctx, req) => {\n const input = req.input as WriteToolInput;\n const language = detectLanguage(input.file_path);\n return {\n context: { wrote: input.file_path },\n ui: {\n uri: \"ui://devenv/file\",\n title: input.file_path,\n data: { filePath: input.file_path, content: input.content, language },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface ReadToolInput {\n file_path: string;\n offset?: number;\n limit?: number;\n}\n\nfunction stripLineNumbers(text: string): string {\n return text.replace(/^\\s*\\d+[\\t→]/gm, \"\");\n}\n\nfunction detectLanguage(filePath: string): string | undefined {\n const ext = filePath.split(\".\").pop()?.toLowerCase();\n const langMap: Record<string, string> = {\n ts: \"typescript\", tsx: \"typescript\", js: \"javascript\", jsx: \"javascript\",\n py: \"python\", rs: \"rust\", go: \"go\", rb: \"ruby\", java: \"java\",\n css: \"css\", scss: \"scss\", html: \"html\", json: \"json\",\n yaml: \"yaml\", yml: \"yaml\", toml: \"toml\", xml: \"xml\",\n md: \"markdown\", sql: \"sql\", sh: \"shell\", bash: \"shell\",\n };\n return ext ? langMap[ext] : undefined;\n}\n\nexport const readTool = tool({\n name: \"Read\",\n description: \"Read file contents\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n file_path: { type: \"string\" },\n offset: { type: \"number\" },\n limit: { type: \"number\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Read File\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<ReadToolInput>;\n const fileName = input.file_path?.split(\"/\").pop() || \"file\";\n if (req.status === \"running\") return `Reading ${fileName}...`;\n if (req.status === \"completed\") return `Read ${fileName}`;\n return `Failed to read ${fileName}`;\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n const input = req.input as ReadToolInput;\n const language = detectLanguage(input.file_path);\n const rawOutput = typeof req.output === \"string\"\n ? req.output\n : JSON.stringify(req.output, null, 2);\n const content = stripLineNumbers(rawOutput);\n return {\n context: { read: input.file_path },\n ui: {\n uri: \"ui://devenv/file\",\n title: input.file_path,\n data: { filePath: input.file_path, content, language, startLine: (input.offset ?? 0) + 1 },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface GlobToolInput {\n pattern: string;\n path?: string;\n}\n\nexport const globTool = tool({\n name: \"Glob\",\n description: \"Search for files by pattern\",\n schema: {\n input: {\n type: \"object\",\n properties: { pattern: { type: \"string\" }, path: { type: \"string\" } },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Find Files\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<GlobToolInput>;\n const pattern = input.pattern || \"files\";\n if (req.status === \"running\") return `Finding ${pattern}...`;\n if (req.status === \"completed\") return `Found files matching ${pattern}`;\n return `Failed to find ${pattern}`;\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n const input = req.input as GlobToolInput;\n const output = typeof req.output === \"string\" ? req.output : JSON.stringify(req.output, null, 2);\n return {\n context: { searched: input.pattern },\n ui: {\n uri: \"ui://devenv/command\",\n title: `Find: ${input.pattern}`,\n data: {\n command: `glob ${input.pattern}${input.path ? ` in ${input.path}` : \"\"}`,\n description: `Find files matching ${input.pattern}`,\n output,\n },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface GrepToolInput {\n pattern: string;\n path?: string;\n glob?: string;\n output_mode?: string;\n}\n\nexport const grepTool = tool({\n name: \"Grep\",\n description: \"Search file contents by pattern\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n pattern: { type: \"string\" },\n path: { type: \"string\" },\n glob: { type: \"string\" },\n output_mode: { type: \"string\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Search Code\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<GrepToolInput>;\n const pattern = input.pattern || \"\";\n if (req.status === \"running\") return `Searching for \"${pattern}\"...`;\n if (req.status === \"completed\") return `Searched for \"${pattern}\"`;\n return `Failed to search for \"${pattern}\"`;\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n const input = req.input as GrepToolInput;\n const output = typeof req.output === \"string\" ? req.output : JSON.stringify(req.output, null, 2);\n return {\n context: { searched: input.pattern },\n ui: {\n uri: \"ui://devenv/command\",\n title: `Search: \"${input.pattern}\"`,\n data: {\n command: `grep \"${input.pattern}\"${input.path ? ` in ${input.path}` : \"\"}${input.glob ? ` (${input.glob})` : \"\"}`,\n description: `Search for \"${input.pattern}\"`,\n output,\n },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface ExitPlanModeToolInput {\n plan: string;\n}\n\nexport const exitPlanModeTool = tool({\n name: \"ExitPlanMode\",\n description: \"Present the plan to the user for review before exiting plan mode\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n plan: { type: \"string\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Review Plan\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n if (req.status === \"running\") return \"Reviewing plan...\";\n if (req.status === \"completed\") return \"Plan reviewed\";\n return \"Plan rejected\";\n },\n },\n hooks: {\n before: async (_ctx, req, options) => {\n const input = req.input as ExitPlanModeToolInput;\n const response = await options.askUser({\n ui: {\n uri: \"ui://agent/plan\",\n title: \"Plan\",\n data: { content: input.plan ?? \"\" },\n },\n });\n if (response?.action === \"deny\") {\n return { action: \"deny\", reason: response.feedback || \"User rejected plan\" };\n }\n return { action: \"allow\" };\n },\n after: async (_ctx, req) => {\n const input = req.input as ExitPlanModeToolInput;\n return {\n context: { planApproved: true },\n ui: {\n uri: \"ui://agent/plan\",\n title: \"Plan\",\n data: { content: input.plan ?? \"\" },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport const enterPlanModeTool = tool({\n name: \"EnterPlanMode\",\n description: \"Signal that the agent is entering plan mode\",\n schema: {\n input: { type: \"object\", properties: {} },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Plan Mode\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n if (req.status === \"running\") return \"Entering plan mode...\";\n if (req.status === \"completed\") return \"In plan mode\";\n return \"Failed to enter plan mode\";\n },\n },\n hooks: {\n after: async () => {\n return { context: { mode: \"plan\" } };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface TodoItem {\n content: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n activeForm: string;\n}\n\nexport interface TodoWriteToolInput {\n todos: TodoItem[];\n}\n\nexport const todoWriteTool = tool({\n name: \"TodoWrite\",\n description: \"Maintain the agent's in-session todo list\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n todos: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n content: { type: \"string\" },\n status: { type: \"string\" },\n activeForm: { type: \"string\" },\n },\n },\n },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Todos\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<TodoWriteToolInput>;\n const todos = input.todos ?? [];\n const total = todos.length;\n const done = todos.filter((t) => t.status === \"completed\").length;\n if (req.status === \"running\") return `Updating todos (${done}/${total})...`;\n if (req.status === \"completed\") return `Todos updated (${done}/${total})`;\n return \"Failed to update todos\";\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n const input = req.input as TodoWriteToolInput;\n const todos = input.todos ?? [];\n return {\n context: { todos },\n ui: {\n uri: \"ui://agent/todos\",\n title: \"Todos\",\n data: { todos },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface WebSearchToolInput {\n query: string;\n allowed_domains?: string[];\n blocked_domains?: string[];\n}\n\ninterface WebSearchHit {\n title: string;\n url: string;\n}\n\ninterface WebSearchOutput {\n query?: string;\n results?: Array<{ content?: WebSearchHit[] } | string>;\n durationSeconds?: number;\n}\n\nfunction flattenHits(output: WebSearchOutput | undefined): WebSearchHit[] {\n const hits: WebSearchHit[] = [];\n for (const r of output?.results ?? []) {\n if (typeof r === \"string\") continue;\n for (const hit of r.content ?? []) hits.push(hit);\n }\n return hits;\n}\n\nexport const webSearchTool = tool({\n name: \"WebSearch\",\n description: \"Search the web\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n query: { type: \"string\" },\n allowed_domains: { type: \"array\", items: { type: \"string\" } },\n blocked_domains: { type: \"array\", items: { type: \"string\" } },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Web Search\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<WebSearchToolInput>;\n const q = input.query ?? \"\";\n const short = q.length > 40 ? q.slice(0, 37) + \"...\" : q;\n if (req.status === \"running\") return `Searching: ${short}...`;\n if (req.status === \"completed\") return `Searched: ${short}`;\n return `Failed to search: ${short}`;\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n const input = req.input as WebSearchToolInput;\n const output = req.output as WebSearchOutput | undefined;\n const hits = flattenHits(output);\n return {\n context: { query: input.query, hitCount: hits.length },\n ui: {\n uri: \"ui://agent/web-search\",\n title: input.query,\n data: {\n title: input.query,\n items: hits.map((h) => ({ title: h.title, description: h.url })),\n },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface WebFetchToolInput {\n url: string;\n prompt: string;\n}\n\ninterface WebFetchOutput {\n bytes?: number;\n code?: number;\n codeText?: string;\n result?: string;\n durationMs?: number;\n url?: string;\n}\n\nfunction hostOf(url: string | undefined): string {\n if (!url) return \"url\";\n try {\n return new URL(url).host;\n } catch {\n return url.length > 40 ? url.slice(0, 37) + \"...\" : url;\n }\n}\n\nexport const webFetchTool = tool({\n name: \"WebFetch\",\n description: \"Fetch a URL and run a prompt over its content\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n url: { type: \"string\" },\n prompt: { type: \"string\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Web Fetch\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<WebFetchToolInput>;\n const host = hostOf(input.url);\n if (req.status === \"running\") return `Fetching ${host}...`;\n if (req.status === \"completed\") return `Fetched ${host}`;\n return `Failed to fetch ${host}`;\n },\n },\n hooks: {\n before: async (_ctx, req, options) => {\n const input = req.input as WebFetchToolInput;\n const response = await options.askUser({\n ui: {\n uri: \"ui://agent/web-fetch\",\n title: input.url,\n data: { url: input.url, prompt: input.prompt },\n },\n });\n if (response?.action === \"deny\") {\n return { action: \"deny\", reason: response.feedback || \"User denied fetch\" };\n }\n return { action: \"allow\" };\n },\n after: async (_ctx, req) => {\n const input = req.input as WebFetchToolInput;\n const output = req.output as WebFetchOutput | undefined;\n return {\n context: { fetched: input.url, code: output?.code },\n ui: {\n uri: \"ui://agent/web-fetch\",\n title: input.url,\n data: {\n title: input.url,\n url: input.url,\n prompt: input.prompt,\n status: output?.code,\n bytes: output?.bytes,\n durationMs: output?.durationMs,\n result: output?.result,\n },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\n\nexport interface AgentToolInput {\n description: string;\n prompt: string;\n subagent_type?: string;\n model?: \"sonnet\" | \"opus\" | \"haiku\";\n run_in_background?: boolean;\n name?: string;\n}\n\ninterface AgentToolOutput {\n agentId?: string;\n agentType?: string;\n content?: Array<{ type: \"text\"; text: string }>;\n totalToolUseCount?: number;\n totalDurationMs?: number;\n totalTokens?: number;\n}\n\nfunction joinText(content: AgentToolOutput[\"content\"]): string {\n return (content ?? []).map((c) => c.text).join(\"\\n\");\n}\n\nexport const agentTool = tool({\n name: \"Agent\",\n description: \"Spawn a sub-agent to handle a task\",\n schema: {\n input: {\n type: \"object\",\n properties: {\n description: { type: \"string\" },\n prompt: { type: \"string\" },\n subagent_type: { type: \"string\" },\n model: { type: \"string\" },\n run_in_background: { type: \"boolean\" },\n name: { type: \"string\" },\n },\n },\n output: { type: \"object\" },\n },\n metadata: {\n label: \"Sub-Agent\",\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n const input = req.input as Partial<AgentToolInput>;\n const label = input.name || input.subagent_type || input.description || \"agent\";\n if (req.status === \"running\") return `Running ${label}...`;\n if (req.status === \"completed\") return `Ran ${label}`;\n return `Failed: ${label}`;\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n const input = req.input as AgentToolInput;\n const output = req.output as AgentToolOutput | undefined;\n return {\n context: {\n agentId: output?.agentId,\n totalTokens: output?.totalTokens,\n totalToolUseCount: output?.totalToolUseCount,\n },\n ui: {\n uri: \"ui://agent/subagent\",\n title: input.description,\n data: {\n title: input.description,\n subagentType: input.subagent_type ?? output?.agentType,\n name: input.name,\n model: input.model,\n toolCalls: output?.totalToolUseCount,\n durationMs: output?.totalDurationMs,\n totalTokens: output?.totalTokens,\n result: joinText(output?.content),\n },\n },\n };\n },\n },\n});\n","import { tool } from \"@jarvis/sdk\";\nimport type { Tool } from \"@jarvis/types\";\n\n/**\n * Wrap a native Claude Code tool with a minimal `tool()` definition.\n * The `after` hook emits raw input/output through a type-keyed URI; the UI\n * falls back to the wildcard `defaultArtifactConfig`\n * (GenericObjectArtifact / GenericListArtifact).\n */\nfunction genericClaudeCodeTool(options: {\n name: string;\n label: string;\n description: string;\n verb: string;\n uriType: string;\n}): Tool {\n const { name, label, description, verb, uriType } = options;\n return tool({\n name,\n description,\n schema: {\n input: { type: \"object\", properties: {} },\n output: { type: \"object\" },\n },\n metadata: {\n label,\n provider: \"claude-code\",\n describe: (_ctx, req) => {\n if (req.status === \"running\") return `${verb}...`;\n if (req.status === \"completed\") return verb.replace(/ing$/, \"ed\");\n return `Failed: ${label}`;\n },\n },\n hooks: {\n after: async (_ctx, req) => {\n return {\n context: { tool: name },\n ui: {\n uri: `ui://agent/${uriType}`,\n title: label,\n data: { ...(req.input as object), ...(req.output as object) },\n },\n };\n },\n },\n });\n}\n\nexport const taskOutputTool = genericClaudeCodeTool({\n name: \"TaskOutput\",\n label: \"Sub-Agent Output\",\n description: \"Read output from a sub-agent\",\n verb: \"Reading sub-agent output\",\n uriType: \"task-output\",\n});\n\nexport const taskStopTool = genericClaudeCodeTool({\n name: \"TaskStop\",\n label: \"Stop Sub-Agent\",\n description: \"Stop a running sub-agent\",\n verb: \"Stopping sub-agent\",\n uriType: \"task-stop\",\n});\n\nexport const notebookEditTool = genericClaudeCodeTool({\n name: \"NotebookEdit\",\n label: \"Notebook Edit\",\n description: \"Edit a Jupyter notebook cell\",\n verb: \"Editing notebook\",\n uriType: \"notebook-edit\",\n});\n\nexport const enterWorktreeTool = genericClaudeCodeTool({\n name: \"EnterWorktree\",\n label: \"Enter Worktree\",\n description: \"Enter an isolated git worktree\",\n verb: \"Entering worktree\",\n uriType: \"enter-worktree\",\n});\n\nexport const exitWorktreeTool = genericClaudeCodeTool({\n name: \"ExitWorktree\",\n label: \"Exit Worktree\",\n description: \"Exit the current git worktree\",\n verb: \"Exiting worktree\",\n uriType: \"exit-worktree\",\n});\n","export { editTool } from \"./edit.tool\";\nexport { bashTool } from \"./bash.tool\";\nexport { writeTool } from \"./write.tool\";\nexport { readTool } from \"./read.tool\";\nexport { globTool } from \"./glob.tool\";\nexport { grepTool } from \"./grep.tool\";\nexport { exitPlanModeTool } from \"./exit-plan-mode.tool\";\nexport { enterPlanModeTool } from \"./enter-plan-mode.tool\";\nexport { todoWriteTool } from \"./todo-write.tool\";\nexport { webSearchTool } from \"./web-search.tool\";\nexport { webFetchTool } from \"./web-fetch.tool\";\nexport { agentTool } from \"./agent.tool\";\nexport {\n taskOutputTool,\n taskStopTool,\n notebookEditTool,\n enterWorktreeTool,\n exitWorktreeTool,\n} from \"./generic.tool\";\n\nimport { agentTool } from \"./agent.tool\";\nimport { bashTool } from \"./bash.tool\";\nimport { editTool } from \"./edit.tool\";\nimport { enterPlanModeTool } from \"./enter-plan-mode.tool\";\nimport { exitPlanModeTool } from \"./exit-plan-mode.tool\";\nimport {\n enterWorktreeTool,\n exitWorktreeTool,\n notebookEditTool,\n taskOutputTool,\n taskStopTool,\n} from \"./generic.tool\";\nimport { globTool } from \"./glob.tool\";\nimport { grepTool } from \"./grep.tool\";\nimport { readTool } from \"./read.tool\";\nimport { todoWriteTool } from \"./todo-write.tool\";\nimport { webFetchTool } from \"./web-fetch.tool\";\nimport { webSearchTool } from \"./web-search.tool\";\nimport { writeTool } from \"./write.tool\";\n\n/** All Claude Code native tools with hooks */\nexport const claudeCodeTools = [\n editTool,\n bashTool,\n writeTool,\n readTool,\n globTool,\n grepTool,\n exitPlanModeTool,\n enterPlanModeTool,\n todoWriteTool,\n webSearchTool,\n webFetchTool,\n agentTool,\n taskOutputTool,\n taskStopTool,\n notebookEditTool,\n enterWorktreeTool,\n exitWorktreeTool,\n];\n","/**\n * Tool Description Formatter\n *\n * Human-readable descriptions for tool calls in progress messages.\n */\n\nexport function formatToolDescription(toolName: string, input?: Record<string, unknown>): string {\n if (!input) return toolName;\n switch (toolName) {\n case \"Read\":\n return `Reading ${input.file_path || \"file\"}`;\n case \"Edit\":\n return `Editing ${input.file_path || \"file\"}`;\n case \"Write\":\n return `Writing to ${input.file_path || \"file\"}`;\n case \"Bash\":\n return typeof input.command === \"string\"\n ? input.command.length > 80\n ? input.command.slice(0, 80) + \"…\"\n : input.command\n : \"Running command\";\n case \"Glob\":\n return `Searching for ${input.pattern || \"files\"}`;\n case \"Grep\":\n return `Searching for \"${input.pattern || \"\"}\"`;\n case \"Tool Search\":\n case \"ToolSearch\": {\n const refs = Array.isArray(input.tool_names)\n ? (input.tool_names as string[])\n : Array.isArray(input.tools)\n ? (input.tools as Array<{ tool_name?: string } | string>)\n .map((t) => (typeof t === \"string\" ? t : t?.tool_name))\n .filter((n): n is string => !!n)\n : [];\n if (refs.length === 0) return \"Looking up tools\";\n if (refs.length === 1) return `Looking up ${refs[0]}`;\n return `Looking up ${refs.join(\", \")}`;\n }\n default:\n return toolName;\n }\n}\n","/**\n * Git Worktree Utilities\n *\n * Per-task isolation using git worktrees.\n * Default location: ~/.jarvis/worktrees/\n */\n\nimport { exec as execCb } from \"child_process\";\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport { promisify } from \"util\";\n\nconst exec = promisify(execCb);\n\nconst DEFAULT_WORKTREE_DIR = path.join(os.homedir(), \".jarvis\", \"worktrees\");\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface CreateWorktreeRequest {\n repoPath: string;\n taskId: string;\n branch?: string;\n /** Base directory for worktrees (default: ~/.jarvis/worktrees) */\n worktreeDir?: string;\n}\n\nexport interface CreateWorktreeResponse {\n worktreePath: string;\n branchName: string;\n /** Resolved sha of the start point at creation time. Frozen for the\n * lifetime of the task — diff scans compute against this so they show\n * the cumulative session delta, not just the last commit. */\n baselineRef: string;\n}\n\nexport interface RemoveWorktreeRequest {\n repoPath: string;\n taskId: string;\n /** Base directory for worktrees (default: ~/.jarvis/worktrees) */\n worktreeDir?: string;\n}\n\nexport interface ListWorktreesRequest {\n repoPath: string;\n}\n\nexport interface WorktreeInfo {\n taskId: string;\n path: string;\n branch: string;\n}\n\nexport interface WorktreeExistsRequest {\n taskId: string;\n /** Base directory for worktrees (default: ~/.jarvis/worktrees) */\n worktreeDir?: string;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction resolveDir(worktreeDir?: string): string {\n if (!worktreeDir) return DEFAULT_WORKTREE_DIR;\n return worktreeDir.replace(/^~/, os.homedir());\n}\n\n// =============================================================================\n// Functions\n// =============================================================================\n\nexport async function createWorktree(req: CreateWorktreeRequest): Promise<CreateWorktreeResponse> {\n const branchName = `jarvis/task-${req.taskId}`;\n const baseDir = resolveDir(req.worktreeDir);\n const worktreePath = path.join(baseDir, `task-${req.taskId}`);\n\n await fs.mkdir(path.dirname(worktreePath), { recursive: true });\n\n const startPoint = req.branch ?? \"HEAD\";\n\n if (await worktreeExists({ taskId: req.taskId, worktreeDir: req.worktreeDir })) {\n const baselineRef = await resolveBaselineRef(req.repoPath, branchName, startPoint);\n return { worktreePath, branchName, baselineRef };\n }\n\n await exec(`git worktree add -b \"${branchName}\" \"${worktreePath}\" \"${startPoint}\"`, {\n cwd: req.repoPath,\n });\n\n const baselineRef = await resolveBaselineRef(req.repoPath, branchName, startPoint);\n return { worktreePath, branchName, baselineRef };\n}\n\n/** Resolve the start point to a sha so subsequent commits don't move it. */\nasync function resolveBaselineRef(\n repoPath: string,\n branchName: string,\n startPoint: string,\n): Promise<string> {\n // Prefer the start point — the user-supplied base. Fall back to the new\n // branch tip (equivalent immediately after worktree creation) if the start\n // point can't be resolved (e.g. a stale local ref).\n for (const ref of [startPoint, branchName]) {\n try {\n const { stdout } = await exec(`git rev-parse \"${ref}\"`, { cwd: repoPath });\n const sha = stdout.trim();\n if (sha) return sha;\n } catch {\n /* try next */\n }\n }\n return \"\";\n}\n\nexport async function removeWorktree(req: RemoveWorktreeRequest): Promise<void> {\n const branchName = `jarvis/task-${req.taskId}`;\n const baseDir = resolveDir(req.worktreeDir);\n const worktreePath = path.join(baseDir, `task-${req.taskId}`);\n\n try {\n await exec(`git worktree remove --force \"${worktreePath}\"`, { cwd: req.repoPath });\n } catch {\n await fs.rm(worktreePath, { recursive: true, force: true });\n await exec(\"git worktree prune\", { cwd: req.repoPath }).catch(() => {});\n }\n\n await exec(`git branch -D \"${branchName}\"`, { cwd: req.repoPath }).catch(() => {});\n}\n\nexport async function listWorktrees(req: ListWorktreesRequest): Promise<WorktreeInfo[]> {\n const { stdout } = await exec(\"git worktree list --porcelain\", { cwd: req.repoPath });\n const worktrees: WorktreeInfo[] = [];\n\n let currentPath = \"\";\n let currentBranch = \"\";\n\n for (const line of stdout.split(\"\\n\")) {\n if (line.startsWith(\"worktree \")) {\n currentPath = line.slice(9);\n } else if (line.startsWith(\"branch refs/heads/\")) {\n currentBranch = line.slice(18);\n if (currentBranch.startsWith(\"jarvis/task-\")) {\n worktrees.push({\n taskId: currentBranch.replace(\"jarvis/task-\", \"\"),\n path: currentPath,\n branch: currentBranch,\n });\n }\n }\n }\n\n return worktrees;\n}\n\nexport async function worktreeExists(req: WorktreeExistsRequest): Promise<boolean> {\n const baseDir = resolveDir(req.worktreeDir);\n const worktreePath = path.join(baseDir, `task-${req.taskId}`);\n try {\n await fs.access(worktreePath);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * @jarvis/agent\n *\n * Shared agent utilities — tools, formatters, worktree management.\n * Used by: apps/cli, workflows/devenv-workflow, apps/vscode\n * No Temporal dependency.\n */\n\nexport { claudeCodeTools } from \"./tools\";\nexport { editTool } from \"./tools/edit.tool\";\nexport { bashTool } from \"./tools/bash.tool\";\nexport { writeTool } from \"./tools/write.tool\";\nexport { readTool } from \"./tools/read.tool\";\nexport { globTool } from \"./tools/glob.tool\";\nexport { grepTool } from \"./tools/grep.tool\";\n\nexport { formatToolDescription } from \"./format\";\n\nexport {\n createWorktree,\n removeWorktree,\n listWorktrees,\n worktreeExists,\n} from \"./worktree\";\nexport type {\n CreateWorktreeRequest,\n CreateWorktreeResponse,\n RemoveWorktreeRequest,\n ListWorktreesRequest,\n WorktreeInfo,\n WorktreeExistsRequest,\n} from \"./worktree\";\n","/**\n * Attachment resolver for claude-code runs.\n *\n * Fetches uploaded files by URL and either inlines their content (text) or\n * saves them to the worktree (images / binary). Returns a preamble that\n * `run()` prepends to the last user message.\n */\n\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nimport { logger } from \"@jarvis/logger\";\n\ninterface Attachment {\n key: string;\n url: string;\n fileName: string;\n mimeType: string;\n size: number;\n}\n\nconst TEXT_MIME_PREFIXES = [\n \"text/\",\n \"application/json\",\n \"application/xml\",\n \"application/javascript\",\n];\nconst IMAGE_MIME_PREFIXES = [\"image/\"];\n\nfunction isTextFile(mimeType: string): boolean {\n return TEXT_MIME_PREFIXES.some((p) => mimeType.startsWith(p));\n}\n\nfunction isImageFile(mimeType: string): boolean {\n return IMAGE_MIME_PREFIXES.some((p) => mimeType.startsWith(p));\n}\n\n/** Resolve a relative storage URL (`/api/v1/storage/...`) to an absolute one. */\nfunction resolveUrl(url: string, baseUrl: string): string {\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) return url;\n return `${baseUrl}${url}`;\n}\n\nexport async function resolveAttachments(\n attachments: Attachment[],\n workspacePath: string,\n baseUrl: string,\n): Promise<string> {\n if (!attachments.length) return \"\";\n\n const parts: string[] = [];\n const uploadDir = path.join(workspacePath, \".jarvis-uploads\");\n\n for (const att of attachments) {\n try {\n const fullUrl = resolveUrl(att.url, baseUrl);\n\n if (isTextFile(att.mimeType)) {\n const res = await fetch(fullUrl);\n if (!res.ok) {\n logger.sys.warn(\"[Attachments] Failed to fetch text file\", {\n fileName: att.fileName,\n status: res.status,\n });\n continue;\n }\n parts.push(`<file name=\"${att.fileName}\">\\n${await res.text()}\\n</file>`);\n } else if (isImageFile(att.mimeType)) {\n await fs.mkdir(uploadDir, { recursive: true });\n const localPath = path.join(uploadDir, att.fileName);\n const res = await fetch(fullUrl);\n if (!res.ok) {\n logger.sys.warn(\"[Attachments] Failed to fetch image\", {\n fileName: att.fileName,\n status: res.status,\n });\n continue;\n }\n await fs.writeFile(localPath, Buffer.from(await res.arrayBuffer()));\n parts.push(`[Image attached: ${localPath}]`);\n } else {\n await fs.mkdir(uploadDir, { recursive: true });\n const localPath = path.join(uploadDir, att.fileName);\n const res = await fetch(fullUrl);\n if (!res.ok) {\n logger.sys.warn(\"[Attachments] Failed to fetch file\", {\n fileName: att.fileName,\n status: res.status,\n });\n continue;\n }\n await fs.writeFile(localPath, Buffer.from(await res.arrayBuffer()));\n parts.push(`[File attached: ${localPath}]`);\n }\n } catch (err) {\n logger.sys.warn(\"[Attachments] Error processing attachment\", {\n fileName: att.fileName,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return parts.length ? parts.join(\"\\n\\n\") : \"\";\n}\n","/**\n * Progress handlers for claude-code runs.\n *\n * Converts Claude Agent SDK progress events into the typed stream callbacks\n * on `RunOptions` (`onMessage` / `onToken` / `onUsage`).\n */\n\nimport crypto from \"crypto\";\n\nimport { formatToolDescription } from \"@jarvis/agent\";\nimport type {\n ChatMessage,\n PendingUserInput,\n RunOptions,\n ToolCallData,\n Ui,\n UserInputResponse,\n} from \"@jarvis/types\";\n\n/**\n * Internal enrichment shape captured from Claude SDK's tool_use blocks\n * before we lift them into a canonical `Ui`. Lives here (not in\n * `@jarvis/types`) because it's an Anthropic-specific intermediate.\n */\ninterface ToolUiEntry {\n type: string;\n title?: string;\n data: unknown;\n}\n\nexport interface ClaudeCodeProgressHandlers {\n /** Feed a raw Claude SDK event. */\n handleProgress: (message: unknown) => Promise<void>;\n /** Called by claudeCodeProvider's tool-hook integration. */\n handleUserInput: (input: PendingUserInput) => Promise<UserInputResponse>;\n /** Notify the timeline of the user's permission decision, so the tool's\n * dot updates to denied/modified/allowed even if the SDK aborts before\n * emitting a tool_result block. */\n handlePermissions: (params: {\n toolUseId: string;\n toolName: string;\n action: \"allow\" | \"deny\" | \"modify\";\n feedback?: string;\n }) => void;\n /** Finalize any in-flight tool blocks. */\n completeTools: () => Promise<void>;\n}\n\nexport interface ClaudeCodeProgressConfig {\n runId: string;\n chatId: string;\n options: RunOptions;\n}\n\nexport function createClaudeCodeProgress(\n config: ClaudeCodeProgressConfig,\n): ClaudeCodeProgressHandlers {\n const { runId, chatId, options } = config;\n const toolIds = new Map<string, { name: string; input?: Record<string, unknown> }>();\n let currentThinkingId: string | null = null;\n let currentTextId: string | null = null;\n let currentTextContent = \"\";\n\n function emitMessage(msg: ChatMessage): void {\n options.onMessage?.(msg);\n }\n\n async function completeTools(): Promise<void> {\n const now = new Date().toISOString();\n for (const [toolId, { name: toolName }] of toolIds) {\n emitMessage({\n id: `tool-${toolId}`,\n role: \"assistant\",\n type: \"tool\",\n content: \"\",\n createdAt: now,\n metadata: {\n toolCall: { toolName, toolCallId: toolId, status: \"completed\" },\n isPartial: false,\n },\n });\n }\n toolIds.clear();\n }\n\n async function handleUserInput(input: PendingUserInput): Promise<UserInputResponse> {\n const toolName = input.toolName ?? \"\";\n // askUser and UI-bearing tools always require user decision.\n const needsUser = toolName === \"askUser\" || !!input.ui;\n if (needsUser && options.onUserInputRequest) {\n return options.onUserInputRequest(input);\n }\n return { action: \"allow\" };\n }\n\n function handlePermissions(params: {\n toolUseId: string;\n toolName: string;\n action: \"allow\" | \"deny\" | \"modify\";\n feedback?: string;\n }): void {\n // Skip \"allow\" — the tool's normal lifecycle (running → completed) will\n // emit the right status as the SDK runs and reports its tool_result.\n if (params.action === \"allow\") return;\n const status: \"denied\" | \"modify\" =\n params.action === \"modify\" ? \"modify\" : \"denied\";\n const now = new Date().toISOString();\n emitMessage({\n id: `tool-${params.toolUseId}`,\n role: \"assistant\",\n type: \"tool\",\n content: params.feedback ?? \"\",\n createdAt: now,\n metadata: {\n toolCall: {\n toolName: params.toolName,\n toolCallId: params.toolUseId,\n status,\n ...(params.feedback ? { error: params.feedback } : {}),\n },\n isPartial: false,\n },\n });\n // Drop from in-flight tracking so completeTools() doesn't stomp over us.\n toolIds.delete(params.toolUseId);\n }\n\n async function handleProgress(message: unknown): Promise<void> {\n const raw = message as {\n type?: string;\n message?: {\n content?: Array<Record<string, unknown>>;\n usage?: { input_tokens?: number; output_tokens?: number };\n model?: string;\n };\n usage?: { input_tokens?: number; output_tokens?: number };\n model?: string;\n _toolUi?: Record<string, ToolUiEntry>;\n };\n if (!raw?.type) return;\n\n const now = new Date().toISOString();\n\n // Per-assistant-message usage delta — emit as soon as the SDK reports\n // tokens for this message so the token panel updates live (instead of\n // waiting for the `result` event at turn-end). Each assistant message\n // carries its own usage; summing per-message yields the turn total, so\n // the result-phase emission is intentionally dropped (see below) to\n // avoid double-counting.\n if (raw.type === \"assistant\" && raw.message?.usage) {\n const u = raw.message.usage;\n const inputTokens = u.input_tokens ?? 0;\n const outputTokens = u.output_tokens ?? 0;\n if (inputTokens || outputTokens) {\n options.onUsage?.({\n chatId,\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n model: raw.message.model ?? raw.model ?? \"unknown\",\n });\n }\n }\n\n if (raw.type === \"assistant\" && Array.isArray(raw.message?.content)) {\n for (const block of raw.message!.content) {\n if (block.type === \"thinking\" && block.thinking) {\n if (!currentThinkingId) currentThinkingId = `thinking-${crypto.randomUUID()}`;\n emitMessage({\n id: currentThinkingId,\n role: \"assistant\",\n type: \"thinking\",\n content: block.thinking as string,\n createdAt: now,\n metadata: { isPartial: true },\n });\n continue;\n }\n\n currentThinkingId = null;\n\n if (block.type === \"text\" && block.text) {\n if (!currentTextId) currentTextId = `text-${crypto.randomUUID()}`;\n currentTextContent += block.text as string;\n options.onToken?.({\n messageId: currentTextId,\n content: currentTextContent,\n isComplete: false,\n });\n }\n\n if (block.type === \"tool_use\" && block.id && block.name) {\n if (currentTextId) {\n options.onToken?.({\n messageId: currentTextId,\n content: currentTextContent,\n isComplete: true,\n isFinal: false,\n });\n currentTextId = null;\n currentTextContent = \"\";\n }\n const blockId = block.id as string;\n const blockName = block.name as string;\n const blockInput = block.input as Record<string, unknown> | undefined;\n toolIds.set(blockId, { name: blockName, input: blockInput });\n\n const toolCall: ToolCallData = {\n toolName: blockName,\n toolCallId: blockId,\n status: \"running\",\n input: block.input as Record<string, unknown>,\n };\n\n emitMessage({\n id: `tool-${blockId}`,\n role: \"assistant\",\n type: \"tool\",\n content: formatToolDescription(blockName, block.input as Record<string, unknown>),\n createdAt: now,\n metadata: { toolCall, isPartial: true },\n });\n }\n }\n }\n\n currentThinkingId = null;\n if (currentTextId) {\n options.onToken?.({\n messageId: currentTextId,\n content: currentTextContent,\n isComplete: true,\n });\n currentTextId = null;\n currentTextContent = \"\";\n }\n\n if (raw.type === \"user\" && Array.isArray(raw.message?.content)) {\n for (const block of raw.message!.content) {\n if (!block.tool_use_id) continue;\n\n const toolUseId = block.tool_use_id as string;\n const tracked = toolIds.get(toolUseId);\n const toolName = tracked?.name ?? \"\";\n const output =\n typeof block.content === \"string\" ? block.content : JSON.stringify(block.content);\n const truncated = output && output.length > 1000 ? output.slice(0, 1000) + \"...\" : output;\n\n const toolUiData = raw._toolUi?.[toolUseId];\n const toolUi: Ui | undefined = toolUiData\n ? {\n uri: `ui://devenv/${toolUiData.type}`,\n title: toolUiData.title ?? \"\",\n data: toolUiData.data,\n }\n : undefined;\n\n const toolCall: ToolCallData = {\n toolName,\n toolCallId: toolUseId,\n status: block.is_error ? \"error\" : \"completed\",\n output: truncated,\n error: block.is_error ? (truncated ?? undefined) : undefined,\n };\n\n // Tool Search returns structured tool_reference blocks as its result,\n // which JSON.stringify cannot render meaningfully. Keep the body as\n // the input-derived description (\"Looking up X\") through completion.\n const isToolSearch = toolName === \"Tool Search\" || toolName === \"ToolSearch\";\n const body = isToolSearch\n ? formatToolDescription(toolName, tracked?.input)\n : (truncated ?? \"\");\n\n emitMessage({\n id: `tool-${toolUseId}`,\n role: \"assistant\",\n type: \"tool\",\n content: body,\n createdAt: now,\n metadata: {\n toolCall,\n ...(toolUi ? { ui: toolUi } : {}),\n isPartial: false,\n },\n });\n toolIds.delete(toolUseId);\n }\n }\n\n if (raw.type === \"result\") {\n // Usage is streamed per assistant message above (raw.message.usage),\n // so emitting again here would double-count the workflow's accumulator.\n // The `result` event remains the trigger for completeTools().\n await completeTools();\n }\n }\n\n // runId is threaded into this module via config so future signatures can\n // include it on typed events if needed — reference it to satisfy eslint.\n void runId;\n\n return { handleProgress, handleUserInput, handlePermissions, completeTools };\n}\n","/**\n * Claude Code Agent Provider\n *\n * Implements the full `CodeAgentProvider` interface for Claude Code:\n * - `run` / `abort` — dispatch an agent turn via the Claude Code SDK,\n * streaming progress through the `RunOptions` callbacks.\n * - `scanChats` / `readChat` / `extractChatMetadata` / `extractMessages`\n * / `extractFileChanges` / `extractFileTree` — data projection over CC's\n * native `~/.claude/projects/<encoded-cwd>/*.jsonl` storage.\n * - `estimateCost` — pricing from `anthropic.models.ts`.\n */\n\nimport crypto from \"crypto\";\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport readline from \"readline\";\nimport { createReadStream } from \"fs\";\n\nimport { claudeCodeTools } from \"@jarvis/agent\";\nimport { logger } from \"@jarvis/logger\";\nimport type {\n InterruptAgentRequest,\n AgentFileChange,\n AgentFileTreeNode,\n AgentMode,\n AgentTurnUsage,\n Chat,\n ChatMessage,\n CodeAgentProvider,\n Context,\n EstimateCostRequest,\n EstimateCostResponse,\n ExtractChatMetadataResponse,\n ExtractChatRequest,\n ExtractFileChangesResponse,\n ExtractFileTreeRequest,\n ExtractFileTreeResponse,\n ExtractMessagesResponse,\n Message,\n Model,\n ModelCost,\n RunAgentRequest,\n RunAgentResponse,\n ReadChatRequest,\n ReadChatResponse,\n RunOptions,\n ScanChatsRequest,\n ScanChatsResponse,\n Usage,\n} from \"@jarvis/types\";\n\nimport { anthropicModels, claudeCodeModels } from \"./anthropic.models\";\nimport { resolveAttachments } from \"./attachments\";\nimport { claudeCodeProvider } from \"./claude-code.llm.provider\";\nimport { createClaudeCodeProgress } from \"./progress\";\n\ntype SdkPermissionMode = \"default\" | \"acceptEdits\" | \"bypassPermissions\" | \"plan\";\n\nfunction toSdkPermissionMode(mode: AgentMode | undefined): SdkPermissionMode {\n switch (mode) {\n case \"auto\":\n return \"acceptEdits\";\n case \"plan\":\n return \"plan\";\n case \"ask\":\n default:\n return \"default\";\n }\n}\n\n// =============================================================================\n// Path Encoding (CC stores projects under ~/.claude/projects/<encoded-cwd>/)\n// =============================================================================\n\nfunction encodePath(p: string): string {\n return p.replace(/\\//g, \"-\");\n}\n\nfunction getClaudeDir(): string {\n return path.join(os.homedir(), \".claude\");\n}\n\nfunction getProjectsDir(): string {\n return path.join(getClaudeDir(), \"projects\");\n}\n\n/** Guard caller-supplied session file paths against traversal. CC sessions\n * always live under `~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl` —\n * reject anything that escapes that root. */\nfunction requireUnderProjectsDir(filePath: string): string {\n const projectsDir = getProjectsDir();\n const resolved = path.resolve(filePath);\n const rel = path.relative(projectsDir, resolved);\n if (rel.startsWith(\"..\") || path.isAbsolute(rel)) {\n throw new Error(`Refusing to read file outside projects dir: ${filePath}`);\n }\n return resolved;\n}\n\n// =============================================================================\n// History Index (ai-title lookup)\n// =============================================================================\n\ninterface HistoryEntry {\n display?: string;\n timestamp?: string;\n project?: string;\n sessionId?: string;\n}\n\nlet historyCache: Map<string, HistoryEntry> | null = null;\nlet historyCacheMtime = 0;\n\nasync function loadHistory(): Promise<Map<string, HistoryEntry>> {\n const historyPath = path.join(getClaudeDir(), \"history.jsonl\");\n try {\n const stat = await fs.stat(historyPath);\n if (historyCache && stat.mtimeMs === historyCacheMtime) return historyCache;\n const content = await fs.readFile(historyPath, \"utf-8\");\n const entries = new Map<string, HistoryEntry>();\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const entry = JSON.parse(line) as HistoryEntry;\n if (entry.sessionId) entries.set(entry.sessionId, entry);\n } catch {\n /* skip */\n }\n }\n historyCache = entries;\n historyCacheMtime = stat.mtimeMs;\n return entries;\n } catch {\n return new Map();\n }\n}\n\n// =============================================================================\n// JSONL Event Types\n// =============================================================================\n\ninterface RawEvent {\n type?: string;\n uuid?: string;\n parentUuid?: string;\n timestamp?: string;\n sessionId?: string;\n isSidechain?: boolean;\n message?: {\n role?: string;\n content?: unknown;\n model?: string;\n usage?: Record<string, number>;\n };\n title?: string;\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Session Metadata Extraction\n// =============================================================================\n\ninterface RawMetadata {\n title: string | null;\n messageCount: number;\n createdAt: string | null;\n lastMessageAt: string | null;\n model: string | null;\n gitBranch: string | null;\n cwd: string | null;\n}\n\nasync function extractRawMetadata(\n filePath: string,\n history: Map<string, HistoryEntry>,\n): Promise<RawMetadata> {\n let title: string | null = null;\n let firstUserMessage: string | null = null;\n let messageCount = 0;\n let createdAt: string | null = null;\n let lastMessageAt: string | null = null;\n let model: string | null = null;\n let gitBranch: string | null = null;\n let sessionId: string | null = null;\n let cwd: string | null = null;\n\n const rl = readline.createInterface({\n input: createReadStream(filePath),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line) as RawEvent;\n if (event.timestamp) {\n if (!createdAt) createdAt = event.timestamp;\n lastMessageAt = event.timestamp;\n }\n if (!sessionId && event.sessionId) sessionId = event.sessionId;\n if ((event.type === \"user\" || event.type === \"assistant\") && !event.isSidechain) {\n messageCount++;\n }\n // Capture the first non-sidechain user message as a title fallback.\n if (\n !firstUserMessage &&\n event.type === \"user\" &&\n !event.isSidechain &&\n event.message?.content\n ) {\n firstUserMessage = extractTextContent(event.message.content);\n }\n if (event.type === \"ai-title\") {\n const aiTitle = (event as Record<string, unknown>).aiTitle ?? event.title;\n if (aiTitle) title = aiTitle as string;\n }\n if (!model && event.type === \"assistant\" && event.message?.model) {\n model = event.message.model;\n }\n if (!gitBranch && event.gitBranch) gitBranch = event.gitBranch as string;\n if (!cwd && (event as Record<string, unknown>).cwd) {\n cwd = (event as Record<string, unknown>).cwd as string;\n }\n } catch {\n /* skip */\n }\n }\n\n if (!title && sessionId) {\n const historyEntry = history.get(sessionId);\n if (historyEntry?.display) title = historyEntry.display;\n }\n\n // Last-resort title: first ~80 chars of the first user message, single-line.\n if (!title && firstUserMessage) {\n const trimmed = firstUserMessage.replace(/\\s+/g, \" \").trim();\n title = trimmed.length > 80 ? trimmed.slice(0, 77) + \"...\" : trimmed || null;\n }\n\n return { title, messageCount, createdAt, lastMessageAt, model, gitBranch, cwd };\n}\n\n// =============================================================================\n// Per-turn Usage Extraction\n// =============================================================================\n\nasync function extractTurnsFromFile(filePath: string): Promise<AgentTurnUsage[]> {\n const turns: AgentTurnUsage[] = [];\n let turnIndex = 0;\n let sessionModel: string | null = null;\n\n const rl = readline.createInterface({\n input: createReadStream(filePath),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line) as RawEvent;\n if (event.isSidechain) continue;\n if (event.type !== \"assistant\" || !event.message) continue;\n\n const model = event.message.model ?? sessionModel ?? \"unknown\";\n if (!sessionModel && event.message.model) sessionModel = event.message.model;\n\n const usage = event.message.usage;\n if (!usage) continue;\n const inputTokens = Number(usage.input_tokens ?? 0);\n const outputTokens = Number(usage.output_tokens ?? 0);\n const cacheRead = Number(usage.cache_read_input_tokens ?? 0);\n const cacheWrite = Number(usage.cache_creation_input_tokens ?? 0);\n if (inputTokens === 0 && outputTokens === 0 && cacheRead === 0 && cacheWrite === 0) continue;\n\n turns.push({\n turnIndex,\n model,\n inputTokens,\n outputTokens,\n cacheTokens: { read: cacheRead, write: cacheWrite },\n timestamp: event.timestamp ?? new Date().toISOString(),\n });\n turnIndex++;\n } catch {\n /* skip */\n }\n }\n\n return turns;\n}\n\n// =============================================================================\n// File Changes + Unified Patch Reconstruction\n// =============================================================================\n\nfunction countLines(s: string): number {\n if (!s) return 0;\n const parts = s.split(\"\\n\");\n if (parts.length > 0 && parts[parts.length - 1] === \"\") parts.pop();\n return parts.length;\n}\n\nfunction toPatchLines(prefix: \"+\" | \"-\", text: string): string {\n const lines = text.split(\"\\n\");\n if (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n return lines.map((l) => `${prefix}${l}`).join(\"\\n\");\n}\n\nasync function extractFileChangesFromFile(filePath: string): Promise<AgentFileChange[]> {\n const byFile = new Map<string, AgentFileChange>();\n let editCounter = 0;\n\n const rl = readline.createInterface({\n input: createReadStream(filePath),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line) as RawEvent;\n if (event.isSidechain) continue;\n if (event.type !== \"assistant\" || !event.message) continue;\n const blocks = event.message.content;\n if (!Array.isArray(blocks)) continue;\n\n const ts = event.timestamp ?? new Date().toISOString();\n for (const block of blocks) {\n const b = block as Record<string, unknown>;\n if (b.type !== \"tool_use\") continue;\n const name = b.name as string;\n const input = (b.input ?? {}) as Record<string, unknown>;\n const file = input.file_path as string | undefined;\n if (!file) continue;\n\n editCounter++;\n const existing = byFile.get(file) ?? {\n file,\n additions: 0,\n deletions: 0,\n patch: \"\",\n lastChangedAt: ts,\n };\n\n if (name === \"Edit\") {\n const oldStr = (input.old_string as string) ?? \"\";\n const newStr = (input.new_string as string) ?? \"\";\n existing.deletions += countLines(oldStr);\n existing.additions += countLines(newStr);\n const header = `@@ Edit ${editCounter} @@`;\n const body = [toPatchLines(\"-\", oldStr), toPatchLines(\"+\", newStr)]\n .filter(Boolean)\n .join(\"\\n\");\n existing.patch = existing.patch\n ? `${existing.patch}\\n${header}\\n${body}`\n : `${header}\\n${body}`;\n } else if (name === \"Write\") {\n const content = (input.content as string) ?? \"\";\n existing.additions += countLines(content);\n const header = `@@ Write ${editCounter} @@`;\n const body = toPatchLines(\"+\", content);\n existing.patch = existing.patch\n ? `${existing.patch}\\n${header}\\n${body}`\n : `${header}\\n${body}`;\n } else {\n continue;\n }\n\n existing.lastChangedAt = ts;\n byFile.set(file, existing);\n }\n } catch {\n /* skip */\n }\n }\n\n return Array.from(byFile.values());\n}\n\n// =============================================================================\n// Message Parsing (for readSession) — includes plan-mode artifact injection\n// =============================================================================\n\nfunction extractTextContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .filter((b: Record<string, unknown>) => b.type === \"text\")\n .map((b: Record<string, unknown>) => b.text as string)\n .join(\"\\n\");\n }\n return \"\";\n}\n\nfunction buildToolUi(\n toolName: string,\n input: Record<string, unknown>,\n output?: string,\n): { uri: string; title: string; data: unknown } | undefined {\n switch (toolName) {\n case \"Bash\":\n return {\n uri: \"ui://devenv/command\",\n title: (input.description as string) || (input.command as string) || \"Command\",\n data: { command: input.command, description: input.description, output },\n };\n case \"Edit\":\n return {\n uri: \"ui://devenv/diff\",\n title: (input.file_path as string) || \"Edit\",\n data: {\n filePath: input.file_path,\n oldString: input.old_string,\n newString: input.new_string,\n },\n };\n case \"Write\":\n return {\n uri: \"ui://devenv/file\",\n title: (input.file_path as string) || \"Write\",\n data: { filePath: input.file_path, content: input.content },\n };\n case \"Read\":\n return {\n uri: \"ui://devenv/file\",\n title: (input.file_path as string) || \"Read\",\n data: {\n filePath: input.file_path,\n content: output,\n startLine: ((input.offset as number) ?? 0) + 1,\n },\n };\n case \"Glob\":\n return {\n uri: \"ui://devenv/command\",\n title: `Find: ${input.pattern ?? \"\"}`,\n data: {\n command: `glob ${input.pattern ?? \"\"}${input.path ? ` in ${input.path}` : \"\"}`,\n output,\n },\n };\n case \"Grep\":\n return {\n uri: \"ui://devenv/command\",\n title: `Search: \"${input.pattern ?? \"\"}\"`,\n data: {\n command: `grep \"${input.pattern ?? \"\"}\"${input.path ? ` in ${input.path}` : \"\"}`,\n output,\n },\n };\n case \"ExitPlanMode\":\n return {\n uri: \"ui://agent/plan\",\n title: \"Plan\",\n data: { content: (input.plan as string) ?? \"\" },\n };\n case \"TodoWrite\":\n return {\n uri: \"ui://agent/todos\",\n title: \"Todos\",\n data: { todos: (input.todos as unknown[]) ?? [] },\n };\n case \"WebSearch\":\n return {\n uri: \"ui://agent/web-search\",\n title: (input.query as string) ?? \"Web search\",\n data: { title: (input.query as string) ?? \"\", items: [] },\n };\n case \"WebFetch\":\n return {\n uri: \"ui://agent/web-fetch\",\n title: (input.url as string) ?? \"Web fetch\",\n data: {\n title: (input.url as string) ?? \"\",\n url: input.url as string,\n prompt: input.prompt as string,\n },\n };\n case \"Agent\":\n return {\n uri: \"ui://agent/subagent\",\n title: (input.description as string) ?? \"Sub-agent\",\n data: {\n title: (input.description as string) ?? \"\",\n subagentType: input.subagent_type as string,\n name: input.name as string,\n model: input.model as string,\n },\n };\n default:\n return undefined;\n }\n}\n\nasync function parseMessages(filePath: string): Promise<ChatMessage[]> {\n const messages: ChatMessage[] = [];\n\n const rl = readline.createInterface({\n input: createReadStream(filePath),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line) as RawEvent;\n if (!event.type || !event.uuid) continue;\n if (event.isSidechain) continue;\n\n if (event.type === \"user\" && event.message) {\n const contentBlocks = event.message.content;\n\n if (Array.isArray(contentBlocks)) {\n for (const block of contentBlocks) {\n const b = block as Record<string, unknown>;\n if (b.type === \"tool_result\" && b.tool_use_id) {\n const toolUseId = b.tool_use_id as string;\n let toolMsgIdx = -1;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].metadata?.toolCall?.toolCallId === toolUseId) {\n toolMsgIdx = i;\n break;\n }\n }\n if (toolMsgIdx >= 0 && messages[toolMsgIdx].metadata?.toolCall) {\n const resultContent = extractTextContent(b.content);\n const msg = messages[toolMsgIdx];\n const meta = (msg.metadata = msg.metadata ?? {});\n meta.toolCall!.output = resultContent;\n const toolName = meta.toolCall!.toolName;\n const input = meta.toolCall!.input as Record<string, unknown> | undefined;\n meta.ui = buildToolUi(toolName, input ?? {}, resultContent);\n }\n }\n }\n }\n\n const textContent = extractTextContent(contentBlocks);\n if (textContent) {\n messages.push({\n id: event.uuid,\n role: \"user\",\n type: \"text\",\n content: textContent,\n createdAt: event.timestamp ?? new Date().toISOString(),\n });\n }\n } else if (event.type === \"assistant\" && event.message) {\n const contentBlocks = event.message.content;\n if (!Array.isArray(contentBlocks)) continue;\n\n for (const block of contentBlocks) {\n const b = block as Record<string, unknown>;\n\n if (b.type === \"thinking\" && b.thinking) {\n messages.push({\n id: `${event.uuid}-thinking`,\n role: \"assistant\",\n type: \"thinking\",\n content: b.thinking as string,\n createdAt: event.timestamp ?? new Date().toISOString(),\n metadata: { thinking: { status: \"complete\" } },\n });\n } else if (b.type === \"text\" && b.text) {\n messages.push({\n id: `${event.uuid}-text`,\n role: \"assistant\",\n type: \"text\",\n content: b.text as string,\n createdAt: event.timestamp ?? new Date().toISOString(),\n });\n } else if (b.type === \"tool_use\") {\n const toolName = b.name as string;\n const toolId = (b.id as string) ?? `${event.uuid}-tool`;\n const input = b.input as Record<string, unknown>;\n messages.push({\n id: toolId,\n role: \"assistant\",\n type: \"tool\",\n content: \"\",\n createdAt: event.timestamp ?? new Date().toISOString(),\n metadata: {\n toolCall: {\n toolName,\n toolCallId: toolId,\n status: \"completed\",\n input,\n },\n ui: buildToolUi(toolName, input),\n },\n });\n }\n }\n }\n } catch {\n /* skip */\n }\n }\n\n return messages;\n}\n\n// =============================================================================\n// File Tree Walker\n// =============================================================================\n\nconst TREE_SKIP_DIRS = new Set([\n \".git\",\n \"node_modules\",\n \".next\",\n \"dist\",\n \"build\",\n \".turbo\",\n \".cache\",\n \"coverage\",\n \".pnpm-store\",\n]);\n\nasync function walkDirectory(\n absPath: string,\n rootPath: string,\n depth: number,\n): Promise<AgentFileTreeNode[]> {\n if (depth > 6) return [];\n let entries: Array<{ name: string; isDirectory: boolean }>;\n try {\n const raw = await fs.readdir(absPath, { withFileTypes: true });\n entries = raw\n .map((e) => ({ name: e.name, isDirectory: e.isDirectory() }))\n .filter((e) => !e.name.startsWith(\".\"))\n .filter((e) => !TREE_SKIP_DIRS.has(e.name));\n } catch {\n return [];\n }\n entries.sort((a, b) => {\n if (a.isDirectory !== b.isDirectory) return a.isDirectory ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n const nodes: AgentFileTreeNode[] = [];\n for (const entry of entries) {\n const childAbs = path.join(absPath, entry.name);\n const relPath = path.relative(rootPath, childAbs);\n if (entry.isDirectory) {\n const children = await walkDirectory(childAbs, rootPath, depth + 1);\n nodes.push({ name: entry.name, path: relPath, type: \"directory\", children });\n } else {\n nodes.push({ name: entry.name, path: relPath, type: \"file\" });\n }\n }\n return nodes;\n}\n\n// =============================================================================\n// Cost — read pricing from this provider's own model registries\n// =============================================================================\n\n/** Look up a cost config in this provider's own registry. Falls back to\n * family (opus/sonnet/haiku) match for dated CC SDK variants. */\nfunction resolveModelCost(modelId: string): ModelCost | null {\n const all: Model[] = [...anthropicModels.list(), ...claudeCodeModels.list()];\n const exact = all.find((m) => m.id === modelId);\n if (exact) return exact.cost;\n const lower = modelId.toLowerCase();\n for (const family of [\"haiku\", \"sonnet\", \"opus\"]) {\n if (!lower.includes(family)) continue;\n const match = all.find((m) => m.id.toLowerCase().includes(family));\n if (match) return match.cost;\n }\n return null;\n}\n\nfunction computeCost(model: string, usage: Usage): number {\n const cost = resolveModelCost(model);\n if (!cost) return 0;\n const input = ((cost.inputTokens ?? 0) * (usage.inputTokens ?? 0)) / 1_000_000;\n const output = ((cost.outputTokens ?? 0) * (usage.outputTokens ?? 0)) / 1_000_000;\n const read = ((cost.cacheTokens?.read ?? 0) * (usage.cacheTokens?.read ?? 0)) / 1_000_000;\n const write = ((cost.cacheTokens?.write ?? 0) * (usage.cacheTokens?.write ?? 0)) / 1_000_000;\n return input + output + read + write;\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\nexport interface ClaudeCodeAgentConfig {\n /** Override the Claude home directory (defaults to ~/.claude). Useful for tests. */\n claudeDir?: string;\n /** Anthropic API key (falls back to ANTHROPIC_API_KEY). */\n apiKey?: string;\n /** Use Claude Code subscription (skips api-key auth). */\n useSubscription?: boolean;\n /** User id threaded into the Claude SDK for auth/observability. */\n userId?: string;\n /** Web-app origin used to resolve relative attachment URLs. */\n appUrl?: string;\n /** Default workdir used when `req.code?.workdir` is omitted. */\n defaultWorkspace?: string;\n}\n\n/**\n * Factory matching @jarvis/llm's `provider()` shape.\n * Usage: `const cc = claudeCodeAgent({ apiKey, userId, defaultWorkspace });`\n * Returns a `CodeAgentProvider` — runs, aborts, scans, and extracts.\n */\nexport function claudeCodeAgent(config: ClaudeCodeAgentConfig = {}): CodeAgentProvider {\n const activeRuns = new Map<string, AbortController>();\n\n return {\n id: \"claude-code\",\n name: \"Claude Code\",\n kind: \"local\",\n models: [...claudeCodeModels.list(), ...anthropicModels.list()].map((m) => m.id),\n\n async run<TState = unknown>(\n ctx: Context,\n req: RunAgentRequest<TState>,\n options: RunOptions = {},\n ): Promise<RunAgentResponse<TState>> {\n const runId = req.runId ?? crypto.randomUUID();\n const chatId = req.chatId ?? runId;\n\n const abortController = new AbortController();\n options.signal?.addEventListener(\"abort\", () => abortController.abort());\n activeRuns.set(runId, abortController);\n\n const progress = createClaudeCodeProgress({ runId, chatId, options });\n\n try {\n const wsPath = req.code?.workdir ?? config.defaultWorkspace ?? process.cwd();\n const systemMsg = req.messages.find((m) => m.role === \"system\");\n const turns = req.messages.filter((m) => m.role !== \"system\");\n\n if (req.attachments?.length && config.appUrl) {\n const preamble = await resolveAttachments(\n req.attachments,\n wsPath,\n config.appUrl,\n );\n if (preamble) {\n let lastUserIdx = -1;\n for (let i = turns.length - 1; i >= 0; i--) {\n if (turns[i].role === \"user\") {\n lastUserIdx = i;\n break;\n }\n }\n if (lastUserIdx >= 0) {\n const orig = turns[lastUserIdx];\n turns[lastUserIdx] = {\n ...orig,\n content: `${preamble}\\n\\n${orig.content ?? \"\"}`,\n };\n }\n }\n }\n\n logger.sys.info(\"[claude-code] Running\", {\n runId,\n modelId: req.modelId,\n workdir: wsPath,\n session: req.session,\n messageCount: req.messages.length,\n });\n\n const baseConfig = {\n ...(config.useSubscription\n ? { useSubscription: true }\n : { apiKey: config.apiKey }),\n workingDirectory: wsPath,\n tools: claudeCodeTools,\n ...(req.maxTurns ? { maxTurns: req.maxTurns } : {}),\n ...(config.userId ? { userId: config.userId } : {}),\n abortController,\n heartbeat: () => {},\n onProgress: progress.handleProgress,\n onUserInput: progress.handleUserInput,\n onPermissionResult: progress.handlePermissions,\n ...(req.disallowedTools?.length ? { disallowedTools: req.disallowedTools } : {}),\n ...(req.thinking ? { thinking: req.thinking } : {}),\n };\n\n const provider = claudeCodeProvider({\n ...baseConfig,\n systemPrompt: (systemMsg?.content as string) ?? \"\",\n permissionMode: toSdkPermissionMode(req.mode as AgentMode | undefined),\n ...(req.session ? { session: req.session } : {}),\n });\n\n // Fail loud — no resume-fallback retry. The workflow owns sessionId\n // and decides create-vs-resume based on `chat.metadata.sessionId`\n // and the workflow's `sessionStarted` flag, so a resume failure is\n // a real error worth surfacing rather than silently masking with\n // a fresh session.\n const response = await provider.query(ctx, {\n model: req.modelId ?? \"claude-sonnet-4-20250514\",\n messages: turns as Message[],\n });\n\n await progress.completeTools();\n\n const aborted = abortController.signal.aborted;\n logger.sys.info(\"[claude-code] Completed\", {\n runId,\n success: !response.error && !aborted,\n });\n\n return {\n message: response.content ?? \"\",\n success: !response.error && !aborted,\n cancelled: aborted,\n state: (req.state ?? ({} as TState)) as TState,\n metadata: { inputTokens: 0, outputTokens: 0, totalTokens: 0, iterations: 0 },\n ...(response.error\n ? { exit: { reason: \"error\" as const, message: response.error } }\n : {}),\n };\n } catch (err) {\n const aborted = abortController.signal.aborted;\n if (aborted) {\n logger.info(ctx, \"[claude-code] Interrupted\", { runId });\n return {\n message: \"\",\n success: false,\n cancelled: true,\n state: (req.state ?? ({} as TState)) as TState,\n metadata: { inputTokens: 0, outputTokens: 0, totalTokens: 0, iterations: 0 },\n exit: { reason: \"cancelled\", message: \"Interrupted\" },\n };\n }\n const message = err instanceof Error ? err.message : String(err);\n logger.error(ctx, \"[claude-code] Failed\", { runId, error: message });\n return {\n message: \"\",\n success: false,\n cancelled: false,\n state: (req.state ?? ({} as TState)) as TState,\n metadata: { inputTokens: 0, outputTokens: 0, totalTokens: 0, iterations: 0 },\n exit: { reason: \"error\", message },\n };\n } finally {\n activeRuns.delete(runId);\n }\n },\n\n async interrupt(_ctx: Context, req: InterruptAgentRequest): Promise<void> {\n const controller = activeRuns.get(req.runId);\n // Triggers the AbortController (web standard); the SDK throws out of\n // its loop, the runner publishes `agent.output { interrupted: true }`,\n // and the workflow renders a \"Stopped\" status row.\n if (controller) controller.abort();\n },\n\n async estimateCost(_ctx: Context, req: EstimateCostRequest): Promise<EstimateCostResponse> {\n return { costUsd: computeCost(req.model, req.usage) };\n },\n\n async scanChats(_ctx: Context, req: ScanChatsRequest): Promise<ScanChatsResponse> {\n const repoPaths = req.repoPaths ?? [];\n const history = await loadHistory();\n const chats: Chat[] = [];\n\n let projectDirs: Array<{ dir: string; repoPath: string }> = [];\n if (repoPaths.length > 0) {\n projectDirs = repoPaths.map((repoPath) => ({\n dir: path.join(getClaudeDir(), \"projects\", encodePath(repoPath)),\n repoPath,\n }));\n } else {\n try {\n const projectsRoot = path.join(getClaudeDir(), \"projects\");\n const allDirs = await fs.readdir(projectsRoot);\n projectDirs = allDirs\n .filter((d) => d.startsWith(\"-\"))\n .map((d) => ({ dir: path.join(projectsRoot, d), repoPath: d.replace(/-/g, \"/\") }));\n } catch {\n // ~/.claude/projects doesn't exist\n }\n }\n\n for (const { dir: projectDir, repoPath } of projectDirs) {\n try {\n const stat = await fs.stat(projectDir);\n if (!stat.isDirectory()) continue;\n const entries = await fs.readdir(projectDir);\n const jsonlFiles = entries.filter((f) => f.endsWith(\".jsonl\") && !f.startsWith(\".\"));\n for (const file of jsonlFiles) {\n const filePath = path.join(projectDir, file);\n const sessionId = path.basename(file, \".jsonl\");\n try {\n const meta = await extractRawMetadata(filePath, history);\n if (meta.messageCount === 0) continue;\n chats.push({\n id: sessionId,\n userId: \"\",\n title: meta.title,\n status: \"completed\",\n source: \"external\",\n provider: \"claude-code\",\n externalId: sessionId,\n taskId: null,\n model: meta.model,\n metadata: {\n filePath,\n cwd: meta.cwd ?? repoPath,\n gitBranch: meta.gitBranch,\n messageCount: meta.messageCount,\n // Imported chats already own their SDK session id (the\n // JSONL filename). Store it under the same key native\n // chats use so the workflow has a single source of truth.\n sessionId,\n },\n createdAt: meta.createdAt ?? new Date().toISOString(),\n updatedAt: meta.lastMessageAt ?? new Date().toISOString(),\n endedAt: null,\n });\n } catch {\n /* skip bad file */\n }\n }\n } catch {\n /* project dir missing */\n }\n }\n\n // Sort newest-first so pagination walks from now → backwards, and apply\n // the caller's time window + cursor + limit.\n chats.sort((a, b) => (b.updatedAt ?? \"\").localeCompare(a.updatedAt ?? \"\"));\n\n const before = req.before; // exclusive upper bound (walk further back from here)\n const after = req.after; // exclusive lower bound (stop once we reach the last sync)\n const filtered = chats.filter((c) => {\n if (before && c.updatedAt >= before) return false;\n if (after && c.updatedAt <= after) return false;\n return true;\n });\n\n // Cursor = index into the sorted list, encoded as a string.\n const startIdx = req.cursor ? Math.max(0, parseInt(req.cursor, 10) || 0) : 0;\n const limit = req.limit ?? filtered.length;\n const page = filtered.slice(startIdx, startIdx + limit);\n const nextCursor =\n startIdx + limit < filtered.length ? String(startIdx + limit) : undefined;\n\n return { chats: page, nextCursor };\n },\n\n async readChat(_ctx: Context, req: ReadChatRequest): Promise<ReadChatResponse> {\n if (!req.filePath) return { messages: [], total: 0, hasMore: false };\n const filePath = requireUnderProjectsDir(req.filePath);\n const offset = req.offset ?? 0;\n const limit = req.limit ?? 50;\n const all = await parseMessages(filePath);\n const total = all.length;\n // Paginate from end: offset 0 = most recent\n const end = total - offset;\n const start = Math.max(0, end - limit);\n const page = all.slice(start, end);\n return { messages: page, total, hasMore: offset + limit < total };\n },\n\n async extractChatMetadata(\n _ctx: Context,\n req: ExtractChatRequest,\n ): Promise<ExtractChatMetadataResponse> {\n if (!req.filePath) {\n return { chat: { id: req.chatId ?? \"\" } };\n }\n const filePath = requireUnderProjectsDir(req.filePath);\n const history = await loadHistory();\n const raw = await extractRawMetadata(filePath, history);\n return {\n chat: {\n id: req.chatId ?? path.basename(filePath, \".jsonl\"),\n title: raw.title,\n model: raw.model,\n provider: \"claude-code\",\n source: \"external\",\n metadata: {\n filePath,\n cwd: raw.cwd,\n gitBranch: raw.gitBranch,\n },\n createdAt: raw.createdAt ?? new Date().toISOString(),\n updatedAt: raw.lastMessageAt ?? raw.createdAt ?? new Date().toISOString(),\n },\n };\n },\n\n async extractMessages(\n _ctx: Context,\n req: ExtractChatRequest,\n ): Promise<ExtractMessagesResponse> {\n if (!req.filePath) return { turns: [] };\n const turns = await extractTurnsFromFile(requireUnderProjectsDir(req.filePath));\n return { turns };\n },\n\n async extractFileChanges(\n _ctx: Context,\n req: ExtractChatRequest,\n ): Promise<ExtractFileChangesResponse> {\n if (!req.filePath) return { fileChanges: [] };\n const fileChanges = await extractFileChangesFromFile(requireUnderProjectsDir(req.filePath));\n return { fileChanges };\n },\n\n async extractFileTree(\n _ctx: Context,\n req: ExtractFileTreeRequest,\n ): Promise<ExtractFileTreeResponse> {\n const cwd = req.cwd;\n if (!cwd) return { tree: [] };\n try {\n const stat = await fs.stat(cwd);\n if (!stat.isDirectory()) return { tree: [] };\n } catch {\n return { tree: [] };\n }\n const tree = await walkDirectory(cwd, cwd, 0);\n return { tree };\n },\n };\n}\n","/**\n * @jarvis/anthropic - Anthropic provider\n * Provides LLM (query, stream) capabilities using Claude models\n *\n * @example Default import\n * ```typescript\n * import anthropic from \"@jarvis/anthropic\";\n * const provider = anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });\n *\n * // LLM query\n * const response = await provider.query({\n * model: \"claude-sonnet-4-5-20250929\",\n * messages: [{ role: \"user\", content: \"Hello!\" }],\n * });\n * ```\n *\n * @example Named import\n * ```typescript\n * import { provider } from \"@jarvis/anthropic\";\n * const anthropic = provider({ apiKey: \"...\" });\n * ```\n */\n\n// Default export\nexport { provider as default } from \"./anthropic.llm.provider\";\n\n// Named export\nexport { provider } from \"./anthropic.llm.provider\";\n\n// Claude Code provider\nexport { claudeCodeProvider } from \"./claude-code.llm.provider\";\n\n// Claude Code agent provider (implements AgentProvider — scan/read/extract/cost)\nexport { claudeCodeAgent } from \"./claude-code.agent.provider\";\nexport type { ClaudeCodeAgentConfig } from \"./claude-code.agent.provider\";\n\n// Connector\n\n// Types\nexport type { Config, AnthropicProvider } from \"./anthropic.llm.provider\";\nexport type { ClaudeCodeConfig, ClaudeCodeMCPServer, ProviderTool } from \"./claude-code.types\";\nexport type { LLMProvider } from \"@jarvis/types\";\n","/**\n * Agent Config\n *\n * Manages ~/.jarvis/config.json — saved by `jarvis connect <token>`,\n * read on `jarvis start`.\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\nimport { fileURLToPath } from \"url\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface AgentConfig {\n /** Cloud WS API URL (from connect token) */\n apiUrl?: string;\n /** JWT auth token (from connect token) */\n token?: string;\n /** Long-lived refresh token for obtaining new access tokens */\n refreshToken?: string;\n /** User ID */\n userId: string;\n /** Environment ID */\n envId?: string;\n /** Workspace root path for repo operations */\n workspacePath?: string;\n /** Web app URL for browser-based auth */\n appUrl?: string;\n /** Anthropic API key (for local-only use without cloud) */\n anthropicApiKey?: string;\n /** Use Anthropic subscription instead of API key */\n useSubscription?: boolean;\n /** When the config was last updated */\n connectedAt?: string;\n}\n\nexport interface ConnectToken {\n apiUrl: string;\n jwt: string;\n refreshToken: string;\n userId: string;\n envId: string;\n}\n\n// =============================================================================\n// Paths\n// =============================================================================\n\n// =============================================================================\n// Environment (single source of truth)\n// =============================================================================\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/** Single source of truth for dev vs prod.\n * Reads env.json relative to the CLI package root.\n * Dev: apps/cli/env.json has { \"env\": \"development\" }\n * Prod: dist/env.json has { \"env\": \"production\" } (written by tsup build) */\nexport function isDev(): boolean {\n try {\n const envFile = path.join(__dirname, \"..\", \"env.json\");\n const data = JSON.parse(fs.readFileSync(envFile, \"utf-8\"));\n return data.env === \"development\";\n } catch {\n return false;\n }\n}\n\nconst PROD_APP_URL = \"https://jarvis.appchy.com\";\nconst DEV_APP_URL = \"http://localhost:3000\";\n\n/** App URL for the current environment. */\nexport function getDefaultAppUrl(): string {\n return isDev() ? (process.env.APP_URL || DEV_APP_URL) : PROD_APP_URL;\n}\n\n// =============================================================================\n// Config directory\n// =============================================================================\n\n/** Determine config directory.\n * - JARVIS_CONFIG_DIR env var takes priority (escape hatch for CI/testing)\n * - dev → ~/.jarvis/dev/\n * - prod → ~/.jarvis/ */\nfunction resolveConfigDir(): string {\n if (process.env.JARVIS_CONFIG_DIR) return process.env.JARVIS_CONFIG_DIR;\n const base = path.join(os.homedir(), \".jarvis\");\n return isDev() ? path.join(base, \"dev\") : base;\n}\n\nconst CONFIG_DIR = resolveConfigDir();\nconst CONFIG_FILE = path.join(CONFIG_DIR, \"config.json\");\n\n// =============================================================================\n// Operations\n// =============================================================================\n\nexport function loadConfig(): AgentConfig | null {\n try {\n const raw = fs.readFileSync(CONFIG_FILE, \"utf-8\");\n return JSON.parse(raw) as AgentConfig;\n } catch {\n return null;\n }\n}\n\nexport function saveConfig(config: AgentConfig): void {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\nexport function clearConfig(): void {\n try {\n fs.unlinkSync(CONFIG_FILE);\n } catch {}\n}\n\nexport function parseConnectToken(token: string): ConnectToken {\n try {\n const decoded = Buffer.from(token, \"base64\").toString(\"utf-8\");\n const parsed = JSON.parse(decoded);\n if (!parsed.apiUrl || !parsed.jwt || !parsed.userId) {\n throw new Error(\"Invalid token: missing required fields (apiUrl, jwt, userId)\");\n }\n return parsed as ConnectToken;\n } catch (err) {\n if (err instanceof SyntaxError) {\n throw new Error(\"Invalid token: not valid base64-encoded JSON\");\n }\n throw err;\n }\n}\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n","/**\n * Jarvis CLI — orchestrator.\n *\n * Each command lives in src/commands/<name>.ts and exports a `register(program)`\n * function that wires its `program.command(...).action(...)` block.\n *\n * The default (no-subcommand) action is the chat TUI; it must be registered\n * LAST so commander matches real subcommands first.\n */\n\nimport { Command } from \"commander\";\n\nimport * as connect from \"./commands/connect\";\nimport * as start from \"./commands/start\";\nimport * as stop from \"./commands/stop\";\nimport * as restart from \"./commands/restart\";\nimport * as logs from \"./commands/logs\";\nimport * as status from \"./commands/status\";\nimport * as install from \"./commands/install\";\nimport * as uninstall from \"./commands/uninstall\";\nimport * as logout from \"./commands/logout\";\nimport * as chat from \"./commands/chat\";\nimport { PKG_VERSION } from \"./version\";\n\nexport function createCli(): Command {\n const program = new Command()\n .name(\"jarvis\")\n .description(\"Jarvis local agent — runs Claude Code on your machine\")\n .version(PKG_VERSION);\n\n connect.register(program);\n start.register(program);\n stop.register(program);\n restart.register(program);\n logs.register(program);\n status.register(program);\n install.register(program);\n uninstall.register(program);\n logout.register(program);\n chat.register(program); // must be last (isDefault: true)\n\n return program;\n}\n","import type { Command } from \"commander\";\n\nimport { loadConfig, saveConfig, parseConnectToken, getConfigPath } from \"../config\";\n\nexport function register(program: Command): void {\n program\n .command(\"connect <token>\")\n .description(\"Connect to Jarvis cloud using a token from the web UI\")\n .option(\"-w, --workspace <path>\", \"Workspace root path for repo operations\")\n .action((token: string, opts: { workspace?: string }) => {\n try {\n const parsed = parseConnectToken(token);\n const existing = loadConfig();\n\n saveConfig({\n ...existing,\n apiUrl: parsed.apiUrl,\n token: parsed.jwt,\n refreshToken: parsed.refreshToken,\n userId: parsed.userId,\n envId: parsed.envId,\n ...(opts.workspace ? { workspacePath: opts.workspace } : {}),\n connectedAt: new Date().toISOString(),\n });\n\n console.log(`Connected to Jarvis cloud`);\n console.log(` User: ${parsed.userId}`);\n console.log(` Env: ${parsed.envId}`);\n console.log(` API: ${parsed.apiUrl}`);\n console.log(` Config: ${getConfigPath()}`);\n console.log();\n console.log(`Run 'jarvis start' to begin.`);\n } catch (err) {\n console.error(`Error: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n}\n","/**\n * Browser-based authentication.\n *\n * Flow: open the web app's /auth/cli page, the page POSTs the connect token\n * back to a transient localhost callback server we spin up here, we save it\n * to ~/.jarvis/config.json, and the runner picks it up on next launch.\n */\n\nimport { exec } from \"child_process\";\n\nimport {\n loadConfig,\n saveConfig,\n clearConfig,\n parseConnectToken,\n getDefaultAppUrl,\n} from \"./config\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface AwaitAuthCallbackRequest {\n port: number;\n /** Total wait time in ms before rejecting (default 2 minutes). */\n timeoutMs?: number;\n}\n\nexport interface AwaitAuthCallbackResponse {\n token: string;\n}\n\n// =============================================================================\n// Public\n// =============================================================================\n\n/** Resolve app URL for browser auth: stored config wins, else build-time default\n * (dev → localhost:3000, prod → jarvis.appchy.com). */\nexport function getAppUrl(): string {\n return loadConfig()?.appUrl ?? getDefaultAppUrl();\n}\n\n/** Find a free port for the auth-callback HTTP server. */\nexport async function findFreePort(): Promise<number> {\n const net = await import(\"net\");\n return new Promise((resolve, reject) => {\n const server = net.createServer();\n server.listen(0, \"127.0.0.1\", () => {\n const addr = server.address();\n const port = typeof addr === \"object\" && addr ? addr.port : 0;\n server.close(() => resolve(port));\n });\n server.on(\"error\", reject);\n });\n}\n\n/** Spin up a one-shot HTTP listener that resolves with the connect token\n * delivered to GET /callback?token=... by the web app. */\nexport async function awaitAuthCallback(\n req: AwaitAuthCallbackRequest,\n): Promise<AwaitAuthCallbackResponse> {\n const http = await import(\"http\");\n const timeoutMs = req.timeoutMs ?? 120_000;\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n server.close();\n reject(new Error(\"Browser authentication timed out (2 minutes)\"));\n }, timeoutMs);\n\n const server = http.createServer((httpReq, res) => {\n const url = new URL(httpReq.url ?? \"/\", `http://127.0.0.1:${req.port}`);\n\n if (url.pathname === \"/callback\") {\n const token = url.searchParams.get(\"token\");\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET\");\n\n if (token) {\n res.writeHead(200, { \"Content-Type\": \"text/plain\" });\n res.end(\"OK\");\n clearTimeout(timeout);\n server.close();\n resolve({ token });\n } else {\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\n res.end(\"Missing token\");\n }\n return;\n }\n\n res.writeHead(404);\n res.end();\n });\n\n server.listen(req.port, \"127.0.0.1\");\n });\n}\n\n/** Open the browser to the cloud's CLI auth page, wait for it to POST a\n * connect token back, and persist it to ~/.jarvis/config.json. */\nexport async function browserAuth(appUrl: string): Promise<boolean> {\n const config = loadConfig();\n const callbackPort = await findFreePort();\n const loginUrl = `${appUrl}/auth/cli?port=${callbackPort}`;\n\n console.log();\n console.log(\"Opening browser for sign in...\");\n console.log(` If it doesn't open, visit: ${loginUrl}`);\n console.log();\n\n const platform = process.platform;\n const openCmd = platform === \"darwin\" ? \"open\" : platform === \"win32\" ? \"start\" : \"xdg-open\";\n exec(`${openCmd} \"${loginUrl}\"`);\n\n console.log(\"Waiting for authentication...\");\n\n try {\n const { token } = await awaitAuthCallback({ port: callbackPort });\n const parsed = parseConnectToken(token);\n saveConfig({\n ...config,\n apiUrl: parsed.apiUrl,\n token: parsed.jwt,\n refreshToken: parsed.refreshToken,\n userId: parsed.userId,\n envId: parsed.envId,\n connectedAt: new Date().toISOString(),\n });\n console.log();\n console.log(`Signed in as ${parsed.userId}`);\n return true;\n } catch (err) {\n console.error(`Authentication failed: ${err instanceof Error ? err.message : err}`);\n return false;\n }\n}\n\n/** Ensure the agent has a usable config: API key / subscription mode skips\n * auth; otherwise re-auth via browser to guarantee a fresh token + correct\n * userId + WS URL. */\nexport async function ensureConfig(): Promise<boolean> {\n const config = loadConfig();\n if (config?.anthropicApiKey || config?.useSubscription) return true;\n\n clearConfig();\n return browserAuth(getAppUrl());\n}\n","/**\n * Resolve the CLI's own entry point so `start`/`install` can re-spawn it\n * (as a daemon child or via the OS service).\n *\n * Dev runs use `tsx src/bin.ts`; prod runs use the bundled `dist/bin.js`.\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\n\nimport { isDev } from \"./config\";\n\nexport interface ResolveEntryPointResponse {\n /** Node binary or tsx path used to execute the entry. */\n nodePath: string;\n /** Path to the CLI entry script (.ts in dev, .js in prod). */\n entryPath: string;\n}\n\nexport function resolveEntryPoint(): ResolveEntryPointResponse {\n const binPath = process.argv[1]!;\n const cliRoot = path.resolve(path.dirname(binPath), \"..\");\n const distEntry = path.join(cliRoot, \"dist\", \"bin.js\");\n const srcEntry = path.join(cliRoot, \"src\", \"bin.ts\");\n const useSrc = isDev() && fs.existsSync(srcEntry);\n const entryPath = useSrc ? srcEntry : fs.existsSync(distEntry) ? distEntry : binPath;\n const tsxBin = path.join(cliRoot, \"node_modules\", \".bin\", \"tsx\");\n const nodePath = useSrc && fs.existsSync(tsxBin) ? tsxBin : process.execPath;\n\n return { nodePath, entryPath };\n}\n","/**\n * Filesystem paths under ~/.jarvis (or ~/.jarvis/dev/ in dev mode).\n *\n * Single source of truth for log/pid file locations so commands and the\n * runner agree on where to read/write lifecycle artifacts.\n */\n\nimport path from \"path\";\nimport os from \"os\";\n\nimport { isDev } from \"./config\";\n\nexport function getLogDir(): string {\n return isDev()\n ? path.join(os.homedir(), \".jarvis\", \"dev\")\n : path.join(os.homedir(), \".jarvis\");\n}\n\nexport function getLogFile(): string {\n return path.join(getLogDir(), \"agent.log\");\n}\n\nexport function getPidFile(): string {\n return path.join(getLogDir(), \"agent.pid\");\n}\n","/**\n * Agent liveness — PID file at ~/.jarvis[/dev]/agent.pid.\n *\n * Replaces the old `isPortInUse` probe (which depended on the local 7862 WS).\n * The runner writes its PID on start and clears it on shutdown; CLI commands\n * read the file and verify the process is alive.\n */\n\nimport fs from \"fs\";\n\nimport { getLogDir, getPidFile } from \"./paths\";\n\nexport function writePid(pid: number = process.pid): void {\n fs.mkdirSync(getLogDir(), { recursive: true });\n fs.writeFileSync(getPidFile(), String(pid));\n}\n\nexport function readPid(): number | null {\n try {\n const pid = parseInt(fs.readFileSync(getPidFile(), \"utf-8\").trim(), 10);\n if (isNaN(pid)) return null;\n try {\n process.kill(pid, 0);\n return pid;\n } catch {\n fs.unlinkSync(getPidFile());\n return null;\n }\n } catch {\n return null;\n }\n}\n\nexport function clearPid(): void {\n try {\n fs.unlinkSync(getPidFile());\n } catch {}\n}\n\nexport function isAgentRunning(): boolean {\n return readPid() !== null;\n}\n","/**\n * Interactive setup helpers used by `jarvis start`.\n *\n * `promptWorkspace` asks the user for a workspace path (default = saved\n * config or cwd) and persists the answer.\n * `registerRepo` introspects the workspace's git remote and PATCHes the\n * repo→path mapping into the user's environment settings (best-effort).\n */\n\nimport { execSync } from \"child_process\";\nimport { createInterface } from \"readline\";\n\nimport { loadConfig, saveConfig, type AgentConfig } from \"./config\";\nimport { getAppUrl } from \"./auth\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface PromptWorkspaceRequest {\n /** Default path shown in the prompt. */\n defaultPath: string;\n}\n\nexport interface PromptWorkspaceResponse {\n workspacePath: string;\n}\n\n// =============================================================================\n// Public\n// =============================================================================\n\n/** Ask the user where their workspace lives. The user can hit Enter to accept\n * the default. The chosen path is persisted to config.workspacePath so the\n * next run pre-fills it. */\nexport async function promptWorkspace(\n req: PromptWorkspaceRequest,\n): Promise<PromptWorkspaceResponse> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer: string = await new Promise((resolve) => {\n rl.question(`Workspace path? [${req.defaultPath}] `, (input) => {\n resolve(input.trim());\n });\n });\n rl.close();\n\n const workspacePath = answer || req.defaultPath;\n const existing = loadConfig();\n if (existing) saveConfig({ ...existing, workspacePath });\n\n return { workspacePath };\n}\n\n/** Auto-register the workspace repo in environment settings.\n * Detects the git remote and PATCHes user preferences with the repo→path\n * mapping. Silent on failure — never blocks startup. */\nexport async function registerRepo(\n workspacePath: string,\n config: AgentConfig | null,\n): Promise<void> {\n try {\n const remoteUrl = execSync(\"git config --get remote.origin.url\", {\n cwd: workspacePath,\n encoding: \"utf-8\",\n timeout: 5000,\n }).trim();\n if (!remoteUrl) return;\n\n const parsed = parseGitRemote(remoteUrl);\n if (!parsed) return;\n\n const slug = `${parsed.owner}/${parsed.name}`;\n const appUrl = config?.appUrl ?? getAppUrl();\n const token = config?.token;\n if (!token) return;\n\n console.log(`Registering repo ${slug} → ${workspacePath}`);\n\n const envId = config?.envId ?? \"local\";\n const res = await fetch(`${appUrl}/api/v1/settings/preferences/repos?envId=${envId}`, {\n method: \"PATCH\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ [slug]: workspacePath }),\n });\n\n if (res.ok) {\n console.log(` Repo registered`);\n } else {\n const body = await res.text().catch(() => \"\");\n console.error(` Failed to register repo (${res.status}): ${body}`);\n }\n } catch (err) {\n console.error(` Failed to register repo: ${err instanceof Error ? err.message : err}`);\n }\n}\n\n// =============================================================================\n// Internals\n// =============================================================================\n\nfunction parseGitRemote(url: string): { owner: string; name: string } | null {\n const match = url.match(/[:\\/]([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n if (!match) return null;\n return { owner: match[1]!, name: match[2]! };\n}\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n return (byteToHex[arr[offset + 0]] +\n byteToHex[arr[offset + 1]] +\n byteToHex[arr[offset + 2]] +\n byteToHex[arr[offset + 3]] +\n '-' +\n byteToHex[arr[offset + 4]] +\n byteToHex[arr[offset + 5]] +\n '-' +\n byteToHex[arr[offset + 6]] +\n byteToHex[arr[offset + 7]] +\n '-' +\n byteToHex[arr[offset + 8]] +\n byteToHex[arr[offset + 9]] +\n '-' +\n byteToHex[arr[offset + 10]] +\n byteToHex[arr[offset + 11]] +\n byteToHex[arr[offset + 12]] +\n byteToHex[arr[offset + 13]] +\n byteToHex[arr[offset + 14]] +\n byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset);\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;\n","import { randomFillSync } from 'crypto';\nconst rnds8Pool = new Uint8Array(256);\nlet poolPtr = rnds8Pool.length;\nexport default function rng() {\n if (poolPtr > rnds8Pool.length - 16) {\n randomFillSync(rnds8Pool);\n poolPtr = 0;\n }\n return rnds8Pool.slice(poolPtr, (poolPtr += 16));\n}\n","import { randomUUID } from 'crypto';\nexport default { randomUUID };\n","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n options = options || {};\n const rnds = options.random ?? options.rng?.() ?? rng();\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16');\n }\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n if (buf) {\n offset = offset || 0;\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n }\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nexport default v4;\n","/**\n * JSON-RPC 2.0 runtime: envelope predicates/builders + a WS-backed RpcClient.\n *\n * Types live in `@jarvis/types/stream/rpc.types.ts`; this module only holds\n * runtime behavior so the type layer stays transport-agnostic.\n *\n * The client wraps a caller-supplied `send` function (so ws/mock/etc all\n * work) and:\n * 1. generates request ids\n * 2. writes JSON-RPC envelopes\n * 3. correlates inbound responses to pending calls\n * 4. fans inbound events out to topic subscribers\n */\n\nimport { v4 as uuid } from \"uuid\";\n\nimport type {\n Context,\n JsonRpcError,\n JsonRpcId,\n JsonRpcMessage,\n JsonRpcRequest,\n JsonRpcSuccess,\n RpcErrorData,\n RpcClient,\n} from \"@jarvis/types\";\nimport { JSON_RPC } from \"@jarvis/types\";\n\n/** Re-exported so ESM consumers (apps/cli, apps/ws) can get JSON-RPC error\n * codes via the transport package — `@jarvis/types` is CJS-by-default and\n * its named value exports aren't visible to pure-ESM importers. */\nexport { JSON_RPC };\n\n// =============================================================================\n// Envelope predicates\n// =============================================================================\n\n/**\n * Request predicate. A JSON-RPC request shape: `jsonrpc: \"2.0\"` + string\n * `method`. The `id` field may or may not be present — when present the\n * caller expects a response, when absent it's a fire-and-forget event.\n * Dispatch code can split on `\"id\" in frame` inline.\n */\nexport function isJsonRpcRequest(msg: unknown): msg is JsonRpcRequest {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n (msg as { jsonrpc?: unknown }).jsonrpc === \"2.0\" &&\n typeof (msg as { method?: unknown }).method === \"string\"\n );\n}\n\nexport function isJsonRpcSuccess(msg: unknown): msg is JsonRpcSuccess {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n (msg as { jsonrpc?: unknown }).jsonrpc === \"2.0\" &&\n \"id\" in msg &&\n \"result\" in msg\n );\n}\n\nexport function isJsonRpcError(msg: unknown): msg is JsonRpcError {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n (msg as { jsonrpc?: unknown }).jsonrpc === \"2.0\" &&\n \"error\" in msg\n );\n}\n\nexport function buildSuccess<TResult>(id: JsonRpcId, result: TResult): JsonRpcSuccess<TResult> {\n return { jsonrpc: \"2.0\", id, result };\n}\n\nexport function buildError(\n id: JsonRpcId | null,\n code: number,\n message: string,\n data?: unknown,\n): JsonRpcError {\n return { jsonrpc: \"2.0\", id, error: { code, message, ...(data !== undefined ? { data } : {}) } };\n}\n\n// =============================================================================\n// Error\n// =============================================================================\n\nexport class RpcError extends Error {\n constructor(\n public readonly code: number,\n message: string,\n public readonly data?: unknown,\n ) {\n super(message);\n this.name = \"RpcError\";\n }\n\n /** Domain `kind` from application-error `data.kind`, if present. */\n get kind(): string | undefined {\n if (this.data && typeof this.data === \"object\" && \"kind\" in (this.data as object)) {\n return (this.data as RpcErrorData).kind;\n }\n return undefined;\n }\n}\n\n// =============================================================================\n// Client\n// =============================================================================\n\nexport interface RpcClientConfig {\n /** Send a JSON-RPC message to the wire. Caller owns connection state. */\n send(frame: JsonRpcRequest): void;\n /** Default per-call timeout (ms). */\n defaultTimeoutMs?: number;\n}\n\ninterface PendingCall {\n resolve: (value: unknown) => void;\n reject: (err: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n abortListener?: () => void;\n signal?: AbortSignal;\n}\n\nexport interface JsonRpcClient extends RpcClient {\n /** Feed an inbound frame (from the underlying transport) to the client.\n * Matches responses by id and dispatches events to topic subscribers. */\n deliver(frame: unknown): void;\n /** Reject all pending calls (used when the transport closes). */\n failAll(reason: Error): void;\n}\n\nexport function rpcClient(config: RpcClientConfig): JsonRpcClient {\n const pending = new Map<string, PendingCall>();\n const topicSubscribers = new Map<string, Set<(payload: unknown) => void>>();\n const defaultTimeoutMs = config.defaultTimeoutMs ?? 30_000;\n\n function settle(id: string, fn: (entry: PendingCall) => void): void {\n const entry = pending.get(id);\n if (!entry) return;\n pending.delete(id);\n clearTimeout(entry.timer);\n if (entry.signal && entry.abortListener) {\n entry.signal.removeEventListener(\"abort\", entry.abortListener);\n }\n fn(entry);\n }\n\n return {\n call<TResp>(\n ctx: Context,\n req: { method: string; params?: unknown },\n options?: { timeoutMs?: number; signal?: AbortSignal },\n ): Promise<TResp> {\n const id = uuid();\n const timeoutMs = options?.timeoutMs ?? defaultTimeoutMs;\n\n return new Promise<TResp>((resolve, reject) => {\n const timer = setTimeout(() => {\n settle(id, (entry) =>\n entry.reject(new RpcError(JSON_RPC.INTERNAL_ERROR, `RPC timeout: ${req.method}`)),\n );\n }, timeoutMs);\n\n const entry: PendingCall = {\n resolve: (v) => resolve(v as TResp),\n reject,\n timer,\n signal: options?.signal,\n };\n\n if (options?.signal) {\n if (options.signal.aborted) {\n clearTimeout(timer);\n reject(new RpcError(JSON_RPC.INTERNAL_ERROR, \"aborted\"));\n return;\n }\n entry.abortListener = () => {\n settle(id, (e) => e.reject(new RpcError(JSON_RPC.INTERNAL_ERROR, \"aborted\")));\n };\n options.signal.addEventListener(\"abort\", entry.abortListener);\n }\n\n pending.set(id, entry);\n\n // ctx travels on the wire so the server can propagate caller\n // provenance end-to-end. Trust is enforced at the server boundary\n // via `requireContext(...)` — the client simply attaches what it\n // has, the server decides what to do with it.\n const frame: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id,\n method: req.method,\n ...(req.params !== undefined ? { params: req.params } : {}),\n ctx,\n };\n try {\n config.send(frame);\n } catch (err) {\n settle(id, (e) => e.reject(err instanceof Error ? err : new Error(String(err))));\n }\n });\n },\n\n subscribe<TPayload>(\n _ctx: Context,\n req: { topic: string },\n options: { onPayload: (payload: TPayload) => void },\n ): () => void {\n let subs = topicSubscribers.get(req.topic);\n if (!subs) {\n subs = new Set();\n topicSubscribers.set(req.topic, subs);\n }\n const wrapped = options.onPayload as (payload: unknown) => void;\n subs.add(wrapped);\n return () => {\n const bucket = topicSubscribers.get(req.topic);\n if (!bucket) return;\n bucket.delete(wrapped);\n if (bucket.size === 0) topicSubscribers.delete(req.topic);\n };\n },\n\n deliver(frame: unknown): void {\n if (isJsonRpcSuccess(frame)) {\n const success = frame as JsonRpcSuccess;\n settle(String(success.id), (e) => e.resolve(success.result));\n return;\n }\n if (isJsonRpcError(frame)) {\n const err = frame as JsonRpcError;\n if (err.id === null) return; // parse errors without correlation — swallow\n settle(String(err.id), (e) =>\n e.reject(new RpcError(err.error.code, err.error.message, err.error.data)),\n );\n return;\n }\n // Event — request frame with no `id`. Fan out to subscribers keyed\n // by method name.\n if (isJsonRpcRequest(frame) && !(\"id\" in frame)) {\n const subs = topicSubscribers.get(frame.method);\n if (!subs) return;\n for (const fn of subs) {\n try {\n fn(frame.params);\n } catch {\n /* listener errors shouldn't break delivery to peers */\n }\n }\n }\n },\n\n failAll(reason: Error): void {\n for (const id of Array.from(pending.keys())) {\n settle(id, (e) => e.reject(reason));\n }\n },\n };\n}\n\n// =============================================================================\n// Router\n// =============================================================================\n\nexport interface RpcRequestInfo {\n method: string;\n /** Present when the frame was a request (expects a response). Absent for\n * fire-and-forget events. */\n id?: JsonRpcId;\n signal?: AbortSignal;\n}\n\nexport type RpcValidator<TReq> = (params: unknown) => TReq;\nexport type RpcHandler<TReq = unknown, TResp = unknown> = (\n ctx: Context,\n req: TReq,\n info: RpcRequestInfo,\n) => Promise<TResp> | TResp;\n\nexport type RpcMiddleware = (ctx: Context, info: RpcRequestInfo) => Promise<void> | void;\n\ninterface RegisteredMethod {\n name: string;\n validate?: RpcValidator<unknown>;\n handler: RpcHandler;\n}\n\nexport interface RpcRouter {\n method<TReq, TResp>(\n name: string,\n validate: RpcValidator<TReq>,\n handler: RpcHandler<TReq, TResp>,\n ): void;\n method<TResp>(name: string, handler: RpcHandler<unknown, TResp>): void;\n use(fn: RpcMiddleware): void;\n dispatch(\n ctx: Context,\n frame: JsonRpcMessage,\n send: (frame: JsonRpcMessage) => void,\n ): Promise<void>;\n handleFrame(ctx: Context, raw: string, send: (frame: JsonRpcMessage) => void): Promise<void>;\n}\n\nexport function rpcRouter(): RpcRouter {\n const methods = new Map<string, RegisteredMethod>();\n const middleware: RpcMiddleware[] = [];\n\n async function invoke(\n ctx: Context,\n frame: JsonRpcRequest,\n send: (f: JsonRpcMessage) => void,\n ): Promise<void> {\n // Events (requests with no `id`) are fire-and-forget — the router still\n // runs the handler but swallows responses / errors.\n const isEvent = !(\"id\" in frame) || frame.id === undefined;\n const method = methods.get(frame.method);\n\n if (!method) {\n if (!isEvent) {\n send(\n buildError(\n frame.id as JsonRpcId,\n JSON_RPC.METHOD_NOT_FOUND,\n `Unknown method: ${frame.method}`,\n ),\n );\n }\n return;\n }\n\n const info: RpcRequestInfo = { method: frame.method, id: frame.id };\n\n let req: unknown = frame.params;\n if (method.validate) {\n try {\n req = method.validate(frame.params);\n } catch (err) {\n if (!isEvent) {\n send(\n buildError(\n frame.id as JsonRpcId,\n JSON_RPC.INVALID_PARAMS,\n err instanceof Error ? err.message : \"Invalid params\",\n ),\n );\n }\n return;\n }\n }\n\n try {\n for (const fn of middleware) {\n await fn(ctx, info);\n }\n const result = await method.handler(ctx, req, info);\n if (!isEvent) send(buildSuccess(frame.id as JsonRpcId, result));\n } catch (err) {\n if (err instanceof RpcError) {\n if (!isEvent) {\n send(buildError(frame.id as JsonRpcId, err.code, err.message, err.data));\n }\n return;\n }\n // Handlers should throw RpcError for domain errors. Anything else is a\n // bug — surface it to the caller as INTERNAL_ERROR and log to stderr.\n console.error(\"[rpc.router] handler threw\", {\n method: frame.method,\n requestId: frame.id === null ? undefined : String(frame.id),\n error: err instanceof Error ? err.message : String(err),\n });\n if (!isEvent) {\n send(\n buildError(\n frame.id as JsonRpcId,\n JSON_RPC.INTERNAL_ERROR,\n err instanceof Error ? err.message : \"Internal error\",\n ),\n );\n }\n }\n }\n\n function method(\n name: string,\n validateOrHandler: RpcValidator<unknown> | RpcHandler,\n handler?: RpcHandler,\n ): void {\n if (handler) {\n methods.set(name, {\n name,\n validate: validateOrHandler as RpcValidator<unknown>,\n handler,\n });\n } else {\n methods.set(name, { name, handler: validateOrHandler as RpcHandler });\n }\n }\n\n return {\n method: method as RpcRouter[\"method\"],\n\n use(fn) {\n middleware.push(fn);\n },\n\n async dispatch(ctx, frame, send) {\n if (isJsonRpcRequest(frame)) {\n await invoke(ctx, frame as JsonRpcRequest, send);\n }\n },\n\n async handleFrame(ctx, raw, send) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n send(buildError(null, JSON_RPC.PARSE_ERROR, \"Parse error\"));\n return;\n }\n if (Array.isArray(parsed)) {\n for (const item of parsed) {\n await this.dispatch(ctx, item as JsonRpcMessage, send);\n }\n return;\n }\n await this.dispatch(ctx, parsed as JsonRpcMessage, send);\n },\n };\n}\n\n// =============================================================================\n// Event helper (JSON-RPC request frame with no `id` — fire-and-forget).\n// Carries ctx so subscribers on the receiving end see the original caller's\n// provenance (userId, requestId, timestamp).\n// =============================================================================\n\nexport function buildEvent<TParams>(\n ctx: Context,\n channel: string,\n params?: TParams,\n): JsonRpcRequest<TParams> {\n return {\n jsonrpc: \"2.0\",\n method: channel,\n ...(params !== undefined ? { params } : {}),\n ctx,\n };\n}\n","/**\n * Agent Start\n *\n * Pure outbound runner: connects to the hub WS, executes work the hub\n * forwards (file/git/agent ops), and streams events back over the same\n * socket. No inbound listener.\n *\n * All traffic is JSON-RPC. Inbound frames go through `router.handleFrame`.\n * Streaming events are fanned out as JSON-RPC events (requests with no `id`)\n * via `publish(...)`, which writes to the upstream socket.\n */\n\nimport { buildEvent } from \"@jarvis/transport\";\nimport { logger } from \"@jarvis/logger\";\nimport type { Context } from \"@jarvis/types\";\n\nimport { initAgent } from \"./agent\";\nimport { getDefaultAppUrl } from \"./config\";\nimport { writePid, clearPid } from \"./pid\";\nimport { setPublisher } from \"./pubsub\";\nimport { router } from \"./rpc\";\nimport { createUpstreamClient, type UpstreamConfig } from \"./upstream\";\nimport { setWorkspacePath } from \"./workspace\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface StartAgentOptions {\n workspacePath: string;\n anthropicApiKey?: string;\n useSubscription?: boolean;\n userId: string;\n upstream: UpstreamConfig;\n}\n\n// =============================================================================\n// Start\n// =============================================================================\n\nexport interface AgentHandle {\n shutdown: () => Promise<void>;\n}\n\nexport async function startAgent(options: StartAgentOptions): Promise<AgentHandle> {\n setWorkspacePath(options.workspacePath);\n initAgent({\n anthropicApiKey: options.anthropicApiKey,\n useSubscription: options.useSubscription,\n userId: options.userId,\n appUrl: getDefaultAppUrl(),\n });\n\n const upstream = createUpstreamClient(options.upstream);\n\n // publish(ctx, channel, payload) — fan out a JSON-RPC event over upstream.\n // Hub's broadcast subscriber re-fans to every connected client of this user.\n //\n // The actual `ws.send` is deferred via `setImmediate` so Node's event loop\n // services its I/O queue (incoming WS frames!) between SDK-message pumps.\n // Without this, the SDK's stdout stream can saturate the event loop with\n // synchronous publish-then-send calls, starving an inbound `agent.interrupt`\n // frame for tens of seconds. `setImmediate` runs in the \"check\" phase AFTER\n // I/O callbacks, so an inbound frame fires `ws.on(\"message\")` BEFORE the\n // next deferred publish — the abort lands within the SDK's next chunk\n // boundary instead of after the whole stream finishes. Order is preserved\n // (FIFO across `setImmediate`).\n setPublisher((ctx, channel, payload) => {\n logger.info(ctx, \"[Agent] publish\", {\n channel,\n runId: (payload as { runId?: string } | undefined)?.runId,\n });\n const frame = buildEvent(ctx, channel, payload);\n setImmediate(() => upstream.sendFrame(frame));\n });\n\n function handleFrame(ctx: Context, raw: string, send: (frame: unknown) => void): void {\n router.handleFrame(ctx, raw, send).catch((err) => {\n logger.error(ctx, \"[Agent] router.handleFrame threw\", {\n error: err instanceof Error ? err.message : String(err),\n });\n });\n }\n\n upstream.onFrame(({ ctx, raw, send }) => handleFrame(ctx, raw, send));\n upstream.connect();\n\n writePid();\n\n console.log();\n console.log(`Jarvis Agent v0.0.0`);\n console.log(` Workspace: ${options.workspacePath}`);\n console.log(` User: ${options.userId}`);\n console.log(` Cloud: ${options.upstream.apiUrl}`);\n console.log();\n console.log(\"Waiting for tasks...\");\n console.log();\n\n const teardown = async (): Promise<void> => {\n upstream.close();\n clearPid();\n };\n\n const shutdown = () => {\n console.log(\"\\nShutting down...\");\n void teardown();\n process.exit(0);\n };\n\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n\n return { shutdown: teardown };\n}\n","/**\n * Agent singleton — thin wrapper around the `claudeCodeAgent` provider.\n *\n * `initAgent({...})` constructs the provider once with the user's credentials\n * and workspace root. `runTask` / `interruptTask` / `resolveUserInput` are\n * imported directly by the RPC controllers; the provider does all the Claude\n * SDK work, streaming events back through `options.onMessage` / `onToken` /\n * `onUsage` / `onUserInputRequest`, which we re-emit as `agent.*` JSON-RPC\n * events via the shared `publish(...)` channel.\n */\n\nimport crypto from \"crypto\";\n\nimport { claudeCodeAgent } from \"@jarvis/anthropic\";\nimport { logger } from \"@jarvis/logger\";\nimport type {\n CodeAgentProvider,\n Context,\n InterruptAgentRequest,\n PendingUserInput,\n RunAgentRequest,\n UserInputResponse,\n} from \"@jarvis/types\";\n\nimport { publish } from \"./pubsub\";\nimport { getWorkspacePath } from \"./workspace\";\n\n// =============================================================================\n// State\n// =============================================================================\n\nlet provider: CodeAgentProvider | null = null;\n\ninterface PendingInputEntry {\n resolve: (r: UserInputResponse) => void;\n runId: string;\n ctx: Context;\n}\n\nconst pendingInputs = new Map<string, PendingInputEntry>();\n\ninterface InitAgentConfig {\n anthropicApiKey?: string;\n useSubscription?: boolean;\n userId: string;\n /** Web app URL (resolves relative attachment URLs). */\n appUrl?: string;\n}\n\nexport function initAgent(c: InitAgentConfig): void {\n provider = claudeCodeAgent({\n apiKey: c.anthropicApiKey,\n useSubscription: c.useSubscription,\n userId: c.userId,\n appUrl: c.appUrl,\n defaultWorkspace: getWorkspacePath(),\n });\n}\n\nfunction requireProvider(): CodeAgentProvider {\n if (!provider) throw new Error(\"agent not initialized — call initAgent() at startup\");\n return provider;\n}\n\n// =============================================================================\n// User-input correlation — the provider awaits a Promise that we resolve\n// when the matching `agent.userInput` RPC arrives.\n// =============================================================================\n\nexport function resolveUserInput(req: {\n inputId: string;\n response: UserInputResponse;\n}): boolean {\n const entry = pendingInputs.get(req.inputId);\n if (!entry) return false;\n\n entry.resolve(req.response);\n pendingInputs.delete(req.inputId);\n\n // The SDK's `interrupt: true` field on a deny PermissionResult is\n // undocumented and empirically does NOT abort `query()` — the agent loop\n // keeps emitting messages and pivots around the deny. The official abort\n // path is `AbortController.abort()` via `provider.interrupt()`. Resolving\n // the permission promise above lets the SDK fire `onPermissionResult`\n // synchronously (so the gated tool's UI flips to `status: \"modify\"`);\n // calling `interruptTask` immediately after aborts the run so the\n // workflow's loop dequeues the queued feedback `sendMessage` and the\n // next `runTurn` resumes with the feedback as the user prompt.\n if (req.response.action === \"modify\") {\n void interruptTask(entry.ctx, { runId: entry.runId });\n }\n\n return true;\n}\n\nfunction onUserInputRequest(runId: string, ctx: Context) {\n return (input: PendingUserInput): Promise<UserInputResponse> =>\n new Promise((resolve) => {\n pendingInputs.set(input.id, { resolve, runId, ctx });\n publish(ctx, \"agent.onUserInputRequest\", { runId, input });\n });\n}\n\n// =============================================================================\n// Run / interrupt\n// =============================================================================\n\nexport async function runTask(ctx: Context, req: RunAgentRequest): Promise<void> {\n const runId = req.runId ?? crypto.randomUUID();\n const normalized: RunAgentRequest = { ...req, runId };\n\n publish(ctx, \"agent.status\", { status: \"busy\", runId });\n\n try {\n const result = await requireProvider().run(ctx, normalized, {\n onMessage: (message) => publish(ctx, \"agent.onMessage\", { runId, message }),\n onToken: (params) => publish(ctx, \"agent.onToken\", { runId, ...params }),\n onUsage: (params) => publish(ctx, \"agent.onUsage\", { runId, ...params }),\n onUserInputRequest: onUserInputRequest(runId, ctx),\n });\n\n publish(ctx, \"agent.output\", {\n runId,\n output: {\n success: result.success,\n content: result.message,\n error: result.exit?.message,\n interrupted: result.cancelled,\n ...(result.sessionId ? { sessionId: result.sessionId } : {}),\n },\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(ctx, \"[Agent] Run failed unexpectedly\", { runId, error: message });\n publish(ctx, \"agent.output\", {\n runId,\n output: { success: false, content: \"\", error: message },\n });\n } finally {\n publish(ctx, \"agent.status\", { status: \"idle\" });\n }\n}\n\nexport async function interruptTask(\n ctx: Context,\n req: InterruptAgentRequest,\n): Promise<void> {\n logger.info(ctx, \"[Agent] Interrupting run\", { runId: req.runId, reason: req.reason });\n await requireProvider().interrupt(ctx, req);\n}\n","/**\n * Event publishing singleton.\n *\n * `setPublisher(fn)` is called once at startup by `start.ts` to install the\n * transport (local server broadcast + upstream sendFrame). Every `agents.*`\n * streaming event flows through `publish(ctx, channel, payload)`.\n *\n * `channel` is the JSON-RPC method string (e.g. `agents.onMessage`) — the\n * same word used by the canonical `Publisher` in\n * `@jarvis/types/stream/pubsub.types.ts`. The wire frame is a\n * `JsonRpcRequest` with no `id` — a JSON-RPC event.\n */\n\nimport type { Context } from \"@jarvis/types\";\n\nexport type Publisher = (ctx: Context, channel: string, payload: unknown) => void;\n\nlet publisher: Publisher = () => {\n // No-op before startup wires one up; keeps early events from crashing but\n // surfaces the misconfiguration via logs if it persists.\n // eslint-disable-next-line no-console\n console.warn(\"[pubsub] publish called before setPublisher() — dropping event\");\n};\n\nexport function setPublisher(fn: Publisher): void {\n publisher = fn;\n}\n\nexport function publish(ctx: Context, channel: string, payload: unknown): void {\n publisher(ctx, channel, payload);\n}\n","/**\n * Workspace singleton — the root directory for file / git operations.\n *\n * Set once at agent start; read by RPC controllers. Throws if read before set\n * so a misconfigured process fails fast instead of silently searching the CWD.\n */\n\nlet workspacePath: string | null = null;\n\nexport function setWorkspacePath(path: string): void {\n workspacePath = path;\n}\n\nexport function getWorkspacePath(): string {\n if (!workspacePath) {\n throw new Error(\"workspace path not initialized — call setWorkspacePath() at startup\");\n }\n return workspacePath;\n}\n","/**\n * CLI agent RPC router singleton.\n *\n * Factory + types live in `@jarvis/transport`. Controllers in this directory\n * register methods on the shared `router` via `registerCliRpc(...)`.\n */\n\nexport { rpcRouter } from \"@jarvis/transport\";\nexport type {\n RpcHandler,\n RpcMiddleware,\n RpcRequestInfo,\n RpcRouter,\n RpcValidator,\n} from \"@jarvis/transport\";\n\nimport { rpcRouter, type RpcRouter } from \"@jarvis/transport\";\n\nexport const router: RpcRouter = rpcRouter();\n","/**\n * RPC controller: agent.*\n *\n * Thin adapter over the agent singleton in `../agent`.\n *\n * `agent.run` — fire a turn; streaming events come back as\n * `agent.onMessage` / `onToken` / `onUsage` /\n * `onUserInputRequest` / `output` / `status` events.\n * `agent.interrupt` — stop an in-flight turn (CC-style).\n * `agent.userInput` — resolve a pending user-input request.\n */\n\nimport { JSON_RPC, RpcError } from \"@jarvis/transport\";\nimport type {\n Context,\n InterruptAgentRequest,\n RunAgentRequest,\n UserInput,\n UserInputResponse,\n} from \"@jarvis/types\";\n\nimport { interruptTask, resolveUserInput, runTask } from \"../agent\";\nimport { router } from \"./router\";\n\n// =============================================================================\n// agent.run\n// =============================================================================\n\nfunction parseRun(params: unknown): RunAgentRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (!Array.isArray(p.messages)) throw new Error(\"messages required\");\n return p as unknown as RunAgentRequest;\n}\n\nasync function run(ctx: Context, req: RunAgentRequest): Promise<{ started: true }> {\n runTask(ctx, req).catch(() => {\n /* errors are surfaced via agent.output */\n });\n return { started: true };\n}\n\n// =============================================================================\n// agent.interrupt\n// =============================================================================\n\nfunction parseInterrupt(params: unknown): InterruptAgentRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.runId !== \"string\") throw new Error(\"runId required\");\n const out: InterruptAgentRequest = { runId: p.runId };\n if (p.reason !== undefined) {\n if (typeof p.reason !== \"string\") throw new Error(\"reason must be a string\");\n out.reason = p.reason;\n }\n return out;\n}\n\nasync function interrupt(\n ctx: Context,\n req: InterruptAgentRequest,\n): Promise<{ interrupted: true }> {\n interruptTask(ctx, req);\n return { interrupted: true };\n}\n\n// =============================================================================\n// agent.userInput\n// =============================================================================\n\nfunction parseUserInput(params: unknown): UserInput {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.id !== \"string\") throw new Error(\"id required\");\n if (typeof p.action !== \"string\") throw new Error(\"action required\");\n const out: UserInput = {\n id: p.id,\n action: p.action as UserInputResponse[\"action\"],\n };\n if (p.data !== undefined) out.data = p.data as Record<string, unknown>;\n if (p.feedback !== undefined) {\n if (typeof p.feedback !== \"string\") throw new Error(\"feedback must be a string\");\n out.feedback = p.feedback;\n }\n return out;\n}\n\nasync function userInput(\n _ctx: Context,\n req: UserInput,\n): Promise<{ received: true }> {\n const received = resolveUserInput({\n inputId: req.id,\n response: { action: req.action, data: req.data, feedback: req.feedback },\n });\n if (!received) {\n // No matching pending-input: stale UI, double-submit, or runner restart\n // dropped the in-memory map. Surface as a real error so the web client\n // can refetch state instead of silently waiting for an SDK promise that\n // will never resolve.\n throw new RpcError(JSON_RPC.APPLICATION_ERROR, \"input_id_unknown\", {\n kind: \"input_id_unknown\",\n inputId: req.id,\n });\n }\n return { received: true };\n}\n\n// =============================================================================\n// Register\n// =============================================================================\n\nrouter.method(\"agent.run\", parseRun, run);\nrouter.method(\"agent.interrupt\", parseInterrupt, interrupt);\nrouter.method(\"agent.userInput\", parseUserInput, userInput);\n","/**\n * Shared routing helpers for composed `AgentProvider` / `CodeAgentProvider`\n * factories. Keeps resolution + fan-out consistent across both tiers.\n */\n\nimport type { AgentProvider, AgentProviderId } from \"@jarvis/types\";\n\nexport interface CompositionConfig<TProvider extends AgentProvider> {\n providers: TProvider[];\n /** Provider used when `req.provider` is omitted. Falls back to `providers[0]`. */\n defaultProvider?: AgentProviderId;\n}\n\n/** Resolve the target provider for an atomic call:\n * 1. `req.provider` if registered\n * 2. `defaultProvider` if registered\n * 3. first registered provider (when there's only one, it's unambiguous)\n */\nexport function resolveProvider<TProvider extends AgentProvider>(\n config: CompositionConfig<TProvider>,\n providerId: AgentProviderId | undefined,\n): TProvider {\n const byId = new Map<AgentProviderId, TProvider>();\n for (const p of config.providers) byId.set(p.id, p);\n\n const picked = providerId ?? config.defaultProvider;\n if (picked && byId.has(picked)) return byId.get(picked)!;\n if (!picked && config.providers.length >= 1) return config.providers[0];\n throw new Error(\n `No agent provider registered for \"${picked ?? \"<unspecified>\"}\". Available: ${[...byId.keys()].join(\", \")}`,\n );\n}\n\n/** Fan a method out across every provider that implements it, swallowing\n * per-provider failures and returning the successful subset. Used by\n * `scanChats` / `listChats` when no explicit provider is picked. */\nexport async function fanOut<TProvider extends AgentProvider, TResult>(\n providers: TProvider[],\n invoke: (provider: TProvider) => Promise<TResult> | undefined,\n fallback: TResult,\n): Promise<TResult[]> {\n const calls = providers.map((p) => {\n const maybe = invoke(p);\n if (!maybe) return Promise.resolve(fallback);\n return maybe.catch(() => fallback);\n });\n return Promise.all(calls);\n}\n\n/** Union of model ids across providers — composed provider advertises every\n * model its constituents accept. */\nexport function unionModels<TProvider extends AgentProvider>(\n providers: TProvider[],\n): string[] {\n return Array.from(new Set(providers.flatMap((p) => p.models)));\n}\n","/**\n * Composed `AgentProvider` — routes by `req.provider` / `defaultProvider`\n * across registered atomic providers. Fan-out discovery; single-target run.\n */\n\nimport type {\n InterruptAgentRequest,\n InterruptOptions,\n AgentProvider,\n AgentProviderId,\n Context,\n EstimateCostRequest,\n EstimateCostResponse,\n ExtractChatMetadataResponse,\n ExtractChatRequest,\n ExtractMessagesResponse,\n ListChatsRequest,\n ListChatsResponse,\n ReadChatRequest,\n RunAgentRequest,\n RunAgentResponse,\n ReadChatResponse,\n RunOptions,\n ScanChatsRequest,\n ScanChatsResponse,\n StartChatRequest,\n StartChatResponse,\n StopChatRequest,\n StopChatResponse,\n} from \"@jarvis/types\";\n\nimport { fanOut, resolveProvider, unionModels, type CompositionConfig } from \"./routing\";\n\nexport type AgentsConfig = CompositionConfig<AgentProvider>;\n\nexport function agents(config: AgentsConfig): AgentProvider {\n const { providers } = config;\n if (!providers || providers.length === 0) {\n throw new Error(\"At least one agent provider is required\");\n }\n\n const resolve = (id?: AgentProviderId) => resolveProvider(config, id);\n\n return {\n id: \"multi\",\n name: \"multi-agent\",\n kind: \"cloud\" as const,\n models: unionModels(providers),\n\n run<TState = unknown>(\n ctx: Context,\n req: RunAgentRequest<TState>,\n options?: RunOptions,\n ): Promise<RunAgentResponse<TState>> {\n return resolve(req.provider as AgentProviderId | undefined).run(ctx, req, options);\n },\n\n async interrupt(\n ctx: Context,\n req: InterruptAgentRequest,\n options?: InterruptOptions,\n ): Promise<void> {\n // runId isn't keyed by provider on the wire — fan out and swallow misses.\n await Promise.all(\n providers.map((p) => p.interrupt(ctx, req, options).catch(() => undefined)),\n );\n },\n\n estimateCost(ctx: Context, req: EstimateCostRequest): Promise<EstimateCostResponse> {\n return resolve(req.provider).estimateCost(ctx, req);\n },\n\n async listChats(\n ctx: Context,\n req: ListChatsRequest,\n options?: Record<string, unknown>,\n ): Promise<ListChatsResponse> {\n if (req.provider) {\n const target = resolve(req.provider);\n return target.listChats ? target.listChats(ctx, req, options) : { chats: [] };\n }\n const results = await fanOut<AgentProvider, ListChatsResponse>(\n providers,\n (p) => p.listChats?.(ctx, req, options),\n { chats: [] },\n );\n return { chats: results.flatMap((r) => r.chats) };\n },\n\n async scanChats(\n ctx: Context,\n req: ScanChatsRequest,\n options?: Record<string, unknown>,\n ): Promise<ScanChatsResponse> {\n if (req.provider) {\n const target = resolve(req.provider);\n return target.scanChats ? target.scanChats(ctx, req, options) : { chats: [] };\n }\n const results = await fanOut<AgentProvider, ScanChatsResponse>(\n providers,\n (p) => p.scanChats?.(ctx, req, options),\n { chats: [] },\n );\n return { chats: results.flatMap((r) => r.chats) };\n },\n\n readChat(\n ctx: Context,\n req: ReadChatRequest,\n options?: Record<string, unknown>,\n ): Promise<ReadChatResponse> {\n const target = resolve(req.provider);\n return target.readChat\n ? target.readChat(ctx, req, options)\n : Promise.resolve({ messages: [], total: 0, hasMore: false });\n },\n\n extractMessages(\n ctx: Context,\n req: ExtractChatRequest,\n ): Promise<ExtractMessagesResponse> {\n const target = resolve(req.provider);\n return target.extractMessages\n ? target.extractMessages(ctx, req)\n : Promise.resolve({ turns: [] });\n },\n\n extractChatMetadata(\n ctx: Context,\n req: ExtractChatRequest,\n ): Promise<ExtractChatMetadataResponse> {\n const target = resolve(req.provider);\n return target.extractChatMetadata\n ? target.extractChatMetadata(ctx, req)\n : Promise.resolve({ chat: { id: req.chatId ?? req.filePath ?? \"\" } });\n },\n\n startChat(\n ctx: Context,\n req: StartChatRequest,\n options?: Record<string, unknown>,\n ): Promise<StartChatResponse> {\n const target = resolve(req.provider);\n if (!target.startChat) {\n throw new Error(`Provider \"${target.id}\" does not support startChat`);\n }\n return target.startChat(ctx, req, options);\n },\n\n stopChat(\n ctx: Context,\n req: StopChatRequest,\n options?: Record<string, unknown>,\n ): Promise<StopChatResponse> {\n const target = resolve(req.provider);\n if (!target.stopChat) return Promise.resolve({ stopped: false });\n return target.stopChat(ctx, req, options);\n },\n };\n}\n\n/** @deprecated Use `agents(config)` — keeps the old name alive during migration. */\nexport const provider = agents;\n","/**\n * Composed `CodeAgentProvider` — like `agents()` but every constituent is\n * code-capable (extractFileChanges / extractFileTree). Callers that need the\n * narrower type use this factory; everything else uses `agents()`.\n */\n\nimport type {\n AgentProviderId,\n CodeAgentProvider,\n Context,\n ExtractChatRequest,\n ExtractFileChangesResponse,\n ExtractFileTreeRequest,\n ExtractFileTreeResponse,\n} from \"@jarvis/types\";\n\nimport { agents } from \"./agents.provider\";\nimport { resolveProvider, type CompositionConfig } from \"./routing\";\n\nexport type CodeAgentsConfig = CompositionConfig<CodeAgentProvider>;\n\nexport function codeAgents(config: CodeAgentsConfig): CodeAgentProvider {\n const { providers } = config;\n if (!providers || providers.length === 0) {\n throw new Error(\"At least one code agent provider is required\");\n }\n\n // Build the base composed AgentProvider, then layer the code methods on top.\n const base = agents(config);\n\n const resolve = (id?: AgentProviderId) => resolveProvider(config, id);\n\n return {\n ...base,\n\n extractFileChanges(\n ctx: Context,\n req: ExtractChatRequest,\n ): Promise<ExtractFileChangesResponse> {\n return resolve(req.provider).extractFileChanges(ctx, req);\n },\n\n extractFileTree(\n ctx: Context,\n req: ExtractFileTreeRequest,\n ): Promise<ExtractFileTreeResponse> {\n return resolve(req.provider).extractFileTree(ctx, req);\n },\n };\n}\n","/**\n * Chat providers used by the RPC layer.\n *\n * `agents()` covers the base methods (scan / read / extractMessages /\n * extractChatMetadata); `codeAgents()` adds the code surfaces\n * (extractFileChanges / extractFileTree).\n */\n\nimport { agents, codeAgents } from \"@jarvis/agents\";\nimport { claudeCodeAgent } from \"@jarvis/anthropic\";\n\nconst claudeCode = claudeCodeAgent();\n\nexport const agentProvider = agents({ providers: [claudeCode] });\nexport const codeAgentProvider = codeAgents({ providers: [claudeCode] });\n","/**\n * RPC controller: chats.*\n *\n * Thin adapter over the shared chat providers in `../chats`.\n */\n\nimport type {\n AgentProviderId,\n Context,\n ExtractChatMetadataResponse,\n ExtractFileChangesResponse,\n ExtractFileTreeResponse,\n ExtractMessagesResponse,\n ReadChatResponse,\n ScanChatsResponse,\n} from \"@jarvis/types\";\n\nimport { agentProvider, codeAgentProvider } from \"../chats\";\nimport { router } from \"./router\";\n\n// =============================================================================\n// chats.scan\n// =============================================================================\n\ninterface ScanRequest {\n provider?: AgentProviderId;\n repoPaths?: string[];\n cursor?: string;\n limit?: number;\n before?: string;\n after?: string;\n}\n\nfunction parseScan(params: unknown): ScanRequest {\n if (params === undefined || params === null) return {};\n if (typeof params !== \"object\") throw new Error(\"params must be an object\");\n const p = params as Record<string, unknown>;\n const out: ScanRequest = {};\n if (p.provider !== undefined) {\n if (typeof p.provider !== \"string\") throw new Error(\"provider must be a string\");\n out.provider = p.provider as AgentProviderId;\n }\n if (p.repoPaths !== undefined) {\n if (!Array.isArray(p.repoPaths)) throw new Error(\"repoPaths must be an array\");\n out.repoPaths = p.repoPaths.map((x) => String(x));\n }\n if (p.cursor !== undefined) {\n if (typeof p.cursor !== \"string\") throw new Error(\"cursor must be a string\");\n out.cursor = p.cursor;\n }\n if (p.limit !== undefined) {\n if (typeof p.limit !== \"number\" || !Number.isFinite(p.limit)) {\n throw new Error(\"limit must be a number\");\n }\n out.limit = Math.min(500, Math.max(1, Math.floor(p.limit)));\n }\n if (p.before !== undefined) {\n if (typeof p.before !== \"string\") throw new Error(\"before must be a string\");\n out.before = p.before;\n }\n if (p.after !== undefined) {\n if (typeof p.after !== \"string\") throw new Error(\"after must be a string\");\n out.after = p.after;\n }\n return out;\n}\n\nasync function scan(ctx: Context, req: ScanRequest): Promise<ScanChatsResponse> {\n if (!agentProvider.scanChats) return { chats: [] };\n return agentProvider.scanChats(ctx, req);\n}\n\n// =============================================================================\n// chats.read\n// =============================================================================\n\ninterface ReadRequest {\n provider: AgentProviderId;\n chatId?: string;\n filePath?: string;\n offset?: number;\n limit?: number;\n}\n\nfunction parseRead(params: unknown): ReadRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.provider !== \"string\") throw new Error(\"provider required\");\n const out: ReadRequest = { provider: p.provider as AgentProviderId };\n if (p.chatId !== undefined) {\n if (typeof p.chatId !== \"string\") throw new Error(\"chatId must be a string\");\n out.chatId = p.chatId;\n }\n if (p.filePath !== undefined) {\n if (typeof p.filePath !== \"string\") throw new Error(\"filePath must be a string\");\n out.filePath = p.filePath;\n }\n if (p.offset !== undefined) {\n if (typeof p.offset !== \"number\") throw new Error(\"offset must be a number\");\n out.offset = Math.max(0, Math.floor(p.offset));\n }\n if (p.limit !== undefined) {\n if (typeof p.limit !== \"number\") throw new Error(\"limit must be a number\");\n out.limit = Math.min(500, Math.max(1, Math.floor(p.limit)));\n }\n return out;\n}\n\nasync function read(ctx: Context, req: ReadRequest): Promise<ReadChatResponse> {\n if (!agentProvider.readChat) return { messages: [], total: 0, hasMore: false };\n return agentProvider.readChat(ctx, req);\n}\n\n// =============================================================================\n// chats.extractMetadata / chats.extractFileChanges / chats.extractFileTree\n// =============================================================================\n\ninterface ExtractRequest {\n provider: AgentProviderId;\n chatId?: string;\n filePath?: string;\n}\n\nfunction parseExtract(params: unknown): ExtractRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.provider !== \"string\") throw new Error(\"provider required\");\n const out: ExtractRequest = { provider: p.provider as AgentProviderId };\n if (p.chatId !== undefined) {\n if (typeof p.chatId !== \"string\") throw new Error(\"chatId must be a string\");\n out.chatId = p.chatId;\n }\n if (p.filePath !== undefined) {\n if (typeof p.filePath !== \"string\") throw new Error(\"filePath must be a string\");\n out.filePath = p.filePath;\n }\n return out;\n}\n\nasync function extractMetadata(\n ctx: Context,\n req: ExtractRequest,\n): Promise<ExtractChatMetadataResponse> {\n if (!agentProvider.extractChatMetadata) {\n return { chat: { id: req.chatId ?? req.filePath ?? \"\" } };\n }\n return agentProvider.extractChatMetadata(ctx, req);\n}\n\nasync function extractFileChanges(\n ctx: Context,\n req: ExtractRequest,\n): Promise<ExtractFileChangesResponse> {\n return codeAgentProvider.extractFileChanges(ctx, req);\n}\n\ninterface ExtractTreeRequest extends ExtractRequest {\n cwd?: string;\n}\n\nfunction parseExtractTree(params: unknown): ExtractTreeRequest {\n const base = parseExtract(params);\n const p = (params ?? {}) as Record<string, unknown>;\n if (p.cwd !== undefined) {\n if (typeof p.cwd !== \"string\") throw new Error(\"cwd must be a string\");\n return { ...base, cwd: p.cwd };\n }\n return base;\n}\n\nasync function extractFileTree(\n ctx: Context,\n req: ExtractTreeRequest,\n): Promise<ExtractFileTreeResponse> {\n return codeAgentProvider.extractFileTree(ctx, req);\n}\n\nasync function extractMessages(\n ctx: Context,\n req: ExtractRequest,\n): Promise<ExtractMessagesResponse> {\n if (!agentProvider.extractMessages) return { turns: [] };\n return agentProvider.extractMessages(ctx, req);\n}\n\n// =============================================================================\n// Register\n// =============================================================================\n\nrouter.method(\"chats.scan\", parseScan, scan);\nrouter.method(\"chats.read\", parseRead, read);\nrouter.method(\"chats.extractMetadata\", parseExtract, extractMetadata);\nrouter.method(\"chats.extractFileChanges\", parseExtract, extractFileChanges);\nrouter.method(\"chats.extractFileTree\", parseExtractTree, extractFileTree);\nrouter.method(\"chats.extractMessages\", parseExtract, extractMessages);\n","/**\n * File operations — search, tree walk, content read.\n *\n * Pure functions. No WS plumbing. Callers (RPC controllers, CLI harness)\n * invoke them directly and do their own framing.\n */\n\nimport { execFile } from \"child_process\";\nimport { promisify } from \"util\";\nimport path from \"path\";\nimport fs from \"fs/promises\";\n\nimport type { AgentFileTreeNode } from \"@jarvis/types\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface FileSearchResult {\n path: string;\n name: string;\n type: \"file\" | \"directory\";\n}\n\nconst MAX_SEARCH_RESULTS = 50;\n\n/** Search workspace for files/dirs matching `query`. gitignore-aware via\n * `git ls-files`; falls back to fs scan when git is unavailable. */\nexport async function searchFiles(\n workspacePath: string,\n query: string,\n): Promise<FileSearchResult[]> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"ls-files\", \"--cached\", \"--others\", \"--exclude-standard\"],\n { cwd: workspacePath, maxBuffer: 1024 * 1024 },\n );\n const allFiles = stdout.split(\"\\n\").filter(Boolean);\n\n const dirSet = new Set<string>();\n for (const f of allFiles) {\n const parts = f.split(\"/\");\n for (let i = 1; i < parts.length; i++) dirSet.add(parts.slice(0, i).join(\"/\"));\n }\n\n const allEntries: FileSearchResult[] = [\n ...[...dirSet].map((d) => ({\n path: d,\n name: path.basename(d),\n type: \"directory\" as const,\n })),\n ...allFiles.map((f) => ({ path: f, name: path.basename(f), type: \"file\" as const })),\n ];\n\n if (!query.trim()) {\n const sorted = [...allEntries].sort((a, b) => {\n const depthA = a.path.split(\"/\").length;\n const depthB = b.path.split(\"/\").length;\n if (depthA !== depthB) return depthA - depthB;\n if (a.type !== b.type) return a.type === \"directory\" ? -1 : 1;\n return a.path.localeCompare(b.path);\n });\n return sorted.slice(0, MAX_SEARCH_RESULTS);\n }\n\n const q = query.toLowerCase();\n return allEntries\n .filter((e) => e.path.toLowerCase().includes(q))\n .sort((a, b) => {\n const aExact = a.name.toLowerCase() === q ? 0 : 1;\n const bExact = b.name.toLowerCase() === q ? 0 : 1;\n if (aExact !== bExact) return aExact - bExact;\n if (a.type !== b.type) return a.type === \"directory\" ? -1 : 1;\n return a.path.localeCompare(b.path);\n })\n .slice(0, MAX_SEARCH_RESULTS);\n } catch {\n return fallbackSearch(workspacePath, query);\n }\n}\n\nasync function fallbackSearch(\n workspacePath: string,\n query: string,\n): Promise<FileSearchResult[]> {\n const results: FileSearchResult[] = [];\n const q = query.toLowerCase();\n\n async function walk(dir: string, depth: number): Promise<void> {\n if (depth > 4 || results.length >= MAX_SEARCH_RESULTS) return;\n try {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (results.length >= MAX_SEARCH_RESULTS) break;\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n const rel = path.relative(workspacePath, path.join(dir, entry.name));\n if (rel.toLowerCase().includes(q)) {\n results.push({\n path: rel,\n name: entry.name,\n type: entry.isDirectory() ? \"directory\" : \"file\",\n });\n }\n if (entry.isDirectory()) await walk(path.join(dir, entry.name), depth + 1);\n }\n } catch {\n /* unreadable — skip */\n }\n }\n\n await walk(workspacePath, 0);\n return results;\n}\n\n// =============================================================================\n// Tree walk + file read\n// =============================================================================\n\nconst TREE_SKIP_DIRS = new Set([\n \".git\",\n \"node_modules\",\n \".next\",\n \"dist\",\n \"build\",\n \".turbo\",\n \".cache\",\n \"coverage\",\n \".pnpm-store\",\n \"out\",\n]);\n\nconst MAX_TREE_DEPTH = 6;\nconst MAX_FILE_BYTES = 512 * 1024;\n\nexport interface ReadFileResult {\n path: string;\n content: string | null;\n size?: number;\n tooLarge?: boolean;\n}\n\nexport class FileReadError extends Error {\n constructor(\n message: string,\n public readonly kind: \"path_outside_worktree\" | \"not_a_file\",\n ) {\n super(message);\n this.name = \"FileReadError\";\n }\n}\n\nexport async function readFileTree(\n workdir: string,\n): Promise<{ tree: AgentFileTreeNode[]; root: string | null }> {\n const stat = await fs.stat(workdir);\n if (!stat.isDirectory()) return { tree: [], root: null };\n const tree = await walkTree(workdir, workdir, 0);\n return { tree, root: workdir };\n}\n\nasync function walkTree(\n absPath: string,\n rootPath: string,\n depth: number,\n): Promise<AgentFileTreeNode[]> {\n if (depth > MAX_TREE_DEPTH) return [];\n let entries: Array<{ name: string; isDirectory: boolean }>;\n try {\n const raw = await fs.readdir(absPath, { withFileTypes: true });\n entries = raw\n .map((e) => ({ name: e.name, isDirectory: e.isDirectory() }))\n .filter((e) => !e.name.startsWith(\".\"))\n .filter((e) => !TREE_SKIP_DIRS.has(e.name));\n } catch {\n return [];\n }\n entries.sort((a, b) => {\n if (a.isDirectory !== b.isDirectory) return a.isDirectory ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n const nodes: AgentFileTreeNode[] = [];\n for (const entry of entries) {\n const childAbs = path.join(absPath, entry.name);\n const rel = path.relative(rootPath, childAbs);\n if (entry.isDirectory) {\n const children = await walkTree(childAbs, rootPath, depth + 1);\n nodes.push({ name: entry.name, path: rel, type: \"directory\", children });\n } else {\n nodes.push({ name: entry.name, path: rel, type: \"file\" });\n }\n }\n return nodes;\n}\n\nexport async function readFileContent(\n workdir: string,\n relPath: string,\n): Promise<ReadFileResult> {\n const absPath = path.resolve(workdir, relPath);\n const resolvedRoot = path.resolve(workdir);\n if (!absPath.startsWith(resolvedRoot + path.sep) && absPath !== resolvedRoot) {\n throw new FileReadError(\"path_outside_workdir\", \"path_outside_worktree\"); // kind kept for wire compat\n }\n const stat = await fs.stat(absPath);\n if (!stat.isFile()) {\n throw new FileReadError(\"not_a_file\", \"not_a_file\");\n }\n if (stat.size > MAX_FILE_BYTES) {\n return { path: relPath, content: null, size: stat.size, tooLarge: true };\n }\n const content = await fs.readFile(absPath, \"utf-8\");\n return { path: relPath, content, size: stat.size };\n}\n","/**\n * RPC controller: files.*\n *\n * Thin adapter: validate params, delegate to `../files`.\n */\n\nimport { JSON_RPC, RpcError } from \"@jarvis/transport\";\nimport type { AgentFileTreeNode, Context } from \"@jarvis/types\";\n\nimport {\n FileReadError,\n type FileSearchResult,\n type ReadFileResult,\n readFileContent,\n readFileTree,\n searchFiles,\n} from \"../files\";\nimport { getWorkspacePath } from \"../workspace\";\nimport { router } from \"./router\";\n\n// =============================================================================\n// files.search\n// =============================================================================\n\ninterface SearchRequest {\n query: string;\n}\n\nfunction parseSearch(params: unknown): SearchRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n return { query: typeof p.query === \"string\" ? p.query : \"\" };\n}\n\nasync function search(\n _ctx: Context,\n req: SearchRequest,\n): Promise<{ files: FileSearchResult[] }> {\n return { files: await searchFiles(getWorkspacePath(), req.query) };\n}\n\n// =============================================================================\n// files.tree\n// =============================================================================\n\ninterface TreeRequest {\n workdir: string;\n}\n\nfunction parseTree(params: unknown): TreeRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.workdir !== \"string\") throw new Error(\"workdir required\");\n return { workdir: p.workdir };\n}\n\nasync function tree(\n _ctx: Context,\n req: TreeRequest,\n): Promise<{ tree: AgentFileTreeNode[]; root: string | null }> {\n return readFileTree(req.workdir);\n}\n\n// =============================================================================\n// files.read\n// =============================================================================\n\ninterface ReadRequest {\n workdir: string;\n path: string;\n}\n\nfunction parseReadFile(params: unknown): ReadRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.workdir !== \"string\") throw new Error(\"workdir required\");\n if (typeof p.path !== \"string\") throw new Error(\"path required\");\n return { workdir: p.workdir, path: p.path };\n}\n\nasync function readFile(_ctx: Context, req: ReadRequest): Promise<ReadFileResult> {\n try {\n return await readFileContent(req.workdir, req.path);\n } catch (err) {\n if (err instanceof FileReadError) {\n throw new RpcError(JSON_RPC.INVALID_PARAMS, err.kind, { kind: err.kind });\n }\n throw err;\n }\n}\n\n// =============================================================================\n// Register\n// =============================================================================\n\nrouter.method(\"files.search\", parseSearch, search);\nrouter.method(\"files.tree\", parseTree, tree);\nrouter.method(\"files.read\", parseReadFile, readFile);\n","/**\n * Git operations — pure functions over the user's workspace.\n *\n * Callers (RPC controllers, tests) invoke directly and frame results\n * themselves. No WS plumbing in this file.\n */\n\nimport { exec as execCb } from \"child_process\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { promisify } from \"util\";\n\nimport { createWorktree, listWorktrees } from \"@jarvis/agent\";\n\nconst exec = promisify(execCb);\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nasync function hasGitDir(dir: string): Promise<boolean> {\n return fs\n .access(path.join(dir, \".git\"))\n .then(() => true)\n .catch(() => false);\n}\n\nasync function fetchAndCheckout(repoDir: string, branch: string): Promise<void> {\n await exec(\"git fetch origin\", { cwd: repoDir, timeout: 120000 });\n try {\n await exec(`git checkout \"${branch}\"`, { cwd: repoDir });\n } catch {\n await exec(`git checkout -b \"${branch}\" \"origin/${branch}\"`, { cwd: repoDir });\n }\n await exec(\"git pull --ff-only\", { cwd: repoDir }).catch(() => {});\n}\n\n// =============================================================================\n// resolveRepo\n// =============================================================================\n\nexport interface ResolveRepoRequest {\n owner: string;\n name: string;\n branch: string;\n /** Explicit local path override from user preferences (checked first). */\n repoPath?: string;\n}\n\nexport async function resolveRepo(\n workspacePath: string,\n req: ResolveRepoRequest,\n): Promise<{ repoPath: string }> {\n if (req.repoPath && (await hasGitDir(req.repoPath))) {\n await fetchAndCheckout(req.repoPath, req.branch);\n return { repoPath: req.repoPath };\n }\n const byName = path.join(workspacePath, req.name);\n if (await hasGitDir(byName)) {\n await fetchAndCheckout(byName, req.branch);\n return { repoPath: byName };\n }\n const byOwnerName = path.join(workspacePath, req.owner, req.name);\n if (await hasGitDir(byOwnerName)) {\n await fetchAndCheckout(byOwnerName, req.branch);\n return { repoPath: byOwnerName };\n }\n await fs.mkdir(path.join(workspacePath, req.owner), { recursive: true });\n const cloneUrl = `git@github.com:${req.owner}/${req.name}.git`;\n await exec(`git clone \"${cloneUrl}\" \"${byOwnerName}\"`, { timeout: 300000 });\n await fetchAndCheckout(byOwnerName, req.branch);\n return { repoPath: byOwnerName };\n}\n\n// =============================================================================\n// commit\n// =============================================================================\n\nexport interface CommitResponse {\n success: boolean;\n output: string;\n error?: string;\n}\n\nexport async function commitWorktree(\n workdir: string,\n title: string,\n): Promise<CommitResponse> {\n try {\n await exec(\"git add -A\", { cwd: workdir });\n const { stdout: status } = await exec(\"git status --porcelain\", { cwd: workdir });\n if (!status.trim()) return { success: true, output: \"Nothing to commit\" };\n const safeTitle = title.replace(/\"/g, '\\\\\"');\n const { stdout } = await exec(`git commit -m \"jarvis: ${safeTitle}\"`, { cwd: workdir });\n return { success: true, output: stdout };\n } catch (err) {\n return {\n success: false,\n output: \"\",\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n// =============================================================================\n// pushBranch\n// =============================================================================\n\nexport interface PushBranchResponse {\n success: boolean;\n output: string;\n error?: string;\n}\n\n/** Push the current branch to `origin`. Optionally commit any uncommitted\n * changes first (matches `git commit -m \"jarvis: <title>\"` semantics from\n * `commitWorktree`). Used from the PR creation flow before opening the PR\n * on GitHub. Returns success+output rather than throwing so the caller\n * can surface a clean error to the UI without unwinding through transport. */\nexport async function pushBranch(\n workdir: string,\n branchName: string,\n options?: { commitTitle?: string },\n): Promise<PushBranchResponse> {\n try {\n if (options?.commitTitle) {\n // Match commitWorktree's behavior — best-effort, ignore \"nothing to commit\".\n const { stdout: status } = await exec(\"git status --porcelain\", { cwd: workdir });\n if (status.trim()) {\n await exec(\"git add -A\", { cwd: workdir });\n const safeTitle = options.commitTitle.replace(/\"/g, '\\\\\"');\n await exec(`git commit -m \"jarvis: ${safeTitle}\"`, { cwd: workdir });\n }\n }\n const { stdout } = await exec(`git push -u origin \"${branchName}\"`, {\n cwd: workdir,\n timeout: 120000,\n });\n return { success: true, output: stdout };\n } catch (err) {\n return {\n success: false,\n output: \"\",\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n// =============================================================================\n// browseDir — native macOS folder picker\n// =============================================================================\n\nexport async function browseDir(): Promise<{ path: string }> {\n const { stdout } = await exec(\n `osascript -e 'set theFolder to POSIX path of (choose folder with prompt \"Select worktree directory\")' -e 'return theFolder'`,\n { timeout: 60000 },\n );\n return { path: stdout.trim() };\n}\n\n// =============================================================================\n// Re-exports from @jarvis/agent for consistent callsites\n// =============================================================================\n\nexport { createWorktree, listWorktrees };\n","/**\n * RPC controller: git.*\n *\n * Thin adapter: validate params, delegate to `../git`.\n */\n\nimport type { Context } from \"@jarvis/types\";\n\nimport {\n browseDir,\n type CommitResponse,\n commitWorktree,\n createWorktree,\n listWorktrees,\n pushBranch,\n type PushBranchResponse,\n resolveRepo,\n} from \"../git\";\nimport { getWorkspacePath } from \"../workspace\";\nimport { router } from \"./router\";\n\n// =============================================================================\n// git.resolveRepo\n// =============================================================================\n\ninterface ResolveRepoRequest {\n owner: string;\n name: string;\n branch: string;\n repoPath?: string;\n}\n\nfunction parseResolveRepo(params: unknown): ResolveRepoRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.owner !== \"string\") throw new Error(\"owner required\");\n if (typeof p.name !== \"string\") throw new Error(\"name required\");\n if (typeof p.branch !== \"string\") throw new Error(\"branch required\");\n const out: ResolveRepoRequest = { owner: p.owner, name: p.name, branch: p.branch };\n if (p.repoPath !== undefined) {\n if (typeof p.repoPath !== \"string\") throw new Error(\"repoPath must be a string\");\n out.repoPath = p.repoPath;\n }\n return out;\n}\n\nasync function resolveRepoHandler(\n _ctx: Context,\n req: ResolveRepoRequest,\n): Promise<{ repoPath: string }> {\n return resolveRepo(getWorkspacePath(), req);\n}\n\n// =============================================================================\n// git.createWorktree\n// =============================================================================\n\ninterface CreateWorktreeRequest {\n repoPath: string;\n taskId: string;\n branch?: string;\n}\n\nfunction parseCreateWorktree(params: unknown): CreateWorktreeRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.repoPath !== \"string\") throw new Error(\"repoPath required\");\n if (typeof p.taskId !== \"string\") throw new Error(\"taskId required\");\n const out: CreateWorktreeRequest = { repoPath: p.repoPath, taskId: p.taskId };\n if (p.branch !== undefined) {\n if (typeof p.branch !== \"string\") throw new Error(\"branch must be a string\");\n out.branch = p.branch;\n }\n return out;\n}\n\nasync function createWorktreeHandler(_ctx: Context, req: CreateWorktreeRequest): Promise<unknown> {\n return createWorktree(req);\n}\n\n// =============================================================================\n// git.commit\n// =============================================================================\n\ninterface CommitRequest {\n title: string;\n workdir: string;\n}\n\nfunction parseCommit(params: unknown): CommitRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.title !== \"string\") throw new Error(\"title required\");\n if (typeof p.workdir !== \"string\") throw new Error(\"workdir required\");\n return { title: p.title, workdir: p.workdir };\n}\n\nasync function commitHandler(_ctx: Context, req: CommitRequest): Promise<CommitResponse> {\n return commitWorktree(req.workdir, req.title);\n}\n\n// =============================================================================\n// git.push\n// =============================================================================\n\ninterface PushBranchRequest {\n workdir: string;\n branchName: string;\n /** When set, commit any uncommitted changes with this title before pushing.\n * Mirrors `commitWorktree`'s \"jarvis: <title>\" message convention. */\n commitTitle?: string;\n}\n\nfunction parsePush(params: unknown): PushBranchRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.workdir !== \"string\") throw new Error(\"workdir required\");\n if (typeof p.branchName !== \"string\") throw new Error(\"branchName required\");\n const out: PushBranchRequest = { workdir: p.workdir, branchName: p.branchName };\n if (p.commitTitle !== undefined) {\n if (typeof p.commitTitle !== \"string\") throw new Error(\"commitTitle must be a string\");\n out.commitTitle = p.commitTitle;\n }\n return out;\n}\n\nasync function pushHandler(_ctx: Context, req: PushBranchRequest): Promise<PushBranchResponse> {\n return pushBranch(req.workdir, req.branchName, {\n ...(req.commitTitle ? { commitTitle: req.commitTitle } : {}),\n });\n}\n\n// =============================================================================\n// git.listWorktrees\n// =============================================================================\n\ninterface ListWorktreesRequest {\n repoPath: string;\n}\n\nfunction parseListWorktrees(params: unknown): ListWorktreesRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.repoPath !== \"string\") throw new Error(\"repoPath required\");\n return { repoPath: p.repoPath };\n}\n\nasync function listWorktreesHandler(_ctx: Context, req: ListWorktreesRequest): Promise<unknown> {\n return listWorktrees(req);\n}\n\n// =============================================================================\n// git.browseDir\n// =============================================================================\n\nasync function browseDirHandler(_ctx: Context): Promise<{ path: string }> {\n return browseDir();\n}\n\n// =============================================================================\n// Register\n// =============================================================================\n\nrouter.method(\"git.resolveRepo\", parseResolveRepo, resolveRepoHandler);\nrouter.method(\"git.createWorktree\", parseCreateWorktree, createWorktreeHandler);\nrouter.method(\"git.commit\", parseCommit, commitHandler);\nrouter.method(\"git.push\", parsePush, pushHandler);\nrouter.method(\"git.listWorktrees\", parseListWorktrees, listWorktreesHandler);\nrouter.method(\"git.browseDir\", browseDirHandler);\n","/**\n * Workdir-scan operations — read the live state of a task's workdir and\n * produce diffs + file tree.\n *\n * Works for both worktree mode (with `baselineRef` capturing the fork point)\n * and direct mode (no baseline; falls back to `git diff HEAD` showing\n * uncommitted edits).\n *\n * Pure functions over the user's filesystem; RPC controllers in `rpc/workdir.ts`\n * frame results for transport.\n */\n\nimport { exec as execCb } from \"child_process\";\nimport { promisify } from \"util\";\n\nimport type { FileDiff, TaskDiff } from \"@jarvis/types\";\n\nimport { readFileTree } from \"./files\";\n\nconst exec = promisify(execCb);\n\n/** Per-file patch cap. Larger patches truncate with a marker. */\nconst PATCH_CAP_BYTES = 200 * 1024;\n\nexport interface ScanRequest {\n workdir: string;\n /** Optional. When set: diff against this fork-point sha (worktree mode).\n * When omitted: diff against `HEAD` to surface uncommitted edits\n * (direct mode). */\n baselineRef?: string;\n}\n\nexport interface ScanResponse {\n diffs: TaskDiff;\n files: Awaited<ReturnType<typeof readFileTree>>;\n}\n\ninterface NumstatRow {\n additions: number;\n deletions: number;\n file: string;\n binary: boolean;\n}\n\n/** Parse `git diff --numstat <ref>` output. Binary files appear as \"- - file\". */\nfunction parseNumstat(stdout: string): NumstatRow[] {\n const rows: NumstatRow[] = [];\n for (const line of stdout.split(\"\\n\")) {\n if (!line.trim()) continue;\n const [add, del, ...rest] = line.split(\"\\t\");\n const file = rest.join(\"\\t\");\n if (!file) continue;\n const binary = add === \"-\" && del === \"-\";\n rows.push({\n additions: binary ? 0 : Number(add) || 0,\n deletions: binary ? 0 : Number(del) || 0,\n file,\n binary,\n });\n }\n return rows;\n}\n\n/** Shell-escape a path for inclusion after `--` in a git command. */\nfunction shellQuote(p: string): string {\n return `'${p.replace(/'/g, \"'\\\\''\")}'`;\n}\n\nasync function unifiedPatchFor(\n workdir: string,\n ref: string,\n file: string,\n): Promise<string> {\n try {\n const { stdout } = await exec(\n `git diff --no-color --unified=3 ${ref} -- ${shellQuote(file)}`,\n { cwd: workdir, maxBuffer: PATCH_CAP_BYTES * 2 },\n );\n if (stdout.length > PATCH_CAP_BYTES) {\n return stdout.slice(0, PATCH_CAP_BYTES) + \"\\n@@ truncated @@\\n\";\n }\n return stdout;\n } catch {\n return \"\";\n }\n}\n\n/**\n * Scan a task's workdir. Returns:\n * - `diffs`: per-file unified patches + aggregate add/del counts. Binary\n * files are flagged with a placeholder patch and 0/0 counts.\n * - `files`: the workdir's file tree (same shape as `files.tree` RPC).\n *\n * Diff target:\n * - Worktree mode (baselineRef set) → cumulative session delta against the\n * captured fork-point sha.\n * - Direct mode (no baselineRef) → uncommitted edits against `HEAD`.\n *\n * Failures inside individual `git diff` calls are absorbed (file gets an\n * empty patch); top-level failures propagate so the caller can surface them.\n */\nexport async function scanWorkdir(req: ScanRequest): Promise<ScanResponse> {\n const { workdir } = req;\n const ref = req.baselineRef && req.baselineRef.trim() ? req.baselineRef : \"HEAD\";\n\n let numstat = \"\";\n try {\n const { stdout } = await exec(`git diff --numstat ${ref}`, {\n cwd: workdir,\n maxBuffer: 4 * 1024 * 1024,\n });\n numstat = stdout;\n } catch {\n // Not a git dir, or ref doesn't exist — return empty diffs + file tree.\n numstat = \"\";\n }\n\n const rows = parseNumstat(numstat);\n const files: FileDiff[] = [];\n let additions = 0;\n let deletions = 0;\n const now = new Date().toISOString();\n\n for (const row of rows) {\n const patch = row.binary\n ? \"Binary files differ\"\n : await unifiedPatchFor(workdir, ref, row.file);\n files.push({\n file: row.file,\n additions: row.additions,\n deletions: row.deletions,\n patch,\n lastChangedAt: now,\n });\n additions += row.additions;\n deletions += row.deletions;\n }\n\n const tree = await readFileTree(workdir);\n\n return {\n diffs: { files, additions, deletions },\n files: tree,\n };\n}\n","/**\n * RPC controller: workdir.*\n *\n * Thin adapter: validate params, delegate to `../workdir`.\n */\n\nimport type { Context } from \"@jarvis/types\";\n\nimport { scanWorkdir, type ScanRequest, type ScanResponse } from \"../workdir\";\nimport { router } from \"./router\";\n\n// =============================================================================\n// workdir.scan\n// =============================================================================\n\nfunction parseScan(params: unknown): ScanRequest {\n if (!params || typeof params !== \"object\") throw new Error(\"params required\");\n const p = params as Record<string, unknown>;\n if (typeof p.workdir !== \"string\") throw new Error(\"workdir required\");\n const out: ScanRequest = { workdir: p.workdir };\n if (p.baselineRef !== undefined) {\n if (typeof p.baselineRef !== \"string\") throw new Error(\"baselineRef must be a string\");\n out.baselineRef = p.baselineRef;\n }\n return out;\n}\n\nasync function scanHandler(_ctx: Context, req: ScanRequest): Promise<ScanResponse> {\n return scanWorkdir(req);\n}\n\n// =============================================================================\n// Register\n// =============================================================================\n\nrouter.method(\"workdir.scan\", parseScan, scanHandler);\n","/**\n * Upstream WS Client\n *\n * Connects to the cloud hub so web/mobile can dispatch tasks and receive\n * progress. All traffic is JSON-RPC: inbound requests/notifications are\n * routed by `start.ts`; outbound responses and streaming notifications are\n * written raw.\n */\n\nimport WebSocket from \"ws\";\n\nimport { logger } from \"@jarvis/logger\";\nimport type { Context } from \"@jarvis/types\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface UpstreamConfig {\n apiUrl: string;\n token: string;\n refreshToken?: string;\n /** HTTP base URL for refresh (derived from apiUrl if not set) */\n refreshUrl?: string;\n /** Called when auth fails after all retries — return a new token, or null to give up. */\n onAuthExhausted?: () => Promise<{ token: string; refreshToken?: string } | null>;\n}\n\nexport interface UpstreamFrameContext {\n ctx: Context;\n raw: string;\n send: (frame: unknown) => void;\n}\n\n// =============================================================================\n// Client\n// =============================================================================\n\nexport function createUpstreamClient(config: UpstreamConfig) {\n let ws: WebSocket | null = null;\n let frameHandler: ((frame: UpstreamFrameContext) => void) | null = null;\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let refreshTimer: ReturnType<typeof setTimeout> | null = null;\n let closed = false;\n let authFailures = 0;\n let retries = 0;\n let currentToken = config.token;\n const MAX_AUTH_RETRIES = 3;\n const MAX_RETRIES = 3;\n const REFRESH_BUFFER_MS = 5 * 60 * 1000;\n\n function getRefreshUrl(): string | null {\n if (config.refreshUrl) return config.refreshUrl;\n if (!config.refreshToken) return null;\n return config.apiUrl.replace(/^wss:/, \"https:\").replace(/^ws:/, \"http:\") + \"/refresh\";\n }\n\n function getTokenExpiry(token: string): number | null {\n try {\n const parts = token.split(\".\");\n if (parts.length === 5) return Math.floor(Date.now() / 1000) + 3600;\n const [, body] = parts;\n if (!body) return null;\n const payload = JSON.parse(Buffer.from(body, \"base64\").toString());\n return payload.exp ?? null;\n } catch {\n return null;\n }\n }\n\n function scheduleRefresh(): void {\n if (refreshTimer) clearTimeout(refreshTimer);\n if (!config.refreshToken) return;\n\n const exp = getTokenExpiry(currentToken);\n if (!exp) return;\n\n const msUntilExpiry = exp * 1000 - Date.now();\n const refreshIn = Math.max(msUntilExpiry - REFRESH_BUFFER_MS, 0);\n logger.sys.info(\"[Upstream] Token refresh scheduled\", {\n expiresIn: `${Math.round(msUntilExpiry / 1000)}s`,\n refreshIn: `${Math.round(refreshIn / 1000)}s`,\n });\n refreshTimer = setTimeout(refreshToken, refreshIn);\n }\n\n async function refreshToken(): Promise<boolean> {\n const url = getRefreshUrl();\n if (!url || !config.refreshToken) return false;\n try {\n logger.sys.info(\"[Upstream] Refreshing token...\");\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ refreshToken: config.refreshToken }),\n });\n if (!res.ok) {\n logger.sys.error(\"[Upstream] Token refresh failed\", { status: res.status });\n return false;\n }\n const { token } = (await res.json()) as { token: string };\n currentToken = token;\n logger.sys.info(\"[Upstream] Token refreshed successfully\");\n ws?.close();\n scheduleRefresh();\n return true;\n } catch (err) {\n logger.sys.error(\"[Upstream] Token refresh error\", {\n error: err instanceof Error ? err.message : String(err),\n });\n return false;\n }\n }\n\n function attemptReauth(): void {\n if (!config.onAuthExhausted) {\n logger.sys.error(\"[Upstream] Auth failed after max retries, giving up\");\n return;\n }\n logger.sys.info(\"[Upstream] Auth exhausted, attempting re-authentication...\");\n config\n .onAuthExhausted()\n .then((result) => {\n if (!result) {\n logger.sys.error(\"[Upstream] Re-authentication failed, giving up\");\n return;\n }\n currentToken = result.token;\n if (result.refreshToken) config.refreshToken = result.refreshToken;\n authFailures = 0;\n retries = 0;\n logger.sys.info(\"[Upstream] Re-authenticated, reconnecting...\");\n reconnectTimer = setTimeout(connect, 1000);\n })\n .catch((err) => {\n logger.sys.error(\"[Upstream] Re-authentication error\", {\n error: err instanceof Error ? err.message : String(err),\n });\n });\n }\n\n function connect(): void {\n if (closed) return;\n\n ws = new WebSocket(config.apiUrl, {\n headers: { authorization: `Bearer ${currentToken}` },\n });\n\n ws.on(\"open\", () => {\n authFailures = 0;\n retries = 0;\n logger.sys.info(\"[Upstream] Connected to cloud\", { apiUrl: config.apiUrl });\n scheduleRefresh();\n });\n\n ws.on(\"message\", (raw) => {\n const text = raw.toString();\n // Transport-level ping/pong — never reaches the handler.\n if (text.includes('\"ping\"')) {\n try {\n const parsed = JSON.parse(text) as { type?: string; method?: string };\n if (parsed.type === \"ping\" || parsed.method === \"ping\") {\n ws?.send(JSON.stringify({ jsonrpc: \"2.0\", method: \"pong\" }));\n return;\n }\n } catch {\n /* fall through */\n }\n }\n\n // Upstream connection is authenticated per-socket. userId comes from\n // the authenticated token — for CLI agents the hub forwards frames on\n // behalf of the connected user, so we synthesize ctx accordingly.\n const ctx: Context = {\n userId: \"system\",\n requestId: crypto.randomUUID(),\n timestamp: Date.now(),\n };\n\n frameHandler?.({\n ctx,\n raw: text,\n send: (frame) => {\n if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(frame));\n },\n });\n });\n\n ws.on(\"close\", (code) => {\n console.error(\"[Upstream] Connection closed, code:\", code);\n if (closed) return;\n\n if (code === 4001 || code === 4003) {\n if (config.refreshToken) {\n refreshToken().then((ok) => {\n if (ok) {\n reconnectTimer = setTimeout(connect, 1000);\n } else {\n authFailures++;\n if (authFailures >= MAX_AUTH_RETRIES) {\n attemptReauth();\n return;\n }\n reconnectTimer = setTimeout(connect, 3000);\n }\n });\n return;\n }\n\n authFailures++;\n if (authFailures >= MAX_AUTH_RETRIES) {\n attemptReauth();\n return;\n }\n logger.sys.warn(\"[Upstream] Auth failed, retrying...\", {\n code,\n attempt: authFailures,\n maxRetries: MAX_AUTH_RETRIES,\n });\n reconnectTimer = setTimeout(connect, 3000);\n return;\n }\n\n retries++;\n if (retries >= MAX_RETRIES) {\n logger.sys.error(\"[Upstream] Max reconnect attempts reached, giving up\", {\n attempts: retries,\n });\n return;\n }\n\n logger.sys.info(\"[Upstream] Disconnected, reconnecting in 3s...\", {\n code,\n attempt: retries,\n maxRetries: MAX_RETRIES,\n });\n reconnectTimer = setTimeout(connect, 3000);\n });\n\n ws.on(\"error\", (err) => {\n console.error(\"[Upstream] Connection error:\", err.message);\n logger.sys.error(\"[Upstream] Connection error\", { error: err.message });\n });\n }\n\n /** Send a raw JSON-RPC frame (response / notification). */\n function sendFrame(frame: unknown): void {\n if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(frame));\n }\n\n function onFrame(handler: (frame: UpstreamFrameContext) => void): void {\n frameHandler = handler;\n }\n\n function isConnected(): boolean {\n return ws?.readyState === WebSocket.OPEN;\n }\n\n function close(): void {\n closed = true;\n if (reconnectTimer) clearTimeout(reconnectTimer);\n if (refreshTimer) clearTimeout(refreshTimer);\n ws?.close();\n }\n\n return { connect, sendFrame, onFrame, isConnected, close };\n}\n\nexport type UpstreamClient = ReturnType<typeof createUpstreamClient>;\n","/**\n * Cross-platform service manager for always-on agent.\n *\n * macOS: LaunchAgent plist (~/.jarvis/LaunchAgents/com.appchy.jarvis.plist)\n * Windows: Task Scheduler XML (schtasks /Create)\n */\n\nimport { execSync, spawn } from \"child_process\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\nimport { isDev } from \"./config\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface ServiceOptions {\n workspacePath: string;\n nodePath: string;\n entryPath: string;\n upstream: boolean;\n /** Extra environment variables to propagate to the service child process */\n env?: Record<string, string>;\n}\n\nexport interface ServiceStatus {\n installed: boolean;\n running: boolean;\n pid?: number;\n os?: \"macOS\" | \"windows\" | \"linux\";\n}\n\nexport interface ServiceManager {\n install(opts: ServiceOptions): void;\n uninstall(): void;\n isInstalled(): boolean;\n start(): void;\n stop(): void;\n status(): ServiceStatus;\n}\n\n// =============================================================================\n// Factory\n// =============================================================================\n\nexport function createServiceManager(): ServiceManager {\n if (process.platform === \"darwin\") return new MacOSService();\n if (process.platform === \"win32\") return new WindowsService();\n if (process.platform === \"linux\") return new LinuxService();\n return new FallbackService();\n}\n\n// =============================================================================\n// macOS — LaunchAgent\n// =============================================================================\n\nconst PLIST_LABEL = isDev() ? \"com.appchy.jarvis.dev\" : \"com.appchy.jarvis\";\nconst PLIST_DIR = path.join(os.homedir(), \"Library\", \"LaunchAgents\");\nconst PLIST_PATH = path.join(PLIST_DIR, `${PLIST_LABEL}.plist`);\n\nfunction escapeXml(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nclass MacOSService implements ServiceManager {\n install(opts: ServiceOptions): void {\n const args = [\n opts.nodePath,\n opts.entryPath,\n \"start\",\n \"--foreground\",\n \"--workspace\",\n opts.workspacePath,\n ];\n if (!opts.upstream) {\n args.push(\"--no-upstream\");\n }\n\n const logFile = isDev()\n ? path.join(os.homedir(), \".jarvis\", \"dev\", \"agent.log\")\n : path.join(os.homedir(), \".jarvis\", \"agent.log\");\n const envPath = process.env.PATH ?? \"/usr/local/bin:/usr/bin:/bin\";\n\n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${PLIST_LABEL}</string>\n\n <key>ProgramArguments</key>\n <array>\n${args.map((a) => ` <string>${escapeXml(a)}</string>`).join(\"\\n\")}\n </array>\n\n <key>WorkingDirectory</key>\n <string>${escapeXml(opts.workspacePath)}</string>\n\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>${escapeXml(envPath)}</string>\n <key>HOME</key>\n <string>${escapeXml(os.homedir())}</string>\n <key>NODE_NO_WARNINGS</key>\n <string>1</string>\n${Object.entries(opts.env ?? {}).map(([k, v]) => ` <key>${escapeXml(k)}</key>\\n <string>${escapeXml(v)}</string>`).join(\"\\n\")}\n </dict>\n\n <key>RunAtLoad</key>\n <true/>\n\n <key>KeepAlive</key>\n <true/>\n\n <key>ProcessType</key>\n <string>Interactive</string>\n\n <key>ThrottleInterval</key>\n <integer>5</integer>\n\n <key>StandardOutPath</key>\n <string>${escapeXml(logFile)}</string>\n\n <key>StandardErrorPath</key>\n <string>${escapeXml(logFile)}</string>\n</dict>\n</plist>\n`;\n\n // Ensure directories exist\n fs.mkdirSync(PLIST_DIR, { recursive: true });\n fs.mkdirSync(path.dirname(logFile), { recursive: true });\n\n // Unload existing service if present (ignore errors)\n if (this.isInstalled()) {\n try {\n execSync(`launchctl unload -w \"${PLIST_PATH}\"`, { stdio: \"ignore\" });\n } catch {}\n }\n\n fs.writeFileSync(PLIST_PATH, plist);\n execSync(`launchctl load -w \"${PLIST_PATH}\"`);\n }\n\n uninstall(): void {\n try {\n execSync(`launchctl unload -w \"${PLIST_PATH}\"`, { stdio: \"ignore\" });\n } catch {}\n try {\n fs.unlinkSync(PLIST_PATH);\n } catch {}\n }\n\n isInstalled(): boolean {\n return fs.existsSync(PLIST_PATH);\n }\n\n start(): void {\n try {\n // load -w both loads and starts the agent\n execSync(`launchctl load -w \"${PLIST_PATH}\"`);\n } catch {\n // Already loaded — just kick it\n execSync(`launchctl start ${PLIST_LABEL}`);\n }\n }\n\n stop(): void {\n try {\n // unload -w stops the process AND prevents KeepAlive from restarting\n execSync(`launchctl unload -w \"${PLIST_PATH}\"`, { stdio: \"ignore\" });\n } catch {}\n }\n\n status(): ServiceStatus {\n const installed = this.isInstalled();\n if (!installed) return { installed: false, running: false };\n\n try {\n const output = execSync(`launchctl list ${PLIST_LABEL}`, {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n // Parse PID from launchctl list output\n const pidMatch = output.match(/\"PID\"\\s*=\\s*(\\d+)/);\n const pid = pidMatch ? parseInt(pidMatch[1], 10) : undefined;\n return { installed: true, running: pid !== undefined, pid, os: \"macOS\" };\n } catch {\n return { installed: true, running: false, os: \"macOS\" };\n }\n }\n}\n\n// =============================================================================\n// Windows — Task Scheduler\n// =============================================================================\n\nconst TASK_NAME = isDev() ? \"JarvisAgentDev\" : \"JarvisAgent\";\n\nclass WindowsService implements ServiceManager {\n install(opts: ServiceOptions): void {\n const args = [\n opts.entryPath,\n \"start\",\n \"--foreground\",\n \"--workspace\",\n `\"${opts.workspacePath}\"`,\n ];\n if (!opts.upstream) {\n args.push(\"--no-upstream\");\n }\n\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n<Task version=\"1.2\" xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">\n <RegistrationInfo>\n <Description>Jarvis AI Agent — always-on background service</Description>\n </RegistrationInfo>\n <Triggers>\n <LogonTrigger>\n <Enabled>true</Enabled>\n </LogonTrigger>\n </Triggers>\n <Principals>\n <Principal id=\"Author\">\n <LogonType>InteractiveToken</LogonType>\n <RunLevel>LeastPrivilege</RunLevel>\n </Principal>\n </Principals>\n <Settings>\n <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>\n <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>\n <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>\n <AllowHardTerminate>true</AllowHardTerminate>\n <StartWhenAvailable>true</StartWhenAvailable>\n <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>\n <AllowStartOnDemand>true</AllowStartOnDemand>\n <Enabled>true</Enabled>\n <Hidden>false</Hidden>\n <RunOnlyIfIdle>false</RunOnlyIfIdle>\n <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>\n <Priority>7</Priority>\n <RestartOnFailure>\n <Interval>PT1M</Interval>\n <Count>999</Count>\n </RestartOnFailure>\n </Settings>\n <Actions Context=\"Author\">\n <Exec>\n <Command>${escapeXml(opts.nodePath)}</Command>\n <Arguments>${escapeXml(args.join(\" \"))}</Arguments>\n <WorkingDirectory>${escapeXml(opts.workspacePath)}</WorkingDirectory>\n </Exec>\n </Actions>\n</Task>\n`;\n\n // Write XML to temp file\n const tmpDir = os.tmpdir();\n const tmpFile = path.join(tmpDir, `jarvis-task-${Date.now()}.xml`);\n fs.writeFileSync(tmpFile, xml, { encoding: \"utf-16le\" });\n\n try {\n execSync(`schtasks /Create /TN \"${TASK_NAME}\" /XML \"${tmpFile}\" /F`, {\n stdio: \"ignore\",\n });\n } finally {\n try {\n fs.unlinkSync(tmpFile);\n } catch {}\n }\n }\n\n uninstall(): void {\n try {\n execSync(`schtasks /Delete /TN \"${TASK_NAME}\" /F`, { stdio: \"ignore\" });\n } catch {}\n }\n\n isInstalled(): boolean {\n try {\n execSync(`schtasks /Query /TN \"${TASK_NAME}\"`, { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n }\n\n start(): void {\n execSync(`schtasks /Run /TN \"${TASK_NAME}\"`, { stdio: \"ignore\" });\n }\n\n stop(): void {\n execSync(`schtasks /End /TN \"${TASK_NAME}\"`, { stdio: \"ignore\" });\n }\n\n status(): ServiceStatus {\n if (!this.isInstalled()) return { installed: false, running: false };\n\n try {\n const output = execSync(`schtasks /Query /TN \"${TASK_NAME}\" /FO CSV /NH`, {\n encoding: \"utf-8\",\n });\n const running = output.includes(\"Running\");\n return { installed: true, running, os: \"windows\" };\n } catch {\n return { installed: true, running: false, os: \"windows\" };\n }\n }\n}\n\n// =============================================================================\n// Linux — systemd user service\n// =============================================================================\n\nconst SYSTEMD_DIR = path.join(os.homedir(), \".config\", \"systemd\", \"user\");\nconst UNIT_NAME = isDev() ? \"jarvis-dev.service\" : \"jarvis.service\";\nconst UNIT_PATH = path.join(SYSTEMD_DIR, UNIT_NAME);\n\nclass LinuxService implements ServiceManager {\n install(opts: ServiceOptions): void {\n const args = [\n opts.entryPath,\n \"start\",\n \"--foreground\",\n \"--workspace\",\n opts.workspacePath,\n ];\n if (!opts.upstream) {\n args.push(\"--no-upstream\");\n }\n\n const logFile = isDev()\n ? path.join(os.homedir(), \".jarvis\", \"dev\", \"agent.log\")\n : path.join(os.homedir(), \".jarvis\", \"agent.log\");\n const envPath = process.env.PATH ?? \"/usr/local/bin:/usr/bin:/bin\";\n\n const unit = `[Unit]\nDescription=Jarvis AI Agent${isDev() ? \" (Dev)\" : \"\"}\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=${opts.nodePath} ${args.join(\" \")}\nWorkingDirectory=${opts.workspacePath}\nEnvironment=PATH=${envPath}\nEnvironment=HOME=${os.homedir()}\nEnvironment=NODE_NO_WARNINGS=1\nRestart=always\nRestartSec=5\nStandardOutput=append:${logFile}\nStandardError=append:${logFile}\n\n[Install]\nWantedBy=default.target\n`;\n\n // Ensure directories exist\n fs.mkdirSync(SYSTEMD_DIR, { recursive: true });\n fs.mkdirSync(path.dirname(logFile), { recursive: true });\n\n // Stop existing service if running\n if (this.isInstalled()) {\n try {\n execSync(`systemctl --user stop ${UNIT_NAME}`, { stdio: \"ignore\" });\n } catch {}\n }\n\n fs.writeFileSync(UNIT_PATH, unit);\n execSync(\"systemctl --user daemon-reload\", { stdio: \"ignore\" });\n execSync(`systemctl --user enable ${UNIT_NAME}`, { stdio: \"ignore\" });\n execSync(`systemctl --user start ${UNIT_NAME}`, { stdio: \"ignore\" });\n\n // Enable lingering so the service runs even when user is not logged in\n // (equivalent to ProcessType: Interactive on macOS)\n try {\n execSync(`loginctl enable-linger ${os.userInfo().username}`, { stdio: \"ignore\" });\n } catch {\n // May require root — not critical, service still works when logged in\n }\n }\n\n uninstall(): void {\n try {\n execSync(`systemctl --user stop ${UNIT_NAME}`, { stdio: \"ignore\" });\n } catch {}\n try {\n execSync(`systemctl --user disable ${UNIT_NAME}`, { stdio: \"ignore\" });\n } catch {}\n try {\n fs.unlinkSync(UNIT_PATH);\n } catch {}\n try {\n execSync(\"systemctl --user daemon-reload\", { stdio: \"ignore\" });\n } catch {}\n }\n\n isInstalled(): boolean {\n return fs.existsSync(UNIT_PATH);\n }\n\n start(): void {\n execSync(`systemctl --user start ${UNIT_NAME}`);\n }\n\n stop(): void {\n execSync(`systemctl --user stop ${UNIT_NAME}`, { stdio: \"ignore\" });\n }\n\n status(): ServiceStatus {\n if (!this.isInstalled()) return { installed: false, running: false };\n\n try {\n const output = execSync(`systemctl --user show ${UNIT_NAME} --property=ActiveState,MainPID`, {\n encoding: \"utf-8\",\n });\n const active = output.includes(\"ActiveState=active\");\n const pidMatch = output.match(/MainPID=(\\d+)/);\n const pid = pidMatch ? parseInt(pidMatch[1], 10) : undefined;\n return {\n installed: true,\n running: active && pid !== undefined && pid > 0,\n pid: pid && pid > 0 ? pid : undefined,\n os: \"linux\",\n };\n } catch {\n return { installed: true, running: false, os: \"linux\" };\n }\n }\n}\n\n// =============================================================================\n// Unsupported platform\n// =============================================================================\n\n/**\n * Fallback for unsupported platforms.\n *\n * Uses a detached Node.js child process — the agent runs in the background\n * but won't auto-start on login, survive reboots, or recover from crashes.\n */\nclass FallbackService implements ServiceManager {\n private baseDir = isDev()\n ? path.join(os.homedir(), \".jarvis\", \"dev\")\n : path.join(os.homedir(), \".jarvis\");\n private pidFile = path.join(this.baseDir, \"agent.pid\");\n private logFile = path.join(this.baseDir, \"agent.log\");\n private markerFile = path.join(this.baseDir, \"service-installed\");\n\n install(opts: ServiceOptions): void {\n const jarvisDir = path.join(os.homedir(), \".jarvis\");\n fs.mkdirSync(jarvisDir, { recursive: true });\n\n // Stop existing process if running\n this.stop();\n\n const args = [\n opts.entryPath,\n \"start\",\n \"--foreground\",\n \"--workspace\",\n opts.workspacePath,\n ];\n if (!opts.upstream) {\n args.push(\"--no-upstream\");\n }\n\n const logFd = fs.openSync(this.logFile, \"a\");\n const child = spawn(opts.nodePath, args, {\n detached: true,\n stdio: [\"ignore\", logFd, logFd],\n cwd: opts.workspacePath,\n env: { ...process.env, NODE_NO_WARNINGS: \"1\" },\n });\n child.unref();\n fs.closeSync(logFd);\n\n // Save PID and marker\n fs.writeFileSync(this.pidFile, String(child.pid));\n fs.writeFileSync(this.markerFile, JSON.stringify({\n nodePath: opts.nodePath,\n entryPath: opts.entryPath,\n workspacePath: opts.workspacePath,\n upstream: opts.upstream,\n }));\n\n console.log(\n `\\x1b[33mNote:\\x1b[0m OS-level service not available on ${process.platform}.`,\n );\n console.log(\" Agent is running as a background process (PID: \" + child.pid + \").\");\n console.log(\" It will NOT auto-start on reboot or recover from crashes.\");\n }\n\n uninstall(): void {\n this.stop();\n try { fs.unlinkSync(this.markerFile); } catch {}\n }\n\n isInstalled(): boolean {\n return fs.existsSync(this.markerFile);\n }\n\n start(): void {\n if (!this.isInstalled()) {\n throw new Error(\"Service not installed. Run 'jarvis install' first.\");\n }\n // Re-install with saved options to spawn a new process\n const saved = JSON.parse(fs.readFileSync(this.markerFile, \"utf-8\"));\n this.install(saved);\n }\n\n stop(): void {\n try {\n const pid = parseInt(fs.readFileSync(this.pidFile, \"utf-8\").trim(), 10);\n if (!isNaN(pid)) {\n process.kill(pid, \"SIGTERM\");\n }\n } catch {}\n try { fs.unlinkSync(this.pidFile); } catch {}\n }\n\n status(): ServiceStatus {\n if (!this.isInstalled()) return { installed: false, running: false };\n\n try {\n const pid = parseInt(fs.readFileSync(this.pidFile, \"utf-8\").trim(), 10);\n if (isNaN(pid)) return { installed: true, running: false };\n process.kill(pid, 0); // Check if alive\n return { installed: true, running: true, pid };\n } catch {\n return { installed: true, running: false };\n }\n }\n}\n","import type { Command } from \"commander\";\n\nimport { browserAuth, ensureConfig, getAppUrl } from \"../auth\";\nimport { loadConfig, type AgentConfig } from \"../config\";\nimport { resolveEntryPoint } from \"../entry\";\nimport { getLogFile } from \"../paths\";\nimport { isAgentRunning, readPid, clearPid } from \"../pid\";\nimport { promptWorkspace, registerRepo } from \"../setup\";\nimport { startAgent } from \"../start\";\nimport { createServiceManager } from \"../service\";\nimport type { UpstreamConfig } from \"../upstream\";\n\ninterface StartOptions {\n workspace?: string;\n apiKey?: string;\n upstream: boolean;\n foreground?: boolean;\n}\n\nexport function register(program: Command): void {\n program\n .command(\"start\")\n .description(\"Start the local agent (authenticates, cleans up stale processes, starts fresh)\")\n .option(\"-w, --workspace <path>\", \"Workspace root path\")\n .option(\"--api-key <key>\", \"Anthropic API key (for local-only use)\")\n .option(\"--no-upstream\", \"Don't connect to cloud (local-only mode)\")\n .option(\"--foreground\", \"Run in foreground (don't daemonize)\")\n .action(async (opts: StartOptions) => {\n if (!opts.foreground) {\n const ok = await ensureConfig();\n if (!ok) {\n console.error(\"Setup failed. Cannot start agent.\");\n process.exit(1);\n }\n }\n\n const config = loadConfig();\n const workspacePath = await resolveWorkspacePath(opts, config);\n const userId = config?.userId ?? process.env.JARVIS_USER_ID ?? \"local\";\n\n if (!opts.foreground) {\n await registerRepo(workspacePath, config);\n }\n\n const explicitApiKey = opts.apiKey ?? config?.anthropicApiKey;\n const useSubscription = !explicitApiKey;\n const anthropicApiKey = explicitApiKey;\n\n if (opts.foreground) {\n if (useSubscription && process.env.ANTHROPIC_API_KEY) {\n delete process.env.ANTHROPIC_API_KEY;\n }\n const upstream = buildUpstreamConfig({ config, opts });\n if (!upstream) {\n console.error(\"Agent requires a hub connection. Run 'jarvis connect <token>' first.\");\n process.exit(1);\n }\n await startAgent({\n workspacePath,\n anthropicApiKey,\n useSubscription,\n userId,\n upstream,\n });\n return;\n }\n\n // Clean restart: nuke everything, then install fresh as an OS service.\n const service = createServiceManager();\n if (service.isInstalled()) {\n try {\n service.uninstall();\n } catch {}\n }\n\n const stalePid = readPid();\n if (stalePid) {\n try {\n process.kill(stalePid, \"SIGTERM\");\n } catch {}\n clearPid();\n }\n\n const { nodePath, entryPath } = resolveEntryPoint();\n\n const serviceEnv: Record<string, string> = {};\n if (process.env.JARVIS_CONFIG_DIR) serviceEnv.JARVIS_CONFIG_DIR = process.env.JARVIS_CONFIG_DIR;\n if (process.env.JARVIS_USER_ID) serviceEnv.JARVIS_USER_ID = process.env.JARVIS_USER_ID;\n if (process.env.JARVIS_ENV_ID) serviceEnv.JARVIS_ENV_ID = process.env.JARVIS_ENV_ID;\n\n service.install({\n workspacePath,\n nodePath,\n entryPath,\n upstream: opts.upstream,\n ...(Object.keys(serviceEnv).length > 0 ? { env: serviceEnv } : {}),\n });\n\n const startTime = Date.now();\n let agentReady = false;\n while (Date.now() - startTime < 15_000) {\n if (isAgentRunning()) {\n agentReady = true;\n break;\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n\n if (!agentReady) {\n console.error(\"Agent failed to start. Check logs:\");\n console.error(` ${getLogFile()}`);\n process.exit(1);\n }\n\n const status = service.status();\n console.log(`Jarvis agent started`);\n console.log(` Workspace: ${workspacePath}`);\n console.log(` Logs: ${getLogFile()}`);\n if (config?.apiUrl) {\n console.log(` Cloud: ${config.apiUrl}`);\n }\n if (status.os) {\n console.log(` Service: ${status.os} (auto-start on login, crash recovery)`);\n }\n });\n}\n\n// =============================================================================\n// Internals\n// =============================================================================\n\n/** Resolve the workspace path: explicit `--workspace` flag wins, foreground/\n * daemon mode falls back to config or cwd, interactive sessions prompt. */\nasync function resolveWorkspacePath(\n opts: StartOptions,\n config: AgentConfig | null,\n): Promise<string> {\n if (opts.workspace) return opts.workspace;\n\n const defaultPath = config?.workspacePath ?? process.cwd();\n if (opts.foreground) return defaultPath;\n\n const { workspacePath } = await promptWorkspace({ defaultPath });\n return workspacePath;\n}\n\ninterface BuildUpstreamConfigRequest {\n config: AgentConfig | null;\n opts: StartOptions;\n}\n\nfunction buildUpstreamConfig(req: BuildUpstreamConfigRequest): UpstreamConfig | null {\n const apiUrl = process.env.JARVIS_UPSTREAM_URL ?? req.config?.apiUrl;\n const token = process.env.JARVIS_UPSTREAM_TOKEN ?? req.config?.token;\n if (!req.opts.upstream || !apiUrl || !token) return null;\n\n const appUrl = getAppUrl();\n return {\n apiUrl,\n token,\n refreshToken: req.config?.refreshToken,\n onAuthExhausted: async () => {\n console.log(\"\\n[Auth] Token expired — re-authenticating...\");\n const ok = await browserAuth(appUrl);\n if (!ok) return null;\n const fresh = loadConfig();\n if (!fresh?.token) return null;\n return { token: fresh.token, refreshToken: fresh.refreshToken };\n },\n };\n}\n","import type { Command } from \"commander\";\n\nimport { readPid, clearPid } from \"../pid\";\nimport { createServiceManager } from \"../service\";\n\nexport function register(program: Command): void {\n program\n .command(\"stop\")\n .description(\"Stop the running agent\")\n .action(() => {\n const service = createServiceManager();\n if (service.isInstalled()) {\n service.stop();\n clearPid();\n console.log(\"Agent stopped via OS service.\");\n console.log(\"Use 'jarvis start' to re-enable, or 'jarvis uninstall' to remove auto-start.\");\n return;\n }\n\n const pid = readPid();\n if (pid) {\n try {\n process.kill(pid, \"SIGTERM\");\n clearPid();\n console.log(`Agent stopped (PID: ${pid})`);\n } catch {\n clearPid();\n console.log(\"Agent process not found. Cleaned up PID file.\");\n }\n return;\n }\n\n console.log(\"No agent is running.\");\n });\n}\n","import type { Command } from \"commander\";\n\nexport function register(program: Command): void {\n program\n .command(\"restart\")\n .description(\"Restart the agent (alias for start — start always does a clean restart)\")\n .action(async () => {\n // start already handles: auth → kill stale → start fresh\n await program.parseAsync([\"node\", \"jarvis\", \"start\"]);\n });\n}\n","import type { Command } from \"commander\";\nimport { spawn, execSync } from \"child_process\";\nimport fs from \"fs\";\n\nimport { getLogFile } from \"../paths\";\n\nexport function register(program: Command): void {\n program\n .command(\"logs\")\n .description(\"View agent logs\")\n .option(\"-f, --follow\", \"Follow log output (like tail -f)\", true)\n .option(\"-n, --lines <n>\", \"Number of lines to show\", \"50\")\n .action((opts: { follow?: boolean; lines: string }) => {\n const logFile = getLogFile();\n if (!fs.existsSync(logFile)) {\n console.log(\"No log file found. Start the agent first: jarvis start\");\n return;\n }\n\n if (opts.follow) {\n const tail = spawn(\"tail\", [\"-f\", \"-n\", opts.lines, logFile], {\n stdio: \"inherit\",\n });\n process.on(\"SIGINT\", () => {\n tail.kill();\n process.exit(0);\n });\n tail.on(\"exit\", () => process.exit(0));\n } else {\n const content = execSync(`tail -n ${opts.lines} \"${logFile}\"`, { encoding: \"utf-8\" });\n process.stdout.write(content);\n }\n });\n}\n","import { createRequire } from \"module\";\n\nconst _require = createRequire(import.meta.url);\n\nexport const PKG_VERSION: string = _require(\"../package.json\").version ?? \"dev\";\n","import type { Command } from \"commander\";\n\nimport { loadConfig, getConfigPath } from \"../config\";\nimport { readPid } from \"../pid\";\nimport { getLogFile } from \"../paths\";\nimport { createServiceManager } from \"../service\";\nimport { PKG_VERSION } from \"../version\";\n\nexport function register(program: Command): void {\n program\n .command(\"status\")\n .description(\"Show agent configuration and connection status\")\n .action(() => {\n const config = loadConfig();\n const pid = readPid();\n const running = pid !== null;\n\n console.log(`Jarvis Agent v${PKG_VERSION}:`);\n console.log(\n ` Status: ${running ? `\\x1b[32mrunning\\x1b[0m` : `\\x1b[31mstopped\\x1b[0m`}${pid ? ` (PID: ${pid})` : \"\"}`,\n );\n console.log(` Config: ${getConfigPath()}`);\n\n if (config) {\n console.log(` User: ${config.userId}`);\n console.log(` Env: ${config.envId ?? \"local\"}`);\n console.log(` Workspace: ${config.workspacePath ?? \"(cwd)\"}`);\n console.log(` Cloud: ${config.apiUrl ?? \"(not connected)\"}`);\n if (config.connectedAt) {\n console.log(` Connected: ${config.connectedAt}`);\n }\n } else {\n console.log(` Config: Not set up. Run 'jarvis connect <token>'`);\n }\n\n const svc = createServiceManager();\n const svcStatus = svc.status();\n if (svcStatus.installed) {\n const label = svcStatus.os ?? \"unknown\";\n const state = svcStatus.running\n ? `\\x1b[32minstalled & running\\x1b[0m (${label})`\n : `\\x1b[33minstalled, stopped\\x1b[0m (${label})`;\n console.log(` Service: ${state}`);\n } else {\n console.log(` Service: not installed (run 'jarvis install' for always-on)`);\n }\n\n console.log(` Logs: ${getLogFile()}`);\n });\n}\n","import type { Command } from \"commander\";\n\nimport { ensureConfig } from \"../auth\";\nimport { loadConfig } from \"../config\";\nimport { resolveEntryPoint } from \"../entry\";\nimport { readPid, clearPid } from \"../pid\";\nimport { createServiceManager } from \"../service\";\n\nexport function register(program: Command): void {\n program\n .command(\"install\")\n .description(\"Install as OS service for auto-start on login and crash recovery\")\n .option(\"-w, --workspace <path>\", \"Workspace root path\")\n .option(\"--no-upstream\", \"Don't connect to cloud\")\n .action(async (opts: { workspace?: string; upstream: boolean }) => {\n await ensureConfig();\n const config = loadConfig();\n const workspacePath = opts.workspace ?? config?.workspacePath ?? process.cwd();\n const service = createServiceManager();\n const { nodePath, entryPath } = resolveEntryPoint();\n\n // Kill any existing detached daemon — service takes over\n const pid = readPid();\n if (pid) {\n try {\n process.kill(pid, \"SIGTERM\");\n } catch {}\n clearPid();\n }\n\n const installEnv: Record<string, string> = {};\n if (process.env.JARVIS_CONFIG_DIR) installEnv.JARVIS_CONFIG_DIR = process.env.JARVIS_CONFIG_DIR;\n if (process.env.JARVIS_USER_ID) installEnv.JARVIS_USER_ID = process.env.JARVIS_USER_ID;\n if (process.env.JARVIS_ENV_ID) installEnv.JARVIS_ENV_ID = process.env.JARVIS_ENV_ID;\n\n try {\n service.install({\n workspacePath,\n nodePath,\n entryPath,\n upstream: opts.upstream,\n ...(Object.keys(installEnv).length > 0 ? { env: installEnv } : {}),\n });\n } catch (err) {\n console.error(`Failed to install service: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n\n const status = service.status();\n console.log(`Jarvis agent installed as OS service`);\n console.log(` Platform: ${status.os}`);\n console.log(` Workspace: ${workspacePath}`);\n console.log(` Auto-start on login: \\x1b[32menabled\\x1b[0m`);\n console.log(` Crash recovery: \\x1b[32menabled\\x1b[0m`);\n console.log();\n console.log(`Commands:`);\n console.log(` jarvis status — Check service status`);\n console.log(` jarvis uninstall — Remove OS service`);\n });\n}\n","import type { Command } from \"commander\";\n\nimport { clearPid } from \"../pid\";\nimport { createServiceManager } from \"../service\";\n\nexport function register(program: Command): void {\n program\n .command(\"uninstall\")\n .description(\"Remove OS service (stops auto-start and crash recovery)\")\n .action(() => {\n const service = createServiceManager();\n if (!service.isInstalled()) {\n console.log(\"No service is installed. Nothing to do.\");\n return;\n }\n\n try {\n service.stop();\n } catch {}\n service.uninstall();\n clearPid();\n console.log(\"Jarvis OS service removed.\");\n console.log(\"The agent will no longer auto-start on login or restart on crash.\");\n });\n}\n","import type { Command } from \"commander\";\n\nimport { clearConfig } from \"../config\";\n\nexport function register(program: Command): void {\n program\n .command(\"logout\")\n .description(\"Clear saved configuration\")\n .action(() => {\n clearConfig();\n console.log(\"Configuration cleared.\");\n });\n}\n","/**\n * Chat Entry Point\n *\n * Launches the interactive TUI:\n * 1. Load settings (file + CLI flags)\n * 2. Auto-start agent server as a detached child process (silent)\n * 3. Render Ink app — owns stdout/stderr exclusively\n */\n\nimport React from \"react\";\nimport { render } from \"ink\";\nimport { spawn, type ChildProcess } from \"child_process\";\nimport { fileURLToPath } from \"url\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport os from \"os\";\n\nimport { loadSettings, mergeCliFlags, type TuiSettings } from \"./settings\";\nimport { loadConfig } from \"../config\";\nimport { isAgentRunning } from \"../pid\";\nimport { App } from \"./app\";\n\n/** Agent child process — killed on TUI exit */\nlet agentChild: ChildProcess | null = null;\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface ChatOptions {\n model?: string;\n mode?: string;\n thinking?: string;\n thinkingBudget?: string;\n maxTurns?: string;\n server: boolean; // --no-server sets to false\n workspace?: string;\n}\n\n// =============================================================================\n// Launch\n// =============================================================================\n\nexport async function launchChat(opts: ChatOptions): Promise<void> {\n const config = loadConfig();\n\n // Load and merge settings\n const fileSettings = loadSettings();\n const settings: TuiSettings = mergeCliFlags(fileSettings, {\n model: opts.model,\n mode: opts.mode,\n thinking: opts.thinking,\n thinkingBudget: opts.thinkingBudget,\n maxTurns: opts.maxTurns,\n });\n\n const workspacePath = opts.workspace ?? config?.workspacePath ?? process.cwd();\n\n // Auto-start agent runner if --no-server wasn't passed\n let weSpawnedAgent = false;\n if (opts.server) {\n if (!isAgentRunning()) {\n spawnAgentProcess(workspacePath);\n weSpawnedAgent = true;\n await waitForAgent();\n }\n }\n\n // Kill agent on exit if we spawned it\n const cleanup = () => {\n if (weSpawnedAgent && agentChild && !agentChild.killed) {\n agentChild.kill(\"SIGTERM\");\n agentChild = null;\n }\n };\n\n process.on(\"exit\", cleanup);\n process.on(\"SIGINT\", () => {\n cleanup();\n process.exit(0);\n });\n process.on(\"SIGTERM\", () => {\n cleanup();\n process.exit(0);\n });\n process.on(\"SIGHUP\", () => {\n cleanup();\n process.exit(0);\n });\n\n // Render the TUI — Ink owns stdout/stderr from here\n const { waitUntilExit } = render(\n React.createElement(App, {\n initialSettings: settings,\n workspacePath,\n }),\n );\n\n await waitUntilExit();\n cleanup();\n}\n\n// =============================================================================\n// Agent Process (child, killed on TUI exit)\n// =============================================================================\n\n/**\n * Spawn `jarvis start` as a child process.\n * stdout/stderr → ~/.jarvis/agent.log (TUI owns the terminal).\n * NOT detached — dies when the TUI process exits.\n */\nfunction spawnAgentProcess(workspacePath: string): void {\n const config = loadConfig();\n\n // Log file for agent output\n const logDir = path.join(os.homedir(), \".jarvis\");\n fs.mkdirSync(logDir, { recursive: true });\n const logFile = path.join(logDir, \"agent.log\");\n const logFd = fs.openSync(logFile, \"a\");\n\n // Find the bin entry point (same binary the user invoked)\n const __filename = fileURLToPath(import.meta.url);\n const cliRoot = path.resolve(path.dirname(__filename), \"../..\");\n const binPath = path.join(cliRoot, \"bin\", \"jarvis.mjs\");\n\n // Build args for `jarvis start`\n const args = [\"start\", \"--workspace\", workspacePath];\n\n if (config?.apiUrl && config?.token) {\n // upstream is auto-detected from config\n } else {\n args.push(\"--no-upstream\");\n }\n\n const apiKey = config?.anthropicApiKey ?? process.env.ANTHROPIC_API_KEY;\n if (apiKey) {\n args.push(\"--api-key\", apiKey);\n }\n\n agentChild = spawn(process.execPath, [binPath, ...args], {\n stdio: [\"ignore\", logFd, logFd],\n cwd: workspacePath,\n env: { ...process.env },\n });\n\n fs.closeSync(logFd);\n}\n\n// =============================================================================\n// Agent Health Check\n// =============================================================================\n\nasync function waitForAgent(maxAttempts = 30): Promise<void> {\n for (let i = 0; i < maxAttempts; i++) {\n if (isAgentRunning()) return;\n await new Promise((r) => setTimeout(r, 250));\n }\n // Don't console.log here — TUI will show connection status in status bar\n}\n","/**\n * TUI Settings\n *\n * Load/save/merge ~/.jarvis/settings.json — user preferences for the TUI.\n * These are TUI-local and applied per agent:dispatch message.\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\n\nimport type { ThinkingConfig } from \"@jarvis/types\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type PermissionMode = \"supervised\" | \"auto\" | \"plan\" | \"yolo\";\n\nexport interface TuiSettings {\n model: string;\n thinking: ThinkingConfig;\n permissionMode: PermissionMode;\n maxTurns: number;\n theme: \"dark\" | \"light\";\n disallowedTools: string[];\n}\n\n// =============================================================================\n// Defaults\n// =============================================================================\n\nexport const DEFAULT_SETTINGS: TuiSettings = {\n model: \"claude-sonnet-4-20250514\",\n thinking: { type: \"adaptive\" },\n permissionMode: \"supervised\",\n maxTurns: 25,\n theme: \"dark\",\n disallowedTools: [],\n};\n\n// =============================================================================\n// Paths\n// =============================================================================\n\nconst SETTINGS_DIR = path.join(os.homedir(), \".jarvis\");\nconst SETTINGS_FILE = path.join(SETTINGS_DIR, \"settings.json\");\n\n// =============================================================================\n// Operations\n// =============================================================================\n\nexport function loadSettings(): TuiSettings {\n try {\n const raw = fs.readFileSync(SETTINGS_FILE, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<TuiSettings>;\n return { ...DEFAULT_SETTINGS, ...parsed };\n } catch {\n return { ...DEFAULT_SETTINGS };\n }\n}\n\nexport function saveSettings(settings: TuiSettings): void {\n fs.mkdirSync(SETTINGS_DIR, { recursive: true });\n fs.writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2) + \"\\n\");\n}\n\n/**\n * Merge CLI flags into loaded settings.\n * Only non-undefined flags override.\n */\nexport function mergeCliFlags(\n settings: TuiSettings,\n flags: {\n model?: string;\n mode?: string;\n thinking?: string;\n thinkingBudget?: string;\n maxTurns?: string;\n },\n): TuiSettings {\n const merged = { ...settings };\n\n if (flags.model) merged.model = flags.model;\n if (flags.mode) merged.permissionMode = flags.mode as PermissionMode;\n if (flags.maxTurns) merged.maxTurns = parseInt(flags.maxTurns, 10);\n\n if (flags.thinking) {\n const type = flags.thinking as ThinkingConfig[\"type\"];\n merged.thinking = { type };\n if (type === \"enabled\" && flags.thinkingBudget) {\n merged.thinking.budgetTokens = parseInt(flags.thinkingBudget, 10);\n }\n }\n\n return merged;\n}\n\nexport function getSettingsPath(): string {\n return SETTINGS_FILE;\n}\n","/**\n * Jarvis TUI App\n *\n * Rendering strategy — zero dynamic content above the input bar:\n * - ALL messages go into <Static> (rendered once, never re-rendered)\n * - Streaming text is committed to <Static> only when finalized\n * - The ONLY dynamic elements are: spinner + overlays + input bar + footer\n * - This eliminates all jumpiness during streaming\n */\n\nimport React, { useState, useCallback, useRef, useEffect } from \"react\";\nimport { Box, Static, Text, useApp, useInput } from \"ink\";\n\nimport type {\n OnAgentMessageParams,\n OnAgentTokenParams,\n OnAgentUsageParams,\n OnAgentUserInputRequestParams,\n AgentOutputParams,\n AgentStatusParams,\n} from \"@jarvis/types\";\n\nimport type { TuiSettings } from \"./settings\";\nimport { useAgentClient, type AgentNotification } from \"./hooks/use-agent-client\";\nimport { useMessages, type DisplayMessage } from \"./hooks/use-messages\";\nimport { useTask } from \"./hooks/use-task\";\nimport { useSettings } from \"./hooks/use-settings\";\nimport { parseSlashCommand } from \"./utils/slash-commands\";\nimport { shouldAutoApprove } from \"./utils/auto-approve\";\n\nimport { WelcomeHeader } from \"./components/welcome-header\";\nimport { UserMessage } from \"./components/user-message\";\nimport { Spinner } from \"./components/spinner\";\nimport { Divider } from \"./components/divider\";\nimport { PromptInput } from \"./components/prompt-input\";\nimport { StatusBar } from \"./components/status-bar\";\nimport { PermissionDialog } from \"./components/permission-dialog\";\nimport { PlanReview } from \"./components/plan-review\";\nimport { MaxIterations } from \"./components/max-iterations\";\nimport { HelpMenu } from \"./components/help-menu\";\nimport { StatusDisplay } from \"./components/status-display\";\nimport { ModelPicker } from \"./components/model-picker\";\nimport { ModePicker } from \"./components/mode-picker\";\nimport { ThinkingPicker } from \"./components/thinking-picker\";\nimport { SettingsDialog } from \"./components/settings-dialog\";\nimport { Notification } from \"./components/notification\";\nimport { MarkdownText } from \"./components/markdown-text\";\nimport { t } from \"./theme\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\ntype Overlay = \"none\" | \"help\" | \"status\" | \"config\" | \"model\" | \"mode\" | \"thinking\";\n\ninterface AppProps {\n initialSettings: TuiSettings;\n workspacePath: string;\n}\n\ninterface StaticItem {\n key: string;\n node: React.ReactNode;\n}\n\n// =============================================================================\n// App\n// =============================================================================\n\nexport function App({ initialSettings, workspacePath }: AppProps) {\n const { exit } = useApp();\n const [overlay, setOverlay] = useState<Overlay>(\"none\");\n const [notification, setNotification] = useState<string | null>(null);\n\n const { settings, setModel, setThinking, setPermissionMode, cyclePermissionMode, setMaxTurns } =\n useSettings(initialSettings);\n\n const {\n messages,\n streamingTextContent: _streamingTextContent,\n addUserMessage,\n handleChatMessage,\n handleTokenEvent,\n clearMessages,\n } = useMessages();\n\n // ==========================================================================\n // Static output — append-only list rendered by <Static>\n // ==========================================================================\n\n const [staticItems, setStaticItems] = useState<StaticItem[]>([\n {\n key: \"welcome\",\n node: <WelcomeHeader settings={settings} workspacePath={workspacePath} />,\n },\n ]);\n const committedIdsRef = useRef(new Set<string>());\n\n // Commit finalized messages to static.\n // Thinking messages are always isPartial=true (never finalized by the agent),\n // so we commit them when a newer message appears after them (thinking is over).\n useEffect(() => {\n const newItems: StaticItem[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i]!;\n if (committedIdsRef.current.has(msg.id)) continue;\n\n // Non-partial → commit immediately\n if (!msg.isPartial) {\n committedIdsRef.current.add(msg.id);\n newItems.push({ key: msg.id, node: renderMessage(msg) });\n continue;\n }\n\n // Partial thinking → commit if a later message exists (thinking phase is over)\n if (msg.type === \"thinking\" && i < messages.length - 1) {\n committedIdsRef.current.add(msg.id);\n newItems.push({ key: msg.id, node: renderMessage(msg) });\n continue;\n }\n }\n\n if (newItems.length > 0) {\n setStaticItems((prev) => [...prev, ...newItems]);\n }\n }, [messages]);\n\n // ==========================================================================\n // WS handler\n // ==========================================================================\n\n const handleNotification = useCallback(\n (note: AgentNotification) => {\n switch (note.method) {\n case \"agent.onMessage\": {\n const p = note.params as OnAgentMessageParams;\n handleChatMessage(p.message);\n break;\n }\n case \"agent.onToken\":\n handleTokenEvent(note.params as OnAgentTokenParams);\n break;\n case \"agent.onUsage\": {\n const p = note.params as OnAgentUsageParams;\n task.addTokens(p.totalTokens);\n break;\n }\n case \"agent.onUserInputRequest\": {\n const p = note.params as OnAgentUserInputRequestParams;\n if (shouldAutoApprove(settings.permissionMode, p.input)) {\n task.setPendingInput(p.input);\n setTimeout(() => {\n if (task.currentTaskId) {\n client.respondToInput(p.input.id, \"allow\");\n task.setPendingInput(null);\n task.setAgentState(\"busy\");\n }\n }, 0);\n } else {\n task.setPendingInput(p.input);\n task.setAgentState(\"awaiting-input\");\n }\n break;\n }\n case \"agent.output\": {\n const p = note.params as AgentOutputParams;\n void p;\n task.setAgentState(\"idle\");\n break;\n }\n case \"agent.status\": {\n const p = note.params as AgentStatusParams;\n if (p.status === \"idle\") task.setAgentState(\"idle\");\n break;\n }\n }\n },\n [settings.permissionMode],\n );\n\n const client = useAgentClient(handleNotification);\n const task = useTask(client, settings);\n\n // ==========================================================================\n // Keybindings\n // ==========================================================================\n\n useInput((_input, key) => {\n if (key.ctrl && _input === \"c\") {\n if (task.agentState === \"busy\") task.abort();\n else exit();\n return;\n }\n if (key.ctrl && _input === \"d\") { exit(); return; }\n if (key.shift && key.tab) {\n setNotification(`Mode: ${cyclePermissionMode()}`);\n return;\n }\n });\n\n const handleEscape = useCallback(() => {\n if (overlay !== \"none\") setOverlay(\"none\");\n else if (task.agentState === \"busy\" || task.agentState === \"awaiting-input\") task.abort();\n }, [overlay, task]);\n\n const handleHelp = useCallback(() => {\n setOverlay((prev) => (prev === \"help\" ? \"none\" : \"help\"));\n }, []);\n\n const handleSubmit = useCallback(\n (value: string) => {\n const cmd = parseSlashCommand(value);\n if (cmd) {\n switch (cmd.command) {\n case \"help\": setOverlay(\"help\"); return;\n case \"config\": setOverlay(\"config\"); return;\n case \"model\":\n if (cmd.arg) { setModel(cmd.arg); setNotification(`Model: ${cmd.arg}`); }\n else setOverlay(\"model\");\n return;\n case \"mode\":\n if (cmd.arg) { setPermissionMode(cmd.arg as TuiSettings[\"permissionMode\"]); setNotification(`Mode: ${cmd.arg}`); }\n else setOverlay(\"mode\");\n return;\n case \"thinking\":\n if (cmd.arg) {\n const tp = cmd.arg as \"adaptive\" | \"enabled\" | \"disabled\";\n setThinking({ type: tp, ...(tp === \"enabled\" ? { budgetTokens: 32768 } : {}) });\n setNotification(`Thinking: ${cmd.arg}`);\n } else setOverlay(\"thinking\");\n return;\n case \"status\": setOverlay(\"status\"); return;\n case \"clear\":\n clearMessages();\n committedIdsRef.current.clear();\n setStaticItems([{\n key: `welcome-${Date.now()}`,\n node: <WelcomeHeader settings={settings} workspacePath={workspacePath} />,\n }]);\n setNotification(\"Conversation cleared\");\n return;\n case \"compact\": setNotification(\"Compact not yet implemented\"); return;\n case \"exit\": exit(); return;\n }\n }\n addUserMessage(value);\n task.dispatch(value);\n },\n [addUserMessage, task, setModel, setThinking, setPermissionMode, clearMessages, exit, settings, workspacePath],\n );\n\n const closeOverlay = useCallback(() => setOverlay(\"none\"), []);\n\n // ==========================================================================\n // Render\n // ==========================================================================\n\n return (\n <Box flexDirection=\"column\">\n {/* All committed output — rendered once, scrolls naturally in terminal */}\n <Static items={staticItems}>\n {(item) => (\n <Box key={item.key} flexDirection=\"column\">\n {item.node}\n </Box>\n )}\n </Static>\n\n {/* === Everything below is the ONLY dynamic area === */}\n\n {/* Spinner (shown while agent is working) */}\n {task.agentState === \"busy\" && <Spinner />}\n\n {/* Overlays */}\n {overlay === \"help\" && <HelpMenu onClose={closeOverlay} />}\n {overlay === \"status\" && (\n <StatusDisplay settings={settings} connected={client.connected} sessionId={task.sessionId} totalTokens={task.totalTokens} workspacePath={workspacePath} onClose={closeOverlay} />\n )}\n {overlay === \"config\" && (\n <SettingsDialog settings={settings} onUpdateModel={setModel} onUpdateThinking={setThinking} onUpdateMode={setPermissionMode} onUpdateMaxTurns={setMaxTurns} onClose={closeOverlay} />\n )}\n {overlay === \"model\" && (\n <ModelPicker currentModel={settings.model} onSelect={setModel} onClose={closeOverlay} />\n )}\n {overlay === \"mode\" && (\n <ModePicker currentMode={settings.permissionMode} onSelect={setPermissionMode} onClose={closeOverlay} />\n )}\n {overlay === \"thinking\" && (\n <ThinkingPicker current={settings.thinking} onSelect={setThinking} onClose={closeOverlay} />\n )}\n\n {/* Permission dialogs */}\n {task.pendingInput && task.agentState === \"awaiting-input\" && (\n <>\n {task.pendingInput.type === \"tool\" && (\n <PermissionDialog input={task.pendingInput} onRespond={task.respondToInput} />\n )}\n {task.pendingInput.type === \"plan\" && (\n <PlanReview input={task.pendingInput} onRespond={task.respondToInput} />\n )}\n {task.pendingInput.type === \"max_iterations\" && (\n <MaxIterations input={task.pendingInput} onRespond={task.respondToInput} />\n )}\n </>\n )}\n\n {/* Notification */}\n <Notification message={notification} />\n\n {/* Bottom bar */}\n <Divider />\n <Box paddingX={0} marginY={0}>\n <PromptInput\n onSubmit={handleSubmit}\n onEscape={handleEscape}\n onHelp={handleHelp}\n onSlashCommand={handleSubmit}\n isLoading={task.agentState !== \"idle\"}\n workspacePath={workspacePath}\n />\n </Box>\n <Divider />\n <StatusBar\n mode={settings.permissionMode}\n model={settings.model}\n thinking={settings.thinking}\n agentState={task.agentState}\n totalTokens={task.totalTokens}\n connected={client.connected}\n sessionId={task.sessionId}\n workspacePath={workspacePath}\n />\n </Box>\n );\n}\n\n// =============================================================================\n// Message renderer — creates the React node for a committed message\n// =============================================================================\n\nfunction renderMessage(m: DisplayMessage): React.ReactNode {\n // User messages — gold arrow, extra spacing above\n if (m.type === \"user\") {\n return (\n <Box marginTop={1}>\n <UserMessage content={m.content} />\n </Box>\n );\n }\n\n // Tool calls — colored dot + tool name + description\n if (m.type === \"tool\") {\n const status = m.toolCall?.status ?? \"running\";\n const dot = status === \"completed\" ? t.toolSuccess : status === \"error\" ? t.toolError : t.toolRunning;\n const desc = getToolDesc(m.toolCall);\n return (\n <Box>\n <Box width={2} flexShrink={0}><Text color={dot}>●</Text></Box>\n <Text bold>{m.toolCall?.toolName ?? \"Tool\"}</Text>\n {desc && <Text color={t.dim}> {desc}</Text>}\n {m.toolCall?.error && <Text color={t.toolError}> {truncate(m.toolCall.error, 60)}</Text>}\n </Box>\n );\n }\n\n // Thinking — dim dot + muted content, spacing above\n if (m.type === \"thinking\") {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Box>\n <Box width={2} flexShrink={0}><Text color={t.dim}>●</Text></Box>\n <Text color={t.dim} underline>Thinking</Text>\n </Box>\n {m.content && (\n <Box paddingLeft={2}>\n <Text color={t.dim}>{m.content}</Text>\n </Box>\n )}\n </Box>\n );\n }\n\n // Assistant text — green dot + markdown, spacing above\n if (m.type === \"assistant-text\") {\n return (\n <Box flexDirection=\"row\" marginTop={1}>\n <Box width={2} flexShrink={0}><Text color={t.toolSuccess}>●</Text></Box>\n <Box flexDirection=\"column\" flexGrow={1}>\n <MarkdownText content={m.content} />\n </Box>\n </Box>\n );\n }\n\n return null;\n}\n\nfunction getToolDesc(toolCall?: DisplayMessage[\"toolCall\"]): string {\n if (!toolCall) return \"\";\n const { toolName, input, output } = toolCall;\n if (toolCall.status === \"completed\" && output != null) {\n const out = String(output);\n if (out.length < 50 && !out.includes(\"\\n\")) return out;\n }\n if (!input) return \"\";\n switch (toolName) {\n case \"Read\": return String(input.file_path ?? \"\");\n case \"Write\": return String(input.file_path ?? \"\");\n case \"Edit\": return String(input.file_path ?? \"\");\n case \"Bash\": return truncate(String(input.command ?? \"\"), 50);\n case \"Glob\": return String(input.pattern ?? \"\");\n case \"Grep\": return String(input.pattern ?? \"\");\n case \"Agent\": return String(input.description ?? \"\");\n default: return \"\";\n }\n}\n\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + \"…\";\n}\n","/**\n * useAgentClient — JSON-RPC client for the agent, via the cloud hub.\n *\n * Flow:\n * 1. Read runner token + hub URL from ~/.jarvis/config.json\n * 2. Exchange runner token for a `scope: \"client\"` JWT via /api/v1/ws/token\n * 3. Connect to hub at config.apiUrl with `?token=<clientJwt>`\n * 4. Same RPC surface as before (`agent.run`, `agent.interrupt`, `agent.userInput`)\n *\n * The hub forwards method calls to the registered runner for this user/env.\n */\n\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport crypto from \"crypto\";\nimport WebSocket from \"ws\";\n\nimport { rpcClient, type JsonRpcClient } from \"@jarvis/transport\";\nimport type { RunAgentRequest, Context } from \"@jarvis/types\";\n\nimport { loadConfig, getDefaultAppUrl } from \"../../config\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface AgentNotification {\n method: string;\n params: unknown;\n}\n\nexport interface AgentClientState {\n connected: boolean;\n dispatchTask: (task: RunAgentRequest) => void;\n interruptTask: (taskId: string, reason?: string) => void;\n respondToInput: (\n inputId: string,\n action: string,\n data?: Record<string, unknown>,\n feedback?: string,\n ) => void;\n}\n\nfunction localCtx(): Context {\n return { userId: \"\", requestId: crypto.randomUUID(), timestamp: Date.now() };\n}\n\nasync function fetchClientToken(appUrl: string, runnerToken: string): Promise<string> {\n const res = await fetch(`${appUrl}/api/v1/ws/token`, {\n headers: { authorization: `Bearer ${runnerToken}` },\n });\n if (!res.ok) throw new Error(`token exchange failed: ${res.status}`);\n const { token } = (await res.json()) as { token: string };\n return token;\n}\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useAgentClient(\n onNotification: (note: AgentNotification) => void,\n): AgentClientState {\n const [connected, setConnected] = useState(false);\n const wsRef = useRef<WebSocket | null>(null);\n const closedRef = useRef(false);\n const clientRef = useRef<JsonRpcClient | null>(null);\n const onNotificationRef = useRef(onNotification);\n onNotificationRef.current = onNotification;\n\n useEffect(() => {\n closedRef.current = false;\n\n async function tryConnect() {\n if (closedRef.current) return;\n\n const config = loadConfig();\n if (!config?.apiUrl || !config?.token) {\n // Not connected to a cloud — retry; user may run `jarvis connect` mid-session.\n if (!closedRef.current) setTimeout(() => void tryConnect(), 3000);\n return;\n }\n\n let clientToken: string;\n try {\n const appUrl = config.appUrl ?? getDefaultAppUrl();\n clientToken = await fetchClientToken(appUrl, config.token);\n } catch {\n if (!closedRef.current) setTimeout(() => void tryConnect(), 3000);\n return;\n }\n\n try {\n const url = `${config.apiUrl}?token=${encodeURIComponent(clientToken)}`;\n const ws = new WebSocket(url);\n wsRef.current = ws;\n\n const client = rpcClient({\n send: (frame) => {\n if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify(frame));\n },\n });\n clientRef.current = client;\n\n ws.on(\"open\", () => setConnected(true));\n\n ws.on(\"message\", (raw) => {\n try {\n const frame = JSON.parse(raw.toString()) as {\n jsonrpc?: string;\n method?: string;\n params?: unknown;\n };\n if (frame.method === \"pong\") return;\n\n if (frame.jsonrpc === \"2.0\" && \"id\" in frame) {\n client.deliver(frame);\n return;\n }\n\n if (frame.jsonrpc === \"2.0\" && typeof frame.method === \"string\") {\n onNotificationRef.current({ method: frame.method, params: frame.params });\n }\n } catch {\n /* malformed — ignore */\n }\n });\n\n ws.on(\"close\", () => {\n setConnected(false);\n client.failAll(new Error(\"ws_closed\"));\n clientRef.current = null;\n if (!closedRef.current) setTimeout(() => void tryConnect(), 3000);\n });\n\n ws.on(\"error\", () => {\n /* triggers close → reconnect */\n });\n } catch {\n if (!closedRef.current) setTimeout(() => void tryConnect(), 3000);\n }\n }\n\n void tryConnect();\n\n return () => {\n closedRef.current = true;\n wsRef.current?.close();\n wsRef.current = null;\n clientRef.current = null;\n };\n }, []);\n\n const dispatchTask = useCallback((task: RunAgentRequest) => {\n clientRef.current\n ?.call(localCtx(), { method: \"agent.run\", params: task })\n .catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[tui] agents.run failed\", err);\n });\n }, []);\n\n const interruptTask = useCallback((taskId: string, reason?: string) => {\n clientRef.current\n ?.call(localCtx(), {\n method: \"agent.interrupt\",\n params: { taskId, ...(reason ? { reason } : {}) },\n })\n .catch(() => {});\n }, []);\n\n const respondToInput = useCallback(\n (\n inputId: string,\n action: string,\n data?: Record<string, unknown>,\n feedback?: string,\n ) => {\n clientRef.current\n ?.call(localCtx(), {\n method: \"agent.userInput\",\n params: {\n inputId,\n action,\n ...(data ? { data } : {}),\n ...(feedback !== undefined ? { feedback } : {}),\n },\n })\n .catch(() => {});\n },\n [],\n );\n\n return { connected, dispatchTask, interruptTask, respondToInput };\n}\n","/**\n * useMessages Hook\n *\n * Manages the message list state from `agents.onMessage` + `agents.onToken`\n * notifications. Messages are keyed by id — partial messages get replaced\n * when updated. Token events are throttled to reduce re-render churn.\n */\n\nimport { useState, useCallback, useRef } from \"react\";\n\nimport type { OnAgentTokenParams, ChatMessage } from \"@jarvis/types\";\n\ntype ChatMeta = NonNullable<ChatMessage[\"metadata\"]>;\n\nexport interface DisplayMessage {\n id: string;\n type: \"user\" | \"assistant-text\" | \"thinking\" | \"tool\" | \"status\";\n content: string;\n toolCall?: ChatMeta[\"toolCall\"];\n thinking?: ChatMeta[\"thinking\"];\n ui?: ChatMeta[\"ui\"];\n isPartial?: boolean;\n createdAt?: string;\n}\n\nexport interface MessagesState {\n messages: DisplayMessage[];\n streamingTextContent: string | null;\n addUserMessage: (content: string) => void;\n handleChatMessage: (msg: ChatMessage) => void;\n handleTokenEvent: (event: OnAgentTokenParams) => void;\n clearMessages: () => void;\n}\n\nconst TOKEN_THROTTLE_MS = 80; // ~12fps for streaming text\n\nexport function useMessages(): MessagesState {\n const [messages, setMessages] = useState<DisplayMessage[]>([]);\n const [streamingTextContent, setStreamingTextContent] = useState<string | null>(null);\n const streamingIdRef = useRef<string | null>(null);\n const throttleRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingContentRef = useRef<string | null>(null);\n\n const addUserMessage = useCallback((content: string) => {\n const msg: DisplayMessage = {\n id: `user-${Date.now()}`,\n type: \"user\",\n content,\n createdAt: new Date().toISOString(),\n };\n setMessages((prev) => [...prev, msg]);\n }, []);\n\n const handleChatMessage = useCallback((msg: ChatMessage) => {\n const display: DisplayMessage = {\n id: msg.id,\n type:\n msg.type === \"thinking\"\n ? \"thinking\"\n : msg.type === \"tool\"\n ? \"tool\"\n : msg.type === \"status\"\n ? \"status\"\n : \"assistant-text\",\n content: msg.content,\n toolCall: msg.metadata?.toolCall,\n thinking: msg.metadata?.thinking,\n ui: msg.metadata?.ui,\n isPartial: msg.metadata?.isPartial,\n createdAt: msg.createdAt,\n };\n\n setMessages((prev) => {\n const idx = prev.findIndex((m) => m.id === msg.id);\n if (idx >= 0) {\n const updated = [...prev];\n updated[idx] = display;\n return updated;\n }\n return [...prev, display];\n });\n }, []);\n\n const flushStreamingContent = useCallback(() => {\n if (pendingContentRef.current !== null) {\n setStreamingTextContent(pendingContentRef.current);\n }\n throttleRef.current = null;\n }, []);\n\n const handleTokenEvent = useCallback(\n (event: OnAgentTokenParams) => {\n if (event.isComplete) {\n if (throttleRef.current) {\n clearTimeout(throttleRef.current);\n throttleRef.current = null;\n }\n streamingIdRef.current = null;\n pendingContentRef.current = null;\n setStreamingTextContent(null);\n setMessages((prev) => {\n const existing = prev.findIndex((m) => m.id === event.messageId);\n const finalMsg: DisplayMessage = {\n id: event.messageId,\n type: \"assistant-text\",\n content: event.content,\n isPartial: false,\n createdAt: new Date().toISOString(),\n };\n if (existing >= 0) {\n const updated = [...prev];\n updated[existing] = finalMsg;\n return updated;\n }\n return [...prev, finalMsg];\n });\n } else {\n streamingIdRef.current = event.messageId;\n pendingContentRef.current = event.content;\n if (!throttleRef.current) {\n setStreamingTextContent(event.content);\n throttleRef.current = setTimeout(flushStreamingContent, TOKEN_THROTTLE_MS);\n }\n }\n },\n [flushStreamingContent],\n );\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n setStreamingTextContent(null);\n streamingIdRef.current = null;\n pendingContentRef.current = null;\n if (throttleRef.current) {\n clearTimeout(throttleRef.current);\n throttleRef.current = null;\n }\n }, []);\n\n return {\n messages,\n streamingTextContent,\n addUserMessage,\n handleChatMessage,\n handleTokenEvent,\n clearMessages,\n };\n}\n","/**\n * useTask Hook\n *\n * Manages task lifecycle: dispatch, abort, user input responses. Constructs\n * `agents.run` requests from TUI settings.\n */\n\nimport { useState, useCallback, useRef } from \"react\";\nimport crypto from \"crypto\";\n\nimport type { RunAgentRequest, PendingUserInput } from \"@jarvis/types\";\n\nimport type { TuiSettings } from \"../settings\";\nimport type { AgentClientState } from \"./use-agent-client\";\n\nexport type AgentState = \"idle\" | \"busy\" | \"awaiting-input\";\n\nexport interface TaskState {\n agentState: AgentState;\n currentTaskId: string | null;\n sessionId: string | null;\n totalTokens: number;\n pendingInput: PendingUserInput | null;\n dispatch: (userMessage: string) => void;\n abort: () => void;\n respondToInput: (\n action: string,\n data?: Record<string, unknown>,\n feedback?: string,\n ) => void;\n setAgentState: (state: AgentState) => void;\n setPendingInput: (input: PendingUserInput | null) => void;\n addTokens: (tokens: number) => void;\n setSessionId: (id: string) => void;\n}\n\nexport function useTask(client: AgentClientState, settings: TuiSettings): TaskState {\n const [agentState, setAgentState] = useState<AgentState>(\"idle\");\n const [currentTaskId, setCurrentTaskId] = useState<string | null>(null);\n const [sessionId, setSessionId] = useState<string | null>(null);\n const [totalTokens, setTotalTokens] = useState(0);\n const [pendingInput, setPendingInput] = useState<PendingUserInput | null>(null);\n const chatIdRef = useRef(`chat-${crypto.randomUUID()}`);\n\n const dispatch = useCallback(\n (userMessage: string) => {\n const runId = crypto.randomUUID();\n setCurrentTaskId(runId);\n setAgentState(\"busy\");\n\n const req: RunAgentRequest = {\n runId,\n chatId: chatIdRef.current,\n messages: [{ role: \"user\", content: userMessage }],\n modelId: settings.model,\n maxTurns: settings.maxTurns,\n mode:\n settings.permissionMode === \"yolo\"\n ? \"auto\"\n : settings.permissionMode === \"supervised\"\n ? \"ask\"\n : settings.permissionMode,\n disallowedTools:\n settings.disallowedTools.length > 0 ? settings.disallowedTools : undefined,\n ...(sessionId\n ? { session: { resume: sessionId, persist: true } }\n : { session: { persist: true } }),\n };\n\n client.dispatchTask(req);\n },\n [client, settings, sessionId],\n );\n\n const abort = useCallback(() => {\n if (currentTaskId) client.interruptTask(currentTaskId);\n }, [client, currentTaskId]);\n\n const respondToInput = useCallback(\n (\n action: string,\n data?: Record<string, unknown>,\n feedback?: string,\n ) => {\n if (currentTaskId && pendingInput) {\n client.respondToInput(pendingInput.id, action, data, feedback);\n setPendingInput(null);\n setAgentState(\"busy\");\n }\n },\n [client, currentTaskId, pendingInput],\n );\n\n const addTokens = useCallback((tokens: number) => {\n setTotalTokens((prev) => prev + tokens);\n }, []);\n\n return {\n agentState,\n currentTaskId,\n sessionId,\n totalTokens,\n pendingInput,\n dispatch,\n abort,\n respondToInput,\n setAgentState,\n setPendingInput,\n addTokens,\n setSessionId,\n };\n}\n","/**\n * useSettings Hook\n *\n * Runtime settings state with persistence to ~/.jarvis/settings.json.\n */\n\nimport { useState, useCallback } from \"react\";\n\nimport type { ThinkingConfig } from \"@jarvis/types\";\n\nimport {\n type TuiSettings,\n type PermissionMode,\n saveSettings,\n} from \"../settings\";\n\nconst MODE_CYCLE: PermissionMode[] = [\"supervised\", \"auto\", \"plan\", \"yolo\"];\n\nexport interface SettingsState {\n settings: TuiSettings;\n setModel: (model: string) => void;\n setThinking: (thinking: ThinkingConfig) => void;\n setPermissionMode: (mode: PermissionMode) => void;\n cyclePermissionMode: () => PermissionMode;\n setMaxTurns: (turns: number) => void;\n setTheme: (theme: \"dark\" | \"light\") => void;\n}\n\nexport function useSettings(initial: TuiSettings): SettingsState {\n const [settings, setSettings] = useState<TuiSettings>(initial);\n\n const update = useCallback((patch: Partial<TuiSettings>) => {\n setSettings((prev) => {\n const next = { ...prev, ...patch };\n saveSettings(next);\n return next;\n });\n }, []);\n\n const setModel = useCallback(\n (model: string) => update({ model }),\n [update],\n );\n\n const setThinking = useCallback(\n (thinking: ThinkingConfig) => update({ thinking }),\n [update],\n );\n\n const setPermissionMode = useCallback(\n (permissionMode: PermissionMode) => update({ permissionMode }),\n [update],\n );\n\n const cyclePermissionMode = useCallback(() => {\n let nextMode: PermissionMode = \"supervised\";\n setSettings((prev) => {\n const idx = MODE_CYCLE.indexOf(prev.permissionMode);\n nextMode = MODE_CYCLE[(idx + 1) % MODE_CYCLE.length]!;\n const next = { ...prev, permissionMode: nextMode };\n saveSettings(next);\n return next;\n });\n return nextMode;\n }, []);\n\n const setMaxTurns = useCallback(\n (maxTurns: number) => update({ maxTurns }),\n [update],\n );\n\n const setTheme = useCallback(\n (theme: \"dark\" | \"light\") => update({ theme }),\n [update],\n );\n\n return {\n settings,\n setModel,\n setThinking,\n setPermissionMode,\n cyclePermissionMode,\n setMaxTurns,\n setTheme,\n };\n}\n","/**\n * Slash Command Parser\n *\n * Parses /command [args] from user input.\n */\n\nexport type SlashCommand =\n | { command: \"help\" }\n | { command: \"config\" }\n | { command: \"model\"; arg?: string }\n | { command: \"mode\"; arg?: string }\n | { command: \"thinking\"; arg?: string }\n | { command: \"status\" }\n | { command: \"clear\" }\n | { command: \"compact\" }\n | { command: \"exit\" };\n\nexport function parseSlashCommand(input: string): SlashCommand | null {\n const trimmed = input.trim();\n if (!trimmed.startsWith(\"/\")) return null;\n\n const parts = trimmed.split(/\\s+/);\n const cmd = parts[0]!.slice(1).toLowerCase();\n const arg = parts.slice(1).join(\" \") || undefined;\n\n switch (cmd) {\n case \"help\":\n case \"h\":\n return { command: \"help\" };\n case \"config\":\n case \"settings\":\n return { command: \"config\" };\n case \"model\":\n case \"m\":\n return { command: \"model\", arg };\n case \"mode\":\n return { command: \"mode\", arg };\n case \"thinking\":\n return { command: \"thinking\", arg };\n case \"status\":\n return { command: \"status\" };\n case \"clear\":\n return { command: \"clear\" };\n case \"compact\":\n return { command: \"compact\" };\n case \"exit\":\n case \"quit\":\n case \"q\":\n return { command: \"exit\" };\n default:\n return null;\n }\n}\n","/**\n * Auto-Approval Logic\n *\n * Determines whether a tool should be auto-approved based on permission mode.\n */\n\nimport type { PendingUserInput } from \"@jarvis/types\";\n\nimport type { PermissionMode } from \"../settings\";\n\n/** Tools considered safe for auto-approval in \"auto\" mode */\nconst SAFE_TOOLS = new Set([\n \"Read\",\n \"Glob\",\n \"Grep\",\n \"WebSearch\",\n \"WebFetch\",\n \"Agent\",\n \"TodoWrite\",\n \"Skill\",\n \"ToolSearch\",\n]);\n\n/**\n * Returns true if the pending input should be auto-approved without showing a dialog.\n */\nexport function shouldAutoApprove(\n mode: PermissionMode,\n input: PendingUserInput,\n): boolean {\n // Plan type always needs review in plan mode, auto-approve otherwise\n if (input.type === \"plan\") {\n return mode !== \"plan\" && mode !== \"supervised\";\n }\n\n // Max iterations: always ask\n if (input.type === \"max_iterations\") {\n return false;\n }\n\n // Yolo mode: approve everything\n if (mode === \"yolo\") return true;\n\n // Auto mode: approve safe tools, ask for dangerous\n if (mode === \"auto\") {\n const toolName = input.toolName ?? \"\";\n return SAFE_TOOLS.has(toolName);\n }\n\n // Supervised/plan: never auto-approve tools\n return false;\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport type { TuiSettings } from \"../settings\";\nimport { t } from \"../theme\";\n\ninterface WelcomeHeaderProps {\n settings: TuiSettings;\n workspacePath: string;\n}\n\nconst LOGO = [\n \" ╦╔═╗╦═╗╦ ╦╦╔═╗\",\n \" ║╠═╣╠╦╝╚╗╔╝║╚═╗\",\n \" ╚╝╩ ╩╩╚═ ╚╝ ╩╚═╝\",\n];\n\nfunction shortModel(model: string): string {\n const m = model.match(/(sonnet|opus|haiku)[- ](\\d+(?:\\.\\d+)?)/i);\n if (m) return `${m[1]![0]!.toUpperCase()}${m[1]!.slice(1)} ${m[2]}`;\n return model;\n}\n\nfunction shortPath(p: string): string {\n const home = process.env.HOME ?? \"\";\n if (home && p.startsWith(home)) return \"~\" + p.slice(home.length);\n return p;\n}\n\nexport function WelcomeHeader({ settings, workspacePath }: WelcomeHeaderProps) {\n return (\n <Box flexDirection=\"column\" paddingTop={1} paddingBottom={0}>\n <Box flexDirection=\"column\" paddingLeft={4}>\n {LOGO.map((line, i) => (\n <Text key={i} color={t.logo} bold>{line}</Text>\n ))}\n </Box>\n <Box flexDirection=\"column\" paddingLeft={4} marginTop={0}>\n <Text>\n <Text color={t.logo} bold>Jarvis</Text>\n <Text color={t.dim}>{\" v0.1.0\"}</Text>\n </Text>\n <Text color={t.dim}>\n {shortModel(settings.model)} · {settings.permissionMode}\n </Text>\n <Text color={t.dim}>\n {shortPath(workspacePath)}\n </Text>\n </Box>\n </Box>\n );\n}\n","/**\n * TUI Theme\n *\n * JARVIS terminal color palette — matches the web app theme:\n * Primary: #FFB800 (gold/amber — Iron Man's gold)\n * Secondary: #DC4545 (soft red — Iron Man's red)\n * Neutral: #1E293B (navy-tinted gray)\n *\n * Only accents/indicators are colorful. Regular text stays default.\n */\n\n// =============================================================================\n// Brand Colors (hex values for Ink's `color` prop)\n// =============================================================================\n\nexport const colors = {\n // Primary — gold\n gold: \"#FFB800\",\n goldDim: \"#B38200\",\n goldBg: \"#3D2E00\",\n\n // Secondary — red\n red: \"#DC4545\",\n redDim: \"#991B1B\",\n\n // Accent — purple (from SDK theme)\n purple: \"#8270DB\",\n\n // Status\n green: \"#22C55E\",\n yellow: \"#FFB800\",\n cyan: \"#06B6D4\",\n\n // Neutral\n navy: \"#1E293B\",\n navyLight: \"#64748B\",\n navyLighter: \"#94A3B8\",\n\n // Foreground\n text: undefined, // default terminal color\n dim: \"#64748B\",\n muted: \"#94A3B8\",\n} as const;\n\n// =============================================================================\n// Semantic tokens — what color each UI element uses\n// =============================================================================\n\nexport const t = {\n // Logo & branding\n logo: colors.gold,\n\n // Prompt\n promptArrow: colors.gold,\n\n // Spinner / working indicator\n spinner: colors.gold,\n\n // Divider\n divider: colors.navyLight,\n\n // Tool icons\n toolSuccess: colors.green,\n toolError: colors.red,\n toolRunning: colors.gold,\n\n // Permission mode indicator\n mode: {\n supervised: colors.green,\n auto: colors.gold,\n plan: colors.purple,\n yolo: colors.red,\n } as Record<string, string>,\n\n // Headings in markdown\n heading: colors.gold,\n\n // Slash commands in help menu\n command: colors.gold,\n\n // Status bar\n hint: colors.dim,\n disconnected: colors.red,\n\n // Overlays — border accents\n dialogBorder: colors.navyLight,\n dialogTitle: colors.gold,\n dialogAction: colors.gold,\n dialogDanger: colors.red,\n\n // Notification flash\n notification: colors.gold,\n\n // Dim / muted text\n dim: colors.dim,\n muted: colors.muted,\n} as const;\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport { t } from \"../theme\";\n\ninterface UserMessageProps {\n content: string;\n}\n\nexport function UserMessage({ content }: UserMessageProps) {\n return (\n <Box marginTop={1}>\n <Text color={t.promptArrow} bold>{\"❯ \"}</Text>\n <Text>{content}</Text>\n </Box>\n );\n}\n","import React, { useState, useEffect, useRef } from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport { t } from \"../theme\";\n\n// =============================================================================\n// Fake word generator (from packages/ui StreamingText)\n// =============================================================================\n\nconst PREFIXES = [\n \"Pro\", \"Re\", \"De\", \"Con\", \"Syn\", \"Meta\", \"Hyper\", \"Trans\",\n \"Neo\", \"Poly\", \"Multi\", \"Sub\", \"Inter\", \"Ultra\", \"Semi\",\n \"Auto\", \"Para\", \"Mono\",\n];\nconst ROOTS = [\n \"cog\", \"flux\", \"morph\", \"lex\", \"graph\", \"lys\", \"gen\", \"struct\",\n \"val\", \"duc\", \"fract\", \"gress\", \"ject\", \"spect\", \"vert\", \"tract\",\n \"form\", \"plex\", \"crypt\", \"volt\", \"quant\", \"phas\", \"nex\", \"fus\",\n];\nconst SUFFIXES = [\n \"izing\", \"ating\", \"ifying\", \"enting\", \"uting\", \"ecting\", \"uming\",\n \"ering\", \"ising\", \"ancing\", \"encing\", \"oring\", \"uring\", \"aling\",\n];\n\nfunction pick<T>(arr: T[]): T {\n return arr[Math.floor(Math.random() * arr.length)]!;\n}\n\nfunction generateWord(): string {\n const usePrefix = Math.random() > 0.3;\n const prefix = usePrefix ? pick(PREFIXES) : \"\";\n const root = pick(ROOTS);\n const suffix = pick(SUFFIXES);\n const word = prefix + root + suffix;\n return word.charAt(0).toUpperCase() + word.slice(1);\n}\n\n// =============================================================================\n// Spinner glyph — Claude Code style: growing/shrinking symbols\n// Wrapped in fixed-width Box to prevent jumpiness\n// =============================================================================\n\nconst GLYPHS =\n process.platform === \"darwin\"\n ? [\"·\", \"✢\", \"✳\", \"✶\", \"✻\", \"✽\"]\n : [\"·\", \"✢\", \"*\", \"✶\", \"✻\", \"✽\"];\n\nconst GLYPH_FRAMES = [...GLYPHS, ...[...GLYPHS].reverse()];\n\n// =============================================================================\n// Component\n// =============================================================================\n\nexport function Spinner() {\n const [glyphFrame, setGlyphFrame] = useState(0);\n const [word, setWord] = useState(generateWord);\n const [overwriteIdx, setOverwriteIdx] = useState(0);\n const [prevWord, setPrevWord] = useState(\"\");\n const [phase, setPhase] = useState<\"display\" | \"transition\">(\"display\");\n const startRef = useRef(Date.now());\n\n // Glyph animation: 120ms per frame\n useEffect(() => {\n const timer = setInterval(\n () => setGlyphFrame((f) => (f + 1) % GLYPH_FRAMES.length),\n 120,\n );\n return () => clearInterval(timer);\n }, []);\n\n // Word transition: overwrite char by char at 50ms\n useEffect(() => {\n if (phase === \"transition\") {\n const totalLen = (prevWord + \"…\").length;\n if (overwriteIdx < totalLen) {\n const timer = setTimeout(() => setOverwriteIdx((i) => i + 1), 50);\n return () => clearTimeout(timer);\n } else {\n setPhase(\"display\");\n }\n }\n }, [overwriteIdx, prevWord, phase]);\n\n // Wait then start next word transition\n useEffect(() => {\n if (phase === \"display\") {\n const timer = setTimeout(() => {\n setPrevWord(word);\n setWord(generateWord());\n setOverwriteIdx(0);\n setPhase(\"transition\");\n }, 2500);\n return () => clearTimeout(timer);\n }\n }, [phase, word]);\n\n const elapsed = Math.floor((Date.now() - startRef.current) / 1000);\n\n // Build display text\n let displayText: string;\n if (phase === \"display\") {\n displayText = word + \"…\";\n } else {\n const oldText = prevWord + \"…\";\n const newText = word + \"…\";\n displayText = newText.slice(0, overwriteIdx) + oldText.slice(overwriteIdx);\n }\n\n return (\n <Box marginTop={1}>\n <Box width={2} flexShrink={0}>\n <Text color={t.spinner}>{GLYPH_FRAMES[glyphFrame]}</Text>\n </Box>\n <Text color={t.spinner}>{displayText}</Text>\n {elapsed > 2 && <Text color={t.dim}> {elapsed}s</Text>}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport { t } from \"../theme\";\nimport { useTerminal } from \"../hooks/use-terminal\";\n\nexport function Divider() {\n const { columns } = useTerminal();\n return (\n <Box>\n <Text color={t.divider}>{\"─\".repeat(columns)}</Text>\n </Box>\n );\n}\n","/**\n * useTerminal Hook\n *\n * Terminal dimensions with resize tracking.\n */\n\nimport { useState, useEffect } from \"react\";\n\nexport interface TerminalSize {\n columns: number;\n rows: number;\n}\n\nexport function useTerminal(): TerminalSize {\n const [size, setSize] = useState<TerminalSize>({\n columns: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n });\n\n useEffect(() => {\n const onResize = () => {\n setSize({\n columns: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n });\n };\n\n process.stdout.on(\"resize\", onResize);\n return () => {\n process.stdout.off(\"resize\", onResize);\n };\n }, []);\n\n return size;\n}\n","/**\n * PromptInput with autocomplete\n *\n * Detects:\n * - `/` at start → slash command suggestions\n * - `@` → file picker suggestions\n * - `?` on empty input → help toggle\n * - Esc → abort/close\n * - Arrow keys → navigate suggestions when open\n * - Enter → select suggestion or submit\n * - Tab → accept suggestion\n */\n\nimport React, { useState, useCallback, useMemo } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport TextInput from \"ink-text-input\";\n\nimport { t } from \"../theme\";\nimport {\n type Suggestion,\n filterSlashCommands,\n Suggestions,\n} from \"./suggestions\";\nimport { filterFiles, FilePicker } from \"./file-picker\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\ntype PickerMode = \"none\" | \"slash\" | \"file\";\n\ninterface PromptInputProps {\n onSubmit: (value: string) => void;\n onEscape: () => void;\n onHelp: () => void;\n onSlashCommand: (command: string) => void;\n isLoading?: boolean;\n workspacePath: string;\n}\n\n// =============================================================================\n// Component\n// =============================================================================\n\nexport function PromptInput({\n onSubmit,\n onEscape,\n onHelp,\n onSlashCommand,\n isLoading,\n workspacePath,\n}: PromptInputProps) {\n const [value, setValue] = useState(\"\");\n const [selectedIdx, setSelectedIdx] = useState(0);\n\n // Detect picker mode from input\n const pickerMode: PickerMode = useMemo(() => {\n if (isLoading) return \"none\";\n if (value.startsWith(\"/\")) return \"slash\";\n // Detect @ at start or after whitespace\n const atMatch = value.match(/(^|\\s)@([^\\s]*)$/);\n if (atMatch) return \"file\";\n return \"none\";\n }, [value, isLoading]);\n\n // Get filtered suggestions\n const suggestions: Suggestion[] = useMemo(() => {\n if (pickerMode === \"slash\") {\n return filterSlashCommands(value.slice(1)); // remove leading /\n }\n if (pickerMode === \"file\") {\n const atMatch = value.match(/(^|\\s)@([^\\s]*)$/);\n const query = atMatch?.[2] ?? \"\";\n return filterFiles(query, workspacePath);\n }\n return [];\n }, [pickerMode, value, workspacePath]);\n\n // Reset selection when suggestions change\n const prevSugLen = React.useRef(suggestions.length);\n if (suggestions.length !== prevSugLen.current) {\n prevSugLen.current = suggestions.length;\n if (selectedIdx >= suggestions.length) {\n setSelectedIdx(Math.max(0, suggestions.length - 1));\n }\n }\n\n const handleMove = useCallback(\n (delta: number) => {\n setSelectedIdx((prev) => {\n const next = prev + delta;\n if (next < 0) return suggestions.length - 1;\n if (next >= suggestions.length) return 0;\n return next;\n });\n },\n [suggestions.length],\n );\n\n const handleSelectSuggestion = useCallback(\n (item: Suggestion) => {\n if (pickerMode === \"slash\") {\n // Execute the slash command directly\n setValue(\"\");\n onSlashCommand(item.value);\n } else if (pickerMode === \"file\") {\n // Replace @query with the file path\n const before = value.replace(/(^|\\s)@[^\\s]*$/, \"$1\");\n setValue(before + item.value + \" \");\n }\n setSelectedIdx(0);\n },\n [pickerMode, value, onSlashCommand],\n );\n\n const handleChange = useCallback(\n (text: string) => {\n if (!isLoading) {\n setValue(text);\n setSelectedIdx(0);\n }\n },\n [isLoading],\n );\n\n useInput((_input, key) => {\n // Escape\n if (key.escape) {\n if (pickerMode !== \"none\") {\n // Close suggestions by clearing the trigger char\n if (pickerMode === \"slash\") setValue(\"\");\n else setValue(value.replace(/(^|\\s)@[^\\s]*$/, \"$1\"));\n setSelectedIdx(0);\n } else {\n onEscape();\n }\n return;\n }\n\n // Arrow keys when suggestions are open\n if (pickerMode !== \"none\") {\n if (key.upArrow) {\n handleMove(-1);\n return;\n }\n if (key.downArrow) {\n handleMove(1);\n return;\n }\n if (key.tab && suggestions[selectedIdx]) {\n handleSelectSuggestion(suggestions[selectedIdx]);\n return;\n }\n }\n\n // ? on empty input → help\n if (_input === \"?\" && value === \"\" && !isLoading) {\n onHelp();\n return;\n }\n\n // Enter\n if (key.return) {\n // If suggestions open and one is selected, pick it\n if (pickerMode === \"slash\" && suggestions[selectedIdx]) {\n handleSelectSuggestion(suggestions[selectedIdx]);\n return;\n }\n // Otherwise submit\n if (value.trim() && !isLoading) {\n const text = value.trim();\n setValue(\"\");\n setSelectedIdx(0);\n onSubmit(text);\n }\n }\n });\n\n return (\n <Box flexDirection=\"column\">\n {/* Suggestions dropdown (above input) */}\n {pickerMode === \"slash\" && suggestions.length > 0 && (\n <Suggestions\n items={suggestions}\n selectedIndex={selectedIdx}\n />\n )}\n {pickerMode === \"file\" && suggestions.length > 0 && (\n <FilePicker\n items={suggestions}\n selectedIndex={selectedIdx}\n />\n )}\n\n {/* Input line */}\n <Box>\n <Text color={isLoading ? t.dim : t.promptArrow} dimColor={isLoading}>\n {\"❯ \"}\n </Text>\n <TextInput\n value={value}\n onChange={handleChange}\n placeholder=\"\"\n showCursor={!isLoading}\n />\n </Box>\n </Box>\n );\n}\n","/**\n * Suggestions Dropdown\n *\n * Renders filtered slash command suggestions.\n * Navigation is handled by PromptInput — this is a pure display component.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport { t } from \"../theme\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface Suggestion {\n id: string;\n icon: string;\n label: string;\n description: string;\n value: string;\n}\n\ninterface SuggestionsProps {\n items: Suggestion[];\n selectedIndex: number;\n maxVisible?: number;\n}\n\n// =============================================================================\n// Slash Commands\n// =============================================================================\n\nexport const SLASH_COMMANDS: Suggestion[] = [\n { id: \"help\", icon: \"?\", label: \"/help\", description: \"Show available commands\", value: \"/help\" },\n { id: \"config\", icon: \"⚙\", label: \"/config\", description: \"Open settings\", value: \"/config\" },\n { id: \"model\", icon: \"◆\", label: \"/model\", description: \"Switch model\", value: \"/model\" },\n { id: \"mode\", icon: \"●\", label: \"/mode\", description: \"Switch permission mode\", value: \"/mode\" },\n { id: \"thinking\", icon: \"▸\", label: \"/thinking\", description: \"Toggle thinking config\", value: \"/thinking\" },\n { id: \"status\", icon: \"ℹ\", label: \"/status\", description: \"Show session info\", value: \"/status\" },\n { id: \"clear\", icon: \"✕\", label: \"/clear\", description: \"Clear conversation\", value: \"/clear\" },\n { id: \"compact\", icon: \"◇\", label: \"/compact\", description: \"Compact old messages\", value: \"/compact\" },\n { id: \"exit\", icon: \"→\", label: \"/exit\", description: \"Exit Jarvis\", value: \"/exit\" },\n];\n\nexport function filterSlashCommands(query: string): Suggestion[] {\n const q = query.toLowerCase();\n if (!q) return SLASH_COMMANDS;\n return SLASH_COMMANDS.filter(\n (cmd) =>\n cmd.label.toLowerCase().includes(q) ||\n cmd.description.toLowerCase().includes(q),\n );\n}\n\n// =============================================================================\n// Component (pure display — no useInput)\n// =============================================================================\n\nexport function Suggestions({\n items,\n selectedIndex,\n maxVisible = 6,\n}: SuggestionsProps) {\n if (items.length === 0) return null;\n\n const half = Math.floor(maxVisible / 2);\n const startIdx = Math.max(\n 0,\n Math.min(selectedIndex - half, items.length - maxVisible),\n );\n const visible = items.slice(startIdx, startIdx + maxVisible);\n\n return (\n <Box flexDirection=\"column\" paddingLeft={2} marginBottom={0}>\n {visible.map((item, i) => {\n const realIdx = startIdx + i;\n const selected = realIdx === selectedIndex;\n return (\n <Box key={item.id}>\n <Text color={selected ? t.dialogTitle : t.dim}>\n {selected ? \"❯ \" : \" \"}\n </Text>\n <Text color={selected ? t.dialogTitle : undefined} bold={selected}>\n {item.icon} {item.label}\n </Text>\n <Text color={t.dim}>{\" \"}{item.description}</Text>\n </Box>\n );\n })}\n </Box>\n );\n}\n","/**\n * File Picker\n *\n * Triggered by @ in the input. Shows files matching the query.\n * Pure display component — navigation handled by PromptInput.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport path from \"path\";\nimport fs from \"fs\";\n\nimport { t } from \"../theme\";\nimport type { Suggestion } from \"./suggestions\";\n\n// =============================================================================\n// File scanning\n// =============================================================================\n\nlet cachedFiles: string[] | null = null;\n\nfunction scanFiles(workspacePath: string): string[] {\n if (cachedFiles) return cachedFiles;\n\n const results: string[] = [];\n const ignoreSet = new Set([\n \"node_modules\", \".git\", \"dist\", \"build\", \".next\", \"coverage\",\n \".turbo\", \".cache\", \"__pycache__\", \".DS_Store\",\n ]);\n\n function walk(dir: string, depth: number) {\n if (depth > 4) return;\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (ignoreSet.has(entry.name) || entry.name.startsWith(\".\")) continue;\n const full = path.join(dir, entry.name);\n const rel = path.relative(workspacePath, full);\n if (entry.isDirectory()) {\n results.push(rel + \"/\");\n walk(full, depth + 1);\n } else {\n results.push(rel);\n }\n if (results.length > 500) return;\n }\n } catch {\n // permission errors\n }\n }\n\n walk(workspacePath, 0);\n cachedFiles = results;\n return results;\n}\n\nexport function filterFiles(query: string, workspacePath: string): Suggestion[] {\n const files = scanFiles(workspacePath);\n const q = query.toLowerCase();\n\n const matches = q\n ? files.filter((f) => f.toLowerCase().includes(q))\n : files.slice(0, 20);\n\n return matches.slice(0, 20).map((f) => ({\n id: `file-${f}`,\n icon: f.endsWith(\"/\") ? \"📁\" : \"📄\",\n label: f,\n description: \"\",\n value: f,\n }));\n}\n\nexport function resetFileCache(): void {\n cachedFiles = null;\n}\n\n// =============================================================================\n// Component (pure display — no useInput)\n// =============================================================================\n\ninterface FilePickerProps {\n items: Suggestion[];\n selectedIndex: number;\n maxVisible?: number;\n}\n\nexport function FilePicker({\n items,\n selectedIndex,\n maxVisible = 8,\n}: FilePickerProps) {\n if (items.length === 0) {\n return (\n <Box paddingLeft={2}>\n <Text color={t.dim}>No files found</Text>\n </Box>\n );\n }\n\n const half = Math.floor(maxVisible / 2);\n const startIdx = Math.max(\n 0,\n Math.min(selectedIndex - half, items.length - maxVisible),\n );\n const visible = items.slice(startIdx, startIdx + maxVisible);\n\n return (\n <Box flexDirection=\"column\" paddingLeft={2} marginBottom={0}>\n {visible.map((item, i) => {\n const realIdx = startIdx + i;\n const selected = realIdx === selectedIndex;\n return (\n <Box key={item.id}>\n <Text color={selected ? t.dialogTitle : t.dim}>\n {selected ? \"❯ \" : \" \"}\n </Text>\n <Text color={selected ? t.dialogTitle : undefined} bold={selected}>\n {item.icon} {item.label}\n </Text>\n </Box>\n );\n })}\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nimport type { PermissionMode } from \"../settings\";\nimport type { AgentState } from \"../hooks/use-task\";\nimport type { ThinkingConfig } from \"@jarvis/types\";\nimport { formatTokens } from \"../utils/format-tokens\";\nimport { useTerminal } from \"../hooks/use-terminal\";\nimport { t } from \"../theme\";\n\ninterface StatusBarProps {\n mode: PermissionMode;\n model: string;\n thinking: ThinkingConfig;\n agentState: AgentState;\n totalTokens: number;\n connected: boolean;\n sessionId: string | null;\n workspacePath: string;\n}\n\nfunction shortModel(model: string): string {\n const m = model.match(/(sonnet|opus|haiku)[- ](\\d)/i);\n if (m) return `${m[1]![0]!.toUpperCase()}${m[1]!.slice(1)} ${m[2]}`;\n return model;\n}\n\nfunction getThinkingLabel(thinking: ThinkingConfig): string {\n if (thinking.type === \"disabled\") return \"\";\n if (thinking.type === \"adaptive\") return \"thinking\";\n return thinking.budgetTokens\n ? `thinking (${Math.round(thinking.budgetTokens / 1024)}k)`\n : \"thinking\";\n}\n\nfunction shortPath(p: string): string {\n const home = process.env.HOME ?? \"\";\n if (home && p.startsWith(home)) return \"~\" + p.slice(home.length);\n return p;\n}\n\nexport function StatusBar({\n mode,\n model,\n thinking,\n agentState,\n totalTokens,\n connected,\n sessionId,\n workspacePath,\n}: StatusBarProps) {\n const { columns } = useTerminal();\n\n // --- Row 1: left hints · right info ---\n\n // Left\n let leftText: string;\n if (agentState === \"awaiting-input\") {\n leftText = \"y/n to respond\";\n } else if (agentState === \"busy\") {\n leftText = \"esc to interrupt\";\n } else {\n leftText = \"? for shortcuts\";\n }\n\n // Right: model · mode · thinking · tokens\n const thinkingLabel = getThinkingLabel(thinking);\n const modelStr = shortModel(model);\n const tokenStr = totalTokens > 0 ? ` · ${formatTokens(totalTokens)} tokens` : \"\";\n const thinkingStr = thinkingLabel ? ` · ${thinkingLabel}` : \"\";\n const rightPlain = `${modelStr} · ${mode}${thinkingStr}${tokenStr}`;\n\n const gap1 = Math.max(1, columns - leftText.length - rightPlain.length - 2);\n\n // --- Row 2: left empty · right context info ---\n const contextParts: string[] = [];\n if (!connected) contextParts.push(\"disconnected\");\n if (sessionId) contextParts.push(`session: ${sessionId.slice(0, 8)}`);\n const row2Right = contextParts.length > 0\n ? contextParts.join(\" · \")\n : shortPath(workspacePath);\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n {/* Row 1 */}\n <Box>\n <Text color={t.hint}>{leftText}</Text>\n <Text>{\" \".repeat(gap1)}</Text>\n {!connected ? (\n <Text color={t.disconnected}>{rightPlain}</Text>\n ) : (\n <Text>\n <Text color={t.hint}>{modelStr} · </Text>\n <Text color={t.mode[mode]}>{mode}</Text>\n {thinkingStr && <Text color={t.hint}>{thinkingStr}</Text>}\n {tokenStr && <Text color={t.hint}>{tokenStr}</Text>}\n </Text>\n )}\n </Box>\n {/* Row 2 */}\n <Box justifyContent=\"flex-end\">\n <Text color={t.hint}>{row2Right}</Text>\n </Box>\n </Box>\n );\n}\n","/**\n * Token formatting utilities\n */\n\nexport function formatTokens(count: number): string {\n if (count === 0) return \"0\";\n return count.toLocaleString(\"en-US\");\n}\n\nexport function formatDuration(startMs: number): string {\n const elapsed = (Date.now() - startMs) / 1000;\n if (elapsed < 60) return `${elapsed.toFixed(1)}s`;\n const mins = Math.floor(elapsed / 60);\n const secs = Math.floor(elapsed % 60);\n return `${mins}m${secs}s`;\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport type { PendingUserInput } from \"@jarvis/types\";\nimport { t } from \"../theme\";\n\ninterface PermissionDialogProps {\n input: PendingUserInput;\n onRespond: (action: string, data?: Record<string, unknown>, feedback?: string) => void;\n}\n\nexport function PermissionDialog({ input, onRespond }: PermissionDialogProps) {\n useInput((char) => {\n switch (char.toLowerCase()) {\n case \"y\": onRespond(\"allow\"); break;\n case \"n\": onRespond(\"deny\"); break;\n case \"a\": onRespond(\"allow\", { always: true }); break;\n }\n });\n\n const toolName = input.toolName ?? \"unknown\";\n const description = getInputDescription(input);\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"╭─ \"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.dialogTitle} bold>Jarvis wants to use: {toolName}</Text>\n </Box>\n {description && (\n <>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n {description.split(\"\\n\").map((line, i) => (\n <Box key={i}>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text>{line}</Text>\n </Box>\n ))}\n </>\n )}\n {input.ui?.data != null && (\n <>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text dimColor>{truncate(JSON.stringify(input.ui.data, null, 2), 500)}</Text>\n </Box>\n </>\n )}\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.toolSuccess} bold>Allow (y)</Text>\n <Text>{\" \"}</Text>\n <Text color={t.dialogDanger} bold>Reject (n)</Text>\n <Text>{\" \"}</Text>\n <Text color={t.dialogAction} bold>Always allow (a)</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"╰─\"}</Text>\n </Box>\n );\n}\n\nfunction getInputDescription(input: PendingUserInput): string | null {\n const toolName = input.toolName ?? \"\";\n const inp = input.input ?? {};\n\n switch (toolName) {\n case \"Bash\":\n return `Command: ${inp.command ?? \"\"}${inp.description ? `\\nDescription: ${inp.description}` : \"\"}`;\n case \"Write\": return `File: ${inp.file_path ?? \"\"}`;\n case \"Edit\": return `File: ${inp.file_path ?? \"\"}`;\n case \"NotebookEdit\": return `Notebook: ${inp.notebook_path ?? \"\"}`;\n default:\n if (input.reason) return input.reason;\n return null;\n }\n}\n\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 3) + \"...\";\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport type { PendingUserInput } from \"@jarvis/types\";\nimport { t } from \"../theme\";\n\ninterface PlanReviewProps {\n input: PendingUserInput;\n onRespond: (action: string, data?: Record<string, unknown>, feedback?: string) => void;\n}\n\nexport function PlanReview({ input, onRespond }: PlanReviewProps) {\n useInput((char) => {\n switch (char.toLowerCase()) {\n case \"y\": onRespond(\"allow\"); break;\n case \"n\": onRespond(\"deny\"); break;\n }\n });\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"╭─ Plan ─\"}</Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n {input.items?.map((item, i) => (\n <Box key={item.id}>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text>{i + 1}. {item.title}</Text>\n </Box>\n ))}\n {input.reason && !input.items?.length && (\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text>{input.reason}</Text>\n </Box>\n )}\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.toolSuccess} bold>Approve plan (y)</Text>\n <Text>{\" \"}</Text>\n <Text color={t.dialogDanger} bold>Reject (n)</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"╰─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport type { PendingUserInput } from \"@jarvis/types\";\nimport { t } from \"../theme\";\n\ninterface MaxIterationsProps {\n input: PendingUserInput;\n onRespond: (action: string, data?: Record<string, unknown>) => void;\n}\n\nexport function MaxIterations({ input, onRespond }: MaxIterationsProps) {\n useInput((char) => {\n switch (char.toLowerCase()) {\n case \"y\": onRespond(\"allow\"); break;\n case \"n\": onRespond(\"deny\"); break;\n }\n });\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"╭─ \"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.dialogTitle} bold>\n Reached {input.iteration ?? \"?\"}/{input.maxIterations ?? \"?\"} turns\n </Text>\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text>Continue for {input.initialMaxIterations ?? input.maxIterations ?? 25} more turns?</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.toolSuccess} bold>Continue (y)</Text>\n <Text>{\" \"}</Text>\n <Text color={t.dialogDanger} bold>Stop (n)</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"╰─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport { t } from \"../theme\";\n\ninterface HelpMenuProps {\n onClose: () => void;\n}\n\nconst COMMANDS: [string, string][] = [\n [\"/config\", \"Open settings (model, thinking, mode)\"],\n [\"/model\", \"Quick model switch\"],\n [\"/mode\", \"Quick permission mode switch\"],\n [\"/thinking\", \"Toggle thinking config\"],\n [\"/status\", \"Show connection & session info\"],\n [\"/clear\", \"Clear conversation history and free up context\"],\n [\"/compact\", \"Compact old messages\"],\n [\"/help\", \"Show this help\"],\n [\"/exit\", \"Exit Jarvis\"],\n];\n\nexport function HelpMenu({ onClose }: HelpMenuProps) {\n useInput((_input, key) => {\n if (key.escape || _input === \"q\" || key.return) onClose();\n });\n\n return (\n <Box flexDirection=\"column\" marginTop={1} paddingLeft={1}>\n {COMMANDS.map(([cmd, desc]) => (\n <Box key={cmd}>\n <Text color={t.command}>{cmd!.padEnd(16)}</Text>\n <Text>{desc}</Text>\n </Box>\n ))}\n <Box marginTop={1}>\n <Text color={t.hint}>Shift+Tab to cycle modes · Ctrl+C to interrupt · Esc to close</Text>\n </Box>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nimport type { TuiSettings } from \"../settings\";\nimport { formatTokens } from \"../utils/format-tokens\";\nimport { t } from \"../theme\";\nimport { loadConfig } from \"../../config\";\n\ninterface StatusDisplayProps {\n settings: TuiSettings;\n connected: boolean;\n sessionId: string | null;\n totalTokens: number;\n workspacePath: string;\n onClose: () => void;\n}\n\nexport function StatusDisplay({\n settings,\n connected,\n sessionId,\n totalTokens,\n workspacePath,\n onClose,\n}: StatusDisplayProps) {\n const hubUrl = loadConfig()?.apiUrl ?? \"(not connected)\";\n useInput((_input, key) => {\n if (key.escape || _input === \"q\") onClose();\n });\n\n const thinkingLabel =\n settings.thinking.type === \"enabled\"\n ? `enabled (${settings.thinking.budgetTokens ?? 32768})`\n : settings.thinking.type;\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>\n {\"┌─ \"}\n <Text color={t.dialogTitle}>Jarvis Status</Text>\n {\" ─\"}\n </Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n {[\n [\"Hub\", `${hubUrl} (${connected ? \"connected\" : \"disconnected\"})`],\n [\"Session\", sessionId ?? \"none\"],\n [\"Model\", settings.model],\n [\"Mode\", settings.permissionMode],\n [\"Thinking\", thinkingLabel],\n [\"Max turns\", String(settings.maxTurns)],\n [\"Workspace\", workspacePath],\n [\"Tokens used\", `${formatTokens(totalTokens)} (session)`],\n ].map(([label, value]) => (\n <Box key={label}>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold>{label!.padEnd(14)}</Text>\n <Text dimColor>{value}</Text>\n </Box>\n ))}\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>Press Esc or q to close</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"└─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport SelectInput from \"ink-select-input\";\n\nimport { t } from \"../theme\";\n\ninterface ModelPickerProps {\n currentModel: string;\n onSelect: (model: string) => void;\n onClose: () => void;\n}\n\nconst MODELS = [\n { label: \"claude-sonnet-4-20250514\", value: \"claude-sonnet-4-20250514\" },\n { label: \"claude-opus-4-20250514\", value: \"claude-opus-4-20250514\" },\n { label: \"claude-haiku-4-5-20251001\", value: \"claude-haiku-4-5-20251001\" },\n];\n\nexport function ModelPicker({ currentModel, onSelect, onClose }: ModelPickerProps) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"┌─ \"}<Text color={t.dialogTitle}>Model</Text>{\" ─\"}</Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text dimColor>Current: {currentModel}</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box paddingLeft={2}>\n <SelectInput\n items={MODELS}\n initialIndex={MODELS.findIndex((m) => m.value === currentModel)}\n onSelect={(item) => { onSelect(item.value); onClose(); }}\n />\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>↑/↓ select · Enter confirm · Esc cancel</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"└─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport SelectInput from \"ink-select-input\";\n\nimport type { PermissionMode } from \"../settings\";\nimport { t } from \"../theme\";\n\ninterface ModePickerProps {\n currentMode: PermissionMode;\n onSelect: (mode: PermissionMode) => void;\n onClose: () => void;\n}\n\nconst MODES = [\n { label: \"Supervised — Ask before dangerous tools\", value: \"supervised\" as const },\n { label: \"Auto — Auto-approve safe tools\", value: \"auto\" as const },\n { label: \"Plan — Plan first, then execute\", value: \"plan\" as const },\n { label: \"Yolo — Bypass all permissions\", value: \"yolo\" as const },\n];\n\nexport function ModePicker({ currentMode, onSelect, onClose }: ModePickerProps) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"┌─ \"}<Text color={t.dialogTitle}>Permission Mode</Text>{\" ─\"}</Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box paddingLeft={2}>\n <SelectInput\n items={MODES}\n initialIndex={MODES.findIndex((m) => m.value === currentMode)}\n onSelect={(item) => { onSelect(item.value); onClose(); }}\n />\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>↑/↓ select · Enter confirm · Esc cancel</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"└─\"}</Text>\n </Box>\n );\n}\n","import React from \"react\";\nimport { Box, Text } from \"ink\";\nimport SelectInput from \"ink-select-input\";\n\nimport type { ThinkingConfig } from \"@jarvis/types\";\nimport { t } from \"../theme\";\n\ninterface ThinkingPickerProps {\n current: ThinkingConfig;\n onSelect: (config: ThinkingConfig) => void;\n onClose: () => void;\n}\n\nconst OPTIONS = [\n { label: \"Adaptive — Model decides when to think\", value: \"adaptive\" },\n { label: \"Enabled — Always think (budget: 32768)\", value: \"enabled\" },\n { label: \"Disabled — No extended thinking\", value: \"disabled\" },\n];\n\nexport function ThinkingPicker({ current, onSelect, onClose }: ThinkingPickerProps) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>{\"┌─ \"}<Text color={t.dialogTitle}>Thinking</Text>{\" ─\"}</Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box paddingLeft={2}>\n <SelectInput\n items={OPTIONS}\n initialIndex={OPTIONS.findIndex((o) => o.value === current.type)}\n onSelect={(item) => {\n const config: ThinkingConfig = { type: item.value as ThinkingConfig[\"type\"] };\n if (item.value === \"enabled\") config.budgetTokens = 32768;\n onSelect(config);\n onClose();\n }}\n />\n </Box>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>↑/↓ select · Enter confirm · Esc cancel</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"└─\"}</Text>\n </Box>\n );\n}\n","import React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport SelectInput from \"ink-select-input\";\n\nimport type { ThinkingConfig } from \"@jarvis/types\";\nimport type { PermissionMode, TuiSettings } from \"../settings\";\nimport { t } from \"../theme\";\n\ninterface SettingsDialogProps {\n settings: TuiSettings;\n onUpdateModel: (model: string) => void;\n onUpdateThinking: (thinking: ThinkingConfig) => void;\n onUpdateMode: (mode: PermissionMode) => void;\n onUpdateMaxTurns: (turns: number) => void;\n onClose: () => void;\n}\n\ntype Section = \"model\" | \"thinking\" | \"mode\" | \"maxTurns\";\nconst SECTIONS: Section[] = [\"model\", \"thinking\", \"mode\", \"maxTurns\"];\n\nconst MODELS = [\n { label: \"claude-sonnet-4-20250514\", value: \"claude-sonnet-4-20250514\" },\n { label: \"claude-opus-4-20250514\", value: \"claude-opus-4-20250514\" },\n { label: \"claude-haiku-4-5-20251001\", value: \"claude-haiku-4-5-20251001\" },\n];\n\nconst THINKING_OPTIONS = [\n { label: \"Adaptive — Model decides\", value: \"adaptive\" },\n { label: \"Enabled — Always (32k budget)\", value: \"enabled\" },\n { label: \"Disabled — Never\", value: \"disabled\" },\n];\n\nconst MODE_OPTIONS = [\n { label: \"Supervised\", value: \"supervised\" },\n { label: \"Auto\", value: \"auto\" },\n { label: \"Plan\", value: \"plan\" },\n { label: \"Yolo\", value: \"yolo\" },\n];\n\nconst MAX_TURNS_OPTIONS = [\n { label: \"10\", value: \"10\" },\n { label: \"25 (default)\", value: \"25\" },\n { label: \"50\", value: \"50\" },\n { label: \"100\", value: \"100\" },\n { label: \"200\", value: \"200\" },\n];\n\nexport function SettingsDialog({\n settings,\n onUpdateModel,\n onUpdateThinking,\n onUpdateMode,\n onUpdateMaxTurns,\n onClose,\n}: SettingsDialogProps) {\n const [activeSection, setActiveSection] = useState<Section>(\"model\");\n\n useInput((_input, key) => {\n if (key.escape) onClose();\n if (key.tab) {\n const idx = SECTIONS.indexOf(activeSection);\n setActiveSection(SECTIONS[(idx + 1) % SECTIONS.length]!);\n }\n });\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color={t.dialogBorder}>\n {\"╭─ \"}\n <Text color={t.dialogTitle}>Settings</Text>\n {\" ─\"}\n </Text>\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n\n {/* Model */}\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold color={activeSection === \"model\" ? t.dialogTitle : undefined}>\n Model\n </Text>\n </Box>\n {activeSection === \"model\" && (\n <Box paddingLeft={4}>\n <SelectInput\n items={MODELS}\n initialIndex={MODELS.findIndex((m) => m.value === settings.model)}\n onSelect={(item) => onUpdateModel(item.value)}\n />\n </Box>\n )}\n\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n\n {/* Thinking */}\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold color={activeSection === \"thinking\" ? t.dialogTitle : undefined}>\n Thinking\n </Text>\n </Box>\n {activeSection === \"thinking\" && (\n <Box paddingLeft={4}>\n <SelectInput\n items={THINKING_OPTIONS}\n initialIndex={THINKING_OPTIONS.findIndex((o) => o.value === settings.thinking.type)}\n onSelect={(item) => {\n const config: ThinkingConfig = { type: item.value as ThinkingConfig[\"type\"] };\n if (item.value === \"enabled\") config.budgetTokens = 32768;\n onUpdateThinking(config);\n }}\n />\n </Box>\n )}\n\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n\n {/* Permission Mode */}\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold color={activeSection === \"mode\" ? t.dialogTitle : undefined}>\n Permission Mode\n </Text>\n </Box>\n {activeSection === \"mode\" && (\n <Box paddingLeft={4}>\n <SelectInput\n items={MODE_OPTIONS}\n initialIndex={MODE_OPTIONS.findIndex((m) => m.value === settings.permissionMode)}\n onSelect={(item) => onUpdateMode(item.value as PermissionMode)}\n />\n </Box>\n )}\n\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n\n {/* Max Turns */}\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text bold color={activeSection === \"maxTurns\" ? t.dialogTitle : undefined}>\n Max Turns\n </Text>\n </Box>\n {activeSection === \"maxTurns\" && (\n <Box paddingLeft={4}>\n <SelectInput\n items={MAX_TURNS_OPTIONS}\n initialIndex={MAX_TURNS_OPTIONS.findIndex((o) => o.value === String(settings.maxTurns))}\n onSelect={(item) => onUpdateMaxTurns(parseInt(item.value, 10))}\n />\n </Box>\n )}\n\n <Text color={t.dialogBorder}>{\"│\"}</Text>\n <Box>\n <Text color={t.dialogBorder}>{\"│ \"}</Text>\n <Text color={t.hint}>Tab to switch section · Esc to close</Text>\n </Box>\n <Text color={t.dialogBorder}>{\"╰─\"}</Text>\n </Box>\n );\n}\n","import React, { useEffect, useState } from \"react\";\nimport { Text } from \"ink\";\n\nimport { t } from \"../theme\";\n\ninterface NotificationProps {\n message: string | null;\n duration?: number;\n}\n\nexport function Notification({ message, duration = 2000 }: NotificationProps) {\n const [visible, setVisible] = useState(false);\n const [text, setText] = useState(\"\");\n\n useEffect(() => {\n if (message) {\n setText(message);\n setVisible(true);\n const timer = setTimeout(() => setVisible(false), duration);\n return () => clearTimeout(timer);\n }\n }, [message, duration]);\n\n if (!visible || !text) return null;\n return <Text color={t.notification}>{text}</Text>;\n}\n","/**\n * Markdown Text Renderer\n *\n * Simple terminal markdown: bold, headers, lists, code blocks, inline code.\n * Matches Claude Code's clean output style.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\ninterface MarkdownTextProps {\n content: string;\n}\n\nexport function MarkdownText({ content }: MarkdownTextProps) {\n if (!content) return null;\n\n const lines = content.split(\"\\n\");\n const elements: React.ReactNode[] = [];\n let inCodeBlock = false;\n let codeLines: string[] = [];\n let codeLanguage = \"\";\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n\n // Code block start/end\n if (line.startsWith(\"```\")) {\n if (inCodeBlock) {\n // End code block\n elements.push(\n <Box key={`code-${i}`} flexDirection=\"column\" marginTop={0} marginBottom={0} paddingLeft={2}>\n {codeLanguage && (\n <Text dimColor>{codeLanguage}</Text>\n )}\n {codeLines.map((cl, j) => (\n <Text key={j} color=\"gray\">{cl}</Text>\n ))}\n </Box>,\n );\n codeLines = [];\n codeLanguage = \"\";\n inCodeBlock = false;\n } else {\n inCodeBlock = true;\n codeLanguage = line.slice(3).trim();\n }\n continue;\n }\n\n if (inCodeBlock) {\n codeLines.push(line);\n continue;\n }\n\n // Empty line\n if (line.trim() === \"\") {\n elements.push(<Text key={`empty-${i}`}>{\"\"}</Text>);\n continue;\n }\n\n // Headers\n const h1 = line.match(/^# (.+)/);\n if (h1) {\n elements.push(\n <Text key={`h1-${i}`} bold color=\"white\">\n {renderInline(h1[1]!)}\n </Text>,\n );\n continue;\n }\n\n const h2 = line.match(/^## (.+)/);\n if (h2) {\n elements.push(\n <Text key={`h2-${i}`} bold>\n {renderInline(h2[1]!)}\n </Text>,\n );\n continue;\n }\n\n const h3 = line.match(/^### (.+)/);\n if (h3) {\n elements.push(\n <Text key={`h3-${i}`} bold dimColor>\n {renderInline(h3[1]!)}\n </Text>,\n );\n continue;\n }\n\n // Unordered list items\n const ul = line.match(/^(\\s*)[-*] (.+)/);\n if (ul) {\n const indent = Math.floor((ul[1]?.length ?? 0) / 2);\n elements.push(\n <Box key={`ul-${i}`} paddingLeft={indent * 2}>\n <Text dimColor>{\"– \"}</Text>\n <Text>{renderInline(ul[2]!)}</Text>\n </Box>,\n );\n continue;\n }\n\n // Ordered list items\n const ol = line.match(/^(\\s*)\\d+\\. (.+)/);\n if (ol) {\n const indent = Math.floor((ol[1]?.length ?? 0) / 2);\n const num = line.match(/^(\\s*)(\\d+)\\./);\n elements.push(\n <Box key={`ol-${i}`} paddingLeft={indent * 2}>\n <Text dimColor>{`${num?.[2]}. `}</Text>\n <Text>{renderInline(ol[2]!)}</Text>\n </Box>,\n );\n continue;\n }\n\n // Horizontal rule\n if (/^---+$/.test(line.trim()) || /^\\*\\*\\*+$/.test(line.trim())) {\n elements.push(\n <Text key={`hr-${i}`} dimColor>{\"─\".repeat(40)}</Text>,\n );\n continue;\n }\n\n // Regular paragraph\n elements.push(\n <Text key={`p-${i}`}>{renderInline(line)}</Text>,\n );\n }\n\n return <Box flexDirection=\"column\">{elements}</Box>;\n}\n\n/**\n * Render inline markdown: **bold**, `code`, *italic*\n * Returns a string with ANSI escape sequences.\n *\n * Note: Ink <Text> doesn't support mixed inline styles easily,\n * so we return plain text with markdown stripped for now.\n * Bold is rendered via chalk-style markup.\n */\nfunction renderInline(text: string): string {\n return text\n // Remove bold markers (Ink doesn't support inline bold mixing easily)\n .replace(/\\*\\*(.+?)\\*\\*/g, \"$1\")\n // Remove italic markers\n .replace(/\\*(.+?)\\*/g, \"$1\")\n // Remove inline code markers\n .replace(/`(.+?)`/g, \"$1\");\n}\n","import type { Command } from \"commander\";\n\nimport { ensureConfig } from \"../auth\";\nimport { launchChat, type ChatOptions } from \"../tui/chat\";\n\nexport function register(program: Command): void {\n // Default action when no subcommand is given. Must be registered LAST so\n // commander matches real subcommands (start, stop, ...) before falling back.\n program\n .command(\"chat\", { isDefault: true, hidden: true })\n .description(\"Interactive TUI\")\n .option(\"--model <id>\", \"Model (e.g., claude-opus-4-20250514)\")\n .option(\"--mode <mode>\", \"Permission mode: supervised|auto|plan|yolo\")\n .option(\"--thinking <config>\", \"Thinking: adaptive|enabled|disabled\")\n .option(\"--thinking-budget <n>\", \"Token budget when thinking=enabled\")\n .option(\"--max-turns <n>\", \"Max turns per task\")\n .option(\"-w, --workspace <path>\", \"Workspace root path\")\n .option(\"--no-server\", \"Connect to existing agent, don't auto-start\")\n .action(async (opts: ChatOptions) => {\n await ensureConfig();\n await launchChat(opts);\n });\n}\n","import { isDev } from \"./config\";\n\n// In dev mode (env.json has \"development\"), load .env so APP_URL etc. are available.\n// In prod mode, skip .env entirely — use production defaults.\nif (isDev()) {\n const dotenv = await import(\"dotenv\");\n const fs = await import(\"fs\");\n const path = await import(\"path\");\n\n let dir = process.cwd();\n while (dir !== path.dirname(dir)) {\n const envPath = path.join(dir, \".env\");\n if (fs.existsSync(envPath)) {\n dotenv.config({ path: envPath });\n break;\n }\n dir = path.dirname(dir);\n }\n}\n\nimport { createCli } from \"./cli\";\n\ncreateCli().parse();\n"],"mappings":"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","names":["init_provider_types","init_provider_types","init_chat_types","init_usage_types","init_chat_types","init_usage_types","init_src","t","pendingInput","prompt","init_src","init_agents","init_messages","userInput","userInput","context","init_tools","init_tools","init_skills","init_src","init_src","prompt","init_prompts","init_resources","init_agents","init_messages","init_tools","init_skills","init_prompts","init_resources","init_context","init_context","init_data","init_context","init_src","init_agents","init_data","init_src","init_src","init_src","detectLanguage","init_src","init_src","init_src","exitPlanModeTool","init_src","enterPlanModeTool","init_src","init_src","t","init_src","init_src","agentTool","init_src","init_src","init_tools","exitPlanModeTool","enterPlanModeTool","agentTool","t","fs","os","path","baselineRef","exec","ref","init_src","init_tools","fs","path","workspacePath","init_src","crypto","init_src","crypto","fs","os","path","read","provider","before","after","tree","init_src","init_src","fs","path","path","fs","path","os","path","os","fs","fs","workspacePath","entry","method","init_src","init_src","crypto","path","provider","crypto","init_src","promisify","path","fs","workspacePath","TREE_SKIP_DIRS","tree","init_src","execCb","fs","path","promisify","exec","workspacePath","execCb","promisify","exec","promisify","execCb","add","ref","tree","parseScan","init_src","execSync","fs","path","os","path","os","fs","execSync","register","workspacePath","register","register","spawn","execSync","fs","register","fs","spawn","execSync","register","state","register","workspacePath","register","register","React","render","spawn","fileURLToPath","path","fs","os","fs","path","os","useState","useCallback","useRef","useEffect","Box","Text","useInput","crypto","WebSocket","crypto","WebSocket","interruptTask","useState","useCallback","useRef","useState","useCallback","useRef","crypto","useState","useCallback","useState","useCallback","workspacePath","Box","Text","jsx","jsxs","Box","Text","useState","useEffect","useRef","Box","Text","jsx","jsxs","useState","useRef","useEffect","Box","Text","Box","Text","useState","useEffect","jsx","Box","Text","React","useState","useCallback","Box","Text","Box","Text","jsx","jsxs","Box","Text","Box","Text","path","fs","jsx","jsxs","workspacePath","fs","path","jsx","Box","Text","jsxs","jsx","jsxs","workspacePath","useState","React","useCallback","before","Box","Text","Box","Text","jsx","jsxs","shortModel","shortPath","workspacePath","Box","Text","Box","Text","useInput","jsx","jsxs","useInput","Box","Text","Box","Text","useInput","jsx","jsxs","useInput","Box","Text","Box","Text","useInput","jsx","jsxs","useInput","Box","Text","Box","Text","useInput","jsx","jsxs","useInput","Box","Text","Box","Text","useInput","jsx","jsxs","workspacePath","useInput","Box","Text","Box","Text","jsx","jsxs","Box","Text","Box","Text","SelectInput","jsx","jsxs","Box","Text","SelectInput","Box","Text","SelectInput","jsx","jsxs","Box","Text","SelectInput","useState","Box","Text","useInput","SelectInput","jsx","jsxs","MODELS","useState","useInput","Box","Text","SelectInput","useEffect","useState","Text","jsx","useState","useEffect","Text","Box","Text","jsx","jsxs","Fragment","jsx","jsxs","workspacePath","useState","useRef","useEffect","renderMessage","useCallback","useInput","Box","Text","truncate","workspacePath","render","React","path","os","fs","__filename","fileURLToPath","spawn","register","register","fs","path"]}