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

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.68",
3
+ "version": "3.0.0-beta.70",
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.68",
28
- "@robota-sdk/agent-framework": "3.0.0-beta.68"
27
+ "@robota-sdk/agent-core": "3.0.0-beta.70",
28
+ "@robota-sdk/agent-framework": "3.0.0-beta.70"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "^22.14.0",
@@ -27,6 +27,7 @@ function createSessionRuntime(): ICommandSessionRuntime {
27
27
  getMessageCount: () => 0,
28
28
  getSessionAllowedTools: () => [],
29
29
  getAutoCompactThreshold: () => false,
30
+ getFullHistory: () => [],
30
31
  };
31
32
  }
32
33
 
@@ -35,6 +35,7 @@ function createRuntime(beforeCount = 10, afterCount = 3): ICommandSessionRuntime
35
35
  getMessageCount,
36
36
  getSessionAllowedTools: () => [],
37
37
  getAutoCompactThreshold: () => 0.835,
38
+ getFullHistory: () => [],
38
39
  };
39
40
  }
40
41
 
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
+ import type { IHistoryEntry } from '@robota-sdk/agent-core';
2
3
  import type {
3
4
  ICommandHostContext,
4
5
  IContextReferenceAddResult,
@@ -45,7 +46,22 @@ const PROMPT_REFERENCE: IContextReferenceItem = {
45
46
  lastUsedAt: '2026-05-05T00:00:01.000Z',
46
47
  };
47
48
 
48
- function createRuntime(state: { threshold: number | false }): ICommandSessionRuntime {
49
+ const SYSTEM_REFERENCE: IContextReferenceItem = {
50
+ id: 'system:AGENTS.md',
51
+ sourcePath: '/workspace/AGENTS.md',
52
+ relativePath: 'AGENTS.md',
53
+ originalReference: 'AGENTS.md',
54
+ loadType: 'system',
55
+ status: 'active',
56
+ byteLength: 1024,
57
+ loadedAt: '2026-05-05T00:00:00.000Z',
58
+ lastUsedAt: '2026-05-05T00:00:00.000Z',
59
+ };
60
+
61
+ function createRuntime(
62
+ state: { threshold: number | false },
63
+ history: IHistoryEntry[] = [],
64
+ ): ICommandSessionRuntime {
49
65
  let mode: TPermissionMode = 'default';
50
66
  return {
51
67
  clearHistory: vi.fn(),
@@ -59,6 +75,7 @@ function createRuntime(state: { threshold: number | false }): ICommandSessionRun
59
75
  getMessageCount: () => 1,
60
76
  getSessionAllowedTools: () => [],
61
77
  getAutoCompactThreshold: () => state.threshold,
78
+ getFullHistory: () => history,
62
79
  setAutoCompactThreshold: (threshold) => {
63
80
  state.threshold = threshold;
64
81
  },
@@ -190,9 +207,9 @@ describe('createContextCommandModule', () => {
190
207
  const result = await createExecutor().execute('context', context, 'list');
191
208
 
192
209
  expect(result?.success).toBe(true);
193
- expect(result?.message).toContain('AGENTS.md [manual, active] 42 B');
210
+ expect(result?.message).toContain('AGENTS.md [manual, active] ~11 tokens');
194
211
  expect(result?.message).toContain(
195
- 'packages/agent-sdk/docs/SPEC.md [prompt-reference, observed] 200 B',
212
+ 'packages/agent-sdk/docs/SPEC.md [prompt-reference, observed] ~50 tokens',
196
213
  );
197
214
  expect(result?.data?.references).toEqual([MANUAL_REFERENCE, PROMPT_REFERENCE]);
198
215
  });
@@ -203,7 +220,9 @@ describe('createContextCommandModule', () => {
203
220
  const result = await createExecutor().execute('context', context, 'add AGENTS.md');
204
221
 
205
222
  expect(result?.success).toBe(true);
206
- expect(result?.message).toContain('Context reference added: AGENTS.md [manual, active] 42 B.');
223
+ expect(result?.message).toContain(
224
+ 'Context reference added: AGENTS.md [manual, active] ~11 tokens.',
225
+ );
207
226
  expect(context.references[0]?.relativePath).toBe('AGENTS.md');
208
227
  });
209
228
 
@@ -214,7 +233,9 @@ describe('createContextCommandModule', () => {
214
233
  const result = await createExecutor().execute('context', context, 'remove AGENTS.md');
215
234
 
216
235
  expect(result?.success).toBe(true);
217
- expect(result?.message).toBe('Context reference removed: AGENTS.md [manual, active] 42 B.');
236
+ expect(result?.message).toBe(
237
+ 'Context reference removed: AGENTS.md [manual, active] ~11 tokens.',
238
+ );
218
239
  expect(context.references).toEqual([]);
219
240
  });
220
241
 
@@ -291,4 +312,39 @@ describe('createContextCommandModule', () => {
291
312
  expect(result?.success).toBe(false);
292
313
  expect(result?.message).toContain('greater than 0% and at most 100%');
293
314
  });
315
+
316
+ it('lists system context references with [system, active] label', async () => {
317
+ const context = createCommandHostContext();
318
+ context.references.push(SYSTEM_REFERENCE);
319
+
320
+ const result = await createExecutor().execute('context', context, 'list');
321
+
322
+ expect(result?.success).toBe(true);
323
+ expect(result?.message).toContain('AGENTS.md [system, active] ~256 tokens');
324
+ expect(result?.data?.references).toEqual([SYSTEM_REFERENCE]);
325
+ });
326
+
327
+ it('includes system references in context summary active count', async () => {
328
+ const context = createCommandHostContext();
329
+ context.references.push(SYSTEM_REFERENCE, MANUAL_REFERENCE);
330
+
331
+ const result = await createExecutor().execute('context', context, '');
332
+
333
+ expect(result?.success).toBe(true);
334
+ expect(result?.message).toContain('References: 2 active, 0 observed');
335
+ });
336
+
337
+ it('shows full context breakdown with empty sections when no references', async () => {
338
+ const context = createCommandHostContext();
339
+
340
+ const result = await createExecutor().execute('context', context, 'list');
341
+
342
+ expect(result?.success).toBe(true);
343
+ expect(result?.message).toContain('System prompt (active every turn):');
344
+ expect(result?.message).toContain('Conversation history — 0 turns:');
345
+ expect(result?.message).toContain('Manually added:');
346
+ expect(result?.message).toContain('Prompt references (@-syntax):');
347
+ // All sections empty
348
+ expect(result?.message).not.toContain('~');
349
+ });
294
350
  });
@@ -12,6 +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
16
  import type {
16
17
  ICommandHostContext,
17
18
  ICommandResult,
@@ -63,11 +64,15 @@ export async function executeContextCommand(
63
64
  const state = readCommandContextState(context);
64
65
  const autoCompactThreshold = readAutoCompactThreshold(context);
65
66
  const autoCompactThresholdSource = readAutoCompactThresholdSource(context);
67
+ const history = context.getSession().getFullHistory();
68
+ const analysis = analyzeHistory(history);
69
+ const references = listCommandContextReferences(context);
66
70
  return {
67
71
  message: [
68
72
  `Context: ${state.usedTokens.toLocaleString()} / ${state.maxTokens.toLocaleString()} tokens (${Math.round(state.usedPercentage)}%)`,
69
73
  formatAutoCompactLine(autoCompactThreshold, autoCompactThresholdSource),
70
- formatContextReferenceSummary(listCommandContextReferences(context)),
74
+ formatContextReferenceSummary(references),
75
+ `History: ${analysis.turnCount} turn${analysis.turnCount !== 1 ? 's' : ''}`,
71
76
  ].join('\n'),
72
77
  success: true,
73
78
  data: {
@@ -76,7 +81,7 @@ export async function executeContextCommand(
76
81
  percentage: state.usedPercentage,
77
82
  autoCompactThreshold,
78
83
  autoCompactThresholdSource,
79
- references: listCommandContextReferences(context),
84
+ references,
80
85
  },
81
86
  };
82
87
  }
@@ -88,7 +93,7 @@ async function executeContextSubcommand(
88
93
  const [subcommand, ...rest] = parts;
89
94
  if (subcommand === 'list') {
90
95
  if (rest.length > 0) return { success: false, message: USAGE };
91
- return formatContextReferenceList(listCommandContextReferences(context));
96
+ return formatFullContextBreakdown(context);
92
97
  }
93
98
  if (subcommand === 'add') {
94
99
  return executeAddContextReference(context, rest);
@@ -278,22 +283,197 @@ function formatContextReferenceSummary(references: readonly IContextReferenceIte
278
283
  return `References: ${active} active, ${observed} observed`;
279
284
  }
280
285
 
281
- function formatContextReferenceList(references: readonly IContextReferenceItem[]): ICommandResult {
282
- if (references.length === 0) {
283
- return { success: true, message: 'No context references.', data: { references } };
284
- }
286
+ // 1 token ≈ 4 chars — same approximation used across the codebase (limits-helpers.ts)
287
+ const CHARS_PER_TOKEN = 4;
288
+ const TOOL_ARG_MAX_LEN = 60;
285
289
 
286
- return {
287
- success: true,
288
- message: ['Context references:', ...references.map(formatContextReferenceLine)].join('\n'),
289
- data: { references },
290
- };
290
+ function estimateTokens(charLength: number): number {
291
+ return Math.ceil(charLength / CHARS_PER_TOKEN);
291
292
  }
292
293
 
293
294
  function formatContextReferenceLine(reference: IContextReferenceItem): string {
294
295
  return [
295
296
  reference.relativePath,
296
297
  `[${reference.loadType}, ${reference.status}]`,
297
- `${reference.byteLength.toLocaleString()} B`,
298
+ `~${estimateTokens(reference.byteLength).toLocaleString()} tokens`,
298
299
  ].join(' ');
299
300
  }
301
+
302
+ // ── History analysis ────────────────────────────────────────────────────────
303
+
304
+ interface IToolResultSummary {
305
+ toolName: string;
306
+ displayArg: string;
307
+ tokens: number;
308
+ }
309
+
310
+ interface IHistoryAnalysis {
311
+ turnCount: number;
312
+ userCount: number;
313
+ userTokens: number;
314
+ assistantCount: number;
315
+ assistantTokens: number;
316
+ toolResults: IToolResultSummary[];
317
+ totalTokens: number;
318
+ }
319
+
320
+ function parseToolCallArgs(argsJson: string): Record<string, unknown> | null {
321
+ try {
322
+ return JSON.parse(argsJson) as Record<string, unknown>;
323
+ } catch {
324
+ // allow-fallback: tool call arguments JSON may be malformed; display-only degradation, not a terminal path
325
+ return null;
326
+ }
327
+ }
328
+
329
+ function extractFirstToolArg(argsJson: string): string {
330
+ const parsed = parseToolCallArgs(argsJson);
331
+ if (parsed === null) return '';
332
+ const first = Object.values(parsed)[0];
333
+ const raw = typeof first === 'string' ? first : JSON.stringify(first);
334
+ return raw.length > TOOL_ARG_MAX_LEN ? `${raw.slice(0, TOOL_ARG_MAX_LEN)}…` : raw;
335
+ }
336
+
337
+ function analyzeHistory(history: IHistoryEntry[]): IHistoryAnalysis {
338
+ type TToolCallEntry = { name: string; firstArg: string };
339
+ const toolCallMap = new Map<string, TToolCallEntry>();
340
+
341
+ for (const entry of history) {
342
+ if (entry.category !== 'chat' || entry.type !== 'assistant') continue;
343
+ const data = entry.data as {
344
+ toolCalls?: Array<{ id: string; function: { name: string; arguments: string } }>;
345
+ };
346
+ for (const tc of data.toolCalls ?? []) {
347
+ toolCallMap.set(tc.id, {
348
+ name: tc.function.name,
349
+ firstArg: extractFirstToolArg(tc.function.arguments),
350
+ });
351
+ }
352
+ }
353
+
354
+ let userCount = 0;
355
+ let userTokens = 0;
356
+ let assistantCount = 0;
357
+ let assistantTokens = 0;
358
+ const toolResultMap = new Map<string, IToolResultSummary>();
359
+
360
+ for (const entry of history) {
361
+ if (entry.category !== 'chat') continue;
362
+ 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
+ );
372
+ } else if (entry.type === 'tool') {
373
+ const data = entry.data as { content?: string; toolCallId?: string };
374
+ const tc = toolCallMap.get(data.toolCallId ?? '');
375
+ const toolName = tc?.name ?? 'tool';
376
+ const displayArg = tc?.firstArg ?? '';
377
+ const tokens = estimateTokens((data.content ?? '').length);
378
+ toolResultMap.set(`${toolName}:${displayArg}`, { toolName, displayArg, tokens });
379
+ }
380
+ }
381
+
382
+ const toolResults = [...toolResultMap.values()];
383
+ const toolTokens = toolResults.reduce((s, t) => s + t.tokens, 0);
384
+ return {
385
+ turnCount: userCount,
386
+ userCount,
387
+ userTokens,
388
+ assistantCount,
389
+ assistantTokens,
390
+ toolResults,
391
+ totalTokens: userTokens + assistantTokens + toolTokens,
392
+ };
393
+ }
394
+
395
+ // ── Full context breakdown (for /context list) ──────────────────────────────
396
+
397
+ function formatSection(title: string, tokens: number, lines: string[]): string {
398
+ const tokenLabel = tokens > 0 ? ` — ~${tokens.toLocaleString()} tokens` : '';
399
+ const header = `${title}${tokenLabel}:`;
400
+ return lines.length === 0
401
+ ? `${header}\n (none)`
402
+ : [header, ...lines.map((l) => ` ${l}`)].join('\n');
403
+ }
404
+
405
+ function formatFullContextBreakdown(context: ICommandHostContext): ICommandResult {
406
+ const state = readCommandContextState(context);
407
+ const autoCompactThreshold = readAutoCompactThreshold(context);
408
+ const autoCompactThresholdSource = readAutoCompactThresholdSource(context);
409
+ const history = context.getSession().getFullHistory();
410
+ const analysis = analyzeHistory(history);
411
+ const references = listCommandContextReferences(context);
412
+
413
+ const systemRefs = references.filter((r) => r.loadType === 'system');
414
+ const manualRefs = references.filter((r) => r.loadType === 'manual');
415
+ const promptRefs = references.filter((r) => r.loadType === 'prompt-reference');
416
+
417
+ const systemTokens = systemRefs.reduce((s, r) => s + estimateTokens(r.byteLength), 0);
418
+ const manualTokens = manualRefs.reduce((s, r) => s + estimateTokens(r.byteLength), 0);
419
+ const promptRefTokens = promptRefs.reduce((s, r) => s + estimateTokens(r.byteLength), 0);
420
+
421
+ const convTurnLabel =
422
+ analysis.turnCount === 0
423
+ ? 'Conversation history — 0 turns'
424
+ : `Conversation history — ${analysis.turnCount} turn${analysis.turnCount !== 1 ? 's' : ''} | ~${analysis.totalTokens.toLocaleString()} tokens`;
425
+
426
+ const toolResultLines = analysis.toolResults.map(
427
+ (t) =>
428
+ `${t.toolName}${t.displayArg ? `: ${t.displayArg}` : ''} — ~${t.tokens.toLocaleString()} tokens`,
429
+ );
430
+
431
+ const conversationLines: string[] =
432
+ analysis.turnCount === 0
433
+ ? []
434
+ : [
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)`,
443
+ ];
444
+
445
+ const convSection =
446
+ analysis.turnCount === 0
447
+ ? `${convTurnLabel}:\n (none)`
448
+ : [`${convTurnLabel}:`, ...conversationLines.map((l) => ` ${l}`)].join('\n');
449
+
450
+ const message = [
451
+ `Context: ${state.usedTokens.toLocaleString()} / ${state.maxTokens.toLocaleString()} tokens (${Math.round(state.usedPercentage)}%)`,
452
+ formatAutoCompactLine(autoCompactThreshold, autoCompactThresholdSource),
453
+ '',
454
+ formatSection(
455
+ 'System prompt (active every turn)',
456
+ systemTokens,
457
+ systemRefs.map(formatContextReferenceLine),
458
+ ),
459
+ '',
460
+ convSection,
461
+ '',
462
+ formatSection('Manually added', manualTokens, manualRefs.map(formatContextReferenceLine)),
463
+ '',
464
+ formatSection(
465
+ 'Prompt references (@-syntax)',
466
+ promptRefTokens,
467
+ promptRefs.map(formatContextReferenceLine),
468
+ ),
469
+ ].join('\n');
470
+
471
+ return {
472
+ success: true,
473
+ message,
474
+ data: {
475
+ references,
476
+ history: { turnCount: analysis.turnCount, toolResults: analysis.toolResults },
477
+ },
478
+ };
479
+ }
@@ -4,6 +4,7 @@ import { executeExitCommand } from './exit-command.js';
4
4
 
5
5
  import type {
6
6
  ICommand,
7
+ ICommandInteractionHint,
7
8
  ICommandModule,
8
9
  ICommandSource,
9
10
  ISystemCommand,
@@ -41,10 +42,15 @@ export class ExitCommandSource implements ICommandSource {
41
42
  }
42
43
  }
43
44
 
45
+ const EXIT_INTERACTION_HINTS: Record<string, ICommandInteractionHint> = {
46
+ exit: { type: 'confirm', message: 'Exit the session?' },
47
+ };
48
+
44
49
  export function createExitCommandModule(): ICommandModule {
45
50
  return {
46
51
  name: 'agent-command-exit',
47
52
  commandSources: [new ExitCommandSource()],
48
53
  systemCommands: [createExitSystemCommand()],
54
+ interactionHints: EXIT_INTERACTION_HINTS,
49
55
  };
50
56
  }
@@ -19,6 +19,7 @@ function createCommandSessionRuntime(): ICommandSessionRuntime {
19
19
  getMessageCount: () => 0,
20
20
  getSessionAllowedTools: () => [],
21
21
  getAutoCompactThreshold: () => false,
22
+ getFullHistory: () => [],
22
23
  };
23
24
  }
24
25
 
@@ -22,6 +22,7 @@ function createCommandSessionRuntime(): ICommandSessionRuntime {
22
22
  getMessageCount: () => 0,
23
23
  getSessionAllowedTools: () => [],
24
24
  getAutoCompactThreshold: () => false,
25
+ getFullHistory: () => [],
25
26
  };
26
27
  }
27
28
 
@@ -8,6 +8,7 @@ import { executeLanguageCommand } from './language-command.js';
8
8
 
9
9
  import type {
10
10
  ICommand,
11
+ ICommandInteractionHint,
11
12
  ICommandModule,
12
13
  ICommandSource,
13
14
  ISystemCommand,
@@ -49,10 +50,23 @@ export class LanguageCommandSource implements ICommandSource {
49
50
  }
50
51
  }
51
52
 
53
+ const LANGUAGE_INTERACTION_HINTS: Record<string, ICommandInteractionHint> = {
54
+ language: {
55
+ type: 'pick',
56
+ getItems: () =>
57
+ buildLanguageCommandSubcommands().map((sub) => ({
58
+ label: `${sub.name} ${sub.description ?? ''}`.trimEnd(),
59
+ value: sub.name,
60
+ description: sub.description,
61
+ })),
62
+ },
63
+ };
64
+
52
65
  export function createLanguageCommandModule(): ICommandModule {
53
66
  return {
54
67
  name: 'agent-command-language',
55
68
  commandSources: [new LanguageCommandSource()],
56
69
  systemCommands: [createLanguageSystemCommand()],
70
+ interactionHints: LANGUAGE_INTERACTION_HINTS,
57
71
  };
58
72
  }
@@ -8,6 +8,7 @@ import { executeModeCommand } from './mode-command.js';
8
8
 
9
9
  import type {
10
10
  ICommand,
11
+ ICommandInteractionHint,
11
12
  ICommandModule,
12
13
  ICommandSource,
13
14
  ISystemCommand,
@@ -49,10 +50,23 @@ export class ModeCommandSource implements ICommandSource {
49
50
  }
50
51
  }
51
52
 
53
+ const MODE_INTERACTION_HINTS: Record<string, ICommandInteractionHint> = {
54
+ mode: {
55
+ type: 'pick',
56
+ getItems: () =>
57
+ buildPermissionModeSubcommands().map((sub) => ({
58
+ label: sub.name,
59
+ value: sub.name,
60
+ description: sub.description,
61
+ })),
62
+ },
63
+ };
64
+
52
65
  export function createModeCommandModule(): ICommandModule {
53
66
  return {
54
67
  name: 'agent-command-mode',
55
68
  commandSources: [new ModeCommandSource()],
56
69
  systemCommands: [createModeSystemCommand()],
70
+ interactionHints: MODE_INTERACTION_HINTS,
57
71
  };
58
72
  }
@@ -40,6 +40,7 @@ function createCommandSessionRuntime(): ICommandSessionRuntime {
40
40
  getMessageCount: () => 0,
41
41
  getSessionAllowedTools: () => [],
42
42
  getAutoCompactThreshold: () => false,
43
+ getFullHistory: () => [],
43
44
  };
44
45
  }
45
46
 
@@ -2,6 +2,7 @@ import { executeProviderCommand } from './provider-command-execution.js';
2
2
 
3
3
  import type {
4
4
  ICommand,
5
+ ICommandInteractionHint,
5
6
  ICommandModule as TCommandModule,
6
7
  ICommandSource,
7
8
  IProviderCommandModuleOptions,
@@ -57,6 +58,18 @@ function createProviderSystemCommand(options: IProviderCommandModuleOptions): TS
57
58
  };
58
59
  }
59
60
 
61
+ const PROVIDER_INTERACTION_HINTS: Record<string, ICommandInteractionHint> = {
62
+ provider: {
63
+ type: 'pick',
64
+ getItems: () =>
65
+ buildProviderSubcommands().map((sub) => ({
66
+ label: sub.name,
67
+ value: sub.name,
68
+ description: sub.description,
69
+ })),
70
+ },
71
+ };
72
+
60
73
  export function createProviderCommandModule(
61
74
  options: IProviderCommandModuleOptions,
62
75
  ): TCommandModule {
@@ -64,5 +77,6 @@ export function createProviderCommandModule(
64
77
  name: 'agent-command-provider',
65
78
  commandSources: [new ProviderCommandSource()],
66
79
  systemCommands: [createProviderSystemCommand(options)],
80
+ interactionHints: PROVIDER_INTERACTION_HINTS,
67
81
  };
68
82
  }
@@ -19,6 +19,7 @@ function createRuntime(): ICommandSessionRuntime {
19
19
  getMessageCount: () => 5,
20
20
  getSessionAllowedTools: () => [],
21
21
  getAutoCompactThreshold: () => false,
22
+ getFullHistory: () => [],
22
23
  };
23
24
  }
24
25
 
@@ -16,6 +16,7 @@ import {
16
16
 
17
17
  import type {
18
18
  ICommand,
19
+ ICommandInteractionHint,
19
20
  ICommandModule,
20
21
  ICommandSource,
21
22
  ISystemCommand,
@@ -155,6 +156,10 @@ export class SessionCommandSource implements ICommandSource {
155
156
  }
156
157
  }
157
158
 
159
+ const SESSION_INTERACTION_HINTS: Record<string, ICommandInteractionHint> = {
160
+ clear: { type: 'confirm', message: 'Clear conversation history?' },
161
+ };
162
+
158
163
  export function createSessionCommandModule(): ICommandModule {
159
164
  return {
160
165
  name: 'agent-command-session',
@@ -166,5 +171,6 @@ export function createSessionCommandModule(): ICommandModule {
166
171
  createCostSystemCommand(),
167
172
  createValidateSessionSystemCommand(),
168
173
  ],
174
+ interactionHints: SESSION_INTERACTION_HINTS,
169
175
  };
170
176
  }