@robota-sdk/agent-command 3.0.0-beta.86 → 3.0.0-beta.88

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 (62) hide show
  1. package/CHANGELOG.md +64 -12
  2. package/README.md +6 -3
  3. package/dist/node/index.cjs +72 -70
  4. package/dist/node/index.d.cts +16 -8
  5. package/dist/node/index.d.cts.map +1 -1
  6. package/dist/node/index.d.ts +16 -8
  7. package/dist/node/index.d.ts.map +1 -1
  8. package/dist/node/index.js +51 -49
  9. package/dist/node/index.js.map +1 -1
  10. package/package.json +15 -13
  11. package/src/agent/__tests__/agent-command.test.ts +5 -5
  12. package/src/agent/agent-command-module.ts +1 -1
  13. package/src/background/__tests__/background-command-module.test.ts +6 -6
  14. package/src/default/__tests__/__snapshots__/model-exposure.test.ts.snap +15 -4
  15. package/src/default/__tests__/default-command-modules.test.ts +2 -2
  16. package/src/default/__tests__/model-exposure.test.ts +18 -5
  17. package/src/default/__tests__/org-policy-forwarding.test.ts +1 -1
  18. package/src/default/default-command-modules.ts +2 -2
  19. package/src/devices/devices-command-module.ts +1 -1
  20. package/src/doctor/__tests__/doctor-command-module.test.ts +10 -10
  21. package/src/doctor/__tests__/doctor-display-vocabulary.test.ts +1 -1
  22. package/src/doctor/__tests__/doctor-fixture.ts +14 -14
  23. package/src/doctor/__tests__/doctor-runner.test.ts +57 -57
  24. package/src/doctor/doctor-storage-probe.ts +1 -1
  25. package/src/doctor/doctor-types.ts +2 -2
  26. package/src/editor/__tests__/editor-command-functional.test.ts +1 -1
  27. package/src/fork/__tests__/fork-command.test.ts +1 -1
  28. package/src/fork/fork-command-module.ts +1 -1
  29. package/src/git/__tests__/git-command-module.test.ts +1 -1
  30. package/src/handoff/__tests__/handoff-command-module.test.ts +1 -1
  31. package/src/handoff/handoff-command-module.ts +1 -1
  32. package/src/keybindings/keybindings-command-module.ts +1 -1
  33. package/src/mcp-activation/__tests__/mcp-activation-command.test.ts +8 -8
  34. package/src/mcp-activation/__tests__/mcp-model-view.test.ts +43 -12
  35. package/src/mcp-activation/__tests__/mcp-skill-command.test.ts +141 -0
  36. package/src/mcp-activation/mcp-activation-command-module.ts +27 -2
  37. package/src/mcp-activation/mcp-activation-command.ts +149 -15
  38. package/src/mcp-activation/mcp-model-notice.ts +19 -5
  39. package/src/mcp-activation/mcp-model-status.ts +7 -2
  40. package/src/memory/__tests__/memory-command-module.test.ts +89 -16
  41. package/src/memory/memory-command-module.ts +4 -1
  42. package/src/memory/memory-command.ts +53 -1
  43. package/src/peers/__tests__/peers-command-module.test.ts +1 -1
  44. package/src/peers/peers-command-module.ts +1 -1
  45. package/src/permissions/__tests__/permissions-command-module.test.ts +4 -4
  46. package/src/plugin/__tests__/plugin-active-turn.test.ts +100 -0
  47. package/src/plugin/__tests__/plugin-command-module.test.ts +7 -7
  48. package/src/plugin/plugin-command-module.ts +4 -0
  49. package/src/provider/provider-startup.ts +4 -2
  50. package/src/remote-control/__tests__/remote-control-command.test.ts +2 -2
  51. package/src/rewind/__tests__/rewind-command-module.test.ts +4 -3
  52. package/src/rewind/rewind-command.ts +27 -21
  53. package/src/schedule/schedule-command-module.ts +1 -1
  54. package/src/session/__tests__/session-command-module.test.ts +2 -2
  55. package/src/skills/__tests__/skill-read-command.test.ts +64 -0
  56. package/src/skills/__tests__/skills-command-module.test.ts +2 -1
  57. package/src/skills/skill-read-command.ts +60 -0
  58. package/src/skills/skills-command-module.ts +3 -2
  59. package/src/terminal-client/__tests__/terminal-client-commands.test.ts +1 -1
  60. package/src/theme/__tests__/theme-command.test.ts +1 -1
  61. package/src/theme/theme-command-module.ts +1 -1
  62. package/src/user-local/__tests__/user-local-command.test.ts +16 -16
