@lunora/solid 1.0.0-alpha.41 → 1.0.0-alpha.42

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
@@ -49,7 +49,7 @@ interface AgentThreadRecord {
49
49
  updatedAt?: number;
50
50
  }
51
51
  /** A plain value or a Solid accessor of it — matching `createQuery`'s reactive-args contract. */
52
- type MaybeAccessor$1<T> = Accessor<T> | T;
52
+ type MaybeAccessor<T> = Accessor<T> | T;
53
53
  /**
54
54
  * The `agents.agentThread` reference the primitive subscribes to for live thread
55
55
  * state (status + the in-flight `instanceId`). A structural subset of the
@@ -82,7 +82,7 @@ interface CreateAgentOptions {
82
82
  /** Extra args merged into every `run` call (e.g. an `owner` or `title`). */
83
83
  runArgs?: Record<string, unknown>;
84
84
  /** The thread to observe and drive — a plain value or accessor (an accessor re-subscribes on change). */
85
- threadKey: MaybeAccessor$1<string>;
85
+ threadKey: MaybeAccessor<string>;
86
86
  }
87
87
  interface CreateAgentResult {
88
88
  /**
@@ -244,7 +244,7 @@ interface CreateAgentChatOptions {
244
244
  */
245
245
  stream?: AgentTokenStreamReference;
246
246
  /** The thread to observe and continue — a plain value or accessor (an accessor re-subscribes on change). */
247
- threadKey: MaybeAccessor$1<string>;
247
+ threadKey: MaybeAccessor<string>;
248
248
  }
249
249
  interface CreateAgentChatResult {
250
250
  /** Approve a paused human-in-the-loop tool call (optionally with a note). */
@@ -305,7 +305,7 @@ interface CreateAgentStateOptions {
305
305
  /** The generated `api` — its `agents.agentState` query drives live thread state. */
306
306
  api: CreateAgentStateApi;
307
307
  /** The thread whose synced state to observe — a plain value or accessor (an accessor re-subscribes on change). */
308
- threadKey: MaybeAccessor$1<string>;
308
+ threadKey: MaybeAccessor<string>;
309
309
  }
310
310
  interface CreateAgentStateResult<T> {
311
311
  /** The subscription error, if the live channel reported one. */
@@ -365,7 +365,7 @@ interface CreateAgentToolEventsOptions {
365
365
  */
366
366
  stream?: AgentLiveStreamReference;
367
367
  /** The thread whose tool activity to observe — a plain value or accessor (an accessor re-subscribes on change). */
368
- threadKey: MaybeAccessor$1<string>;
368
+ threadKey: MaybeAccessor<string>;
369
369
  }
370
370
  /**
371
371
  * A single tool-lifecycle event for a thread. The durable arms
@@ -466,8 +466,6 @@ type FlagContext = Record<string, unknown>;
466
466
  type FlagValue = boolean | number | string | {
467
467
  [key: string]: unknown;
468
468
  } | unknown[] | null;
469
- /** A plain value or a Solid accessor of it — matching `createQuery`'s reactive-args contract. */
470
- type MaybeAccessor<T> = Accessor<T> | T;
471
469
  /**
472
470
  * Subscribe to a single feature flag and return a reactive accessor of its value.
473
471
  *
@@ -876,7 +874,7 @@ interface CreateVoiceAgentOptions {
876
874
  /** Input RMS below which audio counts as silence. Default `0.01`. */
877
875
  silenceThreshold?: number;
878
876
  /** The thread to converse on — shared with the agent's text turns. May be a plain value or accessor (resolved when the call opens). */
879
- threadKey: MaybeAccessor$1<string>;
877
+ threadKey: MaybeAccessor<string>;
880
878
  /** The generated `api.agents.<name>Voice` reference — identifies the voice DO endpoint. */
881
879
  voice: VoiceReference;
882
880
  }
package/dist/index.d.ts CHANGED
@@ -49,7 +49,7 @@ interface AgentThreadRecord {
49
49
  updatedAt?: number;
50
50
  }
51
51
  /** A plain value or a Solid accessor of it — matching `createQuery`'s reactive-args contract. */
52
- type MaybeAccessor$1<T> = Accessor<T> | T;
52
+ type MaybeAccessor<T> = Accessor<T> | T;
53
53
  /**
54
54
  * The `agents.agentThread` reference the primitive subscribes to for live thread
55
55
  * state (status + the in-flight `instanceId`). A structural subset of the
@@ -82,7 +82,7 @@ interface CreateAgentOptions {
82
82
  /** Extra args merged into every `run` call (e.g. an `owner` or `title`). */
83
83
  runArgs?: Record<string, unknown>;
84
84
  /** The thread to observe and drive — a plain value or accessor (an accessor re-subscribes on change). */
85
- threadKey: MaybeAccessor$1<string>;
85
+ threadKey: MaybeAccessor<string>;
86
86
  }
87
87
  interface CreateAgentResult {
88
88
  /**
@@ -244,7 +244,7 @@ interface CreateAgentChatOptions {
244
244
  */
245
245
  stream?: AgentTokenStreamReference;
246
246
  /** The thread to observe and continue — a plain value or accessor (an accessor re-subscribes on change). */
247
- threadKey: MaybeAccessor$1<string>;
247
+ threadKey: MaybeAccessor<string>;
248
248
  }
