@robota-sdk/agent-command 3.0.0-beta.64

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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/dist/node/index.cjs +30 -0
  3. package/dist/node/index.d.ts +293 -0
  4. package/dist/node/index.d.ts.map +1 -0
  5. package/dist/node/index.js +31 -0
  6. package/dist/node/index.js.map +1 -0
  7. package/package.json +48 -0
  8. package/src/agent/__tests__/agent-command.test.ts +504 -0
  9. package/src/agent/agent-command-module.ts +82 -0
  10. package/src/agent/agent-command-parser.ts +180 -0
  11. package/src/agent/agent-command.ts +235 -0
  12. package/src/agent/index.ts +7 -0
  13. package/src/background/__tests__/background-command-module.test.ts +255 -0
  14. package/src/background/background-command-module.ts +53 -0
  15. package/src/background/background-command.ts +63 -0
  16. package/src/background/index.ts +6 -0
  17. package/src/compact/__tests__/compact-command-module.test.ts +162 -0
  18. package/src/compact/compact-command-module.ts +51 -0
  19. package/src/compact/compact-command.ts +21 -0
  20. package/src/compact/index.ts +6 -0
  21. package/src/context/__tests__/context-command-module.test.ts +294 -0
  22. package/src/context/context-command-module.ts +54 -0
  23. package/src/context/context-command.ts +298 -0
  24. package/src/context/index.ts +6 -0
  25. package/src/exit/__tests__/exit-command-module.test.ts +35 -0
  26. package/src/exit/exit-command-module.ts +48 -0
  27. package/src/exit/exit-command.ts +10 -0
  28. package/src/exit/index.ts +6 -0
  29. package/src/help/__tests__/help-command-module.test.ts +106 -0
  30. package/src/help/help-command-module.ts +48 -0
  31. package/src/help/help-command.ts +9 -0
  32. package/src/help/index.ts +6 -0
  33. package/src/index.ts +20 -0
  34. package/src/language/__tests__/language-command-module.test.ts +105 -0
  35. package/src/language/index.ts +6 -0
  36. package/src/language/language-command-module.ts +56 -0
  37. package/src/language/language-command.ts +22 -0
  38. package/src/memory/__tests__/memory-command-module.test.ts +272 -0
  39. package/src/memory/index.ts +6 -0
  40. package/src/memory/memory-command-module.ts +57 -0
  41. package/src/memory/memory-command.ts +234 -0
  42. package/src/mode/__tests__/mode-command-module.test.ts +143 -0
  43. package/src/mode/index.ts +6 -0
  44. package/src/mode/mode-command-module.ts +56 -0
  45. package/src/mode/mode-command.ts +34 -0
  46. package/src/model/__tests__/model-command-module.test.ts +273 -0
  47. package/src/model/index.ts +6 -0
  48. package/src/model/model-command-module.ts +68 -0
  49. package/src/model/model-command.ts +40 -0
  50. package/src/permissions/__tests__/permissions-command-module.test.ts +164 -0
  51. package/src/permissions/index.ts +6 -0
  52. package/src/permissions/permissions-command-module.ts +56 -0
  53. package/src/permissions/permissions-command.ts +45 -0
  54. package/src/plugin/__tests__/plugin-command-module.test.ts +214 -0
  55. package/src/plugin/index.ts +7 -0
  56. package/src/plugin/plugin-command-module.ts +81 -0
  57. package/src/plugin/plugin-command.ts +230 -0
  58. package/src/provider/__tests__/provider-command-module.test.ts +488 -0
  59. package/src/provider/__tests__/provider-setup-flow.test.ts +43 -0
  60. package/src/provider/index.ts +30 -0
  61. package/src/provider/provider-command-execution.ts +150 -0
  62. package/src/provider/provider-command-module.ts +65 -0
  63. package/src/provider/provider-command-profile-lifecycle.ts +211 -0
  64. package/src/provider/provider-command-profile-operations.ts +198 -0
  65. package/src/provider/provider-command-profile.ts +109 -0
  66. package/src/provider/provider-command-setup.ts +104 -0
  67. package/src/provider/provider-setup-flow.ts +309 -0
  68. package/src/reset/__tests__/reset-command-module.test.ts +63 -0
  69. package/src/reset/index.ts +2 -0
  70. package/src/reset/reset-command-module.ts +49 -0
  71. package/src/reset/reset-command.ts +10 -0
  72. package/src/rewind/__tests__/rewind-command-module.test.ts +215 -0
  73. package/src/rewind/index.ts +2 -0
  74. package/src/rewind/rewind-command-module.ts +57 -0
  75. package/src/rewind/rewind-command.ts +184 -0
  76. package/src/session/__tests__/session-command-module.test.ts +339 -0
  77. package/src/session/index.ts +17 -0
  78. package/src/session/session-command-module.ts +168 -0
  79. package/src/session/session-command.ts +74 -0
  80. package/src/settings/index.ts +7 -0
  81. package/src/settings/settings-command-module.ts +50 -0
  82. package/src/skills/__tests__/skills-command-module.test.ts +157 -0
  83. package/src/skills/index.ts +6 -0
  84. package/src/skills/skills-command-module.ts +62 -0
  85. package/src/skills/skills-command.ts +110 -0
  86. package/src/statusline/__tests__/statusline-command-module.test.ts +95 -0
  87. package/src/statusline/index.ts +6 -0
  88. package/src/statusline/statusline-command-module.ts +56 -0
  89. package/src/statusline/statusline-command.ts +79 -0
  90. package/src/user-local/__tests__/user-local-command.test.ts +145 -0
  91. package/src/user-local/index.ts +13 -0
  92. package/src/user-local/user-local-command-constants.ts +5 -0
  93. package/src/user-local/user-local-command-module.ts +67 -0
  94. package/src/user-local/user-local-command.ts +205 -0
  95. package/src/user-local/user-local-memory-command.ts +147 -0
