@pellux/goodvibes-agent 0.1.111 → 0.1.113

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 (34) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +3 -3
  3. package/dist/package/main.js +9921 -9868
  4. package/docs/getting-started.md +3 -3
  5. package/package.json +1 -1
  6. package/src/cli/help.ts +4 -1
  7. package/src/cli/local-library-command.ts +90 -1
  8. package/src/cli/parser.ts +0 -8
  9. package/src/cli/service-posture.ts +1 -8
  10. package/src/cli/status.ts +1 -30
  11. package/src/cli/types.ts +0 -1
  12. package/src/input/agent-workspace-categories.ts +5 -7
  13. package/src/input/agent-workspace-snapshot.ts +2 -10
  14. package/src/input/agent-workspace-types.ts +2 -3
  15. package/src/input/commands/brief-runtime.ts +1 -1
  16. package/src/input/commands/channels-runtime.ts +397 -35
  17. package/src/input/commands/experience-runtime.ts +4 -9
  18. package/src/input/commands/health-runtime.ts +26 -6
  19. package/src/input/commands/mcp-runtime.ts +51 -26
  20. package/src/input/commands/memory.ts +10 -10
  21. package/src/input/commands/planning-runtime.ts +4 -9
  22. package/src/input/commands/provider-accounts-runtime.ts +2 -3
  23. package/src/input/commands/qrcode-runtime.ts +48 -9
  24. package/src/input/commands/recall-bundle.ts +16 -16
  25. package/src/input/commands/recall-capture.ts +18 -18
  26. package/src/input/commands/recall-query.ts +22 -22
  27. package/src/input/commands/recall-review.ts +12 -12
  28. package/src/input/commands/tasks-runtime.ts +9 -15
  29. package/src/input/commands/work-plan-runtime.ts +5 -19
  30. package/src/input/commands.ts +2 -7
  31. package/src/renderer/agent-workspace.ts +1 -2
  32. package/src/renderer/ui-factory.ts +1 -1
  33. package/src/runtime/onboarding/derivation.ts +6 -67
  34. package/src/version.ts +1 -1
@@ -1,16 +1,16 @@
1
1
  /**
2
- * /recall command handler.
2
+ * /memory command handler.
3
3
  *
4
4
  * Implements the Project Memory Substrate commands:
5
5
  *
6
- * /recall add <class> <summary> — Add a new memory record
7
- * /recall add <class> <summary> --detail <text> --tags <tag,tag>
8
- * /recall search [query] — Search memory records
9
- * /recall search --cls <class> — Filter by class
10
- * /recall link <fromId> <toId> <relation> --yes — Link two records
11
- * /recall get <id> — Show a single record with provenance
12
- * /recall list [class] — List all records (optionally by class)
13
- * /recall remove <id> --yes — Delete a record
6
+ * /memory add <class> <summary> — Add a new memory record
7
+ * /memory add <class> <summary> --detail <text> --tags <tag,tag>
8
+ * /memory search [query] — Search memory records
9
+ * /memory search --cls <class> — Filter by class
10
+ * /memory link <fromId> <toId> <relation> --yes — Link two records
11
+ * /memory get <id> — Show a single record with provenance
12
+ * /memory list [class] — List all records (optionally by class)
13
+ * /memory remove <id> --yes — Delete a record
14
14
  */
15
15
 
16
16
  import type { SlashCommand, CommandContext } from '../command-registry.ts';
