@pellux/goodvibes-agent 0.1.116 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -661
- package/README.md +64 -57
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +199180 -192185
- package/docs/README.md +15 -8
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +59 -0
- package/docs/getting-started.md +61 -50
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +48 -11
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +3 -6
- package/src/agent/behavior-discovery-summary.ts +1 -3
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-discovery.ts +1 -3
- package/src/agent/persona-registry.ts +19 -16
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +27 -26
- package/src/agent/routine-registry.ts +54 -14
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +35 -33
- package/src/agent/routine-schedule-receipts.ts +29 -27
- package/src/agent/runtime-profile-starters.ts +5 -5
- package/src/agent/runtime-profile.ts +91 -12
- package/src/agent/skill-registry.ts +210 -32
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +40 -34
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +14 -9
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/entrypoint.ts +16 -7
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +54 -29
- package/src/cli/local-library-command.ts +203 -83
- package/src/cli/management-commands.ts +105 -68
- package/src/cli/management.ts +55 -74
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -3
- package/src/cli/profiles-command.ts +166 -31
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +176 -40
- package/src/cli/service-posture.ts +16 -16
- package/src/cli/status.ts +56 -135
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
- package/src/input/agent-workspace-access-command-editors.ts +170 -0
- package/src/input/agent-workspace-activation.ts +35 -8
- package/src/input/agent-workspace-basic-command-editor-submission.ts +351 -94
- package/src/input/agent-workspace-basic-command-editors.ts +502 -9
- package/src/input/agent-workspace-categories.ts +423 -51
- package/src/input/agent-workspace-channel-command-editor-submission.ts +83 -0
- package/src/input/agent-workspace-channel-command-editors.ts +65 -0
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +41 -3
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
- package/src/input/agent-workspace-editors.ts +166 -1
- package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
- package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-learned-behavior.ts +67 -0
- package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
- package/src/input/agent-workspace-library-command-editors.ts +35 -0
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
- package/src/input/agent-workspace-memory-command-editors.ts +180 -0
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +81 -0
- package/src/input/agent-workspace-notify-editor-submission.ts +121 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +208 -0
- package/src/input/agent-workspace-operations-command-editors.ts +196 -0
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
- package/src/input/agent-workspace-provider-command-editors.ts +93 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-requirements.ts +11 -0
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
- package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
- package/src/input/agent-workspace-session-command-editors.ts +249 -0
- package/src/input/agent-workspace-setup.ts +37 -16
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
- package/src/input/agent-workspace-snapshot.ts +162 -21
- package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
- package/src/input/agent-workspace-task-command-editors.ts +47 -0
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +212 -4
- package/src/input/agent-workspace-voice-media.ts +4 -7
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
- package/src/input/agent-workspace.ts +178 -240
- package/src/input/command-registry.ts +5 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +126 -37
- package/src/input/commands/agent-skills-runtime.ts +149 -72
- package/src/input/commands/agent-workspace-runtime.ts +23 -6
- package/src/input/commands/brief-runtime.ts +55 -25
- package/src/input/commands/channels-runtime.ts +147 -33
- package/src/input/commands/compat-runtime.ts +32 -0
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +149 -126
- package/src/input/commands/knowledge.ts +82 -60
- package/src/input/commands/local-provider-runtime.ts +43 -21
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +10 -20
- package/src/input/commands/mcp-runtime.ts +63 -46
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -76
- package/src/input/commands/personas-runtime.ts +46 -31
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +35 -98
- package/src/input/commands/product-runtime.ts +2 -2
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +50 -9
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +99 -45
- package/src/input/commands/runtime-services.ts +1 -14
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +6 -11
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +134 -104
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +38 -17
- package/src/input/commands/subscription-runtime.ts +54 -185
- package/src/input/commands/support-bundle-runtime.ts +53 -0
- package/src/input/commands/tasks-runtime.ts +21 -21
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +6 -2
- package/src/input/feed-context-factory.ts +2 -2
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -26
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -5
- package/src/input/handler-interactions.ts +9 -36
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +52 -91
- package/src/input/handler-shortcuts.ts +16 -7
- package/src/input/handler.ts +50 -23
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +27 -16
- package/src/input/mcp-workspace.ts +90 -26
- package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +62 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +223 -55
- package/src/input/onboarding/onboarding-wizard-steps.ts +59 -35
- package/src/input/onboarding/onboarding-wizard-types.ts +4 -1
- package/src/input/onboarding/onboarding-wizard.ts +87 -2
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- package/src/input/settings-modal-agent-policy.ts +6 -6
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +20 -66
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -10
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +4 -4
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +3 -12
- package/src/panels/builtin/session.ts +32 -24
- package/src/panels/builtin/shared.ts +7 -7
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +19 -12
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +48 -7
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +44 -20
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +6 -6
- package/src/panels/system-messages-panel.ts +3 -3
- package/src/panels/tasks-panel.ts +21 -14
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +3 -3
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +254 -57
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/block-actions.ts +1 -3
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +112 -34
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +176 -43
- package/src/renderer/model-picker-overlay.ts +58 -3
- package/src/renderer/model-workspace.ts +104 -22
- package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +21 -5
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +88 -55
- package/src/renderer/system-message.ts +1 -1
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +129 -0
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +11 -8
- package/src/runtime/bootstrap-core.ts +23 -65
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +46 -8
- package/src/runtime/bootstrap.ts +36 -46
- package/src/runtime/connected-host-auth.ts +47 -0
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -5
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +288 -74
- package/src/runtime/onboarding/derivation.ts +10 -13
- package/src/runtime/onboarding/snapshot.ts +2 -17
- package/src/runtime/onboarding/types.ts +34 -20
- package/src/runtime/onboarding/verify.ts +105 -4
- package/src/runtime/operator-token-cleanup.ts +3 -3
- package/src/runtime/services.ts +95 -11
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/service-settings-sync.ts +7 -7
- package/src/shell/ui-openers.ts +17 -38
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +279 -73
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +13 -15
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/docs/connected-services.md +0 -51
- package/src/cli/package-verification.ts +0 -274
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -17
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
import type { Line } from '../types/grid.ts';
|
|
9
9
|
import type { SettingsModal, SettingEntry, FlagEntry, McpEntry, SubscriptionEntry, SettingsCategory } from '../input/settings-modal.ts';
|
|
10
|
-
import {
|
|
10
|
+
import { isExternalHostOwnedSettingKey, SETTINGS_CATEGORIES, SETTINGS_CATEGORY_GROUPS } from '../input/settings-modal.ts';
|
|
11
11
|
import { getDisplayWidth, wrapText } from '../utils/terminal-width.ts';
|
|
12
12
|
import { CATEGORY_LABELS, describeUiRouting, formatValue, getSettingLabel, inferSubscriptionRouteReason, valueColor } from './settings-modal-helpers.ts';
|
|
13
13
|
import { isSecretConfigKey } from '../config/secret-config.ts';
|
|
14
|
+
import { formatProviderAuthRouteId } from '../provider-auth-route-display.ts';
|
|
14
15
|
import { GLYPHS } from './ui-primitives.ts';
|
|
15
16
|
import {
|
|
16
17
|
clamp,
|
|
@@ -30,34 +31,23 @@ const CATEGORY_INFO: Record<SettingsCategory, string> = {
|
|
|
30
31
|
behavior: 'Day-to-day shell behavior: approval posture, compaction, history, guidance, notifications, stale-context warnings, return context, and Human-in-the-Loop mode.',
|
|
31
32
|
storage: 'Local storage posture, including secret storage policy and maximum artifact size for Agent Knowledge, artifacts, and document ingestion.',
|
|
32
33
|
permissions: 'Permission mode and tool-class policy. These settings decide whether the shell prompts before read/write/exec/network/agent actions.',
|
|
33
|
-
orchestration: 'Agent orchestration limits and recursion controls.',
|
|
34
|
-
wrfc: 'WRFC is external to normal Agent operation. Review these compatibility values only for explicit GoodVibes TUI build delegation.',
|
|
35
34
|
helper: 'Helper model defaults used by helper subsystems when they do not use the main chat route.',
|
|
36
35
|
tts: 'Text-to-speech provider, voice, and optional spoken-turn LLM overrides.',
|
|
37
|
-
service: 'Connected-service installation posture. Agent shows these compatibility keys for inspection only and does not install, start, stop, restart, or autostart anything.',
|
|
38
|
-
controlPlane: 'Connected-service API settings. Agent uses these settings for access and does not mutate bind posture.',
|
|
39
|
-
httpListener: 'Inbound event endpoint settings owned by connected GoodVibes services. Agent inspects readiness and does not expose endpoints.',
|
|
40
|
-
web: 'External browser companion settings. Agent does not own browser hosting or network bind lifecycle.',
|
|
41
|
-
batch: 'Batch execution settings reported from connected GoodVibes services. Agent does not own remote queue provisioning.',
|
|
42
36
|
automation: 'Scheduled and automated run settings, concurrency, timeout, catch-up, cooldown, and retention behavior.',
|
|
43
|
-
watchers: 'File/process watcher heartbeat, polling, and recovery-window behavior.',
|
|
44
|
-
runtime: 'Connected-service guardrails such as companion chat limiter and event bus listener caps.',
|
|
45
37
|
telemetry: 'Telemetry payload policy.',
|
|
46
38
|
cache: 'Provider and model cache behavior, TTL, and hit-rate monitoring.',
|
|
47
39
|
mcp: 'MCP server trust and scope review. Trust changes can expose local files, tools, databases, browsers, or remote automation depending on the server.',
|
|
48
40
|
surfaces: 'Messaging and notification channel accounts such as Slack, Discord, ntfy, Telegram, chat bridges, and delivery providers.',
|
|
49
|
-
release: '
|
|
50
|
-
danger: 'High-impact service switches. Agent renders service-owned switches read-only; change them outside Agent.',
|
|
41
|
+
release: 'Update-channel preference.',
|
|
51
42
|
tools: 'Tool LLM and helper model routing. Empty provider/model values inherit the active chat route unless a specific helper/tool route is set.',
|
|
52
|
-
flags: 'Feature
|
|
53
|
-
network: 'Read-only view of connected GoodVibes API, inbound-event, and browser companion bind posture plus editable Agent network settings.',
|
|
43
|
+
flags: 'Feature controls for optional behavior that can be enabled or disabled separately from normal configuration.',
|
|
54
44
|
};
|
|
55
45
|
|
|
56
46
|
const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
|
|
57
47
|
'behavior.hitlMode': {
|
|
58
48
|
quiet: 'Minimize operational interruptions and surface fewer Human-in-the-Loop prompts.',
|
|
59
49
|
balanced: 'Show important Human-in-the-Loop prompts without turning routine work into noise.',
|
|
60
|
-
operator: 'Surface more operational detail for users actively supervising agents, tools,
|
|
50
|
+
operator: 'Surface more operational detail for users actively supervising agents, tools, connected-host posture, and automation.',
|
|
61
51
|
},
|
|
62
52
|
'behavior.guidanceMode': {
|
|
63
53
|
off: 'Do not add extra guidance beyond direct command output.',
|
|
@@ -74,26 +64,6 @@ const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
|
|
|
74
64
|
require_secure: 'Require secure secret storage and reject plaintext fallback.',
|
|
75
65
|
plaintext_allowed: 'Allow plaintext fallback when secure storage is unavailable.',
|
|
76
66
|
},
|
|
77
|
-
'batch.mode': {
|
|
78
|
-
off: 'Keep runtime work on the immediate local path.',
|
|
79
|
-
explicit: 'Use batch only when callers explicitly request batch execution.',
|
|
80
|
-
'eligible-by-default': 'Allow eligible runtime work to use the batch path unless callers opt out.',
|
|
81
|
-
},
|
|
82
|
-
'controlPlane.hostMode': {
|
|
83
|
-
localhost: 'Bind only to this computer.',
|
|
84
|
-
network: 'Bind for LAN access using the default network host.',
|
|
85
|
-
custom: 'Use the explicit host value in the related host setting.',
|
|
86
|
-
},
|
|
87
|
-
'httpListener.hostMode': {
|
|
88
|
-
localhost: 'Bind only to this computer.',
|
|
89
|
-
network: 'Bind for LAN event delivery using the default network host.',
|
|
90
|
-
custom: 'Use the explicit host value in the related host setting.',
|
|
91
|
-
},
|
|
92
|
-
'web.hostMode': {
|
|
93
|
-
localhost: 'Serve the browser UI only on this computer.',
|
|
94
|
-
network: 'Serve the browser UI on the LAN.',
|
|
95
|
-
custom: 'Use the explicit host value in the related host setting.',
|
|
96
|
-
},
|
|
97
67
|
'ui.systemMessages': {
|
|
98
68
|
panel: 'Show system messages in panels only.',
|
|
99
69
|
conversation: 'Show system messages inline in the transcript.',
|
|
@@ -104,11 +74,6 @@ const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
|
|
|
104
74
|
conversation: 'Show operational messages inline in the transcript.',
|
|
105
75
|
both: 'Show operational messages in both panels and the transcript.',
|
|
106
76
|
},
|
|
107
|
-
'ui.wrfcMessages': {
|
|
108
|
-
panel: 'Show explicit delegated-build WRFC messages in panels only.',
|
|
109
|
-
conversation: 'Show explicit delegated-build WRFC messages inline in the transcript.',
|
|
110
|
-
both: 'Show explicit delegated-build WRFC messages in both panels and the transcript.',
|
|
111
|
-
},
|
|
112
77
|
'surfaces.telegram.mode': {
|
|
113
78
|
webhook: 'Receive Telegram updates through externally hosted delivery.',
|
|
114
79
|
polling: 'Poll Telegram for updates from the configured account.',
|
|
@@ -148,14 +113,13 @@ function buildSettingContext(modal: SettingsModal, entry: SettingEntry): string[
|
|
|
148
113
|
];
|
|
149
114
|
|
|
150
115
|
if (entry.locked) lines.push(`Locked: ${entry.lockReason ?? 'This setting is locked by a higher-priority layer.'}`);
|
|
151
|
-
if (entry.conflict) lines.push(`Conflict: inspect with /settings and resolve
|
|
116
|
+
if (entry.conflict) lines.push(`Conflict: inspect with /settings and resolve host-owned sync state in the owning host.`);
|
|
152
117
|
|
|
153
118
|
lines.push('', entry.setting.description);
|
|
154
119
|
|
|
155
120
|
if (
|
|
156
121
|
entry.setting.key === 'ui.systemMessages'
|
|
157
122
|
|| entry.setting.key === 'ui.operationalMessages'
|
|
158
|
-
|| entry.setting.key === 'ui.wrfcMessages'
|
|
159
123
|
) {
|
|
160
124
|
lines.push(`Routing meaning: ${describeUiRouting(String(entry.currentValue))}.`);
|
|
161
125
|
}
|
|
@@ -194,8 +158,12 @@ function buildSettingContext(modal: SettingsModal, entry: SettingEntry): string[
|
|
|
194
158
|
return lines;
|
|
195
159
|
}
|
|
196
160
|
|
|
161
|
+
function formatSubscriptionRoute(route: SubscriptionEntry['activeRoute'] | SubscriptionEntry['preferredRoute']): string {
|
|
162
|
+
return route ? formatProviderAuthRouteId(route) : 'n/a';
|
|
163
|
+
}
|
|
164
|
+
|
|
197
165
|
function buildFlagContext(entry: FlagEntry | null): string[] {
|
|
198
|
-
if (!entry) return ['Feature
|
|
166
|
+
if (!entry) return ['Feature Controls', 'No feature control is selected.'];
|
|
199
167
|
return [
|
|
200
168
|
entry.flag.name,
|
|
201
169
|
`ID: ${entry.flag.id}`,
|
|
@@ -209,7 +177,7 @@ function buildFlagContext(entry: FlagEntry | null): string[] {
|
|
|
209
177
|
'',
|
|
210
178
|
entry.flag.runtimeToggleable
|
|
211
179
|
? 'Impact: changes apply immediately and are also persisted as an override when they differ from the default.'
|
|
212
|
-
: 'Impact: this
|
|
180
|
+
: 'Impact: this override is saved for the next Agent launch or owning-host reload, depending on who owns the flag.',
|
|
213
181
|
];
|
|
214
182
|
}
|
|
215
183
|
|
|
@@ -248,14 +216,14 @@ function buildSubscriptionContext(modal: SettingsModal, entry: SubscriptionEntry
|
|
|
248
216
|
? modal.subscriptionLogoutConfirmationTarget === entry.provider
|
|
249
217
|
? `Press Enter again to sign out ${entry.provider}. Move selection or close config to cancel.`
|
|
250
218
|
: 'Press Enter to review sign-out for this provider session.'
|
|
251
|
-
: `
|
|
219
|
+
: `Open Agent Workspace -> Setup and choose Start subscription login for ${entry.provider}.`;
|
|
252
220
|
return [
|
|
253
221
|
entry.provider,
|
|
254
222
|
`State: ${entry.state}`,
|
|
255
223
|
...(routeReason ? [routeReason] : []),
|
|
256
224
|
logout,
|
|
257
|
-
`Active route: ${entry.activeRoute
|
|
258
|
-
`Preferred route: ${entry.preferredRoute
|
|
225
|
+
`Active route: ${formatSubscriptionRoute(entry.activeRoute)}`,
|
|
226
|
+
`Preferred route: ${formatSubscriptionRoute(entry.preferredRoute)}`,
|
|
259
227
|
`OAuth configured: ${entry.oauthConfigured ? 'yes' : 'no'}`,
|
|
260
228
|
`Freshness: ${entry.authFreshness ?? 'n/a'}`,
|
|
261
229
|
`Expires: ${expires}`,
|
|
@@ -390,10 +358,10 @@ function renderFlagRows(modal: SettingsModal, width: number, height: number): st
|
|
|
390
358
|
const nameWidth = clamp(Math.floor(width * 0.40), 24, 58);
|
|
391
359
|
const stateWidth = 10;
|
|
392
360
|
const tierWidth = 6;
|
|
393
|
-
const runtimeWidth =
|
|
361
|
+
const runtimeWidth = 10;
|
|
394
362
|
const defaultWidth = 9;
|
|
395
363
|
const idWidth = Math.max(12, width - nameWidth - stateWidth - tierWidth - runtimeWidth - defaultWidth - 14);
|
|
396
|
-
rows.push(` ${padDisplay('Feature Flag', nameWidth)} ${padDisplay('State', stateWidth)} ${padDisplay('Tier', tierWidth)} ${padDisplay('
|
|
364
|
+
rows.push(` ${padDisplay('Feature Flag', nameWidth)} ${padDisplay('State', stateWidth)} ${padDisplay('Tier', tierWidth)} ${padDisplay('Applies', runtimeWidth)} ${padDisplay('Default', defaultWidth)} ${padDisplay('ID', idWidth)}`);
|
|
397
365
|
const visibleCount = Math.max(1, height - 2);
|
|
398
366
|
const window = stableWindow(items.length, selectedIndex, visibleCount);
|
|
399
367
|
if (window.start > 0) rows.push(`${GLYPHS.navigation.moreAbove} ${window.start} more flag(s) above`);
|
|
@@ -401,7 +369,7 @@ function renderFlagRows(modal: SettingsModal, width: number, height: number): st
|
|
|
401
369
|
const entry = items[index]!;
|
|
402
370
|
const selected = index === selectedIndex;
|
|
403
371
|
const marker = selected ? (modal.focusPane === 'settings' ? GLYPHS.navigation.selected : '•') : ' ';
|
|
404
|
-
rows.push(`${marker} ${padDisplay(entry.flag.name, nameWidth)} ${padDisplay(entry.state, stateWidth)} ${padDisplay(String(entry.flag.tier), tierWidth)} ${padDisplay(entry.flag.runtimeToggleable ? '
|
|
372
|
+
rows.push(`${marker} ${padDisplay(entry.flag.name, nameWidth)} ${padDisplay(entry.state, stateWidth)} ${padDisplay(String(entry.flag.tier), tierWidth)} ${padDisplay(entry.flag.runtimeToggleable ? 'now' : 'next run', runtimeWidth)} ${padDisplay(entry.flag.defaultState, defaultWidth)} ${padDisplay(entry.flag.id, idWidth)}`);
|
|
405
373
|
}
|
|
406
374
|
if (window.end < items.length) rows.push(`${GLYPHS.navigation.moreBelow} ${items.length - window.end} more flag(s) below`);
|
|
407
375
|
return rows.slice(0, height);
|
|
@@ -450,7 +418,7 @@ function renderSubscriptionRows(modal: SettingsModal, width: number, height: num
|
|
|
450
418
|
const entry = items[index]!;
|
|
451
419
|
const selected = index === selectedIndex;
|
|
452
420
|
const marker = selected ? (modal.focusPane === 'settings' ? GLYPHS.navigation.selected : '•') : ' ';
|
|
453
|
-
rows.push(`${marker} ${padDisplay(entry.provider, providerWidth)} ${padDisplay(entry.state, stateWidth)} ${padDisplay(entry.activeRoute
|
|
421
|
+
rows.push(`${marker} ${padDisplay(entry.provider, providerWidth)} ${padDisplay(entry.state, stateWidth)} ${padDisplay(formatSubscriptionRoute(entry.activeRoute), routeWidth)} ${padDisplay(entry.authFreshness ?? 'n/a', freshnessWidth)} ${padDisplay(entry.oauthConfigured ? 'yes' : 'no', oauthWidth)} ${padDisplay(inferSubscriptionRouteReason(entry) ?? '', noteWidth)}`);
|
|
454
422
|
}
|
|
455
423
|
if (window.end < items.length) rows.push(`${GLYPHS.navigation.moreBelow} ${items.length - window.end} more subscription provider(s) below`);
|
|
456
424
|
return rows.slice(0, height);
|
|
@@ -464,7 +432,6 @@ function renderControlRows(modal: SettingsModal, width: number, height: number):
|
|
|
464
432
|
}
|
|
465
433
|
|
|
466
434
|
function rowColorForSetting(modal: SettingsModal, rowText: string): string {
|
|
467
|
-
if (modal.currentCategory === 'danger') return PALETTE.bad;
|
|
468
435
|
if (rowText.startsWith(GLYPHS.navigation.selected)) return PALETTE.text;
|
|
469
436
|
const selected = modal.getSelected();
|
|
470
437
|
if (!selected) return PALETTE.text;
|
|
@@ -478,19 +445,85 @@ function footerText(modal: SettingsModal): string {
|
|
|
478
445
|
if (modal.currentCategory === 'mcp') return 'Focus settings · Up/Down server · Left categories · Tab pane · Enter edit trust · Esc close';
|
|
479
446
|
if (modal.currentCategory === 'flags') return 'Focus feature flags · Up/Down flag · Left categories · Tab pane · Enter/Space toggle · Esc close';
|
|
480
447
|
const selected = modal.getSelected();
|
|
481
|
-
if (selected &&
|
|
482
|
-
return 'Read-only connected-
|
|
448
|
+
if (selected && isExternalHostOwnedSettingKey(selected.setting.key)) {
|
|
449
|
+
return 'Read-only connected-host setting · Change from GoodVibes TUI or the owning host · Esc close';
|
|
483
450
|
}
|
|
484
451
|
return 'Focus settings · Up/Down setting · Left categories · Tab pane · Enter/Space edit/toggle · R reset · Esc close';
|
|
485
452
|
}
|
|
486
453
|
|
|
454
|
+
export function renderSettingsModalPackageText(): string {
|
|
455
|
+
const lines: string[] = [
|
|
456
|
+
'Configuration Workspace / Settings',
|
|
457
|
+
'Categories',
|
|
458
|
+
'Setting',
|
|
459
|
+
'Value',
|
|
460
|
+
'Type',
|
|
461
|
+
'Source',
|
|
462
|
+
'Default',
|
|
463
|
+
'Feature Flag',
|
|
464
|
+
'State',
|
|
465
|
+
'Tier',
|
|
466
|
+
'Applies',
|
|
467
|
+
'Server',
|
|
468
|
+
'Trust',
|
|
469
|
+
'Status',
|
|
470
|
+
'Scope',
|
|
471
|
+
'Provider',
|
|
472
|
+
'Route',
|
|
473
|
+
'Freshness',
|
|
474
|
+
'OAuth',
|
|
475
|
+
'Note',
|
|
476
|
+
'No settings in this category.',
|
|
477
|
+
'No feature flags registered.',
|
|
478
|
+
'No MCP servers registered.',
|
|
479
|
+
'No provider subscriptions available or configured.',
|
|
480
|
+
'No setting is selected in this category.',
|
|
481
|
+
'No feature control is selected.',
|
|
482
|
+
'No MCP server is selected.',
|
|
483
|
+
'No subscription provider is selected.',
|
|
484
|
+
'Trust meanings:',
|
|
485
|
+
'constrained: keep MCP activity inside declared paths/hosts and prompt on risk.',
|
|
486
|
+
'ask-on-risk: allow routine MCP operations but ask before risky behavior.',
|
|
487
|
+
'allow-all: allow unrestricted MCP operations for this server after explicit confirmation.',
|
|
488
|
+
'blocked: prevent this MCP server from being used.',
|
|
489
|
+
'Possible values:',
|
|
490
|
+
'true: enabled or allowed for this setting.',
|
|
491
|
+
'false: disabled or not allowed for this setting.',
|
|
492
|
+
'Secret handling: raw values entered here are stored through the secret manager and the config receives a goodvibes:// secret reference. Empty input clears the config value.',
|
|
493
|
+
'Editing: Enter opens inline edit, then type the value and press Enter to save. Arrow keys only navigate.',
|
|
494
|
+
'Editing: Enter opens inline edit. Delete the current text to save an empty value when that is valid for the setting.',
|
|
495
|
+
'Enter Confirm edit · Esc Cancel edit · text keys edit the selected field',
|
|
496
|
+
'Focus categories · Up/Down choose · Right/Enter settings · Tab pane · Esc close',
|
|
497
|
+
'Focus settings · Up/Down provider · Left categories · Tab pane · Enter review/sign out · Esc close',
|
|
498
|
+
'Focus settings · Up/Down server · Left categories · Tab pane · Enter edit trust · Esc close',
|
|
499
|
+
'Focus feature flags · Up/Down flag · Left categories · Tab pane · Enter/Space toggle · Esc close',
|
|
500
|
+
'Read-only connected-host setting · Change from GoodVibes TUI or the owning host · Esc close',
|
|
501
|
+
'Focus settings · Up/Down setting · Left categories · Tab pane · Enter/Space edit/toggle · R reset · Esc close',
|
|
502
|
+
];
|
|
503
|
+
|
|
504
|
+
for (const group of SETTINGS_CATEGORY_GROUPS) {
|
|
505
|
+
lines.push(group.label);
|
|
506
|
+
for (const category of group.categories) {
|
|
507
|
+
lines.push(category, CATEGORY_LABELS[category], CATEGORY_INFO[category]);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
for (const [key, values] of Object.entries(ENUM_VALUE_DESCRIPTIONS)) {
|
|
512
|
+
lines.push(key);
|
|
513
|
+
for (const [value, description] of Object.entries(values)) {
|
|
514
|
+
lines.push(value, description);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return lines.join('\n');
|
|
519
|
+
}
|
|
520
|
+
|
|
487
521
|
export function renderSettingsModal(
|
|
488
522
|
modal: SettingsModal,
|
|
489
523
|
width: number,
|
|
490
524
|
viewportHeight = 24,
|
|
491
525
|
): Line[] {
|
|
492
526
|
const notices = [
|
|
493
|
-
...(modal.lastSaveTriggeredRestart ? [`Owning host must restart ${modal.lastSaveTriggeredRestart}`] : []),
|
|
494
527
|
...(modal.lastSettingEffectMessage ? [modal.lastSettingEffectMessage] : []),
|
|
495
528
|
];
|
|
496
529
|
const metrics = getFullscreenWorkspaceMetrics({ width, height: viewportHeight });
|
|
@@ -20,7 +20,7 @@ export function classifySystemMessage(content: string): SystemMessageType {
|
|
|
20
20
|
if (/FAILED|cascade abort/i.test(content)) return 'error';
|
|
21
21
|
// Review failed to reach threshold → warning (yellow, retry in progress)
|
|
22
22
|
if (/spawning a fix agent/i.test(content)) return 'warning';
|
|
23
|
-
// All other
|
|
23
|
+
// All other explicit delegated review/build messages classify as info.
|
|
24
24
|
return 'info';
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -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);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
2
|
+
import type { ConversationFollowUpItem } from '@pellux/goodvibes-sdk/platform/core';
|
|
3
|
+
import type { AgentManager } from '@pellux/goodvibes-sdk/platform/tools';
|
|
4
|
+
import type {
|
|
5
|
+
AgentEvent,
|
|
6
|
+
ProviderEvent,
|
|
7
|
+
RuntimeEventBus,
|
|
8
|
+
} from '@/runtime/index.ts';
|
|
9
|
+
import type { createDomainDispatch } from './store/index.ts';
|
|
10
|
+
|
|
11
|
+
const AGENT_STATUS_INTERVAL_MS = 30_000;
|
|
12
|
+
|
|
13
|
+
export interface AgentRuntimeMessageRouter {
|
|
14
|
+
low(message: string): void;
|
|
15
|
+
high(message: string): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface AgentRuntimeEventBridgeOptions {
|
|
19
|
+
readonly runtimeBus: RuntimeEventBus;
|
|
20
|
+
readonly domainDispatch: ReturnType<typeof createDomainDispatch>;
|
|
21
|
+
readonly getSystemMessageRouter: () => AgentRuntimeMessageRouter | null;
|
|
22
|
+
readonly queueConversationFollowUp?: (item: ConversationFollowUpItem) => void;
|
|
23
|
+
readonly requestRender: () => void;
|
|
24
|
+
readonly configManager: ConfigManager;
|
|
25
|
+
readonly agentManager: AgentManager;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function withRouter(
|
|
29
|
+
getSystemMessageRouter: () => AgentRuntimeMessageRouter | null,
|
|
30
|
+
action: (router: AgentRuntimeMessageRouter) => void,
|
|
31
|
+
): void {
|
|
32
|
+
const router = getSystemMessageRouter();
|
|
33
|
+
if (router) action(router);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function formatAgentTask(task: string): string {
|
|
37
|
+
return task.length > 50 ? `${task.slice(0, 50)}...` : task;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function registerAgentRuntimeEvents(options: AgentRuntimeEventBridgeOptions): {
|
|
41
|
+
unsubs: Array<() => void>;
|
|
42
|
+
agentStatusIntervalRef: { value: ReturnType<typeof setInterval> | null };
|
|
43
|
+
} {
|
|
44
|
+
const {
|
|
45
|
+
runtimeBus,
|
|
46
|
+
domainDispatch,
|
|
47
|
+
getSystemMessageRouter,
|
|
48
|
+
queueConversationFollowUp,
|
|
49
|
+
requestRender,
|
|
50
|
+
agentManager,
|
|
51
|
+
} = options;
|
|
52
|
+
const unsubs: Array<() => void> = [];
|
|
53
|
+
|
|
54
|
+
unsubs.push(runtimeBus.onDomain('turn', (env) => {
|
|
55
|
+
domainDispatch.dispatchTurnEvent(env.payload);
|
|
56
|
+
}));
|
|
57
|
+
unsubs.push(runtimeBus.onDomain('agents', (env) => {
|
|
58
|
+
domainDispatch.dispatchAgentEvent(env.payload);
|
|
59
|
+
}));
|
|
60
|
+
unsubs.push(runtimeBus.onDomain('orchestration', (env) => {
|
|
61
|
+
domainDispatch.dispatchOrchestrationEvent(env.payload);
|
|
62
|
+
}));
|
|
63
|
+
unsubs.push(runtimeBus.onDomain('communication', (env) => {
|
|
64
|
+
domainDispatch.dispatchCommunicationEvent(env.payload);
|
|
65
|
+
}));
|
|
66
|
+
unsubs.push(runtimeBus.onDomain('compaction', (env) => {
|
|
67
|
+
domainDispatch.dispatchCompactionEvent(env.payload);
|
|
68
|
+
}));
|
|
69
|
+
unsubs.push(runtimeBus.onDomain('transport', (env) => {
|
|
70
|
+
domainDispatch.dispatchTransportEvent(env.payload);
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
unsubs.push(runtimeBus.on<Extract<ProviderEvent, { type: 'MODEL_FALLBACK' }>>('MODEL_FALLBACK', ({ payload }) => {
|
|
74
|
+
withRouter(getSystemMessageRouter, (router) => {
|
|
75
|
+
router.high(`[Model] ${payload.from} exhausted across all providers. Automatically falling back to ${payload.to} via ${payload.provider}.`);
|
|
76
|
+
});
|
|
77
|
+
requestRender();
|
|
78
|
+
}));
|
|
79
|
+
unsubs.push(runtimeBus.on<Extract<AgentEvent, { type: 'AGENT_STREAM_DELTA' }>>('AGENT_STREAM_DELTA', () => {
|
|
80
|
+
requestRender();
|
|
81
|
+
}));
|
|
82
|
+
unsubs.push(runtimeBus.on<Extract<AgentEvent, { type: 'AGENT_PROGRESS' }>>('AGENT_PROGRESS', () => {
|
|
83
|
+
requestRender();
|
|
84
|
+
}));
|
|
85
|
+
unsubs.push(runtimeBus.on<Extract<AgentEvent, { type: 'AGENT_COMPLETED' }>>('AGENT_COMPLETED', ({ payload }) => {
|
|
86
|
+
const record = agentManager.getStatus(payload.agentId);
|
|
87
|
+
if (record) {
|
|
88
|
+
const durationSeconds = record.completedAt !== undefined ? Math.round((record.completedAt - record.startedAt) / 1000) : 0;
|
|
89
|
+
const taskSnippet = formatAgentTask(record.task);
|
|
90
|
+
withRouter(getSystemMessageRouter, (router) => {
|
|
91
|
+
router.low(`[Delegated task] ${record.template} ${payload.agentId.slice(-8)} completed in ${durationSeconds}s "${taskSnippet}"`);
|
|
92
|
+
});
|
|
93
|
+
queueConversationFollowUp?.({
|
|
94
|
+
key: `agent:${payload.agentId}:completed`,
|
|
95
|
+
summary: `${record.template} delegated task ${payload.agentId.slice(-8)} completed "${taskSnippet}" in ${durationSeconds}s after ${record.toolCallCount} tool calls.`,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
requestRender();
|
|
99
|
+
}));
|
|
100
|
+
unsubs.push(runtimeBus.on<Extract<AgentEvent, { type: 'AGENT_FAILED' }>>('AGENT_FAILED', ({ payload }) => {
|
|
101
|
+
const record = agentManager.getStatus(payload.agentId);
|
|
102
|
+
if (record && record.status !== 'cancelled') {
|
|
103
|
+
const durationSeconds = record.completedAt !== undefined ? Math.round((record.completedAt - record.startedAt) / 1000) : 0;
|
|
104
|
+
const taskSnippet = formatAgentTask(record.task);
|
|
105
|
+
withRouter(getSystemMessageRouter, (router) => {
|
|
106
|
+
router.low(`[Delegated task] ${record.template} ${payload.agentId.slice(-8)} failed in ${durationSeconds}s ${payload.error.slice(0, 80)}`);
|
|
107
|
+
});
|
|
108
|
+
queueConversationFollowUp?.({
|
|
109
|
+
key: `agent:${payload.agentId}:failed`,
|
|
110
|
+
summary: `${record.template} delegated task ${payload.agentId.slice(-8)} failed while working on "${taskSnippet}" ${payload.error.slice(0, 120)}`,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
requestRender();
|
|
114
|
+
}));
|
|
115
|
+
|
|
116
|
+
const agentStatusIntervalRef = { value: null as ReturnType<typeof setInterval> | null };
|
|
117
|
+
agentStatusIntervalRef.value = setInterval(() => {
|
|
118
|
+
const running = agentManager.list().filter((agent) => agent.status === 'running');
|
|
119
|
+
if (running.length === 0) return;
|
|
120
|
+
const lines = running.map((agent) => ` ${agent.id.slice(-8)} ${agent.progress ?? agent.status}`);
|
|
121
|
+
withRouter(getSystemMessageRouter, (router) => {
|
|
122
|
+
router.low(`[Delegated task] ${running.length} running\n${lines.join('\n')}`);
|
|
123
|
+
});
|
|
124
|
+
requestRender();
|
|
125
|
+
}, AGENT_STATUS_INTERVAL_MS);
|
|
126
|
+
agentStatusIntervalRef.value.unref?.();
|
|
127
|
+
|
|
128
|
+
return { unsubs, agentStatusIntervalRef };
|
|
129
|
+
}
|
|
@@ -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'
|
|
@@ -171,8 +174,9 @@ export function createBootstrapCommandActions(
|
|
|
171
174
|
} = options;
|
|
172
175
|
|
|
173
176
|
const showPanel = (panelId: string, pane?: 'top' | 'bottom') => {
|
|
174
|
-
|
|
175
|
-
panelManager.
|
|
177
|
+
void pane;
|
|
178
|
+
panelManager.hide();
|
|
179
|
+
conversation.log(`Panel route "${panelId}" is handled through Agent Workspace. Use /agent for current operator controls.`, { fg: '214' });
|
|
176
180
|
requestRender();
|
|
177
181
|
};
|
|
178
182
|
|
|
@@ -200,7 +204,7 @@ export function createBootstrapCommandActions(
|
|
|
200
204
|
// Write to tool LLM config keys and enable the tool LLM
|
|
201
205
|
configManager.set('tools.llmProvider', def.provider);
|
|
202
206
|
configManager.set('tools.llmModel', key);
|
|
203
|
-
configManager.setDynamic('tools.llmEnabled'
|
|
207
|
+
configManager.setDynamic('tools.llmEnabled', true);
|
|
204
208
|
conversation.log(`Tool LLM set to: ${def.displayName} (${def.provider})`, { fg: '135' });
|
|
205
209
|
} else if (resolvedTarget === 'tts') {
|
|
206
210
|
configManager.set('tts.llmProvider', def.provider);
|
|
@@ -237,9 +241,6 @@ export function createBootstrapCommandActions(
|
|
|
237
241
|
exit: () => unwiredShellAction('exit'),
|
|
238
242
|
reloadSystemPrompt: loadSystemPrompt,
|
|
239
243
|
showPanel,
|
|
240
|
-
openPolicyPanel: () => {
|
|
241
|
-
showPanel('policy');
|
|
242
|
-
},
|
|
243
244
|
openMcpWorkspace: () => unwiredShellAction('openMcpWorkspace'),
|
|
244
245
|
openAgentWorkspace: () => unwiredShellAction('openAgentWorkspace'),
|
|
245
246
|
openSecurityPanel: () => {
|
|
@@ -308,7 +309,7 @@ export function createBootstrapCommandWorkspaceSection(
|
|
|
308
309
|
export function createBootstrapCommandPlatformSection(
|
|
309
310
|
options: Pick<
|
|
310
311
|
BootstrapCommandSectionOptions,
|
|
311
|
-
'configManager' | 'voiceProviderRegistry' | 'voiceService' | 'mediaProviderRegistry'
|
|
312
|
+
'configManager' | 'voiceProviderRegistry' | 'voiceService' | 'mediaProviderRegistry' | 'artifactStore' | 'channelDeliveryRouter'
|
|
312
313
|
>,
|
|
313
314
|
shellServices: BootstrapCommandShellServices,
|
|
314
315
|
): BootstrapCommandPlatformSection {
|
|
@@ -318,6 +319,8 @@ export function createBootstrapCommandPlatformSection(
|
|
|
318
319
|
voiceProviderRegistry: options.voiceProviderRegistry,
|
|
319
320
|
voiceService: options.voiceService,
|
|
320
321
|
mediaProviderRegistry: options.mediaProviderRegistry,
|
|
322
|
+
artifactStore: options.artifactStore,
|
|
323
|
+
channelDeliveryRouter: options.channelDeliveryRouter,
|
|
321
324
|
...shellServices.platform,
|
|
322
325
|
};
|
|
323
326
|
}
|