@lunora/svelte 1.0.0-alpha.272 → 1.0.0-alpha.274

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { FunctionReference, ArgsOf, ActionCallOptions, ReturnOf, LunoraClient, SubscriptionErrorCallback, User, ConnectionStatus, Preloaded, LiveStreamSubscribeError, LiveTopicRef, LiveTopicOptions, MutationCallOptions, MutatorHandle, SubscriptionError } from '@lunora/client';
1
+ import { FunctionReference, ArgsOf, ActionCallOptions, ReturnOf, LunoraClient, SubscriptionErrorCallback, User, ConnectionStatus, Preloaded, LiveStreamSubscribeError, LiveTopicRef, LiveTopicOptions, MutationCallOptions, OnlineOnlyOption, MutatorHandle, SubscriptionError } from '@lunora/client';
2
2
  export type { ArgsOf, ConnectionStatus, FunctionReference, LunoraClient, MutationCallOptions, MutatorHandle, MutatorTransaction, Preloaded, ReturnOf } from '@lunora/client';
3
3
  import { Readable } from 'svelte/store';
4
4
  import { AuthStatus } from '@lunora/client/auth';
@@ -173,8 +173,8 @@ interface AgentChatMessage {
173
173
  optimistic?: boolean;
174
174
  role: "assistant" | "system" | "tool" | "user";
175
175
  seq: number;
176
- /** Approval lifecycle marker on a human-in-the-loop tool message. */
177
- status?: "approved" | "awaiting_approval" | "rejected";
176
+ /** Approval or secret-request lifecycle marker on a human-in-the-loop tool message. */
177
+ status?: "approved" | "awaiting_approval" | "awaiting_secret" | "rejected";
178
178
  toolCallId?: string;
179
179
  toolCalls?: ReadonlyArray<{
180
180
  id: string;
@@ -228,7 +228,7 @@ type AgentMessagesReference$1 = FunctionReference<"query", {
228
228
  }, ReadonlyArray<Record<string, unknown>>>;
229
229
  /** The `agents:agentResolveApproval` reference — resolves a human-in-the-loop tool approval. */
230
230
  type AgentApprovalReference = FunctionReference<"mutation", {
231
- decision: "approve" | "reject";
231
+ decision: "approve" | "approve_for_thread" | "reject";
232
232
  instanceId: string;
233
233
  note?: string;
234
234
  threadKey: string;
@@ -236,10 +236,41 @@ type AgentApprovalReference = FunctionReference<"mutation", {
236
236
  }, {
237
237
  resolved: boolean;
238
238
  }>;
239
+ /** The `agents:agentSupplySecret` reference — stores a person's value for a paused `requestSecretTool` call. */
240
+ type AgentSupplySecretReference = FunctionReference<"mutation", {
241
+ secret: string;
242
+ threadKey: string;
243
+ toolCallId: string;
244
+ }, {
245
+ resolved: boolean;
246
+ }>;
247
+ /** The `agents:agentDeclineSecret` reference — refuses a paused `requestSecretTool` call. */
248
+ type AgentDeclineSecretReference = FunctionReference<"mutation", {
249
+ threadKey: string;
250
+ toolCallId: string;
251
+ }, {
252
+ resolved: boolean;
253
+ }>;
239
254
  /** The `agents:agentThread` reference — live thread status + in-flight `instanceId`. */
240
255
  type AgentThreadReference = FunctionReference<"query", {
241
256
  key: string;
242
257
  }, Record<string, unknown> | undefined>;
258
+ /** A tool approved for the rest of a thread, as `agents:agentApprovalGrants` lists it. */
259
+ interface AgentApprovalGrant {
260
+ createdAt: number;
261
+ toolName: string;
262
+ }
263
+ /** The `agents:agentApprovalGrants` reference — live thread-scoped approval grants. */
264
+ type AgentApprovalGrantsReference = FunctionReference<"query", {
265
+ key: string;
266
+ }, ReadonlyArray<AgentApprovalGrant>>;
267
+ /** The `agents:agentRevokeApprovalGrant` reference — removes a thread-scoped approval grant. */
268
+ type AgentRevokeApprovalGrantReference = FunctionReference<"mutation", {
269
+ threadKey: string;
270
+ toolName: string;
271
+ }, {
272
+ revoked: boolean;
273
+ }>;
243
274
  /**
244
275
  * An app stream reference that tees the agent's in-flight live events, keyed by
245
276
  * thread. Carries token deltas and — since `ctx.reportProgress` rides the same
@@ -254,8 +285,12 @@ type AgentTokenStreamReference = FunctionReference<"stream", {
254
285
  */
255
286
  interface AgentChatApi {
256
287
  agents: {
288
+ agentApprovalGrants: AgentApprovalGrantsReference;
289
+ agentDeclineSecret: AgentDeclineSecretReference;
257
290
  agentMessages: AgentMessagesReference$1;
258
291
  agentResolveApproval: AgentApprovalReference;
292
+ agentRevokeApprovalGrant: AgentRevokeApprovalGrantReference;
293
+ agentSupplySecret: AgentSupplySecretReference;
259
294
  agentThread: AgentThreadReference;
260
295
  };
261
296
  }
@@ -272,7 +307,7 @@ interface AgentChatOptions {
272
307
  /** History depth forwarded to `agents:agentMessages`. */
273
308
  limit?: number;
274
309
  /**
275
- * Called when the live history or thread subscription reports an error (a
310
+ * Called when the live history, thread, or grants subscription reports an error (a
276
311
  * session expiry, an RLS denial). Without it such an error is dropped and
277
312
  * `messages` / `status` freeze at their last value — unlike the React, Angular,
278
313
  * Solid and Vue ports, this one leaves the value store untouched on error.
@@ -296,17 +331,28 @@ interface AgentChatOptions {
296
331
  threadKey: string;
297
332
  }
298
333
  interface AgentChatHandle {
334
+ /** The tools approved for the rest of this thread, live. Read with `$approvalGrants`. */
335
+ approvalGrants: Readable<ReadonlyArray<AgentApprovalGrant>>;
299
336
  /** Approve a paused human-in-the-loop tool call (optionally with a note). */
300
337
  approve: (toolCallId: string, note?: string) => Promise<void>;
338
+ /**
339
+ * Approve a paused tool call and grant that tool for the rest of the thread, so
340
+ * later calls to it run without pausing. Undo with {@link AgentChatHandle.revokeGrant}.
341
+ */
342
+ approveForThread: (toolCallId: string, note?: string) => Promise<void>;
301
343
  /**
302
344
  * Terminate the in-flight run and mark its thread `"cancelled"`. Resolves as a
303
345
  * no-op when no `cancel` mutation was supplied or no run is in flight.
304
346
  */
305
347
  cancel: () => Promise<void>;
348
+ /** Refuse a paused `requestSecretTool` call: the run resumes with a "declined" result. */
349
+ declineSecret: (toolCallId: string) => Promise<void>;
306
350
  /** Durable thread history (oldest first) plus any un-acknowledged optimistic user turns. Read with `$messages`. */
307
351
  messages: Readable<ReadonlyArray<AgentChatMessage>>;
308
352
  /** Reject a paused human-in-the-loop tool call (optionally with a reason). */
309
353
  reject: (toolCallId: string, note?: string) => Promise<void>;
354
+ /** Remove a thread-scoped approval grant so the tool's gate applies again to later calls. */
355
+ revokeGrant: (toolName: string) => Promise<void>;
310
356
  /** Start (or continue) a run with a user message; extra args merge over `sendArgs`. Appends an optimistic user turn. */
311
357
  send: (input: string, args?: Record<string, unknown>) => Promise<void>;
312
358
  /** The live thread status, or `undefined` before the thread exists. Read with `$status`. */
@@ -319,14 +365,21 @@ interface AgentChatHandle {
319
365
  */
320
366
  streamingText: Readable<string>;
321
367
  /**
322
- * Stop the live history + thread subscriptions (and the token stream, if any).
368
+ * Give a paused `requestSecretTool` call its value. Always sent online-only: the
369
+ * value is never queued, persisted or replayed, and the call rejects with
370
+ * `OFFLINE_NOT_QUEUED` while the connection is down. The handle keeps no copy;
371
+ * a failure rethrows the original error.
372
+ */
373
+ supplySecret: (toolCallId: string, secret: string) => Promise<void>;
374
+ /**
375
+ * Stop the live history, thread, and grants subscriptions (and the token stream, if any).
323
376
  * Call in `onDestroy` (`onDestroy(handle.teardown)`).
324
377
  */
325
378
  teardown: () => void;
326
379
  }
327
380
  /**
328
381
  * A first-class agent chat surface: live durable history + in-flight token
329
- * streaming + the send / approve / reject / cancel writes, keyed by `threadKey` —
382
+ * streaming + the send / approve / reject / secret / cancel writes, keyed by `threadKey` —
330
383
  * the Svelte counterpart to React's `useAgentChat`, re-expressed as stores you
331
384
  * read with `$`.
332
385
  *
@@ -431,7 +484,7 @@ interface AgentToolEventsOptions {
431
484
  * Optional live event stream — the same app stream function `agentChat` uses.
432
485
  * When supplied, ephemeral `ctx.reportProgress(...)` events for the thread are
433
486
  * surfaced as `{ type: "progress" }` entries; when omitted only the durable
434
- * lifecycle (call / result / awaiting-approval) is returned.
487
+ * lifecycle (call / result / awaiting-approval / awaiting-secret) is returned.
435
488
  */
436
489
  stream?: AgentLiveStreamReference;
437
490
  /** The thread whose tool activity to observe. */
@@ -439,7 +492,7 @@ interface AgentToolEventsOptions {
439
492
  }
440
493
  /**
441
494
  * A single tool-lifecycle event for a thread. The durable arms
442
- * (`call`/`result`/`awaiting-approval`) are derived from `agents:agentMessages`
495
+ * (`call`/`result`/`awaiting-approval`/`awaiting-secret`) are derived from `agents:agentMessages`
443
496
  * and carry the persisted `seq`; the ephemeral `progress` arm comes live off the
444
497
  * stream and has no `seq`. Discriminate on `type`.
445
498
  */
@@ -465,6 +518,11 @@ type AgentToolEvent = {
465
518
  toolCallId?: string;
466
519
  toolName?: string;
467
520
  type: "awaiting-approval";
521
+ } | {
522
+ seq: number;
523
+ toolCallId?: string;
524
+ toolName?: string;
525
+ type: "awaiting-secret";
468
526
  };
469
527
  interface AgentToolEventsHandle {
470
528
  /**
@@ -725,7 +783,7 @@ interface MutationHandle<F extends FunctionReference> {
725
783
  * `options` are applied and rolled back by the client against the live query
726
784
  * subscriptions, exactly as in the React adapter.
727
785
  */
728
- mutate: (args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>;
786
+ mutate: (args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>> & OnlineOnlyOption<F>) => Promise<ReturnOf<F>>;
729
787
  /**
730
788
  * `true` while any invocation from this handle is in flight. Ref-counted, so
731
789
  * overlapping calls compose and it only flips back to `false` once the last
@@ -1267,7 +1325,7 @@ interface VoiceAgentHandle {
1267
1325
  */
1268
1326
  declare function voiceAgent(options: VoiceAgentOptions): VoiceAgentHandle;
1269
1327
  declare function voiceAgent(client: LunoraClient, options: VoiceAgentOptions): VoiceAgentHandle;
1270
- export { type ActionHandle, type AgentApi, type AgentChatApi, type AgentChatHandle, type AgentChatMessage, type AgentChatOptions, type AgentHandle, type AgentLiveEvent, type AgentOptions, type AgentProgressEvent, type AgentStateApi, type AgentStateHandle, type AgentStateOptions, type AgentThreadRecord, type AgentThreadStatus, type AgentTokenDelta, type AgentToolEvent, type AgentToolEventsApi, type AgentToolEventsHandle, type AgentToolEventsOptions, type AuthGateStore, type AuthStore, type ConnectionStatusStore, type FlagValue, type HeartbeatReference, type InfiniteQueryHandle, type InfiniteQueryOptions, type ListPresentReference, type LiveTopicState, type MutationHandle, type MutatorHandleStore, type PageItemOf, type PaginatedArgs, type PaginatedQueryHandle, type PaginatedQueryOptions, type PresenceHandle, type PresenceOptions, type QueryStore, type QueryStoreOptions, type RateLimitHandle, type RateLimitOptions, type ReactiveArgs, type ReactivePaginatedArgs, type StreamHandle, type StreamStatus, type StreamStoreOptions, type SubscriptionHandle, type SubscriptionStoreOptions, type VoiceAgentHandle, type VoiceAgentOptions, type VoiceAudioFormat, type VoiceReference, type VoiceStatus, action, agent, agentChat, agentState, agentToolEvents, auth, authGate, connectionStatus, flag, flags,
1328
+ export { type ActionHandle, type AgentApi, type AgentApprovalGrant, type AgentChatApi, type AgentChatHandle, type AgentChatMessage, type AgentChatOptions, type AgentHandle, type AgentLiveEvent, type AgentOptions, type AgentProgressEvent, type AgentStateApi, type AgentStateHandle, type AgentStateOptions, type AgentThreadRecord, type AgentThreadStatus, type AgentTokenDelta, type AgentToolEvent, type AgentToolEventsApi, type AgentToolEventsHandle, type AgentToolEventsOptions, type AuthGateStore, type AuthStore, type ConnectionStatusStore, type FlagValue, type HeartbeatReference, type InfiniteQueryHandle, type InfiniteQueryOptions, type ListPresentReference, type LiveTopicState, type MutationHandle, type MutatorHandleStore, type PageItemOf, type PaginatedArgs, type PaginatedQueryHandle, type PaginatedQueryOptions, type PresenceHandle, type PresenceOptions, type QueryStore, type QueryStoreOptions, type RateLimitHandle, type RateLimitOptions, type ReactiveArgs, type ReactivePaginatedArgs, type StreamHandle, type StreamStatus, type StreamStoreOptions, type SubscriptionHandle, type SubscriptionStoreOptions, type VoiceAgentHandle, type VoiceAgentOptions, type VoiceAudioFormat, type VoiceReference, type VoiceStatus, action, agent, agentChat, agentState, agentToolEvents, auth, authGate, connectionStatus, flag, flags,
1271
1329
  /**
1272
1330
  * Svelte adapter for Lunora (`@lunora/svelte`).
1273
1331
  *
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { FunctionReference, ArgsOf, ActionCallOptions, ReturnOf, LunoraClient, SubscriptionErrorCallback, User, ConnectionStatus, Preloaded, LiveStreamSubscribeError, LiveTopicRef, LiveTopicOptions, MutationCallOptions, MutatorHandle, SubscriptionError } from '@lunora/client';
1
+ import { FunctionReference, ArgsOf, ActionCallOptions, ReturnOf, LunoraClient, SubscriptionErrorCallback, User, ConnectionStatus, Preloaded, LiveStreamSubscribeError, LiveTopicRef, LiveTopicOptions, MutationCallOptions, OnlineOnlyOption, MutatorHandle, SubscriptionError } from '@lunora/client';
2
2
  export type { ArgsOf, ConnectionStatus, FunctionReference, LunoraClient, MutationCallOptions, MutatorHandle, MutatorTransaction, Preloaded, ReturnOf } from '@lunora/client';
3
3
  import { Readable } from 'svelte/store';
4
4
  import { AuthStatus } from '@lunora/client/auth';
@@ -173,8 +173,8 @@ interface AgentChatMessage {
173
173
  optimistic?: boolean;
174
174
  role: "assistant" | "system" | "tool" | "user";
175
175
  seq: number;
176
- /** Approval lifecycle marker on a human-in-the-loop tool message. */
177
- status?: "approved" | "awaiting_approval" | "rejected";
176
+ /** Approval or secret-request lifecycle marker on a human-in-the-loop tool message. */
177
+ status?: "approved" | "awaiting_approval" | "awaiting_secret" | "rejected";
178
178
  toolCallId?: string;
179
179
  toolCalls?: ReadonlyArray<{
180
180
  id: string;
@@ -228,7 +228,7 @@ type AgentMessagesReference$1 = FunctionReference<"query", {
228
228
  }, ReadonlyArray<Record<string, unknown>>>;
229
229
  /** The `agents:agentResolveApproval` reference — resolves a human-in-the-loop tool approval. */
230
230
  type AgentApprovalReference = FunctionReference<"mutation", {
231
- decision: "approve" | "reject";
231
+ decision: "approve" | "approve_for_thread" | "reject";
232
232
  instanceId: string;
233
233
  note?: string;
234
234
  threadKey: string;
@@ -236,10 +236,41 @@ type AgentApprovalReference = FunctionReference<"mutation", {
236
236
  }, {
237
237
  resolved: boolean;
238
238
  }>;
239
+ /** The `agents:agentSupplySecret` reference — stores a person's value for a paused `requestSecretTool` call. */
240
+ type AgentSupplySecretReference = FunctionReference<"mutation", {
241
+ secret: string;
242
+ threadKey: string;
243
+ toolCallId: string;
244
+ }, {
245
+ resolved: boolean;
246
+ }>;
247
+ /** The `agents:agentDeclineSecret` reference — refuses a paused `requestSecretTool` call. */
248
+ type AgentDeclineSecretReference = FunctionReference<"mutation", {
249
+ threadKey: string;
250
+ toolCallId: string;
251
+ }, {
252
+ resolved: boolean;
253
+ }>;
239
254
  /** The `agents:agentThread` reference — live thread status + in-flight `instanceId`. */
240
255
  type AgentThreadReference = FunctionReference<"query", {
241
256
  key: string;
242
257
  }, Record<string, unknown> | undefined>;
258
+ /** A tool approved for the rest of a thread, as `agents:agentApprovalGrants` lists it. */
259
+ interface AgentApprovalGrant {
260
+ createdAt: number;
261
+ toolName: string;
262
+ }
263
+ /** The `agents:agentApprovalGrants` reference — live thread-scoped approval grants. */
264
+ type AgentApprovalGrantsReference = FunctionReference<"query", {
265
+ key: string;
266
+ }, ReadonlyArray<AgentApprovalGrant>>;
267
+ /** The `agents:agentRevokeApprovalGrant` reference — removes a thread-scoped approval grant. */
268
+ type AgentRevokeApprovalGrantReference = FunctionReference<"mutation", {
269
+ threadKey: string;
270
+ toolName: string;
271
+ }, {
272
+ revoked: boolean;
273
+ }>;
243
274
  /**
244
275
  * An app stream reference that tees the agent's in-flight live events, keyed by
245
276
  * thread. Carries token deltas and — since `ctx.reportProgress` rides the same
@@ -254,8 +285,12 @@ type AgentTokenStreamReference = FunctionReference<"stream", {
254
285
  */
255
286
  interface AgentChatApi {
256
287
  agents: {
288
+ agentApprovalGrants: AgentApprovalGrantsReference;
289
+ agentDeclineSecret: AgentDeclineSecretReference;
257
290
  agentMessages: AgentMessagesReference$1;
258
291
  agentResolveApproval: AgentApprovalReference;
292
+ agentRevokeApprovalGrant: AgentRevokeApprovalGrantReference;
293
+ agentSupplySecret: AgentSupplySecretReference;
259
294
  agentThread: AgentThreadReference;
260
295
  };
261
296
  }
@@ -272,7 +307,7 @@ interface AgentChatOptions {
272
307
  /** History depth forwarded to `agents:agentMessages`. */
273
308
  limit?: number;
274
309
  /**
275
- * Called when the live history or thread subscription reports an error (a
310
+ * Called when the live history, thread, or grants subscription reports an error (a
276
311
  * session expiry, an RLS denial). Without it such an error is dropped and
277
312
  * `messages` / `status` freeze at their last value — unlike the React, Angular,
278
313
  * Solid and Vue ports, this one leaves the value store untouched on error.
@@ -296,17 +331,28 @@ interface AgentChatOptions {
296
331
  threadKey: string;
297
332
  }
298
333
  interface AgentChatHandle {
334
+ /** The tools approved for the rest of this thread, live. Read with `$approvalGrants`. */
335
+ approvalGrants: Readable<ReadonlyArray<AgentApprovalGrant>>;
299
336
  /** Approve a paused human-in-the-loop tool call (optionally with a note). */
300
337
  approve: (toolCallId: string, note?: string) => Promise<void>;
338
+ /**
339
+ * Approve a paused tool call and grant that tool for the rest of the thread, so
340
+ * later calls to it run without pausing. Undo with {@link AgentChatHandle.revokeGrant}.
341
+ */
342
+ approveForThread: (toolCallId: string, note?: string) => Promise<void>;
301
343
  /**
302
344
  * Terminate the in-flight run and mark its thread `"cancelled"`. Resolves as a
303
345
  * no-op when no `cancel` mutation was supplied or no run is in flight.
304
346
  */
305
347
  cancel: () => Promise<void>;
348
+ /** Refuse a paused `requestSecretTool` call: the run resumes with a "declined" result. */
349
+ declineSecret: (toolCallId: string) => Promise<void>;
306
350
  /** Durable thread history (oldest first) plus any un-acknowledged optimistic user turns. Read with `$messages`. */
307
351
  messages: Readable<ReadonlyArray<AgentChatMessage>>;
308
352
  /** Reject a paused human-in-the-loop tool call (optionally with a reason). */
309
353
  reject: (toolCallId: string, note?: string) => Promise<void>;
354
+ /** Remove a thread-scoped approval grant so the tool's gate applies again to later calls. */
355
+ revokeGrant: (toolName: string) => Promise<void>;
310
356
  /** Start (or continue) a run with a user message; extra args merge over `sendArgs`. Appends an optimistic user turn. */
311
357
  send: (input: string, args?: Record<string, unknown>) => Promise<void>;
312
358
  /** The live thread status, or `undefined` before the thread exists. Read with `$status`. */
@@ -319,14 +365,21 @@ interface AgentChatHandle {
319
365
  */
320
366
  streamingText: Readable<string>;
321
367
  /**
322
- * Stop the live history + thread subscriptions (and the token stream, if any).
368
+ * Give a paused `requestSecretTool` call its value. Always sent online-only: the
369
+ * value is never queued, persisted or replayed, and the call rejects with
370
+ * `OFFLINE_NOT_QUEUED` while the connection is down. The handle keeps no copy;
371
+ * a failure rethrows the original error.
372
+ */
373
+ supplySecret: (toolCallId: string, secret: string) => Promise<void>;
374
+ /**
375
+ * Stop the live history, thread, and grants subscriptions (and the token stream, if any).
323
376
  * Call in `onDestroy` (`onDestroy(handle.teardown)`).
324
377
  */
325
378
  teardown: () => void;
326
379
  }
327
380
  /**
328
381
  * A first-class agent chat surface: live durable history + in-flight token
329
- * streaming + the send / approve / reject / cancel writes, keyed by `threadKey` —
382
+ * streaming + the send / approve / reject / secret / cancel writes, keyed by `threadKey` —
330
383
  * the Svelte counterpart to React's `useAgentChat`, re-expressed as stores you
331
384
  * read with `$`.
332
385
  *
@@ -431,7 +484,7 @@ interface AgentToolEventsOptions {
431
484
  * Optional live event stream — the same app stream function `agentChat` uses.
432
485
  * When supplied, ephemeral `ctx.reportProgress(...)` events for the thread are
433
486
  * surfaced as `{ type: "progress" }` entries; when omitted only the durable
434
- * lifecycle (call / result / awaiting-approval) is returned.
487
+ * lifecycle (call / result / awaiting-approval / awaiting-secret) is returned.
435
488
  */
436
489
  stream?: AgentLiveStreamReference;
437
490
  /** The thread whose tool activity to observe. */
@@ -439,7 +492,7 @@ interface AgentToolEventsOptions {
439
492
  }
440
493
  /**
441
494
  * A single tool-lifecycle event for a thread. The durable arms
442
- * (`call`/`result`/`awaiting-approval`) are derived from `agents:agentMessages`
495
+ * (`call`/`result`/`awaiting-approval`/`awaiting-secret`) are derived from `agents:agentMessages`
443
496
  * and carry the persisted `seq`; the ephemeral `progress` arm comes live off the
444
497
  * stream and has no `seq`. Discriminate on `type`.
445
498
  */
@@ -465,6 +518,11 @@ type AgentToolEvent = {
465
518
  toolCallId?: string;
466
519
  toolName?: string;
467
520
  type: "awaiting-approval";
521
+ } | {
522
+ seq: number;
523
+ toolCallId?: string;
524
+ toolName?: string;
525
+ type: "awaiting-secret";
468
526
  };
469
527
  interface AgentToolEventsHandle {
470
528
  /**
@@ -725,7 +783,7 @@ interface MutationHandle<F extends FunctionReference> {
725
783
  * `options` are applied and rolled back by the client against the live query
726
784
  * subscriptions, exactly as in the React adapter.
727
785
  */
728
- mutate: (args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>;
786
+ mutate: (args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>> & OnlineOnlyOption<F>) => Promise<ReturnOf<F>>;
729
787
  /**
730
788
  * `true` while any invocation from this handle is in flight. Ref-counted, so
731
789
  * overlapping calls compose and it only flips back to `false` once the last
@@ -1267,7 +1325,7 @@ interface VoiceAgentHandle {
1267
1325
  */
1268
1326
  declare function voiceAgent(options: VoiceAgentOptions): VoiceAgentHandle;
1269
1327
  declare function voiceAgent(client: LunoraClient, options: VoiceAgentOptions): VoiceAgentHandle;
1270
- export { type ActionHandle, type AgentApi, type AgentChatApi, type AgentChatHandle, type AgentChatMessage, type AgentChatOptions, type AgentHandle, type AgentLiveEvent, type AgentOptions, type AgentProgressEvent, type AgentStateApi, type AgentStateHandle, type AgentStateOptions, type AgentThreadRecord, type AgentThreadStatus, type AgentTokenDelta, type AgentToolEvent, type AgentToolEventsApi, type AgentToolEventsHandle, type AgentToolEventsOptions, type AuthGateStore, type AuthStore, type ConnectionStatusStore, type FlagValue, type HeartbeatReference, type InfiniteQueryHandle, type InfiniteQueryOptions, type ListPresentReference, type LiveTopicState, type MutationHandle, type MutatorHandleStore, type PageItemOf, type PaginatedArgs, type PaginatedQueryHandle, type PaginatedQueryOptions, type PresenceHandle, type PresenceOptions, type QueryStore, type QueryStoreOptions, type RateLimitHandle, type RateLimitOptions, type ReactiveArgs, type ReactivePaginatedArgs, type StreamHandle, type StreamStatus, type StreamStoreOptions, type SubscriptionHandle, type SubscriptionStoreOptions, type VoiceAgentHandle, type VoiceAgentOptions, type VoiceAudioFormat, type VoiceReference, type VoiceStatus, action, agent, agentChat, agentState, agentToolEvents, auth, authGate, connectionStatus, flag, flags,
1328
+ export { type ActionHandle, type AgentApi, type AgentApprovalGrant, type AgentChatApi, type AgentChatHandle, type AgentChatMessage, type AgentChatOptions, type AgentHandle, type AgentLiveEvent, type AgentOptions, type AgentProgressEvent, type AgentStateApi, type AgentStateHandle, type AgentStateOptions, type AgentThreadRecord, type AgentThreadStatus, type AgentTokenDelta, type AgentToolEvent, type AgentToolEventsApi, type AgentToolEventsHandle, type AgentToolEventsOptions, type AuthGateStore, type AuthStore, type ConnectionStatusStore, type FlagValue, type HeartbeatReference, type InfiniteQueryHandle, type InfiniteQueryOptions, type ListPresentReference, type LiveTopicState, type MutationHandle, type MutatorHandleStore, type PageItemOf, type PaginatedArgs, type PaginatedQueryHandle, type PaginatedQueryOptions, type PresenceHandle, type PresenceOptions, type QueryStore, type QueryStoreOptions, type RateLimitHandle, type RateLimitOptions, type ReactiveArgs, type ReactivePaginatedArgs, type StreamHandle, type StreamStatus, type StreamStoreOptions, type SubscriptionHandle, type SubscriptionStoreOptions, type VoiceAgentHandle, type VoiceAgentOptions, type VoiceAudioFormat, type VoiceReference, type VoiceStatus, action, agent, agentChat, agentState, agentToolEvents, auth, authGate, connectionStatus, flag, flags,
1271
1329
  /**
1272
1330
  * Svelte adapter for Lunora (`@lunora/svelte`).
1273
1331
  *
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{action as t}from"./packem_shared/action-SjeZUGhX.mjs";import{agent as m}from"./packem_shared/agent-WMVWf1Ks.mjs";import{agentChat as a}from"./packem_shared/agentChat-CX6dTMoY.mjs";import{agentState as n}from"./packem_shared/agentState-BCWHx7mX.mjs";import{agentToolEvents as i}from"./packem_shared/agentToolEvents-CnL44w5Y.mjs";import{auth as g,authGate as s}from"./packem_shared/auth-Z0G_aZYz.mjs";import{connectionStatus as l}from"./packem_shared/connectionStatus-DMx3BE5Q.mjs";import{getLunoraClient as h,setLunoraClient as y}from"./packem_shared/getLunoraClient-DU7BmZy1.mjs";import{flag as C,flags as L}from"./packem_shared/flag-Csh9LBiO.mjs";import{hydratePreloaded as S}from"./packem_shared/hydratePreloaded-CNm2-Rha.mjs";import{liveTopic as b}from"./packem_shared/liveTopic-DKHSwXiX.mjs";import{mutation as A}from"./packem_shared/mutation-DLBr5Op1.mjs";import{mutator as G}from"./packem_shared/mutator-DECDuo94.mjs";import{infiniteQuery as j,paginatedQuery as k}from"./packem_shared/infiniteQuery-B6dobUkL.mjs";import{presence as z}from"./packem_shared/presence-C4ZgfGfr.mjs";import{query as D}from"./packem_shared/query-C6B__ZRN.mjs";import{rateLimit as H}from"./packem_shared/rateLimit-Cli38qWO.mjs";import{stream as J}from"./packem_shared/stream-Cxl8guzh.mjs";import{subscription as M}from"./packem_shared/subscription-BQC3Asdx.mjs";import{voiceAgent as O}from"./packem_shared/voiceAgent-KSChAXsW.mjs";export{t as action,m as agent,a as agentChat,n as agentState,i as agentToolEvents,g as auth,s as authGate,l as connectionStatus,C as flag,L as flags,h as getLunoraClient,S as hydratePreloaded,j as infiniteQuery,b as liveTopic,A as mutation,G as mutator,k as paginatedQuery,z as presence,D as query,H as rateLimit,y as setLunoraClient,J as stream,M as subscription,O as voiceAgent};
1
+ import{action as t}from"./packem_shared/action-SjeZUGhX.mjs";import{agent as m}from"./packem_shared/agent-WMVWf1Ks.mjs";import{agentChat as a}from"./packem_shared/agentChat-COq1hXPF.mjs";import{agentState as n}from"./packem_shared/agentState-BCWHx7mX.mjs";import{agentToolEvents as i}from"./packem_shared/agentToolEvents-DV3zjAh0.mjs";import{auth as g,authGate as s}from"./packem_shared/auth-Z0G_aZYz.mjs";import{connectionStatus as l}from"./packem_shared/connectionStatus-DMx3BE5Q.mjs";import{getLunoraClient as h,setLunoraClient as y}from"./packem_shared/getLunoraClient-DU7BmZy1.mjs";import{flag as C,flags as L}from"./packem_shared/flag-Csh9LBiO.mjs";import{hydratePreloaded as S}from"./packem_shared/hydratePreloaded-CNm2-Rha.mjs";import{liveTopic as b}from"./packem_shared/liveTopic-DKHSwXiX.mjs";import{mutation as A}from"./packem_shared/mutation-DLBr5Op1.mjs";import{mutator as G}from"./packem_shared/mutator-DECDuo94.mjs";import{infiniteQuery as j,paginatedQuery as k}from"./packem_shared/infiniteQuery-B6dobUkL.mjs";import{presence as z}from"./packem_shared/presence-C4ZgfGfr.mjs";import{query as D}from"./packem_shared/query-C6B__ZRN.mjs";import{rateLimit as H}from"./packem_shared/rateLimit-Cli38qWO.mjs";import{stream as J}from"./packem_shared/stream-Cxl8guzh.mjs";import{subscription as M}from"./packem_shared/subscription-BQC3Asdx.mjs";import{voiceAgent as O}from"./packem_shared/voiceAgent-B7AkAkB_.mjs";export{t as action,m as agent,a as agentChat,n as agentState,i as agentToolEvents,g as auth,s as authGate,l as connectionStatus,C as flag,L as flags,h as getLunoraClient,S as hydratePreloaded,j as infiniteQuery,b as liveTopic,A as mutation,G as mutator,k as paginatedQuery,z as presence,D as query,H as rateLimit,y as setLunoraClient,J as stream,M as subscription,O as voiceAgent};
@@ -0,0 +1 @@
1
+ import{reconcileOptimistic as R,maxSeq as _}from"@lunora/client";import{writable as l}from"svelte/store";import{i as b}from"./is-browser-BEdfLJHK.mjs";import{isClient as tt,NO_MUTATION_REF as et}from"./agent-WMVWf1Ks.mjs";import{getLunoraClient as st}from"./getLunoraClient-DU7BmZy1.mjs";import{mutation as i}from"./mutation-DLBr5Op1.mjs";import{stream as nt}from"./stream-Cxl8guzh.mjs";const rt={__lunoraRef:""},at=(n,d)=>{const{api:a,cancel:p,limit:g,onError:v,send:C,sendArgs:E,stream:S,threadKey:r}=d,I=i(n,C),G=i(n,p??et),q=i(n,a.agents.agentResolveApproval),j=i(n,a.agents.agentRevokeApprovalGrant),D=i(n,a.agents.agentSupplySecret),F=i(n,a.agents.agentDeclineSecret);let m,o=[],u=[],w=[],k=0;const y=l([]),x=l(),A=l([]),T=l(""),h=()=>{const t=R(u,o);if(t.length===0){y.set(o);return}const e=_(o);y.set([...o,...t.map((s,c)=>({content:s.content,optimistic:!0,role:"user",seq:e+1+c}))])},M=()=>{const t=o.filter(s=>s.role==="assistant").length,e=w.filter(s=>s.kind!=="progress"&&s.threadKey===r&&s.turn>=t).map(s=>s.text).join("");T.set(e)},N=S===void 0?"skip":{key:r},H=b()?nt(n,S??rt,N).chunks.subscribe(t=>{w=t,M()}):()=>{},K=g===void 0?{key:r}:{key:r,limit:g},B=b()?n.subscribe(a.agents.agentMessages,K,t=>{o=t,h(),M()},{onError:v}):()=>{},L=b()?n.subscribe(a.agents.agentThread,{key:r},t=>{m=t,x.set(m?.status)},{onError:v}):()=>{},O=b()?n.subscribe(a.agents.agentApprovalGrants,{key:r},t=>{A.set(t)},{onError:v}):()=>{},U=async(t,e)=>{const s=k;k+=1;const c=_(o);u=[...R(u,o),{content:t,id:s,maxDurableSeqAtSend:c}],h();try{await I.mutate({input:t,threadKey:r,...E,...e})}catch(Y){throw u=u.filter(Z=>Z.id!==s),h(),Y}},f=async(t,e,s)=>{const c=m?.instanceId;if(c===void 0)throw new Error(`agentChat: cannot ${t} — no in-flight run (thread has no instanceId)`);await q.mutate({decision:t,instanceId:c,threadKey:r,toolCallId:e,...s===void 0?{}:{note:s}})},$=async(t,e)=>f("approve",t,e),z=async(t,e)=>f("approve_for_thread",t,e),J=async(t,e)=>f("reject",t,e),P=async t=>{await j.mutate({threadKey:r,toolName:t})},Q=async(t,e)=>{await D.mutate({secret:e,threadKey:r,toolCallId:t},{onlineOnly:!0})},V=async t=>{await F.mutate({threadKey:r,toolCallId:t})},W=async()=>{const t=m?.instanceId;p===void 0||t===void 0||await G.mutate({instanceId:t,threadKey:r})},X=()=>{B(),L(),O(),H()};return{approvalGrants:{subscribe:A.subscribe},approve:$,approveForThread:z,cancel:W,declineSecret:V,messages:{subscribe:y.subscribe},reject:J,revokeGrant:P,send:U,status:{subscribe:x.subscribe},streamingText:{subscribe:T.subscribe},supplySecret:Q,teardown:X}};function bt(n,d){const a=tt(n),p=a?n:st();return at(p,a?d:n)}export{bt as agentChat};
@@ -0,0 +1 @@
1
+ import{derived as y}from"svelte/store";import{isClient as E}from"./agent-WMVWf1Ks.mjs";import{getLunoraClient as I}from"./getLunoraClient-DU7BmZy1.mjs";import{stream as N}from"./stream-Cxl8guzh.mjs";import{subscription as m}from"./subscription-BQC3Asdx.mjs";const _={__lunoraRef:""},h={awaiting_approval:"awaiting-approval",awaiting_secret:"awaiting-secret"},k=t=>{const o=t.status===void 0?void 0:h[t.status];if(o!==void 0)return{seq:t.seq,type:o,...t.toolCallId===void 0?{}:{toolCallId:t.toolCallId},...t.toolName===void 0?{}:{toolName:t.toolName}}},q=t=>{if(t.role==="assistant"&&t.toolCalls)return t.toolCalls.map(r=>({input:r.input,seq:t.seq,toolCallId:r.id,toolName:r.name,type:"call"}));if(t.role!=="tool")return;const o=k(t);return o!==void 0?[o]:[{output:t.content,seq:t.seq,type:"result",...t.status==="approved"||t.status==="rejected"?{status:t.status}:{},...t.toolCallId===void 0?{}:{toolCallId:t.toolCallId},...t.toolName===void 0?{}:{toolName:t.toolName}}]};function x(t,o){const r=E(t),a=r?t:I(),s=r?o:t,{api:u,limit:e,stream:i,threadKey:l}=s,p=e===void 0?{key:l}:{key:l,limit:e},{data:c}=m(a,u.agents.agentMessages,p),v=N(a,i??_,i===void 0?"skip":{key:l});return{events:y([c,v.chunks],([f,C])=>{const d=(f??[]).flatMap(n=>q(n)??[]);for(const n of C)n.kind==="progress"&&n.threadKey===l&&d.push({data:n.data,toolCallId:n.toolCallId,type:"progress"});return d})}}export{x as agentToolEvents};
@@ -0,0 +1 @@
1
+ import{writable as A,get as H}from"svelte/store";import{isClient as V}from"./agent-WMVWf1Ks.mjs";import{getLunoraClient as $}from"./getLunoraClient-DU7BmZy1.mjs";const I="/_lunora/ws",O="/_lunora/voice/",B=4001,U=e=>e.startsWith("https://")?`wss://${e.slice(8)}`:e.startsWith("http://")?`ws://${e.slice(7)}`:e,q=e=>{const s=e.startsWith("agents:")?e.slice(7):e;return s.endsWith("Voice")?s.slice(0,-5):s},K=(e,s)=>{if(s===void 0||s==="")return U(e);if(s.endsWith(I))return s.slice(0,-I.length);try{return new URL(s).origin}catch{return U(e)}},J=e=>{const s=K(e.httpUrl,e.wsUrl),r=s.endsWith("/")?s.slice(0,-1):s,a=new URLSearchParams({threadKey:e.threadKey});return`${r}${O}${encodeURIComponent(e.agent)}?${a.toString()}`},G=(e,s)=>{if(s?.code===B)return new Error(`${e}: authentication token expired — refresh the credential and start a new call`)},X=(e,s,r)=>{const a=e.currentIdentity();return e.onAuthTokenChange(()=>{e.currentIdentity()!==a&&r(new Error(`${s}: the signed-in identity changed during the call — the session was ended; start a new call`))})},j=16e3,z=e=>{if(e.length===0)return 0;let s=0;for(const r of e)s+=r*r;return Math.sqrt(s/e.length)},Q=(e,s)=>{const r=s/j,a=r>1?Math.floor(e.length/r):e.length,f=new ArrayBuffer(a*2),d=new DataView(f);for(let u=0;u<a;u+=1){const b=e[Math.floor(u*r)]??0,k=Math.max(-1,Math.min(1,b));d.setInt16(u*2,k<0?k*32768:k*32767,!0)}return new Uint8Array(f)},Y=async e=>{const s=globalThis,r=s.navigator?.mediaDevices?.getUserMedia.bind(s.navigator.mediaDevices),a=s.AudioContext??s.webkitAudioContext;if(!r||!a)throw new Error("useVoiceAgent: microphone capture requires getUserMedia + AudioContext (no browser audio available)");const f=await r({audio:{channelCount:1,echoCancellation:!0,noiseSuppression:!0}}),d=new a,u=d.createMediaStreamSource(f),b=d.createScriptProcessor(4096,1,1);let k=!1,w=!1,g=0,o=0;return b.onaudioprocess=c=>{const l=c.inputBuffer.getChannelData(0),p=k?0:z(l);if(e.onLevel(p),k)return;if(e.onAudio(Q(l,d.sampleRate)),e.isTurnActive()){o=p>=e.interruptThreshold?o+1:0,o>=e.interruptChunks&&(o=0,e.onInterrupt());return}o=0;const T=l.length/d.sampleRate*1e3;if(p>=e.silenceThreshold){w=!0,g=0;return}w&&(g+=T,g>=e.silenceDurationMs&&(w=!1,g=0,e.onSilence()))},u.connect(b),b.connect(d.destination),{setMuted:c=>{k=c},stop:()=>{b.disconnect(),u.disconnect();for(const c of f.getTracks())c.stop();d.close()}}},Z=()=>{const e=globalThis,s=e.AudioContext??e.webkitAudioContext;if(!s)throw new Error("useVoiceAgent: audio playback requires AudioContext (no browser audio available)");const r=new s,a=new Set;let f=0,d=Promise.resolve(),u=0;const b=async(g,o)=>{if(o!==u)return;let c;try{c=await r.decodeAudioData(g.buffer)}catch{return}if(o!==u)return;const l=r.createBufferSource();l.buffer=c,l.connect(r.destination);const p=Math.max(r.currentTime,f);l.start(p),f=p+c.duration,a.add(l),l.onended=()=>{a.delete(l)}},k=g=>{const o=Uint8Array.from(g),c=u;d=d.then(()=>b(o,c))},w=()=>{u+=1;for(const g of a)try{g.stop()}catch{}a.clear(),f=r.currentTime};return{enqueue:k,interrupt:w,stop:()=>{w(),r.close()}}},R=1,ee=.01,te=1200,ne=.15,se=3,re=(e,s)=>{const{createMicrophone:r=Y,createSpeaker:a=Z,createSocket:f,interruptChunks:d=se,interruptThreshold:u=ne,silenceDurationMs:b=te,silenceThreshold:k=ee,threadKey:w,voice:g}=s,o=A("idle"),c=A(!1),l=A(""),p=A(""),T=A(0),v=A(!1),m=A();let i,E=!1;const _=n=>{const t=i?.socket;return t?.readyState===R?(t.send(JSON.stringify(n)),!0):!1},C=()=>{const n=i;if(i=void 0,n){n.unwatchIdentity?.(),n.microphone?.stop(),n.speaker?.stop(),n.socket.onmessage=null,n.socket.onerror=null,n.socket.onclose=null;try{n.socket.close()}catch{}}E=!1,c.set(!1),o.set("idle"),T.set(0)},L=C,D=n=>{const t=i;switch(n.type){case"assistant_delta":{t&&(t.speaking=!0),o.set("speaking"),p.update(x=>x+n.text);break}case"assistant_discarded":{t&&(t.suppressAudio=!0),t?.speaker?.interrupt(),p.set("");break}case"assistant_done":{t&&(t.awaitingTurn=!1,t.speaking=!1),p.set(n.text),o.set("listening");break}case"error":{t&&(t.awaitingTurn=!1,t.speaking=!1),m.set(new Error(n.message)),o.set("listening");break}case"interrupted":{t&&(t.awaitingTurn=!1,t.speaking=!1,t.suppressAudio=!1),t?.speaker?.interrupt(),o.set("listening");break}case"ready":{t&&(t.audioFormat=n.audioFormat,t.suppressAudio=!1),c.set(!0),o.set("listening");break}case"user_transcript":{t&&(t.suppressAudio=!1),l.set(n.text),p.set(""),o.set("thinking");break}}},F=n=>{const t=i;!t||t.suppressAudio||(t.speaker??=a({audioFormat:t.audioFormat}),t.speaking=!0,o.set("speaking"),t.speaker.enqueue(n))},W=async()=>{if(i||E)return;E=!0,m.set(void 0),l.set(""),p.set("");let n;try{const t=J({agent:q(g.__lunoraRef),httpUrl:e.url,threadKey:w,wsUrl:e.wsUrl}),S=(f??(h=>{const y=e.getWebSocketImpl();if(!y)throw new Error("voiceAgent: no WebSocket implementation available (pass createSocket explicitly)");return new y(h)}))(t);S.binaryType="arraybuffer",n={audioFormat:"mp3",microphone:void 0,socket:S,speaker:void 0,speaking:!1,awaitingTurn:!1,suppressAudio:!1,unwatchIdentity:void 0},i=n,n.unwatchIdentity=X(e,"voiceAgent",h=>{i===n&&(m.set(h),C())}),S.onmessage=h=>{if(typeof h.data=="string"){try{D(JSON.parse(h.data))}catch{}return}F(new Uint8Array(h.data))},S.onerror=()=>{m.set(new Error("voiceAgent: voice socket error"))},S.onclose=h=>{if(i!==n)return;const y=G("voiceAgent",h);y&&m.set(y),C()};const M=await r({interruptChunks:d,interruptThreshold:u,isTurnActive:()=>(i?.speaking??!1)||(i?.awaitingTurn??!1),onAudio:h=>{S.readyState===R&&S.send(h)},onInterrupt:()=>{_({type:"interrupt"}),i?.speaker?.interrupt(),i&&(i.awaitingTurn=!1,i.speaking=!1,i.suppressAudio=!0),o.set("listening")},onLevel:h=>{T.set(h)},onSilence:()=>{_({type:"commit"}),i&&(i.awaitingTurn=!0),o.set("thinking")},silenceDurationMs:b,silenceThreshold:k});i===n?(n.microphone=M,v.set(!1),n.speaking||o.set("listening")):M.stop()}catch(t){i===n&&(m.set(t instanceof Error?t:new Error(String(t))),C())}finally{E=!1}},N=()=>{const n=!H(v);return i?.microphone?.setMuted(n),v.set(n),n},P=n=>{_({text:n,type:"text"})&&(i&&(i.awaitingTurn=!0),o.set("thinking"))};return{audioLevel:{subscribe:T.subscribe},connected:{subscribe:c.subscribe},endCall:L,error:{subscribe:m.subscribe},interimTranscript:{subscribe:p.subscribe},isMuted:{subscribe:v.subscribe},sendText:P,startCall:W,status:{subscribe:o.subscribe},toggleMute:N,transcript:{subscribe:l.subscribe}}};function ce(e,s){const r=V(e),a=r?e:$();return re(a,r?s:e)}export{ce as voiceAgent};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/svelte",
3
- "version": "1.0.0-alpha.272",
3
+ "version": "1.0.0-alpha.274",
4
4
  "description": "Svelte adapter for Lunora — live stores, optimistic mutations, and reactive loaders",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -54,10 +54,10 @@
54
54
  "access": "public"
55
55
  },
56
56
  "dependencies": {
57
- "@lunora/client": "1.0.0-alpha.233",
57
+ "@lunora/client": "1.0.0-alpha.235",
58
58
  "@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
59
- "@lunora/ratelimit": "1.0.0-alpha.155",
60
- "@lunora/wire": "1.0.0-alpha.1",
59
+ "@lunora/ratelimit": "1.0.0-alpha.157",
60
+ "@lunora/wire": "1.0.0-alpha.2",
61
61
  "@visulima/storage-client": "1.0.9"
62
62
  },
63
63
  "peerDependencies": {
@@ -1 +0,0 @@
1
- import{reconcileOptimistic as k,maxSeq as C}from"@lunora/client";import{writable as g}from"svelte/store";import{i as f}from"./is-browser-BEdfLJHK.mjs";import{isClient as J,NO_MUTATION_REF as O}from"./agent-WMVWf1Ks.mjs";import{getLunoraClient as P}from"./getLunoraClient-DU7BmZy1.mjs";import{mutation as h}from"./mutation-DLBr5Op1.mjs";import{stream as Q}from"./stream-Cxl8guzh.mjs";const V={__lunoraRef:""},W=(n,d)=>{const{api:a,cancel:u,limit:l,onError:v,send:E,sendArgs:I,stream:y,threadKey:r}=d,M=h(n,E),_=h(n,u??O),q=h(n,a.agents.agentResolveApproval);let m,o=[],i=[],x=[],S=0;const b=g([]),w=g(),A=g(""),p=()=>{const t=k(i,o);if(t.length===0){b.set(o);return}const s=C(o);b.set([...o,...t.map((e,c)=>({content:e.content,optimistic:!0,role:"user",seq:s+1+c}))])},T=()=>{const t=o.filter(e=>e.role==="assistant").length,s=x.filter(e=>e.kind!=="progress"&&e.threadKey===r&&e.turn>=t).map(e=>e.text).join("");A.set(s)},j=y===void 0?"skip":{key:r},N=f()?Q(n,y??V,j).chunks.subscribe(t=>{x=t,T()}):()=>{},D=l===void 0?{key:r}:{key:r,limit:l},F=f()?n.subscribe(a.agents.agentMessages,D,t=>{o=t,p(),T()},{onError:v}):()=>{},H=f()?n.subscribe(a.agents.agentThread,{key:r},t=>{m=t,w.set(m?.status)},{onError:v}):()=>{},K=async(t,s)=>{const e=S;S+=1;const c=C(o);i=[...k(i,o),{content:t,id:e,maxDurableSeqAtSend:c}],p();try{await M.mutate({input:t,threadKey:r,...I,...s})}catch(z){throw i=i.filter(G=>G.id!==e),p(),z}},R=async(t,s,e)=>{const c=m?.instanceId;if(c===void 0)throw new Error(`agentChat: cannot ${t} — no in-flight run (thread has no instanceId)`);await q.mutate({decision:t,instanceId:c,threadKey:r,toolCallId:s,...e===void 0?{}:{note:e}})},B=async(t,s)=>R("approve",t,s),L=async(t,s)=>R("reject",t,s),U=async()=>{const t=m?.instanceId;u===void 0||t===void 0||await _.mutate({instanceId:t,threadKey:r})},$=()=>{F(),H(),N()};return{approve:B,cancel:U,messages:{subscribe:b.subscribe},reject:L,send:K,status:{subscribe:w.subscribe},streamingText:{subscribe:A.subscribe},teardown:$}};function rt(n,d){const a=J(n),u=a?n:P();return W(u,a?d:n)}export{rt as agentChat};
@@ -1 +0,0 @@
1
- import{derived as y}from"svelte/store";import{isClient as m}from"./agent-WMVWf1Ks.mjs";import{getLunoraClient as I}from"./getLunoraClient-DU7BmZy1.mjs";import{stream as N}from"./stream-Cxl8guzh.mjs";import{subscription as h}from"./subscription-BQC3Asdx.mjs";const k={__lunoraRef:""},q=t=>{if(t.role==="assistant"&&t.toolCalls)return t.toolCalls.map(l=>({input:l.input,seq:t.seq,toolCallId:l.id,toolName:l.name,type:"call"}));if(t.role==="tool")return t.status==="awaiting_approval"?[{seq:t.seq,type:"awaiting-approval",...t.toolCallId===void 0?{}:{toolCallId:t.toolCallId},...t.toolName===void 0?{}:{toolName:t.toolName}}]:[{output:t.content,seq:t.seq,type:"result",...t.status==="approved"||t.status==="rejected"?{status:t.status}:{},...t.toolCallId===void 0?{}:{toolCallId:t.toolCallId},...t.toolName===void 0?{}:{toolName:t.toolName}}]};function K(t,l){const n=m(t),a=n?t:I(),u=n?l:t,{api:p,limit:e,stream:i,threadKey:r}=u,s=e===void 0?{key:r}:{key:r,limit:e},{data:c}=h(a,p.agents.agentMessages,s),v=N(a,i??k,i===void 0?"skip":{key:r});return{events:y([c,v.chunks],([f,C])=>{const d=(f??[]).flatMap(o=>q(o)??[]);for(const o of C)o.kind==="progress"&&o.threadKey===r&&d.push({data:o.data,toolCallId:o.toolCallId,type:"progress"});return d})}}export{K as agentToolEvents};
@@ -1 +0,0 @@
1
- import{writable as A,get as H}from"svelte/store";import{isClient as V}from"./agent-WMVWf1Ks.mjs";import{getLunoraClient as $}from"./getLunoraClient-DU7BmZy1.mjs";const I="/_lunora/ws",O="/_lunora/voice/",B=4001,U=e=>e.startsWith("https://")?`wss://${e.slice(8)}`:e.startsWith("http://")?`ws://${e.slice(7)}`:e,q=e=>{const n=e.startsWith("agents:")?e.slice(7):e;return n.endsWith("Voice")?n.slice(0,-5):n},K=(e,n)=>{if(n===void 0||n==="")return U(e);if(n.endsWith(I))return n.slice(0,-I.length);try{return new URL(n).origin}catch{return U(e)}},J=e=>{const n=K(e.httpUrl,e.wsUrl),r=n.endsWith("/")?n.slice(0,-1):n,a=new URLSearchParams({threadKey:e.threadKey});return`${r}${O}${encodeURIComponent(e.agent)}?${a.toString()}`},G=(e,n)=>{if(n?.code===B)return new Error(`${e}: authentication token expired — refresh the credential and start a new call`)},X=(e,n,r)=>{const a=e.currentIdentity();return e.onAuthTokenChange(()=>{e.currentIdentity()!==a&&r(new Error(`${n}: the signed-in identity changed during the call — the session was ended; start a new call`))})},j=16e3,z=e=>{if(e.length===0)return 0;let n=0;for(const r of e)n+=r*r;return Math.sqrt(n/e.length)},Q=(e,n)=>{const r=n/j,a=r>1?Math.floor(e.length/r):e.length,h=new ArrayBuffer(a*2),d=new DataView(h);for(let u=0;u<a;u+=1){const b=e[Math.floor(u*r)]??0,k=Math.max(-1,Math.min(1,b));d.setInt16(u*2,k<0?k*32768:k*32767,!0)}return new Uint8Array(h)},Y=async e=>{const n=globalThis,r=n.navigator?.mediaDevices?.getUserMedia.bind(n.navigator.mediaDevices),a=n.AudioContext??n.webkitAudioContext;if(!r||!a)throw new Error("useVoiceAgent: microphone capture requires getUserMedia + AudioContext (no browser audio available)");const h=await r({audio:{channelCount:1,echoCancellation:!0,noiseSuppression:!0}}),d=new a,u=d.createMediaStreamSource(h),b=d.createScriptProcessor(4096,1,1);let k=!1,w=!1,f=0,o=0;return b.onaudioprocess=c=>{const l=c.inputBuffer.getChannelData(0),g=k?0:z(l);if(e.onLevel(g),k)return;if(e.onAudio(Q(l,d.sampleRate)),e.isTurnActive()){o=g>=e.interruptThreshold?o+1:0,o>=e.interruptChunks&&(o=0,e.onInterrupt());return}o=0;const T=l.length/d.sampleRate*1e3;if(g>=e.silenceThreshold){w=!0,f=0;return}w&&(f+=T,f>=e.silenceDurationMs&&(w=!1,f=0,e.onSilence()))},u.connect(b),b.connect(d.destination),{setMuted:c=>{k=c},stop:()=>{b.disconnect(),u.disconnect();for(const c of h.getTracks())c.stop();d.close()}}},Z=()=>{const e=globalThis,n=e.AudioContext??e.webkitAudioContext;if(!n)throw new Error("useVoiceAgent: audio playback requires AudioContext (no browser audio available)");const r=new n,a=new Set;let h=0,d=Promise.resolve(),u=0;const b=async(f,o)=>{if(o!==u)return;let c;try{c=await r.decodeAudioData(f.buffer)}catch{return}if(o!==u)return;const l=r.createBufferSource();l.buffer=c,l.connect(r.destination);const g=Math.max(r.currentTime,h);l.start(g),h=g+c.duration,a.add(l),l.onended=()=>{a.delete(l)}},k=f=>{const o=Uint8Array.from(f),c=u;d=d.then(()=>b(o,c))},w=()=>{u+=1;for(const f of a)try{f.stop()}catch{}a.clear(),h=r.currentTime};return{enqueue:k,interrupt:w,stop:()=>{w(),r.close()}}},R=1,ee=.01,te=1200,ne=.15,se=3,re=(e,n)=>{const{createMicrophone:r=Y,createSpeaker:a=Z,createSocket:h,interruptChunks:d=se,interruptThreshold:u=ne,silenceDurationMs:b=te,silenceThreshold:k=ee,threadKey:w,voice:f}=n,o=A("idle"),c=A(!1),l=A(""),g=A(""),T=A(0),v=A(!1),m=A();let i,E=!1;const _=t=>{const s=i?.socket;return s?.readyState===R?(s.send(JSON.stringify(t)),!0):!1},C=()=>{const t=i;if(i=void 0,t){t.unwatchIdentity?.(),t.microphone?.stop(),t.speaker?.stop(),t.socket.onmessage=null,t.socket.onerror=null,t.socket.onclose=null;try{t.socket.close()}catch{}}E=!1,c.set(!1),o.set("idle"),T.set(0)},L=C,D=t=>{const s=i;switch(t.type){case"assistant_delta":{s&&(s.speaking=!0),o.set("speaking"),g.update(x=>x+t.text);break}case"assistant_done":{s&&(s.awaitingTurn=!1,s.speaking=!1),g.set(t.text),o.set("listening");break}case"error":{s&&(s.awaitingTurn=!1,s.speaking=!1),m.set(new Error(t.message)),o.set("listening");break}case"interrupted":{s&&(s.awaitingTurn=!1,s.speaking=!1,s.suppressAudio=!1),s?.speaker?.interrupt(),o.set("listening");break}case"ready":{s&&(s.audioFormat=t.audioFormat,s.suppressAudio=!1),c.set(!0),o.set("listening");break}case"user_transcript":{s&&(s.suppressAudio=!1),l.set(t.text),g.set(""),o.set("thinking");break}}},F=t=>{const s=i;!s||s.suppressAudio||(s.speaker??=a({audioFormat:s.audioFormat}),s.speaking=!0,o.set("speaking"),s.speaker.enqueue(t))},W=async()=>{if(i||E)return;E=!0,m.set(void 0),l.set(""),g.set("");let t;try{const s=J({agent:q(f.__lunoraRef),httpUrl:e.url,threadKey:w,wsUrl:e.wsUrl}),S=(h??(p=>{const y=e.getWebSocketImpl();if(!y)throw new Error("voiceAgent: no WebSocket implementation available (pass createSocket explicitly)");return new y(p)}))(s);S.binaryType="arraybuffer",t={audioFormat:"mp3",microphone:void 0,socket:S,speaker:void 0,speaking:!1,awaitingTurn:!1,suppressAudio:!1,unwatchIdentity:void 0},i=t,t.unwatchIdentity=X(e,"voiceAgent",p=>{i===t&&(m.set(p),C())}),S.onmessage=p=>{if(typeof p.data=="string"){try{D(JSON.parse(p.data))}catch{}return}F(new Uint8Array(p.data))},S.onerror=()=>{m.set(new Error("voiceAgent: voice socket error"))},S.onclose=p=>{if(i!==t)return;const y=G("voiceAgent",p);y&&m.set(y),C()};const M=await r({interruptChunks:d,interruptThreshold:u,isTurnActive:()=>(i?.speaking??!1)||(i?.awaitingTurn??!1),onAudio:p=>{S.readyState===R&&S.send(p)},onInterrupt:()=>{_({type:"interrupt"}),i?.speaker?.interrupt(),i&&(i.awaitingTurn=!1,i.speaking=!1,i.suppressAudio=!0),o.set("listening")},onLevel:p=>{T.set(p)},onSilence:()=>{_({type:"commit"}),i&&(i.awaitingTurn=!0),o.set("thinking")},silenceDurationMs:b,silenceThreshold:k});i===t?(t.microphone=M,v.set(!1),t.speaking||o.set("listening")):M.stop()}catch(s){i===t&&(m.set(s instanceof Error?s:new Error(String(s))),C())}finally{E=!1}},N=()=>{const t=!H(v);return i?.microphone?.setMuted(t),v.set(t),t},P=t=>{_({text:t,type:"text"})&&(i&&(i.awaitingTurn=!0),o.set("thinking"))};return{audioLevel:{subscribe:T.subscribe},connected:{subscribe:c.subscribe},endCall:L,error:{subscribe:m.subscribe},interimTranscript:{subscribe:g.subscribe},isMuted:{subscribe:v.subscribe},sendText:P,startCall:W,status:{subscribe:o.subscribe},toggleMute:N,transcript:{subscribe:l.subscribe}}};function ce(e,n){const r=V(e),a=r?e:$();return re(a,r?n:e)}export{ce as voiceAgent};