@robota-sdk/agent-command 3.0.0-beta.70 → 3.0.0-beta.71

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-command",
3
- "version": "3.0.0-beta.70",
3
+ "version": "3.0.0-beta.71",
4
4
  "description": "Consolidated command module implementations for Robota SDK CLI",
5
5
  "type": "module",
6
6
  "main": "dist/node/index.js",
@@ -24,8 +24,8 @@
24
24
  "src"
25
25
  ],
26
26
  "dependencies": {
27
- "@robota-sdk/agent-core": "3.0.0-beta.70",
28
- "@robota-sdk/agent-framework": "3.0.0-beta.70"
27
+ "@robota-sdk/agent-core": "3.0.0-beta.71",
28
+ "@robota-sdk/agent-framework": "3.0.0-beta.71"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "^22.14.0",
@@ -28,6 +28,7 @@ function createSessionRuntime(): ICommandSessionRuntime {
28
28
  getSessionAllowedTools: () => [],
29
29
  getAutoCompactThreshold: () => false,
30
30
  getFullHistory: () => [],
31
+ getHistory: () => [],
31
32
  };
32
33
  }
33
34
 
@@ -36,6 +36,7 @@ function createRuntime(beforeCount = 10, afterCount = 3): ICommandSessionRuntime
36
36
  getSessionAllowedTools: () => [],
37
37
  getAutoCompactThreshold: () => 0.835,
38
38
  getFullHistory: () => [],
39
+ getHistory: () => [],
39
40
  };
40
41
  }
41
42
 
