@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
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { CommandRegistry } from '../command-registry.ts';
|
|
2
|
+
import type { ProfileData } from '@pellux/goodvibes-sdk/platform/profiles';
|
|
2
3
|
import { ToolContractVerifier } from '@/runtime/index.ts';
|
|
3
4
|
import type { ReplaySnapshotInput } from '@/runtime/index.ts';
|
|
4
5
|
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
5
6
|
import { registerOperatorPanelCommand } from './operator-panel-runtime.ts';
|
|
6
7
|
import { requireProfileManager, requireReplayEngine } from './runtime-services.ts';
|
|
7
8
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
9
|
+
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
8
10
|
|
|
9
11
|
function printOpsMutationBlocked(print: (text: string) => void, target: string): void {
|
|
10
12
|
print([
|
|
@@ -76,15 +78,71 @@ export function registerOperatorRuntimeCommands(registry: CommandRegistry): void
|
|
|
76
78
|
registry.register({
|
|
77
79
|
name: 'profiles',
|
|
78
80
|
aliases: ['profile'],
|
|
79
|
-
description: 'Browse and
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
description: 'Browse, save, and delete config profiles',
|
|
82
|
+
usage: '[list|open|save <name> --yes|delete <name> --yes]',
|
|
83
|
+
argsHint: '[list|open|save --yes|delete --yes]',
|
|
84
|
+
handler(args, ctx) {
|
|
85
|
+
const parsed = stripYesFlag(args);
|
|
86
|
+
const sub = parsed.rest[0] ?? 'open';
|
|
87
|
+
const profileManager = requireProfileManager(ctx);
|
|
88
|
+
if (sub === 'open') {
|
|
89
|
+
if (ctx.openProfilePicker) {
|
|
90
|
+
ctx.openProfilePicker();
|
|
91
|
+
} else {
|
|
92
|
+
const profiles = profileManager.list();
|
|
93
|
+
if (profiles.length === 0) ctx.print('No profiles saved. Use /profiles save <name> --yes to save the current settings as a profile.');
|
|
94
|
+
else ctx.print(['Saved profiles:', ...profiles.map(p => ` ${p.name}`)].join('\n'));
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (sub === 'list') {
|
|
99
|
+
const profiles = profileManager.list();
|
|
100
|
+
if (profiles.length === 0) ctx.print('No profiles saved. Use /profiles save <name> --yes to save the current settings as a profile.');
|
|
86
101
|
else ctx.print(['Saved profiles:', ...profiles.map(p => ` ${p.name}`)].join('\n'));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (sub === 'save') {
|
|
105
|
+
const name = parsed.rest[1];
|
|
106
|
+
if (!name) {
|
|
107
|
+
ctx.print('Usage: /profiles save <name> --yes');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (!parsed.yes) {
|
|
111
|
+
requireYesFlag(ctx, `save config profile ${name}`, '/profiles save <name> --yes');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const all = ctx.platform.configManager.getAll();
|
|
115
|
+
const data: ProfileData = {
|
|
116
|
+
display: { ...all.display },
|
|
117
|
+
provider: {
|
|
118
|
+
model: all.provider.model,
|
|
119
|
+
reasoningEffort: all.provider.reasoningEffort,
|
|
120
|
+
},
|
|
121
|
+
behavior: { ...all.behavior },
|
|
122
|
+
};
|
|
123
|
+
profileManager.save(name, data);
|
|
124
|
+
ctx.print(`Profile saved: ${name}`);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (sub === 'delete' || sub === 'remove') {
|
|
128
|
+
const name = parsed.rest[1];
|
|
129
|
+
if (!name) {
|
|
130
|
+
ctx.print('Usage: /profiles delete <name> --yes');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (!parsed.yes) {
|
|
134
|
+
requireYesFlag(ctx, `delete config profile ${name}`, '/profiles delete <name> --yes');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const deleted = profileManager.delete(name);
|
|
138
|
+
ctx.print(deleted ? `Profile deleted: ${name}` : `Profile not found: ${name}`);
|
|
139
|
+
return;
|
|
87
140
|
}
|
|
141
|
+
if (args.length === 0 && ctx.openProfilePicker) {
|
|
142
|
+
ctx.openProfilePicker();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
ctx.print('Usage: /profiles [list|open|save <name> --yes|delete <name> --yes]');
|
|
88
146
|
},
|
|
89
147
|
});
|
|
90
148
|
|
|
@@ -103,7 +161,7 @@ export function registerOperatorRuntimeCommands(registry: CommandRegistry): void
|
|
|
103
161
|
name: 'mode',
|
|
104
162
|
aliases: ['hitl'],
|
|
105
163
|
description: 'Manage HITL UX notification mode (quiet/balanced/operator)',
|
|
106
|
-
usage: '[quiet|balanced|operator|show|set-domain <domain> <verbosity>]',
|
|
164
|
+
usage: '[quiet|balanced|operator --yes|show|set-domain <domain> <verbosity> --yes]',
|
|
107
165
|
argsHint: '[preset|show|set-domain]',
|
|
108
166
|
handler(args, ctx) {
|
|
109
167
|
const mgr = ctx.ops.modeManager;
|
|
@@ -111,9 +169,15 @@ export function registerOperatorRuntimeCommands(registry: CommandRegistry): void
|
|
|
111
169
|
ctx.print('Interaction mode manager is not available in this runtime.');
|
|
112
170
|
return;
|
|
113
171
|
}
|
|
114
|
-
const
|
|
172
|
+
const parsed = stripYesFlag(args);
|
|
173
|
+
const commandArgs = [...parsed.rest];
|
|
174
|
+
const sub = commandArgs[0] ?? 'show';
|
|
115
175
|
|
|
116
176
|
if (sub === 'quiet' || sub === 'balanced' || sub === 'operator') {
|
|
177
|
+
if (!parsed.yes) {
|
|
178
|
+
requireYesFlag(ctx, `set HITL mode to ${sub}`, '/mode <quiet|balanced|operator> --yes');
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
117
181
|
const newMode = sub as 'quiet' | 'balanced' | 'operator';
|
|
118
182
|
mgr.setHITLMode(newMode);
|
|
119
183
|
try {
|
|
@@ -156,29 +220,33 @@ export function registerOperatorRuntimeCommands(registry: CommandRegistry): void
|
|
|
156
220
|
}
|
|
157
221
|
|
|
158
222
|
if (sub === 'set-domain') {
|
|
159
|
-
const domain =
|
|
160
|
-
const verbosity =
|
|
223
|
+
const domain = commandArgs[1];
|
|
224
|
+
const verbosity = commandArgs[2];
|
|
161
225
|
if (!domain || !verbosity) {
|
|
162
|
-
ctx.print('Usage: /mode set-domain <domain> <minimal|normal|verbose>');
|
|
226
|
+
ctx.print('Usage: /mode set-domain <domain> <minimal|normal|verbose> --yes');
|
|
163
227
|
return;
|
|
164
228
|
}
|
|
165
229
|
if (verbosity !== 'minimal' && verbosity !== 'normal' && verbosity !== 'verbose') {
|
|
166
230
|
ctx.print(`Invalid verbosity "${verbosity}". Valid values: minimal, normal, verbose`);
|
|
167
231
|
return;
|
|
168
232
|
}
|
|
233
|
+
if (!parsed.yes) {
|
|
234
|
+
requireYesFlag(ctx, `set HITL verbosity for ${domain}`, '/mode set-domain <domain> <minimal|normal|verbose> --yes');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
169
237
|
mgr.setDomainVerbosity(domain, verbosity as 'minimal' | 'normal' | 'verbose');
|
|
170
238
|
ctx.print(`Domain "${domain}" verbosity set to: ${verbosity}`);
|
|
171
239
|
return;
|
|
172
240
|
}
|
|
173
241
|
|
|
174
242
|
ctx.print(
|
|
175
|
-
'Usage: /mode [quiet|balanced|operator|show|set-domain <domain> <verbosity>]\n'
|
|
243
|
+
'Usage: /mode [quiet|balanced|operator --yes|show|set-domain <domain> <verbosity> --yes]\n'
|
|
176
244
|
+ ' /mode — show current mode and settings\n'
|
|
177
245
|
+ ' /mode show — show current mode and settings\n'
|
|
178
|
-
+ ' /mode quiet
|
|
179
|
-
+ ' /mode balanced
|
|
180
|
-
+ ' /mode operator
|
|
181
|
-
+ ' /mode set-domain <d> <v>
|
|
246
|
+
+ ' /mode quiet --yes — suppress all non-critical notifications\n'
|
|
247
|
+
+ ' /mode balanced --yes — surface warnings, batch info noise (default)\n'
|
|
248
|
+
+ ' /mode operator --yes — full verbosity, no suppression\n'
|
|
249
|
+
+ ' /mode set-domain <d> <v> --yes — per-domain verbosity override (minimal|normal|verbose)'
|
|
182
250
|
);
|
|
183
251
|
},
|
|
184
252
|
});
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
7
7
|
import type { CommandRegistry } from '../command-registry.ts';
|
|
8
8
|
import { requirePlanManager, requireSessionLineageTracker } from './runtime-services.ts';
|
|
9
|
+
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
9
10
|
|
|
10
11
|
function recordNextQuestion(
|
|
11
12
|
state: Partial<ProjectPlanningState>,
|
|
@@ -51,15 +52,21 @@ export function registerPlanningRuntimeCommands(registry: CommandRegistry): void
|
|
|
51
52
|
registry.register({
|
|
52
53
|
name: 'plan',
|
|
53
54
|
description: 'Inspect or seed Agent workspace planning state',
|
|
54
|
-
usage: '[panel | approve | list | show <id> | mode | explain | override <strategy> | status | clear | <planning goal>]',
|
|
55
|
+
usage: '[panel | approve --yes | list | show <id> | mode | explain | override <strategy> --yes | status | clear --yes | <planning goal>]',
|
|
55
56
|
argsHint: '[panel|approve|status|<goal>]',
|
|
56
57
|
async handler(args, ctx) {
|
|
57
58
|
const planManager = requirePlanManager(ctx);
|
|
58
59
|
const sessionLineageTracker = requireSessionLineageTracker(ctx);
|
|
59
60
|
const plannerSubs = ['mode', 'explain', 'override', 'status', 'clear'];
|
|
60
61
|
if (args.length > 0 && plannerSubs.includes(args[0].toLowerCase())) {
|
|
62
|
+
const parsed = stripYesFlag(args);
|
|
63
|
+
const subcommand = parsed.rest[0]?.toLowerCase() ?? '';
|
|
64
|
+
if ((subcommand === 'override' || subcommand === 'clear') && !parsed.yes) {
|
|
65
|
+
requireYesFlag(ctx, `${subcommand} planner runtime state`, `/plan ${subcommand}${subcommand === 'override' ? ' <strategy>' : ''} --yes`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
61
68
|
const result = ctx.ops.planRuntime
|
|
62
|
-
? ctx.ops.planRuntime(args[0],
|
|
69
|
+
? ctx.ops.planRuntime(parsed.rest[0] ?? args[0], parsed.rest.slice(1))
|
|
63
70
|
: { ok: false, output: 'Plan runtime bridge is not available in this runtime.' };
|
|
64
71
|
ctx.print(result.output);
|
|
65
72
|
return;
|
|
@@ -109,6 +116,11 @@ export function registerPlanningRuntimeCommands(registry: CommandRegistry): void
|
|
|
109
116
|
}
|
|
110
117
|
|
|
111
118
|
if (args[0] === 'approve') {
|
|
119
|
+
const parsed = stripYesFlag(args);
|
|
120
|
+
if (!parsed.yes) {
|
|
121
|
+
requireYesFlag(ctx, 'approve project planning state for execution', '/plan approve --yes');
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
112
124
|
if (!projectPlanningService || !projectId) {
|
|
113
125
|
ctx.print('Project planning service is not available in this runtime.');
|
|
114
126
|
return;
|
|
@@ -6,6 +6,7 @@ import { listBuiltinSubscriptionProviders } from '@pellux/goodvibes-sdk/platform
|
|
|
6
6
|
import { handleLocalAuthCommand } from './local-auth-runtime.ts';
|
|
7
7
|
import { buildAuthInspectionSnapshot, inspectProviderAuth } from '@/runtime/index.ts';
|
|
8
8
|
import { requireProfileManager, requireSecretsManager, requireServiceRegistry, requireShellPaths, requireSubscriptionManager } from './runtime-services.ts';
|
|
9
|
+
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
9
10
|
|
|
10
11
|
interface InstallBundle {
|
|
11
12
|
readonly version: 1;
|
|
@@ -81,61 +82,79 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
81
82
|
registry.register({
|
|
82
83
|
name: 'login',
|
|
83
84
|
description: 'Front-door login flow for provider subscriptions and local service sessions',
|
|
84
|
-
usage: '[provider <name> start|finish <code
|
|
85
|
+
usage: '[provider <name> start|finish <code> --yes|service <daemon|listener> <baseUrl> <username> <password> [secretKey] --yes]',
|
|
85
86
|
async handler(args, ctx) {
|
|
87
|
+
const parsed = stripYesFlag(args);
|
|
88
|
+
const commandArgs = [...parsed.rest];
|
|
86
89
|
const shellPaths = requireShellPaths(ctx);
|
|
87
|
-
const target = (
|
|
90
|
+
const target = (commandArgs[0] ?? '').toLowerCase();
|
|
88
91
|
if (target === 'provider') {
|
|
89
|
-
const provider =
|
|
90
|
-
const mode =
|
|
92
|
+
const provider = commandArgs[1];
|
|
93
|
+
const mode = commandArgs[2]?.toLowerCase();
|
|
91
94
|
if (!provider || !mode) {
|
|
92
|
-
ctx.print('Usage: /login provider <name> start|finish <code>');
|
|
95
|
+
ctx.print('Usage: /login provider <name> start|finish <code> --yes');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (!parsed.yes) {
|
|
99
|
+
requireYesFlag(ctx, `${mode} provider subscription login for ${provider}`, '/login provider <name> start|finish <code> --yes');
|
|
93
100
|
return;
|
|
94
101
|
}
|
|
95
102
|
if (ctx.executeCommand) {
|
|
96
|
-
await ctx.executeCommand('subscription', ['login', provider, mode, ...
|
|
103
|
+
await ctx.executeCommand('subscription', ['login', provider, mode, ...commandArgs.slice(3), '--yes']);
|
|
97
104
|
return;
|
|
98
105
|
}
|
|
99
|
-
ctx.print(`Use /subscription login ${provider} ${mode}${
|
|
106
|
+
ctx.print(`Use /subscription login ${provider} ${mode}${commandArgs[3] ? ` ${commandArgs[3]}` : ''} --yes`);
|
|
100
107
|
return;
|
|
101
108
|
}
|
|
102
109
|
if (target === 'service') {
|
|
110
|
+
if (!parsed.yes) {
|
|
111
|
+
requireYesFlag(ctx, 'store a local service session token', '/login service <daemon|listener> <baseUrl> <username> <password> [secretKey] --yes');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
103
114
|
if (ctx.executeCommand) {
|
|
104
|
-
await ctx.executeCommand('auth', ['login', ...
|
|
115
|
+
await ctx.executeCommand('auth', ['login', ...commandArgs.slice(1), '--yes']);
|
|
105
116
|
return;
|
|
106
117
|
}
|
|
107
|
-
ctx.print('Use /auth login <daemon|listener> <baseUrl> <username> <password> [secretKey]');
|
|
118
|
+
ctx.print('Use /auth login <daemon|listener> <baseUrl> <username> <password> [secretKey] --yes');
|
|
108
119
|
return;
|
|
109
120
|
}
|
|
110
|
-
ctx.print('Usage: /login [provider <name> start|finish <code
|
|
121
|
+
ctx.print('Usage: /login [provider <name> start|finish <code> --yes|service <daemon|listener> <baseUrl> <username> <password> [secretKey] --yes]');
|
|
111
122
|
},
|
|
112
123
|
});
|
|
113
124
|
|
|
114
125
|
registry.register({
|
|
115
126
|
name: 'logout',
|
|
116
127
|
description: 'Front-door logout flow for provider subscription sessions and supported overrides',
|
|
117
|
-
usage: 'provider <name>',
|
|
128
|
+
usage: 'provider <name> --yes',
|
|
118
129
|
async handler(args, ctx) {
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
130
|
+
const parsed = stripYesFlag(args);
|
|
131
|
+
const commandArgs = [...parsed.rest];
|
|
132
|
+
const target = (commandArgs[0] ?? '').toLowerCase();
|
|
133
|
+
if (target !== 'provider' || !commandArgs[1]) {
|
|
134
|
+
ctx.print('Usage: /logout provider <name> --yes');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (!parsed.yes) {
|
|
138
|
+
requireYesFlag(ctx, `log out provider subscription ${commandArgs[1]}`, '/logout provider <name> --yes');
|
|
122
139
|
return;
|
|
123
140
|
}
|
|
124
141
|
if (ctx.executeCommand) {
|
|
125
|
-
await ctx.executeCommand('subscription', ['logout',
|
|
142
|
+
await ctx.executeCommand('subscription', ['logout', commandArgs[1], '--yes']);
|
|
126
143
|
return;
|
|
127
144
|
}
|
|
128
|
-
ctx.print(`Use /subscription logout ${
|
|
145
|
+
ctx.print(`Use /subscription logout ${commandArgs[1]} --yes`);
|
|
129
146
|
},
|
|
130
147
|
});
|
|
131
148
|
|
|
132
149
|
registry.register({
|
|
133
150
|
name: 'install',
|
|
134
151
|
description: 'Review install posture and export portable install bundles',
|
|
135
|
-
usage: '[review|bundle export <path
|
|
152
|
+
usage: '[review|bundle export <path> --yes|bundle inspect <path>]',
|
|
136
153
|
async handler(args, ctx) {
|
|
154
|
+
const parsed = stripYesFlag(args);
|
|
155
|
+
const commandArgs = [...parsed.rest];
|
|
137
156
|
const shellPaths = requireShellPaths(ctx);
|
|
138
|
-
const sub =
|
|
157
|
+
const sub = commandArgs[0] ?? 'review';
|
|
139
158
|
if (sub === 'review') {
|
|
140
159
|
const profiles = requireProfileManager(ctx).list();
|
|
141
160
|
const secretKeys = await requireSecretsManager(ctx).list();
|
|
@@ -149,14 +168,18 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
149
168
|
return;
|
|
150
169
|
}
|
|
151
170
|
if (sub === 'bundle') {
|
|
152
|
-
const mode =
|
|
153
|
-
const pathArg =
|
|
171
|
+
const mode = commandArgs[1];
|
|
172
|
+
const pathArg = commandArgs[2];
|
|
154
173
|
if ((mode === 'export' || mode === 'inspect') && !pathArg) {
|
|
155
|
-
ctx.print(`Usage: /install bundle ${mode} <path
|
|
174
|
+
ctx.print(`Usage: /install bundle ${mode} <path>${mode === 'export' ? ' --yes' : ''}`);
|
|
156
175
|
return;
|
|
157
176
|
}
|
|
158
177
|
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
159
178
|
if (mode === 'export') {
|
|
179
|
+
if (!parsed.yes) {
|
|
180
|
+
requireYesFlag(ctx, `export install bundle to ${pathArg}`, '/install bundle export <path> --yes');
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
160
183
|
const profiles = requireProfileManager(ctx).list();
|
|
161
184
|
const secretKeys = await requireSecretsManager(ctx).list();
|
|
162
185
|
const bundle: InstallBundle = {
|
|
@@ -185,7 +208,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
185
208
|
return;
|
|
186
209
|
}
|
|
187
210
|
}
|
|
188
|
-
ctx.print('Usage: /install [review|bundle export <path
|
|
211
|
+
ctx.print('Usage: /install [review|bundle export <path> --yes|bundle inspect <path>]');
|
|
189
212
|
},
|
|
190
213
|
});
|
|
191
214
|
|
|
@@ -193,10 +216,12 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
193
216
|
name: 'update',
|
|
194
217
|
aliases: ['upgrade'],
|
|
195
218
|
description: 'Review update posture, choose release channel guidance, and package portable update bundles',
|
|
196
|
-
usage: '[review|channel <stable|preview
|
|
219
|
+
usage: '[review|channel <stable|preview> --yes|bundle export <path> --yes|bundle inspect <path>]',
|
|
197
220
|
handler(args, ctx) {
|
|
221
|
+
const parsed = stripYesFlag(args);
|
|
222
|
+
const commandArgs = [...parsed.rest];
|
|
198
223
|
const shellPaths = requireShellPaths(ctx);
|
|
199
|
-
const sub =
|
|
224
|
+
const sub = commandArgs[0] ?? 'review';
|
|
200
225
|
const subscriptions = requireSubscriptionManager(ctx);
|
|
201
226
|
const serviceRegistry = requireServiceRegistry(ctx);
|
|
202
227
|
const secretsManager = requireSecretsManager(ctx);
|
|
@@ -216,14 +241,18 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
216
241
|
` built-in subscription providers: ${builtinProviders.length}${builtinProviders.length > 0 ? ` (${builtinProviders.join(', ')})` : ''}`,
|
|
217
242
|
` active subscriptions: ${activeSubscriptions.length}${activeSubscriptions.length > 0 ? ` (${activeSubscriptions.join(', ')})` : ''}`,
|
|
218
243
|
` sandbox profile: ${sandboxProfile}`,
|
|
219
|
-
' use /update channel <stable|preview> to change release posture',
|
|
244
|
+
' use /update channel <stable|preview> --yes to change release posture',
|
|
220
245
|
].join('\n'));
|
|
221
246
|
return;
|
|
222
247
|
}
|
|
223
248
|
if (sub === 'channel') {
|
|
224
|
-
const channel =
|
|
249
|
+
const channel = commandArgs[1];
|
|
225
250
|
if (channel !== 'stable' && channel !== 'preview') {
|
|
226
|
-
ctx.print('Usage: /update channel <stable|preview>');
|
|
251
|
+
ctx.print('Usage: /update channel <stable|preview> --yes');
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (!parsed.yes) {
|
|
255
|
+
requireYesFlag(ctx, `set update channel to ${channel}`, '/update channel <stable|preview> --yes');
|
|
227
256
|
return;
|
|
228
257
|
}
|
|
229
258
|
ctx.platform.configManager.setDynamic('release.channel', channel);
|
|
@@ -231,14 +260,18 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
231
260
|
return;
|
|
232
261
|
}
|
|
233
262
|
if (sub === 'bundle') {
|
|
234
|
-
const mode =
|
|
235
|
-
const pathArg =
|
|
263
|
+
const mode = commandArgs[1];
|
|
264
|
+
const pathArg = commandArgs[2];
|
|
236
265
|
if ((mode === 'export' || mode === 'inspect') && !pathArg) {
|
|
237
|
-
ctx.print(`Usage: /update bundle ${mode} <path
|
|
266
|
+
ctx.print(`Usage: /update bundle ${mode} <path>${mode === 'export' ? ' --yes' : ''}`);
|
|
238
267
|
return;
|
|
239
268
|
}
|
|
240
269
|
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
241
270
|
if (mode === 'export') {
|
|
271
|
+
if (!parsed.yes) {
|
|
272
|
+
requireYesFlag(ctx, `export update bundle to ${pathArg}`, '/update bundle export <path> --yes');
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
242
275
|
const bundle: UpdateBundle = {
|
|
243
276
|
version: 1,
|
|
244
277
|
exportedAt: Date.now(),
|
|
@@ -262,17 +295,19 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
262
295
|
return;
|
|
263
296
|
}
|
|
264
297
|
}
|
|
265
|
-
ctx.print('Usage: /update [review|channel <stable|preview
|
|
298
|
+
ctx.print('Usage: /update [review|channel <stable|preview> --yes|bundle export <path> --yes|bundle inspect <path>]');
|
|
266
299
|
},
|
|
267
300
|
});
|
|
268
301
|
|
|
269
302
|
registry.register({
|
|
270
303
|
name: 'auth',
|
|
271
304
|
description: 'Review auth posture and exchange session login tokens with local services',
|
|
272
|
-
usage: '[review|show <provider>|repair <provider>|bundle export <path
|
|
305
|
+
usage: '[review|show <provider>|repair <provider>|bundle export <path> --yes|bundle inspect <path>|login <daemon|listener> <baseUrl> <username> <password> [secretKey] --yes|local <review|panel|add-user --yes|delete-user --yes|rotate-password --yes|revoke-session --yes|clear-bootstrap-file --yes>]',
|
|
273
306
|
async handler(args, ctx) {
|
|
307
|
+
const parsed = stripYesFlag(args);
|
|
308
|
+
const commandArgs = [...parsed.rest];
|
|
274
309
|
const shellPaths = requireShellPaths(ctx);
|
|
275
|
-
const sub =
|
|
310
|
+
const sub = commandArgs[0] ?? 'review';
|
|
276
311
|
const subscriptions = requireSubscriptionManager(ctx);
|
|
277
312
|
const serviceRegistry = requireServiceRegistry(ctx);
|
|
278
313
|
const secretsManager = requireSecretsManager(ctx);
|
|
@@ -301,7 +336,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
301
336
|
}
|
|
302
337
|
|
|
303
338
|
if (sub === 'show') {
|
|
304
|
-
const provider =
|
|
339
|
+
const provider = commandArgs[1];
|
|
305
340
|
if (!provider) {
|
|
306
341
|
ctx.print('Usage: /auth show <provider>');
|
|
307
342
|
return;
|
|
@@ -331,7 +366,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
331
366
|
}
|
|
332
367
|
|
|
333
368
|
if (sub === 'repair') {
|
|
334
|
-
const provider =
|
|
369
|
+
const provider = commandArgs[1];
|
|
335
370
|
if (!provider) {
|
|
336
371
|
ctx.print('Usage: /auth repair <provider>');
|
|
337
372
|
return;
|
|
@@ -355,14 +390,18 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
355
390
|
}
|
|
356
391
|
|
|
357
392
|
if (sub === 'bundle') {
|
|
358
|
-
const mode =
|
|
359
|
-
const pathArg =
|
|
393
|
+
const mode = commandArgs[1];
|
|
394
|
+
const pathArg = commandArgs[2];
|
|
360
395
|
if ((mode === 'export' || mode === 'inspect') && !pathArg) {
|
|
361
|
-
ctx.print(`Usage: /auth bundle ${mode} <path
|
|
396
|
+
ctx.print(`Usage: /auth bundle ${mode} <path>${mode === 'export' ? ' --yes' : ''}`);
|
|
362
397
|
return;
|
|
363
398
|
}
|
|
364
399
|
const targetPath = shellPaths.resolveWorkspacePath(pathArg!);
|
|
365
400
|
if (mode === 'export') {
|
|
401
|
+
if (!parsed.yes) {
|
|
402
|
+
requireYesFlag(ctx, `export auth review bundle to ${pathArg}`, '/auth bundle export <path> --yes');
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
366
405
|
const secretKeys = await secretsManager.list();
|
|
367
406
|
const bundle: AuthReviewBundle = {
|
|
368
407
|
version: 1,
|
|
@@ -386,13 +425,17 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
386
425
|
}
|
|
387
426
|
|
|
388
427
|
if (sub === 'login') {
|
|
389
|
-
const target =
|
|
390
|
-
const baseUrl =
|
|
391
|
-
const username =
|
|
392
|
-
const password =
|
|
393
|
-
const secretKey =
|
|
428
|
+
const target = commandArgs[1];
|
|
429
|
+
const baseUrl = commandArgs[2];
|
|
430
|
+
const username = commandArgs[3];
|
|
431
|
+
const password = commandArgs[4];
|
|
432
|
+
const secretKey = commandArgs[5] ?? `${target?.toUpperCase() ?? 'SERVICE'}_SESSION_TOKEN`;
|
|
394
433
|
if ((target !== 'daemon' && target !== 'listener') || !baseUrl || !username || !password) {
|
|
395
|
-
ctx.print('Usage: /auth login <daemon|listener> <baseUrl> <username> <password> [secretKey]');
|
|
434
|
+
ctx.print('Usage: /auth login <daemon|listener> <baseUrl> <username> <password> [secretKey] --yes');
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
if (!parsed.yes) {
|
|
438
|
+
requireYesFlag(ctx, `store ${target} session token`, '/auth login <daemon|listener> <baseUrl> <username> <password> [secretKey] --yes');
|
|
396
439
|
return;
|
|
397
440
|
}
|
|
398
441
|
const url = new URL('/login', baseUrl).toString();
|
|
@@ -416,7 +459,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
416
459
|
return;
|
|
417
460
|
}
|
|
418
461
|
|
|
419
|
-
ctx.print('Usage: /auth [review|show <provider>|bundle export <path
|
|
462
|
+
ctx.print('Usage: /auth [review|show <provider>|bundle export <path> --yes|bundle inspect <path>|login <daemon|listener> <baseUrl> <username> <password> [secretKey] --yes|local <review|panel|add-user --yes|delete-user --yes|rotate-password --yes|revoke-session --yes|clear-bootstrap-file --yes>]');
|
|
420
463
|
},
|
|
421
464
|
});
|
|
422
465
|
}
|