car-runtime 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.d.ts +199 -2
  2. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -49,9 +49,30 @@ export class CarRuntime {
49
49
  /** Register CAR's built-in agent utility tools. */
50
50
  registerAgentBasics(): Promise<void>;
51
51
 
52
+ /**
53
+ * Open a policy-scoping session and return its opaque id. Hosts
54
+ * that drive multiple concurrent agent contexts through one
55
+ * CarRuntime (IDE per-project rules, multi-tenant servers) call
56
+ * this once per context, then pass the id to subsequent
57
+ * `registerPolicy` and `executeProposal` calls so per-context rules
58
+ * stack on top of any global ones. Embedded only.
59
+ * See `docs/proposals/per-session-policy-scoping.md`.
60
+ */
61
+ openSession(): Promise<string>;
62
+
63
+ /**
64
+ * Close a session and drop every policy scoped to it. Returns true
65
+ * if a session by that id existed, false if it didn't (already
66
+ * closed, never opened).
67
+ */
68
+ closeSession(sessionId: string): Promise<boolean>;
69
+
52
70
  /**
53
71
  * Register a policy enforced in Rust on every action.
54
- * `rule` is one of: "deny_tool", "deny_tool_param", "require_state".
72
+ * `rule` is one of: "deny_tool", "deny_tool_param", "require_state",
73
+ * "deny_tool_callback".
74
+ * `sessionId`, when set, scopes the policy to the named session
75
+ * (opened via `openSession`). Without it, the policy is global.
55
76
  */
56
77
  registerPolicy(
57
78
  name: string,
@@ -60,6 +81,7 @@ export class CarRuntime {
60
81
  key?: string | null,
61
82
  pattern?: string | null,
62
83
  valueJson?: string | null,
84
+ sessionId?: string | null,
63
85
  ): Promise<void>;
64
86
 
65
87
  /**
@@ -339,6 +361,15 @@ export class CarRuntime {
339
361
  /** Count of events in this runtime's execution log. */
340
362
  eventCount(): Promise<number>;
341
363
 
364
+ /** Execution log counts and approximate retained native bytes. Returns JSON. */
365
+ eventLogStats(): Promise<string>;
366
+
367
+ /** Keep only the newest events/spans in this runtime's execution log. Returns JSON. */
368
+ truncateEventLog(maxEvents?: number | null, maxSpans?: number | null): Promise<string>;
369
+
370
+ /** Clear this runtime's execution log. Returns JSON. */
371
+ clearEventLog(): Promise<string>;
372
+
342
373
  /** Verify a proposal against this runtime's state + tools. Returns JSON. */
343
374
  verifyProposal(proposalJson: string): Promise<string>;
344
375
 
@@ -460,7 +491,7 @@ export class CarRuntime {
460
491
  accountsOpen(accountId?: string | null): string;
461
492
 
462
493
  // -------------------------------------------------------------------------
463
- // Calendar / Contacts / Mail integrations (delegated to OS providers)
494
+ // Calendar / Contacts / Mail / Messages integrations (delegated to OS providers)
464
495
  // -------------------------------------------------------------------------
465
496
 
466
497
  /** Returns JSON array of calendars discovered through the OS provider. */
@@ -501,6 +532,42 @@ export class CarRuntime {
501
532
  */
502
533
  mailSend(sendRequestJson: string): string;
503
534
 
535
+ /** Returns JSON array of Messages.app services/accounts. */
536
+ messagesServices(): string;
537
+
538
+ /** Returns JSON array of recent Messages.app chats. */
539
+ messagesChats(limit?: number | null): string;
540
+
541
+ /**
542
+ * Send a message through Messages.app. `sendRequestJson` is
543
+ * `{recipient, body, service_id?}`.
544
+ */
545
+ messagesSend(sendRequestJson: string): string;
546
+
547
+ /** Returns JSON array of Notes.app accounts. */
548
+ notesAccounts(): string;
549
+
550
+ /** Search Notes.app notes. */
551
+ notesFind(query: string, limit?: number | null): string;
552
+
553
+ /** Returns JSON array of Reminders.app lists. */
554
+ remindersLists(): string;
555
+
556
+ /** Returns JSON array of incomplete reminders. */
557
+ remindersItems(limit?: number | null): string;
558
+
559
+ /** Returns JSON array of Photos.app albums. */
560
+ photosAlbums(): string;
561
+
562
+ /** Returns JSON array of Safari bookmarks. */
563
+ bookmarksList(limit?: number | null): string;
564
+
565
+ /** Returns JSON standard account-backed file locations. */
566
+ filesLocations(): string;
567
+
568
+ /** Returns JSON OS keychain availability. */
569
+ keychainStatus(): string;
570
+
504
571
  // -------------------------------------------------------------------------
505
572
  // Wearable / activity (HealthKit + Fitbit/Garmin/Oura/etc.)
506
573
  // -------------------------------------------------------------------------
@@ -526,11 +593,18 @@ export class CarRuntime {
526
593
  * Execute a proposal through a CarRuntime with a JS tool callback.
527
594
  * The callback receives `{"tool":"name","params":{...}}` as a JSON string
528
595
  * and must return a JSON string.
596
+ *
597
+ * `sessionId`, when provided, scopes per-action policy validation to
598
+ * the named session opened via `CarRuntime.openSession()`. Global
599
+ * policies still apply, plus the session's. Without a session id the
600
+ * behavior matches the no-scope path bit-for-bit. See
601
+ * `docs/proposals/per-session-policy-scoping.md`.
529
602
  */
530
603
  export function executeProposal(
531
604
  rt: CarRuntime,
532
605
  proposalJson: string,
533
606
  toolFn: (callJson: string) => Promise<string>,
607
+ sessionId?: string | null,
534
608
  ): Promise<string>;
535
609
 
536
610
  /**
@@ -622,6 +696,14 @@ export interface IntentHint {
622
696
  * quality-aware with a strong local_bonus so the hint wins ties.
623
697
  */
624
698
  prefer_local?: boolean;
699
+ /**
700
+ * Bias the score profile aggressively toward time-to-first-token.
701
+ * Maps to `RoutingWorkload::Fastest` — heavy latency weight, near-zero
702
+ * quality and cost weight. Designed for the fast track in voice-turn
703
+ * dispatch (sub-500ms first-audio target). Takes precedence over
704
+ * `prefer_local` if both are set.
705
+ */
706
+ prefer_fast?: boolean;
625
707
  }
626
708
 
627
709
  // --- Voice streaming (stored-callback pattern) ---
@@ -661,6 +743,23 @@ export interface TranscribeStreamOptions {
661
743
  * built lazily from `~/.car/voiceprints/`.
662
744
  */
663
745
  enrolled?: boolean;
746
+ /**
747
+ * Voice-context prompt overlay prepended to system prompts on the
748
+ * voice-invoked inference path. Omit (or pass `null`) to use the
749
+ * built-in default. An empty string disables the overlay (e.g. for
750
+ * callers who already supply their own voice-tuned system prompt).
751
+ */
752
+ voice_prompt_overlay?: string | null;
753
+ /**
754
+ * Streaming STT provider override. Currently only meaningful with
755
+ * `pcm_push` sources. `'elevenlabs'` opens an ElevenLabs Realtime
756
+ * websocket and forwards pushed PCM frames to it instead of running
757
+ * the in-process VAD + batch STT pipeline. Requires
758
+ * `ELEVENLABS_API_KEY` in env, config, or keychain. `'local'` is the
759
+ * explicit form of the default behavior. Unrecognised values fail at
760
+ * `transcribeStreamStart` time with a clear error.
761
+ */
762
+ provider?: 'elevenlabs' | 'local';
664
763
  }
665
764
 
666
765
  export type VoiceStreamEvent =
@@ -696,6 +795,66 @@ export function transcribeStreamPush(
696
795
 
697
796
  export function listVoiceSessions(rt: CarRuntime): string;
698
797
 
798
+ // --- Voice turn dispatch (two-track sidecar pattern) ---
799
+
800
+ export interface DispatchVoiceTurnRequest {
801
+ /** Finalized utterance text (typically from STT). */
802
+ utterance: string;
803
+ /** Optional voice session id this turn belongs to. */
804
+ session_id?: string | null;
805
+ /**
806
+ * Optional override for the voice-context overlay.
807
+ * `null`/omitted uses the default; an empty string disables.
808
+ */
809
+ config_overlay?: string | null;
810
+ /** Optional sidecar wait timeout in milliseconds. Default 30000. */
811
+ sidecar_timeout_ms?: number | null;
812
+ }
813
+
814
+ export interface DispatchVoiceTurnResponse {
815
+ turn_id: number;
816
+ }
817
+
818
+ export type VoiceTurnEvent =
819
+ | { type: 'voice.turn.fast_delta'; turn_id: number; text: string }
820
+ | { type: 'voice.turn.fast_done'; turn_id: number }
821
+ | {
822
+ type: 'voice.turn.bridge';
823
+ turn_id: number;
824
+ kind: 'email' | 'calendar' | 'search' | 'unknown';
825
+ phrase: string;
826
+ }
827
+ | { type: 'voice.turn.sidecar'; turn_id: number; text: string }
828
+ | { type: 'voice.turn.error'; turn_id: number; error: string }
829
+ | { type: 'voice.turn.cancelled'; turn_id: number };
830
+
831
+ /**
832
+ * Dispatch a voice-turn utterance through the two-track sidecar pattern.
833
+ *
834
+ * Returns `{"turn_id": N}` (JSON-encoded) synchronously. Subsequent
835
+ * fast deltas, bridge phrases, sidecar results, errors, and
836
+ * cancellations flow through the JS callback registered via
837
+ * `registerVoiceEventHandler` as JSON-encoded `VoiceTurnEvent` objects.
838
+ * The host plays audio (or otherwise renders) from those events —
839
+ * CAR does NOT own the speaker on this path.
840
+ *
841
+ * Not available in Daemon mode (no in-process inference engine);
842
+ * connect to `ws://127.0.0.1:9100/` for the WebSocket flow there.
843
+ */
844
+ export function dispatchVoiceTurn(rt: CarRuntime, requestJson: string): Promise<string>;
845
+
846
+ /** Cancel the in-flight voice turn (if any). Idempotent. */
847
+ export function cancelVoiceTurn(rt: CarRuntime): Promise<void>;
848
+
849
+ /**
850
+ * Issue a 1-token probe with `prefer_fast: true` so the fast model is
851
+ * loaded into memory before the first user turn. Best-effort and
852
+ * idempotent — call at app startup.
853
+ *
854
+ * Not available in Daemon mode.
855
+ */
856
+ export function prewarmVoiceTurn(rt: CarRuntime): Promise<void>;
857
+
699
858
  /**
700
859
  * Voice providers (STT + TTS) compiled into this build.
701
860
  *
@@ -928,6 +1087,44 @@ export function registerAgentRunner(
928
1087
  agentFn: (specJson: string, taskJson: string) => Promise<string>,
929
1088
  ): Promise<void>;
930
1089
 
1090
+ /**
1091
+ * Register the inference runner callback. Closes
1092
+ * Parslee-ai/car-releases#24 — when a model schema declares
1093
+ * `source: { type: "delegated", ... }`, CAR routes the request through
1094
+ * this callback. The host owns the wire format (Anthropic, OpenAI,
1095
+ * Vercel AI SDK, GitHub Models, etc.); CAR observes events and stays
1096
+ * in the policy / replay path.
1097
+ *
1098
+ * The runner emits stream events for every chunk it receives from its
1099
+ * provider via `inferenceRunnerEmitEvent(callId, eventJson)`, then
1100
+ * resolves the promise with the final aggregated result JSON
1101
+ * (`{text: string, tool_calls: ToolCall[]}`).
1102
+ *
1103
+ * Idempotent — re-calling overwrites the previous runner. Only one
1104
+ * runner can be registered per process (matches `registerAgentRunner`).
1105
+ *
1106
+ * Event JSON shapes match `inferStream`'s event taxonomy:
1107
+ * `{type: "text", data: string}`
1108
+ * `{type: "tool_start", name: string, index: number, id?: string}`
1109
+ * `{type: "tool_delta", index: number, data: string}`
1110
+ * `{type: "usage", input_tokens: number, output_tokens: number}`
1111
+ * `{type: "done", text: string, tool_calls: ToolCall[]}`
1112
+ */
1113
+ export function registerInferenceRunner(
1114
+ runnerFn: (requestJson: string, callId: string) => Promise<string>,
1115
+ ): void;
1116
+
1117
+ /**
1118
+ * Emit a stream event from inside the inference runner callback.
1119
+ * `callId` is the second argument the runner received; `eventJson`
1120
+ * is one of the shapes documented on `registerInferenceRunner`.
1121
+ *
1122
+ * Silently no-ops if `callId` is unknown (call already completed or
1123
+ * the runner emitted after returning) — racing the normal completion
1124
+ * path shouldn't error.
1125
+ */
1126
+ export function inferenceRunnerEmitEvent(callId: string, eventJson: string): void;
1127
+
931
1128
  /** Run a Swarm pattern. `mode` is "parallel", "sequential", or "debate". */
932
1129
  export function runSwarm(
933
1130
  mode: string,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "car-runtime",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Common Agent Runtime — a deterministic execution layer for AI agents",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",