@pellux/goodvibes-agent 0.1.70 → 0.1.72

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 (78) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +3 -3
  3. package/docs/README.md +2 -2
  4. package/docs/getting-started.md +1 -1
  5. package/docs/runtime-connection.md +37 -0
  6. package/package.json +43 -2
  7. package/src/agent/skill-discovery.ts +119 -0
  8. package/src/cli/config-overrides.ts +1 -5
  9. package/src/cli/entrypoint.ts +0 -6
  10. package/src/cli/help.ts +0 -43
  11. package/src/cli/index.ts +0 -2
  12. package/src/cli/management-commands.ts +1 -109
  13. package/src/cli/management.ts +1 -32
  14. package/src/cli/package-verification.ts +12 -4
  15. package/src/cli/parser.ts +0 -16
  16. package/src/cli/status.ts +1 -1
  17. package/src/cli/types.ts +0 -8
  18. package/src/input/commands/delegation-runtime.ts +0 -8
  19. package/src/input/commands/experience-runtime.ts +0 -177
  20. package/src/input/commands/guidance-runtime.ts +0 -69
  21. package/src/input/commands/local-runtime.ts +1 -57
  22. package/src/input/commands/local-setup-review.ts +1 -1
  23. package/src/input/commands/operator-runtime.ts +1 -145
  24. package/src/input/commands/platform-access-runtime.ts +2 -195
  25. package/src/input/commands/product-runtime.ts +0 -116
  26. package/src/input/commands/security-runtime.ts +88 -0
  27. package/src/input/commands/session-content.ts +0 -97
  28. package/src/input/commands/shell-core.ts +0 -13
  29. package/src/input/commands.ts +2 -95
  30. package/src/panels/builtin/operations.ts +3 -184
  31. package/src/panels/confirm-state.ts +1 -1
  32. package/src/panels/index.ts +0 -11
  33. package/src/version.ts +1 -1
  34. package/docs/deployment-and-services.md +0 -52
  35. package/src/cli/service-command.ts +0 -26
  36. package/src/cli/surface-command.ts +0 -247
  37. package/src/input/commands/branch-runtime.ts +0 -72
  38. package/src/input/commands/control-room-runtime.ts +0 -234
  39. package/src/input/commands/discovery-runtime.ts +0 -61
  40. package/src/input/commands/hooks-runtime.ts +0 -207
  41. package/src/input/commands/incident-runtime.ts +0 -106
  42. package/src/input/commands/integration-runtime.ts +0 -437
  43. package/src/input/commands/local-setup.ts +0 -288
  44. package/src/input/commands/managed-runtime.ts +0 -240
  45. package/src/input/commands/marketplace-runtime.ts +0 -305
  46. package/src/input/commands/memory-product-runtime.ts +0 -148
  47. package/src/input/commands/operator-panel-runtime.ts +0 -146
  48. package/src/input/commands/platform-services-runtime.ts +0 -271
  49. package/src/input/commands/profile-sync-runtime.ts +0 -110
  50. package/src/input/commands/provider.ts +0 -363
  51. package/src/input/commands/remote-runtime-pool.ts +0 -89
  52. package/src/input/commands/remote-runtime-setup.ts +0 -226
  53. package/src/input/commands/remote-runtime.ts +0 -432
  54. package/src/input/commands/replay-runtime.ts +0 -25
  55. package/src/input/commands/services-runtime.ts +0 -220
  56. package/src/input/commands/settings-sync-runtime.ts +0 -197
  57. package/src/input/commands/share-runtime.ts +0 -127
  58. package/src/input/commands/skills-runtime.ts +0 -226
  59. package/src/input/commands/teleport-runtime.ts +0 -68
  60. package/src/panels/cockpit-panel.ts +0 -183
  61. package/src/panels/communication-panel.ts +0 -153
  62. package/src/panels/control-plane-panel.ts +0 -211
  63. package/src/panels/forensics-panel.ts +0 -364
  64. package/src/panels/hooks-panel.ts +0 -239
  65. package/src/panels/incident-review-panel.ts +0 -197
  66. package/src/panels/marketplace-panel.ts +0 -212
  67. package/src/panels/ops-control-panel.ts +0 -150
  68. package/src/panels/ops-strategy-panel.ts +0 -235
  69. package/src/panels/orchestration-panel.ts +0 -272
  70. package/src/panels/plugins-panel.ts +0 -178
  71. package/src/panels/remote-panel.ts +0 -449
  72. package/src/panels/routes-panel.ts +0 -178
  73. package/src/panels/services-panel.ts +0 -231
  74. package/src/panels/settings-sync-panel.ts +0 -120
  75. package/src/panels/skills-panel.ts +0 -431
  76. package/src/panels/watchers-panel.ts +0 -193
  77. package/src/verification/live-verifier.ts +0 -588
  78. package/src/verification/verification-ledger.ts +0 -239
