@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.
- package/CHANGELOG.md +12 -0
- package/README.md +3 -3
- package/docs/README.md +2 -2
- package/docs/getting-started.md +1 -1
- package/docs/runtime-connection.md +37 -0
- package/package.json +43 -2
- package/src/agent/skill-discovery.ts +119 -0
- package/src/cli/config-overrides.ts +1 -5
- package/src/cli/entrypoint.ts +0 -6
- package/src/cli/help.ts +0 -43
- package/src/cli/index.ts +0 -2
- package/src/cli/management-commands.ts +1 -109
- package/src/cli/management.ts +1 -32
- package/src/cli/package-verification.ts +12 -4
- package/src/cli/parser.ts +0 -16
- package/src/cli/status.ts +1 -1
- package/src/cli/types.ts +0 -8
- package/src/input/commands/delegation-runtime.ts +0 -8
- package/src/input/commands/experience-runtime.ts +0 -177
- package/src/input/commands/guidance-runtime.ts +0 -69
- package/src/input/commands/local-runtime.ts +1 -57
- package/src/input/commands/local-setup-review.ts +1 -1
- package/src/input/commands/operator-runtime.ts +1 -145
- package/src/input/commands/platform-access-runtime.ts +2 -195
- package/src/input/commands/product-runtime.ts +0 -116
- package/src/input/commands/security-runtime.ts +88 -0
- package/src/input/commands/session-content.ts +0 -97
- package/src/input/commands/shell-core.ts +0 -13
- package/src/input/commands.ts +2 -95
- package/src/panels/builtin/operations.ts +3 -184
- package/src/panels/confirm-state.ts +1 -1
- package/src/panels/index.ts +0 -11
- package/src/version.ts +1 -1
- package/docs/deployment-and-services.md +0 -52
- package/src/cli/service-command.ts +0 -26
- package/src/cli/surface-command.ts +0 -247
- package/src/input/commands/branch-runtime.ts +0 -72
- package/src/input/commands/control-room-runtime.ts +0 -234
- package/src/input/commands/discovery-runtime.ts +0 -61
- package/src/input/commands/hooks-runtime.ts +0 -207
- package/src/input/commands/incident-runtime.ts +0 -106
- package/src/input/commands/integration-runtime.ts +0 -437
- package/src/input/commands/local-setup.ts +0 -288
- package/src/input/commands/managed-runtime.ts +0 -240
- package/src/input/commands/marketplace-runtime.ts +0 -305
- package/src/input/commands/memory-product-runtime.ts +0 -148
- package/src/input/commands/operator-panel-runtime.ts +0 -146
- package/src/input/commands/platform-services-runtime.ts +0 -271
- package/src/input/commands/profile-sync-runtime.ts +0 -110
- package/src/input/commands/provider.ts +0 -363
- package/src/input/commands/remote-runtime-pool.ts +0 -89
- package/src/input/commands/remote-runtime-setup.ts +0 -226
- package/src/input/commands/remote-runtime.ts +0 -432
- package/src/input/commands/replay-runtime.ts +0 -25
- package/src/input/commands/services-runtime.ts +0 -220
- package/src/input/commands/settings-sync-runtime.ts +0 -197
- package/src/input/commands/share-runtime.ts +0 -127
- package/src/input/commands/skills-runtime.ts +0 -226
- package/src/input/commands/teleport-runtime.ts +0 -68
- package/src/panels/cockpit-panel.ts +0 -183
- package/src/panels/communication-panel.ts +0 -153
- package/src/panels/control-plane-panel.ts +0 -211
- package/src/panels/forensics-panel.ts +0 -364
- package/src/panels/hooks-panel.ts +0 -239
- package/src/panels/incident-review-panel.ts +0 -197
- package/src/panels/marketplace-panel.ts +0 -212
- package/src/panels/ops-control-panel.ts +0 -150
- package/src/panels/ops-strategy-panel.ts +0 -235
- package/src/panels/orchestration-panel.ts +0 -272
- package/src/panels/plugins-panel.ts +0 -178
- package/src/panels/remote-panel.ts +0 -449
- package/src/panels/routes-panel.ts +0 -178
- package/src/panels/services-panel.ts +0 -231
- package/src/panels/settings-sync-panel.ts +0 -120
- package/src/panels/skills-panel.ts +0 -431
- package/src/panels/watchers-panel.ts +0 -193
- package/src/verification/live-verifier.ts +0 -588
- 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
|
-
}
|