@lumavox/client 0.14.0 → 0.15.1

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/README.md CHANGED
@@ -91,7 +91,7 @@ key, dials, authenticates, and from then on:
91
91
 
92
92
  | Handler | Frame |
93
93
  |---|---|
94
- | `onReady` `onTurnStart` `onHeard` `onHeardPartial` `onKnowledge` `onMood` `onThought` `onText` `onChunk` `onToolStart` `onToolEnd` `onToolConfirm` `onUsage` `onMuted` `onAudioStart` `onAudioEnd` `onTranscript` `onDone` `onInterrupted` `onError` | the wire's frame, as it is |
94
+ | `onReady` `onTurnStart` `onHeard` `onHeardPartial` `onKnowledge` `onMood` `onThought` `onText` `onChunk` `onToolStart` `onToolEnd` `onToolConfirm` `onUsage` `onMuted` `onAudioStart` `onAudioEnd` `onTranscript` `onCompacted` `onDone` `onInterrupted` `onError` | the wire's frame, as it is |
95
95
  | `onAudio` | `{ pcm, chunk, turn, sample_rate, channels }`: raw 16-bit PCM, never copied |
96
96
  | `onRelation` | the relationship, each change once |
97
97
  | `onState` | `connecting` `ready` `busy` `reconnecting` `dormant` `closed` |
