@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
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { dirname, join } from 'node:path';
|
|
2
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
3
3
|
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
4
|
-
import { AgentPersonaRegistry } from './persona-registry.ts';
|
|
4
|
+
import { AgentPersonaRegistry, assertNoSecretLikeText } from './persona-registry.ts';
|
|
5
5
|
import { AgentRoutineRegistry } from './routine-registry.ts';
|
|
6
6
|
import { AgentSkillRegistry } from './skill-registry.ts';
|
|
7
|
+
import { discoverVibeFiles } from './vibe-file.ts';
|
|
7
8
|
import { discoverPersonas, type DiscoveredPersonaRecord } from './persona-discovery.ts';
|
|
8
9
|
import { discoverRoutines, type DiscoveredRoutineRecord } from './routine-discovery.ts';
|
|
9
10
|
import { discoverSkills, type SkillRecord } from './skill-discovery.ts';
|
|
@@ -20,6 +21,7 @@ export interface AgentRuntimeProfileTemplateSummary {
|
|
|
20
21
|
readonly personaName: string;
|
|
21
22
|
readonly skillNames: readonly string[];
|
|
22
23
|
readonly routineNames: readonly string[];
|
|
24
|
+
readonly vibeIncluded?: boolean;
|
|
23
25
|
readonly source: AgentRuntimeProfileTemplateSource;
|
|
24
26
|
readonly path?: string;
|
|
25
27
|
}
|
|
@@ -50,12 +52,22 @@ export interface AgentRuntimeProfileTemplateApplication {
|
|
|
50
52
|
readonly personaIds: readonly string[];
|
|
51
53
|
readonly skillIds: readonly string[];
|
|
52
54
|
readonly routineIds: readonly string[];
|
|
55
|
+
readonly vibePath?: string;
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
export interface CreateAgentRuntimeProfileOptions {
|
|
56
59
|
readonly templateId?: AgentRuntimeProfileTemplateId;
|
|
57
60
|
}
|
|
58
61
|
|
|
62
|
+
type AgentRuntimeProfileTemplateShellPaths =
|
|
63
|
+
Pick<ShellPathService, 'homeDirectory' | 'workingDirectory'>
|
|
64
|
+
& Partial<Pick<ShellPathService, 'resolveUserPath' | 'expandHomePath' | 'resolveWorkspacePath'>>;
|
|
65
|
+
|
|
66
|
+
export interface AgentRuntimeProfileTemplateExportOptions {
|
|
67
|
+
readonly includeVibe?: boolean;
|
|
68
|
+
readonly shellPaths?: AgentRuntimeProfileTemplateShellPaths;
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
export interface CreateAgentRuntimeProfileTemplateFromDiscoveredOptions {
|
|
60
72
|
readonly id: AgentRuntimeProfileTemplateId;
|
|
61
73
|
readonly name?: string;
|
|
@@ -63,6 +75,7 @@ export interface CreateAgentRuntimeProfileTemplateFromDiscoveredOptions {
|
|
|
63
75
|
readonly persona?: string;
|
|
64
76
|
readonly skills?: readonly string[];
|
|
65
77
|
readonly routines?: readonly string[];
|
|
78
|
+
readonly includeVibe?: boolean;
|
|
66
79
|
readonly replace?: boolean;
|
|
67
80
|
}
|
|
68
81
|
|
|
@@ -242,6 +255,7 @@ function summarizeTemplate(template: AgentRuntimeProfileStarterTemplate): AgentR
|
|
|
242
255
|
personaName: template.personaName,
|
|
243
256
|
skillNames: [...template.skillNames],
|
|
244
257
|
routineNames: [...template.routineNames],
|
|
258
|
+
vibeIncluded: Boolean(template.vibe?.body.trim()),
|
|
245
259
|
source: template.source,
|
|
246
260
|
path: template.path,
|
|
247
261
|
};
|
|
@@ -350,6 +364,73 @@ function parseTemplateRoutine(value: unknown): AgentRuntimeProfileStarterTemplat
|
|
|
350
364
|
};
|
|
351
365
|
}
|
|
352
366
|
|
|
367
|
+
function parseTemplateVibe(value: unknown): AgentRuntimeProfileStarterTemplate['vibe'] | undefined {
|
|
368
|
+
if (value === undefined || value === null) return undefined;
|
|
369
|
+
const record = readTemplateObject(value, 'vibe');
|
|
370
|
+
const body = readTemplateTextBlock(record.body, 'vibe.body');
|
|
371
|
+
assertNoSecretLikeText([body], 'Agent starter VIBE.md');
|
|
372
|
+
const source = record.source === 'template' ? 'template' : 'discovered';
|
|
373
|
+
const appliedAs = record.appliedAs === 'global' ? 'global' : 'global';
|
|
374
|
+
const truncated = typeof record.truncated === 'number' && Number.isFinite(record.truncated)
|
|
375
|
+
? Math.max(0, Math.trunc(record.truncated))
|
|
376
|
+
: 0;
|
|
377
|
+
return {
|
|
378
|
+
body,
|
|
379
|
+
source,
|
|
380
|
+
appliedAs,
|
|
381
|
+
sourcePaths: parseStringArray(record.sourcePaths),
|
|
382
|
+
truncated,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function profileTemplateVibeShellPaths(shellPaths: AgentRuntimeProfileTemplateShellPaths): Parameters<typeof discoverVibeFiles>[0] {
|
|
387
|
+
return {
|
|
388
|
+
homeDirectory: shellPaths.homeDirectory,
|
|
389
|
+
workingDirectory: shellPaths.workingDirectory,
|
|
390
|
+
resolveUserPath: shellPaths.resolveUserPath ?? ((...parts: string[]) => join(shellPaths.homeDirectory, '.goodvibes', ...parts)),
|
|
391
|
+
expandHomePath: shellPaths.expandHomePath ?? ((value: string) => value.startsWith('~/') ? join(shellPaths.homeDirectory, value.slice(2)) : value),
|
|
392
|
+
resolveWorkspacePath: shellPaths.resolveWorkspacePath ?? ((value: string) => {
|
|
393
|
+
const expanded = value.startsWith('~/') ? join(shellPaths.homeDirectory, value.slice(2)) : value;
|
|
394
|
+
return isAbsolute(expanded) ? resolve(expanded) : resolve(shellPaths.workingDirectory, expanded);
|
|
395
|
+
}),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function discoveredVibeToTemplate(
|
|
400
|
+
shellPaths: AgentRuntimeProfileTemplateExportOptions['shellPaths'],
|
|
401
|
+
): AgentRuntimeProfileStarterTemplate['vibe'] | undefined {
|
|
402
|
+
if (!shellPaths) throw new Error('Including VIBE.md in a starter template requires shell path context.');
|
|
403
|
+
const snapshot = discoverVibeFiles(profileTemplateVibeShellPaths(shellPaths));
|
|
404
|
+
if (snapshot.blocked.length > 0) {
|
|
405
|
+
throw new Error(`Cannot include VIBE.md in a starter template while ${snapshot.blocked.length} VIBE.md file is blocked. Run /vibe status and repair it first.`);
|
|
406
|
+
}
|
|
407
|
+
if (snapshot.files.length === 0) return undefined;
|
|
408
|
+
const body = snapshot.files.map((file) => [
|
|
409
|
+
`## ${file.scope === 'global' ? 'Global' : 'Project'} VIBE.md`,
|
|
410
|
+
`Source: ${file.path}`,
|
|
411
|
+
'',
|
|
412
|
+
file.body,
|
|
413
|
+
file.truncated ? '[This VIBE.md was truncated before profile starter export.]' : '',
|
|
414
|
+
].filter(Boolean).join('\n')).join('\n\n');
|
|
415
|
+
assertNoSecretLikeText([body], 'Agent starter VIBE.md');
|
|
416
|
+
return {
|
|
417
|
+
body,
|
|
418
|
+
source: 'discovered',
|
|
419
|
+
appliedAs: 'global',
|
|
420
|
+
sourcePaths: snapshot.files.map((file) => file.path),
|
|
421
|
+
truncated: snapshot.files.filter((file) => file.truncated).length,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function withOptionalVibe(
|
|
426
|
+
template: AgentRuntimeProfileStarterTemplate,
|
|
427
|
+
options: AgentRuntimeProfileTemplateExportOptions | undefined,
|
|
428
|
+
): AgentRuntimeProfileStarterTemplate {
|
|
429
|
+
if (options?.includeVibe !== true) return template;
|
|
430
|
+
const vibe = discoveredVibeToTemplate(options.shellPaths);
|
|
431
|
+
return vibe ? { ...template, vibe } : template;
|
|
432
|
+
}
|
|
433
|
+
|
|
353
434
|
function parseStarterTemplate(raw: unknown, source: AgentRuntimeProfileTemplateSource, path?: string): AgentRuntimeProfileStarterTemplate {
|
|
354
435
|
const file = readTemplateObject(raw, 'file');
|
|
355
436
|
const templateRecord = readTemplateObject(file.template ?? raw, 'template');
|
|
@@ -357,6 +438,7 @@ function parseStarterTemplate(raw: unknown, source: AgentRuntimeProfileTemplateS
|
|
|
357
438
|
const personaRecord = readTemplateObject(templateRecord.persona, 'persona');
|
|
358
439
|
const skills = Array.isArray(templateRecord.skills) ? templateRecord.skills.map(parseTemplateSkill) : [];
|
|
359
440
|
const routines = Array.isArray(templateRecord.routines) ? templateRecord.routines.map(parseTemplateRoutine) : [];
|
|
441
|
+
const vibe = parseTemplateVibe(templateRecord.vibe);
|
|
360
442
|
if (skills.length === 0) throw new Error(`Starter template ${id} must include at least one skill.`);
|
|
361
443
|
if (routines.length === 0) throw new Error(`Starter template ${id} must include at least one routine.`);
|
|
362
444
|
const persona = {
|
|
@@ -378,6 +460,7 @@ function parseStarterTemplate(raw: unknown, source: AgentRuntimeProfileTemplateS
|
|
|
378
460
|
persona,
|
|
379
461
|
skills,
|
|
380
462
|
routines,
|
|
463
|
+
...(vibe ? { vibe: { ...vibe, source: 'template' } } : {}),
|
|
381
464
|
};
|
|
382
465
|
}
|
|
383
466
|
|
|
@@ -434,8 +517,13 @@ function templateFilePayload(template: AgentRuntimeProfileStarterTemplate): Agen
|
|
|
434
517
|
};
|
|
435
518
|
}
|
|
436
519
|
|
|
437
|
-
export function exportAgentRuntimeProfileTemplate(
|
|
438
|
-
|
|
520
|
+
export function exportAgentRuntimeProfileTemplate(
|
|
521
|
+
baseHomeDirectory: string,
|
|
522
|
+
templateId: AgentRuntimeProfileTemplateId,
|
|
523
|
+
outputPath: string,
|
|
524
|
+
options: AgentRuntimeProfileTemplateExportOptions = {},
|
|
525
|
+
): AgentRuntimeProfileTemplateSummary {
|
|
526
|
+
const template = withOptionalVibe(resolveAgentRuntimeProfileTemplate(templateId, baseHomeDirectory), options);
|
|
439
527
|
const target = outputPath.trim();
|
|
440
528
|
if (!target) throw new Error('Template export path is required.');
|
|
441
529
|
mkdirSync(dirname(target), { recursive: true });
|
|
@@ -472,6 +560,7 @@ export async function createAgentRuntimeProfileTemplateFromDiscovered(
|
|
|
472
560
|
throw new Error(`Agent starter template already exists ${id}. Rerun with --replace to overwrite it.`);
|
|
473
561
|
}
|
|
474
562
|
const persona = discoveredPersonaToTemplate(selectedPersona);
|
|
563
|
+
const vibe = options.includeVibe ? discoveredVibeToTemplate(shellPaths) : undefined;
|
|
475
564
|
const template: AgentRuntimeProfileStarterTemplate = {
|
|
476
565
|
id,
|
|
477
566
|
source: 'local',
|
|
@@ -484,6 +573,7 @@ export async function createAgentRuntimeProfileTemplateFromDiscovered(
|
|
|
484
573
|
persona,
|
|
485
574
|
skills: selectedSkills.map(discoveredSkillToTemplate),
|
|
486
575
|
routines: selectedRoutines.map(discoveredRoutineToTemplate),
|
|
576
|
+
...(vibe ? { vibe } : {}),
|
|
487
577
|
};
|
|
488
578
|
mkdirSync(dirname(target), { recursive: true });
|
|
489
579
|
writeFileSync(target, `${JSON.stringify(templateFilePayload(template), null, 2)}\n`, 'utf-8');
|
|
@@ -510,6 +600,7 @@ export async function createAgentRuntimeProfileFromDiscovered(
|
|
|
510
600
|
persona: options.persona,
|
|
511
601
|
skills: options.skills,
|
|
512
602
|
routines: options.routines,
|
|
603
|
+
includeVibe: options.includeVibe,
|
|
513
604
|
replace: options.replace,
|
|
514
605
|
});
|
|
515
606
|
const profile = createAgentRuntimeProfile(shellPaths.homeDirectory, profileId, { templateId: template.id });
|
|
@@ -546,6 +637,15 @@ function createMissingRoutine(registry: AgentRoutineRegistry, template: AgentRun
|
|
|
546
637
|
}).id;
|
|
547
638
|
}
|
|
548
639
|
|
|
640
|
+
function writeTemplateVibe(homeDirectory: string, template: AgentRuntimeProfileStarterTemplate): string | undefined {
|
|
641
|
+
if (!template.vibe?.body.trim()) return undefined;
|
|
642
|
+
assertNoSecretLikeText([template.vibe.body], 'Agent starter VIBE.md');
|
|
643
|
+
const path = join(homeDirectory, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'VIBE.md');
|
|
644
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
645
|
+
writeFileSync(path, `${template.vibe.body.trimEnd()}\n`, 'utf-8');
|
|
646
|
+
return path;
|
|
647
|
+
}
|
|
648
|
+
|
|
549
649
|
export function applyAgentRuntimeProfileTemplate(homeDirectory: string, templateId: AgentRuntimeProfileTemplateId, baseHomeDirectory?: string): AgentRuntimeProfileTemplateApplication {
|
|
550
650
|
const template = resolveAgentRuntimeProfileTemplate(templateId, baseHomeDirectory);
|
|
551
651
|
const personaRegistry = new AgentPersonaRegistry(profileStorePath(homeDirectory, 'personas', 'personas.json'));
|
|
@@ -564,6 +664,7 @@ export function applyAgentRuntimeProfileTemplate(homeDirectory: string, template
|
|
|
564
664
|
personaRegistry.setActive(persona.id);
|
|
565
665
|
const skillIds = template.skills.map((skill) => createMissingSkill(skillRegistry, skill));
|
|
566
666
|
const routineIds = template.routines.map((routine) => createMissingRoutine(routineRegistry, routine));
|
|
667
|
+
const vibePath = writeTemplateVibe(homeDirectory, template);
|
|
567
668
|
return {
|
|
568
669
|
id: template.id,
|
|
569
670
|
name: template.name,
|
|
@@ -572,6 +673,7 @@ export function applyAgentRuntimeProfileTemplate(homeDirectory: string, template
|
|
|
572
673
|
personaIds: [persona.id],
|
|
573
674
|
skillIds,
|
|
574
675
|
routineIds,
|
|
676
|
+
...(vibePath ? { vibePath } : {}),
|
|
575
677
|
};
|
|
576
678
|
}
|
|
577
679
|
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { formatEveryInterval } from '@pellux/goodvibes-sdk/platform/automation';
|
|
2
|
+
import type {
|
|
3
|
+
ScheduleEditFailure,
|
|
4
|
+
ScheduleEditPreview,
|
|
5
|
+
ScheduleEditSuccess,
|
|
6
|
+
} from './schedule-edit.ts';
|
|
7
|
+
import { scheduleConfirmationRouteLines, scheduleNextRouteLines, scheduleRouteArg } from './schedule-next-routes.ts';
|
|
8
|
+
|
|
9
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
10
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function readString(record: Record<string, unknown>, key: string): string | null {
|
|
14
|
+
const value = record[key];
|
|
15
|
+
return typeof value === 'string' ? value : null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function scheduleValue(schedule: unknown): string {
|
|
19
|
+
if (!isRecord(schedule)) return 'unchanged';
|
|
20
|
+
if (schedule.kind === 'cron') {
|
|
21
|
+
return [
|
|
22
|
+
readString(schedule, 'expression') ?? '',
|
|
23
|
+
readString(schedule, 'timezone') ? `[${readString(schedule, 'timezone')}]` : '',
|
|
24
|
+
typeof schedule.staggerMs === 'number' ? `[stagger ${schedule.staggerMs}ms]` : '',
|
|
25
|
+
].filter(Boolean).join(' ');
|
|
26
|
+
}
|
|
27
|
+
if (schedule.kind === 'every' && typeof schedule.intervalMs === 'number') return formatEveryInterval(schedule.intervalMs);
|
|
28
|
+
if (schedule.kind === 'at' && typeof schedule.at === 'number') return new Date(schedule.at).toISOString();
|
|
29
|
+
return String(schedule.kind ?? 'unknown');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function patchScheduleValue(preview: ScheduleEditPreview): string {
|
|
33
|
+
return scheduleValue(preview.payload.schedule);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function scheduleEditConfirmationRoute(preview: ScheduleEditPreview): string {
|
|
37
|
+
const args = [
|
|
38
|
+
'schedule action:"edit"',
|
|
39
|
+
`scheduleId:${scheduleRouteArg(preview.scheduleId)}`,
|
|
40
|
+
];
|
|
41
|
+
if (preview.payload.name) args.push(`name:${scheduleRouteArg(String(preview.payload.name))}`);
|
|
42
|
+
if (preview.payload.schedule) {
|
|
43
|
+
const schedule = preview.payload.schedule;
|
|
44
|
+
if (isRecord(schedule) && typeof schedule.kind === 'string') {
|
|
45
|
+
args.push(`scheduleKind:${scheduleRouteArg(schedule.kind)}`);
|
|
46
|
+
args.push(`scheduleValue:${scheduleRouteArg(scheduleValue(schedule))}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (preview.payload.prompt) args.push('prompt:"..."');
|
|
50
|
+
args.push('confirm:true', 'explicitUserRequest:"..."');
|
|
51
|
+
return args.join(' ');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function formatCurrentScheduleDiff(preview: ScheduleEditPreview): readonly string[] {
|
|
55
|
+
const current = preview.current;
|
|
56
|
+
if (!current) return [];
|
|
57
|
+
const lines = [
|
|
58
|
+
` current source ${current.method} GET ${current.route}`,
|
|
59
|
+
current.found
|
|
60
|
+
? ` current status ${current.status ?? 'unknown'}`
|
|
61
|
+
: ` current schedule not found`,
|
|
62
|
+
current.note ? ` current note ${current.note}` : '',
|
|
63
|
+
];
|
|
64
|
+
for (const diff of current.diffs) {
|
|
65
|
+
lines.push(` ${diff.field} ${diff.before} -> ${diff.after}${diff.changed ? '' : ' (unchanged)'}`);
|
|
66
|
+
}
|
|
67
|
+
return lines.filter((line) => line !== '');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function responseRecord(result: ScheduleEditSuccess): Record<string, unknown> {
|
|
71
|
+
return isRecord(result.schedule) ? result.schedule : {};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function formatScheduleEditFailureKind(kind: ScheduleEditFailure['kind']): string {
|
|
75
|
+
if (kind === 'confirmation_required') return 'confirmation required';
|
|
76
|
+
if (kind === 'auth_required') return 'authorization required';
|
|
77
|
+
if (kind === 'connected_host_unavailable') return 'connected host unavailable';
|
|
78
|
+
if (kind === 'connected_host_incompatible') return 'connected host incompatible';
|
|
79
|
+
if (kind === 'connected_host_route_unavailable') return 'connected host route unavailable';
|
|
80
|
+
return 'connected host error';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function formatScheduleEditPreview(preview: ScheduleEditPreview): string {
|
|
84
|
+
return [
|
|
85
|
+
'GoodVibes schedule edit preview',
|
|
86
|
+
` method ${preview.method}`,
|
|
87
|
+
` route PATCH ${preview.route.replace('{jobId}', preview.scheduleId)}`,
|
|
88
|
+
` schedule ${preview.scheduleId}`,
|
|
89
|
+
` changes ${preview.changes.join(', ')}`,
|
|
90
|
+
...formatCurrentScheduleDiff(preview),
|
|
91
|
+
preview.payload.name ? ` name ${preview.payload.name}` : '',
|
|
92
|
+
preview.payload.schedule ? ` schedule ${patchScheduleValue(preview)}` : '',
|
|
93
|
+
preview.payload.prompt ? ' prompt replacement prepared' : '',
|
|
94
|
+
` requested by ${preview.explicitUserRequest}`,
|
|
95
|
+
'',
|
|
96
|
+
'Confirmation required: rerun with --yes or call the model tool with confirm:true only when the user explicitly asked for this exact schedule edit.',
|
|
97
|
+
...scheduleConfirmationRouteLines({ model: scheduleEditConfirmationRoute(preview) }),
|
|
98
|
+
].filter((line) => line !== '').join('\n');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function formatScheduleEditSuccess(result: ScheduleEditSuccess): string {
|
|
102
|
+
const record = responseRecord(result);
|
|
103
|
+
const id = readString(record, 'id') ?? result.scheduleId;
|
|
104
|
+
const status = readString(record, 'status') ?? (record.enabled === false ? 'paused' : record.enabled === true ? 'enabled' : 'ok');
|
|
105
|
+
return [
|
|
106
|
+
'Updated GoodVibes schedule',
|
|
107
|
+
` schedule ${id}`,
|
|
108
|
+
` method ${result.kind}`,
|
|
109
|
+
` route PATCH ${result.route.replace('{jobId}', result.scheduleId)}`,
|
|
110
|
+
` status ${status}`,
|
|
111
|
+
isRecord(record.schedule) ? ` schedule ${scheduleValue(record.schedule)}` : '',
|
|
112
|
+
...scheduleNextRouteLines(id),
|
|
113
|
+
].filter((line) => line !== '').join('\n');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function formatScheduleEditFailure(failure: ScheduleEditFailure): string {
|
|
117
|
+
return [
|
|
118
|
+
`GoodVibes schedule edit error ${formatScheduleEditFailureKind(failure.kind)}`,
|
|
119
|
+
` route PATCH ${failure.route}`,
|
|
120
|
+
failure.baseUrl ? ` connected host ${failure.baseUrl}` : '',
|
|
121
|
+
` error ${failure.error}`,
|
|
122
|
+
failure.kind === 'auth_required'
|
|
123
|
+
? ' next pair or start the connected GoodVibes host so an operator token is available.'
|
|
124
|
+
: '',
|
|
125
|
+
failure.kind === 'connected_host_incompatible'
|
|
126
|
+
? ' next update the connected GoodVibes host so automation.jobs.patch is available.'
|
|
127
|
+
: '',
|
|
128
|
+
].filter((line) => line !== '').join('\n');
|
|
129
|
+
}
|