@@ -118,7 +118,7 @@ export const recallCommand: SlashCommand = {
118
118
 
119
119
  default: {
120
120
  const usage = [
121
- 'Usage: /recall <subcommand>',
121
+ 'Usage: /memory <subcommand>',
122
122
  ' add <class> <summary> [--scope <session|project|team>] [--detail <text>] [--tags <t,t>] [--session <id>] [--task <id>] [--file <path>]',
123
123
  ` classes: ${VALID_CLASSES.join(', ')}`,
124
124
  ' capture incident <id|latest> — Capture a forensics incident as durable memory',
@@ -44,7 +44,7 @@ function formatNextQuestion(question: ProjectPlanningQuestion | undefined): stri
44
44
  if (!question) return 'No next question recorded.';
45
45
  const lines = [`Next question: ${question.prompt}`];
46
46
  if (question.recommendedAnswer) lines.push(`Recommended answer: ${question.recommendedAnswer}`);
47
- lines.push('Answer in the prompt, or focus the Planning workspace to choose/type an answer.');
47
+ lines.push('Answer in the main prompt or review planning state with /plan status.');
48
48
  return lines.join('\n');
49
49
  }
50
50
 
@@ -52,8 +52,8 @@ export function registerPlanningRuntimeCommands(registry: CommandRegistry): void
52
52
  registry.register({
53
53
  name: 'plan',
54
54
  description: 'Inspect or seed Agent workspace planning state',
55
- usage: '[panel | approve --yes | list | show <id> | mode | explain | override <strategy> --yes | status | clear --yes | <planning goal>]',
56
- argsHint: '[panel|approve|status|<goal>]',
55
+ usage: '[approve --yes | list | show <id> | mode | explain | override <strategy> --yes | status | clear --yes | <planning goal>]',
56
+ argsHint: '[approve|status|list|<goal>]',
57
57
  async handler(args, ctx) {
58
58
  const planManager = requirePlanManager(ctx);
59
59
  const sessionLineageTracker = requireSessionLineageTracker(ctx);
@@ -74,7 +74,6 @@ export function registerPlanningRuntimeCommands(registry: CommandRegistry): void
74
74
 
75
75
  const projectPlanningService = ctx.workspace.projectPlanningService;
76
76
  const projectId = ctx.workspace.projectPlanningProjectId;
77
- const openProjectPlanningPanel = () => ctx.showPanel?.('project-planning');
78
77
 
79
78
  if (args.length === 0) {
80
79
  if (projectPlanningService && projectId) {
@@ -92,7 +91,6 @@ export function registerPlanningRuntimeCommands(registry: CommandRegistry): void
92
91
  const planningNamespace = String(
93
92
  status[['knowledge', 'SpaceId'].join('') as keyof typeof status] ?? `project:${status.projectId}`,
94
93
  );
95
- openProjectPlanningPanel();
96
94
  ctx.print(
97
95
  `Project planning: ${evaluation.readiness}\n` +
98
96
  `Project: ${status.projectId}\n` +
@@ -113,8 +111,7 @@ export function registerPlanningRuntimeCommands(registry: CommandRegistry): void
113
111
  }
114
112
 
115
113
  if (args[0] === 'panel') {
116
- openProjectPlanningPanel();
117
- ctx.print('Opened project planning panel.');
114
+ ctx.print('Planning panels are not part of the Agent workspace. Use /plan status or /plan list.');
118
115
  return;
119
116
  }
120
117
 
@@ -146,7 +143,6 @@ export function registerPlanningRuntimeCommands(registry: CommandRegistry): void
146
143
  },
147
144
  });
148
145
  const evaluation = await projectPlanningService.evaluate({ projectId });
149
- openProjectPlanningPanel();
150
146
  ctx.print(`Project planning approved. Readiness: ${evaluation.readiness}. State: ${result.state?.id ?? 'current'}.`);
151
147
  return;
152
148
  }
@@ -208,7 +204,6 @@ export function registerPlanningRuntimeCommands(registry: CommandRegistry): void
208
204
  ? await persistEvaluatedNextQuestion(projectPlanningService, projectId, result.state, initialEvaluation)
209
205
  : { state: result.state, evaluation: initialEvaluation };
210
206
  sessionLineageTracker.setOriginalTask(taskDescription.slice(0, 200));
211
- openProjectPlanningPanel();
212
207
 
213
208
  ctx.print(
214
209
  `Project planning seeded: "${state?.goal ?? taskDescription}"\n` +
@@ -4,7 +4,6 @@ import type {
4
4
  ProviderAccountSnapshot,
5
5
  } from '@/runtime/index.ts';
6
6
  import {
7
- openCommandPanel,
8
7
  requireOperatorClient,
9
8
  } from './runtime-services.ts';
10
9
 
@@ -25,11 +24,11 @@ export function registerProviderAccountsRuntimeCommands(registry: CommandRegistr
25
24
  name: 'accounts',
26
25
  aliases: ['account'],
27
26
  description: 'Review provider auth routes, subscription windows, and billing-path safety',
28
- usage: '[review|panel|show <provider>|routes <provider>|repair <provider>]',
27
+ usage: '[review|show <provider>|routes <provider>|repair <provider>]',
29
28
  async handler(args, ctx) {
30
29
  const sub = (args[0] ?? 'review').toLowerCase();
31
30
  if (sub === 'panel' || sub === 'open') {
32
- openCommandPanel(ctx, 'accounts');
31
+ ctx.print('Provider account panels are not part of the Agent workspace. Use /accounts review.');
33
32
  return;
34
33
  }
35
34
  const snapshot = await loadProviderAccountSnapshot(ctx);
@@ -1,20 +1,59 @@
1
1
  import type { CommandRegistry } from '../command-registry.ts';
2
- import { openCommandPanel } from './runtime-services.ts';
2
+ import { join } from 'node:path';
3
+ import { networkInterfaces } from 'node:os';
4
+ import {
5
+ buildCompanionConnectionInfo,
6
+ encodeConnectionPayload,
7
+ formatConnectionBlock,
8
+ generateQrMatrix,
9
+ getOrCreateCompanionToken,
10
+ renderQrToString,
11
+ } from '@pellux/goodvibes-sdk/platform/pairing';
12
+ import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../../config/surface.ts';
13
+ import { resolveRuntimeEndpointBinding } from '../../cli/endpoints.ts';
14
+ import { requirePlatform, requireShellPaths } from './runtime-services.ts';
15
+
16
+ function getLocalNetworkIp(): string {
17
+ try {
18
+ const nets = networkInterfaces();
19
+ for (const name of Object.keys(nets)) {
20
+ for (const netInfo of nets[name] ?? []) {
21
+ if (netInfo.family === 'IPv4' && !netInfo.internal) return netInfo.address;
22
+ }
23
+ }
24
+ } catch {
25
+ return '127.0.0.1';
26
+ }
27
+ return '127.0.0.1';
28
+ }
29
+
30
+ function urlHostForBindHost(host: string): string {
31
+ if (host === '0.0.0.0' || host === '::') return getLocalNetworkIp();
32
+ return host || '127.0.0.1';
33
+ }
3
34
 
4
- /**
5
- * Register the /qrcode command.
6
- *
7
- * Opens the QR Code panel which displays a scannable QR code for
8
- * companion app pairing, along with connection URL, token, and username.
9
- */
10
35
  export function registerQrcodeRuntimeCommands(registry: CommandRegistry): void {
11
36
  registry.register({
12
37
  name: 'qrcode',
13
38
  aliases: ['qr', 'pair'],
14
- description: 'Open the QR code panel for companion app pairing',
39
+ description: 'Print companion pairing details and a QR code',
15
40
  usage: '',
16
41
  handler(_args, ctx) {
17
- openCommandPanel(ctx, 'qr-code');
42
+ const shellPaths = requireShellPaths(ctx);
43
+ const configManager = requirePlatform(ctx).configManager;
44
+ const daemonHomeDir = join(shellPaths.homeDirectory, '.goodvibes', 'daemon');
45
+ const tokenRecord = getOrCreateCompanionToken(GOODVIBES_AGENT_PAIRING_SURFACE, { daemonHomeDir });
46
+ const binding = resolveRuntimeEndpointBinding(configManager, 'controlPlane');
47
+ const daemonUrl = `http://${urlHostForBindHost(binding.host)}:${binding.port}`;
48
+ const info = buildCompanionConnectionInfo({
49
+ daemonUrl,
50
+ token: tokenRecord.token,
51
+ username: 'admin',
52
+ surface: GOODVIBES_AGENT_PAIRING_SURFACE,
53
+ });
54
+ const payload = encodeConnectionPayload(info);
55
+ const qr = renderQrToString(generateQrMatrix(payload));
56
+ ctx.print([formatConnectionBlock(info, payload), '', qr].join('\n'));
18
57
  },
19
58
  });
20
59
  }
@@ -18,11 +18,11 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
18
18
 
19
19
  const pathArg = commandArgs[0];
20
20
  if (!pathArg) {
21
- context.print('[recall] Usage: /recall export <path> [--scope <scope>] [--cls <class>] --yes');
21
+ context.print('[memory] Usage: /memory export <path> [--scope <scope>] [--cls <class>] --yes');
22
22
  return;
23
23
  }
24
24
  if (!parsed.yes) {
25
- requireYesFlag(context, `export durable memory bundle to ${pathArg}`, '/recall export <path> [--scope <scope>] [--cls <class>] --yes');
25
+ requireYesFlag(context, `export durable memory bundle to ${pathArg}`, '/memory export <path> [--scope <scope>] [--cls <class>] --yes');
26
26
  return;
27
27
  }
28
28
 
@@ -31,7 +31,7 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
31
31
  if (scopeIdx !== -1 && commandArgs[scopeIdx + 1]) {
32
32
  const scope = commandArgs[scopeIdx + 1];
33
33
  if (!isValidScope(scope)) {
34
- context.print(`[recall] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
34
+ context.print(`[memory] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
35
35
  return;
36
36
  }
37
37
  filter.scope = scope;
@@ -41,7 +41,7 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
41
41
  if (clsIdx !== -1 && commandArgs[clsIdx + 1]) {
42
42
  const cls = commandArgs[clsIdx + 1];
43
43
  if (!isValidClass(cls)) {
44
- context.print(`[recall] Unknown class "${cls}". Valid: ${VALID_CLASSES.join(', ')}`);
44
+ context.print(`[memory] Unknown class "${cls}". Valid: ${VALID_CLASSES.join(', ')}`);
45
45
  return;
46
46
  }
47
47
  filter.cls = cls;
@@ -51,7 +51,7 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
51
51
  const targetPath = resolveBundlePath(pathArg, requireShellPaths(context));
52
52
  mkdirSync(dirname(targetPath), { recursive: true });
53
53
  writeFileSync(targetPath, JSON.stringify(bundle, null, 2) + '\n', 'utf-8');
54
- context.print(`[recall] Exported ${bundle.recordCount} record(s) and ${bundle.linkCount} link(s) to ${targetPath}`);
54
+ context.print(`[memory] Exported ${bundle.recordCount} record(s) and ${bundle.linkCount} link(s) to ${targetPath}`);
55
55
  }
56
56
 
57
57
  export async function handleRecallImport(args: string[], context: CommandContext): Promise<void> {
@@ -64,11 +64,11 @@ export async function handleRecallImport(args: string[], context: CommandContext
64
64
 
65
65
  const pathArg = commandArgs[0];
66
66
  if (!pathArg) {
67
- context.print('[recall] Usage: /recall import <path> --yes');
67
+ context.print('[memory] Usage: /memory import <path> --yes');
68
68
  return;
69
69
  }
70
70
  if (!parsed.yes) {
71
- requireYesFlag(context, `import durable memory bundle from ${pathArg}`, '/recall import <path> --yes');
71
+ requireYesFlag(context, `import durable memory bundle from ${pathArg}`, '/memory import <path> --yes');
72
72
  return;
73
73
  }
74
74
 
@@ -77,12 +77,12 @@ export async function handleRecallImport(args: string[], context: CommandContext
77
77
  try {
78
78
  bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as MemoryBundle;
79
79
  } catch (error) {
80
- context.print(`[recall] Failed to read memory bundle: ${summarizeError(error)}`);
80
+ context.print(`[memory] Failed to read memory bundle: ${summarizeError(error)}`);
81
81
  return;
82
82
  }
83
83
 
84
84
  const result = await memory.importBundle(bundle);
85
- context.print(`[recall] Imported bundle from ${targetPath}`);
85
+ context.print(`[memory] Imported bundle from ${targetPath}`);
86
86
  context.print(` Records: imported=${result.importedRecords} skipped=${result.skippedRecords}`);
87
87
  context.print(` Links: imported=${result.importedLinks}`);
88
88
  }
@@ -106,30 +106,30 @@ export function handleRecallHandoffExport(args: string[], context: CommandContex
106
106
  }
107
107
  const pathArg = commandArgs[0];
108
108
  if (!pathArg) {
109
- context.print('[recall] Usage: /recall handoff-export <path> [--scope <scope>] --yes');
109
+ context.print('[memory] Usage: /memory handoff-export <path> [--scope <scope>] --yes');
110
110
  return;
111
111
  }
112
112
  if (!parsed.yes) {
113
- requireYesFlag(context, `export memory handoff bundle to ${pathArg}`, '/recall handoff-export <path> [--scope <scope>] --yes');
113
+ requireYesFlag(context, `export memory handoff bundle to ${pathArg}`, '/memory handoff-export <path> [--scope <scope>] --yes');
114
114
  return;
115
115
  }
116
116
  const scopeIdx = commandArgs.indexOf('--scope');
117
117
  const scopeRaw = scopeIdx !== -1 ? commandArgs[scopeIdx + 1] : 'team';
118
118
  if (!scopeRaw || !isValidScope(scopeRaw)) {
119
- context.print(`[recall] Unknown scope "${scopeRaw ?? ''}". Valid: ${VALID_SCOPES.join(', ')}`);
119
+ context.print(`[memory] Unknown scope "${scopeRaw ?? ''}". Valid: ${VALID_SCOPES.join(', ')}`);
120
120
  return;
121
121
  }
122
122
  const bundle = memory.exportBundle({ scope: scopeRaw });
123
123
  const targetPath = resolveBundlePath(pathArg, requireShellPaths(context));
124
124
  mkdirSync(dirname(targetPath), { recursive: true });
125
125
  writeFileSync(targetPath, JSON.stringify(bundle, null, 2) + '\n', 'utf-8');
126
- context.print(`[recall] Exported ${scopeRaw} handoff bundle to ${targetPath}`);
126
+ context.print(`[memory] Exported ${scopeRaw} handoff bundle to ${targetPath}`);
127
127
  }
128
128
 
129
129
  export function handleRecallHandoffInspect(args: string[], context: CommandContext): void {
130
130
  const pathArg = args[0];
131
131
  if (!pathArg) {
132
- context.print('[recall] Usage: /recall handoff-inspect <path>');
132
+ context.print('[memory] Usage: /memory handoff-inspect <path>');
133
133
  return;
134
134
  }
135
135
  const targetPath = resolveBundlePath(pathArg, requireShellPaths(context));
@@ -137,7 +137,7 @@ export function handleRecallHandoffInspect(args: string[], context: CommandConte
137
137
  const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as MemoryBundle;
138
138
  context.print(inspectBundle(bundle));
139
139
  } catch (error) {
140
- context.print(`[recall] Failed to inspect handoff bundle: ${summarizeError(error)}`);
140
+ context.print(`[memory] Failed to inspect handoff bundle: ${summarizeError(error)}`);
141
141
  }
142
142
  }
143
143
 
@@ -146,7 +146,7 @@ export async function handleRecallHandoffImport(args: string[], context: Command
146
146
  const commandArgs = [...parsed.rest];
147
147
  const pathArg = commandArgs[0];
148
148
  if (!pathArg) {
149
- context.print('[recall] Usage: /recall handoff-import <path> --yes');
149
+ context.print('[memory] Usage: /memory handoff-import <path> --yes');
150
150
  return;
151
151
  }
152
152
  await handleRecallImport([pathArg, ...(parsed.yes ? ['--yes'] : [])], context);
@@ -17,7 +17,7 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
17
17
 
18
18
  const cls = args[0];
19
19
  if (!cls || !isValidClass(cls)) {
20
- context.print(`[recall] Invalid class "${cls ?? ''}". Valid: ${VALID_CLASSES.join(', ')}`);
20
+ context.print(`[memory] Invalid class "${cls ?? ''}". Valid: ${VALID_CLASSES.join(', ')}`);
21
21
  return;
22
22
  }
23
23
 
@@ -36,7 +36,7 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
36
36
  const scope = scopeRaw && isValidScope(scopeRaw) ? scopeRaw : 'project';
37
37
 
38
38
  if (scopeRaw && !isValidScope(scopeRaw)) {
39
- context.print(`[recall] Invalid scope "${scopeRaw}". Valid: ${VALID_SCOPES.join(', ')}`);
39
+ context.print(`[memory] Invalid scope "${scopeRaw}". Valid: ${VALID_SCOPES.join(', ')}`);
40
40
  return;
41
41
  }
42
42
 
@@ -55,12 +55,12 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
55
55
  }
56
56
  const summary = summaryTokens.join(' ');
57
57
  if (!summary.trim()) {
58
- context.print('[recall] Usage: /recall add <class> <summary> [--detail <text>] [--tags <t1,t2>]');
58
+ context.print('[memory] Usage: /memory add <class> <summary> [--detail <text>] [--tags <t1,t2>]');
59
59
  return;
60
60
  }
61
61
 
62
62
  const record = await memory.add({ scope, cls, summary, detail, tags, provenance });
63
- context.print(`[recall] Added ${cls}: ${record.id}`);
63
+ context.print(`[memory] Added ${cls}: ${record.id}`);
64
64
  context.print(` Scope: ${record.scope}`);
65
65
  context.print(` Summary: ${record.summary}`);
66
66
  if (record.tags.length) context.print(` Tags: ${record.tags.join(', ')}`);
@@ -76,7 +76,7 @@ export async function handleRecallCapture(args: string[], context: CommandContex
76
76
  return;
77
77
  }
78
78
  if (!context.extensions.forensicsRegistry) {
79
- context.print('[recall] Forensics registry not available.');
79
+ context.print('[memory] Forensics registry not available.');
80
80
  return;
81
81
  }
82
82
 
@@ -87,66 +87,66 @@ export async function handleRecallCapture(args: string[], context: CommandContex
87
87
  ? context.extensions.forensicsRegistry.latest()
88
88
  : context.extensions.forensicsRegistry.getById(requestedId);
89
89
  if (!report) {
90
- context.print(`[recall] Incident not found: ${requestedId ?? 'latest'}`);
90
+ context.print(`[memory] Incident not found: ${requestedId ?? 'latest'}`);
91
91
  return;
92
92
  }
93
93
  const bundle = context.extensions.forensicsRegistry.buildBundle(report.id);
94
94
  if (!bundle) {
95
- context.print(`[recall] Failed to build incident bundle: ${report.id}`);
95
+ context.print(`[memory] Failed to build incident bundle: ${report.id}`);
96
96
  return;
97
97
  }
98
98
  const record = await memory.add(buildIncidentMemoryAddOptions(bundle));
99
- context.print(`[recall] Captured incident ${report.id} into memory as ${record.id}`);
99
+ context.print(`[memory] Captured incident ${report.id} into memory as ${record.id}`);
100
100
  return;
101
101
  }
102
102
 
103
103
  if (target === 'policy') {
104
104
  const review = context.extensions.policyRuntimeState?.getSnapshot().lastPreflightReview;
105
105
  if (!review) {
106
- context.print('[recall] No policy preflight review is available to capture.');
106
+ context.print('[memory] No policy preflight review is available to capture.');
107
107
  return;
108
108
  }
109
109
  const record = await memory.add(buildPolicyPreflightMemoryAddOptions(review));
110
- context.print(`[recall] Captured policy preflight into memory as ${record.id}`);
110
+ context.print(`[memory] Captured policy preflight into memory as ${record.id}`);
111
111
  return;
112
112
  }
113
113
 
114
114
  if (target === 'mcp') {
115
115
  const serverName = args[1];
116
116
  if (!serverName) {
117
- context.print('[recall] Usage: /recall capture mcp <server>');
117
+ context.print('[memory] Usage: /memory capture mcp <server>');
118
118
  return;
119
119
  }
120
120
  const server = context.extensions.mcpRegistry.listServerSecurity().find((entry) => entry.name === serverName);
121
121
  if (!server) {
122
- context.print(`[recall] MCP server not found: ${serverName}`);
122
+ context.print(`[memory] MCP server not found: ${serverName}`);
123
123
  return;
124
124
  }
125
125
  const record = await memory.add(buildMcpSecurityMemoryAddOptions(server));
126
- context.print(`[recall] Captured MCP server ${server.name} into memory as ${record.id}`);
126
+ context.print(`[memory] Captured MCP server ${server.name} into memory as ${record.id}`);
127
127
  return;
128
128
  }
129
129
 
130
130
  if (target === 'plugin') {
131
131
  if (!pluginManager) {
132
- context.print('[recall] Plugin manager not available.');
132
+ context.print('[memory] Plugin manager not available.');
133
133
  return;
134
134
  }
135
135
  const pluginName = args[1];
136
136
  if (!pluginName) {
137
- context.print('[recall] Usage: /recall capture plugin <name>');
137
+ context.print('[memory] Usage: /memory capture plugin <name>');
138
138
  return;
139
139
  }
140
140
  const plugin = pluginManager.list().find((entry) => entry.name === pluginName);
141
141
  if (!plugin) {
142
- context.print(`[recall] Plugin not found: ${pluginName}`);
142
+ context.print(`[memory] Plugin not found: ${pluginName}`);
143
143
  return;
144
144
  }
145
145
  const quarantineReason = pluginManager.getQuarantineRecord(plugin.name)?.reason;
146
146
  const record = await memory.add(buildPluginSecurityMemoryAddOptions(plugin, quarantineReason));
147
- context.print(`[recall] Captured plugin ${plugin.name} into memory as ${record.id}`);
147
+ context.print(`[memory] Captured plugin ${plugin.name} into memory as ${record.id}`);
148
148
  return;
149
149
  }
150
150
 
151
- context.print('[recall] Usage: /recall capture incident <id|latest> | /recall capture policy | /recall capture mcp <server> | /recall capture plugin <name>');
151
+ context.print('[memory] Usage: /memory capture incident <id|latest> | /memory capture policy | /memory capture mcp <server> | /memory capture plugin <name>');
152
152
  }
@@ -7,8 +7,8 @@ import { requireYesFlag, stripYesFlag } from './confirmation.ts';
7
7
  export function getMemoryApi(context: CommandContext): MemoryApi | null {
8
8
  const memoryApi = context.clients?.agentKnowledgeApi?.memory;
9
9
  if (!memoryApi) {
10
- context.print('[recall] Agent Memory API is not available in this runtime.');
11
- context.print('[recall] Refusing to use default Knowledge/Wiki or non-Agent knowledge fallback.');
10
+ context.print('[memory] Agent Memory API is not available in this runtime.');
11
+ context.print('[memory] Refusing to use default Knowledge/Wiki or non-Agent knowledge fallback.');
12
12
  return null;
13
13
  }
14
14
  return memoryApi;
@@ -29,7 +29,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
29
29
  const cls = args[clsIdx + 1];
30
30
  if (isValidClass(cls)) filter.cls = cls;
31
31
  else {
32
- context.print(`[recall] Unknown class "${cls}". Valid: ${VALID_CLASSES.join(', ')}`);
32
+ context.print(`[memory] Unknown class "${cls}". Valid: ${VALID_CLASSES.join(', ')}`);
33
33
  return;
34
34
  }
35
35
  }
@@ -39,7 +39,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
39
39
  const scope = args[scopeIdx + 1];
40
40
  if (isValidScope(scope)) filter.scope = scope;
41
41
  else {
42
- context.print(`[recall] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
42
+ context.print(`[memory] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
43
43
  return;
44
44
  }
45
45
  }
@@ -59,11 +59,11 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
59
59
  const semanticResults = semantic ? memory.searchSemantic(filter) : [];
60
60
  const results = semantic ? semanticResults.map((entry) => entry.record) : memory.search(filter);
61
61
  if (!results.length) {
62
- context.print('[recall] No records found.');
62
+ context.print('[memory] No records found.');
63
63
  return;
64
64
  }
65
65
 
66
- context.print(`[recall] ${results.length} ${semantic ? 'semantic ' : ''}record(s):`);
66
+ context.print(`[memory] ${results.length} ${semantic ? 'semantic ' : ''}record(s):`);
67
67
  for (const record of results) {
68
68
  const semanticEntry = semanticResults.find((entry) => entry.record.id === record.id);
69
69
  const ts = new Date(record.createdAt).toISOString().slice(0, 16).replace('T', ' ');
@@ -93,7 +93,7 @@ export function handleRecallVector(args: string[], context: CommandContext): voi
93
93
  context.print(formatVectorStats(memory.vectorStats(), sub));
94
94
  return;
95
95
  }
96
- context.print('[recall] Usage: /recall vector [status|doctor|rebuild]');
96
+ context.print('[memory] Usage: /memory vector [status|doctor|rebuild]');
97
97
  }
98
98
 
99
99
  function formatVectorStats(
@@ -101,7 +101,7 @@ function formatVectorStats(
101
101
  label: string,
102
102
  ): string {
103
103
  return [
104
- `[recall] Vector index ${label}`,
104
+ `[memory] Vector index ${label}`,
105
105
  ` backend: ${stats.backend}`,
106
106
  ` enabled: ${stats.enabled ? 'yes' : 'no'}`,
107
107
  ` available: ${stats.available ? 'yes' : 'no'}`,
@@ -119,16 +119,16 @@ export function handleRecallGet(args: string[], context: CommandContext): void {
119
119
  }
120
120
  const id = args[0];
121
121
  if (!id) {
122
- context.print('[recall] Usage: /recall get <id>');
122
+ context.print('[memory] Usage: /memory get <id>');
123
123
  return;
124
124
  }
125
125
  const record = memory.get(id);
126
126
  if (!record) {
127
- context.print(`[recall] Record not found: ${id}`);
127
+ context.print(`[memory] Record not found: ${id}`);
128
128
  return;
129
129
  }
130
130
  const ts = new Date(record.createdAt).toISOString().slice(0, 19).replace('T', ' ');
131
- context.print(`[recall] ${record.id}`);
131
+ context.print(`[memory] ${record.id}`);
132
132
  context.print(` Scope: ${record.scope}`);
133
133
  context.print(` Class: ${record.cls}`);
134
134
  context.print(` Summary: ${record.summary}`);
@@ -163,19 +163,19 @@ export async function handleRecallLink(args: string[], context: CommandContext):
163
163
  const parsed = stripYesFlag(args);
164
164
  const [fromId, toId, relation] = parsed.rest;
165
165
  if (!fromId || !toId || !relation) {
166
- context.print('[recall] Usage: /recall link <fromId> <toId> <relation> --yes');
166
+ context.print('[memory] Usage: /memory link <fromId> <toId> <relation> --yes');
167
167
  return;
168
168
  }
169
169
  if (!parsed.yes) {
170
- requireYesFlag(context, `link memory records ${fromId} and ${toId}`, '/recall link <fromId> <toId> <relation> --yes');
170
+ requireYesFlag(context, `link memory records ${fromId} and ${toId}`, '/memory link <fromId> <toId> <relation> --yes');
171
171
  return;
172
172
  }
173
173
  const link = await memory.link(fromId, toId, relation);
174
174
  if (!link) {
175
- context.print('[recall] Link failed — check that both IDs exist.');
175
+ context.print('[memory] Link failed — check that both IDs exist.');
176
176
  return;
177
177
  }
178
- context.print(`[recall] Linked: ${fromId} -> ${toId} [${relation}]`);
178
+ context.print(`[memory] Linked: ${fromId} -> ${toId} [${relation}]`);
179
179
  }
180
180
 
181
181
  export function handleRecallRemove(args: string[], context: CommandContext): void {
@@ -186,19 +186,19 @@ export function handleRecallRemove(args: string[], context: CommandContext): voi
186
186
  const parsed = stripYesFlag(args);
187
187
  const id = parsed.rest[0];
188
188
  if (!id) {
189
- context.print('[recall] Usage: /recall remove <id> --yes');
189
+ context.print('[memory] Usage: /memory remove <id> --yes');
190
190
  return;
191
191
  }
192
192
  if (!parsed.yes) {
193
- requireYesFlag(context, `delete durable memory record ${id}`, '/recall remove <id> --yes');
193
+ requireYesFlag(context, `delete durable memory record ${id}`, '/memory remove <id> --yes');
194
194
  return;
195
195
  }
196
196
  const removed = memory.delete(id);
197
197
  if (!removed) {
198
- context.print(`[recall] Record not found: ${id}`);
198
+ context.print(`[memory] Record not found: ${id}`);
199
199
  return;
200
200
  }
201
- context.print(`[recall] Deleted: ${id}`);
201
+ context.print(`[memory] Deleted: ${id}`);
202
202
  }
203
203
 
204
204
  export function handleRecallList(args: string[], context: CommandContext): void {
@@ -213,7 +213,7 @@ export function handleRecallList(args: string[], context: CommandContext): void
213
213
  if (scopeIdx !== -1 && args[scopeIdx + 1]) {
214
214
  const scope = args[scopeIdx + 1];
215
215
  if (!isValidScope(scope)) {
216
- context.print(`[recall] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
216
+ context.print(`[memory] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
217
217
  return;
218
218
  }
219
219
  filter.scope = scope;
@@ -221,7 +221,7 @@ export function handleRecallList(args: string[], context: CommandContext): void
221
221
 
222
222
  const records = memory.search(filter);
223
223
  if (!records.length) {
224
- context.print('[recall] No records.');
224
+ context.print('[memory] No records.');
225
225
  return;
226
226
  }
227
227
 
@@ -232,7 +232,7 @@ export function handleRecallList(args: string[], context: CommandContext): void
232
232
  }
233
233
 
234
234
  for (const [clsName, group] of Object.entries(grouped)) {
235
- context.print(`\n[recall] ${clsName.toUpperCase()} (${group.length}):`);
235
+ context.print(`\n[memory] ${clsName.toUpperCase()} (${group.length}):`);
236
236
  for (const record of group) {
237
237
  const tagStr = record.tags.length ? ` [${record.tags.join(', ')}]` : '';
238
238
  context.print(` ${record.id} [${record.scope}]${tagStr} ${record.summary}`);