@@ -0,0 +1,145 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import path from 'node:path';
4
+ import { afterEach, describe, expect, it } from 'vitest';
5
+ import { executeUserLocalDirectCommand } from '../user-local-command.js';
6
+
7
+ const tempRoots: string[] = [];
8
+
9
+ async function createTempRoot(name: string): Promise<string> {
10
+ const root = await fs.mkdtemp(path.join(tmpdir(), name));
11
+ tempRoots.push(root);
12
+ return root;
13
+ }
14
+
15
+ afterEach(async () => {
16
+ await Promise.all(
17
+ tempRoots.splice(0).map((root) => fs.rm(root, { recursive: true, force: true })),
18
+ );
19
+ });
20
+
21
+ describe('user-local command', () => {
22
+ it('prints storage inspection JSON without provider configuration', async () => {
23
+ const workspace = await createTempRoot('robota-user-local-command-');
24
+ const repo = path.join(workspace, 'repo');
25
+ const home = path.join(workspace, 'home');
26
+ await fs.mkdir(repo);
27
+ await fs.mkdir(home);
28
+ const originalHome = process.env.HOME;
29
+ process.env.HOME = home;
30
+
31
+ try {
32
+ const result = await executeUserLocalDirectCommand({
33
+ cwd: repo,
34
+ argv: ['storage', 'list'],
35
+ format: 'json',
36
+ });
37
+ const parsed = JSON.parse(result.message) as {
38
+ root: string;
39
+ categories: readonly { category: string; mayExecuteCommands: boolean }[];
40
+ };
41
+
42
+ expect(result.success).toBe(true);
43
+ expect(parsed.root).toBe(path.join(home, '.robota'));
44
+ expect(parsed.categories.map((item) => item.category)).toEqual([
45
+ 'preferences',
46
+ 'view-state',
47
+ 'memory-projections',
48
+ 'task-associations',
49
+ 'workflow-metadata',
50
+ 'inspection-index',
51
+ ]);
52
+ expect(parsed.categories.every((item) => item.mayExecuteCommands === false)).toBe(true);
53
+ } finally {
54
+ if (originalHome === undefined) {
55
+ delete process.env.HOME;
56
+ } else {
57
+ process.env.HOME = originalHome;
58
+ }
59
+ }
60
+ });
61
+
62
+ it('stores, lists, inspects, disables, and deletes user-local memory items', async () => {
63
+ const workspace = await createTempRoot('robota-user-local-memory-command-');
64
+ const repo = path.join(workspace, 'repo');
65
+ const home = path.join(workspace, 'home');
66
+ await fs.mkdir(repo);
67
+ await fs.mkdir(home);
68
+ const originalHome = process.env.HOME;
69
+ process.env.HOME = home;
70
+
71
+ try {
72
+ const setResult = await executeUserLocalDirectCommand({
73
+ cwd: repo,
74
+ argv: ['memory', 'set', 'view-preference', 'last-panel', 'background'],
75
+ summary: 'Open the background panel',
76
+ source: 'user-input',
77
+ });
78
+ expect(setResult.success).toBe(true);
79
+ expect(setResult.message).toContain('view-preference/last-panel');
80
+
81
+ const listResult = await executeUserLocalDirectCommand({
82
+ cwd: repo,
83
+ argv: ['memory', 'list'],
84
+ format: 'json',
85
+ });
86
+ const list = JSON.parse(listResult.message) as {
87
+ items: readonly { category: string; key: string; enabled: boolean }[];
88
+ };
89
+ expect(listResult.success).toBe(true);
90
+ expect(list.items).toHaveLength(1);
91
+ expect(list.items[0]).toMatchObject({
92
+ category: 'view-preference',
93
+ key: 'last-panel',
94
+ enabled: true,
95
+ });
96
+
97
+ const inspectResult = await executeUserLocalDirectCommand({
98
+ cwd: repo,
99
+ argv: ['memory', 'inspect', 'view-preference', 'last-panel'],
100
+ format: 'json',
101
+ });
102
+ const inspected = JSON.parse(inspectResult.message) as {
103
+ commandExecutionEffect: string;
104
+ displayNavigationRule: string;
105
+ };
106
+ expect(inspectResult.success).toBe(true);
107
+ expect(inspected.commandExecutionEffect).toBe('none');
108
+ expect(inspected.displayNavigationRule).toContain('display/navigation only');
109
+
110
+ const disableResult = await executeUserLocalDirectCommand({
111
+ cwd: repo,
112
+ argv: ['memory', 'disable', 'view-preference', 'last-panel'],
113
+ });
114
+ expect(disableResult.success).toBe(true);
115
+
116
+ const disabledInspectResult = await executeUserLocalDirectCommand({
117
+ cwd: repo,
118
+ argv: ['memory', 'inspect', 'view-preference', 'last-panel'],
119
+ format: 'json',
120
+ });
121
+ const disabled = JSON.parse(disabledInspectResult.message) as { enabled: boolean };
122
+ expect(disabled.enabled).toBe(false);
123
+
124
+ const deleteResult = await executeUserLocalDirectCommand({
125
+ cwd: repo,
126
+ argv: ['memory', 'delete', 'view-preference', 'last-panel'],
127
+ });
128
+ expect(deleteResult.success).toBe(true);
129
+
130
+ const missingResult = await executeUserLocalDirectCommand({
131
+ cwd: repo,
132
+ argv: ['memory', 'inspect', 'view-preference', 'last-panel'],
133
+ format: 'json',
134
+ });
135
+ expect(missingResult.success).toBe(false);
136
+ expect(missingResult.message).toBe('User-local memory item not found.');
137
+ } finally {
138
+ if (originalHome === undefined) {
139
+ delete process.env.HOME;
140
+ } else {
141
+ process.env.HOME = originalHome;
142
+ }
143
+ }
144
+ });
145
+ });
@@ -0,0 +1,13 @@
1
+ export {
2
+ UserLocalCommandSource,
3
+ createUserLocalCommandEntry,
4
+ createUserLocalCommandModule,
5
+ } from './user-local-command-module.js';
6
+ export {
7
+ USER_LOCAL_COMMAND_ARGUMENT_HINT,
8
+ USER_LOCAL_COMMAND_DESCRIPTION,
9
+ USER_LOCAL_COMMAND_USAGE,
10
+ executeUserLocalCommand,
11
+ executeUserLocalDirectCommand,
12
+ } from './user-local-command.js';
13
+ export type { IUserLocalDirectCommandOptions } from './user-local-command.js';
@@ -0,0 +1,5 @@
1
+ export const USER_LOCAL_COMMAND_DESCRIPTION = 'Inspect Robota user-local storage and memory state.';
2
+ export const USER_LOCAL_COMMAND_ARGUMENT_HINT =
3
+ 'storage list [--format json] | memory set/list/inspect/disable/delete';
4
+ export const USER_LOCAL_COMMAND_USAGE =
5
+ 'Usage: user-local storage list [--format json] | user-local memory set <category> <key> <value> --summary <summary> --source <source> | user-local memory list [--format json] | user-local memory inspect <category> <key> [--format json] | user-local memory disable <category> <key> | user-local memory delete <category> <key>';
@@ -0,0 +1,67 @@
1
+ import type {
2
+ ICommand,
3
+ ICommandModule,
4
+ ICommandSource,
5
+ ISystemCommand,
6
+ } from '@robota-sdk/agent-framework';
7
+ import {
8
+ USER_LOCAL_COMMAND_ARGUMENT_HINT,
9
+ USER_LOCAL_COMMAND_DESCRIPTION,
10
+ executeUserLocalCommand,
11
+ } from './user-local-command.js';
12
+
13
+ export function createUserLocalCommandEntry(): ICommand {
14
+ return {
15
+ name: 'user-local',
16
+ displayName: 'User Config',
17
+ description: USER_LOCAL_COMMAND_DESCRIPTION,
18
+ source: 'user-local',
19
+ argumentHint: USER_LOCAL_COMMAND_ARGUMENT_HINT,
20
+ modelInvocable: false,
21
+ safety: 'read-only',
22
+ subcommands: [
23
+ {
24
+ name: 'storage',
25
+ description: 'Inspect user-local storage categories',
26
+ source: 'user-local',
27
+ },
28
+ {
29
+ name: 'memory',
30
+ description: 'Inspect and manage user-local memory items',
31
+ source: 'user-local',
32
+ },
33
+ ],
34
+ };
35
+ }
36
+
37
+ function createUserLocalSystemCommand(): ISystemCommand {
38
+ const entry = createUserLocalCommandEntry();
39
+ return {
40
+ name: entry.name,
41
+ displayName: entry.displayName,
42
+ description: entry.description,
43
+ requiresPermission: false,
44
+ userInvocable: true,
45
+ modelInvocable: false,
46
+ argumentHint: entry.argumentHint,
47
+ safety: entry.safety,
48
+ subcommands: entry.subcommands,
49
+ execute: executeUserLocalCommand,
50
+ };
51
+ }
52
+
53
+ export class UserLocalCommandSource implements ICommandSource {
54
+ readonly name = 'user-local';
55
+
56
+ getCommands(): ICommand[] {
57
+ return [createUserLocalCommandEntry()];
58
+ }
59
+ }
60
+
61
+ export function createUserLocalCommandModule(): ICommandModule {
62
+ return {
63
+ name: 'agent-command-user-local',
64
+ commandSources: [new UserLocalCommandSource()],
65
+ systemCommands: [createUserLocalSystemCommand()],
66
+ };
67
+ }
@@ -0,0 +1,205 @@
1
+ import type { ICommandHostContext, ICommandResult } from '@robota-sdk/agent-framework';
2
+ import { inspectUserLocalStorage } from '@robota-sdk/agent-framework';
3
+ import { executeMemoryCommand } from './user-local-memory-command.js';
4
+ import { USER_LOCAL_COMMAND_USAGE } from './user-local-command-constants.js';
5
+ export {
6
+ USER_LOCAL_COMMAND_ARGUMENT_HINT,
7
+ USER_LOCAL_COMMAND_DESCRIPTION,
8
+ USER_LOCAL_COMMAND_USAGE,
9
+ } from './user-local-command-constants.js';
10
+
11
+ type TUserLocalOutputFormat = 'text' | 'json';
12
+
13
+ export interface IUserLocalDirectCommandOptions {
14
+ readonly cwd: string;
15
+ readonly argv: readonly string[];
16
+ readonly format?: string;
17
+ readonly summary?: string;
18
+ readonly source?: string;
19
+ }
20
+
21
+ interface IParsedUserLocalCommand {
22
+ readonly target?: string;
23
+ readonly action?: string;
24
+ readonly positional: readonly string[];
25
+ readonly format: TUserLocalOutputFormat;
26
+ readonly summary?: string;
27
+ readonly source?: string;
28
+ }
29
+
30
+ interface IParsedUserLocalOption {
31
+ readonly format?: string;
32
+ readonly summary?: string;
33
+ readonly source?: string;
34
+ readonly nextIndex: number;
35
+ }
36
+
37
+ function parseOutputFormat(value: string | undefined): TUserLocalOutputFormat {
38
+ if (value === undefined || value === 'text') {
39
+ return 'text';
40
+ }
41
+ if (value === 'json') {
42
+ return 'json';
43
+ }
44
+ throw new Error(`Unsupported user-local output format: ${value}`);
45
+ }
46
+
47
+ function parseUserLocalOption(
48
+ arg: string,
49
+ argv: readonly string[],
50
+ index: number,
51
+ ): IParsedUserLocalOption | null {
52
+ if (arg === '--format') {
53
+ return { format: argv[index + 1], nextIndex: index + 1 };
54
+ }
55
+ if (arg.startsWith('--format=')) {
56
+ return { format: arg.slice('--format='.length), nextIndex: index };
57
+ }
58
+ if (arg === '--summary') {
59
+ return { summary: argv[index + 1], nextIndex: index + 1 };
60
+ }
61
+ if (arg.startsWith('--summary=')) {
62
+ return { summary: arg.slice('--summary='.length), nextIndex: index };
63
+ }
64
+ if (arg === '--source') {
65
+ return { source: argv[index + 1], nextIndex: index + 1 };
66
+ }
67
+ if (arg.startsWith('--source=')) {
68
+ return { source: arg.slice('--source='.length), nextIndex: index };
69
+ }
70
+ return null;
71
+ }
72
+
73
+ function parseUserLocalArgs(
74
+ argv: readonly string[],
75
+ directOptions: {
76
+ readonly format?: string;
77
+ readonly summary?: string;
78
+ readonly source?: string;
79
+ } = {},
80
+ ): IParsedUserLocalCommand {
81
+ let format = directOptions.format;
82
+ let summary = directOptions.summary;
83
+ let source = directOptions.source;
84
+ const positional: string[] = [];
85
+
86
+ for (let index = 0; index < argv.length; index += 1) {
87
+ const arg = argv[index];
88
+ const option = parseUserLocalOption(arg, argv, index);
89
+ if (option !== null) {
90
+ format = option.format ?? format;
91
+ summary = option.summary ?? summary;
92
+ source = option.source ?? source;
93
+ index = option.nextIndex;
94
+ continue;
95
+ }
96
+ positional.push(arg);
97
+ }
98
+
99
+ return {
100
+ target: positional[0],
101
+ action: positional[1],
102
+ positional: positional.slice(2),
103
+ format: parseOutputFormat(format),
104
+ summary,
105
+ source,
106
+ };
107
+ }
108
+
109
+ function splitRawArgs(rawArgs: string): readonly string[] {
110
+ return rawArgs.trim().split(/\s+/).filter(Boolean);
111
+ }
112
+
113
+ function formatStorageInspectionText(
114
+ root: string,
115
+ categories: readonly { category: string }[],
116
+ ): string {
117
+ const categoryLines = categories.map((item) => `- ${item.category}`);
118
+ return [`User-local storage root: ${root}`, 'Categories:', ...categoryLines].join('\n');
119
+ }
120
+
121
+ async function executeStorageCommand(
122
+ cwd: string,
123
+ parsed: IParsedUserLocalCommand,
124
+ ): Promise<ICommandResult> {
125
+ if ((parsed.action ?? 'list') !== 'list') {
126
+ return {
127
+ message: USER_LOCAL_COMMAND_USAGE,
128
+ success: false,
129
+ };
130
+ }
131
+
132
+ const inspection = await inspectUserLocalStorage({ activeRepositoryRoot: cwd });
133
+ return {
134
+ message:
135
+ parsed.format === 'json'
136
+ ? JSON.stringify(inspection, null, 2)
137
+ : formatStorageInspectionText(inspection.root, inspection.categories),
138
+ success: true,
139
+ data: {
140
+ root: inspection.root,
141
+ categories: inspection.categories,
142
+ inspection,
143
+ },
144
+ };
145
+ }
146
+
147
+ async function executeParsedUserLocalCommand(
148
+ cwd: string,
149
+ parsed: IParsedUserLocalCommand,
150
+ ): Promise<ICommandResult> {
151
+ if (parsed.target === 'storage') {
152
+ return executeStorageCommand(cwd, parsed);
153
+ }
154
+ if (parsed.target === 'memory') {
155
+ return executeMemoryCommand(cwd, parsed);
156
+ }
157
+ return {
158
+ message: USER_LOCAL_COMMAND_USAGE,
159
+ success: false,
160
+ };
161
+ }
162
+
163
+ function formatCommandErrorMessage(errorMessage: string): string {
164
+ if (errorMessage.includes('ENOENT')) {
165
+ return 'User-local memory item not found.';
166
+ }
167
+ return errorMessage;
168
+ }
169
+
170
+ export async function executeUserLocalDirectCommand(
171
+ options: IUserLocalDirectCommandOptions,
172
+ ): Promise<ICommandResult> {
173
+ try {
174
+ return await executeParsedUserLocalCommand(
175
+ options.cwd,
176
+ parseUserLocalArgs(options.argv, {
177
+ format: options.format,
178
+ summary: options.summary,
179
+ source: options.source,
180
+ }),
181
+ );
182
+ } catch (error) {
183
+ return {
184
+ message: formatCommandErrorMessage(error instanceof Error ? error.message : String(error)),
185
+ success: false,
186
+ };
187
+ }
188
+ }
189
+
190
+ export async function executeUserLocalCommand(
191
+ context: ICommandHostContext,
192
+ rawArgs: string,
193
+ ): Promise<ICommandResult> {
194
+ try {
195
+ return await executeParsedUserLocalCommand(
196
+ context.getCwd(),
197
+ parseUserLocalArgs(splitRawArgs(rawArgs)),
198
+ );
199
+ } catch (error) {
200
+ return {
201
+ message: formatCommandErrorMessage(error instanceof Error ? error.message : String(error)),
202
+ success: false,
203
+ };
204
+ }
205
+ }
@@ -0,0 +1,147 @@
1
+ import type { ICommandResult, TUserLocalMemoryCategory } from '@robota-sdk/agent-framework';
2
+ import {
3
+ deleteUserLocalMemoryItem,
4
+ disableUserLocalMemoryItem,
5
+ inspectUserLocalMemoryItem,
6
+ listUserLocalMemoryItems,
7
+ setUserLocalMemoryItem,
8
+ } from '@robota-sdk/agent-framework';
9
+ import { USER_LOCAL_COMMAND_USAGE } from './user-local-command-constants.js';
10
+
11
+ export interface IUserLocalMemoryCommandArgs {
12
+ readonly action?: string;
13
+ readonly positional: readonly string[];
14
+ readonly format: 'text' | 'json';
15
+ readonly summary?: string;
16
+ readonly source?: string;
17
+ }
18
+
19
+ function formatMemoryListText(
20
+ items: readonly { category: string; key: string; enabled: boolean }[],
21
+ ): string {
22
+ if (items.length === 0) {
23
+ return 'No user-local memory items.';
24
+ }
25
+ return items
26
+ .map((item) => `- ${item.category}/${item.key} (${item.enabled ? 'enabled' : 'disabled'})`)
27
+ .join('\n');
28
+ }
29
+
30
+ function parseMemoryCategory(value: string | undefined): TUserLocalMemoryCategory {
31
+ if (value === undefined) {
32
+ throw new Error('User-local memory category is required.');
33
+ }
34
+ return value as TUserLocalMemoryCategory;
35
+ }
36
+
37
+ async function executeMemoryListCommand(
38
+ activeRepositoryRoot: string,
39
+ parsed: IUserLocalMemoryCommandArgs,
40
+ ): Promise<ICommandResult> {
41
+ const list = await listUserLocalMemoryItems({ activeRepositoryRoot });
42
+ return {
43
+ message:
44
+ parsed.format === 'json' ? JSON.stringify(list, null, 2) : formatMemoryListText(list.items),
45
+ success: true,
46
+ data: { list },
47
+ };
48
+ }
49
+
50
+ async function executeMemorySetCommand(
51
+ activeRepositoryRoot: string,
52
+ parsed: IUserLocalMemoryCommandArgs,
53
+ ): Promise<ICommandResult> {
54
+ const [category, key, value] = parsed.positional;
55
+ const item = await setUserLocalMemoryItem({
56
+ activeRepositoryRoot,
57
+ category: parseMemoryCategory(category),
58
+ key: key ?? '',
59
+ value: value ?? '',
60
+ summary: parsed.summary ?? '',
61
+ source: parsed.source ?? '',
62
+ });
63
+ return {
64
+ message: `Stored user-local memory item ${item.category}/${item.key} at ${item.storageLocation}`,
65
+ success: true,
66
+ data: { item },
67
+ };
68
+ }
69
+
70
+ async function executeMemoryInspectCommand(
71
+ activeRepositoryRoot: string,
72
+ parsed: IUserLocalMemoryCommandArgs,
73
+ ): Promise<ICommandResult> {
74
+ const [category, key] = parsed.positional;
75
+ const item = await inspectUserLocalMemoryItem({
76
+ activeRepositoryRoot,
77
+ category: parseMemoryCategory(category),
78
+ key: key ?? '',
79
+ });
80
+ return {
81
+ message:
82
+ parsed.format === 'json'
83
+ ? JSON.stringify(item, null, 2)
84
+ : `${item.category}/${item.key}: ${item.summary}`,
85
+ success: true,
86
+ data: { item },
87
+ };
88
+ }
89
+
90
+ async function executeMemoryDisableCommand(
91
+ activeRepositoryRoot: string,
92
+ parsed: IUserLocalMemoryCommandArgs,
93
+ ): Promise<ICommandResult> {
94
+ const [category, key] = parsed.positional;
95
+ const item = await disableUserLocalMemoryItem({
96
+ activeRepositoryRoot,
97
+ category: parseMemoryCategory(category),
98
+ key: key ?? '',
99
+ });
100
+ return {
101
+ message: `Disabled user-local memory item ${item.category}/${item.key}`,
102
+ success: true,
103
+ data: { item },
104
+ };
105
+ }
106
+
107
+ async function executeMemoryDeleteCommand(
108
+ activeRepositoryRoot: string,
109
+ parsed: IUserLocalMemoryCommandArgs,
110
+ ): Promise<ICommandResult> {
111
+ const [category, key] = parsed.positional;
112
+ const result = await deleteUserLocalMemoryItem({
113
+ activeRepositoryRoot,
114
+ category: parseMemoryCategory(category),
115
+ key: key ?? '',
116
+ });
117
+ return {
118
+ message: `Deleted user-local memory item ${result.category}/${result.key}`,
119
+ success: true,
120
+ data: { result },
121
+ };
122
+ }
123
+
124
+ export async function executeMemoryCommand(
125
+ cwd: string,
126
+ parsed: IUserLocalMemoryCommandArgs,
127
+ ): Promise<ICommandResult> {
128
+ if ((parsed.action ?? 'list') === 'list') {
129
+ return executeMemoryListCommand(cwd, parsed);
130
+ }
131
+ if (parsed.action === 'set') {
132
+ return executeMemorySetCommand(cwd, parsed);
133
+ }
134
+ if (parsed.action === 'inspect') {
135
+ return executeMemoryInspectCommand(cwd, parsed);
136
+ }
137
+ if (parsed.action === 'disable') {
138
+ return executeMemoryDisableCommand(cwd, parsed);
139
+ }
140
+ if (parsed.action === 'delete') {
141
+ return executeMemoryDeleteCommand(cwd, parsed);
142
+ }
143
+ return {
144
+ message: USER_LOCAL_COMMAND_USAGE,
145
+ success: false,
146
+ };
147
+ }