@pellux/goodvibes-agent 0.1.114 → 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.
Files changed (168) hide show
  1. package/CHANGELOG.md +41 -650
  2. package/README.md +40 -50
  3. package/dist/package/main.js +38224 -35673
  4. package/docs/README.md +5 -4
  5. package/docs/{connected-services.md → connected-host.md} +18 -10
  6. package/docs/getting-started.md +43 -42
  7. package/docs/release-and-publishing.md +6 -4
  8. package/package.json +3 -3
  9. package/src/agent/behavior-discovery-summary.ts +165 -0
  10. package/src/agent/persona-discovery.ts +1 -3
  11. package/src/agent/persona-registry.ts +5 -3
  12. package/src/agent/reminder-schedule-format.ts +6 -6
  13. package/src/agent/reminder-schedule.ts +1 -1
  14. package/src/agent/routine-registry.ts +43 -4
  15. package/src/agent/routine-schedule-format.ts +6 -6
  16. package/src/agent/routine-schedule-promotion.ts +1 -1
  17. package/src/agent/routine-schedule-receipts.ts +1 -1
  18. package/src/agent/runtime-profile-starters.ts +331 -0
  19. package/src/agent/runtime-profile.ts +228 -330
  20. package/src/agent/skill-registry.ts +190 -13
  21. package/src/cli/agent-knowledge-command.ts +2 -2
  22. package/src/cli/agent-knowledge-format.ts +2 -2
  23. package/src/cli/agent-knowledge-runtime.ts +1 -1
  24. package/src/cli/bundle-command.ts +1 -1
  25. package/src/cli/entrypoint.ts +16 -7
  26. package/src/cli/help.ts +26 -19
  27. package/src/cli/local-library-command.ts +75 -21
  28. package/src/cli/management-commands.ts +7 -6
  29. package/src/cli/management.ts +6 -51
  30. package/src/cli/parser.ts +23 -2
  31. package/src/cli/profiles-command.ts +247 -1
  32. package/src/cli/routines-command.ts +139 -11
  33. package/src/cli/service-posture.ts +11 -11
  34. package/src/cli/status.ts +21 -25
  35. package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
  36. package/src/input/agent-workspace-access-command-editors.ts +170 -0
  37. package/src/input/agent-workspace-activation.ts +2 -1
  38. package/src/input/agent-workspace-basic-command-editor-submission.ts +787 -0
  39. package/src/input/agent-workspace-basic-command-editors.ts +524 -459
  40. package/src/input/agent-workspace-categories.ts +177 -14
  41. package/src/input/agent-workspace-channel-command-editor-submission.ts +49 -0
  42. package/src/input/agent-workspace-channel-command-editors.ts +47 -0
  43. package/src/input/agent-workspace-command-editor.ts +25 -1
  44. package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
  45. package/src/input/agent-workspace-editors.ts +27 -0
  46. package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
  47. package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
  48. package/src/input/agent-workspace-learned-behavior.ts +67 -0
  49. package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
  50. package/src/input/agent-workspace-library-command-editors.ts +35 -0
  51. package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
  52. package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
  53. package/src/input/agent-workspace-memory-command-editors.ts +180 -0
  54. package/src/input/agent-workspace-navigation.ts +45 -0
  55. package/src/input/agent-workspace-notify-editor-submission.ts +107 -0
  56. package/src/input/agent-workspace-operations-command-editor-submission.ts +146 -0
  57. package/src/input/agent-workspace-operations-command-editors.ts +119 -0
  58. package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
  59. package/src/input/agent-workspace-provider-command-editors.ts +93 -0
  60. package/src/input/agent-workspace-requirements.ts +11 -0
  61. package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
  62. package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
  63. package/src/input/agent-workspace-session-command-editors.ts +249 -0
  64. package/src/input/agent-workspace-setup.ts +49 -19
  65. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
  66. package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
  67. package/src/input/agent-workspace-snapshot.ts +56 -8
  68. package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
  69. package/src/input/agent-workspace-task-command-editors.ts +47 -0
  70. package/src/input/agent-workspace-types.ts +124 -0
  71. package/src/input/agent-workspace-voice-media.ts +1 -1
  72. package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
  73. package/src/input/agent-workspace.ts +47 -37
  74. package/src/input/command-registry.ts +1 -1
  75. package/src/input/commands/agent-runtime-profile-runtime.ts +160 -6
  76. package/src/input/commands/agent-skills-runtime.ts +76 -12
  77. package/src/input/commands/agent-workspace-runtime.ts +4 -3
  78. package/src/input/commands/brief-runtime.ts +38 -9
  79. package/src/input/commands/channels-runtime.ts +3 -3
  80. package/src/input/commands/compat-runtime.ts +32 -0
  81. package/src/input/commands/health-runtime.ts +22 -24
  82. package/src/input/commands/knowledge.ts +26 -5
  83. package/src/input/commands/local-provider-runtime.ts +7 -3
  84. package/src/input/commands/local-setup-review.ts +4 -14
  85. package/src/input/commands/mcp-runtime.ts +8 -12
  86. package/src/input/commands/operator-runtime.ts +8 -67
  87. package/src/input/commands/personas-runtime.ts +1 -1
  88. package/src/input/commands/platform-access-runtime.ts +7 -70
  89. package/src/input/commands/policy-dispatch.ts +1 -1
  90. package/src/input/commands/policy.ts +1 -5
  91. package/src/input/commands/product-runtime.ts +2 -2
  92. package/src/input/commands/qrcode-runtime.ts +6 -4
  93. package/src/input/commands/routines-runtime.ts +44 -6
  94. package/src/input/commands/runtime-services.ts +1 -14
  95. package/src/input/commands/security-runtime.ts +3 -8
  96. package/src/input/commands/session-content.ts +1 -1
  97. package/src/input/commands/session-workflow.ts +5 -14
  98. package/src/input/commands/shell-core.ts +8 -2
  99. package/src/input/commands/subscription-runtime.ts +1 -6
  100. package/src/input/commands/support-bundle-runtime.ts +53 -0
  101. package/src/input/commands/tasks-runtime.ts +2 -2
  102. package/src/input/commands.ts +4 -0
  103. package/src/input/feed-context-factory.ts +0 -1
  104. package/src/input/handler-content-actions.ts +0 -25
  105. package/src/input/handler-feed.ts +0 -2
  106. package/src/input/handler-interactions.ts +2 -31
  107. package/src/input/handler-onboarding.ts +29 -12
  108. package/src/input/handler-shortcuts.ts +1 -3
  109. package/src/input/handler.ts +4 -7
  110. package/src/input/keybindings.ts +9 -9
  111. package/src/input/mcp-workspace.ts +90 -26
  112. package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
  113. package/src/input/onboarding/onboarding-wizard-apply.ts +49 -0
  114. package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
  115. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +126 -11
  116. package/src/input/onboarding/onboarding-wizard-steps.ts +15 -8
  117. package/src/input/onboarding/onboarding-wizard-types.ts +1 -0
  118. package/src/input/onboarding/onboarding-wizard.ts +19 -2
  119. package/src/input/profile-picker-modal.ts +2 -2
  120. package/src/input/settings-modal-agent-policy.ts +6 -6
  121. package/src/input/settings-modal-subscriptions.ts +3 -3
  122. package/src/input/settings-modal.ts +14 -14
  123. package/src/main.ts +0 -2
  124. package/src/panels/automation-control-panel.ts +3 -3
  125. package/src/panels/builtin/agent.ts +1 -1
  126. package/src/panels/builtin/operations.ts +2 -2
  127. package/src/panels/builtin/session.ts +26 -18
  128. package/src/panels/builtin/shared.ts +6 -6
  129. package/src/panels/project-planning-panel.ts +1 -1
  130. package/src/panels/provider-health-domains.ts +3 -3
  131. package/src/panels/qr-panel.ts +44 -20
  132. package/src/panels/subscription-panel.ts +3 -3
  133. package/src/panels/system-messages-panel.ts +2 -2
  134. package/src/panels/tasks-panel.ts +4 -4
  135. package/src/planning/project-planning-coordinator.ts +2 -2
  136. package/src/renderer/agent-workspace.ts +52 -5
  137. package/src/renderer/block-actions.ts +1 -3
  138. package/src/renderer/help-overlay.ts +13 -8
  139. package/src/renderer/mcp-workspace.ts +32 -13
  140. package/src/renderer/model-picker-overlay.ts +0 -1
  141. package/src/renderer/model-workspace.ts +0 -2
  142. package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
  143. package/src/renderer/panel-picker-overlay.ts +1 -1
  144. package/src/renderer/profile-picker-modal.ts +2 -2
  145. package/src/renderer/settings-modal-helpers.ts +23 -23
  146. package/src/renderer/settings-modal.ts +18 -18
  147. package/src/renderer/system-message.ts +1 -1
  148. package/src/runtime/agent-runtime-events.ts +129 -0
  149. package/src/runtime/bootstrap-command-parts.ts +3 -2
  150. package/src/runtime/bootstrap-core.ts +4 -64
  151. package/src/runtime/bootstrap-shell.ts +42 -4
  152. package/src/runtime/bootstrap.ts +8 -27
  153. package/src/runtime/connected-host-auth.ts +42 -0
  154. package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
  155. package/src/runtime/index.ts +1 -5
  156. package/src/runtime/onboarding/apply.ts +213 -0
  157. package/src/runtime/onboarding/derivation.ts +25 -6
  158. package/src/runtime/onboarding/snapshot.ts +4 -2
  159. package/src/runtime/onboarding/types.ts +28 -1
  160. package/src/runtime/onboarding/verify.ts +81 -2
  161. package/src/runtime/operator-token-cleanup.ts +2 -2
  162. package/src/runtime/services.ts +27 -12
  163. package/src/shell/service-settings-sync.ts +7 -7
  164. package/src/shell/ui-openers.ts +27 -38
  165. package/src/tools/agent-local-registry-tool.ts +10 -4
  166. package/src/tools/agent-tool-policy-guard.ts +5 -7
  167. package/src/version.ts +1 -1
  168. package/src/cli/package-verification.ts +0 -274
