@lunora/svelte 1.0.0-alpha.272 → 1.0.0-alpha.273
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 +69 -11
- package/dist/index.d.ts +69 -11
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/agentChat-COq1hXPF.mjs +1 -0
- package/dist/packem_shared/agentToolEvents-DV3zjAh0.mjs +1 -0
- package/dist/packem_shared/voiceAgent-B7AkAkB_.mjs +1 -0
- package/package.json +3 -3
- package/dist/packem_shared/agentChat-CX6dTMoY.mjs +0 -1
- package/dist/packem_shared/agentToolEvents-CnL44w5Y.mjs +0 -1
- package/dist/packem_shared/voiceAgent-KSChAXsW.mjs +0 -1
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
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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-
|
|
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.
|
|
3
|
+
"version": "1.0.0-alpha.273",
|
|
4
4
|
"description": "Svelte adapter for Lunora — live stores, optimistic mutations, and reactive loaders",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@lunora/client": "1.0.0-alpha.
|
|
57
|
+
"@lunora/client": "1.0.0-alpha.234",
|
|
58
58
|
"@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
|
|
59
|
-
"@lunora/ratelimit": "1.0.0-alpha.
|
|
59
|
+
"@lunora/ratelimit": "1.0.0-alpha.156",
|
|
60
60
|
"@lunora/wire": "1.0.0-alpha.1",
|
|
61
61
|
"@visulima/storage-client": "1.0.9"
|
|
62
62
|
},
|
|
@@ -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};
|