@pellux/goodvibes-agent 0.1.116 → 0.1.117
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 +41 -663
- package/README.md +38 -52
- package/dist/package/main.js +37826 -35924
- package/docs/README.md +5 -4
- package/docs/{connected-services.md → connected-host.md} +18 -10
- package/docs/getting-started.md +41 -44
- package/docs/release-and-publishing.md +6 -4
- package/package.json +3 -3
- package/src/agent/behavior-discovery-summary.ts +1 -3
- package/src/agent/persona-discovery.ts +1 -3
- package/src/agent/persona-registry.ts +5 -3
- package/src/agent/reminder-schedule-format.ts +6 -6
- package/src/agent/reminder-schedule.ts +1 -1
- package/src/agent/routine-registry.ts +43 -4
- package/src/agent/routine-schedule-format.ts +6 -6
- package/src/agent/routine-schedule-promotion.ts +1 -1
- package/src/agent/routine-schedule-receipts.ts +1 -1
- package/src/agent/runtime-profile-starters.ts +3 -3
- package/src/agent/runtime-profile.ts +78 -0
- package/src/agent/skill-registry.ts +190 -13
- package/src/cli/agent-knowledge-command.ts +2 -2
- package/src/cli/agent-knowledge-format.ts +2 -2
- package/src/cli/agent-knowledge-runtime.ts +1 -1
- package/src/cli/bundle-command.ts +1 -1
- package/src/cli/entrypoint.ts +16 -7
- package/src/cli/help.ts +26 -19
- package/src/cli/local-library-command.ts +75 -21
- package/src/cli/management-commands.ts +7 -6
- package/src/cli/management.ts +6 -51
- package/src/cli/parser.ts +23 -2
- package/src/cli/profiles-command.ts +119 -1
- package/src/cli/routines-command.ts +139 -11
- package/src/cli/service-posture.ts +11 -11
- package/src/cli/status.ts +21 -25
- 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 +2 -1
- package/src/input/agent-workspace-basic-command-editor-submission.ts +345 -92
- package/src/input/agent-workspace-basic-command-editors.ts +480 -7
- package/src/input/agent-workspace-categories.ts +175 -15
- package/src/input/agent-workspace-channel-command-editor-submission.ts +49 -0
- package/src/input/agent-workspace-channel-command-editors.ts +47 -0
- package/src/input/agent-workspace-command-editor.ts +23 -1
- package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
- package/src/input/agent-workspace-editors.ts +27 -0
- 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-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-mcp-command-editor-submission.ts +95 -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-navigation.ts +45 -0
- package/src/input/agent-workspace-notify-editor-submission.ts +107 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +146 -0
- package/src/input/agent-workspace-operations-command-editors.ts +119 -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-requirements.ts +11 -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 +24 -14
- 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 +50 -8
- 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-types.ts +120 -0
- package/src/input/agent-workspace-voice-media.ts +1 -1
- package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
- package/src/input/agent-workspace.ts +47 -37
- package/src/input/command-registry.ts +1 -1
- package/src/input/commands/agent-runtime-profile-runtime.ts +89 -4
- package/src/input/commands/agent-skills-runtime.ts +76 -12
- package/src/input/commands/agent-workspace-runtime.ts +4 -3
- package/src/input/commands/brief-runtime.ts +38 -9
- package/src/input/commands/channels-runtime.ts +3 -3
- package/src/input/commands/compat-runtime.ts +32 -0
- package/src/input/commands/health-runtime.ts +22 -24
- package/src/input/commands/knowledge.ts +26 -5
- package/src/input/commands/local-provider-runtime.ts +7 -3
- package/src/input/commands/local-setup-review.ts +4 -14
- package/src/input/commands/mcp-runtime.ts +8 -12
- package/src/input/commands/operator-runtime.ts +8 -67
- package/src/input/commands/personas-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +7 -70
- package/src/input/commands/policy-dispatch.ts +1 -1
- package/src/input/commands/policy.ts +1 -5
- package/src/input/commands/product-runtime.ts +2 -2
- package/src/input/commands/qrcode-runtime.ts +6 -4
- package/src/input/commands/routines-runtime.ts +44 -6
- package/src/input/commands/runtime-services.ts +1 -14
- package/src/input/commands/security-runtime.ts +3 -8
- package/src/input/commands/session-content.ts +1 -1
- package/src/input/commands/session-workflow.ts +5 -14
- package/src/input/commands/shell-core.ts +8 -2
- package/src/input/commands/subscription-runtime.ts +1 -6
- package/src/input/commands/support-bundle-runtime.ts +53 -0
- package/src/input/commands/tasks-runtime.ts +2 -2
- package/src/input/commands.ts +4 -0
- package/src/input/feed-context-factory.ts +0 -1
- package/src/input/handler-content-actions.ts +0 -25
- package/src/input/handler-feed.ts +0 -2
- package/src/input/handler-interactions.ts +2 -31
- package/src/input/handler-onboarding.ts +29 -12
- package/src/input/handler-shortcuts.ts +1 -3
- package/src/input/handler.ts +4 -7
- package/src/input/keybindings.ts +9 -9
- 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 +49 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +81 -3
- package/src/input/onboarding/onboarding-wizard-steps.ts +14 -7
- package/src/input/onboarding/onboarding-wizard-types.ts +1 -0
- package/src/input/onboarding/onboarding-wizard.ts +19 -2
- package/src/input/profile-picker-modal.ts +2 -2
- package/src/input/settings-modal-agent-policy.ts +6 -6
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal.ts +14 -14
- package/src/main.ts +0 -2
- package/src/panels/automation-control-panel.ts +3 -3
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +2 -2
- package/src/panels/builtin/session.ts +26 -18
- package/src/panels/builtin/shared.ts +6 -6
- package/src/panels/project-planning-panel.ts +1 -1
- package/src/panels/provider-health-domains.ts +3 -3
- package/src/panels/qr-panel.ts +44 -20
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +2 -2
- package/src/panels/tasks-panel.ts +4 -4
- package/src/planning/project-planning-coordinator.ts +2 -2
- package/src/renderer/agent-workspace.ts +26 -5
- package/src/renderer/block-actions.ts +1 -3
- package/src/renderer/help-overlay.ts +13 -8
- package/src/renderer/mcp-workspace.ts +32 -13
- package/src/renderer/model-picker-overlay.ts +0 -1
- package/src/renderer/model-workspace.ts +0 -2
- package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
- package/src/renderer/panel-picker-overlay.ts +1 -1
- package/src/renderer/profile-picker-modal.ts +2 -2
- package/src/renderer/settings-modal-helpers.ts +23 -23
- package/src/renderer/settings-modal.ts +18 -18
- package/src/renderer/system-message.ts +1 -1
- package/src/runtime/agent-runtime-events.ts +129 -0
- package/src/runtime/bootstrap-command-parts.ts +3 -2
- package/src/runtime/bootstrap-core.ts +4 -64
- package/src/runtime/bootstrap-shell.ts +42 -4
- package/src/runtime/bootstrap.ts +8 -27
- package/src/runtime/connected-host-auth.ts +42 -0
- package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
- package/src/runtime/index.ts +1 -5
- package/src/runtime/onboarding/apply.ts +213 -0
- package/src/runtime/onboarding/derivation.ts +5 -5
- package/src/runtime/onboarding/snapshot.ts +2 -2
- package/src/runtime/onboarding/types.ts +26 -1
- package/src/runtime/onboarding/verify.ts +81 -2
- package/src/runtime/operator-token-cleanup.ts +2 -2
- package/src/runtime/services.ts +27 -12
- package/src/shell/service-settings-sync.ts +7 -7
- package/src/shell/ui-openers.ts +27 -38
- package/src/tools/agent-local-registry-tool.ts +10 -4
- package/src/tools/agent-tool-policy-guard.ts +5 -7
- package/src/version.ts +1 -1
- package/src/cli/package-verification.ts +0 -274
|
@@ -82,16 +82,22 @@ function selectedDetailLines(workspace: McpWorkspace, width: number): WorkspaceR
|
|
|
82
82
|
if (workspace.mode === 'form') {
|
|
83
83
|
const field = workspace.formFields[workspace.formIndex];
|
|
84
84
|
lines.push(
|
|
85
|
-
workspace.editingServerName ? `
|
|
86
|
-
'Workspace writes
|
|
85
|
+
workspace.editingServerName ? `Editing server: ${workspace.editingServerName}` : 'Drafting an MCP server',
|
|
86
|
+
'Workspace writes require explicit confirmation. Type yes on the Confirm field, then save from here.',
|
|
87
87
|
field ? `${field.label}: ${field.help}` : '',
|
|
88
|
-
'Project/global config locations are shown for review.
|
|
88
|
+
'Project/global config locations are shown for review. The workspace dispatches confirmed MCP changes through the TUI command router.',
|
|
89
89
|
);
|
|
90
90
|
} else if (workspace.mode === 'delete-confirm') {
|
|
91
91
|
lines.push(
|
|
92
|
-
`
|
|
93
|
-
'
|
|
94
|
-
'Press n or Esc to return.',
|
|
92
|
+
`Remove server: ${workspace.editingServerName ?? '(unknown)'}`,
|
|
93
|
+
'Press Enter or y to remove through the TUI command router.',
|
|
94
|
+
'Press n or Esc to return without changing config.',
|
|
95
|
+
);
|
|
96
|
+
} else if (workspace.mode === 'reload-confirm') {
|
|
97
|
+
lines.push(
|
|
98
|
+
'Reload MCP runtime',
|
|
99
|
+
'Press Enter or y to reload MCP runtime from the current config through the TUI command router.',
|
|
100
|
+
'Press n or Esc to return without reloading.',
|
|
95
101
|
);
|
|
96
102
|
} else {
|
|
97
103
|
const selected = workspace.selectedRow;
|
|
@@ -200,27 +206,40 @@ function buildDeleteRows(workspace: McpWorkspace, height: number): WorkspaceRow[
|
|
|
200
206
|
return rows.slice(0, height);
|
|
201
207
|
}
|
|
202
208
|
|
|
209
|
+
function buildReloadRows(height: number): WorkspaceRow[] {
|
|
210
|
+
const rows: WorkspaceRow[] = [
|
|
211
|
+
{ text: `${GLYPHS.navigation.selected} Confirm MCP runtime reload`, selected: true, fg: PALETTE.warn, bold: true },
|
|
212
|
+
{ text: ' Cancel and return to MCP server browser', fg: PALETTE.muted },
|
|
213
|
+
];
|
|
214
|
+
while (rows.length < height) rows.push({ text: '', kind: 'empty' });
|
|
215
|
+
return rows.slice(0, height);
|
|
216
|
+
}
|
|
217
|
+
|
|
203
218
|
function buildControlRows(workspace: McpWorkspace, width: number, height: number): WorkspaceRow[] {
|
|
204
219
|
if (workspace.mode === 'form') return buildFormRows(workspace, width, height);
|
|
205
220
|
if (workspace.mode === 'delete-confirm') return buildDeleteRows(workspace, height);
|
|
221
|
+
if (workspace.mode === 'reload-confirm') return buildReloadRows(height);
|
|
206
222
|
return buildToolRows(workspace, width, height);
|
|
207
223
|
}
|
|
208
224
|
|
|
209
225
|
function footerText(workspace: McpWorkspace): string {
|
|
210
|
-
if (workspace.mode === 'form') return 'Focus server
|
|
211
|
-
if (workspace.mode === 'delete-confirm') return 'Focus remove
|
|
212
|
-
return 'Focus
|
|
226
|
+
if (workspace.mode === 'form') return 'Focus MCP server form · Up/Down field · Left/Right cycle · Type edit · Enter save/cancel · Esc back';
|
|
227
|
+
if (workspace.mode === 'delete-confirm') return 'Focus remove confirmation · Enter/y remove · n/Esc cancel';
|
|
228
|
+
if (workspace.mode === 'reload-confirm') return 'Focus reload confirmation · Enter/y reload · n/Esc cancel';
|
|
229
|
+
return 'Focus MCP workspace · Up/Down choose · Enter view/action · a add · d remove · r reload · t tools · Esc close';
|
|
213
230
|
}
|
|
214
231
|
|
|
215
232
|
export function renderMcpWorkspace(workspace: McpWorkspace, width: number, height: number): Line[] {
|
|
216
233
|
const metrics = getFullscreenWorkspaceMetrics({ width, height });
|
|
217
234
|
const connected = workspace.servers.filter((server) => server.connected).length;
|
|
218
|
-
const stateLabel = workspace.mode === 'browse' ? 'Browse' : workspace.mode === 'form' ? '
|
|
235
|
+
const stateLabel = workspace.mode === 'browse' ? 'Browse' : workspace.mode === 'form' ? 'Server Form' : workspace.mode === 'delete-confirm' ? 'Remove Confirm' : 'Reload Confirm';
|
|
219
236
|
const mainHeader = workspace.mode === 'form'
|
|
220
|
-
? 'MCP server
|
|
237
|
+
? 'MCP server form'
|
|
221
238
|
: workspace.mode === 'delete-confirm'
|
|
222
|
-
? 'MCP remove
|
|
223
|
-
:
|
|
239
|
+
? 'MCP remove confirmation'
|
|
240
|
+
: workspace.mode === 'reload-confirm'
|
|
241
|
+
? 'MCP reload confirmation'
|
|
242
|
+
: `Servers ${connected}/${workspace.servers.length} connected · Tools ${workspace.tools.length}`;
|
|
224
243
|
|
|
225
244
|
return renderFullscreenWorkspace({
|
|
226
245
|
width,
|
|
@@ -240,7 +240,6 @@ export function renderModelPickerOverlay(
|
|
|
240
240
|
if (caps.reasoning) capParts.push('Reasoning: \u2713');
|
|
241
241
|
if (caps.multimodal) capParts.push('Vision: \u2713');
|
|
242
242
|
if (caps.toolCalling) capParts.push('Tools: \u2713');
|
|
243
|
-
if (caps.codeEditing) capParts.push('Code: \u2713');
|
|
244
243
|
const capText = capParts.join(' ');
|
|
245
244
|
const capLine = createOverlayContentLine(width, layout, borderFg, DEFAULT_OVERLAY_PALETTE.bodyBg);
|
|
246
245
|
putRowText(capLine, layout.margin + 2, contentW, fitDisplay(truncateDisplay(capText, contentW), contentW), '244');
|
|
@@ -184,7 +184,6 @@ function detailLines(picker: ModelPickerModal, width: number): string[] {
|
|
|
184
184
|
caps.reasoning ? 'reasoning' : '',
|
|
185
185
|
caps.multimodal ? 'vision' : '',
|
|
186
186
|
caps.toolCalling ? 'tools' : '',
|
|
187
|
-
caps.codeEditing ? 'code' : '',
|
|
188
187
|
].filter(Boolean).join(', ') || 'standard';
|
|
189
188
|
lines.push(`Selected: ${modelKey(selected)} | ${selected.displayName} | context ${formatContext(selected.contextWindow)} | ${capText}`);
|
|
190
189
|
}
|
|
@@ -261,7 +260,6 @@ function renderModelRows(picker: ModelPickerModal, lines: Line[], rows: number,
|
|
|
261
260
|
caps.reasoning ? 'R' : '-',
|
|
262
261
|
caps.multimodal ? 'V' : '-',
|
|
263
262
|
caps.toolCalling ? 'T' : '-',
|
|
264
|
-
caps.codeEditing ? 'C' : '-',
|
|
265
263
|
].join('');
|
|
266
264
|
let x = startX + 1;
|
|
267
265
|
writeText(line, x, 2, padDisplay(marker, 2), { fg: PALETTE.text, bg, bold: selected }); x += 2;
|
|
@@ -161,16 +161,28 @@ function fieldHint(
|
|
|
161
161
|
const rawValue = wizard.editBuffer.length > 0 ? wizard.editBuffer : field.placeholder;
|
|
162
162
|
const editingValue = field.kind === 'masked' && wizard.editBuffer.length > 0
|
|
163
163
|
? '•'.repeat(Math.min(12, Math.max(4, wizard.editBuffer.length)))
|
|
164
|
-
: rawValue;
|
|
164
|
+
: formatEditingValue(rawValue, field.kind === 'text' && field.multiline === true);
|
|
165
165
|
return `Editing: ${editingValue}█`;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
if (selected && field.kind === 'modelPicker') return `${field.hint} Press Enter to open picker.`;
|
|
169
|
-
if (selected && field.kind === 'text')
|
|
169
|
+
if (selected && field.kind === 'text') {
|
|
170
|
+
return field.multiline === true
|
|
171
|
+
? `${field.hint} Press Enter to edit; Ctrl-J inserts a new line.`
|
|
172
|
+
: `${field.hint} Press Enter to edit inline.`;
|
|
173
|
+
}
|
|
170
174
|
if (selected && field.kind === 'masked') return `${field.hint} Press Enter to edit inline.`;
|
|
171
175
|
return field.hint;
|
|
172
176
|
}
|
|
173
177
|
|
|
178
|
+
function formatEditingValue(value: string, multiline: boolean): string {
|
|
179
|
+
if (!multiline) return value;
|
|
180
|
+
const lines = value.split(/\r?\n/);
|
|
181
|
+
if (lines.length <= 1) return value;
|
|
182
|
+
const preview = lines[lines.length - 1] ?? '';
|
|
183
|
+
return `${preview} (${lines.length} lines)`;
|
|
184
|
+
}
|
|
185
|
+
|
|
174
186
|
function fieldRowPrefix(
|
|
175
187
|
wizard: OnboardingWizardController,
|
|
176
188
|
field: OnboardingWizardFieldDefinition,
|
|
@@ -255,7 +267,9 @@ function renderFieldRow(
|
|
|
255
267
|
|
|
256
268
|
function footerText(wizard: OnboardingWizardController): string {
|
|
257
269
|
if (wizard.isEditingTextField()) {
|
|
258
|
-
return
|
|
270
|
+
return wizard.isEditingMultilineTextField()
|
|
271
|
+
? '[Enter] Save value [Ctrl-J] New line [Esc] Cancel edit [Backspace] Delete char [Del/Ctrl+U] Clear value'
|
|
272
|
+
: '[Enter] Save value [Esc] Cancel edit [Backspace] Delete char [Del/Ctrl+U] Clear value';
|
|
259
273
|
}
|
|
260
274
|
|
|
261
275
|
return '[Enter] Toggle/open [Esc] Close [Tab/Shift+Tab] Screen [↑↓] Move [Del/Ctrl+U] Clear input';
|
|
@@ -263,7 +277,9 @@ function footerText(wizard: OnboardingWizardController): string {
|
|
|
263
277
|
|
|
264
278
|
function controlsText(wizard: OnboardingWizardController): string {
|
|
265
279
|
if (wizard.isEditingTextField()) {
|
|
266
|
-
return
|
|
280
|
+
return wizard.isEditingMultilineTextField()
|
|
281
|
+
? 'Controls: Enter saves, Ctrl-J inserts a line, Esc cancels, Backspace deletes, Del clears.'
|
|
282
|
+
: 'Controls: Enter saves, Esc cancels, Backspace deletes, Del clears.';
|
|
267
283
|
}
|
|
268
284
|
return 'Controls: Enter selects, Del clears, Tab moves.';
|
|
269
285
|
}
|
|
@@ -46,7 +46,7 @@ export function renderPanelPickerOverlay(
|
|
|
46
46
|
|
|
47
47
|
// ── Title bar ──────────────────────────────────────────────────────────────
|
|
48
48
|
const titleLine = createOverlayBorderLine(width, layout, '┌', '─', '┐', borderFg);
|
|
49
|
-
putOverlayText(titleLine, layout.margin + 2, layout.width - 4, '
|
|
49
|
+
putOverlayText(titleLine, layout.margin + 2, layout.width - 4, 'Deferred Workspace Picker', { fg: titleFg, bold: true });
|
|
50
50
|
lines.push(titleLine);
|
|
51
51
|
|
|
52
52
|
// ── Search bar (shown when query is non-empty) ──────────────────────────────
|
|
@@ -51,7 +51,7 @@ export function renderProfilePickerModal(
|
|
|
51
51
|
});
|
|
52
52
|
sections.push({
|
|
53
53
|
type: 'text',
|
|
54
|
-
content: 'Use /profiles
|
|
54
|
+
content: 'Use /agent profiles to create and manage isolated Agent profile homes.',
|
|
55
55
|
style: { fg: '240', dim: true },
|
|
56
56
|
});
|
|
57
57
|
} else {
|
|
@@ -114,7 +114,7 @@ export function renderProfilePickerModal(
|
|
|
114
114
|
margin: boxMargin,
|
|
115
115
|
targetContentRows,
|
|
116
116
|
sections,
|
|
117
|
-
hints: ['[Up/Down] Navigate', '[Enter] Load', '
|
|
117
|
+
hints: ['[Up/Down] Navigate', '[Enter] Load', 'Agent profiles: /agent profiles', '[Esc] Close'],
|
|
118
118
|
},
|
|
119
119
|
width,
|
|
120
120
|
);
|
|
@@ -83,12 +83,12 @@ export const CATEGORY_LABELS: Record<(typeof SETTINGS_CATEGORIES)[number], strin
|
|
|
83
83
|
storage: 'Storage',
|
|
84
84
|
permissions: 'Permissions',
|
|
85
85
|
orchestration: 'Orchestration',
|
|
86
|
-
wrfc: '
|
|
86
|
+
wrfc: 'Build Delegation',
|
|
87
87
|
helper: 'Helper',
|
|
88
88
|
tts: 'TTS',
|
|
89
|
-
service: '
|
|
90
|
-
controlPlane: '
|
|
91
|
-
httpListener: 'Inbound
|
|
89
|
+
service: 'Connected Host',
|
|
90
|
+
controlPlane: 'Connected API',
|
|
91
|
+
httpListener: 'Inbound Delivery',
|
|
92
92
|
web: 'Browser Companion',
|
|
93
93
|
batch: 'Batch',
|
|
94
94
|
automation: 'Automation',
|
|
@@ -108,7 +108,7 @@ export const CATEGORY_LABELS: Record<(typeof SETTINGS_CATEGORIES)[number], strin
|
|
|
108
108
|
export const SETTING_LABELS: Partial<Record<string, string>> = {
|
|
109
109
|
'ui.systemMessages': 'System Message Target',
|
|
110
110
|
'ui.operationalMessages': 'Operational Message Target',
|
|
111
|
-
'ui.wrfcMessages': 'Delegated
|
|
111
|
+
'ui.wrfcMessages': 'Delegated Build Message Target',
|
|
112
112
|
'ui.voiceEnabled': 'Voice Interaction',
|
|
113
113
|
'behavior.autoCompactThreshold': 'Auto-Compact %',
|
|
114
114
|
'behavior.staleContextWarnings': 'Context Warnings',
|
|
@@ -124,24 +124,24 @@ export const SETTING_LABELS: Partial<Record<string, string>> = {
|
|
|
124
124
|
'helper.globalProvider': 'Helper Provider',
|
|
125
125
|
'helper.globalModel': 'Helper Model',
|
|
126
126
|
// Runtime API
|
|
127
|
-
'controlPlane.enabled': '
|
|
128
|
-
'controlPlane.hostMode': '
|
|
129
|
-
'controlPlane.host': '
|
|
130
|
-
'controlPlane.port': '
|
|
131
|
-
'controlPlane.baseUrl': '
|
|
132
|
-
'controlPlane.streamMode': '
|
|
133
|
-
'controlPlane.allowRemote': '
|
|
134
|
-
'controlPlane.trustProxy': '
|
|
135
|
-
'controlPlane.tls.mode': '
|
|
136
|
-
'controlPlane.tls.certFile': '
|
|
137
|
-
'controlPlane.tls.keyFile': '
|
|
138
|
-
// Inbound
|
|
139
|
-
'httpListener.hostMode': '
|
|
140
|
-
'httpListener.host': '
|
|
141
|
-
'httpListener.port': '
|
|
142
|
-
'httpListener.trustProxy': '
|
|
143
|
-
'httpListener.tls.mode': '
|
|
144
|
-
'httpListener.tls.certFile': '
|
|
127
|
+
'controlPlane.enabled': 'Connected API Enabled',
|
|
128
|
+
'controlPlane.hostMode': 'Connected API Host Mode',
|
|
129
|
+
'controlPlane.host': 'Connected API Host',
|
|
130
|
+
'controlPlane.port': 'Connected API Port',
|
|
131
|
+
'controlPlane.baseUrl': 'Connected API Base URL',
|
|
132
|
+
'controlPlane.streamMode': 'Connected API Stream Mode',
|
|
133
|
+
'controlPlane.allowRemote': 'Connected API Allow Remote',
|
|
134
|
+
'controlPlane.trustProxy': 'Connected API Trust Proxy',
|
|
135
|
+
'controlPlane.tls.mode': 'Connected API TLS Mode',
|
|
136
|
+
'controlPlane.tls.certFile': 'Connected API TLS Cert',
|
|
137
|
+
'controlPlane.tls.keyFile': 'Connected API TLS Key',
|
|
138
|
+
// Inbound delivery endpoint
|
|
139
|
+
'httpListener.hostMode': 'Inbound Delivery Host Mode',
|
|
140
|
+
'httpListener.host': 'Inbound Delivery Host',
|
|
141
|
+
'httpListener.port': 'Inbound Delivery Port',
|
|
142
|
+
'httpListener.trustProxy': 'Inbound Delivery Trust Proxy',
|
|
143
|
+
'httpListener.tls.mode': 'Inbound Delivery TLS Mode',
|
|
144
|
+
'httpListener.tls.certFile': 'Inbound Delivery TLS Cert',
|
|
145
145
|
// Browser companion
|
|
146
146
|
'web.enabled': 'Web Enabled',
|
|
147
147
|
'web.hostMode': 'Web Host Mode',
|
|
@@ -7,7 +7,7 @@
|
|
|
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';
|
|
@@ -30,34 +30,34 @@ const CATEGORY_INFO: Record<SettingsCategory, string> = {
|
|
|
30
30
|
behavior: 'Day-to-day shell behavior: approval posture, compaction, history, guidance, notifications, stale-context warnings, return context, and Human-in-the-Loop mode.',
|
|
31
31
|
storage: 'Local storage posture, including secret storage policy and maximum artifact size for Agent Knowledge, artifacts, and document ingestion.',
|
|
32
32
|
permissions: 'Permission mode and tool-class policy. These settings decide whether the shell prompts before read/write/exec/network/agent actions.',
|
|
33
|
-
orchestration: 'Agent
|
|
34
|
-
wrfc: '
|
|
33
|
+
orchestration: 'Hidden compatibility settings. Normal Agent operation stays serial and does not expose local spawn fanout.',
|
|
34
|
+
wrfc: 'Build-review routing is external to normal Agent operation. Review these compatibility values only for explicit delegated build work.',
|
|
35
35
|
helper: 'Helper model defaults used by helper subsystems when they do not use the main chat route.',
|
|
36
36
|
tts: 'Text-to-speech provider, voice, and optional spoken-turn LLM overrides.',
|
|
37
|
-
service: 'Connected-
|
|
38
|
-
controlPlane: 'Connected
|
|
39
|
-
httpListener: 'Inbound
|
|
37
|
+
service: 'Connected-host status posture. Agent inspects these values only and does not install, start, stop, restart, or autostart anything.',
|
|
38
|
+
controlPlane: 'Connected API settings. Agent uses these values for access and does not mutate bind posture.',
|
|
39
|
+
httpListener: 'Inbound delivery endpoint settings owned by the connected GoodVibes host. Agent inspects readiness and does not expose endpoints.',
|
|
40
40
|
web: 'External browser companion settings. Agent does not own browser hosting or network bind lifecycle.',
|
|
41
|
-
batch: '
|
|
41
|
+
batch: 'Queued execution settings reported from the connected GoodVibes host. Agent does not own remote queue provisioning.',
|
|
42
42
|
automation: 'Scheduled and automated run settings, concurrency, timeout, catch-up, cooldown, and retention behavior.',
|
|
43
43
|
watchers: 'File/process watcher heartbeat, polling, and recovery-window behavior.',
|
|
44
|
-
runtime: 'Connected-
|
|
44
|
+
runtime: 'Connected-host guardrails such as companion chat limits and event-stream caps.',
|
|
45
45
|
telemetry: 'Telemetry payload policy.',
|
|
46
46
|
cache: 'Provider and model cache behavior, TTL, and hit-rate monitoring.',
|
|
47
47
|
mcp: 'MCP server trust and scope review. Trust changes can expose local files, tools, databases, browsers, or remote automation depending on the server.',
|
|
48
48
|
surfaces: 'Messaging and notification channel accounts such as Slack, Discord, ntfy, Telegram, chat bridges, and delivery providers.',
|
|
49
49
|
release: 'Release-channel preference.',
|
|
50
|
-
danger: 'High-impact
|
|
50
|
+
danger: 'High-impact host switches. Agent renders host-owned switches read-only; change them outside Agent.',
|
|
51
51
|
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
52
|
flags: 'Feature flags are SDK gates. They are separate from normal config keys because they enable or disable staged behavior.',
|
|
53
|
-
network: 'Read-only view of connected GoodVibes API, inbound
|
|
53
|
+
network: 'Read-only view of connected GoodVibes API, inbound delivery, and browser companion bind posture plus editable Agent network settings.',
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
|
|
57
57
|
'behavior.hitlMode': {
|
|
58
58
|
quiet: 'Minimize operational interruptions and surface fewer Human-in-the-Loop prompts.',
|
|
59
59
|
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,
|
|
60
|
+
operator: 'Surface more operational detail for users actively supervising agents, tools, connected-host posture, and automation.',
|
|
61
61
|
},
|
|
62
62
|
'behavior.guidanceMode': {
|
|
63
63
|
off: 'Do not add extra guidance beyond direct command output.',
|
|
@@ -105,9 +105,9 @@ const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
|
|
|
105
105
|
both: 'Show operational messages in both panels and the transcript.',
|
|
106
106
|
},
|
|
107
107
|
'ui.wrfcMessages': {
|
|
108
|
-
panel: 'Show explicit delegated
|
|
109
|
-
conversation: 'Show explicit delegated
|
|
110
|
-
both: 'Show explicit delegated
|
|
108
|
+
panel: 'Show explicit delegated build messages in panels only.',
|
|
109
|
+
conversation: 'Show explicit delegated build messages inline in the transcript.',
|
|
110
|
+
both: 'Show explicit delegated build messages in both panels and the transcript.',
|
|
111
111
|
},
|
|
112
112
|
'surfaces.telegram.mode': {
|
|
113
113
|
webhook: 'Receive Telegram updates through externally hosted delivery.',
|
|
@@ -148,7 +148,7 @@ function buildSettingContext(modal: SettingsModal, entry: SettingEntry): string[
|
|
|
148
148
|
];
|
|
149
149
|
|
|
150
150
|
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
|
|
151
|
+
if (entry.conflict) lines.push(`Conflict: inspect with /settings and resolve host-owned sync state in the owning host.`);
|
|
152
152
|
|
|
153
153
|
lines.push('', entry.setting.description);
|
|
154
154
|
|
|
@@ -248,7 +248,7 @@ function buildSubscriptionContext(modal: SettingsModal, entry: SubscriptionEntry
|
|
|
248
248
|
? modal.subscriptionLogoutConfirmationTarget === entry.provider
|
|
249
249
|
? `Press Enter again to sign out ${entry.provider}. Move selection or close config to cancel.`
|
|
250
250
|
: 'Press Enter to review sign-out for this provider session.'
|
|
251
|
-
: `
|
|
251
|
+
: `Open /agent setup and choose Start subscription login for ${entry.provider}.`;
|
|
252
252
|
return [
|
|
253
253
|
entry.provider,
|
|
254
254
|
`State: ${entry.state}`,
|
|
@@ -478,8 +478,8 @@ function footerText(modal: SettingsModal): string {
|
|
|
478
478
|
if (modal.currentCategory === 'mcp') return 'Focus settings · Up/Down server · Left categories · Tab pane · Enter edit trust · Esc close';
|
|
479
479
|
if (modal.currentCategory === 'flags') return 'Focus feature flags · Up/Down flag · Left categories · Tab pane · Enter/Space toggle · Esc close';
|
|
480
480
|
const selected = modal.getSelected();
|
|
481
|
-
if (selected &&
|
|
482
|
-
return 'Read-only connected-
|
|
481
|
+
if (selected && isExternalHostOwnedSettingKey(selected.setting.key)) {
|
|
482
|
+
return 'Read-only connected-host setting · Change from GoodVibes TUI or the owning host · Esc close';
|
|
483
483
|
}
|
|
484
484
|
return 'Focus settings · Up/Down setting · Left categories · Tab pane · Enter/Space edit/toggle · R reset · Esc close';
|
|
485
485
|
}
|
|
@@ -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
|
|
|
@@ -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(`[Agent 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} agent ${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(`[Agent 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} agent ${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(`[Agent 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
|
+
}
|
|
@@ -171,8 +171,9 @@ export function createBootstrapCommandActions(
|
|
|
171
171
|
} = options;
|
|
172
172
|
|
|
173
173
|
const showPanel = (panelId: string, pane?: 'top' | 'bottom') => {
|
|
174
|
-
|
|
175
|
-
panelManager.
|
|
174
|
+
void pane;
|
|
175
|
+
panelManager.hide();
|
|
176
|
+
conversation.log(`Panel "${panelId}" is deferred in GoodVibes Agent. Use /agent for the operator workspace.`, { fg: '214' });
|
|
176
177
|
requestRender();
|
|
177
178
|
};
|
|
178
179
|
|
|
@@ -26,12 +26,12 @@ import {
|
|
|
26
26
|
} from '@/runtime/index.ts';
|
|
27
27
|
import { loadBootstrapSystemPrompt, syncConfiguredServices } from '@/runtime/index.ts';
|
|
28
28
|
import { registerBootstrapHookBridge } from '@/runtime/index.ts';
|
|
29
|
-
import { registerBootstrapRuntimeEvents } from '@/runtime/index.ts';
|
|
30
29
|
import { createRuntimeServices, type RuntimeServices } from './services.ts';
|
|
31
30
|
import { createUiRuntimeServices, type UiRuntimeServices } from './ui-services.ts';
|
|
32
31
|
import { installAgentToolPolicyGuard } from '../tools/agent-tool-policy-guard.ts';
|
|
33
32
|
import { registerAgentLocalRegistryTool } from '../tools/agent-local-registry-tool.ts';
|
|
34
33
|
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
34
|
+
import { registerAgentRuntimeEvents } from './agent-runtime-events.ts';
|
|
35
35
|
|
|
36
36
|
export interface BootstrapCoreState {
|
|
37
37
|
readonly userSessionId: string;
|
|
@@ -211,7 +211,6 @@ export async function initializeBootstrapCore(
|
|
|
211
211
|
agentManager: services.agentManager,
|
|
212
212
|
agentMessageBus: services.agentMessageBus,
|
|
213
213
|
archetypeLoader: services.archetypeLoader,
|
|
214
|
-
wrfcController: services.wrfcController,
|
|
215
214
|
webSearchService: services.webSearchService,
|
|
216
215
|
channelRegistry: services.channelPlugins,
|
|
217
216
|
remoteRunnerRegistry: services.remoteRunnerRegistry,
|
|
@@ -314,7 +313,7 @@ export async function initializeBootstrapCore(
|
|
|
314
313
|
const runtimeSessionIdRef = { value: userSessionId };
|
|
315
314
|
const systemMessageRouterRef: { value: SystemMessageRouter | null } = { value: null };
|
|
316
315
|
const conversationFollowUpRef: { value: ((item: ConversationFollowUpItem) => void) | null } = { value: null };
|
|
317
|
-
const { unsubs: runtimeUnsubs, agentStatusIntervalRef } =
|
|
316
|
+
const { unsubs: runtimeUnsubs, agentStatusIntervalRef } = registerAgentRuntimeEvents({
|
|
318
317
|
runtimeBus,
|
|
319
318
|
domainDispatch,
|
|
320
319
|
getSystemMessageRouter: () => systemMessageRouterRef.value,
|
|
@@ -322,69 +321,10 @@ export async function initializeBootstrapCore(
|
|
|
322
321
|
requestRender,
|
|
323
322
|
configManager,
|
|
324
323
|
agentManager: services.agentManager,
|
|
325
|
-
wrfcController: services.wrfcController,
|
|
326
324
|
});
|
|
327
325
|
|
|
328
|
-
//
|
|
329
|
-
//
|
|
330
|
-
// core WORKFLOW_REVIEW_COMPLETED / WORKFLOW_CHAIN_CREATED messages.
|
|
331
|
-
// The SDK does not surface constraint-specific system messages; the TUI layer
|
|
332
|
-
// adds them here so operators can observe constraint enumeration and violations
|
|
333
|
-
// in the SystemMessagesPanel and main conversation.
|
|
334
|
-
runtimeUnsubs.push(
|
|
335
|
-
runtimeBus.on<Extract<import('@/runtime/index.ts').WorkflowEvent, { type: 'WORKFLOW_CONSTRAINTS_ENUMERATED' }>>(
|
|
336
|
-
'WORKFLOW_CONSTRAINTS_ENUMERATED',
|
|
337
|
-
({ payload }) => {
|
|
338
|
-
const router = systemMessageRouterRef.value;
|
|
339
|
-
if (!router) return;
|
|
340
|
-
const count = payload.constraints.length;
|
|
341
|
-
if (count > 0) {
|
|
342
|
-
router.wrfc(
|
|
343
|
-
`[WRFC] Engineer enumerated ${count} constraint${count !== 1 ? 's' : ''} for chain ${payload.chainId.slice(0, 12)}`,
|
|
344
|
-
'low',
|
|
345
|
-
);
|
|
346
|
-
}
|
|
347
|
-
requestRender();
|
|
348
|
-
},
|
|
349
|
-
),
|
|
350
|
-
);
|
|
351
|
-
runtimeUnsubs.push(
|
|
352
|
-
runtimeBus.on<Extract<import('@/runtime/index.ts').WorkflowEvent, { type: 'WORKFLOW_FIX_ATTEMPTED' }>>(
|
|
353
|
-
'WORKFLOW_FIX_ATTEMPTED',
|
|
354
|
-
({ payload }) => {
|
|
355
|
-
const router = systemMessageRouterRef.value;
|
|
356
|
-
if (!router) return;
|
|
357
|
-
const targetIds = payload.targetConstraintIds;
|
|
358
|
-
if (targetIds && targetIds.length > 0) {
|
|
359
|
-
router.wrfc(
|
|
360
|
-
`[WRFC] Fix #${payload.attempt} targeting ${targetIds.length} constraint${targetIds.length !== 1 ? 's' : ''} on chain ${payload.chainId.slice(0, 12)}`,
|
|
361
|
-
'low',
|
|
362
|
-
);
|
|
363
|
-
requestRender();
|
|
364
|
-
}
|
|
365
|
-
},
|
|
366
|
-
),
|
|
367
|
-
);
|
|
368
|
-
runtimeUnsubs.push(
|
|
369
|
-
runtimeBus.on<Extract<import('@/runtime/index.ts').WorkflowEvent, { type: 'WORKFLOW_REVIEW_COMPLETED' }>>(
|
|
370
|
-
'WORKFLOW_REVIEW_COMPLETED',
|
|
371
|
-
({ payload }) => {
|
|
372
|
-
const router = systemMessageRouterRef.value;
|
|
373
|
-
if (!router) return;
|
|
374
|
-
const unsatisfied = payload.unsatisfiedConstraintIds;
|
|
375
|
-
if (!payload.passed && unsatisfied && unsatisfied.length > 0) {
|
|
376
|
-
router.wrfc(
|
|
377
|
-
`[WRFC] ✗ Chain ${payload.chainId.slice(0, 12)}: ${unsatisfied.length} constraint violation${unsatisfied.length !== 1 ? 's' : ''} forced failure`,
|
|
378
|
-
'high',
|
|
379
|
-
);
|
|
380
|
-
requestRender();
|
|
381
|
-
}
|
|
382
|
-
},
|
|
383
|
-
),
|
|
384
|
-
);
|
|
385
|
-
|
|
386
|
-
// Subscribe to companion main-chat messages received from the daemon's HTTP layer.
|
|
387
|
-
// The daemon emits COMPANION_MESSAGE_RECEIVED on the runtime bus when a companion
|
|
326
|
+
// Subscribe to companion main-chat messages received from the connected host's HTTP layer.
|
|
327
|
+
// The connected host emits COMPANION_MESSAGE_RECEIVED on the runtime bus when a companion
|
|
388
328
|
// POST /api/sessions/:id/messages with kind='message' arrives.
|
|
389
329
|
//
|
|
390
330
|
// bootstrap.ts patches orchestratorHandleUserInputRef.value after the Orchestrator
|