@robota-sdk/agent-command 3.0.0-beta.79 → 3.0.0-beta.82

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.
Files changed (201) hide show
  1. package/README.md +11 -2
  2. package/dist/node/index.cjs +77 -38
  3. package/dist/node/index.d.cts +946 -0
  4. package/dist/node/index.d.cts.map +1 -0
  5. package/dist/node/index.d.ts +564 -51
  6. package/dist/node/index.d.ts.map +1 -1
  7. package/dist/node/index.js +77 -38
  8. package/dist/node/index.js.map +1 -1
  9. package/package.json +39 -16
  10. package/src/advisor/advisor-command-module.ts +47 -0
  11. package/src/advisor/advisor-command.test.ts +102 -0
  12. package/src/advisor/advisor-command.ts +55 -0
  13. package/src/advisor/advisor-cost-functional.test.ts +92 -0
  14. package/src/advisor/index.ts +6 -0
  15. package/src/agent/__tests__/agent-command.test.ts +39 -8
  16. package/src/agent/agent-command-module.ts +14 -7
  17. package/src/agent/agent-command-parser.ts +1 -1
  18. package/src/agent/agent-command.ts +3 -3
  19. package/src/background/__tests__/background-command-module.test.ts +59 -52
  20. package/src/background/background-command-module.ts +2 -1
  21. package/src/background/background-command.ts +3 -3
  22. package/src/command-module-utils.ts +33 -0
  23. package/src/compact/__tests__/compact-command-module.test.ts +31 -23
  24. package/src/compact/compact-command-module.ts +10 -1
  25. package/src/compact/compact-command.ts +6 -3
  26. package/src/context/__tests__/context-command-module.test.ts +214 -63
  27. package/src/context/auto-compact-format.ts +25 -0
  28. package/src/context/context-breakdown.ts +295 -0
  29. package/src/context/context-command-module.ts +45 -14
  30. package/src/context/context-command.ts +34 -257
  31. package/src/default/__tests__/__snapshots__/model-exposure.test.ts.snap +110 -0
  32. package/src/default/__tests__/default-command-modules.test.ts +59 -7
  33. package/src/default/__tests__/model-exposure.test.ts +241 -0
  34. package/src/default/__tests__/org-policy-forwarding.test.ts +98 -0
  35. package/src/default/default-command-modules.ts +130 -18
  36. package/src/default/index.ts +4 -1
  37. package/src/devices/__tests__/devices-command-module.test.ts +212 -0
  38. package/src/devices/devices-command-module.ts +224 -0
  39. package/src/devices/devices-command-port.ts +82 -0
  40. package/src/devices/index.ts +11 -0
  41. package/src/doctor/__tests__/doctor-command-module.test.ts +145 -0
  42. package/src/doctor/__tests__/doctor-display-vocabulary.test.ts +38 -0
  43. package/src/doctor/__tests__/doctor-fixture.ts +145 -0
  44. package/src/doctor/__tests__/doctor-redaction.test.ts +29 -0
  45. package/src/doctor/__tests__/doctor-runner.test.ts +464 -0
  46. package/src/doctor/doctor-command-module.ts +132 -0
  47. package/src/doctor/doctor-extensions-probe.ts +299 -0
  48. package/src/doctor/doctor-node-deps.ts +89 -0
  49. package/src/doctor/doctor-redaction.ts +99 -0
  50. package/src/doctor/doctor-render.ts +70 -0
  51. package/src/doctor/doctor-repair.ts +136 -0
  52. package/src/doctor/doctor-runner.ts +122 -0
  53. package/src/doctor/doctor-settings-probe.ts +239 -0
  54. package/src/doctor/doctor-storage-probe.ts +187 -0
  55. package/src/doctor/doctor-types.ts +109 -0
  56. package/src/doctor/index.ts +32 -0
  57. package/src/editor/__tests__/editor-command-functional.test.ts +49 -16
  58. package/src/editor/editor-command-module.ts +6 -5
  59. package/src/editor/editor-command.ts +10 -5
  60. package/src/effort/effort-command-module.ts +51 -0
  61. package/src/effort/effort-command.test.ts +140 -0
  62. package/src/effort/effort-command.ts +122 -0
  63. package/src/effort/index.ts +6 -0
  64. package/src/exit/__tests__/exit-command-module.test.ts +16 -9
  65. package/src/exit/exit-command-module.ts +2 -1
  66. package/src/exit/exit-command.ts +6 -6
  67. package/src/fork/__tests__/fork-command.test.ts +184 -0
  68. package/src/fork/fork-command-module.ts +61 -0
  69. package/src/fork/fork-command.ts +162 -0
  70. package/src/fork/index.ts +8 -0
  71. package/src/git/__tests__/fake-git-port.ts +28 -0
  72. package/src/git/__tests__/git-command-module.test.ts +103 -0
  73. package/src/git/__tests__/git-commit.test.ts +185 -0
  74. package/src/git/__tests__/git-diff.test.ts +125 -0
  75. package/src/git/__tests__/git-process.test.ts +221 -0
  76. package/src/git/__tests__/git-status.test.ts +117 -0
  77. package/src/git/git-command-module.ts +139 -0
  78. package/src/git/git-commit.ts +251 -0
  79. package/src/git/git-diff.ts +129 -0
  80. package/src/git/git-process.ts +169 -0
  81. package/src/git/git-status.ts +134 -0
  82. package/src/git/index.ts +17 -0
  83. package/src/goal/__tests__/goal-command.test.ts +9 -4
  84. package/src/goal/goal-command-module.ts +2 -1
  85. package/src/goal/goal-command.ts +6 -9
  86. package/src/handoff/__tests__/handoff-command-module.test.ts +24 -0
  87. package/src/handoff/__tests__/handoff-command.test.ts +218 -0
  88. package/src/handoff/handoff-command-module.ts +49 -0
  89. package/src/handoff/handoff-command.ts +187 -0
  90. package/src/handoff/index.ts +6 -0
  91. package/src/help/__tests__/help-command-module.test.ts +63 -40
  92. package/src/help/__tests__/help-command.test.ts +46 -37
  93. package/src/help/help-command-module.ts +2 -1
  94. package/src/help/help-command.ts +3 -3
  95. package/src/index.ts +124 -2
  96. package/src/keybindings/__tests__/keybindings-command-module.test.ts +57 -0
  97. package/src/keybindings/index.ts +6 -0
  98. package/src/keybindings/keybindings-command-module.ts +74 -0
  99. package/src/language/__tests__/language-command-module.test.ts +33 -28
  100. package/src/language/language-command-module.ts +2 -1
  101. package/src/language/language-command.ts +8 -6
  102. package/src/mcp-activation/__tests__/mcp-activation-command.test.ts +630 -0
  103. package/src/mcp-activation/__tests__/mcp-model-view.test.ts +211 -0
  104. package/src/mcp-activation/index.ts +12 -0
  105. package/src/mcp-activation/mcp-activation-command-module.ts +92 -0
  106. package/src/mcp-activation/mcp-activation-command.ts +448 -0
  107. package/src/mcp-activation/mcp-model-notice.ts +85 -0
  108. package/src/mcp-activation/mcp-model-status.ts +99 -0
  109. package/src/memory/__tests__/memory-command-module.test.ts +167 -74
  110. package/src/memory/memory-command-module.ts +18 -1
  111. package/src/memory/memory-command.ts +38 -38
  112. package/src/mode/__tests__/mode-command-module.test.ts +51 -38
  113. package/src/mode/mode-command-module.ts +2 -1
  114. package/src/mode/mode-command.ts +15 -7
  115. package/src/output-style/__tests__/output-style-command.test.ts +96 -0
  116. package/src/output-style/index.ts +6 -0
  117. package/src/output-style/output-style-command-module.ts +143 -0
  118. package/src/peers/__tests__/peers-command.test.ts +321 -0
  119. package/src/peers/index.ts +9 -0
  120. package/src/peers/peers-command-module.ts +49 -0
  121. package/src/peers/peers-command.ts +191 -0
  122. package/src/permissions/__tests__/permissions-command-module.test.ts +149 -37
  123. package/src/permissions/permissions-command-module.ts +2 -1
  124. package/src/permissions/permissions-command.ts +46 -4
  125. package/src/plan/__tests__/plan-command.test.ts +129 -0
  126. package/src/plan/index.ts +9 -0
  127. package/src/plan/plan-command-module.ts +49 -0
  128. package/src/plan/plan-command.ts +92 -0
  129. package/src/plugin/__tests__/plugin-command-module.test.ts +46 -40
  130. package/src/plugin/__tests__/plugin-host-boundary.test.ts +11 -0
  131. package/src/plugin/plugin-command-module.ts +3 -1
  132. package/src/plugin/plugin-command.ts +17 -16
  133. package/src/preset/__tests__/host-supplied-preset-registry.test.ts +98 -0
  134. package/src/preset/__tests__/preset-command-module.test.ts +102 -56
  135. package/src/preset/preset-command-module.ts +26 -8
  136. package/src/preset/preset-command.ts +85 -27
  137. package/src/provider/__tests__/org-policy.test.ts +4 -5
  138. package/src/provider/__tests__/provider-command-module.test.ts +11 -14
  139. package/src/provider/__tests__/provider-startup-host-settings.test.ts +16 -0
  140. package/src/provider/__tests__/scripted-interaction.ts +7 -5
  141. package/src/provider/provider-command-execution.ts +4 -4
  142. package/src/provider/provider-command-module.ts +2 -1
  143. package/src/provider/provider-command-profile-lifecycle.ts +4 -4
  144. package/src/provider/provider-command-profile-operations.ts +3 -3
  145. package/src/provider/provider-command-profile.ts +1 -1
  146. package/src/provider/provider-command-setup.ts +4 -4
  147. package/src/provider/provider-startup.ts +62 -35
  148. package/src/remote-control/__tests__/remote-control-command-module.test.ts +36 -0
  149. package/src/remote-control/__tests__/remote-control-command.test.ts +216 -0
  150. package/src/remote-control/index.ts +8 -0
  151. package/src/remote-control/remote-control-command-module.ts +61 -0
  152. package/src/remote-control/remote-control-command.ts +138 -0
  153. package/src/reset/__tests__/reset-command-module.test.ts +5 -5
  154. package/src/reset/reset-command-module.ts +2 -1
  155. package/src/reset/reset-command.ts +3 -4
  156. package/src/rewind/__tests__/rewind-command-module.test.ts +40 -0
  157. package/src/rewind/rewind-command-module.ts +2 -1
  158. package/src/rewind/rewind-command.ts +73 -6
  159. package/src/sandbox/__tests__/sandbox-command.test.ts +80 -0
  160. package/src/sandbox/index.ts +2 -0
  161. package/src/sandbox/sandbox-command-module.ts +56 -0
  162. package/src/sandbox/sandbox-command.ts +94 -0
  163. package/src/schedule/__tests__/loop-command-functional.test.ts +386 -0
  164. package/src/schedule/__tests__/loop-command.test.ts +360 -0
  165. package/src/schedule/__tests__/loop-jitter.test.ts +25 -0
  166. package/src/schedule/__tests__/monitor-model-permission-functional.test.ts +126 -0
  167. package/src/schedule/__tests__/schedule-command.test.ts +143 -3
  168. package/src/schedule/__tests__/schedule-redos.test.ts +81 -0
  169. package/src/schedule/index.ts +3 -0
  170. package/src/schedule/loop-command.ts +333 -0
  171. package/src/schedule/loop-jitter.ts +41 -0
  172. package/src/schedule/schedule-command-module.ts +92 -14
  173. package/src/schedule/schedule-command.ts +98 -9
  174. package/src/schedule/schedule-spec-parser.ts +5 -1
  175. package/src/session/__tests__/rename-host-persistence.test.ts +72 -0
  176. package/src/session/__tests__/session-command-module.test.ts +210 -45
  177. package/src/session/session-command-module.ts +68 -37
  178. package/src/session/session-command.ts +147 -80
  179. package/src/settings/settings-command-module.ts +3 -2
  180. package/src/shell/__tests__/resolve-shell-host.test.ts +11 -0
  181. package/src/shell/__tests__/shell-command-functional.test.ts +23 -1
  182. package/src/shell/resolve-shell.ts +2 -2
  183. package/src/shell/shell-command-module.ts +6 -5
  184. package/src/shell/shell-command.ts +9 -5
  185. package/src/skills/__tests__/skills-command-module.test.ts +69 -28
  186. package/src/skills/index.ts +1 -0
  187. package/src/skills/skills-command-module.ts +22 -5
  188. package/src/skills/skills-command.ts +14 -13
  189. package/src/statusline/__tests__/statusline-command-module.test.ts +5 -4
  190. package/src/statusline/statusline-command-module.ts +2 -1
  191. package/src/statusline/statusline-command.ts +4 -4
  192. package/src/theme/__tests__/theme-command.test.ts +204 -0
  193. package/src/theme/index.ts +12 -0
  194. package/src/theme/theme-command-module.ts +211 -0
  195. package/src/user-local/__tests__/user-local-command.test.ts +145 -110
  196. package/src/user-local/user-local-command-constants.ts +1 -1
  197. package/src/user-local/user-local-command-module.ts +6 -5
  198. package/src/user-local/user-local-command.ts +12 -6
  199. package/src/user-local/user-local-memory-command.ts +17 -7
  200. package/src/plugins/default-plugin-command-adapter.ts +0 -164
  201. package/src/plugins/default-plugin-command-source-loader.ts +0 -31
