@robota-sdk/agent-transport 3.0.0-beta.96 → 3.0.0-beta.99

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robota-sdk/agent-transport",
3
- "version": "3.0.0-beta.96",
3
+ "version": "3.0.0-beta.99",
4
4
  "description": "Carrier-neutral wire protocol, session dispatch and delivery for Robota SDK transports",
5
5
  "type": "module",
6
6
  "main": "dist/node/index.js",
@@ -80,13 +80,13 @@
80
80
  ],
81
81
  "dependencies": {
82
82
  "jose": "6.2.3",
83
- "@robota-sdk/agent-core": "3.0.0-beta.96",
84
- "@robota-sdk/agent-interface-analytics": "3.0.0-beta.96",
85
- "@robota-sdk/agent-interface-command": "3.0.0-beta.96",
86
- "@robota-sdk/agent-interface-execution": "3.0.0-beta.96",
87
- "@robota-sdk/agent-interface-session": "3.0.0-beta.96",
88
- "@robota-sdk/agent-interface-session-mobility": "3.0.0-beta.96",
89
- "@robota-sdk/agent-interface-transport": "3.0.0-beta.96"
83
+ "@robota-sdk/agent-core": "3.0.0-beta.99",
84
+ "@robota-sdk/agent-interface-analytics": "3.0.0-beta.99",
85
+ "@robota-sdk/agent-interface-command": "3.0.0-beta.99",
86
+ "@robota-sdk/agent-interface-execution": "3.0.0-beta.99",
87
+ "@robota-sdk/agent-interface-session": "3.0.0-beta.99",
88
+ "@robota-sdk/agent-interface-session-mobility": "3.0.0-beta.99",
89
+ "@robota-sdk/agent-interface-transport": "3.0.0-beta.99"
90
90
  },
91
91
  "devDependencies": {
92
92
  "rimraf": "^5.0.10",
@@ -838,3 +838,33 @@ describe('decodeFrame — the one carrier path', () => {
838
838
  });
839
839
  });
840
840
  });
841
+
842
+ describe('completed compaction metadata', () => {
843
+ it('accepts both a legacy history change and the optional typed completion', () => {
844
+ for (const message of [
845
+ { type: 'history_changed' },
846
+ {
847
+ type: 'history_changed',
848
+ compact: { trigger: 'auto', beforeUsedPercentage: 90.5, afterUsedPercentage: 20 },
849
+ },
850
+ {
851
+ type: 'history_changed',
852
+ compact: { trigger: 'manual', beforeUsedPercentage: 10, afterUsedPercentage: 2 },
853
+ },
854
+ ]) {
855
+ expect(decodeServerMessage(message)).toEqual({ ok: true, message });
856
+ }
857
+ });
858
+
859
+ it.each([
860
+ null,
861
+ [],
862
+ {},
863
+ { trigger: 'unknown', beforeUsedPercentage: 90, afterUsedPercentage: 20 },
864
+ { trigger: 'auto', beforeUsedPercentage: '90', afterUsedPercentage: 20 },
865
+ { trigger: 'auto', beforeUsedPercentage: 90, afterUsedPercentage: NaN },
866
+ { trigger: 'auto', beforeUsedPercentage: Infinity, afterUsedPercentage: 20 },
867
+ ])('refuses malformed completion metadata %j', (compact) => {
868
+ expect(decodeServerMessage({ type: 'history_changed', compact }).ok).toBe(false);
869
+ });
870
+ });
@@ -303,7 +303,7 @@ describe('pushed session state (#3189)', () => {
303
303
  expect(client.sent).toEqual([{ type: 'context', state }]);
304
304
  });
305
305
 