@@ -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
- panelManager.open(panelId, pane);
175
- panelManager.show();
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 } = registerBootstrapRuntimeEvents({
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
- // ── TUI-specific WRFC constraint-propagation event subscriptions (SDK 0.23.0) ──
329
- // These supplement the SDK's registerBootstrapRuntimeEvents which handles the
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
@@ -62,6 +62,43 @@ export interface BootstrapShellOptions {
62
62
  readonly completeModelSelectionSideEffect?: () => void;
63
63
  }
64
64
 
65
+ type PlanningAnswerSubmit = (answer: string) => void;
66
+
67
+ export interface PlanningAnswerSubmitBridgeOptions {
68
+ readonly getSubmitInput: () => PlanningAnswerSubmit | undefined;
69
+ readonly addSystemMessage: (message: string) => void;
70
+ readonly requestRender: () => void;
71
+ readonly defer?: (callback: () => void) => void;
72
+ }
73
+
74
+ export function submitPlanningAnswerWithShellFallback(
75
+ answer: string,
76
+ options: PlanningAnswerSubmitBridgeOptions,
77
+ ): void {
78
+ const submit = options.getSubmitInput();
79
+ if (submit) {
80
+ submit(answer);
81
+ return;
82
+ }
83
+
84
+ const defer = options.defer ?? ((callback) => {
85
+ setTimeout(callback, 0);
86
+ });
87
+ defer(() => {
88
+ const deferredSubmit = options.getSubmitInput();
89
+ if (deferredSubmit) {
90
+ deferredSubmit(answer);
91
+ return;
92
+ }
93
+
94
+ options.addSystemMessage([
95
+ '[Planning] Could not submit the selected answer because the prompt bridge is not ready.',
96
+ `Paste this answer into the prompt to continue planning: ${answer}`,
97
+ ].join('\n'));
98
+ options.requestRender();
99
+ });
100
+ }
101
+
65
102
  export function createBootstrapShell(options: BootstrapShellOptions): BootstrapShellState {
66
103
  const {
67
104
  configManager,
@@ -113,10 +150,11 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
113
150
  resumeSession,
114
151
  requestRender,
115
152
  submitPlanningAnswer: (answer) => {
116
- if (!commandContextRef?.submitInput) {
117
- throw new Error('Planning answer submission is not wired yet.');
118
- }
119
- commandContextRef.submitInput(answer);
153
+ submitPlanningAnswerWithShellFallback(answer, {
154
+ getSubmitInput: () => commandContextRef?.submitInput,
155
+ addSystemMessage: (message) => conversation.addSystemMessage(message),
156
+ requestRender,
157
+ });
120
158
  },
121
159
  dismissPlanning: () => {
122
160
  services.panelManager.close('project-planning');
@@ -10,7 +10,6 @@
10
10
  * - lifecycle.ts: save/shutdown helpers
11
11
  */
12
12
  import { Orchestrator, type OrchestratorUserInputOptions } from '../core/orchestrator.ts';
13
- import { AcpManager } from '@pellux/goodvibes-sdk/platform/acp';
14
13
  import { getTierPromptSupplement, getTierForContextWindow } from '@pellux/goodvibes-sdk/platform/providers';
15
14
  import { logger } from '@pellux/goodvibes-sdk/platform/utils';
16
15
  import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions';
@@ -23,7 +22,6 @@ import type { RuntimeContext, BootstrapOptions } from './context.ts';
23
22
  import { shutdownRuntime, fireSessionStart, saveSession } from '@/runtime/index.ts';
24
23
  import { createTaskManager } from '@/runtime/index.ts';
25
24
  import { OpsControlPlane } from '@/runtime/index.ts';
26
- import { AcpTaskAdapter } from '@/runtime/index.ts';
27
25
  import type { SystemMessageRouter } from '../core/system-message-router.ts';
28
26
  import { emitSessionReady, emitSessionStarted } from '@/runtime/index.ts';
29
27
  import {
@@ -47,8 +45,8 @@ import { buildReviewedMemoryPrompt } from '../agent/memory-prompt.ts';
47
45
 
48
46
  const GOODVIBES_AGENT_OPERATOR_POLICY = [
49
47
  '## GoodVibes Agent Operator Policy',
50
- '- Default to serial, proactive assistant work in the main conversation. Answer, inspect, summarize, remember useful non-secret facts, configure local Agent state, use read-only connected-service/operator routes, and take safe non-destructive actions without spawning local agents or WRFC.',
51
- '- GoodVibes Agent connects to GoodVibes services owned outside this package. Do not start, stop, restart, install, expose, or mutate connected-service network/listener posture from Agent.',
48
+ '- Default to serial, proactive assistant work in the main conversation. Answer, inspect, summarize, remember useful non-secret facts, configure local Agent state, use read-only connected-host/operator routes, and take safe non-destructive actions without spawning local agents or WRFC.',
49
+ '- GoodVibes Agent connects to a GoodVibes host owned outside this package. Do not start, stop, restart, install, expose, or mutate connected-host network/listener posture from Agent.',
52
50
  '- Use the `agent_local_registry` tool when a durable memory, reusable persona, skill, skill bundle, or routine would improve future work. Keep those records local, non-secret, source/provenance tagged, and reviewable. Review memory with a confidence score when it should shape future turns. Starting a routine means applying its steps in this same serial conversation, not creating a background job.',
53
51
  '- WRFC is never the default Agent reasoning path. Do not create local WRFC chains for planning, research, operations, knowledge, memory, configuration, approvals, automation observability, or ordinary assistant work.',
54
52
  '- GoodVibes Agent is not the coding TUI. Do not use the `agent` tool to spawn local Engineer, Reviewer, Tester, Verifier, or batch-spawn roots from Agent.',
@@ -130,7 +128,7 @@ export type BootstrapContext = RuntimeContext & {
130
128
  * 3. Tool registry + agent wiring
131
129
  * 4. Runtime bus subscriptions (WRFC, subagent, hook bridge)
132
130
  * 5. Providers, webhooks, PermissionManager, HookDispatcher
133
- * 6. Orchestrator + AcpManager
131
+ * 6. Orchestrator and Agent-local task read models
134
132
  * 7. MCP auto-connect + workspace/panel manager
135
133
  * 8. Command registry + plugin init + CommandContext
136
134
  * 9. Input handler wiring
@@ -183,7 +181,7 @@ export async function bootstrapRuntime(
183
181
  pluginManager,
184
182
  } = services;
185
183
 
186
- // ── Phase 6: Orchestrator + AcpManager ───────────────────────────────────
184
+ // ── Phase 6: Orchestrator and Agent-local task read models ───────────────
187
185
 
188
186
  // Mutable function refs so main.ts can patch these after constructing the scroll/viewport state.
189
187
  // The orchestrator closes over these refs, so patching them in main.ts takes immediate effect.
@@ -243,17 +241,6 @@ export async function bootstrapRuntime(
243
241
  });
244
242
  conversation.setSessionLineageTracker(services.sessionLineageTracker);
245
243
 
246
- const acpManager = new AcpManager({
247
- requestPermission: (request) => permissionPromptRef.requestPermission(request),
248
- runtimeBus,
249
- hookDispatcher: services.hookDispatcher,
250
- });
251
- const acpTaskAdapter = new AcpTaskAdapter(store);
252
- const ACP_TASK_SYNC_INTERVAL_MS = 1_000;
253
- const acpTaskSyncInterval = setInterval(() => {
254
- acpTaskAdapter.sync(acpManager);
255
- }, ACP_TASK_SYNC_INTERVAL_MS);
256
- bootstrapUnsubs.push(() => clearInterval(acpTaskSyncInterval));
257
244
  const opsTaskManager = createTaskManager(store, runtimeBus, userSessionId);
258
245
  const opsControlPlane = services.featureFlags.isEnabled('operator-control-plane')
259
246
  ? new OpsControlPlane(opsTaskManager, runtimeBus, store, userSessionId)
@@ -334,7 +321,7 @@ export async function bootstrapRuntime(
334
321
  port,
335
322
  baseUrl: formatHostServiceBaseUrl(host, port),
336
323
  reason: service === 'daemon'
337
- ? 'GoodVibes Agent connects to GoodVibes services owned outside this product and does not start or restart them.'
324
+ ? 'GoodVibes Agent connects to a GoodVibes host owned outside this product and does not start or restart them.'
338
325
  : 'GoodVibes Agent does not own listener lifecycle.',
339
326
  };
340
327
  };
@@ -375,7 +362,7 @@ export async function bootstrapRuntime(
375
362
  daemonStatus: createExternalAgentServiceStatus('daemon'),
376
363
  httpListenerStatus: createExternalAgentServiceStatus('httpListener'),
377
364
  };
378
- systemMessageRouter.high('[Startup] GoodVibes Agent does not start or restart connected GoodVibes services. Start them from GoodVibes TUI or the owning host, then refresh status.');
365
+ systemMessageRouter.high('[Startup] GoodVibes Agent does not start or restart the connected GoodVibes host. Start it from GoodVibes TUI or the owning host, then refresh status.');
379
366
  requestRender();
380
367
  return inspectExternalServices();
381
368
  },
@@ -452,8 +439,8 @@ export async function bootstrapRuntime(
452
439
  });
453
440
  bootstrapUnsubs.push(() => mcpAutoReload.stop());
454
441
  if (configManager.get('automation.enabled')) {
455
- logger.warn('Local automation startup is disabled in GoodVibes Agent; use connected-service observability instead.');
456
- systemMessageRouter.low('[Startup] Local automation runners are disabled in GoodVibes Agent; use read-only automation observability or explicit connected-service actions.');
442
+ logger.warn('Local automation startup is disabled in GoodVibes Agent; use connected-host observability instead.');
443
+ systemMessageRouter.low('[Startup] Local automation runners are disabled in GoodVibes Agent; use read-only automation observability or explicit connected-host actions.');
457
444
  }
458
445
 
459
446
  // ── Phase 12: Session:start lifecycle hook ─────────────────────────────
@@ -554,12 +541,6 @@ export async function bootstrapRuntime(
554
541
  },
555
542
  };
556
543
 
557
- // ── Phase 12b: Operator intervention wiring (feature-gated) ──────────────
558
- // Keep service-owned control-plane state internal. GoodVibes Agent does not
559
- // expose the local ops-control panel; operator control is surfaced
560
- // through Agent-owned status, approvals, automation, and delegation flows.
561
- ctx.commandContext.ops.acpManager = acpManager;
562
-
563
544
  // Wire exit from options if provided; otherwise main.ts binds the shell bridge.
564
545
  if (options?.exit) {
565
546
  ctx.commandContext.exit = options.exit;
@@ -0,0 +1,42 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+
4
+ type JsonRecord = Record<string, unknown>;
5
+
6
+ export interface ConnectedHostOperatorToken {
7
+ readonly path: string;
8
+ readonly present: boolean;
9
+ readonly token: string | null;
10
+ readonly error?: string;
11
+ }
12
+
13
+ function isRecord(value: unknown): value is JsonRecord {
14
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
15
+ }
16
+
17
+ export function connectedHostOperatorTokenPath(homeDirectory: string): string {
18
+ return join(homeDirectory, '.goodvibes', 'daemon', 'operator-tokens.json');
19
+ }
20
+
21
+ export function readConnectedHostOperatorToken(homeDirectory: string): ConnectedHostOperatorToken {
22
+ const path = connectedHostOperatorTokenPath(homeDirectory);
23
+ if (!existsSync(path)) return { path, present: false, token: null };
24
+ try {
25
+ const parsed = JSON.parse(readFileSync(path, 'utf-8')) as unknown;
26
+ const token = isRecord(parsed) && typeof parsed.token === 'string' && parsed.token.trim().length > 0
27
+ ? parsed.token
28
+ : null;
29
+ return { path, present: true, token };
30
+ } catch (error) {
31
+ return { path, present: true, token: null, error: error instanceof Error ? error.message : String(error) };
32
+ }
33
+ }
34
+
35
+ export function connectedHostTokenRequiredMessage(path: string): string {
36
+ return [
37
+ 'Connected-host operator token is required.',
38
+ ` token path: ${path}`,
39
+ ' Agent does not create or rotate connected-host auth tokens.',
40
+ ' Start or repair the owning GoodVibes host, then rerun this command.',
41
+ ].join('\n');
42
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Panel resource diagnostics panel data provider.
3
3
  *
4
- * Polls the shared TUI-owned ComponentHealthMonitor and produces PanelResourceSnapshot
4
+ * Polls the shared shell ComponentHealthMonitor and produces PanelResourceSnapshot
5
5
  * values for the diagnostics panel to render.
6
6
  */
7
7
  import type { ComponentHealthMonitor } from '../../perf/panel-health-monitor.ts';
@@ -97,7 +97,6 @@ export const restoreRuntimeModel = bootstrap.restoreRuntimeModel;
97
97
  export const restoreSavedModel = bootstrap.restoreRuntimeModel;
98
98
  export const synchronizeConfiguredServices = bootstrap.synchronizeConfiguredServices;
99
99
  export const syncConfiguredServices = bootstrap.synchronizeConfiguredServices;
100
- export const registerBootstrapRuntimeEvents = bootstrap.registerBootstrapRuntimeEvents;
101
100
  export const registerHostRuntimeEvents = bootstrap.registerHostRuntimeEvents;
102
101
  function agentExternalHostStatus(
103
102
  config: Bootstrap.HostServicesConfig,
@@ -113,7 +112,7 @@ function agentExternalHostStatus(
113
112
  port,
114
113
  baseUrl: `http://${host}:${port}`,
115
114
  reason: service === 'daemon'
116
- ? 'GoodVibes Agent connects to GoodVibes services owned outside this product and does not start or restart them.'
115
+ ? 'GoodVibes Agent connects to a GoodVibes host owned outside this product and does not start or restart them.'
117
116
  : 'GoodVibes Agent does not own listener lifecycle.',
118
117
  };
119
118
  }
@@ -245,7 +244,6 @@ export type RemoteRuntimeEvents = Transport.RemoteRuntimeEvents;
245
244
  export type SerializedRuntimeEnvelope = Transport.SerializedRuntimeEnvelope;
246
245
 
247
246
  // Operations compatibility aliases.
248
- export const AcpTaskAdapter = operations.AcpTaskAdapter;
249
247
  export const OpsControlPlane = operations.OpsControlPlane;
250
248
  export const OpsIllegalActionError = operations.OpsIllegalActionError;
251
249
  export const OpsTargetNotFoundError = operations.OpsTargetNotFoundError;
@@ -436,7 +434,6 @@ export const uninstallEcosystemCatalogEntry = shell.uninstallEcosystemCatalogEnt
436
434
  export const updateInstalledEcosystemEntry = shell.updateInstalledEcosystemEntry;
437
435
  export const upsertEcosystemCatalogEntry = shell.upsertEcosystemCatalogEntry;
438
436
  export const summarizeWorktreeOwnership = shell.summarizeWorktreeOwnership;
439
- export const WorktreeRegistry = shell.WorktreeRegistry;
440
437
  export const listPersistedWorktreeMeta = shell.listPersistedWorktreeMeta;
441
438
  export const getPersistedWorktreeMeta = shell.getPersistedWorktreeMeta;
442
439
  export const reviewWorktreeAttachments = shell.reviewWorktreeAttachments;
@@ -458,7 +455,6 @@ export type WorktreeRegistry = Shell.WorktreeRegistry;
458
455
  export type WorktreeStatusRecord = Shell.WorktreeStatusRecord;
459
456
  export type ManagedWorktreeMeta = Shell.ManagedWorktreeMeta;
460
457
  export type ShellAgentManagerService = Shell.ShellAgentManagerService;
461
- export type ShellAcpManagerService = Shell.ShellAcpManagerService;
462
458
  export type ShellAutomationManagerService = Shell.ShellAutomationManagerService;
463
459
  export type ShellAutomationManagerRuntimeService = Shell.ShellAutomationManagerRuntimeService;
464
460
  export type ShellModeManagerService = Shell.ShellModeManagerService;