@pellux/goodvibes-agent 1.1.7 → 1.3.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 +329 -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 +138903 -91477
- 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 +58 -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 +116 -45
- package/docs/voice-and-live-tts.md +3 -1
- package/package.json +3 -2
- package/release/release-notes.md +142 -5
- package/release/release-readiness.json +124 -94
- 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 +294 -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-artifact-receipts.ts +366 -0
- package/src/agent/setup-wizard-checkpoint.ts +140 -0
- package/src/agent/setup-wizard.ts +683 -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 +313 -30
- package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
- package/src/input/agent-workspace-setup-snapshot.ts +217 -0
- package/src/input/agent-workspace-setup.ts +61 -1
- package/src/input/agent-workspace-snapshot.ts +184 -149
- package/src/input/agent-workspace-types.ts +287 -2
- package/src/input/agent-workspace.ts +23 -1
- 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/input/setup-wizard-live-receipts.ts +76 -0
- package/src/main.ts +15 -15
- package/src/panels/qr-panel.ts +2 -2
- package/src/renderer/agent-workspace-context-lines.ts +701 -0
- package/src/renderer/agent-workspace.ts +68 -421
- 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-policy.ts +75 -0
- package/src/tools/agent-harness-agent-orchestration.ts +791 -0
- package/src/tools/agent-harness-autonomy-intake.ts +785 -0
- package/src/tools/agent-harness-autonomy-live-records.ts +742 -0
- package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
- package/src/tools/agent-harness-autonomy-queue.ts +571 -0
- package/src/tools/agent-harness-autonomy-watcher-read-models.ts +509 -0
- package/src/tools/agent-harness-background-processes-types.ts +35 -0
- package/src/tools/agent-harness-background-processes.ts +798 -0
- package/src/tools/agent-harness-browser-cockpit-route.ts +373 -0
- package/src/tools/agent-harness-browser-control.ts +346 -0
- package/src/tools/agent-harness-browser-pwa-read-models.ts +622 -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-device-live-read-models.ts +366 -0
- 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 +385 -0
- package/src/tools/agent-harness-file-recovery.ts +135 -0
- package/src/tools/agent-harness-interactive-runtime-records.ts +421 -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 +269 -0
- package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
- package/src/tools/agent-harness-local-model-endpoints.ts +788 -0
- package/src/tools/agent-harness-local-model-smoke.ts +277 -0
- package/src/tools/agent-harness-local-model-url.ts +78 -0
- package/src/tools/agent-harness-media-posture.ts +223 -2
- package/src/tools/agent-harness-memory-external-providers.ts +796 -0
- package/src/tools/agent-harness-memory-posture.ts +672 -0
- package/src/tools/agent-harness-memory-provider-certification.ts +219 -0
- package/src/tools/agent-harness-memory-refinement.ts +340 -0
- package/src/tools/agent-harness-metadata.ts +100 -168
- package/src/tools/agent-harness-mode-catalog.ts +86 -33
- package/src/tools/agent-harness-model-catalog.ts +162 -0
- package/src/tools/agent-harness-model-provider-health.ts +283 -0
- package/src/tools/agent-harness-model-readiness.ts +432 -0
- package/src/tools/agent-harness-model-routing-types.ts +327 -0
- package/src/tools/agent-harness-model-routing-utils.ts +30 -0
- package/src/tools/agent-harness-model-routing.ts +165 -193
- package/src/tools/agent-harness-operator-methods.ts +115 -133
- package/src/tools/agent-harness-pairing-posture.ts +452 -18
- package/src/tools/agent-harness-personal-ops-certification.ts +116 -0
- 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 +270 -0
- package/src/tools/agent-harness-personal-ops-operations.ts +225 -0
- package/src/tools/agent-harness-personal-ops-provider-records.ts +358 -0
- package/src/tools/agent-harness-personal-ops-provider-task-records.ts +321 -0
- package/src/tools/agent-harness-personal-ops-records.ts +684 -0
- package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
- package/src/tools/agent-harness-personal-ops-types.ts +240 -0
- package/src/tools/agent-harness-personal-ops.ts +613 -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-remote-read-models.ts +541 -0
- package/src/tools/agent-harness-research-briefing.ts +446 -0
- package/src/tools/agent-harness-research-live-read-models.ts +500 -0
- package/src/tools/agent-harness-research-queue.ts +250 -0
- package/src/tools/agent-harness-research-runs.ts +307 -0
- package/src/tools/agent-harness-research-workflow.ts +395 -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 +102 -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 +533 -0
- package/src/tools/agent-harness-sudo-posture.ts +114 -0
- package/src/tools/agent-harness-tool-schema.ts +142 -7
- package/src/tools/agent-harness-tool-types.ts +83 -0
- package/src/tools/agent-harness-tool-utils.ts +43 -0
- package/src/tools/agent-harness-tool.ts +319 -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 +253 -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 +735 -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-runner.ts +367 -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 +515 -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
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export type AgentSkillSource = 'user' | 'agent' | 'imported' | 'system';
|
|
2
|
+
export type AgentSkillReviewState = 'fresh' | 'reviewed' | 'stale';
|
|
3
|
+
export type AgentSkillRequirementKind = 'env' | 'command';
|
|
4
|
+
|
|
5
|
+
export interface AgentSkillRequirement {
|
|
6
|
+
readonly kind: AgentSkillRequirementKind;
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly description?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface AgentSkillReadiness {
|
|
12
|
+
readonly ready: boolean;
|
|
13
|
+
readonly met: readonly AgentSkillRequirement[];
|
|
14
|
+
readonly missing: readonly AgentSkillRequirement[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface AgentSkillBundleReadiness {
|
|
18
|
+
readonly ready: boolean;
|
|
19
|
+
readonly includedSkills: readonly AgentSkillRecord[];
|
|
20
|
+
readonly missingSkillIds: readonly string[];
|
|
21
|
+
readonly missingRequirements: readonly AgentSkillRequirement[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AgentSkillRecord {
|
|
25
|
+
readonly id: string;
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly description: string;
|
|
28
|
+
readonly procedure: string;
|
|
29
|
+
readonly triggers: readonly string[];
|
|
30
|
+
readonly tags: readonly string[];
|
|
31
|
+
readonly requirements: readonly AgentSkillRequirement[];
|
|
32
|
+
readonly enabled: boolean;
|
|
33
|
+
readonly source: AgentSkillSource;
|
|
34
|
+
readonly provenance: string;
|
|
35
|
+
readonly reviewState: AgentSkillReviewState;
|
|
36
|
+
readonly staleReason?: string;
|
|
37
|
+
readonly createdAt: string;
|
|
38
|
+
readonly updatedAt: string;
|
|
39
|
+
readonly reviewedAt?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface AgentSkillBundleRecord {
|
|
43
|
+
readonly id: string;
|
|
44
|
+
readonly name: string;
|
|
45
|
+
readonly description: string;
|
|
46
|
+
readonly skillIds: readonly string[];
|
|
47
|
+
readonly enabled: boolean;
|
|
48
|
+
readonly source: AgentSkillSource;
|
|
49
|
+
readonly provenance: string;
|
|
50
|
+
readonly reviewState: AgentSkillReviewState;
|
|
51
|
+
readonly staleReason?: string;
|
|
52
|
+
readonly createdAt: string;
|
|
53
|
+
readonly updatedAt: string;
|
|
54
|
+
readonly reviewedAt?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface AgentSkillCreateInput {
|
|
58
|
+
readonly name: string;
|
|
59
|
+
readonly description: string;
|
|
60
|
+
readonly procedure: string;
|
|
61
|
+
readonly triggers?: readonly string[];
|
|
62
|
+
readonly tags?: readonly string[];
|
|
63
|
+
readonly requirements?: readonly AgentSkillRequirement[];
|
|
64
|
+
readonly enabled?: boolean;
|
|
65
|
+
readonly source?: AgentSkillSource;
|
|
66
|
+
readonly provenance?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface AgentSkillBundleCreateInput {
|
|
70
|
+
readonly name: string;
|
|
71
|
+
readonly description: string;
|
|
72
|
+
readonly skillIds: readonly string[];
|
|
73
|
+
readonly enabled?: boolean;
|
|
74
|
+
readonly source?: AgentSkillSource;
|
|
75
|
+
readonly provenance?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface AgentSkillUpdateInput {
|
|
79
|
+
readonly name?: string;
|
|
80
|
+
readonly description?: string;
|
|
81
|
+
readonly procedure?: string;
|
|
82
|
+
readonly triggers?: readonly string[];
|
|
83
|
+
readonly tags?: readonly string[];
|
|
84
|
+
readonly requirements?: readonly AgentSkillRequirement[];
|
|
85
|
+
readonly provenance?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface AgentSkillBundleUpdateInput {
|
|
89
|
+
readonly name?: string;
|
|
90
|
+
readonly description?: string;
|
|
91
|
+
readonly skillIds?: readonly string[];
|
|
92
|
+
readonly provenance?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface AgentSkillSnapshot {
|
|
96
|
+
readonly path: string;
|
|
97
|
+
readonly skills: readonly AgentSkillRecord[];
|
|
98
|
+
readonly enabledSkills: readonly AgentSkillRecord[];
|
|
99
|
+
readonly bundles: readonly AgentSkillBundleRecord[];
|
|
100
|
+
readonly enabledBundles: readonly AgentSkillBundleRecord[];
|
|
101
|
+
readonly activeSkills: readonly AgentSkillRecord[];
|
|
102
|
+
}
|
|
@@ -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
|
+
}
|