306
- it.each(['compact', 'skill_activation', 'memory_event'])(
306
+ it.each(['skill_activation', 'memory_event'])(
307
307
  'tells the client the history changed on %s, without sending the entries',
308
308
  (event) => {
309
309
  const session = createSession();
@@ -315,6 +315,25 @@ describe('pushed session state (#3189)', () => {
315
315
  },
316
316
  );
317
317
 
318
+ it('preserves completed compaction metadata without sending or replacing history entries', () => {
319
+ const session = createSession();
320
+ const client = attach(session);
321
+ session.emit('compact', {
322
+ trigger: 'auto',
323
+ before: { usedTokens: 900, maxTokens: 1000, usedPercentage: 90, remainingPercentage: 10 },
324
+ after: { usedTokens: 200, maxTokens: 1000, usedPercentage: 20, remainingPercentage: 80 },
325
+ });
326
+ expect(client.sent).toEqual([
327
+ {
328
+ type: 'history_changed',
329
+ compact: { trigger: 'auto', beforeUsedPercentage: 90, afterUsedPercentage: 20 },
330
+ },
331
+ ]);
332
+ client.leave();
333
+ session.emit('compact', { trigger: 'auto' });
334
+ expect(client.sent).toHaveLength(1);
335
+ });
336
+
318
337
  it('delivers where a turn came from', () => {
319
338
  const session = createSession();
320
339
  const client = attach(session);
@@ -330,12 +349,15 @@ describe('pushed session state (#3189)', () => {
330
349
  const state = { usedTokens: 1, maxTokens: 10, usedPercentage: 10, remainingPercentage: 90 };
331
350
 
332
351
  session.emit('context_update', state);
333
- session.emit('compact', {});
352
+ session.emit('compact', { trigger: 'auto', before: state, after: state });
334
353
  session.emit('turn_source', 'user');
335
354
 
336
355
  expect(observer.sent).toEqual([
337
356
  { type: 'context', state },
338
- { type: 'history_changed' },
357
+ {
358
+ type: 'history_changed',
359
+ compact: { trigger: 'auto', beforeUsedPercentage: 10, afterUsedPercentage: 10 },
360
+ },
339
361
  { type: 'turn_source', source: 'user' },
340
362
  ]);
341
363
  });
@@ -324,7 +324,15 @@ export const SERVER_MESSAGE_SHAPES: Readonly<Record<TServerMessage['type'], TVar
324
324
  messages: { messages: isRecordArray, display: isOptional(isRecordArray), ...authored },
325
325
  history: { startIndex: isCount, total: isCount, entries: isWireHistoryEntries },
326
326
  context: { state: isRecord },
327
- history_changed: {},
327
+ history_changed: {
328
+ compact: isOptional(
329
+ (value) =>
330
+ isRecord(value) &&
331
+ oneOf(['auto', 'manual'])(value['trigger']) &&
332
+ isFiniteNumber(value['beforeUsedPercentage']) &&
333
+ isFiniteNumber(value['afterUsedPercentage']),
334
+ ),
335
+ },
328
336
  turn_source: { source: oneOf(Object.keys(TURN_SOURCES)) },
329
337
  commands: { commands: isRecordArray, skills: isRecordArray },
330
338
  session_status: { status: isRecord },
@@ -25,6 +25,7 @@ import type {
25
25
  import type {
26
26
  IAskRequestEvent,
27
27
  IBranchEvent,
28
+ ICompactEvent,
28
29
  IContextFileRefreshedEvent,
29
30
  IExecutionResult,
30
31
  IPermissionRequestEvent,
@@ -203,6 +204,15 @@ export function subscribeSessionEvents(
203
204
  const onContextUpdate = (state: ReturnType<IProtocolSession['getContextState']>): void =>
204
205
  deliver({ type: 'context', state });
205
206
  const onHistoryChanged = (): void => deliver({ type: 'history_changed' });
207
+ const onCompact = (event: ICompactEvent): void =>
208
+ deliver({
209
+ type: 'history_changed',
210
+ compact: {
211
+ trigger: event.trigger,
212
+ beforeUsedPercentage: event.before.usedPercentage,
213
+ afterUsedPercentage: event.after.usedPercentage,
214
+ },
215
+ });
206
216
  const onTurnSource = (source: TTurnSource): void => deliver({ type: 'turn_source', source });
207
217
  // One client's `/mode` or `/model` shows on every client on this session, in the frame
208
218
  // `get-status` answers with.
@@ -233,7 +243,7 @@ export function subscribeSessionEvents(
233
243
  session.on('history_cleared', onHistoryCleared);
234
244
  session.on('session_switched', onSessionSwitched);
235
245
  session.on('context_update', onContextUpdate);
236
- session.on('compact', onHistoryChanged);
246
+ session.on('compact', onCompact);
237
247
  session.on('skill_activation', onHistoryChanged);
238
248
  session.on('memory_event', onHistoryChanged);
239
249
  session.on('turn_source', onTurnSource);
@@ -264,7 +274,7 @@ export function subscribeSessionEvents(
264
274
  session.off('history_cleared', onHistoryCleared);
265
275
  session.off('session_switched', onSessionSwitched);
266
276
  session.off('context_update', onContextUpdate);
267
- session.off('compact', onHistoryChanged);
277
+ session.off('compact', onCompact);
268
278
  session.off('skill_activation', onHistoryChanged);
269
279
  session.off('memory_event', onHistoryChanged);
270
280
  session.off('turn_source', onTurnSource);
@@ -32,6 +32,7 @@ import type {
32
32
  import type {
33
33
  IAskRequestEvent,
34
34
  IBranchEvent,
35
+ ICompactEvent,
35
36
  IExecutionResult,
36
37
  IContextFileRefreshedEvent,
37
38
  IModelListGroup,
@@ -270,7 +271,15 @@ export type TServerMessage =
270
271
  | { type: 'context'; state: ReturnType<ISessionConversationRead['getContextState']> }
271
272
  // #3189: the full history gained entries that no streamed frame carries (a compaction, a skill
272
273
  // activation, a memory event). A client that shows the full history re-reads it with `get-history`.
273
- | { type: 'history_changed' }
274
+ | {
275
+ type: 'history_changed';
276
+ /** A completed compaction, for clients that do not render the full system history. */
277
+ compact?: {
278
+ trigger: ICompactEvent['trigger'];
279
+ beforeUsedPercentage: number;
280
+ afterUsedPercentage: number;
281
+ };
282
+ }
274
283
  // #3189: where the turn now starting came from (the user, a wake-up, a peer, an external event).
275
284
  | { type: 'turn_source'; source: TTurnSource }
276
285
  | { type: 'commands'; commands: ICommandListEntry[]; skills: ICommandSkillListEntry[] }
@@ -1 +0,0 @@
1
- {"version":3,"file":"observer-messages-DoWb6RNv.d.ts","names":[],"sources":["../../src/wire-messages.ts","../../src/message-decoders.ts","../../src/observer-messages.ts"],"mappings":"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"}