@@ -6,10 +6,15 @@ import {
6
6
  createBackgroundCommandModule,
7
7
  executeBackgroundCommand,
8
8
  } from '../index.js';
9
- import type { IBackgroundTaskState } from '@robota-sdk/agent-interface-transport';
9
+ import type { IBackgroundTaskState } from '@robota-sdk/agent-interface-execution';
10
+ import { createTestSessionRuntime } from '@robota-sdk/agent-framework/testing';
11
+ import {
12
+ createTestCommandHost,
13
+ type ICreateTestCommandHostOptions,
14
+ } from '@robota-sdk/agent-framework/testing';
10
15
 
11
- function createSessionRuntime(): ICommandSessionRuntime {
12
- return {
16
+ function createSessionRuntime() {
17
+ return createTestSessionRuntime({
13
18
  clearHistory: () => undefined,
14
19
  compact: async () => undefined,
15
20
  getContextState: () => ({
@@ -26,10 +31,10 @@ function createSessionRuntime(): ICommandSessionRuntime {
26
31
  getAutoCompactThreshold: () => false,
27
32
  getFullHistory: () => [],
28
33
  getHistory: () => [],
29
- };
34
+ });
30
35
  }
31
36
 
32
- function createTask(overrides?: Partial<IBackgroundTaskState>): IBackgroundTaskState {
37
+ function createTask(overrides?: Partial<IBackgroundTaskState<'agent'>>): IBackgroundTaskState {
33
38
  return {
34
39
  id: 'agent_1',
35
40
  kind: 'agent',
@@ -47,53 +52,55 @@ function createTask(overrides?: Partial<IBackgroundTaskState>): IBackgroundTaskS
47
52
  };
48
53
  }
49
54
 
50
- function createCommandHostContext(overrides?: Partial<ICommandHostContext>): ICommandHostContext {
51
- return {
52
- getSession: () => createSessionRuntime(),
53
- getContextState: () => ({
54
- maxTokens: 100,
55
- usedTokens: 10,
56
- usedPercentage: 10,
57
- remainingPercentage: 90,
58
- }),
59
- getAutoCompactThreshold: () => 0.8,
60
- compactContext: async () => undefined,
61
- getCwd: () => '/workspace',
62
- listEditCheckpoints: () => [],
63
- restoreEditCheckpoint: async () => ({
64
- target: {
65
- id: 'checkpoint_1',
66
- sessionId: 'session_1',
67
- sequence: 1,
68
- prompt: 'edit',
69
- createdAt: '2026-05-03T00:00:00.000Z',
70
- fileCount: 0,
71
- },
72
- restoredCheckpointCount: 1,
73
- restoredFileCount: 0,
74
- removedCheckpointCount: 0,
75
- }),
76
- rollbackEditCheckpoint: async () => ({
77
- target: {
78
- id: 'checkpoint_1',
79
- sessionId: 'session_1',
80
- sequence: 1,
81
- prompt: 'edit',
82
- createdAt: '2026-05-03T00:00:00.000Z',
83
- fileCount: 0,
84
- },
85
- restoredCheckpointCount: 1,
86
- restoredFileCount: 0,
87
- removedCheckpointCount: 0,
88
- }),
89
- getUsedMemoryReferences: () => [],
90
- recordMemoryEvent: () => undefined,
91
- listBackgroundTasks: () => [],
92
- readBackgroundTaskLog: async (taskId) => ({ taskId, lines: [] }),
93
- cancelBackgroundTask: async () => undefined,
94
- closeBackgroundTask: async () => undefined,
95
- ...overrides,
96
- };
55
+ function createCommandHostContext(overrides?: ICreateTestCommandHostOptions['overrides']) {
56
+ return createTestCommandHost({
57
+ overrides: {
58
+ getSession: () => createSessionRuntime(),
59
+ getContextState: () => ({
60
+ maxTokens: 100,
61
+ usedTokens: 10,
62
+ usedPercentage: 10,
63
+ remainingPercentage: 90,
64
+ }),
65
+ getAutoCompactThreshold: () => 0.8,
66
+ compactContext: async () => undefined,
67
+ getCwd: () => '/workspace',
68
+ listEditCheckpoints: () => [],
69
+ restoreEditCheckpoint: async () => ({
70
+ target: {
71
+ id: 'checkpoint_1',
72
+ sessionId: 'session_1',
73
+ sequence: 1,
74
+ prompt: 'edit',
75
+ createdAt: '2026-05-03T00:00:00.000Z',
76
+ fileCount: 0,
77
+ },
78
+ restoredCheckpointCount: 1,
79
+ restoredFileCount: 0,
80
+ removedCheckpointCount: 0,
81
+ }),
82
+ rollbackEditCheckpoint: async () => ({
83
+ target: {
84
+ id: 'checkpoint_1',
85
+ sessionId: 'session_1',
86
+ sequence: 1,
87
+ prompt: 'edit',
88
+ createdAt: '2026-05-03T00:00:00.000Z',
89
+ fileCount: 0,
90
+ },
91
+ restoredCheckpointCount: 1,
92
+ restoredFileCount: 0,
93
+ removedCheckpointCount: 0,
94
+ }),
95
+ getUsedMemoryReferences: () => [],
96
+ recordMemoryEvent: () => undefined,
97
+ listBackgroundTasks: () => [],
98
+ readBackgroundTaskLog: async (taskId) => ({ taskId, lines: [] }),
99
+ cancelBackgroundTask: async () => undefined,
100
+ closeBackgroundTask: async () => undefined,
101
+ ...overrides,
102
+ },
103
+ });
97
104
  }
98
105
 
99
106
  describe('background command module', () => {
@@ -6,7 +6,7 @@ import {
6
6
  import { executeBackgroundCommand } from './background-command.js';
7
7
 
8
8
  import type { ICommandModule, ISystemCommand } from '@robota-sdk/agent-framework';
9
- import type { ICommand, ICommandSource } from '@robota-sdk/agent-interface-transport';
9
+ import type { ICommand, ICommandSource } from '@robota-sdk/agent-interface-command';
10
10
 
11
11
  export function createBackgroundCommandEntry(): ICommand {
12
12
  return {
@@ -14,6 +14,7 @@ export function createBackgroundCommandEntry(): ICommand {
14
14
  displayName: 'Background Tasks',
15
15
  description: BACKGROUND_COMMAND_DESCRIPTION,
16
16
  source: 'background',
17
+ // User-only: a view onto the user's job panel; the model manages its own jobs through `agent`.
17
18
  modelInvocable: false,
18
19
  subcommands: buildBackgroundCommandSubcommands(),
19
20
  };
@@ -8,15 +8,15 @@ import {
8
8
  readCommandBackgroundTaskLog,
9
9
  } from '@robota-sdk/agent-framework';
10
10
 
11
- import type { ICommandHostContext } from '@robota-sdk/agent-framework';
12
- import type { ICommandResult } from '@robota-sdk/agent-interface-transport';
11
+ import type { ICommandHostBackgroundTasks } from '@robota-sdk/agent-framework';
12
+ import type { ICommandResult } from '@robota-sdk/agent-interface-command';
13
13
 
14
14
  function parseCommandParts(args: string): string[] {
15
15
  return args.trim().split(/\s+/).filter(Boolean);
16
16
  }
17
17
 
18
18
  export async function executeBackgroundCommand(
19
- context: ICommandHostContext,
19
+ context: ICommandHostBackgroundTasks,
20
20
  args: string,
21
21
  ): Promise<ICommandResult> {
22
22
  const [action = 'list', taskId, ...reasonParts] = parseCommandParts(args);
@@ -0,0 +1,33 @@
1
+ import type { ICommand, ICommandResult } from '@robota-sdk/agent-interface-command';
2
+ import type { ICommandHostContext, ISystemCommand } from '@robota-sdk/agent-framework';
3
+
4
+ /** Build executable metadata from the palette entry so user and model views cannot drift. */
5
+ export function createSystemCommandFromEntry(
6
+ entry: ICommand,
7
+ behavior: {
8
+ lifecycle: NonNullable<ISystemCommand['lifecycle']>;
9
+ requiresPermission: boolean;
10
+ execute: (
11
+ context: ICommandHostContext,
12
+ args: string,
13
+ ) => ICommandResult | Promise<ICommandResult>;
14
+ semanticRole?: ISystemCommand['semanticRole'];
15
+ },
16
+ ): ISystemCommand {
17
+ return {
18
+ name: entry.name,
19
+ ...(entry.displayName !== undefined ? { displayName: entry.displayName } : {}),
20
+ description: entry.description,
21
+ ...(entry.example !== undefined ? { example: entry.example } : {}),
22
+ ...(entry.modelInvocable !== undefined ? { modelInvocable: entry.modelInvocable } : {}),
23
+ ...(entry.modelDescription !== undefined ? { modelDescription: entry.modelDescription } : {}),
24
+ ...(entry.userInvocable !== undefined ? { userInvocable: entry.userInvocable } : {}),
25
+ ...(entry.argumentHint !== undefined ? { argumentHint: entry.argumentHint } : {}),
26
+ ...(entry.safety !== undefined ? { safety: entry.safety } : {}),
27
+ ...(entry.subcommands !== undefined ? { subcommands: entry.subcommands } : {}),
28
+ ...(behavior.semanticRole !== undefined ? { semanticRole: behavior.semanticRole } : {}),
29
+ lifecycle: behavior.lifecycle,
30
+ requiresPermission: behavior.requiresPermission,
31
+ execute: behavior.execute,
32
+ };
33
+ }
@@ -2,8 +2,13 @@ import { describe, expect, it, vi } from 'vitest';
2
2
  import type { ICommandHostContext, ICommandSessionRuntime } from '@robota-sdk/agent-framework';
3
3
  import { InteractiveSession, SystemCommandExecutor } from '@robota-sdk/agent-framework';
4
4
  import { createCompactCommandModule } from '../compact-command-module.js';
5
+ import type { ICommandHostContextWindow } from '@robota-sdk/agent-framework';
6
+ import {
7
+ createTestCommandHost,
8
+ createTestSessionRuntime,
9
+ } from '@robota-sdk/agent-framework/testing';
5
10
 
6
- type TContextWindowState = ReturnType<ICommandHostContext['getContextState']>;
11
+ type TContextWindowState = ReturnType<ICommandHostContextWindow['getContextState']>;
7
12
  type TPermissionMode = ReturnType<ICommandSessionRuntime['getPermissionMode']>;
8
13
 
9
14
  const BEFORE_CONTEXT: TContextWindowState = {
@@ -20,10 +25,10 @@ const AFTER_CONTEXT: TContextWindowState = {
20
25
  remainingPercentage: 65,
21
26
  };
22
27
 
23
- function createRuntime(beforeCount = 10, afterCount = 3): ICommandSessionRuntime {
28
+ function createRuntime(beforeCount = 10, afterCount = 3) {
24
29
  let mode: TPermissionMode = 'default';
25
30
  const getMessageCount = vi.fn().mockReturnValueOnce(beforeCount).mockReturnValue(afterCount);
26
- return {
31
+ return createTestSessionRuntime({
27
32
  clearHistory: vi.fn(),
28
33
  compact: vi.fn().mockResolvedValue(undefined),
29
34
  getContextState: vi.fn().mockReturnValue(AFTER_CONTEXT),
@@ -37,10 +42,10 @@ function createRuntime(beforeCount = 10, afterCount = 3): ICommandSessionRuntime
37
42
  getAutoCompactThreshold: () => 0.835,
38
43
  getFullHistory: () => [],
39
44
  getHistory: () => [],
40
- };
45
+ });
41
46
  }
42
47
 
43
- function createCommandHostContext(): ICommandHostContext & {
48
+ function createCommandHostContext(): ReturnType<typeof createTestCommandHost> & {
44
49
  compactContext: ReturnType<typeof vi.fn>;
45
50
  } {
46
51
  const runtime = createRuntime();
@@ -48,23 +53,25 @@ function createCommandHostContext(): ICommandHostContext & {
48
53
  .fn()
49
54
  .mockReturnValueOnce(BEFORE_CONTEXT)
50
55
  .mockReturnValue(AFTER_CONTEXT);
51
- return {
52
- getSession: () => runtime,
53
- getContextState,
54
- getAutoCompactThreshold: () => 0.835,
55
- compactContext: vi.fn().mockResolvedValue(undefined),
56
- getCwd: () => '/workspace',
57
- listCommands: () => [],
58
- listEditCheckpoints: () => [],
59
- restoreEditCheckpoint: vi.fn(),
60
- rollbackEditCheckpoint: vi.fn(),
61
- getUsedMemoryReferences: () => [],
62
- recordMemoryEvent: vi.fn(),
63
- listBackgroundTasks: () => [],
64
- readBackgroundTaskLog: vi.fn().mockResolvedValue({ taskId: 'task_1', lines: [] }),
65
- cancelBackgroundTask: vi.fn(),
66
- closeBackgroundTask: vi.fn(),
67
- };
56
+ return createTestCommandHost({
57
+ overrides: {
58
+ getSession: () => runtime,
59
+ getContextState,
60
+ getAutoCompactThreshold: () => 0.835,
61
+ compactContext: vi.fn().mockResolvedValue(undefined),
62
+ getCwd: () => '/workspace',
63
+ listCommands: () => [],
64
+ listEditCheckpoints: () => [],
65
+ restoreEditCheckpoint: vi.fn(),
66
+ rollbackEditCheckpoint: vi.fn(),
67
+ getUsedMemoryReferences: () => [],
68
+ recordMemoryEvent: vi.fn(),
69
+ listBackgroundTasks: () => [],
70
+ readBackgroundTaskLog: vi.fn().mockResolvedValue({ taskId: 'task_1', lines: [] }),
71
+ cancelBackgroundTask: vi.fn(),
72
+ closeBackgroundTask: vi.fn(),
73
+ },
74
+ }) as ReturnType<typeof createCommandHostContext>;
68
75
  }
69
76
 
70
77
  describe('createCompactCommandModule', () => {
@@ -86,6 +93,7 @@ describe('createCompactCommandModule', () => {
86
93
  expect(command).toEqual(
87
94
  expect.objectContaining({
88
95
  name: 'compact',
96
+ semanticRole: 'contextReduction',
89
97
  lifecycle: 'blocking',
90
98
  modelInvocable: true,
91
99
  safety: 'write',
@@ -102,7 +110,7 @@ describe('createCompactCommandModule', () => {
102
110
  {
103
111
  name: 'compact',
104
112
  kind: 'builtin-command',
105
- description: 'Compress context window',
113
+ description: expect.stringContaining('Summarize older conversation turns'),
106
114
  userInvocable: true,
107
115
  modelInvocable: true,
108
116
  argumentHint: '[instructions]',
@@ -1,13 +1,20 @@
1
1
  import { executeCompactCommand } from './compact-command.js';
2
2
 
3
3
  import type { ICommandModule, ISystemCommand } from '@robota-sdk/agent-framework';
4
- import type { ICommand, ICommandSource } from '@robota-sdk/agent-interface-transport';
4
+ import type { ICommand, ICommandSource } from '@robota-sdk/agent-interface-command';
5
5
 
6
6
  export function createCompactCommandEntry(): ICommand {
7
7
  return {
8
8
  name: 'compact',
9
9
  displayName: 'Compact Context',
10
10
  description: 'Compress context window',
11
+ // Model-invocable: compaction only summarizes the model's own context, and the model is the one
12
+ // that notices when it is running out of room.
13
+ modelDescription:
14
+ 'Summarize older conversation turns to free context-window space. Use it when the context is ' +
15
+ 'nearly full (check with the context command) or before starting a large new task; optional ' +
16
+ 'instructions say what the summary must keep. Returns how many messages were removed and the ' +
17
+ 'context usage before and after.',
11
18
  source: 'compact',
12
19
  modelInvocable: true,
13
20
  argumentHint: '[instructions]',
@@ -20,8 +27,10 @@ function createCompactSystemCommand(): ISystemCommand {
20
27
  const entry = createCompactCommandEntry();
21
28
  return {
22
29
  name: entry.name,
30
+ semanticRole: 'contextReduction',
23
31
  displayName: entry.displayName,
24
32
  description: entry.description,
33
+ ...(entry.modelDescription !== undefined ? { modelDescription: entry.modelDescription } : {}),
25
34
  example: entry.example,
26
35
  requiresPermission: false,
27
36
  userInvocable: true,
@@ -1,7 +1,10 @@
1
1
  import { compactCommandContext } from '@robota-sdk/agent-framework';
2
2
 
3
- import type { ICommandHostContext } from '@robota-sdk/agent-framework';
4
- import type { ICommandResult } from '@robota-sdk/agent-interface-transport';
3
+ import type {
4
+ ICommandHostContextWindow,
5
+ ICommandHostSessionAccess,
6
+ } from '@robota-sdk/agent-framework';
7
+ import type { ICommandResult } from '@robota-sdk/agent-interface-command';
5
8
 
6
9
  function parseInstructions(args: string): string | undefined {
7
10
  const instructions = args.trim();
@@ -9,7 +12,7 @@ function parseInstructions(args: string): string | undefined {
9
12
  }
10
13
 
11
14
  export async function executeCompactCommand(
12
- context: ICommandHostContext,
15
+ context: ICommandHostContextWindow & ICommandHostSessionAccess,
13
16
  args: string,
14
17
  ): Promise<ICommandResult> {
15
18
  const result = await compactCommandContext(context, parseInstructions(args));