249
249
  interface CreateAgentChatResult {
250
250
  /** Approve a paused human-in-the-loop tool call (optionally with a note). */
@@ -305,7 +305,7 @@ interface CreateAgentStateOptions {
305
305
  /** The generated `api` — its `agents.agentState` query drives live thread state. */
306
306
  api: CreateAgentStateApi;
307
307
  /** The thread whose synced state to observe — a plain value or accessor (an accessor re-subscribes on change). */
308
- threadKey: MaybeAccessor$1<string>;
308
+ threadKey: MaybeAccessor<string>;
309
309
  }
310
310
  interface CreateAgentStateResult<T> {
311
311
  /** The subscription error, if the live channel reported one. */
@@ -365,7 +365,7 @@ interface CreateAgentToolEventsOptions {
365
365
  */
366
366
  stream?: AgentLiveStreamReference;
367
367
  /** The thread whose tool activity to observe — a plain value or accessor (an accessor re-subscribes on change). */
368
- threadKey: MaybeAccessor$1<string>;
368
+ threadKey: MaybeAccessor<string>;
369
369
  }
370
370
  /**
371
371
  * A single tool-lifecycle event for a thread. The durable arms
@@ -466,8 +466,6 @@ type FlagContext = Record<string, unknown>;
466
466
  type FlagValue = boolean | number | string | {
467
467
  [key: string]: unknown;
468
468
  } | unknown[] | null;
469
- /** A plain value or a Solid accessor of it — matching `createQuery`'s reactive-args contract. */
470
- type MaybeAccessor<T> = Accessor<T> | T;
471
469
  /**
472
470
  * Subscribe to a single feature flag and return a reactive accessor of its value.
473
471
  *
@@ -876,7 +874,7 @@ interface CreateVoiceAgentOptions {
876
874
  /** Input RMS below which audio counts as silence. Default `0.01`. */
877
875
  silenceThreshold?: number;
878
876
  /** The thread to converse on — shared with the agent's text turns. May be a plain value or accessor (resolved when the call opens). */
879
- threadKey: MaybeAccessor$1<string>;
877
+ threadKey: MaybeAccessor<string>;
880
878
  /** The generated `api.agents.<name>Voice` reference — identifies the voice DO endpoint. */
881
879
  voice: VoiceReference;
882
880
  }
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{LunoraContext as r,useLunora as o}from"./packem_shared/LunoraContext-CVOsskhY.mjs";import{createAgent as c}from"./packem_shared/createAgent-BbHVxEpf.mjs";import{createAgentChat as f}from"./packem_shared/createAgentChat-B79ZiHfq.mjs";import{createAgentState as p}from"./packem_shared/createAgentState-CbE2MP_H.mjs";import{createAgentToolEvents as u}from"./packem_shared/createAgentToolEvents-DOU_J3JT.mjs";import{AuthLoading as d,Authenticated as g,Unauthenticated as s,createAuth as A}from"./packem_shared/AuthLoading-D6A1mBRs.mjs";import{default as h}from"./packem_shared/createConnectionStatus-B9ly5m1x.mjs";import{createFlag as y,createFlags as C}from"./packem_shared/createFlag-qBxuQ5hP.mjs";import{createMutation as S,createMutationForClient as F}from"./packem_shared/createMutation-9i34uh8U.mjs";import{createMutator as Q}from"./packem_shared/createMutator-zzxMk2QQ.mjs";import{createInfiniteQuery as b,createPaginatedQuery as E}from"./packem_shared/createInfiniteQuery-Cq1TI1WK.mjs";import{createPresence as R}from"./packem_shared/createPresence-DNVSvTzP.mjs";import{createQuery as U}from"./packem_shared/createQuery-CFb7mUGW.mjs";import{createRateLimit as j}from"./packem_shared/createRateLimit-BdVo3eNW.mjs";import{createStream as q}from"./packem_shared/createStream-DozkYNOc.mjs";import{createSubscription as z}from"./packem_shared/createSubscription-KbQk0ohZ.mjs";import{createVoiceAgent as D}from"./packem_shared/createVoiceAgent-CzXF9acz.mjs";import{default as H}from"./packem_shared/hydratePreloaded-BbGFlPEb.mjs";import{LunoraProvider as K}from"./packem_shared/LunoraProvider-cifsrLab.mjs";export{d as AuthLoading,g as Authenticated,r as LunoraContext,K as LunoraProvider,s as Unauthenticated,c as createAgent,f as createAgentChat,p as createAgentState,u as createAgentToolEvents,A as createAuth,h as createConnectionStatus,y as createFlag,C as createFlags,b as createInfiniteQuery,S as createMutation,F as createMutationForClient,Q as createMutator,E as createPaginatedQuery,R as createPresence,U as createQuery,j as createRateLimit,q as createStream,z as createSubscription,D as createVoiceAgent,H as hydratePreloaded,o as useLunora};
1
+ import{LunoraContext as r,useLunora as o}from"./packem_shared/LunoraContext-CVOsskhY.mjs";import{createAgent as c}from"./packem_shared/createAgent-BbHVxEpf.mjs";import{createAgentChat as f}from"./packem_shared/createAgentChat-B9X5a6Dl.mjs";import{createAgentState as p}from"./packem_shared/createAgentState-CbE2MP_H.mjs";import{createAgentToolEvents as u}from"./packem_shared/createAgentToolEvents-DOU_J3JT.mjs";import{AuthLoading as d,Authenticated as g,Unauthenticated as s,createAuth as A}from"./packem_shared/AuthLoading-D6A1mBRs.mjs";import{default as h}from"./packem_shared/createConnectionStatus-B9ly5m1x.mjs";import{createFlag as y,createFlags as C}from"./packem_shared/createFlag-TCzRHafe.mjs";import{createMutation as S,createMutationForClient as F}from"./packem_shared/createMutation-9i34uh8U.mjs";import{createMutator as Q}from"./packem_shared/createMutator-zzxMk2QQ.mjs";import{createInfiniteQuery as b,createPaginatedQuery as E}from"./packem_shared/createInfiniteQuery-B5cuybnA.mjs";import{createPresence as R}from"./packem_shared/createPresence-DNVSvTzP.mjs";import{createQuery as U}from"./packem_shared/createQuery-CFb7mUGW.mjs";import{createRateLimit as j}from"./packem_shared/createRateLimit-BdVo3eNW.mjs";import{createStream as q}from"./packem_shared/createStream-DozkYNOc.mjs";import{createSubscription as z}from"./packem_shared/createSubscription-KbQk0ohZ.mjs";import{createVoiceAgent as D}from"./packem_shared/createVoiceAgent-n6zFudOx.mjs";import{default as H}from"./packem_shared/hydratePreloaded-BbGFlPEb.mjs";import{LunoraProvider as K}from"./packem_shared/LunoraProvider-cifsrLab.mjs";export{d as AuthLoading,g as Authenticated,r as LunoraContext,K as LunoraProvider,s as Unauthenticated,c as createAgent,f as createAgentChat,p as createAgentState,u as createAgentToolEvents,A as createAuth,h as createConnectionStatus,y as createFlag,C as createFlags,b as createInfiniteQuery,S as createMutation,F as createMutationForClient,Q as createMutator,E as createPaginatedQuery,R as createPresence,U as createQuery,j as createRateLimit,q as createStream,z as createSubscription,D as createVoiceAgent,H as hydratePreloaded,o as useLunora};
@@ -0,0 +1 @@
1
+ import{reconcileOptimistic as v,maxSeq as k}from"@lunora/client";import{createSignal as N,createMemo as i}from"solid-js";import{resolveMaybe as r,NO_MUTATION_REF as U}from"./createAgent-BbHVxEpf.mjs";import{createMutation as l}from"./createMutation-9i34uh8U.mjs";import{createStream as D}from"./createStream-DozkYNOc.mjs";import{createSubscription as I}from"./createSubscription-KbQk0ohZ.mjs";const P={__lunoraRef:""},Q=w=>{const{api:d,cancel:p,limit:u,send:A,sendArgs:S,stream:g,threadKey:n}=w,{data:x}=I(d.agents.agentMessages,()=>{const t=r(n);return u===void 0?{key:t}:{key:t,limit:u}}),{data:K}=I(d.agents.agentThread,()=>({key:r(n)})),M=g===void 0?"skip":()=>({key:r(n)}),{chunks:O}=D(g??P,M),T=l(A),$=l(p??U),b=l(d.agents.agentResolveApproval),[j,h]=N([]);let y=0;const m=i(()=>K()),_=i(()=>m()?.status),c=i(()=>x()??[]),q=i(()=>{const t=c(),a=v(j(),t);if(a.length===0)return t;const e=k(t);return[...t,...a.map((s,o)=>({content:s.content,optimistic:!0,role:"user",seq:e+1+o}))]}),C=i(()=>{const t=r(n),a=c().filter(e=>e.role==="assistant").length;return O().filter(e=>e.kind!=="progress"&&e.threadKey===t&&e.turn>=a).map(e=>e.text).join("")}),E=async(t,a)=>{const e=y;y+=1;const s=k(c());h(o=>[...v(o,c()),{content:t,id:e,maxDurableSeqAtSend:s}]);try{await T.mutate({input:t,threadKey:r(n),...S,...a})}catch(o){throw h(R=>R.filter(F=>F.id!==e)),o}},f=async(t,a,e)=>{const s=m()?.instanceId;if(s===void 0)throw new Error(`createAgentChat: cannot ${t} — no in-flight run (thread has no instanceId)`);await b.mutate({decision:t,instanceId:s,threadKey:r(n),toolCallId:a,...e===void 0?{}:{note:e}})};return{approve:async(t,a)=>f("approve",t,a),cancel:async()=>{const t=m()?.instanceId;p===void 0||t===void 0||await $.mutate({instanceId:t,threadKey:r(n)})},messages:q,reject:async(t,a)=>f("reject",t,a),send:E,status:_,streamingText:C}};export{Q as createAgentChat};
@@ -0,0 +1 @@
1
+ import{createSignal as m,createEffect as p,on as b,onCleanup as y}from"solid-js";import{e as _}from"./stable-key-BSG0zK_E.mjs";import{useLunora as g}from"./LunoraContext-CVOsskhY.mjs";import{resolveMaybe as r}from"./createAgent-BbHVxEpf.mjs";const j="__lunora_flags__:eval",x=t=>{const e=typeof t;return e==="boolean"||e==="number"||e==="string"?e:"object"},d={__lunoraRef:j},h=t=>t===void 0?"":_(t),E=(t,e,s)=>{const f=g(),a=x(e),[l,n]=m(e);return p(b(()=>`${r(t)} ${h(r(s))}`,()=>{const u=r(t),o=r(s);n(()=>e);let c;try{c=f.subscribe(d,{context:o,default:e,key:u,type:a},i=>{n(()=>i)})}catch{return}y(c)})),l},L=(t,e)=>{const s=g(),[f,a]=m(t),l=_(t);return p(b(()=>`${l} ${h(r(e))}`,()=>{const n=r(e);a(()=>t);const u=[];for(const[o,c]of Object.entries(t))try{u.push(s.subscribe(d,{context:n,default:c,key:o,type:x(c)},i=>{a(v=>({...v,[o]:i}))}))}catch{}y(()=>{for(const o of u)o()})})),f};export{E as createFlag,L as createFlags};
@@ -0,0 +1 @@
1
+ import{initialPages as U,derivePaginationStatus as E,applyLoadMore as G,rebalance as H}from"@lunora/client/pagination";import{createMemo as _,createSignal as B,createEffect as F,on as Q,onCleanup as V}from"solid-js";import{e as J}from"./stable-key-BSG0zK_E.mjs";import{useLunora as W}from"./LunoraContext-CVOsskhY.mjs";const N=e=>{let r="";for(let u=0;u<e.length;u+=32768)r+=String.fromCharCode(...e.subarray(u,u+32768));return btoa(r)},c="$lunora.wire$",D=64,X="__proto__",Y=e=>{if(e===null||typeof e!="object")return!1;const r=Object.getPrototypeOf(e);return r===null||r===Object.prototype},b=(e,r=0)=>{if(r>D)throw new RangeError(`wire-codec: value nesting exceeds the ${D}-level limit`);if(e===void 0)return[c,"undefined"];if(e===null)return null;const u=typeof e;if(u==="bigint")return[c,"bigint",e.toString()];if(u==="number"){const t=e;return Number.isNaN(t)?[c,"nan"]:t===1/0?[c,"inf"]:t===-1/0?[c,"-inf"]:t}if(u!=="object")return e;if(e instanceof Date)return[c,"date",b(e.getTime(),r+1)];if(e instanceof Error){const t=e,o={};for(const y of Object.keys(t))t[y]!==void 0&&(o[y]=b(t[y],r+1));const n=[c,"error",t.name,t.message,o];return t.cause!==void 0&&n.push(b(t.cause,r+1)),n}if(e instanceof URL)return[c,"url",e.href];if(e instanceof Map)return[c,"map",[...e.entries()].map(([t,o])=>[b(t,r+1),b(o,r+1)])];if(e instanceof Set)return[c,"set",[...e].map(t=>b(t,r+1))];if(e instanceof ArrayBuffer)return[c,"bytes",N(new Uint8Array(e)),"ArrayBuffer"];if(ArrayBuffer.isView(e)){const t=e,o=t.constructor.name,n=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);return o==="Uint8Array"?[c,"bytes",N(n)]:[c,"bytes",N(n),o]}if(Array.isArray(e)){const t=e.map(o=>b(o,r+1));return t.length>0&&t[0]===c?[c,"arr",t]:t}if(!Y(e)){const t=e.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${t} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const w=e,g={};for(const t of Object.keys(w)){const o=w[t];if(o===void 0)continue;const n=b(o,r+1);t===X?Object.defineProperty(g,t,{configurable:!0,enumerable:!0,value:n,writable:!0}):g[t]=n}return g},Z=e=>J(b(e)),v=(e,r)=>({...r,paginationOpts:{cursor:e.lower,endCursor:e.upper,numItems:e.numItems}}),k=(e,r)=>`${e}::${Z(r)}`,K=(e,r,u)=>{const w=W(),{initialNumItems:g,shardKey:t}=u,o=()=>typeof r=="function"?r():r,[n,y]=B(U(g)),l=new Map,[R,h]=B([]),L=new Map,A=new Set,j=(a,f)=>{const p=a.map(s=>{const i=k(e.__lunoraRef,v(s,f));return l.get(i)});h(p)},T=(a,f,p)=>{const s=i=>k(e.__lunoraRef,v(i,p));for(const i of f){const d=s(i);if(l.has(d))continue;const M=a.find(m=>m.lower===i.lower);if(M){const m=l.get(s(M));m&&l.set(d,m)}}},q=(a,f)=>{const p=new Set;for(const s of a)p.add(k(e.__lunoraRef,v(s,f)));for(const[s,i]of L)p.has(s)||(i(),L.delete(s),A.delete(s),l.delete(s));for(const s of a){const i=v(s,f),d=k(e.__lunoraRef,i);if(L.has(d))continue;A.add(d);const M=w.subscribe(e,i,m=>{l.set(d,m),A.delete(d);const P=o();if(P!=="skip"&&(j(n(),P),A.size===0)){const O=n(),C=H(O,R());C&&(T(O,C,P),y(C))}},{shardKey:t});L.set(d,M)}};let S=!1,$=!1;const x=(a,f)=>{if(S){$=!0;return}S=!0;try{let p=a,s=f;do{$=!1,q(p,s);const i=o();if(i==="skip")break;p=n(),s=i}while($)}finally{S=!1}},I=()=>{for(const a of L.values())a();L.clear(),l.clear(),A.clear()};F(Q(o,a=>{I(),y(U(g)),h([]),a!=="skip"&&(x(n(),a),j(n(),a)),V(I)})),F(Q(n,a=>{const f=o();f!=="skip"&&(x(a,f),j(a,f))}));const z=_(()=>{const a=o()==="skip";return E(a,R()).status});return{loadMore:a=>{const f=o();if(f==="skip")return;const{nextCursor:p,status:s}=E(!1,R());if(s!=="CanLoadMore")return;const i=G(n(),p,a);if(!i)return;const d=n().at(-1),M=i.at(-2);if(d&&M){const m=k(e.__lunoraRef,v(d,f)),P=k(e.__lunoraRef,v(M,f));if(m!==P){const O=l.get(m);O&&l.set(P,O)}}y(i)},pageResults:R,status:z}},ne=(e,r,u)=>{const{loadMore:w,pageResults:g,status:t}=K(e,r,u),o=_(()=>g().flatMap(n=>n?.page??[]));return{isLoading:_(()=>t()==="LoadingFirstPage"||t()==="LoadingMore"),loadMore:w,results:o,status:t}},ae=(e,r,u)=>{const{initialNumItems:w}=u,{loadMore:g,pageResults:t,status:o}=K(e,r,u),n=_(()=>t().flatMap(h=>h?[h.page]:[])),y=_(()=>o()==="LoadingFirstPage"),l=_(()=>o()==="CanLoadMore"),R=_(()=>o()==="LoadingMore");return{fetchNextPage:h=>{g(h??w)},hasNextPage:l,isFetchingNextPage:R,isLoading:y,pages:n,status:o}};export{ae as createInfiniteQuery,ne as createPaginatedQuery};
@@ -1 +1 @@
1
- import{createSignal as w,onCleanup as N}from"solid-js";import{useLunora as O}from"./LunoraContext-CVOsskhY.mjs";import{resolveMaybe as J}from"./createAgent-BbHVxEpf.mjs";const K=t=>{if(t.length===0)return 0;let o=0;for(const n of t)o+=n*n;return Math.sqrt(o/t.length)},z=(t,o)=>{const n=o/16e3,a=n>1?Math.floor(t.length/n):t.length,l=new ArrayBuffer(a*2),i=new DataView(l);for(let u=0;u<a;u+=1){const g=t[Math.floor(u*n)]??0,h=Math.max(-1,Math.min(1,g));i.setInt16(u*2,h<0?h*32768:h*32767,!0)}return new Uint8Array(l)},G=async t=>{const o=globalThis,n=o.navigator?.mediaDevices?.getUserMedia.bind(o.navigator.mediaDevices),a=o.AudioContext??o.webkitAudioContext;if(!n||!a)throw new Error("createVoiceAgent: microphone capture requires getUserMedia + AudioContext (no browser audio available)");const l=await n({audio:{channelCount:1,echoCancellation:!0,noiseSuppression:!0}}),i=new a,u=i.createMediaStreamSource(l),g=i.createScriptProcessor(4096,1,1);let h=!1,y=!1,p=0,d=0;return g.onaudioprocess=s=>{const f=s.inputBuffer.getChannelData(0),k=h?0:K(f);if(t.onLevel(k),h)return;if(t.onAudio(z(f,i.sampleRate)),t.isSpeaking()){d=k>=t.interruptThreshold?d+1:0,d>=t.interruptChunks&&(d=0,t.onInterrupt());return}d=0;const C=f.length/i.sampleRate*1e3;if(k>=t.silenceThreshold){y=!0,p=0;return}y&&(p+=C,p>=t.silenceDurationMs&&(y=!1,p=0,t.onSilence()))},u.connect(g),g.connect(i.destination),{setMuted:s=>{h=s},stop:()=>{g.disconnect(),u.disconnect();for(const s of l.getTracks())s.stop();i.close()}}},H=()=>{const t=globalThis,o=t.AudioContext??t.webkitAudioContext;if(!o)throw new Error("createVoiceAgent: audio playback requires AudioContext (no browser audio available)");const n=new o,a=new Set;let l=0,i=Promise.resolve(),u=0;const g=async(p,d)=>{if(d!==u)return;let s;try{s=await n.decodeAudioData(p.buffer)}catch{return}if(d!==u)return;const f=n.createBufferSource();f.buffer=s,f.connect(n.destination);const k=Math.max(n.currentTime,l);f.start(k),l=k+s.duration,a.add(f),f.onended=()=>{a.delete(f)}},h=p=>{const d=Uint8Array.from(p),s=u;i=i.then(()=>g(d,s))},y=()=>{u+=1;for(const p of a)try{p.stop()}catch{}a.clear(),l=n.currentTime};return{enqueue:h,interrupt:y,stop:()=>{y(),n.close()}}},W=1,Q=.01,X=1200,Y=.15,Z=3,j=t=>t.startsWith("https://")?`wss://${t.slice(8)}`:t.startsWith("http://")?`ws://${t.slice(7)}`:t,ee=t=>{const o=t.__lunoraRef,n=o.startsWith("agents:")?o.slice(7):o;return n.endsWith("Voice")?n.slice(0,-5):n},te=(t,o,n)=>{const a=j(t),l=a.endsWith("/")?a.slice(0,-1):a,i=new URLSearchParams({threadKey:n});return`${l}/_lunora/voice/${encodeURIComponent(o)}?${i.toString()}`},oe=t=>{const{createMicrophone:o=G,createSpeaker:n=H,createSocket:a,interruptChunks:l=Z,interruptThreshold:i=Y,silenceDurationMs:u=X,silenceThreshold:g=Q,threadKey:h,voice:y}=t,p=O(),[d,s]=w("idle"),[f,k]=w(!1),[C,T]=w(""),[_,A]=w(""),[F,D]=w(0),[U,E]=w(!1),[L,S]=w(void 0);let c,v=!1;const x=r=>{const e=c?.socket;return e?.readyState===W?(e.send(JSON.stringify(r)),!0):!1},M=()=>{const r=c;if(c=void 0,r){r.microphone?.stop(),r.speaker?.stop();try{r.socket.close()}catch{}}v=!1,k(!1),s("idle"),D(0)},R=()=>{M()},$=r=>{const e=c;switch(r.type){case"assistant_delta":{e&&(e.speaking=!0),s("speaking"),A(b=>b+r.text);break}case"assistant_done":{e&&(e.speaking=!1),A(r.text),s("listening");break}case"error":{e&&(e.speaking=!1),S(new Error(r.message)),s("listening");break}case"interrupted":{e&&(e.speaking=!1,e.suppressAudio=!1),e?.speaker?.interrupt(),s("listening");break}case"ready":{e&&(e.audioFormat=r.audioFormat,e.suppressAudio=!1),k(!0),s("listening");break}case"user_transcript":{e&&(e.suppressAudio=!1),T(r.text),A(""),s("thinking");break}}},q=r=>{const e=c;!e||e.suppressAudio||(e.speaker??=n({audioFormat:e.audioFormat}),e.speaking=!0,s("speaking"),e.speaker.enqueue(r))},I=async()=>{if(!(c||v)){v=!0,S(void 0),T(""),A("");try{const r=te(p.url,ee(y),J(h)),e=(a??(m=>new globalThis.WebSocket(m)))(r);e.binaryType="arraybuffer";const b={audioFormat:"mp3",microphone:void 0,socket:e,speaker:void 0,speaking:!1,suppressAudio:!1};c=b,e.onmessage=m=>{if(typeof m.data=="string"){try{$(JSON.parse(m.data))}catch{}return}q(new Uint8Array(m.data))},e.onerror=()=>{S(new Error("createVoiceAgent: voice socket error"))},e.onclose=()=>{c===b&&M()};const V=await o({interruptChunks:l,interruptThreshold:i,isSpeaking:()=>c?.speaking??!1,onAudio:m=>{e.readyState===W&&e.send(m)},onInterrupt:()=>{x({type:"interrupt"}),c?.speaker?.interrupt(),c&&(c.speaking=!1,c.suppressAudio=!0),s("listening")},onLevel:m=>{D(m)},onSilence:()=>{x({type:"commit"}),s("thinking")},silenceDurationMs:u,silenceThreshold:g});c===b?(b.microphone=V,E(!1),s("listening")):V.stop()}catch(r){S(r instanceof Error?r:new Error(String(r))),M()}finally{v=!1}}},B=()=>{const r=!U();return c?.microphone?.setMuted(r),E(r),r},P=r=>{x({text:r,type:"text"})&&s("thinking")};return N(M),{audioLevel:F,connected:f,endCall:R,error:L,interimTranscript:_,isMuted:U,sendText:P,startCall:I,status:d,toggleMute:B,transcript:C}};export{oe as createVoiceAgent};
1
+ import{createSignal as w,onCleanup as N}from"solid-js";import{useLunora as O}from"./LunoraContext-CVOsskhY.mjs";import{resolveMaybe as J}from"./createAgent-BbHVxEpf.mjs";const K=t=>{if(t.length===0)return 0;let o=0;for(const n of t)o+=n*n;return Math.sqrt(o/t.length)},z=(t,o)=>{const n=o/16e3,a=n>1?Math.floor(t.length/n):t.length,l=new ArrayBuffer(a*2),i=new DataView(l);for(let u=0;u<a;u+=1){const g=t[Math.floor(u*n)]??0,h=Math.max(-1,Math.min(1,g));i.setInt16(u*2,h<0?h*32768:h*32767,!0)}return new Uint8Array(l)},G=async t=>{const o=globalThis,n=o.navigator?.mediaDevices?.getUserMedia.bind(o.navigator.mediaDevices),a=o.AudioContext??o.webkitAudioContext;if(!n||!a)throw new Error("createVoiceAgent: microphone capture requires getUserMedia + AudioContext (no browser audio available)");const l=await n({audio:{channelCount:1,echoCancellation:!0,noiseSuppression:!0}}),i=new a,u=i.createMediaStreamSource(l),g=i.createScriptProcessor(4096,1,1);let h=!1,y=!1,p=0,d=0;return g.onaudioprocess=s=>{const f=s.inputBuffer.getChannelData(0),k=h?0:K(f);if(t.onLevel(k),h)return;if(t.onAudio(z(f,i.sampleRate)),t.isSpeaking()){d=k>=t.interruptThreshold?d+1:0,d>=t.interruptChunks&&(d=0,t.onInterrupt());return}d=0;const C=f.length/i.sampleRate*1e3;if(k>=t.silenceThreshold){y=!0,p=0;return}y&&(p+=C,p>=t.silenceDurationMs&&(y=!1,p=0,t.onSilence()))},u.connect(g),g.connect(i.destination),{setMuted:s=>{h=s},stop:()=>{g.disconnect(),u.disconnect();for(const s of l.getTracks())s.stop();i.close()}}},H=()=>{const t=globalThis,o=t.AudioContext??t.webkitAudioContext;if(!o)throw new Error("createVoiceAgent: audio playback requires AudioContext (no browser audio available)");const n=new o,a=new Set;let l=0,i=Promise.resolve(),u=0;const g=async(p,d)=>{if(d!==u)return;let s;try{s=await n.decodeAudioData(p.buffer)}catch{return}if(d!==u)return;const f=n.createBufferSource();f.buffer=s,f.connect(n.destination);const k=Math.max(n.currentTime,l);f.start(k),l=k+s.duration,a.add(f),f.onended=()=>{a.delete(f)}},h=p=>{const d=Uint8Array.from(p),s=u;i=i.then(()=>g(d,s))},y=()=>{u+=1;for(const p of a)try{p.stop()}catch{}a.clear(),l=n.currentTime};return{enqueue:h,interrupt:y,stop:()=>{y(),n.close()}}},W=1,Q=.01,X=1200,Y=.15,Z=3,j=t=>t.startsWith("https://")?`wss://${t.slice(8)}`:t.startsWith("http://")?`ws://${t.slice(7)}`:t,ee=t=>{const o=t.__lunoraRef,n=o.startsWith("agents:")?o.slice(7):o;return n.endsWith("Voice")?n.slice(0,-5):n},te=(t,o,n)=>{const a=j(t),l=a.endsWith("/")?a.slice(0,-1):a,i=new URLSearchParams({threadKey:n});return`${l}/_lunora/voice/${encodeURIComponent(o)}?${i.toString()}`},oe=t=>{const{createMicrophone:o=G,createSpeaker:n=H,createSocket:a,interruptChunks:l=Z,interruptThreshold:i=Y,silenceDurationMs:u=X,silenceThreshold:g=Q,threadKey:h,voice:y}=t,p=O(),[d,s]=w("idle"),[f,k]=w(!1),[C,T]=w(""),[_,A]=w(""),[F,D]=w(0),[U,E]=w(!1),[L,S]=w(void 0);let c,v=!1;const x=r=>{const e=c?.socket;return e?.readyState===W?(e.send(JSON.stringify(r)),!0):!1},M=()=>{const r=c;if(c=void 0,r){r.microphone?.stop(),r.speaker?.stop();try{r.socket.close()}catch{}}v=!1,k(!1),s("idle"),D(0)},R=M,$=r=>{const e=c;switch(r.type){case"assistant_delta":{e&&(e.speaking=!0),s("speaking"),A(b=>b+r.text);break}case"assistant_done":{e&&(e.speaking=!1),A(r.text),s("listening");break}case"error":{e&&(e.speaking=!1),S(new Error(r.message)),s("listening");break}case"interrupted":{e&&(e.speaking=!1,e.suppressAudio=!1),e?.speaker?.interrupt(),s("listening");break}case"ready":{e&&(e.audioFormat=r.audioFormat,e.suppressAudio=!1),k(!0),s("listening");break}case"user_transcript":{e&&(e.suppressAudio=!1),T(r.text),A(""),s("thinking");break}}},q=r=>{const e=c;!e||e.suppressAudio||(e.speaker??=n({audioFormat:e.audioFormat}),e.speaking=!0,s("speaking"),e.speaker.enqueue(r))},I=async()=>{if(!(c||v)){v=!0,S(void 0),T(""),A("");try{const r=te(p.url,ee(y),J(h)),e=(a??(m=>new globalThis.WebSocket(m)))(r);e.binaryType="arraybuffer";const b={audioFormat:"mp3",microphone:void 0,socket:e,speaker:void 0,speaking:!1,suppressAudio:!1};c=b,e.onmessage=m=>{if(typeof m.data=="string"){try{$(JSON.parse(m.data))}catch{}return}q(new Uint8Array(m.data))},e.onerror=()=>{S(new Error("createVoiceAgent: voice socket error"))},e.onclose=()=>{c===b&&M()};const V=await o({interruptChunks:l,interruptThreshold:i,isSpeaking:()=>c?.speaking??!1,onAudio:m=>{e.readyState===W&&e.send(m)},onInterrupt:()=>{x({type:"interrupt"}),c?.speaker?.interrupt(),c&&(c.speaking=!1,c.suppressAudio=!0),s("listening")},onLevel:m=>{D(m)},onSilence:()=>{x({type:"commit"}),s("thinking")},silenceDurationMs:u,silenceThreshold:g});c===b?(b.microphone=V,E(!1),s("listening")):V.stop()}catch(r){S(r instanceof Error?r:new Error(String(r))),M()}finally{v=!1}}},B=()=>{const r=!U();return c?.microphone?.setMuted(r),E(r),r},P=r=>{x({text:r,type:"text"})&&s("thinking")};return N(M),{audioLevel:F,connected:f,endCall:R,error:L,interimTranscript:_,isMuted:U,sendText:P,startCall:I,status:d,toggleMute:B,transcript:C}};export{oe as createVoiceAgent};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/solid",
3
- "version": "1.0.0-alpha.41",
3
+ "version": "1.0.0-alpha.42",
4
4
  "description": "SolidJS adapter for Lunora — live queries, 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.40",
58
- "@lunora/errors": "1.0.0-alpha.14",
59
- "@lunora/ratelimit": "1.0.0-alpha.17",
57
+ "@lunora/client": "1.0.0-alpha.41",
58
+ "@lunora/errors": "1.0.0-alpha.15",
59
+ "@lunora/ratelimit": "1.0.0-alpha.18",
60
60
  "@visulima/storage-client": "1.0.0"
61
61
  },
