futurex-cli 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../packages/futurex-protocol/src/types.ts", "../../../packages/futurex-protocol/src/tier.ts", "../src/client/factory.ts", "../src/creds.ts", "../src/config.ts", "../src/permissions.ts", "../../../packages/futurex-tools/src/types.ts", "../../../packages/futurex-tools/src/paths.ts", "../../../packages/futurex-tools/src/tools.ts", "../src/repo.ts", "../../../packages/config/src/env.ts", "../../../packages/logger/src/logger.ts", "../../../packages/logger/src/create.ts", "../../../packages/utils/src/errors.ts", "../../../packages/utils/src/async.ts", "../../../packages/ai-sdk/src/internal/http.ts", "../../../packages/ai-sdk/src/internal/sse.ts", "../../../packages/ai-sdk/src/providers/anthropic.ts", "../../../packages/ai-sdk/src/providers/deepseek.ts", "../../../packages/ai-sdk/src/providers/openai.ts", "../../../packages/ai-sdk/src/types.ts", "../../../packages/ai-sdk/src/client.ts", "../src/client/direct.ts", "../src/client/gateway.ts", "../src/auth.ts", "../src/http.ts", "../src/tool-runner.ts", "../src/ui.ts", "../src/augment.ts", "../src/context.ts", "../src/system-prompt.ts", "../src/index-store.ts", "../../../packages/futurex-vector/src/local-embedder.ts", "../../../packages/futurex-vector/src/flat-store.ts", "../../../packages/futurex-vector/src/index.ts", "../../../packages/futurex-context/src/scan.ts", "../../../packages/futurex-context/src/ignore.ts", "../../../packages/futurex-context/src/chunk.ts", "../../../packages/futurex-context/src/redact.ts", "../../../packages/futurex-context/src/ts-symbols.ts", "../../../packages/futurex-context/src/symbol-index.ts", "../../../packages/futurex-context/src/imports.ts", "../../../packages/futurex-context/src/indexer.ts", "../../../packages/futurex-context/src/retrieve.ts", "../../../packages/futurex-context/src/persist.ts", "../src/marker.ts", "../src/pricing.ts", "../src/render.ts", "../src/ask.ts", "../src/repl.ts", "../src/agent.ts", "../src/diagnostics.ts", "../src/repair.ts", "../src/finish.ts", "../src/repl-runtime.ts", "../src/chatbox.ts", "../src/permissions-command.ts", "../src/memory.ts", "../src/memory-command.ts", "../src/build-command.ts", "../src/goal.ts", "../src/budget.ts", "../src/planner.ts", "../src/planning-config.ts", "../src/selection.ts", "../src/value.ts", "../src/pipeline.ts", "../src/plan-command.ts", "../src/skills.ts", "../src/skills-command.ts", "../src/verify-command.ts", "../src/index-command.ts", "../src/device.ts", "../src/commands.ts", "../src/index.ts"],
4
+ "sourcesContent": ["/**\n * Core FutureX domain types shared between the CLI and the backend.\n */\n\n/** Role of a single conversation turn. */\nexport type Role = 'system' | 'user' | 'assistant';\n\n/** One message in a conversation. */\nexport interface Message {\n readonly role: Role;\n readonly content: string;\n}\n\n/**\n * Thinking control. `false` forces a fast answer; `true` enables thinking at the\n * provider default effort; `{ effort }` selects the level. DeepSeek accepts only\n * `high | max` (see `@fim/ai-sdk`), never the OpenAI-style low/medium/high.\n */\nexport type ReasoningOption = boolean | { readonly effort?: 'high' | 'max' };\n\n/**\n * The three real DeepSeek effort states (Blueprint v2 \u00A73.2), named for the CLI +\n * tier layer:\n * - `off` \u2014 thinking disabled (fast, non-thinking).\n * - `high` \u2014 thinking enabled, reasoning_effort=high.\n * - `max` \u2014 thinking enabled, reasoning_effort=max (a.k.a. xhigh).\n * DeepSeek has no low/medium rung \u2014 the cheaper lever is `off` or a smaller model.\n */\nexport type EffortLevel = 'off' | 'high' | 'max';\n\n/**\n * FutureX product tiers (Blueprint v2 \u00A73.3) \u2014 each maps to a model + default\n * effort + an allowed-override set. The routing table + enforcing resolver live in\n * `tier.ts` ({@link TIERS}, {@link resolveTier}).\n */\nexport type Tier = 'fx-pro' | 'fx-fast' | 'fx-mini' | 'fx-eco';\n\n/** Translate a named {@link EffortLevel} into the SDK's {@link ReasoningOption}. */\nexport function effortToReasoning(effort: EffortLevel): ReasoningOption {\n return effort === 'off' ? false : { effort };\n}\n\n/** Classify a {@link ReasoningOption} back into a named {@link EffortLevel}. */\nexport function reasoningToEffort(reasoning: ReasoningOption | undefined): EffortLevel {\n if (!reasoning) return 'off'; // undefined or false \u2192 thinking disabled\n if (reasoning === true) return 'high'; // provider default effort is high\n return reasoning.effort ?? 'high';\n}\n\n/**\n * A request for one assistant turn. The CLI builds this; the {@link FutureXClient}\n * turns it into a model (or gateway) call.\n */\nexport interface ChatTurn {\n /**\n * The stable, cache-targeted prefix (system prompt + project memory + repo\n * card). Pinned for the life of a session so DeepSeek prefix-caching hits.\n */\n readonly system?: string;\n /** Conversation history, with the new user message last. At least one entry. */\n readonly messages: readonly Message[];\n /** Thinking control. Defaults to off (fast). */\n readonly reasoning?: ReasoningOption;\n /** Override the model id (e.g. `deepseek-v4-pro`). */\n readonly model?: string;\n /** Upper bound on output tokens. */\n readonly maxTokens?: number;\n /**\n * The {@link Tier} this turn routed through, when one was selected. The gateway\n * re-resolves and ENFORCES it server-side (overriding model/reasoning/maxTokens),\n * so it is sent alongside the already-resolved values. Absent for an untiered turn.\n */\n readonly tier?: Tier;\n /** The effort level chosen for {@link tier} (resolved default or override). */\n readonly effort?: EffortLevel;\n /** Abort signal to cancel the in-flight turn (e.g. Ctrl+C). */\n readonly signal?: AbortSignal;\n}\n\n/**\n * A tool the CLI can execute, described for the model. The gateway feeds these\n * descriptors to DeepSeek to drive the agent loop; the executable implementation\n * (and Zod validation of the model's arguments) lives CLIENT-SIDE in\n * `@fim/futurex-tools`. The CLI advertises its descriptors at session open\n * ({@link OpenSessionRequest.tools}), so the backend never needs to depend on the\n * tool package and a client can expose a platform-specific tool set.\n */\nexport interface ToolDescriptor {\n readonly name: string;\n readonly description: string;\n /** JSON Schema for the tool's arguments \u2014 exactly what the model sees. */\n readonly parameters: Record<string, unknown>;\n /** Mutating tools are permission-gated on the CLI before they run. */\n readonly mutating: boolean;\n}\n\n/**\n * A compact summary of the working repository, folded into the stable prefix so\n * the assistant is grounded in the project's stack without dumping files.\n */\nexport interface RepoCard {\n readonly root: string;\n readonly name?: string;\n readonly language?: string;\n readonly framework?: string;\n readonly backend?: string;\n readonly orm?: string;\n readonly packageManager?: string;\n readonly test?: string;\n}\n", "/**\n * FutureX tier routing (Blueprint v2 \u00A73.3). The single source of truth mapping a\n * {@link Tier} to its model + default effort + allowed-override set + token caps,\n * plus the resolver that ENFORCES the allowed-override set. Shared by the CLI\n * (client-side rejection) and the gateway (authoritative server-side enforcement),\n * so a client can never bypass a tier's caps or allowed-effort set.\n */\nimport { effortToReasoning, type EffortLevel, type ReasoningOption, type Tier } from './types.js';\n\nexport interface TierSpec {\n /** Human-facing mode label. */\n readonly mode: string;\n /**\n * DeepSeek model id. MUST match `@fim/ai-sdk`'s `DEEPSEEK_DEFAULT_MODEL` /\n * `DEEPSEEK_PRO_MODEL` \u2014 inlined here so this shared contract stays\n * dependency-free (the SDK constants are the canonical source).\n */\n readonly model: string;\n readonly defaultEffort: EffortLevel;\n readonly allowedEfforts: readonly EffortLevel[];\n /** Hard upper bound on output tokens for the tier (Eco), if any. */\n readonly maxOutputTokens?: number;\n}\n\n/** The \u00A73.3 tier table. */\nexport const TIERS: Readonly<Record<Tier, TierSpec>> = {\n 'fx-pro': {\n mode: 'Pro',\n model: 'deepseek-v4-pro',\n defaultEffort: 'max',\n allowedEfforts: ['off', 'high', 'max'],\n },\n 'fx-fast': {\n mode: 'Fast',\n model: 'deepseek-v4-flash',\n defaultEffort: 'off',\n allowedEfforts: ['off', 'high'],\n },\n 'fx-mini': {\n mode: 'Light',\n model: 'deepseek-v4-flash',\n defaultEffort: 'high',\n allowedEfforts: ['off', 'high', 'max'],\n },\n 'fx-eco': {\n mode: 'Eco',\n model: 'deepseek-v4-flash',\n defaultEffort: 'off',\n allowedEfforts: ['off'],\n maxOutputTokens: 4096,\n },\n};\n\n/** Default tier when none is selected (Flash-first cost discipline). */\nexport const DEFAULT_TIER: Tier = 'fx-fast';\n\n/** The tier ids, for help text + validation. */\nexport const TIER_IDS = Object.keys(TIERS) as Tier[];\n\n/** Narrow an arbitrary string to a {@link Tier}. */\nexport function isTier(x: string): x is Tier {\n return Object.prototype.hasOwnProperty.call(TIERS, x);\n}\n\nconst TIER_ALIASES: Readonly<Record<string, Tier>> = {\n 'fx-pro': 'fx-pro',\n pro: 'fx-pro',\n 'fx-fast': 'fx-fast',\n fast: 'fx-fast',\n 'fx-mini': 'fx-mini',\n mini: 'fx-mini',\n light: 'fx-mini',\n 'fx-eco': 'fx-eco',\n eco: 'fx-eco',\n};\n\n/** Normalize a user-typed module name (an `fx-*` id or a short alias) to a {@link Tier}. */\nexport function normalizeTier(s: string): Tier | undefined {\n return TIER_ALIASES[s.trim().toLowerCase()];\n}\n\n/** Thrown when a per-request effort override is not allowed by the tier. */\nexport class TierOverrideError extends Error {\n constructor(\n readonly tier: Tier,\n readonly effort: EffortLevel,\n readonly allowed: readonly EffortLevel[],\n ) {\n super(`effort '${effort}' is not allowed for tier '${tier}' (allowed: ${allowed.join(', ')})`);\n this.name = 'TierOverrideError';\n }\n}\n\n/** A tier resolved into concrete request parameters. */\nexport interface ResolvedTier {\n readonly tier: Tier;\n readonly model: string;\n readonly effort: EffortLevel;\n readonly reasoning: ReasoningOption;\n readonly maxTokens?: number;\n}\n\n/**\n * Resolve a tier (+ optional effort / maxTokens override) into the concrete\n * model + reasoning + token cap, ENFORCING the tier's allowed-override set.\n * @throws {@link TierOverrideError} when `overrides.effort` is not permitted.\n */\nexport function resolveTier(\n tier: Tier,\n overrides: { readonly effort?: EffortLevel; readonly maxTokens?: number } = {},\n): ResolvedTier {\n const spec = TIERS[tier];\n const effort = overrides.effort ?? spec.defaultEffort;\n if (!spec.allowedEfforts.includes(effort)) {\n throw new TierOverrideError(tier, effort, spec.allowedEfforts);\n }\n // The tier cap is an upper bound; a smaller caller request is honored.\n const cap = spec.maxOutputTokens;\n const maxTokens =\n cap === undefined ? overrides.maxTokens : Math.min(cap, overrides.maxTokens ?? cap);\n return {\n tier,\n model: spec.model,\n effort,\n reasoning: effortToReasoning(effort),\n ...(maxTokens !== undefined ? { maxTokens } : {}),\n };\n}\n", "import { createInterface } from 'node:readline';\nimport type { FutureXClient } from '@fim/futurex-protocol';\nimport { readCreds } from '../creds.js';\nimport { createPermissionGate, type AskFn, type Gate } from '../permissions.js';\nimport { findRepoRoot } from '../repo.js';\nimport { createDirectClient } from './direct.js';\nimport { createGatewayClient } from './gateway.js';\n\n/** Which backend the CLI is talking to. */\nexport interface ResolvedClient {\n client: FutureXClient;\n mode: 'gateway' | 'local';\n email?: string;\n}\n\nexport interface ClientOptions {\n /** Permission gate for mutating tools. Interactive callers (REPL) pass their own. */\n readonly gate?: Gate;\n /** Repo root tools are confined to (defaults to the detected root). */\n readonly repoRoot?: string;\n readonly useRepo?: boolean;\n readonly useMemory?: boolean;\n}\n\n/**\n * Default permission gate for one-shot / standalone commands: stored per-project\n * always-allow/deny decisions apply first; only an 'ask' state prompts (TTY), and\n * an always-* answer here persists like everywhere else. Denies when stdin isn't\n * interactive (never hang a pipe).\n */\nfunction defaultGate(repoRoot: string): Gate {\n const ask: AskFn = async (req) => {\n if (process.stdin.isTTY !== true) return 'no';\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n try {\n const answer = (\n await new Promise<string>((resolve) =>\n rl.question(`approve [${req.kind}] ${req.preview}? [y/N/a]lways/[d]eny-always `, resolve),\n )\n )\n .trim()\n .toLowerCase();\n if (answer === 'a' || answer === 'always') return 'always-allow';\n if (answer === 'd' || answer === 'deny' || answer === 'never') return 'always-deny';\n return answer === 'y' || answer === 'yes' ? 'yes' : 'no';\n } finally {\n rl.close();\n }\n };\n return createPermissionGate(repoRoot, ask);\n}\n\n/**\n * Choose the backend: the FIM gateway when logged in (`futurex login`), else the\n * local direct-to-DeepSeek fallback. The gateway client is a full agent client \u2014\n * it executes the tools the gateway's model requests. Both implement the same\n * {@link FutureXClient}, so callers don't care which they get.\n */\nexport function createClient(options: ClientOptions = {}): ResolvedClient {\n const creds = readCreds();\n if (creds?.accessToken) {\n const repoRoot = options.repoRoot ?? findRepoRoot();\n return {\n client: createGatewayClient(creds, {\n gate: options.gate ?? defaultGate(repoRoot),\n repoRoot,\n ...(options.useRepo !== undefined ? { useRepo: options.useRepo } : {}),\n ...(options.useMemory !== undefined ? { useMemory: options.useMemory } : {}),\n }),\n mode: 'gateway',\n email: creds.email,\n };\n }\n return { client: createDirectClient(), mode: 'local' };\n}\n", "import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { credsPath } from './config.js';\n\n/**\n * Stored CLI credentials. Phase 0/1 keeps the access token + the rotating refresh\n * cookie in a 0600 file. Phase 4 hardens this (OS keychain / encrypt-at-rest,\n * refresh-only) per docs/futurex/decisions.md (D4).\n */\nexport interface Credentials {\n apiUrl: string;\n email?: string;\n accessToken: string;\n refreshCookie?: string;\n}\n\nexport function readCreds(): Credentials | null {\n const path = credsPath();\n if (!existsSync(path)) return null;\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as Credentials;\n } catch {\n return null;\n }\n}\n\nexport function writeCreds(creds: Credentials): void {\n const path = credsPath();\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(creds, null, 2), { mode: 0o600 });\n}\n\nexport function clearCreds(): void {\n try {\n rmSync(credsPath(), { force: true });\n } catch {\n /* ignore */\n }\n}\n", "import { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n/**\n * Base URL of the FIM gateway the CLI talks to.\n *\n * Defaults to the hosted production gateway so the installed, env-less binary\n * works out of the box (no repo `.env` to fall back on). `FUTUREX_API_URL`\n * (preferred) or `API_URL` override it; local dev sets `API_URL` in `.env`\n * (e.g. `http://localhost:4000`). The CLI appends `/api/v1/...` itself, so this\n * is the bare origin with no trailing slash and no `/api/v1` suffix.\n */\nconst DEFAULT_API_URL = 'https://api.futurim.org';\n\nexport function apiBaseUrl(): string {\n return process.env.FUTUREX_API_URL ?? process.env.API_URL ?? DEFAULT_API_URL;\n}\n\n/**\n * The FutureX home directory (`~/.futurex`) holding credentials, the permission\n * store, pipelines, and the index. `FUTUREX_HOME` overrides it (tests, CI).\n */\nexport function futurexHome(): string {\n return process.env.FUTUREX_HOME ?? join(homedir(), '.futurex');\n}\n\n/** Where credentials are stored (Phase 0/1: plain file under the home dir). */\nexport function credsPath(): string {\n return join(futurexHome(), 'credentials.json');\n}\n\n/**\n * The per-project permission store. Deliberately under the HOME dir (keyed by\n * project root) and never inside the repo \u2014 a cloned repository must not be able\n * to grant itself permissions.\n */\nexport function permissionsPath(): string {\n return join(futurexHome(), 'permissions.json');\n}\n\n/** Optional planning-config overrides (effort/value/budget knobs). */\nexport function planningConfigPath(): string {\n return join(futurexHome(), 'planning.json');\n}\n", "/**\n * Granular, persistent permissions (project-scoped).\n *\n * Every mutating tool call resolves to one {@link ActionKind} \u2014 edit / create /\n * delete / run \u2014 and each kind carries its own consent state: `ask` (prompt\n * every time), `allow` (always allow), or `deny` (always deny). Decisions made\n * via an\n * \"always \u2026\" answer are written through to `~/.futurex/permissions.json` keyed\n * by the project root, so they survive process restarts and govern every later\n * action of the same kind in the same project.\n *\n * The flow is a single audited path implemented by {@link createPermissionGate}:\n * action \u2192 kind resolution (ToolSpec.classify) \u2192 store lookup \u2192\n * prompt only if `ask` \u2192 persist on an always-* decision.\n *\n * The store lives under the user's home dir, NEVER inside the repository \u2014 a\n * cloned repo must not be able to grant itself permissions. All kinds default\n * to `ask`; `run` (shell commands) is never auto-defaulted to allow.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { ACTION_KINDS, type ActionKind } from '@fim/futurex-tools';\nimport { permissionsPath } from './config.js';\n\n/** Consent state for one action kind. */\nexport type Consent = 'ask' | 'allow' | 'deny';\n\n/** Consent per action kind for one project (missing kind = 'ask'). */\nexport type ProjectPermissions = Partial<Record<ActionKind, Consent>>;\n\n/** What the gate is being asked to approve. */\nexport interface GateRequest {\n /** Tool name (e.g. `write_file`). */\n readonly tool: string;\n /** The permission type this call resolved to. */\n readonly kind: ActionKind;\n /** Human-readable one-line preview of the action. */\n readonly preview: string;\n}\n\n/** Permission decision for a mutating tool call: resolve true to allow. */\nexport type Gate = (req: GateRequest) => Promise<boolean>;\n\n/** A user's answer to a permission prompt. */\nexport type GateAnswer = 'yes' | 'no' | 'always-allow' | 'always-deny';\n\n/** UI hook that actually shows the prompt (chatbox modal / readline / deny-all). */\nexport type AskFn = (req: GateRequest) => Promise<GateAnswer>;\n\ninterface PermissionFile {\n version: 1;\n /** Keyed by normalized project root. */\n projects: Record<string, ProjectPermissions>;\n}\n\n/** Stable store key for a project root (case-normalized on Windows). */\nexport function projectKey(root: string): string {\n const abs = resolve(root);\n return process.platform === 'win32' ? abs.toLowerCase() : abs;\n}\n\nfunction isConsent(v: unknown): v is Consent {\n return v === 'ask' || v === 'allow' || v === 'deny';\n}\n\nfunction readStore(): PermissionFile {\n const path = permissionsPath();\n if (!existsSync(path)) return { version: 1, projects: {} };\n try {\n const raw = JSON.parse(readFileSync(path, 'utf8')) as Partial<PermissionFile>;\n const projects: Record<string, ProjectPermissions> = {};\n for (const [proj, perms] of Object.entries(raw.projects ?? {})) {\n const clean: ProjectPermissions = {};\n for (const kind of ACTION_KINDS) {\n const v = (perms as Record<string, unknown>)[kind];\n if (isConsent(v) && v !== 'ask') clean[kind] = v;\n }\n if (Object.keys(clean).length > 0) projects[proj] = clean;\n }\n return { version: 1, projects };\n } catch {\n // Unreadable/corrupt store \u2192 fail safe: everything back to 'ask'.\n return { version: 1, projects: {} };\n }\n}\n\nfunction writeStore(store: PermissionFile): void {\n const path = permissionsPath();\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(store, null, 2), { mode: 0o600 });\n}\n\n/** Load the consent map for a project (kinds absent from the store are 'ask'). */\nexport function loadProjectPermissions(root: string): Record<ActionKind, Consent> {\n const stored = readStore().projects[projectKey(root)] ?? {};\n const out = {} as Record<ActionKind, Consent>;\n for (const kind of ACTION_KINDS) out[kind] = stored[kind] ?? 'ask';\n return out;\n}\n\n/** Persist one consent decision for a project ('ask' clears the stored entry). */\nexport function setConsent(root: string, kind: ActionKind, consent: Consent): void {\n const store = readStore();\n const key = projectKey(root);\n const perms: ProjectPermissions = { ...(store.projects[key] ?? {}) };\n if (consent === 'ask') delete perms[kind];\n else perms[kind] = consent;\n if (Object.keys(perms).length === 0) delete store.projects[key];\n else store.projects[key] = perms;\n writeStore(store);\n}\n\n/** Drop every stored decision for a project (all kinds back to 'ask'). */\nexport function resetProjectPermissions(root: string): void {\n const store = readStore();\n delete store.projects[projectKey(root)];\n writeStore(store);\n}\n\nexport interface PermissionGateOptions {\n /** Approve everything without prompting (dangerous; for scripts/tests). */\n readonly autoApprove?: boolean;\n}\n\n/**\n * THE permission gate: store lookup \u2192 prompt only when `ask` \u2192 persist on an\n * always-* answer. The store is re-read per request (it is one tiny JSON file),\n * so a decision immediately governs the very next action of the same kind \u2014 no\n * matter whether it came from a prompt, `/permissions set`, or another process.\n */\nexport function createPermissionGate(\n root: string,\n ask: AskFn,\n opts: PermissionGateOptions = {},\n): Gate {\n return async (req) => {\n if (opts.autoApprove) return true;\n const consent = loadProjectPermissions(root)[req.kind]; // store lookup BEFORE any prompt\n if (consent === 'allow') return true;\n if (consent === 'deny') return false;\n const answer = await ask(req);\n if (answer === 'always-allow') {\n setConsent(root, req.kind, 'allow');\n return true;\n }\n if (answer === 'always-deny') {\n setConsent(root, req.kind, 'deny');\n return false;\n }\n return answer === 'yes';\n };\n}\n\n/** One line per kind for `/permissions` and `futurex permissions show`. */\nexport function describePermissions(root: string): string[] {\n const consents = loadProjectPermissions(root);\n const label: Record<Consent, string> = {\n ask: 'ask each time',\n allow: 'always allow',\n deny: 'always deny',\n };\n return ACTION_KINDS.map((kind) => `${kind.padEnd(6)} ${label[consents[kind]]}`);\n}\n\n/** Narrow user input to an {@link ActionKind}. */\nexport function parseActionKind(s: string): ActionKind | undefined {\n const v = s.trim().toLowerCase();\n return (ACTION_KINDS as readonly string[]).includes(v) ? (v as ActionKind) : undefined;\n}\n\n/** Narrow user input to a {@link Consent}. */\nexport function parseConsent(s: string): Consent | undefined {\n const v = s.trim().toLowerCase();\n if (v === 'allow' || v === 'always-allow') return 'allow';\n if (v === 'deny' || v === 'always-deny') return 'deny';\n if (v === 'ask') return 'ask';\n return undefined;\n}\n", "import type { ZodTypeAny } from 'zod';\n\n/** Execution context handed to every tool. */\nexport interface ToolContext {\n /** Absolute repository root; all file paths are confined to it. */\n readonly repoRoot: string;\n}\n\n/**\n * The permission type a mutating tool call resolves to. Each kind carries its\n * own independent consent state in the CLI's permission store:\n * - `edit` \u2014 modifying an existing file\n * - `create` \u2014 creating a new file/resource\n * - `delete` \u2014 removing a file\n * - `run` \u2014 executing a shell/system command\n */\nexport type ActionKind = 'edit' | 'delete' | 'create' | 'run';\n\n/** All permission kinds, for iteration/validation (order = display order). */\nexport const ACTION_KINDS: readonly ActionKind[] = ['edit', 'create', 'delete', 'run'];\n\n/** The outcome of running a tool \u2014 `output` is fed back to the model verbatim. */\nexport interface ToolResult {\n readonly ok: boolean;\n readonly output: string;\n}\n\n/**\n * A tool the agent can call. `parameters` is the JSON Schema sent to the model;\n * `schema` is the Zod schema used to validate the model's arguments before\n * execution (model tool-call args are untrusted). `mutating` tools are gated\n * behind a permission prompt.\n */\nexport interface ToolSpec {\n readonly name: string;\n readonly description: string;\n readonly parameters: Record<string, unknown>;\n readonly mutating: boolean;\n readonly schema: ZodTypeAny;\n /** A short, human-readable preview of what executing `args` will do (permission gate). */\n preview(args: unknown, ctx: ToolContext): string;\n /**\n * Resolve which permission {@link ActionKind} executing `args` needs, or null\n * for a read-only call (never gated). May inspect the filesystem \u2014 e.g.\n * write_file is `edit` for an existing file and `create` for a new one.\n * Invariant: returns null iff `mutating` is false.\n */\n classify(args: unknown, ctx: ToolContext): ActionKind | null;\n run(args: unknown, ctx: ToolContext): Promise<ToolResult>;\n}\n", "import { isAbsolute, relative, resolve, sep } from 'node:path';\n\n/**\n * Resolve a model-supplied relative path to an absolute path INSIDE the repo, or\n * throw. Rejects absolute/UNC paths and `..` escapes (model tool-call args are\n * untrusted). Lexical check \u2014 a symlink-escape hardening pass is a later refinement.\n */\nexport function resolveInRepo(repoRoot: string, p: string): string {\n if (typeof p !== 'string' || p.length === 0) throw new Error('path is required');\n if (p.includes('\\0')) throw new Error('invalid path');\n if (isAbsolute(p)) throw new Error('absolute paths are not allowed');\n const abs = resolve(repoRoot, p);\n const rel = relative(repoRoot, abs);\n // Check the path SEGMENT, not the string prefix, so a file merely *named* with\n // leading dots (e.g. `...eslintrc`) is allowed while `../` traversal is rejected.\n if (rel === '..' || rel.startsWith(`..${sep}`) || rel.startsWith('../') || isAbsolute(rel)) {\n throw new Error('path escapes the repository root');\n }\n return abs;\n}\n", "import {\n type Dirent,\n existsSync,\n lstatSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n realpathSync,\n rmSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport { dirname, isAbsolute, join, relative, sep } from 'node:path';\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { z } from 'zod';\nimport { resolveInRepo } from './paths.js';\nimport type { ToolResult, ToolSpec } from './types.js';\n\nconst pexec = promisify(exec);\n\nconst MAX_OUTPUT = 8000;\nconst MAX_FILE_BYTES = 512 * 1024;\nconst EXEC_TIMEOUT_MS = 30_000;\nconst GREP_MAX_HITS = 100;\nconst GREP_BUDGET_MS = 5_000;\nconst GREP_MAX_LINE = 2_000;\nconst NUL = String.fromCharCode(0);\nconst WALK_IGNORE = new Set([\n '.git',\n 'node_modules',\n 'dist',\n 'build',\n '.next',\n '.turbo',\n 'coverage',\n '.data',\n '.cache',\n]);\n\n/** Destructive commands refused even after approval (defense-in-depth; the permission gate is primary). */\nconst EXEC_DENYLIST: readonly RegExp[] = [\n /\\brm\\s+(-\\w*[rf]\\w*|--(recursive|force|no-preserve-root))/i,\n /\\b(del|erase)\\s+\\/[sq]/i,\n /\\b(rd|rmdir)\\b[^\\n]*\\/s/i,\n /\\b(Remove-Item|ri)\\b[^\\n]*-Recurse/i,\n /\\bfind\\b[^\\n]*-delete\\b/i,\n /\\bchmod\\s+-R\\b/i,\n /\\bformat\\b/i,\n /\\bmkfs\\b/i,\n /\\bdd\\s+if=/i,\n /\\b(shutdown|reboot|halt)\\b/i,\n /:\\(\\)\\s*\\{.*\\};\\s*:/, // fork bomb\n /\\bgit\\s+push\\b/i,\n /\\b(curl|wget|irm|iwr)\\b[^|]*\\|\\s*(sh|bash|zsh|iex|powershell)/i,\n />\\s*\\/dev\\/sd/i,\n];\n\nfunction truncate(s: string, n = MAX_OUTPUT): string {\n return s.length > n ? `${s.slice(0, n)}\\n\u2026[truncated ${s.length - n} chars]` : s;\n}\n\n/**\n * Symlink-escape guard: the lexical check confines the path STRING; verify the\n * REAL parent directory is still inside the repo (a symlinked dir could\n * otherwise escape). The parent must exist when this is called.\n */\nfunction realParentEscapesRepo(abs: string, repoRoot: string): boolean {\n const realParent = realpathSync(dirname(abs));\n const relParent = relative(realpathSync(repoRoot), realParent);\n return relParent === '..' || relParent.startsWith(`..${sep}`) || isAbsolute(relParent);\n}\n\nfunction walkFiles(\n dir: string,\n repoRoot: string,\n onFile: (rel: string, content: string) => void,\n stop: () => boolean,\n): void {\n let entries: Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (stop()) return;\n const abs = join(dir, entry.name);\n if (entry.isDirectory()) {\n if (!WALK_IGNORE.has(entry.name)) walkFiles(abs, repoRoot, onFile, stop);\n continue;\n }\n if (!entry.isFile()) continue;\n try {\n if (statSync(abs).size > MAX_FILE_BYTES) continue;\n const content = readFileSync(abs, 'utf8');\n if (content.slice(0, 8000).includes(NUL)) continue;\n onFile(relative(repoRoot, abs).split(sep).join('/'), content);\n } catch {\n /* unreadable \u2014 skip */\n }\n }\n}\n\nconst readFileSpec: ToolSpec = {\n name: 'read_file',\n description: 'Read a UTF-8 text file from the repository.',\n parameters: {\n type: 'object',\n properties: { path: { type: 'string', description: 'repo-relative file path' } },\n required: ['path'],\n additionalProperties: false,\n },\n mutating: false,\n schema: z.object({ path: z.string().min(1) }),\n preview: (args) => `read ${(args as { path: string }).path}`,\n classify: () => null,\n async run(args, ctx): Promise<ToolResult> {\n const { path } = args as { path: string };\n const abs = resolveInRepo(ctx.repoRoot, path);\n if (!existsSync(abs)) return { ok: false, output: `not found: ${path}` };\n return { ok: true, output: truncate(readFileSync(abs, 'utf8')) };\n },\n};\n\nconst listDirSpec: ToolSpec = {\n name: 'list_dir',\n description: 'List the entries of a directory in the repository.',\n parameters: {\n type: 'object',\n properties: { path: { type: 'string', description: 'repo-relative directory (default \".\")' } },\n required: [],\n additionalProperties: false,\n },\n mutating: false,\n schema: z.object({ path: z.string().optional() }),\n preview: (args) => `list ${(args as { path?: string }).path ?? '.'}`,\n classify: () => null,\n async run(args, ctx): Promise<ToolResult> {\n const { path } = args as { path?: string };\n const abs = resolveInRepo(ctx.repoRoot, path && path.length > 0 ? path : '.');\n let entries: Dirent[];\n try {\n entries = readdirSync(abs, { withFileTypes: true });\n } catch {\n return { ok: false, output: `cannot list: ${path ?? '.'}` };\n }\n const names = entries.map((e) => (e.isDirectory() ? `${e.name}/` : e.name)).sort();\n return { ok: true, output: truncate(names.join('\\n')) || '(empty)' };\n },\n};\n\nconst grepSpec: ToolSpec = {\n name: 'grep_search',\n description:\n 'Search repository files for a JavaScript regular expression. Returns matching lines as \"path:line: text\".',\n parameters: {\n type: 'object',\n properties: {\n pattern: { type: 'string', description: 'regular expression' },\n path: { type: 'string', description: 'repo-relative directory to search (default \".\")' },\n },\n required: ['pattern'],\n additionalProperties: false,\n },\n mutating: false,\n schema: z.object({ pattern: z.string().min(1), path: z.string().optional() }),\n preview: (args) => `grep /${(args as { pattern: string }).pattern}/`,\n classify: () => null,\n async run(args, ctx): Promise<ToolResult> {\n const { pattern, path } = args as { pattern: string; path?: string };\n let re: RegExp;\n try {\n re = new RegExp(pattern);\n } catch {\n return { ok: false, output: `invalid regex: ${pattern}` };\n }\n const root = resolveInRepo(ctx.repoRoot, path && path.length > 0 ? path : '.');\n const hits: string[] = [];\n const deadline = Date.now() + GREP_BUDGET_MS;\n const stop = (): boolean => hits.length >= GREP_MAX_HITS || Date.now() > deadline;\n walkFiles(\n root,\n ctx.repoRoot,\n (rel, content) => {\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length && !stop(); i++) {\n const line = lines[i] ?? '';\n // Skip very long (minified) lines so a model-supplied regex can't ReDoS on them.\n if (line.length <= GREP_MAX_LINE && re.test(line)) {\n hits.push(`${rel}:${i + 1}: ${line.trim().slice(0, 200)}`);\n }\n }\n },\n stop,\n );\n const note = Date.now() > deadline ? '\\n\u2026[search time budget reached]' : '';\n return {\n ok: true,\n output: hits.length > 0 ? truncate(hits.join('\\n')) + note : 'no matches',\n };\n },\n};\n\nconst writeFileSpec: ToolSpec = {\n name: 'write_file',\n description: 'Create or overwrite a text file in the repository.',\n parameters: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'repo-relative file path' },\n content: { type: 'string', description: 'full new file contents' },\n },\n required: ['path', 'content'],\n additionalProperties: false,\n },\n mutating: true,\n schema: z.object({ path: z.string().min(1), content: z.string() }),\n preview: (args) => {\n const a = args as { path: string; content: string };\n return `write ${a.path} (${a.content.length} bytes)`;\n },\n // Overwriting an existing file is an EDIT; a new path is a CREATE \u2014 the two\n // carry independent consent states. Unresolvable paths classify as `create`\n // (the stricter-sounding default); run() re-validates and refuses anyway.\n classify: (args, ctx) => {\n try {\n return existsSync(resolveInRepo(ctx.repoRoot, (args as { path: string }).path))\n ? 'edit'\n : 'create';\n } catch {\n return 'create';\n }\n },\n async run(args, ctx): Promise<ToolResult> {\n const { path, content } = args as { path: string; content: string };\n const abs = resolveInRepo(ctx.repoRoot, path);\n mkdirSync(dirname(abs), { recursive: true });\n if (realParentEscapesRepo(abs, ctx.repoRoot)) {\n return { ok: false, output: 'refused: resolved path escapes the repository root' };\n }\n // writeFileSync FOLLOWS an existing symlink \u2014 refuse when its real target\n // lives outside the repo (the parent check above only covers directories).\n if (existsSync(abs)) {\n const real = realpathSync(abs);\n const rel = relative(realpathSync(ctx.repoRoot), real);\n if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {\n return { ok: false, output: 'refused: resolved path escapes the repository root' };\n }\n }\n writeFileSync(abs, content);\n return { ok: true, output: `wrote ${content.length} bytes to ${path}` };\n },\n};\n\nconst deleteFileSpec: ToolSpec = {\n name: 'delete_file',\n description: 'Delete a single file from the repository (not directories).',\n parameters: {\n type: 'object',\n properties: { path: { type: 'string', description: 'repo-relative file path' } },\n required: ['path'],\n additionalProperties: false,\n },\n mutating: true,\n schema: z.object({ path: z.string().min(1) }),\n preview: (args) => `delete ${(args as { path: string }).path}`,\n classify: () => 'delete',\n async run(args, ctx): Promise<ToolResult> {\n const { path } = args as { path: string };\n const abs = resolveInRepo(ctx.repoRoot, path);\n if (!existsSync(abs)) return { ok: false, output: `not found: ${path}` };\n // lstat (not stat): refuse symlinks outright rather than judging by their target.\n if (!lstatSync(abs).isFile()) {\n return { ok: false, output: `refused: ${path} is not a regular file` };\n }\n if (realParentEscapesRepo(abs, ctx.repoRoot)) {\n return { ok: false, output: 'refused: resolved path escapes the repository root' };\n }\n rmSync(abs);\n return { ok: true, output: `deleted ${path}` };\n },\n};\n\nconst execSpec: ToolSpec = {\n name: 'terminal_exec',\n description: 'Run a shell command in the repository root (builds, tests, inspection). Output is captured.',\n parameters: {\n type: 'object',\n properties: { command: { type: 'string', description: 'the shell command' } },\n required: ['command'],\n additionalProperties: false,\n },\n mutating: true,\n schema: z.object({ command: z.string().min(1) }),\n preview: (args) => `run: ${(args as { command: string }).command}`,\n classify: () => 'run',\n async run(args, ctx): Promise<ToolResult> {\n const { command } = args as { command: string };\n if (EXEC_DENYLIST.some((re) => re.test(command))) {\n return { ok: false, output: 'refused: command matches the destructive denylist' };\n }\n try {\n // killSignal makes the timeout terminate hard. NOTE: this does not kill a\n // descendant process tree on Windows \u2014 a full Job-Object kill-tree is a\n // tracked hardening refinement; the permission gate is the primary boundary.\n const { stdout, stderr } = await pexec(command, {\n cwd: ctx.repoRoot,\n timeout: EXEC_TIMEOUT_MS,\n killSignal: 'SIGKILL',\n maxBuffer: 1_000_000,\n windowsHide: true,\n });\n const out = `${stdout}${stderr ? `\\n[stderr]\\n${stderr}` : ''}`;\n return { ok: true, output: truncate(out) || '(no output)' };\n } catch (err) {\n const e = err as { stdout?: string; stderr?: string; message?: string; killed?: boolean };\n const body =\n `${e.killed ? 'command timed out\\n' : ''}${e.stdout ?? ''}${e.stderr ?? ''}` ||\n (e.message ?? 'command failed');\n return { ok: false, output: truncate(body) };\n }\n },\n};\n\n/** A lookup over the built-in tools. */\nexport interface ToolRegistry {\n readonly specs: readonly ToolSpec[];\n get(name: string): ToolSpec | undefined;\n}\n\nexport function createToolRegistry(): ToolRegistry {\n const specs: readonly ToolSpec[] = [\n readFileSpec,\n listDirSpec,\n grepSpec,\n writeFileSpec,\n deleteFileSpec,\n execSpec,\n ];\n const byName = new Map(specs.map((s) => [s.name, s] as const));\n return { specs, get: (name) => byName.get(name) };\n}\n", "/**\n * Local repo intelligence (Phase 0 lite): find the repo root, build a compact\n * RepoCard from manifests, and read the project memory file. Full AST/symbol\n * indexing + retrieval is Phase 2 (`@fim/futurex-context`).\n */\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport type { RepoCard } from '@fim/futurex-protocol';\n\nexport const MEMORY_FILENAME = 'futurex-memory.md';\n\n/**\n * Resolve the project root. A `.git` directory wins (the usual repo root). With\n * no `.git`, prefer the OUTERMOST workspace root (pnpm/lerna/nx) so running in a\n * sub-package still indexes the whole monorepo; otherwise fall back to the\n * nearest `package.json`.\n */\nconst WORKSPACE_MARKERS = ['pnpm-workspace.yaml', 'lerna.json', 'nx.json', 'turbo.json'];\n\nexport function findRepoRoot(start: string = process.cwd()): string {\n let dir = resolve(start);\n let nearestPackage: string | null = null;\n let workspaceRoot: string | null = null;\n for (;;) {\n if (existsSync(join(dir, '.git'))) return dir;\n if (WORKSPACE_MARKERS.some((m) => existsSync(join(dir, m)))) workspaceRoot = dir;\n if (nearestPackage === null && existsSync(join(dir, 'package.json'))) nearestPackage = dir;\n const parent = dirname(dir);\n if (parent === dir) break; // filesystem root\n dir = parent;\n }\n return workspaceRoot ?? nearestPackage ?? resolve(start);\n}\n\ninterface PackageJson {\n name?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n packageManager?: string;\n}\n\nfunction readJson(path: string): PackageJson | null {\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as PackageJson;\n } catch {\n return null;\n }\n}\n\n/** Best-effort: derive a compact card from package.json + lockfiles. */\nexport function buildRepoCard(root: string): RepoCard {\n const pkg = readJson(join(root, 'package.json'));\n const deps: Record<string, string> = {\n ...(pkg?.dependencies ?? {}),\n ...(pkg?.devDependencies ?? {}),\n };\n const has = (name: string): boolean => name in deps;\n\n const card: {\n -readonly [K in keyof RepoCard]: RepoCard[K];\n } = { root };\n\n if (pkg?.name) card.name = pkg.name;\n if (has('typescript')) card.language = 'TypeScript';\n\n if (has('next')) card.framework = 'Next.js';\n else if (has('react')) card.framework = 'React';\n else if (has('vue')) card.framework = 'Vue';\n else if (has('svelte')) card.framework = 'Svelte';\n\n if (has('fastify')) card.backend = 'Fastify';\n else if (has('express')) card.backend = 'Express';\n else if (has('@nestjs/core')) card.backend = 'NestJS';\n\n if (has('prisma') || has('@prisma/client')) card.orm = 'Prisma';\n else if (has('drizzle-orm')) card.orm = 'Drizzle';\n else if (has('typeorm')) card.orm = 'TypeORM';\n\n if (pkg?.packageManager?.startsWith('pnpm') || existsSync(join(root, 'pnpm-lock.yaml'))) {\n card.packageManager = 'pnpm';\n } else if (existsSync(join(root, 'yarn.lock'))) card.packageManager = 'yarn';\n else if (existsSync(join(root, 'package-lock.json'))) card.packageManager = 'npm';\n\n const testScript = pkg?.scripts?.test ?? '';\n if (/vitest/.test(testScript)) card.test = 'vitest';\n else if (/jest/.test(testScript)) card.test = 'jest';\n else if (/playwright/.test(testScript)) card.test = 'playwright';\n\n return card;\n}\n\n/** Read `futurex-memory.md` from the repo root, if present. */\nexport function readMemory(root: string): string | null {\n const path = join(root, MEMORY_FILENAME);\n if (!existsSync(path)) return null;\n try {\n const text = readFileSync(path, 'utf8').trim();\n return text.length > 0 ? text : null;\n } catch {\n return null;\n }\n}\n\n/** Write `futurex-memory.md` at the repo root (creating or overwriting it). */\nexport function saveMemory(root: string, content: string): void {\n writeFileSync(join(root, MEMORY_FILENAME), content.endsWith('\\n') ? content : `${content}\\n`, 'utf8');\n}\n", "/**\n * Environment validation for the FutureIST Master platform.\n *\n * The server schema is parsed exactly once at module load. If validation fails\n * the process throws a single, human-readable error that lists every missing or\n * invalid variable, so misconfiguration is caught at boot rather than at runtime.\n *\n * Client-safe values (anything that may be inlined into a browser bundle) are\n * validated separately via {@link clientEnv} and may ONLY contain `NEXT_PUBLIC_*`\n * keys. Never read server secrets from `clientEnv`.\n */\nimport { z } from 'zod';\n\n/** Recognized runtime modes for the platform. */\nexport const NODE_ENVS = ['development', 'test', 'production'] as const;\nexport type NodeEnv = (typeof NODE_ENVS)[number];\n\n/** A non-empty string that has been trimmed. */\nconst nonEmpty = (label: string) =>\n z.string({ required_error: `${label} is required` }).trim().min(1, `${label} must not be empty`);\n\n/** A URL string. Accepts http(s) and common service schemes (redis://, postgres://, s3://). */\nconst urlLike = (label: string) =>\n nonEmpty(label).refine(\n (value) => /^[a-z][a-z0-9+.-]*:\\/\\//i.test(value),\n `${label} must be a valid URL (e.g. https://\u2026, postgresql://\u2026, redis://\u2026)`,\n );\n\n/**\n * A datastore connection string. Accepts standard `scheme://\u2026` URLs (postgres,\n * redis, \u2026) AND SQLite-style `file:` paths (e.g. `file:./dev.db`), which have no\n * `//` authority component and would otherwise fail {@link urlLike}.\n */\nconst dbUrl = (label: string) =>\n nonEmpty(label).refine(\n (value) => /^[a-z][a-z0-9+.-]*:\\/\\//i.test(value) || /^file:/i.test(value),\n `${label} must be a connection URL (postgresql://\u2026) or a SQLite path (file:./dev.db)`,\n );\n\n/** A strict http/https URL (used for public-facing URLs). */\nconst httpUrl = (label: string) =>\n nonEmpty(label).refine((value) => {\n try {\n const parsed = new URL(value);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n return false;\n }\n }, `${label} must be a valid http(s) URL`);\n\n/** Coerce a stringified integer with optional bounds. */\nconst intFromString = (label: string, min = 0, max = 65535) =>\n z.coerce\n .number({ invalid_type_error: `${label} must be a number` })\n .int(`${label} must be an integer`)\n .min(min, `${label} must be >= ${min}`)\n .max(max, `${label} must be <= ${max}`);\n\n/** A duration accepted by jsonwebtoken / ms (e.g. \"15m\", \"7d\", \"3600\"). */\nconst duration = (label: string) =>\n nonEmpty(label).refine(\n (value) => /^\\d+$/.test(value) || /^\\d+(ms|s|m|h|d|w|y)$/i.test(value),\n `${label} must be a duration like \"15m\", \"7d\", or a number of seconds`,\n );\n\n/** A secret with a minimum length to discourage weak keys in any environment. */\nconst secret = (label: string, min = 16) =>\n nonEmpty(label).min(min, `${label} must be at least ${min} characters`);\n\n/**\n * An optional string where an empty/blank value (common in a copied `.env`\n * template, e.g. `ANTHROPIC_API_KEY=`) is treated as \"unset\" rather than an\n * invalid empty string.\n */\nconst optionalNonEmpty = () =>\n z.preprocess(\n (value) => (typeof value === \"string\" && value.trim() === \"\" ? undefined : value),\n z.string().trim().min(1).optional(),\n );\n\n/** Like {@link optionalNonEmpty} but falls back to `def` when unset/blank. */\nconst nonEmptyWithDefault = (def: string) =>\n z.preprocess(\n (value) => (typeof value === \"string\" && value.trim() === \"\" ? undefined : value),\n z.string().trim().min(1).default(def),\n );\n\n/**\n * An optional, case-insensitive enum where a blank value means \"unset\"\n * (provider auto-selection). Unknown values fail validation at boot rather\n * than at first use.\n */\nconst optionalEnum = <const T extends readonly [string, ...string[]]>(values: T) =>\n z.preprocess(\n (value) =>\n typeof value === \"string\" ? value.trim().toLowerCase() || undefined : value,\n z.enum(values).optional(),\n );\n\n/**\n * A strict optional boolean flag. Unlike `z.coerce.boolean()` (which treats\n * the string \"false\" as true), this maps \"1/true/on/yes\" \u2192 true and\n * \"0/false/off/no\" \u2192 false; blank/absent stays `undefined` so downstream\n * consumers can apply their own default.\n */\nconst optionalBoolFlag = () =>\n z.preprocess((value) => {\n if (typeof value === \"boolean\") return value;\n if (typeof value !== \"string\") return value;\n const v = value.trim().toLowerCase();\n if (v === \"\") return undefined;\n if ([\"1\", \"true\", \"on\", \"yes\"].includes(v)) return true;\n if ([\"0\", \"false\", \"off\", \"no\"].includes(v)) return false;\n return value; // let z.boolean() report the invalid value\n }, z.boolean().optional());\n\n/**\n * Environment-aware default: in production, fall back to the futurim.org\n * hostnames instead of localhost \u2014 so a prod build/process that's missing a URL\n * env var never silently emits a localhost link. An explicit env var still\n * overrides both; dev/test keep the localhost defaults. (`next build` sets\n * NODE_ENV=production, so client bundles inline the prod values too.)\n */\nconst PROD_ENV = process.env.NODE_ENV === 'production';\nconst byEnv = (dev: string, prod: string): string => (PROD_ENV ? prod : dev);\n\n/**\n * The full server-side environment schema. Optional integrations (AI, SMTP, S3)\n * are individually optional, but each is internally consistent: an S3 bucket\n * without credentials, for example, is reported by downstream feature flags.\n */\nconst serverObjectSchema = z.object({\n // \u2500\u2500 Runtime \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n NODE_ENV: z.enum(NODE_ENVS).default('development'),\n PORT: intFromString('PORT', 1).default(4000),\n WEB_PORT: intFromString('WEB_PORT', 1).default(3000),\n DASHBOARD_PORT: intFromString('DASHBOARD_PORT', 1).default(3001),\n WS_PORT: intFromString('WS_PORT', 1).default(4001),\n HOST: nonEmpty('HOST').default('0.0.0.0'),\n LOG_LEVEL: z\n .enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent'])\n .default('info'),\n /** Service name stamped into every structured log line. */\n SERVICE_NAME: nonEmpty('SERVICE_NAME').default('fim'),\n\n // \u2500\u2500 Runtime mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /**\n * Embedded / zero-dependency mode. When true the platform runs without any\n * external services: SQLite replaces Postgres, an in-process store replaces\n * Redis (cache / queues / pub-sub), the local filesystem replaces S3, and\n * outbound email is written to disk instead of an SMTP relay. Intended for\n * local development without Docker.\n */\n FIM_EMBEDDED: z.coerce.boolean().default(false),\n\n // \u2500\u2500 Datastores \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n DATABASE_URL: dbUrl('DATABASE_URL'),\n /** Direct (non-pooled) connection used by Prisma migrations. Falls back to DATABASE_URL. */\n DIRECT_URL: dbUrl('DIRECT_URL').optional(),\n REDIS_URL: urlLike('REDIS_URL').default('redis://localhost:6379'),\n\n // \u2500\u2500 Auth / JWT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n JWT_ACCESS_SECRET: secret('JWT_ACCESS_SECRET', 32),\n JWT_REFRESH_SECRET: secret('JWT_REFRESH_SECRET', 32),\n JWT_ACCESS_TTL: duration('JWT_ACCESS_TTL').default('15m'),\n JWT_REFRESH_TTL: duration('JWT_REFRESH_TTL').default('30d'),\n JWT_ISSUER: nonEmpty('JWT_ISSUER').default('futureist-master'),\n JWT_AUDIENCE: nonEmpty('JWT_AUDIENCE').default('fim-platform'),\n COOKIE_SECRET: secret('COOKIE_SECRET', 32).optional(),\n COOKIE_DOMAIN: z.string().trim().optional(),\n\n // \u2500\u2500 Better-Auth / FIM identity (BLUEPRINT \u00A74, Phases 3\u20139) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Canonical origin of the Better-Auth server (the API). Unset \u2192 inferred. */\n BETTER_AUTH_URL: httpUrl('BETTER_AUTH_URL').optional(),\n /** Better-Auth signing/encryption secret. REQUIRED + non-default in production. */\n BETTER_AUTH_SECRET: optionalNonEmpty(),\n /**\n * Toggle Better-Auth's built-in per-IP rate limiting. Unset \u2192 enabled\n * everywhere except `NODE_ENV=test` (see @fim/auth `createFimAuth`).\n */\n FIM_AUTH_RATE_LIMIT: optionalBoolFlag(),\n /** Embedded PGlite data dir (relative paths resolve against the repo root). */\n FIM_PGLITE_DIR: nonEmptyWithDefault('.data/pglite'),\n /** Root for on-disk dev sinks (mail, \u2026). Unset \u2192 `<repo>/.data`. */\n FIM_DATA_DIR: optionalNonEmpty(),\n /** Dev-only seeded studio owner (ignored in production). */\n FIM_OWNER_EMAIL: z.preprocess(\n (value) => (typeof value === 'string' && value.trim() === '' ? undefined : value),\n z.string().trim().email('FIM_OWNER_EMAIL must be a valid email address').optional(),\n ),\n FIM_OWNER_PASSWORD: z.preprocess(\n (value) => (typeof value === 'string' && value.trim() === '' ? undefined : value),\n z.string().min(8, 'FIM_OWNER_PASSWORD must be at least 8 characters').optional(),\n ),\n\n // \u2500\u2500 Payments (BLUEPRINT \u00A75.7, Phase 6) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Explicit provider override; unset \u2192 auto-select (stripe iff key present). */\n FIM_PAYMENTS_PROVIDER: optionalEnum(['stripe', 'dev']),\n STRIPE_SECRET_KEY: optionalNonEmpty(),\n STRIPE_WEBHOOK_SECRET: optionalNonEmpty(),\n /** HMAC secret for the dev provider's simulated stripe-signature header. */\n FIM_DEV_WEBHOOK_SECRET: nonEmptyWithDefault('dev-only-webhook-secret-change-me'),\n\n // \u2500\u2500 Portal files (BLUEPRINT \u00A75.8, Phase 8) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Explicit storage override; unset \u2192 auto-select (r2 iff all creds present). */\n FIM_FILES_PROVIDER: optionalEnum(['r2', 'dev']),\n /** Local-disk root for the dev provider (relative paths resolve to repo root). */\n FIM_FILES_DIR: nonEmptyWithDefault('.data/uploads/portal'),\n /** HMAC secret signing short-lived dev upload/download URLs. */\n FIM_DEV_FILES_SECRET: nonEmptyWithDefault('dev-only-files-secret-change-me'),\n R2_ACCOUNT_ID: optionalNonEmpty(),\n R2_ACCESS_KEY_ID: optionalNonEmpty(),\n R2_SECRET_ACCESS_KEY: optionalNonEmpty(),\n R2_BUCKET: optionalNonEmpty(),\n\n // \u2500\u2500 OAuth / social sign-in \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // All optional: a provider is \"configured\" only when BOTH its id and secret\n // are present. Register apps at:\n // GitHub \u2192 https://github.com/settings/developers\n // Google \u2192 https://console.cloud.google.com/apis/credentials\n // Apple \u2192 https://developer.apple.com/account/resources (Sign in with Apple)\n // Two auth surfaces consume these, each with its OWN callback URL \u2014 register\n // whichever you use on the provider (or both):\n // \u2022 Portal (Better-Auth): ${BETTER_AUTH_URL}/api/auth/callback/<provider>\n // \u2022 Dashboard (legacy): ${OAUTH_CALLBACK_BASE_URL ?? API_URL}/api/v1/auth/oauth/<provider>/callback\n GITHUB_OAUTH_CLIENT_ID: optionalNonEmpty(),\n GITHUB_OAUTH_CLIENT_SECRET: optionalNonEmpty(),\n GOOGLE_OAUTH_CLIENT_ID: optionalNonEmpty(),\n GOOGLE_OAUTH_CLIENT_SECRET: optionalNonEmpty(),\n // Apple: client id = Services ID; secret = the generated client-secret JWT.\n // The bundle id is only needed for native (iOS) clients.\n APPLE_OAUTH_CLIENT_ID: optionalNonEmpty(),\n APPLE_OAUTH_CLIENT_SECRET: optionalNonEmpty(),\n APPLE_OAUTH_APP_BUNDLE_IDENTIFIER: optionalNonEmpty(),\n /** Origin the providers redirect back to. Defaults to {@link API_URL}. */\n OAUTH_CALLBACK_BASE_URL: httpUrl('OAUTH_CALLBACK_BASE_URL').optional(),\n\n // \u2500\u2500 AI providers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n AI_PROVIDER: z.enum(['anthropic', 'openai', 'deepseek']).default('anthropic'),\n ANTHROPIC_API_KEY: optionalNonEmpty(),\n ANTHROPIC_MODEL: nonEmpty('ANTHROPIC_MODEL').default('claude-opus-4-8'),\n OPENAI_API_KEY: optionalNonEmpty(),\n OPENAI_MODEL: nonEmpty('OPENAI_MODEL').default('gpt-4o'),\n DEEPSEEK_API_KEY: optionalNonEmpty(),\n // Legacy aliases (deepseek-chat / deepseek-reasoner) are retired 2026-07-24 and\n // removed from @fim/ai-sdk \u2014 reject them here with a clear message rather than\n // letting a stale config silently 400 at request time. (Inlined, not imported\n // from @fim/ai-sdk, because @fim/ai-sdk depends on @fim/config \u2014 not the reverse.)\n DEEPSEEK_MODEL: nonEmpty('DEEPSEEK_MODEL')\n .refine((m) => m !== 'deepseek-chat' && m !== 'deepseek-reasoner', {\n message:\n \"DEEPSEEK_MODEL 'deepseek-chat' / 'deepseek-reasoner' are deprecated and removed; use 'deepseek-v4-flash' or 'deepseek-v4-pro'.\",\n })\n .default('deepseek-v4-flash'),\n /** Override the DeepSeek base URL (proxy / gateway / self-hosted). */\n DEEPSEEK_BASE_URL: urlLike('DEEPSEEK_BASE_URL').optional(),\n AI_EMBEDDING_MODEL: nonEmpty('AI_EMBEDDING_MODEL').default('text-embedding-3-large'),\n\n // \u2500\u2500 FutureX context engine (docs/futurex/context-engine-discovery.md \u00A76.1) \u2500\n // Which per-turn context provider the futurex gateway uses: 'legacy' (the\n // session-digest summary message \u2014 today's behavior, byte-identical) or\n // 'graph' (the Context Graph Engine). Pinned into SessionMeta at session\n // open so an in-flight session never flips mid-conversation (prefix-cache\n // discipline). Stays 'legacy' until the engine wins its Phase 8 eval.\n // (Inlined union, not imported from @fim/futurex-context-engine, to keep\n // @fim/config dependency-free \u2014 same reasoning as DEEPSEEK_MODEL above.)\n FUTUREX_CONTEXT_ENGINE: z.enum(['graph', 'legacy']).default('legacy'),\n\n // \u2500\u2500 SMTP / Mail \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n SMTP_HOST: z.string().trim().optional(),\n SMTP_PORT: intFromString('SMTP_PORT', 1).default(587),\n SMTP_USER: z.string().trim().optional(),\n SMTP_PASSWORD: z.string().optional(),\n SMTP_SECURE: z.coerce.boolean().default(false),\n MAIL_FROM: z\n .string()\n .trim()\n .email('MAIL_FROM must be a valid email address')\n .default('no-reply@futureist.io'),\n MAIL_FROM_NAME: nonEmpty('MAIL_FROM_NAME').default('FutureIST Master'),\n\n // \u2500\u2500 Object storage (S3 compatible) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n S3_REGION: nonEmpty('S3_REGION').default('us-east-1'),\n S3_ENDPOINT: urlLike('S3_ENDPOINT').optional(),\n S3_BUCKET: z.string().trim().optional(),\n S3_ACCESS_KEY_ID: z.string().trim().optional(),\n S3_SECRET_ACCESS_KEY: z.string().optional(),\n S3_FORCE_PATH_STYLE: z.coerce.boolean().default(false),\n S3_PUBLIC_URL: httpUrl('S3_PUBLIC_URL').optional(),\n\n // \u2500\u2500 Public URLs (server-known canonical origins) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n APP_URL: httpUrl('APP_URL').default(byEnv('http://localhost:3000', 'https://futurim.org')),\n DASHBOARD_URL: httpUrl('DASHBOARD_URL').default(\n byEnv('http://localhost:3001', 'https://admin.futurim.org'),\n ),\n PORTAL_URL: httpUrl('PORTAL_URL').default(\n byEnv('http://localhost:3002', 'https://portal.futurim.org'),\n ),\n API_URL: httpUrl('API_URL').default(byEnv('http://localhost:4000', 'https://api.futurim.org')),\n WS_URL: urlLike('WS_URL').default(byEnv('ws://localhost:4001', 'wss://api.futurim.org')),\n\n // \u2500\u2500 CORS / security \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n CORS_ORIGINS: z\n .string()\n .trim()\n .default(\n byEnv(\n 'http://localhost:3000,http://localhost:3001',\n 'https://futurim.org,https://www.futurim.org,https://admin.futurim.org,https://portal.futurim.org',\n ),\n )\n .transform((value) =>\n value\n .split(',')\n .map((origin) => origin.trim())\n .filter(Boolean),\n ),\n RATE_LIMIT_MAX: intFromString('RATE_LIMIT_MAX', 1, 1_000_000).default(100),\n RATE_LIMIT_WINDOW: duration('RATE_LIMIT_WINDOW').default('1m'),\n\n // \u2500\u2500 Feature toggles (raw; parsed in feature-flags.ts) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n FEATURE_AI_ASSISTANT: z.coerce.boolean().optional(),\n FEATURE_REALTIME: z.coerce.boolean().optional(),\n FEATURE_ANALYTICS: z.coerce.boolean().optional(),\n FEATURE_BILLING: z.coerce.boolean().optional(),\n FEATURE_FILE_UPLOADS: z.coerce.boolean().optional(),\n FEATURE_EMAIL_NOTIFICATIONS: z.coerce.boolean().optional(),\n MAINTENANCE_MODE: z.coerce.boolean().optional(),\n});\n\n/**\n * Production-only consistency refinements (BLUEPRINT Phase 9 hardening).\n * Development/test keep the permissive optional-with-defaults behavior.\n */\nconst serverSchema = serverObjectSchema.superRefine((cfg, ctx) => {\n if (cfg.NODE_ENV !== 'production') return;\n\n // Better-Auth secret: required, non-trivial, and never a dev placeholder.\n if (!cfg.BETTER_AUTH_SECRET) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['BETTER_AUTH_SECRET'],\n message: 'BETTER_AUTH_SECRET is required in production',\n });\n } else if (\n cfg.BETTER_AUTH_SECRET.length < 32 ||\n cfg.BETTER_AUTH_SECRET.includes('change-me') ||\n cfg.BETTER_AUTH_SECRET.startsWith('dev-')\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['BETTER_AUTH_SECRET'],\n message:\n 'BETTER_AUTH_SECRET must be a real secret in production (>= 32 chars, not a dev placeholder)',\n });\n }\n\n // Stripe credentials are mandatory when the provider is explicitly stripe.\n if (cfg.FIM_PAYMENTS_PROVIDER === 'stripe') {\n for (const key of ['STRIPE_SECRET_KEY', 'STRIPE_WEBHOOK_SECRET'] as const) {\n if (!cfg[key]) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [key],\n message: `${key} is required in production when FIM_PAYMENTS_PROVIDER=stripe`,\n });\n }\n }\n }\n\n // R2 credentials are mandatory when the files provider is explicitly r2.\n if (cfg.FIM_FILES_PROVIDER === 'r2') {\n for (const key of [\n 'R2_ACCOUNT_ID',\n 'R2_ACCESS_KEY_ID',\n 'R2_SECRET_ACCESS_KEY',\n 'R2_BUCKET',\n ] as const) {\n if (!cfg[key]) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [key],\n message: `${key} is required in production when FIM_FILES_PROVIDER=r2`,\n });\n }\n }\n }\n});\n\n/** Inferred shape of the validated server environment. */\nexport type ServerEnv = z.infer<typeof serverObjectSchema>;\n\n/** Public client schema. ONLY `NEXT_PUBLIC_*` keys are permitted here. */\nconst clientSchema = z.object({\n NEXT_PUBLIC_APP_NAME: nonEmpty('NEXT_PUBLIC_APP_NAME').default('FutureIST Master'),\n NEXT_PUBLIC_APP_URL: httpUrl('NEXT_PUBLIC_APP_URL').default(\n byEnv('http://localhost:3000', 'https://futurim.org'),\n ),\n // Includes the versioned API prefix: the dashboard's api-client and AuthProvider\n // address routes WITHOUT re-stating `/api/v1` (e.g. `/auth/login`, `/projects`),\n // so the base must carry it. Backend mounts every module under `/api/v1`.\n NEXT_PUBLIC_API_URL: httpUrl('NEXT_PUBLIC_API_URL').default(\n byEnv('http://localhost:4000/api/v1', 'https://api.futurim.org/api/v1'),\n ),\n // Browser-side origin of the Better-Auth server (no /api/v1 suffix \u2014 the\n // auth client appends /api/auth itself).\n NEXT_PUBLIC_AUTH_URL: httpUrl('NEXT_PUBLIC_AUTH_URL').default(\n byEnv('http://localhost:4000', 'https://api.futurim.org'),\n ),\n // The portal (apps/portal) origin, used by site CTAs and cross-app links.\n NEXT_PUBLIC_PORTAL_URL: httpUrl('NEXT_PUBLIC_PORTAL_URL').default(\n byEnv('http://localhost:3002', 'https://portal.futurim.org'),\n ),\n NEXT_PUBLIC_WS_URL: urlLike('NEXT_PUBLIC_WS_URL').default(\n byEnv('ws://localhost:4001', 'wss://api.futurim.org'),\n ),\n NEXT_PUBLIC_ENV: z.enum(NODE_ENVS).default('development'),\n NEXT_PUBLIC_ANALYTICS_WRITE_KEY: z.string().trim().optional(),\n NEXT_PUBLIC_SENTRY_DSN: z.string().trim().optional(),\n});\n\n/** Inferred shape of the validated client environment. */\nexport type ClientEnv = z.infer<typeof clientSchema>;\n\n/**\n * Format a {@link z.ZodError} into a single multi-line message listing each\n * offending variable so the failure is actionable at a glance.\n */\nfunction describeEnvError(error: z.ZodError, scope: 'server' | 'client'): string {\n const lines = error.issues.map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';\n return ` \u2022 ${path}: ${issue.message}`;\n });\n return [\n `Invalid ${scope} environment configuration. ${error.issues.length} problem(s) found:`,\n ...lines,\n '',\n `Fix the variables above in your .env file (or deployment secrets) and restart.`,\n ].join('\\n');\n}\n\n/**\n * Parse the server environment from a source object (defaults to `process.env`).\n * Throws an {@link Error} with a clear, aggregated message on failure.\n */\nexport function parseServerEnv(source: NodeJS.ProcessEnv = process.env): ServerEnv {\n const parsed = serverSchema.safeParse(source);\n if (!parsed.success) {\n throw new Error(describeEnvError(parsed.error, 'server'));\n }\n // DIRECT_URL conventionally mirrors DATABASE_URL when not explicitly set.\n return {\n ...parsed.data,\n DIRECT_URL: parsed.data.DIRECT_URL ?? parsed.data.DATABASE_URL,\n };\n}\n\n/**\n * Parse the client environment from a source object (defaults to `process.env`).\n * Safe to call in the browser when bundlers inline `NEXT_PUBLIC_*` values.\n */\nexport function parseClientEnv(source: NodeJS.ProcessEnv = process.env): ClientEnv {\n const parsed = clientSchema.safeParse(source);\n if (!parsed.success) {\n throw new Error(describeEnvError(parsed.error, 'client'));\n }\n return parsed.data;\n}\n\n/**\n * On the server, validation is memoized and deferred to the FIRST property\n * access on {@link env}: services that read `env.*` at boot (the API, workers)\n * still fail fast with the aggregated message, while modules that only need\n * {@link clientEnv} or {@link siteConfig} (e.g. the marketing site's\n * robots/sitemap during `next build`, where NODE_ENV=production but no server\n * secrets exist) can be imported without triggering server-secret validation.\n * In the browser we skip the server parse entirely (its secrets are never\n * present) and build a stub so importing `env` from client code does not crash\n * \u2014 though client code should use {@link clientEnv} instead.\n */\nconst isServer = typeof (globalThis as { window?: unknown }).window === 'undefined';\n\n/** Memoized result of the one-time server parse (see {@link env}). */\nlet serverEnvCache: ServerEnv | undefined;\n\n/** Parse-and-memoize the server environment (throws on invalid config). */\nfunction resolveServerEnv(): ServerEnv {\n // NOT frozen: the proxy below rejects writes itself, and reporting frozen\n // (non-configurable) descriptors through a proxy whose target is `{}` would\n // violate proxy invariants.\n serverEnvCache ??= parseServerEnv();\n return serverEnvCache;\n}\n\n/**\n * The validated, typed, immutable server environment. Parsed once, on first\n * property access (lazy via Proxy \u2014 see the note above).\n */\nexport const env: ServerEnv = isServer\n ? (new Proxy({} as ServerEnv, {\n get: (_target, prop) => Reflect.get(resolveServerEnv(), prop),\n has: (_target, prop) => Reflect.has(resolveServerEnv(), prop),\n ownKeys: () => Reflect.ownKeys(resolveServerEnv()),\n getOwnPropertyDescriptor: (_target, prop) => {\n const desc = Reflect.getOwnPropertyDescriptor(resolveServerEnv(), prop);\n // Report configurable so the (extensible, empty) proxy target does not\n // violate invariants; immutability is enforced by the traps below.\n return desc ? { ...desc, configurable: true } : undefined;\n },\n set: () => false,\n defineProperty: () => false,\n deleteProperty: () => false,\n }) as ServerEnv)\n : (Object.freeze(\n // On the client, only NEXT_PUBLIC_* exist; coerce a best-effort view so a\n // stray server-side import in a shared module does not throw. Access to a\n // real secret will be `undefined`, which downstream guards already handle.\n serverObjectSchema.partial().parse(\n typeof process !== 'undefined' ? (process.env ?? {}) : {},\n ),\n ) as ServerEnv);\n\n/** The validated, typed, immutable client environment. Parsed once. */\nexport const clientEnv: ClientEnv = Object.freeze(\n parseClientEnv(typeof process !== 'undefined' ? process.env : ({} as NodeJS.ProcessEnv)),\n);\n\n/**\n * Raw NODE_ENV view, mirroring the schema's enum-with-default. Computed from\n * `process.env` directly so the convenience predicates below do not force the\n * full (lazy) server-env parse at import time.\n */\nconst rawNodeEnv: NodeEnv = (() => {\n const raw = typeof process !== 'undefined' ? process.env.NODE_ENV : undefined;\n return raw !== undefined && (NODE_ENVS as readonly string[]).includes(raw)\n ? (raw as NodeEnv)\n : 'development';\n})();\n\n/** Convenience predicates derived from NODE_ENV. */\nexport const isProduction = rawNodeEnv === 'production';\nexport const isDevelopment = rawNodeEnv === 'development';\nexport const isTest = rawNodeEnv === 'test';\n\n/**\n * Whether the platform is running in embedded / zero-dependency mode (SQLite +\n * in-process Redis substitutes + local filesystem storage + on-disk mail).\n * Mirrors the schema's `z.coerce.boolean()` on FIM_EMBEDDED (any non-empty\n * string \u2192 true) without forcing the lazy server parse.\n */\nexport const isEmbedded =\n isServer && typeof process !== 'undefined' && Boolean(process.env.FIM_EMBEDDED);\n\n/** Whether the runtime currently executes on the server. */\nexport const IS_SERVER = isServer;\n", "import { hostname } from 'node:os';\n\nimport { pino } from 'pino';\nimport type { Logger, LoggerOptions, TransportSingleOptions } from 'pino';\n\nimport { env } from '@fim/config';\n\n/**\n * Fields that must never be written to logs in plaintext. The list covers the\n * most common locations where credentials, tokens, and other secrets leak into\n * structured log payloads (HTTP headers, auth bodies, cookies, etc.).\n *\n * pino's `redact` option supports both dotted and bracketed JSON paths; we\n * enumerate the realistic nesting depths used across the FIM services so that a\n * secret is scrubbed regardless of where it appears in the merged log object.\n */\nconst REDACT_PATHS: readonly string[] = [\n 'password',\n 'newPassword',\n 'currentPassword',\n 'token',\n 'accessToken',\n 'refreshToken',\n 'apiKey',\n 'secret',\n 'authorization',\n 'cookie',\n 'set-cookie',\n // Nested under a request object.\n 'req.headers.authorization',\n 'req.headers.cookie',\n 'req.body.password',\n 'req.body.token',\n 'req.body.accessToken',\n 'req.body.refreshToken',\n // Nested under a response object.\n 'res.headers[\"set-cookie\"]',\n // Generic header maps (case variations seen across HTTP stacks).\n 'headers.authorization',\n 'headers.Authorization',\n 'headers.cookie',\n 'headers.Cookie',\n '*.password',\n '*.token',\n '*.accessToken',\n '*.refreshToken',\n];\n\n/** Placeholder rendered in place of a redacted value. */\nconst REDACT_CENSOR = '[REDACTED]';\n\n/** The (non-secret) trio of env values the logger actually needs. */\ninterface LoggerEnv {\n nodeEnv: 'development' | 'test' | 'production';\n logLevel: string;\n serviceName: string;\n}\n\n/** Pino levels accepted by the schema; mirrored for the raw fallback below. */\nconst LOG_LEVELS: readonly string[] = ['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent'];\n\n/**\n * Resolve NODE_ENV / LOG_LEVEL / SERVICE_NAME. Prefer the validated env, but a\n * logger must never crash the process over an UNRELATED misconfigured secret \u2014\n * e.g. during a Next.js production build of the marketing site, where reading\n * `@fim/config`'s (lazy) `env` throws because no server secrets exist. In that\n * case degrade to raw `process.env` with the schema's own defaults.\n */\nfunction readLoggerEnv(): LoggerEnv {\n try {\n return {\n nodeEnv: env.NODE_ENV,\n logLevel: env.LOG_LEVEL,\n serviceName: env.SERVICE_NAME ?? 'fim',\n };\n } catch {\n const raw = typeof process !== 'undefined' ? process.env : ({} as NodeJS.ProcessEnv);\n const nodeEnv =\n raw.NODE_ENV === 'production' || raw.NODE_ENV === 'test' ? raw.NODE_ENV : 'development';\n const rawLevel = raw.LOG_LEVEL?.trim() ?? '';\n return {\n nodeEnv,\n logLevel: LOG_LEVELS.includes(rawLevel) ? rawLevel : 'info',\n serviceName: raw.SERVICE_NAME?.trim() || 'fim',\n };\n }\n}\n\nconst loggerEnv = readLoggerEnv();\n\nconst isProduction = loggerEnv.nodeEnv === 'production';\nconst isTest = loggerEnv.nodeEnv === 'test';\n\n/**\n * In development we stream through `pino-pretty` for human-friendly, colorized\n * output. In production (and test) we emit newline-delimited JSON so logs can be\n * ingested by aggregators (Loki, Datadog, CloudWatch, etc.) without a parsing\n * step. The transport is only attached when pretty printing is desired.\n */\nfunction buildTransport(): TransportSingleOptions | undefined {\n if (isProduction || isTest) {\n return undefined;\n }\n // Under Next.js (bundled server / SSR), pino's worker-thread transport cannot\n // resolve its worker file and crashes the request. Fall back to plain JSON.\n if (process.env.NEXT_RUNTIME) {\n return undefined;\n }\n\n return {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l',\n ignore: 'pid,hostname',\n singleLine: false,\n messageKey: 'msg',\n errorLikeObjectKeys: ['err', 'error'],\n },\n };\n}\n\n/**\n * Base configuration shared by the root logger and every child created from it.\n * Exported so that sibling helpers (e.g. the HTTP request logger) can derive a\n * consistent configuration instead of re-declaring serializers/redaction.\n */\nexport const baseLoggerOptions: LoggerOptions = {\n level: loggerEnv.logLevel,\n // ISO-8601 timestamps with millisecond precision, e.g. 2026-06-05T12:34:56.789Z\n timestamp: pino.stdTimeFunctions.isoTime,\n messageKey: 'msg',\n errorKey: 'err',\n // Surface human-readable level labels in the JSON output instead of numbers.\n formatters: {\n level(label: string, _number: number) {\n return { level: label };\n },\n bindings(bindings) {\n return {\n pid: bindings['pid'],\n hostname: bindings['hostname'],\n };\n },\n },\n redact: {\n paths: [...REDACT_PATHS],\n censor: REDACT_CENSOR,\n remove: false,\n },\n base: {\n service: loggerEnv.serviceName,\n env: loggerEnv.nodeEnv,\n hostname: hostname(),\n },\n // Silence logging entirely under test unless a level is explicitly requested,\n // keeping unit-test output clean and deterministic.\n enabled: !isTest || loggerEnv.logLevel !== 'silent',\n};\n\n/**\n * The application-wide root logger. Import this directly for module-level or\n * one-off logging, or call {@link createLogger} to derive a namespaced child.\n *\n * @example\n * ```ts\n * import { logger } from '@fim/logger';\n * logger.info({ userId }, 'user authenticated');\n * ```\n */\nexport const logger: Logger = (() => {\n const transport = buildTransport();\n return transport\n ? pino({ ...baseLoggerOptions, transport })\n : pino(baseLoggerOptions);\n})();\n\nexport type { Logger };\n", "import type { Bindings, Logger } from 'pino';\n\nimport { logger } from './logger.js';\n\n/**\n * Create a namespaced child logger derived from the application root logger.\n *\n * The supplied `name` is attached as a `name` binding on every record emitted by\n * the returned logger, which makes it trivial to filter logs by subsystem (e.g.\n * `name=auth` or `name=ws:gateway`). Additional static bindings can be supplied\n * and will be merged onto every record as well.\n *\n * Child loggers are cheap to create and inherit the parent's level, redaction\n * rules, serializers, and transport \u2014 so it is idiomatic to create one per\n * module, class, or long-lived component.\n *\n * @param name - Stable identifier for the subsystem, e.g. `\"auth\"`, `\"api\"`.\n * @param bindings - Optional extra fields merged onto every child record.\n * @returns A pino child {@link Logger}.\n *\n * @example\n * ```ts\n * const log = createLogger('projects');\n * log.debug({ projectId }, 'recalculating progress');\n * ```\n */\nexport function createLogger(name: string, bindings: Bindings = {}): Logger {\n return logger.child({ name, ...bindings });\n}\n", "/**\n * Application error hierarchy for the FIM platform.\n *\n * Every error carries an HTTP `statusCode`, a stable machine-readable `code`,\n * and an `isOperational` flag distinguishing expected/operational failures\n * (bad input, missing resource, auth) from unexpected programmer errors. HTTP\n * layers should serialize operational errors to clients and treat\n * non-operational ones as opaque 500s.\n */\n\n/** Stable, machine-readable error codes emitted across the platform. */\nexport const ErrorCode = {\n INTERNAL: 'INTERNAL_ERROR',\n NOT_FOUND: 'NOT_FOUND',\n UNAUTHORIZED: 'UNAUTHORIZED',\n FORBIDDEN: 'FORBIDDEN',\n VALIDATION: 'VALIDATION_ERROR',\n CONFLICT: 'CONFLICT',\n RATE_LIMIT: 'RATE_LIMITED',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\n/** Structured field-level validation issue. */\nexport interface ValidationIssue {\n /** Dotted/array path to the offending field, e.g. `user.email`. */\n readonly path: string;\n /** Human-readable message describing the problem. */\n readonly message: string;\n /** Optional validator-specific code, e.g. `too_small`. */\n readonly code?: string;\n}\n\n/** Options accepted by every {@link AppError}. */\nexport interface AppErrorOptions {\n /** HTTP status code associated with this error. */\n readonly statusCode?: number;\n /** Stable machine-readable code. */\n readonly code?: string;\n /**\n * Whether the error is operational (expected) versus a programmer error.\n * Operational errors are safe to surface to API consumers.\n */\n readonly isOperational?: boolean;\n /** The underlying cause, preserved for logging and stack chaining. */\n readonly cause?: unknown;\n /** Arbitrary structured context attached for debugging/telemetry. */\n readonly details?: unknown;\n}\n\n/** Shape produced by {@link AppError.toJSON}, safe for API responses. */\nexport interface SerializedError {\n readonly name: string;\n readonly message: string;\n readonly code: string;\n readonly statusCode: number;\n readonly details?: unknown;\n}\n\n/**\n * Base class for all known application errors.\n *\n * Extends the native `Error` while preserving the prototype chain under\n * transpilation, capturing a clean stack trace, and forwarding `cause` to the\n * standard `Error` options.\n */\nexport class AppError extends Error {\n public readonly statusCode: number;\n public readonly code: string;\n public readonly isOperational: boolean;\n public readonly details?: unknown;\n\n constructor(message: string, options: AppErrorOptions = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n\n this.name = new.target.name;\n this.statusCode = options.statusCode ?? 500;\n this.code = options.code ?? ErrorCode.INTERNAL;\n this.isOperational = options.isOperational ?? true;\n this.details = options.details;\n\n // Restore prototype chain for instanceof checks after transpilation to ES5/ESNext targets.\n Object.setPrototypeOf(this, new.target.prototype);\n\n // Exclude the constructor frame from the captured stack when available (V8).\n const captureStackTrace = (\n Error as unknown as {\n captureStackTrace?: (target: object, ctor?: Function) => void;\n }\n ).captureStackTrace;\n if (typeof captureStackTrace === 'function') {\n captureStackTrace(this, new.target);\n }\n }\n\n /** Serialize to a client-safe plain object. */\n toJSON(): SerializedError {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n statusCode: this.statusCode,\n ...(this.details === undefined ? {} : { details: this.details }),\n };\n }\n}\n\n/** Resource could not be located (HTTP 404). */\nexport class NotFoundError extends AppError {\n constructor(message = 'Resource not found', options: Omit<AppErrorOptions, 'statusCode' | 'code'> = {}) {\n super(message, { ...options, statusCode: 404, code: ErrorCode.NOT_FOUND, isOperational: true });\n }\n}\n\n/** Authentication is required or the supplied credentials are invalid (HTTP 401). */\nexport class UnauthorizedError extends AppError {\n constructor(message = 'Authentication required', options: Omit<AppErrorOptions, 'statusCode' | 'code'> = {}) {\n super(message, { ...options, statusCode: 401, code: ErrorCode.UNAUTHORIZED, isOperational: true });\n }\n}\n\n/** The caller is authenticated but lacks permission (HTTP 403). */\nexport class ForbiddenError extends AppError {\n constructor(message = 'You do not have permission to perform this action', options: Omit<AppErrorOptions, 'statusCode' | 'code'> = {}) {\n super(message, { ...options, statusCode: 403, code: ErrorCode.FORBIDDEN, isOperational: true });\n }\n}\n\n/**\n * Input failed validation (HTTP 422).\n *\n * Carries a structured list of field-level {@link ValidationIssue}s in addition\n * to the generic `details` payload.\n */\nexport class ValidationError extends AppError {\n public readonly issues: readonly ValidationIssue[];\n\n constructor(\n message = 'The request payload is invalid',\n issues: readonly ValidationIssue[] = [],\n options: Omit<AppErrorOptions, 'statusCode' | 'code' | 'details'> = {},\n ) {\n super(message, {\n ...options,\n statusCode: 422,\n code: ErrorCode.VALIDATION,\n isOperational: true,\n details: { issues },\n });\n this.issues = issues;\n }\n}\n\n/** The request conflicts with the current state of the resource (HTTP 409). */\nexport class ConflictError extends AppError {\n constructor(message = 'The request conflicts with the current resource state', options: Omit<AppErrorOptions, 'statusCode' | 'code'> = {}) {\n super(message, { ...options, statusCode: 409, code: ErrorCode.CONFLICT, isOperational: true });\n }\n}\n\n/** Options specific to {@link RateLimitError}. */\nexport interface RateLimitErrorOptions extends Omit<AppErrorOptions, 'statusCode' | 'code'> {\n /** Seconds the client should wait before retrying (maps to `Retry-After`). */\n readonly retryAfterSeconds?: number;\n}\n\n/** Too many requests in a given window (HTTP 429). */\nexport class RateLimitError extends AppError {\n public readonly retryAfterSeconds?: number;\n\n constructor(message = 'Too many requests, please slow down', options: RateLimitErrorOptions = {}) {\n const { retryAfterSeconds, ...rest } = options;\n super(message, { ...rest, statusCode: 429, code: ErrorCode.RATE_LIMIT, isOperational: true });\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\n/**\n * An unexpected, non-operational failure (HTTP 500).\n *\n * Defaults `isOperational` to `false` so monitoring can distinguish genuine\n * bugs from anticipated failures.\n */\nexport class InternalError extends AppError {\n constructor(message = 'An unexpected error occurred', options: Omit<AppErrorOptions, 'statusCode' | 'code'> = {}) {\n super(message, { isOperational: false, ...options, statusCode: 500, code: ErrorCode.INTERNAL });\n }\n}\n\n/** Type guard narrowing an unknown value to {@link AppError}. */\nexport function isAppError(value: unknown): value is AppError {\n return value instanceof AppError;\n}\n\n/**\n * Normalize any thrown value into an {@link AppError}.\n *\n * Already-{@link AppError} values pass through unchanged; native `Error`s and\n * arbitrary thrown values are wrapped in a non-operational {@link InternalError}\n * with the original preserved as `cause`.\n */\nexport function toAppError(value: unknown): AppError {\n if (isAppError(value)) return value;\n if (value instanceof Error) {\n return new InternalError(value.message, { cause: value });\n }\n return new InternalError('Unknown error', { cause: value });\n}\n", "/**\n * Asynchronous control-flow helpers: delays, retries with backoff, timeouts,\n * and bounded-concurrency mapping. All helpers are isomorphic (no Node-only\n * APIs) and honour `AbortSignal` where it makes sense.\n */\n\n/** Reusable abort-aware delay error. */\nexport class AbortError extends Error {\n constructor(message = 'The operation was aborted') {\n super(message);\n this.name = 'AbortError';\n }\n}\n\n/** Options for {@link sleep}. */\nexport interface SleepOptions {\n /** Abort the pending delay early, rejecting with {@link AbortError}. */\n readonly signal?: AbortSignal;\n}\n\n/**\n * Resolve after `ms` milliseconds. When an aborted `signal` is supplied the\n * returned promise rejects immediately (or as soon as the signal fires).\n */\nexport function sleep(ms: number, options: SleepOptions = {}): Promise<void> {\n const { signal } = options;\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(toAbortError(signal));\n return;\n }\n\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, Math.max(0, ms));\n\n const onAbort = (): void => {\n cleanup();\n reject(toAbortError(signal));\n };\n\n const cleanup = (): void => {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n };\n\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/** Configuration for {@link retry}. */\nexport interface RetryOptions {\n /** Maximum number of retry attempts after the initial try. Default `3`. */\n readonly retries?: number;\n /** Base delay in milliseconds between attempts. Default `200`. */\n readonly delay?: number;\n /**\n * Backoff strategy. `exponential` doubles the delay each attempt (with full\n * jitter), `linear` multiplies by attempt index, `fixed` keeps `delay`\n * constant. Default `exponential`.\n */\n readonly backoff?: 'fixed' | 'linear' | 'exponential';\n /** Upper bound applied to any computed delay, in milliseconds. */\n readonly maxDelay?: number;\n /** Predicate deciding whether a given error is retryable. Default: always. */\n readonly shouldRetry?: (error: unknown, attempt: number) => boolean;\n /** Invoked before each backoff wait, for logging/telemetry. */\n readonly onRetry?: (error: unknown, attempt: number, waitMs: number) => void;\n /** Abort all pending retries. */\n readonly signal?: AbortSignal;\n}\n\n/**\n * Invoke `fn`, retrying on rejection according to {@link RetryOptions}.\n *\n * The function receives the 1-based attempt number. The final error is rethrown\n * once all retries are exhausted or `shouldRetry` returns `false`.\n */\nexport async function retry<T>(fn: (attempt: number) => Promise<T> | T, options: RetryOptions = {}): Promise<T> {\n const {\n retries = 3,\n delay = 200,\n backoff = 'exponential',\n maxDelay = 30_000,\n shouldRetry = () => true,\n onRetry,\n signal,\n } = options;\n\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= retries + 1; attempt += 1) {\n if (signal?.aborted) throw toAbortError(signal);\n try {\n return await fn(attempt);\n } catch (error) {\n lastError = error;\n const isLastAttempt = attempt > retries;\n if (isLastAttempt || !shouldRetry(error, attempt)) {\n throw error;\n }\n const waitMs = Math.min(maxDelay, computeBackoff(backoff, delay, attempt));\n onRetry?.(error, attempt, waitMs);\n await sleep(waitMs, signal ? { signal } : {});\n }\n }\n\n // Unreachable in practice; satisfies the type checker.\n throw lastError;\n}\n\nfunction computeBackoff(strategy: NonNullable<RetryOptions['backoff']>, base: number, attempt: number): number {\n switch (strategy) {\n case 'fixed':\n return base;\n case 'linear':\n return base * attempt;\n case 'exponential': {\n const ceiling = base * 2 ** (attempt - 1);\n // Full jitter to avoid thundering-herd retries.\n return Math.random() * ceiling;\n }\n default:\n return base;\n }\n}\n\n/** Options for {@link withTimeout}. */\nexport interface TimeoutOptions {\n /** Error thrown when the timeout elapses. Defaults to a generic timeout error. */\n readonly error?: Error;\n /** Propagate cancellation to the wrapped operation if it observes the signal. */\n readonly signal?: AbortSignal;\n}\n\n/** Error thrown by {@link withTimeout} when the deadline is exceeded. */\nexport class TimeoutError extends Error {\n constructor(message = 'Operation timed out') {\n super(message);\n this.name = 'TimeoutError';\n }\n}\n\n/**\n * Race a promise against a timeout.\n *\n * Accepts either a promise or a factory that receives an `AbortSignal` so the\n * underlying work can be cancelled when the deadline fires.\n */\nexport function withTimeout<T>(\n input: Promise<T> | ((signal: AbortSignal) => Promise<T>),\n ms: number,\n options: TimeoutOptions = {},\n): Promise<T> {\n const controller = new AbortController();\n if (options.signal) {\n if (options.signal.aborted) controller.abort(options.signal.reason);\n else options.signal.addEventListener('abort', () => controller.abort(options.signal?.reason), { once: true });\n }\n\n const work = typeof input === 'function' ? input(controller.signal) : input;\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n controller.abort();\n reject(options.error ?? new TimeoutError(`Operation timed out after ${ms}ms`));\n }, ms);\n\n work.then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (error: unknown) => {\n clearTimeout(timer);\n reject(error instanceof Error ? error : new Error(String(error)));\n },\n );\n });\n}\n\n/** Options for {@link pMap}. */\nexport interface PMapOptions {\n /** Maximum number of concurrently running mappers. Default `Infinity`. */\n readonly concurrency?: number;\n /**\n * When `false`, collect all settled outcomes and reject with an\n * `AggregateError` only after every item completes. Default `true`.\n */\n readonly stopOnError?: boolean;\n /** Abort remaining work. In-flight mappers should observe the signal. */\n readonly signal?: AbortSignal;\n}\n\n/**\n * Map over an iterable with bounded concurrency, preserving input order in the\n * output array. The mapper receives the element and its index.\n */\nexport async function pMap<T, R>(\n items: Iterable<T>,\n mapper: (item: T, index: number) => Promise<R> | R,\n options: PMapOptions = {},\n): Promise<R[]> {\n const { concurrency = Number.POSITIVE_INFINITY, stopOnError = true, signal } = options;\n if (concurrency < 1) throw new TypeError('pMap: concurrency must be at least 1');\n\n const entries = Array.from(items);\n const results: R[] = new Array<R>(entries.length);\n const errors: unknown[] = [];\n let cursor = 0;\n\n const limit = Math.min(concurrency, entries.length) || 0;\n\n const worker = async (): Promise<void> => {\n while (cursor < entries.length) {\n if (signal?.aborted) throw toAbortError(signal);\n const index = cursor;\n cursor += 1;\n try {\n results[index] = await mapper(entries[index] as T, index);\n } catch (error) {\n if (stopOnError) throw error;\n errors.push(error);\n }\n }\n };\n\n const workers = Array.from({ length: limit }, () => worker());\n await Promise.all(workers);\n\n if (errors.length > 0) {\n throw new AggregateError(errors, `pMap: ${errors.length} of ${entries.length} items failed`);\n }\n\n return results;\n}\n\nfunction toAbortError(signal?: AbortSignal): Error {\n const reason = signal?.reason;\n if (reason instanceof Error) return reason;\n return new AbortError(typeof reason === 'string' ? reason : undefined);\n}\n", "import { AppError, TimeoutError, withTimeout } from '@fim/utils';\n\nimport type { ProviderOptions } from '../provider.js';\nimport type { AiProviderName } from '../types.js';\n\n/**\n * Error thrown when an upstream AI provider returns a non-2xx response. Carries\n * the HTTP status and the (best-effort) parsed provider error payload so call\n * sites can branch on rate limits, auth failures, etc.\n */\nexport class AiProviderError extends AppError {\n readonly provider: AiProviderName;\n readonly status: number;\n readonly providerCode: string | undefined;\n\n constructor(args: {\n provider: AiProviderName;\n status: number;\n message: string;\n providerCode?: string;\n cause?: unknown;\n }) {\n super(args.message, {\n code: 'AI_PROVIDER_ERROR',\n statusCode: normalizeStatus(args.status),\n cause: args.cause,\n });\n this.name = 'AiProviderError';\n this.provider = args.provider;\n this.status = args.status;\n this.providerCode = args.providerCode;\n }\n\n /** Provider errors that are safe to retry (rate limit / transient server). */\n get retryable(): boolean {\n return this.status === 408 || this.status === 429 || this.status >= 500;\n }\n}\n\nfunction normalizeStatus(status: number): number {\n return status >= 400 && status <= 599 ? status : 502;\n}\n\nexport interface PostJsonArgs {\n readonly provider: AiProviderName;\n readonly url: string;\n readonly headers: Record<string, string>;\n readonly body: unknown;\n readonly timeoutMs: number;\n readonly fetchImpl: typeof fetch;\n readonly signal?: AbortSignal;\n}\n\n/**\n * POST a JSON body and return the raw `Response`. Applies a hard timeout and\n * converts non-2xx responses into a typed {@link AiProviderError}.\n *\n * The body is left unread so callers can either `.json()` it or consume the\n * SSE stream from `response.body`.\n */\nexport async function postJson(args: PostJsonArgs): Promise<Response> {\n const { provider, url, headers, body, timeoutMs, fetchImpl, signal } = args;\n\n // Pass a factory so `withTimeout` can abort the in-flight fetch on deadline.\n // The caller `signal` is merged into the timeout controller via options.\n const response = await withTimeout(\n (timeoutSignal) =>\n fetchImpl(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...headers },\n body: JSON.stringify(body),\n signal: timeoutSignal,\n }),\n timeoutMs,\n {\n ...(signal ? { signal } : {}),\n error: new TimeoutError(\n `${provider} request timed out after ${timeoutMs}ms`,\n ),\n },\n );\n\n if (!response.ok) {\n throw await toProviderError(provider, response);\n }\n\n return response;\n}\n\n/** Build an {@link AiProviderError} from a failed `Response`. */\nasync function toProviderError(\n provider: AiProviderName,\n response: Response,\n): Promise<AiProviderError> {\n let message = `${provider} request failed with status ${response.status}`;\n let providerCode: string | undefined;\n\n try {\n const text = await response.text();\n if (text) {\n const parsed = JSON.parse(text) as {\n error?: { message?: string; type?: string; code?: string };\n message?: string;\n };\n const detail =\n parsed.error?.message ?? parsed.message ?? text.slice(0, 500);\n message = `${provider} request failed (${response.status}): ${detail}`;\n providerCode = parsed.error?.code ?? parsed.error?.type;\n }\n } catch {\n // Non-JSON or empty body \u2014 keep the generic message.\n }\n\n return new AiProviderError({\n provider,\n status: response.status,\n message,\n providerCode,\n });\n}\n\n/** Read and JSON-parse a successful response body with a typed cast. */\nexport async function readJson<T>(response: Response): Promise<T> {\n return (await response.json()) as T;\n}\n\n/**\n * Resolve the effective timeout for a provider, preferring the explicit option\n * and falling back to a sane default.\n */\nexport function resolveTimeout(options: ProviderOptions | undefined): number {\n return options?.timeoutMs && options.timeoutMs > 0\n ? options.timeoutMs\n : 60_000;\n}\n\n/** Resolve the fetch implementation, preferring an injected one for testing. */\nexport function resolveFetch(options: ProviderOptions | undefined): typeof fetch {\n const impl = options?.fetch ?? globalThis.fetch;\n if (typeof impl !== 'function') {\n throw new AppError('No fetch implementation available in this runtime', {\n code: 'AI_NO_FETCH',\n statusCode: 500,\n });\n }\n return impl;\n}\n", "/**\n * Minimal, dependency-free Server-Sent Events (SSE) parsing utilities used by\n * the streaming providers. Works against a WHATWG `ReadableStream<Uint8Array>`\n * (the body returned by `fetch`).\n */\n\nexport interface SseEvent {\n /** The `event:` field, if present. */\n readonly event?: string;\n /** The concatenated `data:` payload for this event. */\n readonly data: string;\n}\n\n/**\n * Decode a byte stream into discrete SSE events.\n *\n * Handles multi-line `data:` fields, CRLF/LF newlines, and partial chunks that\n * split an event across read boundaries. Comment lines (`:`-prefixed) and the\n * `id:`/`retry:` fields are ignored, which is sufficient for the chat APIs.\n */\nexport async function* parseSseStream(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<SseEvent, void, unknown> {\n const reader = body.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Emit every complete event currently buffered (LF or CRLF framed).\n let separatorIndex = indexOfEventSeparator(buffer);\n while (separatorIndex !== -1) {\n const rawEvent = buffer.slice(0, separatorIndex.index);\n buffer = buffer.slice(separatorIndex.index + separatorIndex.length);\n\n const parsed = parseEventBlock(rawEvent);\n if (parsed) yield parsed;\n\n separatorIndex = indexOfEventSeparator(buffer);\n }\n }\n\n // Flush any trailing event that wasn't terminated by a blank line.\n buffer += decoder.decode();\n const trailing = parseEventBlock(buffer);\n if (trailing) yield trailing;\n } finally {\n reader.releaseLock();\n }\n}\n\ninterface SeparatorMatch {\n readonly index: number;\n readonly length: number;\n}\n\n/** Find the next blank-line separator (`\\n\\n` or `\\r\\n\\r\\n`). */\nfunction indexOfEventSeparator(buffer: string): SeparatorMatch | -1 {\n const lf = buffer.indexOf('\\n\\n');\n const crlf = buffer.indexOf('\\r\\n\\r\\n');\n\n if (lf === -1 && crlf === -1) return -1;\n if (crlf === -1) return { index: lf, length: 2 };\n if (lf === -1) return { index: crlf, length: 4 };\n\n return lf < crlf ? { index: lf, length: 2 } : { index: crlf, length: 4 };\n}\n\n/** Parse a single raw event block into an {@link SseEvent}, or `null` if empty. */\nfunction parseEventBlock(rawEvent: string): SseEvent | null {\n const lines = rawEvent.split(/\\r?\\n/);\n const dataParts: string[] = [];\n let eventName: string | undefined;\n\n for (const line of lines) {\n if (line === '' || line.startsWith(':')) continue;\n\n const colon = line.indexOf(':');\n const field = colon === -1 ? line : line.slice(0, colon);\n // Per the SSE spec a single leading space after the colon is stripped.\n let value = colon === -1 ? '' : line.slice(colon + 1);\n if (value.startsWith(' ')) value = value.slice(1);\n\n if (field === 'data') {\n dataParts.push(value);\n } else if (field === 'event') {\n eventName = value;\n }\n // `id` and `retry` are intentionally ignored.\n }\n\n if (dataParts.length === 0 && eventName === undefined) return null;\n\n return { event: eventName, data: dataParts.join('\\n') };\n}\n", "import { env } from '@fim/config';\nimport { AppError } from '@fim/utils';\n\nimport {\n AiProviderError,\n postJson,\n readJson,\n resolveFetch,\n resolveTimeout,\n} from '../internal/http.js';\nimport { parseSseStream } from '../internal/sse.js';\nimport type { AiProvider, ProviderOptions } from '../provider.js';\nimport type {\n AiFinishReason,\n AiModel,\n ChatChunk,\n ChatRequest,\n ChatResult,\n EmbedRequest,\n EmbedResponse,\n} from '../types.js';\n\nconst ANTHROPIC_VERSION = '2023-06-01';\nconst DEFAULT_BASE_URL = 'https://api.anthropic.com';\nexport const ANTHROPIC_DEFAULT_MODEL = 'claude-opus-4-8';\nconst DEFAULT_MAX_TOKENS = 4096;\n\nconst ANTHROPIC_MODELS: readonly AiModel[] = [\n {\n id: 'claude-opus-4-8',\n provider: 'anthropic',\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsStreaming: true,\n supportsEmbeddings: false,\n },\n {\n id: 'claude-sonnet-4-6',\n provider: 'anthropic',\n contextWindow: 1_000_000,\n maxOutputTokens: 64_000,\n supportsStreaming: true,\n supportsEmbeddings: false,\n },\n {\n id: 'claude-haiku-4-5',\n provider: 'anthropic',\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n supportsStreaming: true,\n supportsEmbeddings: false,\n },\n];\n\n/* -------------------------------------------------------------------------- */\n/* Wire shapes */\n/* -------------------------------------------------------------------------- */\n\ninterface AnthropicMessage {\n readonly role: 'user' | 'assistant';\n readonly content: string;\n}\n\ninterface AnthropicRequestBody {\n model: string;\n max_tokens: number;\n messages: AnthropicMessage[];\n system?: string;\n temperature?: number;\n stream?: boolean;\n metadata?: { user_id?: string } & Record<string, string>;\n}\n\ninterface AnthropicContentBlock {\n readonly type: string;\n readonly text?: string;\n}\n\ninterface AnthropicUsage {\n readonly input_tokens: number;\n readonly output_tokens: number;\n}\n\ninterface AnthropicMessageResponse {\n readonly model: string;\n readonly stop_reason: string | null;\n readonly content: readonly AnthropicContentBlock[];\n readonly usage?: AnthropicUsage;\n}\n\n/** SSE event payloads emitted by the Anthropic Messages streaming API. */\ntype AnthropicStreamEvent =\n | { type: 'message_start'; message: { model: string; usage?: AnthropicUsage } }\n | { type: 'content_block_start'; index: number; content_block: { type: string } }\n | {\n type: 'content_block_delta';\n index: number;\n delta: { type: string; text?: string };\n }\n | { type: 'content_block_stop'; index: number }\n | {\n type: 'message_delta';\n delta: { stop_reason?: string | null };\n usage?: AnthropicUsage;\n }\n | { type: 'message_stop' }\n | { type: 'ping' }\n | { type: 'error'; error: { type: string; message: string } };\n\n/**\n * Anthropic Messages API provider. Implements {@link AiProvider} via raw\n * `fetch` against `/v1/messages`, with real SSE parsing for {@link stream}.\n */\nclass AnthropicProvider implements AiProvider {\n readonly name = 'anthropic' as const;\n readonly defaultModel: string;\n readonly models = ANTHROPIC_MODELS;\n\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n private readonly extraHeaders: Record<string, string>;\n\n constructor(options: ProviderOptions = {}) {\n const apiKey = options.apiKey ?? env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n throw new AppError('ANTHROPIC_API_KEY is not configured', {\n code: 'AI_MISSING_API_KEY',\n statusCode: 500,\n });\n }\n this.apiKey = apiKey;\n this.baseUrl = stripTrailingSlash(options.baseUrl ?? DEFAULT_BASE_URL);\n this.defaultModel =\n options.defaultModel ?? env.ANTHROPIC_MODEL ?? ANTHROPIC_DEFAULT_MODEL;\n this.timeoutMs = resolveTimeout(options);\n this.fetchImpl = resolveFetch(options);\n this.extraHeaders = { ...options.headers };\n }\n\n async chat(request: ChatRequest): Promise<string> {\n return (await this.chatVerbose(request)).content;\n }\n\n async chatVerbose(request: ChatRequest): Promise<ChatResult> {\n const response = await postJson({\n provider: this.name,\n url: `${this.baseUrl}/v1/messages`,\n headers: this.headers(),\n body: this.buildBody(request, false),\n timeoutMs: this.timeoutMs,\n fetchImpl: this.fetchImpl,\n signal: request.signal,\n });\n\n const data = await readJson<AnthropicMessageResponse>(response);\n const content = data.content\n .filter((block) => block.type === 'text' && typeof block.text === 'string')\n .map((block) => block.text ?? '')\n .join('');\n\n return {\n content,\n model: data.model,\n finishReason: mapStopReason(data.stop_reason),\n usage: data.usage\n ? {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.input_tokens + data.usage.output_tokens,\n }\n : undefined,\n };\n }\n\n async *stream(request: ChatRequest): AsyncIterable<ChatChunk> {\n const response = await postJson({\n provider: this.name,\n url: `${this.baseUrl}/v1/messages`,\n headers: this.headers(),\n body: this.buildBody(request, true),\n timeoutMs: this.timeoutMs,\n fetchImpl: this.fetchImpl,\n signal: request.signal,\n });\n\n if (!response.body) {\n throw new AiProviderError({\n provider: this.name,\n status: response.status,\n message: 'Anthropic stream response had no body',\n });\n }\n\n let inputTokens = 0;\n let outputTokens = 0;\n let finishReason: AiFinishReason = 'unknown';\n\n for await (const sse of parseSseStream(response.body)) {\n if (!sse.data || sse.data === '[DONE]') continue;\n\n const event = safeParse<AnthropicStreamEvent>(sse.data);\n if (!event) continue;\n\n switch (event.type) {\n case 'message_start': {\n if (event.message.usage) inputTokens = event.message.usage.input_tokens;\n break;\n }\n case 'content_block_delta': {\n if (event.delta.type === 'text_delta' && event.delta.text) {\n yield { delta: event.delta.text, done: false };\n }\n break;\n }\n case 'message_delta': {\n if (event.delta.stop_reason) {\n finishReason = mapStopReason(event.delta.stop_reason);\n }\n if (event.usage) outputTokens = event.usage.output_tokens;\n break;\n }\n case 'error': {\n throw new AiProviderError({\n provider: this.name,\n status: 502,\n message: `Anthropic stream error: ${event.error.message}`,\n providerCode: event.error.type,\n });\n }\n case 'message_stop': {\n yield this.terminalChunk(finishReason, inputTokens, outputTokens);\n return;\n }\n default:\n break;\n }\n }\n\n // Stream ended without an explicit `message_stop` \u2014 still emit a terminal.\n yield this.terminalChunk(finishReason, inputTokens, outputTokens);\n }\n\n embed(_request: EmbedRequest): Promise<EmbedResponse> {\n throw new AppError(\n 'Anthropic does not expose a native embeddings endpoint; configure AI_PROVIDER=openai for embeddings',\n { code: 'AI_EMBEDDINGS_UNSUPPORTED', statusCode: 400 },\n );\n }\n\n private terminalChunk(\n finishReason: AiFinishReason,\n inputTokens: number,\n outputTokens: number,\n ): ChatChunk {\n return {\n delta: '',\n done: true,\n finishReason,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n };\n }\n\n private headers(): Record<string, string> {\n return {\n 'x-api-key': this.apiKey,\n 'anthropic-version': ANTHROPIC_VERSION,\n ...this.extraHeaders,\n };\n }\n\n private buildBody(request: ChatRequest, stream: boolean): AnthropicRequestBody {\n const { system, messages } = splitSystem(request);\n\n const body: AnthropicRequestBody = {\n model: request.model ?? this.defaultModel,\n max_tokens: request.maxTokens ?? DEFAULT_MAX_TOKENS,\n messages,\n stream,\n };\n\n if (system) body.system = system;\n if (typeof request.temperature === 'number') {\n body.temperature = request.temperature;\n }\n if (request.metadata && Object.keys(request.metadata).length > 0) {\n body.metadata = { ...request.metadata };\n }\n\n return body;\n }\n}\n\n/**\n * Factory for the Anthropic provider. Reads `ANTHROPIC_API_KEY` from\n * `@fim/config` unless overridden via {@link ProviderOptions}.\n */\nexport const anthropicProvider = (options?: ProviderOptions): AiProvider =>\n new AnthropicProvider(options);\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Anthropic carries the system prompt as a top-level field rather than a\n * `system`-role message. Hoist any system content and coalesce consecutive\n * same-role turns (the API combines them, but normalising keeps things clean).\n */\nfunction splitSystem(request: ChatRequest): {\n system: string | undefined;\n messages: AnthropicMessage[];\n} {\n const systemParts: string[] = [];\n if (request.system) systemParts.push(request.system);\n\n const messages: AnthropicMessage[] = [];\n for (const message of request.messages) {\n if (message.role === 'system') {\n systemParts.push(message.content);\n continue;\n }\n // Tool messages flow only to tool-capable providers (DeepSeek); skip to stay well-typed.\n if (message.role === 'tool') continue;\n messages.push({ role: message.role, content: message.content });\n }\n\n return {\n system: systemParts.length > 0 ? systemParts.join('\\n\\n') : undefined,\n messages: ensureLeadingUser(messages),\n };\n}\n\n/** Anthropic requires the first message to be a `user` turn. */\nfunction ensureLeadingUser(messages: AnthropicMessage[]): AnthropicMessage[] {\n if (messages.length === 0) {\n return [{ role: 'user', content: '' }];\n }\n if (messages[0]!.role !== 'user') {\n return [{ role: 'user', content: '' }, ...messages];\n }\n return messages;\n}\n\nfunction mapStopReason(reason: string | null): AiFinishReason {\n switch (reason) {\n case 'end_turn':\n case 'stop_sequence':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'tool_use':\n return 'tool_use';\n case 'refusal':\n return 'content_filter';\n case null:\n case undefined:\n return 'unknown';\n default:\n return 'unknown';\n }\n}\n\nfunction safeParse<T>(raw: string): T | null {\n try {\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n\nfunction stripTrailingSlash(url: string): string {\n return url.endsWith('/') ? url.slice(0, -1) : url;\n}\n", "import { env } from '@fim/config';\nimport { AppError } from '@fim/utils';\n\nimport {\n AiProviderError,\n postJson,\n readJson,\n resolveFetch,\n resolveTimeout,\n} from '../internal/http.js';\nimport { parseSseStream } from '../internal/sse.js';\nimport type { AiProvider, ProviderOptions } from '../provider.js';\nimport type {\n AiFinishReason,\n AiModel,\n ChatChunk,\n ChatRequest,\n ChatResult,\n EmbedRequest,\n EmbedResponse,\n ReasoningEffort,\n ToolCall,\n} from '../types.js';\n\n/**\n * DeepSeek's HTTP API is OpenAI Chat-Completions compatible, so this provider\n * mirrors {@link ./openai.ts} closely. The two meaningful differences are:\n *\n * 1. **Thinking mode.** The v4 models ship an extended-reasoning (\"thinking\")\n * mode toggled per request via a `thinking` object. It is *on by default*,\n * so to get fast coding answers callers must explicitly disable it.\n * 2. **`reasoning_content`.** When thinking is on, the chain-of-thought is\n * returned in a `reasoning_content` field alongside `content` (in both the\n * non-streaming message and the streaming delta). We surface it through the\n * canonical `ChatResult.reasoning` / `ChatChunk.reasoningDelta` fields.\n *\n * DeepSeek does not expose an embeddings endpoint; {@link embed} therefore\n * throws, matching the Anthropic provider.\n */\nconst DEFAULT_BASE_URL = 'https://api.deepseek.com';\nexport const DEEPSEEK_DEFAULT_MODEL = 'deepseek-v4-flash';\n/** Higher-capability sibling for hard reasoning / large refactors. */\nexport const DEEPSEEK_PRO_MODEL = 'deepseek-v4-pro';\nconst DEFAULT_MAX_TOKENS = 8192;\n\nconst DEEPSEEK_MODELS: readonly AiModel[] = [\n {\n id: 'deepseek-v4-flash',\n provider: 'deepseek',\n contextWindow: 1_000_000,\n maxOutputTokens: 384_000,\n supportsStreaming: true,\n supportsEmbeddings: false,\n },\n {\n id: 'deepseek-v4-pro',\n provider: 'deepseek',\n contextWindow: 1_000_000,\n maxOutputTokens: 384_000,\n supportsStreaming: true,\n supportsEmbeddings: false,\n },\n];\n\n/**\n * Legacy DeepSeek aliases, deprecated by DeepSeek and retired 2026-07-24 15:59\n * UTC. They are no longer part of {@link DEEPSEEK_MODELS}; if one still reaches\n * the provider (a stale config or a caller-supplied string) it is repinned to the\n * v4 model that preserves the alias's INTENT, with a one-time deprecation warning:\n *\n * - `deepseek-chat` \u2014 the non-thinking chat model \u2192 {@link DEEPSEEK_DEFAULT_MODEL}\n * - `deepseek-reasoner` \u2014 the reasoning model \u2192 {@link DEEPSEEK_PRO_MODEL}\n *\n * (Server-side `deepseek-reasoner` currently routes to Flash, which silently\n * degrades heavy reasoning \u2014 repinning to Pro restores the original intent.)\n */\nexport const LEGACY_DEEPSEEK_ALIASES: Readonly<Record<string, string>> = {\n 'deepseek-chat': DEEPSEEK_DEFAULT_MODEL,\n 'deepseek-reasoner': DEEPSEEK_PRO_MODEL,\n};\n\n/** True when `model` is a retired legacy DeepSeek alias. */\nexport function isLegacyDeepSeekModel(model: string): boolean {\n return Object.prototype.hasOwnProperty.call(LEGACY_DEEPSEEK_ALIASES, model);\n}\n\nconst warnedLegacyDeepSeekModels = new Set<string>();\n\n/**\n * Map a legacy alias to its canonical v4 model, emitting a one-time Node\n * deprecation warning per distinct alias. Non-legacy ids pass through unchanged.\n */\nexport function repinLegacyDeepSeekModel(model: string): string {\n const canonical = LEGACY_DEEPSEEK_ALIASES[model];\n if (!canonical) return model;\n if (!warnedLegacyDeepSeekModels.has(model)) {\n warnedLegacyDeepSeekModels.add(model);\n process.emitWarning(\n `DeepSeek model '${model}' is a deprecated legacy alias (retired 2026-07-24); repinned to '${canonical}'. Update your configuration to use '${canonical}'.`,\n { type: 'DeprecationWarning', code: 'FIM_DEEPSEEK_LEGACY_MODEL' },\n );\n }\n return canonical;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Wire shapes */\n/* -------------------------------------------------------------------------- */\n\ninterface DeepSeekToolCall {\n readonly id: string;\n readonly type?: 'function';\n readonly function: { readonly name: string; readonly arguments: string };\n}\n\ninterface DeepSeekChatMessage {\n readonly role: 'system' | 'user' | 'assistant' | 'tool';\n readonly content: string | null;\n readonly tool_call_id?: string;\n readonly tool_calls?: DeepSeekToolCall[];\n}\n\ninterface DeepSeekToolDef {\n readonly type: 'function';\n readonly function: {\n readonly name: string;\n readonly description?: string;\n readonly parameters: Record<string, unknown>;\n };\n}\n\ninterface DeepSeekThinkingConfig {\n type: 'enabled' | 'disabled';\n reasoning_effort?: ReasoningEffort;\n}\n\ninterface DeepSeekChatRequestBody {\n model: string;\n messages: DeepSeekChatMessage[];\n tools?: DeepSeekToolDef[];\n tool_choice?: 'auto' | 'none' | 'required';\n max_tokens?: number;\n temperature?: number;\n stream?: boolean;\n stream_options?: { include_usage: boolean };\n /**\n * DeepSeek structured output: `{type:'json_object'}` forces valid JSON (the\n * prompt must contain the word \"json\"). No json_schema/strict mode exists \u2014\n * shape validation is the caller's job (review.md).\n */\n response_format?: { type: 'json_object' };\n thinking?: DeepSeekThinkingConfig;\n /**\n * Top-level effort, mirroring `thinking.reasoning_effort`. DeepSeek documents\n * the effort under `thinking` but its OpenAI-compatible surface also reads the\n * standard top-level `reasoning_effort`; sending both maximises the chance the\n * level is honoured regardless of which form the gateway expects.\n */\n reasoning_effort?: ReasoningEffort;\n user?: string;\n}\n\ninterface DeepSeekUsage {\n readonly prompt_tokens: number;\n readonly completion_tokens: number;\n readonly total_tokens: number;\n // DeepSeek prefix-cache split (present when caching is active).\n readonly prompt_cache_hit_tokens?: number;\n readonly prompt_cache_miss_tokens?: number;\n // OpenAI-compatible breakdown; carries the chain-of-thought token count when\n // thinking is on. Present only when DeepSeek reports it.\n readonly completion_tokens_details?: { readonly reasoning_tokens?: number };\n}\n\n/** Map DeepSeek wire usage onto the SDK's AiUsage, preserving the cache split. */\nfunction toAiUsage(u: DeepSeekUsage): {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n cacheHitTokens?: number;\n cacheMissTokens?: number;\n reasoningTokens?: number;\n} {\n // hit + miss partition prompt_tokens; if the wire sends only one, derive the\n // other so the ledger + cache-ratio are robust to partial payloads.\n const hit = u.prompt_cache_hit_tokens;\n const miss = u.prompt_cache_miss_tokens;\n return {\n inputTokens: u.prompt_tokens,\n outputTokens: u.completion_tokens,\n totalTokens: u.total_tokens,\n cacheHitTokens: hit ?? (miss !== undefined ? Math.max(0, u.prompt_tokens - miss) : undefined),\n cacheMissTokens: miss ?? (hit !== undefined ? Math.max(0, u.prompt_tokens - hit) : undefined),\n // Thinking-token count, when DeepSeek meters it (a subset of completion).\n reasoningTokens: u.completion_tokens_details?.reasoning_tokens,\n };\n}\n\ninterface DeepSeekChatResponse {\n readonly model: string;\n readonly choices: ReadonlyArray<{\n readonly message: {\n readonly content: string | null;\n readonly reasoning_content?: string | null;\n readonly tool_calls?: DeepSeekToolCall[];\n };\n readonly finish_reason: string | null;\n }>;\n readonly usage?: DeepSeekUsage;\n}\n\ninterface DeepSeekStreamToolCall {\n readonly index: number;\n readonly id?: string;\n readonly type?: string;\n readonly function?: { readonly name?: string; readonly arguments?: string };\n}\n\ninterface DeepSeekChatStreamChunk {\n readonly model: string;\n readonly choices: ReadonlyArray<{\n readonly delta: {\n readonly content?: string | null;\n readonly reasoning_content?: string | null;\n readonly tool_calls?: DeepSeekStreamToolCall[];\n };\n readonly finish_reason: string | null;\n }>;\n readonly usage?: DeepSeekUsage | null;\n}\n\n/**\n * DeepSeek chat provider. Implements {@link AiProvider} via raw `fetch` against\n * `/chat/completions`, with SSE parsing for {@link stream}.\n */\nclass DeepSeekProvider implements AiProvider {\n readonly name = 'deepseek' as const;\n readonly defaultModel: string;\n readonly models = DEEPSEEK_MODELS;\n\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n private readonly extraHeaders: Record<string, string>;\n\n constructor(options: ProviderOptions = {}) {\n const apiKey = options.apiKey ?? env.DEEPSEEK_API_KEY;\n if (!apiKey) {\n throw new AppError('DEEPSEEK_API_KEY is not configured', {\n code: 'AI_MISSING_API_KEY',\n statusCode: 500,\n });\n }\n this.apiKey = apiKey;\n this.baseUrl = stripTrailingSlash(\n options.baseUrl ?? env.DEEPSEEK_BASE_URL ?? DEFAULT_BASE_URL,\n );\n this.defaultModel =\n options.defaultModel ?? env.DEEPSEEK_MODEL ?? DEEPSEEK_DEFAULT_MODEL;\n this.timeoutMs = resolveTimeout(options);\n this.fetchImpl = resolveFetch(options);\n this.extraHeaders = { ...options.headers };\n }\n\n async chat(request: ChatRequest): Promise<string> {\n return (await this.chatVerbose(request)).content;\n }\n\n async chatVerbose(request: ChatRequest): Promise<ChatResult> {\n const response = await postJson({\n provider: this.name,\n url: `${this.baseUrl}/chat/completions`,\n headers: this.headers(),\n body: this.buildChatBody(request, false),\n timeoutMs: this.timeoutMs,\n fetchImpl: this.fetchImpl,\n signal: request.signal,\n });\n\n const data = await readJson<DeepSeekChatResponse>(response);\n const choice = data.choices[0];\n const reasoning = choice?.message.reasoning_content;\n const toolCalls = mapToolCalls(choice?.message.tool_calls);\n\n return {\n content: choice?.message.content ?? '',\n model: data.model,\n finishReason: mapFinishReason(choice?.finish_reason ?? null),\n ...(reasoning ? { reasoning } : {}),\n ...(toolCalls.length > 0 ? { toolCalls } : {}),\n usage: data.usage ? toAiUsage(data.usage) : undefined,\n };\n }\n\n async *stream(request: ChatRequest): AsyncIterable<ChatChunk> {\n const response = await postJson({\n provider: this.name,\n url: `${this.baseUrl}/chat/completions`,\n headers: this.headers(),\n body: this.buildChatBody(request, true),\n timeoutMs: this.timeoutMs,\n fetchImpl: this.fetchImpl,\n signal: request.signal,\n });\n\n if (!response.body) {\n throw new AiProviderError({\n provider: this.name,\n status: response.status,\n message: 'DeepSeek stream response had no body',\n });\n }\n\n let finishReason: AiFinishReason = 'unknown';\n let usage: DeepSeekUsage | undefined;\n // Accumulate streamed tool-call fragments by index (id/name arrive once,\n // arguments stream as JSON fragments to be concatenated).\n const toolAcc = new Map<number, { id?: string; name?: string; args: string }>();\n\n for await (const sse of parseSseStream(response.body)) {\n const payload = sse.data.trim();\n if (!payload) continue;\n if (payload === '[DONE]') break;\n\n const chunk = safeParse<DeepSeekChatStreamChunk>(payload);\n if (!chunk) continue;\n\n if (chunk.usage) usage = chunk.usage;\n\n const choice = chunk.choices[0];\n if (!choice) continue;\n\n // Chain-of-thought arrives before the visible answer; emit it on its own\n // channel so callers can render or ignore it independently.\n if (choice.delta.reasoning_content) {\n yield { delta: '', done: false, reasoningDelta: choice.delta.reasoning_content };\n }\n if (choice.delta.content) {\n yield { delta: choice.delta.content, done: false };\n }\n for (const tc of choice.delta.tool_calls ?? []) {\n const entry = toolAcc.get(tc.index) ?? { args: '' };\n if (tc.id) entry.id = tc.id;\n if (tc.function?.name) entry.name = tc.function.name;\n if (tc.function?.arguments) entry.args += tc.function.arguments;\n toolAcc.set(tc.index, entry);\n yield {\n delta: '',\n done: false,\n toolCallDelta: {\n index: tc.index,\n ...(tc.id ? { id: tc.id } : {}),\n ...(tc.function?.name ? { name: tc.function.name } : {}),\n ...(tc.function?.arguments ? { argumentsDelta: tc.function.arguments } : {}),\n },\n };\n }\n if (choice.finish_reason) {\n finishReason = mapFinishReason(choice.finish_reason);\n }\n }\n\n const toolCalls: ToolCall[] = [...toolAcc.entries()]\n .sort((a, b) => a[0] - b[0])\n // Synthesize a stable id if the stream never sent one (empty id would drop\n // tool_call_id on the wire and 400 DeepSeek); drop a fragment group that\n // never received a name (unusable).\n .map(([index, e]) => ({ id: e.id || `call_${index}`, name: e.name ?? '', arguments: e.args }))\n .filter((tc) => tc.name.length > 0);\n\n yield {\n delta: '',\n done: true,\n finishReason,\n ...(toolCalls.length > 0 ? { toolCalls } : {}),\n usage: usage ? toAiUsage(usage) : undefined,\n };\n }\n\n embed(_request: EmbedRequest): Promise<EmbedResponse> {\n throw new AppError(\n 'DeepSeek does not expose an embeddings endpoint',\n { code: 'AI_EMBEDDINGS_UNSUPPORTED', statusCode: 400 },\n );\n }\n\n private headers(): Record<string, string> {\n return {\n authorization: `Bearer ${this.apiKey}`,\n ...this.extraHeaders,\n };\n }\n\n private buildChatBody(\n request: ChatRequest,\n stream: boolean,\n ): DeepSeekChatRequestBody {\n const messages: DeepSeekChatMessage[] = [];\n if (request.system) {\n messages.push({ role: 'system', content: request.system });\n }\n for (const message of request.messages) {\n const toolCalls = message.toolCalls ?? [];\n const hasToolCalls = toolCalls.length > 0;\n messages.push({\n // Canonical form for an assistant tool-call turn is content: null, which\n // stricter OpenAI-compatible surfaces require.\n content: hasToolCalls && message.content === '' ? null : message.content,\n role: message.role,\n ...(message.toolCallId ? { tool_call_id: message.toolCallId } : {}),\n ...(hasToolCalls\n ? {\n tool_calls: toolCalls.map((tc) => ({\n id: tc.id,\n type: 'function' as const,\n function: { name: tc.name, arguments: tc.arguments },\n })),\n }\n : {}),\n });\n }\n\n const body: DeepSeekChatRequestBody = {\n model: repinLegacyDeepSeekModel(request.model ?? this.defaultModel),\n messages,\n max_tokens: request.maxTokens ?? DEFAULT_MAX_TOKENS,\n };\n\n if (request.tools && request.tools.length > 0) {\n body.tools = request.tools.map((t) => ({\n type: 'function',\n function: {\n name: t.name,\n ...(t.description ? { description: t.description } : {}),\n parameters: t.parameters,\n },\n }));\n if (request.toolChoice) body.tool_choice = request.toolChoice;\n }\n\n if (request.responseFormat === 'json_object') {\n body.response_format = { type: 'json_object' };\n }\n\n const thinking = resolveThinking(request.reasoning);\n const thinkingEnabled = thinking?.type === 'enabled';\n if (thinking) {\n body.thinking = thinking;\n if (thinking.reasoning_effort) {\n body.reasoning_effort = thinking.reasoning_effort;\n }\n }\n\n // In thinking mode DeepSeek forbids sampling params (temperature / top_p /\n // presence_penalty / frequency_penalty) \u2014 they are rejected or silently\n // dropped \u2014 so temperature is forwarded ONLY when thinking is off (Blueprint\n // v2 \u00A73.2). The other three are never added to the body in any mode.\n if (!thinkingEnabled && typeof request.temperature === 'number') {\n body.temperature = request.temperature;\n }\n if (stream) {\n body.stream = true;\n body.stream_options = { include_usage: true };\n }\n if (request.metadata?.userId) {\n body.user = request.metadata.userId;\n }\n\n return body;\n }\n}\n\n/**\n * Factory for the DeepSeek provider. Reads `DEEPSEEK_API_KEY` (and the optional\n * `DEEPSEEK_MODEL` / `DEEPSEEK_BASE_URL`) from `@fim/config` unless overridden\n * via {@link ProviderOptions}.\n */\nexport const deepseekProvider = (options?: ProviderOptions): AiProvider =>\n new DeepSeekProvider(options);\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\n/** Translate the canonical `reasoning` flag into DeepSeek's `thinking` object. */\nfunction resolveThinking(\n reasoning: ChatRequest['reasoning'],\n): DeepSeekThinkingConfig | undefined {\n if (reasoning === undefined) return undefined;\n if (reasoning === false) return { type: 'disabled' };\n if (reasoning === true) return { type: 'enabled', reasoning_effort: 'high' };\n return { type: 'enabled', reasoning_effort: reasoning.effort ?? 'high' };\n}\n\nfunction mapToolCalls(tcs?: DeepSeekToolCall[]): ToolCall[] {\n if (!tcs || tcs.length === 0) return [];\n return tcs.map((tc) => ({ id: tc.id, name: tc.function.name, arguments: tc.function.arguments }));\n}\n\nfunction mapFinishReason(reason: string | null): AiFinishReason {\n switch (reason) {\n case 'stop':\n return 'stop';\n case 'length':\n return 'length';\n case 'content_filter':\n return 'content_filter';\n case 'tool_calls':\n case 'function_call':\n return 'tool_use';\n case null:\n return 'unknown';\n default:\n return 'unknown';\n }\n}\n\nfunction safeParse<T>(raw: string): T | null {\n try {\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n\nfunction stripTrailingSlash(url: string): string {\n return url.endsWith('/') ? url.slice(0, -1) : url;\n}\n", "import { env } from '@fim/config';\nimport { AppError } from '@fim/utils';\n\nimport {\n AiProviderError,\n postJson,\n readJson,\n resolveFetch,\n resolveTimeout,\n} from '../internal/http.js';\nimport { parseSseStream } from '../internal/sse.js';\nimport type { AiProvider, ProviderOptions } from '../provider.js';\nimport type {\n AiFinishReason,\n AiModel,\n ChatChunk,\n ChatRequest,\n ChatResult,\n EmbedRequest,\n EmbedResponse,\n} from '../types.js';\n\nconst DEFAULT_BASE_URL = 'https://api.openai.com/v1';\nexport const OPENAI_DEFAULT_MODEL = 'gpt-4o';\nexport const OPENAI_DEFAULT_EMBEDDING_MODEL = 'text-embedding-3-small';\nconst DEFAULT_MAX_TOKENS = 4096;\n\nconst OPENAI_MODELS: readonly AiModel[] = [\n {\n id: 'gpt-4o',\n provider: 'openai',\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n supportsStreaming: true,\n supportsEmbeddings: false,\n },\n {\n id: 'gpt-4o-mini',\n provider: 'openai',\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n supportsStreaming: true,\n supportsEmbeddings: false,\n },\n {\n id: 'text-embedding-3-small',\n provider: 'openai',\n contextWindow: 8_191,\n maxOutputTokens: 0,\n supportsStreaming: false,\n supportsEmbeddings: true,\n },\n {\n id: 'text-embedding-3-large',\n provider: 'openai',\n contextWindow: 8_191,\n maxOutputTokens: 0,\n supportsStreaming: false,\n supportsEmbeddings: true,\n },\n];\n\n/* -------------------------------------------------------------------------- */\n/* Wire shapes */\n/* -------------------------------------------------------------------------- */\n\ninterface OpenAiChatMessage {\n readonly role: 'system' | 'user' | 'assistant';\n readonly content: string;\n}\n\ninterface OpenAiChatRequestBody {\n model: string;\n messages: OpenAiChatMessage[];\n max_tokens?: number;\n temperature?: number;\n stream?: boolean;\n stream_options?: { include_usage: boolean };\n user?: string;\n}\n\ninterface OpenAiUsage {\n readonly prompt_tokens: number;\n readonly completion_tokens: number;\n readonly total_tokens: number;\n}\n\ninterface OpenAiChatResponse {\n readonly model: string;\n readonly choices: ReadonlyArray<{\n readonly message: { readonly content: string | null };\n readonly finish_reason: string | null;\n }>;\n readonly usage?: OpenAiUsage;\n}\n\ninterface OpenAiChatStreamChunk {\n readonly model: string;\n readonly choices: ReadonlyArray<{\n readonly delta: { readonly content?: string | null };\n readonly finish_reason: string | null;\n }>;\n readonly usage?: OpenAiUsage | null;\n}\n\ninterface OpenAiEmbeddingResponse {\n readonly model: string;\n readonly data: ReadonlyArray<{ readonly index: number; readonly embedding: number[] }>;\n readonly usage?: { readonly prompt_tokens: number; readonly total_tokens: number };\n}\n\n/**\n * OpenAI Chat Completions provider. Implements {@link AiProvider} via raw\n * `fetch` against `/chat/completions` and `/embeddings`, with SSE parsing for\n * {@link stream}.\n */\nclass OpenAiProvider implements AiProvider {\n readonly name = 'openai' as const;\n readonly defaultModel: string;\n readonly models = OPENAI_MODELS;\n\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly embeddingModel: string;\n private readonly timeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n private readonly extraHeaders: Record<string, string>;\n\n constructor(options: ProviderOptions = {}) {\n const apiKey = options.apiKey ?? env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new AppError('OPENAI_API_KEY is not configured', {\n code: 'AI_MISSING_API_KEY',\n statusCode: 500,\n });\n }\n this.apiKey = apiKey;\n this.baseUrl = stripTrailingSlash(options.baseUrl ?? DEFAULT_BASE_URL);\n this.defaultModel =\n options.defaultModel ?? env.OPENAI_MODEL ?? OPENAI_DEFAULT_MODEL;\n this.embeddingModel =\n options.defaultEmbeddingModel ??\n env.AI_EMBEDDING_MODEL ??\n OPENAI_DEFAULT_EMBEDDING_MODEL;\n this.timeoutMs = resolveTimeout(options);\n this.fetchImpl = resolveFetch(options);\n this.extraHeaders = { ...options.headers };\n }\n\n async chat(request: ChatRequest): Promise<string> {\n return (await this.chatVerbose(request)).content;\n }\n\n async chatVerbose(request: ChatRequest): Promise<ChatResult> {\n const response = await postJson({\n provider: this.name,\n url: `${this.baseUrl}/chat/completions`,\n headers: this.headers(),\n body: this.buildChatBody(request, false),\n timeoutMs: this.timeoutMs,\n fetchImpl: this.fetchImpl,\n signal: request.signal,\n });\n\n const data = await readJson<OpenAiChatResponse>(response);\n const choice = data.choices[0];\n\n return {\n content: choice?.message.content ?? '',\n model: data.model,\n finishReason: mapFinishReason(choice?.finish_reason ?? null),\n usage: data.usage\n ? {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined,\n };\n }\n\n async *stream(request: ChatRequest): AsyncIterable<ChatChunk> {\n const response = await postJson({\n provider: this.name,\n url: `${this.baseUrl}/chat/completions`,\n headers: this.headers(),\n body: this.buildChatBody(request, true),\n timeoutMs: this.timeoutMs,\n fetchImpl: this.fetchImpl,\n signal: request.signal,\n });\n\n if (!response.body) {\n throw new AiProviderError({\n provider: this.name,\n status: response.status,\n message: 'OpenAI stream response had no body',\n });\n }\n\n let finishReason: AiFinishReason = 'unknown';\n let usage: OpenAiUsage | undefined;\n\n for await (const sse of parseSseStream(response.body)) {\n const payload = sse.data.trim();\n if (!payload) continue;\n if (payload === '[DONE]') break;\n\n const chunk = safeParse<OpenAiChatStreamChunk>(payload);\n if (!chunk) continue;\n\n if (chunk.usage) usage = chunk.usage;\n\n const choice = chunk.choices[0];\n if (!choice) continue;\n\n if (choice.delta.content) {\n yield { delta: choice.delta.content, done: false };\n }\n if (choice.finish_reason) {\n finishReason = mapFinishReason(choice.finish_reason);\n }\n }\n\n yield {\n delta: '',\n done: true,\n finishReason,\n usage: usage\n ? {\n inputTokens: usage.prompt_tokens,\n outputTokens: usage.completion_tokens,\n totalTokens: usage.total_tokens,\n }\n : undefined,\n };\n }\n\n async embed(request: EmbedRequest): Promise<EmbedResponse> {\n const response = await postJson({\n provider: this.name,\n url: `${this.baseUrl}/embeddings`,\n headers: this.headers(),\n body: {\n model: request.model ?? this.embeddingModel,\n input: [...request.input],\n ...(request.dimensions ? { dimensions: request.dimensions } : {}),\n },\n timeoutMs: this.timeoutMs,\n fetchImpl: this.fetchImpl,\n signal: request.signal,\n });\n\n const data = await readJson<OpenAiEmbeddingResponse>(response);\n // Preserve input order regardless of the order the API returns rows in.\n const ordered = [...data.data].sort((a, b) => a.index - b.index);\n\n return {\n model: data.model,\n embeddings: ordered.map((row) => row.embedding),\n usage: data.usage\n ? {\n inputTokens: data.usage.prompt_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined,\n };\n }\n\n private headers(): Record<string, string> {\n return {\n authorization: `Bearer ${this.apiKey}`,\n ...this.extraHeaders,\n };\n }\n\n private buildChatBody(\n request: ChatRequest,\n stream: boolean,\n ): OpenAiChatRequestBody {\n const messages: OpenAiChatMessage[] = [];\n if (request.system) {\n messages.push({ role: 'system', content: request.system });\n }\n for (const message of request.messages) {\n // Tool messages flow only to tool-capable providers (DeepSeek); skip to stay well-typed.\n if (message.role === 'tool') continue;\n messages.push({ role: message.role, content: message.content });\n }\n\n const body: OpenAiChatRequestBody = {\n model: request.model ?? this.defaultModel,\n messages,\n max_tokens: request.maxTokens ?? DEFAULT_MAX_TOKENS,\n };\n\n if (typeof request.temperature === 'number') {\n body.temperature = request.temperature;\n }\n if (stream) {\n body.stream = true;\n // Ask OpenAI to emit a final usage-bearing chunk.\n body.stream_options = { include_usage: true };\n }\n if (request.metadata?.userId) {\n body.user = request.metadata.userId;\n }\n\n return body;\n }\n}\n\n/**\n * Factory for the OpenAI provider. Reads `OPENAI_API_KEY` from `@fim/config`\n * unless overridden via {@link ProviderOptions}.\n */\nexport const openaiProvider = (options?: ProviderOptions): AiProvider =>\n new OpenAiProvider(options);\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction mapFinishReason(reason: string | null): AiFinishReason {\n switch (reason) {\n case 'stop':\n return 'stop';\n case 'length':\n return 'length';\n case 'content_filter':\n return 'content_filter';\n case 'tool_calls':\n case 'function_call':\n return 'tool_use';\n case null:\n return 'unknown';\n default:\n return 'unknown';\n }\n}\n\nfunction safeParse<T>(raw: string): T | null {\n try {\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n\nfunction stripTrailingSlash(url: string): string {\n return url.endsWith('/') ? url.slice(0, -1) : url;\n}\n", "import { z } from 'zod';\n\n/**\n * Supported provider identifiers. Selected at runtime via `env.AI_PROVIDER`\n * or explicitly through {@link createAiClient}.\n */\nexport const AI_PROVIDERS = ['anthropic', 'openai', 'deepseek'] as const;\n\nexport type AiProviderName = (typeof AI_PROVIDERS)[number];\n\n/**\n * Role of a single message in a chat conversation.\n *\n * - `system` high-level instructions that steer the assistant.\n * - `user` input from the end user.\n * - `assistant` a prior model response (for multi-turn context).\n */\nexport type ChatRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/** A function the model may call. `parameters` is a JSON Schema for the arguments. */\nexport interface ToolDefinition {\n readonly name: string;\n readonly description?: string;\n readonly parameters: Record<string, unknown>;\n}\n\n/** A tool invocation emitted by the model. `arguments` is a raw JSON string. */\nexport interface ToolCall {\n readonly id: string;\n readonly name: string;\n readonly arguments: string;\n}\n\n/** How the model may use tools: pick freely, never, or must call one. */\nexport type ToolChoice = 'auto' | 'none' | 'required';\n\n/** A single turn in a chat conversation. */\nexport interface ChatMessage {\n readonly role: ChatRole;\n /** Visible text. Empty is allowed for an assistant turn that only emits `toolCalls`. */\n readonly content: string;\n /** For `role: 'tool'` \u2014 the id of the tool call this message answers. */\n readonly toolCallId?: string;\n /** For `role: 'assistant'` \u2014 the tool calls the model emitted on this turn. */\n readonly toolCalls?: readonly ToolCall[];\n}\n\n/**\n * A canonical, provider-agnostic chat request. Providers translate this into\n * their own wire formats (Anthropic Messages API, OpenAI Chat Completions, ...).\n */\nexport interface ChatRequest {\n /**\n * Model identifier. When omitted, the provider falls back to its configured\n * default (e.g. `claude-opus-4-8` for Anthropic, `gpt-4o` for OpenAI).\n */\n readonly model?: string;\n /** Ordered conversation history. Must contain at least one non-system turn. */\n readonly messages: readonly ChatMessage[];\n /**\n * Sampling temperature in the `[0, 2]` range. Higher values produce more\n * varied output. Providers that do not accept sampling params ignore this.\n */\n readonly temperature?: number;\n /** Upper bound on tokens to generate. */\n readonly maxTokens?: number;\n /** Optional top-level system prompt (merged with any `system` messages). */\n readonly system?: string;\n /**\n * When `true`, callers are expected to consume the result via\n * {@link AiProvider.stream}. The flag is also forwarded to providers so they\n * can opt into server-side streaming transports.\n */\n readonly stream?: boolean;\n /** Optional per-request abort signal. */\n readonly signal?: AbortSignal;\n /** Arbitrary provider-specific metadata (forwarded verbatim where supported). */\n readonly metadata?: Readonly<Record<string, string>>;\n /**\n * Provider-agnostic reasoning / \"thinking\" control. Providers that expose an\n * extended-thinking mode (e.g. DeepSeek v4) honor this; others ignore it.\n *\n * - `true` enable thinking at the provider default effort.\n * - `false` explicitly disable thinking (force a fast answer).\n * - `{ effort }` enable thinking at the given effort level.\n * - omitted leave the provider's own default in place.\n */\n readonly reasoning?: boolean | { readonly effort?: ReasoningEffort };\n /** Tools (functions) the model may call. Honored by tool-capable providers (DeepSeek). */\n readonly tools?: readonly ToolDefinition[];\n /** Tool-use policy. Defaults to the provider's behavior ('auto') when tools are present. */\n readonly toolChoice?: ToolChoice;\n /**\n * Output-format constraint. `'json_object'` maps to DeepSeek's\n * `response_format: {type: 'json_object'}` (valid-JSON output). Caveats per\n * docs/futurex/review.md: the prompt MUST contain the literal word \"json\"\n * (+ ideally an example), and the SHAPE is not guaranteed \u2014 validate with\n * Zod and run a bounded repair round (see `callJson` in\n * `@fim/futurex-context-engine`). Ignored by providers without support.\n */\n readonly responseFormat?: 'json_object';\n}\n\n/** Reasoning effort levels recognised by thinking-capable providers. */\nexport type ReasoningEffort = 'high' | 'max';\n\n/**\n * One incremental piece of a streamed completion.\n *\n * `delta` carries the newly generated text since the previous chunk (empty on\n * the terminal chunk). `done` is `true` exactly once, on the final chunk.\n */\nexport interface ChatChunk {\n readonly delta: string;\n readonly done: boolean;\n /**\n * Incremental chain-of-thought text from a thinking-capable provider, emitted\n * before the visible answer. Empty/absent for providers without a reasoning\n * channel or when thinking is disabled.\n */\n readonly reasoningDelta?: string;\n /**\n * Incremental tool-call fragment. Tool-call arguments stream as JSON fragments\n * across chunks and must be reassembled by `index` \u2014 the provider also emits the\n * assembled {@link ChatChunk.toolCalls} on the terminal chunk.\n */\n readonly toolCallDelta?: {\n readonly index: number;\n readonly id?: string;\n readonly name?: string;\n readonly argumentsDelta?: string;\n };\n /** Populated on the terminal chunk when the model emitted tool calls. */\n readonly toolCalls?: readonly ToolCall[];\n /** Populated on the terminal chunk when the provider reports a stop reason. */\n readonly finishReason?: AiFinishReason;\n /** Populated on the terminal chunk when usage accounting is available. */\n readonly usage?: AiUsage;\n}\n\nexport type AiFinishReason =\n | 'stop'\n | 'length'\n | 'content_filter'\n | 'tool_use'\n | 'error'\n | 'unknown';\n\n/** Token accounting returned by providers that expose it. */\nexport interface AiUsage {\n readonly inputTokens: number;\n readonly outputTokens: number;\n readonly totalTokens: number;\n /**\n * Prefix-cache split, for providers with automatic caching (DeepSeek). The\n * cache-hit portion of input is billed at a fraction (~1/50th) of cache-miss,\n * so this is the lever the cost model + cache-ratio metric depend on. Absent\n * when the provider does not report it.\n */\n readonly cacheHitTokens?: number;\n readonly cacheMissTokens?: number;\n /**\n * Tokens spent on chain-of-thought (\"thinking\"), when the provider meters them\n * separately (DeepSeek `completion_tokens_details.reasoning_tokens`). A subset\n * of `outputTokens`, surfaced so cost accounting can attribute reasoning spend.\n * Absent when thinking is off or the provider does not report it.\n */\n readonly reasoningTokens?: number;\n}\n\n/** A full, non-streamed chat completion result. */\nexport interface ChatResult {\n readonly content: string;\n readonly model: string;\n readonly finishReason: AiFinishReason;\n /** Tool calls the model emitted, if any (finishReason will be 'tool_use'). */\n readonly toolCalls?: readonly ToolCall[];\n readonly usage?: AiUsage;\n /**\n * The full chain-of-thought returned by a thinking-capable provider, when\n * thinking was enabled. Absent otherwise.\n */\n readonly reasoning?: string;\n}\n\n/** Request to embed one or more text inputs into dense vectors. */\nexport interface EmbedRequest {\n /** Embedding model id (provider default used when omitted). */\n readonly model?: string;\n /** One or more strings to embed. */\n readonly input: readonly string[];\n /** Optional output dimensionality, where the provider supports it. */\n readonly dimensions?: number;\n readonly signal?: AbortSignal;\n}\n\n/** Result of an {@link EmbedRequest}: one vector per input, in order. */\nexport interface EmbedResponse {\n readonly model: string;\n readonly embeddings: readonly (readonly number[])[];\n readonly usage?: Pick<AiUsage, 'inputTokens' | 'totalTokens'>;\n}\n\n/** Lightweight description of a model the SDK knows how to address. */\nexport interface AiModel {\n readonly id: string;\n readonly provider: AiProviderName;\n readonly contextWindow: number;\n readonly maxOutputTokens: number;\n readonly supportsStreaming: boolean;\n readonly supportsEmbeddings: boolean;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Runtime validation schemas (Zod) */\n/* -------------------------------------------------------------------------- */\n\nexport const chatRoleSchema = z.enum(['system', 'user', 'assistant', 'tool']);\n\nexport const toolCallSchema = z.object({\n id: z.string(),\n name: z.string().min(1),\n arguments: z.string(),\n});\n\nexport const toolDefinitionSchema = z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n parameters: z.record(z.unknown()),\n});\n\nexport const chatMessageSchema = z.object({\n role: chatRoleSchema,\n // Empty content is valid for an assistant turn that only carries tool_calls.\n content: z.string(),\n toolCallId: z.string().optional(),\n toolCalls: z.array(toolCallSchema).optional(),\n});\n\nexport const chatRequestSchema = z.object({\n model: z.string().min(1).optional(),\n messages: z.array(chatMessageSchema).min(1, 'at least one message is required'),\n temperature: z.number().min(0).max(2).optional(),\n maxTokens: z.number().int().positive().optional(),\n system: z.string().optional(),\n stream: z.boolean().optional(),\n metadata: z.record(z.string()).optional(),\n reasoning: z\n .union([z.boolean(), z.object({ effort: z.enum(['high', 'max']).optional() })])\n .optional(),\n tools: z.array(toolDefinitionSchema).optional(),\n toolChoice: z.enum(['auto', 'none', 'required']).optional(),\n responseFormat: z.literal('json_object').optional(),\n});\n\nexport const embedRequestSchema = z.object({\n model: z.string().min(1).optional(),\n input: z.array(z.string().min(1)).min(1, 'at least one input is required'),\n dimensions: z.number().int().positive().optional(),\n});\n\nexport type ChatRequestInput = z.infer<typeof chatRequestSchema>;\nexport type EmbedRequestInput = z.infer<typeof embedRequestSchema>;\n", "import { env } from '@fim/config';\nimport { createLogger } from '@fim/logger';\nimport { retry, ValidationError, type ValidationIssue } from '@fim/utils';\nimport type { ZodError } from 'zod';\n\nimport { AiProviderError } from './internal/http.js';\nimport { anthropicProvider } from './providers/anthropic.js';\nimport { deepseekProvider } from './providers/deepseek.js';\nimport { openaiProvider } from './providers/openai.js';\nimport type { AiProvider, ProviderOptions } from './provider.js';\nimport {\n chatRequestSchema,\n embedRequestSchema,\n type AiModel,\n type AiProviderName,\n type ChatChunk,\n type ChatRequest,\n type ChatResult,\n type EmbedRequest,\n type EmbedResponse,\n} from './types.js';\n\nconst logger = createLogger('ai-sdk');\n\n/** Options for {@link createAiClient}. */\nexport interface AiClientOptions extends ProviderOptions {\n /**\n * Force a specific provider. When omitted, the provider is chosen from\n * `env.AI_PROVIDER`, defaulting to `deepseek` (DeepSeek-only system).\n */\n readonly provider?: AiProviderName;\n /** Maximum retry attempts for transient failures. Defaults to 3. */\n readonly maxRetries?: number;\n /** Base backoff in milliseconds for retries. Defaults to 500. */\n readonly retryBaseMs?: number;\n}\n\n/**\n * The public client surface. Adds validation, retry, and convenience helpers\n * on top of the selected {@link AiProvider}.\n */\nexport interface AiClient {\n readonly provider: AiProvider;\n readonly providerName: AiProviderName;\n\n /** Run a chat completion, returning the assistant text. */\n chat(request: ChatRequest): Promise<string>;\n\n /** Run a chat completion, returning the full result with usage/finish data. */\n chatVerbose(request: ChatRequest): Promise<ChatResult>;\n\n /** Stream a chat completion as {@link ChatChunk}s. */\n stream(request: ChatRequest): AsyncIterable<ChatChunk>;\n\n /** Embed one or more inputs into dense vectors. */\n embed(request: EmbedRequest): Promise<EmbedResponse>;\n\n /** List the models the active provider can address. */\n listModels(): readonly AiModel[];\n}\n\nconst PROVIDER_FACTORIES: Record<\n AiProviderName,\n (options?: ProviderOptions) => AiProvider\n> = {\n anthropic: anthropicProvider,\n openai: openaiProvider,\n deepseek: deepseekProvider,\n};\n\n/**\n * Create an {@link AiClient}, selecting the backend from `opts.provider` or\n * `env.AI_PROVIDER` (default `deepseek`).\n *\n * Non-streaming calls (`chat`, `chatVerbose`, `embed`) are wrapped in\n * exponential-backoff retry via `@fim/utils.retry`, retrying only on transient\n * provider errors (HTTP 408/429/5xx). Streaming is intentionally not retried \u2014\n * a half-consumed stream cannot be safely replayed; callers restart explicitly.\n */\nexport function createAiClient(opts: AiClientOptions = {}): AiClient {\n const providerName = resolveProviderName(opts.provider);\n const factory = PROVIDER_FACTORIES[providerName];\n const provider = factory(toProviderOptions(opts));\n\n const maxRetries = opts.maxRetries ?? 3;\n const retryBaseMs = opts.retryBaseMs ?? 500;\n\n const withRetry = <T>(label: string, fn: () => Promise<T>): Promise<T> =>\n retry(fn, {\n retries: maxRetries,\n delay: retryBaseMs,\n backoff: 'exponential',\n shouldRetry: isRetryable,\n onRetry: (error, attempt) => {\n logger.warn(\n { provider: providerName, op: label, attempt, err: describe(error) },\n 'retrying AI request',\n );\n },\n });\n\n return {\n provider,\n providerName,\n\n async chat(request: ChatRequest): Promise<string> {\n const validated = validateChat(request);\n return withRetry('chat', () => provider.chat(validated));\n },\n\n async chatVerbose(request: ChatRequest): Promise<ChatResult> {\n const validated = validateChat(request);\n return withRetry('chatVerbose', () => provider.chatVerbose(validated));\n },\n\n stream(request: ChatRequest): AsyncIterable<ChatChunk> {\n const validated = validateChat({ ...request, stream: true });\n return provider.stream(validated);\n },\n\n async embed(request: EmbedRequest): Promise<EmbedResponse> {\n const validated = validateEmbed(request);\n return withRetry('embed', () => provider.embed(validated));\n },\n\n listModels(): readonly AiModel[] {\n return provider.models;\n },\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction resolveProviderName(explicit?: AiProviderName): AiProviderName {\n // Read AI_PROVIDER defensively: the value is validated by `@fim/config`, but\n // we tolerate config builds that predate the key by treating it as optional.\n const fromEnv = (env as Record<string, unknown>).AI_PROVIDER;\n const candidate =\n explicit ?? (typeof fromEnv === 'string' ? (fromEnv as AiProviderName) : undefined);\n if (candidate && candidate in PROVIDER_FACTORIES) {\n return candidate;\n }\n if (candidate) {\n logger.warn(\n { requested: candidate },\n 'unknown AI_PROVIDER, falling back to deepseek',\n );\n }\n // DeepSeek-only system: DeepSeek is the default provider.\n return 'deepseek';\n}\n\nfunction toProviderOptions(opts: AiClientOptions): ProviderOptions {\n const { apiKey, baseUrl, defaultModel, defaultEmbeddingModel, timeoutMs, fetch, headers } =\n opts;\n return { apiKey, baseUrl, defaultModel, defaultEmbeddingModel, timeoutMs, fetch, headers };\n}\n\nfunction validateChat(request: ChatRequest): ChatRequest {\n const result = chatRequestSchema.safeParse(request);\n if (!result.success) {\n throw new ValidationError('Invalid chat request', toIssues(result.error));\n }\n // Re-attach non-serialisable fields the schema strips (signal).\n return { ...request, ...result.data };\n}\n\nfunction validateEmbed(request: EmbedRequest): EmbedRequest {\n const result = embedRequestSchema.safeParse(request);\n if (!result.success) {\n throw new ValidationError('Invalid embed request', toIssues(result.error));\n }\n return { ...request, ...result.data };\n}\n\n/** Flatten a {@link ZodError} into the platform's {@link ValidationIssue} shape. */\nfunction toIssues(error: ZodError): ValidationIssue[] {\n return error.issues.map((issue) => ({\n path: issue.path.join('.'),\n message: issue.message,\n code: issue.code,\n }));\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof AiProviderError) return error.retryable;\n // Network-level failures (DNS, reset, abort-on-timeout) are worth one more try.\n if (error instanceof Error) {\n return (\n error.name === 'AbortError' ||\n error.name === 'TimeoutError' ||\n /network|fetch failed|ECONN|ETIMEDOUT|EAI_AGAIN/i.test(error.message)\n );\n }\n return false;\n}\n\nfunction describe(error: unknown): string {\n if (error instanceof Error) return `${error.name}: ${error.message}`;\n return String(error);\n}\n", "import { createAiClient, type ChatRequest } from '@fim/ai-sdk';\nimport type { ChatTurn, FutureXClient, StreamEvent } from '@fim/futurex-protocol';\n\n/**\n * Phase-0 backend: streams straight from DeepSeek via `@fim/ai-sdk`, mapping its\n * `ChatChunk`s onto the protocol's `StreamEvent`s. In Phase 1 a gateway-backed\n * client implements the same {@link FutureXClient} and this is swapped out \u2014 the\n * REPL/ask code never changes.\n *\n * NOTE: this is the ONLY place the CLI talks to DeepSeek directly, and the\n * `@fim/ai-sdk` dependency is **Phase-0 only**. The end-state CLI (per the\n * review / \u00A716) routes through the gateway and never sees the model \u2014 so this\n * file AND the `@fim/ai-sdk` dependency in package.json must be deleted when the\n * gateway-backed client lands in Phase 1. See docs/futurex/review.md (reuse map).\n */\nexport function createDirectClient(): FutureXClient {\n const ai = createAiClient({ provider: 'deepseek' });\n\n return {\n async *chat(turn: ChatTurn): AsyncIterable<StreamEvent> {\n const request: ChatRequest = {\n messages: turn.messages.map((m) => ({ role: m.role, content: m.content })),\n system: turn.system,\n reasoning: turn.reasoning,\n model: turn.model,\n maxTokens: turn.maxTokens,\n signal: turn.signal,\n };\n\n try {\n for await (const chunk of ai.stream(request)) {\n if (chunk.reasoningDelta) {\n yield { t: 'thought', text: chunk.reasoningDelta };\n }\n if (chunk.delta) {\n yield { t: 'token', text: chunk.delta };\n }\n if (chunk.done) {\n if (chunk.usage) {\n yield {\n t: 'usage',\n usage: {\n inputTokens: chunk.usage.inputTokens,\n outputTokens: chunk.usage.outputTokens,\n totalTokens: chunk.usage.totalTokens,\n ...(chunk.usage.cacheHitTokens !== undefined\n ? { cacheHitTokens: chunk.usage.cacheHitTokens }\n : {}),\n ...(chunk.usage.cacheMissTokens !== undefined\n ? { cacheMissTokens: chunk.usage.cacheMissTokens }\n : {}),\n ...(chunk.usage.reasoningTokens !== undefined\n ? { reasoningTokens: chunk.usage.reasoningTokens }\n : {}),\n },\n };\n }\n yield { t: 'done', finishReason: chunk.finishReason };\n }\n }\n } catch (err) {\n yield { t: 'error', message: err instanceof Error ? err.message : String(err) };\n }\n },\n };\n}\n", "import { basename } from 'node:path';\nimport type {\n ChatTurn,\n FutureXClient,\n OpenSessionResponse,\n StreamEvent,\n ToolResultMessage,\n} from '@fim/futurex-protocol';\nimport type { Credentials } from '../creds.js';\nimport { refresh } from '../auth.js';\nimport { parseSse } from '../http.js';\nimport { buildRepoCard, readMemory } from '../repo.js';\nimport { createToolRunner, type Gate } from '../tool-runner.js';\nimport { line, toolCallLine, toolResultLine } from '../ui.js';\n\nexport interface GatewayClientDeps {\n /** Permission gate for mutating tools (the gateway never executes them). */\n readonly gate: Gate;\n /** Repository root the tools are confined to. */\n readonly repoRoot: string;\n /** Include the repo card in the session prefix (default true). */\n readonly useRepo?: boolean;\n /** Include futurex-memory.md in the session prefix (default true). */\n readonly useMemory?: boolean;\n /**\n * Observe each tool the gateway asked this client to run (after it ran).\n * The completion engine uses this to know when files changed, so it can\n * verify before letting a turn finish.\n */\n readonly onTool?: (info: { name: string; mutating: boolean; ok: boolean }) => void;\n}\n\n/**\n * Turn a non-2xx gateway response into a clear, actionable message by reading\n * the API's `{ error: { code, message } }` envelope. The gateway gates FutureX\n * behind the subscription/tier checks, so surface those (and what to do)\n * instead of a bare status code.\n */\nasync function gatewayError(res: Response, fallback: string): Promise<string> {\n let code: string | undefined;\n let message: string | undefined;\n try {\n const body = (await res.json()) as { error?: { code?: string; message?: string } };\n code = body.error?.code;\n message = body.error?.message;\n } catch {\n /* non-JSON body \u2014 fall back to the status code */\n }\n if (code === 'DAILY_LIMIT_REACHED') {\n return message ?? 'Daily token limit reached \u2014 it resets at 00:00 UTC. Try again then.';\n }\n if (code === 'TOKEN_CAP_REACHED') {\n return message ?? 'Monthly token limit reached \u2014 top up or upgrade in the dashboard.';\n }\n if (code === 'SUBSCRIPTION_REQUIRED' || res.status === 402) {\n return `${message ?? 'A FutureX subscription is required.'}\\n Subscribe (the Free plan is enough to start) in the dashboard, then run this again.`;\n }\n // 403 from a tier check already carries an actionable \"\u2026upgrade to use it.\" message.\n if (res.status === 403) {\n return message ?? 'Your account is not permitted to use FutureX.';\n }\n return message ?? fallback;\n}\n\n/**\n * Gateway-backed agent client \u2014 the thin client's whole backend.\n *\n * Opens a FutureX session (advertising the repo card, project memory, and the\n * tools it can execute), POSTs each turn, and relays the SSE stream. The CLI\n * never calls DeepSeek: the gateway runs the agent loop and, whenever its model\n * needs the repo, emits a `tool_request` \u2014 which this client runs LOCALLY\n * (Zod-validated, mutating tools permission-gated) and answers via\n * `POST \u2026/tool-result`. Source never leaves the machine beyond what the model\n * explicitly reads. Silently refreshes the access token once on a 401.\n */\nexport function createGatewayClient(initial: Credentials, deps: GatewayClientDeps): FutureXClient {\n let creds = initial;\n let sessionId: string | null = null;\n const runner = createToolRunner(deps.repoRoot);\n const mutating = new Set(runner.descriptors().filter((t) => t.mutating).map((t) => t.name));\n\n async function authedFetch(path: string, init: RequestInit, allowRefresh = true): Promise<Response> {\n const res = await fetch(`${creds.apiUrl}${path}`, {\n ...init,\n headers: { ...(init.headers as Record<string, string>), authorization: `Bearer ${creds.accessToken}` },\n });\n if (res.status === 401 && allowRefresh) {\n creds = await refresh(creds);\n return authedFetch(path, init, false);\n }\n return res;\n }\n\n async function ensureSession(): Promise<string> {\n if (sessionId) return sessionId;\n const card = deps.useRepo === false ? undefined : (buildRepoCard(deps.repoRoot) ?? undefined);\n const memory = deps.useMemory === false ? undefined : (readMemory(deps.repoRoot) ?? undefined);\n const res = await authedFetch('/api/v1/futurex/sessions', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n repoName: basename(deps.repoRoot),\n ...(card ? { repoCard: card } : {}),\n ...(memory ? { memory } : {}),\n tools: runner.descriptors(),\n }),\n });\n if (!res.ok) throw new Error(await gatewayError(res, `failed to open session (${res.status})`));\n const json = (await res.json()) as { data: OpenSessionResponse };\n sessionId = json.data.sessionId;\n return sessionId;\n }\n\n async function postToolResult(id: string, message: ToolResultMessage): Promise<void> {\n try {\n await authedFetch(`/api/v1/futurex/sessions/${id}/tool-result`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(message),\n });\n } catch {\n // The loop's per-tool timeout will surface a clean failure if this is lost.\n }\n }\n\n /** Run a tool the gateway asked for, print its activity, and POST the result. */\n async function handleToolRequest(\n id: string,\n requestId: string,\n ev: Extract<StreamEvent, { t: 'tool_request' }>,\n ): Promise<void> {\n const preview = runner.preview(ev.name, ev.arguments) ?? ev.name;\n const isMutating = mutating.has(ev.name);\n line(toolCallLine(preview, isMutating));\n const result = await runner.run(ev.name, ev.arguments, deps.gate);\n line(toolResultLine(result.output, result.ok));\n deps.onTool?.({ name: ev.name, mutating: isMutating, ok: result.ok });\n await postToolResult(id, { requestId, toolCallId: ev.id, ok: result.ok, output: result.output });\n }\n\n return {\n async *chat(turn: ChatTurn): AsyncIterable<StreamEvent> {\n try {\n const id = await ensureSession();\n const init: RequestInit = {\n method: 'POST',\n headers: { 'content-type': 'application/json', accept: 'text/event-stream' },\n // The gateway OWNS the system prefix (built from card + memory at open),\n // so the turn carries only the conversation + routing \u2014 never `system`.\n body: JSON.stringify({\n messages: turn.messages,\n reasoning: turn.reasoning,\n model: turn.model,\n maxTokens: turn.maxTokens,\n tier: turn.tier,\n effort: turn.effort,\n }),\n };\n if (turn.signal) init.signal = turn.signal;\n\n const res = await authedFetch(`/api/v1/futurex/sessions/${id}/chat`, init);\n if (!res.ok) {\n yield { t: 'error', message: await gatewayError(res, `gateway error (${res.status})`) };\n return;\n }\n if (!res.body) {\n yield { t: 'error', message: `gateway error (${res.status})` };\n return;\n }\n const requestId = res.headers.get('x-futurex-request-id') ?? '';\n\n for await (const data of parseSse(res.body)) {\n if (data === '[DONE]') break;\n let event: StreamEvent;\n try {\n event = JSON.parse(data) as StreamEvent;\n } catch {\n continue;\n }\n if (event.t === 'tool_request') {\n // Execute locally + answer the gateway; don't surface it as chat output.\n await handleToolRequest(id, requestId, event);\n continue;\n }\n if (event.t === 'status') continue; // transport status (e.g. \"open\")\n yield event;\n }\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') return;\n yield { t: 'error', message: err instanceof Error ? err.message : String(err) };\n }\n },\n };\n}\n", "import { apiBaseUrl } from './config.js';\nimport { writeCreds, type Credentials } from './creds.js';\n\ninterface AuthEnvelope {\n success?: boolean;\n data?: {\n user?: { email?: string };\n tokens?: { accessToken?: string };\n accessToken?: string;\n };\n error?: { message?: string };\n}\n\nfunction extractAccessToken(json: AuthEnvelope): string | undefined {\n return json.data?.tokens?.accessToken ?? json.data?.accessToken;\n}\n\n/** Pull the `fim_rt` refresh cookie out of a response's Set-Cookie headers. */\nfunction extractRefreshCookie(res: Response): string | undefined {\n const getSetCookie = (res.headers as { getSetCookie?: () => string[] }).getSetCookie;\n const cookies = typeof getSetCookie === 'function' ? getSetCookie.call(res.headers) : [];\n for (const c of cookies) {\n if (c.startsWith('fim_rt=')) return c.split(';')[0];\n }\n return undefined;\n}\n\n/** Authenticate with email/password and persist credentials. */\nexport async function login(email: string, password: string): Promise<Credentials> {\n const apiUrl = apiBaseUrl();\n const res = await fetch(`${apiUrl}/api/v1/auth/login`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ email, password }),\n });\n const json = (await res.json().catch(() => ({}))) as AuthEnvelope;\n const accessToken = extractAccessToken(json);\n if (!res.ok || json.success === false || !accessToken) {\n throw new Error(json.error?.message ?? `login failed (${res.status})`);\n }\n const creds: Credentials = {\n apiUrl,\n email: json.data?.user?.email ?? email,\n accessToken,\n refreshCookie: extractRefreshCookie(res),\n };\n writeCreds(creds);\n return creds;\n}\n\n/** Exchange the refresh cookie for a fresh access token (single-use rotation). */\nexport async function refresh(creds: Credentials): Promise<Credentials> {\n if (!creds.refreshCookie) throw new Error('not logged in \u2014 run `futurex login`');\n const res = await fetch(`${creds.apiUrl}/api/v1/auth/refresh`, {\n method: 'POST',\n headers: { cookie: creds.refreshCookie },\n });\n const json = (await res.json().catch(() => ({}))) as AuthEnvelope;\n const accessToken = extractAccessToken(json);\n if (!res.ok || !accessToken) {\n throw new Error('session expired \u2014 run `futurex login`');\n }\n const updated: Credentials = {\n ...creds,\n accessToken,\n refreshCookie: extractRefreshCookie(res) ?? creds.refreshCookie,\n };\n writeCreds(updated);\n return updated;\n}\n", "/**\n * Parse a Server-Sent-Events body into successive `data:` payloads. Yields the\n * decoded data string of each `\\n\\n`-delimited event (joining multi-line data).\n */\nexport async function* parseSse(body: ReadableStream<Uint8Array>): AsyncGenerator<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n if (value) buffer += decoder.decode(value, { stream: true });\n let idx: number;\n while ((idx = buffer.indexOf('\\n\\n')) !== -1) {\n const event = buffer.slice(0, idx);\n buffer = buffer.slice(idx + 2);\n const data = event\n .split('\\n')\n .filter((l) => l.startsWith('data:'))\n .map((l) => l.slice(5).replace(/^ /, ''))\n .join('\\n');\n if (data) yield data;\n }\n }\n } finally {\n try {\n reader.releaseLock();\n } catch {\n /* ignore */\n }\n }\n}\n", "/**\n * Local tool execution for the thin client.\n *\n * In the gateway architecture the BACKEND drives the agent loop and asks the CLI\n * to run tools (`tool_request`); this runner is the CLI's executor. It owns the\n * `@fim/futurex-tools` registry, validates the model's (untrusted) arguments with\n * each tool's Zod schema, gates mutating tools behind a permission prompt, and\n * runs them confined to the repo root. The descriptors it advertises are exactly\n * what the gateway feeds the model \u2014 the CLI is authoritative about its own tools.\n */\nimport { createToolRegistry, type ToolContext } from '@fim/futurex-tools';\nimport type { ToolDescriptor } from '@fim/futurex-protocol';\nimport type { Gate } from './permissions.js';\n\nexport type { Gate } from './permissions.js';\n\nexport interface ToolRunner {\n /** Tool descriptors to advertise to the gateway (name/description/params/mutating). */\n descriptors(): ToolDescriptor[];\n /** Human-readable one-line preview of a tool call, or null if the call is invalid. */\n preview(name: string, argsJson: string): string | null;\n /** Validate, (gate if mutating), and run a tool. Never throws \u2014 errors become output. */\n run(name: string, argsJson: string, gate: Gate): Promise<{ ok: boolean; output: string }>;\n /** Number of tools available (for banners). */\n readonly count: number;\n}\n\nexport function createToolRunner(repoRoot: string): ToolRunner {\n const registry = createToolRegistry();\n const ctx: ToolContext = { repoRoot };\n\n const parse = (name: string, argsJson: string): { spec: ReturnType<typeof registry.get>; args?: unknown; error?: string } => {\n const spec = registry.get(name);\n if (!spec) return { spec, error: `unknown tool: ${name}` };\n try {\n return { spec, args: spec.schema.parse(JSON.parse(argsJson || '{}')) };\n } catch (err) {\n return { spec, error: `invalid arguments: ${err instanceof Error ? err.message : String(err)}` };\n }\n };\n\n return {\n count: registry.specs.length,\n descriptors() {\n return registry.specs.map((s) => ({\n name: s.name,\n description: s.description,\n parameters: s.parameters,\n mutating: s.mutating,\n }));\n },\n preview(name, argsJson) {\n const { spec, args, error } = parse(name, argsJson);\n if (!spec || error || args === undefined) return null;\n return spec.preview(args, ctx);\n },\n async run(name, argsJson, gate) {\n const { spec, args, error } = parse(name, argsJson);\n if (!spec) return { ok: false, output: error ?? `unknown tool: ${name}` };\n if (error || args === undefined) return { ok: false, output: error ?? 'invalid arguments' };\n const kind = spec.classify(args, ctx);\n if (kind !== null) {\n const approved = await gate({ tool: spec.name, kind, preview: spec.preview(args, ctx) });\n if (!approved) return { ok: false, output: 'denied by the user' };\n }\n try {\n return await spec.run(args, ctx);\n } catch (err) {\n return { ok: false, output: `tool error: ${err instanceof Error ? err.message : String(err)}` };\n }\n },\n };\n}\n", "/**\n * Tiny dependency-free terminal helpers: ANSI colour, status lines, and a\n * spinner. Kept local so the CLI has no UI dependency.\n *\n * Colour is gated per destination stream: `color` for stdout, `errColor` for\n * stderr \u2014 so redirecting one stream never leaks escape codes into the other.\n *\n * Every output call also passes through an optional {@link OutputSink}. The\n * interactive chatbox (the fixed bottom input bar) installs itself as the sink\n * with {@link setOutputSink}; that single hook makes every existing `line` /\n * `info` / `out` / `startSpinner` call across the agent loop AND the slash\n * commands redraw ABOVE the input bar instead of trampling it \u2014 no per-callsite\n * edits required. With no sink installed (the default, and every non-interactive\n * subcommand) behaviour is byte-for-byte what it always was: stdout for content,\n * stderr for notes.\n */\n\n/** ASCII escape (0x1B) \u2014 derived from char code to avoid literal-escape issues. */\nconst ESC = String.fromCharCode(27);\n\ntype Palette = Record<\n 'bold' | 'dim' | 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'gray',\n (s: string) => string\n>;\n\nfunction palette(isTty: boolean): Palette {\n const wrap = (code: number) => (s: string) => (isTty ? `${ESC}[${code}m${s}${ESC}[0m` : s);\n return {\n bold: wrap(1),\n dim: wrap(2),\n red: wrap(31),\n green: wrap(32),\n yellow: wrap(33),\n blue: wrap(34),\n magenta: wrap(35),\n cyan: wrap(36),\n gray: wrap(90),\n };\n}\n\nexport const color: Palette = palette(process.stdout.isTTY === true);\nexport const errColor: Palette = palette(process.stderr.isTTY === true);\n\n/**\n * A consumer that intercepts CLI output so a full-screen-ish TUI (the chatbox)\n * can own the bottom of the terminal. Installed via {@link setOutputSink}.\n */\nexport interface OutputSink {\n /** A complete line of committed output (the sink adds the newline + layout). */\n line(text: string): void;\n /** A streaming fragment with no implied newline (assistant tokens). */\n partial(text: string): void;\n /** Show/replace a spinner with this label, or clear it when null. */\n spinner(label: string | null): void;\n}\n\nlet sink: OutputSink | null = null;\n\n/** Route all subsequent output through `s` (the chatbox), or back to the raw streams when null. */\nexport function setOutputSink(s: OutputSink | null): void {\n sink = s;\n}\n\n/** Write to stdout without a trailing newline (used for streaming the answer). */\nexport function out(text: string): void {\n if (sink) sink.partial(text);\n else process.stdout.write(text);\n}\n\n/** Write to stderr without a trailing newline (used for the streamed thinking lane). */\nexport function eout(text: string): void {\n if (sink) sink.partial(text);\n else process.stderr.write(text);\n}\n\n/** Print a line to stdout. */\nexport function line(text = ''): void {\n if (sink) sink.line(text);\n else process.stdout.write(`${text}\\n`);\n}\n\n/** Print an informational note to stderr (so it never pollutes piped stdout). */\nexport function info(text: string): void {\n if (sink) sink.line(color.dim(text));\n else process.stderr.write(`${errColor.dim(text)}\\n`);\n}\n\n/** Print an error to stderr. */\nexport function error(text: string): void {\n if (sink) sink.line(`${color.red('error')} ${text}`);\n else process.stderr.write(`${errColor.red('error')} ${text}\\n`);\n}\n\n/** Print a warning to stderr (yellow). */\nexport function warn(text: string): void {\n if (sink) sink.line(`${color.yellow('warning')} ${text}`);\n else process.stderr.write(`${errColor.yellow('warning')} ${text}\\n`);\n}\n\n// --- shared visual language ---------------------------------------------------\n//\n// One vocabulary for the whole CLI so the agent loop, the gateway client, and\n// the slash commands all render identically: phases are dim rules with a bold\n// label, reads are cyan `\u25B8`, writes are yellow `\u270E`, results hang under the call\n// as a dim `\u21B3` line, and verification verdicts are green \u2713 / red \u2717.\n\n/** Compact human token/number count: 950 \u2192 \"950\", 12_345 \u2192 \"12.3k\", 1.2M\u2026. */\nexport function formatCount(n: number): string {\n if (n < 1000) return String(n);\n if (n < 1_000_000) {\n const k = n / 1000;\n return `${k >= 100 ? Math.round(k) : k.toFixed(1).replace(/\\.0$/, '')}k`;\n }\n const m = n / 1_000_000;\n return `${m >= 100 ? Math.round(m) : m.toFixed(1).replace(/\\.0$/, '')}M`;\n}\n\n/** A dim horizontal rule with a phase label: `\u2500\u2500\u2500 build \u2500\u2500\u2500\u2026`. */\nexport function phaseRule(label: string): string {\n const bar = '\u2500'.repeat(3);\n const rest = '\u2500'.repeat(Math.max(4, 38 - label.length));\n return color.dim(`${bar} `) + color.bold(label) + color.dim(` ${rest}`);\n}\n\n/** Print a phase transition (plan / build / verify / repair). */\nexport function phase(label: string): void {\n line(phaseRule(label));\n}\n\n/** One tool invocation: yellow \u270E for mutations, cyan \u25B8 for reads. */\nexport function toolCallLine(preview: string, mutating: boolean): string {\n return ` ${mutating ? color.yellow('\u270E') : color.cyan('\u25B8')} ${preview}`;\n}\n\n/** The result line that hangs under a tool call: ` \u21B3 first line \u2026(+n lines)`. */\nexport function toolResultLine(output: string, ok = true): string {\n const rows = output.split('\\n');\n const head = (rows[0] ?? '').slice(0, 88);\n const more = rows.length > 1 ? ` ${color.dim(`\u2026(+${rows.length - 1} lines)`)}` : '';\n const mark = ok ? color.dim('\u21B3') : color.red('\u21B3');\n return ` ${mark} ${color.dim(head || (ok ? '(ok)' : '(failed)'))}${more}`;\n}\n\n/** A green-check / red-cross verdict line (verification output). */\nexport function verdictLine(ok: boolean, text: string): string {\n return ` ${ok ? color.green('\u2713') : color.red('\u2717')} ${text}`;\n}\n\nconst SPINNER_FRAMES = ['\u280B', '\u2819', '\u2839', '\u2838', '\u283C', '\u2834', '\u2826', '\u2827', '\u2807', '\u280F'];\n\n/** A running spinner on stderr; call stop() to clear it. No-op off a TTY. */\nexport interface Spinner {\n stop(): void;\n}\n\n/**\n * Start a Braille spinner with a dim label. When a sink (the chatbox) is\n * installed the spinner is delegated to it; otherwise it animates on stderr\n * (and is a no-op when stderr isn't a TTY).\n */\nexport function startSpinner(label: string): Spinner {\n const installed = sink;\n if (installed) {\n installed.spinner(label);\n return {\n stop() {\n installed.spinner(null);\n },\n };\n }\n if (process.stderr.isTTY !== true) return { stop() {} };\n let i = 0;\n process.stderr.write(`${ESC}[?25l`); // hide cursor\n const render = (): void => {\n const frame = SPINNER_FRAMES[i % SPINNER_FRAMES.length] ?? '';\n process.stderr.write(`\\r${errColor.cyan(frame)} ${errColor.dim(label)}${ESC}[K`);\n i += 1;\n };\n render();\n const timer = setInterval(render, 80);\n timer.unref?.();\n return {\n stop() {\n clearInterval(timer);\n process.stderr.write(`\\r${ESC}[K${ESC}[?25h`); // clear line + restore cursor\n },\n };\n}\n", "import type { Message } from '@fim/futurex-protocol';\nimport type { ScoredRecord } from '@fim/futurex-vector';\nimport type { Chunk } from '@fim/futurex-context';\nimport type { Retriever } from './index-store.js';\n\nfunction renderChunks(hits: ScoredRecord<Chunk>[]): string {\n return hits\n .map((h) => `// ${h.payload.path}:${h.payload.startLine}-${h.payload.endLine}\\n${h.payload.text}`)\n .join('\\n\\n');\n}\n\n/**\n * Insert a retrieved-context message immediately before the latest user message.\n * It is added only to the messages sent for THIS turn (never stored in history),\n * so the pinned cached prefix stays byte-identical and context refreshes per turn.\n */\nexport async function augmentMessages(\n messages: Message[],\n retriever: Retriever | null,\n topK: number,\n): Promise<Message[]> {\n if (!retriever || retriever.size === 0 || topK <= 0) return messages;\n\n let idx = -1;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i]?.role === 'user') {\n idx = i;\n break;\n }\n }\n if (idx < 0) return messages;\n\n const query = messages[idx]?.content ?? '';\n const hits = await retriever.retrieve(query, topK);\n if (hits.length === 0) return messages;\n\n const contextMessage: Message = {\n role: 'user',\n content: `Relevant repository code (retrieved for this question):\\n\\n${renderChunks(hits)}`,\n };\n return [...messages.slice(0, idx), contextMessage, ...messages.slice(idx)];\n}\n", "import { createHash } from 'node:crypto';\nimport type { RepoCard } from '@fim/futurex-protocol';\nimport { buildRepoCard, findRepoRoot, readMemory } from './repo.js';\nimport { buildSystemPrompt } from './system-prompt.js';\nimport { loadRetriever, type Retriever } from './index-store.js';\n\n/** The per-session context: the repo, the pinned stable prefix, and the retriever. */\nexport interface SessionContext {\n readonly root: string;\n readonly card: RepoCard | null;\n /** The stable, cache-targeted system prefix (built once, never mutated). */\n readonly system: string;\n /**\n * Fingerprint of {@link system}, captured at session open. The prefix is pinned\n * for the life of the session so DeepSeek prefix-caching hits; comparing it to a\n * recompute from disk is the cache canary. See {@link currentPrefixDigest}.\n */\n readonly systemDigest: string;\n /** Loaded repo index for retrieval augmentation, or null if none/disabled. */\n readonly retriever: Retriever | null;\n}\n\n/** Short content fingerprint of the stable prefix (first 12 hex of SHA-256). */\nexport function prefixDigest(system: string): string {\n return createHash('sha256').update(system).digest('hex').slice(0, 12);\n}\n\n/**\n * Recompute the prefix digest from what is on disk RIGHT NOW (futurex-memory.md +\n * repo card). Compared against the pinned {@link SessionContext.systemDigest} this\n * is the cache canary: a difference means the source changed mid-session. The live\n * session deliberately keeps the pinned prefix (so DeepSeek's cache still hits) \u2014\n * the caller just warns the user to restart to pick the change up.\n */\nexport function currentPrefixDigest(\n ctx: SessionContext,\n opts: { readonly useMemory: boolean; readonly useRepo: boolean },\n): string {\n const card = opts.useRepo ? buildRepoCard(ctx.root) : null;\n const memory = opts.useMemory ? readMemory(ctx.root) : null;\n return prefixDigest(buildSystemPrompt(card, memory));\n}\n\n/** Detect the repo and assemble the stable prefix + retriever according to flags. */\nexport function loadContext(opts: {\n readonly useMemory: boolean;\n readonly useRepo: boolean;\n readonly useContext: boolean;\n}): SessionContext {\n const root = findRepoRoot();\n const card = opts.useRepo ? buildRepoCard(root) : null;\n const memory = opts.useMemory ? readMemory(root) : null;\n const retriever = opts.useContext ? loadRetriever(root) : null;\n const system = buildSystemPrompt(card, memory);\n return { root, card, system, systemDigest: prefixDigest(system), retriever };\n}\n", "/**\n * Assembles the stable, cache-targeted prefix: system prompt + project memory +\n * repo card. Per the review, this prefix must stay byte-identical across a\n * session for DeepSeek prefix-caching to hit \u2014 so it is built ONCE at startup\n * and never mutated mid-session.\n *\n * NOTE: the gateway has its own copy of this text (apps/api \u2026/futurex/prompt.ts)\n * because the backend cannot import the CLI. Keep the protocol sections in sync.\n */\nimport type { RepoCard } from '@fim/futurex-protocol';\n\n/**\n * Versioned base system prompt. Bump `SYSTEM_PROMPT_VERSION` on any edit; never\n * hot-edit the text mid-session (it would break the cached prefix).\n */\nexport const SYSTEM_PROMPT_VERSION = 3;\n\nconst SYSTEM_BASE = [\n 'You are FutureX, a terminal-native AI software engineer working inside the',\n \"user's repository.\",\n '',\n 'Voice: direct, precise, calm. No filler, no flattery, no apologies. Every',\n 'sentence must carry information. Be concise by default; expand only when',\n 'correctness demands it.',\n '',\n 'Quality bar:',\n \"- Correctness over speed. Match the repo's existing conventions, naming, and\",\n ' formatting exactly \u2014 your code should be indistinguishable from the code',\n ' around it.',\n '- Prefer minimal, reviewable changes. Never invent APIs, paths, or flags \u2014',\n ' verify them against the actual code before using them.',\n '- If a request is ambiguous in a way that would change the outcome, ask ONE',\n ' focused question; otherwise state your assumption in one line and proceed.',\n '',\n 'IMPORTANT: you can only create, edit, or delete files when file-writing tools',\n 'are listed under a \"Tools\" section (FutureX\\'s agent mode). If no such tools',\n 'are present you have NO way to touch the filesystem \u2014 do NOT say you created,',\n 'wrote, edited, or deleted any file. Instead, output the file path with its',\n 'full proposed contents and tell the user to run `futurex agent \"<task>\"` to',\n 'apply it.',\n].join('\\n');\n\n/**\n * The working protocol appended to the prefix whenever tools are available\n * (agent mode / the REPL). This is the contract the completion engine\n * (finish.ts) enforces from the outside: plan \u2192 build \u2192 verify, never stop\n * mid-task, and end the final answer with the [[FX:DONE]] marker.\n */\nexport const AGENT_PROTOCOL = [\n '# How you work: plan \u2192 build \u2192 verify (all in ONE turn)',\n '',\n 'You have tools: read_file, list_dir, grep_search (run automatically) and',\n 'write_file, delete_file, terminal_exec (each gated by user approval).',\n 'For any request that changes the repo or needs multiple steps, work through',\n 'three phases without stopping:',\n '',\n '1. PLAN \u2014 before touching anything, output a short plan:',\n ' ## Plan',\n ' Goal: <the user\\'s goal in one line>',\n ' Steps: <numbered, small, concrete \u2014 name the files each step touches>',\n ' Done when: <2-4 checkable criteria>',\n ' Keep it under ~12 lines. For trivial requests (a question, a one-line',\n ' tweak) skip the plan and just answer or make the change.',\n '',\n '2. BUILD \u2014 execute the plan immediately after stating it. The request itself',\n ' is your permission; never pause to ask \"shall I proceed?\".',\n ' - Ground yourself first: grep_search the relevant symbols/usages and',\n ' read_file EVERY file you will modify (and the modules it imports)',\n ' before editing it.',\n ' - write_file takes the FULL new file contents (repo-relative path).',\n ' Never output a diff, never claim an edit happened without the tool',\n ' call. Remove files with delete_file, not shell commands.',\n ' - Make minimal, correct changes that match the surrounding code.',\n '',\n '3. VERIFY \u2014 prove the goal is reached before finishing:',\n ' - Re-read changed files when unsure they are coherent.',\n ' - Where the project has checks (typecheck / lint / tests), run them via',\n ' terminal_exec and fix every failure you introduced. The CLI also runs',\n ' checks automatically after you write files and will hand you any',\n ' failures \u2014 fix them ALL, then re-verify.',\n '',\n 'PERSISTENCE \u2014 the core rule: NEVER end your reply while planned steps or',\n 'fixable failures remain. Never describe what you are \"about to\" do \u2014 do it',\n 'in the same reply by calling the tool. You never need permission to',\n 'continue. If your output gets cut off mid-work you will be told to resume:',\n 'continue exactly where you stopped without repeating anything.',\n '',\n 'COMPLETION CONTRACT \u2014 when (and only when) the goal is fully met and',\n 'verified, end with a 1-3 sentence summary (what changed, which files, how it',\n 'was verified) followed by the literal marker [[FX:DONE]] on its own final',\n 'line. The marker is stripped before display \u2014 the user never sees it. Every',\n 'reply must either contain a tool call or end with this marker; emitting',\n 'neither means you stopped mid-task, which is a protocol violation.',\n].join('\\n');\n\nfunction renderCard(card: RepoCard): string {\n const rows: Array<[string, string | undefined]> = [\n ['name', card.name],\n ['language', card.language],\n ['framework', card.framework],\n ['backend', card.backend],\n ['orm', card.orm],\n ['package manager', card.packageManager],\n ['tests', card.test],\n ];\n return rows\n .filter((r): r is [string, string] => Boolean(r[1]))\n .map(([k, v]) => `- ${k}: ${v}`)\n .join('\\n');\n}\n\n/** Build the stable prefix from the (optional) repo card and memory file. */\nexport function buildSystemPrompt(\n card: RepoCard | null,\n memory: string | null,\n): string {\n // The version marker is part of the prefix, so a forgotten bump after editing\n // SYSTEM_BASE still changes the cached prefix (and a deliberate bump is visible).\n const parts = [`<!-- futurex-system v${SYSTEM_PROMPT_VERSION} -->`, SYSTEM_BASE];\n if (memory) {\n parts.push(`# Project memory (futurex-memory.md)\\n${memory}`);\n }\n if (card) {\n const body = renderCard(card);\n if (body) parts.push(`# Repository\\n${body}`);\n }\n return parts.join('\\n\\n');\n}\n", "import { createHash } from 'node:crypto';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { FlatVectorStore, LocalEmbedder, type Embedder, type ScoredRecord } from '@fim/futurex-vector';\nimport { loadIndex, retrieve, SymbolIndex, ImportGraph, type Chunk } from '@fim/futurex-context';\n\n/** Per-repo index location, keyed by a hash of the absolute repo root. */\nexport function indexPath(root: string): string {\n const hash = createHash('sha1').update(root).digest('hex').slice(0, 16);\n return join(homedir(), '.futurex', 'index', `${hash}.json`);\n}\n\nexport interface Retriever {\n readonly size: number;\n /** AST symbol table (\u00A73.5) \u2014 answers \"is this symbol defined?\" without regex. */\n readonly symbols: SymbolIndex;\n /** Import graph \u2014 file dependencies + broken-link detection. */\n readonly imports: ImportGraph;\n retrieve(query: string, topK: number): Promise<ScoredRecord<Chunk>[]>;\n}\n\n/**\n * Recreate the embedder the index was built with. The id encodes the embedding\n * space (algorithm + dimension) \u2014 `local-hash-v1-d<DIM>` \u2014 so retrieval\n * reconstructs an exact match. DeepSeek-only: the only embedder is the local one.\n */\nfunction embedderFor(id: string): Embedder | null {\n if (id.startsWith('local-hash-')) return new LocalEmbedder();\n return null;\n}\n\n/** Load a persisted index into a retriever, or null if absent/unusable/mismatched. */\nexport function loadRetriever(root: string): Retriever | null {\n const data = loadIndex(indexPath(root));\n if (!data) return null;\n const embedder = embedderFor(data.embedderId);\n if (!embedder) return null;\n // Embedding-space safety: refuse a stale index whose dimension no longer matches\n // the reconstructed embedder (e.g. a bumped LocalEmbedder DIM) rather than\n // mis-scoring against different-length vectors.\n if (embedder.dimensions !== data.dimensions) return null;\n\n const store = FlatVectorStore.fromRecords(data.records);\n return {\n size: data.records.length,\n symbols: SymbolIndex.fromJSON(data.symbols ?? []),\n imports: ImportGraph.fromJSON(data.imports ?? []),\n retrieve: (query, topK) => retrieve(store, embedder, query, topK),\n };\n}\n", "import type { Embedder } from './types.js';\n\n/**\n * Offline, deterministic, dependency-free embedder: hashes tokens into a fixed\n * bag-of-features vector with sublinear TF weighting, L2-normalized so a dot\n * product is cosine similarity. Crude vs a real model (it's lexical, not\n * semantic), but it needs no API key and never sends source off the machine \u2014\n * the right default for embedded mode and \"never upload\" repos. Production uses\n * {@link OpenAiEmbedder}.\n */\nconst DIM = 512;\n\n/** FNV-1a 32-bit hash \u2192 bucket index. */\nfunction bucket(token: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < token.length; i++) {\n h ^= token.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0) % DIM;\n}\n\nfunction tokenize(text: string): string[] {\n return text.toLowerCase().match(/[a-z0-9_]{2,}/g) ?? [];\n}\n\nfunction embedOne(text: string): number[] {\n const vec = new Array<number>(DIM).fill(0);\n for (const token of tokenize(text)) {\n const b = bucket(token);\n vec[b] = (vec[b] ?? 0) + 1;\n }\n // sublinear TF\n for (let i = 0; i < DIM; i++) {\n const v = vec[i] ?? 0;\n vec[i] = v > 0 ? 1 + Math.log(v) : 0;\n }\n // L2 normalize\n let norm = 0;\n for (let i = 0; i < DIM; i++) {\n const v = vec[i] ?? 0;\n norm += v * v;\n }\n norm = Math.sqrt(norm) || 1;\n for (let i = 0; i < DIM; i++) {\n vec[i] = (vec[i] ?? 0) / norm;\n }\n return vec;\n}\n\nexport class LocalEmbedder implements Embedder {\n // Dimension is part of the id so any DIM change invalidates stale indexes by\n // id mismatch rather than silently mis-scoring against a different-length vector.\n readonly id = `local-hash-v1-d${DIM}`;\n readonly dimensions = DIM;\n\n async embed(texts: readonly string[]): Promise<number[][]> {\n return texts.map(embedOne);\n }\n}\n", "import type { ScoredRecord, VectorRecord, VectorStore } from './types.js';\n\n/** Dot product (== cosine when both inputs are L2-normalized). */\nfunction dot(a: readonly number[], b: readonly number[]): number {\n const n = Math.min(a.length, b.length);\n let sum = 0;\n for (let i = 0; i < n; i++) sum += (a[i] ?? 0) * (b[i] ?? 0);\n return sum;\n}\n\n/**\n * In-memory flat vector index: brute-force cosine over all records. Fine for a\n * single repo's chunk set (the embedded/dev path). The prod path swaps in a\n * Qdrant-backed store behind {@link VectorStore}.\n */\nexport class FlatVectorStore<P> implements VectorStore<P> {\n private records: VectorRecord<P>[] = [];\n\n async upsert(records: ReadonlyArray<VectorRecord<P>>): Promise<void> {\n const byId = new Map(this.records.map((r) => [r.id, r] as const));\n for (const r of records) byId.set(r.id, r);\n this.records = [...byId.values()];\n }\n\n async query(vector: readonly number[], topK: number): Promise<ScoredRecord<P>[]> {\n return this.records\n .map((r) => ({ id: r.id, score: dot(vector, r.vector), payload: r.payload }))\n .sort((a, b) => b.score - a.score)\n .slice(0, Math.max(0, topK));\n }\n\n async size(): Promise<number> {\n return this.records.length;\n }\n\n async clear(): Promise<void> {\n this.records = [];\n }\n\n /** The records, for persistence. */\n toRecords(): VectorRecord<P>[] {\n return [...this.records];\n }\n\n static fromRecords<P>(records: ReadonlyArray<VectorRecord<P>>): FlatVectorStore<P> {\n const store = new FlatVectorStore<P>();\n store.upsert(records);\n return store;\n }\n}\n", "/**\n * `@fim/futurex-vector` \u2014 the embedding + vector-store layer.\n *\n * DeepSeek-only system: DeepSeek has no embeddings endpoint, so retrieval\n * embeddings are computed entirely IN-PROCESS by {@link LocalEmbedder} (no\n * external vendor \u2014 the only external AI API in the system is DeepSeek). A\n * self-hosted neural embedder is the planned quality upgrade behind this same\n * {@link Embedder} interface \u2014 still no second vendor.\n */\nexport type { Embedder, VectorRecord, ScoredRecord, VectorStore } from './types.js';\nexport { LocalEmbedder } from './local-embedder.js';\nexport { FlatVectorStore } from './flat-store.js';\n\nimport { LocalEmbedder } from './local-embedder.js';\nimport type { Embedder } from './types.js';\n\n/** The embedder for the DeepSeek-only system: the offline, in-process LocalEmbedder. */\nexport function createEmbedder(): Embedder {\n return new LocalEmbedder();\n}\n", "import { type Dirent, readdirSync, readFileSync, statSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\nimport { createIgnore } from './ignore.js';\n\n/** Skip files larger than this (generated bundles, data dumps). */\nconst MAX_FILE_BYTES = 512 * 1024;\n/** How many leading chars to scan for a NUL byte (the binary signal). */\nconst BINARY_SNIFF = 8000;\n\n/**\n * True when decoded text looks binary \u2014 a meaningful FRACTION of NUL bytes in the\n * first {@link BINARY_SNIFF} chars. A stray NUL in real source (e.g. a sentinel\n * string literal) must not exclude the file; genuine binaries are NUL-dense.\n */\nfunction looksBinary(text: string): boolean {\n const limit = Math.min(text.length, BINARY_SNIFF);\n if (limit === 0) return false;\n let nul = 0;\n for (let i = 0; i < limit; i++) {\n if (text.charCodeAt(i) === 0) nul += 1;\n }\n return nul / limit > 0.01;\n}\n\n/**\n * Decode a file buffer to text, honoring a UTF-16 / UTF-8 BOM so UTF-16-encoded\n * source (common on Windows) is NOT mistaken for binary. Returns null only for\n * genuinely binary content \u2014 a NUL byte surviving a plain UTF-8 decode.\n */\nfunction decodeText(buf: Buffer): string | null {\n let text: string;\n if (buf.length >= 2 && buf[0] === 0xff && buf[1] === 0xfe) {\n text = buf.toString('utf16le'); // UTF-16 LE\n } else if (buf.length >= 2 && buf[0] === 0xfe && buf[1] === 0xff && buf.length % 2 === 0) {\n const swapped = Buffer.from(buf); // UTF-16 BE \u2192 swap to LE\n swapped.swap16();\n text = swapped.toString('utf16le');\n } else if (buf.length >= 3 && buf[0] === 0xef && buf[1] === 0xbb && buf[2] === 0xbf) {\n text = buf.subarray(3).toString('utf8'); // UTF-8 BOM\n } else {\n text = buf.toString('utf8');\n if (looksBinary(text)) return null;\n }\n return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text; // strip a leading BOM\n}\n\nexport interface ScannedFile {\n /** Repo-relative, POSIX path. */\n path: string;\n content: string;\n}\n\n/** Walk the repo, honoring ignore rules, returning readable text files (UTF-8/UTF-16). */\nexport function scanRepo(root: string): ScannedFile[] {\n const isIgnored = createIgnore(root);\n const out: ScannedFile[] = [];\n\n const walk = (dir: string): void => {\n let entries: Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const abs = join(dir, entry.name);\n const rel = relative(root, abs).split(sep).join('/');\n if (!rel || isIgnored(rel, entry.isDirectory())) continue;\n if (entry.isDirectory()) {\n walk(abs);\n } else if (entry.isFile()) {\n try {\n if (statSync(abs).size > MAX_FILE_BYTES) continue;\n const content = decodeText(readFileSync(abs));\n if (content === null) continue; // genuinely binary\n out.push({ path: rel, content });\n } catch {\n /* unreadable \u2014 skip */\n }\n }\n }\n };\n\n walk(root);\n return out;\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/**\n * Always-skip entries: build/dep dirs, lockfiles, binaries, and \u2014 critically \u2014\n * secret-bearing files (.env*, keys, certs) so they are never read, chunked, or\n * embedded (the first line of the \u00A716 redaction defense).\n */\nconst DEFAULT_IGNORES = [\n '.git',\n 'node_modules',\n 'dist',\n 'build',\n '.next',\n '.turbo',\n 'coverage',\n '.data',\n '.cache',\n 'pnpm-lock.yaml',\n 'yarn.lock',\n 'package-lock.json',\n '*.lock',\n '.env',\n '.env.*',\n '*.pem',\n '*.key',\n '*.crt',\n '*.p12',\n '*.pfx',\n // binaries / assets\n '*.png',\n '*.jpg',\n '*.jpeg',\n '*.gif',\n '*.ico',\n '*.webp',\n '*.svg',\n '*.pdf',\n '*.zip',\n '*.gz',\n '*.tar',\n '*.wasm',\n '*.node',\n '*.dll',\n '*.exe',\n '*.woff',\n '*.woff2',\n '*.ttf',\n '*.mp4',\n '*.mp3',\n];\n\ninterface CompiledPattern {\n re: RegExp;\n /** Match against the basename (pattern has no slash) vs the full relpath. */\n matchBasename: boolean;\n /** Trailing-slash pattern: matches directories only. */\n dirOnly: boolean;\n /** Literal name (no `*`): also matched against any path segment (prune at any depth). */\n literal: boolean;\n}\n\n/** Compile one ignore pattern (a pragmatic subset of gitignore) to a matcher. */\nfunction patternToRegExp(pattern: string): CompiledPattern {\n let p = pattern.trim();\n const dirOnly = p.endsWith('/');\n if (dirOnly) p = p.slice(0, -1);\n // A leading `**/` matches zero or more leading directories (so it matches at root too).\n let prefixAnySegments = false;\n if (p.startsWith('**/')) {\n prefixAnySegments = true;\n p = p.slice(3);\n }\n const matchBasename = !p.includes('/');\n const literal = !p.includes('*');\n const body = p\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/\\*\\*/g, '.*')\n .replace(/\\*/g, '[^/]*');\n const source = prefixAnySegments ? `(?:.*/)?${body}` : body;\n return { re: new RegExp(`^${source}$`), matchBasename, dirOnly, literal };\n}\n\nexport interface IgnoreMatcher {\n (relPath: string, isDir: boolean): boolean;\n}\n\nfunction loadFile(root: string, name: string): string[] {\n const path = join(root, name);\n if (!existsSync(path)) return [];\n try {\n return (\n readFileSync(path, 'utf8')\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n // Skip blanks, comments, and negations (`!` re-includes are not supported).\n .filter((l) => l.length > 0 && !l.startsWith('#') && !l.startsWith('!'))\n );\n } catch {\n return [];\n }\n}\n\n/** Build an ignore matcher from defaults + the repo's .gitignore and .futurexignore. */\nexport function createIgnore(root: string): IgnoreMatcher {\n const patterns = [...DEFAULT_IGNORES, ...loadFile(root, '.gitignore'), ...loadFile(root, '.futurexignore')];\n const compiled = patterns.map(patternToRegExp);\n return (relPath: string, isDir: boolean): boolean => {\n const basename = relPath.split('/').pop() ?? relPath;\n for (const { re, matchBasename, dirOnly, literal } of compiled) {\n if (dirOnly && !isDir) continue; // `build/` matches directories only\n if (re.test(matchBasename ? basename : relPath)) return true;\n // Prune literal names (node_modules, dist, \u2026) at any depth; do NOT do this\n // for glob patterns like `*.png`, which would wrongly prune a dir `x.png/`.\n if (matchBasename && literal && relPath.split('/').some((seg) => re.test(seg))) return true;\n }\n return false;\n };\n}\n", "import type { Chunk } from './types.js';\n\n/**\n * Size-bounded, line-tracked chunker. Pragmatic for Phase 2 (keeps the package\n * pure-JS, no WASM grammars); the planned upgrade is symbol-aware splitting via\n * web-tree-sitter (D5) behind this same function signature.\n */\nconst MAX_CHARS = 1600;\nconst SOFT_MIN_CHARS = 600;\n\nexport function chunkFile(path: string, content: string): Chunk[] {\n const lines = content.split('\\n');\n const chunks: Chunk[] = [];\n let startLine = 1;\n let buf: string[] = [];\n let size = 0;\n\n const flush = (endLine: number): void => {\n if (buf.length === 0) return;\n const text = buf.join('\\n').trim();\n if (text.length > 0) {\n chunks.push({ id: `${path}:${startLine}-${endLine}`, path, startLine, endLine, text });\n }\n buf = [];\n size = 0;\n };\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? '';\n buf.push(line);\n size += line.length + 1;\n const lineNo = i + 1;\n const blank = line.trim().length === 0;\n // Prefer to break at a blank line once past the soft minimum; hard-break at the cap.\n if ((blank && size >= SOFT_MIN_CHARS) || size >= MAX_CHARS) {\n flush(lineNo);\n startLine = lineNo + 1;\n }\n }\n flush(lines.length);\n return chunks;\n}\n", "/**\n * Best-effort secret redaction applied to every chunk before it can leave the\n * machine (e.g. shipped to an embedding vendor or the gateway). This complements\n * \u2014 does not replace \u2014 ignoring secret-bearing files entirely (see ignore.ts).\n * A real deployment should additionally run a gitleaks/trufflehog ruleset.\n */\nconst SECRET_PATTERNS: ReadonlyArray<RegExp> = [\n /AKIA[0-9A-Z]{16}/g, // AWS access key id\n /\\bsk-[A-Za-z0-9]{20,}\\b/g, // OpenAI-style secret keys\n /\\bgh[pousr]_[A-Za-z0-9]{20,}\\b/g, // GitHub tokens\n /-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----[\\s\\S]*?-----END (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/g,\n /\\beyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\b/g, // JWT\n /\\b(?:postgres(?:ql)?|mysql|mongodb(?:\\+srv)?|redis|amqps?):\\/\\/[^\\s'\"]*:[^\\s'\"@/]+@[^\\s'\"]+/gi, // conn string with inline creds\n /\\b(?:password|passwd|secret|api[_-]?key|access[_-]?key|auth[_-]?token)\\b\\s*[:=]\\s*['\"][^'\"\\n]{6,}['\"]/gi, // assigned literal secrets\n];\n\nconst PLACEHOLDER = '\u00ABredacted-secret\u00BB';\n\nexport function redactSecrets(text: string): { text: string; redacted: number } {\n let redacted = 0;\n let out = text;\n for (const re of SECRET_PATTERNS) {\n out = out.replace(re, () => {\n redacted += 1;\n return PLACEHOLDER;\n });\n }\n return { text: out, redacted };\n}\n", "/**\n * Symbol extractor backed by the TypeScript compiler API \u2014 a proper AST, not\n * regex (Blueprint v2 \u00A73.5). Handles .ts/.tsx/.mts/.cts and .js/.jsx/.mjs/.cjs.\n * `typescript` is already a workspace dependency, so this adds no new runtime\n * weight beyond what the repo already ships; other languages get their own\n * extractor (web-tree-sitter, D5) behind {@link SymbolExtractor}.\n */\nimport * as ts from 'typescript';\nimport type { SymbolDef, SymbolExtractor, SymbolKind } from './symbols.js';\n\nconst TS_EXTENSIONS = ['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs'] as const;\n\nfunction scriptKindFor(path: string): ts.ScriptKind {\n if (path.endsWith('.tsx')) return ts.ScriptKind.TSX;\n if (path.endsWith('.jsx')) return ts.ScriptKind.JSX;\n if (path.endsWith('.js') || path.endsWith('.mjs') || path.endsWith('.cjs')) return ts.ScriptKind.JS;\n return ts.ScriptKind.TS;\n}\n\n/** Flatten an identifier or a destructuring pattern into its bound names. */\nfunction bindingNames(name: ts.BindingName): string[] {\n const out: string[] = [];\n const walk = (n: ts.BindingName): void => {\n if (ts.isIdentifier(n)) {\n out.push(n.text);\n return;\n }\n for (const el of n.elements) {\n if (ts.isOmittedExpression(el)) continue;\n walk(el.name);\n }\n };\n walk(name);\n return out;\n}\n\nexport class TypeScriptSymbolExtractor implements SymbolExtractor {\n supports(path: string): boolean {\n return TS_EXTENSIONS.some((ext) => path.endsWith(ext));\n }\n\n extract(path: string, content: string): SymbolDef[] {\n const sf = ts.createSourceFile(\n path,\n content,\n ts.ScriptTarget.Latest,\n /* setParentNodes */ true,\n scriptKindFor(path),\n );\n const out: SymbolDef[] = [];\n // Local names exported via a bare `export { x }` statement (no `from`), so a\n // post-pass can flip their declaration's `exported` flag to true.\n const exportedLocals = new Set<string>();\n const lineOf = (pos: number): number => sf.getLineAndCharacterOfPosition(pos).line + 1;\n\n const push = (\n name: string,\n kind: SymbolKind,\n node: ts.Node,\n exported: boolean,\n signature: string,\n container?: string,\n ): void => {\n out.push({\n name,\n kind,\n signature: signature.replace(/\\s+/g, ' ').trim().slice(0, 200),\n file: path,\n startLine: lineOf(node.getStart(sf)),\n endLine: lineOf(node.getEnd()),\n exported,\n ...(container ? { container } : {}),\n });\n };\n\n const isExported = (node: ts.Node): boolean => {\n const mods = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;\n return (\n mods?.some(\n (m) =>\n m.kind === ts.SyntaxKind.ExportKeyword || m.kind === ts.SyntaxKind.DefaultKeyword,\n ) ?? false\n );\n };\n\n const params = (ps: ts.NodeArray<ts.ParameterDeclaration>): string =>\n `(${ps.map((p) => p.getText(sf)).join(', ')})`;\n\n const visit = (node: ts.Node, container?: string): void => {\n // `export { a, b }` / `export { orig as alias }` / `export { x } from './y'`.\n if (ts.isExportDeclaration(node)) {\n const clause = node.exportClause;\n if (clause && ts.isNamedExports(clause)) {\n for (const spec of clause.elements) {\n if (!ts.isIdentifier(spec.name)) continue;\n if (node.moduleSpecifier) {\n // Re-export from another module \u2192 a new alias surfaced here.\n push(spec.name.text, 'variable', spec, true, spec.name.text, container);\n } else {\n // Bare re-export \u2192 the LOCAL declaration is the exported one.\n const local =\n spec.propertyName && ts.isIdentifier(spec.propertyName)\n ? spec.propertyName.text\n : spec.name.text;\n exportedLocals.add(local);\n }\n }\n }\n return;\n }\n if (ts.isFunctionDeclaration(node) && node.name) {\n const ret = node.type ? `: ${node.type.getText(sf)}` : '';\n push(node.name.text, 'function', node, isExported(node), `${node.name.text}${params(node.parameters)}${ret}`, container);\n return;\n }\n if (ts.isClassDeclaration(node) && node.name) {\n const className = node.name.text;\n push(className, 'class', node, isExported(node), `class ${className}`, container);\n node.members.forEach((m) => visit(m, className));\n return;\n }\n if (ts.isInterfaceDeclaration(node)) {\n push(node.name.text, 'interface', node, isExported(node), `interface ${node.name.text}`, container);\n return;\n }\n if (ts.isTypeAliasDeclaration(node)) {\n push(node.name.text, 'type', node, isExported(node), `type ${node.name.text}`, container);\n return;\n }\n if (ts.isEnumDeclaration(node)) {\n const enumName = node.name.text;\n const exported = isExported(node);\n push(enumName, 'enum', node, exported, `enum ${enumName}`, container);\n for (const m of node.members) {\n if (ts.isIdentifier(m.name)) {\n push(m.name.text, 'property', m, exported, `${enumName}.${m.name.text}`, enumName);\n }\n }\n return;\n }\n if (ts.isModuleDeclaration(node) && ts.isIdentifier(node.name)) {\n const nsName = node.name.text;\n push(nsName, 'namespace', node, isExported(node), `namespace ${nsName}`, container);\n if (node.body && ts.isModuleBlock(node.body)) {\n node.body.statements.forEach((s) => visit(s, nsName));\n }\n return;\n }\n if (ts.isVariableStatement(node)) {\n const exported = isExported(node);\n for (const decl of node.declarationList.declarations) {\n if (ts.isIdentifier(decl.name)) {\n const init = decl.initializer;\n if (init && (ts.isArrowFunction(init) || ts.isFunctionExpression(init))) {\n const ret = init.type\n ? `: ${init.type.getText(sf)}`\n : decl.type\n ? `: ${decl.type.getText(sf)}`\n : '';\n push(decl.name.text, 'function', decl, exported, `${decl.name.text}${params(init.parameters)}${ret}`, container);\n } else {\n const typeSig = decl.type ? `: ${decl.type.getText(sf)}` : '';\n push(decl.name.text, 'variable', decl, exported, `${decl.name.text}${typeSig}`, container);\n }\n } else {\n // Destructuring: `const { a, b } = ...` / `const [x, y] = ...`.\n for (const bound of bindingNames(decl.name)) {\n push(bound, 'variable', decl, exported, bound, container);\n }\n }\n }\n return;\n }\n if (container && ts.isMethodDeclaration(node) && ts.isIdentifier(node.name)) {\n const ret = node.type ? `: ${node.type.getText(sf)}` : '';\n push(node.name.text, 'method', node, false, `${node.name.text}${params(node.parameters)}${ret}`, container);\n return;\n }\n if (container && (ts.isGetAccessor(node) || ts.isSetAccessor(node)) && ts.isIdentifier(node.name)) {\n const kw = ts.isGetAccessor(node) ? 'get' : 'set';\n const ret = node.type ? `: ${node.type.getText(sf)}` : '';\n push(node.name.text, 'method', node, false, `${kw} ${node.name.text}${params(node.parameters)}${ret}`, container);\n return;\n }\n if (container && ts.isPropertyDeclaration(node) && ts.isIdentifier(node.name)) {\n const typeSig = node.type ? `: ${node.type.getText(sf)}` : '';\n push(node.name.text, 'property', node, false, `${node.name.text}${typeSig}`, container);\n return;\n }\n // Unhandled node: descend (reaches top-level stmts, block bodies, etc.).\n ts.forEachChild(node, (c) => visit(c, container));\n };\n\n visit(sf);\n\n // A declaration named in a bare `export { x }` is exported even though its own\n // modifiers don't say so.\n if (exportedLocals.size === 0) return out;\n return out.map((d) =>\n !d.exported && exportedLocals.has(d.name) ? { ...d, exported: true } : d,\n );\n }\n}\n", "/**\n * The symbol table + its definition lookup (Blueprint v2 \u00A73.5). Answers \"is this\n * symbol already defined?\" from an AST index, never regex. Indexed by name AND by\n * file, so a single file's symbols can be replaced incrementally on a write.\n */\nimport { redactSecrets } from './redact.js';\nimport type { ScannedFile } from './scan.js';\nimport type { SymbolDef, SymbolExtractor, SymbolKind } from './symbols.js';\nimport { TypeScriptSymbolExtractor } from './ts-symbols.js';\n\n/** Registered extractors, tried in order (first whose `supports()` matches wins). */\nexport const DEFAULT_EXTRACTORS: readonly SymbolExtractor[] = [new TypeScriptSymbolExtractor()];\n\n/** Extract symbols from one file with the registered extractors (no parser \u2192 []). */\nexport function extractSymbols(\n path: string,\n content: string,\n extractors: readonly SymbolExtractor[] = DEFAULT_EXTRACTORS,\n): SymbolDef[] {\n const ex = extractors.find((e) => e.supports(path));\n if (!ex) return [];\n try {\n // Redact secrets that could ride along in a default-parameter value or typed\n // initializer captured by the signature (the extractor reads raw source).\n return ex.extract(path, content).map((d) =>\n d.signature ? { ...d, signature: redactSecrets(d.signature).text } : d,\n );\n } catch {\n return []; // a parse error must never abort indexing\n }\n}\n\n/** Extract symbols across many files. */\nexport function extractSymbolsFromFiles(\n files: readonly ScannedFile[],\n extractors: readonly SymbolExtractor[] = DEFAULT_EXTRACTORS,\n): SymbolDef[] {\n const out: SymbolDef[] = [];\n for (const f of files) out.push(...extractSymbols(f.path, f.content, extractors));\n return out;\n}\n\nexport interface SymbolStats {\n readonly files: number;\n readonly symbols: number;\n}\n\nexport class SymbolIndex {\n private readonly byName = new Map<string, SymbolDef[]>();\n private readonly byFile = new Map<string, SymbolDef[]>();\n\n /** Replace all symbols for `file` (incremental update on a write). */\n setFile(file: string, defs: readonly SymbolDef[]): void {\n this.removeFile(file);\n if (defs.length === 0) return;\n const copy = [...defs];\n this.byFile.set(file, copy);\n for (const d of copy) {\n const arr = this.byName.get(d.name);\n if (arr) arr.push(d);\n else this.byName.set(d.name, [d]);\n }\n }\n\n /** Drop all symbols for `file`. */\n removeFile(file: string): void {\n const existing = this.byFile.get(file);\n if (!existing) return;\n this.byFile.delete(file);\n for (const d of existing) {\n const arr = this.byName.get(d.name);\n if (!arr) continue;\n const left = arr.filter((x) => x.file !== file);\n if (left.length > 0) this.byName.set(d.name, left);\n else this.byName.delete(d.name);\n }\n }\n\n /** Is a symbol with this name (optionally of this kind) already defined? */\n isDefined(name: string, kind?: SymbolKind): boolean {\n const defs = this.byName.get(name);\n if (!defs || defs.length === 0) return false;\n return kind ? defs.some((d) => d.kind === kind) : true;\n }\n\n /** Every exact-match definition of `name`, across files. */\n lookup(name: string): SymbolDef[] {\n return this.byName.get(name)?.slice() ?? [];\n }\n\n /** Fuzzy substring match (case-insensitive), capped at `limit`. */\n search(query: string, limit = 25): SymbolDef[] {\n const q = query.toLowerCase();\n const hits: SymbolDef[] = [];\n for (const defs of this.byFile.values()) {\n for (const d of defs) {\n if (d.name.toLowerCase().includes(q)) {\n hits.push(d);\n if (hits.length >= limit) return hits;\n }\n }\n }\n return hits;\n }\n\n all(): SymbolDef[] {\n const out: SymbolDef[] = [];\n for (const defs of this.byFile.values()) out.push(...defs);\n return out;\n }\n\n stats(): SymbolStats {\n return { files: this.byFile.size, symbols: this.all().length };\n }\n\n /** Flat serialization (persisted alongside the vector index). */\n toJSON(): SymbolDef[] {\n return this.all();\n }\n\n /** Rebuild from a flat serialization. */\n static fromJSON(defs: readonly SymbolDef[]): SymbolIndex {\n const idx = new SymbolIndex();\n const byFile = new Map<string, SymbolDef[]>();\n for (const d of defs) {\n const arr = byFile.get(d.file);\n if (arr) arr.push(d);\n else byFile.set(d.file, [d]);\n }\n for (const [file, fileDefs] of byFile) idx.setFile(file, fileDefs);\n return idx;\n }\n}\n", "/**\n * Import graph (advanced code understanding). Parses each file's imports via the\n * TypeScript compiler API, resolves relative specifiers against the indexed repo\n * (extension + `/index` probing), and classifies each as `internal` (resolved to a\n * repo file), `external` (a bare package), or `unresolved` (a relative import that\n * points at no existing file \u2014 i.e. a BROKEN import). Persisted with the index so\n * retrieval/agents can pull a file's dependencies and surface broken links.\n */\nimport * as ts from 'typescript';\nimport type { ScannedFile } from './scan.js';\n\nconst TS_LIKE = ['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs'];\nconst RESOLVE_EXTS = ['', '.ts', '.tsx', '.d.ts', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs', '.json'];\nconst INDEX_FILES = ['index.ts', 'index.tsx', 'index.mts', 'index.cts', 'index.js', 'index.jsx'];\n// TS/ESM lets a relative import carry a `.js`-family extension that resolves to the\n// `.ts` source on disk (`import './x.js'` \u2192 `x.ts`). Map those so they aren't false broken.\nconst JS_TO_TS: Record<string, string[]> = {\n '.js': ['.ts', '.tsx', '.d.ts'],\n '.jsx': ['.tsx'],\n '.mjs': ['.mts'],\n '.cjs': ['.cts'],\n};\n\nexport type ImportKind = 'internal' | 'external' | 'unresolved';\n\nexport interface ImportRef {\n readonly specifier: string;\n /** Repo-relative POSIX path when resolved to an indexed file, else null. */\n readonly resolved: string | null;\n readonly kind: ImportKind;\n}\n\nexport interface FileImports {\n readonly file: string;\n readonly imports: readonly ImportRef[];\n}\n\nfunction isTsLike(path: string): boolean {\n return TS_LIKE.some((e) => path.endsWith(e));\n}\n\nfunction scriptKind(path: string): ts.ScriptKind {\n if (path.endsWith('.tsx')) return ts.ScriptKind.TSX;\n if (path.endsWith('.jsx')) return ts.ScriptKind.JSX;\n if (/\\.(?:js|mjs|cjs)$/.test(path)) return ts.ScriptKind.JS;\n return ts.ScriptKind.TS;\n}\n\n/** Module specifiers imported by a file (static import/export-from + dynamic import + require). */\nexport function extractImportSpecifiers(path: string, content: string): string[] {\n const sf = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, false, scriptKind(path));\n const out: string[] = [];\n const visit = (node: ts.Node): void => {\n if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {\n out.push(node.moduleSpecifier.text);\n } else if (\n ts.isExportDeclaration(node) &&\n node.moduleSpecifier &&\n ts.isStringLiteral(node.moduleSpecifier)\n ) {\n out.push(node.moduleSpecifier.text);\n } else if (ts.isCallExpression(node)) {\n const isRequire = ts.isIdentifier(node.expression) && node.expression.text === 'require';\n const isDynamic = node.expression.kind === ts.SyntaxKind.ImportKeyword;\n const arg = node.arguments[0];\n if ((isRequire || isDynamic) && arg && ts.isStringLiteral(arg)) out.push(arg.text);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n return out;\n}\n\nfunction posixDirname(p: string): string {\n const i = p.lastIndexOf('/');\n return i === -1 ? '' : p.slice(0, i);\n}\n\n/** Resolve `rel` against `baseDir` (both repo-relative POSIX), normalizing ./ and ../ */\nfunction posixResolve(baseDir: string, rel: string): string {\n const stack: string[] = [];\n for (const part of `${baseDir}/${rel}`.split('/')) {\n if (part === '' || part === '.') continue;\n if (part === '..') stack.pop();\n else stack.push(part);\n }\n return stack.join('/');\n}\n\n/** Resolve a relative specifier to an indexed repo file, or null when broken. */\nfunction resolveRelative(fromFile: string, spec: string, fileSet: ReadonlySet<string>): string | null {\n const target = posixResolve(posixDirname(fromFile), spec);\n // 1. Exact path (the specifier already names an existing file).\n if (fileSet.has(target)) return target;\n // 2. A `.js`-family extension that maps to TS source on disk.\n const jsExt = Object.keys(JS_TO_TS).find((e) => target.endsWith(e));\n if (jsExt) {\n const base = target.slice(0, -jsExt.length);\n for (const tsExt of JS_TO_TS[jsExt] ?? []) {\n if (fileSet.has(`${base}${tsExt}`)) return `${base}${tsExt}`;\n }\n }\n // 3. Extensionless specifier \u2014 probe known extensions.\n for (const ext of RESOLVE_EXTS) {\n if (ext && fileSet.has(`${target}${ext}`)) return `${target}${ext}`;\n }\n // 4. Directory import \u2014 probe `<dir>/index.*`.\n for (const idx of INDEX_FILES) {\n const cand = target ? `${target}/${idx}` : idx;\n if (fileSet.has(cand)) return cand;\n }\n return null;\n}\n\n/** Build the per-file import list for the whole repo. */\nexport function buildImportGraph(files: readonly ScannedFile[]): FileImports[] {\n const fileSet = new Set(files.map((f) => f.path));\n const out: FileImports[] = [];\n for (const f of files) {\n if (!isTsLike(f.path)) continue;\n let specs: string[];\n try {\n specs = extractImportSpecifiers(f.path, f.content);\n } catch {\n continue; // never let a parse error abort indexing\n }\n if (specs.length === 0) continue;\n const imports: ImportRef[] = specs.map((specifier) => {\n if (specifier.startsWith('.')) {\n const resolved = resolveRelative(f.path, specifier, fileSet);\n return { specifier, resolved, kind: resolved ? 'internal' : 'unresolved' };\n }\n return { specifier, resolved: null, kind: 'external' };\n });\n out.push({ file: f.path, imports });\n }\n return out;\n}\n\nexport interface ImportStats {\n readonly files: number;\n readonly edges: number;\n readonly internal: number;\n readonly external: number;\n readonly broken: number;\n}\n\nexport interface BrokenImport {\n readonly file: string;\n readonly specifier: string;\n}\n\n/** Queryable import graph: forward + reverse edges + broken-link detection. */\nexport class ImportGraph {\n private readonly byFile = new Map<string, ImportRef[]>();\n private readonly importers = new Map<string, Set<string>>();\n\n static fromJSON(data: readonly FileImports[]): ImportGraph {\n const g = new ImportGraph();\n for (const fi of data) {\n g.byFile.set(fi.file, [...fi.imports]);\n for (const imp of fi.imports) {\n if (imp.resolved) {\n const set = g.importers.get(imp.resolved) ?? new Set<string>();\n set.add(fi.file);\n g.importers.set(imp.resolved, set);\n }\n }\n }\n return g;\n }\n\n /** What `file` imports. */\n importsOf(file: string): ImportRef[] {\n return this.byFile.get(file)?.slice() ?? [];\n }\n\n /** Repo files that import `file` (reverse deps). */\n importersOf(file: string): string[] {\n return [...(this.importers.get(file) ?? [])];\n }\n\n /** Resolved internal files `file` depends on (1 hop). */\n dependenciesOf(file: string): string[] {\n return this.importsOf(file)\n .map((i) => i.resolved)\n .filter((r): r is string => r !== null);\n }\n\n /** Files that have at least one recorded import. */\n files(): string[] {\n return [...this.byFile.keys()];\n }\n\n /** Unresolved relative imports across the repo (broken links). */\n broken(): BrokenImport[] {\n const out: BrokenImport[] = [];\n for (const [file, imps] of this.byFile) {\n for (const imp of imps) {\n if (imp.kind === 'unresolved') out.push({ file, specifier: imp.specifier });\n }\n }\n return out;\n }\n\n stats(): ImportStats {\n let edges = 0;\n let internal = 0;\n let external = 0;\n let broken = 0;\n for (const imps of this.byFile.values()) {\n for (const imp of imps) {\n edges++;\n if (imp.kind === 'internal') internal++;\n else if (imp.kind === 'external') external++;\n else broken++;\n }\n }\n return { files: this.byFile.size, edges, internal, external, broken };\n }\n}\n", "import type { Embedder, VectorStore } from '@fim/futurex-vector';\nimport { scanRepo } from './scan.js';\nimport { chunkFile } from './chunk.js';\nimport { redactSecrets } from './redact.js';\nimport { extractSymbols } from './symbol-index.js';\nimport { buildImportGraph } from './imports.js';\nimport type { FileImports } from './imports.js';\nimport type { SymbolDef } from './symbols.js';\nimport type { Chunk, IndexStats } from './types.js';\n\nconst EMBED_BATCH = 64;\n\n/** What {@link buildIndex} produces: the stats plus the extracted symbol defs (to persist). */\nexport interface IndexResult {\n readonly stats: IndexStats;\n readonly symbols: SymbolDef[];\n readonly imports: FileImports[];\n}\n\n/** Scan \u2192 chunk \u2192 redact \u2192 embed \u2192 upsert, and extract an AST symbol index. The\n * chunk text fed to the embedder is prefixed with the path so retrieval can key\n * on filenames too. */\nexport async function buildIndex(\n root: string,\n embedder: Embedder,\n store: VectorStore<Chunk>,\n): Promise<IndexResult> {\n const files = scanRepo(root);\n const chunks: Chunk[] = [];\n const symbols: SymbolDef[] = [];\n let redacted = 0;\n\n for (const file of files) {\n for (const chunk of chunkFile(file.path, file.content)) {\n const r = redactSecrets(chunk.text);\n redacted += r.redacted;\n chunks.push(r.redacted > 0 ? { ...chunk, text: r.text } : chunk);\n }\n // AST symbols from the raw source. Signatures are declaration headers (names +\n // types), never initializer values, so redaction is unnecessary here.\n symbols.push(...extractSymbols(file.path, file.content));\n }\n\n await store.clear();\n for (let i = 0; i < chunks.length; i += EMBED_BATCH) {\n const batch = chunks.slice(i, i + EMBED_BATCH);\n const vectors = await embedder.embed(batch.map((c) => `${c.path}\\n${c.text}`));\n await store.upsert(batch.map((c, j) => ({ id: c.id, vector: vectors[j] ?? [], payload: c })));\n }\n\n // Import graph: resolve each file's imports against the indexed set + flag broken links.\n const imports = buildImportGraph(files);\n let edges = 0;\n let broken = 0;\n for (const fi of imports) {\n for (const imp of fi.imports) {\n edges += 1;\n if (imp.kind === 'unresolved') broken += 1;\n }\n }\n\n return {\n stats: {\n files: files.length,\n chunks: chunks.length,\n redacted,\n symbols: symbols.length,\n imports: edges,\n brokenImports: broken,\n },\n symbols,\n imports,\n };\n}\n", "import type { Embedder, ScoredRecord, VectorStore } from '@fim/futurex-vector';\nimport type { Chunk } from './types.js';\n\n/** Embed the query and return the top-K most similar chunks. */\nexport async function retrieve(\n store: VectorStore<Chunk>,\n embedder: Embedder,\n query: string,\n topK: number,\n): Promise<ScoredRecord<Chunk>[]> {\n if (topK <= 0 || (await store.size()) === 0) return [];\n const vectors = await embedder.embed([query]);\n const vec = vectors[0];\n if (!vec) return [];\n return store.query(vec, topK);\n}\n", "import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { VectorRecord } from '@fim/futurex-vector';\nimport type { FileImports } from './imports.js';\nimport type { SymbolDef } from './symbols.js';\nimport type { Chunk } from './types.js';\n\n// v2 added the AST symbol table; v3 added the import graph. An older index fails to\n// load \u2192 forces a clean rebuild rather than silently running without them.\nconst VERSION = 3;\n\nexport interface PersistedIndex {\n version: number;\n /** Embedder id the records were built with \u2014 retrieval MUST use a matching embedder. */\n embedderId: string;\n dimensions: number;\n root: string;\n createdAt: string;\n records: VectorRecord<Chunk>[];\n /** AST symbol table (\u00A73.5). */\n symbols: SymbolDef[];\n /** Import graph (advanced code understanding). */\n imports: FileImports[];\n}\n\nexport function saveIndex(path: string, data: Omit<PersistedIndex, 'version'>): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify({ version: VERSION, ...data }), { mode: 0o600 });\n}\n\nexport function loadIndex(path: string): PersistedIndex | null {\n if (!existsSync(path)) return null;\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf8')) as PersistedIndex;\n return parsed.version === VERSION ? parsed : null;\n } catch {\n return null;\n }\n}\n", "/**\n * The completion marker + its streaming filter \u2014 a leaf module (no internal\n * imports) so both the render path and the completion engine can use it\n * without an import cycle.\n *\n * The model is instructed (system-prompt.ts AGENT_PROTOCOL) to end its FINAL\n * answer with {@link DONE_MARKER}; the filter strips it from everything the\n * user sees while recording that it appeared, which is the signal finish.ts's\n * completion policy keys on.\n */\n\n/**\n * Completion marker the model must end its FINAL answer with (ASCII-only \u2014 see\n * the PS5.1 UTF-8 round-trip caveat). Stripped from display by the filter.\n */\nexport const DONE_MARKER = '[[FX:DONE]]';\n\n/**\n * Strips {@link DONE_MARKER} out of a token stream without ever flushing a\n * partial marker (the marker can arrive split across chunks). `push` returns\n * the displayable text for each delta; call `flush` once at stream end.\n */\nexport interface DoneFilter {\n push(delta: string): string;\n flush(): string;\n readonly sawMarker: boolean;\n}\n\n/** Longest suffix of `s` that is a (proper) prefix of the marker. */\nfunction markerPrefixSuffix(s: string): number {\n const max = Math.min(s.length, DONE_MARKER.length - 1);\n for (let len = max; len > 0; len--) {\n if (s.endsWith(DONE_MARKER.slice(0, len))) return len;\n }\n return 0;\n}\n\nexport function createDoneFilter(): DoneFilter {\n let tail = '';\n let saw = false;\n return {\n get sawMarker(): boolean {\n return saw;\n },\n push(delta: string): string {\n let buf = tail + delta;\n let idx = buf.indexOf(DONE_MARKER);\n while (idx !== -1) {\n saw = true;\n buf = buf.slice(0, idx) + buf.slice(idx + DONE_MARKER.length);\n idx = buf.indexOf(DONE_MARKER);\n }\n const hold = markerPrefixSuffix(buf);\n tail = hold > 0 ? buf.slice(buf.length - hold) : '';\n return hold > 0 ? buf.slice(0, buf.length - hold) : buf;\n },\n flush(): string {\n const rest = tail;\n tail = '';\n return rest;\n },\n };\n}\n", "/**\n * DeepSeek price table + cost model (Blueprint v2 \u00A73.4 / P10). Prices are a\n * snapshot (USD per 1M tokens) \u2014 re-verify V4-Pro on the live dashboard before\n * billing (the disputed promo rate was 0.435 / 0.003625 / 0.87). Cost is\n * cache-aware: the cached portion of input bills at a fraction of cache-miss.\n */\nimport type { UsageReport } from '@fim/futurex-protocol';\n\nexport interface ModelPrice {\n readonly inputPerM: number;\n readonly cachedInputPerM: number;\n readonly outputPerM: number;\n}\n\nconst FLASH: ModelPrice = { inputPerM: 0.14, cachedInputPerM: 0.014, outputPerM: 0.28 };\nconst PRO: ModelPrice = { inputPerM: 1.74, cachedInputPerM: 0.0145, outputPerM: 3.48 };\n\nexport const PRICES: Readonly<Record<string, ModelPrice>> = {\n 'deepseek-v4-flash': FLASH,\n 'deepseek-v4-pro': PRO,\n};\n\nexport function priceFor(model: string): ModelPrice {\n return PRICES[model] ?? FLASH;\n}\n\n/** USD cost of one call, given its usage. */\nexport function computeCost(model: string, usage: UsageReport): number {\n const p = priceFor(model);\n const cachedIn = usage.cacheHitTokens ?? 0;\n const uncachedIn = Math.max(0, usage.inputTokens - cachedIn);\n return (\n (uncachedIn * p.inputPerM + cachedIn * p.cachedInputPerM + usage.outputTokens * p.outputPerM) /\n 1_000_000\n );\n}\n\n/** Running per-session usage totals. */\nexport interface UsageTotals {\n calls: number;\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n costUsd: number;\n}\n\nexport function emptyTotals(): UsageTotals {\n return { calls: 0, inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, reasoningTokens: 0, costUsd: 0 };\n}\n\n/**\n * Sum two usage reports field-by-field. An agentic turn is MANY model calls\n * (one per tool round); budget/billing must see the whole turn, not the last call.\n */\nexport function accumulateUsage(a: UsageReport, b: UsageReport): UsageReport {\n const opt = (x?: number, y?: number): number | undefined =>\n x === undefined && y === undefined ? undefined : (x ?? 0) + (y ?? 0);\n const cacheHitTokens = opt(a.cacheHitTokens, b.cacheHitTokens);\n const cacheMissTokens = opt(a.cacheMissTokens, b.cacheMissTokens);\n const reasoningTokens = opt(a.reasoningTokens, b.reasoningTokens);\n return {\n inputTokens: a.inputTokens + b.inputTokens,\n outputTokens: a.outputTokens + b.outputTokens,\n totalTokens: a.totalTokens + b.totalTokens,\n ...(cacheHitTokens !== undefined ? { cacheHitTokens } : {}),\n ...(cacheMissTokens !== undefined ? { cacheMissTokens } : {}),\n ...(reasoningTokens !== undefined ? { reasoningTokens } : {}),\n };\n}\n\n/** Fold one call's usage into the running totals. */\nexport function addUsage(totals: UsageTotals, model: string, usage: UsageReport): void {\n totals.calls += 1;\n totals.inputTokens += usage.inputTokens;\n totals.cachedInputTokens += usage.cacheHitTokens ?? 0;\n totals.outputTokens += usage.outputTokens;\n totals.reasoningTokens += usage.reasoningTokens ?? 0;\n totals.costUsd += computeCost(model, usage);\n}\n\n/** A compact, multi-field rendering of the totals (cache-hit ratio + cost). */\nexport function formatUsage(totals: UsageTotals): string[] {\n const ratio = totals.inputTokens > 0 ? Math.round((totals.cachedInputTokens / totals.inputTokens) * 100) : 0;\n return [\n `calls ${totals.calls}`,\n `in ${totals.inputTokens} (${ratio}% cached)`,\n `out ${totals.outputTokens}${totals.reasoningTokens ? ` (+${totals.reasoningTokens} reasoning)` : ''}`,\n `cost $${totals.costUsd.toFixed(4)}`,\n ];\n}\n", "import type { ChatTurn, FutureXClient, UsageReport } from '@fim/futurex-protocol';\nimport { createDoneFilter } from './marker.js';\nimport { accumulateUsage } from './pricing.js';\nimport { errColor, eout, formatCount, out } from './ui.js';\n\n/** Outcome of consuming one response stream. */\nexport interface RenderResult {\n /** The visible answer text (marker stripped \u2014 safe for history + display). */\n text: string;\n usage?: UsageReport;\n finishReason?: string;\n /** The completion marker appeared in this stream (the model declared done). */\n sawMarker?: boolean;\n /** Set if the stream ended in an error. */\n error?: string;\n}\n\n/**\n * Consume a {@link FutureXClient} stream and render it: the dim \"thinking\" lane\n * goes to STDERR (so `... > file` captures only the answer), the answer goes to\n * STDOUT. The completion marker ([[FX:DONE]]) is stripped from both the display\n * and the collected text \u2014 `sawMarker` reports it so the completion policy can\n * tell \"finished\" from \"stopped\". The one render path shared by `ask` and the\n * REPL.\n */\nexport async function renderStream(\n client: FutureXClient,\n turn: ChatTurn,\n opts: { showReasoning?: boolean } = {},\n): Promise<RenderResult> {\n const showReasoning = opts.showReasoning ?? true;\n let text = '';\n let usage: UsageReport | undefined;\n let finishReason: string | undefined;\n let inThought = false;\n let wroteAnswer = false;\n const filter = createDoneFilter();\n\n const closeLanes = (): void => {\n const rest = filter.flush();\n if (rest) {\n out(rest);\n text += rest;\n wroteAnswer = true;\n }\n if (inThought) {\n eout('\\n');\n inThought = false;\n }\n if (wroteAnswer) out('\\n');\n };\n\n for await (const ev of client.chat(turn)) {\n switch (ev.t) {\n case 'thought':\n if (showReasoning) {\n if (!inThought) {\n eout(errColor.dim('thinking \u00B7 '));\n inThought = true;\n }\n eout(errColor.dim(ev.text));\n }\n break;\n case 'token': {\n if (inThought) {\n eout('\\n');\n inThought = false;\n }\n const visible = filter.push(ev.text);\n if (visible) {\n out(visible);\n text += visible;\n wroteAnswer = true;\n }\n break;\n }\n case 'usage':\n // The gateway loop emits one usage frame per model call (one per tool\n // round) \u2014 accumulate so budgets/billing see the whole turn.\n usage = usage ? accumulateUsage(usage, ev.usage) : ev.usage;\n break;\n case 'done':\n finishReason = ev.finishReason;\n break;\n case 'error':\n closeLanes();\n return { text, usage, sawMarker: filter.sawMarker, error: ev.message };\n case 'status':\n break;\n }\n }\n\n closeLanes();\n return { text, usage, finishReason, sawMarker: filter.sawMarker };\n}\n\n/** A compact one-line usage summary for stderr (with cache-hit ratio when known). */\nexport function usageLine(usage: UsageReport, model: string): string {\n let line = `${model} \u00B7 ${formatCount(usage.inputTokens)}\u2192${formatCount(usage.outputTokens)} tok`;\n if (usage.reasoningTokens !== undefined && usage.reasoningTokens > 0) {\n line += ` (${formatCount(usage.reasoningTokens)} reasoning)`;\n }\n const hit = usage.cacheHitTokens;\n const miss = usage.cacheMissTokens;\n if (hit !== undefined && miss !== undefined && hit + miss > 0) {\n const pct = Math.round((hit / (hit + miss)) * 100);\n line += ` \u00B7 cache ${pct}%`;\n }\n return line;\n}\n", "import type { ChatTurn, Message } from '@fim/futurex-protocol';\nimport { createClient } from './client/factory.js';\nimport { augmentMessages } from './augment.js';\nimport { loadContext } from './context.js';\nimport { renderStream, usageLine } from './render.js';\nimport type { CliOptions } from './options.js';\nimport { error, info } from './ui.js';\n\n/** One-shot: stream a single answer to a prompt, then exit. Ctrl+C cancels cleanly. */\nexport async function runAsk(promptText: string, opts: CliOptions): Promise<void> {\n const q = promptText.trim();\n if (!q) {\n error('usage: futurex ask \"your question\"');\n process.exitCode = 1;\n return;\n }\n\n const { client, mode } = createClient({ useRepo: opts.useRepo, useMemory: opts.useMemory });\n const ac = new AbortController();\n const onSigint = (): void => ac.abort();\n process.on('SIGINT', onSigint);\n\n try {\n const base: Message[] = [{ role: 'user', content: q }];\n // Gateway path: the backend OWNS the prefix + gathers context agentically via\n // tools, so we send only the conversation. Local fallback: build the prefix +\n // pre-inject retrieved chunks here (the CLI is the AI in that mode).\n let messages: Message[] = base;\n let system: string | undefined;\n if (mode === 'local') {\n const ctx = loadContext(opts);\n messages = await augmentMessages(base, ctx.retriever, opts.topK);\n system = ctx.system;\n }\n const turn: ChatTurn = {\n ...(system ? { system } : {}),\n messages,\n reasoning: opts.reasoning,\n model: opts.model,\n maxTokens: opts.maxTokens,\n ...(opts.tier ? { tier: opts.tier } : {}),\n ...(opts.effort ? { effort: opts.effort } : {}),\n signal: ac.signal,\n };\n\n const result = await renderStream(client, turn);\n if (result.error) {\n if (ac.signal.aborted) info('cancelled');\n else {\n error(result.error);\n process.exitCode = 1;\n }\n return;\n }\n if (result.usage) info(usageLine(result.usage, opts.tier ?? 'fx-fast'));\n } finally {\n process.removeListener('SIGINT', onSigint);\n }\n}\n", "import { createInterface } from 'node:readline';\nimport type { AiUsage } from '@fim/ai-sdk';\nimport { normalizeTier, resolveTier, TIER_IDS } from '@fim/futurex-protocol';\nimport type { Tier } from '@fim/futurex-protocol';\nimport { type ReplAgent } from './agent.js';\nimport { createReplRuntime } from './repl-runtime.js';\nimport { Chatbox, createChatboxAsk, type Suggestion } from './chatbox.js';\nimport { createPermissionGate, type AskFn } from './permissions.js';\nimport { runPermissions } from './permissions-command.js';\nimport { currentPrefixDigest, loadContext } from './context.js';\nimport { bootstrapMemory } from './memory.js';\nimport { runCompact, runInit } from './memory-command.js';\nimport { createAiClient } from '@fim/ai-sdk';\nimport { executePlan } from './build-command.js';\nimport { evaluateGoal } from './goal.js';\nimport { runDiagnostics } from './diagnostics.js';\nimport { ensureBuildPlan, printBuildPlan, runPlan, runResume } from './plan-command.js';\nimport { pipelineId, readCheckpoint, writeCheckpoint } from './pipeline.js';\nimport { runSkills } from './skills-command.js';\nimport { runVerify } from './verify-command.js';\nimport { runImports, runSymbols } from './index-command.js';\nimport { buildRepoCard, findRepoRoot, MEMORY_FILENAME, readMemory } from './repo.js';\nimport { loadRetriever } from './index-store.js';\nimport { usageLine } from './render.js';\nimport { addUsage, emptyTotals, formatUsage } from './pricing.js';\nimport type { CliOptions } from './options.js';\nimport { color, error, info, line, setOutputSink, warn } from './ui.js';\n\n/** Slash commands offered in the chatbox dropdown + Tab-completion. */\nconst SLASH_COMMANDS: Suggestion[] = [\n { value: '/help', hint: 'commands & usage' },\n { value: '/exit', hint: 'quit' },\n { value: '/clear', hint: 'reset the conversation' },\n { value: '/model', hint: 'switch fx-* module' },\n { value: '/tier', hint: 'switch fx-* module' },\n { value: '/effort', hint: 'reasoning effort' },\n { value: '/usage', hint: 'tokens + cost' },\n { value: '/permissions', hint: 'view/reset consent' },\n { value: '/context', hint: 'session context' },\n { value: '/memory', hint: 'project memory' },\n { value: '/skills', hint: 'available skills' },\n { value: '/symbols', hint: 'symbol index' },\n { value: '/imports', hint: 'import graph' },\n { value: '/init', hint: 'write the memory file' },\n { value: '/compact', hint: 'compact memory' },\n { value: '/plan', hint: 'plan a task' },\n { value: '/build', hint: 'execute a plan' },\n { value: '/resume', hint: 'resume a plan' },\n { value: '/verify', hint: 'typecheck + lint' },\n { value: '/test', hint: 'run tests' },\n];\n\n/** One pending input action. */\ntype Action = { kind: 'cmd'; cmd: string; rest: string } | { kind: 'prompt'; text: string };\n\n/**\n * Interactive REPL \u2014 an agentic, repo-aware coding session as a chatbox: the\n * input bar is pinned to the bottom (raw-mode {@link Chatbox}) while streaming\n * output, tool activity, and the spinner flow above it. Keep typing while a\n * prompt runs \u2014 extra prompts QUEUE and run in order. Falls back to a plain\n * readline loop when stdin/stdout isn't a TTY (piped input).\n */\nexport async function runRepl(opts: CliOptions): Promise<void> {\n // Bootstrap project memory on a new session, BEFORE loadContext so the pinned\n // prefix includes it from the start.\n if (opts.useMemory) {\n const root = findRepoRoot();\n if (readMemory(root) === null) {\n const card = opts.useRepo ? buildRepoCard(root) : null;\n const symbols = loadRetriever(root)?.symbols ?? null;\n if (bootstrapMemory(root, card, symbols)) {\n info(`wrote ${MEMORY_FILENAME} (project memory) \u2014 edit it to guide FutureX`);\n }\n }\n }\n const ctx = loadContext(opts);\n\n let tier: Tier = opts.tier ?? 'fx-fast'; // /model and /tier change this mid-session\n const totals = emptyTotals();\n const queue: Action[] = [];\n let running = false;\n let closed = false;\n let active: AbortController | null = null;\n let prefixDriftWarned = false;\n\n let box: Chatbox | null = null;\n let rl: ReturnType<typeof createInterface> | null = null;\n let finish: () => void = () => {};\n let agentRuntime: ReplAgent;\n const agentOptions = { autoApprove: false, maxSteps: 32, verify: 'auto' as const };\n\n const waitingPrompts = (): number => queue.filter((a) => a.kind === 'prompt').length;\n\n /** Dynamic status text shown on the chatbox's bottom line (dot added by the box). */\n const statusLine = (): string => {\n const bits = [running ? 'working' : 'ready', tier, `${agentRuntime.toolCount} tools`, 'verify auto'];\n const waiting = waitingPrompts();\n if (waiting > 0) bits.push(`${waiting} queued`);\n return `${bits.join(' \u00B7 ')} /help \u00B7 ctrl+c cancels`;\n };\n\n /** Repaint the chatbox status, or re-show the readline prompt when idle. */\n const refresh = (): void => {\n if (box) box.refresh();\n else if (!running && !closed) rl?.prompt();\n };\n\n /** Ctrl+C: cancel the in-flight turn + drop anything queued; otherwise quit. */\n const interrupt = (): void => {\n if (active && !active.signal.aborted) {\n active.abort();\n queue.length = 0;\n box?.refresh();\n } else {\n finish();\n }\n };\n\n /** `/plan --restart <task>` style prefix flags for the REPL plan/build commands. */\n const replPlanFlags = (rest: string): { task: string; restart: boolean } => {\n let task = rest.trim();\n let restart = false;\n if (task.startsWith('--restart')) {\n restart = true;\n task = task.slice('--restart'.length).trim();\n }\n return { task, restart };\n };\n\n /** CliOptions re-routed through the LIVE tier (changed mid-session via /model). */\n const liveOpts = (): CliOptions => {\n const r = resolveTier(tier);\n return { ...opts, model: r.model, effort: r.effort, reasoning: r.reasoning, tier };\n };\n\n /**\n * `/build [--restart] <task>` \u2014 produce (or resume) the pre-build plan, then\n * execute its task DAG through THIS session's agent runtime + permission\n * gate, stopping when the acceptance criteria are met or the token budget\n * runs out.\n */\n const runBuildInRepl = async (rest: string): Promise<void> => {\n const { task: q, restart } = replPlanFlags(rest);\n if (!q) {\n error('usage: /build [--restart] <task>');\n return;\n }\n // The controller must exist BEFORE the (multi-model-call) planning phase so\n // Ctrl+C cancels the build instead of tearing the whole REPL down.\n const ac = new AbortController();\n active = ac;\n try {\n const buildOpts = liveOpts();\n const outcome = await ensureBuildPlan(q, buildOpts, { restart }, (name, status) =>\n info(` ${status === 'cached' ? '\u2713 resumed' : '\u2026 running'} ${name}`),\n );\n if (ac.signal.aborted || closed) return;\n if (outcome.kind === 'clarify') {\n info('one question before building:');\n line(` ? ${outcome.question}`);\n return;\n }\n printBuildPlan(outcome.plan);\n const model = buildOpts.model;\n const ai = createAiClient({ provider: 'deepseek' });\n const buildTotals = emptyTotals();\n const planId = pipelineId(`${ctx.root}::${q}`);\n const result = await executePlan({\n plan: outcome.plan,\n signal: ac.signal,\n async turn(prompt) {\n const usage = await agentRuntime.turn(prompt, model, ac.signal);\n if (usage) {\n addUsage(buildTotals, model, usage);\n addUsage(totals, model, usage);\n }\n },\n evaluate: (evidence) => evaluateGoal(outcome.plan.goal, evidence, ai, { model }),\n verify: () => runDiagnostics(ctx.root).map((r) => ({ name: r.name, ok: r.ok })),\n usedTokens: () => buildTotals.outputTokens + buildTotals.reasoningTokens,\n isTaskDone: (taskId) => readCheckpoint(planId, `exec-${taskId}`) !== null,\n markTaskDone: (taskId) => writeCheckpoint(planId, `exec-${taskId}`, { completed: true }),\n report: (text) => info(text),\n });\n info(\n `build ${result.status} \u00B7 ${result.completedTasks.length}/${outcome.plan.tasks.length} tasks \u00B7 ` +\n formatUsage(buildTotals).join(' \u00B7 '),\n );\n if (result.evaluation && !result.evaluation.done) {\n info(`remaining criteria: ${result.evaluation.remaining.join(', ')}`);\n }\n } catch (err) {\n if (!ac.signal.aborted) error(err instanceof Error ? err.message : String(err));\n else info('build cancelled');\n } finally {\n active = null;\n }\n };\n\n /** Handle a `/command rest`. Returns 'exit' to leave the REPL. */\n const runCommand = async (cmd: string, rest: string): Promise<'exit' | void> => {\n switch (cmd) {\n case 'exit':\n case 'quit':\n return 'exit';\n case 'clear':\n agentRuntime.clear();\n info('conversation cleared');\n return;\n case 'help':\n line(color.bold('How it works'));\n line(color.dim(' Type what you want built. Every coding prompt runs plan \u2192 build \u2192 verify:'));\n line(color.dim(' the agent plans, edits files (writes ask first), then runs your typecheck/'));\n line(color.dim(' lint/tests and fixes failures before it declares the task done.'));\n line(color.dim(' Keep typing while one runs \u2014 extra prompts queue and run in order.'));\n line(color.bold('Commands'));\n line(color.dim(` /model | /tier [${TIER_IDS.join('|')}] /effort /usage`));\n line(color.dim(' /permissions [show|set <kind> <ask|allow|deny>|reset]'));\n line(color.dim(' /context [show|clear] /memory [show|compact] /skills [request]'));\n line(color.dim(' /init /compact /plan <task> /build <task> /resume [id]'));\n line(color.dim(' /symbols [name] /imports [file] /verify /test'));\n line(color.dim(' /clear /help /exit'));\n return;\n case 'model':\n case 'tier': {\n if (!rest) {\n info(`module: ${tier}`);\n return;\n }\n const norm = normalizeTier(rest);\n if (!norm) {\n error(`unknown module \"${rest}\" (expected: ${TIER_IDS.join(' | ')})`);\n return;\n }\n tier = norm;\n info(`module \u2192 ${tier}`);\n return;\n }\n case 'effort':\n info('the interactive agent runs fast (non-thinking) for reliable tool calls;');\n info('for harder tasks switch module with /model fx-pro, or use /plan + /build');\n info('which plan with high reasoning effort before executing');\n return;\n case 'usage':\n if (totals.calls === 0) info('no usage yet this session');\n else info(`usage \u00B7 ${formatUsage(totals).join(' \u00B7 ')}`);\n return;\n case 'permissions':\n runPermissions(ctx.root, rest);\n return;\n case 'memory': {\n if (rest.toLowerCase() === 'compact') {\n runCompact();\n return;\n }\n const mem = readMemory(ctx.root);\n if (!mem) info(`no ${MEMORY_FILENAME} \u2014 run /init`);\n else line(mem.length > 1200 ? `${mem.slice(0, 1200)}\\n\u2026(truncated)` : mem);\n return;\n }\n case 'context': {\n if (rest.toLowerCase() === 'clear') {\n agentRuntime.clear();\n info('conversation context cleared');\n return;\n }\n const idx = ctx.retriever\n ? `${ctx.retriever.size} chunks \u00B7 ${ctx.retriever.symbols.stats().symbols} symbols \u00B7 ${ctx.retriever.imports.stats().edges} imports`\n : 'no index';\n info(`context \u00B7 history ${agentRuntime.size()} msgs \u00B7 index ${idx} \u00B7 prefix ${ctx.systemDigest}`);\n return;\n }\n case 'skills':\n runSkills(rest);\n return;\n case 'symbols':\n runSymbols(rest);\n return;\n case 'imports':\n runImports(rest);\n return;\n case 'init':\n runInit();\n return;\n case 'compact':\n runCompact();\n return;\n case 'plan': {\n const { task: planTask, restart } = replPlanFlags(rest);\n // runPlan sets process.exitCode on failure for the one-shot CLI; a\n // failed /plan must not poison the eventual REPL exit code.\n const priorExitCode = process.exitCode;\n await runPlan(planTask, liveOpts(), { restart });\n process.exitCode = priorExitCode;\n return;\n }\n case 'build':\n await runBuildInRepl(rest);\n return;\n case 'resume':\n runResume(rest || undefined);\n return;\n case 'test':\n await runVerify({ only: 'test' });\n return;\n case 'verify':\n case 'run':\n await runVerify();\n return;\n default:\n info(`unknown command: /${cmd} (try /help)`);\n return;\n }\n };\n\n /** Run one prompt agentically (one queued item). */\n const runTurn = async (text: string): Promise<void> => {\n if (!prefixDriftWarned && currentPrefixDigest(ctx, opts) !== ctx.systemDigest) {\n prefixDriftWarned = true;\n warn('futurex-memory.md / repo changed on disk \u2014 keeping the session prefix (restart to apply)');\n }\n const ac = new AbortController();\n active = ac;\n const model = resolveTier(tier).model;\n let usage: AiUsage | undefined;\n try {\n usage = await agentRuntime.turn(text, model, ac.signal);\n } catch (err) {\n if (!ac.signal.aborted) error(err instanceof Error ? err.message : String(err));\n }\n active = null;\n if (usage) {\n addUsage(totals, model, usage);\n info(usageLine(usage, tier));\n }\n };\n\n /** Drain the queue one action at a time, then settle the prompt when idle. */\n const drain = async (): Promise<void> => {\n if (running) return;\n running = true;\n box?.refresh();\n while (queue.length > 0 && !closed) {\n const action = queue.shift();\n if (!action) break;\n if (action.kind === 'cmd') {\n if ((await runCommand(action.cmd, action.rest)) === 'exit') {\n finish();\n break;\n }\n } else {\n await runTurn(action.text);\n box?.flushLive();\n if (!box) {\n const waiting = waitingPrompts();\n if (waiting > 0) info(color.dim(`\u21B3 ${waiting} more queued\u2026`));\n }\n }\n box?.refresh();\n }\n running = false;\n refresh();\n };\n\n /** Accept a submitted line: route /commands, else queue a prompt; /exit quits now. */\n const submit = (raw0: string): void => {\n const raw = raw0.trim();\n if (!raw) {\n refresh();\n return;\n }\n if (raw.startsWith('/')) {\n const sp = raw.indexOf(' ');\n const cmd = (sp === -1 ? raw.slice(1) : raw.slice(1, sp)).toLowerCase();\n const rest = sp === -1 ? '' : raw.slice(sp + 1).trim();\n if (cmd === 'exit' || cmd === 'quit') {\n finish();\n return;\n }\n queue.push({ kind: 'cmd', cmd, rest });\n } else {\n queue.push({ kind: 'prompt', text: raw });\n }\n box?.refresh();\n void drain();\n };\n\n /** Live `/`-command suggestions as the user types (chatbox only). */\n const onChange = (buf: string): void => {\n if (!box) return;\n const t = buf.trimStart().toLowerCase();\n if (t.startsWith('/') && !t.includes(' ')) {\n box.setSuggestions(SLASH_COMMANDS.filter((c) => c.value.startsWith(t)).slice(0, 6));\n } else {\n box.setSuggestions([]);\n }\n };\n\n const banner = (): void => {\n const stack = [ctx.card?.framework, ctx.card?.backend, ctx.card?.orm]\n .filter((x): x is string => Boolean(x))\n .join(' \u00B7 ');\n const index = ctx.retriever\n ? `${ctx.retriever.size} chunks \u00B7 ${ctx.retriever.symbols.stats().symbols} symbols`\n : 'none (run `futurex index`)';\n line();\n line(` ${color.bold(color.magenta('\u25C6 FutureX'))} ${color.dim('\u2014 agentic coding terminal')}`);\n line(` ${color.dim('module')} ${color.cyan(tier)} ${color.dim(`\u00B7 ${agentRuntime.toolCount} tools \u00B7 index ${index}`)}`);\n if (stack) line(` ${color.dim(`stack ${stack}`)}`);\n line(` ${color.cyan('plan')} ${color.dim('\u2192')} ${color.yellow('build')} ${color.dim('\u2192')} ${color.green('verify')} ${color.dim('\u00B7 writes ask first \u00B7 checks run automatically after edits')}`);\n line(\n color.dim(\n box\n ? ' type below \u00B7 queue more while one runs \u00B7 Tab completes /commands \u00B7 Ctrl+C cancels'\n : ' keep typing to queue \u00B7 /help \u00B7 /exit',\n ),\n );\n line();\n };\n\n // --- mount ----------------------------------------------------------------\n\n const useBox = process.stdin.isTTY === true && process.stdout.isTTY === true;\n if (useBox) {\n box = new Chatbox({\n status: statusLine,\n state: () => (running ? 'working' : 'ready'),\n handlers: { onSubmit: submit, onInterrupt: interrupt, onExit: () => finish(), onChange },\n });\n }\n\n // Per-project persistent gate: stored always-allow/deny decisions apply even\n // before any prompt; only an 'ask' state reaches the (TTY-only) modal.\n const ask: AskFn = box\n ? createChatboxAsk(box)\n : async () => {\n info('non-interactive: writes/exec denied \u2014 run futurex in a terminal to approve');\n return 'no';\n };\n const gate = createPermissionGate(ctx.root, ask, { autoApprove: agentOptions.autoApprove });\n\n try {\n // Gateway-backed when logged in (the backend runs the loop); local direct\n // fallback otherwise \u2014 which needs FX_API_KEY.\n agentRuntime = createReplRuntime(ctx, opts, agentOptions, gate);\n } catch (err) {\n error(err instanceof Error ? err.message : String(err));\n error('run `futurex login` to use the FIM gateway, or set FX_API_KEY for local mode');\n process.exitCode = 1;\n return;\n }\n\n if (box) {\n setOutputSink(box);\n box.start();\n banner();\n process.on('SIGINT', interrupt);\n await new Promise<void>((resolve) => {\n finish = () => {\n closed = true;\n resolve();\n };\n });\n process.removeListener('SIGINT', interrupt);\n (active as AbortController | null)?.abort();\n box.stop();\n setOutputSink(null);\n } else {\n rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n completer: (l: string): [string[], string] => {\n const vals = SLASH_COMMANDS.map((c) => c.value);\n if (!l.startsWith('/')) return [[], l];\n const hits = vals.filter((v) => v.startsWith(l.trimEnd()));\n return [hits.length > 0 ? hits : vals, l];\n },\n });\n banner();\n finish = () => {\n closed = true;\n rl?.close();\n };\n rl.on('SIGINT', interrupt);\n process.on('SIGINT', interrupt);\n rl.on('line', submit);\n rl.setPrompt(color.magenta('\u276F '));\n rl.prompt();\n await new Promise<void>((resolve) => {\n rl?.once('close', () => {\n closed = true;\n resolve();\n });\n });\n (active as AbortController | null)?.abort();\n rl.removeListener('SIGINT', interrupt);\n process.removeListener('SIGINT', interrupt);\n }\n}\n", "import { createInterface, type Interface } from 'node:readline';\nimport {\n createAiClient,\n type AiUsage,\n type ChatMessage,\n type ToolCall,\n type ToolDefinition,\n} from '@fim/ai-sdk';\nimport { createToolRegistry, type ToolContext } from '@fim/futurex-tools';\nimport type { Message } from '@fim/futurex-protocol';\nimport { augmentMessages } from './augment.js';\nimport { loadContext, type SessionContext } from './context.js';\nimport { readCreds } from './creds.js';\nimport { createGatewayClient } from './client/gateway.js';\nimport { createPermissionGate, type AskFn, type Gate } from './permissions.js';\nimport { accumulateUsage } from './pricing.js';\nimport { findRepoRoot } from './repo.js';\nimport {\n createDoneFilter,\n decideNext,\n NUDGE_FINISH,\n NUDGE_LENGTH,\n nudgeVerifyFailures,\n runGatewayTurnToCompletion,\n runVerifyPhase,\n type VerifyMode,\n type VerifyOutcome,\n} from './finish.js';\nimport { AGENT_PROTOCOL } from './system-prompt.js';\nimport type { CliOptions } from './options.js';\nimport {\n color,\n errColor,\n eout,\n error,\n info,\n line,\n out,\n phase,\n startSpinner,\n toolCallLine,\n toolResultLine,\n verdictLine,\n type Spinner,\n} from './ui.js';\n\nexport interface AgentOptions {\n /** Approve every mutating tool without prompting (dangerous; for scripts/tests). */\n readonly autoApprove: boolean;\n /** Max model\u2194tool rounds before stopping. */\n readonly maxSteps: number;\n /** Run the repo's checks after the agent writes files ('auto', default) or not ('off'). */\n readonly verify?: VerifyMode;\n}\n\nexport type { Gate } from './permissions.js';\n\nfunction question(rl: Interface, q: string): Promise<string> {\n return new Promise((resolve) => rl.question(q, resolve));\n}\n\n/**\n * A permission prompt over readline (one-shot `futurex agent` mode). Always-*\n * answers are persisted per action kind by the permission gate wrapping this.\n */\nexport function createReadlineAsk(rl: Interface): AskFn {\n return async (req) => {\n // Non-interactive stdin can never answer the prompt \u2192 fail safe (deny), don't hang.\n if (process.stdin.isTTY !== true) {\n info('non-interactive stdin: re-run with --auto-approve to permit writes/exec');\n return 'no';\n }\n const caution = req.kind === 'run' ? ' (commands run with your shell access)' : '';\n eout(`\\n${errColor.yellow('permission')} [${req.kind}] ${req.preview}${caution}\\n`);\n const ans = (\n await question(\n rl,\n errColor.yellow(` approve? [y]es / [n]o / [a]lways allow ${req.kind} / always [d]eny ${req.kind} `),\n )\n )\n .trim()\n .toLowerCase();\n if (ans === 'a' || ans === 'always') return 'always-allow';\n if (ans === 'd' || ans === 'deny' || ans === 'never') return 'always-deny';\n if (ans === 'y' || ans === 'yes') return 'yes';\n return 'no';\n };\n}\n\n/** Dependencies of one agent turn (exported for the orchestrator tests). */\nexport interface TurnDeps {\n readonly ai: ReturnType<typeof createAiClient>;\n readonly toolDefs: ToolDefinition[];\n readonly registry: ReturnType<typeof createToolRegistry>;\n readonly toolCtx: ToolContext;\n readonly agentSystem: string;\n readonly model: string;\n readonly maxTokens?: number;\n readonly maxSteps: number;\n readonly gate: Gate;\n readonly signal: AbortSignal;\n /** Repo root, for the automatic verification phase. */\n readonly root: string;\n readonly verify: VerifyMode;\n}\n\n/**\n * One user turn of the agent as a phased pipeline over a PERSISTENT `messages`\n * array: PLAN/BUILD \u2014 stream the model, run its tool calls (reads auto,\n * writes/exec gated) and feed results back; VERIFY \u2014 when files changed, run\n * the repo's own checks; REPAIR \u2014 feed failures back for bounded fix rounds.\n *\n * The turn only ends when the completion policy (finish.ts) accepts it: a\n * length-cut answer is auto-continued, a \"narrate and stop\" answer is nudged\n * to keep working, and written files must pass the project checks. The user\n * never has to type \"continue\".\n */\nexport async function runAgentTurn(messages: ChatMessage[], d: TurnDeps): Promise<AiUsage | undefined> {\n // Accumulated across ALL steps of the turn \u2014 budgets/billing must see every\n // model call of the tool loop, not just the final one.\n let turnUsage: AiUsage | undefined;\n const startedAt = Date.now();\n let toolRuns = 0;\n const filesChanged = new Set<string>();\n let shownPhase: string | null = null;\n let verifyMode = d.verify;\n let lengthContinues = 0;\n let finishNudges = 0;\n let repairRounds = 0;\n let mutatedSinceVerify = false;\n let verifyRan = false;\n let verifyFailed = false;\n let lastVerify: VerifyOutcome | null = null;\n\n const showPhase = (p: 'build' | 'verify' | 'repair'): void => {\n if (shownPhase !== p) {\n shownPhase = p;\n phase(p);\n }\n };\n\n const finishTurn = (): AiUsage | undefined => {\n if (toolRuns > 0) {\n const secs = ((Date.now() - startedAt) / 1000).toFixed(1);\n const bits = [`${secs}s`, `${toolRuns} tool call${toolRuns === 1 ? '' : 's'}`];\n if (filesChanged.size > 0) bits.push(`${filesChanged.size} file${filesChanged.size === 1 ? '' : 's'} changed`);\n if (verifyRan && !verifyFailed) bits.push('checks pass');\n const mark = verifyFailed ? color.yellow('!') : color.green('\u2713');\n line(`${mark} ${color.dim(bits.join(' \u00B7 '))}`);\n if (verifyFailed && lastVerify) {\n for (const l of lastVerify.lines) {\n if (l.includes('FAIL')) line(verdictLine(false, l));\n }\n info('verification failures remain \u2014 say \"fix the failing checks\" to retry');\n }\n }\n return turnUsage;\n };\n\n const spinLabel = (step: number): string => {\n if (shownPhase === 'repair') return 'repairing\u2026';\n if (step === 0) return messages.length <= 2 ? 'planning\u2026' : 'thinking\u2026';\n return 'working\u2026';\n };\n\n for (let step = 0; step < d.maxSteps; step++) {\n const lastStep = step === d.maxSteps - 1;\n let text = '';\n let toolCalls: ToolCall[] = [];\n let finishReason: string | undefined;\n let printedText = false;\n const filter = createDoneFilter();\n let spin: Spinner | null = startSpinner(spinLabel(step));\n const stopSpin = (): void => {\n if (spin) {\n spin.stop();\n spin = null;\n }\n };\n try {\n for await (const chunk of d.ai.stream({\n model: d.model,\n ...(d.maxTokens !== undefined ? { maxTokens: d.maxTokens } : {}),\n system: d.agentSystem,\n messages,\n tools: d.toolDefs,\n // Force a final text answer on the last step instead of dead-ending mid-tool.\n toolChoice: lastStep ? 'none' : 'auto',\n reasoning: false,\n signal: d.signal,\n })) {\n stopSpin(); // first chunk arrived \u2014 clear the spinner before any output\n if (chunk.delta) {\n const visible = filter.push(chunk.delta);\n if (visible) {\n out(visible);\n text += visible;\n printedText = true;\n }\n }\n if (chunk.done) {\n if (chunk.toolCalls) toolCalls = [...chunk.toolCalls];\n finishReason = chunk.finishReason;\n if (chunk.usage) turnUsage = turnUsage ? accumulateUsage(turnUsage, chunk.usage) : chunk.usage;\n }\n }\n } finally {\n stopSpin();\n }\n const rest = filter.flush();\n if (rest) {\n out(rest);\n text += rest;\n printedText = true;\n }\n if (printedText) out('\\n');\n\n if (d.signal.aborted) {\n info('cancelled');\n return turnUsage;\n }\n\n if (toolCalls.length > 0) {\n showPhase('build');\n messages.push({ role: 'assistant', content: text, toolCalls });\n\n for (const tc of toolCalls) {\n const spec = d.registry.get(tc.name);\n if (!spec) {\n messages.push({ role: 'tool', toolCallId: tc.id, content: `unknown tool: ${tc.name}` });\n continue;\n }\n let parsed: unknown;\n try {\n parsed = spec.schema.parse(JSON.parse(tc.arguments || '{}'));\n } catch (err) {\n messages.push({\n role: 'tool',\n toolCallId: tc.id,\n content: `invalid arguments: ${err instanceof Error ? err.message : String(err)}`,\n });\n continue;\n }\n const preview = spec.preview(parsed, d.toolCtx);\n const kind = spec.classify(parsed, d.toolCtx);\n if (kind !== null) {\n const approved = await d.gate({ tool: spec.name, kind, preview });\n if (!approved) {\n line(verdictLine(false, `denied: ${spec.name}`));\n messages.push({ role: 'tool', toolCallId: tc.id, content: 'denied by the user' });\n continue;\n }\n }\n line(toolCallLine(preview, spec.mutating));\n let result: { ok: boolean; output: string };\n try {\n result = await spec.run(parsed, d.toolCtx);\n } catch (err) {\n result = { ok: false, output: `tool error: ${err instanceof Error ? err.message : String(err)}` };\n }\n toolRuns += 1;\n if (spec.mutating && result.ok) {\n mutatedSinceVerify = true;\n verifyRan = false;\n verifyFailed = false;\n const path = (parsed as { path?: string }).path;\n if (path) filesChanged.add(path);\n }\n line(toolResultLine(result.output, result.ok));\n messages.push({ role: 'tool', toolCallId: tc.id, content: result.output });\n }\n continue;\n }\n\n // \u2500\u2500 Text-only stop: apply the completion policy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (text) messages.push({ role: 'assistant', content: text });\n\n let proceed = false;\n while (!proceed) {\n const action = decideNext({\n sawMarker: filter.sawMarker,\n finishReason,\n mutatedSinceVerify,\n verifyRan,\n verifyFailed,\n lengthContinues,\n finishNudges,\n repairRounds,\n verifyMode,\n });\n switch (action.kind) {\n case 'accept':\n return finishTurn();\n case 'continue-length':\n lengthContinues += 1;\n info('output hit the token limit \u2014 continuing automatically');\n messages.push({ role: 'user', content: NUDGE_LENGTH });\n proceed = true;\n break;\n case 'nudge-finish':\n finishNudges += 1;\n messages.push({ role: 'user', content: NUDGE_FINISH });\n proceed = true;\n break;\n case 'repair':\n showPhase('repair');\n repairRounds += 1;\n info(`repair round ${repairRounds} \u2014 feeding the failures back`);\n messages.push({\n role: 'user',\n content: nudgeVerifyFailures(lastVerify?.failureSummary ?? 'checks failed'),\n });\n proceed = true;\n break;\n case 'verify': {\n showPhase('verify');\n const vSpin = startSpinner('verifying \u2014 running project checks\u2026');\n try {\n lastVerify = await runVerifyPhase(d.root, { signal: d.signal });\n } finally {\n vSpin.stop();\n }\n if (d.signal.aborted) {\n info('cancelled');\n return turnUsage;\n }\n if (!lastVerify.ran) {\n // No checks in this repo \u2014 verification can't gate completion here.\n info('no typecheck/lint/test scripts detected \u2014 skipping verification');\n verifyMode = 'off';\n verifyRan = false;\n verifyFailed = false;\n } else {\n verifyRan = true;\n verifyFailed = !lastVerify.ok;\n for (const l of lastVerify.lines) line(verdictLine(!l.includes('FAIL'), l));\n if (lastVerify.timedOut) info('a check hit its time budget \u2014 result treated as inconclusive');\n }\n break; // re-decide with the verification outcome\n }\n }\n }\n }\n info(`reached the ${d.maxSteps}-step safety limit \u2014 stopping; send another message to continue`);\n return finishTurn();\n}\n\nfunction toolDefsFrom(registry: ReturnType<typeof createToolRegistry>): ToolDefinition[] {\n return registry.specs.map((s) => ({\n name: s.name,\n description: s.description,\n parameters: s.parameters,\n }));\n}\n\n/**\n * Local agentic loop for `futurex agent \"<task>\"`. The model plans, calls\n * tools, the CLI executes them (reads auto; mutating behind a permission gate)\n * and feeds results back; written files are verified against the repo's own\n * checks before the turn may finish. `deps` lets a parent (the REPL) share its\n * readline + abort so the loop runs embedded.\n */\nexport async function runAgent(\n task: string,\n opts: CliOptions,\n agent: AgentOptions,\n deps: { rl?: Interface; signal?: AbortSignal } = {},\n): Promise<void> {\n const prompt = task.trim();\n if (!prompt) {\n error('usage: futurex agent \"<task>\"');\n process.exitCode = 1;\n return;\n }\n\n // Standalone: own the abort signal + SIGINT + readline. Embedded (REPL): the\n // caller passes its signal + readline so we never double-register or close them.\n const ownAc = deps.signal ? null : new AbortController();\n const signal: AbortSignal = deps.signal ?? (ownAc as AbortController).signal;\n const onSigint = (): void => ownAc?.abort();\n if (!deps.signal) process.on('SIGINT', onSigint);\n const ownRl = deps.rl === undefined;\n const rl = deps.rl ?? createInterface({ input: process.stdin, output: process.stdout });\n // With a readline attached to the TTY, Ctrl+C is delivered to the INTERFACE,\n // not the process \u2014 listen on both so the first Ctrl+C aborts cleanly.\n if (ownRl) rl.on('SIGINT', onSigint);\n const repoRoot = findRepoRoot();\n // Persistent per-project gate: store lookup first, prompt only when 'ask'.\n const gate = createPermissionGate(repoRoot, createReadlineAsk(rl), {\n autoApprove: agent.autoApprove,\n });\n\n try {\n const creds = readCreds();\n if (creds?.accessToken) {\n // Gateway: the backend runs the agent loop and asks this client to execute\n // tools (reads auto; writes/exec gated). No local AI or context engine.\n let mutated = false;\n const client = createGatewayClient(creds, {\n gate,\n repoRoot,\n onTool: (t) => {\n if (t.mutating && t.ok) mutated = true;\n },\n ...(opts.useRepo !== undefined ? { useRepo: opts.useRepo } : {}),\n ...(opts.useMemory !== undefined ? { useMemory: opts.useMemory } : {}),\n });\n info(`mode: gateway agent \u00B7 ${opts.tier ?? 'fx-fast'}`);\n const history: Message[] = [{ role: 'user', content: prompt }];\n const result = await runGatewayTurnToCompletion({\n client,\n history,\n base: {\n model: opts.model,\n ...(opts.maxTokens !== undefined ? { maxTokens: opts.maxTokens } : {}),\n ...(opts.tier ? { tier: opts.tier } : {}),\n ...(opts.effort ? { effort: opts.effort } : {}),\n },\n signal,\n root: repoRoot,\n verify: agent.verify ?? 'auto',\n mutated: () => mutated,\n resetMutated: () => {\n mutated = false;\n },\n });\n if (result.error && !signal.aborted) {\n error(result.error);\n process.exitCode = 1;\n }\n return;\n }\n\n // Local fallback (direct DeepSeek loop) \u2014 needs FX_API_KEY.\n const ctx = loadContext(opts);\n const ai = createAiClient({ provider: 'deepseek' });\n const registry = createToolRegistry();\n const toolCtx: ToolContext = { repoRoot: ctx.root };\n const messages: ChatMessage[] = (\n await augmentMessages([{ role: 'user', content: prompt }] as Message[], ctx.retriever, opts.topK)\n ).map((m) => ({ role: m.role, content: m.content }));\n info(`mode: local agent \u00B7 ${opts.tier ?? 'fx-fast'} \u00B7 ${registry.specs.length} tools`);\n await runAgentTurn(messages, {\n ai,\n toolDefs: toolDefsFrom(registry),\n registry,\n toolCtx,\n agentSystem: `${ctx.system}\\n\\n${AGENT_PROTOCOL}`,\n model: opts.model,\n maxTokens: opts.maxTokens,\n maxSteps: agent.maxSteps,\n gate,\n signal,\n root: ctx.root,\n verify: agent.verify ?? 'auto',\n });\n } catch (err) {\n if (signal.aborted || (err instanceof Error && err.name === 'AbortError')) {\n info('cancelled');\n } else {\n error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n } finally {\n if (ownRl) rl.close();\n if (!deps.signal) process.removeListener('SIGINT', onSigint);\n }\n}\n\n/**\n * A persistent agentic runtime for the REPL: holds the conversation history + the\n * tool loop, so every normal prompt can read/write files (gated) with multi-turn\n * memory. Shares the REPL's readline for the permission prompt.\n */\nexport interface ReplAgent {\n /** Run one user turn agentically (mutates internal history); returns final usage. */\n turn(userMessage: string, model: string, signal: AbortSignal): Promise<AiUsage | undefined>;\n /** Reset the conversation history. */\n clear(): void;\n /** Number of messages in the running history. */\n size(): number;\n /** Tool count (for the banner). */\n readonly toolCount: number;\n}\n\nexport function createReplAgent(\n ctx: SessionContext,\n opts: CliOptions,\n agentOptions: AgentOptions,\n gate: Gate,\n): ReplAgent {\n const ai = createAiClient({ provider: 'deepseek' });\n const registry = createToolRegistry();\n const toolCtx: ToolContext = { repoRoot: ctx.root };\n const toolDefs = toolDefsFrom(registry);\n const agentSystem = `${ctx.system}\\n\\n${AGENT_PROTOCOL}`;\n const messages: ChatMessage[] = [];\n\n return {\n toolCount: registry.specs.length,\n async turn(userMessage, model, signal) {\n const augmented = (\n await augmentMessages([{ role: 'user', content: userMessage }] as Message[], ctx.retriever, opts.topK)\n ).map((m) => ({ role: m.role, content: m.content }));\n messages.push(...augmented);\n return runAgentTurn(messages, {\n ai,\n toolDefs,\n registry,\n toolCtx,\n agentSystem,\n model,\n maxTokens: opts.maxTokens,\n maxSteps: agentOptions.maxSteps,\n gate,\n signal,\n root: ctx.root,\n verify: agentOptions.verify ?? 'auto',\n });\n },\n clear() {\n messages.length = 0;\n },\n size() {\n return messages.length;\n },\n };\n}\n", "/**\n * Diagnostics tool (Blueprint v2 P9): run the project's typecheck / lint / test /\n * build in the workspace and capture STRUCTURED results (pass/fail + the failing\n * files parsed from the output), so the repair loop can feed back only the failing\n * file + exact error rather than a wall of text.\n */\nimport { spawn, spawnSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport interface Check {\n readonly name: string;\n readonly command: string;\n}\n\nexport interface CheckResult {\n readonly name: string;\n readonly command: string;\n readonly ok: boolean;\n readonly output: string;\n /** Best-effort list of files implicated by the output. */\n readonly failingFiles: string[];\n readonly durationMs: number;\n}\n\ninterface PackageJson {\n scripts?: Record<string, string>;\n}\n\nfunction readPackageJson(root: string): PackageJson | null {\n try {\n return JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) as PackageJson;\n } catch {\n return null;\n }\n}\n\nfunction detectPm(root: string): string {\n if (existsSync(join(root, 'pnpm-lock.yaml'))) return 'pnpm';\n if (existsSync(join(root, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\n/** The check scripts we know how to run, in repair-priority order. */\nconst KNOWN_CHECKS = ['typecheck', 'lint', 'test', 'build'] as const;\n\n/** Detect runnable checks from the repo's package.json scripts. */\nexport function detectChecks(root: string): Check[] {\n const scripts = readPackageJson(root)?.scripts ?? {};\n const pm = detectPm(root);\n const out: Check[] = [];\n for (const name of KNOWN_CHECKS) {\n if (typeof scripts[name] === 'string') out.push({ name, command: `${pm} run ${name}` });\n }\n return out;\n}\n\n/** Parse plausible source-file paths out of compiler/linter output. */\nfunction parseFailingFiles(output: string): string[] {\n const files = new Set<string>();\n // `path/to/file.ts(12,3)` (tsc) and `path/to/file.ts:12:3` (eslint/jest).\n const re = /([A-Za-z0-9_./\\\\-]+\\.[A-Za-z]{1,5})[(:]\\d+/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(output)) !== null) {\n const p = m[1];\n if (p && !p.includes('node_modules')) files.add(p.split('\\\\').join('/'));\n if (files.size >= 50) break;\n }\n return [...files];\n}\n\n/** Run one check in `root`, capturing combined output (best-effort, never throws). */\nexport function runCheck(root: string, check: Check, timeoutMs = 300_000): CheckResult {\n let output = '';\n let ok = false;\n let durationMs = 0;\n try {\n const startedHint = process.hrtime.bigint();\n const res = spawnSync(check.command, {\n cwd: root,\n shell: true,\n encoding: 'utf8',\n timeout: timeoutMs,\n maxBuffer: 16 * 1024 * 1024,\n });\n durationMs = Number((process.hrtime.bigint() - startedHint) / 1_000_000n);\n output = `${res.stdout ?? ''}${res.stderr ?? ''}`;\n ok = res.status === 0 && !res.error;\n } catch (err) {\n output = err instanceof Error ? err.message : String(err);\n ok = false;\n }\n return { name: check.name, command: check.command, ok, output, failingFiles: parseFailingFiles(output), durationMs };\n}\n\n/** Run a set of checks (or the detected ones) and return structured results. */\nexport function runDiagnostics(root: string, checks?: readonly Check[]): CheckResult[] {\n const toRun = checks ?? detectChecks(root);\n return toRun.map((c) => runCheck(root, c));\n}\n\n/** A check result that also distinguishes \"killed at the time budget\". */\nexport interface AsyncCheckResult extends CheckResult {\n /** True when the check was killed by the timeout/abort, so `ok:false` is inconclusive. */\n readonly timedOut?: boolean;\n}\n\n/**\n * Kill a `shell: true` child AND its process tree. A plain `child.kill()` only\n * kills the shell \u2014 on Windows the actual tool (the grandchild) keeps running,\n * keeps the stdio pipes open, and `close` never fires.\n */\nfunction killTree(pid: number | undefined): void {\n if (!pid) return;\n try {\n if (process.platform === 'win32') {\n spawn('taskkill', ['/pid', String(pid), '/T', '/F'], { stdio: 'ignore' }).unref();\n } else {\n process.kill(pid, 'SIGKILL');\n }\n } catch {\n /* already gone */\n }\n}\n\n/**\n * Non-blocking variant of {@link runCheck}: spawns the command so the event\n * loop (spinner, Ctrl+C, queued input) stays alive while a slow typecheck or\n * test run executes. Aborting the signal (or the time budget) kills the whole\n * process tree; if stubborn grandchildren still hold the pipes open, a short\n * fallback timer settles the result anyway.\n */\nexport function runCheckAsync(\n root: string,\n check: Check,\n opts: { timeoutMs?: number; signal?: AbortSignal } = {},\n): Promise<AsyncCheckResult> {\n const timeoutMs = opts.timeoutMs ?? 300_000;\n return new Promise((resolve) => {\n const started = process.hrtime.bigint();\n let output = '';\n let killed = false;\n let settled = false;\n let fallback: ReturnType<typeof setTimeout> | null = null;\n const child = spawn(check.command, { cwd: root, shell: true });\n const finish = (ok: boolean): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n if (fallback) clearTimeout(fallback);\n opts.signal?.removeEventListener('abort', onAbort);\n child.stdout?.destroy();\n child.stderr?.destroy();\n child.unref();\n const durationMs = Number((process.hrtime.bigint() - started) / 1_000_000n);\n resolve({\n name: check.name,\n command: check.command,\n ok,\n output: output.slice(0, 16 * 1024 * 1024),\n failingFiles: parseFailingFiles(output),\n durationMs,\n ...(killed ? { timedOut: true } : {}),\n });\n };\n const kill = (): void => {\n killed = true;\n killTree(child.pid);\n // Don't wait on `close` forever if a grandchild survives the kill.\n fallback = setTimeout(() => finish(false), 2000);\n fallback.unref?.();\n };\n const timer = setTimeout(kill, timeoutMs);\n const onAbort = (): void => kill();\n opts.signal?.addEventListener('abort', onAbort, { once: true });\n child.stdout?.on('data', (d: Buffer) => {\n output += d.toString('utf8');\n });\n child.stderr?.on('data', (d: Buffer) => {\n output += d.toString('utf8');\n });\n child.on('error', (err) => {\n output += err.message;\n finish(false);\n });\n child.on('close', (code) => finish(code === 0 && !killed));\n });\n}\n\n/**\n * Run checks sequentially without blocking the event loop. With `failFast`,\n * stop at the first real failure (timeouts don't trip it) so the repair loop\n * gets feedback as early as possible.\n */\nexport async function runDiagnosticsAsync(\n root: string,\n opts: { checks?: readonly Check[]; timeoutMs?: number; signal?: AbortSignal; failFast?: boolean } = {},\n): Promise<AsyncCheckResult[]> {\n const toRun = opts.checks ?? detectChecks(root);\n const results: AsyncCheckResult[] = [];\n for (const check of toRun) {\n if (opts.signal?.aborted) break;\n const r = await runCheckAsync(root, check, {\n ...(opts.timeoutMs !== undefined ? { timeoutMs: opts.timeoutMs } : {}),\n ...(opts.signal ? { signal: opts.signal } : {}),\n });\n results.push(r);\n if (opts.failFast && !r.ok && !r.timedOut) break;\n }\n return results;\n}\n", "/**\n * Verify \u2192 repair loop (Blueprint v2 P9). Run diagnostics; on failure, feed back\n * only the failing file + exact error to a generator for a bounded number of\n * retries on the same model, then ESCALATE to a stronger model (Pro-MAX) for a\n * final attempt, then surface a diagnosis. The generator + apply are injected so\n * this orchestration is pure and unit-reasonable; the model call lives in the\n * caller (DeepSeek), keeping this file transport-agnostic.\n */\nimport type { CheckResult } from './diagnostics.js';\nimport type { FileMapEntry } from './skills.js';\n\nexport interface RepairModel {\n /** Tier id used for the attempt (e.g. fx-pro). */\n readonly tier: string;\n readonly effort: 'off' | 'high' | 'max';\n}\n\nexport interface RepairContext {\n readonly failures: readonly CheckResult[];\n readonly attempt: number;\n readonly model: RepairModel;\n /** True on the escalated attempt (stronger model). */\n readonly escalated: boolean;\n}\n\nexport interface RepairOptions {\n /** Generate a fix as a file map, given the focused failure context. */\n generate(ctx: RepairContext): Promise<FileMapEntry[]>;\n /** Apply a generated file map to the workspace. */\n applyFiles(files: readonly FileMapEntry[]): void;\n /** Re-run diagnostics; return the results. */\n verify(): CheckResult[];\n /** Same-model retries before escalation (default 2). */\n maxRetries?: number;\n baseModel: RepairModel;\n /** Stronger model used for the final attempt (Pro-MAX). */\n escalateModel: RepairModel;\n onAttempt?(attempt: number, escalated: boolean, remaining: number): void;\n}\n\nexport interface RepairOutcome {\n readonly ok: boolean;\n readonly attempts: number;\n readonly escalated: boolean;\n /** Remaining failures when `ok` is false (the diagnosis to surface). */\n readonly finalFailures: CheckResult[];\n}\n\n/** Compact failure context for the model: failing check + first errors + files. */\nexport function summarizeFailures(failures: readonly CheckResult[]): string {\n return failures\n .map((f) => {\n const head = f.output.split('\\n').filter((l) => l.trim()).slice(0, 20).join('\\n');\n const files = f.failingFiles.length ? `\\nfiles: ${f.failingFiles.join(', ')}` : '';\n return `## ${f.name} FAILED (${f.command})${files}\\n${head}`;\n })\n .join('\\n\\n');\n}\n\n/**\n * Run the bounded verify\u2192repair\u2192escalate loop. Returns `ok` with the attempt count\n * and escalation flag, or the remaining failures to surface as a diagnosis.\n */\nexport async function verifyAndRepair(opts: RepairOptions): Promise<RepairOutcome> {\n const maxRetries = opts.maxRetries ?? 2;\n let failures = opts.verify().filter((r) => !r.ok);\n if (failures.length === 0) return { ok: true, attempts: 0, escalated: false, finalFailures: [] };\n\n // maxRetries same-model attempts, then ONE escalated attempt.\n const totalAttempts = maxRetries + 1;\n let escalatedEver = false;\n for (let attempt = 1; attempt <= totalAttempts; attempt++) {\n const escalated = attempt > maxRetries;\n escalatedEver = escalatedEver || escalated;\n const model = escalated ? opts.escalateModel : opts.baseModel;\n opts.onAttempt?.(attempt, escalated, totalAttempts - attempt);\n\n const files = await opts.generate({ failures, attempt, model, escalated });\n if (files.length > 0) opts.applyFiles(files);\n\n failures = opts.verify().filter((r) => !r.ok);\n if (failures.length === 0) {\n return { ok: true, attempts: attempt, escalated: escalatedEver, finalFailures: [] };\n }\n }\n return { ok: false, attempts: totalAttempts, escalated: escalatedEver, finalFailures: failures };\n}\n", "/**\n * Turn-completion engine \u2014 the fix for \"the agent stops mid-task\".\n *\n * The model is bound to a completion contract (see system-prompt.ts): every\n * reply either calls a tool or ends with the literal marker {@link DONE_MARKER}\n * after a final summary. This module enforces the contract from the outside:\n *\n * - {@link createDoneFilter} strips the marker from the visible stream (the\n * user never sees it) while recording that it appeared;\n * - {@link decideNext} is the pure policy: given how a model call ended\n * (marker? length-cut? unverified writes? failing checks?) it picks the next\n * action \u2014 auto-continue, auto-verify, repair, or accept \u2014 all BOUNDED so a\n * confused model can never loop forever;\n * - {@link runVerifyPhase} runs the repo's own checks (typecheck/lint/test)\n * after the agent wrote files, so \"done\" means \"the goal is reached and the\n * project still passes its checks\", not \"the model said so\".\n */\nimport type { ChatTurn, FutureXClient, Message, UsageReport } from '@fim/futurex-protocol';\nimport { detectChecks, runDiagnosticsAsync, type AsyncCheckResult } from './diagnostics.js';\nimport { DONE_MARKER } from './marker.js';\nimport { accumulateUsage } from './pricing.js';\nimport { renderStream } from './render.js';\nimport { summarizeFailures } from './repair.js';\nimport { info, line, phase, startSpinner, verdictLine } from './ui.js';\n\nexport { createDoneFilter, DONE_MARKER, type DoneFilter } from './marker.js';\n\n/** Bounded continuation budgets \u2014 a confused model can never loop forever. */\nexport const MAX_LENGTH_CONTINUES = 3;\nexport const MAX_FINISH_NUDGES = 2;\nexport const MAX_REPAIR_ROUNDS = 3;\n\n/** Auto-continue prompt when the model hit the output-token ceiling mid-work. */\nexport const NUDGE_LENGTH = [\n 'Your previous message hit the output-length limit mid-work.',\n 'Continue EXACTLY where you stopped \u2014 do not repeat anything already produced.',\n `Finish the remaining steps; end with the summary + ${DONE_MARKER} only when fully done.`,\n].join(' ');\n\n/** Nudge when the model stopped without a tool call and without the marker. */\nexport const NUDGE_FINISH = [\n 'Your last reply ended without a tool call and without the completion marker.',\n `If the request is fully complete and verified, reply with ONLY the marker ${DONE_MARKER}`,\n '(nothing else \u2014 it is hidden from the user). Otherwise continue the remaining work NOW',\n 'using your tools; never stop to narrate what you plan to do.',\n].join(' ');\n\n/** Feed verification failures back as the next instruction (repair round). */\nexport function nudgeVerifyFailures(failureSummary: string): string {\n return [\n 'Automatic verification ran the project checks and found failures:',\n '',\n failureSummary,\n '',\n 'Fix ALL of these now: read the failing files, correct them with write_file,',\n `and only when everything passes finish with your summary + ${DONE_MARKER}.`,\n ].join('\\n');\n}\n\n// --- the completion policy ----------------------------------------------------\n\n/** How verification is applied to a turn. */\nexport type VerifyMode = 'auto' | 'off';\n\n/** Everything the policy needs to know about how the last model call ended. */\nexport interface TurnState {\n /** The completion marker appeared in this call's output. */\n readonly sawMarker: boolean;\n /** Provider finish reason of the last call ('length' = cut off mid-output). */\n readonly finishReason?: string | undefined;\n /** A mutating tool ran since the last verification (or ever, if none ran). */\n readonly mutatedSinceVerify: boolean;\n /** Verification ran for the current state of the tree. */\n readonly verifyRan: boolean;\n /** Verification ran and produced real failures (not timeouts). */\n readonly verifyFailed: boolean;\n readonly lengthContinues: number;\n readonly finishNudges: number;\n readonly repairRounds: number;\n readonly verifyMode: VerifyMode;\n}\n\nexport type NextAction =\n /** The turn is complete \u2014 accept the last text as the final answer. */\n | { readonly kind: 'accept' }\n /** Output was cut at the token ceiling \u2014 auto-continue. */\n | { readonly kind: 'continue-length' }\n /** Files changed and checks haven't run \u2014 run verification now. */\n | { readonly kind: 'verify' }\n /** Verification failed \u2014 feed the failures back for a repair round. */\n | { readonly kind: 'repair' }\n /** No tool call, no marker \u2014 demand completion or continuation. */\n | { readonly kind: 'nudge-finish' };\n\n/**\n * The pure completion policy, applied whenever a model call ends WITHOUT tool\n * calls. Order matters: a length cut is continued first; unverified writes are\n * verified before anything is accepted; real failures get bounded repair\n * rounds; a missing marker gets a bounded \"finish or continue\" nudge; and a\n * verified clean tree is accepted even without the marker (verification is the\n * stronger signal \u2014 no extra model call just for etiquette).\n */\nexport function decideNext(s: TurnState): NextAction {\n if (s.finishReason === 'length' && s.lengthContinues < MAX_LENGTH_CONTINUES) {\n return { kind: 'continue-length' };\n }\n if (s.verifyMode === 'auto' && s.mutatedSinceVerify && !s.verifyRan) {\n return { kind: 'verify' };\n }\n if (s.verifyRan && s.verifyFailed && s.repairRounds < MAX_REPAIR_ROUNDS) {\n return { kind: 'repair' };\n }\n const verifiedClean = s.verifyRan && !s.verifyFailed;\n if (!s.sawMarker && !verifiedClean && s.finishNudges < MAX_FINISH_NUDGES) {\n return { kind: 'nudge-finish' };\n }\n return { kind: 'accept' };\n}\n\n// --- the verification phase ----------------------------------------------------\n\nexport interface VerifyOutcome {\n /** True when no check failed (timeouts don't count as failures). */\n readonly ok: boolean;\n /** False when the repo has no runnable checks (nothing was verified). */\n readonly ran: boolean;\n /** One rendered line per check (for the UI). */\n readonly lines: readonly string[];\n /** Compact failure context to feed back to the model. */\n readonly failureSummary: string;\n /** At least one check was killed at the time budget (inconclusive, not failed). */\n readonly timedOut: boolean;\n readonly results: readonly AsyncCheckResult[];\n}\n\n/** Per-check time budget. A timeout is reported, not repaired. */\nconst VERIFY_CHECK_TIMEOUT_MS = 240_000;\n\n/**\n * Run the repo's own checks (typecheck \u2192 lint \u2192 test, fail-fast; `build` is\n * skipped \u2014 slow and usually covered by typecheck) and shape the outcome for\n * both the UI and the repair nudge.\n */\nexport async function runVerifyPhase(\n root: string,\n opts: { signal?: AbortSignal; timeoutMs?: number } = {},\n): Promise<VerifyOutcome> {\n const checks = detectChecks(root).filter((c) => c.name !== 'build');\n if (checks.length === 0) {\n return { ok: true, ran: false, lines: [], failureSummary: '', timedOut: false, results: [] };\n }\n const results = await runDiagnosticsAsync(root, {\n checks,\n failFast: true,\n timeoutMs: opts.timeoutMs ?? VERIFY_CHECK_TIMEOUT_MS,\n ...(opts.signal ? { signal: opts.signal } : {}),\n });\n const failures = results.filter((r) => !r.ok && !r.timedOut);\n const timedOut = results.some((r) => r.timedOut === true);\n const lines = results.map((r) => {\n const secs = (r.durationMs / 1000).toFixed(1);\n const state = r.timedOut ? 'timed out' : r.ok ? 'pass' : 'FAIL';\n return `${r.name} ${state} (${secs}s)`;\n });\n return {\n ok: failures.length === 0,\n ran: true,\n lines,\n failureSummary: failures.length > 0 ? summarizeFailures(failures) : '',\n timedOut,\n results,\n };\n}\n\n// --- gateway-mode completion loop ----------------------------------------------\n\n/**\n * Hard outer bound on client-driven model rounds per user turn (the gateway\n * itself loops tools within each round). Covers the worst legal case:\n * 1 + length-continues + finish-nudges + repair-rounds, with slack.\n */\nconst MAX_GATEWAY_ROUNDS = 12;\n\nexport interface GatewayTurnDeps {\n readonly client: FutureXClient;\n /** Shared conversation history \u2014 nudges and replies are appended here. */\n readonly history: Message[];\n /** Routing fields re-sent on every round (model/tier/effort/maxTokens). */\n readonly base: Omit<ChatTurn, 'messages' | 'signal'>;\n readonly signal: AbortSignal;\n /** Repo root, for the automatic verification phase. */\n readonly root: string;\n readonly verify: VerifyMode;\n /** True when a mutating tool ran since {@link resetMutated} (client-side). */\n mutated(): boolean;\n resetMutated(): void;\n}\n\n/**\n * Drive a gateway-backed turn to ACTUAL completion. The gateway streams one\n * agentic round; this loop applies the same completion policy as the local\n * agent \u2014 auto-continue on a length cut, verify after writes, bounded repair\n * rounds on failures, and a finish-or-continue nudge when the model stops\n * without the completion marker. Used by the REPL runtime and one-shot\n * `futurex agent` so both finish without the user typing \"continue\".\n */\nexport async function runGatewayTurnToCompletion(\n deps: GatewayTurnDeps,\n): Promise<{ usage?: UsageReport; error?: string }> {\n let usage: UsageReport | undefined;\n let verifyMode = deps.verify;\n let lengthContinues = 0;\n let finishNudges = 0;\n let repairRounds = 0;\n let verifyRan = false;\n let verifyFailed = false;\n let shownPhase: string | null = null;\n let lastVerify: VerifyOutcome | null = null;\n deps.resetMutated();\n\n const showPhase = (p: string): void => {\n if (shownPhase !== p) {\n shownPhase = p;\n phase(p);\n }\n };\n\n for (let round = 0; round < MAX_GATEWAY_ROUNDS; round++) {\n const result = await renderStream(deps.client, {\n ...deps.base,\n messages: deps.history,\n signal: deps.signal,\n });\n if (result.usage) usage = usage ? accumulateUsage(usage, result.usage) : result.usage;\n if (result.error) return { ...(usage ? { usage } : {}), error: result.error };\n if (result.text) deps.history.push({ role: 'assistant', content: result.text });\n if (deps.signal.aborted) return usage ? { usage } : {};\n if (deps.mutated()) {\n verifyRan = false;\n verifyFailed = false;\n }\n\n let proceed = false;\n while (!proceed) {\n const action = decideNext({\n sawMarker: result.sawMarker === true,\n finishReason: result.finishReason,\n mutatedSinceVerify: deps.mutated(),\n verifyRan,\n verifyFailed,\n lengthContinues,\n finishNudges,\n repairRounds,\n verifyMode,\n });\n switch (action.kind) {\n case 'accept': {\n if (verifyFailed && lastVerify) {\n for (const l of lastVerify.lines) {\n if (l.includes('FAIL')) line(verdictLine(false, l));\n }\n info('verification failures remain \u2014 say \"fix the failing checks\" to retry');\n }\n return usage ? { usage } : {};\n }\n case 'continue-length':\n lengthContinues += 1;\n info('output hit the token limit \u2014 continuing automatically');\n deps.history.push({ role: 'user', content: NUDGE_LENGTH });\n proceed = true;\n break;\n case 'nudge-finish':\n finishNudges += 1;\n deps.history.push({ role: 'user', content: NUDGE_FINISH });\n proceed = true;\n break;\n case 'repair':\n showPhase('repair');\n repairRounds += 1;\n info(`repair round ${repairRounds} \u2014 feeding the failures back`);\n deps.history.push({\n role: 'user',\n content: nudgeVerifyFailures(lastVerify?.failureSummary ?? 'checks failed'),\n });\n proceed = true;\n break;\n case 'verify': {\n showPhase('verify');\n const spin = startSpinner('verifying \u2014 running project checks\u2026');\n try {\n lastVerify = await runVerifyPhase(deps.root, { signal: deps.signal });\n } finally {\n spin.stop();\n }\n if (deps.signal.aborted) return usage ? { usage } : {};\n if (!lastVerify.ran) {\n info('no typecheck/lint/test scripts detected \u2014 skipping verification');\n verifyMode = 'off';\n verifyRan = false;\n verifyFailed = false;\n } else {\n deps.resetMutated();\n verifyRan = true;\n verifyFailed = !lastVerify.ok;\n for (const l of lastVerify.lines) line(verdictLine(!l.includes('FAIL'), l));\n if (lastVerify.timedOut) info('a check hit its time budget \u2014 result treated as inconclusive');\n }\n break; // re-decide with the verification outcome\n }\n }\n }\n }\n info('reached the round safety limit \u2014 stopping; send another message to continue');\n return usage ? { usage } : {};\n}\n", "/**\n * Chooses the REPL's agent runtime: gateway-backed when logged in (the backend\n * runs the agent loop; this client only executes the tools it requests), else the\n * local direct-to-DeepSeek loop as an offline fallback. Both satisfy the same\n * {@link ReplAgent} interface, so the REPL is agnostic.\n *\n * The gateway runtime keeps the conversation history client-side and replays it\n * each turn; the backend owns the system prefix, context gathering (agentic tool\n * reads), memory, and the session digest. Either way the turn is driven to\n * ACTUAL completion by finish.ts: auto-continue on a length cut, verify after\n * writes, bounded repair rounds \u2014 the user never has to type \"continue\".\n */\nimport type { AiUsage } from '@fim/ai-sdk';\nimport type { Message } from '@fim/futurex-protocol';\nimport { readCreds } from './creds.js';\nimport { createGatewayClient } from './client/gateway.js';\nimport { createReplAgent, type AgentOptions, type Gate, type ReplAgent } from './agent.js';\nimport { createToolRunner } from './tool-runner.js';\nimport { runGatewayTurnToCompletion } from './finish.js';\nimport { error } from './ui.js';\nimport type { SessionContext } from './context.js';\nimport type { CliOptions } from './options.js';\n\nexport function createReplRuntime(\n ctx: SessionContext,\n opts: CliOptions,\n agentOptions: AgentOptions,\n gate: Gate,\n): ReplAgent {\n const creds = readCreds();\n\n // Not logged in \u2192 local fallback (direct DeepSeek). `futurex login` to use the API.\n if (!creds?.accessToken) {\n return createReplAgent(ctx, opts, agentOptions, gate);\n }\n\n let mutated = false;\n const client = createGatewayClient(creds, {\n gate,\n repoRoot: ctx.root,\n onTool: (t) => {\n if (t.mutating && t.ok) mutated = true;\n },\n ...(opts.useRepo !== undefined ? { useRepo: opts.useRepo } : {}),\n ...(opts.useMemory !== undefined ? { useMemory: opts.useMemory } : {}),\n });\n const history: Message[] = [];\n const toolCount = createToolRunner(ctx.root).count;\n\n return {\n toolCount,\n async turn(userMessage: string, model: string, signal: AbortSignal): Promise<AiUsage | undefined> {\n history.push({ role: 'user', content: userMessage });\n const result = await runGatewayTurnToCompletion({\n client,\n history,\n base: { model },\n signal,\n root: ctx.root,\n verify: agentOptions.verify ?? 'auto',\n mutated: () => mutated,\n resetMutated: () => {\n mutated = false;\n },\n });\n if (result.error && !signal.aborted) error(result.error);\n return result.usage;\n },\n clear() {\n history.length = 0;\n },\n size() {\n return history.length;\n },\n };\n}\n", "/**\n * The FutureX chatbox: a fixed input bar pinned to the bottom of the terminal\n * with streaming output flowing above it \u2014 the experience you'd get from an Ink\n * TUI, hand-rolled with raw ANSI so it needs zero dependencies.\n *\n * Rendering model (the `log-update` pattern): finished output is *committed* to\n * the real terminal scrollback, and only a small DYNAMIC block at the bottom is\n * repainted in place \u2014 a live stream preview, an optional spinner (with elapsed\n * time), a full-width separator rule, the input line (with a fake caret; the\n * real cursor is hidden), the `/`-command suggestions, and a status line with a\n * state dot. Before printing any committed output we erase the dynamic block,\n * write the output (it scrolls into history), then redraw the block underneath \u2014\n * so the input bar always sits at the bottom and never gets interleaved with\n * streaming text.\n *\n * The chatbox is an {@link OutputSink}: install it with `setOutputSink(box)` and\n * every `line`/`info`/`out`/`startSpinner` call elsewhere lands here.\n */\nimport { emitKeypressEvents } from 'node:readline';\nimport { color, type OutputSink } from './ui.js';\nimport type { AskFn, GateAnswer } from './permissions.js';\n\n/** ASCII escape (0x1B) \u2014 derived from char code to avoid literal-escape issues. */\nconst ESC = String.fromCharCode(27);\nconst SPINNER_FRAMES = ['\u280B', '\u2819', '\u2839', '\u2838', '\u283C', '\u2834', '\u2826', '\u2827', '\u2807', '\u280F'];\nconst PROMPT = '\u276F ';\n\n/** Minimal shape of the keypress event node's readline emits in raw mode. */\ninterface KeyInfo {\n sequence?: string;\n name?: string;\n ctrl?: boolean;\n meta?: boolean;\n shift?: boolean;\n}\n\n/** A row in the `/`-command suggestion dropdown. */\nexport interface Suggestion {\n /** The command inserted on Tab (e.g. `/model`). */\n value: string;\n /** A short dim description shown beside it. */\n hint: string;\n}\n\n/** The session state reflected in the status dot + prompt glyph. */\nexport type ChatboxState = 'ready' | 'working';\n\n/** Callbacks the REPL wires into the chatbox. */\nexport interface ChatboxHandlers {\n /** Enter pressed \u2014 the (possibly empty) submitted line. */\n onSubmit(text: string): void;\n /** Ctrl+C \u2014 cancel a running turn, or quit when idle. */\n onInterrupt(): void;\n /** Ctrl+D on an empty line (EOF) \u2014 quit. */\n onExit(): void;\n /** The input buffer changed (drives live `/` suggestions). */\n onChange?(buffer: string): void;\n}\n\nexport interface ChatboxOptions {\n /** Dynamic status text rendered (dimmed) on the bottom line. */\n status(): string;\n /** Current session state \u2014 drives the status dot colour. Default 'ready'. */\n state?(): ChatboxState;\n handlers: ChatboxHandlers;\n}\n\n/** Display width of one code point, biased to over-estimate so we never wrap. */\nfunction cellWidth(cp: number): number {\n if (cp === 0) return 0;\n // Zero-width: combining marks, zero-width spaces, BOM.\n if ((cp >= 0x0300 && cp <= 0x036f) || (cp >= 0x200b && cp <= 0x200f) || cp === 0xfeff) return 0;\n // Wide: CJK, Hangul, Kana, fullwidth, and the common emoji/symbol blocks.\n if (\n (cp >= 0x1100 && cp <= 0x115f) ||\n (cp >= 0x231a && cp <= 0x23ff) || // misc technical (\u231A \u23F3 \u23F0 \u2026)\n (cp >= 0x2600 && cp <= 0x27bf) || // misc symbols + dingbats\n (cp >= 0x2b00 && cp <= 0x2bff) ||\n (cp >= 0x2e80 && cp <= 0x303e) ||\n (cp >= 0x3041 && cp <= 0x33ff) ||\n (cp >= 0x3400 && cp <= 0x4dbf) ||\n (cp >= 0x4e00 && cp <= 0x9fff) ||\n (cp >= 0xa000 && cp <= 0xa4cf) ||\n (cp >= 0xac00 && cp <= 0xd7a3) ||\n (cp >= 0xf900 && cp <= 0xfaff) ||\n (cp >= 0xfe30 && cp <= 0xfe4f) ||\n (cp >= 0xff00 && cp <= 0xff60) ||\n (cp >= 0xffe0 && cp <= 0xffe6) ||\n (cp >= 0x1f000 && cp <= 0x1f0ff) ||\n (cp >= 0x1f300 && cp <= 0x1faff)\n ) {\n return 2;\n }\n return 1;\n}\n\nfunction widthOf(plain: string): number {\n let w = 0;\n for (const ch of plain) w += cellWidth(ch.codePointAt(0) ?? 0);\n return w;\n}\n\n/** Truncate plain text (no ANSI) to `max` display columns, adding `\u2026` when cut. */\nfunction fitWidth(plain: string, max: number): string {\n if (widthOf(plain) <= max) return plain;\n let w = 0;\n let out = '';\n for (const ch of plain) {\n const cw = cellWidth(ch.codePointAt(0) ?? 0);\n if (w + cw > max - 1) break; // reserve 1 col for the ellipsis\n out += ch;\n w += cw;\n }\n return `${out}\u2026`;\n}\n\n/** Keep the TAIL of plain text within `max` columns (for the live stream preview). */\nfunction fitTail(plain: string, max: number): string {\n if (widthOf(plain) <= max) return plain;\n const chars = [...plain];\n let w = 0;\n const picked: string[] = [];\n for (let i = chars.length - 1; i >= 0; i--) {\n const ch = chars[i] ?? '';\n const cw = cellWidth(ch.codePointAt(0) ?? 0);\n if (w + cw > max - 1) break;\n picked.push(ch);\n w += cw;\n }\n picked.reverse();\n return `\u2026${picked.join('')}`;\n}\n\n/**\n * The fixed-input chatbox. Owns stdin (raw mode) and the bottom of stdout while\n * mounted. Construct, {@link start}, install as the output sink, and the REPL\n * drives it via handlers + the OutputSink methods.\n */\nexport class Chatbox implements OutputSink {\n private buffer = '';\n private caret = 0; // code-unit index into buffer\n private readonly history: string[] = [];\n private histIndex = -1; // -1 = editing live buffer; else browsing history\n private histStash = '';\n private liveBuf = ''; // current uncommitted streaming line (no newline)\n private spinnerLabel: string | null = null;\n private spinnerFrame = 0;\n private spinnerSince = 0; // epoch ms when the current spinner appeared\n private suggestions: Suggestion[] = [];\n private drawnLines = 0; // physical lines the dynamic block currently occupies\n private cols = 80;\n private started = false;\n private gatePrompt: string | null = null;\n private gateResolve: ((ans: 'y' | 'n' | 'a' | 'd') => void) | null = null;\n private gateChain: Promise<unknown> = Promise.resolve();\n private spinTimer: ReturnType<typeof setInterval> | null = null;\n private readonly statusFn: () => string;\n private readonly stateFn: () => ChatboxState;\n private readonly handlers: ChatboxHandlers;\n private readonly onKey = (str: string | undefined, key: KeyInfo | undefined): void =>\n this.handleKey(str, key);\n private readonly onResize = (): void => {\n this.cols = process.stdout.columns ?? 80;\n this.render();\n };\n\n constructor(opts: ChatboxOptions) {\n this.statusFn = opts.status;\n this.stateFn = opts.state ?? ((): ChatboxState => 'ready');\n this.handlers = opts.handlers;\n }\n\n /** Enter raw mode, hide the cursor, and paint the input bar. */\n start(): void {\n if (this.started) return;\n this.started = true;\n this.cols = process.stdout.columns ?? 80;\n emitKeypressEvents(process.stdin);\n if (process.stdin.isTTY) process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on('keypress', this.onKey);\n process.stdout.on('resize', this.onResize);\n process.stdout.write(`${ESC}[?25l`); // hide the real cursor; we draw a fake one\n this.spinTimer = setInterval(() => {\n if (this.spinnerLabel !== null && this.liveBuf === '') {\n this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER_FRAMES.length;\n this.render();\n }\n }, 90);\n this.spinTimer.unref?.();\n this.draw();\n }\n\n /** Tear down: clear the bar, restore the cursor and cooked mode. */\n stop(): void {\n if (!this.started) return;\n this.erase();\n this.started = false;\n if (this.spinTimer) {\n clearInterval(this.spinTimer);\n this.spinTimer = null;\n }\n process.stdin.removeListener('keypress', this.onKey);\n process.stdout.removeListener('resize', this.onResize);\n process.stdout.write(`${ESC}[?25h`); // restore the real cursor\n if (process.stdin.isTTY) {\n try {\n process.stdin.setRawMode(false);\n } catch {\n /* not a TTY anymore \u2014 ignore */\n }\n }\n process.stdin.pause();\n }\n\n // --- OutputSink -----------------------------------------------------------\n\n line(text: string): void {\n this.commit(text);\n }\n\n partial(text: string): void {\n this.liveBuf += text;\n let nl = this.liveBuf.indexOf('\\n');\n while (nl !== -1) {\n const done = this.liveBuf.slice(0, nl);\n this.liveBuf = this.liveBuf.slice(nl + 1);\n this.commit(done);\n nl = this.liveBuf.indexOf('\\n');\n }\n this.render();\n }\n\n spinner(label: string | null): void {\n if (label !== null && this.spinnerLabel === null) this.spinnerSince = Date.now();\n this.spinnerLabel = label;\n this.render();\n }\n\n // --- driven by the REPL ---------------------------------------------------\n\n /** Commit any half-streamed line (call when a turn ends). */\n flushLive(): void {\n if (!this.liveBuf) return;\n const rest = this.liveBuf;\n this.liveBuf = '';\n this.commit(rest);\n }\n\n setSuggestions(list: Suggestion[]): void {\n this.suggestions = list;\n this.render();\n }\n\n /** Force a repaint (e.g. the status line changed). */\n refresh(): void {\n this.render();\n }\n\n /**\n * Modal permission prompt: show it in place of the input line and resolve with\n * the user's single-key answer. The in-progress input buffer is preserved.\n * Concurrent calls are serialized \u2014 a second prompt waits for the first.\n */\n askGate(prompt: string): Promise<'y' | 'n' | 'a' | 'd'> {\n const show = (): Promise<'y' | 'n' | 'a' | 'd'> =>\n new Promise((resolve) => {\n this.gatePrompt = prompt;\n this.gateResolve = (ans) => {\n this.gatePrompt = null;\n this.gateResolve = null;\n this.render();\n resolve(ans);\n };\n this.render();\n });\n const next = this.gateChain.then(show, show);\n this.gateChain = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n }\n\n // --- rendering ------------------------------------------------------------\n\n private commit(text: string): void {\n if (!this.started) {\n process.stdout.write(`${text}\\n`);\n return;\n }\n this.erase();\n process.stdout.write(`${text}\\n`);\n this.draw();\n }\n\n private erase(): void {\n if (this.drawnLines === 0) return;\n let s = '\\r';\n if (this.drawnLines > 1) s += `${ESC}[${this.drawnLines - 1}A`;\n s += `${ESC}[0J`; // clear from cursor to end of screen\n process.stdout.write(s);\n this.drawnLines = 0;\n }\n\n private draw(): void {\n if (!this.started) return;\n const lines = this.buildBlock();\n this.drawnLines = lines.length;\n // No trailing newline: the cursor parks at the end of the last line, which\n // is exactly where erase() expects to start from next time.\n process.stdout.write(lines.join('\\n'));\n }\n\n private render(): void {\n if (!this.started) return;\n this.erase();\n this.draw();\n }\n\n private buildBlock(): string[] {\n const w = Math.max(8, this.cols - 1); // leave a column of slack to avoid wrap\n const lines: string[] = [];\n const working = this.stateFn() === 'working';\n\n // 1. live streaming preview, or the spinner while we wait for the first token.\n if (this.liveBuf) {\n lines.push(color.dim('\u2503 ') + color.dim(fitTail(this.liveBuf.replace(/\\s+/g, ' '), w - 2)));\n } else if (this.spinnerLabel !== null) {\n const frame = SPINNER_FRAMES[this.spinnerFrame % SPINNER_FRAMES.length] ?? '';\n const secs = Math.floor((Date.now() - this.spinnerSince) / 1000);\n const elapsed = secs >= 2 ? ` \u00B7 ${secs}s` : '';\n lines.push(\n `${color.cyan(frame)} ${color.dim(fitWidth(`${this.spinnerLabel}${elapsed}`, w - 2))}`,\n );\n }\n\n // 2. full-width separator rule.\n lines.push(color.dim('\u2500'.repeat(w)));\n\n // 3. input line, or the modal permission prompt.\n if (this.gatePrompt) {\n lines.push(`${color.yellow('\u26A0 permission')} ${color.bold(fitWidth(this.gatePrompt, w - 14))}`);\n const plainKeys = ' [y] yes [n] no [a] always allow [d] always deny (enter = no)';\n if (widthOf(plainKeys) <= w) {\n lines.push(\n ` ${color.green('[y]')} yes ${color.red('[n]')} no ${color.cyan('[a]')} always allow ` +\n `${color.cyan('[d]')} always deny ${color.dim('(enter = no)')}`,\n );\n } else {\n lines.push(color.dim(fitWidth(plainKeys, w)));\n }\n } else {\n lines.push(this.renderInput(w, working));\n for (const [i, sug] of this.suggestions.slice(0, 6).entries()) {\n const text = fitWidth(` ${sug.value.padEnd(14)} ${sug.hint}`, w);\n lines.push(i === 0 ? color.cyan(text) : color.dim(text));\n }\n }\n\n // 4. status line with a state dot.\n const dot = working ? color.yellow('\u25CF') : color.green('\u25CF');\n lines.push(`${dot} ${color.dim(fitWidth(this.statusFn(), w - 2))}`);\n\n return lines;\n }\n\n private renderInput(w: number, working: boolean): string {\n const avail = Math.max(4, w - widthOf(PROMPT)); // columns for buffer + caret\n const winChars = avail - 1; // reserve one cell for the caret block\n const start = this.caret > winChars ? this.caret - winChars : 0;\n const visible = this.buffer.slice(start, start + winChars);\n const rel = this.caret - start;\n const before = visible.slice(0, rel);\n const atChar = visible.slice(rel, rel + 1) || ' ';\n const after = visible.slice(rel + 1);\n const caretCell = `${ESC}[7m${atChar}${ESC}[0m`; // reverse-video fake caret\n const glyph = working ? color.yellow(PROMPT) : color.magenta(PROMPT);\n return `${glyph}${before}${caretCell}${after}`;\n }\n\n // --- input ----------------------------------------------------------------\n\n private handleKey(str: string | undefined, key: KeyInfo | undefined): void {\n if (!this.started) return;\n const k = key ?? {};\n\n // Modal gate: capture only plain y / n / a / d (Enter and Ctrl+C default to\n // \"no\"); other modified keys (Ctrl+A, Ctrl+D, \u2026) must not answer the prompt.\n if (this.gateResolve) {\n const resolve = this.gateResolve;\n if (k.ctrl && k.name === 'c') return resolve('n');\n if (k.ctrl || k.meta) return;\n if (k.name === 'return' || k.name === 'enter') return resolve('n');\n const ch = (str ?? k.name ?? '').toLowerCase();\n if (ch === 'y' || ch === 'n' || ch === 'a' || ch === 'd') return resolve(ch);\n return;\n }\n\n if (k.ctrl && k.name === 'c') return this.handlers.onInterrupt();\n if (k.ctrl && k.name === 'd') {\n if (this.buffer === '') return this.handlers.onExit();\n this.buffer = this.buffer.slice(0, this.caret) + this.buffer.slice(this.caret + 1);\n return this.afterEdit();\n }\n\n switch (k.name) {\n case 'return':\n case 'enter': {\n const text = this.buffer;\n this.buffer = '';\n this.caret = 0;\n this.histIndex = -1;\n if (text.trim()) {\n this.history.push(text);\n if (this.history.length > 200) this.history.shift();\n }\n this.suggestions = [];\n this.handlers.onSubmit(text);\n this.render();\n return;\n }\n case 'backspace':\n if (this.caret > 0) {\n this.buffer = this.buffer.slice(0, this.caret - 1) + this.buffer.slice(this.caret);\n this.caret -= 1;\n }\n return this.afterEdit();\n case 'delete':\n this.buffer = this.buffer.slice(0, this.caret) + this.buffer.slice(this.caret + 1);\n return this.afterEdit();\n case 'left':\n if (this.caret > 0) this.caret -= 1;\n return this.render();\n case 'right':\n if (this.caret < this.buffer.length) this.caret += 1;\n return this.render();\n case 'home':\n this.caret = 0;\n return this.render();\n case 'end':\n this.caret = this.buffer.length;\n return this.render();\n case 'up':\n return this.historyPrev();\n case 'down':\n return this.historyNext();\n case 'tab':\n if (this.suggestions.length > 0) {\n this.buffer = `${this.suggestions[0]?.value ?? ''} `;\n this.caret = this.buffer.length;\n this.suggestions = [];\n this.afterEdit();\n }\n return;\n default:\n break;\n }\n\n if (k.ctrl) {\n switch (k.name) {\n case 'a':\n this.caret = 0;\n return this.render();\n case 'e':\n this.caret = this.buffer.length;\n return this.render();\n case 'u':\n this.buffer = this.buffer.slice(this.caret);\n this.caret = 0;\n return this.afterEdit();\n case 'k':\n this.buffer = this.buffer.slice(0, this.caret);\n return this.afterEdit();\n case 'w':\n return this.deleteWord();\n default:\n return;\n }\n }\n\n // Printable insertion (strip any stray control chars).\n if (str && !k.ctrl && !k.meta) {\n const clean = [...str]\n .filter((ch) => {\n const c = ch.codePointAt(0) ?? 0;\n return c >= 0x20 && c !== 0x7f;\n })\n .join('');\n if (clean) {\n this.buffer = this.buffer.slice(0, this.caret) + clean + this.buffer.slice(this.caret);\n this.caret += clean.length;\n this.afterEdit();\n }\n }\n }\n\n private afterEdit(): void {\n this.histIndex = -1;\n this.handlers.onChange?.(this.buffer);\n this.render();\n }\n\n private historyPrev(): void {\n if (this.history.length === 0) return;\n if (this.histIndex === -1) {\n this.histStash = this.buffer;\n this.histIndex = this.history.length - 1;\n } else if (this.histIndex > 0) {\n this.histIndex -= 1;\n }\n this.buffer = this.history[this.histIndex] ?? '';\n this.caret = this.buffer.length;\n this.handlers.onChange?.(this.buffer);\n this.render();\n }\n\n private historyNext(): void {\n if (this.histIndex === -1) return;\n if (this.histIndex < this.history.length - 1) {\n this.histIndex += 1;\n this.buffer = this.history[this.histIndex] ?? '';\n } else {\n this.histIndex = -1;\n this.buffer = this.histStash;\n }\n this.caret = this.buffer.length;\n this.handlers.onChange?.(this.buffer);\n this.render();\n }\n\n private deleteWord(): void {\n let i = this.caret;\n while (i > 0 && this.buffer[i - 1] === ' ') i -= 1;\n while (i > 0 && this.buffer[i - 1] !== ' ') i -= 1;\n this.buffer = this.buffer.slice(0, i) + this.buffer.slice(this.caret);\n this.caret = i;\n this.afterEdit();\n }\n}\n\n/**\n * A permission prompt backed by the chatbox's modal: pauses for a single\n * keypress. `[a]lways allow` / `[d] always deny` are persisted per action kind\n * by the permission gate that wraps this ask (see permissions.ts).\n */\nexport function createChatboxAsk(box: Chatbox): AskFn {\n const toAnswer: Record<'y' | 'n' | 'a' | 'd', GateAnswer> = {\n y: 'yes',\n n: 'no',\n a: 'always-allow',\n d: 'always-deny',\n };\n return async (req) => {\n const caution = req.kind === 'run' ? ' \u2014 runs with your shell access' : '';\n const ans = await box.askGate(`${req.kind} \u00B7 ${req.preview}${caution}`);\n return toAnswer[ans];\n };\n}\n", "/**\n * `futurex permissions [show|set <kind> <ask|allow|deny>|reset]` and the REPL's\n * `/permissions` \u2014 view, change, and revoke the project's persistent per-kind\n * consent (see permissions.ts). `show` is the default.\n */\nimport { ACTION_KINDS } from '@fim/futurex-tools';\nimport {\n describePermissions,\n parseActionKind,\n parseConsent,\n resetProjectPermissions,\n setConsent,\n} from './permissions.js';\nimport { color, error, info, line } from './ui.js';\n\nexport function runPermissions(root: string, rest: string): void {\n const [sub = 'show', ...args] = rest.trim().split(/\\s+/).filter(Boolean);\n\n switch (sub.toLowerCase()) {\n case 'show':\n case '': {\n info(`permissions for ${root} (stored in ~/.futurex/permissions.json)`);\n for (const lineText of describePermissions(root)) line(` ${lineText}`);\n line(color.dim(' change: permissions set <kind> <ask|allow|deny> \u00B7 revoke all: permissions reset'));\n return;\n }\n case 'reset': {\n resetProjectPermissions(root);\n info('permissions reset \u2014 every action kind will ask again');\n return;\n }\n case 'set': {\n const kind = args[0] !== undefined ? parseActionKind(args[0]) : undefined;\n const consent = args[1] !== undefined ? parseConsent(args[1]) : undefined;\n if (!kind || !consent) {\n error(`usage: permissions set <${ACTION_KINDS.join('|')}> <ask|allow|deny>`);\n return;\n }\n setConsent(root, kind, consent);\n info(`${kind} \u2192 ${consent === 'ask' ? 'ask each time' : `always ${consent}`}`);\n return;\n }\n default:\n error(`unknown subcommand \"${sub}\" (expected: show | set | reset)`);\n }\n}\n", "/**\n * Project memory (Blueprint v2 P6 / \u00A79): `futurex-memory.md` at the repo root with\n * fixed headings, bootstrapped from the repo card + symbol index, and bounded by a\n * token-aware /compact that regenerates the DERIVED sections and archives an\n * overlong Decisions log to `.futurex/logs/`.\n */\nimport { existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { RepoCard } from '@fim/futurex-protocol';\nimport type { SymbolIndex } from '@fim/futurex-context';\nimport { MEMORY_FILENAME, readMemory, saveMemory } from './repo.js';\n\n/** Fixed headings, in order. */\nexport const MEMORY_HEADINGS = [\n 'Overview',\n 'Stack',\n 'Architecture map',\n 'Key modules',\n 'Conventions',\n 'Decisions log',\n 'Open tasks',\n] as const;\n\nconst MEMORY_TITLE = '# FutureX project memory';\n\n/** Sections regenerated from the repo (card + symbol index) on bootstrap/compact. */\nconst DERIVED = new Set<string>(['Overview', 'Stack', 'Architecture map', 'Key modules']);\n\nconst PLACEHOLDERS: Record<string, string> = {\n Conventions: '_(Add project conventions \u2014 naming, structure, testing \u2014 here.)_',\n 'Decisions log': '_(Append decisions as `- YYYY-MM-DD: <decision>`.)_',\n 'Open tasks': '_(Track open tasks here.)_',\n};\n\n/** ~chars-per-token heuristic (no tokenizer dependency). */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/** Soft ceiling: above this, /compact regenerates derived sections + archives decisions. */\nexport const MEMORY_TOKEN_LIMIT = 7000;\n\nfunction overviewSection(card: RepoCard | null): string {\n const name = card?.name ?? 'This project';\n const stack = [card?.framework, card?.backend, card?.orm]\n .filter((x): x is string => Boolean(x))\n .join(' + ');\n return `${name}${stack ? ` \u2014 ${stack}` : ''}. _(Edit to describe the project's purpose & goals.)_`;\n}\n\nfunction stackSection(card: RepoCard | null): string {\n if (!card) return '_(no manifest detected)_';\n const rows: Array<[string, string | undefined]> = [\n ['Language', card.language],\n ['Framework', card.framework],\n ['Backend', card.backend],\n ['ORM', card.orm],\n ['Package manager', card.packageManager],\n ['Tests', card.test],\n ];\n const lines = rows.filter((r): r is [string, string] => Boolean(r[1])).map(([k, v]) => `- ${k}: ${v}`);\n return lines.length > 0 ? lines.join('\\n') : '_(stack not detected)_';\n}\n\nfunction architectureSection(root: string): string {\n let dirs: string[];\n try {\n dirs = readdirSync(root, { withFileTypes: true })\n .filter((d) => d.isDirectory() && !d.name.startsWith('.') && d.name !== 'node_modules')\n .map((d) => d.name)\n .sort()\n .slice(0, 30);\n } catch {\n return '_(unreadable)_';\n }\n return dirs.length > 0 ? dirs.map((d) => `- \\`${d}/\\``).join('\\n') : '_(no top-level directories)_';\n}\n\nfunction keyModulesSection(symbols: SymbolIndex | null): string {\n if (!symbols) return '_(run `futurex index` to populate from the symbol index)_';\n const byFile = new Map<string, number>();\n for (const d of symbols.all()) {\n if (d.exported) byFile.set(d.file, (byFile.get(d.file) ?? 0) + 1);\n }\n const top = [...byFile.entries()].sort((a, b) => b[1] - a[1]).slice(0, 15);\n return top.length > 0\n ? top.map(([f, n]) => `- \\`${f}\\` \u2014 ${n} exported symbol${n === 1 ? '' : 's'}`).join('\\n')\n : '_(no exported symbols indexed)_';\n}\n\nfunction derivedSection(\n heading: string,\n root: string,\n card: RepoCard | null,\n symbols: SymbolIndex | null,\n): string {\n switch (heading) {\n case 'Overview':\n return overviewSection(card);\n case 'Stack':\n return stackSection(card);\n case 'Architecture map':\n return architectureSection(root);\n case 'Key modules':\n return keyModulesSection(symbols);\n default:\n return '';\n }\n}\n\n/** Parse a memory markdown into a heading\u2192body map (bodies trimmed). */\nexport function parseMemorySections(md: string): Map<string, string> {\n const out = new Map<string, string>();\n for (const part of md.split(/^## /m)) {\n const nl = part.indexOf('\\n');\n if (nl === -1) continue;\n const heading = part.slice(0, nl).trim();\n if (!heading || heading.startsWith('#')) continue; // skip the title block\n out.set(heading, part.slice(nl + 1).trim());\n }\n return out;\n}\n\n/** Render sections in the fixed heading order, appending any extras. */\nfunction renderMemory(sections: Map<string, string>): string {\n const blocks: string[] = [MEMORY_TITLE];\n const seen = new Set<string>();\n for (const heading of MEMORY_HEADINGS) {\n seen.add(heading);\n blocks.push(`## ${heading}\\n\\n${sections.get(heading) ?? PLACEHOLDERS[heading] ?? '_(empty)_'}`);\n }\n for (const [heading, body] of sections) {\n if (!seen.has(heading)) blocks.push(`## ${heading}\\n\\n${body}`);\n }\n return `${blocks.join('\\n\\n')}\\n`;\n}\n\n/** Build a provisional memory skeleton from the repo card + symbol index. */\nexport function buildMemorySkeleton(\n root: string,\n card: RepoCard | null,\n symbols: SymbolIndex | null,\n): string {\n const sections = new Map<string, string>();\n for (const heading of MEMORY_HEADINGS) {\n sections.set(\n heading,\n DERIVED.has(heading) ? derivedSection(heading, root, card, symbols) : PLACEHOLDERS[heading] ?? '',\n );\n }\n return renderMemory(sections);\n}\n\n/** Write a provisional futurex-memory.md if absent. Returns whether it was created. */\nexport function bootstrapMemory(\n root: string,\n card: RepoCard | null,\n symbols: SymbolIndex | null,\n): boolean {\n if (readMemory(root) !== null || existsSync(join(root, MEMORY_FILENAME))) return false;\n saveMemory(root, buildMemorySkeleton(root, card, symbols));\n return true;\n}\n\nexport interface CompactResult {\n action: 'compacted' | 'unchanged' | 'absent';\n beforeTokens: number;\n afterTokens: number;\n archived?: string;\n}\n\nfunction archiveDecisions(root: string, lines: string[]): string {\n const stamp = new Date().toISOString().replace(/[:.]/g, '-');\n const relPosix = `.futurex/logs/decisions-${stamp}.md`;\n mkdirSync(join(root, '.futurex', 'logs'), { recursive: true });\n writeFileSync(join(root, '.futurex', 'logs', `decisions-${stamp}.md`), `# Archived decisions (${stamp})\\n\\n${lines.join('\\n')}\\n`, 'utf8');\n return relPosix;\n}\n\n/**\n * Bound memory growth: when over {@link MEMORY_TOKEN_LIMIT}, regenerate the derived\n * sections (Overview/Stack/Architecture/Key modules from the live card + symbol\n * index) and compress the Decisions log \u2014 keep the latest 20 entries inline, archive\n * the rest to `.futurex/logs/`. Below the limit it is a no-op.\n */\nexport function compactMemory(\n root: string,\n card: RepoCard | null,\n symbols: SymbolIndex | null,\n): CompactResult {\n const existing = readMemory(root);\n if (existing === null) return { action: 'absent', beforeTokens: 0, afterTokens: 0 };\n const before = estimateTokens(existing);\n if (before <= MEMORY_TOKEN_LIMIT) return { action: 'unchanged', beforeTokens: before, afterTokens: before };\n\n const sections = parseMemorySections(existing);\n for (const heading of DERIVED) sections.set(heading, derivedSection(heading, root, card, symbols));\n\n let archived: string | undefined;\n const entries = (sections.get('Decisions log') ?? '').split('\\n').filter((l) => l.trim().startsWith('- '));\n if (entries.length > 20) {\n archived = archiveDecisions(root, entries.slice(0, -20));\n sections.set('Decisions log', [`_(older entries archived to \\`${archived}\\`)_`, '', ...entries.slice(-20)].join('\\n'));\n }\n\n const rebuilt = renderMemory(sections);\n saveMemory(root, rebuilt);\n return { action: 'compacted', beforeTokens: before, afterTokens: estimateTokens(rebuilt), archived };\n}\n", "/**\n * `futurex init` / `futurex compact` \u2014 bootstrap and bound the project memory file.\n */\nimport { buildRepoCard, findRepoRoot, MEMORY_FILENAME } from './repo.js';\nimport { loadRetriever } from './index-store.js';\nimport { bootstrapMemory, compactMemory, MEMORY_TOKEN_LIMIT } from './memory.js';\nimport { info } from './ui.js';\n\n/** `futurex init` \u2014 write a provisional futurex-memory.md if one is absent. */\nexport function runInit(): void {\n const root = findRepoRoot();\n const card = buildRepoCard(root);\n const symbols = loadRetriever(root)?.symbols ?? null;\n if (bootstrapMemory(root, card, symbols)) {\n info(`created ${MEMORY_FILENAME} at ${root} \u2014 edit it to guide FutureX`);\n } else {\n info(`${MEMORY_FILENAME} already exists \u2014 leaving it untouched`);\n }\n}\n\n/** `futurex compact` \u2014 bound memory growth (regenerate derived sections + archive decisions). */\nexport function runCompact(): void {\n const root = findRepoRoot();\n const card = buildRepoCard(root);\n const symbols = loadRetriever(root)?.symbols ?? null;\n const res = compactMemory(root, card, symbols);\n switch (res.action) {\n case 'absent':\n info(`no ${MEMORY_FILENAME} \u2014 run \\`futurex init\\` first`);\n return;\n case 'unchanged':\n info(`${MEMORY_FILENAME} is ~${res.beforeTokens} tok (\u2264 ${MEMORY_TOKEN_LIMIT}) \u2014 no compaction needed`);\n return;\n case 'compacted':\n info(\n `compacted ${MEMORY_FILENAME}: ~${res.beforeTokens} \u2192 ~${res.afterTokens} tok` +\n (res.archived ? ` \u00B7 decisions archived to ${res.archived}` : ''),\n );\n return;\n }\n}\n", "/**\n * `futurex build \"<task>\"` / REPL `/build` \u2014 execute AGAINST the pre-build plan\n * (plan-command.ts) instead of improvising: each plan task becomes one agent\n * turn (with the plan's goal + decided tooling injected), progress is evaluated\n * against the acceptance criteria after every task \u2014 the build STOPS when all\n * are met \u2014 and the token budget (effort \u00D7 value) is enforced throughout.\n * Executed tasks are checkpointed, so a killed build resumes where it stopped.\n */\nimport { createInterface } from 'node:readline';\nimport { createAiClient } from '@fim/ai-sdk';\nimport { evaluateGoal, type GoalEvaluation } from './goal.js';\nimport { loadContext } from './context.js';\nimport { createPermissionGate } from './permissions.js';\nimport { createReadlineAsk } from './agent.js';\nimport { createReplRuntime } from './repl-runtime.js';\nimport { runDiagnostics } from './diagnostics.js';\nimport { ensureBuildPlan, printBuildPlan, type PlanFlags } from './plan-command.js';\nimport { scheduleByDeps, type BuildPlan, type Task } from './planner.js';\nimport { readCheckpoint, writeCheckpoint } from './pipeline.js';\nimport { addUsage, emptyTotals, formatUsage } from './pricing.js';\nimport { findRepoRoot } from './repo.js';\nimport type { CliOptions } from './options.js';\nimport { color, error, info, line } from './ui.js';\n\n/** Why an execution ended. */\nexport type BuildStatus = 'done' | 'tasks-exhausted' | 'budget-exhausted' | 'aborted';\n\nexport interface BuildResult {\n readonly status: BuildStatus;\n readonly completedTasks: readonly string[];\n readonly evaluation?: GoalEvaluation;\n}\n\n/** Everything executePlan needs, injected so the loop is unit-testable. */\nexport interface ExecutePlanDeps {\n readonly plan: BuildPlan;\n /** Run one agent turn for a task prompt. */\n turn(prompt: string): Promise<void>;\n /** Judge accumulated evidence against the goal's criteria. */\n evaluate(evidence: string): Promise<GoalEvaluation>;\n /** Optional validation pass (typecheck/lint/test); lines feed the evidence. */\n verify?(): readonly { name: string; ok: boolean }[];\n /** Output tokens spent so far (the budget is an output-token allowance). */\n usedTokens(): number;\n /** Has this task already been executed (resume)? */\n isTaskDone(taskId: string): boolean;\n markTaskDone(taskId: string): void;\n report(text: string): void;\n readonly signal?: AbortSignal;\n}\n\n/** The plan context injected into every task turn, so tooling isn't improvised. */\nexport function buildTaskPrompt(plan: BuildPlan, task: Task, isFirst: boolean): string {\n const parts: string[] = [\n `You are executing ONE step of an approved build plan. Work only toward this step.`,\n `END GOAL: ${plan.goal.statement}`,\n ];\n if (plan.tooling.length > 0) {\n parts.push(\n 'TOOLING (decided in the plan \u2014 use these, do not substitute alternatives):',\n ...plan.tooling.map((t) => `- ${t.area}: ${t.chosen}`),\n );\n }\n if (isFirst && plan.research.length > 0) {\n parts.push(\n 'Before implementing, ground yourself on these questions (use read_file/grep_search/list_dir):',\n ...plan.research.map((r) => `- ${r.question}`),\n );\n }\n parts.push(`STEP ${task.id}: ${task.title}`, task.description);\n if (task.targets.length > 0) parts.push(`Expected to touch: ${task.targets.join(', ')}`);\n return parts.join('\\n');\n}\n\n/**\n * Execute the plan's task DAG in dependency order: budget check \u2192 agent turn \u2192\n * checkpoint \u2192 (scheduled) validation pass \u2192 goal evaluation; stop on done.\n */\nexport async function executePlan(deps: ExecutePlanDeps): Promise<BuildResult> {\n const { plan } = deps;\n const ordered = scheduleByDeps(plan.tasks).flat();\n const completed: string[] = [];\n const evidence: string[] = [\n `Goal: ${plan.goal.statement}`,\n `Planned tasks: ${plan.tasks.map((t) => `${t.id} (${t.title})`).join(', ')}`,\n ];\n let evaluation: GoalEvaluation | undefined;\n\n // Spread the budgeted validation passes evenly across the task list; the\n // last task always qualifies, so even a 1-task plan gets its pass.\n const passes = plan.budget.validationPasses;\n const interval = passes > 0 ? Math.max(1, Math.floor(ordered.length / (passes + 1))) : Number.POSITIVE_INFINITY;\n let passesRun = 0;\n let researchInjected = false;\n\n for (let i = 0; i < ordered.length; i++) {\n const task = ordered[i];\n if (!task) continue;\n if (deps.signal?.aborted) return { status: 'aborted', completedTasks: completed, ...(evaluation ? { evaluation } : {}) };\n\n if (deps.isTaskDone(task.id)) {\n completed.push(task.id);\n evidence.push(`Task ${task.id} \"${task.title}\": completed in a previous run.`);\n deps.report(`\u2713 ${task.id} ${task.title} (resumed)`);\n continue;\n }\n\n const used = deps.usedTokens();\n if (used >= plan.budget.tokens) {\n deps.report(\n `budget exhausted: ${used.toLocaleString()} / ${plan.budget.tokens.toLocaleString()} output tokens \u2014 ` +\n 'stopping (re-run with --budget <n> or a higher --value to continue)',\n );\n return { status: 'budget-exhausted', completedTasks: completed, ...(evaluation ? { evaluation } : {}) };\n }\n\n deps.report(`\u25B6 ${task.id} ${task.title}`);\n // Research grounds the FIRST task actually executed this run \u2014 also after a\n // resume, where the new process has none of the prior grounding in context.\n await deps.turn(buildTaskPrompt(plan, task, !researchInjected));\n researchInjected = true;\n if (deps.signal?.aborted) return { status: 'aborted', completedTasks: completed, ...(evaluation ? { evaluation } : {}) };\n deps.markTaskDone(task.id);\n completed.push(task.id);\n evidence.push(`Task ${task.id} \"${task.title}\": executed (targets: ${task.targets.join(', ') || 'n/a'}).`);\n\n if (deps.verify && passesRun < passes && ((i + 1) % interval === 0 || i === ordered.length - 1)) {\n passesRun += 1;\n const results = deps.verify();\n const summary = results.map((r) => `${r.name}=${r.ok ? 'pass' : 'FAIL'}`).join(' ');\n evidence.push(`Validation pass ${passesRun}: ${summary || 'no checks detected'}`);\n deps.report(`verify: ${summary || 'no checks detected'}`);\n }\n\n evaluation = await deps.evaluate(evidence.join('\\n'));\n deps.report(\n `progress: ${evaluation.met.length}/${plan.goal.criteria.length} criteria met` +\n (evaluation.remaining.length > 0 ? ` \u2014 remaining: ${evaluation.remaining.join(', ')}` : ''),\n );\n if (evaluation.done) {\n deps.report('all acceptance criteria met \u2014 stopping here instead of continuing open-endedly');\n return { status: 'done', completedTasks: completed, evaluation };\n }\n }\n\n return { status: 'tasks-exhausted', completedTasks: completed, ...(evaluation ? { evaluation } : {}) };\n}\n\n/** `futurex build \"<task>\"` \u2014 plan (or resume the plan), then execute against it. */\nexport async function runBuild(task: string, opts: CliOptions, flags: PlanFlags = {}): Promise<void> {\n const q = task.trim();\n if (!q) {\n error('usage: futurex build \"<task>\"');\n process.exitCode = 1;\n return;\n }\n\n const outcome = await ensureBuildPlan(q, opts, flags, (name, status) =>\n info(` ${status === 'cached' ? '\u2713 resumed' : '\u2026 running'} ${name}`),\n );\n if (outcome.kind === 'clarify') {\n info('one question before building:');\n line(` ? ${outcome.question}`);\n line(color.dim('(answer by re-running build with the detail added)'));\n return;\n }\n const { id, plan } = outcome;\n printBuildPlan(plan);\n line();\n\n const ctx = loadContext(opts);\n const root = findRepoRoot();\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const gate = createPermissionGate(ctx.root, createReadlineAsk(rl));\n const ac = new AbortController();\n const onSigint = (): void => ac.abort();\n // With a readline attached to the TTY, Ctrl+C is delivered to the INTERFACE,\n // not the process \u2014 listen on both so the first Ctrl+C aborts cleanly.\n rl.on('SIGINT', onSigint);\n process.on('SIGINT', onSigint);\n const totals = emptyTotals();\n const ai = createAiClient({ provider: 'deepseek' });\n\n try {\n const runtime = createReplRuntime(ctx, opts, { autoApprove: false, maxSteps: 12 }, gate);\n const result = await executePlan({\n plan,\n signal: ac.signal,\n async turn(prompt) {\n const usage = await runtime.turn(prompt, opts.model, ac.signal);\n if (usage) addUsage(totals, opts.model, usage);\n },\n evaluate: (evidence) => evaluateGoal(plan.goal, evidence, ai, { model: opts.model }),\n verify: () => runDiagnostics(root).map((r) => ({ name: r.name, ok: r.ok })),\n usedTokens: () => totals.outputTokens + totals.reasoningTokens,\n isTaskDone: (taskId) => readCheckpoint(id, `exec-${taskId}`) !== null,\n markTaskDone: (taskId) => writeCheckpoint(id, `exec-${taskId}`, { completed: true }),\n report: (text) => info(text),\n });\n\n line();\n info(`build ${result.status} \u00B7 ${result.completedTasks.length}/${plan.tasks.length} tasks \u00B7 ${formatUsage(totals).join(' \u00B7 ')}`);\n if (result.evaluation && !result.evaluation.done) {\n info(`remaining criteria: ${result.evaluation.remaining.join(', ')}`);\n }\n } catch (err) {\n if (!ac.signal.aborted) {\n error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n } else {\n info('cancelled');\n }\n } finally {\n rl.close();\n process.removeListener('SIGINT', onSigint);\n }\n}\n", "/**\n * Session end-goal + definition-of-done. At the start of a planned session the\n * user's request is distilled into an explicit goal statement plus acceptance\n * criteria (or ONE clarifying question when too vague). The goal is persisted\n * as a pipeline checkpoint, feeds the planner, and after each major build step\n * progress is re-evaluated against the criteria \u2014 the build STOPS when all are\n * met instead of continuing open-endedly.\n */\nimport { effortToReasoning, type EffortLevel } from '@fim/futurex-protocol';\n\n/** Minimal model surface (injectable for tests). */\nexport interface ChatClient {\n chat(request: {\n system?: string;\n messages: { role: 'system' | 'user' | 'assistant'; content: string }[];\n reasoning?: boolean | { effort?: 'high' | 'max' };\n model?: string;\n maxTokens?: number;\n }): Promise<string>;\n}\n\nexport interface AcceptanceCriterion {\n readonly id: string;\n readonly text: string;\n}\n\nexport interface SessionGoal {\n /** One-sentence end-goal statement. */\n readonly statement: string;\n readonly criteria: readonly AcceptanceCriterion[];\n /** The original user request the goal was derived from. */\n readonly task: string;\n}\n\nexport type GoalResult =\n | { readonly kind: 'goal'; readonly goal: SessionGoal }\n | { readonly kind: 'clarify'; readonly question: string };\n\nconst GOAL_SYSTEM = [\n 'You distill a coding request into an explicit end goal and a definition of done.',\n 'Respond with ONLY one minified JSON object \u2014 no prose, no code fence \u2014 that is EITHER',\n '{\"kind\":\"goal\",\"statement\":string,\"criteria\":string[]}',\n 'OR {\"kind\":\"clarify\",\"question\":string} when the request is too vague to state a goal confidently.',\n 'The statement is one sentence. Criteria are 2-6 concrete, checkable conditions.',\n 'Ask at most ONE clarifying question, and only when truly necessary.',\n].join('\\n');\n\nfunction extractJson(raw: string): Record<string, unknown> | null {\n const start = raw.indexOf('{');\n const end = raw.lastIndexOf('}');\n if (start === -1 || end <= start) return null;\n try {\n return JSON.parse(raw.slice(start, end + 1)) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n/** Parse a goal reply (defensive \u2014 model output is untrusted). */\nexport function parseGoalResult(raw: string, task: string): GoalResult {\n const json = extractJson(raw);\n if (!json) return { kind: 'clarify', question: 'Could you restate what you want built, in one or two sentences?' };\n if (json.kind === 'clarify') {\n const question = typeof json.question === 'string' && json.question ? json.question : 'Could you add more detail to the request?';\n return { kind: 'clarify', question };\n }\n const statement = typeof json.statement === 'string' ? json.statement.trim() : '';\n const criteria = (Array.isArray(json.criteria) ? json.criteria : [])\n .filter((c): c is string => typeof c === 'string' && c.trim().length > 0)\n .map((text, i) => ({ id: `c${i + 1}`, text: text.trim() }));\n if (!statement || criteria.length === 0) {\n return { kind: 'clarify', question: 'What does \"done\" look like for this task?' };\n }\n return { kind: 'goal', goal: { statement, criteria, task } };\n}\n\n/** Derive the session's end goal + acceptance criteria from the request. */\nexport async function deriveGoal(\n task: string,\n context: string,\n ai: ChatClient,\n opts: { model: string; effort: EffortLevel; maxTokens?: number },\n): Promise<GoalResult> {\n const reply = await ai.chat({\n system: GOAL_SYSTEM,\n messages: [{ role: 'user', content: `CONTEXT:\\n${context.slice(0, 4000)}\\n\\nREQUEST:\\n${task}` }],\n reasoning: effortToReasoning(opts.effort),\n model: opts.model,\n maxTokens: opts.maxTokens ?? 1000,\n });\n return parseGoalResult(reply, task);\n}\n\nexport interface GoalEvaluation {\n /** Criterion ids judged satisfied by the evidence so far. */\n readonly met: readonly string[];\n /** Criterion ids still outstanding. */\n readonly remaining: readonly string[];\n readonly summary: string;\n /** True when every criterion is met \u2014 the signal to stop building. */\n readonly done: boolean;\n}\n\nconst EVAL_SYSTEM = [\n 'You judge progress against a definition of done.',\n 'Given acceptance criteria (each with an id) and evidence of work performed, respond with ONLY one',\n 'minified JSON object {\"met\":string[],\"remaining\":string[],\"summary\":string} where met/remaining',\n 'partition the criterion ids. Be strict: a criterion is met only when the evidence shows it.',\n].join('\\n');\n\n/** Parse an evaluation reply; on garbage, fail safe (nothing met). */\nexport function parseGoalEvaluation(raw: string, goal: SessionGoal): GoalEvaluation {\n const ids = goal.criteria.map((c) => c.id);\n const json = extractJson(raw);\n const claimed = new Set(\n (Array.isArray(json?.met) ? json.met : []).filter(\n (x): x is string => typeof x === 'string' && ids.includes(x),\n ),\n );\n const met = ids.filter((id) => claimed.has(id));\n const remaining = ids.filter((id) => !claimed.has(id));\n const summary = typeof json?.summary === 'string' ? json.summary : '';\n return { met, remaining, summary, done: remaining.length === 0 && met.length > 0 };\n}\n\n/** Evaluate evidence (step results, diffs, verify output) against the goal. */\nexport async function evaluateGoal(\n goal: SessionGoal,\n evidence: string,\n ai: ChatClient,\n opts: { model: string; maxTokens?: number },\n): Promise<GoalEvaluation> {\n const criteriaText = goal.criteria.map((c) => `${c.id}: ${c.text}`).join('\\n');\n const reply = await ai.chat({\n system: EVAL_SYSTEM,\n messages: [\n {\n role: 'user',\n content:\n `GOAL: ${goal.statement}\\n\\nCRITERIA:\\n${criteriaText}\\n\\n` +\n `EVIDENCE OF WORK SO FAR:\\n${evidence.slice(0, 8000)}`,\n },\n ],\n reasoning: false,\n model: opts.model,\n maxTokens: opts.maxTokens ?? 800,\n });\n return parseGoalEvaluation(reply, goal);\n}\n\n/** Render the goal for banners and checkpoints. */\nexport function formatGoal(goal: SessionGoal): string[] {\n return [\n `goal: ${goal.statement}`,\n ...goal.criteria.map((c) => ` ${c.id}. ${c.text}`),\n ];\n}\n", "/**\n * Budget composition \u2014 THE one place user-selected effort and inferred project\n * value combine into the build's token/depth allowance:\n *\n * tokens = baseTokensByEffort[effort] \u00D7 valueTiers[tier].multiplier\n * capped by the user's --budget override and the config hard cap.\n *\n * Depth knobs (research steps, validation passes) start from the effort profile\n * and are scaled by the same value multiplier. Everything is reported back in\n * `explanation` so the user can see \u2014 and override \u2014 exactly what was decided.\n */\nimport type { EffortLevel } from '@fim/futurex-protocol';\nimport type { PlanningConfig, ValueTier } from './planning-config.js';\n\nexport interface Budget {\n /** Output-token allowance for the whole build. */\n readonly tokens: number;\n /** Max research steps the plan may schedule. */\n readonly researchSteps: number;\n /** Tooling candidates considered per decision area. */\n readonly candidatesPerChoice: number;\n /** Verification passes scheduled during the build. */\n readonly validationPasses: number;\n /** Upper bound on plan tasks. */\n readonly maxPlanTasks: number;\n /** Human-readable derivation of the numbers above. */\n readonly explanation: string;\n}\n\nexport interface BudgetOverrides {\n /**\n * User-supplied token budget (`--budget`): an explicit OVERRIDE of the\n * formula in either direction (it is the advertised recovery from budget\n * exhaustion), still bounded by the configured hard cap.\n */\n readonly maxTokens?: number;\n}\n\nconst scale = (base: number, multiplier: number, min: number): number =>\n Math.max(min, Math.round(base * multiplier));\n\n/** Compose effort (user-selected baseline) with value (inferred multiplier). */\nexport function computeBudget(\n effort: EffortLevel,\n valueTier: ValueTier,\n cfg: PlanningConfig,\n overrides: BudgetOverrides = {},\n): Budget {\n const profile = cfg.efforts[effort];\n const multiplier = cfg.valueTiers[valueTier].multiplier;\n const base = cfg.budget.baseTokensByEffort[effort];\n\n const formula = Math.round(base * multiplier);\n const requested = overrides.maxTokens !== undefined && overrides.maxTokens > 0 ? overrides.maxTokens : formula;\n const tokens = Math.min(requested, cfg.budget.hardCapTokens);\n\n let note: string;\n if (requested !== formula) {\n note =\n tokens < requested\n ? ` \u2014 overridden by your --budget ${requested.toLocaleString()}, capped at the configured hard cap`\n : ` \u2014 overridden by your --budget`;\n } else {\n note = tokens < formula ? ' (capped by the configured hard cap)' : '';\n }\n\n return {\n tokens,\n researchSteps: scale(profile.researchSteps, multiplier, 1),\n candidatesPerChoice: scale(profile.candidatesPerChoice, multiplier, 1),\n validationPasses: scale(profile.validationPasses, Math.min(multiplier, 1.5), 0),\n maxPlanTasks: scale(profile.maxPlanTasks, multiplier, 2),\n explanation:\n `effort ${effort} baseline ${base.toLocaleString()} tokens \u00D7 value ${valueTier} \u00D7${multiplier}` +\n ` = ${tokens.toLocaleString()} tokens${note}`,\n };\n}\n", "/**\n * Planner (Blueprint v2 P7): decompose a task into a minimal task DAG via DeepSeek\n * (thinking), or ask to clarify when too ambiguous. Pure `scheduleByDeps` batches\n * the DAG by dependency tags for a bounded worker pool.\n *\n * On top of the DAG sits the model- and effort-aware BUILD PLAN\n * ({@link draftBuildPlan}): research steps, tooling candidates per decision area\n * (resolved by selection.ts), and build tasks \u2014 its depth scaled by the budget\n * (effort \u00D7 value, see budget.ts) and the executing model's profile. The engine\n * executes against this plan instead of improvising tool choices mid-build.\n */\nimport { createAiClient, DEEPSEEK_PRO_MODEL } from '@fim/ai-sdk';\nimport { effortToReasoning, type EffortLevel, type Tier } from '@fim/futurex-protocol';\nimport type { Budget } from './budget.js';\nimport type { ChatClient, SessionGoal } from './goal.js';\nimport type { ModelProfile } from './planning-config.js';\nimport type { SelectionResult } from './selection.js';\nimport type { ValueAssessment } from './value.js';\n\nexport interface Task {\n readonly id: string;\n readonly title: string;\n readonly description: string;\n readonly dependsOn: readonly string[];\n /** Files / areas this task is expected to touch. */\n readonly targets: readonly string[];\n}\n\nexport interface Plan {\n readonly summary: string;\n readonly tasks: readonly Task[];\n}\n\nexport type PlanResult =\n | { readonly kind: 'plan'; readonly plan: Plan }\n | { readonly kind: 'clarify'; readonly questions: readonly string[] };\n\nconst PLANNER_SYSTEM = [\n 'You are a senior engineer decomposing a coding task into a minimal task DAG.',\n 'Respond with ONLY one minified JSON object \u2014 no prose, no code fence \u2014 that is EITHER',\n '{\"kind\":\"plan\",\"plan\":{\"summary\":string,\"tasks\":[{\"id\":string,\"title\":string,\"description\":string,\"dependsOn\":string[],\"targets\":string[]}]}}',\n 'OR {\"kind\":\"clarify\",\"questions\":string[]} when the task is too ambiguous to plan.',\n 'Keep tasks coarse (3-8), give each a short stable id, and set dependsOn to other task ids.',\n].join('\\n');\n\nfunction asStrings(v: unknown): string[] {\n return Array.isArray(v) ? v.filter((x): x is string => typeof x === 'string' && x.length > 0) : [];\n}\n\nfunction normalizeTask(v: unknown, i: number): Task | null {\n if (!v || typeof v !== 'object') return null;\n const o = v as Record<string, unknown>;\n const title = typeof o.title === 'string' ? o.title : '';\n if (!title) return null;\n return {\n id: typeof o.id === 'string' && o.id ? o.id : `t${i + 1}`,\n title,\n description: typeof o.description === 'string' ? o.description : '',\n dependsOn: asStrings(o.dependsOn),\n targets: asStrings(o.targets),\n };\n}\n\n/** Parse a planner reply into a {@link PlanResult} (defensive). */\nexport function parsePlanResult(raw: string): PlanResult {\n const start = raw.indexOf('{');\n const end = raw.lastIndexOf('}');\n if (start === -1 || end <= start) {\n return { kind: 'clarify', questions: ['The planner returned no usable JSON. Rephrase the task?'] };\n }\n let json: Record<string, unknown>;\n try {\n json = JSON.parse(raw.slice(start, end + 1)) as Record<string, unknown>;\n } catch {\n return { kind: 'clarify', questions: ['The plan was not valid JSON. Rephrase the task?'] };\n }\n if (json.kind === 'clarify') {\n const questions = asStrings(json.questions);\n return { kind: 'clarify', questions: questions.length > 0 ? questions : ['Please clarify the task.'] };\n }\n const planObj = json.plan && typeof json.plan === 'object' ? (json.plan as Record<string, unknown>) : json;\n const rawTasks = Array.isArray(planObj.tasks) ? planObj.tasks : [];\n const tasks = rawTasks.map((t, i) => normalizeTask(t, i)).filter((t): t is Task => t !== null);\n if (tasks.length === 0) {\n return { kind: 'clarify', questions: ['Could not derive any tasks. Add detail to the request?'] };\n }\n return {\n kind: 'plan',\n plan: { summary: typeof planObj.summary === 'string' ? planObj.summary : '', tasks },\n };\n}\n\n/** Decompose `task` into a {@link PlanResult} using DeepSeek (thinking, Pro). */\nexport async function planFromIntent(task: string, context: string): Promise<PlanResult> {\n const ai = createAiClient({ provider: 'deepseek' });\n const reply = await ai.chat({\n system: PLANNER_SYSTEM,\n messages: [{ role: 'user', content: `CONTEXT:\\n${context.slice(0, 6000)}\\n\\nTASK:\\n${task}` }],\n reasoning: { effort: 'high' }, // thinking for a coherent plan\n model: DEEPSEEK_PRO_MODEL,\n maxTokens: 4000,\n });\n return parsePlanResult(reply);\n}\n\n// --- the model/effort-aware build plan ---------------------------------------\n\n/** One research step the engine performs before building. */\nexport interface ResearchStep {\n readonly id: string;\n readonly question: string;\n}\n\n/** A decision area where the model proposes candidates; selection.ts decides. */\nexport interface ToolingArea {\n readonly area: string;\n readonly candidates: readonly string[];\n}\n\n/** The draft the model produces (before candidate ranking resolves choices). */\nexport interface BuildPlanDraft {\n readonly research: readonly ResearchStep[];\n readonly tooling: readonly ToolingArea[];\n readonly tasks: readonly Task[];\n}\n\n/**\n * The full pre-build plan: produced and surfaced BEFORE execution starts, then\n * checkpointed so the build executes against it (and it stays inspectable).\n */\nexport interface BuildPlan {\n readonly goal: SessionGoal;\n readonly model: string;\n readonly tier?: Tier;\n readonly effort: EffortLevel;\n readonly value: ValueAssessment;\n readonly budget: Budget;\n readonly research: readonly ResearchStep[];\n /** Resolved tooling choices with recorded rationale (auditable). */\n readonly tooling: readonly SelectionResult[];\n /** Packages the build expects to pull (the chosen candidates). */\n readonly packages: readonly string[];\n readonly tasks: readonly Task[];\n}\n\nconst BUILD_PLAN_SYSTEM = [\n 'You are a senior engineer planning HOW to build a task before any code is written.',\n 'Respond with ONLY one minified JSON object \u2014 no prose, no code fence \u2014 shaped as',\n '{\"research\":[{\"id\":string,\"question\":string}],',\n '\"tooling\":[{\"area\":string,\"candidates\":string[]}],',\n '\"tasks\":[{\"id\":string,\"title\":string,\"description\":string,\"dependsOn\":string[],\"targets\":string[]}]}.',\n 'research = what to investigate first (docs, existing code, APIs).',\n 'tooling = decision areas where a package/framework must be chosen; list candidate npm package names.',\n 'Prefer the most widely-used, well-maintained, well-documented mainstream options as candidates;',\n 'propose a niche package only when the task genuinely requires it.',\n 'tasks = the ordered build steps as a dependency DAG (short stable ids).',\n].join('\\n');\n\nfunction normalizeResearch(v: unknown): ResearchStep[] {\n if (!Array.isArray(v)) return [];\n return v\n .map((r, i) => {\n if (!r || typeof r !== 'object') return null;\n const o = r as Record<string, unknown>;\n const question = typeof o.question === 'string' ? o.question.trim() : '';\n if (!question) return null;\n return { id: typeof o.id === 'string' && o.id ? o.id : `r${i + 1}`, question };\n })\n .filter((r): r is ResearchStep => r !== null);\n}\n\nfunction normalizeTooling(v: unknown): ToolingArea[] {\n if (!Array.isArray(v)) return [];\n return v\n .map((t): ToolingArea | null => {\n if (!t || typeof t !== 'object') return null;\n const o = t as Record<string, unknown>;\n const area = typeof o.area === 'string' ? o.area.trim() : '';\n // Dedupe BEFORE the per-budget clamp, so repeated names can't eat the\n // candidate slots.\n const candidates = [...new Set(asStrings(o.candidates))];\n if (!area || candidates.length === 0) return null;\n return { area, candidates };\n })\n .filter((t): t is ToolingArea => t !== null);\n}\n\n/**\n * Parse a build-plan reply, CLAMPING depth to the budget so the configured\n * effort\u2192depth mapping holds even when the model over-produces.\n */\nexport function parseBuildPlanDraft(raw: string, budget: Budget): BuildPlanDraft | null {\n const start = raw.indexOf('{');\n const end = raw.lastIndexOf('}');\n if (start === -1 || end <= start) return null;\n let json: Record<string, unknown>;\n try {\n json = JSON.parse(raw.slice(start, end + 1)) as Record<string, unknown>;\n } catch {\n return null;\n }\n const rawTasks = Array.isArray(json.tasks) ? json.tasks : [];\n const tasks = rawTasks\n .map((t, i) => normalizeTask(t, i))\n .filter((t): t is Task => t !== null)\n .slice(0, budget.maxPlanTasks);\n if (tasks.length === 0) return null;\n return {\n research: normalizeResearch(json.research).slice(0, budget.researchSteps),\n tooling: normalizeTooling(json.tooling).map((t) => ({\n area: t.area,\n candidates: t.candidates.slice(0, budget.candidatesPerChoice),\n })),\n tasks,\n };\n}\n\n/**\n * Draft the build plan from the goal. Depth knobs (how many research steps,\n * candidates, tasks) come from the budget; how much one step may batch comes\n * from the executing model's profile \u2014 both injected into the prompt, so a\n * higher effort/value visibly produces a deeper plan for the same task.\n */\nexport async function draftBuildPlan(\n goal: SessionGoal,\n context: string,\n ai: ChatClient,\n opts: {\n readonly model: string;\n readonly effort: EffortLevel;\n readonly budget: Budget;\n readonly modelProfile: ModelProfile;\n readonly maxTokens?: number;\n },\n): Promise<BuildPlanDraft | null> {\n const { budget, modelProfile: mp } = opts;\n const knobs = [\n `Plan depth for this run: at most ${budget.researchSteps} research steps,`,\n `at most ${budget.candidatesPerChoice} candidates per tooling area,`,\n `at most ${budget.maxPlanTasks} tasks.`,\n `The executing model handles ${mp.stepComplexity} steps; batch up to ${mp.batchFactor}`,\n 'closely-related subtasks into one task rather than splitting them.',\n ].join(' ');\n const reply = await ai.chat({\n system: `${BUILD_PLAN_SYSTEM}\\n${knobs}`,\n messages: [\n {\n role: 'user',\n content:\n `CONTEXT:\\n${context.slice(0, 6000)}\\n\\nGOAL: ${goal.statement}\\n` +\n `DONE WHEN:\\n${goal.criteria.map((c) => `- ${c.text}`).join('\\n')}\\n\\nTASK:\\n${goal.task}`,\n },\n ],\n reasoning: effortToReasoning(opts.effort),\n model: opts.model,\n maxTokens: opts.maxTokens ?? 4000,\n });\n return parseBuildPlanDraft(reply, budget);\n}\n\n/**\n * Topologically batch tasks by dependency tags: each returned batch may run\n * concurrently in a bounded pool; later batches depend on earlier ones. A cycle\n * or dangling dependency degrades gracefully (the remainder is emitted as one\n * final batch rather than looping forever).\n */\nexport function scheduleByDeps(tasks: readonly Task[]): Task[][] {\n const byId = new Map(tasks.map((t) => [t.id, t]));\n const remaining = new Set(tasks.map((t) => t.id));\n const done = new Set<string>();\n const batches: Task[][] = [];\n\n while (remaining.size > 0) {\n const ready: Task[] = [];\n for (const id of remaining) {\n const t = byId.get(id);\n if (t && t.dependsOn.every((d) => done.has(d) || !byId.has(d))) ready.push(t);\n }\n if (ready.length === 0) {\n const rest: Task[] = [];\n for (const id of remaining) {\n const t = byId.get(id);\n if (t) rest.push(t);\n }\n batches.push(rest);\n break;\n }\n batches.push(ready);\n for (const t of ready) {\n remaining.delete(t.id);\n done.add(t.id);\n }\n }\n return batches;\n}\n", "/**\n * Planning-layer configuration \u2014 every effort/model/value/budget knob in ONE\n * place, with sensible defaults and a user override file\n * (`~/.futurex/planning.json`, partial deep merge). Nothing in the planner,\n * value detector, budget composer, or selection ranker hardcodes these numbers.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport type { EffortLevel } from '@fim/futurex-protocol';\nimport { planningConfigPath } from './config.js';\n\n/** How deep planning goes at a given effort level (the effort\u2192depth mapping). */\nexport interface EffortProfile {\n /** Max research steps the plan may contain. */\n readonly researchSteps: number;\n /** Tooling candidates considered per decision area. */\n readonly candidatesPerChoice: number;\n /** Verification (typecheck/lint/test) passes scheduled during the build. */\n readonly validationPasses: number;\n /** Upper bound on build tasks in the plan. */\n readonly maxPlanTasks: number;\n}\n\n/** How much complexity one step may assume for a given model. */\nexport interface ModelProfile {\n /** How big a single plan step may be for this model. */\n readonly stepComplexity: 'small' | 'medium' | 'large';\n /** How many related subtasks may be batched into one step. */\n readonly batchFactor: number;\n}\n\n/** Inferred project importance. */\nexport type ValueTier = 'low' | 'standard' | 'high' | 'critical';\n\nexport interface ValueTierSpec {\n /** Budget multiplier this tier applies to the effort baseline. */\n readonly multiplier: number;\n readonly description: string;\n}\n\nexport interface PlanningConfig {\n readonly efforts: Record<EffortLevel, EffortProfile>;\n /** Keyed by model id; `default` is the fallback for unknown models. */\n readonly models: Record<string, ModelProfile>;\n readonly valueTiers: Record<ValueTier, ValueTierSpec>;\n readonly budget: {\n /** Effort sets the baseline; value scales it (see budget.ts \u2014 the ONE formula). */\n readonly baseTokensByEffort: Record<EffortLevel, number>;\n /** Absolute output-token ceiling per build, regardless of value tier. */\n readonly hardCapTokens: number;\n };\n readonly selection: {\n /** Ranking weights (normalized at use): popularity + maintenance + docs. */\n readonly weights: { popularity: number; maintenance: number; docs: number };\n /** A release within this window counts as fully maintained. */\n readonly freshnessWindowDays: number;\n /** npm registry fetch timeout; on miss the offline baseline is used. */\n readonly fetchTimeoutMs: number;\n };\n readonly value: {\n /** Heuristic score thresholds (0..1) \u2192 tier. */\n readonly lowBelow: number;\n readonly highAtLeast: number;\n readonly criticalAtLeast: number;\n /** Index-chunk counts that qualify a repo as medium / large. */\n readonly repoMediumChunks: number;\n readonly repoLargeChunks: number;\n /** Signed score contributions per detected signal (see value.ts). */\n readonly weights: {\n readonly repoMedium: number;\n readonly repoLarge: number;\n readonly stackBreadth: number;\n readonly criticalKeyword: number;\n readonly lowKeyword: number;\n readonly broadScope: number;\n };\n };\n}\n\nexport const DEFAULT_PLANNING_CONFIG: PlanningConfig = {\n efforts: {\n off: { researchSteps: 1, candidatesPerChoice: 1, validationPasses: 0, maxPlanTasks: 4 },\n high: { researchSteps: 3, candidatesPerChoice: 2, validationPasses: 1, maxPlanTasks: 8 },\n max: { researchSteps: 6, candidatesPerChoice: 3, validationPasses: 2, maxPlanTasks: 12 },\n },\n models: {\n 'deepseek-v4-pro': { stepComplexity: 'large', batchFactor: 3 },\n 'deepseek-v4-flash': { stepComplexity: 'medium', batchFactor: 2 },\n default: { stepComplexity: 'small', batchFactor: 1 },\n },\n valueTiers: {\n low: { multiplier: 0.5, description: 'throwaway/prototype \u2014 stay conservative' },\n standard: { multiplier: 1, description: 'typical project' },\n high: { multiplier: 1.5, description: 'substantial codebase or stated importance' },\n critical: { multiplier: 2, description: 'production/critical signals \u2014 maximum care' },\n },\n budget: {\n baseTokensByEffort: { off: 30_000, high: 80_000, max: 200_000 },\n hardCapTokens: 500_000,\n },\n selection: {\n weights: { popularity: 0.5, maintenance: 0.3, docs: 0.2 },\n freshnessWindowDays: 180,\n fetchTimeoutMs: 1_500,\n },\n value: {\n lowBelow: 0.25,\n highAtLeast: 0.55,\n criticalAtLeast: 0.8,\n repoMediumChunks: 300,\n repoLargeChunks: 2_000,\n weights: {\n repoMedium: 0.1,\n repoLarge: 0.2,\n stackBreadth: 0.1,\n criticalKeyword: 0.3,\n lowKeyword: -0.3,\n broadScope: 0.15,\n },\n },\n};\n\ntype Plain = Record<string, unknown>;\n\nfunction isPlain(v: unknown): v is Plain {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/** Defaults \u2295 user overrides, object-by-object; scalars/arrays replace wholesale. */\nfunction deepMerge<T>(base: T, override: unknown): T {\n if (!isPlain(base) || !isPlain(override)) return base;\n const out: Plain = { ...base };\n for (const [key, value] of Object.entries(override)) {\n const prior = (base as Plain)[key];\n if (isPlain(prior) && isPlain(value)) out[key] = deepMerge(prior, value);\n else if (typeof value === typeof prior && value !== null) out[key] = value;\n // type-mismatched overrides are ignored (defensive: the file is user-edited)\n }\n return out as T;\n}\n\n/**\n * The planning config: defaults merged with `~/.futurex/planning.json` when\n * present. An unreadable file degrades to the defaults rather than failing.\n */\nexport function loadPlanningConfig(): PlanningConfig {\n const path = planningConfigPath();\n if (!existsSync(path)) return DEFAULT_PLANNING_CONFIG;\n try {\n const raw: unknown = JSON.parse(readFileSync(path, 'utf8'));\n return deepMerge(DEFAULT_PLANNING_CONFIG, raw);\n } catch {\n return DEFAULT_PLANNING_CONFIG;\n }\n}\n\nconst FALLBACK_MODEL_PROFILE: ModelProfile = { stepComplexity: 'small', batchFactor: 1 };\n\n/** The model profile for a model id, falling back to `default`. */\nexport function modelProfile(cfg: PlanningConfig, model: string): ModelProfile {\n return cfg.models[model] ?? cfg.models.default ?? FALLBACK_MODEL_PROFILE;\n}\n", "/**\n * Tooling/package selection \u2014 when the plan has multiple candidates for a step,\n * rank them by explicit signals and pick the winner BEFORE building:\n *\n * score = w_pop \u00B7 popularity + w_maint \u00B7 maintenance + w_docs \u00B7 documentation\n *\n * Popularity comes from npm weekly downloads, maintenance from days since the\n * last publish, documentation from a known docs site. Signals are fetched from\n * the npm registry when the network allows and fall back to a curated baseline\n * of mainstream packages \u2014 biasing selection toward widely-used, maintained,\n * well-documented options by default. Every choice records WHY (the deciding\n * signals), so the selection is auditable from the plan checkpoint.\n */\nimport type { PlanningConfig } from './planning-config.js';\n\nexport interface CandidateSignals {\n readonly weeklyDownloads?: number;\n readonly lastPublishDays?: number;\n readonly hasOfficialDocs?: boolean;\n readonly docsUrl?: string;\n /** Where the signals came from. */\n readonly source: 'npm-registry' | 'baseline' | 'none';\n}\n\nexport interface RankedCandidate {\n readonly name: string;\n /** 0..1 composite of the weighted signals. */\n readonly score: number;\n readonly signals: CandidateSignals;\n}\n\nexport interface SelectionResult {\n /** The decision area (e.g. \"http server\", \"validation\"). */\n readonly area: string;\n readonly chosen: string;\n /** The deciding signals, spelled out. */\n readonly rationale: string;\n /** Full ranking, best first (inspectable). */\n readonly candidates: readonly RankedCandidate[];\n}\n\nexport type SignalFetcher = (name: string, timeoutMs: number) => Promise<CandidateSignals | null>;\n\n/**\n * Curated mainstream baseline (approximate, refreshed manually): keeps ranking\n * deterministic offline and anchors the \"prefer widely-used\" default. Live npm\n * signals override these when reachable.\n */\nexport const BASELINE_SIGNALS: Readonly<Record<string, Omit<CandidateSignals, 'source'>>> = {\n react: { weeklyDownloads: 28_000_000, lastPublishDays: 30, hasOfficialDocs: true, docsUrl: 'https://react.dev' },\n next: { weeklyDownloads: 7_000_000, lastPublishDays: 7, hasOfficialDocs: true, docsUrl: 'https://nextjs.org/docs' },\n vue: { weeklyDownloads: 5_500_000, lastPublishDays: 30, hasOfficialDocs: true, docsUrl: 'https://vuejs.org/guide/' },\n svelte: { weeklyDownloads: 2_200_000, lastPublishDays: 14, hasOfficialDocs: true, docsUrl: 'https://svelte.dev/docs' },\n express: { weeklyDownloads: 35_000_000, lastPublishDays: 90, hasOfficialDocs: true, docsUrl: 'https://expressjs.com' },\n fastify: { weeklyDownloads: 2_500_000, lastPublishDays: 14, hasOfficialDocs: true, docsUrl: 'https://fastify.dev/docs/latest/' },\n '@nestjs/core': { weeklyDownloads: 4_000_000, lastPublishDays: 14, hasOfficialDocs: true, docsUrl: 'https://docs.nestjs.com' },\n koa: { weeklyDownloads: 1_800_000, lastPublishDays: 365, hasOfficialDocs: true, docsUrl: 'https://koajs.com' },\n prisma: { weeklyDownloads: 3_500_000, lastPublishDays: 14, hasOfficialDocs: true, docsUrl: 'https://www.prisma.io/docs' },\n 'drizzle-orm': { weeklyDownloads: 1_500_000, lastPublishDays: 7, hasOfficialDocs: true, docsUrl: 'https://orm.drizzle.team' },\n typeorm: { weeklyDownloads: 2_000_000, lastPublishDays: 60, hasOfficialDocs: true, docsUrl: 'https://typeorm.io' },\n zod: { weeklyDownloads: 18_000_000, lastPublishDays: 14, hasOfficialDocs: true, docsUrl: 'https://zod.dev' },\n vitest: { weeklyDownloads: 9_000_000, lastPublishDays: 7, hasOfficialDocs: true, docsUrl: 'https://vitest.dev' },\n jest: { weeklyDownloads: 24_000_000, lastPublishDays: 120, hasOfficialDocs: true, docsUrl: 'https://jestjs.io/docs/getting-started' },\n playwright: { weeklyDownloads: 6_000_000, lastPublishDays: 14, hasOfficialDocs: true, docsUrl: 'https://playwright.dev/docs/intro' },\n typescript: { weeklyDownloads: 55_000_000, lastPublishDays: 30, hasOfficialDocs: true, docsUrl: 'https://www.typescriptlang.org/docs/' },\n axios: { weeklyDownloads: 50_000_000, lastPublishDays: 60, hasOfficialDocs: true, docsUrl: 'https://axios-http.com/docs/intro' },\n tailwindcss: { weeklyDownloads: 14_000_000, lastPublishDays: 7, hasOfficialDocs: true, docsUrl: 'https://tailwindcss.com/docs' },\n};\n\nfunction clamp01(x: number): number {\n return Math.min(1, Math.max(0, x));\n}\n\n/** Score one candidate's signals against the configured weights (0..1). */\nexport function scoreSignals(signals: CandidateSignals, cfg: PlanningConfig): number {\n const w = cfg.selection.weights;\n const totalWeight = w.popularity + w.maintenance + w.docs;\n if (totalWeight <= 0) return 0;\n\n // Popularity: log-scale weekly downloads; ~10M/wk \u2248 0.875, ~1k/wk \u2248 0.375.\n const downloads = signals.weeklyDownloads ?? 0;\n const popularity = downloads > 0 ? clamp01(Math.log10(downloads) / 8) : 0;\n\n // Maintenance: full credit within the freshness window, linear decay to 0 at 4\u00D7 it.\n const days = signals.lastPublishDays;\n const window = cfg.selection.freshnessWindowDays;\n const maintenance =\n days === undefined ? 0 : days <= window ? 1 : clamp01(1 - (days - window) / (3 * window));\n\n const docs = signals.hasOfficialDocs ? 1 : 0;\n\n return (w.popularity * popularity + w.maintenance * maintenance + w.docs * docs) / totalWeight;\n}\n\n/** Live npm signals: registry metadata (last publish) + weekly downloads. */\nexport const fetchNpmSignals: SignalFetcher = async (name, timeoutMs) => {\n try {\n const enc = encodeURIComponent(name).replace('%40', '@');\n const [meta, dl] = await Promise.all([\n fetch(`https://registry.npmjs.org/${enc}`, { signal: AbortSignal.timeout(timeoutMs) }),\n fetch(`https://api.npmjs.org/downloads/point/last-week/${enc}`, {\n signal: AbortSignal.timeout(timeoutMs),\n }),\n ]);\n if (!meta.ok) return null;\n const metaJson = (await meta.json()) as {\n time?: Record<string, string>;\n homepage?: string;\n };\n const modified = metaJson.time?.modified;\n const lastPublishDays = modified\n ? Math.max(0, Math.round((Date.now() - Date.parse(modified)) / 86_400_000))\n : undefined;\n let weeklyDownloads: number | undefined;\n if (dl.ok) {\n const dlJson = (await dl.json()) as { downloads?: number };\n if (typeof dlJson.downloads === 'number') weeklyDownloads = dlJson.downloads;\n }\n return {\n ...(weeklyDownloads !== undefined ? { weeklyDownloads } : {}),\n ...(lastPublishDays !== undefined ? { lastPublishDays } : {}),\n hasOfficialDocs: typeof metaJson.homepage === 'string' && metaJson.homepage.length > 0,\n ...(typeof metaJson.homepage === 'string' && metaJson.homepage ? { docsUrl: metaJson.homepage } : {}),\n source: 'npm-registry' as const,\n };\n } catch {\n return null; // offline / blocked / timeout \u2192 caller falls back to the baseline\n }\n};\n\nfunction describe(c: RankedCandidate): string {\n const s = c.signals;\n const bits: string[] = [];\n if (s.weeklyDownloads !== undefined) bits.push(`~${Math.round(s.weeklyDownloads / 1_000_000 * 10) / 10}M weekly downloads`);\n if (s.lastPublishDays !== undefined) bits.push(`published ${s.lastPublishDays}d ago`);\n bits.push(s.hasOfficialDocs ? 'official docs' : 'no official docs found');\n bits.push(`signals: ${s.source}`);\n return bits.join(', ');\n}\n\n/**\n * Rank candidates for one decision area and pick the winner. Live signals when\n * reachable, curated baseline otherwise, \"no signals\" scoring as a last resort\n * (an unknown niche package naturally ranks below a documented mainstream one).\n */\nexport async function rankCandidates(\n area: string,\n names: readonly string[],\n cfg: PlanningConfig,\n fetcher: SignalFetcher = fetchNpmSignals,\n): Promise<SelectionResult | null> {\n const unique = [...new Set(names.map((n) => n.trim()).filter(Boolean))];\n if (unique.length === 0) return null;\n\n const ranked: RankedCandidate[] = await Promise.all(\n unique.map(async (name) => {\n const live = await fetcher(name, cfg.selection.fetchTimeoutMs);\n const baseline = BASELINE_SIGNALS[name];\n // Live signals win field-by-field, but a PARTIAL live result (e.g. the\n // downloads endpoint failed) must not zero out a known mainstream\n // package \u2014 fall back to the baseline for the missing fields.\n let signals: CandidateSignals;\n if (live && baseline) {\n signals = {\n ...baseline,\n ...Object.fromEntries(Object.entries(live).filter(([, v]) => v !== undefined)),\n source: live.source,\n };\n } else {\n signals = live ?? (baseline ? { ...baseline, source: 'baseline' } : { source: 'none' });\n }\n return { name, score: scoreSignals(signals, cfg), signals };\n }),\n );\n ranked.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name));\n\n const best = ranked[0];\n if (!best) return null;\n const runnerUp = ranked[1];\n const margin = runnerUp ? ` (next: ${runnerUp.name} ${runnerUp.score.toFixed(2)})` : '';\n return {\n area,\n chosen: best.name,\n rationale: `${best.name} ${best.score.toFixed(2)} \u2014 ${describe(best)}${margin}`,\n candidates: ranked,\n };\n}\n", "/**\n * Project-value detection: infer how much the project at hand matters from\n * observable context \u2014 repo scale, stack breadth, criticality language in the\n * request/memory, request scope \u2014 and emit a {@link ValueAssessment} the budget\n * composer (budget.ts) turns into a token/depth allowance.\n *\n * Deliberately a deterministic heuristic (no model call): it must be cheap,\n * testable, and explainable. Every contributing signal is recorded so the\n * assessment is auditable, and the user can override the tier outright\n * (`--value <tier>`), so a misjudgment can't silently burn tokens.\n */\nimport type { RepoCard } from '@fim/futurex-protocol';\nimport type { PlanningConfig, ValueTier } from './planning-config.js';\n\nexport interface ValueSignal {\n readonly name: string;\n readonly detail: string;\n /** Signed contribution to the score. */\n readonly delta: number;\n}\n\nexport interface ValueAssessment {\n readonly tier: ValueTier;\n /** 0..1; thresholds in config map it to the tier. */\n readonly score: number;\n readonly signals: readonly ValueSignal[];\n /** Set when the user forced the tier (score/signals kept for transparency). */\n readonly overridden?: boolean;\n}\n\nexport interface ValueContext {\n readonly card: RepoCard | null;\n /** Retrieval-index chunk count, when an index exists. */\n readonly indexedChunks?: number;\n /** The user's request \u2014 scanned for criticality/scope language. */\n readonly task: string;\n /** Project memory contents, when present (also scanned). */\n readonly memory?: string | null;\n}\n\n/** Baseline score for a project with no signals either way (\"standard\"). */\nconst BASELINE_SCORE = 0.4;\n\nconst CRITICAL_WORDS = [\n 'production', 'critical', 'payment', 'billing', 'auth', 'authentication',\n 'authorization', 'security', 'compliance', 'customers', 'revenue', 'medical',\n 'finance', 'launch',\n];\nconst LOW_WORDS = [\n 'prototype', 'throwaway', 'experiment', 'demo', 'toy', 'scratch',\n 'poc', 'proof of concept', 'hackathon', 'quick test',\n];\n\n/** Whole-word match \u2014 'poc' must not fire on 'epoch', nor 'auth' on 'author'. */\nfunction mentions(text: string, phrase: string): boolean {\n const escaped = phrase.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\s+/g, '\\\\s+');\n return new RegExp(`\\\\b${escaped}\\\\b`, 'i').test(text);\n}\n\nfunction clamp01(x: number): number {\n return Math.min(1, Math.max(0, x));\n}\n\n/** Assess project value from context. Pure given its inputs + config. */\nexport function assessProjectValue(input: ValueContext, cfg: PlanningConfig): ValueAssessment {\n const v = cfg.value;\n const signals: ValueSignal[] = [];\n\n // Repo scale \u2014 a larger indexed codebase implies more invested (and at-risk) work.\n const chunks = input.indexedChunks ?? 0;\n if (chunks >= v.repoLargeChunks) {\n signals.push({ name: 'repo-scale', detail: `${chunks} indexed chunks (large)`, delta: v.weights.repoLarge });\n } else if (chunks >= v.repoMediumChunks) {\n signals.push({ name: 'repo-scale', detail: `${chunks} indexed chunks (medium)`, delta: v.weights.repoMedium });\n }\n\n // Stack breadth \u2014 multiple detected facets (framework, backend, orm, tests)\n // means a real, multi-layer system rather than a single script.\n const facets = [input.card?.framework, input.card?.backend, input.card?.orm, input.card?.test].filter(Boolean).length;\n if (facets >= 2) {\n signals.push({ name: 'stack-breadth', detail: `${facets} stack facets detected`, delta: v.weights.stackBreadth });\n }\n\n // Criticality language in the request + project memory.\n const text = `${input.task}\\n${input.memory ?? ''}`.toLowerCase();\n const critHits = CRITICAL_WORDS.filter((w) => mentions(text, w));\n if (critHits.length > 0) {\n signals.push({\n name: 'criticality',\n detail: `mentions: ${critHits.slice(0, 4).join(', ')}`,\n delta: v.weights.criticalKeyword,\n });\n }\n const lowHits = LOW_WORDS.filter((w) => mentions(text, w));\n if (lowHits.length > 0) {\n signals.push({\n name: 'low-stakes',\n detail: `mentions: ${lowHits.slice(0, 4).join(', ')}`,\n delta: v.weights.lowKeyword,\n });\n }\n\n // Request scope \u2014 long, multi-part requests imply a broader change surface.\n const parts = input.task.split(/\\n|(?:^|\\s)(?:\\d+[.)]|[-*])\\s/).filter((s) => s.trim().length > 20).length;\n if (parts >= 3 || input.task.length > 600) {\n signals.push({ name: 'broad-scope', detail: `multi-part request (${parts} parts, ${input.task.length} chars)`, delta: v.weights.broadScope });\n }\n\n const score = clamp01(BASELINE_SCORE + signals.reduce((sum, s) => sum + s.delta, 0));\n let tier: ValueTier;\n if (score >= v.criticalAtLeast) tier = 'critical';\n else if (score >= v.highAtLeast) tier = 'high';\n else if (score < v.lowBelow) tier = 'low';\n else tier = 'standard';\n\n return { tier, score, signals };\n}\n\n/** Apply a user override on top of a computed assessment (kept auditable). */\nexport function overrideValueTier(assessment: ValueAssessment, tier: ValueTier): ValueAssessment {\n return { ...assessment, tier, overridden: true };\n}\n\n/** Render the assessment for plan output. */\nexport function formatValue(a: ValueAssessment, cfg: PlanningConfig): string {\n const mult = cfg.valueTiers[a.tier].multiplier;\n const why = a.signals.length > 0 ? a.signals.map((s) => s.detail).join(' \u00B7 ') : 'no strong signals';\n return `value: ${a.tier}${a.overridden ? ' (user override)' : ''} \u00D7${mult} \u2014 ${why}`;\n}\n", "/**\n * Resumable pipeline state machine (Blueprint v2 P7). Each stage writes a\n * checkpoint artifact to `~/.futurex/pipelines/<id>/<stage>.json`; re-running\n * skips already-checkpointed stages, so killing the process mid-pipeline and\n * re-running resumes from the last checkpoint instead of restarting from zero.\n */\nimport { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { futurexHome } from './config.js';\n\n/** Stable pipeline id from a seed (e.g. `${repoRoot}::${task}`). */\nexport function pipelineId(seed: string): string {\n return createHash('sha1').update(seed).digest('hex').slice(0, 16);\n}\n\nfunction pipelineDir(id: string): string {\n return join(futurexHome(), 'pipelines', id);\n}\n\nexport interface Checkpoint {\n readonly stage: string;\n readonly createdAt: string;\n readonly data: unknown;\n}\n\n/** Persist a stage's output as a checkpoint artifact. */\nexport function writeCheckpoint(id: string, stage: string, data: unknown): void {\n const dir = pipelineDir(id);\n mkdirSync(dir, { recursive: true });\n const cp: Checkpoint = { stage, createdAt: new Date().toISOString(), data };\n writeFileSync(join(dir, `${stage}.json`), JSON.stringify(cp), { mode: 0o600 });\n}\n\n/** Load a stage's checkpoint, or null when absent/unreadable. */\nexport function readCheckpoint(id: string, stage: string): Checkpoint | null {\n const path = join(pipelineDir(id), `${stage}.json`);\n if (!existsSync(path)) return null;\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as Checkpoint;\n } catch {\n return null;\n }\n}\n\n/** Stage names checkpointed for a pipeline (no order guarantee). */\nexport function listCheckpoints(id: string): string[] {\n try {\n return readdirSync(pipelineDir(id))\n .filter((f) => f.endsWith('.json'))\n .map((f) => f.slice(0, -'.json'.length));\n } catch {\n return [];\n }\n}\n\n/** Remove a pipeline's checkpoints whose stage name starts with `prefix`. */\nexport function clearCheckpoints(id: string, prefix: string): void {\n for (const stage of listCheckpoints(id)) {\n if (!stage.startsWith(prefix)) continue;\n try {\n rmSync(join(pipelineDir(id), `${stage}.json`), { force: true });\n } catch {\n /* best effort */\n }\n }\n}\n\n/** Pipeline ids that have at least one checkpoint on disk. */\nexport function listPipelines(): string[] {\n try {\n return readdirSync(join(futurexHome(), 'pipelines'));\n } catch {\n return [];\n }\n}\n\nexport interface PipelineStage {\n readonly name: string;\n /** Receives the results of prior stages, keyed by stage name. */\n run(prior: Record<string, unknown>): Promise<unknown>;\n}\n\nexport type StageStatus = 'cached' | 'run';\n\n/**\n * Run `stages` in order, checkpointing each. A stage already checkpointed is\n * skipped and its cached result reused (resume), unless `restart` is set.\n */\nexport async function runResumable(\n id: string,\n stages: readonly PipelineStage[],\n opts: { restart?: boolean; onStage?: (name: string, status: StageStatus) => void } = {},\n): Promise<Record<string, unknown>> {\n const results: Record<string, unknown> = {};\n for (const stage of stages) {\n if (!opts.restart) {\n const cp = readCheckpoint(id, stage.name);\n if (cp) {\n results[stage.name] = cp.data;\n opts.onStage?.(stage.name, 'cached');\n continue;\n }\n }\n opts.onStage?.(stage.name, 'run');\n const data = await stage.run(results);\n writeCheckpoint(id, stage.name, data);\n results[stage.name] = data;\n }\n return results;\n}\n", "/**\n * `futurex plan \"<task>\"` / `futurex resume [id]` \u2014 the pre-build orchestration\n * pipeline (Blueprint v2 P7 + the planning layer). Before anything is built:\n *\n * context \u2192 goal (end goal + definition of done, or ONE clarifying question)\n * \u2192 value (inferred project importance) + budget (effort \u00D7 value)\n * \u2192 draft (model/effort-aware plan: research, tooling areas, task DAG)\n * \u2192 final (tooling candidates ranked + resolved, rationale recorded)\n *\n * Every stage is checkpointed under `~/.futurex/pipelines/<id>/`, so the plan\n * is inspectable (`futurex resume <id>`) and re-running resumes instead of\n * re-calling the model. The build command executes AGAINST the final plan.\n */\nimport { createAiClient } from '@fim/ai-sdk';\nimport type { EffortLevel, RepoCard } from '@fim/futurex-protocol';\nimport { buildRepoCard, findRepoRoot, readMemory } from './repo.js';\nimport { loadRetriever } from './index-store.js';\nimport { computeBudget } from './budget.js';\nimport { deriveGoal, formatGoal, type GoalResult, type SessionGoal } from './goal.js';\nimport {\n draftBuildPlan,\n scheduleByDeps,\n type BuildPlan,\n type BuildPlanDraft,\n type PlanResult,\n type Task,\n} from './planner.js';\nimport { loadPlanningConfig, modelProfile, type ValueTier } from './planning-config.js';\nimport { rankCandidates, type SelectionResult } from './selection.js';\nimport { assessProjectValue, formatValue, overrideValueTier, type ValueAssessment } from './value.js';\nimport {\n clearCheckpoints,\n listCheckpoints,\n listPipelines,\n pipelineId,\n readCheckpoint,\n writeCheckpoint,\n} from './pipeline.js';\nimport type { CliOptions } from './options.js';\nimport { color, error, info, line } from './ui.js';\n\nexport interface PlanFlags {\n /** Ignore checkpoints and re-plan from scratch. */\n readonly restart?: boolean;\n /** User override for the inferred value tier (`--value`). */\n readonly valueTier?: ValueTier;\n /** User cap on the token budget (`--budget`). */\n readonly budgetTokens?: number;\n}\n\nexport type BuildPlanOutcome =\n | { readonly kind: 'plan'; readonly id: string; readonly plan: BuildPlan }\n | { readonly kind: 'clarify'; readonly question: string };\n\nfunction contextSummary(root: string, card: RepoCard): string {\n const symbols = loadRetriever(root)?.symbols ?? null;\n const stack = [card.language, card.framework, card.backend, card.orm, card.packageManager]\n .filter((x): x is string => Boolean(x))\n .join(', ');\n const modules = symbols\n ? [...new Set(symbols.all().filter((d) => d.exported).map((d) => d.file))].slice(0, 30)\n : [];\n return (\n `Repo: ${card.name ?? root}\\nStack: ${stack || 'unknown'}\\n` +\n `Key files:\\n${modules.map((m) => `- ${m}`).join('\\n')}`\n );\n}\n\n/**\n * Produce (or resume) the full pre-build plan for `task`. Shared by `plan`\n * (which prints it) and `build` (which executes against it).\n */\nexport async function ensureBuildPlan(\n task: string,\n opts: CliOptions,\n flags: PlanFlags = {},\n onStage?: (name: string, status: 'cached' | 'run') => void,\n): Promise<BuildPlanOutcome> {\n const root = findRepoRoot();\n const id = pipelineId(`${root}::${task}`);\n const cfg = loadPlanningConfig();\n const effort: EffortLevel = opts.effort ?? 'off';\n // --restart is made atomic by clearing EVERYTHING up front (plan stages AND\n // exec-* progress) \u2014 an interruption mid-restart can never leave a pipeline\n // that silently mixes old and new generations on the next resume.\n if (flags.restart) clearCheckpoints(id, '');\n // --value/--budget must take effect on a RESUMED pipeline too (it is the\n // advertised recovery from budget exhaustion), so the cheap, model-free\n // stages that embed them recompute whenever an override is present.\n const hasBudgetOverride = flags.valueTier !== undefined || flags.budgetTokens !== undefined;\n const stage = <T>(name: string, fresh: () => Promise<T> | T, force = false): Promise<T> | T => {\n if (!force) {\n const cp = readCheckpoint(id, name);\n if (cp) {\n onStage?.(name, 'cached');\n return cp.data as T;\n }\n }\n onStage?.(name, 'run');\n return fresh();\n };\n const checkpoint = <T>(name: string, data: T): T => {\n writeCheckpoint(id, name, data);\n return data;\n };\n\n // 1. context \u2014 repo card + key modules (cheap, local).\n const card = buildRepoCard(root);\n const context = await stage('context', () =>\n checkpoint('context', { context: contextSummary(root, card), task }),\n );\n\n // 2. goal \u2014 explicit end goal + definition of done. A clarify outcome is NOT\n // checkpointed: the user answers, re-runs, and we derive again with the\n // refined task (which keys a fresh pipeline anyway).\n const ai = createAiClient({ provider: 'deepseek' });\n const goalCp = readCheckpoint(id, 'goal');\n let goal: SessionGoal;\n if (goalCp) {\n onStage?.('goal', 'cached');\n goal = goalCp.data as SessionGoal;\n } else {\n onStage?.('goal', 'run');\n const result: GoalResult = await deriveGoal(task, context.context, ai, {\n model: opts.model,\n effort,\n });\n if (result.kind === 'clarify') return { kind: 'clarify', question: result.question };\n goal = checkpoint('goal', result.goal);\n }\n\n // 3. value + budget \u2014 inferred importance composed with the selected effort.\n // Recomputed (no model call) when --value/--budget is supplied.\n const valueAndBudget = await stage(\n 'value',\n () => {\n const detected = assessProjectValue(\n {\n card,\n indexedChunks: loadRetriever(root)?.size ?? 0,\n task,\n memory: readMemory(root),\n },\n cfg,\n );\n const value = flags.valueTier ? overrideValueTier(detected, flags.valueTier) : detected;\n const budget = computeBudget(effort, value.tier, cfg, {\n ...(flags.budgetTokens !== undefined ? { maxTokens: flags.budgetTokens } : {}),\n });\n return checkpoint('value', { value, budget });\n },\n hasBudgetOverride,\n );\n const { value, budget } = valueAndBudget as {\n value: ValueAssessment;\n budget: ReturnType<typeof computeBudget>;\n };\n\n // 4. draft \u2014 the model proposes research steps, tooling candidates, task DAG.\n let draftFresh = false;\n const draft = await stage('draft', async () => {\n draftFresh = true;\n const d = await draftBuildPlan(goal, context.context, ai, {\n model: opts.model,\n effort,\n budget,\n modelProfile: modelProfile(cfg, opts.model),\n });\n if (!d) throw new Error('the planner returned no usable plan \u2014 try rephrasing the task');\n return checkpoint('draft', d);\n });\n\n // 5. final \u2014 rank candidates per tooling area (popularity + maintenance +\n // docs) and record WHY each winner was chosen. Re-assembled (no model\n // call) when the embedded value/budget changed.\n const plan = await stage(\n 'final',\n async () => {\n // A freshly-drafted task DAG invalidates per-task execution progress; a\n // mere budget/value recompute must NOT (that is the \"continue with a\n // bigger budget\" flow).\n if (draftFresh) clearCheckpoints(id, 'exec-');\n const tooling: SelectionResult[] = [];\n for (const area of (draft as BuildPlanDraft).tooling) {\n const resolved = await rankCandidates(area.area, area.candidates, cfg);\n if (resolved) tooling.push(resolved);\n }\n const final: BuildPlan = {\n goal,\n model: opts.model,\n ...(opts.tier ? { tier: opts.tier } : {}),\n effort,\n value,\n budget,\n research: (draft as BuildPlanDraft).research,\n tooling,\n packages: tooling.map((t) => t.chosen),\n tasks: (draft as BuildPlanDraft).tasks,\n };\n return checkpoint('final', final);\n },\n hasBudgetOverride,\n );\n\n return { kind: 'plan', id, plan: plan as BuildPlan };\n}\n\nfunction printTaskDag(tasks: readonly Task[]): void {\n const batches = scheduleByDeps(tasks);\n line(`build: ${tasks.length} tasks in ${batches.length} stage${batches.length === 1 ? '' : 's'}`);\n batches.forEach((batch, i) => {\n line(color.bold(` stage ${i + 1}${batch.length > 1 ? ' (parallel)' : ''}:`));\n for (const t of batch) {\n const deps = t.dependsOn.length ? ` ${color.dim(`[after ${t.dependsOn.join(', ')}]`)}` : '';\n line(` ${color.cyan(t.id)} ${t.title}${deps}`);\n if (t.targets.length) line(color.dim(` targets: ${t.targets.join(', ')}`));\n }\n });\n}\n\n/** Print the full pre-build plan (goal, value, budget, research, tooling, DAG). */\nexport function printBuildPlan(plan: BuildPlan): void {\n const cfg = loadPlanningConfig();\n for (const l of formatGoal(plan.goal)) line(l);\n line(formatValue(plan.value, cfg));\n line(`budget: ${plan.budget.explanation}`);\n line(\n color.dim(\n `depth: ${plan.budget.researchSteps} research \u00B7 ${plan.budget.candidatesPerChoice} candidates/choice \u00B7 ` +\n `${plan.budget.validationPasses} validation pass${plan.budget.validationPasses === 1 ? '' : 'es'} \u00B7 ` +\n `model ${plan.model} (${plan.effort})`,\n ),\n );\n if (plan.research.length > 0) {\n line(color.bold('research first:'));\n for (const r of plan.research) line(` ${r.id}. ${r.question}`);\n }\n if (plan.tooling.length > 0) {\n line(color.bold('tooling (decided before building):'));\n for (const t of plan.tooling) {\n line(` ${t.area}: ${color.cyan(t.chosen)}`);\n line(color.dim(` why: ${t.rationale}`));\n }\n }\n printTaskDag(plan.tasks);\n}\n\n/** `futurex plan \"<task>\"` \u2014 produce + print the pre-build plan (resumable). */\nexport async function runPlan(task: string, opts: CliOptions, flags: PlanFlags = {}): Promise<void> {\n const q = task.trim();\n if (!q) {\n error('usage: futurex plan \"<task>\"');\n process.exitCode = 1;\n return;\n }\n const id = pipelineId(`${findRepoRoot()}::${q}`);\n info(`pipeline ${id}${flags.restart ? ' (restart)' : ''}`);\n try {\n const outcome = await ensureBuildPlan(q, opts, flags, (name, status) =>\n info(` ${status === 'cached' ? '\u2713 resumed' : '\u2026 running'} ${name}`),\n );\n if (outcome.kind === 'clarify') {\n info('one question before planning:');\n line(` ? ${outcome.question}`);\n line(color.dim('(answer by re-running plan with the detail added)'));\n return;\n }\n printBuildPlan(outcome.plan);\n line(color.dim(`(build it with \\`futurex build \"${q}\"\\`, or inspect via \\`futurex resume ${outcome.id}\\`)`));\n } catch (err) {\n error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n}\n\n/** `futurex resume [id]` \u2014 inspect pipeline checkpoints (list all, or show one's plan). */\nexport function runResume(id?: string): void {\n if (!id) {\n const ids = listPipelines();\n if (ids.length === 0) {\n info('no pipelines yet \u2014 run `futurex plan \"<task>\"`');\n return;\n }\n info(`pipelines (${ids.length}):`);\n for (const pid of ids) line(` ${pid} \u2014 ${listCheckpoints(pid).join(', ') || 'no checkpoints'}`);\n line(color.dim('show one with `futurex resume <id>`'));\n return;\n }\n const stages = listCheckpoints(id);\n if (stages.length === 0) {\n info(`no checkpoints for pipeline ${id}`);\n return;\n }\n info(`pipeline ${id}: checkpoints = ${stages.join(', ')}`);\n const finalCp = readCheckpoint(id, 'final');\n if (finalCp) {\n printBuildPlan(finalCp.data as BuildPlan);\n return;\n }\n // Legacy pipelines (pre-planning-layer) checkpointed a bare task DAG as 'plan'.\n const legacy = readCheckpoint(id, 'plan');\n if (legacy) {\n const result = legacy.data as PlanResult;\n if (result.kind === 'plan') printTaskDag(result.plan.tasks);\n else for (const q of result.questions) line(` ? ${q}`);\n return;\n }\n line(color.dim('plan stage not reached \u2014 re-run `futurex plan \"<task>\"` to continue'));\n}\n", "/**\n * Skills (Blueprint v2 P8): reusable, stack-aware capability packs. A skill\n * declares triggers, the stacks it applies to, a model hint, a system-prompt\n * fragment, and an output contract. `selectSkills` routes a request to the\n * matching skills (the deterministic composer core); every codegen skill emits a\n * `{ path: contents }` JSON file map, which `parseFileMap` validates so the write\n * stage is deterministic and path-safe.\n */\nimport { resolve, sep } from 'node:path';\n\nexport interface SkillExample {\n readonly prompt: string;\n readonly note?: string;\n}\n\nexport interface Skill {\n readonly name: string;\n readonly description: string;\n /** Lowercase substrings that route a request to this skill. */\n readonly triggers: readonly string[];\n /** Stacks this skill is tuned for (informational; empty = any). */\n readonly appliesToStacks: readonly string[];\n /** Preferred tier for this skill's generations. */\n readonly modelHint: 'fx-pro' | 'fx-fast' | 'fx-mini';\n /** The system-prompt fragment this skill contributes. */\n readonly system: string;\n /** Output contract \u2014 codegen skills emit a `{ path: contents }` file map. */\n readonly outputContract: 'file-map';\n readonly examples: readonly SkillExample[];\n}\n\nconst FILE_MAP_CONTRACT =\n 'OUTPUT CONTRACT: respond with ONLY a single JSON object mapping each repo-relative POSIX file path ' +\n 'to that file\\'s FULL contents as a string. No prose, no markdown, no code fences. ' +\n 'Example: {\"src/app/page.tsx\":\"export default function Page(){...}\"}';\n\nexport const BUILTIN_SKILLS: readonly Skill[] = [\n {\n name: 'frontend-nextjs-tailwind',\n description: 'Next.js (App Router) + TypeScript + Tailwind UI',\n triggers: ['next.js', 'nextjs', 'next ', 'react', 'tailwind', 'frontend', 'ui ', 'component', 'page ', 'app router'],\n appliesToStacks: ['Next.js', 'React'],\n modelHint: 'fx-pro',\n system: [\n 'You are a senior frontend engineer building Next.js (App Router) + TypeScript + Tailwind CSS.',\n 'Default to React Server Components; add \"use client\" only when interactivity requires it.',\n 'Style with Tailwind utility classes; keep components small, typed, and accessible (semantic HTML, aria).',\n 'Co-locate route files under app/, shared UI under components/. No inline styles, no any.',\n ].join(' '),\n outputContract: 'file-map',\n examples: [{ prompt: 'build a chat app in Next.js with a message list and input' }],\n },\n {\n name: 'backend-api',\n description: 'Typed HTTP API (Fastify / Express / NestJS / Go / Python profiles)',\n triggers: ['api', 'endpoint', 'route', 'backend', 'server', 'rest', 'graphql', 'fastify', 'express', 'nestjs', 'controller', 'handler'],\n appliesToStacks: ['Fastify', 'Express', 'NestJS'],\n modelHint: 'fx-pro',\n system: [\n 'You are a senior backend engineer building typed HTTP APIs.',\n 'Match the project framework (Fastify/Express/NestJS/Go/Python). Validate inputs at the boundary,',\n 'return a consistent error envelope, keep handlers thin and business logic in testable services.',\n 'No secrets in code; read config from the environment.',\n ].join(' '),\n outputContract: 'file-map',\n examples: [{ prompt: 'add a REST endpoint POST /messages backed by a service' }],\n },\n {\n name: 'project-structuring',\n description: 'Scaffold project structure, config, and conventions',\n triggers: ['scaffold', 'structure', 'set up', 'setup', 'bootstrap', 'monorepo', 'new project', 'layout', 'organize', 'bootstrapping'],\n appliesToStacks: [],\n modelHint: 'fx-mini',\n system: [\n 'You are a senior engineer setting up project structure.',\n 'Propose a clean directory layout, the minimal config files, and naming conventions suited to the stack.',\n 'Prefer convention over configuration; include a short README and sensible .gitignore.',\n ].join(' '),\n outputContract: 'file-map',\n examples: [{ prompt: 'scaffold a TypeScript monorepo with pnpm workspaces' }],\n },\n];\n\n/**\n * Route a request to the skills whose triggers match (the deterministic composer\n * core; a Flash-OFF intent normalizer can refine this later). Falls back to\n * `project-structuring` when nothing else matches.\n */\nexport function selectSkills(prompt: string, skills: readonly Skill[] = BUILTIN_SKILLS): Skill[] {\n const p = prompt.toLowerCase();\n const matched = skills.filter((s) => s.triggers.some((t) => p.includes(t)));\n if (matched.length > 0) return matched;\n const fallback = skills.find((s) => s.name === 'project-structuring');\n return fallback ? [fallback] : [];\n}\n\n/** Compose the system prompts of the selected skills plus the file-map contract. */\nexport function composeSkillSystems(skills: readonly Skill[]): string {\n const parts = skills.map((s) => `# Skill: ${s.name}\\n${s.system}`);\n parts.push(FILE_MAP_CONTRACT);\n return parts.join('\\n\\n');\n}\n\n/* -------------------------------------------------------------------------- */\n/* Output contract: { path: contents } file map */\n/* -------------------------------------------------------------------------- */\n\nexport interface FileMapEntry {\n readonly path: string;\n readonly contents: string;\n}\n\nexport interface FileMapParse {\n readonly files: FileMapEntry[];\n readonly errors: string[];\n}\n\n/** True when `p` is a safe repo-relative path (no absolute / drive / UNC / `..`). */\nexport function isSafeRepoPath(p: string): boolean {\n if (!p || p.startsWith('/') || p.startsWith('\\\\')) return false;\n if (/^[a-zA-Z]:/.test(p)) return false; // drive-letter absolute\n const segments = p.split(/[\\\\/]/);\n return !segments.some((s) => s === '..' || s === '');\n}\n\nfunction extractJsonObject(raw: string): Record<string, unknown> | undefined {\n const start = raw.indexOf('{');\n const end = raw.lastIndexOf('}');\n if (start === -1 || end <= start) return undefined;\n try {\n return JSON.parse(raw.slice(start, end + 1)) as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Deterministically parse a skill's `{ path: contents }` output into validated,\n * path-safe file entries. Unsafe paths and non-string contents are rejected into\n * `errors` rather than written.\n */\nexport function parseFileMap(raw: string): FileMapParse {\n const json = extractJsonObject(raw);\n if (!json) return { files: [], errors: ['no JSON object found in skill output'] };\n const files: FileMapEntry[] = [];\n const errors: string[] = [];\n for (const [path, contents] of Object.entries(json)) {\n if (typeof contents !== 'string') {\n errors.push(`'${path}': contents is not a string`);\n continue;\n }\n if (!isSafeRepoPath(path)) {\n errors.push(`'${path}': unsafe path rejected (absolute / .. / UNC)`);\n continue;\n }\n files.push({ path: path.split('\\\\').join('/'), contents });\n }\n return { files, errors };\n}\n\n/**\n * Confirm a parsed file entry resolves inside `root` (defense-in-depth over\n * {@link isSafeRepoPath}). The actual write is performed by the caller.\n */\nexport function resolvesInRepo(root: string, relPath: string): boolean {\n const base = resolve(root);\n const abs = resolve(base, relPath);\n return abs === base || abs.startsWith(base + sep);\n}\n", "/**\n * `futurex skills [list | <request>]` \u2014 list the available skills, or show which\n * skills a request routes to (the deterministic intent \u2192 skill composer).\n */\nimport { buildRepoCard, findRepoRoot } from './repo.js';\nimport { BUILTIN_SKILLS, selectSkills } from './skills.js';\nimport { color, info, line } from './ui.js';\n\nexport function runSkills(arg: string): void {\n const q = arg.trim();\n if (q === '' || q === 'list') {\n const card = buildRepoCard(findRepoRoot());\n const stack = [card.framework, card.backend].filter((x): x is string => Boolean(x));\n info(`skills (${BUILTIN_SKILLS.length})${stack.length ? ` \u00B7 detected stack: ${stack.join(', ')}` : ''}:`);\n for (const s of BUILTIN_SKILLS) {\n line(` ${color.cyan(s.name)} \u2014 ${s.description} ${color.dim(`[${s.modelHint}]`)}`);\n line(color.dim(` triggers: ${s.triggers.slice(0, 6).join(', ')}`));\n }\n line(color.dim('route a request: `futurex skills \"build a chat app in Next.js\"`'));\n return;\n }\n const matched = selectSkills(q);\n info(`\"${q}\" \u2192 ${matched.length} skill${matched.length === 1 ? '' : 's'}:`);\n for (const s of matched) {\n line(` ${color.cyan(s.name)} ${color.dim(`[${s.modelHint}]`)} \u2014 ${s.description}`);\n }\n}\n", "/**\n * `futurex verify [--list]` / `futurex test` \u2014 run the project's diagnostics\n * (typecheck/lint/test/build) and report structured pass/fail results. Runs the\n * checks WITHOUT blocking the event loop, so the REPL's chatbox (spinner,\n * Ctrl+C, queued input) stays alive during a slow typecheck. This is the\n * diagnostics surface the repair loop ({@link ./repair.ts}) feeds from.\n */\nimport { findRepoRoot } from './repo.js';\nimport { detectChecks, runDiagnosticsAsync } from './diagnostics.js';\nimport { color, error, info, line, startSpinner, verdictLine } from './ui.js';\n\nexport async function runVerify(\n opts: { list?: boolean; only?: string; signal?: AbortSignal } = {},\n): Promise<void> {\n const root = findRepoRoot();\n let checks = detectChecks(root);\n if (opts.only) checks = checks.filter((c) => c.name === opts.only);\n if (checks.length === 0) {\n info(opts.only ? `no \\`${opts.only}\\` script detected` : 'no typecheck/lint/test/build scripts detected');\n return;\n }\n if (opts.list) {\n info(`detected checks (${checks.length}):`);\n for (const c of checks) line(` ${c.name} \u2192 ${c.command}`);\n return;\n }\n\n info(`running ${checks.length} check${checks.length === 1 ? '' : 's'} in ${root} \u2026`);\n const spin = startSpinner('verifying\u2026');\n let results;\n try {\n results = await runDiagnosticsAsync(root, {\n checks,\n ...(opts.signal ? { signal: opts.signal } : {}),\n });\n } finally {\n spin.stop();\n }\n let failed = 0;\n for (const r of results) {\n const state = r.timedOut ? 'timed out' : '';\n line(verdictLine(r.ok, `${r.name} ${state}${color.dim(`(${(r.durationMs / 1000).toFixed(1)}s)`)}`));\n if (!r.ok) {\n failed++;\n if (r.failingFiles.length > 0) {\n line(color.dim(` files: ${r.failingFiles.slice(0, 8).join(', ')}`));\n }\n }\n }\n if (failed > 0) {\n error(`${failed}/${results.length} checks failed`);\n process.exitCode = 1;\n } else {\n info(`all ${results.length} checks passed`);\n }\n}\n", "import { createEmbedder, FlatVectorStore } from '@fim/futurex-vector';\nimport { buildIndex, saveIndex, type Chunk } from '@fim/futurex-context';\nimport { findRepoRoot } from './repo.js';\nimport { indexPath, loadRetriever } from './index-store.js';\nimport { color, error, info, line } from './ui.js';\n\n/** `futurex index` \u2014 scan the repo, chunk, embed (locally), extract AST symbols, persist. */\nexport async function runIndex(): Promise<void> {\n const root = findRepoRoot();\n const embedder = createEmbedder(); // DeepSeek-only: in-process local embedder\n const store = new FlatVectorStore<Chunk>();\n try {\n info(`indexing ${root} \u2026`);\n const { stats, symbols, imports } = await buildIndex(root, embedder, store);\n saveIndex(indexPath(root), {\n embedderId: embedder.id,\n dimensions: embedder.dimensions,\n root,\n createdAt: new Date().toISOString(),\n records: store.toRecords(),\n symbols,\n imports,\n });\n info(\n `indexed ${stats.files} files \u2192 ${stats.chunks} chunks \u00B7 ${stats.symbols} symbols \u00B7 ${stats.imports} imports (${embedder.id})` +\n (stats.redacted > 0 ? ` \u00B7 ${stats.redacted} secrets redacted` : '') +\n (stats.brokenImports > 0 ? ` \u00B7 ${stats.brokenImports} broken imports` : ''),\n );\n } catch (err) {\n error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n}\n\n/**\n * `futurex symbols [name]` \u2014 answer \"is this symbol already defined?\" from the AST\n * symbol index (\u00A73.5). With no name, print index totals.\n */\nexport function runSymbols(name: string): void {\n const root = findRepoRoot();\n const retriever = loadRetriever(root);\n if (!retriever) {\n info('no index \u2014 run `futurex index` first');\n return;\n }\n const q = name.trim();\n const s = retriever.symbols.stats();\n if (!q) {\n info(`index: ${s.symbols} symbols across ${s.files} files`);\n return;\n }\n const defs = retriever.symbols.lookup(q);\n if (defs.length > 0) {\n line(`'${q}' is defined (${defs.length}):`);\n for (const d of defs) {\n const where = d.container ? `${d.container}.${d.name}` : d.name;\n line(` ${d.kind} ${where} \u2014 ${d.file}:${d.startLine}${d.exported ? ' (exported)' : ''}`);\n }\n return;\n }\n const fuzzy = retriever.symbols.search(q, 10);\n if (fuzzy.length === 0) {\n line(`'${q}' is not defined in the index`);\n return;\n }\n line(`'${q}' is not defined. Similar:`);\n for (const d of fuzzy) line(` ${d.name} (${d.kind}) \u2014 ${d.file}:${d.startLine}`);\n}\n\n/**\n * `futurex imports [file]` \u2014 show the import graph. No file \u2192 totals + broken\n * imports; a file \u2192 its imports (resolved / external / broken) and who imports it.\n */\nexport function runImports(file: string): void {\n const root = findRepoRoot();\n const retriever = loadRetriever(root);\n if (!retriever) {\n info('no index \u2014 run `futurex index` first');\n return;\n }\n const g = retriever.imports;\n const q = file.trim();\n if (!q) {\n const s = g.stats();\n info(\n `imports \u00B7 ${s.edges} edges \u00B7 ${s.internal} internal \u00B7 ${s.external} external \u00B7 ${s.broken} broken (${s.files} files)`,\n );\n const broken = g.broken();\n if (broken.length === 0) {\n line(color.green('no broken imports'));\n return;\n }\n line(color.red(`${broken.length} broken import${broken.length === 1 ? '' : 's'}:`));\n for (const b of broken.slice(0, 30)) line(` ${b.file} ${color.dim('\u2192')} ${b.specifier}`);\n if (broken.length > 30) line(color.dim(` \u2026and ${broken.length - 30} more`));\n return;\n }\n const want = q.split('\\\\').join('/');\n const target =\n g.importsOf(want).length > 0 || g.importersOf(want).length > 0\n ? want\n : g.files().find((f) => f === want || f.endsWith(`/${want}`) || f.endsWith(want));\n if (!target) {\n info(`no import data for '${want}' (not indexed, or it has no imports)`);\n return;\n }\n const imps = g.importsOf(target);\n const importers = g.importersOf(target);\n line(`${color.bold(target)} imports (${imps.length}):`);\n for (const i of imps) {\n const mark =\n i.kind === 'internal'\n ? color.green('\u2192')\n : i.kind === 'external'\n ? color.dim('\u2022')\n : color.red('\u2717 broken');\n line(` ${mark} ${i.specifier}${i.resolved ? color.dim(` (${i.resolved})`) : ''}`);\n }\n if (importers.length > 0) {\n line(\n color.dim(\n `imported by ${importers.length}: ${importers.slice(0, 8).join(', ')}${importers.length > 8 ? ', \u2026' : ''}`,\n ),\n );\n }\n}\n", "/**\n * Device-authorization (\"link code\") login for the CLI.\n *\n * `futurex login` no longer takes a password in the terminal: it asks the\n * gateway to start a device authorization, shows a short code + a verification\n * link, opens the browser, and polls until the user approves while signed in to\n * the web console. On approval the gateway returns the same session tokens a\n * password login would, which {@link writeCreds} persists \u2014 so the rest of the\n * CLI is unchanged.\n */\nimport { spawn } from 'node:child_process';\nimport { apiBaseUrl } from './config.js';\nimport { readCreds, writeCreds, type Credentials } from './creds.js';\nimport { color, info, line, startSpinner } from './ui.js';\n\ninterface DeviceStartData {\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n expiresIn: number;\n interval: number;\n}\n\ninterface Envelope<T> {\n success?: boolean;\n data?: T;\n error?: { message?: string };\n}\n\ninterface TokenData {\n status: 'authorization_pending' | 'denied' | 'expired' | 'approved';\n user?: { email?: string };\n tokens?: { accessToken?: string };\n}\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Pull the `fim_rt` refresh cookie out of a response's Set-Cookie headers. */\nfunction extractRefreshCookie(res: Response): string | undefined {\n const getSetCookie = (res.headers as { getSetCookie?: () => string[] }).getSetCookie;\n const cookies = typeof getSetCookie === 'function' ? getSetCookie.call(res.headers) : [];\n for (const c of cookies) {\n if (c.startsWith('fim_rt=')) return c.split(';')[0];\n }\n return undefined;\n}\n\n/** Best-effort: open `url` in the platform browser. Never throws. */\nfunction openBrowser(url: string): void {\n try {\n const platform = process.platform;\n const [cmd, args] =\n platform === 'win32'\n ? ['cmd', ['/c', 'start', '', url]]\n : platform === 'darwin'\n ? ['open', [url]]\n : ['xdg-open', [url]];\n const child = spawn(cmd, args, { stdio: 'ignore', detached: true });\n child.on('error', () => {});\n child.unref();\n } catch {\n /* headless / no browser \u2014 the printed link is the fallback */\n }\n}\n\n/**\n * Run the device-authorization login. Prints the code + link, opens the\n * browser, and polls until approval, then persists + returns the credentials.\n * Throws on denial, expiry, or timeout.\n */\nexport async function deviceLogin(opts: { noBrowser?: boolean } = {}): Promise<Credentials> {\n const apiUrl = apiBaseUrl();\n\n const startRes = await fetch(`${apiUrl}/api/v1/futurex/device/start`, { method: 'POST' });\n const startJson = (await startRes.json().catch(() => ({}))) as Envelope<DeviceStartData>;\n const start = startJson.data;\n if (!startRes.ok || !start?.deviceCode) {\n throw new Error(startJson.error?.message ?? `could not start sign-in (${startRes.status})`);\n }\n\n line();\n line(` ${color.bold('Sign in to FutureX')}`);\n line(` Open ${color.cyan(start.verificationUri)} and enter this code:`);\n line();\n line(` ${color.bold(color.magenta(start.userCode))}`);\n line();\n line(color.dim(` Only approve a code you started here. The link expires in ${Math.round(start.expiresIn / 60)} min.`));\n line();\n\n if (!opts.noBrowser) {\n info('opening your browser\u2026');\n openBrowser(start.verificationUriComplete);\n }\n\n const intervalMs = Math.max(1, start.interval) * 1000;\n const deadline = Date.now() + start.expiresIn * 1000;\n const spin = startSpinner('waiting for approval in your browser\u2026');\n try {\n while (Date.now() < deadline) {\n await sleep(intervalMs);\n let tokenJson: Envelope<TokenData>;\n try {\n const res = await fetch(`${apiUrl}/api/v1/futurex/device/token`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ deviceCode: start.deviceCode }),\n });\n tokenJson = (await res.json().catch(() => ({}))) as Envelope<TokenData>;\n const data = tokenJson.data;\n if (data?.status === 'approved') {\n const accessToken = data.tokens?.accessToken;\n if (!accessToken) throw new Error('approval returned no access token');\n const creds: Credentials = {\n apiUrl,\n ...(data.user?.email ? { email: data.user.email } : {}),\n accessToken,\n ...(extractRefreshCookie(res) ? { refreshCookie: extractRefreshCookie(res) } : {}),\n };\n writeCreds(creds);\n return creds;\n }\n if (data?.status === 'denied') throw new Error('sign-in was declined in the browser');\n if (data?.status === 'expired') throw new Error('the code expired \u2014 run `futurex login` again');\n // authorization_pending (or a transient non-2xx) \u2192 keep polling.\n } catch (err) {\n // A terminal status above is rethrown; transient network blips fall\n // through and we retry on the next tick.\n if (err instanceof Error && /declined|expired|no access token/.test(err.message)) throw err;\n }\n }\n } finally {\n spin.stop();\n }\n throw new Error('sign-in timed out \u2014 run `futurex login` again');\n}\n\n/**\n * Return stored credentials, or run the device-login flow when absent. The\n * single gate that makes login mandatory: every FutureX command that reaches\n * the gateway calls this first.\n */\nexport async function ensureLoggedIn(): Promise<Credentials> {\n const existing = readCreds();\n if (existing?.accessToken) return existing;\n info('FutureX requires sign-in.');\n const creds = await deviceLogin();\n info(`signed in as ${creds.email ?? 'your account'}`);\n return creds;\n}\n", "import { apiBaseUrl } from './config.js';\nimport { clearCreds, readCreds } from './creds.js';\nimport { login } from './auth.js';\nimport { deviceLogin } from './device.js';\nimport { color, error, info, line } from './ui.js';\n\n/**\n * `futurex login` \u2014 sign in. Default is the browser \"link code\" device flow\n * (no password in the terminal). If both `--email` and `--password` (or the\n * `FUTUREX_EMAIL`/`FUTUREX_PASSWORD` env vars) are supplied, the legacy\n * password login is used instead \u2014 kept only for non-interactive CI.\n */\nexport async function runLogin(flags: Record<string, string | boolean>): Promise<void> {\n const email = typeof flags.email === 'string' ? flags.email : process.env.FUTUREX_EMAIL;\n const password = typeof flags.password === 'string' ? flags.password : process.env.FUTUREX_PASSWORD;\n\n try {\n if (email && password) {\n const creds = await login(email, password);\n info(`logged in as ${creds.email ?? email} \u00B7 ${apiBaseUrl()}`);\n return;\n }\n const creds = await deviceLogin({ noBrowser: flags['no-browser'] === true });\n info(`logged in as ${creds.email ?? 'your account'} \u00B7 ${apiBaseUrl()}`);\n } catch (err) {\n error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n}\n\n/** `futurex logout` \u2014 clear stored credentials. */\nexport function runLogout(): void {\n clearCreds();\n info('logged out');\n}\n\n/** `futurex whoami` \u2014 show the current auth/backend mode. */\nexport function runWhoami(): void {\n const creds = readCreds();\n if (!creds?.accessToken) {\n line('not signed in \u2014 run `futurex login`');\n return;\n }\n line(`${color.bold(creds.email ?? 'unknown')} \u00B7 gateway ${creds.apiUrl}`);\n}\n", "#!/usr/bin/env node\n/**\n * FutureX CLI entrypoint (Phase 0).\n *\n * futurex open the interactive REPL\n * futurex ask \"<prompt>\" one-shot: stream a single answer\n * futurex help show usage\n *\n * Dependency-free arg parsing (commander arrives when the command surface grows).\n */\nimport type { EffortLevel, Tier } from '@fim/futurex-protocol';\nimport { normalizeTier, resolveTier, TIER_IDS } from '@fim/futurex-protocol';\nimport { runAsk } from './ask.js';\nimport { runRepl } from './repl.js';\nimport { runLogin, runLogout, runWhoami } from './commands.js';\nimport { runBuild } from './build-command.js';\nimport { runIndex, runSymbols, runImports } from './index-command.js';\nimport { runInit, runCompact } from './memory-command.js';\nimport { runPermissions } from './permissions-command.js';\nimport { findRepoRoot } from './repo.js';\nimport { runPlan, runResume, type PlanFlags } from './plan-command.js';\nimport { type ValueTier } from './planning-config.js';\nimport { runSkills } from './skills-command.js';\nimport { runVerify } from './verify-command.js';\nimport { runAgent } from './agent.js';\nimport { ensureLoggedIn } from './device.js';\nimport type { CliOptions } from './options.js';\nimport { color, error, info, line } from './ui.js';\n\nconst VERSION = '0.1.0';\n\ninterface ParsedArgs {\n command: string;\n positionals: string[];\n flags: Record<string, string | boolean>;\n}\n\n/** Flags that take a value (`--model x` / `--model=x`). */\nconst VALUE_FLAGS = new Set([\n 'model',\n 'max-tokens',\n 'email',\n 'password',\n 'top-k',\n 'max-steps',\n 'tier',\n 'effort',\n 'value',\n 'budget',\n]);\nconst ALIASES: Record<string, string> = { r: 'reason', h: 'help', v: 'version', m: 'model' };\n\nfunction parseArgs(argv: readonly string[]): ParsedArgs {\n let command = '';\n const positionals: string[] = [];\n const flags: Record<string, string | boolean> = {};\n let noMoreFlags = false;\n\n const takePositional = (tok: string): void => {\n if (command === '' && positionals.length === 0) command = tok;\n else positionals.push(tok);\n };\n\n for (let i = 0; i < argv.length; i++) {\n const tok = argv[i];\n if (tok === undefined) continue;\n\n if (noMoreFlags) {\n takePositional(tok);\n continue;\n }\n if (tok === '--') {\n // Everything after `--` is positional (e.g. a prompt that begins with `-`).\n noMoreFlags = true;\n continue;\n }\n\n if (tok.startsWith('--')) {\n let body = tok.slice(2);\n let value: string | undefined;\n const eq = body.indexOf('=');\n if (eq !== -1) {\n value = body.slice(eq + 1);\n body = body.slice(0, eq);\n }\n if (VALUE_FLAGS.has(body)) {\n if (value === undefined) {\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n value = next;\n i++;\n }\n }\n // Record an empty value when none could be consumed, so downstream\n // validation rejects `--budget` / `--budget -5` instead of silently\n // dropping the user's flag.\n flags[body] = value ?? '';\n } else {\n flags[body] = value === undefined ? true : value !== 'false';\n }\n } else if (tok.startsWith('-') && tok !== '-') {\n const name = ALIASES[tok.slice(1)] ?? tok.slice(1);\n if (VALUE_FLAGS.has(name)) {\n const next = argv[i + 1];\n if (next !== undefined && !next.startsWith('-')) {\n flags[name] = next;\n i++;\n } else {\n flags[name] = '';\n }\n } else {\n flags[name] = true;\n }\n } else {\n takePositional(tok);\n }\n }\n\n return { command, positionals, flags };\n}\n\n/** Parse the named effort (`--effort off|high|max`, falling back to `--max`/`--reason`). */\nfunction effortFromFlags(flags: Record<string, string | boolean>): EffortLevel | undefined {\n const raw = typeof flags.effort === 'string' ? flags.effort.trim().toLowerCase() : '';\n if (raw !== '') {\n if (raw === 'off' || raw === 'high' || raw === 'max') return raw;\n throw new Error(`invalid --effort \"${raw}\" (expected: off | high | max)`);\n }\n if (flags.max === true) return 'max';\n if (flags.reason === true) return 'high';\n return undefined;\n}\n\nfunction buildOptions(flags: Record<string, string | boolean>): CliOptions {\n // Treat an empty `--model=` as unset so we fall back to a real default rather\n // than sending `model: ''` (which the provider would forward into a 400).\n const explicitModel =\n typeof flags.model === 'string' && flags.model.trim() !== '' ? flags.model.trim() : undefined;\n\n const effort = effortFromFlags(flags);\n\n let maxTokens: number | undefined;\n if (typeof flags['max-tokens'] === 'string') {\n const n = Number(flags['max-tokens']);\n if (Number.isFinite(n) && n > 0) maxTokens = Math.floor(n);\n else info(`ignoring invalid --max-tokens \"${flags['max-tokens']}\"`);\n }\n\n // The user-facing unit is a MODULE (fx-*). Default fx-fast; --pro / --max pick a\n // stronger module; --tier <id> is explicit. resolveTier ENFORCES allowed effort.\n // An explicit --model is a power-user escape hatch over the module's model.\n let tier: Tier;\n const tierRaw = typeof flags.tier === 'string' ? flags.tier.trim() : '';\n if (tierRaw !== '') {\n const norm = normalizeTier(tierRaw);\n if (!norm) throw new Error(`unknown module \"${tierRaw}\" (expected: ${TIER_IDS.join(' | ')})`);\n tier = norm;\n } else if (flags.pro === true || effort === 'max') {\n tier = 'fx-pro';\n } else {\n tier = 'fx-fast';\n }\n const resolved = resolveTier(tier, { effort, maxTokens });\n\n let topK = 6;\n if (typeof flags['top-k'] === 'string') {\n const n = Number(flags['top-k']);\n if (Number.isFinite(n) && n >= 0) topK = Math.floor(n);\n else info(`ignoring invalid --top-k \"${flags['top-k']}\"`);\n }\n\n return {\n model: explicitModel ?? resolved.model,\n reasoning: resolved.reasoning,\n tier,\n effort: resolved.effort,\n maxTokens: resolved.maxTokens,\n useMemory: flags['no-memory'] !== true,\n useRepo: flags['no-repo'] !== true,\n useContext: flags['no-context'] !== true,\n topK,\n };\n}\n\nconst VALUE_TIERS: readonly ValueTier[] = ['low', 'standard', 'high', 'critical'];\n\n/** Parse the planning-layer flags (`--restart`, `--value <tier>`, `--budget <n>`). */\nfunction planFlags(flags: Record<string, string | boolean>): PlanFlags {\n let valueTier: ValueTier | undefined;\n if (typeof flags.value === 'string') {\n const v = flags.value.trim().toLowerCase() as ValueTier;\n if (!VALUE_TIERS.includes(v)) {\n throw new Error(`invalid --value \"${flags.value}\" (expected: ${VALUE_TIERS.join(' | ')})`);\n }\n valueTier = v;\n }\n let budgetTokens: number | undefined;\n if (typeof flags.budget === 'string') {\n const n = Number(flags.budget);\n if (Number.isFinite(n) && n > 0) budgetTokens = Math.floor(n);\n else throw new Error(`invalid --budget \"${flags.budget}\" (expected a positive token count)`);\n }\n return {\n restart: flags.restart === true,\n ...(valueTier !== undefined ? { valueTier } : {}),\n ...(budgetTokens !== undefined ? { budgetTokens } : {}),\n };\n}\n\nfunction printHelp(): void {\n line(`${color.bold('futurex')} \u2014 terminal AI coding agent ${color.dim(`(v${VERSION})`)}`);\n line();\n line(color.bold('Usage'));\n line(' futurex open the interactive REPL');\n line(' futurex ask \"<prompt>\" one-shot answer, then exit');\n line(' futurex agent \"<task>\" agentic loop: the model uses tools (reads auto, writes gated)');\n line(' futurex index index the repo for retrieval-augmented answers');\n line(' futurex symbols [name] query the AST symbol index (\"is <name> defined?\")');\n line(' futurex imports [file] show the import graph + broken imports');\n line(' futurex init create futurex-memory.md (project memory) if absent');\n line(' futurex compact bound futurex-memory.md size (regenerate + archive)');\n line(' futurex plan \"<task>\" pre-build plan: goal + value/budget + research + tooling + task DAG');\n line(' futurex build \"<task>\" plan, then execute against the plan (stops when the goal is met)');\n line(' futurex resume [id] inspect/resume pipeline checkpoints');\n line(' futurex skills [request] list skills, or route a request to the matching skills');\n line(' futurex permissions view/change per-project consent (show | set <kind> <state> | reset)');\n line(' futurex verify [--list] run project diagnostics (typecheck/lint/test/build)');\n line(' futurex test run the project test script');\n line(' futurex login sign in via a browser link code (--no-browser to print only)');\n line(' futurex logout clear stored credentials');\n line(' futurex whoami show the current backend/auth mode');\n line(' futurex help show this help');\n line();\n line(color.bold('Options'));\n line(' --tier <module> fx-pro | fx-fast | fx-mini | fx-eco (the module preset)');\n line(' --effort <level> off | high | max (enforced against the module)');\n line(' -r, --reason use more reasoning effort (high)');\n line(' --max use maximum reasoning (implies the fx-pro module)');\n line(' --pro use the fx-pro module');\n line(' -m, --model <id> override the underlying model id (advanced)');\n line(' --max-tokens <n> cap output tokens');\n line(' --no-memory ignore futurex-memory.md');\n line(' --no-repo do not include the repo card');\n line(' --no-context do not augment with retrieved repo chunks');\n line(' --top-k <n> chunks to retrieve per turn (default 6)');\n line(' --auto-approve (agent) run mutating tools without prompting (dangerous)');\n line(' --max-steps <n> (agent) max model/tool rounds (default 32)');\n line(' --no-verify (agent) skip the automatic typecheck/lint/test pass after edits');\n line(' --value <tier> (plan/build) override the detected project value: low | standard | high | critical');\n line(' --budget <n> (plan/build) cap the build token budget');\n line(' --restart (plan/build) ignore checkpoints and re-plan from scratch');\n line(color.dim(' note: in a monorepo, `index` scans the whole workspace root.'));\n line(color.dim(' note: --tier/--effort apply to ask & chat; the agent executor runs fast by design.'));\n line(' -v, --version print version');\n line();\n line(color.dim('Set FX_API_KEY in your .env (auto-loaded when you run `futurex`).'));\n}\n\nasync function main(): Promise<void> {\n const { command, positionals, flags } = parseArgs(process.argv.slice(2));\n\n if (flags.version === true) {\n line(`futurex ${VERSION}`);\n return;\n }\n if (flags.help === true || command === 'help') {\n printHelp();\n return;\n }\n\n const opts = buildOptions(flags);\n\n // Login is mandatory for anything that reaches the gateway. These commands\n // sign in via the browser \"link code\" flow on first use (no-op when already\n // signed in); local utilities (index/symbols/init/verify/\u2026) stay offline.\n const AI_COMMANDS = new Set(['', 'chat', 'ask', 'agent', 'build', 'plan']);\n if (AI_COMMANDS.has(command)) {\n try {\n await ensureLoggedIn();\n } catch (err) {\n error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n return;\n }\n }\n\n switch (command) {\n case '':\n case 'chat':\n await runRepl(opts);\n return;\n case 'ask':\n await runAsk(positionals.join(' '), opts);\n return;\n case 'index':\n await runIndex();\n return;\n case 'symbols':\n runSymbols(positionals.join(' '));\n return;\n case 'imports':\n runImports(positionals.join(' '));\n return;\n case 'init':\n runInit();\n return;\n case 'compact':\n runCompact();\n return;\n case 'plan':\n await runPlan(positionals.join(' '), opts, planFlags(flags));\n return;\n case 'build':\n await runBuild(positionals.join(' '), opts, planFlags(flags));\n return;\n case 'resume':\n runResume(positionals[0]);\n return;\n case 'skills':\n runSkills(positionals.join(' '));\n return;\n case 'verify':\n await runVerify({ list: flags.list === true });\n return;\n case 'test':\n await runVerify({ only: 'test' });\n return;\n case 'agent': {\n const maxRaw = typeof flags['max-steps'] === 'string' ? Number(flags['max-steps']) : NaN;\n const maxSteps = Number.isFinite(maxRaw) && maxRaw > 0 ? Math.floor(maxRaw) : 32;\n await runAgent(positionals.join(' '), opts, {\n autoApprove: flags['auto-approve'] === true,\n maxSteps,\n verify: flags['no-verify'] === true ? 'off' : 'auto',\n });\n return;\n }\n case 'permissions':\n runPermissions(findRepoRoot(), positionals.join(' '));\n return;\n case 'login':\n await runLogin(flags);\n return;\n case 'logout':\n runLogout();\n return;\n case 'whoami':\n runWhoami();\n return;\n default:\n error(`unknown command: ${color.bold(command)}`);\n line();\n line(`run ${color.cyan('futurex help')} for usage.`);\n process.exitCode = 1;\n }\n}\n\nmain().catch((err: unknown) => {\n error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["existsSync", "mkdirSync", "readFileSync", "writeFileSync", "dirname", "resolve", "existsSync", "mkdirSync", "readFileSync", "rmSync", "writeFileSync", "dirname", "isAbsolute", "join", "relative", "sep", "dirname", "relative", "sep", "isAbsolute", "join", "readFileSync", "existsSync", "line", "mkdirSync", "writeFileSync", "rmSync", "out", "resolve", "existsSync", "readFileSync", "mkdirSync", "dirname", "writeFileSync", "out", "existsSync", "readFileSync", "writeFileSync", "dirname", "join", "resolve", "z", "error", "isProduction", "isTest", "resolve", "error", "readJson", "line", "readJson", "DEFAULT_BASE_URL", "DEFAULT_MAX_TOKENS", "stripTrailingSlash", "DEFAULT_BASE_URL", "readJson", "safeParse", "DEFAULT_MAX_TOKENS", "DEFAULT_BASE_URL", "DEFAULT_MAX_TOKENS", "stripTrailingSlash", "readJson", "mapFinishReason", "safeParse", "z", "z", "logger", "error", "fetch", "error", "resolve", "createHash", "homedir", "join", "readdirSync", "readFileSync", "statSync", "join", "relative", "sep", "existsSync", "readFileSync", "join", "basename", "MAX_FILE_BYTES", "out", "readdirSync", "join", "relative", "sep", "statSync", "readFileSync", "line", "out", "out", "out", "ts", "out", "existsSync", "mkdirSync", "readFileSync", "writeFileSync", "dirname", "join", "homedir", "createHash", "line", "createInterface", "createInterface", "existsSync", "readFileSync", "join", "out", "resolve", "resolve", "createInterface", "ESC", "SPINNER_FRAMES", "out", "resolve", "dot", "existsSync", "mkdirSync", "readdirSync", "writeFileSync", "join", "readdirSync", "out", "existsSync", "join", "mkdirSync", "writeFileSync", "createInterface", "question", "question", "existsSync", "readFileSync", "out", "existsSync", "readFileSync", "describe", "clamp01", "createHash", "existsSync", "mkdirSync", "readdirSync", "readFileSync", "rmSync", "writeFileSync", "join", "createHash", "join", "mkdirSync", "writeFileSync", "existsSync", "readFileSync", "readdirSync", "rmSync", "value", "budget", "createInterface", "refresh", "resolve", "createInterface", "spawn", "sleep", "resolve", "extractRefreshCookie", "spawn", "creds", "VERSION"]
7
+ }