@pellux/goodvibes-agent 0.1.117 → 1.0.1
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 +20 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176093 -171065
- 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 +159 -73
- 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 +59 -39
- 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-knowledge-url-editor.ts +4 -11
- 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-local-library-args.ts +52 -0
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +87 -99
- 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 +118 -50
- 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 +49 -59
- 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 +63 -72
- 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 +22 -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
|
@@ -7,6 +7,16 @@ import { stripDangerousAnsi } from './ansi-sanitize.ts';
|
|
|
7
7
|
const TOOL_NAME_MIN_WIDTH = 8;
|
|
8
8
|
const TOOL_NAME_MAX_WIDTH = 20;
|
|
9
9
|
|
|
10
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
11
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function readStringField(value: unknown, field: string): string | null {
|
|
15
|
+
if (!isRecord(value)) return null;
|
|
16
|
+
const fieldValue = value[field];
|
|
17
|
+
return typeof fieldValue === 'string' ? fieldValue : null;
|
|
18
|
+
}
|
|
19
|
+
|
|
10
20
|
function writeStyledText(
|
|
11
21
|
line: Line,
|
|
12
22
|
startCol: number,
|
|
@@ -100,32 +110,31 @@ function extractKeyArg(toolCall: ToolCall): string {
|
|
|
100
110
|
if (Array.isArray(args.files) && args.files.length > 0) {
|
|
101
111
|
const first = args.files[0];
|
|
102
112
|
if (typeof first === 'string') return first;
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
const path = readStringField(first, 'path');
|
|
114
|
+
if (path) return path;
|
|
105
115
|
}
|
|
106
116
|
// Exec
|
|
107
117
|
if (typeof args.command === 'string') return args.command;
|
|
108
118
|
if (typeof args.cmd === 'string') return args.cmd;
|
|
109
119
|
if (Array.isArray(args.commands) && args.commands.length > 0) {
|
|
110
120
|
const first = args.commands[0];
|
|
111
|
-
|
|
112
|
-
|
|
121
|
+
const cmd = readStringField(first, 'cmd');
|
|
122
|
+
if (cmd) return cmd;
|
|
113
123
|
}
|
|
114
124
|
// Find/grep
|
|
115
125
|
if (typeof args.pattern === 'string') return args.pattern;
|
|
116
126
|
if (Array.isArray(args.queries) && args.queries.length > 0) {
|
|
117
127
|
const first = args.queries[0];
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
128
|
+
const query = readStringField(first, 'query');
|
|
129
|
+
if (query) return query;
|
|
130
|
+
const pattern = readStringField(first, 'pattern');
|
|
131
|
+
if (pattern) return pattern;
|
|
123
132
|
}
|
|
124
133
|
// Fetch
|
|
125
134
|
if (Array.isArray(args.urls) && args.urls.length > 0) {
|
|
126
135
|
const first = args.urls[0];
|
|
127
|
-
|
|
128
|
-
|
|
136
|
+
const url = readStringField(first, 'url');
|
|
137
|
+
if (url) return url;
|
|
129
138
|
}
|
|
130
139
|
// Agent
|
|
131
140
|
if (typeof args.task === 'string') return args.task.slice(0, 40);
|
|
@@ -88,11 +88,11 @@ export function registerAgentRuntimeEvents(options: AgentRuntimeEventBridgeOptio
|
|
|
88
88
|
const durationSeconds = record.completedAt !== undefined ? Math.round((record.completedAt - record.startedAt) / 1000) : 0;
|
|
89
89
|
const taskSnippet = formatAgentTask(record.task);
|
|
90
90
|
withRouter(getSystemMessageRouter, (router) => {
|
|
91
|
-
router.low(`[
|
|
91
|
+
router.low(`[Delegated task] ${record.template} ${payload.agentId.slice(-8)} completed in ${durationSeconds}s "${taskSnippet}"`);
|
|
92
92
|
});
|
|
93
93
|
queueConversationFollowUp?.({
|
|
94
94
|
key: `agent:${payload.agentId}:completed`,
|
|
95
|
-
summary: `${record.template}
|
|
95
|
+
summary: `${record.template} delegated task ${payload.agentId.slice(-8)} completed "${taskSnippet}" in ${durationSeconds}s after ${record.toolCallCount} tool calls.`,
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
98
|
requestRender();
|
|
@@ -103,11 +103,11 @@ export function registerAgentRuntimeEvents(options: AgentRuntimeEventBridgeOptio
|
|
|
103
103
|
const durationSeconds = record.completedAt !== undefined ? Math.round((record.completedAt - record.startedAt) / 1000) : 0;
|
|
104
104
|
const taskSnippet = formatAgentTask(record.task);
|
|
105
105
|
withRouter(getSystemMessageRouter, (router) => {
|
|
106
|
-
router.low(`[
|
|
106
|
+
router.low(`[Delegated task] ${record.template} ${payload.agentId.slice(-8)} failed in ${durationSeconds}s ${payload.error.slice(0, 80)}`);
|
|
107
107
|
});
|
|
108
108
|
queueConversationFollowUp?.({
|
|
109
109
|
key: `agent:${payload.agentId}:failed`,
|
|
110
|
-
summary: `${record.template}
|
|
110
|
+
summary: `${record.template} delegated task ${payload.agentId.slice(-8)} failed while working on "${taskSnippet}" ${payload.error.slice(0, 120)}`,
|
|
111
111
|
});
|
|
112
112
|
}
|
|
113
113
|
requestRender();
|
|
@@ -117,9 +117,9 @@ export function registerAgentRuntimeEvents(options: AgentRuntimeEventBridgeOptio
|
|
|
117
117
|
agentStatusIntervalRef.value = setInterval(() => {
|
|
118
118
|
const running = agentManager.list().filter((agent) => agent.status === 'running');
|
|
119
119
|
if (running.length === 0) return;
|
|
120
|
-
const lines = running.map((agent) => ` ${agent.id.slice(-8)}
|
|
120
|
+
const lines = running.map((agent) => ` ${agent.id.slice(-8)} ${agent.progress ?? agent.status}`);
|
|
121
121
|
withRouter(getSystemMessageRouter, (router) => {
|
|
122
|
-
router.low(`[
|
|
122
|
+
router.low(`[Delegated task] ${running.length} running\n${lines.join('\n')}`);
|
|
123
123
|
});
|
|
124
124
|
requestRender();
|
|
125
125
|
}, AGENT_STATUS_INTERVAL_MS);
|
|
@@ -39,6 +39,8 @@ import type { PeerClient } from '@/runtime/index.ts';
|
|
|
39
39
|
import type { DirectTransport } from '@/runtime/index.ts';
|
|
40
40
|
import type { VoiceProviderRegistry, VoiceService } from '@pellux/goodvibes-sdk/platform/voice';
|
|
41
41
|
import type { MediaProviderRegistry } from '@pellux/goodvibes-sdk/platform/media';
|
|
42
|
+
import type { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
|
|
43
|
+
import type { ChannelDeliveryRouter } from '@pellux/goodvibes-sdk/platform/channels';
|
|
42
44
|
import {
|
|
43
45
|
createBootstrapCommandActions,
|
|
44
46
|
createBootstrapCommandClientsSection,
|
|
@@ -63,6 +65,8 @@ export type CreateBootstrapCommandContextOptions = {
|
|
|
63
65
|
voiceProviderRegistry?: VoiceProviderRegistry;
|
|
64
66
|
voiceService?: VoiceService;
|
|
65
67
|
mediaProviderRegistry?: MediaProviderRegistry;
|
|
68
|
+
artifactStore?: ArtifactStore;
|
|
69
|
+
channelDeliveryRouter?: ChannelDeliveryRouter;
|
|
66
70
|
forensicsRegistry: ForensicsRegistry;
|
|
67
71
|
policyRuntimeState: PolicyRuntimeState;
|
|
68
72
|
readModels: UiReadModels;
|
|
@@ -133,6 +137,8 @@ export function createBootstrapCommandContext(
|
|
|
133
137
|
voiceProviderRegistry,
|
|
134
138
|
voiceService,
|
|
135
139
|
mediaProviderRegistry,
|
|
140
|
+
artifactStore,
|
|
141
|
+
channelDeliveryRouter,
|
|
136
142
|
forensicsRegistry,
|
|
137
143
|
policyRuntimeState,
|
|
138
144
|
readModels,
|
|
@@ -240,7 +246,7 @@ export function createBootstrapCommandContext(
|
|
|
240
246
|
projectPlanningProjectId,
|
|
241
247
|
workPlanStore,
|
|
242
248
|
}, shellServices);
|
|
243
|
-
const platform = createBootstrapCommandPlatformSection({ configManager, voiceProviderRegistry, voiceService, mediaProviderRegistry }, shellServices);
|
|
249
|
+
const platform = createBootstrapCommandPlatformSection({ configManager, voiceProviderRegistry, voiceService, mediaProviderRegistry, artifactStore, channelDeliveryRouter }, shellServices);
|
|
244
250
|
const extensions = createBootstrapCommandExtensionsSection({
|
|
245
251
|
toolRegistry,
|
|
246
252
|
mcpRegistry,
|
|
@@ -42,6 +42,8 @@ import type { PeerClient } from '@/runtime/index.ts';
|
|
|
42
42
|
import type { DirectTransport } from '@/runtime/index.ts';
|
|
43
43
|
import type { VoiceProviderRegistry, VoiceService } from '@pellux/goodvibes-sdk/platform/voice';
|
|
44
44
|
import type { MediaProviderRegistry } from '@pellux/goodvibes-sdk/platform/media';
|
|
45
|
+
import type { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
|
|
46
|
+
import type { ChannelDeliveryRouter } from '@pellux/goodvibes-sdk/platform/channels';
|
|
45
47
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
46
48
|
|
|
47
49
|
export type BootstrapCommandSessionSection = CommandContext['session'];
|
|
@@ -79,6 +81,8 @@ export interface BootstrapCommandSectionOptions {
|
|
|
79
81
|
readonly voiceProviderRegistry?: VoiceProviderRegistry;
|
|
80
82
|
readonly voiceService?: VoiceService;
|
|
81
83
|
readonly mediaProviderRegistry?: MediaProviderRegistry;
|
|
84
|
+
readonly artifactStore?: ArtifactStore;
|
|
85
|
+
readonly channelDeliveryRouter?: ChannelDeliveryRouter;
|
|
82
86
|
readonly forensicsRegistry: ForensicsRegistry;
|
|
83
87
|
readonly policyRuntimeState: PolicyRuntimeState;
|
|
84
88
|
readonly readModels: UiReadModels;
|
|
@@ -150,7 +154,6 @@ export function createBootstrapCommandActions(
|
|
|
150
154
|
| 'exit'
|
|
151
155
|
| 'reloadSystemPrompt'
|
|
152
156
|
| 'showPanel'
|
|
153
|
-
| 'openPolicyPanel'
|
|
154
157
|
| 'openMcpWorkspace'
|
|
155
158
|
| 'openAgentWorkspace'
|
|
156
159
|
| 'openSecurityPanel'
|
|
@@ -173,7 +176,7 @@ export function createBootstrapCommandActions(
|
|
|
173
176
|
const showPanel = (panelId: string, pane?: 'top' | 'bottom') => {
|
|
174
177
|
void pane;
|
|
175
178
|
panelManager.hide();
|
|
176
|
-
conversation.log(`Panel "${panelId}" is
|
|
179
|
+
conversation.log(`Panel route "${panelId}" is handled through Agent Workspace. Use /agent for current operator controls.`, { fg: '214' });
|
|
177
180
|
requestRender();
|
|
178
181
|
};
|
|
179
182
|
|
|
@@ -201,7 +204,7 @@ export function createBootstrapCommandActions(
|
|
|
201
204
|
// Write to tool LLM config keys and enable the tool LLM
|
|
202
205
|
configManager.set('tools.llmProvider', def.provider);
|
|
203
206
|
configManager.set('tools.llmModel', key);
|
|
204
|
-
configManager.setDynamic('tools.llmEnabled'
|
|
207
|
+
configManager.setDynamic('tools.llmEnabled', true);
|
|
205
208
|
conversation.log(`Tool LLM set to: ${def.displayName} (${def.provider})`, { fg: '135' });
|
|
206
209
|
} else if (resolvedTarget === 'tts') {
|
|
207
210
|
configManager.set('tts.llmProvider', def.provider);
|
|
@@ -238,9 +241,6 @@ export function createBootstrapCommandActions(
|
|
|
238
241
|
exit: () => unwiredShellAction('exit'),
|
|
239
242
|
reloadSystemPrompt: loadSystemPrompt,
|
|
240
243
|
showPanel,
|
|
241
|
-
openPolicyPanel: () => {
|
|
242
|
-
showPanel('policy');
|
|
243
|
-
},
|
|
244
244
|
openMcpWorkspace: () => unwiredShellAction('openMcpWorkspace'),
|
|
245
245
|
openAgentWorkspace: () => unwiredShellAction('openAgentWorkspace'),
|
|
246
246
|
openSecurityPanel: () => {
|
|
@@ -309,7 +309,7 @@ export function createBootstrapCommandWorkspaceSection(
|
|
|
309
309
|
export function createBootstrapCommandPlatformSection(
|
|
310
310
|
options: Pick<
|
|
311
311
|
BootstrapCommandSectionOptions,
|
|
312
|
-
'configManager' | 'voiceProviderRegistry' | 'voiceService' | 'mediaProviderRegistry'
|
|
312
|
+
'configManager' | 'voiceProviderRegistry' | 'voiceService' | 'mediaProviderRegistry' | 'artifactStore' | 'channelDeliveryRouter'
|
|
313
313
|
>,
|
|
314
314
|
shellServices: BootstrapCommandShellServices,
|
|
315
315
|
): BootstrapCommandPlatformSection {
|
|
@@ -319,6 +319,8 @@ export function createBootstrapCommandPlatformSection(
|
|
|
319
319
|
voiceProviderRegistry: options.voiceProviderRegistry,
|
|
320
320
|
voiceService: options.voiceService,
|
|
321
321
|
mediaProviderRegistry: options.mediaProviderRegistry,
|
|
322
|
+
artifactStore: options.artifactStore,
|
|
323
|
+
channelDeliveryRouter: options.channelDeliveryRouter,
|
|
322
324
|
...shellServices.platform,
|
|
323
325
|
};
|
|
324
326
|
}
|
|
@@ -29,7 +29,16 @@ import { registerBootstrapHookBridge } from '@/runtime/index.ts';
|
|
|
29
29
|
import { createRuntimeServices, type RuntimeServices } from './services.ts';
|
|
30
30
|
import { createUiRuntimeServices, type UiRuntimeServices } from './ui-services.ts';
|
|
31
31
|
import { installAgentToolPolicyGuard } from '../tools/agent-tool-policy-guard.ts';
|
|
32
|
+
import { registerAgentChannelSendTool } from '../tools/agent-channel-send-tool.ts';
|
|
33
|
+
import { registerAgentKnowledgeIngestTool } from '../tools/agent-knowledge-ingest-tool.ts';
|
|
34
|
+
import { registerAgentKnowledgeTool } from '../tools/agent-knowledge-tool.ts';
|
|
32
35
|
import { registerAgentLocalRegistryTool } from '../tools/agent-local-registry-tool.ts';
|
|
36
|
+
import { registerAgentMediaGenerateTool } from '../tools/agent-media-generate-tool.ts';
|
|
37
|
+
import { registerAgentNotifyTool } from '../tools/agent-notify-tool.ts';
|
|
38
|
+
import { registerAgentOperatorActionTool } from '../tools/agent-operator-action-tool.ts';
|
|
39
|
+
import { registerAgentOperatorBriefingTool } from '../tools/agent-operator-briefing-tool.ts';
|
|
40
|
+
import { registerAgentReminderScheduleTool } from '../tools/agent-reminder-schedule-tool.ts';
|
|
41
|
+
import { registerAgentWorkPlanTool } from '../tools/agent-work-plan-tool.ts';
|
|
33
42
|
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
34
43
|
import { registerAgentRuntimeEvents } from './agent-runtime-events.ts';
|
|
35
44
|
|
|
@@ -139,7 +148,7 @@ export async function initializeBootstrapCore(
|
|
|
139
148
|
metadata: {
|
|
140
149
|
product: 'goodvibes-agent',
|
|
141
150
|
surfaceRoot: GOODVIBES_AGENT_SURFACE_ROOT,
|
|
142
|
-
clientKindNote: 'SDK
|
|
151
|
+
clientKindNote: 'SDK compatibility client kind; GoodVibes Agent remains an interactive operator TUI.',
|
|
143
152
|
},
|
|
144
153
|
}, 'bootstrap.control-plane');
|
|
145
154
|
|
|
@@ -227,7 +236,16 @@ export async function initializeBootstrapCore(
|
|
|
227
236
|
overflowHandler: services.overflowHandler,
|
|
228
237
|
changeTracker: services.sessionChangeTracker,
|
|
229
238
|
});
|
|
239
|
+
registerAgentKnowledgeIngestTool(toolRegistry, services.shellPaths, configManager);
|
|
240
|
+
registerAgentChannelSendTool(toolRegistry, services.channelDeliveryRouter);
|
|
241
|
+
registerAgentKnowledgeTool(toolRegistry, services.shellPaths, configManager);
|
|
230
242
|
registerAgentLocalRegistryTool(toolRegistry, services.shellPaths, services.memoryRegistry);
|
|
243
|
+
registerAgentMediaGenerateTool(toolRegistry, services.mediaProviders, services.artifactStore);
|
|
244
|
+
registerAgentNotifyTool(toolRegistry, configManager, services.webhookNotifier);
|
|
245
|
+
registerAgentOperatorActionTool(toolRegistry, services.shellPaths, configManager);
|
|
246
|
+
registerAgentOperatorBriefingTool(toolRegistry, services.shellPaths, configManager);
|
|
247
|
+
registerAgentReminderScheduleTool(toolRegistry, services.shellPaths, configManager);
|
|
248
|
+
registerAgentWorkPlanTool(toolRegistry, services.workPlanStore);
|
|
231
249
|
installAgentToolPolicyGuard(toolRegistry, {
|
|
232
250
|
getLastUserMessage: () => conversation.getLastUserMessage(),
|
|
233
251
|
});
|
|
@@ -10,9 +10,9 @@ import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
|
10
10
|
import { formatReturnContextForDisplay, getReturnContextMode, maybeAssistReturnContextSummary } from '@/runtime/index.ts';
|
|
11
11
|
import type { SharedSessionBroker } from '@pellux/goodvibes-sdk/platform/control-plane';
|
|
12
12
|
import type { SessionManager } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
13
|
-
import type { PanelManager } from '../panels/panel-manager.ts';
|
|
14
13
|
import type { ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
15
14
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
15
|
+
import { readConversationMessageSnapshots } from '../core/conversation-message-snapshot.ts';
|
|
16
16
|
|
|
17
17
|
export interface ResumeSessionOptions {
|
|
18
18
|
readonly runtimeBus: RuntimeEventBus;
|
|
@@ -24,7 +24,6 @@ export interface ResumeSessionOptions {
|
|
|
24
24
|
readonly writeLastSessionPointer: (sessionId: string) => void;
|
|
25
25
|
readonly hookDispatcher: HookDispatcher;
|
|
26
26
|
readonly sessionManager: SessionManager;
|
|
27
|
-
readonly panelManager: PanelManager;
|
|
28
27
|
readonly configManager: Pick<ConfigManager, 'get' | 'getCategory'>;
|
|
29
28
|
readonly providerRegistry: Pick<ProviderRegistry, 'get' | 'getCurrentModel' | 'getForModel' | 'require'>;
|
|
30
29
|
}
|
|
@@ -42,7 +41,7 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
|
|
|
42
41
|
turnCount: messages.length,
|
|
43
42
|
});
|
|
44
43
|
options.conversation.fromJSON({
|
|
45
|
-
messages: messages
|
|
44
|
+
messages: readConversationMessageSnapshots(messages),
|
|
46
45
|
title: meta.title,
|
|
47
46
|
titleSource: meta.titleSource,
|
|
48
47
|
});
|
|
@@ -53,28 +52,18 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
|
|
|
53
52
|
options.writeLastSessionPointer(sessionId);
|
|
54
53
|
void options.sharedSessionBroker.reopenSession(sessionId).catch((err) => { logger.debug('session broker reopen session failed', { err }); });
|
|
55
54
|
options.conversation.log(`Resumed session: ${sessionId}`, { fg: '135' });
|
|
56
|
-
const
|
|
57
|
-
if (meta.returnContext?.openPanels?.length) {
|
|
58
|
-
for (const panelId of meta.returnContext.openPanels.slice(0, 4)) {
|
|
59
|
-
try {
|
|
60
|
-
options.panelManager.open(panelId);
|
|
61
|
-
reopenedPanels.push(panelId);
|
|
62
|
-
} catch {
|
|
63
|
-
// Ignore unavailable panels during restore.
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (reopenedPanels.length > 0) options.panelManager.show();
|
|
67
|
-
}
|
|
55
|
+
const ignoredPanels = meta.returnContext?.openPanels?.slice(0, 4) ?? [];
|
|
68
56
|
const returnContextMode = getReturnContextMode(options.configManager);
|
|
69
57
|
if (returnContextMode !== 'off' && meta.returnContext) {
|
|
70
58
|
for (const line of formatReturnContextForDisplay(meta.returnContext)) {
|
|
59
|
+
if (line.startsWith('Open panels:')) continue;
|
|
71
60
|
options.conversation.log(`Resume: ${line}`, { fg: '244' });
|
|
72
61
|
}
|
|
73
|
-
if (
|
|
74
|
-
options.conversation.log(`Resume:
|
|
62
|
+
if (ignoredPanels.length > 0) {
|
|
63
|
+
options.conversation.log(`Resume: Saved panel state ignored: ${ignoredPanels.join(', ')}. Open the Agent workspace for current operator controls.`, { fg: '244' });
|
|
75
64
|
}
|
|
76
65
|
if ((meta.returnContext.remoteRunners?.length ?? 0) > 0) {
|
|
77
|
-
options.conversation.log('Resume: Remote
|
|
66
|
+
options.conversation.log('Resume: Remote build-host recovery belongs outside Agent; delegate explicit build/fix/review recovery from Agent.', { fg: '244' });
|
|
78
67
|
}
|
|
79
68
|
if (returnContextMode === 'assisted') {
|
|
80
69
|
const helperModel = new HelperModel({
|
|
@@ -133,7 +133,6 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
133
133
|
writeLastSessionPointer,
|
|
134
134
|
hookDispatcher: services.hookDispatcher,
|
|
135
135
|
sessionManager: services.sessionManager,
|
|
136
|
-
panelManager: services.panelManager,
|
|
137
136
|
configManager,
|
|
138
137
|
providerRegistry: services.providerRegistry,
|
|
139
138
|
});
|
|
@@ -180,7 +179,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
180
179
|
hookActivityTracker: services.hookActivityTracker,
|
|
181
180
|
hookWorkbench: services.hookWorkbench,
|
|
182
181
|
mcpRegistry: services.mcpRegistry,
|
|
183
|
-
|
|
182
|
+
connectedHostTokenDir: join(services.homeDirectory, '.goodvibes', 'daemon'),
|
|
184
183
|
});
|
|
185
184
|
services.panelManager.prewarmRegistered();
|
|
186
185
|
|
|
@@ -198,9 +197,8 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
198
197
|
|
|
199
198
|
const commandRegistry = new CommandRegistry();
|
|
200
199
|
registerBuiltinCommands(commandRegistry);
|
|
201
|
-
type RuntimeFoundationInput = Parameters<typeof createRuntimeFoundationClients>[0];
|
|
202
200
|
const foundationClients = createRuntimeFoundationClients({
|
|
203
|
-
runtimeServices: services
|
|
201
|
+
runtimeServices: services,
|
|
204
202
|
tasksReadModel: uiServices.readModels.tasks,
|
|
205
203
|
taskManager,
|
|
206
204
|
opsControlPlane,
|
|
@@ -236,6 +234,8 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
236
234
|
voiceProviderRegistry: services.voiceProviders,
|
|
237
235
|
voiceService: services.voiceService,
|
|
238
236
|
mediaProviderRegistry: services.mediaProviders,
|
|
237
|
+
artifactStore: services.artifactStore,
|
|
238
|
+
channelDeliveryRouter: services.channelDeliveryRouter,
|
|
239
239
|
forensicsRegistry,
|
|
240
240
|
policyRuntimeState,
|
|
241
241
|
readModels: uiServices.readModels,
|
package/src/runtime/bootstrap.ts
CHANGED
|
@@ -45,14 +45,23 @@ import { buildReviewedMemoryPrompt } from '../agent/memory-prompt.ts';
|
|
|
45
45
|
|
|
46
46
|
const GOODVIBES_AGENT_OPERATOR_POLICY = [
|
|
47
47
|
'## GoodVibes Agent Operator Policy',
|
|
48
|
-
'- Default to serial, proactive assistant work in the main conversation. Answer, inspect, summarize, remember useful non-secret facts, configure local
|
|
48
|
+
'- Default to serial, proactive assistant work in the main conversation. Answer, inspect, summarize, remember useful non-secret facts, configure Agent-local state, use read-only connected-host/operator routes, and take safe non-destructive actions without creating separate Agent jobs or GoodVibes TUI delegations.',
|
|
49
49
|
'- GoodVibes Agent connects to a GoodVibes host owned outside this package. Do not start, stop, restart, install, expose, or mutate connected-host network/listener posture from Agent.',
|
|
50
|
-
'- Use the `
|
|
51
|
-
'-
|
|
52
|
-
'-
|
|
53
|
-
'-
|
|
54
|
-
'-
|
|
55
|
-
'-
|
|
50
|
+
'- Use the `agent_operator_briefing` tool for read-only main-conversation summaries of connected work plan, approvals, automation, schedules, and scheduler capacity. This tool must not call mutation routes, connected-host lifecycle routes, default knowledge, non-Agent knowledge spaces, separate Agent job creation, or GoodVibes TUI delegation.',
|
|
51
|
+
'- When the user explicitly asks Agent to approve, deny, or cancel a specific approval, run/pause/resume a specific automation job, cancel/retry a specific automation run, or run a specific schedule, use the `agent_operator_action` tool with confirm:true and the original user request. It can call only its allowlisted public operator routes and must not create, edit, delete, or discover automation definitions.',
|
|
52
|
+
'- Use the `agent_work_plan` tool to keep the visible Agent-local work plan current while working in the main conversation. Create, inspect, and update local work items proactively when useful. Removing items or clearing completed items requires an explicit user request and confirm:true.',
|
|
53
|
+
'- Use the `agent_knowledge` tool for Agent Knowledge status, ask, and search from the main conversation. It must use only /api/goodvibes-agent/knowledge/* and must fail closed instead of falling back to default knowledge or non-Agent knowledge spaces.',
|
|
54
|
+
'- When the user explicitly asks Agent to add, import, remember, or ingest a URL, URL-list file, local file, bookmarks file, browser history, or connector input into Agent Knowledge, use the `agent_knowledge_ingest` tool with confirm:true and the original user request. It must write only to /api/goodvibes-agent/knowledge/* ingest routes and never to default knowledge or non-Agent knowledge spaces.',
|
|
55
|
+
'- Use the `agent_local_registry` tool when a scratchpad note, durable memory, reusable persona, skill, skill bundle, or routine would improve later work. Keep those records Agent-local, non-secret, source/provenance tagged, and reviewable. Notes are for temporary/source-triage context; promote them explicitly into memory, skills, personas, routines, or Agent Knowledge only when that is the correct durable home. Review memory with a confidence score when it should shape later turns. Starting a routine means applying its steps in this same serial conversation, not creating a background job.',
|
|
56
|
+
'- When the user explicitly asks Agent to generate an image, video, or other media artifact, use the `agent_media_generate` tool with confirm:true and the original user request. Generated media is stored as artifacts; do not print base64, call default knowledge, use non-Agent knowledge spaces, send channels, create separate Agent jobs, or request GoodVibes TUI delegation for media generation.',
|
|
57
|
+
'- When the user explicitly asks Agent to send an alert, message, or notification to configured notification targets, use the `agent_notify` tool with confirm:true and the original user request. Do not infer external notifications from vague suggestions, and never create channel routes or account authorizations from the main conversation.',
|
|
58
|
+
'- When the user explicitly asks Agent to send one message to a specific configured channel, route, webhook, or link target, use the `agent_channel_send` tool with confirm:true and the original user request. It can deliver one message through configured delivery strategies, but must not create routes, authorize accounts, manage connected-host hosting, use default knowledge, use non-Agent knowledge spaces, create separate Agent jobs, or request GoodVibes TUI delegation.',
|
|
59
|
+
'- When the user explicitly asks for a reminder or asks Agent to schedule a reminder, use the `agent_reminder_schedule` tool with confirm:true and the original user request. That creates one connected schedules.create reminder on the external GoodVibes host. Do not infer reminders from vague suggestions or routine startup, and never create local scheduler jobs.',
|
|
60
|
+
'- GoodVibes TUI delegation is never the default Agent reasoning path. Do not delegate planning, research, operations, knowledge, memory, configuration, approvals, automation observability, or ordinary assistant work.',
|
|
61
|
+
'- GoodVibes Agent is not the coding TUI. Do not use the `agent` tool to create coding-role Agent jobs or batch job roots from Agent.',
|
|
62
|
+
'- When the user explicitly asks to build, implement, fix, patch, or review code, preserve the full original user ask and delegate one build request to GoodVibes TUI through the public shared-session/build-delegation contract. Include clear executionIntent and request delegated review only for explicit build/fix/review work or when the user explicitly asks for delegated Agent review.',
|
|
63
|
+
'- Do not narrow explicit build/fix/review requests into design-only, read-only, or no-write work unless the user explicitly requested that limitation. TUI owns file edits, git/worktree work, execution isolation UX, and delegated review coordination.',
|
|
64
|
+
'- If a stable public delegation route is unavailable, say that the task needs GoodVibes TUI delegation and report the missing route instead of pretending to implement it locally or creating sibling Agent jobs.',
|
|
56
65
|
].join('\n');
|
|
57
66
|
|
|
58
67
|
function joinPromptParts(...parts: Array<string | null | undefined>): string {
|
|
@@ -126,7 +135,7 @@ export type BootstrapContext = RuntimeContext & {
|
|
|
126
135
|
* 1. Config, caches, keybindings
|
|
127
136
|
* 2. Runtime event bus, conversation, compositor, selection
|
|
128
137
|
* 3. Tool registry + agent wiring
|
|
129
|
-
* 4. Runtime bus subscriptions (
|
|
138
|
+
* 4. Runtime bus subscriptions (delegation, subagent, hook bridge)
|
|
130
139
|
* 5. Providers, webhooks, PermissionManager, HookDispatcher
|
|
131
140
|
* 6. Orchestrator and Agent-local task read models
|
|
132
141
|
* 7. MCP auto-connect + workspace/panel manager
|
|
@@ -295,7 +304,7 @@ export async function bootstrapRuntime(
|
|
|
295
304
|
},
|
|
296
305
|
};
|
|
297
306
|
|
|
298
|
-
// ── Phase 7:
|
|
307
|
+
// ── Phase 7: Connected-host posture + deferred startup ────────────────
|
|
299
308
|
|
|
300
309
|
const deferredStartup = createDeferredStartupCoordinator();
|
|
301
310
|
|
|
@@ -310,7 +319,7 @@ export async function bootstrapRuntime(
|
|
|
310
319
|
return `http://${urlHost}:${port}`;
|
|
311
320
|
};
|
|
312
321
|
|
|
313
|
-
const
|
|
322
|
+
const createAgentDependencyStatus = (
|
|
314
323
|
service: 'daemon' | 'httpListener',
|
|
315
324
|
): HostServiceStatus => {
|
|
316
325
|
const host = String(configManager.get(service === 'daemon' ? 'controlPlane.host' : 'httpListener.host') ?? '127.0.0.1');
|
|
@@ -321,7 +330,7 @@ export async function bootstrapRuntime(
|
|
|
321
330
|
port,
|
|
322
331
|
baseUrl: formatHostServiceBaseUrl(host, port),
|
|
323
332
|
reason: service === 'daemon'
|
|
324
|
-
? 'GoodVibes Agent connects to a GoodVibes host owned outside this product and does not start or restart
|
|
333
|
+
? 'GoodVibes Agent connects to a GoodVibes host owned outside this product and does not start or restart it.'
|
|
325
334
|
: 'GoodVibes Agent does not own listener lifecycle.',
|
|
326
335
|
};
|
|
327
336
|
};
|
|
@@ -330,15 +339,15 @@ export async function bootstrapRuntime(
|
|
|
330
339
|
|
|
331
340
|
const hostServiceIsBlocked = (status: HostServiceStatus): boolean => status.mode === 'blocked';
|
|
332
341
|
|
|
333
|
-
const
|
|
342
|
+
const inspectAgentDependencies = () => {
|
|
334
343
|
const daemonStatus = externalServices.daemonStatus;
|
|
335
344
|
const httpListenerStatus = externalServices.httpListenerStatus;
|
|
336
345
|
return {
|
|
337
|
-
|
|
338
|
-
|
|
346
|
+
connectedHostRunning: hostServiceIsActive(daemonStatus),
|
|
347
|
+
connectedHostPortInUse: hostServiceIsBlocked(daemonStatus),
|
|
339
348
|
httpListenerRunning: hostServiceIsActive(httpListenerStatus),
|
|
340
349
|
httpListenerPortInUse: hostServiceIsBlocked(httpListenerStatus),
|
|
341
|
-
daemonStatus,
|
|
350
|
+
connectedHostStatus: daemonStatus,
|
|
342
351
|
httpListenerStatus,
|
|
343
352
|
};
|
|
344
353
|
};
|
|
@@ -346,8 +355,8 @@ export async function bootstrapRuntime(
|
|
|
346
355
|
let externalServices: ExternalServicesHandle = {
|
|
347
356
|
daemonServer: null,
|
|
348
357
|
httpListener: null,
|
|
349
|
-
daemonStatus:
|
|
350
|
-
httpListenerStatus:
|
|
358
|
+
daemonStatus: createAgentDependencyStatus('daemon'),
|
|
359
|
+
httpListenerStatus: createAgentDependencyStatus('httpListener'),
|
|
351
360
|
listRecentControlPlaneEvents: () => [],
|
|
352
361
|
async stop(): Promise<void> {},
|
|
353
362
|
};
|
|
@@ -355,16 +364,16 @@ export async function bootstrapRuntime(
|
|
|
355
364
|
externalServices: NonNullable<typeof uiServices.platform.externalServices>;
|
|
356
365
|
};
|
|
357
366
|
platformExternalServices.externalServices = {
|
|
358
|
-
inspect:
|
|
367
|
+
inspect: inspectAgentDependencies,
|
|
359
368
|
restart: async () => {
|
|
360
369
|
externalServices = {
|
|
361
370
|
...externalServices,
|
|
362
|
-
daemonStatus:
|
|
363
|
-
httpListenerStatus:
|
|
371
|
+
daemonStatus: createAgentDependencyStatus('daemon'),
|
|
372
|
+
httpListenerStatus: createAgentDependencyStatus('httpListener'),
|
|
364
373
|
};
|
|
365
374
|
systemMessageRouter.high('[Startup] GoodVibes Agent does not start or restart the connected GoodVibes host. Start it from GoodVibes TUI or the owning host, then refresh status.');
|
|
366
375
|
requestRender();
|
|
367
|
-
return
|
|
376
|
+
return inspectAgentDependencies();
|
|
368
377
|
},
|
|
369
378
|
};
|
|
370
379
|
deferredStartup.schedule({
|
|
@@ -440,7 +449,7 @@ export async function bootstrapRuntime(
|
|
|
440
449
|
bootstrapUnsubs.push(() => mcpAutoReload.stop());
|
|
441
450
|
if (configManager.get('automation.enabled')) {
|
|
442
451
|
logger.warn('Local automation startup is disabled in GoodVibes Agent; use connected-host observability instead.');
|
|
443
|
-
systemMessageRouter.low('[Startup] Local automation
|
|
452
|
+
systemMessageRouter.low('[Startup] Local automation execution is disabled in GoodVibes Agent; use read-only automation observability or explicit connected-host actions.');
|
|
444
453
|
}
|
|
445
454
|
|
|
446
455
|
// ── Phase 12: Session:start lifecycle hook ─────────────────────────────
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
1
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
|
|
@@ -32,11 +33,15 @@ export function readConnectedHostOperatorToken(homeDirectory: string): Connected
|
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
export function connectedHostOperatorTokenFingerprint(token: string): string {
|
|
37
|
+
return createHash('sha256').update(token).digest('hex').slice(0, 12);
|
|
38
|
+
}
|
|
39
|
+
|
|
35
40
|
export function connectedHostTokenRequiredMessage(path: string): string {
|
|
36
41
|
return [
|
|
37
42
|
'Connected-host operator token is required.',
|
|
38
|
-
` token path
|
|
43
|
+
` token path ${path}`,
|
|
39
44
|
' Agent does not create or rotate connected-host auth tokens.',
|
|
40
|
-
'
|
|
45
|
+
' Provision or repair connected-host access through the owning GoodVibes host, then rerun this command.',
|
|
41
46
|
].join('\n');
|
|
42
47
|
}
|
|
@@ -12,8 +12,8 @@ export type { InspectableDomain } from '@/runtime/index.ts';
|
|
|
12
12
|
export { HealthPanel } from '@/runtime/index.ts';
|
|
13
13
|
export { DivergencePanel } from '@/runtime/index.ts';
|
|
14
14
|
export { ReplayPanel } from '@/runtime/index.ts';
|
|
15
|
-
export {
|
|
16
|
-
export type {
|
|
15
|
+
export { PolicyDiagnosticsPanel } from './policy.ts';
|
|
16
|
+
export type { PolicyDiagnosticsSnapshot } from './policy.ts';
|
|
17
17
|
export { ToolContractsPanel } from '@/runtime/index.ts';
|
|
18
18
|
export { TransportPanel } from '@/runtime/index.ts';
|
|
19
19
|
export type { TransportPanelSnapshot } from '@/runtime/index.ts';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Policy diagnostics
|
|
2
|
+
* Policy diagnostics data provider.
|
|
3
3
|
*
|
|
4
4
|
* Wraps a `PolicyRegistry` and optionally a `DivergencePanel` to expose
|
|
5
5
|
* combined policy state (current bundle, candidate, simulation status,
|
|
@@ -24,7 +24,7 @@ import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
|
24
24
|
/**
|
|
25
25
|
* A point-in-time snapshot of policy state for diagnostics rendering.
|
|
26
26
|
*/
|
|
27
|
-
export interface
|
|
27
|
+
export interface PolicyDiagnosticsSnapshot {
|
|
28
28
|
/** The currently enforced bundle, or null if no policy is active. */
|
|
29
29
|
current: PolicyBundleVersion | null;
|
|
30
30
|
/** The pending candidate bundle, or null if none loaded. */
|
|
@@ -48,12 +48,12 @@ export interface PolicyPanelSnapshot {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
*
|
|
51
|
+
* PolicyDiagnosticsPanel — diagnostics data provider for the policy registry.
|
|
52
52
|
*
|
|
53
53
|
* Usage:
|
|
54
54
|
* ```ts
|
|
55
55
|
* const registry = new PolicyRegistry();
|
|
56
|
-
* const panel = new
|
|
56
|
+
* const panel = new PolicyDiagnosticsPanel(registry, divergencePanel);
|
|
57
57
|
*
|
|
58
58
|
* panel.subscribe(() => {
|
|
59
59
|
* const snap = panel.getSnapshot();
|
|
@@ -67,7 +67,7 @@ export interface PolicyPanelSnapshot {
|
|
|
67
67
|
* panel.dispose();
|
|
68
68
|
* ```
|
|
69
69
|
*/
|
|
70
|
-
export class
|
|
70
|
+
export class PolicyDiagnosticsPanel {
|
|
71
71
|
private readonly _registry: PolicyRegistry;
|
|
72
72
|
private readonly _divergencePanel: DivergencePanel | null;
|
|
73
73
|
private readonly _config: PanelConfig;
|
|
@@ -118,7 +118,7 @@ export class PolicyPanel {
|
|
|
118
118
|
/**
|
|
119
119
|
* getSnapshot — Returns the current combined policy + divergence snapshot.
|
|
120
120
|
*/
|
|
121
|
-
public getSnapshot():
|
|
121
|
+
public getSnapshot(): PolicyDiagnosticsSnapshot {
|
|
122
122
|
const current = this._registry.getCurrent();
|
|
123
123
|
const candidate = this._registry.getCandidate();
|
|
124
124
|
const rawHistory = this._registry.getHistory();
|
|
@@ -170,7 +170,7 @@ export class PolicyPanel {
|
|
|
170
170
|
try {
|
|
171
171
|
cb();
|
|
172
172
|
} catch (err) {
|
|
173
|
-
logger.warn(`[
|
|
173
|
+
logger.warn(`[PolicyDiagnosticsPanel] subscriber error: ${err}`);
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
}
|
package/src/runtime/index.ts
CHANGED
|
@@ -112,7 +112,7 @@ function agentExternalHostStatus(
|
|
|
112
112
|
port,
|
|
113
113
|
baseUrl: `http://${host}:${port}`,
|
|
114
114
|
reason: service === 'daemon'
|
|
115
|
-
? 'GoodVibes Agent connects to a GoodVibes host owned outside this product and does not start or restart
|
|
115
|
+
? 'GoodVibes Agent connects to a GoodVibes host owned outside this product and does not start or restart it.'
|
|
116
116
|
: 'GoodVibes Agent does not own listener lifecycle.',
|
|
117
117
|
};
|
|
118
118
|
}
|
|
@@ -437,6 +437,7 @@ export const summarizeWorktreeOwnership = shell.summarizeWorktreeOwnership;
|
|
|
437
437
|
export const listPersistedWorktreeMeta = shell.listPersistedWorktreeMeta;
|
|
438
438
|
export const getPersistedWorktreeMeta = shell.getPersistedWorktreeMeta;
|
|
439
439
|
export const reviewWorktreeAttachments = shell.reviewWorktreeAttachments;
|
|
440
|
+
export const WorktreeRegistry = shell.WorktreeRegistry;
|
|
440
441
|
|
|
441
442
|
export type MutableRuntimeState = Shell.MutableRuntimeState;
|
|
442
443
|
export type ProviderAccountRecord = Shell.ProviderAccountRecord;
|