62
62
  "peerDependencies": {
@@ -1 +0,0 @@
1
- import{reconcileOptimistic as v,maxSeq as I}from"@lunora/client";import{createSignal as N,createMemo as s}from"solid-js";import{resolveMaybe as r,NO_MUTATION_REF as R}from"./createAgent-BbHVxEpf.mjs";import{createMutation as l}from"./createMutation-9i34uh8U.mjs";import{createStream as D}from"./createStream-DozkYNOc.mjs";import{createSubscription as w}from"./createSubscription-KbQk0ohZ.mjs";const F={__lunoraRef:""},H=k=>{const{api:d,cancel:p,limit:h,send:A,sendArgs:K,stream:u,threadKey:n}=k,{data:S}=w(d.agents.agentMessages,()=>{const t=r(n);return h===void 0?{key:t}:{key:t,limit:h}}),{data:x}=w(d.agents.agentThread,()=>({key:r(n)})),M=u===void 0?"skip":()=>({key:r(n)}),{chunks:C}=D(u??F,M),O=l(A),T=l(p??R),g=l(d.agents.agentResolveApproval),[$,f]=N([]);let y=0;const i=s(()=>x()),b=s(()=>i()?.status),c=s(()=>S()??[]),j=s(()=>{const t=c(),a=v($(),t);if(a.length===0)return t;const e=I(t);return[...t,...a.map((m,o)=>({content:m.content,optimistic:!0,role:"user",seq:e+1+o}))]}),E=s(()=>{const t=r(n),a=c().filter(e=>e.role==="assistant").length;return C().filter(e=>e.kind!=="progress"&&e.threadKey===t&&e.turn>=a).map(e=>e.text).join("")});return{approve:async(t,a)=>{const e=i()?.instanceId;if(e===void 0)throw new Error("createAgentChat: cannot approve — no in-flight run (thread has no instanceId)");await g.mutate({decision:"approve",instanceId:e,threadKey:r(n),toolCallId:t,...a===void 0?{}:{note:a}})},cancel:async()=>{const t=i()?.instanceId;p===void 0||t===void 0||await T.mutate({instanceId:t,threadKey:r(n)})},messages:j,reject:async(t,a)=>{const e=i()?.instanceId;if(e===void 0)throw new Error("createAgentChat: cannot reject — no in-flight run (thread has no instanceId)");await g.mutate({decision:"reject",instanceId:e,threadKey:r(n),toolCallId:t,...a===void 0?{}:{note:a}})},send:async(t,a)=>{const e=y;y+=1;const m=I(c());f(o=>[...v(o,c()),{content:t,id:e,maxDurableSeqAtSend:m}]);try{await O.mutate({input:t,threadKey:r(n),...K,...a})}catch(o){throw f(_=>_.filter(q=>q.id!==e)),o}},status:b,streamingText:E}};export{H as createAgentChat};
@@ -1 +0,0 @@
1
- import{createSignal as p,createEffect as b,on as y,onCleanup as _}from"solid-js";import{e as m}from"./stable-key-BSG0zK_E.mjs";import{useLunora as g}from"./LunoraContext-CVOsskhY.mjs";const j="__lunora_flags__:eval",x=t=>{const o=typeof t;return o==="boolean"||o==="number"||o==="string"?o:"object"},d={__lunoraRef:j},e=t=>typeof t=="function"?t():t,h=t=>t===void 0?"":m(t),A=(t,o,n)=>{const f=g(),a=x(o),[l,s]=p(o);return b(y(()=>`${e(t)} ${h(e(n))}`,()=>{const u=e(t),r=e(n);s(()=>o);let c;try{c=f.subscribe(d,{context:r,default:o,key:u,type:a},i=>{s(()=>i)})}catch{return}_(c)})),l},E=(t,o)=>{const n=g(),[f,a]=p(t),l=m(t);return b(y(()=>`${l} ${h(e(o))}`,()=>{const s=e(o);a(()=>t);const u=[];for(const[r,c]of Object.entries(t))try{u.push(n.subscribe(d,{context:s,default:c,key:r,type:x(c)},i=>{a(k=>({...k,[r]:i}))}))}catch{}_(()=>{for(const r of u)r()})})),f};export{A as createFlag,E as createFlags};
@@ -1 +0,0 @@
1
- import{initialPages as U,derivePaginationStatus as E,applyLoadMore as G,rebalance as H}from"@lunora/client/pagination";import{createMemo as L,createSignal as F,createEffect as B,on as Q,onCleanup as V}from"solid-js";import{e as J}from"./stable-key-BSG0zK_E.mjs";import{useLunora as W}from"./LunoraContext-CVOsskhY.mjs";const N=e=>{let r="";for(let f=0;f<e.length;f+=32768)r+=String.fromCharCode(...e.subarray(f,f+32768));return btoa(r)},c="$lunora.wire$",D=64,X="__proto__",Y=e=>{if(e===null||typeof e!="object")return!1;const r=Object.getPrototypeOf(e);return r===null||r===Object.prototype},w=(e,r=0)=>{if(r>D)throw new RangeError(`wire-codec: value nesting exceeds the ${D}-level limit`);if(e===void 0)return[c,"undefined"];if(e===null)return null;const f=typeof e;if(f==="bigint")return[c,"bigint",e.toString()];if(f==="number"){const t=e;return Number.isNaN(t)?[c,"nan"]:t===1/0?[c,"inf"]:t===-1/0?[c,"-inf"]:t}if(f!=="object")return e;if(e instanceof Date)return[c,"date",w(e.getTime(),r+1)];if(e instanceof Error){const t=e,o={};for(const l of Object.keys(t))t[l]!==void 0&&(o[l]=w(t[l],r+1));const n=[c,"error",t.name,t.message,o];return t.cause!==void 0&&n.push(w(t.cause,r+1)),n}if(e instanceof URL)return[c,"url",e.href];if(e instanceof Map)return[c,"map",[...e.entries()].map(([t,o])=>[w(t,r+1),w(o,r+1)])];if(e instanceof Set)return[c,"set",[...e].map(t=>w(t,r+1))];if(e instanceof ArrayBuffer)return[c,"bytes",N(new Uint8Array(e)),"ArrayBuffer"];if(ArrayBuffer.isView(e)){const t=e,o=t.constructor.name,n=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);return o==="Uint8Array"?[c,"bytes",N(n)]:[c,"bytes",N(n),o]}if(Array.isArray(e)){const t=e.map(o=>w(o,r+1));return t.length>0&&t[0]===c?[c,"arr",t]:t}if(!Y(e)){const t=e.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${t} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const h=e,m={};for(const t of Object.keys(h)){const o=h[t];if(o===void 0)continue;const n=w(o,r+1);t===X?Object.defineProperty(m,t,{configurable:!0,enumerable:!0,value:n,writable:!0}):m[t]=n}return m},Z=e=>J(w(e)),k=(e,r)=>({...r,paginationOpts:{cursor:e.lower,endCursor:e.upper,numItems:e.numItems}}),A=(e,r)=>`${e}::${Z(r)}`,K=(e,r,f)=>{const h=W(),{initialNumItems:m,shardKey:t}=f,o=()=>typeof r=="function"?r():r,[n,l]=F(U(m)),p=new Map,[P,_]=F([]),y=new Map,R=new Set,j=(a,u)=>{const d=a.map(s=>{const i=A(e.__lunoraRef,k(s,u));return p.get(i)});_(d)},T=(a,u,d)=>{const s=i=>A(e.__lunoraRef,k(i,d));for(const i of u){const g=s(i);if(p.has(g))continue;const M=a.find(b=>b.lower===i.lower);if(M){const b=p.get(s(M));b&&p.set(g,b)}}},q=(a,u)=>{const d=new Set;for(const s of a)d.add(A(e.__lunoraRef,k(s,u)));for(const[s,i]of y)d.has(s)||(i(),y.delete(s),R.delete(s),p.delete(s));for(const s of a){const i=k(s,u),g=A(e.__lunoraRef,i);if(y.has(g))continue;R.add(g);const M=h.subscribe(e,i,b=>{p.set(g,b),R.delete(g);const v=o();if(v!=="skip"&&(j(n(),v),R.size===0)){const O=n(),C=H(O,P());C&&(T(O,C,v),l(C))}},{shardKey:t});y.set(g,M)}};let S=!1,$=!1;const x=(a,u)=>{if(S){$=!0;return}S=!0;try{let d=a,s=u;do{$=!1,q(d,s);const i=o();if(i==="skip")break;d=n(),s=i}while($)}finally{S=!1}},I=()=>{for(const a of y.values())a();y.clear(),p.clear(),R.clear()};B(Q(o,a=>{I(),l(U(m)),_([]),a!=="skip"&&(x(n(),a),j(n(),a)),V(I)})),B(Q(n,a=>{const u=o();u!=="skip"&&(x(a,u),j(a,u))}));const z=L(()=>{const a=o()==="skip";return E(a,P()).status});return{loadMore:a=>{const u=o();if(u==="skip")return;const{nextCursor:d,status:s}=E(!1,P());if(s!=="CanLoadMore")return;const i=G(n(),d,a);if(!i)return;const g=n().at(-1),M=i.at(-2);if(g&&M){const b=A(e.__lunoraRef,k(g,u)),v=A(e.__lunoraRef,k(M,u));if(b!==v){const O=p.get(b);O&&p.set(v,O)}}l(i)},pageResults:P,status:z}},ne=(e,r,f)=>{const{loadMore:h,pageResults:m,status:t}=K(e,r,f),o=L(()=>{const n=[];for(const l of m())l&&n.push(...l.page);return n});return{isLoading:L(()=>t()==="LoadingFirstPage"||t()==="LoadingMore"),loadMore:h,results:o,status:t}},ae=(e,r,f)=>{const{initialNumItems:h}=f,{loadMore:m,pageResults:t,status:o}=K(e,r,f),n=L(()=>{const _=[];for(const y of t())y&&_.push(y.page);return _}),l=L(()=>o()==="LoadingFirstPage"),p=L(()=>o()==="CanLoadMore"),P=L(()=>o()==="LoadingMore");return{fetchNextPage:_=>{m(_??h)},hasNextPage:p,isFetchingNextPage:P,isLoading:l,pages:n,status:o}};export{ae as createInfiniteQuery,ne as createPaginatedQuery};