@pellux/goodvibes-agent 1.1.7 → 1.2.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 +170 -0
- package/README.md +46 -30
- package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-swtppvy9.node} +0 -0
- package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-ttfcdtap.node} +0 -0
- package/dist/package/main.js +132577 -91483
- package/docs/README.md +14 -7
- package/docs/channels-remote-and-api.md +8 -5
- package/docs/connected-host.md +14 -12
- package/docs/getting-started.md +56 -30
- package/docs/knowledge-artifacts-and-multimodal.md +7 -5
- package/docs/project-planning.md +2 -2
- package/docs/providers-and-routing.md +11 -3
- package/docs/tools-and-commands.md +114 -45
- package/docs/voice-and-live-tts.md +3 -1
- package/package.json +3 -2
- package/release/release-notes.md +130 -5
- package/release/release-readiness.json +120 -90
- package/src/agent/assistant-cockpit.ts +247 -0
- package/src/agent/autonomy-schedule-format.ts +96 -0
- package/src/agent/autonomy-schedule.ts +514 -0
- package/src/agent/channel-delivery-receipts.ts +292 -0
- package/src/agent/competitive-feature-inventory.ts +296 -0
- package/src/agent/document-registry-types.ts +106 -0
- package/src/agent/document-registry.ts +734 -0
- package/src/agent/harness-control.ts +2 -2
- package/src/agent/memory-prompt.ts +2 -2
- package/src/agent/operator-actions.ts +50 -6
- package/src/agent/persona-registry.ts +8 -0
- package/src/agent/project-context-files.ts +273 -0
- package/src/agent/prompt-context-receipts.ts +502 -0
- package/src/agent/reminder-schedule-format.ts +16 -2
- package/src/agent/research-run-registry.ts +582 -0
- package/src/agent/research-source-registry.ts +441 -0
- package/src/agent/routine-registry.ts +19 -3
- package/src/agent/routine-schedule-format.ts +27 -2
- package/src/agent/runtime-profile-starters.ts +7 -0
- package/src/agent/runtime-profile.ts +106 -4
- package/src/agent/schedule-edit-format.ts +129 -0
- package/src/agent/schedule-edit.ts +496 -0
- package/src/agent/schedule-next-routes.ts +42 -0
- package/src/agent/setup-wizard-checkpoint.ts +140 -0
- package/src/agent/setup-wizard.ts +447 -0
- package/src/agent/skill-registry-types.ts +102 -0
- package/src/agent/skill-registry.ts +81 -107
- package/src/agent/vibe-confirmation-routes.ts +62 -0
- package/src/agent/vibe-file.ts +285 -0
- package/src/cli/agent-knowledge-command.ts +45 -2
- package/src/cli/help.ts +3 -0
- package/src/cli/profiles-command.ts +25 -11
- package/src/config/agent-settings-policy.ts +1 -18
- package/src/input/agent-workspace-activation.ts +53 -0
- package/src/input/agent-workspace-artifact-browser-editor.ts +494 -0
- package/src/input/agent-workspace-artifact-metadata.ts +17 -0
- package/src/input/agent-workspace-basic-command-editors.ts +5 -1
- package/src/input/agent-workspace-categories.ts +153 -155
- package/src/input/agent-workspace-channel-triage.ts +481 -0
- package/src/input/agent-workspace-channels.ts +263 -0
- package/src/input/agent-workspace-command-editor.ts +152 -0
- package/src/input/agent-workspace-context-snapshot.ts +349 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +8 -0
- package/src/input/agent-workspace-document-editor.ts +502 -0
- package/src/input/agent-workspace-document-ops-editor.ts +523 -0
- package/src/input/agent-workspace-host-category.ts +1 -1
- package/src/input/agent-workspace-local-library-snapshot.ts +167 -0
- package/src/input/agent-workspace-model-compare-editor.ts +376 -0
- package/src/input/agent-workspace-model-compare-prompt-submission.ts +552 -0
- package/src/input/agent-workspace-model-compare-types.ts +82 -0
- package/src/input/agent-workspace-model-compare-utils.ts +35 -0
- package/src/input/agent-workspace-onboarding-categories.ts +141 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +53 -0
- package/src/input/agent-workspace-operations-command-editors.ts +22 -0
- package/src/input/agent-workspace-research-report-editor.ts +212 -0
- package/src/input/agent-workspace-research-run-editor.ts +144 -0
- package/src/input/agent-workspace-research-source-editor.ts +167 -0
- package/src/input/agent-workspace-review-packet-snapshot.ts +593 -0
- package/src/input/agent-workspace-review-packet-utils.ts +265 -0
- package/src/input/agent-workspace-settings.ts +262 -30
- package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
- package/src/input/agent-workspace-setup-snapshot.ts +198 -0
- package/src/input/agent-workspace-setup.ts +34 -1
- package/src/input/agent-workspace-snapshot.ts +162 -147
- package/src/input/agent-workspace-types.ts +287 -2
- package/src/input/agent-workspace.ts +18 -0
- package/src/input/command-registry.ts +9 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +28 -13
- package/src/input/commands/channels-runtime.ts +102 -114
- package/src/input/commands/delegation-runtime.ts +87 -24
- package/src/input/commands/knowledge-browser-flags.ts +12 -0
- package/src/input/commands/knowledge.ts +28 -14
- package/src/input/commands/operator-actions-runtime.ts +6 -3
- package/src/input/commands/schedule-runtime.ts +71 -14
- package/src/input/commands/session-content.ts +2 -2
- package/src/input/commands/shell-core.ts +2 -0
- package/src/input/commands/vibe-runtime.ts +140 -0
- package/src/input/commands.ts +2 -0
- package/src/input/connected-host-routes.ts +123 -0
- package/src/input/settings-modal-types.ts +14 -0
- package/src/main.ts +15 -15
- package/src/panels/qr-panel.ts +2 -2
- package/src/renderer/agent-workspace-context-lines.ts +686 -0
- package/src/renderer/agent-workspace.ts +30 -419
- package/src/renderer/settings-modal-helpers.ts +12 -0
- package/src/renderer/settings-modal.ts +12 -0
- package/src/runtime/bootstrap-command-context.ts +11 -1
- package/src/runtime/bootstrap-command-parts.ts +14 -3
- package/src/runtime/bootstrap-core.ts +39 -1
- package/src/runtime/bootstrap-shell.ts +6 -0
- package/src/runtime/bootstrap.ts +113 -30
- package/src/runtime/connected-host-auth.ts +3 -2
- package/src/runtime/execution-ledger.ts +231 -0
- package/src/runtime/services.ts +88 -10
- package/src/runtime/tool-permission-safety.ts +199 -5
- package/src/shell/session-continuity-hints.ts +39 -0
- package/src/tools/agent-artifacts-tool.ts +606 -0
- package/src/tools/agent-audit-tool.ts +155 -0
- package/src/tools/agent-autonomy-schedule-tool.ts +238 -0
- package/src/tools/agent-autonomy-tool.ts +140 -0
- package/src/tools/agent-channel-send-tool.ts +24 -2
- package/src/tools/agent-channels-tool.ts +140 -0
- package/src/tools/agent-computer-tool.ts +168 -0
- package/src/tools/agent-context-policy.ts +137 -7
- package/src/tools/agent-context-tool.ts +143 -0
- package/src/tools/agent-delegation-tool.ts +128 -0
- package/src/tools/agent-device-tool.ts +240 -0
- package/src/tools/agent-documents-tool.ts +684 -0
- package/src/tools/agent-execution-tool.ts +230 -0
- package/src/tools/agent-harness-agent-orchestration.ts +703 -0
- package/src/tools/agent-harness-autonomy-intake.ts +785 -0
- package/src/tools/agent-harness-autonomy-live-records.ts +588 -0
- package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
- package/src/tools/agent-harness-autonomy-queue.ts +560 -0
- package/src/tools/agent-harness-background-processes-types.ts +35 -0
- package/src/tools/agent-harness-background-processes.ts +794 -0
- package/src/tools/agent-harness-browser-cockpit-route.ts +219 -0
- package/src/tools/agent-harness-browser-control.ts +338 -0
- package/src/tools/agent-harness-channel-metadata.ts +168 -10
- package/src/tools/agent-harness-cli-command-policy.ts +110 -0
- package/src/tools/agent-harness-command-catalog.ts +4 -2
- package/src/tools/agent-harness-command-runner.ts +42 -0
- package/src/tools/agent-harness-connected-host-status.ts +7 -4
- package/src/tools/agent-harness-delegation-posture.ts +234 -19
- package/src/tools/agent-harness-document-ops-reviewer-readiness.ts +234 -0
- package/src/tools/agent-harness-document-ops-types.ts +72 -0
- package/src/tools/agent-harness-document-ops.ts +671 -0
- package/src/tools/agent-harness-execution-history.ts +489 -0
- package/src/tools/agent-harness-execution-posture.ts +382 -0
- package/src/tools/agent-harness-file-recovery.ts +135 -0
- package/src/tools/agent-harness-keybinding-metadata.ts +16 -12
- package/src/tools/agent-harness-learning-curator-common.ts +102 -0
- package/src/tools/agent-harness-learning-curator-consolidation.ts +295 -0
- package/src/tools/agent-harness-learning-curator-proposals.ts +606 -0
- package/src/tools/agent-harness-learning-curator-types.ts +151 -0
- package/src/tools/agent-harness-learning-curator.ts +417 -0
- package/src/tools/agent-harness-local-model-benchmarks.ts +199 -0
- package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
- package/src/tools/agent-harness-local-model-endpoints.ts +673 -0
- package/src/tools/agent-harness-media-posture.ts +208 -2
- package/src/tools/agent-harness-memory-posture.ts +556 -0
- package/src/tools/agent-harness-metadata.ts +100 -168
- package/src/tools/agent-harness-mode-catalog.ts +84 -33
- package/src/tools/agent-harness-model-catalog.ts +162 -0
- package/src/tools/agent-harness-model-provider-health.ts +186 -0
- package/src/tools/agent-harness-model-readiness.ts +406 -0
- package/src/tools/agent-harness-model-routing-types.ts +266 -0
- package/src/tools/agent-harness-model-routing-utils.ts +30 -0
- package/src/tools/agent-harness-model-routing.ts +137 -190
- package/src/tools/agent-harness-operator-methods.ts +115 -133
- package/src/tools/agent-harness-pairing-posture.ts +431 -18
- package/src/tools/agent-harness-personal-ops-discovery.ts +533 -0
- package/src/tools/agent-harness-personal-ops-intake.ts +385 -0
- package/src/tools/agent-harness-personal-ops-lanes.ts +204 -0
- package/src/tools/agent-harness-personal-ops-records.ts +732 -0
- package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
- package/src/tools/agent-harness-personal-ops-types.ts +222 -0
- package/src/tools/agent-harness-personal-ops.ts +606 -0
- package/src/tools/agent-harness-project-context.ts +144 -0
- package/src/tools/agent-harness-prompt-context.ts +589 -0
- package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
- package/src/tools/agent-harness-release-evidence.ts +9 -7
- package/src/tools/agent-harness-release-readiness.ts +9 -7
- package/src/tools/agent-harness-research-briefing.ts +427 -0
- package/src/tools/agent-harness-research-queue.ts +250 -0
- package/src/tools/agent-harness-research-runs.ts +295 -0
- package/src/tools/agent-harness-research-workflow.ts +322 -0
- package/src/tools/agent-harness-security-posture.ts +2 -2
- package/src/tools/agent-harness-service-posture.ts +9 -9
- package/src/tools/agent-harness-session-metadata.ts +3 -3
- package/src/tools/agent-harness-setup-connected-host.ts +501 -0
- package/src/tools/agent-harness-setup-describe.ts +557 -0
- package/src/tools/agent-harness-setup-handoffs.ts +502 -0
- package/src/tools/agent-harness-setup-model-helpers.ts +101 -0
- package/src/tools/agent-harness-setup-plan.ts +253 -0
- package/src/tools/agent-harness-setup-posture-types.ts +218 -0
- package/src/tools/agent-harness-setup-posture-utils.ts +173 -0
- package/src/tools/agent-harness-setup-posture.ts +449 -221
- package/src/tools/agent-harness-setup-smoke.ts +508 -0
- package/src/tools/agent-harness-sudo-posture.ts +114 -0
- package/src/tools/agent-harness-tool-schema.ts +120 -7
- package/src/tools/agent-harness-tool-types.ts +78 -0
- package/src/tools/agent-harness-tool-utils.ts +43 -0
- package/src/tools/agent-harness-tool.ts +311 -370
- package/src/tools/agent-harness-ui-surface-metadata.ts +76 -69
- package/src/tools/agent-harness-ui-surface-types.ts +46 -0
- package/src/tools/agent-harness-vibe-health.ts +105 -0
- package/src/tools/agent-harness-workspace-action-runner.ts +149 -0
- package/src/tools/agent-harness-workspace-actions.ts +114 -8
- package/src/tools/agent-harness-workspace-editor-execution.ts +214 -0
- package/src/tools/agent-harness-workspace-editor-runner.ts +755 -0
- package/src/tools/agent-host-tool.ts +159 -0
- package/src/tools/agent-knowledge-ingest-tool.ts +34 -1
- package/src/tools/agent-learning-consolidation-core.ts +327 -0
- package/src/tools/agent-learning-consolidation-tool.ts +758 -0
- package/src/tools/agent-memory-tool.ts +214 -0
- package/src/tools/agent-model-compare-export.ts +315 -0
- package/src/tools/agent-model-compare-handoff.ts +592 -0
- package/src/tools/agent-model-compare-judgment.ts +633 -0
- package/src/tools/agent-model-compare-run.ts +722 -0
- package/src/tools/agent-model-compare-tool.ts +698 -0
- package/src/tools/agent-model-compare-types.ts +191 -0
- package/src/tools/agent-model-compare-utils.ts +93 -0
- package/src/tools/agent-models-tool.ts +208 -0
- package/src/tools/agent-operator-action-tool.ts +1 -1
- package/src/tools/agent-operator-method-tool.ts +643 -0
- package/src/tools/agent-personal-ops-tool.ts +197 -0
- package/src/tools/agent-policy-explanation.ts +415 -0
- package/src/tools/agent-research-report-tool.ts +608 -0
- package/src/tools/agent-research-runs-tool.ts +434 -0
- package/src/tools/agent-research-sources-tool.ts +443 -0
- package/src/tools/agent-research-tool.ts +687 -0
- package/src/tools/agent-review-packet-presets-core.ts +757 -0
- package/src/tools/agent-review-packet-presets-tool.ts +466 -0
- package/src/tools/agent-review-packet-share-tool.ts +305 -0
- package/src/tools/agent-route-planner-candidates-setup.ts +411 -0
- package/src/tools/agent-route-planner-candidates-surfaces.ts +432 -0
- package/src/tools/agent-route-planner-candidates-work.ts +251 -0
- package/src/tools/agent-route-planner-helpers.ts +667 -0
- package/src/tools/agent-route-planner.ts +185 -0
- package/src/tools/agent-route-tool.ts +105 -0
- package/src/tools/agent-schedule-edit-tool.ts +210 -0
- package/src/tools/agent-schedule-tool.ts +282 -0
- package/src/tools/agent-security-tool.ts +145 -0
- package/src/tools/agent-sessions-tool.ts +122 -0
- package/src/tools/agent-settings-import-tool.ts +104 -0
- package/src/tools/agent-settings-tool.ts +176 -0
- package/src/tools/agent-setup-tool.ts +226 -0
- package/src/tools/agent-support-tool.ts +122 -0
- package/src/tools/agent-terminal-process-tools.ts +167 -0
- package/src/tools/agent-tool-policy-guard-types.ts +77 -0
- package/src/tools/agent-tool-policy-guard.ts +106 -85
- package/src/tools/agent-vibe-tool.ts +297 -0
- package/src/tools/agent-work-plan-tool.ts +265 -6
- package/src/tools/agent-workspace-tool.ts +305 -0
- package/src/tools/artifact-archive.ts +169 -0
- package/src/tools/tool-definition-compaction.ts +36 -0
- package/src/version.ts +1 -1
|
@@ -4,109 +4,34 @@ import type { ShellPathService } from '@/runtime/index.ts';
|
|
|
4
4
|
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
5
5
|
import { assertNoSecretLikeText } from './persona-registry.ts';
|
|
6
6
|
import { formatAgentRecordReviewState } from './record-labels.ts';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
readonly procedure: string;
|
|
36
|
-
readonly triggers: readonly string[];
|
|
37
|
-
readonly tags: readonly string[];
|
|
38
|
-
readonly requirements: readonly AgentSkillRequirement[];
|
|
39
|
-
readonly enabled: boolean;
|
|
40
|
-
readonly source: AgentSkillSource;
|
|
41
|
-
readonly provenance: string;
|
|
42
|
-
readonly reviewState: AgentSkillReviewState;
|
|
43
|
-
readonly staleReason?: string;
|
|
44
|
-
readonly createdAt: string;
|
|
45
|
-
readonly updatedAt: string;
|
|
46
|
-
readonly reviewedAt?: string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export interface AgentSkillBundleRecord {
|
|
50
|
-
readonly id: string;
|
|
51
|
-
readonly name: string;
|
|
52
|
-
readonly description: string;
|
|
53
|
-
readonly skillIds: readonly string[];
|
|
54
|
-
readonly enabled: boolean;
|
|
55
|
-
readonly source: AgentSkillSource;
|
|
56
|
-
readonly provenance: string;
|
|
57
|
-
readonly reviewState: AgentSkillReviewState;
|
|
58
|
-
readonly staleReason?: string;
|
|
59
|
-
readonly createdAt: string;
|
|
60
|
-
readonly updatedAt: string;
|
|
61
|
-
readonly reviewedAt?: string;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface AgentSkillCreateInput {
|
|
65
|
-
readonly name: string;
|
|
66
|
-
readonly description: string;
|
|
67
|
-
readonly procedure: string;
|
|
68
|
-
readonly triggers?: readonly string[];
|
|
69
|
-
readonly tags?: readonly string[];
|
|
70
|
-
readonly requirements?: readonly AgentSkillRequirement[];
|
|
71
|
-
readonly enabled?: boolean;
|
|
72
|
-
readonly source?: AgentSkillSource;
|
|
73
|
-
readonly provenance?: string;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export interface AgentSkillBundleCreateInput {
|
|
77
|
-
readonly name: string;
|
|
78
|
-
readonly description: string;
|
|
79
|
-
readonly skillIds: readonly string[];
|
|
80
|
-
readonly enabled?: boolean;
|
|
81
|
-
readonly source?: AgentSkillSource;
|
|
82
|
-
readonly provenance?: string;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export interface AgentSkillUpdateInput {
|
|
86
|
-
readonly name?: string;
|
|
87
|
-
readonly description?: string;
|
|
88
|
-
readonly procedure?: string;
|
|
89
|
-
readonly triggers?: readonly string[];
|
|
90
|
-
readonly tags?: readonly string[];
|
|
91
|
-
readonly requirements?: readonly AgentSkillRequirement[];
|
|
92
|
-
readonly provenance?: string;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export interface AgentSkillBundleUpdateInput {
|
|
96
|
-
readonly name?: string;
|
|
97
|
-
readonly description?: string;
|
|
98
|
-
readonly skillIds?: readonly string[];
|
|
99
|
-
readonly provenance?: string;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export interface AgentSkillSnapshot {
|
|
103
|
-
readonly path: string;
|
|
104
|
-
readonly skills: readonly AgentSkillRecord[];
|
|
105
|
-
readonly enabledSkills: readonly AgentSkillRecord[];
|
|
106
|
-
readonly bundles: readonly AgentSkillBundleRecord[];
|
|
107
|
-
readonly enabledBundles: readonly AgentSkillBundleRecord[];
|
|
108
|
-
readonly activeSkills: readonly AgentSkillRecord[];
|
|
109
|
-
}
|
|
7
|
+
import type {
|
|
8
|
+
AgentSkillBundleCreateInput,
|
|
9
|
+
AgentSkillBundleReadiness,
|
|
10
|
+
AgentSkillBundleRecord,
|
|
11
|
+
AgentSkillBundleUpdateInput,
|
|
12
|
+
AgentSkillCreateInput,
|
|
13
|
+
AgentSkillReadiness,
|
|
14
|
+
AgentSkillRecord,
|
|
15
|
+
AgentSkillRequirement,
|
|
16
|
+
AgentSkillRequirementKind,
|
|
17
|
+
AgentSkillSnapshot,
|
|
18
|
+
AgentSkillUpdateInput,
|
|
19
|
+
} from './skill-registry-types.ts';
|
|
20
|
+
export type {
|
|
21
|
+
AgentSkillBundleCreateInput,
|
|
22
|
+
AgentSkillBundleReadiness,
|
|
23
|
+
AgentSkillBundleRecord,
|
|
24
|
+
AgentSkillBundleUpdateInput,
|
|
25
|
+
AgentSkillCreateInput,
|
|
26
|
+
AgentSkillReadiness,
|
|
27
|
+
AgentSkillRecord,
|
|
28
|
+
AgentSkillRequirement,
|
|
29
|
+
AgentSkillRequirementKind,
|
|
30
|
+
AgentSkillReviewState,
|
|
31
|
+
AgentSkillSnapshot,
|
|
32
|
+
AgentSkillSource,
|
|
33
|
+
AgentSkillUpdateInput,
|
|
34
|
+
} from './skill-registry-types.ts';
|
|
110
35
|
|
|
111
36
|
interface SkillStoreFile {
|
|
112
37
|
readonly version: 1;
|
|
@@ -754,13 +679,55 @@ export function evaluateAgentSkillBundleReadiness(
|
|
|
754
679
|
|
|
755
680
|
export function buildEnabledSkillsPrompt(shellPaths: ShellPathService): string | null {
|
|
756
681
|
const snapshot = AgentSkillRegistry.fromShellPaths(shellPaths).snapshot();
|
|
757
|
-
const
|
|
758
|
-
|
|
682
|
+
const enabledBundles = snapshot.enabledBundles.filter((bundle) => {
|
|
683
|
+
if (bundle.reviewState !== 'reviewed') return false;
|
|
684
|
+
const readiness = evaluateAgentSkillBundleReadiness(bundle, snapshot.skills);
|
|
685
|
+
return readiness.ready && readiness.includedSkills.every((skill) => skill.reviewState === 'reviewed');
|
|
686
|
+
});
|
|
687
|
+
const activeSkillIds = new Set([
|
|
688
|
+
...snapshot.enabledSkills.map((skill) => skill.id),
|
|
689
|
+
...enabledBundles.flatMap((bundle) => bundle.skillIds),
|
|
690
|
+
]);
|
|
691
|
+
const active = snapshot.skills.filter((skill) => (
|
|
692
|
+
activeSkillIds.has(skill.id)
|
|
693
|
+
&& skill.reviewState === 'reviewed'
|
|
694
|
+
&& evaluateAgentSkillReadiness(skill).ready
|
|
695
|
+
));
|
|
696
|
+
const candidateSkillIds = new Set([
|
|
697
|
+
...snapshot.enabledSkills.map((skill) => skill.id),
|
|
698
|
+
...snapshot.enabledBundles.flatMap((bundle) => bundle.skillIds),
|
|
699
|
+
]);
|
|
700
|
+
const suppressedSkills = snapshot.skills
|
|
701
|
+
.filter((skill) => candidateSkillIds.has(skill.id) && !active.some((activeSkill) => activeSkill.id === skill.id))
|
|
702
|
+
.slice(0, 8)
|
|
703
|
+
.map((skill) => {
|
|
704
|
+
const readiness = evaluateAgentSkillReadiness(skill);
|
|
705
|
+
const review = skill.reviewState === 'reviewed' ? '' : `review=${formatAgentRecordReviewState(skill.reviewState)}`;
|
|
706
|
+
const setup = readiness.ready ? '' : `missing=${readiness.missing.map(formatAgentSkillRequirement).join(', ')}`;
|
|
707
|
+
return `- ${skill.name}: ${[review, setup].filter(Boolean).join('; ')}`;
|
|
708
|
+
});
|
|
709
|
+
const suppressedBundles = snapshot.enabledBundles
|
|
710
|
+
.filter((bundle) => !enabledBundles.some((activeBundle) => activeBundle.id === bundle.id))
|
|
711
|
+
.slice(0, 4)
|
|
712
|
+
.map((bundle) => {
|
|
713
|
+
const readiness = evaluateAgentSkillBundleReadiness(bundle, snapshot.skills);
|
|
714
|
+
const review = bundle.reviewState === 'reviewed' ? '' : `review=${formatAgentRecordReviewState(bundle.reviewState)}`;
|
|
715
|
+
const setup = readiness.ready ? '' : `missing=${[
|
|
716
|
+
...readiness.missingRequirements.map(formatAgentSkillRequirement),
|
|
717
|
+
...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
|
|
718
|
+
].join(', ')}`;
|
|
719
|
+
const unreviewedSkills = readiness.includedSkills
|
|
720
|
+
.filter((skill) => skill.reviewState !== 'reviewed')
|
|
721
|
+
.map((skill) => `${skill.id}:${formatAgentRecordReviewState(skill.reviewState)}`);
|
|
722
|
+
const memberReview = unreviewedSkills.length === 0 ? '' : `member-review=${unreviewedSkills.join(', ')}`;
|
|
723
|
+
return `- ${bundle.name}: ${[review, setup, memberReview].filter(Boolean).join('; ')}`;
|
|
724
|
+
});
|
|
725
|
+
if (active.length === 0 && enabledBundles.length === 0 && suppressedSkills.length === 0 && suppressedBundles.length === 0) return null;
|
|
759
726
|
return [
|
|
760
727
|
'## Enabled GoodVibes Agent Skills',
|
|
761
|
-
'Use
|
|
728
|
+
'Use only reviewed, setup-ready local reusable procedures inside the same serial assistant conversation when they fit the user request.',
|
|
762
729
|
'',
|
|
763
|
-
...
|
|
730
|
+
...enabledBundles.slice(0, 4).flatMap((bundle) => {
|
|
764
731
|
const readiness = evaluateAgentSkillBundleReadiness(bundle, snapshot.skills);
|
|
765
732
|
const missing = [
|
|
766
733
|
...readiness.missingRequirements.map(formatAgentSkillRequirement),
|
|
@@ -784,5 +751,12 @@ export function buildEnabledSkillsPrompt(shellPaths: ShellPathService): string |
|
|
|
784
751
|
skill.procedure,
|
|
785
752
|
'',
|
|
786
753
|
]),
|
|
754
|
+
...(suppressedBundles.length > 0 || suppressedSkills.length > 0 ? [
|
|
755
|
+
'### Suppressed Skills Pending Review Or Setup',
|
|
756
|
+
'Do not apply these skills until the user reviews them or resolves setup through the learning curator.',
|
|
757
|
+
...suppressedBundles,
|
|
758
|
+
...suppressedSkills,
|
|
759
|
+
'',
|
|
760
|
+
] : []),
|
|
787
761
|
].join('\n').trim();
|
|
788
762
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export function vibeRouteArg(value: string): string {
|
|
2
|
+
return JSON.stringify(value);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function routeLine(id: string, route: string): string {
|
|
6
|
+
return ` ${id} ${route}`;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function vibeInitConfirmationRoutes(scope: 'project' | 'global', force = false): Record<string, string> {
|
|
10
|
+
const model = [
|
|
11
|
+
'vibe action:"init"',
|
|
12
|
+
`scope:${vibeRouteArg(scope)}`,
|
|
13
|
+
force ? 'force:true' : '',
|
|
14
|
+
'confirm:true',
|
|
15
|
+
'explicitUserRequest:"..."',
|
|
16
|
+
].filter(Boolean).join(' ');
|
|
17
|
+
const cli = [
|
|
18
|
+
'/vibe init',
|
|
19
|
+
scope === 'global' ? '--global' : '',
|
|
20
|
+
force ? '--force' : '',
|
|
21
|
+
'--yes',
|
|
22
|
+
].filter(Boolean).join(' ');
|
|
23
|
+
return { model, cli };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function vibeImportPersonaConfirmationRoutes(input: {
|
|
27
|
+
readonly reference: string;
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly description: string;
|
|
30
|
+
readonly review: boolean;
|
|
31
|
+
readonly use: boolean;
|
|
32
|
+
}): Record<string, string> {
|
|
33
|
+
const model = [
|
|
34
|
+
'vibe action:"import_persona"',
|
|
35
|
+
`reference:${vibeRouteArg(input.reference)}`,
|
|
36
|
+
input.name ? `name:${vibeRouteArg(input.name)}` : '',
|
|
37
|
+
input.description ? `description:${vibeRouteArg(input.description)}` : '',
|
|
38
|
+
input.review ? 'review:true' : '',
|
|
39
|
+
input.use ? 'use:true' : '',
|
|
40
|
+
'confirm:true',
|
|
41
|
+
'explicitUserRequest:"..."',
|
|
42
|
+
].filter(Boolean).join(' ');
|
|
43
|
+
const cli = [
|
|
44
|
+
'/vibe import-persona',
|
|
45
|
+
vibeRouteArg(input.reference),
|
|
46
|
+
input.name ? `--name ${vibeRouteArg(input.name)}` : '',
|
|
47
|
+
input.description ? `--description ${vibeRouteArg(input.description)}` : '',
|
|
48
|
+
input.review ? '--review' : '',
|
|
49
|
+
input.use ? '--use' : '',
|
|
50
|
+
'--yes',
|
|
51
|
+
].filter(Boolean).join(' ');
|
|
52
|
+
return { model, cli };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function formatVibeConfirmationRouteLines(routes: Record<string, string>): readonly string[] {
|
|
56
|
+
const entries = Object.entries(routes).filter(([, route]) => route.trim() !== '');
|
|
57
|
+
if (entries.length === 0) return [];
|
|
58
|
+
return [
|
|
59
|
+
' confirmationRoutes',
|
|
60
|
+
...entries.map(([id, route]) => routeLine(id, route)),
|
|
61
|
+
];
|
|
62
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
3
|
+
import type { ShellPathService } from '@/runtime/index.ts';
|
|
4
|
+
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
5
|
+
import { assertNoSecretLikeText } from './persona-registry.ts';
|
|
6
|
+
|
|
7
|
+
export type AgentVibeScope = 'project' | 'global';
|
|
8
|
+
|
|
9
|
+
export interface AgentVibeFile {
|
|
10
|
+
readonly path: string;
|
|
11
|
+
readonly scope: AgentVibeScope;
|
|
12
|
+
readonly body: string;
|
|
13
|
+
readonly frontmatter: Record<string, string>;
|
|
14
|
+
readonly truncated: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface BlockedAgentVibeFile {
|
|
18
|
+
readonly path: string;
|
|
19
|
+
readonly scope: AgentVibeScope;
|
|
20
|
+
readonly reason: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AgentVibeSnapshot {
|
|
24
|
+
readonly files: readonly AgentVibeFile[];
|
|
25
|
+
readonly blocked: readonly BlockedAgentVibeFile[];
|
|
26
|
+
readonly searchedPaths: readonly string[];
|
|
27
|
+
readonly projectInitPath: string;
|
|
28
|
+
readonly globalInitPath: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface AgentVibeInitOptions {
|
|
32
|
+
readonly scope?: AgentVibeScope;
|
|
33
|
+
readonly force?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface AgentVibeInitResult {
|
|
37
|
+
readonly path: string;
|
|
38
|
+
readonly created: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface AgentVibeImportSource {
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly description: string;
|
|
44
|
+
readonly body: string;
|
|
45
|
+
readonly path: string;
|
|
46
|
+
readonly scope: AgentVibeScope;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const MAX_VIBE_BODY_CHARS = 8_000;
|
|
50
|
+
const MAX_PROJECT_DEPTH = 32;
|
|
51
|
+
|
|
52
|
+
const DEFAULT_VIBE_BODY = [
|
|
53
|
+
'# VIBE.md',
|
|
54
|
+
'',
|
|
55
|
+
'Describe how GoodVibes Agent should feel and work with you.',
|
|
56
|
+
'',
|
|
57
|
+
'- Be direct about tradeoffs.',
|
|
58
|
+
'- Prefer visible, reversible actions.',
|
|
59
|
+
'- Keep autonomous work user-supervised with clear status and cancel paths.',
|
|
60
|
+
'- Ask before sending messages, changing settings, or starting recurring work.',
|
|
61
|
+
].join('\n');
|
|
62
|
+
|
|
63
|
+
type AgentVibePaths = Pick<ShellPathService,
|
|
64
|
+
'workingDirectory' | 'homeDirectory' | 'resolveUserPath' | 'expandHomePath' | 'resolveWorkspacePath'
|
|
65
|
+
>;
|
|
66
|
+
|
|
67
|
+
function parseFrontmatter(content: string): Record<string, string> {
|
|
68
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
69
|
+
if (!match) return {};
|
|
70
|
+
const result: Record<string, string> = {};
|
|
71
|
+
for (const line of match[1].split('\n')) {
|
|
72
|
+
const [key, ...rest] = line.split(':');
|
|
73
|
+
if (key && rest.length > 0) result[key.trim()] = rest.join(':').trim();
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function markdownBody(content: string): string {
|
|
79
|
+
const frontmatter = parseFrontmatter(content);
|
|
80
|
+
const body = (frontmatter.system_prompt ?? content.replace(/^---\n[\s\S]*?\n---\n?/, '')).trim();
|
|
81
|
+
return body;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function readVibeCandidate(path: string, scope: AgentVibeScope): AgentVibeFile | BlockedAgentVibeFile | null {
|
|
85
|
+
if (!existsSync(path)) return null;
|
|
86
|
+
let content = '';
|
|
87
|
+
try {
|
|
88
|
+
content = readFileSync(path, 'utf-8');
|
|
89
|
+
} catch (error) {
|
|
90
|
+
return {
|
|
91
|
+
path,
|
|
92
|
+
scope,
|
|
93
|
+
reason: `Could not read file: ${error instanceof Error ? error.message : String(error)}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const body = markdownBody(content);
|
|
98
|
+
if (!body) return {
|
|
99
|
+
path,
|
|
100
|
+
scope,
|
|
101
|
+
reason: 'File is empty after frontmatter.',
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
assertNoSecretLikeText([content], 'VIBE.md');
|
|
106
|
+
} catch (error) {
|
|
107
|
+
return {
|
|
108
|
+
path,
|
|
109
|
+
scope,
|
|
110
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
path,
|
|
116
|
+
scope,
|
|
117
|
+
body: body.length > MAX_VIBE_BODY_CHARS ? body.slice(0, MAX_VIBE_BODY_CHARS).trimEnd() : body,
|
|
118
|
+
frontmatter: parseFrontmatter(content),
|
|
119
|
+
truncated: body.length > MAX_VIBE_BODY_CHARS,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function projectWalkRoots(workingDirectory: string): readonly string[] {
|
|
124
|
+
const roots: string[] = [];
|
|
125
|
+
let current = resolve(workingDirectory);
|
|
126
|
+
let foundGitRoot = false;
|
|
127
|
+
for (let depth = 0; depth < MAX_PROJECT_DEPTH; depth += 1) {
|
|
128
|
+
roots.push(current);
|
|
129
|
+
if (existsSync(join(current, '.git'))) {
|
|
130
|
+
foundGitRoot = true;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
const parent = dirname(current);
|
|
134
|
+
if (parent === current) break;
|
|
135
|
+
current = parent;
|
|
136
|
+
}
|
|
137
|
+
if (!foundGitRoot) return [resolve(workingDirectory)];
|
|
138
|
+
return roots.reverse();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function candidatePaths(shellPaths: AgentVibePaths): readonly { readonly path: string; readonly scope: AgentVibeScope }[] {
|
|
142
|
+
const candidates: Array<{ path: string; scope: AgentVibeScope }> = [];
|
|
143
|
+
candidates.push({ path: join(shellPaths.homeDirectory, '.goodvibes', 'VIBE.md'), scope: 'global' });
|
|
144
|
+
candidates.push({ path: shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'VIBE.md'), scope: 'global' });
|
|
145
|
+
for (const root of projectWalkRoots(shellPaths.workingDirectory)) {
|
|
146
|
+
candidates.push({ path: join(root, 'VIBE.md'), scope: 'project' });
|
|
147
|
+
candidates.push({ path: join(root, '.goodvibes', 'VIBE.md'), scope: 'project' });
|
|
148
|
+
candidates.push({ path: join(root, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'VIBE.md'), scope: 'project' });
|
|
149
|
+
}
|
|
150
|
+
return candidates;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function dedupeCandidates(candidates: readonly { readonly path: string; readonly scope: AgentVibeScope }[]): readonly { readonly path: string; readonly scope: AgentVibeScope }[] {
|
|
154
|
+
const seen = new Set<string>();
|
|
155
|
+
const result: Array<{ path: string; scope: AgentVibeScope }> = [];
|
|
156
|
+
for (const candidate of candidates) {
|
|
157
|
+
const key = resolve(candidate.path);
|
|
158
|
+
if (seen.has(key)) continue;
|
|
159
|
+
seen.add(key);
|
|
160
|
+
result.push({ path: key, scope: candidate.scope });
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function projectVibeInitPath(shellPaths: Pick<ShellPathService, 'workingDirectory'>): string {
|
|
166
|
+
return join(shellPaths.workingDirectory, 'VIBE.md');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function globalVibeInitPath(shellPaths: Pick<ShellPathService, 'resolveUserPath'>): string {
|
|
170
|
+
return shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'VIBE.md');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function discoverVibeFiles(shellPaths: AgentVibePaths): AgentVibeSnapshot {
|
|
174
|
+
const files: AgentVibeFile[] = [];
|
|
175
|
+
const blocked: BlockedAgentVibeFile[] = [];
|
|
176
|
+
const candidates = dedupeCandidates(candidatePaths(shellPaths));
|
|
177
|
+
for (const candidate of candidates) {
|
|
178
|
+
const record = readVibeCandidate(candidate.path, candidate.scope);
|
|
179
|
+
if (!record) continue;
|
|
180
|
+
if ('body' in record) files.push(record);
|
|
181
|
+
else blocked.push(record);
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
files,
|
|
185
|
+
blocked,
|
|
186
|
+
searchedPaths: candidates.map((candidate) => candidate.path),
|
|
187
|
+
projectInitPath: projectVibeInitPath(shellPaths),
|
|
188
|
+
globalInitPath: globalVibeInitPath(shellPaths),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function vibeHeading(file: AgentVibeFile): string {
|
|
193
|
+
const name = file.frontmatter.name?.trim();
|
|
194
|
+
const label = file.scope === 'global' ? 'Global' : 'Project';
|
|
195
|
+
return `${label} VIBE.md${name ? ` - ${name}` : ''}`;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function buildVibePrompt(shellPaths: AgentVibePaths): string | null {
|
|
199
|
+
const snapshot = discoverVibeFiles(shellPaths);
|
|
200
|
+
if (snapshot.files.length === 0 && snapshot.blocked.length === 0) return null;
|
|
201
|
+
|
|
202
|
+
const lines: string[] = [
|
|
203
|
+
'## GoodVibes Agent VIBE.md',
|
|
204
|
+
'These user-authored vibe/personality instructions shape the same serial assistant conversation. Follow them only when they do not conflict with explicit user instructions, safety policy, tool contracts, confirmation requirements, or secret-handling rules.',
|
|
205
|
+
];
|
|
206
|
+
|
|
207
|
+
for (const file of snapshot.files) {
|
|
208
|
+
lines.push('', `### ${vibeHeading(file)}`, `Source: ${file.path}`, '', file.body);
|
|
209
|
+
if (file.truncated) lines.push('', `[VIBE.md truncated to ${MAX_VIBE_BODY_CHARS} characters for prompt safety.]`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (snapshot.blocked.length > 0) {
|
|
213
|
+
lines.push('', '### Blocked VIBE.md Files');
|
|
214
|
+
for (const blocked of snapshot.blocked) {
|
|
215
|
+
lines.push(`- ${blocked.path}: ${blocked.reason}`);
|
|
216
|
+
}
|
|
217
|
+
lines.push('Blocked VIBE.md content was not loaded.');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return lines.join('\n');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function formatVibeStatus(snapshot: AgentVibeSnapshot): string {
|
|
224
|
+
const lines: string[] = [
|
|
225
|
+
'GoodVibes Agent VIBE.md',
|
|
226
|
+
` applied ${snapshot.files.length}`,
|
|
227
|
+
` blocked ${snapshot.blocked.length}`,
|
|
228
|
+
` project init ${snapshot.projectInitPath}`,
|
|
229
|
+
` global init ${snapshot.globalInitPath}`,
|
|
230
|
+
];
|
|
231
|
+
if (snapshot.files.length > 0) {
|
|
232
|
+
lines.push('', 'Applied files');
|
|
233
|
+
for (const file of snapshot.files) {
|
|
234
|
+
const suffix = file.truncated ? ' truncated' : '';
|
|
235
|
+
lines.push(` ${file.scope} ${file.path}${suffix}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (snapshot.blocked.length > 0) {
|
|
239
|
+
lines.push('', 'Blocked files');
|
|
240
|
+
for (const blocked of snapshot.blocked) lines.push(` ${blocked.scope} ${blocked.path} - ${blocked.reason}`);
|
|
241
|
+
}
|
|
242
|
+
lines.push(
|
|
243
|
+
'',
|
|
244
|
+
'Next',
|
|
245
|
+
' /vibe init --yes',
|
|
246
|
+
' /vibe init --global --yes',
|
|
247
|
+
' /vibe import-persona project --review --use --yes',
|
|
248
|
+
);
|
|
249
|
+
return lines.join('\n');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function initVibeFile(shellPaths: AgentVibePaths, options: AgentVibeInitOptions = {}): AgentVibeInitResult {
|
|
253
|
+
const path = options.scope === 'global' ? globalVibeInitPath(shellPaths) : projectVibeInitPath(shellPaths);
|
|
254
|
+
if (existsSync(path) && !options.force) return { path, created: false };
|
|
255
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
256
|
+
writeFileSync(path, `${DEFAULT_VIBE_BODY}\n`, 'utf-8');
|
|
257
|
+
return { path, created: true };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export function resolveVibePathReference(shellPaths: AgentVibePaths, reference: string): string {
|
|
261
|
+
const trimmed = reference.trim();
|
|
262
|
+
if (!trimmed || trimmed === 'project') return projectVibeInitPath(shellPaths);
|
|
263
|
+
if (trimmed === 'global') return globalVibeInitPath(shellPaths);
|
|
264
|
+
const expanded = shellPaths.expandHomePath(trimmed);
|
|
265
|
+
return isAbsolute(expanded) ? resolve(expanded) : shellPaths.resolveWorkspacePath(expanded);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function loadVibeImportSource(shellPaths: AgentVibePaths, reference: string): AgentVibeImportSource {
|
|
269
|
+
const path = resolveVibePathReference(shellPaths, reference);
|
|
270
|
+
const scope: AgentVibeScope = path.startsWith(resolve(shellPaths.homeDirectory, '.goodvibes')) ? 'global' : 'project';
|
|
271
|
+
const record = readVibeCandidate(path, scope);
|
|
272
|
+
if (!record) throw new Error(`No VIBE.md found at ${path}`);
|
|
273
|
+
if (!('body' in record)) throw new Error(`Cannot import VIBE.md from ${path}: ${record.reason}`);
|
|
274
|
+
const name = record.frontmatter.name?.trim() || (record.scope === 'global' ? 'Global Vibe' : 'Project Vibe');
|
|
275
|
+
const description = record.frontmatter.description?.trim()
|
|
276
|
+
|| record.frontmatter.summary?.trim()
|
|
277
|
+
|| `Imported ${record.scope} VIBE.md personality instructions.`;
|
|
278
|
+
return {
|
|
279
|
+
name,
|
|
280
|
+
description,
|
|
281
|
+
body: record.body,
|
|
282
|
+
path: record.path,
|
|
283
|
+
scope: record.scope,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
@@ -282,7 +282,7 @@ export async function handleAgentKnowledgeCommand(runtime: CliCommandRuntime): P
|
|
|
282
282
|
};
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
if (normalized === 'ingest-file'
|
|
285
|
+
if (normalized === 'ingest-file') {
|
|
286
286
|
const values = commandValues(rest);
|
|
287
287
|
const path = values[0];
|
|
288
288
|
if (!path) return { output: 'Usage: goodvibes-agent knowledge ingest-file <path> [--title <title>] [--tags a,b] [--folder <path>] --yes', exitCode: 2 };
|
|
@@ -326,6 +326,49 @@ export async function handleAgentKnowledgeCommand(runtime: CliCommandRuntime): P
|
|
|
326
326
|
};
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
if (normalized === 'ingest-artifact') {
|
|
330
|
+
const values = commandValues(rest);
|
|
331
|
+
const artifactId = values[0];
|
|
332
|
+
if (!artifactId) return { output: 'Usage: goodvibes-agent knowledge ingest-artifact <artifactId> [--title <title>] [--tags a,b] [--folder <path>] --yes', exitCode: 2 };
|
|
333
|
+
if (!confirmation.present) {
|
|
334
|
+
const failure = {
|
|
335
|
+
ok: false,
|
|
336
|
+
kind: 'confirmation_required',
|
|
337
|
+
error: `Refusing to ingest artifact into Agent Knowledge ${artifactId} without --yes.`,
|
|
338
|
+
route: AGENT_KNOWLEDGE_METHODS.ingestArtifact.route,
|
|
339
|
+
};
|
|
340
|
+
return {
|
|
341
|
+
output: json ? JSON.stringify(failure, null, 2) : `${failure.error}\nUsage: goodvibes-agent knowledge ingest-artifact <artifactId> [--title <title>] [--tags a,b] [--folder <path>] --yes`,
|
|
342
|
+
exitCode: 2,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const title = readOptionValue(rest, '--title');
|
|
346
|
+
const tags = readStringList(rest, '--tags');
|
|
347
|
+
const folderPath = readOptionValue(rest, '--folder');
|
|
348
|
+
const connectorId = readOptionValue(rest, '--connector') ?? 'goodvibes-agent-artifact-browser';
|
|
349
|
+
const result = await runKnowledgeCall(runtime, AGENT_KNOWLEDGE_METHODS.ingestArtifact, async (connection) => (
|
|
350
|
+
await postAgentKnowledgeJson(connection, AGENT_KNOWLEDGE_METHODS.ingestArtifact.route, {
|
|
351
|
+
artifactId,
|
|
352
|
+
title,
|
|
353
|
+
tags,
|
|
354
|
+
folderPath,
|
|
355
|
+
connectorId,
|
|
356
|
+
metadata: { originSurface: 'goodvibes-agent-cli' },
|
|
357
|
+
})
|
|
358
|
+
));
|
|
359
|
+
if (!result.ok) return { output: formatFailure(result, json), exitCode: 1 };
|
|
360
|
+
return {
|
|
361
|
+
output: formatJsonOrText(runtime.cli)(result, formatIngest(
|
|
362
|
+
result.data,
|
|
363
|
+
artifactId,
|
|
364
|
+
'ingest-artifact',
|
|
365
|
+
'/api/goodvibes-agent/knowledge/ingest/artifact',
|
|
366
|
+
'artifact',
|
|
367
|
+
)),
|
|
368
|
+
exitCode: 0,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
329
372
|
if (normalized === 'import-urls' || normalized === 'import-bookmarks') {
|
|
330
373
|
const values = commandValues(rest);
|
|
331
374
|
const path = values[0];
|
|
@@ -460,7 +503,7 @@ export async function handleAgentKnowledgeCommand(runtime: CliCommandRuntime): P
|
|
|
460
503
|
}
|
|
461
504
|
|
|
462
505
|
return {
|
|
463
|
-
output: 'Usage: goodvibes-agent knowledge [status|ask <question>|search <query>|list|sources|nodes|issues|get <id>|map|connectors|ingest-url <url> --yes|ingest-file <path> --yes|ingest-connector <id> --yes|import-urls <path> --yes|import-bookmarks <path> --yes|import-browser-history --yes|reindex --yes]',
|
|
506
|
+
output: 'Usage: goodvibes-agent knowledge [status|ask <question>|search <query>|list|sources|nodes|issues|get <id>|map|connectors|ingest-url <url> --yes|ingest-file <path> --yes|ingest-artifact <artifactId> --yes|ingest-connector <id> --yes|import-urls <path> --yes|import-bookmarks <path> --yes|import-browser-history --yes|reindex --yes]',
|
|
464
507
|
exitCode: 2,
|
|
465
508
|
};
|
|
466
509
|
}
|
package/src/cli/help.ts
CHANGED
|
@@ -38,6 +38,7 @@ export function renderGoodVibesHelp(binary = 'goodvibes-agent'): string {
|
|
|
38
38
|
' /model Choose provider and model',
|
|
39
39
|
' /knowledge Use isolated Agent Knowledge',
|
|
40
40
|
' /notes Open Agent-local scratchpad notes',
|
|
41
|
+
' /vibe Inspect or create VIBE.md personality',
|
|
41
42
|
' /personas, /skills Tune Agent-local behavior',
|
|
42
43
|
' /routines Run local routines in the main conversation',
|
|
43
44
|
' /schedule remind Create confirmed reminders or inspect schedules',
|
|
@@ -309,6 +310,7 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
|
|
|
309
310
|
'knowledge connectors [connectorId|doctor <connectorId>]',
|
|
310
311
|
'knowledge ingest-url <url> [--title <title>] [--tags a,b] --yes',
|
|
311
312
|
'knowledge ingest-file <path> [--title <title>] [--tags a,b] --yes',
|
|
313
|
+
'knowledge ingest-artifact <artifactId> [--title <title>] [--tags a,b] --yes',
|
|
312
314
|
'knowledge ingest-connector <connectorId> [--input <json-or-text>|--path <path>|--content <text>] --yes',
|
|
313
315
|
'knowledge import-urls <path> --yes',
|
|
314
316
|
'knowledge import-bookmarks <path> --yes',
|
|
@@ -325,6 +327,7 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
|
|
|
325
327
|
'knowledge connectors doctor url',
|
|
326
328
|
'knowledge ingest-url https://example.com/page --title "Reference" --yes',
|
|
327
329
|
'knowledge ingest-file ./docs/guide.md --title "Guide" --yes',
|
|
330
|
+
'knowledge ingest-artifact artifact-123 --title "Reviewed Export" --yes',
|
|
328
331
|
'knowledge ingest-connector url --input https://example.com/reference --yes',
|
|
329
332
|
'knowledge import-urls ~/agent-links.txt --yes',
|
|
330
333
|
'knowledge import-browser-history --browsers chrome,firefox --sources history,bookmark --yes',
|