package/dist/client.d.ts CHANGED
@@ -80,7 +80,8 @@ export interface Sessions {
80
80
  export interface FactListParams {
81
81
  /**
82
82
  * Also the facts a later conversation replaced or removed, each with
83
- * `replaced_at`, until they are deleted 30 days later.
83
+ * `replaced_at`, until they are deleted — the platform's
84
+ * `agents.memory.facts.replaced_kept_days` later (its Limits page).
84
85
  */
85
86
  include_replaced?: boolean;
86
87
  }
@@ -157,6 +157,8 @@ export interface ConversationHandlers {
157
157
  onInterrupted?: On<"interrupted">;
158
158
  /** The relationship, from `ready` and when it moves: each change once. */
159
159
  onRelation?: (relation: RelationInfo) => void;
160
+ /** The conversation was compacted, after a reply: its transcript is unchanged. */
161
+ onCompacted?: On<"compacted">;
160
162
  onError?: On<"error">;
161
163
  onState?: (state: ConversationState) => void;
162
164
  /** Only when it will **not** reconnect. */
@@ -33,6 +33,7 @@ const HANDLER = {
33
33
  "audio.start": "onAudioStart",
34
34
  "audio.end": "onAudioEnd",
35
35
  transcript: "onTranscript",
36
+ compacted: "onCompacted",
36
37
  "turn.done": "onDone",
37
38
  interrupted: "onInterrupted",
38
39
  error: "onError",
package/dist/events.d.ts CHANGED
@@ -142,7 +142,10 @@ export interface ToolCall {
142
142
  name: string;
143
143
  kind: "webhook" | "app";
144
144
  arguments: Record<string, unknown>;
145
- /** What it answered, as the model read it (16 KB at most); `null` for none. */
145
+ /**
146
+ * What it answered, as the model read it — at most the platform's
147
+ * `agents.tools.result_max_bytes` (its Limits page); `null` for none.
148
+ */
146
149
  result: unknown;
147
150
  ok: boolean;
148
151
  /** What failed, as the model was told; `null` when nothing did. */
@@ -179,6 +182,18 @@ export interface MutedFrame extends Frame<"muted">, InTurn {
179
182
  /** The relationship moved on this turn: its new fields. */
180
183
  export interface RelationFrame extends Frame<"relation">, InTurn, RelationInfo {
181
184
  }
185
+ /**
186
+ * The conversation was compacted — the agent's own past its threshold, a
187
+ * pass of a long one, or one asked for — after a reply, never in one: its
188
+ * next turn starts from a summary through `after_seq`, then the messages
189
+ * after it word for word. Not part of any turn.
190
+ */
191
+ export interface CompactedFrame extends Frame<"compacted"> {
192
+ session_id: string;
193
+ /** The last message the summary covers. */
194
+ after_seq: number;
195
+ trigger: "automatic" | "manual";
196
+ }
182
197
  export interface UsageFrame extends Frame<"usage">, InTurn {
183
198
  model: string;
184
199
  input_tokens: number;
@@ -279,6 +294,7 @@ export type ServerFrames = Exhaustive<{
279
294
  "audio.end": AudioEndFrame;
280
295
  muted: MutedFrame;
281
296
  relation: RelationFrame;
297
+ compacted: CompactedFrame;
282
298
  usage: UsageFrame;
283
299
  "turn.done": TurnDoneFrame;
284
300
  interrupted: InterruptedFrame;
@@ -146,7 +146,7 @@ export type MessageToolCall = {
146
146
  [key: string]: unknown;
147
147
  };
148
148
  /**
149
- * What it answered, as the model read it — its JSON, or its text, cut at 16 KB. Null when it answered nothing.
149
+ * What it answered, as the model read it — its JSON, or its text, cut at the platform's `agents.tools.result_max_bytes` (`GET /v1/platform/limits`). Null when it answered nothing.
150
150
  */
151
151
  result?: unknown;
152
152
  /**
@@ -235,7 +235,7 @@ export type SessionCreateRequest = {
235
235
  /**
236
236
  * Whether to continue this person's most recent conversation with this agent instead of starting a new one.
237
237
  *
238
- * **Unset is the useful default**: it resumes when this person has a conversation with this agent from the last 7 days to continue, and starts a new one otherwise. That matches what 'open a conversation with this person' usually means, and it stops an integration that opens a session per page load from scattering somebody's history across a dozen fragments.
238
+ * **Unset is the useful default**: it resumes when this person has a conversation with this agent young enough to continue — within the organisation's `resume_max_age_days`, else the platform's `agents.sessions.resume_max_age_days` (`GET /v1/platform/limits`) — and starts a new one otherwise. That matches what 'open a conversation with this person' usually means, and it stops an integration that opens a session per page load from scattering somebody's history across a dozen fragments.
239
239
  *
240
240
  * `false` always starts a new conversation — this is what a 'new chat' button should send. `true` is the same as leaving it unset; it exists so the intent can be stated rather than implied.
241
241
  *
@@ -270,7 +270,7 @@ export type SessionInfo = {
270
270
  };
271
271
  export type CompactionInfo = {
272
272
  /**
273
- * The last message this summary covers. Anything after it is still sent to the model verbatim.
273
+ * The last message this summary covers. Anything after it — the last few exchanges, kept word for word, then whatever is said next — is still sent to the model verbatim.
274
274
  */
275
275
  after_seq: number;
276
276
  /**
@@ -289,7 +289,7 @@ export type CompactionInfo = {
289
289
  */
290
290
  summary: string;
291
291
  /**
292
- * `manual` (a client asked), `automatic` (a turn reached the agent's threshold) or `idle` (the conversation went quiet and its facts were extracted).
292
+ * `manual` (a client asked) or `automatic` (a turn reached the agent's threshold, or a long compaction's next pass). `idle` is no longer written: it marks compactions made when a quiet conversation's facts were read, before facts were read on their own.
293
293
  */
294
294
  trigger: 'manual' | 'automatic' | 'idle';
295
295
  };
@@ -553,6 +553,10 @@ export type CompactSessionErrors = {
553
553
  * Missing or invalid credentials
554
554
  */
555
555
  401: ErrorResponse;
556
+ /**
557
+ * The key has spent its credit — mint another; nothing was charged
558
+ */
559
+ 402: ErrorResponse;
556
560
  /**
557
561
  * The key is valid but its scopes do not cover this capability
558
562
  */
@@ -566,7 +570,7 @@ export type CompactSessionErrors = {
566
570
  */
567
571
  409: ErrorResponse;
568
572
  /**
569
- * The request failed validation
573
+ * Nothing new to compact since the last compaction, or the model's summary was empty or no shorter than what it would replace; nothing was charged
570
574
  */
571
575
  422: ErrorResponse;
572
576
  /**
@@ -603,6 +607,10 @@ export type ExtractSessionFactsErrors = {
603
607
  * Missing or invalid credentials
604
608
  */
605
609
  401: ErrorResponse;
610
+ /**
611
+ * The key has spent its credit — mint another; nothing was charged
612
+ */
613
+ 402: ErrorResponse;
606
614
  /**
607
615
  * The key is valid but its scopes do not cover this capability
608
616
  */
@@ -616,7 +624,7 @@ export type ExtractSessionFactsErrors = {
616
624
  */
617
625
  409: ErrorResponse;
618
626
  /**
619
- * The request failed validation
627
+ * Nothing new to compact since the last compaction, or the model's summary was empty or no shorter than what it would replace; nothing was charged
620
628
  */
621
629
  422: ErrorResponse;
622
630
  /**
@@ -686,7 +694,7 @@ export type ListFactsData = {
686
694
  */
687
695
  end_user_id?: string;
688
696
  /**
689
- * Also list the facts a later conversation replaced or removed, until they are deleted 30 days later.
697
+ * Also list the facts a later conversation replaced or removed, until they are deleted, the platform's `agents.memory.facts.replaced_kept_days` later (`GET /v1/platform/limits`).
690
698
  */
691
699
  include_replaced?: boolean;
692
700
  /**
@@ -4,7 +4,7 @@ export declare const PROTOCOL = "ino.v2";
4
4
  export declare const CLIENT_VERBS: readonly ["auth", "user_message", "user_audio.start", "user_audio.end", "cancel", "mute", "ping", "tool.confirmed", "tool.result"];
5
5
  export type ClientVerb = (typeof CLIENT_VERBS)[number];
6
6
  /** Every event the edge sends. */
7
- export declare const SERVER_EVENTS: readonly ["ready", "turn.start", "heard", "heard.partial", "barge_in", "transcript", "mood", "text.delta", "text.chunk", "thought.delta", "tool.start", "tool.end", "tool.call", "tool.confirm", "knowledge", "audio.start", "audio.end", "muted", "relation", "usage", "turn.done", "interrupted", "error", "pong"];
7
+ export declare const SERVER_EVENTS: readonly ["ready", "turn.start", "heard", "heard.partial", "barge_in", "transcript", "mood", "text.delta", "text.chunk", "thought.delta", "tool.start", "tool.end", "tool.call", "tool.confirm", "knowledge", "audio.start", "audio.end", "muted", "relation", "compacted", "usage", "turn.done", "interrupted", "error", "pong"];
8
8
  export type ServerEventName = (typeof SERVER_EVENTS)[number];
9
9
  /** The events that end a turn: exactly one of them ends every turn. */
10
10
  export declare const TERMINAL_EVENTS: readonly ["turn.done", "interrupted"];
@@ -7,7 +7,7 @@ export const PROTOCOL = "ino.v2";
7
7
  /** Every frame a client may send; the edge closes on any other (4009). */
8
8
  export const CLIENT_VERBS = ["auth", "user_message", "user_audio.start", "user_audio.end", "cancel", "mute", "ping", "tool.confirmed", "tool.result"];
9
9
  /** Every event the edge sends. */
10
- export const SERVER_EVENTS = ["ready", "turn.start", "heard", "heard.partial", "barge_in", "transcript", "mood", "text.delta", "text.chunk", "thought.delta", "tool.start", "tool.end", "tool.call", "tool.confirm", "knowledge", "audio.start", "audio.end", "muted", "relation", "usage", "turn.done", "interrupted", "error", "pong"];
10
+ export const SERVER_EVENTS = ["ready", "turn.start", "heard", "heard.partial", "barge_in", "transcript", "mood", "text.delta", "text.chunk", "thought.delta", "tool.start", "tool.end", "tool.call", "tool.confirm", "knowledge", "audio.start", "audio.end", "muted", "relation", "compacted", "usage", "turn.done", "interrupted", "error", "pong"];
11
11
  /** The events that end a turn: exactly one of them ends every turn. */
12
12
  export const TERMINAL_EVENTS = ["turn.done", "interrupted"];
13
13
  /** A `ping` of exactly this text is answered by the edge's runtime with `KEEPALIVE_PONG`, which has no `seq`. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumavox/client",
3
- "version": "0.14.0",
3
+ "version": "0.15.1",
4
4
  "description": "Talk to Lumavox agents from a browser, a React Native app or Node, with an end user's ephemeral key: conversations on the agent's socket, sessions, memory and relations. Zero dependencies.",
5
5
  "license": "MIT",
6
6
  "type": "module",