@pellux/goodvibes-agent 0.1.117 → 1.0.0
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 +13 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176073 -170980
- package/docs/README.md +11 -5
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +29 -15
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +44 -9
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +2 -5
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-registry.ts +15 -14
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +26 -25
- package/src/agent/routine-registry.ts +13 -12
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +34 -32
- package/src/agent/routine-schedule-receipts.ts +28 -26
- package/src/agent/runtime-profile-starters.ts +2 -2
- package/src/agent/runtime-profile.ts +18 -17
- package/src/agent/skill-registry.ts +25 -24
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +39 -33
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +13 -8
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +29 -11
- package/src/cli/local-library-command.ts +134 -68
- package/src/cli/management-commands.ts +98 -62
- package/src/cli/management.ts +52 -26
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -24
- package/src/cli/profiles-command.ts +52 -35
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +44 -36
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +46 -121
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-activation.ts +33 -7
- package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
- package/src/input/agent-workspace-basic-command-editors.ts +30 -10
- package/src/input/agent-workspace-categories.ts +276 -64
- package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
- package/src/input/agent-workspace-channel-command-editors.ts +23 -5
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +18 -2
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
- package/src/input/agent-workspace-editors.ts +140 -2
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-learned-behavior.ts +2 -2
- package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
- package/src/input/agent-workspace-library-command-editors.ts +2 -2
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editors.ts +1 -1
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +38 -2
- package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
- package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
- package/src/input/agent-workspace-operations-command-editors.ts +80 -3
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-setup.ts +22 -11
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
- package/src/input/agent-workspace-snapshot.ts +112 -13
- package/src/input/agent-workspace-task-command-editors.ts +4 -4
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +92 -4
- package/src/input/agent-workspace-voice-media.ts +3 -6
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace.ts +136 -208
- package/src/input/command-registry.ts +4 -1
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +83 -70
- package/src/input/commands/agent-workspace-runtime.ts +23 -7
- package/src/input/commands/brief-runtime.ts +25 -24
- package/src/input/commands/channels-runtime.ts +145 -31
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +140 -115
- package/src/input/commands/knowledge.ts +57 -56
- package/src/input/commands/local-provider-runtime.ts +36 -18
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +7 -7
- package/src/input/commands/mcp-runtime.ts +56 -35
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -17
- package/src/input/commands/personas-runtime.ts +45 -30
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +29 -29
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +45 -6
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +59 -43
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +4 -4
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +132 -93
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +32 -17
- package/src/input/commands/subscription-runtime.ts +53 -179
- package/src/input/commands/tasks-runtime.ts +20 -20
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +2 -2
- package/src/input/feed-context-factory.ts +2 -1
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -1
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -3
- package/src/input/handler-interactions.ts +7 -5
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +24 -80
- package/src/input/handler-shortcuts.ts +15 -4
- package/src/input/handler.ts +47 -17
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +22 -11
- package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
- package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/onboarding/onboarding-wizard.ts +68 -0
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +6 -52
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -8
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +2 -2
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +1 -10
- package/src/panels/builtin/session.ts +9 -9
- package/src/panels/builtin/shared.ts +2 -2
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +18 -11
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +45 -4
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +1 -1
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +20 -13
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +1 -1
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +228 -52
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +106 -33
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +164 -50
- package/src/renderer/model-picker-overlay.ts +58 -2
- package/src/renderer/model-workspace.ts +104 -20
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +20 -4
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +83 -50
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +6 -6
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +9 -7
- package/src/runtime/bootstrap-core.ts +19 -1
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +31 -22
- package/src/runtime/connected-host-auth.ts +7 -2
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -1
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +80 -79
- package/src/runtime/onboarding/derivation.ts +5 -8
- package/src/runtime/onboarding/snapshot.ts +0 -15
- package/src/runtime/onboarding/types.ts +8 -19
- package/src/runtime/onboarding/verify.ts +32 -10
- package/src/runtime/operator-token-cleanup.ts +1 -1
- package/src/runtime/services.ts +91 -22
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/ui-openers.ts +3 -13
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +269 -69
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +8 -8
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -13
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
|
|
4
|
+
export type RollbackAction = () => Promise<void> | void;
|
|
5
|
+
|
|
6
|
+
export function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
7
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function readJsonObject(path: string): Record<string, unknown> {
|
|
11
|
+
if (!existsSync(path)) return {};
|
|
12
|
+
const parsed = JSON.parse(readFileSync(path, 'utf-8')) as unknown;
|
|
13
|
+
if (!isPlainObject(parsed)) throw new Error(`Expected an object JSON payload at ${path}.`);
|
|
14
|
+
return parsed;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function writeJsonObject(path: string, payload: Record<string, unknown>): void {
|
|
18
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
19
|
+
writeFileSync(path, `${JSON.stringify(payload, null, 2)}\n`, 'utf-8');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function setNestedValue(root: Record<string, unknown>, key: string, value: unknown): Record<string, unknown> {
|
|
23
|
+
const parts = key.split('.');
|
|
24
|
+
const next = structuredClone(root);
|
|
25
|
+
let cursor: Record<string, unknown> = next;
|
|
26
|
+
|
|
27
|
+
for (let index = 0; index < parts.length - 1; index += 1) {
|
|
28
|
+
const part = parts[index]!;
|
|
29
|
+
let existing = cursor[part];
|
|
30
|
+
if (!isPlainObject(existing)) {
|
|
31
|
+
existing = {};
|
|
32
|
+
cursor[part] = existing;
|
|
33
|
+
}
|
|
34
|
+
cursor = existing as Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
cursor[parts[parts.length - 1]!] = structuredClone(value);
|
|
38
|
+
return next;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function restoreFile(path: string, previous: string | null, reload?: () => void): void {
|
|
42
|
+
if (previous === null) {
|
|
43
|
+
if (existsSync(path)) unlinkSync(path);
|
|
44
|
+
} else {
|
|
45
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
46
|
+
writeFileSync(path, previous, 'utf-8');
|
|
47
|
+
}
|
|
48
|
+
reload?.();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function snapshotFileRollback(path: string, reload?: () => void): RollbackAction {
|
|
52
|
+
const previous = existsSync(path) ? readFileSync(path, 'utf-8') : null;
|
|
53
|
+
return () => restoreFile(path, previous, reload);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function runRollbacks(rollbacks: readonly RollbackAction[]): Promise<readonly string[]> {
|
|
57
|
+
const errors: string[] = [];
|
|
58
|
+
for (const rollback of [...rollbacks].reverse()) {
|
|
59
|
+
try {
|
|
60
|
+
await rollback();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
errors.push(error instanceof Error ? error.message : String(error));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return errors;
|
|
66
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { existsSync,
|
|
2
|
-
import { dirname } from 'node:path';
|
|
1
|
+
import { existsSync, readFileSync, rmSync } from 'node:fs';
|
|
3
2
|
import { isSecretRefInput } from '@pellux/goodvibes-sdk/platform/config';
|
|
4
3
|
import { CONFIG_SCHEMA, DEFAULT_CONFIG } from '../../config/index.ts';
|
|
5
4
|
import {
|
|
@@ -10,10 +9,16 @@ import {
|
|
|
10
9
|
resolveAgentRuntimeProfileHome,
|
|
11
10
|
setAgentRuntimeProfileSelection,
|
|
12
11
|
} from '../../agent/runtime-profile.ts';
|
|
12
|
+
import { AgentNoteRegistry } from '../../agent/note-registry.ts';
|
|
13
13
|
import { AgentPersonaRegistry, assertNoSecretLikeText } from '../../agent/persona-registry.ts';
|
|
14
14
|
import { AgentRoutineRegistry } from '../../agent/routine-registry.ts';
|
|
15
15
|
import { AgentSkillRegistry } from '../../agent/skill-registry.ts';
|
|
16
|
-
import
|
|
16
|
+
import {
|
|
17
|
+
isFeatureFlagConfigKey,
|
|
18
|
+
mergeFeatureFlagConfigValue,
|
|
19
|
+
readFeatureFlagConfigValue,
|
|
20
|
+
type FeatureFlagConfigKey,
|
|
21
|
+
} from '../surface-feature-flags.ts';
|
|
17
22
|
import {
|
|
18
23
|
getOnboardingRuntimeStatePath,
|
|
19
24
|
readOnboardingRuntimeState,
|
|
@@ -29,72 +34,12 @@ import type {
|
|
|
29
34
|
OnboardingApplyRequest,
|
|
30
35
|
OnboardingApplyResult,
|
|
31
36
|
} from './types.ts';
|
|
37
|
+
import { isPlainObject, readJsonObject, restoreFile, runRollbacks, setNestedValue, snapshotFileRollback, writeJsonObject, type RollbackAction } from './apply-file-helpers.ts';
|
|
32
38
|
|
|
33
39
|
function getNow(deps: Pick<OnboardingApplyDependencies, 'clock'>): number {
|
|
34
40
|
return deps.clock?.() ?? Date.now();
|
|
35
41
|
}
|
|
36
42
|
|
|
37
|
-
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
38
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function readJsonObject(path: string): Record<string, unknown> {
|
|
42
|
-
if (!existsSync(path)) return {};
|
|
43
|
-
const parsed = JSON.parse(readFileSync(path, 'utf-8')) as unknown;
|
|
44
|
-
if (!isPlainObject(parsed)) throw new Error(`Expected an object JSON payload at ${path}.`);
|
|
45
|
-
return parsed;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function writeJsonObject(path: string, payload: Record<string, unknown>): void {
|
|
49
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
50
|
-
writeFileSync(path, `${JSON.stringify(payload, null, 2)}\n`, 'utf-8');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function setNestedValue(root: Record<string, unknown>, key: string, value: unknown): Record<string, unknown> {
|
|
54
|
-
const parts = key.split('.');
|
|
55
|
-
const next = structuredClone(root);
|
|
56
|
-
let cursor: Record<string, unknown> = next;
|
|
57
|
-
|
|
58
|
-
for (let index = 0; index < parts.length - 1; index += 1) {
|
|
59
|
-
const part = parts[index]!;
|
|
60
|
-
const existing = cursor[part];
|
|
61
|
-
if (!isPlainObject(existing)) cursor[part] = {};
|
|
62
|
-
cursor = cursor[part] as Record<string, unknown>;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
cursor[parts[parts.length - 1]!] = structuredClone(value);
|
|
66
|
-
return next;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
type RollbackAction = () => Promise<void> | void;
|
|
70
|
-
|
|
71
|
-
function restoreFile(path: string, previous: string | null, reload?: () => void): void {
|
|
72
|
-
if (previous === null) {
|
|
73
|
-
if (existsSync(path)) unlinkSync(path);
|
|
74
|
-
} else {
|
|
75
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
76
|
-
writeFileSync(path, previous, 'utf-8');
|
|
77
|
-
}
|
|
78
|
-
reload?.();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function snapshotFileRollback(path: string, reload?: () => void): RollbackAction {
|
|
82
|
-
const previous = existsSync(path) ? readFileSync(path, 'utf-8') : null;
|
|
83
|
-
return () => restoreFile(path, previous, reload);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async function runRollbacks(rollbacks: readonly RollbackAction[]): Promise<readonly string[]> {
|
|
87
|
-
const errors: string[] = [];
|
|
88
|
-
for (const rollback of [...rollbacks].reverse()) {
|
|
89
|
-
try {
|
|
90
|
-
await rollback();
|
|
91
|
-
} catch (error) {
|
|
92
|
-
errors.push(error instanceof Error ? error.message : String(error));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return errors;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
43
|
function isGoodVibesSecretReferenceValue(value: string): boolean {
|
|
99
44
|
const normalized = value.trim();
|
|
100
45
|
return normalized.startsWith('goodvibes://secrets/') && isSecretRefInput(normalized);
|
|
@@ -105,10 +50,6 @@ function isMalformedGoodVibesSecretReferenceValue(value: string): boolean {
|
|
|
105
50
|
return normalized.startsWith('goodvibes://') && !isGoodVibesSecretReferenceValue(normalized);
|
|
106
51
|
}
|
|
107
52
|
|
|
108
|
-
function isFeatureFlagConfigKey(key: string): key is FeatureFlagConfigKey {
|
|
109
|
-
return key === 'featureFlags' || key.startsWith('featureFlags.');
|
|
110
|
-
}
|
|
111
|
-
|
|
112
53
|
function validateFeatureFlagConfigValue(operation: Extract<OnboardingApplyOperation, { kind: 'set-config' }>): boolean {
|
|
113
54
|
if (!isFeatureFlagConfigKey(operation.key)) return false;
|
|
114
55
|
|
|
@@ -143,7 +84,7 @@ function validateConfigValue(operation: Extract<OnboardingApplyOperation, { kind
|
|
|
143
84
|
const defaultValue = operation.key.split('.').reduce<unknown>((cursor, part) => (
|
|
144
85
|
isPlainObject(cursor) ? cursor[part] : undefined
|
|
145
86
|
), DEFAULT_CONFIG);
|
|
146
|
-
if (defaultValue === undefined) throw new Error(`Unknown config key
|
|
87
|
+
if (defaultValue === undefined) throw new Error(`Unknown config key ${operation.key}`);
|
|
147
88
|
if (typeof defaultValue === 'boolean' && typeof operation.value !== 'boolean') {
|
|
148
89
|
throw new Error(`Config key ${operation.key} expects a boolean value.`);
|
|
149
90
|
}
|
|
@@ -170,11 +111,11 @@ function validateConfigValue(operation: Extract<OnboardingApplyOperation, { kind
|
|
|
170
111
|
}
|
|
171
112
|
|
|
172
113
|
if (schema.type === 'enum' && schema.enumValues && stringValue !== null && !schema.enumValues.includes(stringValue)) {
|
|
173
|
-
throw new Error(`Invalid value for ${operation.key}
|
|
114
|
+
throw new Error(`Invalid value for ${operation.key} ${String(operation.value)}.`);
|
|
174
115
|
}
|
|
175
116
|
|
|
176
117
|
if (schema.validate && !schema.validate(operation.value)) {
|
|
177
|
-
throw new Error(`Invalid value for ${operation.key}
|
|
118
|
+
throw new Error(`Invalid value for ${operation.key} ${String(operation.value)}.`);
|
|
178
119
|
}
|
|
179
120
|
}
|
|
180
121
|
|
|
@@ -287,6 +228,21 @@ function validateCreateLocalRoutineOperation(
|
|
|
287
228
|
if (duplicate) throw new Error(`Routine already exists: ${duplicate.id}`);
|
|
288
229
|
}
|
|
289
230
|
|
|
231
|
+
function validateCreateLocalNoteOperation(
|
|
232
|
+
deps: OnboardingApplyDependencies,
|
|
233
|
+
operation: Extract<OnboardingApplyOperation, { kind: 'create-local-note' }>,
|
|
234
|
+
): void {
|
|
235
|
+
const registry = AgentNoteRegistry.fromShellPaths(deps.shellPaths);
|
|
236
|
+
const title = operation.title.trim();
|
|
237
|
+
const body = operation.body.trim();
|
|
238
|
+
const tags = operation.tags ?? [];
|
|
239
|
+
if (!title) throw new Error('Note title is required.');
|
|
240
|
+
if (!body) throw new Error('Note body is required.');
|
|
241
|
+
assertNoSecretLikeText([title, body, ...tags]);
|
|
242
|
+
const duplicate = registry.get(title);
|
|
243
|
+
if (duplicate) throw new Error(`Note already exists: ${duplicate.id}`);
|
|
244
|
+
}
|
|
245
|
+
|
|
290
246
|
function applyConfigOperation(
|
|
291
247
|
deps: OnboardingApplyDependencies,
|
|
292
248
|
operation: Extract<OnboardingApplyOperation, { kind: 'set-config' }>,
|
|
@@ -306,7 +262,11 @@ function applyConfigOperation(
|
|
|
306
262
|
};
|
|
307
263
|
}
|
|
308
264
|
|
|
309
|
-
|
|
265
|
+
if (isFeatureFlagConfigKey(operation.key)) {
|
|
266
|
+
mergeFeatureFlagConfigValue(deps.config, operation.key, operation.value);
|
|
267
|
+
} else {
|
|
268
|
+
deps.config.setDynamic(operation.key, operation.value);
|
|
269
|
+
}
|
|
310
270
|
return {
|
|
311
271
|
kind: operation.kind,
|
|
312
272
|
summary: `Updated ${operation.key} in global onboarding settings.`,
|
|
@@ -359,9 +319,15 @@ async function buildRollbackAction(
|
|
|
359
319
|
);
|
|
360
320
|
}
|
|
361
321
|
|
|
362
|
-
const previous =
|
|
322
|
+
const previous = isFeatureFlagConfigKey(operation.key)
|
|
323
|
+
? readFeatureFlagConfigValue(deps.config, operation.key)
|
|
324
|
+
: deps.config.get(operation.key);
|
|
363
325
|
return () => {
|
|
364
|
-
|
|
326
|
+
if (isFeatureFlagConfigKey(operation.key)) {
|
|
327
|
+
mergeFeatureFlagConfigValue(deps.config, operation.key, previous ?? 'disabled');
|
|
328
|
+
} else {
|
|
329
|
+
deps.config.setDynamic(operation.key, previous);
|
|
330
|
+
}
|
|
365
331
|
};
|
|
366
332
|
}
|
|
367
333
|
|
|
@@ -392,6 +358,11 @@ async function buildRollbackAction(
|
|
|
392
358
|
return snapshotFileRollback(path);
|
|
393
359
|
}
|
|
394
360
|
|
|
361
|
+
if (operation.kind === 'create-local-note') {
|
|
362
|
+
const registry = AgentNoteRegistry.fromShellPaths(deps.shellPaths);
|
|
363
|
+
return snapshotFileRollback(registry.snapshot().path);
|
|
364
|
+
}
|
|
365
|
+
|
|
395
366
|
if (operation.kind === 'create-local-persona') {
|
|
396
367
|
const registry = AgentPersonaRegistry.fromShellPaths(deps.shellPaths);
|
|
397
368
|
return snapshotFileRollback(registry.snapshot().path);
|
|
@@ -457,7 +428,7 @@ function applySelectAgentProfileOperation(
|
|
|
457
428
|
const selection = setAgentRuntimeProfileSelection(deps.shellPaths.homeDirectory, operation.name);
|
|
458
429
|
return {
|
|
459
430
|
kind: operation.kind,
|
|
460
|
-
summary: `Selected Agent profile ${selection.id} for
|
|
431
|
+
summary: `Selected Agent profile ${selection.id} for later plain goodvibes-agent runs.`,
|
|
461
432
|
};
|
|
462
433
|
}
|
|
463
434
|
|
|
@@ -476,7 +447,7 @@ function applyCreateLocalPersonaOperation(
|
|
|
476
447
|
if (operation.activate !== false) registry.setActive(persona.id);
|
|
477
448
|
return {
|
|
478
449
|
kind: operation.kind,
|
|
479
|
-
summary: `Created local
|
|
450
|
+
summary: `Created Agent-local persona ${persona.id}.`,
|
|
480
451
|
};
|
|
481
452
|
}
|
|
482
453
|
|
|
@@ -494,7 +465,7 @@ function applyCreateLocalSkillOperation(
|
|
|
494
465
|
});
|
|
495
466
|
return {
|
|
496
467
|
kind: operation.kind,
|
|
497
|
-
summary: `Created local
|
|
468
|
+
summary: `Created Agent-local skill ${skill.id}.`,
|
|
498
469
|
};
|
|
499
470
|
}
|
|
500
471
|
|
|
@@ -512,7 +483,24 @@ function applyCreateLocalRoutineOperation(
|
|
|
512
483
|
});
|
|
513
484
|
return {
|
|
514
485
|
kind: operation.kind,
|
|
515
|
-
summary: `Created local
|
|
486
|
+
summary: `Created Agent-local routine ${routine.id}.`,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function applyCreateLocalNoteOperation(
|
|
491
|
+
deps: OnboardingApplyDependencies,
|
|
492
|
+
operation: Extract<OnboardingApplyOperation, { kind: 'create-local-note' }>,
|
|
493
|
+
): OnboardingAppliedOperation {
|
|
494
|
+
const note = AgentNoteRegistry.fromShellPaths(deps.shellPaths).create({
|
|
495
|
+
title: operation.title,
|
|
496
|
+
body: operation.body,
|
|
497
|
+
tags: operation.tags ?? [],
|
|
498
|
+
source: 'user',
|
|
499
|
+
provenance: 'onboarding',
|
|
500
|
+
});
|
|
501
|
+
return {
|
|
502
|
+
kind: operation.kind,
|
|
503
|
+
summary: `Created Agent-local note ${note.id}.`,
|
|
516
504
|
};
|
|
517
505
|
}
|
|
518
506
|
|
|
@@ -530,7 +518,8 @@ function orderApplyOperations(
|
|
|
530
518
|
const agentProfileOperations = operations.filter((operation) => operation.kind === 'create-agent-profile');
|
|
531
519
|
const agentProfileSelectionOperations = operations.filter((operation) => operation.kind === 'select-agent-profile');
|
|
532
520
|
const localBehaviorOperations = operations.filter((operation) => (
|
|
533
|
-
operation.kind === 'create-local-
|
|
521
|
+
operation.kind === 'create-local-note'
|
|
522
|
+
|| operation.kind === 'create-local-persona'
|
|
534
523
|
|| operation.kind === 'create-local-skill'
|
|
535
524
|
|| operation.kind === 'create-local-routine'
|
|
536
525
|
));
|
|
@@ -602,6 +591,11 @@ function prevalidateApplyRequest(
|
|
|
602
591
|
continue;
|
|
603
592
|
}
|
|
604
593
|
|
|
594
|
+
if (operation.kind === 'create-local-note') {
|
|
595
|
+
validateCreateLocalNoteOperation(deps, operation);
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
598
|
+
|
|
605
599
|
if (operation.kind === 'create-local-skill') {
|
|
606
600
|
validateCreateLocalSkillOperation(deps, operation);
|
|
607
601
|
continue;
|
|
@@ -632,6 +626,7 @@ function getVerificationFailureKind(itemId: string): OnboardingApplyOperation['k
|
|
|
632
626
|
if (itemId.startsWith('acknowledge:')) return 'acknowledge';
|
|
633
627
|
if (itemId.startsWith('agent-profile:')) return 'create-agent-profile';
|
|
634
628
|
if (itemId.startsWith('selected-agent-profile:')) return 'select-agent-profile';
|
|
629
|
+
if (itemId.startsWith('local-note:')) return 'create-local-note';
|
|
635
630
|
if (itemId.startsWith('local-persona:')) return 'create-local-persona';
|
|
636
631
|
if (itemId.startsWith('local-skill:')) return 'create-local-skill';
|
|
637
632
|
if (itemId.startsWith('local-routine:')) return 'create-local-routine';
|
|
@@ -703,6 +698,12 @@ export async function applyOnboardingRequest(
|
|
|
703
698
|
continue;
|
|
704
699
|
}
|
|
705
700
|
|
|
701
|
+
if (operation.kind === 'create-local-note') {
|
|
702
|
+
applied.push(applyCreateLocalNoteOperation(deps, operation));
|
|
703
|
+
rollbacks.push(rollback);
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
|
|
706
707
|
if (operation.kind === 'create-local-skill') {
|
|
707
708
|
applied.push(applyCreateLocalSkillOperation(deps, operation));
|
|
708
709
|
rollbacks.push(rollback);
|
|
@@ -83,7 +83,7 @@ function isDeepEqual(left: unknown, right: unknown): boolean {
|
|
|
83
83
|
const rightEntries = Object.entries(right);
|
|
84
84
|
if (leftEntries.length !== rightEntries.length) return false;
|
|
85
85
|
|
|
86
|
-
return leftEntries.every(([key, value]) => isDeepEqual(value, (right
|
|
86
|
+
return leftEntries.every(([key, value]) => isDeepEqual(value, Reflect.get(right, key)));
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
return false;
|
|
@@ -250,7 +250,7 @@ function describeLocalBehavior(snapshot: OnboardingSnapshotState): string {
|
|
|
250
250
|
...discovery.routines.names,
|
|
251
251
|
].slice(0, 4);
|
|
252
252
|
const sampleText = samples.length > 0 ? ` Found: ${samples.join(', ')}.` : '';
|
|
253
|
-
return `Import ${discoveredCount} discovered Agent persona/skill/routine file(s) from local
|
|
253
|
+
return `Import ${discoveredCount} discovered Agent persona/skill/routine file(s) from Agent-local folders before creating blank behavior.${sampleText}`;
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
if (!hasLocalBehaviorCustomization(snapshot)) {
|
|
@@ -288,7 +288,7 @@ function describeAutomationReview(snapshot: OnboardingSnapshotState): string {
|
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
function describeTuiDelegation(): string {
|
|
291
|
-
return 'Delegate explicit build, fix, implementation, and review work to GoodVibes TUI;
|
|
291
|
+
return 'Delegate explicit build, fix, implementation, and review work to GoodVibes TUI; delegated review is requested only when the user explicitly asks for it.';
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
function getAcknowledgementAccepted(
|
|
@@ -391,10 +391,7 @@ export function deriveStep1CapabilityFlags(
|
|
|
391
391
|
};
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
-
export function deriveStep1_5NetworkMode(
|
|
395
|
-
bindSettings: Pick<OnboardingSnapshotState, 'bindSettings'>['bindSettings'],
|
|
396
|
-
): OnboardingNetworkMode {
|
|
397
|
-
void bindSettings;
|
|
394
|
+
export function deriveStep1_5NetworkMode(): OnboardingNetworkMode {
|
|
398
395
|
return 'local-network-default';
|
|
399
396
|
}
|
|
400
397
|
|
|
@@ -488,7 +485,7 @@ export function deriveOnboardingStepState(
|
|
|
488
485
|
): OnboardingStepDerivationState {
|
|
489
486
|
return {
|
|
490
487
|
step1Capabilities: deriveStep1Capabilities(snapshot),
|
|
491
|
-
step1_5NetworkMode: deriveStep1_5NetworkMode(
|
|
488
|
+
step1_5NetworkMode: deriveStep1_5NetworkMode(),
|
|
492
489
|
reopenEditAcknowledgements: deriveReopenEditAcknowledgementState(snapshot),
|
|
493
490
|
};
|
|
494
491
|
}
|
|
@@ -35,15 +35,7 @@ function buildConfigSnapshot(
|
|
|
35
35
|
llmProvider: config.get('tools.llmProvider'),
|
|
36
36
|
llmModel: config.get('tools.llmModel'),
|
|
37
37
|
},
|
|
38
|
-
danger: config.getCategory('danger'),
|
|
39
|
-
controlPlane: config.getCategory('controlPlane'),
|
|
40
|
-
httpListener: config.getCategory('httpListener'),
|
|
41
|
-
web: config.getCategory('web'),
|
|
42
|
-
network: config.getCategory('network'),
|
|
43
38
|
surfaces: config.getCategory('surfaces'),
|
|
44
|
-
service: config.getCategory('service'),
|
|
45
|
-
featureFlags: config.getCategory('featureFlags'),
|
|
46
|
-
batch: config.getCategory('batch'),
|
|
47
39
|
};
|
|
48
40
|
}
|
|
49
41
|
|
|
@@ -389,13 +381,6 @@ export async function collectOnboardingSnapshot(
|
|
|
389
381
|
auth: {
|
|
390
382
|
snapshot: authSnapshotResult.value,
|
|
391
383
|
},
|
|
392
|
-
bindSettings: {
|
|
393
|
-
daemonEnabled: Boolean(config.danger.daemon),
|
|
394
|
-
httpListenerEnabled: Boolean(config.danger.httpListener),
|
|
395
|
-
controlPlane: config.controlPlane,
|
|
396
|
-
httpListener: config.httpListener,
|
|
397
|
-
web: config.web,
|
|
398
|
-
},
|
|
399
384
|
surfaces: {
|
|
400
385
|
configuredEnabledKinds: buildConfiguredSurfaceKinds(config.surfaces),
|
|
401
386
|
records: sortSurfaceRecords(surfaceResult.value),
|
|
@@ -40,15 +40,7 @@ export interface OnboardingConfigSnapshot {
|
|
|
40
40
|
readonly permissions: GoodVibesConfig['permissions'];
|
|
41
41
|
readonly helper: GoodVibesConfig['helper'];
|
|
42
42
|
readonly tools: Pick<GoodVibesConfig['tools'], 'llmEnabled' | 'llmProvider' | 'llmModel'>;
|
|
43
|
-
readonly danger: GoodVibesConfig['danger'];
|
|
44
|
-
readonly controlPlane: GoodVibesConfig['controlPlane'];
|
|
45
|
-
readonly httpListener: GoodVibesConfig['httpListener'];
|
|
46
|
-
readonly web: GoodVibesConfig['web'];
|
|
47
|
-
readonly network: GoodVibesConfig['network'];
|
|
48
43
|
readonly surfaces: GoodVibesConfig['surfaces'];
|
|
49
|
-
readonly service: GoodVibesConfig['service'];
|
|
50
|
-
readonly featureFlags: GoodVibesConfig['featureFlags'];
|
|
51
|
-
readonly batch: GoodVibesConfig['batch'];
|
|
52
44
|
}
|
|
53
45
|
|
|
54
46
|
export interface OnboardingProviderRoutingSnapshot {
|
|
@@ -102,14 +94,6 @@ export interface OnboardingAuthSnapshot {
|
|
|
102
94
|
readonly snapshot: LocalAuthSnapshot;
|
|
103
95
|
}
|
|
104
96
|
|
|
105
|
-
export interface OnboardingBindSettingsSnapshot {
|
|
106
|
-
readonly daemonEnabled: boolean;
|
|
107
|
-
readonly httpListenerEnabled: boolean;
|
|
108
|
-
readonly controlPlane: GoodVibesConfig['controlPlane'];
|
|
109
|
-
readonly httpListener: GoodVibesConfig['httpListener'];
|
|
110
|
-
readonly web: GoodVibesConfig['web'];
|
|
111
|
-
}
|
|
112
|
-
|
|
113
97
|
export interface OnboardingSurfaceRecord {
|
|
114
98
|
readonly id: string;
|
|
115
99
|
readonly kind: string;
|
|
@@ -187,7 +171,6 @@ export interface OnboardingSnapshotState {
|
|
|
187
171
|
readonly subscriptions: OnboardingSubscriptionsSnapshot;
|
|
188
172
|
readonly secrets: OnboardingSecretsSnapshot;
|
|
189
173
|
readonly auth: OnboardingAuthSnapshot;
|
|
190
|
-
readonly bindSettings: OnboardingBindSettingsSnapshot;
|
|
191
174
|
readonly surfaces: OnboardingSurfacesSnapshot;
|
|
192
175
|
readonly providerAccounts: OnboardingProviderAccountsSnapshot | null;
|
|
193
176
|
readonly localBehaviorDiscovery: AgentBehaviorDiscoverySnapshot;
|
|
@@ -276,6 +259,12 @@ export type OnboardingApplyOperation =
|
|
|
276
259
|
readonly kind: 'select-agent-profile';
|
|
277
260
|
readonly name: string;
|
|
278
261
|
}
|
|
262
|
+
| {
|
|
263
|
+
readonly kind: 'create-local-note';
|
|
264
|
+
readonly title: string;
|
|
265
|
+
readonly body: string;
|
|
266
|
+
readonly tags?: readonly string[];
|
|
267
|
+
}
|
|
279
268
|
| {
|
|
280
269
|
readonly kind: 'create-local-persona';
|
|
281
270
|
readonly name: string;
|
|
@@ -408,7 +397,7 @@ export interface OnboardingSnapshotDependencies {
|
|
|
408
397
|
|
|
409
398
|
export interface OnboardingApplyDependencies {
|
|
410
399
|
readonly clock?: () => number;
|
|
411
|
-
readonly config: Pick<ConfigManager, 'get' | 'getRaw' | 'load' | 'setDynamic'>;
|
|
400
|
+
readonly config: Pick<ConfigManager, 'get' | 'getCategory' | 'getRaw' | 'load' | 'mergeCategory' | 'setDynamic'>;
|
|
412
401
|
readonly secrets?: Pick<SecretsManager, 'delete' | 'get' | 'inspect' | 'set'>;
|
|
413
402
|
readonly auth?: Pick<UserAuthManager, 'inspect'>;
|
|
414
403
|
readonly shellPaths: OnboardingShellPaths;
|
|
@@ -417,7 +406,7 @@ export interface OnboardingApplyDependencies {
|
|
|
417
406
|
|
|
418
407
|
export interface OnboardingVerificationDependencies {
|
|
419
408
|
readonly clock?: () => number;
|
|
420
|
-
readonly config: Pick<ConfigManager, 'get'>;
|
|
409
|
+
readonly config: Pick<ConfigManager, 'get' | 'getCategory'>;
|
|
421
410
|
readonly secrets?: Pick<SecretsManager, 'get'>;
|
|
422
411
|
readonly auth?: Pick<UserAuthManager, 'inspect'>;
|
|
423
412
|
readonly shellPaths: OnboardingShellPaths;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { isSecretRefInput } from '@pellux/goodvibes-sdk/platform/config';
|
|
4
|
+
import { AgentNoteRegistry } from '../../agent/note-registry.ts';
|
|
4
5
|
import { AgentPersonaRegistry } from '../../agent/persona-registry.ts';
|
|
5
6
|
import { AgentRoutineRegistry } from '../../agent/routine-registry.ts';
|
|
6
7
|
import { readAgentRuntimeProfileSelection, resolveAgentRuntimeProfileHome } from '../../agent/runtime-profile.ts';
|
|
7
8
|
import { AgentSkillRegistry } from '../../agent/skill-registry.ts';
|
|
9
|
+
import { isFeatureFlagConfigKey, readFeatureFlagConfigValue } from '../surface-feature-flags.ts';
|
|
8
10
|
import { readOnboardingRuntimeState } from './state.ts';
|
|
9
11
|
import type {
|
|
10
12
|
OnboardingApplyOperation,
|
|
@@ -34,7 +36,7 @@ function isDeepEqual(left: unknown, right: unknown): boolean {
|
|
|
34
36
|
const rightEntries = Object.entries(right);
|
|
35
37
|
if (leftEntries.length !== rightEntries.length) return false;
|
|
36
38
|
|
|
37
|
-
return leftEntries.every(([key, value]) => isDeepEqual(value, (right
|
|
39
|
+
return leftEntries.every(([key, value]) => isDeepEqual(value, Reflect.get(right, key)));
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
return false;
|
|
@@ -49,7 +51,9 @@ function verifyConfigOperation(
|
|
|
49
51
|
deps: OnboardingVerificationDependencies,
|
|
50
52
|
operation: Extract<OnboardingApplyOperation, { kind: 'set-config' }>,
|
|
51
53
|
): OnboardingVerificationItem {
|
|
52
|
-
const actual =
|
|
54
|
+
const actual = isFeatureFlagConfigKey(operation.key)
|
|
55
|
+
? readFeatureFlagConfigValue(deps.config, operation.key)
|
|
56
|
+
: deps.config.get(operation.key);
|
|
53
57
|
const ok = isDeepEqual(actual, operation.value);
|
|
54
58
|
|
|
55
59
|
return {
|
|
@@ -158,8 +162,8 @@ function verifySelectAgentProfileOperation(
|
|
|
158
162
|
id: `selected-agent-profile:${resolution.id}`,
|
|
159
163
|
status: ok ? 'pass' : 'fail',
|
|
160
164
|
message: ok
|
|
161
|
-
? `${resolution.id} Agent profile is selected for
|
|
162
|
-
: `${resolution.id} Agent profile is not selected for
|
|
165
|
+
? `${resolution.id} Agent profile is selected for later plain goodvibes-agent runs.`
|
|
166
|
+
: `${resolution.id} Agent profile is not selected for later plain goodvibes-agent runs.`,
|
|
163
167
|
target: resolution.id,
|
|
164
168
|
};
|
|
165
169
|
}
|
|
@@ -177,8 +181,8 @@ function verifyCreateLocalPersonaOperation(
|
|
|
177
181
|
id: `local-persona:${target}`,
|
|
178
182
|
status: ok ? 'pass' : 'fail',
|
|
179
183
|
message: ok
|
|
180
|
-
? `${target} local
|
|
181
|
-
: `${target} local
|
|
184
|
+
? `${target} Agent-local persona exists${operation.activate === false ? '' : ' and is active'}.`
|
|
185
|
+
: `${target} Agent-local persona was not created${operation.activate === false ? '' : ' or activated'}.`,
|
|
182
186
|
target,
|
|
183
187
|
};
|
|
184
188
|
}
|
|
@@ -195,8 +199,8 @@ function verifyCreateLocalSkillOperation(
|
|
|
195
199
|
id: `local-skill:${target}`,
|
|
196
200
|
status: ok ? 'pass' : 'fail',
|
|
197
201
|
message: ok
|
|
198
|
-
? `${target} local
|
|
199
|
-
: `${target} local
|
|
202
|
+
? `${target} Agent-local skill exists${operation.enabled === false ? '' : ' and is enabled'}.`
|
|
203
|
+
: `${target} Agent-local skill was not created${operation.enabled === false ? '' : ' or enabled'}.`,
|
|
200
204
|
target,
|
|
201
205
|
};
|
|
202
206
|
}
|
|
@@ -213,8 +217,25 @@ function verifyCreateLocalRoutineOperation(
|
|
|
213
217
|
id: `local-routine:${target}`,
|
|
214
218
|
status: ok ? 'pass' : 'fail',
|
|
215
219
|
message: ok
|
|
216
|
-
? `${target} local
|
|
217
|
-
: `${target} local
|
|
220
|
+
? `${target} Agent-local routine exists${operation.enabled === false ? '' : ' and is enabled'}.`
|
|
221
|
+
: `${target} Agent-local routine was not created${operation.enabled === false ? '' : ' or enabled'}.`,
|
|
222
|
+
target,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function verifyCreateLocalNoteOperation(
|
|
227
|
+
deps: OnboardingVerificationDependencies,
|
|
228
|
+
operation: Extract<OnboardingApplyOperation, { kind: 'create-local-note' }>,
|
|
229
|
+
): OnboardingVerificationItem {
|
|
230
|
+
const note = AgentNoteRegistry.fromShellPaths(deps.shellPaths).get(operation.title);
|
|
231
|
+
const ok = note !== null && note.body.trim() === operation.body.trim();
|
|
232
|
+
const target = note?.id ?? operation.title.trim();
|
|
233
|
+
return {
|
|
234
|
+
id: `local-note:${target}`,
|
|
235
|
+
status: ok ? 'pass' : 'fail',
|
|
236
|
+
message: ok
|
|
237
|
+
? `${target} Agent-local note exists.`
|
|
238
|
+
: `${target} Agent-local note was not created.`,
|
|
218
239
|
target,
|
|
219
240
|
};
|
|
220
241
|
}
|
|
@@ -229,6 +250,7 @@ async function verifyOperation(
|
|
|
229
250
|
if (operation.kind === 'acknowledge') return verifyAcknowledgementOperation(deps, operation);
|
|
230
251
|
if (operation.kind === 'create-agent-profile') return verifyCreateAgentProfileOperation(deps, operation);
|
|
231
252
|
if (operation.kind === 'select-agent-profile') return verifySelectAgentProfileOperation(deps, operation);
|
|
253
|
+
if (operation.kind === 'create-local-note') return verifyCreateLocalNoteOperation(deps, operation);
|
|
232
254
|
if (operation.kind === 'create-local-persona') return verifyCreateLocalPersonaOperation(deps, operation);
|
|
233
255
|
if (operation.kind === 'create-local-skill') return verifyCreateLocalSkillOperation(deps, operation);
|
|
234
256
|
return verifyCreateLocalRoutineOperation(deps, operation);
|
|
@@ -16,7 +16,7 @@ import { join } from 'node:path';
|
|
|
16
16
|
* Return the list of absolute operator-tokens.json paths the TUI may have written
|
|
17
17
|
* at legacy (pre-0.21.28) workspace-scoped locations under `workingDirectory`.
|
|
18
18
|
*
|
|
19
|
-
* The canonical, current-SDK location is `<
|
|
19
|
+
* The canonical, current-SDK location is `<connectedHostTokenDir>/operator-tokens.json`;
|
|
20
20
|
* this helper is strictly for legacy-cleanup candidates.
|
|
21
21
|
*/
|
|
22
22
|
export function workspaceOperatorTokenCandidates(workingDirectory: string): readonly string[] {
|