@@ -1,207 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import type { CommandRegistry } from '../command-registry.ts';
3
- import { requireHookApi } from './runtime-services.ts';
4
- import { requireYesFlag, stripYesFlag } from './confirmation.ts';
5
-
6
- function isRecord(value: unknown): value is Record<string, unknown> {
7
- return typeof value === 'object' && value !== null && !Array.isArray(value);
8
- }
9
-
10
- function containsAgentHookType(value: unknown): boolean {
11
- if (Array.isArray(value)) return value.some((entry) => containsAgentHookType(entry));
12
- if (!isRecord(value)) return false;
13
- if (value.type === 'agent') return true;
14
- return Object.values(value).some((entry) => containsAgentHookType(entry));
15
- }
16
-
17
- function fileContainsAgentHookType(path: string): boolean {
18
- try {
19
- return containsAgentHookType(JSON.parse(readFileSync(path, 'utf-8')) as unknown);
20
- } catch {
21
- return false;
22
- }
23
- }
24
-
25
- export function registerHooksRuntimeCommands(registry: CommandRegistry): void {
26
- registry.register({
27
- name: 'hooks',
28
- aliases: [],
29
- description: 'Inspect, author, simulate, and reload managed hook workflows',
30
- usage: '[contracts [filter] | reload --yes | scaffold <name> <match> <type> --yes | chain <name> <event1,event2,...> --yes | remove <name> --yes | enable <name> --yes | disable <name> --yes | simulate <eventPath> | inspect <path> | import <path> [merge|replace] --yes | export [path] --yes]',
31
- argsHint: '[subcommand]',
32
- async handler(args, ctx) {
33
- const parsed = stripYesFlag(args);
34
- const commandArgs = [...parsed.rest];
35
- const hookApi = requireHookApi(ctx);
36
- const workbench = hookApi.workbench;
37
- if (commandArgs.length === 0 && ctx.openHooksPanel) {
38
- ctx.openHooksPanel();
39
- return;
40
- }
41
-
42
- const subcommand = (commandArgs[0] ?? 'contracts').toLowerCase();
43
- if (subcommand === 'reload') {
44
- if (!parsed.yes) {
45
- requireYesFlag(ctx, 'reload managed hook workflows', '/hooks reload --yes');
46
- return;
47
- }
48
- await workbench.reload();
49
- ctx.print(`Reloaded managed hooks from ${workbench.getFilePath()}`);
50
- return;
51
- }
52
- if (subcommand === 'scaffold') {
53
- const [name, match, type] = commandArgs.slice(1);
54
- if (!name || !match || !type) {
55
- ctx.print('Usage: /hooks scaffold <name> <match> <command|prompt|http|ts> --yes');
56
- return;
57
- }
58
- if (!parsed.yes) {
59
- requireYesFlag(ctx, `scaffold managed hook ${name}`, '/hooks scaffold <name> <match> <command|prompt|http|ts> --yes');
60
- return;
61
- }
62
- if (type === 'agent') {
63
- ctx.print('Blocked: GoodVibes Agent does not author local agent-spawning hooks. Use command, prompt, http, or ts hooks, or delegate explicit build work to GoodVibes TUI.');
64
- return;
65
- }
66
- if (!['command', 'prompt', 'http', 'ts'].includes(type)) {
67
- ctx.print(`Unknown hook type: ${type}`);
68
- return;
69
- }
70
- const hook = await workbench.scaffoldHook(name, match, type as Parameters<typeof workbench.scaffoldHook>[2]);
71
- ctx.print(`Scaffolded managed hook ${hook.name} at ${match} in ${workbench.getFilePath()}`);
72
- return;
73
- }
74
- if (subcommand === 'chain') {
75
- const name = commandArgs[1];
76
- const matches = commandArgs[2]?.split(',').map((entry) => entry.trim()).filter(Boolean) ?? [];
77
- if (!name || matches.length === 0) {
78
- ctx.print('Usage: /hooks chain <name> <event1,event2,...> --yes');
79
- return;
80
- }
81
- if (!parsed.yes) {
82
- requireYesFlag(ctx, `scaffold managed hook chain ${name}`, '/hooks chain <name> <event1,event2,...> --yes');
83
- return;
84
- }
85
- const chain = await workbench.scaffoldChain(name, matches);
86
- ctx.print(`Scaffolded managed hook chain ${chain.name} with ${chain.steps.length} step(s).`);
87
- return;
88
- }
89
- if (subcommand === 'remove') {
90
- const name = commandArgs[1];
91
- if (!name) {
92
- ctx.print('Usage: /hooks remove <name> --yes');
93
- return;
94
- }
95
- if (!parsed.yes) {
96
- requireYesFlag(ctx, `remove managed hook workflow ${name}`, '/hooks remove <name> --yes');
97
- return;
98
- }
99
- const removed = await workbench.remove(name);
100
- if (!removed) {
101
- ctx.print(`No managed hook or chain named ${name}.`);
102
- return;
103
- }
104
- ctx.print(`Removed managed hook workflow entry ${name}.`);
105
- return;
106
- }
107
- if (subcommand === 'enable' || subcommand === 'disable') {
108
- const name = commandArgs[1];
109
- if (!name) {
110
- ctx.print(`Usage: /hooks ${subcommand} <name> --yes`);
111
- return;
112
- }
113
- if (!parsed.yes) {
114
- requireYesFlag(ctx, `${subcommand} managed hook ${name}`, `/hooks ${subcommand} <name> --yes`);
115
- return;
116
- }
117
- const changed = await workbench.toggle(name, subcommand === 'enable');
118
- if (!changed) {
119
- ctx.print(`No managed hook named ${name}.`);
120
- return;
121
- }
122
- ctx.print(`${subcommand === 'enable' ? 'Enabled' : 'Disabled'} managed hook ${name}.`);
123
- return;
124
- }
125
- if (subcommand === 'simulate') {
126
- const eventPath = commandArgs[1];
127
- if (!eventPath) {
128
- ctx.print('Usage: /hooks simulate <eventPath>');
129
- return;
130
- }
131
- const result = workbench.simulate(eventPath);
132
- ctx.print([
133
- `Hook simulation for ${result.eventPath}`,
134
- ` matched hooks: ${result.matchedHooks.length}`,
135
- ...result.matchedHooks.map((entry) => ` ${entry.name} ${entry.pattern} ${entry.type}`),
136
- ` matched chains: ${result.matchedChains.length}`,
137
- ...result.matchedChains.map((entry) => ` ${entry.name} stepMatches=${entry.stepMatches}`),
138
- ].join('\n'));
139
- return;
140
- }
141
- if (subcommand === 'export') {
142
- if (!parsed.yes) {
143
- requireYesFlag(ctx, 'export managed hook workflows', '/hooks export [path] --yes');
144
- return;
145
- }
146
- const path = await workbench.export(commandArgs[1] ?? workbench.getFilePath());
147
- ctx.print(`Exported managed hooks to ${path}`);
148
- return;
149
- }
150
- if (subcommand === 'inspect') {
151
- const path = commandArgs[1];
152
- if (!path) {
153
- ctx.print('Usage: /hooks inspect <path>');
154
- return;
155
- }
156
- const inspection = workbench.inspect(path);
157
- ctx.print([
158
- `Hook bundle inspection: ${inspection.path}`,
159
- ` hooks: ${inspection.hookCount}`,
160
- ` chains: ${inspection.chainCount}`,
161
- ` patterns: ${inspection.patterns.join(', ') || '(none)'}`,
162
- ].join('\n'));
163
- return;
164
- }
165
- if (subcommand === 'import') {
166
- const path = commandArgs[1];
167
- const strategy = commandArgs[2] === 'replace' ? 'replace' : 'merge';
168
- if (!path) {
169
- ctx.print('Usage: /hooks import <path> [merge|replace] --yes');
170
- return;
171
- }
172
- if (!parsed.yes) {
173
- requireYesFlag(ctx, `import managed hook workflows from ${path}`, '/hooks import <path> [merge|replace] --yes');
174
- return;
175
- }
176
- if (fileContainsAgentHookType(path)) {
177
- ctx.print('Blocked: hook bundle contains type=agent entries. GoodVibes Agent does not import local agent-spawning hooks.');
178
- return;
179
- }
180
- await workbench.import(path, strategy);
181
- ctx.print(`Imported managed hooks from ${path} using ${strategy} strategy.`);
182
- return;
183
- }
184
-
185
- const filter = (subcommand === 'contracts' ? commandArgs.slice(1) : commandArgs).join(' ').trim().toLowerCase();
186
- const contracts = hookApi.contracts(filter);
187
-
188
- if (contracts.length === 0) {
189
- ctx.print(filter.length === 0 ? 'No hook contracts registered.' : `No hook contracts matched "${filter}".`);
190
- return;
191
- }
192
-
193
- const lines: string[] = [`Hook Contracts (${contracts.length}):`];
194
- for (const contract of contracts) {
195
- lines.push(` ${contract.pattern}`);
196
- lines.push(` authority=${contract.authority} mode=${contract.executionMode} deny=${contract.canDeny ? 'yes' : 'no'} mutate=${contract.canMutateInput ? 'yes' : 'no'} inject=${contract.canInjectContext ? 'yes' : 'no'} timeout=${contract.timeoutMs}ms policy=${contract.failurePolicy}`);
197
- lines.push(` ${contract.description}`);
198
- }
199
- const managedHooks = workbench.listManagedHooks();
200
- const managedChains = workbench.listManagedChains();
201
- lines.push('');
202
- lines.push(`Managed hooks file: ${workbench.getFilePath()}`);
203
- lines.push(`Managed entries: hooks=${managedHooks.length} chains=${managedChains.length}`);
204
- ctx.print(lines.join('\n'));
205
- },
206
- });
207
- }
@@ -1,106 +0,0 @@
1
- import { dirname, resolve } from 'path';
2
- import { mkdirSync, writeFileSync } from 'node:fs';
3
- import type { CommandRegistry } from '../command-registry.ts';
4
- import { buildIncidentMemoryAddOptions } from '@pellux/goodvibes-sdk/platform/state';
5
- import { requireShellPaths } from './runtime-services.ts';
6
- import { getMemoryApi } from './recall-query.ts';
7
- import { requireYesFlag, stripYesFlag } from './confirmation.ts';
8
-
9
- export function registerIncidentRuntimeCommands(registry: CommandRegistry): void {
10
- registry.register({
11
- name: 'incident',
12
- aliases: [],
13
- description: 'Open, export, and capture incident review bundles',
14
- usage: '[open | latest | show <id|latest> | export <id|latest> <path> --yes | capture <id|latest> --yes]',
15
- async handler(args, ctx) {
16
- const parsed = stripYesFlag(args);
17
- const commandArgs = [...parsed.rest];
18
- const shellPaths = requireShellPaths(ctx);
19
- const subcommand = (commandArgs[0] ?? 'open').toLowerCase();
20
- const forensicRegistry = ctx.extensions.forensicsRegistry;
21
- if (subcommand === 'open') {
22
- if (ctx.openIncidentPanel) {
23
- ctx.openIncidentPanel();
24
- return;
25
- }
26
- ctx.print('Incident panel is not available in this runtime.');
27
- return;
28
- }
29
- if (!forensicRegistry) {
30
- ctx.print('Forensics registry is not available in this runtime.');
31
- return;
32
- }
33
- const requestedId = commandArgs[1];
34
- const report = !requestedId || requestedId === 'latest'
35
- ? forensicRegistry.latest()
36
- : forensicRegistry.getById(requestedId);
37
- if (subcommand === 'latest' || subcommand === 'show') {
38
- if (!report) {
39
- ctx.print('No incident bundle is available.');
40
- return;
41
- }
42
- const bundle = forensicRegistry.buildBundle(report.id);
43
- if (!bundle) {
44
- ctx.print(`Failed to build incident bundle for ${report.id}.`);
45
- return;
46
- }
47
- ctx.print([
48
- `Incident ${report.id}`,
49
- ` classification: ${report.classification}`,
50
- ` summary: ${report.summary}`,
51
- ` root cause: ${bundle.evidence.rootCause ?? 'n/a'}`,
52
- ` denied permissions: ${bundle.evidence.deniedPermissionCount}`,
53
- ` budget breaches: ${bundle.evidence.budgetBreachCount}`,
54
- ` replay mismatches: ${bundle.replay.mismatchCount}`,
55
- ].join('\n'));
56
- return;
57
- }
58
- if (subcommand === 'export') {
59
- const pathArg = commandArgs[2];
60
- if (!requestedId || !pathArg) {
61
- ctx.print('Usage: /incident export <id|latest> <path> --yes');
62
- return;
63
- }
64
- if (!parsed.yes) {
65
- requireYesFlag(ctx, `export incident bundle ${requestedId}`, '/incident export <id|latest> <path> --yes');
66
- return;
67
- }
68
- if (!report) {
69
- ctx.print(`Incident not found: ${requestedId}`);
70
- return;
71
- }
72
- const bundleJson = forensicRegistry.exportBundleAsJson(report.id);
73
- if (!bundleJson) {
74
- ctx.print(`Failed to export incident bundle for ${report.id}.`);
75
- return;
76
- }
77
- const targetPath = shellPaths.resolveWorkspacePath(pathArg);
78
- mkdirSync(dirname(targetPath), { recursive: true });
79
- writeFileSync(targetPath, `${bundleJson}\n`, 'utf-8');
80
- ctx.print(`Exported incident bundle ${report.id} to ${targetPath}`);
81
- return;
82
- }
83
- if (subcommand === 'capture') {
84
- if (!parsed.yes) {
85
- requireYesFlag(ctx, `capture incident ${requestedId ?? 'latest'} into durable memory`, '/incident capture <id|latest> --yes');
86
- return;
87
- }
88
- const memory = getMemoryApi(ctx);
89
- if (!memory) return;
90
- if (!report) {
91
- ctx.print(`Incident not found: ${requestedId ?? 'latest'}`);
92
- return;
93
- }
94
- const bundle = forensicRegistry.buildBundle(report.id);
95
- if (!bundle) {
96
- ctx.print(`Failed to build incident bundle for ${report.id}.`);
97
- return;
98
- }
99
- const record = await memory.add(buildIncidentMemoryAddOptions(bundle));
100
- ctx.print(`Captured incident ${report.id} into durable memory as ${record.id}`);
101
- return;
102
- }
103
- ctx.print('Usage: /incident [open | latest | show <id|latest> | export <id|latest> <path> --yes | capture <id|latest> --yes]');
104
- },
105
- });
106
- }