@@ -15,8 +15,13 @@ import type {
15
15
  IEditCheckpointRestoreResult,
16
16
  IEditCheckpointSummary,
17
17
  } from '@robota-sdk/agent-framework';
18
+ import type { ICommandProductVocabulary } from '@robota-sdk/agent-framework';
18
19
  import type { ICommandResult } from '@robota-sdk/agent-interface-command';
19
20
 
21
+ type TRewindCommandContext = ICommandHostCheckpoints & {
22
+ getCommandProductVocabulary?(): ICommandProductVocabulary | undefined;
23
+ };
24
+
20
25
  const SUBCOMMAND_INDEX = 0;
21
26
  const CHECKPOINT_ID_INDEX = 1;
22
27
  const PROMPT_PREVIEW_LENGTH = 120;
@@ -123,17 +128,18 @@ function formatRollbackResult(result: IEditCheckpointRestoreResult): ICommandRes
123
128
  }
124
129
 
125
130
  /** A restricted workspace is the one case the user fixes with a command; the rest say why. */
126
- function unavailableMessage(error: EditCheckpointsUnavailableError): string {
127
- return error.reason === 'restricted-workspace'
128
- ? 'Edit checkpoints need a trusted workspace: run robota trust --yes, then restart robota.'
129
- : error.message;
131
+ function unavailableMessage(error: EditCheckpointsUnavailableError, cliName?: string): string {
132
+ if (error.reason !== 'restricted-workspace') return error.message;
133
+ return cliName === undefined
134
+ ? 'Edit checkpoints need a trusted workspace. Trust it from a terminal, then restart the session.'
135
+ : `Edit checkpoints need a trusted workspace: run ${cliName} trust --yes, then restart ${cliName}.`;
130
136
  }
131
137
 
132
- function formatError(error: Error | string): ICommandResult {
138
+ function formatError(error: Error | string, cliName?: string): ICommandResult {
133
139
  return {
134
140
  message:
135
141
  error instanceof EditCheckpointsUnavailableError
136
- ? unavailableMessage(error)
142
+ ? unavailableMessage(error, cliName)
137
143
  : error instanceof Error
138
144
  ? error.message
139
145
  : String(error),
@@ -141,53 +147,53 @@ function formatError(error: Error | string): ICommandResult {
141
147
  };
142
148
  }
143
149
 
144
- function list(context: ICommandHostCheckpoints): ICommandResult {
150
+ function list(context: TRewindCommandContext): ICommandResult {
145
151
  try {
146
152
  return formatList(listCommandEditCheckpoints(context));
147
153
  } catch (error) {
148
- return formatError(error instanceof Error ? error : String(error));
154
+ return formatError(error instanceof Error ? error : String(error), context.getCommandProductVocabulary?.()?.cliName);
149
155
  }
150
156
  }
151
157
 
152
158
  function inspect(
153
- context: ICommandHostCheckpoints,
159
+ context: TRewindCommandContext,
154
160
  checkpointId: string | undefined,
155
161
  ): ICommandResult {
156
162
  if (!checkpointId) return usage();
157
163
  try {
158
164
  return formatInspection(inspectCommandEditCheckpoint(context, checkpointId));
159
165
  } catch (error) {
160
- return formatError(error instanceof Error ? error : String(error));
166
+ return formatError(error instanceof Error ? error : String(error), context.getCommandProductVocabulary?.()?.cliName);
161
167
  }
162
168
  }
163
169
 
164
170
  async function restore(
165
- context: ICommandHostCheckpoints,
171
+ context: TRewindCommandContext,
166
172
  checkpointId: string | undefined,
167
173
  ): Promise<ICommandResult> {
168
174
  if (!checkpointId) return usage();
169
175
  try {
170
176
  return formatRestoreResult(await restoreCommandEditCheckpoint(context, checkpointId));
171
177
  } catch (error) {
172
- return formatError(error instanceof Error ? error : String(error));
178
+ return formatError(error instanceof Error ? error : String(error), context.getCommandProductVocabulary?.()?.cliName);
173
179
  }
174
180
  }
175
181
 
176
182
  async function rollback(
177
- context: ICommandHostCheckpoints,
183
+ context: TRewindCommandContext,
178
184
  checkpointId: string | undefined,
179
185
  ): Promise<ICommandResult> {
180
186
  if (!checkpointId) return usage();
181
187
  try {
182
188
  return formatRollbackResult(await rollbackCommandEditCheckpoint(context, checkpointId));
183
189
  } catch (error) {
184
- return formatError(error instanceof Error ? error : String(error));
190
+ return formatError(error instanceof Error ? error : String(error), context.getCommandProductVocabulary?.()?.cliName);
185
191
  }
186
192
  }
187
193
 
188
194
  // SELFHOST-007: branching time-travel handlers.
189
195
  async function fork(
190
- context: ICommandHostCheckpoints,
196
+ context: TRewindCommandContext,
191
197
  checkpointId: string | undefined,
192
198
  ): Promise<ICommandResult> {
193
199
  if (!checkpointId) return usage();
@@ -202,12 +208,12 @@ async function fork(
202
208
  data: { target: result.target, restoredFileCount: result.restoredFileCount },
203
209
  };
204
210
  } catch (error) {
205
- return formatError(error instanceof Error ? error : String(error));
211
+ return formatError(error instanceof Error ? error : String(error), context.getCommandProductVocabulary?.()?.cliName);
206
212
  }
207
213
  }
208
214
 
209
215
  function switchBranch(
210
- context: ICommandHostCheckpoints,
216
+ context: TRewindCommandContext,
211
217
  checkpointId: string | undefined,
212
218
  ): ICommandResult {
213
219
  if (!checkpointId) return usage();
@@ -215,11 +221,11 @@ function switchBranch(
215
221
  switchCommandEditCheckpointBranch(context, checkpointId);
216
222
  return { message: `Switched to checkpoint branch ${checkpointId}.`, success: true };
217
223
  } catch (error) {
218
- return formatError(error instanceof Error ? error : String(error));
224
+ return formatError(error instanceof Error ? error : String(error), context.getCommandProductVocabulary?.()?.cliName);
219
225
  }
220
226
  }
221
227
 
222
- function branches(context: ICommandHostCheckpoints): ICommandResult {
228
+ function branches(context: TRewindCommandContext): ICommandResult {
223
229
  try {
224
230
  const tips = listCommandEditCheckpointBranches(context);
225
231
  return {
@@ -231,12 +237,12 @@ function branches(context: ICommandHostCheckpoints): ICommandResult {
231
237
  data: { branches: tips },
232
238
  };
233
239
  } catch (error) {
234
- return formatError(error instanceof Error ? error : String(error));
240
+ return formatError(error instanceof Error ? error : String(error), context.getCommandProductVocabulary?.()?.cliName);
235
241
  }
236
242
  }
237
243
 
238
244
  export async function executeRewindCommand(
239
- context: ICommandHostCheckpoints,
245
+ context: TRewindCommandContext,
240
246
  rawArgs: string,
241
247
  ): Promise<ICommandResult> {
242
248
  const args = rawArgs.trim().split(/\s+/).filter(Boolean);
@@ -179,6 +179,6 @@ export function createScheduleCommandModule(options: ILoopCommandOptions = {}):
179
179
  createMonitorSystemCommand(),
180
180
  createLoopSystemCommand(options),
181
181
  ],
182
- sessionRequirements: ['agent-runtime'],
182
+ sessionRequirements: ['runtime'],
183
183
  };
184
184
  }
@@ -544,7 +544,7 @@ describe('createSessionCommandModule', () => {
544
544
  const context = {
545
545
  ...createCommandContext(),
546
546
  validateCurrentSessionReplayLog: () => ({
547
- logFile: '/workspace/.robota/logs/session_1.jsonl',
547
+ logFile: '/workspace/.fixture-state/logs/session_1.jsonl',
548
548
  entryCount: 2,
549
549
  validation: {
550
550
  ok: false,
@@ -565,7 +565,7 @@ describe('createSessionCommandModule', () => {
565
565
  expect(result?.success).toBe(false);
566
566
  expect(result?.message).toContain('PROVIDER_NATIVE_RAW_PAYLOAD_MISSING');
567
567
  expect(result?.data).toEqual({
568
- logFile: '/workspace/.robota/logs/session_1.jsonl',
568
+ logFile: '/workspace/.fixture-state/logs/session_1.jsonl',
569
569
  entryCount: 2,
570
570
  issueCount: 1,
571
571
  ok: false,
@@ -0,0 +1,64 @@
1
+ import { expect, it, vi } from 'vitest';
2
+ import { SystemCommandExecutor } from '@robota-sdk/agent-framework';
3
+ import { createTestCommandHost } from '@robota-sdk/agent-framework/testing';
4
+ import { createSkillsCommandModule } from '../skills-command-module.js';
5
+
6
+ it('offers supporting reads to the model under the composed semantic command identity', async () => {
7
+ const module = createSkillsCommandModule({ contributionSources: [] });
8
+ const executor = new SystemCommandExecutor([...(module.systemCommands ?? [])]);
9
+ expect(executor.getSemanticRoles().skillResourceRead).toBe('skill-read');
10
+ expect(executor.isModelInvocable('skill-read')).toBe(true);
11
+ expect(
12
+ executor.listModelInvocableCommands().find((command) => command.name === 'skill-read')
13
+ ?.description,
14
+ ).toContain('already activated');
15
+ const resource = {
16
+ uri: 'skill://demo/reference%20file.txt',
17
+ digest: 'sha256:verified',
18
+ size: 7,
19
+ text: 'content',
20
+ };
21
+ const readSkillResource = vi.fn(async () => resource);
22
+ const context = createTestCommandHost({ overrides: { readSkillResource } });
23
+ const result = await executor.executeModelInvocable(
24
+ 'skill-read',
25
+ context,
26
+ JSON.stringify(['demo', resource.uri]),
27
+ );
28
+ expect(readSkillResource).toHaveBeenCalledWith('demo', resource.uri);
29
+ expect(result).toMatchObject({ success: true, data: resource });
30
+ });
31
+
32
+ it.each(['', '{}', '["demo"]', '["demo", 3]', '["demo", "uri", "extra"]', '["", "uri"]'])(
33
+ 'refuses malformed resource arguments without calling the host: %s',
34
+ async (args) => {
35
+ const executor = new SystemCommandExecutor([
36
+ ...(createSkillsCommandModule({ contributionSources: [] }).systemCommands ?? []),
37
+ ]);
38
+ const readSkillResource = vi.fn();
39
+ const result = await executor.executeModelInvocable(
40
+ 'skill-read',
41
+ createTestCommandHost({ overrides: { readSkillResource } }),
42
+ args,
43
+ );
44
+ expect(result?.success).toBe(false);
45
+ expect(readSkillResource).not.toHaveBeenCalled();
46
+ },
47
+ );
48
+
49
+ it('reports an unavailable host instead of acquiring a skill or falling back to filesystem reads', async () => {
50
+ const executor = new SystemCommandExecutor([
51
+ ...(createSkillsCommandModule({ contributionSources: [] }).systemCommands ?? []),
52
+ ]);
53
+ const executeSkillCommandByName = vi.fn();
54
+ const result = await executor.executeModelInvocable(
55
+ 'skill-read',
56
+ createTestCommandHost({ overrides: { executeSkillCommandByName } }),
57
+ '["demo", "skill://demo/file"]',
58
+ );
59
+ expect(result).toMatchObject({
60
+ success: false,
61
+ message: expect.stringContaining('does not provide'),
62
+ });
63
+ expect(executeSkillCommandByName).not.toHaveBeenCalled();
64
+ });
@@ -94,6 +94,7 @@ describe('createSkillsCommandModule', () => {
94
94
  expect(module.name).toBe('agent-command-skills');
95
95
  expect(module.commandSources?.[0]?.getCommands().map((entry) => entry.name)).toEqual([
96
96
  'skills',
97
+ 'skill-read',
97
98
  ]);
98
99
  expect(command).toMatchObject({
99
100
  name: 'skills',
@@ -164,7 +165,7 @@ describe('createSkillsCommandModule', () => {
164
165
  });
165
166
 
166
167
  it('lets the SDK normalize virtual /skill-name commands into the composed skills command', async () => {
167
- const cwd = realpathSync(mkdtempSync(join(tmpdir(), 'robota-skills-command-module-')));
168
+ const cwd = realpathSync(mkdtempSync(join(tmpdir(), 'agent-test-skills-command-module-')));
168
169
  createTempSkill(cwd);
169
170
  const parentSession = makeParentSession();
170
171
  const session = new InteractiveSession({
@@ -0,0 +1,60 @@
1
+ import type { ICommand, ICommandResult } from '@robota-sdk/agent-interface-command';
2
+ import type { ICommandHostCatalog, ISystemCommand } from '@robota-sdk/agent-framework';
3
+
4
+ export function createSkillReadCommandEntry(): ICommand {
5
+ return {
6
+ name: 'skill-read',
7
+ description: 'Read a supporting file from a skill active in this execution',
8
+ modelDescription:
9
+ 'Read verified supporting bytes from a skill already activated in this execution. Use when its instructions refer to a resource in the returned manifest. Args are a JSON array ["<skill-name>", "<resource-uri>"]. Returns the verified URI, digest, size and text or base64 blob with optional MIME type. This does not activate nested skills or grant consent; unactivated skills, undeclared resources and ended executions are refused. Binary blobs are returned as encoded data, not a rendered image.',
10
+ argumentHint: '["<skill-name>", "<resource-uri>"]',
11
+ source: 'skills',
12
+ userInvocable: true,
13
+ modelInvocable: true,
14
+ safety: 'read-only',
15
+ };
16
+ }
17
+
18
+ export async function executeSkillReadCommand(
19
+ context: Pick<ICommandHostCatalog, 'readSkillResource'>,
20
+ args = '',
21
+ ): Promise<ICommandResult> {
22
+ let input: unknown;
23
+ try {
24
+ input = JSON.parse(args);
25
+ } catch {
26
+ return { success: false, message: 'Use /skill-read ["<skill-name>", "<resource-uri>"]' };
27
+ }
28
+ if (
29
+ !Array.isArray(input) ||
30
+ input.length !== 2 ||
31
+ input.some((value) => typeof value !== 'string' || !value.length)
32
+ )
33
+ return { success: false, message: 'Use /skill-read ["<skill-name>", "<resource-uri>"]' };
34
+ if (!context.readSkillResource)
35
+ return { success: false, message: 'This host does not provide active skill resource reads.' };
36
+ try {
37
+ const resource = await context.readSkillResource(input[0], input[1]);
38
+ return {
39
+ success: true,
40
+ message: `Read verified skill resource: ${resource.uri}`,
41
+ data: { ...resource },
42
+ };
43
+ } catch (error) {
44
+ return {
45
+ success: false,
46
+ message: `Skill resource read refused: ${error instanceof Error ? error.message : 'host refused the read'}`,
47
+ };
48
+ }
49
+ }
50
+
51
+ export function createSkillReadSystemCommand(): ISystemCommand {
52
+ const entry = createSkillReadCommandEntry();
53
+ return {
54
+ ...entry,
55
+ semanticRole: 'skillResourceRead',
56
+ requiresPermission: false,
57
+ lifecycle: 'inline',
58
+ execute: executeSkillReadCommand,
59
+ };
60
+ }
@@ -1,4 +1,5 @@
1
1
  import { SkillCommandSource } from '@robota-sdk/agent-framework';
2
+ import { createSkillReadCommandEntry, createSkillReadSystemCommand } from './skill-read-command.js';
2
3
 
3
4
  import {
4
5
  executeSkillsCommand,
@@ -57,7 +58,7 @@ export class SkillsCommandSource implements ICommandSource {
57
58
  readonly name = 'skills';
58
59
 
59
60
  getCommands(): ICommand[] {
60
- return [createSkillsCommandEntry()];
61
+ return [createSkillsCommandEntry(), createSkillReadCommandEntry()];
61
62
  }
62
63
  }
63
64
 
@@ -70,6 +71,6 @@ export function createSkillsCommandModule(options: ISkillsCommandModuleOptions):
70
71
  return {
71
72
  name: 'agent-command-skills',
72
73
  commandSources,
73
- systemCommands: [createSkillsSystemCommand()],
74
+ systemCommands: [createSkillsSystemCommand(), createSkillReadSystemCommand()],
74
75
  };
75
76
  }
@@ -35,7 +35,7 @@ import type {
35
35
  } from '@robota-sdk/agent-interface-command';
36
36
 
37
37
  /** User-local storage lives in a private per-run directory, never a fixed name under /tmp. */
38
- const USER_LOCAL_STORAGE_ROOT = mkdtempSync(join(tmpdir(), 'robota-test-'));
38
+ const USER_LOCAL_STORAGE_ROOT = mkdtempSync(join(tmpdir(), 'agent-test-test-'));
39
39
  afterAll(() => rmSync(USER_LOCAL_STORAGE_ROOT, { recursive: true, force: true }));
40
40
 
41
41
  const providerDefinitions: readonly IProviderDefinition[] = [];
@@ -73,7 +73,7 @@ describe('/theme without a catalogue (SCREEN-2002 TC-09)', () => {
73
73
  const result = executeThemeCommand(undefined, 'light');
74
74
 
75
75
  expect(result.success).toBe(false);
76
- expect(result.message).toMatch(/Run \/theme in the robota terminal/);
76
+ expect(result.message).toMatch(/Run \/theme there/);
77
77
  expect(result.hostActions).toBeUndefined();
78
78
  });
79
79
  });
@@ -19,7 +19,7 @@ const THEME_ARGUMENT_HINT = 'list | <theme-id> | syntax on|off | motion on|off';
19
19
  // A host without a terminal (the desktop app's sidecar) still answers, so the command is never
20
20
  // "unknown" there — it says where themes live instead.
21
21
  const THEME_UNAVAILABLE =
22
- 'Themes belong to the robota terminal, and this surface has none. Run /theme in the robota terminal.';
22
+ 'Themes are available in an interactive terminal. Run /theme there.';
23
23
 
24
24
  function formatToggle(value: boolean): string {
25
25
  return value ? 'on' : 'off';
@@ -22,12 +22,12 @@ afterEach(async () => {
22
22
 
23
23
  describe('user-local command', () => {
24
24
  it('does not advertise a specific product from the neutral command entry', async () => {
25
- const module = createUserLocalCommandModule(await createTempRoot('robota-selected-storage-'));
26
- expect(module.commandSources?.[0]?.getCommands()[0]?.description).not.toMatch(/Robota/i);
25
+ const module = createUserLocalCommandModule(await createTempRoot('agent-test-selected-storage-'));
26
+ expect(module.commandSources?.[0]?.getCommands()[0]?.description).not.toMatch(/ConversationAgent/i);
27
27
  });
28
28
 
29
29
  it('fails closed when a direct caller omits the storage root', async () => {
30
- const workspace = await createTempRoot('robota-user-local-missing-root-');
30
+ const workspace = await createTempRoot('agent-test-user-local-missing-root-');
31
31
  const repo = path.join(workspace, 'repo');
32
32
  await fs.mkdir(repo);
33
33
 
@@ -40,9 +40,9 @@ describe('user-local command', () => {
40
40
  });
41
41
 
42
42
  it('uses the explicit root for slash commands', async () => {
43
- const workspace = await createTempRoot('robota-user-local-slash-root-');
43
+ const workspace = await createTempRoot('agent-test-user-local-slash-root-');
44
44
  const repo = path.join(workspace, 'repo');
45
- const selectedRoot = path.join(workspace, 'selected', '.robota');
45
+ const selectedRoot = path.join(workspace, 'selected', '.fixture-state');
46
46
  await fs.mkdir(repo);
47
47
  vi.stubEnv('HOME', path.join(workspace, 'ambient-home'));
48
48
 
@@ -65,7 +65,7 @@ describe('user-local command', () => {
65
65
  });
66
66
 
67
67
  it('prints storage inspection JSON without provider configuration', async () => {
68
- const workspace = await createTempRoot('robota-user-local-command-');
68
+ const workspace = await createTempRoot('agent-test-user-local-command-');
69
69
  const repo = path.join(workspace, 'repo');
70
70
  const home = path.join(workspace, 'home');
71
71
  await fs.mkdir(repo);
@@ -74,7 +74,7 @@ describe('user-local command', () => {
74
74
 
75
75
  const result = await executeUserLocalDirectCommand({
76
76
  cwd: repo,
77
- storageRoot: path.join(home, '.robota'),
77
+ storageRoot: path.join(home, '.fixture-state'),
78
78
  argv: ['storage', 'list'],
79
79
  format: 'json',
80
80
  });
@@ -84,7 +84,7 @@ describe('user-local command', () => {
84
84
  };
85
85
 
86
86
  expect(result.success).toBe(true);
87
- expect(parsed.root).toBe(path.join(home, '.robota'));
87
+ expect(parsed.root).toBe(path.join(home, '.fixture-state'));
88
88
  expect(parsed.categories.map((item) => item.category)).toEqual([
89
89
  'preferences',
90
90
  'view-state',
@@ -97,7 +97,7 @@ describe('user-local command', () => {
97
97
  });
98
98
 
99
99
  it('stores, lists, inspects, disables, and deletes user-local memory items', async () => {
100
- const workspace = await createTempRoot('robota-user-local-memory-command-');
100
+ const workspace = await createTempRoot('agent-test-user-local-memory-command-');
101
101
  const repo = path.join(workspace, 'repo');
102
102
  const home = path.join(workspace, 'home');
103
103
  await fs.mkdir(repo);
@@ -106,7 +106,7 @@ describe('user-local command', () => {
106
106
 
107
107
  const setResult = await executeUserLocalDirectCommand({
108
108
  cwd: repo,
109
- storageRoot: path.join(home, '.robota'),
109
+ storageRoot: path.join(home, '.fixture-state'),
110
110
  argv: ['memory', 'set', 'view-preference', 'last-panel', 'background'],
111
111
  summary: 'Open the background panel',
112
112
  source: 'user-input',
@@ -116,7 +116,7 @@ describe('user-local command', () => {
116
116
 
117
117
  const listResult = await executeUserLocalDirectCommand({
118
118
  cwd: repo,
119
- storageRoot: path.join(home, '.robota'),
119
+ storageRoot: path.join(home, '.fixture-state'),
120
120
  argv: ['memory', 'list'],
121
121
  format: 'json',
122
122
  });
@@ -133,7 +133,7 @@ describe('user-local command', () => {
133
133
 
134
134
  const inspectResult = await executeUserLocalDirectCommand({
135
135
  cwd: repo,
136
- storageRoot: path.join(home, '.robota'),
136
+ storageRoot: path.join(home, '.fixture-state'),
137
137
  argv: ['memory', 'inspect', 'view-preference', 'last-panel'],
138
138
  format: 'json',
139
139
  });
@@ -147,14 +147,14 @@ describe('user-local command', () => {
147
147
 
148
148
  const disableResult = await executeUserLocalDirectCommand({
149
149
  cwd: repo,
150
- storageRoot: path.join(home, '.robota'),
150
+ storageRoot: path.join(home, '.fixture-state'),
151
151
  argv: ['memory', 'disable', 'view-preference', 'last-panel'],
152
152
  });
153
153
  expect(disableResult.success).toBe(true);
154
154
 
155
155
  const disabledInspectResult = await executeUserLocalDirectCommand({
156
156
  cwd: repo,
157
- storageRoot: path.join(home, '.robota'),
157
+ storageRoot: path.join(home, '.fixture-state'),
158
158
  argv: ['memory', 'inspect', 'view-preference', 'last-panel'],
159
159
  format: 'json',
160
160
  });
@@ -163,14 +163,14 @@ describe('user-local command', () => {
163
163
 
164
164
  const deleteResult = await executeUserLocalDirectCommand({
165
165
  cwd: repo,
166
- storageRoot: path.join(home, '.robota'),
166
+ storageRoot: path.join(home, '.fixture-state'),
167
167
  argv: ['memory', 'delete', 'view-preference', 'last-panel'],
168
168
  });
169
169
  expect(deleteResult.success).toBe(true);
170
170
 
171
171
  const missingResult = await executeUserLocalDirectCommand({
172
172
  cwd: repo,
173
- storageRoot: path.join(home, '.robota'),
173
+ storageRoot: path.join(home, '.fixture-state'),
174
174
  argv: ['memory', 'inspect', 'view-preference', 'last-panel'],
175
175
  format: 'json',
176
176
  });