@pellux/goodvibes-agent 0.1.9 → 0.1.11
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 +41 -0
- package/README.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/release-and-publishing.md +2 -2
- package/package.json +4 -1
- package/src/cli/agent-knowledge-command.ts +46 -20
- package/src/cli/help.ts +15 -2
- package/src/cli/management-commands.ts +3 -3
- package/src/cli/management.ts +7 -1
- package/src/cli/parser.ts +3 -0
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +9 -9
- package/src/cli/surface-command.ts +3 -3
- package/src/cli/types.ts +2 -0
- package/src/input/commands/cloudflare-runtime.ts +20 -5
- package/src/input/commands/confirmation.ts +24 -0
- package/src/input/commands/discovery-runtime.ts +16 -7
- package/src/input/commands/eval.ts +27 -14
- package/src/input/commands/experience-runtime.ts +66 -27
- package/src/input/commands/health-runtime.ts +1 -1
- package/src/input/commands/hooks-runtime.ts +79 -20
- package/src/input/commands/incident-runtime.ts +17 -6
- package/src/input/commands/integration-runtime.ts +93 -50
- package/src/input/commands/knowledge.ts +38 -12
- package/src/input/commands/local-auth-runtime.ts +36 -13
- package/src/input/commands/local-provider-runtime.ts +22 -11
- package/src/input/commands/local-runtime.ts +21 -11
- package/src/input/commands/local-setup.ts +35 -16
- package/src/input/commands/managed-runtime.ts +51 -20
- package/src/input/commands/marketplace-runtime.ts +31 -16
- package/src/input/commands/mcp-runtime.ts +65 -34
- package/src/input/commands/memory-product-runtime.ts +72 -35
- package/src/input/commands/memory.ts +9 -9
- package/src/input/commands/notify-runtime.ts +27 -8
- package/src/input/commands/operator-runtime.ts +85 -17
- package/src/input/commands/planning-runtime.ts +14 -2
- package/src/input/commands/platform-access-runtime.ts +88 -45
- package/src/input/commands/platform-services-runtime.ts +51 -25
- package/src/input/commands/product-runtime.ts +54 -27
- package/src/input/commands/profile-sync-runtime.ts +17 -6
- package/src/input/commands/recall-bundle.ts +38 -17
- package/src/input/commands/recall-query.ts +15 -4
- package/src/input/commands/recall-review.ts +9 -3
- package/src/input/commands/remote-runtime-setup.ts +45 -18
- package/src/input/commands/remote-runtime.ts +25 -9
- package/src/input/commands/replay-runtime.ts +9 -2
- package/src/input/commands/services-runtime.ts +21 -10
- package/src/input/commands/session-content.ts +53 -51
- package/src/input/commands/session-workflow.ts +10 -4
- package/src/input/commands/session.ts +1 -1
- package/src/input/commands/settings-sync-runtime.ts +40 -17
- package/src/input/commands/share-runtime.ts +12 -4
- package/src/input/commands/shell-core.ts +3 -3
- package/src/input/commands/subscription-runtime.ts +35 -20
- package/src/input/commands/teleport-runtime.ts +16 -5
- package/src/input/commands/work-plan-runtime.ts +23 -12
- package/src/input/handler-content-actions.ts +11 -62
- package/src/input/handler-interactions.ts +1 -1
- package/src/input/handler-onboarding-cloudflare.ts +48 -117
- package/src/input/handler.ts +1 -0
- package/src/input/keybindings.ts +1 -1
- package/src/input/mcp-workspace.ts +25 -49
- package/src/input/onboarding/onboarding-runtime-status.ts +8 -8
- package/src/input/onboarding/onboarding-wizard-apply.ts +13 -53
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +12 -12
- package/src/input/onboarding/onboarding-wizard-cloudflare.ts +2 -7
- package/src/input/onboarding/onboarding-wizard-constants.ts +7 -7
- package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +4 -4
- package/src/input/onboarding/onboarding-wizard-steps.ts +13 -13
- package/src/input/profile-picker-modal.ts +13 -31
- package/src/input/session-picker-modal.ts +4 -30
- package/src/input/settings-modal-agent-policy.ts +18 -0
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +17 -0
- package/src/input/settings-modal.ts +30 -29
- package/src/main.ts +3 -26
- package/src/panels/incident-review-panel.ts +1 -1
- package/src/panels/local-auth-panel.ts +4 -4
- package/src/panels/provider-account-snapshot.ts +1 -1
- package/src/panels/provider-health-domains.ts +2 -2
- package/src/panels/settings-sync-panel.ts +2 -2
- package/src/panels/subscription-panel.ts +7 -7
- package/src/renderer/block-actions.ts +1 -1
- package/src/renderer/help-overlay.ts +2 -2
- package/src/renderer/mcp-workspace.ts +12 -12
- package/src/renderer/process-modal.ts +17 -8
- package/src/renderer/profile-picker-modal.ts +3 -11
- package/src/renderer/session-picker-modal.ts +2 -10
- package/src/renderer/settings-modal.ts +12 -8
- package/src/renderer/ui-factory.ts +4 -32
- package/src/runtime/bootstrap-shell.ts +0 -13
- package/src/runtime/bootstrap.ts +0 -10
- package/src/runtime/onboarding/derivation.ts +6 -6
- package/src/verification/live-verifier.ts +148 -13
- package/src/version.ts +10 -3
- package/src/input/commands/quit-shared.ts +0 -162
- package/src/renderer/git-status.ts +0 -89
|
@@ -2,6 +2,7 @@ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { dirname, resolve } from 'node:path';
|
|
3
3
|
import type { CommandRegistry } from '../command-registry.ts';
|
|
4
4
|
import { requireSecretsManager, requireShellPaths } from './runtime-services.ts';
|
|
5
|
+
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
5
6
|
|
|
6
7
|
interface SecureStorageBundle {
|
|
7
8
|
readonly version: 1;
|
|
@@ -58,11 +59,13 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
58
59
|
registry.register({
|
|
59
60
|
name: 'storage',
|
|
60
61
|
description: 'Review secure storage posture and export portable storage metadata bundles',
|
|
61
|
-
usage: '[review|list|delete <key
|
|
62
|
+
usage: '[review|list|delete <key> --yes|bundle export <path> --yes|bundle inspect <path>]',
|
|
62
63
|
async handler(args, ctx) {
|
|
64
|
+
const parsed = stripYesFlag(args);
|
|
65
|
+
const commandArgs = [...parsed.rest];
|
|
63
66
|
const shellPaths = requireShellPaths(ctx);
|
|
64
67
|
const manager = requireSecretsManager(ctx);
|
|
65
|
-
const sub =
|
|
68
|
+
const sub = commandArgs[0] ?? 'review';
|
|
66
69
|
const review = await manager.inspect();
|
|
67
70
|
const storedKeys = await manager.list();
|
|
68
71
|
const detailedKeys = await manager.listDetailed();
|
|
@@ -88,9 +91,13 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
88
91
|
return;
|
|
89
92
|
}
|
|
90
93
|
if (sub === 'delete') {
|
|
91
|
-
const key =
|
|
94
|
+
const key = commandArgs[1];
|
|
92
95
|
if (!key) {
|
|
93
|
-
ctx.print('Usage: /storage delete <key>');
|
|
96
|
+
ctx.print('Usage: /storage delete <key> --yes');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (!parsed.yes) {
|
|
100
|
+
requireYesFlag(ctx, `delete secure storage key ${key}`, '/storage delete <key> --yes');
|
|
94
101
|
return;
|
|
95
102
|
}
|
|
96
103
|
await manager.delete(key);
|
|
@@ -98,14 +105,18 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
98
105
|
return;
|
|
99
106
|
}
|
|
100
107
|
if (sub === 'bundle') {
|
|
101
|
-
const mode =
|
|
102
|
-
const pathArg =
|
|
108
|
+
const mode = commandArgs[1];
|
|
109
|
+
const pathArg = commandArgs[2];
|
|
103
110
|
if ((mode === 'export' || mode === 'inspect') && !pathArg) {
|
|
104
|
-
ctx.print(`Usage: /storage bundle ${mode} <path
|
|
111
|
+
ctx.print(`Usage: /storage bundle ${mode} <path>${mode === 'export' ? ' --yes' : ''}`);
|
|
105
112
|
return;
|
|
106
113
|
}
|
|
107
|
-
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
108
114
|
if (mode === 'export') {
|
|
115
|
+
if (!parsed.yes) {
|
|
116
|
+
requireYesFlag(ctx, `export secure storage metadata bundle to ${pathArg}`, '/storage bundle export <path> --yes');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
109
120
|
const bundle: SecureStorageBundle = {
|
|
110
121
|
version: 1,
|
|
111
122
|
exportedAt: Date.now(),
|
|
@@ -118,12 +129,13 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
118
129
|
return;
|
|
119
130
|
}
|
|
120
131
|
if (mode === 'inspect') {
|
|
132
|
+
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
121
133
|
const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as SecureStorageBundle;
|
|
122
134
|
ctx.print(inspectStorageBundle(bundle));
|
|
123
135
|
return;
|
|
124
136
|
}
|
|
125
137
|
}
|
|
126
|
-
ctx.print('Usage: /storage [review|list|delete <key
|
|
138
|
+
ctx.print('Usage: /storage [review|list|delete <key> --yes|bundle export <path> --yes|bundle inspect <path>]');
|
|
127
139
|
},
|
|
128
140
|
});
|
|
129
141
|
|
|
@@ -131,10 +143,12 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
131
143
|
name: 'helpers',
|
|
132
144
|
aliases: ['integration-api'],
|
|
133
145
|
description: 'Review local integration helper API surfaces for remote clients and future web frontends',
|
|
134
|
-
usage: '[review|bundle export <path
|
|
146
|
+
usage: '[review|bundle export <path> --yes|bundle inspect <path>]',
|
|
135
147
|
handler(args, ctx) {
|
|
148
|
+
const parsed = stripYesFlag(args);
|
|
149
|
+
const commandArgs = [...parsed.rest];
|
|
136
150
|
const shellPaths = requireShellPaths(ctx);
|
|
137
|
-
const sub =
|
|
151
|
+
const sub = commandArgs[0] ?? 'review';
|
|
138
152
|
const review = ctx.extensions.integrationHelpers?.buildReview();
|
|
139
153
|
if (!review) {
|
|
140
154
|
ctx.print('Integration helper service unavailable in this runtime.');
|
|
@@ -156,14 +170,18 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
156
170
|
return;
|
|
157
171
|
}
|
|
158
172
|
if (sub === 'bundle') {
|
|
159
|
-
const mode =
|
|
160
|
-
const pathArg =
|
|
173
|
+
const mode = commandArgs[1];
|
|
174
|
+
const pathArg = commandArgs[2];
|
|
161
175
|
if ((mode === 'export' || mode === 'inspect') && !pathArg) {
|
|
162
|
-
ctx.print(`Usage: /helpers bundle ${mode} <path
|
|
176
|
+
ctx.print(`Usage: /helpers bundle ${mode} <path>${mode === 'export' ? ' --yes' : ''}`);
|
|
163
177
|
return;
|
|
164
178
|
}
|
|
165
|
-
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
166
179
|
if (mode === 'export') {
|
|
180
|
+
if (!parsed.yes) {
|
|
181
|
+
requireYesFlag(ctx, `export integration helper bundle to ${pathArg}`, '/helpers bundle export <path> --yes');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
167
185
|
const bundle: IntegrationHelperBundle = {
|
|
168
186
|
version: 1,
|
|
169
187
|
exportedAt: Date.now(),
|
|
@@ -176,12 +194,13 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
176
194
|
return;
|
|
177
195
|
}
|
|
178
196
|
if (mode === 'inspect') {
|
|
197
|
+
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
179
198
|
const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as IntegrationHelperBundle;
|
|
180
199
|
ctx.print(inspectIntegrationHelperBundle(bundle));
|
|
181
200
|
return;
|
|
182
201
|
}
|
|
183
202
|
}
|
|
184
|
-
ctx.print('Usage: /helpers [review|bundle export <path
|
|
203
|
+
ctx.print('Usage: /helpers [review|bundle export <path> --yes|bundle inspect <path>]');
|
|
185
204
|
},
|
|
186
205
|
});
|
|
187
206
|
|
|
@@ -189,10 +208,12 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
189
208
|
name: 'deeplink',
|
|
190
209
|
aliases: ['link'],
|
|
191
210
|
description: 'Review and package deep-link entrypoints for setup and operator surfaces',
|
|
192
|
-
usage: '[review|open <surface> [target]|bundle export <path
|
|
211
|
+
usage: '[review|open <surface> [target]|bundle export <path> --yes|bundle inspect <path>]',
|
|
193
212
|
handler(args, ctx) {
|
|
213
|
+
const parsed = stripYesFlag(args);
|
|
214
|
+
const commandArgs = [...parsed.rest];
|
|
194
215
|
const shellPaths = requireShellPaths(ctx);
|
|
195
|
-
const sub =
|
|
216
|
+
const sub = commandArgs[0] ?? 'review';
|
|
196
217
|
const links = [
|
|
197
218
|
buildSetupLink('cockpit'),
|
|
198
219
|
buildSetupLink('security'),
|
|
@@ -206,8 +227,8 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
206
227
|
return;
|
|
207
228
|
}
|
|
208
229
|
if (sub === 'open') {
|
|
209
|
-
const surface =
|
|
210
|
-
const target =
|
|
230
|
+
const surface = commandArgs[1];
|
|
231
|
+
const target = commandArgs[2];
|
|
211
232
|
if (!surface) {
|
|
212
233
|
ctx.print('Usage: /deeplink open <surface> [target]');
|
|
213
234
|
return;
|
|
@@ -216,14 +237,18 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
216
237
|
return;
|
|
217
238
|
}
|
|
218
239
|
if (sub === 'bundle') {
|
|
219
|
-
const mode =
|
|
220
|
-
const pathArg =
|
|
240
|
+
const mode = commandArgs[1];
|
|
241
|
+
const pathArg = commandArgs[2];
|
|
221
242
|
if ((mode === 'export' || mode === 'inspect') && !pathArg) {
|
|
222
|
-
ctx.print(`Usage: /deeplink bundle ${mode} <path
|
|
243
|
+
ctx.print(`Usage: /deeplink bundle ${mode} <path>${mode === 'export' ? ' --yes' : ''}`);
|
|
223
244
|
return;
|
|
224
245
|
}
|
|
225
|
-
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
226
246
|
if (mode === 'export') {
|
|
247
|
+
if (!parsed.yes) {
|
|
248
|
+
requireYesFlag(ctx, `export deep link bundle to ${pathArg}`, '/deeplink bundle export <path> --yes');
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
227
252
|
const bundle: DeepLinkBundle = {
|
|
228
253
|
version: 1,
|
|
229
254
|
exportedAt: Date.now(),
|
|
@@ -235,12 +260,13 @@ export function registerPlatformServicesRuntimeCommands(registry: CommandRegistr
|
|
|
235
260
|
return;
|
|
236
261
|
}
|
|
237
262
|
if (mode === 'inspect') {
|
|
263
|
+
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
238
264
|
const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as DeepLinkBundle;
|
|
239
265
|
ctx.print(inspectDeepLinkBundle(bundle));
|
|
240
266
|
return;
|
|
241
267
|
}
|
|
242
268
|
}
|
|
243
|
-
ctx.print('Usage: /deeplink [review|open <surface> [target]|bundle export <path
|
|
269
|
+
ctx.print('Usage: /deeplink [review|open <surface> [target]|bundle export <path> --yes|bundle inspect <path>]');
|
|
244
270
|
},
|
|
245
271
|
});
|
|
246
272
|
}
|
|
@@ -4,6 +4,7 @@ import type { CommandContext, CommandRegistry } from '../command-registry.ts';
|
|
|
4
4
|
import { listInstalledEcosystemEntries, loadEcosystemCatalog } from '@/runtime/index.ts';
|
|
5
5
|
import { BUILTIN_SUITES } from '@/runtime/index.ts';
|
|
6
6
|
import { requireEcosystemCatalogPaths, requireReadModels, requireSecretsManager, requireServiceRegistry, requireShellPaths } from './runtime-services.ts';
|
|
7
|
+
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
7
8
|
|
|
8
9
|
interface TrustReviewBundle {
|
|
9
10
|
readonly version: 1;
|
|
@@ -155,23 +156,29 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
|
|
|
155
156
|
registry.register({
|
|
156
157
|
name: 'trust',
|
|
157
158
|
description: 'Review trust posture and export portable trust bundles',
|
|
158
|
-
usage: '[review|bundle export <path
|
|
159
|
+
usage: '[review|bundle export <path> --yes|bundle inspect <path>]',
|
|
159
160
|
async handler(args, ctx) {
|
|
161
|
+
const parsed = stripYesFlag(args);
|
|
162
|
+
const commandArgs = [...parsed.rest];
|
|
160
163
|
const shellPaths = requireShellPaths(ctx);
|
|
161
|
-
const sub =
|
|
164
|
+
const sub = commandArgs[0] ?? 'review';
|
|
162
165
|
if (sub === 'review') {
|
|
163
166
|
const bundle = await buildTrustReviewBundle(ctx);
|
|
164
167
|
ctx.print(formatTrustReview(bundle));
|
|
165
168
|
return;
|
|
166
169
|
}
|
|
167
170
|
if (sub === 'bundle') {
|
|
168
|
-
const mode =
|
|
169
|
-
const pathArg =
|
|
171
|
+
const mode = commandArgs[1];
|
|
172
|
+
const pathArg = commandArgs[2];
|
|
170
173
|
if ((mode === 'export' || mode === 'inspect') && !pathArg) {
|
|
171
|
-
ctx.print(`Usage: /trust bundle ${mode} <path
|
|
174
|
+
ctx.print(`Usage: /trust bundle ${mode} <path>${mode === 'export' ? ' --yes' : ''}`);
|
|
172
175
|
return;
|
|
173
176
|
}
|
|
174
177
|
if (mode === 'export') {
|
|
178
|
+
if (!parsed.yes) {
|
|
179
|
+
requireYesFlag(ctx, `export trust bundle to ${pathArg}`, '/trust bundle export <path> --yes');
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
175
182
|
const bundle = await buildTrustReviewBundle(ctx);
|
|
176
183
|
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
177
184
|
mkdirSync(dirname(targetPath), { recursive: true });
|
|
@@ -184,21 +191,23 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
|
|
|
184
191
|
return;
|
|
185
192
|
}
|
|
186
193
|
}
|
|
187
|
-
ctx.print('Usage: /trust [review|bundle export <path
|
|
194
|
+
ctx.print('Usage: /trust [review|bundle export <path> --yes|bundle inspect <path>]');
|
|
188
195
|
},
|
|
189
196
|
});
|
|
190
197
|
registry.register({
|
|
191
198
|
name: 'bridge',
|
|
192
199
|
description: 'Review and operate self-hosted bridge and remote runner flows',
|
|
193
|
-
usage: '[status|pools|assign <pool> <runner
|
|
200
|
+
usage: '[status|pools|assign <pool> <runner> --yes|runner <id>|review <artifactId>|export <artifactId> [path] --yes|import <path> --yes]',
|
|
194
201
|
async handler(args, ctx) {
|
|
202
|
+
const parsed = stripYesFlag(args);
|
|
203
|
+
const commandArgs = [...parsed.rest];
|
|
195
204
|
const shellPaths = requireShellPaths(ctx);
|
|
196
205
|
if (!ctx.ops.remoteRuntime) {
|
|
197
206
|
ctx.print('Remote runner registry is not available in this runtime.');
|
|
198
207
|
return;
|
|
199
208
|
}
|
|
200
209
|
const remoteRegistry = ctx.ops.remoteRuntime;
|
|
201
|
-
const sub =
|
|
210
|
+
const sub = commandArgs[0] ?? 'status';
|
|
202
211
|
if (sub === 'status') {
|
|
203
212
|
const remote = requireReadModels(ctx).remote.getSnapshot();
|
|
204
213
|
ctx.print([
|
|
@@ -217,10 +226,14 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
|
|
|
217
226
|
return;
|
|
218
227
|
}
|
|
219
228
|
if (sub === 'assign') {
|
|
220
|
-
const poolId =
|
|
221
|
-
const runnerId =
|
|
229
|
+
const poolId = commandArgs[1];
|
|
230
|
+
const runnerId = commandArgs[2];
|
|
222
231
|
if (!poolId || !runnerId) {
|
|
223
|
-
ctx.print('Usage: /bridge assign <pool> <runner>');
|
|
232
|
+
ctx.print('Usage: /bridge assign <pool> <runner> --yes');
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (!parsed.yes) {
|
|
236
|
+
requireYesFlag(ctx, `assign bridge runner ${runnerId} to pool ${poolId}`, '/bridge assign <pool> <runner> --yes');
|
|
224
237
|
return;
|
|
225
238
|
}
|
|
226
239
|
const pool = remoteRegistry.assignRunnerToPool(poolId, runnerId);
|
|
@@ -232,7 +245,7 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
|
|
|
232
245
|
return;
|
|
233
246
|
}
|
|
234
247
|
if (sub === 'runner') {
|
|
235
|
-
const runnerId =
|
|
248
|
+
const runnerId = commandArgs[1];
|
|
236
249
|
if (!runnerId) {
|
|
237
250
|
ctx.print('Usage: /bridge runner <id>');
|
|
238
251
|
return;
|
|
@@ -253,7 +266,7 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
|
|
|
253
266
|
return;
|
|
254
267
|
}
|
|
255
268
|
if (sub === 'review') {
|
|
256
|
-
const artifactId =
|
|
269
|
+
const artifactId = commandArgs[1];
|
|
257
270
|
if (!artifactId) {
|
|
258
271
|
ctx.print('Usage: /bridge review <artifactId>');
|
|
259
272
|
return;
|
|
@@ -263,14 +276,18 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
|
|
|
263
276
|
return;
|
|
264
277
|
}
|
|
265
278
|
if (sub === 'export') {
|
|
266
|
-
const artifactId =
|
|
279
|
+
const artifactId = commandArgs[1];
|
|
267
280
|
if (!artifactId) {
|
|
268
|
-
ctx.print('Usage: /bridge export <artifactId> [path]');
|
|
281
|
+
ctx.print('Usage: /bridge export <artifactId> [path] --yes');
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (!parsed.yes) {
|
|
285
|
+
requireYesFlag(ctx, `export bridge artifact ${artifactId}`, '/bridge export <artifactId> [path] --yes');
|
|
269
286
|
return;
|
|
270
287
|
}
|
|
271
288
|
const exported = await remoteRegistry.exportArtifact(
|
|
272
289
|
artifactId,
|
|
273
|
-
|
|
290
|
+
commandArgs[2] ? shellPaths.resolveWorkspacePath(commandArgs[2]) : undefined,
|
|
274
291
|
);
|
|
275
292
|
if (!exported) {
|
|
276
293
|
ctx.print(`Unknown remote artifact: ${artifactId}`);
|
|
@@ -280,26 +297,32 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
|
|
|
280
297
|
return;
|
|
281
298
|
}
|
|
282
299
|
if (sub === 'import') {
|
|
283
|
-
const pathArg =
|
|
300
|
+
const pathArg = commandArgs[1];
|
|
284
301
|
if (!pathArg) {
|
|
285
|
-
ctx.print('Usage: /bridge import <path>');
|
|
302
|
+
ctx.print('Usage: /bridge import <path> --yes');
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (!parsed.yes) {
|
|
306
|
+
requireYesFlag(ctx, `import bridge artifact from ${pathArg}`, '/bridge import <path> --yes');
|
|
286
307
|
return;
|
|
287
308
|
}
|
|
288
309
|
const artifact = await remoteRegistry.importArtifact(shellPaths.resolveWorkspacePath(pathArg));
|
|
289
310
|
ctx.print(`Imported remote bridge artifact ${artifact.id} for runner ${artifact.runnerId}.`);
|
|
290
311
|
return;
|
|
291
312
|
}
|
|
292
|
-
ctx.print('Usage: /bridge [status|pools|assign <pool> <runner
|
|
313
|
+
ctx.print('Usage: /bridge [status|pools|assign <pool> <runner> --yes|runner <id>|review <artifactId>|export <artifactId> [path] --yes|import <path> --yes]');
|
|
293
314
|
},
|
|
294
315
|
});
|
|
295
316
|
|
|
296
317
|
registry.register({
|
|
297
318
|
name: 'release',
|
|
298
319
|
description: 'Package certification and release-readiness operations',
|
|
299
|
-
usage: '[review|checklist|bundle export <path
|
|
320
|
+
usage: '[review|checklist|bundle export <path> --yes|bundle inspect <path>]',
|
|
300
321
|
handler(args, ctx) {
|
|
322
|
+
const parsed = stripYesFlag(args);
|
|
323
|
+
const commandArgs = [...parsed.rest];
|
|
301
324
|
const shellPaths = requireShellPaths(ctx);
|
|
302
|
-
const sub =
|
|
325
|
+
const sub = commandArgs[0] ?? 'review';
|
|
303
326
|
if (sub === 'review') {
|
|
304
327
|
const bundle = buildReleaseBundle(ctx);
|
|
305
328
|
ctx.print([
|
|
@@ -319,20 +342,24 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
|
|
|
319
342
|
' 1. Run /setup review and /setup doctor',
|
|
320
343
|
' 2. Run /security review and /trust review',
|
|
321
344
|
' 3. Run /policy preflight and /policy simulate',
|
|
322
|
-
' 4. Run /eval gate <suite> for required certification suites',
|
|
345
|
+
' 4. Run /eval gate <suite> --yes for required certification suites',
|
|
323
346
|
' 5. Review /incident latest and /bridge status',
|
|
324
|
-
' 6. Export /release bundle export <path> for release evidence',
|
|
347
|
+
' 6. Export /release bundle export <path> --yes for release evidence',
|
|
325
348
|
].join('\n'));
|
|
326
349
|
return;
|
|
327
350
|
}
|
|
328
351
|
if (sub === 'bundle') {
|
|
329
|
-
const mode =
|
|
330
|
-
const pathArg =
|
|
352
|
+
const mode = commandArgs[1];
|
|
353
|
+
const pathArg = commandArgs[2];
|
|
331
354
|
if ((mode === 'export' || mode === 'inspect') && !pathArg) {
|
|
332
|
-
ctx.print(`Usage: /release bundle ${mode} <path
|
|
355
|
+
ctx.print(`Usage: /release bundle ${mode} <path>${mode === 'export' ? ' --yes' : ''}`);
|
|
333
356
|
return;
|
|
334
357
|
}
|
|
335
358
|
if (mode === 'export') {
|
|
359
|
+
if (!parsed.yes) {
|
|
360
|
+
requireYesFlag(ctx, `export release bundle to ${pathArg}`, '/release bundle export <path> --yes');
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
336
363
|
const bundle = buildReleaseBundle(ctx);
|
|
337
364
|
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
338
365
|
mkdirSync(dirname(targetPath), { recursive: true });
|
|
@@ -345,7 +372,7 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
|
|
|
345
372
|
return;
|
|
346
373
|
}
|
|
347
374
|
}
|
|
348
|
-
ctx.print('Usage: /release [review|checklist|bundle export <path
|
|
375
|
+
ctx.print('Usage: /release [review|checklist|bundle export <path> --yes|bundle inspect <path>]');
|
|
349
376
|
},
|
|
350
377
|
});
|
|
351
378
|
}
|
|
@@ -4,6 +4,7 @@ import type { CommandRegistry } from '../command-registry.ts';
|
|
|
4
4
|
import type { ProfileBundleEntry, ProfileSyncBundle } from '@/runtime/index.ts';
|
|
5
5
|
import { recordSettingsSyncEvent, recordSettingsSyncFailure } from '@/runtime/index.ts';
|
|
6
6
|
import { requireProfileManager, requireShellPaths } from './runtime-services.ts';
|
|
7
|
+
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
7
8
|
|
|
8
9
|
function inspectProfileSyncBundle(bundle: ProfileSyncBundle): string {
|
|
9
10
|
return [
|
|
@@ -18,11 +19,13 @@ export function registerProfileSyncRuntimeCommands(registry: CommandRegistry): v
|
|
|
18
19
|
registry.register({
|
|
19
20
|
name: 'profilesync',
|
|
20
21
|
description: 'Export, import, and inspect profile sync bundles',
|
|
21
|
-
usage: '[list|export <path
|
|
22
|
+
usage: '[list|export <path> --yes|inspect <path>|import <path> [prefix] --yes]',
|
|
22
23
|
handler(args, ctx) {
|
|
24
|
+
const parsed = stripYesFlag(args);
|
|
25
|
+
const commandArgs = [...parsed.rest];
|
|
23
26
|
const shellPaths = requireShellPaths(ctx);
|
|
24
27
|
const controlPlaneConfigDir = ctx.platform.configManager.getControlPlaneConfigDir();
|
|
25
|
-
const sub =
|
|
28
|
+
const sub = commandArgs[0] ?? 'list';
|
|
26
29
|
const pm = requireProfileManager(ctx);
|
|
27
30
|
if (sub === 'list') {
|
|
28
31
|
const profiles = pm.list();
|
|
@@ -34,14 +37,18 @@ export function registerProfileSyncRuntimeCommands(registry: CommandRegistry): v
|
|
|
34
37
|
return;
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
const pathArg =
|
|
40
|
+
const pathArg = commandArgs[1];
|
|
38
41
|
if (!pathArg) {
|
|
39
|
-
ctx.print(`Usage: /profilesync ${sub} <path>${sub === 'import' ? ' [prefix]' : ''}`);
|
|
42
|
+
ctx.print(`Usage: /profilesync ${sub} <path>${sub === 'import' ? ' [prefix]' : ''}${sub === 'export' || sub === 'import' ? ' --yes' : ''}`);
|
|
40
43
|
return;
|
|
41
44
|
}
|
|
42
45
|
const targetPath = shellPaths.resolveWorkspacePath(pathArg);
|
|
43
46
|
|
|
44
47
|
if (sub === 'export') {
|
|
48
|
+
if (!parsed.yes) {
|
|
49
|
+
requireYesFlag(ctx, `export profile sync bundle to ${pathArg}`, '/profilesync export <path> --yes');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
45
52
|
const profiles = pm.list().map((profile) => {
|
|
46
53
|
const loaded = pm.load(profile.name);
|
|
47
54
|
return {
|
|
@@ -75,8 +82,12 @@ export function registerProfileSyncRuntimeCommands(registry: CommandRegistry): v
|
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
if (sub === 'import') {
|
|
85
|
+
if (!parsed.yes) {
|
|
86
|
+
requireYesFlag(ctx, `import profile sync bundle from ${pathArg}`, '/profilesync import <path> [prefix] --yes');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
78
89
|
const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as ProfileSyncBundle;
|
|
79
|
-
const prefix =
|
|
90
|
+
const prefix = commandArgs[2]?.trim() ?? '';
|
|
80
91
|
for (const entry of bundle.profiles) {
|
|
81
92
|
const name = prefix ? `${prefix}-${entry.name}` : entry.name;
|
|
82
93
|
pm.save(name, entry.data);
|
|
@@ -93,7 +104,7 @@ export function registerProfileSyncRuntimeCommands(registry: CommandRegistry): v
|
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
recordSettingsSyncFailure('profiles', `unsupported subcommand: ${sub}`, controlPlaneConfigDir);
|
|
96
|
-
ctx.print('Usage: /profilesync [list|export <path
|
|
107
|
+
ctx.print('Usage: /profilesync [list|export <path> --yes|inspect <path>|import <path> [prefix] --yes]');
|
|
97
108
|
},
|
|
98
109
|
});
|
|
99
110
|
}
|
|
@@ -6,23 +6,30 @@ import { VALID_CLASSES, VALID_SCOPES, isValidClass, isValidScope, resolveBundleP
|
|
|
6
6
|
import { requireShellPaths } from './runtime-services.ts';
|
|
7
7
|
import { getMemoryApi } from './recall-query.ts';
|
|
8
8
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
9
|
+
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
9
10
|
|
|
10
11
|
export function handleRecallExport(args: string[], context: CommandContext): void {
|
|
12
|
+
const parsed = stripYesFlag(args);
|
|
13
|
+
const commandArgs = [...parsed.rest];
|
|
11
14
|
const memory = getMemoryApi(context);
|
|
12
15
|
if (!memory) {
|
|
13
16
|
return;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
const pathArg =
|
|
19
|
+
const pathArg = commandArgs[0];
|
|
17
20
|
if (!pathArg) {
|
|
18
|
-
context.print('[recall] Usage: /recall export <path> [--scope <scope>] [--cls <class>]');
|
|
21
|
+
context.print('[recall] Usage: /recall export <path> [--scope <scope>] [--cls <class>] --yes');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!parsed.yes) {
|
|
25
|
+
requireYesFlag(context, `export durable memory bundle to ${pathArg}`, '/recall export <path> [--scope <scope>] [--cls <class>] --yes');
|
|
19
26
|
return;
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
const filter: MemorySearchFilter = {};
|
|
23
|
-
const scopeIdx =
|
|
24
|
-
if (scopeIdx !== -1 &&
|
|
25
|
-
const scope =
|
|
30
|
+
const scopeIdx = commandArgs.indexOf('--scope');
|
|
31
|
+
if (scopeIdx !== -1 && commandArgs[scopeIdx + 1]) {
|
|
32
|
+
const scope = commandArgs[scopeIdx + 1];
|
|
26
33
|
if (!isValidScope(scope)) {
|
|
27
34
|
context.print(`[recall] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
|
|
28
35
|
return;
|
|
@@ -30,9 +37,9 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
|
|
|
30
37
|
filter.scope = scope;
|
|
31
38
|
}
|
|
32
39
|
|
|
33
|
-
const clsIdx =
|
|
34
|
-
if (clsIdx !== -1 &&
|
|
35
|
-
const cls =
|
|
40
|
+
const clsIdx = commandArgs.indexOf('--cls');
|
|
41
|
+
if (clsIdx !== -1 && commandArgs[clsIdx + 1]) {
|
|
42
|
+
const cls = commandArgs[clsIdx + 1];
|
|
36
43
|
if (!isValidClass(cls)) {
|
|
37
44
|
context.print(`[recall] Unknown class "${cls}". Valid: ${VALID_CLASSES.join(', ')}`);
|
|
38
45
|
return;
|
|
@@ -48,14 +55,20 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
|
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
export async function handleRecallImport(args: string[], context: CommandContext): Promise<void> {
|
|
58
|
+
const parsed = stripYesFlag(args);
|
|
59
|
+
const commandArgs = [...parsed.rest];
|
|
51
60
|
const memory = getMemoryApi(context);
|
|
52
61
|
if (!memory) {
|
|
53
62
|
return;
|
|
54
63
|
}
|
|
55
64
|
|
|
56
|
-
const pathArg =
|
|
65
|
+
const pathArg = commandArgs[0];
|
|
57
66
|
if (!pathArg) {
|
|
58
|
-
context.print('[recall] Usage: /recall import <path>');
|
|
67
|
+
context.print('[recall] Usage: /recall import <path> --yes');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (!parsed.yes) {
|
|
71
|
+
requireYesFlag(context, `import durable memory bundle from ${pathArg}`, '/recall import <path> --yes');
|
|
59
72
|
return;
|
|
60
73
|
}
|
|
61
74
|
|
|
@@ -85,17 +98,23 @@ function inspectBundle(bundle: MemoryBundle): string {
|
|
|
85
98
|
}
|
|
86
99
|
|
|
87
100
|
export function handleRecallHandoffExport(args: string[], context: CommandContext): void {
|
|
101
|
+
const parsed = stripYesFlag(args);
|
|
102
|
+
const commandArgs = [...parsed.rest];
|
|
88
103
|
const memory = getMemoryApi(context);
|
|
89
104
|
if (!memory) {
|
|
90
105
|
return;
|
|
91
106
|
}
|
|
92
|
-
const pathArg =
|
|
107
|
+
const pathArg = commandArgs[0];
|
|
93
108
|
if (!pathArg) {
|
|
94
|
-
context.print('[recall] Usage: /recall handoff-export <path> [--scope <scope>]');
|
|
109
|
+
context.print('[recall] Usage: /recall handoff-export <path> [--scope <scope>] --yes');
|
|
95
110
|
return;
|
|
96
111
|
}
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
if (!parsed.yes) {
|
|
113
|
+
requireYesFlag(context, `export memory handoff bundle to ${pathArg}`, '/recall handoff-export <path> [--scope <scope>] --yes');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const scopeIdx = commandArgs.indexOf('--scope');
|
|
117
|
+
const scopeRaw = scopeIdx !== -1 ? commandArgs[scopeIdx + 1] : 'team';
|
|
99
118
|
if (!scopeRaw || !isValidScope(scopeRaw)) {
|
|
100
119
|
context.print(`[recall] Unknown scope "${scopeRaw ?? ''}". Valid: ${VALID_SCOPES.join(', ')}`);
|
|
101
120
|
return;
|
|
@@ -123,10 +142,12 @@ export function handleRecallHandoffInspect(args: string[], context: CommandConte
|
|
|
123
142
|
}
|
|
124
143
|
|
|
125
144
|
export async function handleRecallHandoffImport(args: string[], context: CommandContext): Promise<void> {
|
|
126
|
-
const
|
|
145
|
+
const parsed = stripYesFlag(args);
|
|
146
|
+
const commandArgs = [...parsed.rest];
|
|
147
|
+
const pathArg = commandArgs[0];
|
|
127
148
|
if (!pathArg) {
|
|
128
|
-
context.print('[recall] Usage: /recall handoff-import <path>');
|
|
149
|
+
context.print('[recall] Usage: /recall handoff-import <path> --yes');
|
|
129
150
|
return;
|
|
130
151
|
}
|
|
131
|
-
await handleRecallImport([pathArg], context);
|
|
152
|
+
await handleRecallImport([pathArg, ...(parsed.yes ? ['--yes'] : [])], context);
|
|
132
153
|
}
|
|
@@ -2,6 +2,7 @@ import type { CommandContext } from '../command-registry.ts';
|
|
|
2
2
|
import type { MemoryApi } from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
3
3
|
import type { MemorySearchFilter } from '@pellux/goodvibes-sdk/platform/state';
|
|
4
4
|
import { VALID_CLASSES, VALID_SCOPES, isValidClass, isValidScope } from './recall-shared.ts';
|
|
5
|
+
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
5
6
|
|
|
6
7
|
export function getMemoryApi(context: CommandContext): MemoryApi | null {
|
|
7
8
|
const memoryApi = context.clients?.agentKnowledgeApi?.memory;
|
|
@@ -159,9 +160,14 @@ export async function handleRecallLink(args: string[], context: CommandContext):
|
|
|
159
160
|
if (!memory) {
|
|
160
161
|
return;
|
|
161
162
|
}
|
|
162
|
-
const
|
|
163
|
+
const parsed = stripYesFlag(args);
|
|
164
|
+
const [fromId, toId, relation] = parsed.rest;
|
|
163
165
|
if (!fromId || !toId || !relation) {
|
|
164
|
-
context.print('[recall] Usage: /recall link <fromId> <toId> <relation>');
|
|
166
|
+
context.print('[recall] Usage: /recall link <fromId> <toId> <relation> --yes');
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (!parsed.yes) {
|
|
170
|
+
requireYesFlag(context, `link memory records ${fromId} and ${toId}`, '/recall link <fromId> <toId> <relation> --yes');
|
|
165
171
|
return;
|
|
166
172
|
}
|
|
167
173
|
const link = await memory.link(fromId, toId, relation);
|
|
@@ -177,9 +183,14 @@ export function handleRecallRemove(args: string[], context: CommandContext): voi
|
|
|
177
183
|
if (!memory) {
|
|
178
184
|
return;
|
|
179
185
|
}
|
|
180
|
-
const
|
|
186
|
+
const parsed = stripYesFlag(args);
|
|
187
|
+
const id = parsed.rest[0];
|
|
181
188
|
if (!id) {
|
|
182
|
-
context.print('[recall] Usage: /recall remove <id>');
|
|
189
|
+
context.print('[recall] Usage: /recall remove <id> --yes');
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (!parsed.yes) {
|
|
193
|
+
requireYesFlag(context, `delete durable memory record ${id}`, '/recall remove <id> --yes');
|
|
183
194
|
return;
|
|
184
195
|
}
|
|
185
196
|
const removed = memory.delete(id);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CommandContext } from '../command-registry.ts';
|
|
2
2
|
import { VALID_REVIEW_STATES, VALID_SCOPES, isValidReviewState, isValidScope } from './recall-shared.ts';
|
|
3
3
|
import { getMemoryApi } from './recall-query.ts';
|
|
4
|
+
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
4
5
|
|
|
5
6
|
export function handleRecallQueue(args: string[], context: CommandContext): void {
|
|
6
7
|
const memory = getMemoryApi(context);
|
|
@@ -83,10 +84,15 @@ export function handleRecallPromote(args: string[], context: CommandContext): vo
|
|
|
83
84
|
if (!memory) {
|
|
84
85
|
return;
|
|
85
86
|
}
|
|
86
|
-
const
|
|
87
|
-
const
|
|
87
|
+
const parsed = stripYesFlag(args);
|
|
88
|
+
const id = parsed.rest[0];
|
|
89
|
+
const scope = parsed.rest[1];
|
|
88
90
|
if (!id || !scope || !isValidScope(scope)) {
|
|
89
|
-
context.print(`[recall] Usage: /recall promote <id> <${VALID_SCOPES.join('|')}
|
|
91
|
+
context.print(`[recall] Usage: /recall promote <id> <${VALID_SCOPES.join('|')}> --yes`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (!parsed.yes) {
|
|
95
|
+
requireYesFlag(context, `promote durable memory record ${id} to ${scope} scope`, '/recall promote <id> <scope> --yes');
|
|
90
96
|
return;
|
|
91
97
|
}
|
|
92
98
|
const record = memory.update(id, { scope });
|