@@ -76,6 +76,7 @@ function createRuntime(
76
76
  getSessionAllowedTools: () => [],
77
77
  getAutoCompactThreshold: () => state.threshold,
78
78
  getFullHistory: () => history,
79
+ getHistory: () => [],
79
80
  setAutoCompactThreshold: (threshold) => {
80
81
  state.threshold = threshold;
81
82
  },
@@ -12,7 +12,7 @@ import {
12
12
  writeAutoCompactThresholdSetting,
13
13
  } from '@robota-sdk/agent-framework';
14
14
 
15
- import type { IHistoryEntry } from '@robota-sdk/agent-core';
15
+ import type { IHistoryEntry, TUniversalMessage } from '@robota-sdk/agent-core';
16
16
  import type {
17
17
  ICommandHostContext,
18
18
  ICommandResult,
@@ -65,14 +65,14 @@ export async function executeContextCommand(
65
65
  const autoCompactThreshold = readAutoCompactThreshold(context);
66
66
  const autoCompactThresholdSource = readAutoCompactThresholdSource(context);
67
67
  const history = context.getSession().getFullHistory();
68
- const analysis = analyzeHistory(history);
68
+ const display = buildToolDisplayList(history);
69
69
  const references = listCommandContextReferences(context);
70
70
  return {
71
71
  message: [
72
72
  `Context: ${state.usedTokens.toLocaleString()} / ${state.maxTokens.toLocaleString()} tokens (${Math.round(state.usedPercentage)}%)`,
73
73
  formatAutoCompactLine(autoCompactThreshold, autoCompactThresholdSource),
74
74
  formatContextReferenceSummary(references),
75
- `History: ${analysis.turnCount} turn${analysis.turnCount !== 1 ? 's' : ''}`,
75
+ `History: ${display.turnCount} turn${display.turnCount !== 1 ? 's' : ''}`,
76
76
  ].join('\n'),
77
77
  success: true,
78
78
  data: {
@@ -304,19 +304,25 @@ function formatContextReferenceLine(reference: IContextReferenceItem): string {
304
304
  interface IToolResultSummary {
305
305
  toolName: string;
306
306
  displayArg: string;
307
- tokens: number;
308
307
  }
309
308
 
310
- interface IHistoryAnalysis {
311
- turnCount: number;
312
- userCount: number;
309
+ interface IMessageTokensByRole {
310
+ systemTokens: number;
313
311
  userTokens: number;
314
- assistantCount: number;
312
+ userCount: number;
315
313
  assistantTokens: number;
316
- toolResults: IToolResultSummary[];
314
+ assistantCount: number;
315
+ toolTokens: number;
316
+ toolCallCount: number;
317
317
  totalTokens: number;
318
318
  }
319
319
 
320
+ interface IToolDisplayList {
321
+ turnCount: number;
322
+ toolResults: IToolResultSummary[];
323
+ totalToolCallCount: number;
324
+ }
325
+
320
326
  function parseToolCallArgs(argsJson: string): Record<string, unknown> | null {
321
327
  try {
322
328
  return JSON.parse(argsJson) as Record<string, unknown>;
@@ -334,7 +340,44 @@ function extractFirstToolArg(argsJson: string): string {
334
340
  return raw.length > TOOL_ARG_MAX_LEN ? `${raw.slice(0, TOOL_ARG_MAX_LEN)}…` : raw;
335
341
  }
336
342
 
337
- function analyzeHistory(history: IHistoryEntry[]): IHistoryAnalysis {
343
+ function computeMessageTokensByRole(rawMessages: TUniversalMessage[]): IMessageTokensByRole {
344
+ let systemTokens = 0;
345
+ let userTokens = 0;
346
+ let userCount = 0;
347
+ let assistantTokens = 0;
348
+ let assistantCount = 0;
349
+ let toolTokens = 0;
350
+ let toolCallCount = 0;
351
+
352
+ for (const msg of rawMessages) {
353
+ const t = Math.ceil(JSON.stringify(msg).length / CHARS_PER_TOKEN);
354
+ if (msg.role === 'system') {
355
+ systemTokens += t;
356
+ } else if (msg.role === 'user') {
357
+ userTokens += t;
358
+ userCount++;
359
+ } else if (msg.role === 'assistant') {
360
+ assistantTokens += t;
361
+ assistantCount++;
362
+ } else if (msg.role === 'tool') {
363
+ toolTokens += t;
364
+ toolCallCount++;
365
+ }
366
+ }
367
+
368
+ return {
369
+ systemTokens,
370
+ userTokens,
371
+ userCount,
372
+ assistantTokens,
373
+ assistantCount,
374
+ toolTokens,
375
+ toolCallCount,
376
+ totalTokens: systemTokens + userTokens + assistantTokens + toolTokens,
377
+ };
378
+ }
379
+
380
+ function buildToolDisplayList(history: IHistoryEntry[]): IToolDisplayList {
338
381
  type TToolCallEntry = { name: string; firstArg: string };
339
382
  const toolCallMap = new Map<string, TToolCallEntry>();
340
383
 
@@ -351,44 +394,28 @@ function analyzeHistory(history: IHistoryEntry[]): IHistoryAnalysis {
351
394
  }
352
395
  }
353
396
 
354
- let userCount = 0;
355
- let userTokens = 0;
356
- let assistantCount = 0;
357
- let assistantTokens = 0;
358
- const toolResultMap = new Map<string, IToolResultSummary>();
397
+ let turnCount = 0;
398
+ let totalToolCallCount = 0;
399
+ const toolDisplayMap = new Map<string, IToolResultSummary>();
359
400
 
360
401
  for (const entry of history) {
361
402
  if (entry.category !== 'chat') continue;
362
403
  if (entry.type === 'user') {
363
- const data = entry.data as { content?: string };
364
- userCount++;
365
- userTokens += estimateTokens((data.content ?? '').length);
366
- } else if (entry.type === 'assistant') {
367
- const data = entry.data as { content?: string | null; toolCalls?: unknown[] };
368
- assistantCount++;
369
- assistantTokens += estimateTokens(
370
- (data.content ?? '').length + (data.toolCalls ? JSON.stringify(data.toolCalls).length : 0),
371
- );
404
+ turnCount++;
372
405
  } else if (entry.type === 'tool') {
373
- const data = entry.data as { content?: string; toolCallId?: string };
406
+ const data = entry.data as { toolCallId?: string };
374
407
  const tc = toolCallMap.get(data.toolCallId ?? '');
375
408
  const toolName = tc?.name ?? 'tool';
376
409
  const displayArg = tc?.firstArg ?? '';
377
- const tokens = estimateTokens((data.content ?? '').length);
378
- toolResultMap.set(`${toolName}:${displayArg}`, { toolName, displayArg, tokens });
410
+ totalToolCallCount++;
411
+ toolDisplayMap.set(`${toolName}:${displayArg}`, { toolName, displayArg });
379
412
  }
380
413
  }
381
414
 
382
- const toolResults = [...toolResultMap.values()];
383
- const toolTokens = toolResults.reduce((s, t) => s + t.tokens, 0);
384
415
  return {
385
- turnCount: userCount,
386
- userCount,
387
- userTokens,
388
- assistantCount,
389
- assistantTokens,
390
- toolResults,
391
- totalTokens: userTokens + assistantTokens + toolTokens,
416
+ turnCount,
417
+ toolResults: [...toolDisplayMap.values()],
418
+ totalToolCallCount,
392
419
  };
393
420
  }
394
421
 
@@ -406,44 +433,53 @@ function formatFullContextBreakdown(context: ICommandHostContext): ICommandResul
406
433
  const state = readCommandContextState(context);
407
434
  const autoCompactThreshold = readAutoCompactThreshold(context);
408
435
  const autoCompactThresholdSource = readAutoCompactThresholdSource(context);
409
- const history = context.getSession().getFullHistory();
410
- const analysis = analyzeHistory(history);
436
+ const rawMessages = context.getSession().getHistory();
437
+ const msgTokens = computeMessageTokensByRole(rawMessages);
438
+ const display = buildToolDisplayList(context.getSession().getFullHistory());
411
439
  const references = listCommandContextReferences(context);
412
440
 
413
441
  const systemRefs = references.filter((r) => r.loadType === 'system');
414
442
  const manualRefs = references.filter((r) => r.loadType === 'manual');
415
443
  const promptRefs = references.filter((r) => r.loadType === 'prompt-reference');
416
444
 
417
- const systemTokens = systemRefs.reduce((s, r) => s + estimateTokens(r.byteLength), 0);
445
+ const systemRefTokens = systemRefs.reduce((s, r) => s + estimateTokens(r.byteLength), 0);
418
446
  const manualTokens = manualRefs.reduce((s, r) => s + estimateTokens(r.byteLength), 0);
419
447
  const promptRefTokens = promptRefs.reduce((s, r) => s + estimateTokens(r.byteLength), 0);
420
448
 
421
449
  const convTurnLabel =
422
- analysis.turnCount === 0
450
+ display.turnCount === 0
423
451
  ? 'Conversation history — 0 turns'
424
- : `Conversation history — ${analysis.turnCount} turn${analysis.turnCount !== 1 ? 's' : ''} | ~${analysis.totalTokens.toLocaleString()} tokens`;
452
+ : `Conversation history — ${display.turnCount} turn${display.turnCount !== 1 ? 's' : ''} | ~${msgTokens.totalTokens.toLocaleString()} tokens`;
425
453
 
426
- const toolResultLines = analysis.toolResults.map(
427
- (t) =>
428
- `${t.toolName}${t.displayArg ? `: ${t.displayArg}` : ''} — ~${t.tokens.toLocaleString()} tokens`,
454
+ const toolResultLines = display.toolResults.map(
455
+ (t) => `${t.toolName}${t.displayArg ? `: ${t.displayArg}` : ''}`,
429
456
  );
430
457
 
458
+ const uniqueToolCount = display.toolResults.length;
459
+ const totalToolCallCount = display.totalToolCallCount;
460
+ const toolResultsLabel =
461
+ totalToolCallCount === 0
462
+ ? 'Tool results (0): (none)'
463
+ : uniqueToolCount < totalToolCallCount
464
+ ? `Tool results (${uniqueToolCount} unique / ${totalToolCallCount} calls, ~${msgTokens.toolTokens.toLocaleString()} tokens):`
465
+ : `Tool results (${uniqueToolCount}, ~${msgTokens.toolTokens.toLocaleString()} tokens):`;
466
+
431
467
  const conversationLines: string[] =
432
- analysis.turnCount === 0
468
+ display.turnCount === 0
433
469
  ? []
434
470
  : [
435
- `User (${analysis.userCount}): ~${analysis.userTokens.toLocaleString()} tokens`,
436
- `Assistant (${analysis.assistantCount}): ~${analysis.assistantTokens.toLocaleString()} tokens`,
437
- analysis.toolResults.length > 0
438
- ? [
439
- `Tool results (${analysis.toolResults.length}):`,
440
- ...toolResultLines.map((l) => ` ${l}`),
441
- ].join('\n')
442
- : `Tool results (0): (none)`,
471
+ `User (${msgTokens.userCount}): ~${msgTokens.userTokens.toLocaleString()} tokens`,
472
+ `Assistant (${msgTokens.assistantCount}): ~${msgTokens.assistantTokens.toLocaleString()} tokens`,
473
+ ...(msgTokens.systemTokens > 0
474
+ ? [`System messages: ~${msgTokens.systemTokens.toLocaleString()} tokens`]
475
+ : []),
476
+ totalToolCallCount > 0
477
+ ? [toolResultsLabel, ...toolResultLines.map((l) => ` ${l}`)].join('\n')
478
+ : toolResultsLabel,
443
479
  ];
444
480
 
445
481
  const convSection =
446
- analysis.turnCount === 0
482
+ display.turnCount === 0
447
483
  ? `${convTurnLabel}:\n (none)`
448
484
  : [`${convTurnLabel}:`, ...conversationLines.map((l) => ` ${l}`)].join('\n');
449
485
 
@@ -453,7 +489,7 @@ function formatFullContextBreakdown(context: ICommandHostContext): ICommandResul
453
489
  '',
454
490
  formatSection(
455
491
  'System prompt (active every turn)',
456
- systemTokens,
492
+ systemRefTokens,
457
493
  systemRefs.map(formatContextReferenceLine),
458
494
  ),
459
495
  '',
@@ -473,7 +509,7 @@ function formatFullContextBreakdown(context: ICommandHostContext): ICommandResul
473
509
  message,
474
510
  data: {
475
511
  references,
476
- history: { turnCount: analysis.turnCount, toolResults: analysis.toolResults },
512
+ history: { turnCount: display.turnCount, toolResults: display.toolResults },
477
513
  },
478
514
  };
479
515
  }
@@ -20,6 +20,7 @@ function createCommandSessionRuntime(): ICommandSessionRuntime {
20
20
  getSessionAllowedTools: () => [],
21
21
  getAutoCompactThreshold: () => false,
22
22
  getFullHistory: () => [],
23
+ getHistory: () => [],
23
24
  };
24
25
  }
25
26
 
@@ -23,6 +23,7 @@ function createCommandSessionRuntime(): ICommandSessionRuntime {
23
23
  getSessionAllowedTools: () => [],
24
24
  getAutoCompactThreshold: () => false,
25
25
  getFullHistory: () => [],
26
+ getHistory: () => [],
26
27
  };
27
28
  }
28
29
 
@@ -41,6 +41,7 @@ function createCommandSessionRuntime(): ICommandSessionRuntime {
41
41
  getSessionAllowedTools: () => [],
42
42
  getAutoCompactThreshold: () => false,
43
43
  getFullHistory: () => [],
44
+ getHistory: () => [],
44
45
  };
45
46
  }
46
47
 
@@ -20,6 +20,7 @@ function createRuntime(): ICommandSessionRuntime {
20
20
  getSessionAllowedTools: () => [],
21
21
  getAutoCompactThreshold: () => false,
22
22
  getFullHistory: () => [],
23
+ getHistory: () => [],
23
24
  };
24
25
  }
25
26