/** Common Agent Runtime — native Node.js bindings. * * Most methods that return structured data return a JSON-encoded string; the * caller is expected to `JSON.parse` the result. This keeps the FFI surface * small and avoids coupling the native binding to any specific TS shape. * * ## Daemon-only * * Every method talks to the singleton car-server daemon over WebSocket * JSON-RPC. There is no embedded-engine fallback (the v0.7.x * `CAR_FFI_MODE=embedded` knob is retired). Start `car-server` before * using the bindings — on macOS the SwiftUI menubar app launches it for * you; on Linux start it manually or via systemd. * * The following methods are **not exposed in the FFI bindings** and throw * with a clear message — connect to the daemon's WebSocket directly * for the equivalent flow (see `docs/websocket-protocol.md`): * * - `executeProposal` — use `proposal.submit` JSON-RPC + a `tools.execute` * handler on the WS connection * - `inferStream`, `transcribeStream`, `dispatchVoiceTurn` — daemon * streams events over WS notifications * - `openSession`, `closeSession`, `registerPolicy(sessionId)` — use * `session.open` / `session.close` JSON-RPC methods * - `stateSnapshot`, `stateKeys` — daemon-side endpoints pending * * (`registerModel` was re-exposed in #39 — it now proxies to the * daemon's `models.register` JSON-RPC. See its docstring for * the visibility caveat.) * * Daemon URL override: `CAR_DAEMON_URL=ws://...` (default * `ws://127.0.0.1:9100`). */ /** Agent-loop tool declaration. `timeoutMs` becomes the action budget. */ export interface AgentToolSchema { name: string; description: string; parameters: Record; timeoutMs?: number; } export interface AgentToolContext { signal: AbortSignal; timeoutMs?: number; } export type AgentTool = ( params: Record, context: AgentToolContext, ) => unknown | Promise; export type AgentOutcomeStatus = | 'success' | 'partial_success' | 'done' | 'give_up' | 'timeout' | 'failure'; export interface AgentOutcome { status: AgentOutcomeStatus; summary: string; evidence: Array<{ kind: string; description: string; data: unknown }>; metrics: { turns: number; tool_calls: number; actions_succeeded: number; actions_failed: number; }; tools_called: string[]; timestamp: string; } /** Declarative input consumed by `car-runtime/agent-loop`. */ export interface AgentLoopConfig { agentId?: string; agentName: string; identity: string; toolSchemas?: AgentToolSchema[]; tools?: Record; policies?: Array<[string, string, string?, string?, string?, string?]>; defaultModel?: string | null; maxTokens?: number; maxTurns?: number; targetOutcome?: string; standingGoal?: string | null; intervalSecs?: number; } export interface AgentLoopOptions { maxTurns?: number; } /** Persistent runtime instance with state, memory, tools, and policies. */ /** * Optional settings for `coderStart`. Every field is independently omittable; * each falls back to the daemon's `~/.car/coder.toml`. * * **Breaking (v0.44.0):** replaced five trailing positional optionals — three * of them numbers — which callers could silently mis-order. */ export interface CoderStartOptions { /** `"auto" | "native" | "external[:agent_id]" | "foreman[:agent_id]"`. */ engine?: string | undefined | null; /** Contract-evaluation rounds before the native loop gives up. */ maxIterations?: number | undefined | null; /** Per-session backbone pin, reaching whichever engine runs. */ model?: string | undefined | null; /** * External-engine hypothesis budget: fresh repair invocations after a red * pass. Recurrence escalation needs >= 2 to reach the model at all. */ repairInvokes?: number | undefined | null; /** * External-engine availability budget: re-invocations after the CLI process * died mid-run. Separate from `repairInvokes` on purpose — one buys a * hypothesis, the other buys a retry. */ transientRetries?: number | undefined | null; /** * Expose the assistant's browser tools for this coder session. Off unless * explicitly true; each browser call still crosses coder policy and is * recorded in the session event stream. */ browser?: boolean | undefined | null; /** * Farm a **foreman** session's subtasks across every reachable CAR instance * that can serve this repository, instead of this machine alone. The * merge-verify gate and delivery stay on the orchestrating host — a peer * returns a patch and this host gates it — so a distributed run still * produces a gated pull request. * * Only the foreman engine decomposes a goal into subtasks, so any other * engine runs locally and says so. Off by default: it spends agent quota on * other people's machines. */ distributed?: boolean | undefined | null; /** * Restrict placement to these instances by name. Empty or omitted means * every instance that reports it can serve the repository. Ignored unless * `distributed` is set. */ workers?: Array | undefined | null; /** * A `coder.discuss` conversation this run was distilled from. Its agreed * constraints ride into contract derivation, so a rule stated once in the * discussion does not have to be restated in the intent, and the session * records the provenance. An unknown id is a clear error — never a silently * ungrounded run. */ discussionId?: string | undefined | null; } export interface DaemonRpcError extends Error { /** Numeric JSON-RPC error code returned by the daemon. */ code: number; /** Daemon-provided diagnostic text. */ message: string; /** Optional JSON-RPC error data returned by the daemon. */ data?: unknown; } export class CarRuntime { constructor(); /** * Invoke any daemon JSON-RPC method with a JSON-encoded params value. * `daemonCall` is the call-by-name escape hatch; use the typed wrappers as the primary API. * The result is returned as JSON. Daemon rejections are `DaemonRpcError`; * transport failures reject without a synthetic numeric code. */ daemonCall(method: string, paramsJson: string): Promise; /** Host-management-token twin of `daemonCall`; the method allowlist remains enforced. */ daemonCallHostManagement(method: string, paramsJson: string): Promise; /** Register a server-initiated JSON-RPC request handler. */ registerDaemonHandler( method: string, handler: (paramsJson: string) => Promise, ): void; /** Register a server-initiated JSON-RPC notification handler. */ registerDaemonNotificationHandler( method: string, handler: (paramsJson: string) => void, ): void; // BEGIN GENERATED daemon wrappers: CarRuntime /** Generated daemon wrapper for `CancelTask` (operator). */ cancelTask(paramsJson: string): Promise; /** Generated daemon wrapper for `CreateTaskPushNotificationConfig` (operator). */ createTaskPushNotificationConfig(paramsJson: string): Promise; /** Generated daemon wrapper for `DeleteTaskPushNotificationConfig` (operator). */ deleteTaskPushNotificationConfig(paramsJson: string): Promise; /** Generated daemon wrapper for `GetExtendedAgentCard` (operator). */ getExtendedAgentCard(paramsJson: string): Promise; /** Generated daemon wrapper for `GetTask` (operator). */ getTask(paramsJson: string): Promise; /** Generated daemon wrapper for `GetTaskPushNotificationConfig` (operator). */ getTaskPushNotificationConfig(paramsJson: string): Promise; /** Generated daemon wrapper for `ListTaskPushNotificationConfigs` (operator). */ listTaskPushNotificationConfigs(paramsJson: string): Promise; /** Generated daemon wrapper for `ListTasks` (operator). */ listTasks(paramsJson: string): Promise; /** Generated daemon wrapper for `SendMessage` (operator). */ sendMessage(paramsJson: string): Promise; /** Generated daemon wrapper for `SendStreamingMessage` (operator). */ sendStreamingMessage(paramsJson: string): Promise; /** Generated daemon wrapper for `SubscribeToTask` (operator). */ subscribeToTask(paramsJson: string): Promise; /** Generated daemon wrapper for `a2a.peers.add` (operator). */ a2aPeersAdd(paramsJson: string): Promise; /** Generated daemon wrapper for `a2a.peers.list` (operator). */ a2aPeersList(paramsJson: string): Promise; /** Generated daemon wrapper for `a2a.peers.remove` (operator). */ a2aPeersRemove(paramsJson: string): Promise; /** Generated daemon wrapper for `a2a.send` (operator). */ a2aSend(paramsJson: string): Promise; /** Generated daemon wrapper for `a2a.start` (operator). */ a2aStart(paramsJson: string): Promise; /** Generated daemon wrapper for `a2a.status` (operator). */ a2aStatus(paramsJson: string): Promise; /** Generated daemon wrapper for `a2a.stop` (operator). */ a2aStop(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui.action` (operator). */ a2uiAction(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui.apply` (operator). */ a2uiApply(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui.capabilities` (operator). */ a2uiCapabilities(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui.get` (operator). */ a2uiGet(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui.ingest` (operator). */ a2uiIngest(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui.reap` (operator). */ a2uiReap(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui.render_report` (operator). */ a2uiRenderReport(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui.surfaces` (operator). */ a2uiSurfaces(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui/replay` (operator). */ a2uiReplay(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui/subscribe` (operator). */ a2uiSubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `a2ui/unsubscribe` (operator). */ a2uiUnsubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `admission.status` (operator). */ admissionStatus(paramsJson: string): Promise; /** Generated daemon wrapper for `agent/getAuthenticatedExtendedCard` (operator). */ agentGetAuthenticatedExtendedCard(paramsJson: string): Promise; /** Generated daemon wrapper for `agent_permissions.evaluate` (operator). */ agentPermissionsEvaluate(paramsJson: string): Promise; /** Generated daemon wrapper for `agent_permissions.get` (operator). */ agentPermissionsGet(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.chat` (agent). */ agentsChat(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.chat.approve` (operator). */ agentsChatApprove(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.chat.cancel` (operator). */ agentsChatCancel(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.detect_external` (operator). */ agentsDetectExternal(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.health` (operator). */ agentsHealth(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.health_external` (operator). */ agentsHealthExternal(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.invoke_external` (operator). */ agentsInvokeExternal(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.list` (operator). */ agentsList(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.list_external` (operator). */ agentsListExternal(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.restart` (agent). */ agentsRestart(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.start` (agent). */ agentsStart(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.stop` (agent). */ agentsStop(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.tail_log` (operator). */ agentsTailLog(paramsJson: string): Promise; /** Generated daemon wrapper for `agents.wait` (operator). */ agentsWait(paramsJson: string): Promise; /** Generated daemon wrapper for `assistants.invoke` (operator). */ assistantsInvoke(paramsJson: string): Promise; /** Generated daemon wrapper for `automation.run_applescript` (operator). */ automationRunApplescript(paramsJson: string): Promise; /** Generated daemon wrapper for `automation.run_powershell` (operator). */ automationRunPowershell(paramsJson: string): Promise; /** Generated daemon wrapper for `automation.shortcuts.list` (operator). */ automationShortcutsList(paramsJson: string): Promise; /** Generated daemon wrapper for `automation.shortcuts.run` (operator). */ automationShortcutsRun(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.producer.register` (operator). */ browserProducerRegister(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.back` (operator). */ browserViewBack(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.click` (operator). */ browserViewClick(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.forward` (operator). */ browserViewForward(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.hand_back` (operator). */ browserViewHandBack(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.keypress` (operator). */ browserViewKeypress(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.navigate` (operator). */ browserViewNavigate(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.paste` (operator). */ browserViewPaste(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.reload` (operator). */ browserViewReload(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.scroll` (operator). */ browserViewScroll(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.subscribe` (operator). */ browserViewSubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.tab_close` (operator). */ browserViewTabClose(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.tab_open` (operator). */ browserViewTabOpen(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.tab_switch` (operator). */ browserViewTabSwitch(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.take_control` (operator). */ browserViewTakeControl(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.type` (operator). */ browserViewType(paramsJson: string): Promise; /** Generated daemon wrapper for `browser.view.unsubscribe` (operator). */ browserViewUnsubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `builder.build` (operator). */ builderBuild(paramsJson: string): Promise; /** Generated daemon wrapper for `capabilities.list` (operator). */ capabilitiesList(paramsJson: string): Promise; /** Generated daemon wrapper for `coder.discuss.subscribe` (operator). */ coderDiscussSubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `coder.discuss.unsubscribe` (operator). */ coderDiscussUnsubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `coder.projects.create` (operator). */ coderProjectsCreate(paramsJson: string): Promise; /** Generated daemon wrapper for `coder.projects.get` (operator). */ coderProjectsGet(paramsJson: string): Promise; /** Generated daemon wrapper for `coder.projects.list` (operator). */ coderProjectsList(paramsJson: string): Promise; /** Generated daemon wrapper for `coder.subscribe` (operator). */ coderSubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `coder.unsubscribe` (operator). */ coderUnsubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.actions` (operator). */ conciergeActions(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.apply` (operator). */ conciergeApply(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.ask` (operator). */ conciergeAsk(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.clear_default` (operator). */ conciergeClearDefault(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.defaults` (operator). */ conciergeDefaults(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.dismiss` (operator). */ conciergeDismiss(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.refresh_catalog` (operator). */ conciergeRefreshCatalog(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.rollback` (operator). */ conciergeRollback(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.set_default` (operator). */ conciergeSetDefault(paramsJson: string): Promise; /** Generated daemon wrapper for `concierge.status` (operator). */ conciergeStatus(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.add` (operator). */ connectorsAdd(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.add_stdio` (operator). */ connectorsAddStdio(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.authenticate` (operator). */ connectorsAuthenticate(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.complete_authentication` (operator). */ connectorsCompleteAuthentication(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.disable_tools` (operator). */ connectorsDisableTools(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.enable_tools` (operator). */ connectorsEnableTools(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.list` (operator). */ connectorsList(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.refresh` (operator). */ connectorsRefresh(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.remove` (operator). */ connectorsRemove(paramsJson: string): Promise; /** Generated daemon wrapper for `connectors.tools` (operator). */ connectorsTools(paramsJson: string): Promise; /** Generated daemon wrapper for `declagents.get` (operator). */ declagentsGet(paramsJson: string): Promise; /** Generated daemon wrapper for `declagents.invoke` (operator). */ declagentsInvoke(paramsJson: string): Promise; /** Generated daemon wrapper for `declagents.list` (operator). */ declagentsList(paramsJson: string): Promise; /** Generated daemon wrapper for `declagents.route` (operator). */ declagentsRoute(paramsJson: string): Promise; /** Generated daemon wrapper for `declagents.route_split` (operator). */ declagentsRouteSplit(paramsJson: string): Promise; /** Generated daemon wrapper for `declagents.routing_stats` (operator). */ declagentsRoutingStats(paramsJson: string): Promise; /** Generated daemon wrapper for `events.chain.enable` (operator). */ eventsChainEnable(paramsJson: string): Promise; /** Generated daemon wrapper for `events.chain.verify` (operator). */ eventsChainVerify(paramsJson: string): Promise; /** Generated daemon wrapper for `events.clear` (operator). */ eventsClear(paramsJson: string): Promise; /** Generated daemon wrapper for `events.cost_by_agent` (operator). */ eventsCostByAgent(paramsJson: string): Promise; /** Generated daemon wrapper for `events.count` (operator). */ eventsCount(paramsJson: string): Promise; /** Generated daemon wrapper for `events.query` (operator). */ eventsQuery(paramsJson: string): Promise; /** Generated daemon wrapper for `events.retention` (operator). */ eventsRetention(paramsJson: string): Promise; /** Generated daemon wrapper for `events.stats` (operator). */ eventsStats(paramsJson: string): Promise; /** Generated daemon wrapper for `events.truncate` (operator). */ eventsTruncate(paramsJson: string): Promise; /** Generated daemon wrapper for `evolution.plan` (operator). */ evolutionPlan(paramsJson: string): Promise; /** Generated daemon wrapper for `evolution.run` (agent). */ evolutionRun(paramsJson: string): Promise; /** Generated daemon wrapper for `feedback.compose_preview` (operator). */ feedbackComposePreview(paramsJson: string): Promise; /** Generated daemon wrapper for `feedback.list` (operator). */ feedbackList(paramsJson: string): Promise; /** Generated daemon wrapper for `feedback.status` (operator). */ feedbackStatus(paramsJson: string): Promise; /** Generated daemon wrapper for `feedback.submit` (operator). */ feedbackSubmit(paramsJson: string): Promise; /** Generated daemon wrapper for `goal.clear` (operator). */ goalClear(paramsJson: string): Promise; /** Generated daemon wrapper for `goal.set` (operator). */ goalSet(paramsJson: string): Promise; /** Generated daemon wrapper for `goal.status` (operator). */ goalStatus(paramsJson: string): Promise; /** Generated daemon wrapper for `goal.suggest` (operator). */ goalSuggest(paramsJson: string): Promise; /** Generated daemon wrapper for `host.subscribe` (operator). */ hostSubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `image.generate` (operator). */ imageGenerate(paramsJson: string): Promise; /** Generated daemon wrapper for `infer.cancel` (operator). */ inferCancel(paramsJson: string): Promise; /** Generated daemon wrapper for `infer.deadline` (operator). */ inferDeadline(paramsJson: string): Promise; /** Generated daemon wrapper for `infer_stream` (agent). */ inferStream(paramsJson: string): Promise; /** Generated daemon wrapper for `inference.register_runner` (operator). */ inferenceRegisterRunner(paramsJson: string): Promise; /** Generated daemon wrapper for `inference.runner.complete` (operator). */ inferenceRunnerComplete(paramsJson: string): Promise; /** Generated daemon wrapper for `inference.runner.event` (operator). */ inferenceRunnerEvent(paramsJson: string): Promise; /** Generated daemon wrapper for `inference.runner.fail` (operator). */ inferenceRunnerFail(paramsJson: string): Promise; /** Generated daemon wrapper for `meeting.get` (operator). */ meetingGet(paramsJson: string): Promise; /** Generated daemon wrapper for `meeting.list` (operator). */ meetingList(paramsJson: string): Promise; /** Generated daemon wrapper for `meeting.start` (operator). */ meetingStart(paramsJson: string): Promise; /** Generated daemon wrapper for `meeting.stop` (operator). */ meetingStop(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.add_fact` (agent). */ memoryAddFact(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.build_context` (operator). */ memoryBuildContext(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.build_context_fast` (operator). */ memoryBuildContextFast(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.consolidate` (agent). */ memoryConsolidate(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.fact_count` (operator). */ memoryFactCount(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.load` (operator). */ memoryLoad(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.persist` (operator). */ memoryPersist(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.query` (operator). */ memoryQuery(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.utility_get` (operator). */ memoryUtilityGet(paramsJson: string): Promise; /** Generated daemon wrapper for `memory.utility_set` (operator). */ memoryUtilitySet(paramsJson: string): Promise; /** Generated daemon wrapper for `message/send` (operator). */ messageSend(paramsJson: string): Promise; /** Generated daemon wrapper for `message/stream` (operator). */ messageStream(paramsJson: string): Promise; /** Generated daemon wrapper for `mobile.runtime` (operator). */ mobileRuntime(paramsJson: string): Promise; /** Generated daemon wrapper for `models.catalog_snapshot` (operator). */ modelsCatalogSnapshot(paramsJson: string): Promise; /** Generated daemon wrapper for `models.check_concierge` (operator). */ modelsCheckConcierge(paramsJson: string): Promise; /** Generated daemon wrapper for `models.check_upgrade_nudge` (operator). */ modelsCheckUpgradeNudge(paramsJson: string): Promise; /** Generated daemon wrapper for `models.detect_upgrades` (operator). */ modelsDetectUpgrades(paramsJson: string): Promise; /** Generated daemon wrapper for `models.dismiss_suggestion` (operator). */ modelsDismissSuggestion(paramsJson: string): Promise; /** Generated daemon wrapper for `models.dismiss_upgrade` (operator). */ modelsDismissUpgrade(paramsJson: string): Promise; /** Generated daemon wrapper for `models.list` (operator). */ modelsList(paramsJson: string): Promise; /** Generated daemon wrapper for `models.list_unified` (operator). */ modelsListUnified(paramsJson: string): Promise; /** Generated daemon wrapper for `models.preflight` (operator). */ modelsPreflight(paramsJson: string): Promise; /** Generated daemon wrapper for `models.recommend` (operator). */ modelsRecommend(paramsJson: string): Promise; /** Generated daemon wrapper for `models.register` (operator). */ modelsRegister(paramsJson: string): Promise; /** Generated daemon wrapper for `models.resource_policy.get` (operator). */ modelsResourcePolicyGet(paramsJson: string): Promise; /** Generated daemon wrapper for `models.route` (operator). */ modelsRoute(paramsJson: string): Promise; /** Generated daemon wrapper for `models.route_provenance` (operator). */ modelsRouteProvenance(paramsJson: string): Promise; /** Generated daemon wrapper for `models.search` (operator). */ modelsSearch(paramsJson: string): Promise; /** Generated daemon wrapper for `models.setup_plan` (operator). */ modelsSetupPlan(paramsJson: string): Promise; /** Generated daemon wrapper for `models.stats` (operator). */ modelsStats(paramsJson: string): Promise; /** Generated daemon wrapper for `models.unregister` (operator). */ modelsUnregister(paramsJson: string): Promise; /** Generated daemon wrapper for `models.update_prefs_get` (operator). */ modelsUpdatePrefsGet(paramsJson: string): Promise; /** Generated daemon wrapper for `models.update_prefs_set` (operator). */ modelsUpdatePrefsSet(paramsJson: string): Promise; /** Generated daemon wrapper for `models.upgrades` (operator). */ modelsUpgrades(paramsJson: string): Promise; /** Generated daemon wrapper for `multi.map_reduce` (operator). */ multiMapReduce(paramsJson: string): Promise; /** Generated daemon wrapper for `multi.pipeline` (operator). */ multiPipeline(paramsJson: string): Promise; /** Generated daemon wrapper for `multi.subtask` (operator). */ multiSubtask(paramsJson: string): Promise; /** Generated daemon wrapper for `multi.supervisor` (operator). */ multiSupervisor(paramsJson: string): Promise; /** Generated daemon wrapper for `multi.swarm` (operator). */ multiSwarm(paramsJson: string): Promise; /** Generated daemon wrapper for `multi.tournament` (operator). */ multiTournament(paramsJson: string): Promise; /** Generated daemon wrapper for `multi.vote` (operator). */ multiVote(paramsJson: string): Promise; /** Generated daemon wrapper for `nlp.extract_entities` (operator). */ nlpExtractEntities(paramsJson: string): Promise; /** Generated daemon wrapper for `nlp.identify_language` (operator). */ nlpIdentifyLanguage(paramsJson: string): Promise; /** Generated daemon wrapper for `nlp.tokenize` (operator). */ nlpTokenize(paramsJson: string): Promise; /** Generated daemon wrapper for `notifications.local` (operator). */ notificationsLocal(paramsJson: string): Promise; /** Generated daemon wrapper for `outcomes.resolve_pending` (operator). */ outcomesResolvePending(paramsJson: string): Promise; /** Generated daemon wrapper for `outcomes.scoreboard` (operator). */ outcomesScoreboard(paramsJson: string): Promise; /** Generated daemon wrapper for `parslee.auth` (operator). */ parsleeAuth(paramsJson: string): Promise; /** Generated daemon wrapper for `permission.classify` (operator). */ permissionClassify(paramsJson: string): Promise; /** Generated daemon wrapper for `permission.evaluate` (agent). */ permissionEvaluate(paramsJson: string): Promise; /** Generated daemon wrapper for `permission.pending` (agent). */ permissionPending(paramsJson: string): Promise; /** Generated daemon wrapper for `permissions.domains` (operator). */ permissionsDomains(paramsJson: string): Promise; /** Generated daemon wrapper for `permissions.explain` (operator). */ permissionsExplain(paramsJson: string): Promise; /** Generated daemon wrapper for `permissions.request` (operator). */ permissionsRequest(paramsJson: string): Promise; /** Generated daemon wrapper for `permissions.status` (operator). */ permissionsStatus(paramsJson: string): Promise; /** Generated daemon wrapper for `policy.list` (operator). */ policyList(paramsJson: string): Promise; /** Generated daemon wrapper for `policy.register` (operator). */ policyRegister(paramsJson: string): Promise; /** Generated daemon wrapper for `policy.unregister` (operator). */ policyUnregister(paramsJson: string): Promise; /** Generated daemon wrapper for `proposal.submit` (owner). */ proposalSubmit(paramsJson: string): Promise; /** Generated daemon wrapper for `registry.heartbeat` (operator). */ registryHeartbeat(paramsJson: string): Promise; /** Generated daemon wrapper for `registry.list` (operator). */ registryList(paramsJson: string): Promise; /** Generated daemon wrapper for `registry.reap` (operator). */ registryReap(paramsJson: string): Promise; /** Generated daemon wrapper for `registry.register` (operator). */ registryRegister(paramsJson: string): Promise; /** Generated daemon wrapper for `registry.unregister` (operator). */ registryUnregister(paramsJson: string): Promise; /** Generated daemon wrapper for `replan.set_config` (operator). */ replanSetConfig(paramsJson: string): Promise; /** Generated daemon wrapper for `runs.cancel` (owner). */ runsCancel(paramsJson: string): Promise; /** Generated daemon wrapper for `runs.get_trace` (owner). */ runsGetTrace(paramsJson: string): Promise; /** Generated daemon wrapper for `runs.list` (owner). */ runsList(paramsJson: string): Promise; /** Generated daemon wrapper for `runs.record_turns` (agent). */ runsRecordTurns(paramsJson: string): Promise; /** Generated daemon wrapper for `runs.resume` (agent). */ runsResume(paramsJson: string): Promise; /** Generated daemon wrapper for `runs.subscribe` (owner). */ runsSubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `runs.unsubscribe` (operator). */ runsUnsubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `scheduler.create` (operator). */ schedulerCreate(paramsJson: string): Promise; /** Generated daemon wrapper for `scheduler.os_install` (operator). */ schedulerOsInstall(paramsJson: string): Promise; /** Generated daemon wrapper for `scheduler.os_list` (operator). */ schedulerOsList(paramsJson: string): Promise; /** Generated daemon wrapper for `scheduler.os_reconcile` (operator). */ schedulerOsReconcile(paramsJson: string): Promise; /** Generated daemon wrapper for `scheduler.os_render` (operator). */ schedulerOsRender(paramsJson: string): Promise; /** Generated daemon wrapper for `scheduler.os_uninstall` (operator). */ schedulerOsUninstall(paramsJson: string): Promise; /** Generated daemon wrapper for `scheduler.run` (operator). */ schedulerRun(paramsJson: string): Promise; /** Generated daemon wrapper for `scheduler.run_loop` (operator). */ schedulerRunLoop(paramsJson: string): Promise; /** Generated daemon wrapper for `session.auth` (agent). */ sessionAuth(paramsJson: string): Promise; /** Generated daemon wrapper for `session.bindSandbox` (agent). */ sessionBindSandbox(paramsJson: string): Promise; /** Generated daemon wrapper for `session.bindSubstrate` (operator). */ sessionBindSubstrate(paramsJson: string): Promise; /** Generated daemon wrapper for `session.init` (operator). */ sessionInit(paramsJson: string): Promise; /** Generated daemon wrapper for `session.policy.close` (operator). */ sessionPolicyClose(paramsJson: string): Promise; /** Generated daemon wrapper for `session.policy.open` (operator). */ sessionPolicyOpen(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.adopt_pack` (operator). */ skillAdoptPack(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.enforce_deployment` (operator). */ skillEnforceDeployment(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.export` (operator). */ skillExport(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.find` (operator). */ skillFind(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.gate_deployment` (operator). */ skillGateDeployment(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.import` (operator). */ skillImport(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.ingest` (operator). */ skillIngest(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.ingest_governed` (operator). */ skillIngestGoverned(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.repair` (operator). */ skillRepair(paramsJson: string): Promise; /** Generated daemon wrapper for `skill.report` (operator). */ skillReport(paramsJson: string): Promise; /** Generated daemon wrapper for `skills.distill` (operator). */ skillsDistill(paramsJson: string): Promise; /** Generated daemon wrapper for `skills.domains_needing_evolution` (operator). */ skillsDomainsNeedingEvolution(paramsJson: string): Promise; /** Generated daemon wrapper for `skills.evolve` (operator). */ skillsEvolve(paramsJson: string): Promise; /** Generated daemon wrapper for `skills.gate` (operator). */ skillsGate(paramsJson: string): Promise; /** Generated daemon wrapper for `skills.ingest_distilled` (operator). */ skillsIngestDistilled(paramsJson: string): Promise; /** Generated daemon wrapper for `skills.ingest_provisional` (operator). */ skillsIngestProvisional(paramsJson: string): Promise; /** Generated daemon wrapper for `skills.list` (operator). */ skillsList(paramsJson: string): Promise; /** Generated daemon wrapper for `speech.prepare` (operator). */ speechPrepare(paramsJson: string): Promise; /** Generated daemon wrapper for `sync.knowledge` (operator). */ syncKnowledge(paramsJson: string): Promise; /** Generated daemon wrapper for `tasks.list` (operator). */ tasksList(paramsJson: string): Promise; /** Generated daemon wrapper for `tasks/cancel` (operator). */ tasksCancel(paramsJson: string): Promise; /** Generated daemon wrapper for `tasks/get` (operator). */ tasksGet(paramsJson: string): Promise; /** Generated daemon wrapper for `tasks/list` (operator). */ tasksSlashList(paramsJson: string): Promise; /** Generated daemon wrapper for `tasks/pushNotificationConfig/delete` (operator). */ tasksPushNotificationConfigDelete(paramsJson: string): Promise; /** Generated daemon wrapper for `tasks/pushNotificationConfig/get` (operator). */ tasksPushNotificationConfigGet(paramsJson: string): Promise; /** Generated daemon wrapper for `tasks/pushNotificationConfig/list` (operator). */ tasksPushNotificationConfigList(paramsJson: string): Promise; /** Generated daemon wrapper for `tasks/pushNotificationConfig/set` (operator). */ tasksPushNotificationConfigSet(paramsJson: string): Promise; /** Generated daemon wrapper for `tasks/resubscribe` (operator). */ tasksResubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `tools.cancel` (operator). */ toolsCancel(paramsJson: string): Promise; /** Generated daemon wrapper for `tools.list` (operator). */ toolsList(paramsJson: string): Promise; /** Generated daemon wrapper for `tools.poll` (operator). */ toolsPoll(paramsJson: string): Promise; /** Generated daemon wrapper for `tools.register` (operator). */ toolsRegister(paramsJson: string): Promise; /** Generated daemon wrapper for `tools.stream.subscribe` (operator). */ toolsStreamSubscribe(paramsJson: string): Promise; /** Generated daemon wrapper for `tools.unregister` (operator). */ toolsUnregister(paramsJson: string): Promise; /** Generated daemon wrapper for `verify` (operator). */ verify(paramsJson: string): Promise; /** Generated daemon wrapper for `verify.monte_carlo` (operator). */ verifyMonteCarlo(paramsJson: string): Promise; /** Generated daemon wrapper for `video.generate` (operator). */ videoGenerate(paramsJson: string): Promise; /** Generated daemon wrapper for `vision.ocr` (operator). */ visionOcr(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.cancel_turn` (operator). */ voiceCancelTurn(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.dispatch_turn` (operator). */ voiceDispatchTurn(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.enroll_speaker` (operator). */ voiceEnrollSpeaker(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.list_enrollments` (operator). */ voiceListEnrollments(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.prepare_diarizer` (operator). */ voicePrepareDiarizer(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.prepare_parakeet` (operator). */ voicePrepareParakeet(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.prewarm_turn` (operator). */ voicePrewarmTurn(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.providers.list` (operator). */ voiceProvidersList(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.remove_enrollment` (operator). */ voiceRemoveEnrollment(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.sessions.list` (operator). */ voiceSessionsList(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.transcribe_stream.push` (operator). */ voiceTranscribeStreamPush(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.transcribe_stream.start` (operator). */ voiceTranscribeStreamStart(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.transcribe_stream.stop` (operator). */ voiceTranscribeStreamStop(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.tts_stream.cancel` (operator). */ voiceTtsStreamCancel(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.tts_stream.list` (operator). */ voiceTtsStreamList(paramsJson: string): Promise; /** Generated daemon wrapper for `voice.tts_stream.start` (operator). */ voiceTtsStreamStart(paramsJson: string): Promise; /** Generated daemon wrapper for `workflow.build_automation` (operator). */ workflowBuildAutomation(paramsJson: string): Promise; /** Generated daemon wrapper for `workflow.chain` (operator). */ workflowChain(paramsJson: string): Promise; /** Generated daemon wrapper for `workflow.list_paused` (operator). */ workflowListPaused(paramsJson: string): Promise; /** Generated daemon wrapper for `workflow.resume` (operator). */ workflowResume(paramsJson: string): Promise; /** Generated daemon wrapper for `workflow.run` (operator). */ workflowRun(paramsJson: string): Promise; /** Generated daemon wrapper for `workflow.verify` (operator). */ workflowVerify(paramsJson: string): Promise; // END GENERATED daemon wrappers: CarRuntime // --- Memory persistence --- /** * Load memory graph from a JSON file. Returns the number of facts loaded. * * Daemon-side read: `path` is sandboxed under `~/.car/memory/` (the * 2026-05 audit boundary). Relative paths land under the base; * absolute paths must already be under the base; `..` segments and * symlinks pointing out of the sandbox are rejected. * * **`path` names a file, not a namespace.** This REPLACES the graph the * connection is bound to — and by default that is the daemon's SHARED graph, * common to every unbound session and to facts ingested over MCP. So on a * multi-project host this both discards other projects' in-memory facts and * leaves the loaded ones visible to them. Set `CAR_MEMORY_NAMESPACE` in the host process to bind a private graph * (car-releases#79/#80); the shared daemon transport puts it on the * `session.auth` handshake for you. */ loadMemory(path: string): Promise; /** * Stream one delta of a chat turn back to the daemon as an * `agent.chat.event` notification (the agent-chat surface). Called from an * `agent.chat` handler (see `registerChatHandler`) to emit the reply * incrementally; the daemon rewrites each event to `agents.chat.event` for * the host that issued `agents.chat`, keyed by `sessionId`. * * `kind` is one of `token` | `tool_call` | `done` | `error`. `delta` carries * the text for `token` (and the final text/status for `done`/`error`); omit * it for a bare signal. */ chatEvent(sessionId: string, kind: string, delta?: string | undefined | null): Promise; /** * Persist memory graph to a JSON file (backward-compatible flat format). * Returns the number of records written. * * Daemon-side write: same `~/.car/memory/` sandbox as `loadMemory`. * * **Writes the whole graph, not a subset.** `path` chooses the destination * file; it does not select the contents. On an unbound session that graph is * the daemon-wide shared one, so per-project files each end up holding every * project's facts. Set `CAR_MEMORY_NAMESPACE` for a file that contains only one project's * facts (car-releases#79/#80). */ persistMemory(path: string): Promise; // --- Foreman --- /** * Decompose a coding `goal` into a footprint-annotated, scheduled subtask * plan. `repo` defaults to the daemon's cwd. Returns a JSON * `ForemanPlanReport` (`schema_version`, `valid`, `prefer_single_session`, * `levels`, `subtasks[]` with declared `writes`/`reads`). */ foremanPlan(goal: string, repo?: string, maxAttempts?: number): Promise; /** * Plan a coding `goal`, then farm the subtasks to an external coding CLI * (`adapter`, default `"claude-code"`) in isolated git worktrees, gating each * worktree and the integrated union. `verifyCommand` is the per-worktree * **regression** check; `unionVerifyCommand` is the integrated-union **goal** * check (falls back to `verifyCommand` when omitted). **Spends real agent * quota.** Returns JSON `{ plan, ran, run? }`. */ foremanRun( goal: string, repo?: string, adapter?: string, verifyCommand?: Array, unionVerifyCommand?: Array, maxAttempts?: number, distributed?: boolean, workers?: Array ): Promise; // --- Fleet --- /** * This instance's agents, capabilities, and models — one `InstanceInventory` * JSON object. The same report peers receive over A2A, plus this session's * own registered tools and learned skills. */ fleetInventory(): Promise; /** * Every agent, capability, and model across this daemon and every reachable * CAR instance, folded so one row names every instance that offers it. * `includeRemote` defaults to true. `timeoutMs` bounds each peer * individually: a sleeping machine appears as an unreachable row carrying the * reason, never a missing one. Returns `FleetComposite` JSON. */ fleetComposite(includeRemote?: boolean, timeoutMs?: number): Promise; /** Whether this instance takes farmed-out coding work. `{ config, profile }` JSON. */ fleetWorkerGet(): Promise; /** * Enroll (or withdraw) this instance as a fleet worker. **Operator-only, and * a real grant**: enrolling lets a trusted peer run a coding CLI against the * checkouts named in `repos`. Only the fields supplied change. * * The limits belong to this machine, not the caller: `dispatchesPerHour` * budgets one peer's spend (concurrency is not a spend bound), * `maxSubtaskSecs` caps the timeout a sender asks for, and `allowedTools` is * intersected with whatever the dispatch requests. `fetchMissingBase` makes * this machine a **runner**: rather than decline a base commit it lacks, it * fetches from `fetchRemote` (its own, default `origin`). */ fleetWorkerSet( acceptsWork?: boolean, repos?: Array, maxParallel?: number, localParallel?: number, dispatchesPerHour?: number, maxSubtaskSecs?: number, allowedTools?: Array, fetchMissingBase?: boolean, fetchRemote?: string ): Promise; // --- Tools & policies --- /** Register a tool by name. */ registerTool(name: string): Promise; /** * The tools currently registered on this runtime, as a JSON array of full * `ToolSchema` objects sorted by name. Every schema includes its runtime- * assigned `source` (`builtin|user_defined|subprocess|mcp`). * * Counterpart to `registerTool` / `registerToolSchema`, which had none: a * caller could add tools but never ask what was actually in effect, so a * governed or read-only deployment could not prove "only these tools are * callable". Sorted, so two calls with no registration in between are * byte-identical and can be diffed. */ listTools(): Promise; /** * Remove a tool by name. Resolves to how many were removed — `0` means * nothing matched, which is not an error, so cleanup can call this * unconditionally. * * Drops the tool from both the runtime's registry and its schema map, so * the model stops seeing it and the validator stops accepting it. */ unregisterTool(name: string): Promise; /** Register CAR's built-in agent utility tools. */ registerAgentBasics(): Promise; /** * Start an agent run on the daemon (agent run tracing). Brackets the * beginning of a run: the daemon mints a durable `run_id`, resolves * the owning `agent_id`, tags it as the session's current run before * replying, and records that the run started. Await this before * submitting any proposal so the per-turn recorder reads the right * `run_id`. * * `paramsJson` is a serialized request object: * `{ intent, agent_id?, agent_name?, outcome_description?, idempotency_key? }`. * When `agent_id` is omitted the daemon resolves it from the session's * `agent_id` binding, then `CAR_AGENT_ID`, then a deterministic id * synthesized from `agent_name`. An `idempotency_key`, when supplied, * becomes the `run_id` and makes the start dedup: if a run with that id * already exists the existing run is returned instead of a duplicate. * Returns `{ run_id, agent_id }` as a JSON string. */ runsStart(paramsJson: string): Promise; /** * Complete an agent run on the daemon (agent run tracing). Records * the terminal `AgentOutcome` for `run_id` and acks. Await this ack * before letting the connection close so a healthy run is never * mislabeled `Incomplete`. * * `paramsJson` is a serialized request object: `{ run_id, outcome }`. * Returns `{ run_id, ok }` as a JSON string. */ runsComplete(paramsJson: string): Promise; /** * Open a policy-scoping session and return its opaque id. Hosts * that drive multiple concurrent agent contexts through one * CarRuntime (IDE per-project rules, multi-tenant servers) call * this once per context, then pass the id to subsequent * `registerPolicy` and `executeProposal` calls so per-context rules * stack on top of any global ones. Embedded only. * See `docs/proposals/per-session-policy-scoping.md`. */ openSession(): Promise; /** * Close a session and drop every policy scoped to it. Returns true * if a session by that id existed, false if it didn't (already * closed, never opened). */ closeSession(sessionId: string): Promise; /** * Register a policy enforced in Rust on every action. * `rule` is one of: "deny_tool", "deny_tool_param", "require_state", * "deny_tool_callback". * `sessionId`, when set, scopes the policy to the named session * (opened via `openSession`). Without it, the policy is global. */ registerPolicy( name: string, rule: string, target?: string | null, key?: string | null, pattern?: string | null, valueJson?: string | null, sessionId?: string | null, ): Promise; /** * Remove a global policy by name. Resolves to how many were removed — * `0` means nothing matched, which is not an error, so cleanup can call * this unconditionally. * * Counterpart to `registerPolicy`, which had none: a policy registered * over the wire could only be cleared by restarting the daemon * (Parslee-ai/car#623). Session-scoped policies stay WS-only, mirroring * `registerPolicy`'s own `sessionId` restriction — close the session to * drop them. */ unregisterPolicy(name: string): Promise; /** * Global policies in force, as a JSON array of `{ name, description }`. * Without this a caller could register a policy but never ask what was * enforced, so an action rejection could not be explained beyond its own * message. */ listPolicies(): Promise; /** * Set replan configuration on this runtime. * `maxReplans` = 0 disables replanning (default). * `replanOnRejected` (default false): when true, validator/policy/capability * rejections (not just runtime failures) also trigger rollback + replan. */ setReplanConfig( maxReplans: number, delayMs?: number | null, replanOnRejected?: boolean | null, ): Promise; // --- State --- /** Set a state key (value must be a JSON string). `tenant` (optional) * scopes the write to one tenant's keyspace (E3). */ stateSet(key: string, valueJson: string, tenant?: string): void; /** Get a state key. Returns the value as a JSON string, or `"null"`. * `tenant` (optional) scopes the read to one tenant's keyspace (E3). */ stateGet(key: string, tenant?: string): string; /** `tenant` (optional) scopes the check to one tenant's keyspace (E3). */ stateExists(key: string, tenant?: string): boolean; /** Snapshot of all state as a JSON string. `tenant` (optional) scopes * the snapshot to one tenant's keyspace (E3). */ stateSnapshot(tenant?: string): string; /** `tenant` (optional) scopes the key list to one tenant's keyspace (E3). */ stateKeys(tenant?: string): string[]; // --- Memory / Facts (graph-backed) --- /** * Add a fact. `kind` is typically "pattern" or "constraint". Optional * `factId`, ordered `tags`, and `source` are preserved by the daemon. * * In Daemon mode, rejects with the daemon-unreachable error * instead of silently returning 0 (#146). */ addFact( subject: string, body: string, kind: string, confidence?: number | null, factId?: string | null, tags?: string[] | null, source?: string | null, ): Promise; /** * Query facts via graph spreading activation. Returns a JSON array whose * rows include `fact_id` (null for graph nodes without one), `subject`, * `body`, `kind`, `confidence`, `tags`, and `source`. */ queryFacts(query: string, k?: number | null): string; /** * Total valid fact count. * * In Daemon mode, hits the daemon's per-session memgine — the * embedded fallback memgine stays empty by design and would * silently return 0 (#146). Rejects with the daemon-unreachable * error instead. */ factCount(): Promise; /** * Build the full 4-layer context for a query. * When `modelContextWindow` is provided, dynamically sizes the budget. * * In Daemon mode, rejects with the daemon-unreachable error * instead of silently returning "" (#146). */ buildContext(query: string, modelContextWindow?: number | null): Promise; /** * Build context in Fast mode for latency-sensitive paths. * Skips embedding flush, skill lookup, PPR-based scoring, known unknowns. */ buildContextFast(query: string, modelContextWindow?: number | null): string; // --- Proactive memory --- /** * Update proactive memory's private progress/risk status. * `paramsJson` is `{ body, tenant_id? }`; returns `ProactiveStatus` JSON. */ memoryUpdateStatus(paramsJson: string): Promise; /** * Run proactive memory Phase 1 maintenance over recent daemon telemetry. * `paramsJson` is `{ max_recent?, tenant_id? }`; returns report JSON. */ memoryMaintain(paramsJson: string): Promise; /** * Save durable proactive knowledge. * `paramsJson` is `ProactiveMemorySave`; returns saved-entry JSON. */ memorySaveKnowledge(paramsJson: string): Promise; /** * Save durable proactive procedural evidence. * `paramsJson` is `ProactiveMemorySave`; returns saved-entry JSON. */ memorySaveProcedural(paramsJson: string): Promise; /** * Delete a proactive memory entry by id. * `paramsJson` is `{ id }`; returns delete report JSON. */ memoryDelete(paramsJson: string): Promise; /** * Select a targeted proactive memory reminder. * `paramsJson` is `ProactiveMemoryRequest`; returns inject/silent JSON. */ memoryIntervene(paramsJson: string): Promise; /** * Evaluate proactive memory against labeled cases and ablation baselines. * `paramsJson` is `ProactiveEvaluationRequest`; returns report JSON. */ memoryEvaluate(paramsJson: string): Promise; /** Run memory consolidation ("dream") pass. Returns a JSON report. */ consolidate(): string; /** * Get the live engine's utility-aware retrieval blend (U-Mem). * Returns JSON `{ utility_weight, utility_exploration }`. */ utilityRetrieval(): string; /** * Set the live engine's utility-aware retrieval blend (U-Mem). * `utilityWeight` 0 = pure relevance (ordering unchanged); * `utilityExploration` scales the UCB uncertainty term (only consulted * when weight > 0). Omitting `utilityExploration` keeps the engine's * current value (read-modify-write), it does NOT reset it to 0. Takes * effect on the next context build. Returns the applied JSON * `{ utility_weight, utility_exploration }`. */ setUtilityRetrieval(utilityWeight: number, utilityExploration?: number | null): Promise; /** * Run the U-Mem cost-aware knowledge cascade (Slice 5 live evolve loop) on * the daemon. `requestJson` is `{ current_confidence, policy, observed, * claim? }`; the daemon runs each tier's mechanic (self_reflect → reflect(), * human_expert → ApprovalLedger HITL) + the budget/target walk, escalating * cheapest-first on the caller-supplied observed confidence. Returns JSON * `{ run, pending_approval? }`. */ cascadeRun(requestJson: string): Promise; /** * Plan an evolution cycle over the daemon's **live** engine signals — the * self-evolution governor's host surface (arXiv 2507.21046). `requestJson` is * `{ policy?: { pressure_threshold?, budget? } }`; the daemon folds the session * memgine's real per-component pressure/evidence and runs the governor. Returns * the `EvolutionPlan` JSON `{ decisions, spent, evolve_now }` — the live * counterpart to the stateless `planEvolution` helper. Plans only; the caller * dispatches the chosen components. */ planEvolutionLive(requestJson: string): Promise; /** * `memory.set_admission_table` — install or clear the durable-state * admission rules: `{ table?: OwnershipTable | null }` → * `{ enabled, ungated_surfaces }`. * * A null or absent `table` turns the gate OFF, which is the default. Off is * not the same as an empty table: an empty table is fail-closed and refuses * every externally-authored fact. */ memorySetAdmissionTable(requestJson: string): Promise; /** * `memory.admission_table` — read back the installed admission rules: `{}` → * `{ enabled, table, ungated_surfaces }`. * * `ungated_surfaces` names surfaces whose rule imposes no real constraint — * worth checking after installing a table that only looks governed. */ memoryAdmissionTable(requestJson: string): Promise; /** * `supervision.subscribe` — register this connection as a supervisor of the * admission gate: `{ filter?: { tools?, sessions?, min_reversibility? } }`. * * Intents arrive as `supervision.intent` NOTIFICATIONS on the same socket. * A caller that cannot read notifications should poll `supervisionPending` * instead — subscribing without consuming them blocks every supervised * proposal until it fails closed. */ supervisionSubscribe(requestJson: string): Promise; /** * `supervision.unsubscribe` — stop supervising: `{}`. Intents already parked * run out their timeout and fail closed rather than being released, so a * supervisor cannot turn a pending deny into an allow by disconnecting. */ supervisionUnsubscribe(requestJson: string): Promise; /** `supervision.pending` — every intent currently parked on a verdict: `{}`. */ supervisionPending(requestJson: string): Promise; /** `supervision.decide` — `{ intent_id, decision: { kind: "allow" | "deny" | "escalate", reason? } }`. */ supervisionDecide(requestJson: string): Promise; /** `sync.status` — roster, journal frontier, stable frontier, state hash (B6). */ syncStatus(requestJson: string): Promise; /** `sync.append` — record an op on any surface: `{ surface, payload, scope? }` (B6). */ syncAppend(requestJson: string): Promise; /** `host.agents` — current host agent registry snapshot. */ hostAgents(): Promise; /** `host.events` — recent host events, newest last; omit `limit` for the daemon default. */ hostEvents(limit?: number): Promise; /** `host.approvals` — pending host approvals. */ hostApprovals(): Promise; /** `host.register_agent` — register an agent on this connection. */ hostRegisterAgent(requestJson: string): Promise; /** `host.unregister_agent` — unregister an agent owned by this connection. */ hostUnregisterAgent(requestJson: string): Promise; /** `host.set_status` — publish status for an agent owned by this connection. */ hostSetStatus(requestJson: string): Promise; /** `host.register_device` — register a device on this connection. */ hostRegisterDevice(requestJson: string): Promise; /** `host.update_device` — update a device owned by this connection. */ hostUpdateDevice(requestJson: string): Promise; /** `host.devices` — current host device registry snapshot. */ hostDevices(): Promise; /** `host.notify` — emit a user-facing host notification. */ hostNotify(requestJson: string): Promise; /** `host.request_approval` — request approval for a gated action. */ hostRequestApproval(requestJson: string): Promise; /** `host.resolve_approval` — resolve one pending host approval. */ hostResolveApproval(requestJson: string): Promise; // `host.subscribe` event delivery is deferred to the callback-aware // daemon-session API; subscribing without a consumer would drop the stream. /** * `agents.peers` — visible peers as JSON. Each row distinguishes the * kind-level `can_receive` capability from the current `reachable` delivery * preflight; the send remains authoritative. */ agentsPeers(requestJson: string): Promise; /** `agents.message` — send text to one peer: `{ to, body, summary? }`. The sender is derived server-side. */ agentsMessage(requestJson: string): Promise; /** `agents.message.pending` — peer messages awaiting an operator decision. Host-only. */ agentsMessagePending(requestJson: string): Promise; /** `agents.message.approve` — release or drop one held message: `{ id, decision }`. Host-only. */ agentsMessageApprove(requestJson: string): Promise; /** Store/load exact supervised-assistant checkpoints in the durable oplog. */ syncAssistantCheckpointPut(requestJson: string): Promise; syncAssistantCheckpointGet(requestJson: string): Promise; /** Append/load monotone supervised-action lifecycle records. */ syncAssistantActionPut(requestJson: string): Promise; syncAssistantActionGet(requestJson: string): Promise; /** `sync.record_turn` — route a conversation turn through the oplog so `syncResume` is real (B6). */ syncRecordTurn(requestJson: string): Promise; /** `sync.record_intent` — write the leased-execution intent ledger; feeds the fence oracle (B6). */ syncRecordIntent(requestJson: string): Promise; /** `sync.pump` — one push/pull/ack reconciliation round against the relay (B6). */ syncPump(requestJson: string): Promise; /** `sync.checkpoint` — publish a device-side checkpoint at the stable frontier (B6). */ syncCheckpoint(requestJson: string): Promise; /** `sync.rebase` — cold bootstrap / straggler re-entry onto the latest checkpoint (B6). */ syncRebase(requestJson: string): Promise; /** `sync.transcript` — the ordered role-threaded `Turn[]` projection (B6). */ syncTranscript(requestJson: string): Promise; /** `sync.resume` — the repaired, provider-valid `Message[]` for replay (B6). */ syncResume(requestJson: string): Promise; /** `sync.fence_check` — the dispatch fence at the point of effect; only `may_dispatch` authorizes (B6). */ syncFenceCheck(requestJson: string): Promise; /** `lease.acquire` — CAS-acquire the per-agent execution lease; epoch bumps on grant (B6). */ leaseAcquire(requestJson: string): Promise; /** `lease.renew` — heartbeat the lease (no epoch bump), iff still the holder (B6). */ leaseRenew(requestJson: string): Promise; /** `lease.release` — clean handoff (next acquire skips the TTL wait) (B6). */ leaseRelease(requestJson: string): Promise; /** `lease.status` — the linearizable read of the current lease, or `null` (B6). */ leaseStatus(requestJson: string): Promise; /** * Run one evolution cycle over the daemon's **live** signals — the * self-evolution governor's real executor (arXiv 2507.21046). `requestJson` * is `{ policy?, dry_run?, harness_baseline_metrics?, * harness_candidate_metrics?, harness_measure?, context_measure? }`; the daemon plans over all five live * components (Memory/Skills/Context from the engine, Harness from the event * log, Tools from connector health) and dispatches each `EvolveNow` * component: Memory → consolidate (sized by decide_maintenance), Skills → * evolve_skills over event-log failure traces, Harness → the HITL-gated * harness_evolution loop (pending approvals resolve via * `permission.approve`/`reject` by fingerprint), Context → the * `context_evolution` loop, which resolves each mutation either through the * opt-in pre-activation grader (`context_measure`) or, for whatever that did * not decide, the diagnose→approve→apply→measure→revert human path. Returns * the cycle record JSON * `{ plan, steps, evolved, out_of_scope, pending_approvals?, measurement? }`, * where each step is `{ component, ran, applied, out_of_scope, outcome }`. * * **Context.** Diagnoses off the engine's own live conversation-layer * saturation and lowers `MemgineConfig.conversation_keep_recent` (halved, * floored at 2) so compaction summarizes more of the older turns. Every * mutation is HITL-gated on the same shared durable `ApprovalLedger` as * harness ones, under its own fingerprint namespace * `context::`, resolved by the same * `permission.approve`/`reject`. There **is** a pre-activation regression * gate, opt-in via `context_measure` (see below) — this doc comment used to * say there was none, because the bench replayed a runtime with no memgine * attached and never offered a `recall` tool; bench tasks may now declare a * `memory:` fixture and are then replayed with a real memgine and the shipped * `recall` tool, so the assembled context moves with the knob. A graded * mutation promotes (`applied` with `governance: "promoted"`) or is rejected * (`rejected_by_gate`) with no operator in the loop. On the human-approved * path — and whenever no grade ran — the daemon measures the MARGIN after the * apply: compact under the unchanged value for a baseline * (`conversation_tokens_baseline`), apply, compact again, and revert unless * the tokens fell below that baseline (`rolled_back`, not counted as * applied; `rollback_failed` with `rollback_error` if even the revert did * not take). Comparing against the baseline rather than the uncompacted * layer is what stops the change being credited with savings compaction * would have produced anyway. So context is **not** unattended out of the * box; it becomes unattended for a given change only once that fingerprint * has been approved — and since the ledger is daemon-wide and the * fingerprint names the change, that approval covers the same change on * every engine this daemon evolves. On the unattended cadence a falsified * mutation then backs off exponentially per fingerprint (`in_backoff`) * instead of being re-applied and re-reverted every tick. The step's * `outcome` is a JSON string `{ mechanism: "context_evolution", mutations, * applied, pending, details }`, each detail carrying `mutation`, * `component`, `fingerprint`, `rationale` and one of `pending_approval` | * `applied` | `rolled_back` | `rollback_failed` | `apply_failed` | * `would_apply` | `in_backoff` | `rejected_by_operator` | * `approved_no_patch` | `rejected_by_gate` | `measurement_failed` | * `config_moved_during_measurement` (a graded promotion whose measured base * was moved by something else while the replays ran — nothing applied, both * values reported, no backoff). When `context_measure` was requested the * summary also carries `context_measured: { status: "measured" | * "skipped_dry_run", grade_attempts, model, split, split_seed }`. * * **Tools** is recorded as `out_of_scope` — a decision, not a failure. * Connector remediation means re-running a connector's OAuth or credential * exchange, an access change this loop holds no authority to perform; * reconnect/re-auth stay operator actions via `connectors.*`. Such a step is * `ran: true, applied: false, out_of_scope: true` with the reason in * `outcome`, and the component appears in the top-level `out_of_scope` * array (always present, empty when none). `ran: false` therefore means one * thing only: the mechanism was invoked and errored. * * `harness_measure` `{ model, split?, held_in_fraction?, split_seed?, * max_turns?, tasks_dir? }` opts into **in-daemon measurement**: the daemon * replays the held-out split itself (once for the baseline under the live * `HarnessConfig`, once per measurable mutation under that config plus the * mutation's patch) and feeds the regression gate, so a cycle can promote or * reject unattended. It is mutually exclusive with the two supplied-metrics * params (sending both errors, naming both); `dry_run` measures nothing and * reports `measurement.status = "skipped_dry_run"`; a build with no * in-process evaluator installed errors rather than degrading to HITL; * safety-affecting and patchless mutations are never measured; a failed * replay reports `measurement_failed` and fabricates no metrics. * * `context_measure` takes the SAME request shape and opts into the **Context * pillar's** pre-activation grader: two replays over the same split, one * under the engine's live `MemgineConfig` and one under it plus the * mutation's patch, graded on TASK outcomes by the same gate. The two params * are not mutually exclusive with each other (different pillars, two * independent measurements). `dry_run` performs no replay; a build with no * evaluator installed errors; a patchless mutation is never measured; the * unattended cadence never requests a grade at all, so an idle timer cannot * start spending benchmark replays. * `measurement` is TOP-LEVEL on the response (not only inside the harness * step) and present whenever `harness_measure` was requested, in every * shape it can end in — `measured` / `skipped_dry_run` / * `measurement_failed` with the error. A replay is a paid side effect and * the plan may legitimately never dispatch Harness, so a side effect * reported only from that step is one a caller can be billed for and never * see. */ runEvolutionCycleLive(requestJson: string): Promise; // --- Skills --- /** * Gate a skill's deployment capability against its provenance on the daemon, * folding the named skill's **live** track record into the decision * (arXiv 2602.12430 "Agent Skills"). `requestJson` is `{ skill_name, * provenance, requested_tier }` where `requested_tier` is * `"read_only" | "sandbox_edit" | "full_access"`. The daemon overrides the * provenance's lifecycle counts with the skill's real success/fail record, so * a skill failing in the field is denied despite an official signature. * Returns the `SkillDeploymentDecision` JSON. Live counterpart to the * stateless `gateSkillDeployment` helper. */ gateSkillDeploymentLive(requestJson: string): Promise; /** * Enforce a skill's deployment at load time against the session's durable * approval ledger (arXiv 2602.12430 "Agent Skills" Slice 4 — the HITL bridge). * `requestJson` is `{ skill_name, provenance, requested_tier }`; the daemon * gates the skill (folding its live track record), then resolves the verdict * against standing operator decisions: `Allow`/`Downgrade` deploy * autonomously, a `Deny` is overridden/blocked/pending. Returns * `{ decision, enforcement, pending_approval? }`; a pending approval is * resolved via `permission.approve`/`permission.reject` by the returned * `fingerprint`. */ enforceSkillDeploymentLive(requestJson: string): Promise; /** * Read the standing permission tier granted to this connection's daemon * session (`read_only` | `sandbox_edit` | `full_access`) — the tier every * {@link submitProposal} on this connection is judged against * (Parslee-ai/car#890). */ permissionGetTier(): Promise; /** * Set this connection's standing permission tier and return the tier as the * daemon now holds it. `tier` is `read_only` | `sandbox_edit` | * `full_access`. * * Lets a binding client govern its own session — most usefully by tightening * it: dropping to `read_only` makes the runtime escalate any write this * client proposes to a human instead of running it. Raising the tier is * host-gated whenever the daemon runs under a host token, so an agent * connection cannot self-elevate. */ permissionSetTier(tier: string): Promise; /** * Ingest a skill through the deployment gate on the daemon (arXiv 2602.12430 * "Agent Skills" — the loader integration). `requestJson` carries the skill * fields (`name`, `code`, `platform`, `persona?`, `url_pattern?`, * `description?`, `supersedes?`, `task_keywords?`) plus `provenance?` and * `requested_tier`. The daemon gates + enforces against the session ledger and * **only ingests when deployment is permitted**, stamping the granted ceiling * onto the skill. Returns `{ ingested, node?, decision, enforcement, * pending_approval? }`; a pending deny is resolved via * `permission.approve`/`permission.reject` by the returned `fingerprint`. */ ingestSkillGoverned(requestJson: string): Promise; /** * Adopt an installed skill pack on the daemon through the skill-trust * deployment gate (arXiv 2602.12430 "Agent Skills" — the pack-adoption * call-site). `requestJson` carries `pack` (an `ApprovedSkillPack`), * `requested_tier?` (default `read_only`), and either `manifest?` — the signed * bundle, whose signature trust is derived against the operator's * `.car/config.toml` `trusted_skill_signers` keyring — or `provenance?` * (caller-assembled), plus optional `scanned?`/`vulnerabilities?`/`source?`. * Governance is unconditional: a denied skill never enters the graph. Returns * `{ loaded, pending, refused, requested_tier, provenance, trusted_signers }`; * a pending deny is resolved via `permission.approve`/`permission.reject` by * the returned `fingerprint`, then re-adopted. */ adoptSkillPack(requestJson: string): Promise; /** * Save a learned skill with trigger context. Returns the node * index. * * In Daemon mode, rejects with the daemon-unreachable error * (or a parse error if the response is malformed) instead of * silently returning 0 (#146). */ ingestSkill( name: string, code: string, platform: string, persona: string, urlPattern: string, taskKeywords: string[], description: string, supersedesSkill?: string | null, ): Promise; /** Find best matching skill for context. Returns JSON or `"null"`. */ findSkill( persona: string, url: string, task: string, maxResults?: number | null, ): string; /** Report skill execution outcome ("success" or "fail"). Returns updated stats JSON. */ reportOutcome(skillName: string, outcome: string): string; /** Distill skills from execution trace events. Returns JSON array of DistilledSkill. */ distillSkills(eventsJson: string): Promise; /** Ingest distilled skills into the memory graph. Returns the count ingested. */ ingestDistilledSkills(skillsJson: string): number; /** List skills (optionally filtered by domain). Returns JSON array. */ listSkills(domain?: string | null): string; /** Domains with success rate below the given threshold (default 0.6). */ domainsNeedingEvolution(threshold?: number | null): string[]; /** Repair a degraded skill using local inference. Returns repaired code or null. */ repairSkill(skillName: string): Promise; /** Evolve skills for a domain based on failed events. Returns JSON array. */ evolveSkills(eventsJson: string, domain: string): Promise; /** * Ingest distilled/evolved skills as validation-gated PROVISIONAL candidates * on trial (vs `ingestDistilledSkills`, which trusts them active). Returns the * count ingested. See docs/solutions/gated-skill-optimization.md. */ ingestProvisionalSkills(skillsJson: string, tenant?: string | null): number; /** * Run the skill promotion gate: provisional candidates with enough trial * outcomes are promoted (strictly-better Wilson lower bound) or rejected. * Returns JSON `{ promoted: string[], rejected: string[] }`. */ gateSkillCandidates(): Promise; /** * Fetch a skill's full SkillMeta by key (lifecycle `status`, `incumbent`, * `version`, `stats`). Returns JSON SkillMeta, or the string "null" if absent. */ skillMeta(key: string): Promise; /** * Export a VALIDATED skill as a portable markdown document (the SkillOpt * best_skill.md analog). Only Active, healthy skills export. Returns the * markdown, or null if the key is absent / not exportable. */ exportSkill(key: string): Promise; /** * Import a skill from a portable markdown document (digest-verified). Returns * true on success; rejects malformed or tampered documents. */ importSkill(markdown: string): Promise; // --- Inference --- /** * Generate text. Returns JSON: `{"text":"..."}`. * * `intentJson` is an optional serialized {@link IntentHint} — * caller-facing routing hints (task, prefer_local, require). Omit to * preserve the existing adaptive vs. pinned-model behavior. */ infer( prompt: string, model?: string | null, maxTokens?: number | null, intentJson?: string | null, ): Promise; /** * Generate with full tracking. Returns JSON with `text`, `tool_calls`, * `usage`, `model_used`, `latency_ms`, `time_to_first_token_ms`, * `trace_id`, `stop_reason`. `time_to_first_token_ms` is wall-clock to * the first sampled token (populated by local Candle/MLX paths; `null` * for non-streaming remote calls). `stop_reason` is the raw provider * termination reason (OpenAI `finish_reason`, Anthropic `stop_reason`, * Google `finishReason`); `null` for local backends or providers that * don't report one. A value of `"length"`/`"max_tokens"`/`"MAX_TOKENS"` * means the output was truncated at the token cap. On local Qwen3 * hybrid-thinking models it is also set to `"thinking_recovered"` when * reasoning consumed the whole token budget and the runtime retried * with reasoning suppressed to produce a direct answer, or * `"thinking_truncated"` when even that retry was empty (car-releases#60). * * `local_last_resort` is present and true ONLY when CAR appended an * installed on-device model behind a remote-only chain and that model * actually served the turn. An explicitly selected local model is not marked. * * `auth_fallback_from` is present ONLY when a candidate earlier in the * fallback chain was skipped because its credential was **rejected** * (not merely absent) and a later model then answered. It names that * dead lane, so a caller can tell the user their sign-in lapsed instead * of silently serving a different model (Parslee-ai/car#888). Absent on * the common path. * * `fallback_from` is an ARRAY of every candidate the chain moved past, * in the order it tried them: `[{ candidate, reason }, ...]`, where * `reason` is one of `"credential_rejected"`, `"credential_absent"`, * `"rate_limited"`, `"quota_exhausted"`, `"timed_out"` or `"failed"`. * Absent when the first candidate served. Before this, a run whose * backbone changed because of a rate limit or a timeout recorded no * cause anywhere, so a surprising result got attributed to the code * rather than to the model swap (Parslee-ai/car#1351). * * `reason` is classified from the runtime's typed error, not from error * prose. `"credential_rejected"` is deliberately BROADER than * `auth_fallback_from`: it covers a provider refusing an API key, whose * remedy is to fix the key, not to sign in. Do not derive one field * from the other. * * **Note:** intent is not exposed on the tracked path until the * positional argument list is converted to an options object — * this method already takes 9 positional parameters and adding * intent would push call sites past readability. For new code, * use {@link inferTrackedWithRequest} which takes a JSON- * stringified `GenerateRequest` and exposes every field * including `intent`. * * `imagesJson` is a JSON-encoded array of `ContentBlock` image * variants — either * `{ "type": "image_base64", "data": "", "media_type": "image/png" }` * or `{ "type": "image_url", "url": "https://…", "detail": "auto" }`. * Vision-capable hosted models (Claude 3.5+/4.x, GPT-4o, Gemini) * accept these directly; non-vision providers reject the request * via a structured error from the daemon. See #230. */ inferTracked( prompt: string, model?: string | null, maxTokens?: number | null, context?: string | null, toolsJson?: string | null, messagesJson?: string | null, toolChoice?: string | null, parallelToolCalls?: boolean | null, imagesJson?: string | null, ): Promise; /** * Generate with full tracking, options-object form. * `requestJson` is a `JSON.stringify`d `GenerateRequest` (every * field optional except `prompt`). Exposes every field on the * Rust struct including `intent`. Same pattern as * {@link verifyProposal}. Closes #107. * * `client_ref` is an opaque correlation token echoed verbatim in the * `inference.runner.invoke` payload and otherwise ignored by CAR. A * delegated-inference host with several calls in flight uses it to map an * invoke back to its own request state — `call_id` is minted by the daemon * only after this call, so it cannot serve that purpose. Hosts previously * had to smuggle an id through `prompt`, which worked only because * delegated models ignore it (car-releases#78). */ inferTrackedWithRequest(requestJson: string): Promise; /** * Generate an image from a text prompt via the daemon's installed Flux/MLX * models. `requestJson` is a JSON-stringified `GenerateImageRequest` * (`{ prompt, model?, width?, height?, steps?, guidance?, seed?, * output_path?, ... }`). Returns `GenerateImageResult` JSON * (`{ image_path, model_used, latency_ms, ... }`). The FFI analogue of the * `image.generate` WS method (car-releases#70). */ generateImage(requestJson: string): Promise; /** * Generate a video from a text/image prompt via the daemon's installed * LTX/MLX models. `requestJson` is a JSON-stringified `GenerateVideoRequest`; * returns `GenerateVideoResult` JSON. FFI analogue of the `video.generate` WS * method (car-releases#70). */ generateVideo(requestJson: string): Promise; /** * Build a runnable workflow from a natural-language goal via the daemon's * builder. `requestJson` is `{ goal, existing?, max_attempts? }`; on the * daemon the catalog (registered tools + models) is authoritative, so the * tool cross-check fires. Returns * `{ valid, workflow, issues, warnings, attempts }` as JSON. */ buildWorkflow(requestJson: string): Promise; /** * Generate text grounded with memory context from this runtime's * memgine. `intentJson` works the same as on {@link infer}. */ inferWithContext( prompt: string, model?: string | null, maxTokens?: number | null, intentJson?: string | null, ): Promise; /** Embed texts. Returns JSON array of float arrays. */ embed(texts: string[], model?: string | null): Promise; /** * Rerank documents against a query using a cross-encoder reranker. * Returns JSON: `{ranked: [{index, score, document}, ...], model_used}`. */ rerank( query: string, documents: string[], model?: string | null, topN?: number | null, instruction?: string | null, ): Promise; /** Classify text against labels. Returns JSON array of `{label, score}`. */ classify(text: string, labels: string[], model?: string | null): Promise; /** * Encode `text` via the named local model's tokenizer. Returns a JSON * array of u32 token IDs, raw (no chat-template wrapping, no BOS). * Pair with `detokenize` for byte-identical round-trip. Remote models * are not supported — call rejects with an error there. */ tokenize(model: string, text: string): Promise; /** * Decode token IDs back to text via the named local model's tokenizer. * Inverse of `tokenize` for the round-trip property. */ detokenize(model: string, tokens: number[]): Promise; // --- Web search --- /** * Web search. The daemon resolves the backend: the signed-in Parslee * account's hosted search when available, else a bring-your-own * `TAVILY_API_KEY`. Returns JSON `{ query, source, results: [{title, url, * snippet, score, published_date}] }`. */ search(query: string, maxResults?: number | null): Promise; /** * Fetch a URL and extract readable text (keyless; companion to `search`). * Returns JSON `{ url, status, content_type, title?, text }`. */ webFetch(url: string): Promise; // --- Speech --- /** * Provision the managed speech runtime and return its root path — the same * root `speechHealth()` / `car speech doctor` report. The first call on a * fresh machine builds a Python venv and can take minutes; afterwards it is * a no-op. The returned path is not a success signal: on Apple Silicon the * runtime is a fallback behind the native MLX backends, so a bootstrap that * cannot run degrades instead of failing. Read * `speechHealth().runtime.installed` for the real state. */ prepareSpeechRuntime(): Promise; /** Transcribe a local audio file. Returns JSON `{text, model_used, language, ...}`. */ transcribe( audioPath: string, model?: string | null, language?: string | null, prompt?: string | null, timestamps?: boolean | null, ): Promise; /** * Synthesize speech to an output file. Returns JSON `{audio_path, media_type, ...}`. * `referenceAudioPath`, `referenceText`, `voiceInstruction` are Qwen3-TTS-specific * controls (voice cloning / voice design); other backends ignore them. */ synthesize( text: string, model?: string | null, voice?: string | null, language?: string | null, speed?: number | null, outputPath?: string | null, format?: string | null, referenceAudioPath?: string | null, referenceText?: string | null, voiceInstruction?: string | null, ): Promise; // --- Models --- /** Local + built-in models. Returns JSON array. */ listModels(): string; /** Download a model. Returns its local path. */ pullModel(name: string): Promise; /** Remove only a receipt-backed CAR-managed artifact. Returns result JSON. */ removeModel(modelId: string): Promise; /** Adopt an already-usable local artifact into CAR ownership. */ adoptModel(modelId: string): Promise; /** Read the saved local-model resource policy and evaluated budget. */ modelResourcePolicyGet(): Promise; /** Persist an exact resource-policy JSON object. */ modelResourcePolicySet(policyJson: string): Promise; /** Evaluate one local model without downloading or loading it. */ modelPreflight(modelId: string, contextTokens?: number): Promise; /** * Unified registry (local + remote). Returns JSON array of * `{ id, name, provider, capabilities, param_count, size_mb, * context_length, available, is_local, operator_managed_external_runtime, * weights_ready, downloads_weights, * max_output_tokens, public_benchmarks, cost, car_enabled, can_remove, * in_use, management_evidence, fit, estimated_peak_mb, * platform_compatible, deprecated, family, version }`. `available` means CAR * can use the model * here — for a local MLX entry with a declared `hf_repo` it is `true` * before a byte is fetched, because it lazy-downloads on first use — * whereas `weights_ready` means the weights are already on disk (remote * models, having none to install, report `true`). Older daemons omit * `weights_ready`; it defaults to `false` rather than failing. * `downloads_weights` is `true` only for entries whose weights CAR fetches * before use (GGUF, MLX, whisper.cpp, and CAR-owned managed vLLM-MLX). * When it is `false` — OS-provided models such as * `windows/speech-synthesis:os` and `apple/foundation:default`, * operator-managed servers such as raw vLLM-MLX and Ollama, and every * remote entry — there is nothing to * install, so `weights_ready` is meaningless and the CLI renders * `INSTALLED` as `-`. Do not substitute `is_local`: OS-provided models are * local but download nothing. A raw external vLLM-MLX row instead * sets `operator_managed_external_runtime=true` and is not local, even for * a loopback endpoint; only CAR-owned managed vLLM-MLX is charged and * supervised as local. Older daemons omit * `downloads_weights`; it defaults to `false` rather than failing. * `max_output_tokens` is the registry-declared * per-model output ceiling (`null` when the entry omits it; callers * then fall back to a fraction of `context_length`). * `public_benchmarks` is `[{ name, score, harness?, source_url?, * measured_at? }]` with score on a 0.0–1.0 scale; ships empty in * the built-in catalog and is populated via curated registry data. * `cost` is the model's declared prices — `{ input_per_mtok, * output_per_mtok, cache_read_input_per_mtok, cache_write_input_per_mtok, * pricing_tiers, size_mb, ram_mb }` — in USD per 1M tokens, with * `pricing_tiers` as `[{ min_prompt_tokens, ...prices }]` prompt-size * overrides (highest threshold not above the prompt wins). Every price is * nullable and `null` means **unpriced, not free**: a local model declares * no prices, and a caller that reads that as `0` publishes a fabricated * cost. The managed `parslee/…` alias rows carry the same prices as the * upstream row they front, and this response carries no upstream * identifier for them. That holds for this catalog view; `models.search` * entries carry these same fields, fit annotation included, and * additionally name `family` / `version` for every row (the upstream * model family for a managed alias). Older daemons omit * `cost` entirely; it deserializes to all-`null` rather than failing. * `fit` (`"fits" | "too_big" | "unknown"`), `estimated_peak_mb` and * `platform_compatible` say whether the row fits the machine the daemon * runs on, by the same rule `models.recommend` uses against the active * resource policy; remote rows always read `fits` / `null` / `true` * because their memory is the server's. `unknown` never means too big * and is what an older daemon's rows read as. `deprecated` mirrors the * catalog flag; `family` and `version` are published for local rows only * (`null` for remote rows, which is how this view keeps carrying no * upstream identifier for managed aliases). The list is never filtered * by the daemon — hide on `fit` in the client, as `car models list` does. */ listModelsUnified(): string; /** * Register a `ModelSchema` via the daemon's `models.register` * JSON-RPC method (Parslee-ai/car-releases#39). The schema is * persisted to `~/.car/models.json` (replacing any existing * entry with the same `id`). * * **Visibility limitation**: the model becomes visible to * `infer` / `models.list` / `models.list_unified` on the **next * daemon boot**. Live hot-update inside a running daemon is * tracked as a separate follow-up that requires interior * mutability on the `UnifiedRegistry`. Register before * starting the daemon's inference path, or restart the daemon * after a batch of registrations. * * Returns JSON `{id, registered, path, note}`. */ registerModel(schemaJson: string): Promise; /** * `assistant.identity.get` — the name the flagship assistant answers to. * * Returns `{ name, spellings, aliases, user_name, brand, updated_at_unix }`. * `aliases` is the derived match set (name and spellings crossed with * "hey"/"ok"/…), longest first — hosts match wake phrases against it locally * so their matcher works before the daemon answers. * * `brand` is the fixed product name and never changes; `name` is what this * user calls the assistant. Both travel together: store copy uses the brand, * addressing copy uses the name. * * Ungated — a name is not a credential. A malformed `identity.json` rejects * rather than silently answering with the default name. */ assistantIdentityGet(): Promise; /** * `assistant.identity.set` — name the assistant. Host/local-auth gated on the * daemon, because a rename repoints the voice wake word. * * `requestJson` is `{ name?, spellings?, user_name? }`. Every field is * optional and unset fields are preserved, so a caller that only knows about * the name cannot wipe spellings another surface wrote. Pass * `user_name: null` to clear it. * * Returns the updated identity JSON, in the same shape as * `assistantIdentityGet`. */ assistantIdentitySet(requestJson: string): Promise; /** * `messaging.config.get` — read the multi-channel approval-transport config * for one channel (enabled flag, allowlisted handles, whether a pairing is * in flight). Host/local-auth gated on the daemon. * * `requestJson` is an optional `{ channel? }` selector — `channel` is * `"imessage"` | `"slack"`, default `"imessage"`. Pass `"{}"` or omit it for * the iMessage (back-compat) channel. * * Returns `MessagingConfigView` JSON. The view always carries a `channel` * key naming which channel it describes (`"imessage"` | `"slack"`). */ messagingConfigGet(requestJson?: string): Promise; /** * `messaging.config.set` — mutate one channel's approval-transport config. * The ONLY allowlist/config-mutation path; host/local-auth gated. * `requestJson` is a `MessagingConfigSetRequest` * (`{ channel?, enabled?, allowlisted_handles?, add_handles?, remove_handles?, * bot_token?, app_token? }`). * `channel` is `"imessage"` | `"slack"`, default `"imessage"` when absent * (back-compat). For `channel: "slack"`, supplying BOTH `bot_token` (`xoxb-`) * and `app_token` (`xapp-`) provisions them into the OS keychain (MC-9) and * persists only a keychain reference into the config — the bearer values are * never stored on disk nor echoed back. * Returns the updated `MessagingConfigView` JSON (with its `channel` key). */ messagingConfigSet(requestJson: string): Promise; /** * `messaging.pairing.start` — mint a fresh high-entropy pairing code for one * channel to display ONLY in the local UI; the paired device sends it back * to bind its handle. Host/local-auth gated. * * `requestJson` is an optional `{ channel? }` selector (`"imessage"` | * `"slack"`, default `"imessage"`). Returns `MessagingPairingStartResponse` * JSON (`{ pairing_code, config }`). */ messagingPairingStart(requestJson?: string): Promise; /** * `messaging.pairing.status` — whether a pairing is in flight on one channel * and (host gated) the active code. `requestJson` is an optional * `{ channel? }` selector (`"imessage"` | `"slack"`, default `"imessage"`). * Returns `MessagingPairingStatusResponse` JSON. */ messagingPairingStatus(requestJson?: string): Promise; /** * `messaging.status` — the real runtime liveness of one channel's approval * transport, computed daemon-side so a host UI can render a SINGLE readiness * state (enabled · watcher running · FDA · paired) plus last-delivered + * last-error. Host/local-auth gated. `requestJson` is an optional * `{ channel? }` selector (`"imessage"` | `"slack"`, default `"imessage"`). * Returns `MessagingStatusView` JSON. */ messagingStatus(requestJson?: string): Promise; /** * `messaging.test_send` — send a fixed, clearly-labeled self-test message to * one channel's paired handle and return `{ ok, error }` synchronously. A * pure send probe: it mints NO approval/pairing mapping and resolves nothing. * Host/local-auth gated. `requestJson` is an optional `{ channel? }` selector * (`"imessage"` | `"slack"`, default `"imessage"`). Returns * `MessagingTestSendResponse` JSON. */ messagingTestSend(requestJson?: string): Promise; /** * Recommend models for this machine + intent. `useCase`/`tier` are * snake_case enum values (e.g. "coding", "most_capable"); `cloudOk` lets * cloud models compete. Returns the `RecommendationSet` JSON * (`{ picks, notEnoughMemory, note }`). */ recommend(useCase: string, tier: string, cloudOk: boolean): Promise; /** * Coder — built-in coding agent (`coder.*` daemon namespace). Sessions * live in the daemon and are visible in CarHost. Live `coder.event` * streaming is WebSocket-only: call `coder.subscribe` on the daemon's * WS directly (same contract as `infer_stream`). * * Start a session: provisions an isolated git worktree of `repo` and * derives a verifiable outcome contract from `intent`. `engine` is * `"auto" | "native" | "external[:agent_id]"` (default auto). Returns * `{session_id, state, engine, worktree, contract, model}` JSON, where * `model` is the effective native-loop pin (per-session `model`, else * `~/.car/coder.toml`, else `null` = adaptive routing). Set * `options.browser` to opt into the assistant's browser tool surface for this * session; it remains absent by default and policy-gated when enabled. */ coderStart( repo: string, intent: string, options?: CoderStartOptions | undefined | null, ): Promise; /** * Confirm the proposed outcome contract (optionally replacing it with * the edited `contractJson`) and start the work loop. */ coderConfirmContract( sessionId: string, contractJson?: string | undefined | null, ): Promise; /** List coder sessions (live and persisted), newest first. */ coderList(): Promise; /** Full session detail, including contract and check results. */ coderGet(sessionId: string): Promise; /** * Answer a `user_input_requested` event (reserved — neither engine * requests mid-session input yet). */ coderRespond(sessionId: string, text: string): Promise; /** * Approve (publish the `car/coder/` branch in the repo) or deny * (abandon) a session awaiting merge approval. Agent-project approvals * return additive `agent_id` and daemon-derived `registry_path` fields. */ coderApproveMerge(sessionId: string, approve: boolean): Promise; /** * Cancel a session: stop the loop, abandon, remove the worktree. Returns * `{state, already_terminal, message}`. * * An already-finished session **succeeds** rather than rejecting: `state` * keeps its pre-existing name and type, `already_terminal` is `true`, and * `message` names what already happened. Callers that cancel unconditionally * on shutdown depend on that — rejecting would turn a quiet exit into a * protocol error whenever the session raced to terminal first. */ coderCancel(sessionId: string): Promise; /** * The current session list AND registration for `coder.session_changed` on * this connection, atomically (registered under the same lock the list is * snapshotted under, so nothing slips through the gap). Notifications are * WebSocket-only, same contract as `coder.subscribe`. * * Each row carries the full summary: the pre-existing * `{session_id, state, intent, repo, engine, iterations, updated_at, live, * error}` plus `needs_you` (`"contract" | "question" | "approval" | "auth" | * null`), `needs_you_label` (the daemon-owned wording, so every client says * the same thing), `question_prompt`, `auth_message`, `auth_wait_secs`, * `failure_kind` (`"budget_exhausted" | "auth_required" | "configuration" | * "infrastructure" | "error"` when failed), `worktree` (only when it still exists on disk), * `project`, `result_branch`, `model`, `discussion_id`, and `next_seq` (live * only — the `coder.subscribe` cursor). * * Pass `renew: true` for the lease-renewal form: it re-registers and answers * `{ was_registered }` — `false` means this connection had been shed and * should take a full snapshot — and builds NO summaries, so it is cheap * enough to call on a timer. The default form is unchanged. */ coderWatch(renew?: boolean | undefined | null): Promise; /** Stop receiving `coder.session_changed` on this connection. */ coderUnwatch(): Promise; /** * Redraft a PROPOSED outcome contract from a plain-English request (e.g. * "also verify the Windows path"). Legal only in `contract_proposed`; * nothing executes and the session stays at the gate either way. Unlimited * rounds. * * Returns `{state, revised, contract, baseline, baseline_gates_nothing, * message}`. **Check `revised` before trusting `contract`**: on a redraft * that does not validate, the previous contract comes back byte-identical * with `revised: false` and a `message` explaining why, and the daemon emits * a `contract_revision_rejected` event. */ coderReviseContract(sessionId: string, request: string): Promise; /** * Open a repo-grounded, strictly **read-only** discussion — a thinking * surface for working out what a change should be, before a run exists. * Bound at `PermissionTier::ReadOnly` with every write/shell escalation * auto-denied, so it can never touch the repo. Returns * `{discussion_id, repo, repo_summary}`; a non-git path is a clear error. */ coderDiscussStart(repo: string): Promise; /** * Send one operator message. Returns `{ok, seq}` where `seq` is the first * event this turn emits; the reply streams as `coder.discuss.event` * (WebSocket-only, same contract as `coder.event`). */ coderDiscussSend(discussionId: string, text: string): Promise; /** * Distill the discussion into `{discussion_id, proposed_intent, * constraints}`. **Starts nothing** — no worktree, no branch, no session. * The caller shows `proposed_intent` (never the transcript) for the operator * to edit, then passes it to `coderStart` with `discussion_id` so the agreed * constraints reach contract derivation. Callable repeatedly. */ coderDiscussPromote(discussionId: string): Promise; /** Free an in-memory discussion. Discussions do not survive a daemon restart. */ coderDiscussClose(discussionId: string): Promise; /** * Open discussions: `{discussions: [{discussion_id, repo, created_at, * turns}]}`. Also the capability probe — a daemon predating this surface * answers JSON-RPC `-32601`. */ coderDiscussList(): Promise; /** * Managed projects + in-daemon declarative agents (the non-developer path). * * Create (or load) a CAR-managed git-backed project under * `~/.car/projects/`. `kind` is `"app"` (code) or `"agent"` (an in-daemon * declarative agent). Returns the `CoderProject` JSON. */ projectCreate(name: string, kind?: string | undefined | null): Promise; /** List managed projects, newest first. */ projectList(): Promise; /** One project's metadata by slug. */ projectGet(slug: string): Promise; /** * Discover what the signed-in Parslee account can do — identity, m365 * product entitlements, and Studio reachability. Read-only. Returns JSON. */ parsleeCapabilities(): Promise; /** * Generate a Word document from a natural-language brief, saved to the * user's connected drive. Gated on the `aie` entitlement. `documentType` * defaults to `Report`. Returns JSON `{ file_id, web_url, ... }`. */ parsleeM365GenerateDocument(contentBrief: string, outputFilePath: string, documentType?: string | undefined | null, title?: string | undefined | null, author?: string | undefined | null): Promise; /** List registered in-daemon declarative agents. */ declagentList(): Promise; /** One declarative agent's spec by id, plus daemon-derived `registry_path`. */ declagentGet(id: string): Promise; /** Unregister a declarative agent. */ declagentRemove(id: string): Promise; /** Enable or disable a declarative agent. */ declagentSetEnabled(id: string, enabled: boolean): Promise; /** * Run a declarative agent on an input, in-daemon (no external process). * Returns `{ output, turns, tool_calls, error? }` JSON. */ declagentInvoke(id: string, input: string): Promise; /** * Route a need to the best-matching declarative agent by capability * similarity. Returns `{ chosen, candidates, next_visited, invoked, result? }` * JSON. With `invoke: true`, the top agent is run on `need` and its result is * included. Network-entry case only; multi-hop Forward chaining (`from` / * `visited`) is WS-only. */ declagentRoute(need: string, invoke: boolean): Promise; /** * Split a composite need into subtasks and route each to its best-matching * agent. Returns `{ subtasks: [{ subtask, chosen, score, result? }], count, * invoked }` JSON. `maxSubtasks` caps the split (clamped to [1, 10]; null = * default 5). With `invoke: true`, each subtask's chosen agent runs. */ declagentRouteSplit( need: string, invoke: boolean, maxSubtasks?: number | undefined | null, decompositionMode?: "vanilla" | "sad" | string | undefined | null, sadHints?: number | undefined | null, sadIterations?: number | undefined | null, sadConvergenceJaccard?: number | undefined | null ): Promise; /** * Read-only view of the learned routing topology: per-agent success stats * and directed agent→agent edge weights. Returns `{ agents, edges }` JSON. */ declagentRoutingStats(): Promise; /** * AgentDNS-style discovery: resolve a natural-language need into ranked * CAR-local services, each named under `agentdns://org/category/name`. * Providers: declarative agents, observe-only registry services * (`~/.car/registry/`, kind `registry`), MCP connector tools, external * CLIs, A2A peers, and an opt-in remote root. Returns `{ services: [{ * identifier, name, kind, protocol, score, similarity }], count }` JSON. * `limit` caps results (clamped to [1, 50]; null = default 5). */ discoveryResolve(need: string, limit?: number | undefined | null): Promise; /** * Record a discovery-routed run's outcome (`"success"` | `"failure"`) into * the routing learning store, keyed by the service's `agentdns://` * identifier — for EVERY provider kind (connector, registry, external, a2a, * declarative). This is the feedback loop `discoveryResolve`'s success * prior learns from. Returns `{ identifier, outcome, successes, failures }` * JSON. */ discoveryReport(identifier: string, outcome: "success" | "failure" | string): Promise; /** * Compose a decompose/retrieve/plan route over all discoverable services. * Returns `{ plan, decomposition, candidates, metadata }` JSON. Planning only; * callers invoke returned targets through existing governed surfaces. */ discoveryRouteCompose( need: string, maxSubtasks?: number | undefined | null, decompositionMode?: "vanilla" | "sad" | string | undefined | null, sadHints?: number | undefined | null, sadIterations?: number | undefined | null, sadConvergenceJaccard?: number | undefined | null, candidatesPerStep?: number | undefined | null, rerank?: boolean ): Promise; /** * Build a concrete onboarding plan (machine summary, top pick, alternatives, * needs-more-memory, note) as JSON. */ setupPlan(useCase: string, tier: string, cloudOk: boolean): Promise; /** Detect upgrades (curated + upstream, channel-gated). Returns JSON. */ detectUpgrades(): Promise; /** Current proactive-upgrade decision (poll form). Returns JSON. */ checkUpgradeNudge(inferenceActive: boolean): Promise; /** Dismiss an upgrade nudge by its `dismissKey` so it never re-fires. */ dismissUpgrade(dismissKey: string): Promise; /** Get update preferences as JSON. */ updatePrefsGet(): Promise; /** Set update preferences (JSON `UpdatePreferences` shape). Returns stored prefs JSON. */ updatePrefsSet(prefsJson: string): Promise; /** * Route a prompt. Returns the routing decision as JSON, including * `candidates`: the advisory ranking of every scored model * (`{ model_id, reliability, score, selected, in_band }`) so callers can see * why a model won and what the alternatives cost in reliability terms. Empty * on explicit-model and cold-start paths where no ranking occurred. * `intentJson.strict_exclusions` makes an exhausted `exclude_models` list * return no route instead of selecting an excluded last resort. */ routeModel(prompt: string, intentJson?: string | null): Promise; /** Per-model performance profiles. Returns JSON. */ modelStats(): Promise; /** * Persistent outcome scoreboard, folded from the durable outcome ledger. * Returns JSON `{ rows: [{ model_id, success_count, fail_count, * inconclusive_count, total_input_tokens, total_output_tokens, avg_quality, * avg_latency_ms, success_rate, tokens_per_success, usd_per_success }], * total_successes, total_failures, total_inconclusive, total_usd, * overall_usd_per_success, model_count, receipts }`. Rows are sorted * cheapest-correct-outcome first. The cross-session, outcome-denominated view * (unlike `modelStats`, the live in-memory profiles). */ outcomeScoreboard(): Promise; // --- Execution --- /** Count of events in this runtime's execution log. */ eventCount(): Promise; /** Drain buffered chunks + current status for a detached * (streaming/long-running) tool invocation (C2). `handle` is the * `tool_handle` a detached ToolCall action (`invocation_mode: "streaming" * | "long_running"`) returned as its output. Returns the ToolPollResult * JSON string `{handle, tool, action_id, status, chunks, result?, * error?}`, or `null` for an unknown / already fully-consumed handle. */ toolPoll(handle: string): Promise; /** Request cooperative cancellation of a detached (streaming/long-running) * tool invocation (C2). Resolves `true` when the handle was known (the * invocation is sealed `cancelled` unless already terminal), `false` for * an unknown handle. */ toolCancel(handle: string): Promise; /** Structured audit query over the event log (G2). `queryJson` is an * EventQuery object (kinds/actionId/proposalId/since/until/dataMatches/limit); * returns `{count, events}` as a JSON string, most-recent-first. * `ActionFailed.data` includes `params_digest`, `expected_effects`, and * `error_class` (`timeout|rejected_by_policy|tool_error|validation|unknown`), * never raw parameters. `ActionSucceeded.data` includes the first two. */ eventQuery(queryJson: string): Promise; /** Get/set the event-log retention policy (G2). Pass a * `{maxEvents, maxAgeSecs}` JSON string to install it, or omit to read the * current policy. Returns a JSON string. */ eventRetention(policyJson?: string): Promise; /** Per-agent token/cost report (G3), folded from metered inference events. * Returns a JSON array of `{agent, calls, tokensIn, tokensOut, costUsd}`. */ eventCostByAgent(): Promise; /** Turn on tamper-evident hash chaining for the session event log (A9). * Every event appended from now on links to its predecessor by a content * hash. Idempotent. */ enableEventLogHashChaining(): Promise; /** Verify the session event log's tamper-evidence chain (A9). Returns * `{"verified": n}` (chained events verified) or `{"tampered_at": i}` * (index of the first interior edit/deletion/reorder) as a JSON string. * Head/tail truncation is not detectable (no anchored head hash). */ verifyEventLogChain(): Promise; /** Live operational metrics rollup (G1) — success/error rate, cost, latency, * approvals, gate rejections, per-agent cost. `cost_usd` is the fold over the * retained window; `cumulative_cost_usd` is the monotonic lifetime spend * (survives retention trims). Returns JSON. */ metricsSummary(): Promise; /** Evaluate live metrics against thresholds (G1). `thresholdsJson` is an * AlertThresholds object (omit for defaults); returns `{summary, alerts}` as * JSON. The `max_cost_usd` budget is checked against the monotonic * `cumulative_cost_usd` counter, so a retention trim never un-fires the * `cost_overage` alert. */ metricsAlerts(thresholdsJson?: string): Promise; /** Self-healing repair loop status: enabled/why-not, cadence, targets, * rejected targets, review panel, engine. */ healStatus(): Promise; /** Run one self-healing repair sweep now. May open a pull request; never merges. */ healRun(): Promise; /** Self-heal status as JSON: cadence, `auto_fix_enabled`, `max_concurrent`, * `max_per_day`, `max_rounds_per_key`, optional `auto_fix_refusal_reason`, * last tick, source route/refusal, * detector counts, and `filing_mode` (`watch-only` or `pr-only`). */ selfhealStatus(): Promise; /** List active (not dismissed) self-heal detections as JSON. Each includes * `route` and an optional `local_issue_path`. Recurring tool failures add * `eligible`, a secret-safe `reconstructed_call` (`tool` plus exact `params`), * optional owner-private `reconstructed_call_path`, `auto_fix_attempts`, * `auto_fix_exhausted`, `auto_fix_in_progress`, and * `last_auto_fix_attempt` (including `exit_code` and `failure_class`). Remote * deduplication adds `auto_fix_awaiting_review`, `auto_fix_parked`, * `remote_pr_number`, and `remote_pr_url`. * `queryJson` carries optional `kind`, `severity`, * `since`, `offset`, and `limit` (max 500). */ selfhealDetections(queryJson?: string): Promise; /** Append a dismissal marker for a stable detection dedup key without * deleting history. */ selfhealDismiss(dedupKey: string): Promise; /** Start one bounded template-owned coder round for an eligible recurring * tool failure. Returns the durable attempt result as JSON. */ selfhealFix(dedupKey: string): Promise; /** Run one non-overlapping detection tick and default-on auto-fix hook. */ selfhealRun(): Promise; /** Execution log counts and approximate retained native bytes. Returns JSON. */ eventLogStats(): Promise; /** Keep only the newest events/spans in this runtime's execution log. Returns JSON. */ truncateEventLog(maxEvents?: number | null, maxSpans?: number | null): Promise; /** Clear this runtime's execution log. Returns JSON. */ clearEventLog(): Promise; /** Verify a proposal against this runtime's state + tools. Returns JSON. */ verifyProposal(proposalJson: string): Promise; /** * Submit a proposal for daemon-side execution using the * persistent `tools.execute` handler set by * `registerToolHandler` (Parslee-ai/car-releases#38). * * Symmetric to `executeProposal` but without the per-call * handler argument — the handler is process-wide. Fails up * front if no handler is registered. * * `sessionId`, when provided, scopes per-action policy * validation to a session opened via the daemon's * `session.policy.open` JSON-RPC method. * * Returns the JSON-encoded execution result. */ submitProposal( proposalJson: string, sessionId?: string | null, ): Promise; // --- Browser automation --- /** * Run a JSON script of browser operations against a persistent Chromium * session attached to this runtime instance. First call lazily launches * Chromium (requires a local Chrome/Chromium binary); subsequent calls * reuse the same session so element IDs from `observe` resolve across * invocations. * * Script shape: `{operations: [{op:"navigate",url:"..."}, {op:"observe"}, ...]}` * Supported ops: navigate, observe, click, type, scroll, keypress, wait. * Returns JSON: `{steps:[{op,status,data,error,duration_ms}]}`. Execution * short-circuits on first error. * * `headed`: when `true`, launches a visible Chromium window * instead of headless mode — for interactive flows like * first-time auth (LinkedIn / OAuth / SSO / 2FA / captcha). * Honoured only on the *first* call that launches the session; * subsequent calls reuse the existing browser regardless. To * switch modes, call `browserClose()` first. * * `extraArgs`: extra Chromium command-line flags appended * verbatim to argv at launch (#112). Use cases: the Google * Meet bot needing `--use-fake-ui-for-media-stream`, * `--autoplay-policy=no-user-gesture-required`, and the * container-friendly `--no-sandbox` / * `--disable-dev-shm-usage` / `--disable-setuid-sandbox`. Like * `headed`, honoured only on the launch call. */ browserRun( scriptJson: string, width?: number | null, height?: number | null, headed?: boolean | null, extraArgs?: string[] | null, ): Promise; /** Close any persistent browser session attached to this runtime. */ browserClose(): Promise; // `browserRun`/`browserClose` above are this runtime's OWN // per-connection scripted browser. Separate from that: the browser // DRAWER surface (`browser.view.*` / `browser.producer.*` / // `agent.browser.*`), which watches and drives the ASSISTANT's // browser (or the shared standing session) for a human at the // Command Deck. It is WS-only — no method here — the same decision // as `runs.subscribe` / `coder.subscribe`: `browser.view.*` requires // the host-management client (`session.auth { host_token }`, stricter // than `runs.subscribe`), so CarHost speaks it directly over the // daemon's WS. `browser.producer.*` / `agent.browser.*` is the agent // side of the same relay; today its only producer is the Rust // `car-cli` binary, so it likewise has no binding here. Full wire // contract: `docs/websocket-protocol.md` (`### browser`) and // `docs/host-protocol.md` (`Live browser view`). /** * Register a tool with a full JSON-serialized `ToolSchema`. * `verifyProposal` validates `Action.parameters` against the schema's * `parameters` field — catching type mismatches like `{path: 42}` for a * tool wanting `{path: string}` before dispatch. The schema also carries * idempotency, cache TTL, and rate-limit hints that the engine wires up * automatically. * * Tools registered via the schemaless `registerTool(name)` bypass type * validation; this is the opt-in upgrade path. The daemon assigns * `source = "user_defined"`; callers cannot claim another origin. * * `schemaJson` carries the caller-settable fields: * ```json * { * "name": "read_file", * "description": "...", * "parameters": {"type":"object","properties":{"path":{"type":"string"}},"required":["path"]}, * "returns": null, * "idempotent": true, * "cache_ttl_secs": 60, * "rate_limit": {"max_calls": 100, "interval_secs": 60} * } * ``` */ registerToolSchema(schemaJson: string): Promise; // ------------------------------------------------------------------------- // OS-native secret store (Keychain / Credential Manager / Secret Service) // ------------------------------------------------------------------------- /** Returns JSON `{available: boolean, reason?: string}`. */ secretAvailable(): string; /** * Store a secret. Returns JSON `{ok: true}` on success. Throws if the * backend is unavailable. `service` defaults to the runtime-wide bundle id. */ secretPut(key: string, value: string, service?: string | null): string; /** * Retrieve a secret. Returns JSON `{value: string}`. Throws `not_found` * if the secret does not exist. */ secretGet(key: string, service?: string | null): string; /** Delete a secret (idempotent). Returns JSON `{ok: true}`. */ secretDelete(key: string, service?: string | null): string; /** Returns JSON `{exists: boolean, key, service}` without exposing the value. */ secretStatus(key: string, service?: string | null): string; /** * List the NAMES of secrets stored through this surface. Returns JSON * `{secrets: [{service, key, exists}]}` — never the values. Backed by the * `~/.car/secret_index.json` name index, joined with a live existence check * (`exists` is `null` if the backend couldn't be probed). */ secretList(): string; // ------------------------------------------------------------------------- // OS permission preflight // ------------------------------------------------------------------------- /** Returns JSON `{domains: [...]}` listing every permission domain CAR knows. */ permissionDomains(): string; /** * Returns JSON `{ domain, status, target_bundle_id }`. `status` is one of * `granted` | `denied` | `not_determined` | `restricted` | `not_applicable` | * `restart_required` | `signature_changed` | `unknown`. The `calendar` domain * additionally reports a real, non-prompting EventKit query and can return * `write_only` (macOS-14 write-only calendar grant). */ permissionStatus(domain: string, targetBundleId?: string | null): string; /** Triggers the OS permission prompt; returns the resulting status. */ permissionRequest(domain: string, targetBundleId?: string | null): string; /** Returns JSON describing what the permission unlocks and how to revoke it. */ permissionExplain(domain: string, targetBundleId?: string | null): string; // ------------------------------------------------------------------------- // Native account discovery (system Settings → Internet Accounts on macOS) // ------------------------------------------------------------------------- /** Returns JSON array of accounts known to the OS. */ accountsList(): string; /** Open the OS's native account-management UI for an account or the root pane. */ accountsOpen(accountId?: string | null): string; // ------------------------------------------------------------------------- // Calendar / Contacts / Mail / Messages integrations (delegated to OS providers) // ------------------------------------------------------------------------- /** Returns JSON array of calendars discovered through the OS provider. */ calendarList(): string; /** * Returns JSON for events in the [start, end] window. Times are RFC3339; * `calendarIdsCsv` is an optional comma-separated filter. * * Each event carries `status` (`confirmed`|`tentative`|`canceled`|`none`, * from `EKEvent.status`) and `attendees` as objects (not bare names): * `{ name?, email?, status?, role?, is_current_user }` where `status` is * `accepted`|`declined`|`tentative`|`pending`|… (`EKParticipant.participantStatus`) * and `role` is `required`|`optional`|`chair`|`non_participant`|`unknown` — so a * consumer can tell a firm commitment from a tentative RSVP. */ calendarEvents( startRfc3339: string, endRfc3339: string, calendarIdsCsv?: string | null, ): string; /** * Create a calendar event. `inputJson` is JSON-encoded * `{ calendar_id, title, start, end, all_day?, notes?, location?, url? }` * with RFC3339 timestamps. Returns JSON-encoded EventMutationResult; its * embedded `event` carries the same enriched shape as `calendarEvents` * (attendee objects with RSVP status + event `status`). */ calendarCreateEvent(inputJson: string): string; /** * Update an existing event. `inputJson` is JSON-encoded * `{ event_id, title?, start?, end?, all_day?, notes?, location?, url? }`. * Absent fields leave existing values; empty string for * notes/location/url clears that field. Returns JSON-encoded * EventMutationResult. */ calendarUpdateEvent(inputJson: string): string; /** Delete an event by host-assigned id. Returns JSON-encoded EventMutationResult. */ calendarDeleteEvent(eventId: string): string; /** Returns JSON array of contact containers (sources). */ contactsContainers(): string; /** Returns JSON array of contacts matching `query`. */ contactsFind( query: string, limit?: number | null, containerIdsCsv?: string | null, ): string; /** Returns JSON array of mail accounts known to the OS provider. */ mailAccounts(): string; /** * Returns JSON inbox snapshot * `{ available, backend, reason?, summaries: InboxSummary[] }` — per-account * unread/total counts, not message rows. Use `mailMessages` for rows. * `accountIdsCsv` is an optional comma-separated filter; omit to query all * known accounts. */ mailInbox(accountIdsCsv?: string | null): string; /** * Enumerate every mailbox (folder) of the given accounts, nested ones * included on BOTH backends. Returns * `{ available, backend, reason?, mailboxes: Mailbox[] }` where `Mailbox` * is `{ account_id, name, full_name, unread, total }`. * * `full_name` is the selector to pass back as `MessageQuery.mailbox` — the * slash-joined path on macOS, the folder id on Microsoft Graph. Graph's * `/me/mailFolders` is root-only, so nested folders come from a bounded * `childFolders` walk (depth 8, at most 64 requests); a tree deeper or * wider than that is truncated. * * An `accountIdsCsv` that matches no account returns `available: false` * with a reason, not an empty list. */ mailMailboxes(accountIdsCsv?: string | null): string; /** * Read message rows, newest first. `queryJson` is a `MessageQuery`: * `{account_ids?: string[], mailbox?: string | null, limit?: number, * since?: string, include_body?: boolean}`. Every field defaults, and * `mailbox: null` means INBOX — so `"{}"` reproduces the pre-existing * INBOX-only read. * * "Newest first" is GLOBAL, not per account: rows from every matched * account are merged into one date-ordered list before `limit` applies, so * `limit: 1` across two accounts returns the newer message rather than * whichever account the backend listed first. * * Returns `{ available, backend, reason?, messages: MessageSummary[] }`; * each row carries a stable opaque `id` accepted by `mailMessageBody`, and * a `mailbox` holding the mailbox as the backend RESOLVED it (a query for * `"travel"` comes back stamped `"Travel/2026"`), so rows match * `mailMailboxes` output. An unresolvable mailbox or an unmatched * `account_ids` returns `available: false` with a reason, never an empty * list. */ mailMessages(queryJson: string): string; /** * Fetch one message body by the `id` from a `mailMessages` row. Returns * `{ available, backend, reason?, id, content_type, body, truncated }`; * bodies are cut at 100,000 characters with `truncated: true`. */ mailMessageBody(messageId: string): string; /** * Send mail. `sendRequestJson` is `{to, subject, body, ...}` per the * provider contract. Returns JSON `{ok, message_id?}`. */ mailSend(sendRequestJson: string): string; /** Returns JSON array of Messages.app services/accounts. */ messagesServices(): string; /** Returns JSON array of recent Messages.app chats. */ messagesChats(limit?: number | null): string; /** * Read Messages.app rows newest first. `queryJson` is * `{chat_ids?: string[], since?: string, limit?: number, * include_body?: boolean}`. Returns `{available, backend, reason?, messages}`; * an unreadable database is unavailable, not an empty conversation. */ messagesRead(queryJson: string): string; /** * Send a message through Messages.app. `sendRequestJson` is * `{recipient, body, service_id?}`. */ messagesSend(sendRequestJson: string): string; /** Returns JSON array of Notes.app accounts. */ notesAccounts(): string; /** Search Notes.app notes. */ notesFind(query: string, limit?: number | null): string; /** Returns JSON array of Reminders.app lists. */ remindersLists(): string; /** Returns JSON array of incomplete reminders. */ remindersItems(limit?: number | null): string; /** Returns JSON array of Photos.app albums. */ photosAlbums(): string; /** Returns JSON array of Safari bookmarks. */ bookmarksList(limit?: number | null): string; /** Returns JSON standard account-backed file locations. */ filesLocations(): string; /** Returns JSON OS keychain availability. */ keychainStatus(): string; // ------------------------------------------------------------------------- // Wearable / activity (HealthKit + Fitbit/Garmin/Oura/etc.) // ------------------------------------------------------------------------- /** Returns JSON `{available, reason?, providers?}`. */ healthStatus(): string; /** Times are RFC3339. Returns JSON array of sleep sessions. */ healthSleep(startRfc3339: string, endRfc3339: string): string; /** Times are RFC3339. Returns JSON array of workouts. */ healthWorkouts(startRfc3339: string, endRfc3339: string): string; /** Dates are YYYY-MM-DD. Returns JSON array of daily activity summaries. */ healthActivity(startYmd: string, endYmd: string): string; } // BEGIN GENERATED daemon wrappers: HostClient /** Host-authority daemon client; host-only methods never appear in CarRuntime's generated region. */ export class HostClient { constructor(runtime: CarRuntime); daemonCallHostManagement(method: string, paramsJson: string): Promise; /** Generated host wrapper for `agent_permissions.evaluate_tool`. */ agentPermissionsEvaluateTool(paramsJson: string): Promise; /** Generated host wrapper for `agent_permissions.reset`. */ agentPermissionsReset(paramsJson: string): Promise; /** Generated host wrapper for `agent_permissions.reset_tool`. */ agentPermissionsResetTool(paramsJson: string): Promise; /** Generated host wrapper for `agent_permissions.set`. */ agentPermissionsSet(paramsJson: string): Promise; /** Generated host wrapper for `agent_permissions.set_default`. */ agentPermissionsSetDefault(paramsJson: string): Promise; /** Generated host wrapper for `agent_permissions.set_tool`. */ agentPermissionsSetTool(paramsJson: string): Promise; /** Generated host wrapper for `agents.install`. */ agentsInstall(paramsJson: string): Promise; /** Generated host wrapper for `agents.remove`. */ agentsRemove(paramsJson: string): Promise; /** Generated host wrapper for `agents.upsert`. */ agentsUpsert(paramsJson: string): Promise; /** Generated host wrapper for `assistant.identity.set`. */ assistantIdentitySet(paramsJson: string): Promise; /** Generated host wrapper for `auth.accounts`. */ authAccounts(paramsJson: string): Promise; /** Generated host wrapper for `auth.authority_hint`. */ authAuthorityHint(paramsJson: string): Promise; /** Generated host wrapper for `auth.complete`. */ authComplete(paramsJson: string): Promise; /** Generated host wrapper for `auth.completion_status`. */ authCompletionStatus(paramsJson: string): Promise; /** Generated host wrapper for `auth.logout`. */ authLogout(paramsJson: string): Promise; /** Generated host wrapper for `auth.remove_account`. */ authRemoveAccount(paramsJson: string): Promise; /** Generated host wrapper for `auth.snapshot`. */ authSnapshot(paramsJson: string): Promise; /** Generated host wrapper for `auth.start`. */ authStart(paramsJson: string): Promise; /** Generated host wrapper for `auth.status`. */ authStatus(paramsJson: string): Promise; /** Generated host wrapper for `auth.switch_account`. */ authSwitchAccount(paramsJson: string): Promise; /** Generated host wrapper for `auth.switch_org`. */ authSwitchOrg(paramsJson: string): Promise; /** Generated host wrapper for `declagents.remove`. */ declagentsRemove(paramsJson: string): Promise; /** Generated host wrapper for `declagents.set_enabled`. */ declagentsSetEnabled(paramsJson: string): Promise; /** Generated host wrapper for `diagnostics.secret_store_activity`. */ diagnosticsSecretStoreActivity(paramsJson: string): Promise; /** Generated host wrapper for `messaging.config.get`. */ messagingConfigGet(paramsJson: string): Promise; /** Generated host wrapper for `messaging.config.set`. */ messagingConfigSet(paramsJson: string): Promise; /** Generated host wrapper for `messaging.pairing.start`. */ messagingPairingStart(paramsJson: string): Promise; /** Generated host wrapper for `messaging.pairing.status`. */ messagingPairingStatus(paramsJson: string): Promise; /** Generated host wrapper for `messaging.status`. */ messagingStatus(paramsJson: string): Promise; /** Generated host wrapper for `messaging.test_send`. */ messagingTestSend(paramsJson: string): Promise; /** Generated host wrapper for `models.adopt`. */ modelsAdopt(paramsJson: string): Promise; /** Generated host wrapper for `models.install`. */ modelsInstall(paramsJson: string): Promise; /** Generated host wrapper for `models.pull`. */ modelsPull(paramsJson: string): Promise; /** Generated host wrapper for `models.remove`. */ modelsRemove(paramsJson: string): Promise; /** Generated host wrapper for `models.resource_policy.set`. */ modelsResourcePolicySet(paramsJson: string): Promise; /** Generated host wrapper for `models.storage_roots`. */ modelsStorageRoots(paramsJson: string): Promise; /** Generated host wrapper for `openrouter.auth_cancel`. */ openrouterAuthCancel(paramsJson: string): Promise; /** Generated host wrapper for `openrouter.auth_start`. */ openrouterAuthStart(paramsJson: string): Promise; /** Generated host wrapper for `openrouter.disconnect`. */ openrouterDisconnect(paramsJson: string): Promise; /** Generated host wrapper for `openrouter.status`. */ openrouterStatus(paramsJson: string): Promise; /** Generated host wrapper for `permission.approve`. */ permissionApprove(paramsJson: string): Promise; /** Generated host wrapper for `permission.reject`. */ permissionReject(paramsJson: string): Promise; /** Generated host wrapper for `permission.set_tier`. */ permissionSetTier(paramsJson: string): Promise; /** Generated host wrapper for `session.clear_halt`. */ sessionClearHalt(paramsJson: string): Promise; /** Generated host wrapper for `tasks.schedule`. */ tasksSchedule(paramsJson: string): Promise; /** Generated host wrapper for `tasks.unschedule`. */ tasksUnschedule(paramsJson: string): Promise; } // END GENERATED daemon wrappers: HostClient // --------------------------------------------------------------------------- // Standalone functions // --------------------------------------------------------------------------- /** * Execute a proposal through a CarRuntime with a JS tool callback. * The callback receives * `{"tool":"name","params":{...},"action_id":"","request_id":"","timeout_ms":,"session_id":"|null","attempt":}` * * `attempt` is the engine's retry counter, 1-based — which retry you are * serving. (Correlate a specific in-flight call by `request_id` instead.) It * was hardcoded to 1 on the wire and dropped here before car#928. * * `session_id` is the daemon-stamped execution session (car#904) — the * attribution key for which mission a callback belongs to. Null when the * caller has no session. Prefer it over reconstructing attribution from * `action_id`, which is client-authored and not unique across concurrent or * retried attempts. * as a JSON string and must return a JSON string. `action_id` is the * originating `Action.id` from the proposal — useful for routing * when the same callback closes over multiple in-flight calls. * `request_id` is the daemon's callback-routing id, which a * `tools.cancel` notification repeats so the host can abort the right * in-flight call. `timeout_ms` is the action's declared budget in * milliseconds when the action declared one (`null` otherwise); the * host's tool runner may use it to bound its own work. Throwing an ordinary * value is an ordinary proposal-scoped failure; throw `TerminalToolError` to * request fail-stop session handling. * * `sessionId`, when provided, scopes per-action policy validation to * the named session opened via `CarRuntime.openSession()`. Global * policies still apply, plus the session's. Without a session id the * behavior matches the no-scope path bit-for-bit. See * `docs/proposals/per-session-policy-scoping.md`. * * `scopeJson`, when provided, is a serialized `RuntimeScope` — * `{ callerId?: string, tenantId?: string, claims?: Record }` * — attaching per-execution caller / tenant identity. When `tenantId` * is set, the runtime routes per-action state R/W through the * tenant-scoped view so distinct tenants can't observe each other's * keys (Parslee-ai/car#187 phase 3). Single-tenant in-process callers * pass `null` / omit and see no behaviour change. * * The returned JSON string is a serialized `ProposalResult`. An * `ActionResult` includes `rolled_back: true` when it succeeded before an * abort restored proposal state; false is omitted. Use this field, not the * human-readable warning in `error`, to detect rollback. */ export function executeProposal( rt: CarRuntime, proposalJson: string, toolFn: (callJson: string) => Promise, sessionId?: string | null, scopeJson?: string | null, ): Promise; /** * @deprecated Unsupported ABI-compatibility stub. This function always * rejects and never calls `onEvent`. Connect to `car-server` directly and use * the `infer_stream` JSON-RPC method plus `inference.stream.event` * notifications. See `docs/websocket-protocol.md`. */ export function inferStream( rt: CarRuntime, requestJson: string, onEvent: (eventJson: string) => void, ): Promise; // --- Caller-facing routing intent (parslee-ai/car-releases#18) --- /** * Coarse-grained task hint the adaptive router maps to its internal * `InferenceTask`. A closed set so adding a new task type is a * deliberate, FFI-visible change rather than a silent fallback. */ export type TaskHint = | 'chat' | 'classify' | 'summarize' | 'reasoning' | 'code' | 'extract'; /** * Hard model-capability filters the router enforces in addition to * any prompt-derived requirements. Mirrors `ModelCapability` in the * registry; values must be one of these snake_case strings. */ export type ModelCapabilityRequirement = | 'generate' | 'embed' | 'rerank' | 'classify' | 'code' | 'reasoning' | 'summarize' | 'tool_use' | 'multi_tool_call' | 'vision' | 'video_understanding' | 'audio_understanding' | 'grounding' | 'speech_to_text' | 'text_to_speech' | 'image_generation' | 'video_generation'; /** * Caller-facing routing intent — express requirements, not model IDs. * * All fields are optional. An IntentHint with no fields set is * equivalent to omitting the hint entirely (adaptive routing as today). * * @example * await rt.infer( * prompt, * null, * null, * JSON.stringify({ task: 'chat', prefer_local: true } satisfies IntentHint), * ); */ export interface IntentHint { /** What the caller is doing. Maps to `InferenceTask` server-side. */ task?: TaskHint; /** * Hard filter — every required capability must be present on the * candidate before scoring runs. */ require?: ModelCapabilityRequirement[]; /** * Bias the score profile toward local on-device models. Maps to a * dedicated `RoutingWorkload::LocalPreferred` weight profile — * quality-aware with a strong local_bonus so the hint wins ties. */ prefer_local?: boolean; /** * Bias the score profile aggressively toward time-to-first-token. * Maps to `RoutingWorkload::Fastest` — heavy latency weight, near-zero * quality and cost weight. Designed for the fast track in voice-turn * dispatch (sub-500ms first-audio target). Takes precedence over * `prefer_local` if both are set. */ prefer_fast?: boolean; /** * Bias the score profile toward the most capable model — quality * dominates, latency and cost near-floor (maps to * `RoutingWorkload::Quality`). For quality-critical, infrequent work * (building/verifying an agent, deriving a contract, structured * extraction) where a weak model fails. Precedence: `prefer_fast` wins, * then `prefer_quality`, then `prefer_local`. */ prefer_quality?: boolean; /** * The operation is high-stakes — consequential or irreversible (e.g. the * session is authorized for FullAccess actions). Forces the strongest * quality posture regardless of task or any cost/latency preference: never * economize on what you can't take back. Highest precedence — wins over * `prefer_fast`, `prefer_quality`, and `prefer_local`. The daemon sets this * automatically for FullAccess-granted sessions. */ high_stakes?: boolean; } // --- Voice streaming (stored-callback pattern) --- export type AudioSourceSpec = | { kind: 'mic' } | { kind: 'system' } | { kind: 'file'; path: string } | { kind: 'fifo'; path: string } | { kind: 'pcm_push'; sample_rate: number; channels?: 1 | 2 }; export interface TranscribeStreamOptions { model?: string; language?: string; prompt?: string; emit_audio_meta?: boolean; /** * Enable native streaming partials. Today only takes effect for * `mic` sources when the runtime was compiled with the `parakeet` * feature; the listener uses Parakeet TDT for transcription and * emits `partial` events per non-blank token before each canonical * `transcript` event. Without the feature or for non-Mic sources * this flag is silently ignored. */ streaming?: boolean; /** * Attach the prepared speaker diarizer to this session so * `transcript` events carry `role: "other:speaker_N"` rather than * `"unknown"`. Caller must `prepareDiarizer()` first. Silently * ignored if no diarizer has been prepared, or if the source isn't * `mic`. */ diarizer?: boolean; /** * Attach the enrollment-based speaker pipeline so segments matching * an enrolled voiceprint get `role: "enrolled_user"`. Pipeline is * built lazily from `~/.car/voiceprints/`. */ enrolled?: boolean; /** * Voice-context prompt overlay prepended to system prompts on the * voice-invoked inference path. Omit (or pass `null`) to use the * built-in default. An empty string disables the overlay (e.g. for * callers who already supply their own voice-tuned system prompt). */ voice_prompt_overlay?: string | null; /** * Streaming STT provider override. Currently only meaningful with * `pcm_push` sources. `'elevenlabs'` opens an ElevenLabs Realtime * websocket and forwards pushed PCM frames to it instead of running * the in-process VAD + batch STT pipeline. Requires * `ELEVENLABS_API_KEY` in env, config, or keychain. `'local'` is the * explicit form of the default behavior. Unrecognised values fail at * `transcribeStreamStart` time with a clear error. */ provider?: 'elevenlabs' | 'local'; } export type VoiceStreamEvent = | { type: 'speech_start' } | { type: 'speech_end' } | { type: 'transcript'; text: string; duration_ms: number; role: string } | { type: 'partial'; text: string; duration_ms: number } | { type: 'audio_chunk'; sample_rate: number; frame_count: number } | { type: 'barge_in' } | { type: 'enrollment_captured'; label: string; save_path: string } | { type: 'enrollment_failed'; reason: string } | { type: 'done' } | { type: 'error'; message: string }; export function registerVoiceEventHandler( onEvent: (sessionId: string, eventJson: string) => void, ): void; /** * Register the JS handler that serves daemon-initiated `agent.chat` * reverse-calls — the agent-chat surface. A supervised agent (running in * `--serve` mode, attached via `session.auth`) calls this once; the daemon * reverse-calls `agent.chat` for every host `agents.chat`, the bridge acks * `{accepted:true}` immediately, and fires this handler. * * `handlerFn(paramsJson)` receives `{"session_id":"...","prompt":"...", * "attachments":[...]?,"context":{...}?}` as a JSON string. Run one * conversational turn — keep a per-`session_id` message thread, run the * agent loop, and stream the reply back via `CarRuntime.chatEvent` — then * return. It is fire-and-forget (the ack already went back), so a rejected * Promise is logged, not surfaced to the host. Process-wide setter, * symmetric to `registerVoiceEventHandler`; pair with * `unregisterChatHandler` to clear. * * The handler may call any runtime method and should run the turn inline. * NAPI dispatches through a non-blocking `ThreadsafeFunction` and `chatEvent` * is async, so this side never had the reentrancy hazard that made the same * surface unusable from Python before Parslee-ai/car#905 — noted here because * the two bindings' handlers now carry the same contract for the same reason, * arrived at differently. */ export function registerChatHandler( handlerFn: (paramsJson: string) => void, ): void; /** * Clear the registered `agent.chat` handler. Subsequent reverse-calls are * refused so the daemon learns this agent is no longer conversational. */ export function unregisterChatHandler(): void; /** * Register the JS `tools.execute` handler for `submitProposal` * (Parslee-ai/car-releases#38). When the daemon dispatches a * proposal carrying host-owned tools, every tool routes through * this handler. * * `handlerFn(callJson)` receives * `{"tool":"name","params":{...},"action_id":"","request_id":"","timeout_ms":,"session_id":"|null","attempt":}` * * `attempt` is the engine's retry counter, 1-based — which retry you are * serving. (Correlate a specific in-flight call by `request_id` instead.) It * was hardcoded to 1 on the wire and dropped here before car#928. * * `session_id` is the daemon-stamped execution session (car#904) — the * attribution key for which mission a callback belongs to. Null when the * caller has no session. Prefer it over reconstructing attribution from * `action_id`, which is client-authored and not unique across concurrent or * retried attempts. * as a JSON string and MUST return a Promise resolving to the tool's * JSON-encoded result. Throwing an ordinary value rejects only the current * proposal. Throw `TerminalToolError` when retry cannot recover: CAR aborts * and rolls back the proposal, marks its failed action `terminal: true`, and * rejects later proposals on this daemon session until a host clears the halt * or the client reconnects. * * `request_id` is the daemon's callback-routing id, repeated by the * `tools.cancel` notification so the host can abort the right * in-flight call. `timeout_ms` is the action's declared budget in * milliseconds when the action declared one (`null` otherwise); the * host's tool runner may use it to bound its own work. * * `action_id` carries the originating `Action.id` from the * proposal so process-wide handlers can route concurrent * callbacks back to the right per-call closure. Empty string when * the daemon's `tools.execute` payload omits it (legacy daemons; * not expected on >=0.9.x). * * Process-wide setter — re-calling overwrites the previous * handler. Pair with `unregisterToolHandler` to clear. Symmetric * to `registerInferenceRunner` / `registerAgentRunner`: only one * handler can be active at a time. * * Required before `submitProposal`. `executeProposal` continues * to accept a per-call handler and does not use this registration. */ export function registerToolHandler( handlerFn: (callJson: string) => Promise, ): void; /** Distinguished fail-stop error for tool callbacks. */ export class TerminalToolError extends Error { constructor(message: string); } /** * Clear the registered `tools.execute` handler. `submitProposal` * calls after this will fail if the proposal carries any * host-tool actions. */ export function unregisterToolHandler(): void; /** * Register the callback fired when a tool callback is reaped * (Parslee-ai/car#264). When a `tools.execute` callback exceeds its budget the * daemon emits a `tools.cancel` notification; this callback receives the * reaped call's `requestId` (the same `request_id` surfaced on the originating * `tools.execute` call_json) so the host can abort the in-flight child it * registered under that id (e.g. `AbortController.abort()` / `child.kill()`). * * Fire-and-forget — no return value. Process-wide setter; re-calling * overwrites. Pair with `unregisterToolCancelHandler` to clear. */ export function registerToolCancelHandler( handlerFn: (requestId: string) => void, ): void; /** * Clear the registered `tools.cancel` handler. Subsequent reaps are no longer * routed to the host (the daemon has already abandoned the call regardless). */ export function unregisterToolCancelHandler(): void; export function transcribeStream( rt: CarRuntime, sessionId: string, audioSourceJson: string, optionsJson?: string | null, ): Promise; export function transcribeStreamStop(rt: CarRuntime, sessionId: string): Promise; export function transcribeStreamPush( rt: CarRuntime, sessionId: string, pcmFrame: Buffer, ): Promise; export function listVoiceSessions(rt: CarRuntime): string; /** * Start a streaming TTS synthesis. * * Stub: not exposed in the FFI bindings. Connect to the daemon's * WebSocket and use `voice.tts_stream.start`; chunks arrive as * `voice.event` notifications with `type = "tts_chunk"`. */ export function ttsStreamStart( rt: CarRuntime, streamId: string, text: string, optionsJson?: string | null, ): Promise; /** Cancel an in-flight TTS stream. Idempotent. */ export function ttsStreamCancel(rt: CarRuntime, streamId: string): Promise; /** List the ids of all in-flight TTS streams. */ export function listTtsStreams(rt: CarRuntime): string; // --- Voice turn dispatch (two-track sidecar pattern) --- export interface DispatchVoiceTurnRequest { /** Finalized utterance text (typically from STT). */ utterance: string; /** Optional voice session id this turn belongs to. */ session_id?: string | null; /** * Optional override for the voice-context overlay. * `null`/omitted uses the default; an empty string disables. */ config_overlay?: string | null; /** Optional sidecar wait timeout in milliseconds. Default 30000. */ sidecar_timeout_ms?: number | null; } export interface DispatchVoiceTurnResponse { turn_id: number; } export type VoiceTurnEvent = | { type: 'voice.turn.fast_delta'; turn_id: number; text: string } | { type: 'voice.turn.fast_done'; turn_id: number } | { type: 'voice.turn.bridge'; turn_id: number; kind: 'email' | 'calendar' | 'search' | 'unknown'; phrase: string; } | { type: 'voice.turn.sidecar'; turn_id: number; text: string } | { type: 'voice.turn.error'; turn_id: number; error: string } | { type: 'voice.turn.cancelled'; turn_id: number }; /** * Dispatch a voice-turn utterance through the two-track sidecar pattern. * * Returns `{"turn_id": N}` (JSON-encoded) synchronously. Subsequent * fast deltas, bridge phrases, sidecar results, errors, and * cancellations flow through the JS callback registered via * `registerVoiceEventHandler` as JSON-encoded `VoiceTurnEvent` objects. * The host plays audio (or otherwise renders) from those events — * CAR does NOT own the speaker on this path. * * Not available in Daemon mode (no in-process inference engine); * connect to `ws://127.0.0.1:9100/` for the WebSocket flow there. */ export function dispatchVoiceTurn(rt: CarRuntime, requestJson: string): Promise; /** Cancel the in-flight voice turn (if any). Idempotent. */ export function cancelVoiceTurn(rt: CarRuntime): Promise; /** * Issue a 1-token probe with `prefer_fast: true` so the fast model is * loaded into memory before the first user turn. Best-effort and * idempotent — call at app startup. * * Not available in Daemon mode. */ export function prewarmVoiceTurn(rt: CarRuntime): Promise; /** * Voice providers (STT + TTS) compiled into this build. * * Returns a JSON-encoded array of objects with shape: * `{ id: string, kind: "stt" | "tts", available: boolean, description: string }`. * * `available` reflects build-time presence (cfg-target, build features) — * runtime readiness (API key set, permission granted, model downloaded) * surfaces via per-provider error paths when you actually use them. * * Stateless; safe to call before constructing a `CarRuntime`. */ export function listVoiceProviders(): string; // --- Meeting capture --- export interface StartMeetingRequest { id?: string; sources: Array<'mic' | 'system'>; title?: string; model?: string; language?: string; persist_audio?: boolean; root?: string; /** * Enable native streaming partials on the mic source. Effective * only when the runtime was built with `--features parakeet`; * silently ignored otherwise. `transcript` events still arrive at * segment end — `partial` events are emitted incrementally per * non-blank token in between. */ streaming?: boolean; /** * Attach the prepared diarizer to the mic source so transcripts * carry per-speaker roles. Call `prepareDiarizer()` first. */ diarizer?: boolean; /** * Attach the enrollment-based pipeline so segments matching an * enrolled voiceprint get `role: "enrolled_user"`. */ enrolled?: boolean; } /** Eagerly download + load the Parakeet TDT model (~600 MB). Idempotent. */ export function prepareParakeet(rt: CarRuntime): Promise; /** Eagerly download + load the speaker diarizer (~28 MB). Idempotent. */ export function prepareDiarizer(rt: CarRuntime): Promise; /** * Enroll a speaker. `audioJson` shape: * - `{"kind":"wav","path":"/abs/path.wav"}` — decoded via hound * - `{"kind":"pcm","sample_rate":48000,"channels":1,"data_b64":""}` * * Saves to `~/.car/voiceprints/