@pellux/goodvibes-agent 0.1.116 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -661
- package/README.md +64 -57
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +199180 -192185
- package/docs/README.md +15 -8
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +59 -0
- package/docs/getting-started.md +61 -50
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +48 -11
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +3 -6
- package/src/agent/behavior-discovery-summary.ts +1 -3
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-discovery.ts +1 -3
- package/src/agent/persona-registry.ts +19 -16
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +27 -26
- package/src/agent/routine-registry.ts +54 -14
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +35 -33
- package/src/agent/routine-schedule-receipts.ts +29 -27
- package/src/agent/runtime-profile-starters.ts +5 -5
- package/src/agent/runtime-profile.ts +91 -12
- package/src/agent/skill-registry.ts +210 -32
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +40 -34
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +14 -9
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/entrypoint.ts +16 -7
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +54 -29
- package/src/cli/local-library-command.ts +203 -83
- package/src/cli/management-commands.ts +105 -68
- package/src/cli/management.ts +55 -74
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -3
- package/src/cli/profiles-command.ts +166 -31
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +176 -40
- package/src/cli/service-posture.ts +16 -16
- package/src/cli/status.ts +56 -135
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
- package/src/input/agent-workspace-access-command-editors.ts +170 -0
- package/src/input/agent-workspace-activation.ts +35 -8
- package/src/input/agent-workspace-basic-command-editor-submission.ts +351 -94
- package/src/input/agent-workspace-basic-command-editors.ts +502 -9
- package/src/input/agent-workspace-categories.ts +423 -51
- package/src/input/agent-workspace-channel-command-editor-submission.ts +83 -0
- package/src/input/agent-workspace-channel-command-editors.ts +65 -0
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +41 -3
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
- package/src/input/agent-workspace-editors.ts +166 -1
- package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
- package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-learned-behavior.ts +67 -0
- package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
- package/src/input/agent-workspace-library-command-editors.ts +35 -0
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
- package/src/input/agent-workspace-memory-command-editors.ts +180 -0
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +81 -0
- package/src/input/agent-workspace-notify-editor-submission.ts +121 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +208 -0
- package/src/input/agent-workspace-operations-command-editors.ts +196 -0
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
- package/src/input/agent-workspace-provider-command-editors.ts +93 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-requirements.ts +11 -0
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
- package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
- package/src/input/agent-workspace-session-command-editors.ts +249 -0
- package/src/input/agent-workspace-setup.ts +37 -16
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
- package/src/input/agent-workspace-snapshot.ts +162 -21
- package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
- package/src/input/agent-workspace-task-command-editors.ts +47 -0
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +212 -4
- package/src/input/agent-workspace-voice-media.ts +4 -7
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
- package/src/input/agent-workspace.ts +178 -240
- package/src/input/command-registry.ts +5 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +126 -37
- package/src/input/commands/agent-skills-runtime.ts +149 -72
- package/src/input/commands/agent-workspace-runtime.ts +23 -6
- package/src/input/commands/brief-runtime.ts +55 -25
- package/src/input/commands/channels-runtime.ts +147 -33
- package/src/input/commands/compat-runtime.ts +32 -0
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +149 -126
- package/src/input/commands/knowledge.ts +82 -60
- package/src/input/commands/local-provider-runtime.ts +43 -21
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +10 -20
- package/src/input/commands/mcp-runtime.ts +63 -46
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -76
- package/src/input/commands/personas-runtime.ts +46 -31
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +35 -98
- package/src/input/commands/product-runtime.ts +2 -2
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +50 -9
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +99 -45
- package/src/input/commands/runtime-services.ts +1 -14
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +6 -11
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +134 -104
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +38 -17
- package/src/input/commands/subscription-runtime.ts +54 -185
- package/src/input/commands/support-bundle-runtime.ts +53 -0
- package/src/input/commands/tasks-runtime.ts +21 -21
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +6 -2
- package/src/input/feed-context-factory.ts +2 -2
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -26
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -5
- package/src/input/handler-interactions.ts +9 -36
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +52 -91
- package/src/input/handler-shortcuts.ts +16 -7
- package/src/input/handler.ts +50 -23
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +27 -16
- package/src/input/mcp-workspace.ts +90 -26
- package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +62 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +223 -55
- package/src/input/onboarding/onboarding-wizard-steps.ts +59 -35
- package/src/input/onboarding/onboarding-wizard-types.ts +4 -1
- package/src/input/onboarding/onboarding-wizard.ts +87 -2
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- package/src/input/settings-modal-agent-policy.ts +6 -6
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +20 -66
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -10
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +4 -4
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +3 -12
- package/src/panels/builtin/session.ts +32 -24
- package/src/panels/builtin/shared.ts +7 -7
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +19 -12
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +48 -7
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +44 -20
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +6 -6
- package/src/panels/system-messages-panel.ts +3 -3
- package/src/panels/tasks-panel.ts +21 -14
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +3 -3
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +254 -57
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/block-actions.ts +1 -3
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +112 -34
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +176 -43
- package/src/renderer/model-picker-overlay.ts +58 -3
- package/src/renderer/model-workspace.ts +104 -22
- package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +21 -5
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +88 -55
- package/src/renderer/system-message.ts +1 -1
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +129 -0
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +11 -8
- package/src/runtime/bootstrap-core.ts +23 -65
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +46 -8
- package/src/runtime/bootstrap.ts +36 -46
- package/src/runtime/connected-host-auth.ts +47 -0
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -5
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +288 -74
- package/src/runtime/onboarding/derivation.ts +10 -13
- package/src/runtime/onboarding/snapshot.ts +2 -17
- package/src/runtime/onboarding/types.ts +34 -20
- package/src/runtime/onboarding/verify.ts +105 -4
- package/src/runtime/operator-token-cleanup.ts +3 -3
- package/src/runtime/services.ts +95 -11
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/service-settings-sync.ts +7 -7
- package/src/shell/ui-openers.ts +17 -38
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +279 -73
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +13 -15
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/docs/connected-services.md +0 -51
- package/src/cli/package-verification.ts +0 -274
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -17
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { createShellPathService } from '@/runtime/index.ts';
|
|
2
|
+
import { formatAgentRecordOrigin, formatAgentRecordReviewState } from '../agent/record-labels.ts';
|
|
2
3
|
import { discoverRoutines, type DiscoveredRoutineRecord } from '../agent/routine-discovery.ts';
|
|
3
|
-
import { AgentRoutineRegistry, type AgentRoutineRecord } from '../agent/routine-registry.ts';
|
|
4
|
+
import { AgentRoutineRegistry, evaluateAgentRoutineReadiness, type AgentRoutineRecord } from '../agent/routine-registry.ts';
|
|
5
|
+
import { buildAgentSkillRequirements, formatAgentSkillRequirement } from '../agent/skill-registry.ts';
|
|
4
6
|
import {
|
|
5
7
|
buildRoutineSchedulePreview,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
promoteRoutineToConnectedSchedule,
|
|
9
|
+
resolveAgentConnectedHostConnection,
|
|
8
10
|
} from '../agent/routine-schedule-promotion.ts';
|
|
9
11
|
import { parseRoutineSchedulePromotionArgs } from '../agent/routine-schedule-args.ts';
|
|
10
12
|
import {
|
|
@@ -34,10 +36,26 @@ interface RoutinesCommandFailure {
|
|
|
34
36
|
readonly error: string;
|
|
35
37
|
}
|
|
36
38
|
|
|
39
|
+
interface ParsedRoutineOptions {
|
|
40
|
+
readonly positionals: readonly string[];
|
|
41
|
+
readonly flags: ReadonlyMap<string, string>;
|
|
42
|
+
readonly yes: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ROUTINE_CREATE_USAGE = 'Usage: goodvibes-agent routines create --name <name> --description <summary> --steps <steps> [--tags a,b] [--triggers a,b] [--requires-env A,B] [--requires-command gh,jq] [--enabled]';
|
|
46
|
+
|
|
37
47
|
function jsonOrText(runtime: CliCommandRuntime, value: unknown, text: string): string {
|
|
38
48
|
return runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(value, null, 2) : text;
|
|
39
49
|
}
|
|
40
50
|
|
|
51
|
+
function commandFailure(runtime: CliCommandRuntime, kind: string, error: string, exitCode: number): CliCommandOutput {
|
|
52
|
+
const failure: RoutinesCommandFailure = { ok: false, kind, error };
|
|
53
|
+
return {
|
|
54
|
+
output: runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(failure, null, 2) : error,
|
|
55
|
+
exitCode,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
41
59
|
function routineRegistry(runtime: CliCommandRuntime): AgentRoutineRegistry {
|
|
42
60
|
return AgentRoutineRegistry.fromShellPaths(createShellPathService({
|
|
43
61
|
workingDirectory: runtime.workingDirectory,
|
|
@@ -64,6 +82,47 @@ function splitList(value: string | undefined): readonly string[] {
|
|
|
64
82
|
return value.split(',').map((entry) => entry.trim()).filter(Boolean);
|
|
65
83
|
}
|
|
66
84
|
|
|
85
|
+
function parseRoutineOptions(args: readonly string[]): ParsedRoutineOptions {
|
|
86
|
+
const flags = new Map<string, string>();
|
|
87
|
+
const positionals: string[] = [];
|
|
88
|
+
let yes = false;
|
|
89
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
90
|
+
const token = args[index] ?? '';
|
|
91
|
+
if (token === '--yes') {
|
|
92
|
+
yes = true;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (token.startsWith('--')) {
|
|
96
|
+
const key = token.slice(2);
|
|
97
|
+
const next = args[index + 1];
|
|
98
|
+
if (next !== undefined && !next.startsWith('--')) {
|
|
99
|
+
flags.set(key, next);
|
|
100
|
+
index += 1;
|
|
101
|
+
} else {
|
|
102
|
+
flags.set(key, 'true');
|
|
103
|
+
}
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
positionals.push(token);
|
|
107
|
+
}
|
|
108
|
+
return { positionals, flags, yes };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function optionValue(options: ParsedRoutineOptions, key: string): string | undefined {
|
|
112
|
+
const value = options.flags.get(key)?.trim();
|
|
113
|
+
return value ? value : undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function hasFlag(options: ParsedRoutineOptions, key: string): boolean {
|
|
117
|
+
return options.flags.get(key) === 'true';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function requiredOption(options: ParsedRoutineOptions, key: string): string {
|
|
121
|
+
const value = optionValue(options, key);
|
|
122
|
+
if (!value) throw new Error(`${ROUTINE_CREATE_USAGE}\nMissing --${key}.`);
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
|
|
67
126
|
function parseImportFlags(args: readonly string[]): {
|
|
68
127
|
readonly name: string;
|
|
69
128
|
readonly enabled: boolean;
|
|
@@ -88,15 +147,17 @@ function parseImportFlags(args: readonly string[]): {
|
|
|
88
147
|
|
|
89
148
|
function summarizeRoutine(routine: AgentRoutineRecord): string {
|
|
90
149
|
const enabled = routine.enabled ? 'enabled' : 'disabled';
|
|
91
|
-
const tags = routine.tags.length > 0 ? `
|
|
92
|
-
|
|
150
|
+
const tags = routine.tags.length > 0 ? ` tags ${routine.tags.join(', ')}` : '';
|
|
151
|
+
const readiness = evaluateAgentRoutineReadiness(routine);
|
|
152
|
+
const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
|
|
153
|
+
return ` ${routine.id} ${enabled} ${formatAgentRecordReviewState(routine.reviewState)} ${ready} starts ${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
|
|
93
154
|
}
|
|
94
155
|
|
|
95
156
|
function summarizeDiscoveredRoutine(routine: DiscoveredRoutineRecord): string {
|
|
96
157
|
const description = routine.description ? ` - ${routine.description}` : '';
|
|
97
158
|
return [
|
|
98
159
|
` ${routine.name} ${routine.origin}${description}`,
|
|
99
|
-
` path
|
|
160
|
+
` path ${routine.path}`,
|
|
100
161
|
].join('\n');
|
|
101
162
|
}
|
|
102
163
|
|
|
@@ -136,35 +197,46 @@ function discoveredRoutineFrontmatterList(routine: DiscoveredRoutineRecord, key:
|
|
|
136
197
|
return splitList(value);
|
|
137
198
|
}
|
|
138
199
|
|
|
139
|
-
function
|
|
200
|
+
function discoveredRoutineFrontmatterAnyList(routine: DiscoveredRoutineRecord, keys: readonly string[]): readonly string[] {
|
|
201
|
+
for (const key of keys) {
|
|
202
|
+
const values = discoveredRoutineFrontmatterList(routine, key);
|
|
203
|
+
if (values.length > 0) return values;
|
|
204
|
+
}
|
|
205
|
+
return [];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function renderRoutineList(title: string, path: string, routines: readonly AgentRoutineRecord[], emptyMessage?: string): string {
|
|
140
209
|
if (routines.length === 0) {
|
|
141
210
|
return [
|
|
142
211
|
title,
|
|
143
|
-
'
|
|
144
|
-
'
|
|
145
|
-
].join('\n');
|
|
212
|
+
` ${emptyMessage ?? 'No Agent-local routines yet.'}`,
|
|
213
|
+
emptyMessage ? '' : ' Open /agent routines in the TUI, or use goodvibes-agent routines create for scripted setup.',
|
|
214
|
+
].filter(Boolean).join('\n');
|
|
146
215
|
}
|
|
147
216
|
return [
|
|
148
217
|
`${title} (${routines.length})`,
|
|
149
|
-
` store
|
|
218
|
+
` store ${path}`,
|
|
150
219
|
...routines.map(summarizeRoutine),
|
|
151
220
|
].join('\n');
|
|
152
221
|
}
|
|
153
222
|
|
|
154
223
|
function renderRoutine(routine: AgentRoutineRecord): string {
|
|
224
|
+
const readiness = evaluateAgentRoutineReadiness(routine);
|
|
155
225
|
return [
|
|
156
226
|
`Routine ${routine.name}`,
|
|
157
|
-
` id
|
|
158
|
-
` enabled
|
|
159
|
-
`
|
|
160
|
-
`
|
|
161
|
-
`
|
|
162
|
-
`
|
|
163
|
-
`
|
|
164
|
-
`
|
|
165
|
-
`
|
|
166
|
-
`
|
|
167
|
-
|
|
227
|
+
` id ${routine.id}`,
|
|
228
|
+
` enabled ${routine.enabled ? 'yes' : 'no'}`,
|
|
229
|
+
` readiness ${readiness.ready ? 'ready' : 'needs setup'}`,
|
|
230
|
+
` requirements ${routine.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
|
|
231
|
+
readiness.missing.length > 0 ? ` missing ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
|
|
232
|
+
` review ${formatAgentRecordReviewState(routine.reviewState)}`,
|
|
233
|
+
` origin ${formatAgentRecordOrigin(routine.source, routine.provenance)}`,
|
|
234
|
+
` tags ${routine.tags.join(', ') || '(none)'}`,
|
|
235
|
+
` triggers ${routine.triggers.join(', ') || '(manual)'}`,
|
|
236
|
+
` started ${routine.startCount}${routine.lastStartedAt ? `; last ${routine.lastStartedAt}` : ''}`,
|
|
237
|
+
` created ${routine.createdAt}`,
|
|
238
|
+
` updated ${routine.updatedAt}`,
|
|
239
|
+
routine.staleReason ? ` stale reason ${routine.staleReason}` : '',
|
|
168
240
|
'',
|
|
169
241
|
routine.description,
|
|
170
242
|
'',
|
|
@@ -195,7 +267,7 @@ async function handleRoutinePromotion(runtime: CliCommandRuntime, args: readonly
|
|
|
195
267
|
const failure: RoutinesCommandFailure = {
|
|
196
268
|
ok: false,
|
|
197
269
|
kind: 'routine_not_found',
|
|
198
|
-
error: `Unknown Agent routine
|
|
270
|
+
error: `Unknown Agent routine ${parsed.routineId ?? ''}`,
|
|
199
271
|
};
|
|
200
272
|
return {
|
|
201
273
|
output: json ? JSON.stringify(failure, null, 2) : failure.error,
|
|
@@ -214,8 +286,8 @@ async function handleRoutinePromotion(runtime: CliCommandRuntime, args: readonly
|
|
|
214
286
|
exitCode: 0,
|
|
215
287
|
};
|
|
216
288
|
}
|
|
217
|
-
const connection =
|
|
218
|
-
const result = await
|
|
289
|
+
const connection = resolveAgentConnectedHostConnection(runtime.configManager, runtime.homeDirectory);
|
|
290
|
+
const result = await promoteRoutineToConnectedSchedule(connection, preview);
|
|
219
291
|
const receipt = routineReceiptStore(runtime).append(connection, preview, result);
|
|
220
292
|
if (!result.ok) {
|
|
221
293
|
return {
|
|
@@ -235,15 +307,23 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
235
307
|
const registry = routineRegistry(runtime);
|
|
236
308
|
const snapshot = registry.snapshot();
|
|
237
309
|
const normalized = sub.toLowerCase();
|
|
238
|
-
if (normalized === 'list' || normalized === 'enabled') {
|
|
239
|
-
const routines = normalized === 'enabled'
|
|
310
|
+
if (normalized === 'list' || normalized === 'enabled' || normalized === 'attention' || normalized === 'needs-setup') {
|
|
311
|
+
const routines = normalized === 'enabled'
|
|
312
|
+
? snapshot.enabledRoutines
|
|
313
|
+
: normalized === 'attention' || normalized === 'needs-setup'
|
|
314
|
+
? snapshot.routines.filter((routine) => !evaluateAgentRoutineReadiness(routine).ready)
|
|
315
|
+
: snapshot.routines;
|
|
240
316
|
const value: RoutinesCommandSuccess<{
|
|
241
317
|
readonly path: string;
|
|
242
318
|
readonly routines: readonly AgentRoutineRecord[];
|
|
243
319
|
readonly enabledCount: number;
|
|
244
320
|
}> = {
|
|
245
321
|
ok: true,
|
|
246
|
-
kind: normalized === 'enabled'
|
|
322
|
+
kind: normalized === 'enabled'
|
|
323
|
+
? 'agent.routines.enabled'
|
|
324
|
+
: normalized === 'attention' || normalized === 'needs-setup'
|
|
325
|
+
? 'agent.routines.attention'
|
|
326
|
+
: 'agent.routines.list',
|
|
247
327
|
data: {
|
|
248
328
|
path: snapshot.path,
|
|
249
329
|
routines,
|
|
@@ -251,7 +331,16 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
251
331
|
},
|
|
252
332
|
};
|
|
253
333
|
return {
|
|
254
|
-
output: jsonOrText(runtime, value, renderRoutineList(
|
|
334
|
+
output: jsonOrText(runtime, value, renderRoutineList(
|
|
335
|
+
normalized === 'enabled'
|
|
336
|
+
? 'Enabled Agent routines'
|
|
337
|
+
: normalized === 'attention' || normalized === 'needs-setup'
|
|
338
|
+
? 'Agent routines needing setup'
|
|
339
|
+
: 'Agent routines',
|
|
340
|
+
snapshot.path,
|
|
341
|
+
routines,
|
|
342
|
+
normalized === 'attention' || normalized === 'needs-setup' ? 'No Agent-local routines need setup.' : undefined,
|
|
343
|
+
)),
|
|
255
344
|
exitCode: 0,
|
|
256
345
|
};
|
|
257
346
|
}
|
|
@@ -285,7 +374,7 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
285
374
|
const failure: RoutinesCommandFailure = {
|
|
286
375
|
ok: false,
|
|
287
376
|
kind: 'routine_discovery_not_found',
|
|
288
|
-
error: `Unknown discovered Agent routine
|
|
377
|
+
error: `Unknown discovered Agent routine ${parsed.name}\nRun goodvibes-agent routines discover to inspect available routine files.`,
|
|
289
378
|
};
|
|
290
379
|
return {
|
|
291
380
|
output: runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(failure, null, 2) : failure.error,
|
|
@@ -301,12 +390,12 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
301
390
|
return {
|
|
302
391
|
output: jsonOrText(runtime, value, [
|
|
303
392
|
'Agent routine import preview',
|
|
304
|
-
` name
|
|
305
|
-
` origin
|
|
306
|
-
` path
|
|
307
|
-
` description
|
|
308
|
-
` steps characters
|
|
309
|
-
' next
|
|
393
|
+
` name ${discovered.name}`,
|
|
394
|
+
` origin ${discovered.origin}`,
|
|
395
|
+
` path ${discovered.path}`,
|
|
396
|
+
` description ${discovered.description || '(none)'}`,
|
|
397
|
+
` steps characters ${discovered.steps.length}`,
|
|
398
|
+
' next rerun with --yes to import into the Agent-local routine registry',
|
|
310
399
|
].join('\n')),
|
|
311
400
|
exitCode: 0,
|
|
312
401
|
};
|
|
@@ -317,6 +406,10 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
317
406
|
steps: discovered.steps,
|
|
318
407
|
tags: discoveredRoutineFrontmatterList(discovered, 'tags'),
|
|
319
408
|
triggers: discoveredRoutineFrontmatterList(discovered, 'triggers'),
|
|
409
|
+
requirements: buildAgentSkillRequirements({
|
|
410
|
+
env: discoveredRoutineFrontmatterAnyList(discovered, ['requiresEnv', 'requires-env', 'requires_env']),
|
|
411
|
+
commands: discoveredRoutineFrontmatterAnyList(discovered, ['requiresCommands', 'requires-commands', 'requires_commands', 'commands']),
|
|
412
|
+
}),
|
|
320
413
|
enabled: parsed.enabled,
|
|
321
414
|
source: 'imported',
|
|
322
415
|
provenance: `discovered:${discovered.origin}:${discovered.path}`,
|
|
@@ -327,10 +420,53 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
327
420
|
data: routine,
|
|
328
421
|
};
|
|
329
422
|
return {
|
|
330
|
-
output: jsonOrText(runtime, value,
|
|
423
|
+
output: jsonOrText(runtime, value, [
|
|
424
|
+
`Imported Agent routine ${routine.id}: ${routine.name}${routine.enabled ? ' (enabled)' : ''}`,
|
|
425
|
+
` name ${routine.name}`,
|
|
426
|
+
` enabled ${routine.enabled ? 'yes' : 'no'}`,
|
|
427
|
+
].join('\n')),
|
|
331
428
|
exitCode: 0,
|
|
332
429
|
};
|
|
333
430
|
}
|
|
431
|
+
if (normalized === 'create') {
|
|
432
|
+
const options = parseRoutineOptions(rest);
|
|
433
|
+
try {
|
|
434
|
+
const routine = registry.create({
|
|
435
|
+
name: requiredOption(options, 'name'),
|
|
436
|
+
description: requiredOption(options, 'description'),
|
|
437
|
+
steps: optionValue(options, 'steps') ?? options.positionals.join(' ').trim(),
|
|
438
|
+
tags: splitList(optionValue(options, 'tags')),
|
|
439
|
+
triggers: splitList(optionValue(options, 'triggers')),
|
|
440
|
+
requirements: buildAgentSkillRequirements({
|
|
441
|
+
env: splitList(optionValue(options, 'requires-env')),
|
|
442
|
+
commands: splitList(optionValue(options, 'requires-command') ?? optionValue(options, 'requires-commands')),
|
|
443
|
+
}),
|
|
444
|
+
enabled: hasFlag(options, 'enabled'),
|
|
445
|
+
source: 'user',
|
|
446
|
+
provenance: 'cli',
|
|
447
|
+
});
|
|
448
|
+
const value: RoutinesCommandSuccess<AgentRoutineRecord> = {
|
|
449
|
+
ok: true,
|
|
450
|
+
kind: 'agent.routines.create',
|
|
451
|
+
data: routine,
|
|
452
|
+
};
|
|
453
|
+
return {
|
|
454
|
+
output: jsonOrText(runtime, value, [
|
|
455
|
+
`Created Agent routine ${routine.id}: ${routine.name}${routine.enabled ? ' (enabled)' : ''}`,
|
|
456
|
+
` name ${routine.name}`,
|
|
457
|
+
` enabled ${routine.enabled ? 'yes' : 'no'}`,
|
|
458
|
+
].join('\n')),
|
|
459
|
+
exitCode: 0,
|
|
460
|
+
};
|
|
461
|
+
} catch (error) {
|
|
462
|
+
return commandFailure(
|
|
463
|
+
runtime,
|
|
464
|
+
error instanceof Error && error.message.startsWith('Usage:') ? 'invalid_routine_command' : 'agent.routines.create.error',
|
|
465
|
+
error instanceof Error ? error.message : String(error),
|
|
466
|
+
error instanceof Error && error.message.startsWith('Usage:') ? 2 : 1,
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
334
470
|
if (normalized === 'show') {
|
|
335
471
|
const id = rest[0];
|
|
336
472
|
if (!id) return { output: 'Usage: goodvibes-agent routines show <id>', exitCode: 2 };
|
|
@@ -363,7 +499,7 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
363
499
|
if (normalized === 'reconcile' || normalized === 'sync' || normalized === 'status') {
|
|
364
500
|
const store = routineReceiptStore(runtime);
|
|
365
501
|
const result = await reconcileRoutineScheduleReceipts(
|
|
366
|
-
|
|
502
|
+
resolveAgentConnectedHostConnection(runtime.configManager, runtime.homeDirectory),
|
|
367
503
|
store.snapshot(),
|
|
368
504
|
);
|
|
369
505
|
return {
|
|
@@ -376,7 +512,7 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
376
512
|
if (!id) return { output: 'Usage: goodvibes-agent routines receipt <receipt-id>', exitCode: 2 };
|
|
377
513
|
const receipt = routineReceiptStore(runtime).get(id);
|
|
378
514
|
if (!receipt) {
|
|
379
|
-
const failure: RoutinesCommandFailure = { ok: false, kind: 'routine_schedule_receipt_not_found', error: `Unknown routine schedule receipt
|
|
515
|
+
const failure: RoutinesCommandFailure = { ok: false, kind: 'routine_schedule_receipt_not_found', error: `Unknown routine schedule receipt ${id}` };
|
|
380
516
|
return {
|
|
381
517
|
output: runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(failure, null, 2) : failure.error,
|
|
382
518
|
exitCode: 1,
|
|
@@ -396,7 +532,7 @@ export async function handleRoutinesCommand(runtime: CliCommandRuntime): Promise
|
|
|
396
532
|
return handleRoutinePromotion(runtime, rest);
|
|
397
533
|
}
|
|
398
534
|
return {
|
|
399
|
-
output:
|
|
535
|
+
output: `Usage: goodvibes-agent routines [list|enabled|attention|discover|import-discovered <name> --yes|create --name <name> --description <summary> --steps <steps>|show <id>|receipts|reconcile|receipt <id>|promote <id> (--cron <expr>|--every <interval>|--at <iso-time>) [--delivery-channel <channel>|--delivery-route <route>|--delivery-webhook <url>] --yes]`,
|
|
400
536
|
exitCode: 2,
|
|
401
537
|
};
|
|
402
538
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { closeSync, existsSync, openSync, readSync, statSync } from 'node:fs';
|
|
2
2
|
import net from 'node:net';
|
|
3
3
|
import { isAbsolute, join } from 'node:path';
|
|
4
|
-
import type { ConfigManager } from '../config/index.ts';
|
|
4
|
+
import type { ConfigKey, ConfigManager } from '../config/index.ts';
|
|
5
5
|
import { resolveRuntimeEndpointBinding } from './endpoints.ts';
|
|
6
6
|
import type { RuntimeEndpointBinding, RuntimeEndpointId } from './endpoints.ts';
|
|
7
7
|
import { classifyBindPosture, isNetworkFacing } from './network-posture.ts';
|
|
@@ -32,7 +32,7 @@ export interface CliServiceLogPosture {
|
|
|
32
32
|
readonly readError?: string;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export interface
|
|
35
|
+
export interface CliExternalHostLifecyclePosture {
|
|
36
36
|
readonly platform: 'manual';
|
|
37
37
|
readonly path: string;
|
|
38
38
|
readonly installed: false;
|
|
@@ -54,13 +54,13 @@ export interface CliServicePosture {
|
|
|
54
54
|
readonly restartOnFailure: boolean;
|
|
55
55
|
readonly daemonEnabled: boolean;
|
|
56
56
|
};
|
|
57
|
-
readonly managed:
|
|
57
|
+
readonly managed: CliExternalHostLifecyclePosture;
|
|
58
58
|
readonly endpoints: readonly CliServiceEndpointPosture[];
|
|
59
59
|
readonly log: CliServiceLogPosture;
|
|
60
60
|
readonly issues: readonly string[];
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
const ENDPOINTS: readonly { readonly id: RuntimeEndpointId; readonly label: string; readonly enabledKey:
|
|
63
|
+
const ENDPOINTS: readonly { readonly id: RuntimeEndpointId; readonly label: string; readonly enabledKey: ConfigKey }[] = [
|
|
64
64
|
{ id: 'controlPlane', label: 'runtime connection', enabledKey: 'controlPlane.enabled' },
|
|
65
65
|
{ id: 'httpListener', label: 'inbound events endpoint', enabledKey: 'danger.httpListener' },
|
|
66
66
|
{ id: 'web', label: 'browser companion route', enabledKey: 'web.enabled' },
|
|
@@ -140,10 +140,10 @@ function resolveConfiguredLogPath(runtime: CliServiceRuntime): string | undefine
|
|
|
140
140
|
return isAbsolute(trimmed) ? trimmed : join(runtime.homeDirectory, trimmed);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
function
|
|
143
|
+
function createExternalHostLifecycle(logPath: string | undefined): CliExternalHostLifecyclePosture {
|
|
144
144
|
return {
|
|
145
145
|
platform: 'manual',
|
|
146
|
-
path: 'connected GoodVibes
|
|
146
|
+
path: 'connected GoodVibes host',
|
|
147
147
|
installed: false,
|
|
148
148
|
autostart: false,
|
|
149
149
|
running: false,
|
|
@@ -151,7 +151,7 @@ function createExternalDaemonLifecycle(logPath: string | undefined): CliExternal
|
|
|
151
151
|
commandPreview: 'managed outside goodvibes-agent',
|
|
152
152
|
suggestedCommands: [],
|
|
153
153
|
lastAction: 'status',
|
|
154
|
-
pidPath: 'connected GoodVibes
|
|
154
|
+
pidPath: 'connected GoodVibes host',
|
|
155
155
|
lastError: null,
|
|
156
156
|
};
|
|
157
157
|
}
|
|
@@ -161,7 +161,7 @@ export async function buildCliServicePosture(
|
|
|
161
161
|
options: CliServicePostureOptions = {},
|
|
162
162
|
): Promise<CliServicePosture> {
|
|
163
163
|
const endpoints = await Promise.all(ENDPOINTS.map(async (endpoint): Promise<CliServiceEndpointPosture> => {
|
|
164
|
-
const enabled = runtime.configManager.get(endpoint.enabledKey
|
|
164
|
+
const enabled = runtime.configManager.get(endpoint.enabledKey) === true;
|
|
165
165
|
const binding = resolveRuntimeEndpointBinding(runtime.configManager, endpoint.id);
|
|
166
166
|
return {
|
|
167
167
|
id: endpoint.id,
|
|
@@ -184,7 +184,7 @@ export async function buildCliServicePosture(
|
|
|
184
184
|
const issues: string[] = [];
|
|
185
185
|
|
|
186
186
|
if (serverBackedEnabled && !config.enabled) {
|
|
187
|
-
issues.push('Connected-
|
|
187
|
+
issues.push('Connected-host settings are present, but Agent host ownership is disabled by design.');
|
|
188
188
|
}
|
|
189
189
|
for (const endpoint of endpoints) {
|
|
190
190
|
if (endpoint.enabled && options.probe && endpoint.reachable === false) {
|
|
@@ -209,7 +209,7 @@ export async function buildCliServicePosture(
|
|
|
209
209
|
|
|
210
210
|
return {
|
|
211
211
|
config,
|
|
212
|
-
managed:
|
|
212
|
+
managed: createExternalHostLifecycle(configuredLogPath),
|
|
213
213
|
endpoints,
|
|
214
214
|
log,
|
|
215
215
|
issues,
|
|
@@ -223,21 +223,21 @@ function yesNo(value: boolean): string {
|
|
|
223
223
|
export function formatCliServicePosture(posture: CliServicePosture, json = false): string {
|
|
224
224
|
if (json) return JSON.stringify(posture, null, 2);
|
|
225
225
|
return [
|
|
226
|
-
'GoodVibes Agent
|
|
227
|
-
'
|
|
228
|
-
' Agent
|
|
226
|
+
'GoodVibes Agent connected-host diagnostics',
|
|
227
|
+
' lifecycle owner: outside goodvibes-agent',
|
|
228
|
+
' Agent starts connected host: no',
|
|
229
229
|
` external host config present: ${yesNo(posture.config.enabled)}`,
|
|
230
230
|
' external host lifecycle config: ignored by Agent',
|
|
231
231
|
` legacy host switch present: ${yesNo(posture.config.daemonEnabled)}`,
|
|
232
232
|
` log: ${posture.log.path ?? 'n/a'} (${posture.log.exists ? 'present' : 'missing'})`,
|
|
233
233
|
...(posture.log.readError ? [` log read error: ${posture.log.readError}`] : []),
|
|
234
234
|
'',
|
|
235
|
-
'Connected
|
|
235
|
+
'Connected API checks',
|
|
236
236
|
...posture.endpoints.map((endpoint) =>
|
|
237
|
-
` ${endpoint.label}
|
|
237
|
+
` ${endpoint.label} enabled ${yesNo(endpoint.enabled)} ${endpoint.binding.hostMode} ${endpoint.binding.host}:${endpoint.binding.port} posture ${endpoint.bindPosture.label}${endpoint.reachable === undefined ? '' : ` reachable ${yesNo(endpoint.reachable)}`}`,
|
|
238
238
|
),
|
|
239
239
|
'',
|
|
240
|
-
posture.issues.length === 0 ? 'Readiness
|
|
240
|
+
posture.issues.length === 0 ? 'Readiness ready' : 'Readiness needs attention',
|
|
241
241
|
...posture.issues.map((issue) => ` - ${issue}`),
|
|
242
242
|
].join('\n');
|
|
243
243
|
}
|