@pellux/goodvibes-agent 0.1.69 → 0.1.71

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 (60) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +42 -1
  3. package/src/agent/skill-discovery.ts +119 -0
  4. package/src/input/commands/delegation-runtime.ts +0 -8
  5. package/src/input/commands/experience-runtime.ts +0 -177
  6. package/src/input/commands/guidance-runtime.ts +9 -77
  7. package/src/input/commands/local-runtime.ts +1 -57
  8. package/src/input/commands/local-setup-review.ts +1 -1
  9. package/src/input/commands/operator-runtime.ts +1 -145
  10. package/src/input/commands/platform-access-runtime.ts +2 -195
  11. package/src/input/commands/product-runtime.ts +0 -116
  12. package/src/input/commands/security-runtime.ts +88 -0
  13. package/src/input/commands/session-content.ts +0 -97
  14. package/src/input/commands/shell-core.ts +1 -22
  15. package/src/input/commands.ts +2 -43
  16. package/src/panels/builtin/operations.ts +3 -184
  17. package/src/panels/index.ts +0 -11
  18. package/src/version.ts +1 -1
  19. package/src/input/commands/branch-runtime.ts +0 -72
  20. package/src/input/commands/control-room-runtime.ts +0 -234
  21. package/src/input/commands/discovery-runtime.ts +0 -61
  22. package/src/input/commands/hooks-runtime.ts +0 -207
  23. package/src/input/commands/incident-runtime.ts +0 -106
  24. package/src/input/commands/integration-runtime.ts +0 -437
  25. package/src/input/commands/local-setup.ts +0 -288
  26. package/src/input/commands/managed-runtime.ts +0 -240
  27. package/src/input/commands/marketplace-runtime.ts +0 -305
  28. package/src/input/commands/memory-product-runtime.ts +0 -148
  29. package/src/input/commands/operator-panel-runtime.ts +0 -146
  30. package/src/input/commands/platform-services-runtime.ts +0 -271
  31. package/src/input/commands/profile-sync-runtime.ts +0 -110
  32. package/src/input/commands/provider.ts +0 -363
  33. package/src/input/commands/remote-runtime-pool.ts +0 -89
  34. package/src/input/commands/remote-runtime-setup.ts +0 -226
  35. package/src/input/commands/remote-runtime.ts +0 -432
  36. package/src/input/commands/replay-runtime.ts +0 -25
  37. package/src/input/commands/services-runtime.ts +0 -220
  38. package/src/input/commands/settings-sync-runtime.ts +0 -197
  39. package/src/input/commands/share-runtime.ts +0 -127
  40. package/src/input/commands/skills-runtime.ts +0 -226
  41. package/src/input/commands/teleport-runtime.ts +0 -68
  42. package/src/panels/cockpit-panel.ts +0 -183
  43. package/src/panels/communication-panel.ts +0 -153
  44. package/src/panels/control-plane-panel.ts +0 -211
  45. package/src/panels/forensics-panel.ts +0 -364
  46. package/src/panels/hooks-panel.ts +0 -239
  47. package/src/panels/incident-review-panel.ts +0 -197
  48. package/src/panels/marketplace-panel.ts +0 -212
  49. package/src/panels/ops-control-panel.ts +0 -150
  50. package/src/panels/ops-strategy-panel.ts +0 -235
  51. package/src/panels/orchestration-panel.ts +0 -272
  52. package/src/panels/plugins-panel.ts +0 -178
  53. package/src/panels/remote-panel.ts +0 -449
  54. package/src/panels/routes-panel.ts +0 -178
  55. package/src/panels/services-panel.ts +0 -231
  56. package/src/panels/settings-sync-panel.ts +0 -120
  57. package/src/panels/skills-panel.ts +0 -431
  58. package/src/panels/watchers-panel.ts +0 -193
  59. package/src/verification/live-verifier.ts +0 -588
  60. package/src/verification/verification-ledger.ts +0 -239
