@pellux/goodvibes-agent 0.1.117 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176073 -170980
- package/docs/README.md +11 -5
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +29 -15
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +44 -9
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +2 -5
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-registry.ts +15 -14
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +26 -25
- package/src/agent/routine-registry.ts +13 -12
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +34 -32
- package/src/agent/routine-schedule-receipts.ts +28 -26
- package/src/agent/runtime-profile-starters.ts +2 -2
- package/src/agent/runtime-profile.ts +18 -17
- package/src/agent/skill-registry.ts +25 -24
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +39 -33
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +13 -8
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +29 -11
- package/src/cli/local-library-command.ts +134 -68
- package/src/cli/management-commands.ts +98 -62
- package/src/cli/management.ts +52 -26
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -24
- package/src/cli/profiles-command.ts +52 -35
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +44 -36
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +46 -121
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-activation.ts +33 -7
- package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
- package/src/input/agent-workspace-basic-command-editors.ts +30 -10
- package/src/input/agent-workspace-categories.ts +276 -64
- package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
- package/src/input/agent-workspace-channel-command-editors.ts +23 -5
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +18 -2
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
- package/src/input/agent-workspace-editors.ts +140 -2
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-learned-behavior.ts +2 -2
- package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
- package/src/input/agent-workspace-library-command-editors.ts +2 -2
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editors.ts +1 -1
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +38 -2
- package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
- package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
- package/src/input/agent-workspace-operations-command-editors.ts +80 -3
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-setup.ts +22 -11
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
- package/src/input/agent-workspace-snapshot.ts +112 -13
- package/src/input/agent-workspace-task-command-editors.ts +4 -4
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +92 -4
- package/src/input/agent-workspace-voice-media.ts +3 -6
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace.ts +136 -208
- package/src/input/command-registry.ts +4 -1
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +83 -70
- package/src/input/commands/agent-workspace-runtime.ts +23 -7
- package/src/input/commands/brief-runtime.ts +25 -24
- package/src/input/commands/channels-runtime.ts +145 -31
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +140 -115
- package/src/input/commands/knowledge.ts +57 -56
- package/src/input/commands/local-provider-runtime.ts +36 -18
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +7 -7
- package/src/input/commands/mcp-runtime.ts +56 -35
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -17
- package/src/input/commands/personas-runtime.ts +45 -30
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +29 -29
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +45 -6
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +59 -43
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +4 -4
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +132 -93
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +32 -17
- package/src/input/commands/subscription-runtime.ts +53 -179
- package/src/input/commands/tasks-runtime.ts +20 -20
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +2 -2
- package/src/input/feed-context-factory.ts +2 -1
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -1
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -3
- package/src/input/handler-interactions.ts +7 -5
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +24 -80
- package/src/input/handler-shortcuts.ts +15 -4
- package/src/input/handler.ts +47 -17
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +22 -11
- package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
- package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/onboarding/onboarding-wizard.ts +68 -0
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +6 -52
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -8
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +2 -2
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +1 -10
- package/src/panels/builtin/session.ts +9 -9
- package/src/panels/builtin/shared.ts +2 -2
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +18 -11
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +45 -4
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +1 -1
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +20 -13
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +1 -1
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +228 -52
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +106 -33
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +164 -50
- package/src/renderer/model-picker-overlay.ts +58 -2
- package/src/renderer/model-workspace.ts +104 -20
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +20 -4
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +83 -50
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +6 -6
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +9 -7
- package/src/runtime/bootstrap-core.ts +19 -1
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +31 -22
- package/src/runtime/connected-host-auth.ts +7 -2
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -1
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +80 -79
- package/src/runtime/onboarding/derivation.ts +5 -8
- package/src/runtime/onboarding/snapshot.ts +0 -15
- package/src/runtime/onboarding/types.ts +8 -19
- package/src/runtime/onboarding/verify.ts +32 -10
- package/src/runtime/operator-token-cleanup.ts +1 -1
- package/src/runtime/services.ts +91 -22
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/ui-openers.ts +3 -13
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +269 -69
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +8 -8
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -13
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -23,6 +23,30 @@ function formatDeliveryTargetKind(target: { readonly kind?: string; readonly sur
|
|
|
23
23
|
return `${target.kind ?? 'unknown'}${target.surfaceKind ? `/${target.surfaceKind}` : ''}`;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
function formatDeliveryTarget(target: {
|
|
27
|
+
readonly kind?: string;
|
|
28
|
+
readonly surfaceKind?: string;
|
|
29
|
+
readonly routeId?: string;
|
|
30
|
+
readonly address?: string;
|
|
31
|
+
readonly label?: string;
|
|
32
|
+
}): string {
|
|
33
|
+
const details = [
|
|
34
|
+
target.routeId ? `route=${target.routeId}` : '',
|
|
35
|
+
target.address ? `address=${target.address}` : '',
|
|
36
|
+
target.label ? `label=${target.label}` : '',
|
|
37
|
+
].filter(Boolean);
|
|
38
|
+
return `${formatDeliveryTargetKind(target)}${details.length > 0 ? ` ${details.join(' ')}` : ''}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function formatRoutineScheduleFailureKind(kind: string): string {
|
|
42
|
+
if (kind === 'auth_required') return 'authorization required';
|
|
43
|
+
if (kind === 'connected_host_unavailable') return 'connected host unavailable';
|
|
44
|
+
if (kind === 'connected_host_route_unavailable') return 'connected host route unavailable';
|
|
45
|
+
if (kind === 'connected_host_error') return 'connected host error';
|
|
46
|
+
if (kind === 'version_mismatch') return 'version mismatch';
|
|
47
|
+
return kind.replace(/[_-]+/g, ' ');
|
|
48
|
+
}
|
|
49
|
+
|
|
26
50
|
export function formatRoutineSchedulePreview(preview: RoutineSchedulePromotionPreview): string {
|
|
27
51
|
const schedule = preview.payload.kind === 'cron'
|
|
28
52
|
? `${preview.payload.cron}${preview.payload.timezone ? ` [${preview.payload.timezone}]` : ''}`
|
|
@@ -33,15 +57,15 @@ export function formatRoutineSchedulePreview(preview: RoutineSchedulePromotionPr
|
|
|
33
57
|
const deliveryTargetCount = delivery?.targets.length ?? 0;
|
|
34
58
|
return [
|
|
35
59
|
'GoodVibes schedule preview for Agent routine',
|
|
36
|
-
` routine
|
|
37
|
-
` route
|
|
38
|
-
` name
|
|
39
|
-
` schedule
|
|
40
|
-
` enabled
|
|
60
|
+
` routine ${preview.routineName} (${preview.routineId})`,
|
|
61
|
+
` route ${preview.method} ${preview.route}`,
|
|
62
|
+
` name ${String(preview.payload.name ?? '(connected-host default)')}`,
|
|
63
|
+
` schedule ${preview.payload.kind} ${schedule}`,
|
|
64
|
+
` enabled ${preview.payload.enabled === false ? 'no' : 'yes'}`,
|
|
41
65
|
` delivery: ${delivery?.mode ?? 'none'}${deliveryTargetCount > 0 ? ` (${deliveryTargetCount} target${deliveryTargetCount === 1 ? '' : 's'})` : ''}`,
|
|
42
|
-
' target
|
|
43
|
-
' policy
|
|
44
|
-
' next
|
|
66
|
+
' target connected GoodVibes host/main conversation route',
|
|
67
|
+
' policy isolated Agent Knowledge only; no default knowledge/non-Agent fallback; no delegated review unless explicitly requested',
|
|
68
|
+
' next rerun with --yes to create this connected schedule',
|
|
45
69
|
].join('\n');
|
|
46
70
|
}
|
|
47
71
|
|
|
@@ -51,11 +75,11 @@ export function formatRoutineScheduleSuccess(result: RoutineSchedulePromotionSuc
|
|
|
51
75
|
const status = readString(record, 'status') ?? (record.enabled === false ? 'paused' : 'enabled');
|
|
52
76
|
return [
|
|
53
77
|
'Created GoodVibes schedule for Agent routine',
|
|
54
|
-
` routine
|
|
55
|
-
` schedule
|
|
56
|
-
` status
|
|
57
|
-
` route
|
|
58
|
-
' next
|
|
78
|
+
` routine ${result.routineName} (${result.routineId})`,
|
|
79
|
+
` schedule ${id}`,
|
|
80
|
+
` status ${status}`,
|
|
81
|
+
` route ${result.kind} ${result.route}`,
|
|
82
|
+
' next inspect with /schedule list or schedule observability',
|
|
59
83
|
].join('\n');
|
|
60
84
|
}
|
|
61
85
|
|
|
@@ -64,18 +88,18 @@ export function formatRoutineScheduleReceipts(snapshot: RoutineScheduleReceiptSn
|
|
|
64
88
|
if (snapshot.receipts.length === 0) {
|
|
65
89
|
return [
|
|
66
90
|
'Agent routine schedule receipts',
|
|
67
|
-
` store
|
|
91
|
+
` store ${snapshot.path}`,
|
|
68
92
|
' No routine schedule promotions have been recorded yet.',
|
|
69
93
|
' Create one with /schedule promote-routine <routine-id> --cron <expr> --yes.',
|
|
70
94
|
].join('\n');
|
|
71
95
|
}
|
|
72
96
|
return [
|
|
73
97
|
`Agent routine schedule receipts (${snapshot.receipts.length})`,
|
|
74
|
-
` store
|
|
98
|
+
` store ${snapshot.path}`,
|
|
75
99
|
...receipts.map((receipt) => {
|
|
76
100
|
const schedule = receipt.scheduleId ? ` schedule=${receipt.scheduleId}` : '';
|
|
77
|
-
const failure = receipt.status === 'failed' && receipt.failureKind ? ` failure
|
|
78
|
-
return ` ${receipt.id} ${receipt.status} ${receipt.scheduleKind} ${receipt.scheduleValue} routine
|
|
101
|
+
const failure = receipt.status === 'failed' && receipt.failureKind ? ` failure ${formatRoutineScheduleFailureKind(receipt.failureKind)}` : '';
|
|
102
|
+
return ` ${receipt.id} ${receipt.status} ${receipt.scheduleKind} ${receipt.scheduleValue} routine ${receipt.routineId}${schedule}${failure}`;
|
|
79
103
|
}),
|
|
80
104
|
snapshot.receipts.length > receipts.length ? ` ...${snapshot.receipts.length - receipts.length} more` : '',
|
|
81
105
|
].filter((line): line is string => Boolean(line)).join('\n');
|
|
@@ -84,20 +108,20 @@ export function formatRoutineScheduleReceipts(snapshot: RoutineScheduleReceiptSn
|
|
|
84
108
|
export function formatRoutineScheduleReceipt(receipt: RoutineScheduleReceipt): string {
|
|
85
109
|
return [
|
|
86
110
|
`Agent routine schedule receipt ${receipt.id}`,
|
|
87
|
-
` created
|
|
88
|
-
` status
|
|
89
|
-
` routine
|
|
90
|
-
` route
|
|
91
|
-
`
|
|
92
|
-
` schedule
|
|
93
|
-
receipt.scheduleStatus ? ` schedule status
|
|
111
|
+
` created ${receipt.createdAt}`,
|
|
112
|
+
` status ${receipt.status}`,
|
|
113
|
+
` routine ${receipt.routineName} (${receipt.routineId})`,
|
|
114
|
+
` route ${receipt.method} ${receipt.route}`,
|
|
115
|
+
` connected host: ${receipt.connectedHostBaseUrl}`,
|
|
116
|
+
` schedule ${receipt.scheduleName}${receipt.scheduleId ? ` (${receipt.scheduleId})` : ''}`,
|
|
117
|
+
receipt.scheduleStatus ? ` schedule status ${receipt.scheduleStatus}` : '',
|
|
94
118
|
` cadence: ${receipt.scheduleKind} ${receipt.scheduleValue}${receipt.timezone ? ` [${receipt.timezone}]` : ''}`,
|
|
95
|
-
` enabled
|
|
96
|
-
receipt.provider ? ` provider
|
|
97
|
-
receipt.model ? ` model
|
|
98
|
-
` target
|
|
119
|
+
` enabled ${receipt.enabled ? 'yes' : 'no'}`,
|
|
120
|
+
receipt.provider ? ` provider ${receipt.provider}` : '',
|
|
121
|
+
receipt.model ? ` model ${receipt.model}` : '',
|
|
122
|
+
` target ${formatDeliveryTargetKind(receipt.target)}`,
|
|
99
123
|
receipt.deliveryMode ? ` delivery: ${receipt.deliveryMode}` : '',
|
|
100
|
-
...(receipt.deliveryTargets ?? []).map((target) => ` delivery target: ${
|
|
124
|
+
...(receipt.deliveryTargets ?? []).map((target) => ` delivery target: ${formatDeliveryTarget(target)}`),
|
|
101
125
|
receipt.failureKind ? ` failure: ${receipt.failureKind}` : '',
|
|
102
126
|
receipt.failureError ? ` error: ${receipt.failureError}` : '',
|
|
103
127
|
].filter((line): line is string => Boolean(line)).join('\n');
|
|
@@ -106,18 +130,18 @@ export function formatRoutineScheduleReceipt(receipt: RoutineScheduleReceipt): s
|
|
|
106
130
|
export function formatRoutineScheduleCorrelation(result: RoutineScheduleCorrelationResult, limit = 10): string {
|
|
107
131
|
if (!result.ok) {
|
|
108
132
|
return [
|
|
109
|
-
`GoodVibes schedule reconciliation error
|
|
133
|
+
`GoodVibes schedule reconciliation error ${formatRoutineScheduleFailureKind(result.kind)}`,
|
|
110
134
|
` ${result.error}`,
|
|
111
|
-
result.baseUrl ? `
|
|
112
|
-
` route
|
|
135
|
+
result.baseUrl ? ` connected host ${result.baseUrl}` : null,
|
|
136
|
+
` route ${ROUTINE_SCHEDULE_LIST_METHOD} ${result.route}`,
|
|
113
137
|
result.kind === 'auth_required'
|
|
114
|
-
? ' next
|
|
138
|
+
? ' next pair/authenticate with the connected GoodVibes host, then retry.'
|
|
115
139
|
: null,
|
|
116
|
-
result.kind === '
|
|
117
|
-
? ' next
|
|
140
|
+
result.kind === 'connected_host_unavailable'
|
|
141
|
+
? ' next make the connected GoodVibes host available outside Agent, then retry.'
|
|
118
142
|
: null,
|
|
119
|
-
result.kind === 'version_mismatch' || result.kind === '
|
|
120
|
-
? ' next
|
|
143
|
+
result.kind === 'version_mismatch' || result.kind === 'connected_host_route_unavailable'
|
|
144
|
+
? ' next update the connected GoodVibes host so public schedules.list is available.'
|
|
121
145
|
: null,
|
|
122
146
|
].filter((line): line is string => Boolean(line)).join('\n');
|
|
123
147
|
}
|
|
@@ -125,7 +149,7 @@ export function formatRoutineScheduleCorrelation(result: RoutineScheduleCorrelat
|
|
|
125
149
|
if (result.receiptCount === 0) {
|
|
126
150
|
return [
|
|
127
151
|
'Agent routine schedule reconciliation',
|
|
128
|
-
`
|
|
152
|
+
` connected host: ${result.baseUrl}`,
|
|
129
153
|
` route: ${result.kind} ${result.route}`,
|
|
130
154
|
` live schedules: ${result.scheduleCount}`,
|
|
131
155
|
' No local routine promotion receipts exist yet.',
|
|
@@ -137,20 +161,20 @@ export function formatRoutineScheduleCorrelation(result: RoutineScheduleCorrelat
|
|
|
137
161
|
const failed = result.correlations.filter((entry) => entry.liveStatus === 'failed-receipt').length;
|
|
138
162
|
return [
|
|
139
163
|
'Agent routine schedule reconciliation',
|
|
140
|
-
`
|
|
164
|
+
` connected host: ${result.baseUrl}`,
|
|
141
165
|
` route: ${result.kind} ${result.route}`,
|
|
142
166
|
` receipts: ${result.receiptCount}; live schedules: ${result.scheduleCount}; matched: ${matched}; missing: ${missing}; failed receipts: ${failed}`,
|
|
143
167
|
...correlations.map((entry) => {
|
|
144
168
|
const receipt = entry.receipt;
|
|
145
169
|
const schedule = entry.schedule;
|
|
146
170
|
const live = schedule
|
|
147
|
-
? ` live=${schedule.id} status
|
|
171
|
+
? ` live=${schedule.id}; status ${schedule.status ?? (schedule.enabled === false ? 'paused' : 'enabled')}`
|
|
148
172
|
: '';
|
|
149
173
|
const runs = schedule && schedule.runCount !== undefined
|
|
150
|
-
? ` runs
|
|
174
|
+
? ` runs ${schedule.runCount}/${schedule.successCount ?? 0}/${schedule.failureCount ?? 0}`
|
|
151
175
|
: '';
|
|
152
|
-
const next = schedule?.nextRunAt ? ` next
|
|
153
|
-
return ` ${receipt.id} ${entry.liveStatus} reason
|
|
176
|
+
const next = schedule?.nextRunAt ? ` next ${new Date(schedule.nextRunAt).toISOString()}` : '';
|
|
177
|
+
return ` ${receipt.id} ${entry.liveStatus} reason ${entry.matchReason} routine ${receipt.routineId} receipt schedule ${receipt.scheduleId ?? '(none)'}${live}${runs}${next}`;
|
|
154
178
|
}),
|
|
155
179
|
result.correlations.length > correlations.length ? ` ...${result.correlations.length - correlations.length} more` : '',
|
|
156
180
|
].filter((line): line is string => Boolean(line)).join('\n');
|
|
@@ -158,21 +182,21 @@ export function formatRoutineScheduleCorrelation(result: RoutineScheduleCorrelat
|
|
|
158
182
|
|
|
159
183
|
export function formatRoutineScheduleFailure(failure: RoutineSchedulePromotionFailure): string {
|
|
160
184
|
return [
|
|
161
|
-
`GoodVibes schedule error
|
|
185
|
+
`GoodVibes schedule error ${formatRoutineScheduleFailureKind(failure.kind)}`,
|
|
162
186
|
` ${failure.error}`,
|
|
163
|
-
failure.baseUrl ? `
|
|
164
|
-
` route
|
|
165
|
-
failure.kind === 'version_mismatch' && failure.
|
|
166
|
-
? ` versions
|
|
187
|
+
failure.baseUrl ? ` connected host ${failure.baseUrl}` : null,
|
|
188
|
+
` route ${ROUTINE_SCHEDULE_METHOD} ${failure.route}`,
|
|
189
|
+
failure.kind === 'version_mismatch' && failure.connectedHostVersion && failure.expectedSdkVersion
|
|
190
|
+
? ` versions connected host ${failure.connectedHostVersion}; expected ${failure.expectedSdkVersion}`
|
|
167
191
|
: null,
|
|
168
192
|
failure.kind === 'auth_required'
|
|
169
|
-
? ' next
|
|
193
|
+
? ' next pair/authenticate with the connected GoodVibes host, then retry with --yes.'
|
|
170
194
|
: null,
|
|
171
|
-
failure.kind === '
|
|
172
|
-
|
|
195
|
+
failure.kind === 'connected_host_unavailable'
|
|
196
|
+
? ' next make the connected GoodVibes host available outside Agent, then retry.'
|
|
173
197
|
: null,
|
|
174
|
-
failure.kind === 'version_mismatch' || failure.kind === '
|
|
175
|
-
? ' next
|
|
198
|
+
failure.kind === 'version_mismatch' || failure.kind === 'connected_host_route_unavailable'
|
|
199
|
+
? ' next update the connected GoodVibes host so public schedules.create is available.'
|
|
176
200
|
: null,
|
|
177
201
|
].filter((line): line is string => Boolean(line)).join('\n');
|
|
178
202
|
}
|
|
@@ -5,6 +5,7 @@ import type { OperatorMethodInput, OperatorMethodOutput } from '@pellux/goodvibe
|
|
|
5
5
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
6
6
|
import { getModelIdFromProviderModel, getProviderIdFromModel } from '../config/provider-model.ts';
|
|
7
7
|
import { SDK_VERSION } from '../version.ts';
|
|
8
|
+
import { formatAgentRecordReviewState } from './record-labels.ts';
|
|
8
9
|
import type { AgentRoutineRecord } from './routine-registry.ts';
|
|
9
10
|
|
|
10
11
|
export const ROUTINE_SCHEDULE_ROUTE = '/api/automation/schedules';
|
|
@@ -16,11 +17,11 @@ type ScheduleCreateOutput = OperatorMethodOutput<'schedules.create'>;
|
|
|
16
17
|
type ScheduleDeliveryInput = NonNullable<ScheduleCreateInput['delivery']>;
|
|
17
18
|
type ScheduleDeliveryTargetInput = ScheduleDeliveryInput['targets'] extends readonly (infer T)[] ? T : never;
|
|
18
19
|
|
|
19
|
-
export interface
|
|
20
|
+
export interface AgentConnectedHostConfigReader {
|
|
20
21
|
get(key: string): unknown;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
export interface
|
|
24
|
+
export interface AgentConnectedHostConnection {
|
|
24
25
|
readonly baseUrl: string;
|
|
25
26
|
readonly token: string | null;
|
|
26
27
|
readonly tokenPath: string;
|
|
@@ -46,6 +47,7 @@ export type RoutineScheduleDeliverySurfaceKind =
|
|
|
46
47
|
| 'google-chat'
|
|
47
48
|
| 'signal'
|
|
48
49
|
| 'whatsapp'
|
|
50
|
+
| 'telephony'
|
|
49
51
|
| 'imessage'
|
|
50
52
|
| 'msteams'
|
|
51
53
|
| 'bluebubbles'
|
|
@@ -105,14 +107,14 @@ export interface RoutineSchedulePromotionFailure {
|
|
|
105
107
|
readonly kind:
|
|
106
108
|
| 'confirmation_required'
|
|
107
109
|
| 'auth_required'
|
|
108
|
-
| '
|
|
110
|
+
| 'connected_host_unavailable'
|
|
109
111
|
| 'version_mismatch'
|
|
110
|
-
| '
|
|
111
|
-
| '
|
|
112
|
+
| 'connected_host_route_unavailable'
|
|
113
|
+
| 'connected_host_error';
|
|
112
114
|
readonly error: string;
|
|
113
115
|
readonly route: typeof ROUTINE_SCHEDULE_ROUTE;
|
|
114
116
|
readonly baseUrl?: string;
|
|
115
|
-
readonly
|
|
117
|
+
readonly connectedHostVersion?: string;
|
|
116
118
|
readonly expectedSdkVersion?: string;
|
|
117
119
|
}
|
|
118
120
|
|
|
@@ -128,7 +130,7 @@ export interface RoutineScheduleReceipt {
|
|
|
128
130
|
readonly route: typeof ROUTINE_SCHEDULE_ROUTE;
|
|
129
131
|
readonly method: typeof ROUTINE_SCHEDULE_METHOD;
|
|
130
132
|
readonly status: 'created' | 'failed';
|
|
131
|
-
readonly
|
|
133
|
+
readonly connectedHostBaseUrl: string;
|
|
132
134
|
readonly scheduleId?: string;
|
|
133
135
|
readonly scheduleStatus?: string;
|
|
134
136
|
readonly scheduleName: string;
|
|
@@ -191,14 +193,14 @@ export interface RoutineScheduleCorrelationFailure {
|
|
|
191
193
|
readonly ok: false;
|
|
192
194
|
readonly kind:
|
|
193
195
|
| 'auth_required'
|
|
194
|
-
| '
|
|
196
|
+
| 'connected_host_unavailable'
|
|
195
197
|
| 'version_mismatch'
|
|
196
|
-
| '
|
|
197
|
-
| '
|
|
198
|
+
| 'connected_host_route_unavailable'
|
|
199
|
+
| 'connected_host_error';
|
|
198
200
|
readonly error: string;
|
|
199
201
|
readonly route: typeof ROUTINE_SCHEDULE_ROUTE;
|
|
200
202
|
readonly baseUrl?: string;
|
|
201
|
-
readonly
|
|
203
|
+
readonly connectedHostVersion?: string;
|
|
202
204
|
readonly expectedSdkVersion?: string;
|
|
203
205
|
}
|
|
204
206
|
|
|
@@ -236,17 +238,17 @@ function deliveryModeFromTargets(targets: readonly RoutineScheduleDeliveryTarget
|
|
|
236
238
|
function toDeliveryTargetInput(target: RoutineScheduleDeliveryTargetSpec): ScheduleDeliveryTargetInput {
|
|
237
239
|
return {
|
|
238
240
|
kind: target.kind,
|
|
239
|
-
surfaceKind: target.surfaceKind,
|
|
241
|
+
surfaceKind: target.surfaceKind as ScheduleDeliveryTargetInput['surfaceKind'],
|
|
240
242
|
address: target.address,
|
|
241
243
|
routeId: target.routeId,
|
|
242
244
|
label: target.label,
|
|
243
245
|
};
|
|
244
246
|
}
|
|
245
247
|
|
|
246
|
-
export function
|
|
247
|
-
configManager:
|
|
248
|
+
export function resolveAgentConnectedHostConnection(
|
|
249
|
+
configManager: AgentConnectedHostConfigReader,
|
|
248
250
|
homeDirectory: string,
|
|
249
|
-
):
|
|
251
|
+
): AgentConnectedHostConnection {
|
|
250
252
|
const host = String(configManager.get('controlPlane.host') ?? '127.0.0.1');
|
|
251
253
|
const port = Number(configManager.get('controlPlane.port') ?? 3421);
|
|
252
254
|
const tokenPath = join(homeDirectory, '.goodvibes', 'daemon', 'operator-tokens.json');
|
|
@@ -265,16 +267,16 @@ export function buildRoutineSchedulePrompt(routine: AgentRoutineRecord): string
|
|
|
265
267
|
'GoodVibes Agent scheduled routine.',
|
|
266
268
|
'',
|
|
267
269
|
`Routine: ${routine.name}`,
|
|
268
|
-
`Routine
|
|
269
|
-
`Review
|
|
270
|
+
`Routine reference: ${routine.id}`,
|
|
271
|
+
`Review: ${formatAgentRecordReviewState(routine.reviewState)}`,
|
|
270
272
|
`Tags: ${routine.tags.join(', ') || '(none)'}`,
|
|
271
273
|
`Triggers: ${routine.triggers.join(', ') || '(manual)'}`,
|
|
272
274
|
'',
|
|
273
275
|
'Operator policy:',
|
|
274
276
|
'- Run this as a serial GoodVibes Agent operator routine.',
|
|
275
|
-
'- Use isolated Agent Knowledge routes only; never use default
|
|
277
|
+
'- Use isolated Agent Knowledge routes only; never use default knowledge or non-Agent knowledge spaces as fallback.',
|
|
276
278
|
'- Do not perform destructive, costly, externally visible, or secret-handling actions without explicit approval.',
|
|
277
|
-
'- Do not request
|
|
279
|
+
'- Do not request GoodVibes TUI delegation unless this scheduled routine explicitly delegates build/fix/review work to GoodVibes TUI.',
|
|
278
280
|
'- Summarize what was checked, what changed, and what still needs user review.',
|
|
279
281
|
'',
|
|
280
282
|
'Routine description:',
|
|
@@ -354,7 +356,7 @@ export function buildRoutineSchedulePreview(
|
|
|
354
356
|
};
|
|
355
357
|
}
|
|
356
358
|
|
|
357
|
-
async function
|
|
359
|
+
async function fetchConnectedHostStatus(connection: AgentConnectedHostConnection): Promise<{
|
|
358
360
|
readonly ok: boolean;
|
|
359
361
|
readonly status: number;
|
|
360
362
|
readonly body: unknown;
|
|
@@ -378,7 +380,7 @@ async function fetchDaemonStatus(connection: AgentDaemonConnection): Promise<{
|
|
|
378
380
|
|
|
379
381
|
async function classifyScheduleError(
|
|
380
382
|
error: unknown,
|
|
381
|
-
connection:
|
|
383
|
+
connection: AgentConnectedHostConnection,
|
|
382
384
|
): Promise<RoutineSchedulePromotionFailure> {
|
|
383
385
|
const message = summarizeError(error);
|
|
384
386
|
const lower = message.toLowerCase();
|
|
@@ -386,30 +388,30 @@ async function classifyScheduleError(
|
|
|
386
388
|
return { ok: false, kind: 'auth_required', error: message, route: ROUTINE_SCHEDULE_ROUTE, baseUrl: connection.baseUrl };
|
|
387
389
|
}
|
|
388
390
|
if (lower.includes('404') || lower.includes('not found')) {
|
|
389
|
-
const
|
|
390
|
-
const record = isRecord(
|
|
391
|
-
const
|
|
392
|
-
if (
|
|
391
|
+
const connectedHost = await fetchConnectedHostStatus(connection);
|
|
392
|
+
const record = isRecord(connectedHost.body) ? connectedHost.body : {};
|
|
393
|
+
const connectedHostVersion = readString(record, 'version') ?? 'unknown';
|
|
394
|
+
if (connectedHost.ok && connectedHostVersion !== SDK_VERSION) {
|
|
393
395
|
return {
|
|
394
396
|
ok: false,
|
|
395
397
|
kind: 'version_mismatch',
|
|
396
|
-
error: `Connected GoodVibes
|
|
398
|
+
error: `Connected GoodVibes host SDK version ${connectedHostVersion} does not match Agent SDK pin ${SDK_VERSION}; schedules.create is unavailable.`,
|
|
397
399
|
route: ROUTINE_SCHEDULE_ROUTE,
|
|
398
400
|
baseUrl: connection.baseUrl,
|
|
399
|
-
|
|
401
|
+
connectedHostVersion,
|
|
400
402
|
expectedSdkVersion: SDK_VERSION,
|
|
401
403
|
};
|
|
402
404
|
}
|
|
403
|
-
return { ok: false, kind: '
|
|
405
|
+
return { ok: false, kind: 'connected_host_route_unavailable', error: message, route: ROUTINE_SCHEDULE_ROUTE, baseUrl: connection.baseUrl };
|
|
404
406
|
}
|
|
405
407
|
if (lower.includes('fetch') || lower.includes('connect') || lower.includes('econnrefused')) {
|
|
406
|
-
return { ok: false, kind: '
|
|
408
|
+
return { ok: false, kind: 'connected_host_unavailable', error: message, route: ROUTINE_SCHEDULE_ROUTE, baseUrl: connection.baseUrl };
|
|
407
409
|
}
|
|
408
|
-
return { ok: false, kind: '
|
|
410
|
+
return { ok: false, kind: 'connected_host_error', error: message, route: ROUTINE_SCHEDULE_ROUTE, baseUrl: connection.baseUrl };
|
|
409
411
|
}
|
|
410
412
|
|
|
411
|
-
export async function
|
|
412
|
-
connection:
|
|
413
|
+
export async function promoteRoutineToConnectedSchedule(
|
|
414
|
+
connection: AgentConnectedHostConnection,
|
|
413
415
|
preview: RoutineSchedulePromotionPreview,
|
|
414
416
|
): Promise<RoutineSchedulePromotionResult> {
|
|
415
417
|
if (!connection.token) {
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
ROUTINE_SCHEDULE_LIST_METHOD,
|
|
13
13
|
ROUTINE_SCHEDULE_METHOD,
|
|
14
14
|
ROUTINE_SCHEDULE_ROUTE,
|
|
15
|
-
type
|
|
15
|
+
type AgentConnectedHostConnection,
|
|
16
16
|
type RoutineScheduleCorrelation,
|
|
17
17
|
type RoutineScheduleCorrelationFailure,
|
|
18
18
|
type RoutineScheduleCorrelationResult,
|
|
@@ -82,6 +82,15 @@ function redactedDeliveryTargets(delivery: ScheduleDeliveryInput | undefined): r
|
|
|
82
82
|
}));
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
function normalizeFailureKind(value: unknown): RoutineScheduleReceipt['failureKind'] {
|
|
86
|
+
if (value === 'confirmation_required' || value === 'auth_required' || value === 'version_mismatch') return value;
|
|
87
|
+
if (value === 'connected_host_unavailable' || value === 'connected_host_route_unavailable' || value === 'connected_host_error') return value;
|
|
88
|
+
if (value === 'daemon_unavailable') return 'connected_host_unavailable';
|
|
89
|
+
if (value === 'daemon_route_unavailable') return 'connected_host_route_unavailable';
|
|
90
|
+
if (value === 'daemon_error') return 'connected_host_error';
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
function readReceipt(value: unknown): RoutineScheduleReceipt | null {
|
|
86
95
|
if (!isRecord(value)) return null;
|
|
87
96
|
const id = readString(value, 'id')?.trim();
|
|
@@ -120,7 +129,7 @@ function readReceipt(value: unknown): RoutineScheduleReceipt | null {
|
|
|
120
129
|
route: ROUTINE_SCHEDULE_ROUTE,
|
|
121
130
|
method: ROUTINE_SCHEDULE_METHOD,
|
|
122
131
|
status,
|
|
123
|
-
|
|
132
|
+
connectedHostBaseUrl: readString(value, 'connectedHostBaseUrl') ?? readString(value, 'daemonBaseUrl') ?? '',
|
|
124
133
|
scheduleId: readString(value, 'scheduleId') ?? undefined,
|
|
125
134
|
scheduleStatus: readString(value, 'scheduleStatus') ?? undefined,
|
|
126
135
|
scheduleName: readString(value, 'scheduleName') ?? routineName,
|
|
@@ -138,14 +147,7 @@ function readReceipt(value: unknown): RoutineScheduleReceipt | null {
|
|
|
138
147
|
},
|
|
139
148
|
deliveryMode: readString(value, 'deliveryMode') ?? undefined,
|
|
140
149
|
deliveryTargets,
|
|
141
|
-
failureKind: value.failureKind
|
|
142
|
-
|| value.failureKind === 'auth_required'
|
|
143
|
-
|| value.failureKind === 'daemon_unavailable'
|
|
144
|
-
|| value.failureKind === 'version_mismatch'
|
|
145
|
-
|| value.failureKind === 'daemon_route_unavailable'
|
|
146
|
-
|| value.failureKind === 'daemon_error'
|
|
147
|
-
? value.failureKind
|
|
148
|
-
: undefined,
|
|
150
|
+
failureKind: normalizeFailureKind(value.failureKind),
|
|
149
151
|
failureError: readString(value, 'failureError') ?? undefined,
|
|
150
152
|
};
|
|
151
153
|
}
|
|
@@ -209,7 +211,7 @@ function resultScheduleRecord(result: RoutineSchedulePromotionResult): Record<st
|
|
|
209
211
|
|
|
210
212
|
function buildReceipt(
|
|
211
213
|
existing: readonly RoutineScheduleReceipt[],
|
|
212
|
-
connection:
|
|
214
|
+
connection: AgentConnectedHostConnection,
|
|
213
215
|
preview: RoutineSchedulePromotionPreview,
|
|
214
216
|
result: RoutineSchedulePromotionResult,
|
|
215
217
|
): RoutineScheduleReceipt {
|
|
@@ -226,7 +228,7 @@ function buildReceipt(
|
|
|
226
228
|
route: ROUTINE_SCHEDULE_ROUTE,
|
|
227
229
|
method: ROUTINE_SCHEDULE_METHOD,
|
|
228
230
|
status: result.ok ? 'created' : 'failed',
|
|
229
|
-
|
|
231
|
+
connectedHostBaseUrl: connection.baseUrl,
|
|
230
232
|
scheduleId,
|
|
231
233
|
scheduleStatus,
|
|
232
234
|
scheduleName: String(preview.payload.name ?? `Agent routine: ${preview.routineName}`),
|
|
@@ -269,7 +271,7 @@ export class RoutineScheduleReceiptStore {
|
|
|
269
271
|
return this.snapshot().receipts.find((receipt) => receipt.id.toLowerCase() === normalized) ?? null;
|
|
270
272
|
}
|
|
271
273
|
|
|
272
|
-
public append(connection:
|
|
274
|
+
public append(connection: AgentConnectedHostConnection, preview: RoutineSchedulePromotionPreview, result: RoutineSchedulePromotionResult): RoutineScheduleReceipt {
|
|
273
275
|
const store = this.readStore();
|
|
274
276
|
const receipt = buildReceipt(store.receipts, connection, preview, result);
|
|
275
277
|
this.writeStore({ ...store, receipts: [...store.receipts, receipt] });
|
|
@@ -281,7 +283,7 @@ export class RoutineScheduleReceiptStore {
|
|
|
281
283
|
try {
|
|
282
284
|
return parseReceiptStore(readFileSync(this.storePath, 'utf-8'));
|
|
283
285
|
} catch (error) {
|
|
284
|
-
throw new Error(`Could not read Agent routine schedule receipt store
|
|
286
|
+
throw new Error(`Could not read Agent routine schedule receipt store ${summarizeError(error)}`);
|
|
285
287
|
}
|
|
286
288
|
}
|
|
287
289
|
|
|
@@ -415,7 +417,7 @@ function correlateReceipts(
|
|
|
415
417
|
});
|
|
416
418
|
}
|
|
417
419
|
|
|
418
|
-
async function
|
|
420
|
+
async function fetchConnectedHostStatus(connection: AgentConnectedHostConnection): Promise<{
|
|
419
421
|
readonly ok: boolean;
|
|
420
422
|
readonly status: number;
|
|
421
423
|
readonly body: unknown;
|
|
@@ -439,7 +441,7 @@ async function fetchDaemonStatus(connection: AgentDaemonConnection): Promise<{
|
|
|
439
441
|
|
|
440
442
|
async function classifyScheduleListError(
|
|
441
443
|
error: unknown,
|
|
442
|
-
connection:
|
|
444
|
+
connection: AgentConnectedHostConnection,
|
|
443
445
|
): Promise<RoutineScheduleCorrelationFailure> {
|
|
444
446
|
const message = summarizeError(error);
|
|
445
447
|
const lower = message.toLowerCase();
|
|
@@ -447,30 +449,30 @@ async function classifyScheduleListError(
|
|
|
447
449
|
return { ok: false, kind: 'auth_required', error: message, route: ROUTINE_SCHEDULE_ROUTE, baseUrl: connection.baseUrl };
|
|
448
450
|
}
|
|
449
451
|
if (lower.includes('404') || lower.includes('not found')) {
|
|
450
|
-
const
|
|
451
|
-
const record = isRecord(
|
|
452
|
-
const
|
|
453
|
-
if (
|
|
452
|
+
const connectedHost = await fetchConnectedHostStatus(connection);
|
|
453
|
+
const record = isRecord(connectedHost.body) ? connectedHost.body : {};
|
|
454
|
+
const connectedHostVersion = readString(record, 'version') ?? 'unknown';
|
|
455
|
+
if (connectedHost.ok && connectedHostVersion !== SDK_VERSION) {
|
|
454
456
|
return {
|
|
455
457
|
ok: false,
|
|
456
458
|
kind: 'version_mismatch',
|
|
457
|
-
error: `Connected GoodVibes
|
|
459
|
+
error: `Connected GoodVibes host SDK version ${connectedHostVersion} does not match Agent SDK pin ${SDK_VERSION}; schedules.list is unavailable.`,
|
|
458
460
|
route: ROUTINE_SCHEDULE_ROUTE,
|
|
459
461
|
baseUrl: connection.baseUrl,
|
|
460
|
-
|
|
462
|
+
connectedHostVersion,
|
|
461
463
|
expectedSdkVersion: SDK_VERSION,
|
|
462
464
|
};
|
|
463
465
|
}
|
|
464
|
-
return { ok: false, kind: '
|
|
466
|
+
return { ok: false, kind: 'connected_host_route_unavailable', error: message, route: ROUTINE_SCHEDULE_ROUTE, baseUrl: connection.baseUrl };
|
|
465
467
|
}
|
|
466
468
|
if (lower.includes('fetch') || lower.includes('connect') || lower.includes('econnrefused')) {
|
|
467
|
-
return { ok: false, kind: '
|
|
469
|
+
return { ok: false, kind: 'connected_host_unavailable', error: message, route: ROUTINE_SCHEDULE_ROUTE, baseUrl: connection.baseUrl };
|
|
468
470
|
}
|
|
469
|
-
return { ok: false, kind: '
|
|
471
|
+
return { ok: false, kind: 'connected_host_error', error: message, route: ROUTINE_SCHEDULE_ROUTE, baseUrl: connection.baseUrl };
|
|
470
472
|
}
|
|
471
473
|
|
|
472
474
|
export async function reconcileRoutineScheduleReceipts(
|
|
473
|
-
connection:
|
|
475
|
+
connection: AgentConnectedHostConnection,
|
|
474
476
|
snapshot: RoutineScheduleReceiptSnapshot,
|
|
475
477
|
): Promise<RoutineScheduleCorrelationResult> {
|
|
476
478
|
if (!connection.token) {
|
|
@@ -81,7 +81,7 @@ export const STARTER_TEMPLATES: readonly AgentRuntimeProfileStarterTemplate[] =
|
|
|
81
81
|
description: 'Review open household commitments, pending approvals, and stale home notes.',
|
|
82
82
|
steps: [
|
|
83
83
|
'1. List pending local routines, workplan tasks, and approvals.',
|
|
84
|
-
'2. Summarize what changed since the last review from local
|
|
84
|
+
'2. Summarize what changed since the last review from Agent-local state.',
|
|
85
85
|
'3. Ask for confirmation before scheduling, sending messages, purchasing, or changing services.',
|
|
86
86
|
'4. Record reviewed preferences and stale notes locally.',
|
|
87
87
|
].join('\n'),
|
|
@@ -200,7 +200,7 @@ export const STARTER_TEMPLATES: readonly AgentRuntimeProfileStarterTemplate[] =
|
|
|
200
200
|
name: 'Pre-trip Readiness Review',
|
|
201
201
|
description: 'Check documents, reservations, transport, packing, weather, and open decisions.',
|
|
202
202
|
steps: [
|
|
203
|
-
'1. Review trip dates, locations, reservations, and open decisions from local
|
|
203
|
+
'1. Review trip dates, locations, reservations, and open decisions from Agent-local state.',
|
|
204
204
|
'2. Refresh current weather, schedule, and rule data when needed.',
|
|
205
205
|
'3. Summarize blockers and next confirmed action.',
|
|
206
206
|
'4. Ask before external sends, purchases, or reservation changes.',
|