@@ -1,305 +0,0 @@
1
- import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { dirname, resolve } from 'node:path';
3
- import type { CommandRegistry } from '../command-registry.ts';
4
- import {
5
- exportEcosystemCatalogBundle,
6
- importEcosystemCatalogBundle,
7
- inspectEcosystemCatalogBundle,
8
- inspectInstalledEcosystemEntry,
9
- installEcosystemCatalogEntry,
10
- listEcosystemInstallBackups,
11
- listInstalledEcosystemEntries,
12
- loadEcosystemCatalog,
13
- rollbackInstalledEcosystemEntry,
14
- reviewEcosystemCatalogEntry,
15
- searchEcosystemCatalog,
16
- uninstallEcosystemCatalogEntry,
17
- updateInstalledEcosystemEntry,
18
- type EcosystemCatalogBundle,
19
- type EcosystemCatalogEntry,
20
- type EcosystemEntryKind,
21
- } from '@/runtime/index.ts';
22
- import { openCommandPanel, requireEcosystemCatalogPaths, requireReadModels, requireShellPaths } from './runtime-services.ts';
23
- import { requireYesFlag, stripYesFlag } from './confirmation.ts';
24
-
25
- function resolveMarketplaceEntry(
26
- kind: EcosystemEntryKind,
27
- entryId: string,
28
- options: Parameters<typeof loadEcosystemCatalog>[1],
29
- ): EcosystemCatalogEntry | null {
30
- return loadEcosystemCatalog(kind, options).find((candidate) => candidate.id === entryId) ?? null;
31
- }
32
-
33
- function formatCompatibility(review: ReturnType<typeof reviewEcosystemCatalogEntry>): string {
34
- if (review.compatibility.reasons.length === 0) return 'compatible with current runtime';
35
- return review.compatibility.reasons.join('; ');
36
- }
37
-
38
- export function registerMarketplaceRuntimeCommands(registry: CommandRegistry): void {
39
- registry.register({
40
- name: 'marketplace',
41
- aliases: ['catalog'],
42
- description: 'Browse the unified plugin and skill marketplace',
43
- usage: '[open|overview|recommend|browse [query]|review <plugin|skill|hook-pack|policy-pack> <id>|provenance <plugin|skill|hook-pack|policy-pack> <id>|install-hint <plugin|skill|hook-pack|policy-pack> <id>|install <plugin|skill|hook-pack|policy-pack> <id> [project|user] --yes|update <plugin|skill|hook-pack|policy-pack> <id> [project|user] --yes|rollback <plugin|skill|hook-pack|policy-pack> <id> [project|user] [backupId] --yes|history <plugin|skill|hook-pack|policy-pack> <id> [project|user]|uninstall <plugin|skill|hook-pack|policy-pack> <id> [project|user] --yes|receipt <plugin|skill|hook-pack|policy-pack> <id> [project|user]|bundle export <path> [project|user] --yes|bundle inspect <path>|bundle import <path> [project|user] --yes|installed]',
44
- handler(args, ctx) {
45
- const parsed = stripYesFlag(args);
46
- const commandArgs = [...parsed.rest];
47
- const shellPaths = requireShellPaths(ctx);
48
- const ecosystemPaths = requireEcosystemCatalogPaths(ctx);
49
- const sub = commandArgs[0] ?? 'open';
50
- if (sub === 'open' || sub === 'panel') {
51
- openCommandPanel(ctx, 'marketplace');
52
- return;
53
- }
54
- if (sub === 'overview') {
55
- const pluginCatalog = loadEcosystemCatalog('plugin', ecosystemPaths);
56
- const skillCatalog = loadEcosystemCatalog('skill', ecosystemPaths);
57
- const hookPackCatalog = loadEcosystemCatalog('hook-pack', ecosystemPaths);
58
- const policyPackCatalog = loadEcosystemCatalog('policy-pack', ecosystemPaths);
59
- const installedPlugins = listInstalledEcosystemEntries('plugin', ecosystemPaths);
60
- const installedSkills = listInstalledEcosystemEntries('skill', ecosystemPaths);
61
- const installedHookPacks = listInstalledEcosystemEntries('hook-pack', ecosystemPaths);
62
- const installedPolicyPacks = listInstalledEcosystemEntries('policy-pack', ecosystemPaths);
63
- ctx.print([
64
- 'Marketplace Overview',
65
- ` curated plugins: ${pluginCatalog.length}`,
66
- ` curated skills: ${skillCatalog.length}`,
67
- ` curated hook packs: ${hookPackCatalog.length}`,
68
- ` curated policy packs: ${policyPackCatalog.length}`,
69
- ` installed plugins: ${installedPlugins.length}`,
70
- ` installed skills: ${installedSkills.length}`,
71
- ` installed hook packs: ${installedHookPacks.length}`,
72
- ` installed policy packs: ${installedPolicyPacks.length}`,
73
- ].join('\n'));
74
- return;
75
- }
76
- if (sub === 'browse') {
77
- const query = commandArgs.slice(1).join(' ');
78
- const pluginEntries = query ? searchEcosystemCatalog('plugin', query, ecosystemPaths) : loadEcosystemCatalog('plugin', ecosystemPaths);
79
- const skillEntries = query ? searchEcosystemCatalog('skill', query, ecosystemPaths) : loadEcosystemCatalog('skill', ecosystemPaths);
80
- const hookPackEntries = query ? searchEcosystemCatalog('hook-pack', query, ecosystemPaths) : loadEcosystemCatalog('hook-pack', ecosystemPaths);
81
- const policyPackEntries = query ? searchEcosystemCatalog('policy-pack', query, ecosystemPaths) : loadEcosystemCatalog('policy-pack', ecosystemPaths);
82
- ctx.print([
83
- `Marketplace Browse${query ? ` (${query})` : ''}`,
84
- ` plugins: ${pluginEntries.length}`,
85
- ...pluginEntries.map((entry) => ` plugin ${entry.id} ${entry.name} ${entry.summary}`),
86
- ` skills: ${skillEntries.length}`,
87
- ...skillEntries.map((entry) => ` skill ${entry.id} ${entry.name} ${entry.summary}`),
88
- ` hook packs: ${hookPackEntries.length}`,
89
- ...hookPackEntries.map((entry) => ` hook-pack ${entry.id} ${entry.name} ${entry.summary}`),
90
- ` policy packs: ${policyPackEntries.length}`,
91
- ...policyPackEntries.map((entry) => ` policy-pack ${entry.id} ${entry.name} ${entry.summary}`),
92
- ].join('\n'));
93
- return;
94
- }
95
- if (sub === 'recommend') {
96
- const recommendations = requireReadModels(ctx).marketplace.getSnapshot().recommendations;
97
- ctx.print(recommendations.length > 0
98
- ? [
99
- 'Marketplace Recommendations',
100
- ...recommendations.map((recommendation) => ` ${recommendation.kind} ${recommendation.entry.id} ${recommendation.title}`),
101
- ...recommendations.map((recommendation) => ` ${recommendation.reason} next=${recommendation.command}`),
102
- ].join('\n')
103
- : 'Marketplace Recommendations\n No contextual recommendations right now.');
104
- return;
105
- }
106
- if (sub === 'installed') {
107
- const receipts = [
108
- ...listInstalledEcosystemEntries('plugin', ecosystemPaths).map((receipt) => ` plugin ${receipt.entry.id} ${receipt.scope} ${receipt.targetPath}`),
109
- ...listInstalledEcosystemEntries('skill', ecosystemPaths).map((receipt) => ` skill ${receipt.entry.id} ${receipt.scope} ${receipt.targetPath}`),
110
- ...listInstalledEcosystemEntries('hook-pack', ecosystemPaths).map((receipt) => ` hook-pack ${receipt.entry.id} ${receipt.scope} ${receipt.targetPath}`),
111
- ...listInstalledEcosystemEntries('policy-pack', ecosystemPaths).map((receipt) => ` policy-pack ${receipt.entry.id} ${receipt.scope} ${receipt.targetPath}`),
112
- ];
113
- ctx.print(receipts.length > 0
114
- ? ['Marketplace Installs', ...receipts].join('\n')
115
- : 'Marketplace Installs\n No curated plugins or skills installed yet.');
116
- return;
117
- }
118
- if (sub === 'bundle') {
119
- const mode = commandArgs[1];
120
- const target = commandArgs[2];
121
- const scope = commandArgs[3] === 'user' ? 'user' : 'project';
122
- if ((mode === 'export' || mode === 'inspect' || mode === 'import') && !target) {
123
- ctx.print(`Usage: /marketplace bundle ${mode} <path>${mode === 'export' || mode === 'import' ? ' [project|user] --yes' : ''}`);
124
- return;
125
- }
126
- if (mode === 'export') {
127
- if (!parsed.yes) {
128
- requireYesFlag(ctx, `export marketplace bundle to ${target}`, '/marketplace bundle export <path> [project|user] --yes');
129
- return;
130
- }
131
- const bundle = exportEcosystemCatalogBundle(scope, ecosystemPaths);
132
- const targetPath = shellPaths.resolveWorkspacePath(target!);
133
- mkdirSync(dirname(targetPath), { recursive: true });
134
- writeFileSync(targetPath, `${JSON.stringify(bundle, null, 2)}\n`, 'utf-8');
135
- ctx.print(`Marketplace bundle exported to ${targetPath}`);
136
- return;
137
- }
138
- if (mode === 'inspect') {
139
- const bundle = JSON.parse(readFileSync(shellPaths.resolveWorkspacePath(target!), 'utf-8')) as EcosystemCatalogBundle;
140
- const summary = inspectEcosystemCatalogBundle(bundle);
141
- ctx.print([
142
- 'Marketplace Bundle Review',
143
- ` exportedAt: ${new Date(summary.exportedAt).toISOString()}`,
144
- ` scope: ${summary.scope}`,
145
- ` plugins: ${summary.counts.plugin}`,
146
- ` skills: ${summary.counts.skill}`,
147
- ].join('\n'));
148
- return;
149
- }
150
- if (mode === 'import') {
151
- if (!parsed.yes) {
152
- requireYesFlag(ctx, `import marketplace bundle from ${target}`, '/marketplace bundle import <path> [project|user] --yes');
153
- return;
154
- }
155
- const bundle = JSON.parse(readFileSync(shellPaths.resolveWorkspacePath(target!), 'utf-8')) as EcosystemCatalogBundle;
156
- const result = importEcosystemCatalogBundle(bundle, { ...ecosystemPaths, scope });
157
- ctx.print([
158
- `Marketplace bundle imported from ${shellPaths.resolveWorkspacePath(target!)}`,
159
- ` entries: ${result.imported}`,
160
- ...Object.entries(result.pathByKind).map(([kind, path]) => ` ${kind}: ${path}`),
161
- ].join('\n'));
162
- return;
163
- }
164
- ctx.print('Usage: /marketplace bundle <export|inspect|import> <path> [project|user] --yes');
165
- return;
166
- }
167
-
168
- const kind = commandArgs[1] as EcosystemEntryKind | undefined;
169
- const entryId = commandArgs[2];
170
- if ((sub === 'review' || sub === 'provenance' || sub === 'install-hint' || sub === 'install' || sub === 'update' || sub === 'rollback' || sub === 'history' || sub === 'uninstall' || sub === 'receipt') && (!kind || !entryId || !['plugin', 'skill', 'hook-pack', 'policy-pack'].includes(kind))) {
171
- ctx.print(`Usage: /marketplace ${sub} <plugin|skill|hook-pack|policy-pack> <id>${sub === 'install' || sub === 'update' || sub === 'rollback' || sub === 'history' || sub === 'uninstall' || sub === 'receipt' ? ' [project|user]' : ''}${sub === 'install' || sub === 'update' || sub === 'rollback' || sub === 'uninstall' ? ' --yes' : ''}`);
172
- return;
173
- }
174
- if (sub === 'review') {
175
- const entry = resolveMarketplaceEntry(kind!, entryId!, ecosystemPaths);
176
- if (!entry) {
177
- ctx.print(`Unknown curated ${kind} entry: ${entryId}`);
178
- return;
179
- }
180
- const review = reviewEcosystemCatalogEntry(entry, ecosystemPaths);
181
- ctx.print([
182
- `Marketplace Review: ${entry.name}`,
183
- ` kind: ${kind}`,
184
- ` id: ${entry.id}`,
185
- ` source: ${entry.source}`,
186
- ` sourceKind: ${review.sourceKind}`,
187
- ` sourceExists: ${review.sourceExists ? 'yes' : 'no'}`,
188
- ` recommendedScope: ${review.recommendedScope}`,
189
- ` risk: ${review.riskLevel}`,
190
- ` compatibility: ${review.compatibility.status}`,
191
- ` notes: ${formatCompatibility(review)}`,
192
- ].join('\n'));
193
- return;
194
- }
195
- if (sub === 'provenance') {
196
- const entry = resolveMarketplaceEntry(kind!, entryId!, ecosystemPaths);
197
- if (!entry) {
198
- ctx.print(`Unknown curated ${kind} entry: ${entryId}`);
199
- return;
200
- }
201
- const review = reviewEcosystemCatalogEntry(entry, ecosystemPaths);
202
- ctx.print([
203
- `Marketplace Provenance: ${entry.name}`,
204
- ` source: ${entry.source}`,
205
- ` provenance: ${entry.provenance ?? '(none declared)'}`,
206
- ` version: ${entry.version ?? '(unspecified)'}`,
207
- ` author: ${entry.author ?? '(unspecified)'}`,
208
- ` signature: ${entry.signature ?? '(none declared)'}`,
209
- ` compatibility: ${formatCompatibility(review)}`,
210
- ` trust notes: ${entry.trustNotes ?? '(none)'}`,
211
- ].join('\n'));
212
- return;
213
- }
214
- if (sub === 'install-hint') {
215
- const entry = resolveMarketplaceEntry(kind!, entryId!, ecosystemPaths);
216
- if (!entry) {
217
- ctx.print(`Unknown curated ${kind} entry: ${entryId}`);
218
- return;
219
- }
220
- ctx.print([
221
- `Marketplace Install Guidance: ${entry.name}`,
222
- ` kind: ${kind}`,
223
- ` source: ${entry.source}`,
224
- ` install hint: ${entry.installHint ?? 'Install from a local curated source with explicit scope.'}`,
225
- ` trust notes: ${entry.trustNotes ?? '(none)'}`,
226
- ].join('\n'));
227
- return;
228
- }
229
- if (sub === 'receipt') {
230
- const scope = commandArgs[3] === 'user' ? 'user' : 'project';
231
- const result = inspectInstalledEcosystemEntry(kind!, entryId!, { ...ecosystemPaths, scope });
232
- if (!result.ok) {
233
- ctx.print(`Error: ${result.error}`);
234
- return;
235
- }
236
- const { receipt } = result;
237
- ctx.print([
238
- `Marketplace Receipt: ${receipt.entry.name}`,
239
- ` installedAt: ${new Date(receipt.installedAt).toISOString()}`,
240
- ` scope: ${receipt.scope}`,
241
- ` targetPath: ${receipt.targetPath}`,
242
- ` fingerprint: ${receipt.fingerprint}`,
243
- ` provenance: ${receipt.provenanceSummary}`,
244
- ` compatibility: ${receipt.compatibility.status}`,
245
- ...receipt.compatibility.reasons.map((reason) => ` note: ${reason}`),
246
- ].join('\n'));
247
- return;
248
- }
249
- if (sub === 'history') {
250
- const scope = commandArgs[3] === 'user' ? 'user' : 'project';
251
- const backups = listEcosystemInstallBackups(kind!, entryId!, { ...ecosystemPaths, scope });
252
- ctx.print(backups.length > 0
253
- ? [
254
- `Marketplace Rollback History: ${kind} ${entryId}`,
255
- ...backups.map((backup) => ` ${backup.id} ${new Date(backup.createdAt).toISOString()} ${backup.reason} ${backup.receipt.entry.version ?? 'n/a'}`),
256
- ].join('\n')
257
- : `Marketplace Rollback History: ${kind} ${entryId}\n No rollback backups recorded.`);
258
- return;
259
- }
260
- if (sub === 'install' || sub === 'update' || sub === 'rollback' || sub === 'uninstall') {
261
- const scope = commandArgs[3] === 'user' ? 'user' : 'project';
262
- if (!parsed.yes) {
263
- requireYesFlag(ctx, `${sub} curated ${kind} ${entryId}`, `/marketplace ${sub} <plugin|skill|hook-pack|policy-pack> <id> [project|user]${sub === 'rollback' ? ' [backupId]' : ''} --yes`);
264
- return;
265
- }
266
- if (sub === 'install') {
267
- const result = installEcosystemCatalogEntry(kind!, entryId!, { ...ecosystemPaths, scope });
268
- if (!result.ok) {
269
- ctx.print(`Error: ${result.error}`);
270
- return;
271
- }
272
- ctx.print(`Installed curated ${kind} ${entryId} into ${result.receipt.targetPath}`);
273
- return;
274
- }
275
- if (sub === 'update') {
276
- const result = updateInstalledEcosystemEntry(kind!, entryId!, { ...ecosystemPaths, scope });
277
- if (!result.ok) {
278
- ctx.print(`Error: ${result.error}`);
279
- return;
280
- }
281
- ctx.print(`Updated curated ${kind} ${entryId} in ${result.receipt.targetPath}`);
282
- return;
283
- }
284
- if (sub === 'rollback') {
285
- const backupId = commandArgs[4];
286
- const result = rollbackInstalledEcosystemEntry(kind!, entryId!, { ...ecosystemPaths, scope, backupId });
287
- if (!result.ok) {
288
- ctx.print(`Error: ${result.error}`);
289
- return;
290
- }
291
- ctx.print(`Rolled back curated ${kind} ${entryId} in ${result.receipt.targetPath} using backup ${result.restoredFrom.id}`);
292
- return;
293
- }
294
- const result = uninstallEcosystemCatalogEntry(kind!, entryId!, { ...ecosystemPaths, scope });
295
- if (!result.ok) {
296
- ctx.print(`Error: ${result.error}`);
297
- return;
298
- }
299
- ctx.print(`Uninstalled curated ${kind} ${entryId} from ${result.removedPath}`);
300
- return;
301
- }
302
- ctx.print('Usage: /marketplace [open|overview|recommend|browse [query]|review <plugin|skill|hook-pack|policy-pack> <id>|provenance <plugin|skill|hook-pack|policy-pack> <id>|install-hint <plugin|skill|hook-pack|policy-pack> <id>|install <plugin|skill|hook-pack|policy-pack> <id> [project|user] --yes|update <plugin|skill|hook-pack|policy-pack> <id> [project|user] --yes|rollback <plugin|skill|hook-pack|policy-pack> <id> [project|user] [backupId] --yes|history <plugin|skill|hook-pack|policy-pack> <id> [project|user]|uninstall <plugin|skill|hook-pack|policy-pack> <id> [project|user] --yes|receipt <plugin|skill|hook-pack|policy-pack> <id> [project|user]|bundle export <path> [project|user] --yes|bundle inspect <path>|bundle import <path> [project|user] --yes|installed]');
303
- },
304
- });
305
- }
@@ -1,148 +0,0 @@
1
- import type { CommandRegistry } from '../command-registry.ts';
2
- import { requireYesFlag, stripYesFlag } from './confirmation.ts';
3
-
4
- export function registerMemoryProductRuntimeCommands(registry: CommandRegistry): void {
5
- registry.register({
6
- name: 'memory-sync',
7
- aliases: ['memsync'],
8
- description: 'Dedicated front-door for durable memory export/import and bundle exchange',
9
- usage: '[export <path> [scope] --yes | import <path> --yes]',
10
- async handler(args, ctx) {
11
- const parsed = stripYesFlag(args);
12
- const commandArgs = [...parsed.rest];
13
- const sub = (commandArgs[0] ?? '').toLowerCase();
14
- if (!ctx.executeCommand) {
15
- ctx.print('Memory sync controls are not available in this runtime.');
16
- return;
17
- }
18
- if (sub === 'export' && commandArgs[1]) {
19
- if (!parsed.yes) {
20
- requireYesFlag(ctx, `export durable memory bundle to ${commandArgs[1]}`, '/memory-sync export <path> [scope] --yes');
21
- return;
22
- }
23
- const scope = commandArgs[2];
24
- const recallArgs = ['export', commandArgs[1], ...(scope ? ['--scope', scope] : []), '--yes'];
25
- await ctx.executeCommand('recall', recallArgs);
26
- return;
27
- }
28
- if (sub === 'import' && commandArgs[1]) {
29
- if (!parsed.yes) {
30
- requireYesFlag(ctx, `import durable memory bundle from ${commandArgs[1]}`, '/memory-sync import <path> --yes');
31
- return;
32
- }
33
- await ctx.executeCommand('recall', ['import', commandArgs[1], '--yes']);
34
- return;
35
- }
36
- ctx.print('Usage: /memory-sync [export <path> [scope] --yes | import <path> --yes]');
37
- },
38
- });
39
-
40
- registry.register({
41
- name: 'handoff',
42
- description: 'Dedicated front-door for reviewable memory handoff bundles',
43
- usage: '[export <path> [scope] --yes | inspect <path> | import <path> --yes]',
44
- async handler(args, ctx) {
45
- const parsed = stripYesFlag(args);
46
- const commandArgs = [...parsed.rest];
47
- const sub = (commandArgs[0] ?? '').toLowerCase();
48
- if (!ctx.executeCommand) {
49
- ctx.print('Handoff controls are not available in this runtime.');
50
- return;
51
- }
52
- if (sub === 'export' && commandArgs[1]) {
53
- if (!parsed.yes) {
54
- requireYesFlag(ctx, `export memory handoff bundle to ${commandArgs[1]}`, '/handoff export <path> [scope] --yes');
55
- return;
56
- }
57
- const scope = commandArgs[2];
58
- await ctx.executeCommand('recall', ['handoff-export', commandArgs[1], ...(scope ? ['--scope', scope] : []), '--yes']);
59
- return;
60
- }
61
- if (sub === 'inspect' && commandArgs[1]) {
62
- await ctx.executeCommand('recall', ['handoff-inspect', commandArgs[1]]);
63
- return;
64
- }
65
- if (sub === 'import' && commandArgs[1]) {
66
- if (!parsed.yes) {
67
- requireYesFlag(ctx, `import memory handoff bundle from ${commandArgs[1]}`, '/handoff import <path> --yes');
68
- return;
69
- }
70
- await ctx.executeCommand('recall', ['handoff-import', commandArgs[1], '--yes']);
71
- return;
72
- }
73
- ctx.print('Usage: /handoff [export <path> [scope] --yes | inspect <path> | import <path> --yes]');
74
- },
75
- });
76
-
77
- registry.register({
78
- name: 'session-memory',
79
- description: 'Dedicated front-door for session-scoped memory capture and review',
80
- usage: '[queue [limit] | export <path> --yes | add <class> <summary...>]',
81
- async handler(args, ctx) {
82
- const parsed = stripYesFlag(args);
83
- const commandArgs = [...parsed.rest];
84
- const sub = (commandArgs[0] ?? 'queue').toLowerCase();
85
- if (!ctx.executeCommand) {
86
- ctx.print('Session memory controls are not available in this runtime.');
87
- return;
88
- }
89
- if (sub === 'queue') {
90
- await ctx.executeCommand('recall', ['queue', ...(commandArgs[1] ? [commandArgs[1]] : [])]);
91
- return;
92
- }
93
- if (sub === 'export' && commandArgs[1]) {
94
- if (!parsed.yes) {
95
- requireYesFlag(ctx, `export session memory bundle to ${commandArgs[1]}`, '/session-memory export <path> --yes');
96
- return;
97
- }
98
- await ctx.executeCommand('recall', ['export', commandArgs[1], '--scope', 'session', '--yes']);
99
- return;
100
- }
101
- if (sub === 'add' && commandArgs.length >= 3) {
102
- await ctx.executeCommand('recall', ['add', commandArgs[1], ...commandArgs.slice(2), '--scope', 'session']);
103
- return;
104
- }
105
- ctx.print('Usage: /session-memory [queue [limit] | export <path> --yes | add <class> <summary...>]');
106
- },
107
- });
108
-
109
- registry.register({
110
- name: 'team-memory',
111
- description: 'Dedicated front-door for team/shared memory review and exchange',
112
- usage: '[queue [limit] | export <path> --yes | import <path> --yes | capture policy]',
113
- async handler(args, ctx) {
114
- const parsed = stripYesFlag(args);
115
- const commandArgs = [...parsed.rest];
116
- const sub = (commandArgs[0] ?? 'queue').toLowerCase();
117
- if (!ctx.executeCommand) {
118
- ctx.print('Team memory controls are not available in this runtime.');
119
- return;
120
- }
121
- if (sub === 'queue') {
122
- await ctx.executeCommand('recall', ['queue', ...(commandArgs[1] ? [commandArgs[1]] : [])]);
123
- return;
124
- }
125
- if (sub === 'export' && commandArgs[1]) {
126
- if (!parsed.yes) {
127
- requireYesFlag(ctx, `export team memory handoff bundle to ${commandArgs[1]}`, '/team-memory export <path> --yes');
128
- return;
129
- }
130
- await ctx.executeCommand('recall', ['handoff-export', commandArgs[1], '--scope', 'team', '--yes']);
131
- return;
132
- }
133
- if (sub === 'import' && commandArgs[1]) {
134
- if (!parsed.yes) {
135
- requireYesFlag(ctx, `import team memory handoff bundle from ${commandArgs[1]}`, '/team-memory import <path> --yes');
136
- return;
137
- }
138
- await ctx.executeCommand('recall', ['handoff-import', commandArgs[1], '--yes']);
139
- return;
140
- }
141
- if (sub === 'capture' && commandArgs[1]?.toLowerCase() === 'policy') {
142
- await ctx.executeCommand('recall', ['capture', 'policy']);
143
- return;
144
- }
145
- ctx.print('Usage: /team-memory [queue [limit] | export <path> --yes | import <path> --yes | capture policy]');
146
- },
147
- });
148
- }
@@ -1,146 +0,0 @@
1
- import type { CommandRegistry } from '../command-registry.ts';
2
- import { requirePanelManager } from './runtime-services.ts';
3
- import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
4
-
5
- export function registerOperatorPanelCommand(registry: CommandRegistry): void {
6
- registry.register({
7
- name: 'panel',
8
- aliases: ['panels', 'p'],
9
- description: 'Open, place, resize, or list panels. Usage: /panel [open <id> [top|bottom]|close <id>|list|toggle|move|focus|split|width|height]',
10
- usage: '[open <id> [top|bottom]|close <id>|list|toggle|move <top|bottom|other> [id]|focus <top|bottom|toggle>|split [show|hide|toggle]|width <left|right|reset>|height <up|down|reset>]',
11
- argsHint: '<open|close|list|toggle|move|focus|split|width|height> [id]',
12
- handler(args, ctx) {
13
- const pm = requirePanelManager(ctx);
14
- const sub = args[0]?.toLowerCase() ?? '';
15
- if (!sub || sub === 'toggle') {
16
- try {
17
- if (ctx.showPanel) ctx.showPanel('panel-list');
18
- else {
19
- pm.open('panel-list');
20
- pm.show();
21
- ctx.focusPanels?.();
22
- ctx.renderRequest();
23
- }
24
- } catch {
25
- pm.toggle();
26
- ctx.renderRequest();
27
- }
28
- } else if (sub === 'list') {
29
- try {
30
- if (ctx.showPanel) ctx.showPanel('panel-list');
31
- else {
32
- pm.open('panel-list');
33
- pm.show();
34
- ctx.focusPanels?.();
35
- ctx.renderRequest();
36
- }
37
- } catch {
38
- pm.show();
39
- ctx.renderRequest();
40
- }
41
- } else if (sub === 'open') {
42
- const id = args[1];
43
- const pane = args[2]?.toLowerCase();
44
- if (!id) { ctx.print('Usage: /panel open <panel-id>'); return; }
45
- if (pane && pane !== 'top' && pane !== 'bottom') {
46
- ctx.print('Usage: /panel open <panel-id> [top|bottom]');
47
- return;
48
- }
49
- try {
50
- if (ctx.showPanel) ctx.showPanel(id, pane as 'top' | 'bottom' | undefined);
51
- else {
52
- pm.open(id, pane as 'top' | 'bottom' | undefined);
53
- pm.show();
54
- ctx.focusPanels?.();
55
- ctx.renderRequest();
56
- }
57
- ctx.print(`Panel opened: ${id}${pane ? ` (${pane} pane)` : ''}`);
58
- } catch (e) {
59
- ctx.print(`Error: ${summarizeError(e)}`);
60
- }
61
- } else if (sub === 'close') {
62
- const id = args[1];
63
- if (!id) { ctx.print('Usage: /panel close <panel-id>'); return; }
64
- try {
65
- pm.close(id);
66
- ctx.focusPrompt?.();
67
- ctx.renderRequest();
68
- ctx.print(`Panel closed: ${id}`);
69
- } catch (e) {
70
- ctx.print(`Error: ${summarizeError(e)}`);
71
- }
72
- } else if (sub === 'move') {
73
- const dest = args[1]?.toLowerCase();
74
- if (dest !== 'top' && dest !== 'bottom' && dest !== 'other') {
75
- ctx.print('Usage: /panel move <top|bottom|other> [panel-id]');
76
- return;
77
- }
78
- const panelId = args[2];
79
- try {
80
- if (dest === 'other') pm.moveToOtherPane(panelId);
81
- else pm.moveToPane(dest, panelId);
82
- ctx.renderRequest();
83
- ctx.print(`Panel moved to ${dest} pane`);
84
- } catch (e) {
85
- ctx.print(`Error: ${summarizeError(e)}`);
86
- }
87
- } else if (sub === 'focus') {
88
- const pane = args[1]?.toLowerCase();
89
- if (pane !== 'top' && pane !== 'bottom' && pane !== 'toggle') {
90
- ctx.print('Usage: /panel focus <top|bottom|toggle>');
91
- return;
92
- }
93
- if (pane === 'toggle') pm.togglePaneFocus();
94
- else pm.focusPane(pane);
95
- ctx.renderRequest();
96
- ctx.print(`Focused ${pm.getFocusedPane()} pane`);
97
- } else if (sub === 'split') {
98
- const mode = args[1]?.toLowerCase() ?? 'toggle';
99
- if (mode !== 'toggle' && mode !== 'show' && mode !== 'hide') {
100
- ctx.print('Usage: /panel split [show|hide|toggle]');
101
- return;
102
- }
103
- if (mode === 'show' && !pm.isBottomPaneVisible()) pm.toggleBottomPane();
104
- if (mode === 'hide' && pm.isBottomPaneVisible()) pm.toggleBottomPane();
105
- if (mode === 'toggle') pm.toggleBottomPane();
106
- ctx.renderRequest();
107
- ctx.print(pm.isBottomPaneVisible() ? 'Bottom pane visible' : 'Bottom pane hidden');
108
- } else if (sub === 'width') {
109
- const dir = args[1]?.toLowerCase();
110
- if (dir !== 'left' && dir !== 'right' && dir !== 'reset') {
111
- ctx.print('Usage: /panel width <left|right|reset>');
112
- return;
113
- }
114
- if (dir === 'left') pm.widenLeft();
115
- else if (dir === 'right') pm.widenRight();
116
- else pm.setSplitRatio(0.6);
117
- ctx.renderRequest();
118
- ctx.print(`Panel width ratio: ${pm.getSplitRatio().toFixed(2)}`);
119
- } else if (sub === 'height') {
120
- const dir = args[1]?.toLowerCase();
121
- if (dir !== 'up' && dir !== 'down' && dir !== 'reset') {
122
- ctx.print('Usage: /panel height <up|down|reset>');
123
- return;
124
- }
125
- if (dir === 'up') pm.setVerticalSplitRatio(pm.getVerticalSplitRatio() - 0.05);
126
- else if (dir === 'down') pm.setVerticalSplitRatio(pm.getVerticalSplitRatio() + 0.05);
127
- else pm.setVerticalSplitRatio(0.5);
128
- ctx.renderRequest();
129
- ctx.print(`Panel height ratio: ${pm.getVerticalSplitRatio().toFixed(2)}`);
130
- } else {
131
- const id = args[0]!;
132
- try {
133
- if (ctx.showPanel) ctx.showPanel(id);
134
- else {
135
- pm.open(id);
136
- pm.show();
137
- ctx.focusPanels?.();
138
- ctx.renderRequest();
139
- }
140
- } catch {
141
- ctx.print(`Unknown panel "${id}". Use /panel list to see available panels.`);
142
- }
143
- }
144
- },
145
- });
146
- }