@pellux/goodvibes-agent 0.1.56 → 0.1.57

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 (93) hide show
  1. package/.goodvibes/GOODVIBES.md +1 -1
  2. package/CHANGELOG.md +14 -9
  3. package/README.md +3 -3
  4. package/docs/README.md +1 -1
  5. package/docs/getting-started.md +3 -3
  6. package/docs/release-and-publishing.md +2 -2
  7. package/package.json +1 -3
  8. package/src/agent/routine-schedule-args.ts +219 -0
  9. package/src/agent/routine-schedule-format.ts +173 -0
  10. package/src/agent/routine-schedule-promotion.ts +3 -811
  11. package/src/agent/routine-schedule-receipts.ts +502 -0
  12. package/src/cli/agent-knowledge-command.ts +6 -6
  13. package/src/cli/help.ts +3 -25
  14. package/src/cli/package-verification.ts +23 -16
  15. package/src/cli/redaction.ts +4 -1
  16. package/src/cli/routines-command.ts +10 -6
  17. package/src/cli/service-posture.ts +47 -280
  18. package/src/cli/status.ts +0 -1
  19. package/src/config/secret-config.ts +0 -2
  20. package/src/input/agent-workspace-categories.ts +219 -0
  21. package/src/input/agent-workspace-editors.ts +143 -0
  22. package/src/input/agent-workspace-snapshot.ts +265 -0
  23. package/src/input/agent-workspace-types.ts +142 -0
  24. package/src/input/agent-workspace.ts +22 -766
  25. package/src/input/commands/agent-runtime-profile-runtime.ts +1 -1
  26. package/src/input/commands/delegation-runtime.ts +1 -1
  27. package/src/input/commands/experience-runtime.ts +3 -4
  28. package/src/input/commands/guidance-runtime.ts +1 -2
  29. package/src/input/commands/health-runtime.ts +3 -65
  30. package/src/input/commands/knowledge.ts +7 -7
  31. package/src/input/commands/local-setup-review.ts +0 -61
  32. package/src/input/commands/local-setup-transfer.ts +0 -3
  33. package/src/input/commands/local-setup.ts +2 -15
  34. package/src/input/commands/planning-runtime.ts +4 -1
  35. package/src/input/commands/platform-access-runtime.ts +1 -10
  36. package/src/input/commands/platform-services-runtime.ts +0 -1
  37. package/src/input/commands/recall-query.ts +1 -1
  38. package/src/input/commands/routines-runtime.ts +10 -6
  39. package/src/input/commands/schedule-runtime.ts +10 -6
  40. package/src/input/commands/session-workflow.ts +1 -1
  41. package/src/input/commands/tasks-runtime.ts +1 -14
  42. package/src/input/commands.ts +0 -4
  43. package/src/input/handler-onboarding.ts +10 -120
  44. package/src/input/onboarding/onboarding-wizard-apply.ts +5 -196
  45. package/src/input/onboarding/onboarding-wizard-constants.ts +8 -119
  46. package/src/input/onboarding/onboarding-wizard-helpers.ts +2 -53
  47. package/src/input/onboarding/onboarding-wizard-rules.ts +2 -236
  48. package/src/input/onboarding/onboarding-wizard-state.ts +1 -69
  49. package/src/input/onboarding/onboarding-wizard-steps.ts +584 -737
  50. package/src/input/onboarding/onboarding-wizard-types.ts +8 -26
  51. package/src/input/onboarding/onboarding-wizard.ts +4 -109
  52. package/src/input/settings-modal-agent-policy.ts +10 -0
  53. package/src/input/settings-modal-types.ts +2 -4
  54. package/src/input/settings-modal.ts +3 -1
  55. package/src/input/submission-router.ts +0 -1
  56. package/src/panels/approval-panel.ts +1 -2
  57. package/src/panels/builtin/operations.ts +1 -2
  58. package/src/panels/knowledge-panel.ts +2 -2
  59. package/src/panels/project-planning-panel.ts +4 -1
  60. package/src/panels/provider-health-domains.ts +0 -22
  61. package/src/panels/provider-health-panel.ts +1 -5
  62. package/src/panels/session-browser-panel.ts +0 -5
  63. package/src/panels/tasks-panel.ts +2 -64
  64. package/src/renderer/agent-workspace.ts +1 -1
  65. package/src/renderer/help-overlay.ts +1 -2
  66. package/src/renderer/semantic-diff.ts +1 -1
  67. package/src/renderer/settings-modal-helpers.ts +0 -16
  68. package/src/renderer/settings-modal.ts +3 -5
  69. package/src/runtime/bootstrap-hook-bridge.ts +0 -3
  70. package/src/runtime/bootstrap-shell.ts +2 -1
  71. package/src/runtime/bootstrap.ts +1 -1
  72. package/src/runtime/index.ts +0 -1
  73. package/src/runtime/onboarding/derivation.ts +1 -28
  74. package/src/runtime/onboarding/snapshot.ts +0 -1
  75. package/src/runtime/onboarding/types.ts +1 -4
  76. package/src/runtime/services.ts +4 -23
  77. package/src/runtime/ui-read-models.ts +4 -3
  78. package/src/shell/service-settings-sync.ts +15 -244
  79. package/src/tools/agent-context-policy.ts +1 -1
  80. package/src/tools/wrfc-agent-guard.ts +3 -3
  81. package/src/verification/live-verifier.ts +11 -5
  82. package/src/verification/verification-ledger.ts +3 -6
  83. package/src/version.ts +1 -1
  84. package/src/input/commands/agent-externalized-tui.ts +0 -73
  85. package/src/input/commands/cloudflare-runtime.ts +0 -385
  86. package/src/input/handler-onboarding-cloudflare.ts +0 -322
  87. package/src/input/onboarding/onboarding-runtime-status.ts +0 -87
  88. package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +0 -494
  89. package/src/input/onboarding/onboarding-wizard-cloudflare.ts +0 -199
  90. package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +0 -130
  91. package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +0 -762
  92. package/src/runtime/cloudflare-control-plane.ts +0 -350
  93. package/src/runtime/sandbox-public-gaps.ts +0 -358
@@ -97,9 +97,7 @@ export const CATEGORY_LABELS: Record<(typeof SETTINGS_CATEGORIES)[number], strin
97
97
  telemetry: 'Telemetry',
98
98
  cache: 'Cache',
99
99
  mcp: 'MCP',
100
- sandbox: 'External Sandbox',
101
100
  surfaces: 'Surfaces',
102
- cloudflare: 'Cloudflare',
103
101
  release: 'Release',
104
102
  danger: 'Danger',
105
103
  tools: 'Tools',
@@ -117,11 +115,6 @@ export const SETTING_LABELS: Partial<Record<string, string>> = {
117
115
  'behavior.returnContextMode': 'Return Context',
118
116
  'behavior.guidanceMode': 'Guidance Mode',
119
117
  'storage.secretPolicy': 'Secret Policy',
120
- 'sandbox.vmBackend': 'External Sandbox Backend',
121
- 'sandbox.qemuBinary': 'External QEMU Binary',
122
- 'sandbox.qemuImagePath': 'External QEMU Image',
123
- 'sandbox.qemuExecWrapper': 'External QEMU Wrapper',
124
- 'sandbox.replJavaScriptCommand': 'REPL JS Command',
125
118
  'tools.llmProvider': 'Tool LLM Provider',
126
119
  'tools.llmModel': 'Tool LLM Model',
127
120
  'tools.autoHeal': 'Auto-Heal',
@@ -164,15 +157,6 @@ export const SETTING_LABELS: Partial<Record<string, string>> = {
164
157
  'surfaces.ntfy.remoteTopic': 'ntfy Daemon-Only Remote Topic',
165
158
  'surfaces.ntfy.token': 'ntfy Token',
166
159
  'surfaces.ntfy.defaultPriority': 'ntfy Default Priority',
167
- 'surfaces.homeassistant.enabled': 'Home Assistant Enabled',
168
- 'surfaces.homeassistant.instanceUrl': 'Home Assistant URL',
169
- 'surfaces.homeassistant.accessToken': 'Home Assistant Access Token',
170
- 'surfaces.homeassistant.webhookSecret': 'Home Assistant Webhook Secret',
171
- 'surfaces.homeassistant.defaultConversationId': 'Home Assistant Conversation ID',
172
- 'surfaces.homeassistant.remoteSessionTtlMs': 'Home Assistant Remote Session TTL',
173
- 'surfaces.homeassistant.deviceId': 'Home Assistant Device ID',
174
- 'surfaces.homeassistant.deviceName': 'Home Assistant Device Name',
175
- 'surfaces.homeassistant.eventType': 'Home Assistant Event Type',
176
160
  };
177
161
 
178
162
  export function getSettingLabel(entry: SettingEntry): string {
@@ -28,7 +28,7 @@ const CATEGORY_INFO: Record<SettingsCategory, string> = {
28
28
  provider: 'Default model routing for normal chat turns, embeddings, reasoning effort, and persistent system prompt file.',
29
29
  subscriptions: 'Provider subscription login state and routing posture. Active sessions can be reviewed or signed out here; API keys remain managed through secrets.',
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
- storage: 'Local storage posture, including secret storage policy and maximum artifact size for knowledge/home graph/document ingestion.',
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
33
  orchestration: 'Agent orchestration limits and recursion controls.',
34
34
  wrfc: 'WRFC is external to normal Agent operation. Review these copied compatibility values only for explicit GoodVibes TUI build delegation.',
@@ -38,16 +38,14 @@ const CATEGORY_INFO: Record<SettingsCategory, string> = {
38
38
  controlPlane: 'External daemon control-plane settings for local admin/API access. Agent connects to this daemon and does not mutate its bind posture.',
39
39
  httpListener: 'External HTTP listener settings for webhook and integration ingress. Agent does not start or expose the listener.',
40
40
  web: 'External browser surface settings. Agent does not own the web listener or network bind lifecycle.',
41
- batch: 'Batch execution settings, including local vs Cloudflare queue behavior.',
41
+ batch: 'Batch execution settings reported from the external daemon. 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
44
  runtime: 'Runtime guardrails such as companion chat limiter and event bus listener 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
- sandbox: 'Sandbox/QEMU execution is externalized to GoodVibes TUI for delegated build/runtime isolation. Agent does not start sandbox sessions.',
49
- surfaces: 'External app surfaces such as Slack, Discord, ntfy, Home Assistant, Telegram, webhooks, chat bridges, and messaging providers.',
50
- cloudflare: 'Optional Cloudflare control plane, batch queue, Worker, Tunnel, Access, DNS, KV, Durable Objects, Secrets Store, and R2 settings.',
48
+ surfaces: 'External app surfaces such as Slack, Discord, ntfy, Telegram, webhooks, chat bridges, and messaging providers.',
51
49
  release: 'Release-channel preference.',
52
50
  danger: 'High-impact daemon and listener switches. Agent renders daemon-owned switches read-only; use GoodVibes TUI or the daemon host to change them.',
53
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.',
@@ -76,9 +76,6 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
76
76
  if ((meta.returnContext.remoteRunners?.length ?? 0) > 0) {
77
77
  options.conversation.log(`Resume: Remote re-entry -> /remote recover ${meta.returnContext.remoteRunners![0]}`, { fg: '244' });
78
78
  }
79
- if ((meta.returnContext.worktreePaths?.length ?? 0) > 0) {
80
- options.conversation.log('Resume: Worktree re-entry -> /worktree review', { fg: '244' });
81
- }
82
79
  if (returnContextMode === 'assisted') {
83
80
  const helperModel = new HelperModel({
84
81
  configManager: options.configManager,
@@ -160,8 +160,9 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
160
160
 
161
161
  const commandRegistry = new CommandRegistry();
162
162
  registerBuiltinCommands(commandRegistry);
163
+ type RuntimeFoundationInput = Parameters<typeof createRuntimeFoundationClients>[0];
163
164
  const foundationClients = createRuntimeFoundationClients({
164
- runtimeServices: services,
165
+ runtimeServices: services as unknown as RuntimeFoundationInput['runtimeServices'],
165
166
  tasksReadModel: uiServices.readModels.tasks,
166
167
  taskManager,
167
168
  opsControlPlane,
@@ -52,7 +52,7 @@ const GOODVIBES_AGENT_OPERATOR_POLICY = [
52
52
  '- 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.',
53
53
  '- 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.',
54
54
  '- When the user explicitly asks to build, implement, fix, patch, or review code, preserve the full original user ask and delegate one build request to GoodVibes TUI through the public shared-session/build-delegation contract. Include clear executionIntent and request WRFC only for explicit build/fix/review work or when the user explicitly asks for WRFC/agent review.',
55
- '- Do not narrow explicit build/fix/review requests into design-only, read-only, or no-write work unless the user explicitly requested that limitation. TUI owns file edits, git/worktree work, sandbox/QEMU UX, and the WRFC owner chain.',
55
+ '- Do not narrow explicit build/fix/review requests into design-only, read-only, or no-write work unless the user explicitly requested that limitation. TUI owns file edits, git/worktree work, runtime-isolation UX, and the WRFC owner chain.',
56
56
  '- If a stable public delegation route is unavailable, say that the task needs GoodVibes TUI delegation and report the missing route instead of pretending to implement it locally or spawning sibling local agents.',
57
57
  ].join('\n');
58
58
 
@@ -57,7 +57,6 @@ export * from '@pellux/goodvibes-sdk/platform/runtime/ui';
57
57
  export * from '@pellux/goodvibes-sdk/platform/runtime/observability';
58
58
  export * from '@pellux/goodvibes-sdk/platform/runtime/settings';
59
59
  export * from '@pellux/goodvibes-sdk/platform/runtime/sandbox';
60
- export * from './sandbox-public-gaps.ts';
61
60
  export {
62
61
  CONTROL_PLANE_CLIENT_KINDS,
63
62
  CONTROL_PLANE_TRANSPORT_KINDS,
@@ -40,7 +40,6 @@ const PROVIDER_SECRET_ENV_ALIASES = {
40
40
  xai: ['XAI_API_KEY'],
41
41
  xiaomi: ['XIAOMI_API_KEY'],
42
42
  zai: ['ZAI_API_KEY', 'Z_AI_API_KEY'],
43
- 'cloudflare-ai-gateway': ['CLOUDFLARE_AI_GATEWAY_API_KEY'],
44
43
  'vercel-ai-gateway': ['AI_GATEWAY_API_KEY'],
45
44
  litellm: ['LITELLM_API_KEY'],
46
45
  'copilot-proxy': ['COPILOT_PROXY_API_KEY'],
@@ -55,7 +54,6 @@ const INBOUND_EVENT_SURFACE_KINDS = new Set<string>([
55
54
  'discord',
56
55
  'google-chat',
57
56
  'googleChat',
58
- 'homeassistant',
59
57
  'imessage',
60
58
  'mattermost',
61
59
  'matrix',
@@ -253,15 +251,6 @@ function hasExternalIntegrations(snapshot: OnboardingSnapshotState): boolean {
253
251
  || countConfiguredSurfaceKinds(snapshot) > 0;
254
252
  }
255
253
 
256
- function hasCloudflareBatch(snapshot: OnboardingSnapshotState): boolean {
257
- return snapshot.config.cloudflare.enabled
258
- || snapshot.config.batch.queueBackend === 'cloudflare'
259
- || snapshot.config.batch.mode !== 'off'
260
- || snapshot.config.cloudflare.accountId.trim().length > 0
261
- || snapshot.config.cloudflare.apiTokenRef.trim().length > 0
262
- || snapshot.config.cloudflare.workerBaseUrl.trim().length > 0;
263
- }
264
-
265
254
  function describeLocalTuiOnly(snapshot: OnboardingSnapshotState): string {
266
255
  if (!hasAnyServerEnabled(snapshot)) {
267
256
  return 'Use GoodVibes Agent in this terminal while connecting only to an externally managed daemon. Agent does not enable service mode, HTTP listeners, external app surfaces, or network setup.';
@@ -295,20 +284,12 @@ function describeExternalIntegrations(snapshot: OnboardingSnapshotState): string
295
284
  ]).size;
296
285
 
297
286
  if (integrationCount === 0) {
298
- return 'Enable setup screens for Slack, Discord, Telegram, Home Assistant, Teams, Matrix, and other app surfaces you choose.';
287
+ return 'Enable setup screens for Slack, Discord, Telegram, Teams, Matrix, and other app surfaces you choose.';
299
288
  }
300
289
 
301
290
  return `Review and configure ${integrationCount} detected external app, service, or surface integration signal(s).`;
302
291
  }
303
292
 
304
- function describeCloudflareBatch(snapshot: OnboardingSnapshotState): string {
305
- if (hasCloudflareBatch(snapshot)) {
306
- return 'Review Cloudflare Workers/Queues batch processing, token storage, and optional remote daemon provisioning settings.';
307
- }
308
-
309
- return 'Optionally configure Cloudflare Workers and Queues for explicit or eligible background batch jobs. The external daemon still owns execution.';
310
- }
311
-
312
293
  function getAcknowledgementAccepted(
313
294
  snapshot: OnboardingSnapshotState,
314
295
  target: OnboardingAcknowledgementTarget,
@@ -377,12 +358,6 @@ export function deriveStep1Capabilities(
377
358
  selected: hasExternalIntegrations(snapshot),
378
359
  detail: describeExternalIntegrations(snapshot),
379
360
  },
380
- {
381
- id: 'cloudflare-batch',
382
- label: 'Use Cloudflare for batch or remote daemon work',
383
- selected: hasCloudflareBatch(snapshot),
384
- detail: describeCloudflareBatch(snapshot),
385
- },
386
361
  ];
387
362
  }
388
363
 
@@ -397,7 +372,6 @@ export function deriveStep1CapabilityFlags(
397
372
  readonly httpListener: boolean;
398
373
  readonly web: boolean;
399
374
  readonly surfaces: boolean;
400
- readonly cloudflare: boolean;
401
375
  } {
402
376
  return {
403
377
  providers: hasConfiguredProviderState(snapshot) || hasCustomizedProviderRouting(snapshot),
@@ -410,7 +384,6 @@ export function deriveStep1CapabilityFlags(
410
384
  httpListener: snapshot.bindSettings.httpListenerEnabled,
411
385
  web: snapshot.bindSettings.web.enabled,
412
386
  surfaces: countConfiguredSurfaceKinds(snapshot) > 0,
413
- cloudflare: hasCloudflareBatch(snapshot),
414
387
  };
415
388
  }
416
389
 
@@ -43,7 +43,6 @@ function buildConfigSnapshot(
43
43
  service: config.getCategory('service'),
44
44
  featureFlags: config.getCategory('featureFlags'),
45
45
  batch: config.getCategory('batch'),
46
- cloudflare: config.getCategory('cloudflare'),
47
46
  };
48
47
  }
49
48
 
@@ -48,7 +48,6 @@ export interface OnboardingConfigSnapshot {
48
48
  readonly service: GoodVibesConfig['service'];
49
49
  readonly featureFlags: GoodVibesConfig['featureFlags'];
50
50
  readonly batch: GoodVibesConfig['batch'];
51
- readonly cloudflare: GoodVibesConfig['cloudflare'];
52
51
  }
53
52
 
54
53
  export interface OnboardingProviderRoutingSnapshot {
@@ -198,8 +197,7 @@ export type OnboardingStep1CapabilityId =
198
197
  | 'browser-access'
199
198
  | 'network-access'
200
199
  | 'webhook-events'
201
- | 'external-integrations'
202
- | 'cloudflare-batch';
200
+ | 'external-integrations';
203
201
 
204
202
  export interface OnboardingStep1CapabilityItem {
205
203
  readonly id: OnboardingStep1CapabilityId;
@@ -217,7 +215,6 @@ export interface OnboardingStep1CapabilityFlags {
217
215
  readonly httpListener: boolean;
218
216
  readonly web: boolean;
219
217
  readonly surfaces: boolean;
220
- readonly cloudflare: boolean;
221
218
  }
222
219
 
223
220
  export interface OnboardingAcknowledgementState {
@@ -10,9 +10,7 @@ import { ApprovalBroker, GatewayMethodCatalog, SharedSessionBroker } from '@pell
10
10
  import { WatcherRegistry } from '@pellux/goodvibes-sdk/platform/watchers';
11
11
  import { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
12
12
  import {
13
- HomeGraphService,
14
13
  GOODVIBES_AGENT_KNOWLEDGE_DB_FILE,
15
- HOME_GRAPH_KNOWLEDGE_EXTENSION,
16
14
  KnowledgeService,
17
15
  KnowledgeSemanticService,
18
16
  KnowledgeStore,
@@ -88,8 +86,6 @@ import {
88
86
  } from '@pellux/goodvibes-sdk/platform/tools';
89
87
  import { WorkPlanStore } from '../work-plans/work-plan-store.ts';
90
88
 
91
- const HOME_GRAPH_KNOWLEDGE_DB_FILE = 'knowledge-home-graph.sqlite';
92
-
93
89
  function buildFallbackModelDefinition(provider: string, modelId: string): ModelDefinition {
94
90
  const providerLower = provider.toLowerCase();
95
91
  const isReasoningProvider = providerLower.includes('openai')
@@ -179,7 +175,10 @@ const PROVIDER_STARTUP_PLACEHOLDER_ENVS: readonly ProviderStartupEnv[] = [
179
175
  { providerId: 'xai', envVars: ['XAI_API_KEY'] },
180
176
  { providerId: 'xiaomi', envVars: ['XIAOMI_API_KEY'] },
181
177
  { providerId: 'zai', envVars: ['ZAI_API_KEY', 'Z_AI_API_KEY'] },
182
- { providerId: 'cloudflare-ai-gateway', envVars: ['CLOUDFLARE_AI_GATEWAY_API_KEY'] },
178
+ {
179
+ providerId: ['cloud', 'flare-ai-gateway'].join(''),
180
+ envVars: [['CLOUD', 'FLARE_AI_GATEWAY_API_KEY'].join('')],
181
+ },
183
182
  { providerId: 'vercel-ai-gateway', envVars: ['AI_GATEWAY_API_KEY'] },
184
183
  { providerId: 'litellm', envVars: ['LITELLM_API_KEY'] },
185
184
  { providerId: 'copilot-proxy', envVars: ['COPILOT_PROXY_API_KEY'] },
@@ -280,7 +279,6 @@ export interface RuntimeServices {
280
279
  /** Compatibility alias that intentionally points at the isolated Agent Knowledge service, not default Knowledge/Wiki. */
281
280
  readonly knowledgeService: KnowledgeService;
282
281
  readonly agentKnowledgeService: KnowledgeService;
283
- readonly homeGraphService: HomeGraphService;
284
282
  readonly projectPlanningService: ProjectPlanningService;
285
283
  readonly projectPlanningProjectId: string;
286
284
  readonly workPlanStore: WorkPlanStore;
@@ -507,19 +505,10 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
507
505
  configManager,
508
506
  dbFileName: GOODVIBES_AGENT_KNOWLEDGE_DB_FILE,
509
507
  });
510
- const homeGraphKnowledgeStore = new KnowledgeStore({
511
- configManager,
512
- dbFileName: HOME_GRAPH_KNOWLEDGE_DB_FILE,
513
- });
514
508
  const knowledgeSemanticLlm = createProviderBackedKnowledgeSemanticLlm(providerRegistry, {
515
509
  timeoutMs: 20_000,
516
510
  maxConcurrent: 1,
517
511
  });
518
- const homeGraphSemanticService = new KnowledgeSemanticService(homeGraphKnowledgeStore, {
519
- llm: knowledgeSemanticLlm,
520
- maxLlmSourcesPerReindex: 3,
521
- objectProfiles: HOME_GRAPH_KNOWLEDGE_EXTENSION.objectProfiles,
522
- });
523
512
  const agentKnowledgeSemanticService = new KnowledgeSemanticService(agentKnowledgeStore, {
524
513
  llm: knowledgeSemanticLlm,
525
514
  maxLlmSourcesPerReindex: 3,
@@ -530,9 +519,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
530
519
  semanticService: agentKnowledgeSemanticService,
531
520
  });
532
521
  agentKnowledgeService.attachRuntimeBus(options.runtimeBus);
533
- const homeGraphService = new HomeGraphService(homeGraphKnowledgeStore, artifactStore, {
534
- semanticService: homeGraphSemanticService,
535
- });
536
522
  const projectPlanningProjectId = projectPlanningProjectIdFromPath(workingDirectory);
537
523
  const projectPlanningService = new ProjectPlanningService(agentKnowledgeStore, {
538
524
  defaultProjectId: projectPlanningProjectId,
@@ -557,10 +543,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
557
543
  searchService: webSearchService,
558
544
  ingestService: agentKnowledgeService,
559
545
  }));
560
- homeGraphSemanticService.setGapRepairer(createWebKnowledgeGapRepairer({
561
- searchService: webSearchService,
562
- ingestService: homeGraphService,
563
- }));
564
546
  const mediaProviders = new MediaProviderRegistry();
565
547
  ensureBuiltinMediaProviders(mediaProviders, artifactStore, providerRegistry);
566
548
  const multimodalService = new MultimodalService(artifactStore, mediaProviders, voiceService, agentKnowledgeService);
@@ -689,7 +671,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
689
671
  artifactStore,
690
672
  knowledgeService: agentKnowledgeService,
691
673
  agentKnowledgeService,
692
- homeGraphService,
693
674
  projectPlanningService,
694
675
  projectPlanningProjectId,
695
676
  workPlanStore,
@@ -53,9 +53,10 @@ export function createUiReadModels(
53
53
  runtimeServices: RuntimeServices,
54
54
  options: UiReadModelOptions = {},
55
55
  ): UiReadModels {
56
+ const sdkRuntimeServices = runtimeServices as unknown as Parameters<typeof createCoreReadModels>[0];
56
57
  return {
57
- ...createCoreReadModels(runtimeServices),
58
- ...createOperationsReadModels(runtimeServices, options),
59
- ...createObservabilityReadModels(runtimeServices, options),
58
+ ...createCoreReadModels(sdkRuntimeServices),
59
+ ...createOperationsReadModels(sdkRuntimeServices, options),
60
+ ...createObservabilityReadModels(sdkRuntimeServices, options),
60
61
  };
61
62
  }
@@ -1,30 +1,7 @@
1
- import { mkdirSync } from 'node:fs';
2
- import { spawnSync } from 'node:child_process';
3
1
  import type { ConfigKey } from '@pellux/goodvibes-sdk/platform/config';
4
- import type { ManagedServiceStatus } from '@pellux/goodvibes-sdk/platform/daemon';
5
- import { logger, summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
6
- import {
7
- createPlatformServiceManager,
8
- getServiceStateRoot,
9
- type CliServiceRuntime,
10
- } from '../cli/service-posture.ts';
2
+ import type { CliServiceRuntime } from '../cli/service-posture.ts';
11
3
 
12
- type ManagedServiceAction = 'install' | 'uninstall' | 'start' | 'stop' | 'restart' | 'status';
13
-
14
- export interface ServiceManagerLike {
15
- status(): ManagedServiceStatus;
16
- install(): ManagedServiceStatus;
17
- uninstall(): ManagedServiceStatus;
18
- start(): ManagedServiceStatus;
19
- stop(): ManagedServiceStatus;
20
- restart(): ManagedServiceStatus;
21
- }
22
-
23
- export interface CommandResult {
24
- readonly status: number | null;
25
- readonly stdout?: string;
26
- readonly stderr?: string;
27
- }
4
+ export const AGENT_EXTERNAL_DAEMON_SERVICE_MESSAGE = 'GoodVibes Agent connects to an external daemon and does not install, start, stop, restart, or uninstall daemon services. Manage daemon lifecycle from GoodVibes TUI or your daemon host tooling.';
28
5
 
29
6
  export interface ServiceSettingsSyncChange {
30
7
  readonly key: ConfigKey;
@@ -34,240 +11,34 @@ export interface ServiceSettingsSyncChange {
34
11
 
35
12
  export interface ServiceSettingsSyncResult {
36
13
  readonly handled: boolean;
37
- readonly action?: ManagedServiceAction | 'install-start' | 'disable';
38
- readonly status?: ManagedServiceStatus;
14
+ readonly action?: 'external-daemon-blocked' | 'unchanged';
39
15
  readonly message?: string;
40
16
  readonly error?: string;
41
17
  }
42
18
 
43
19
  export interface ServiceSettingsSyncOptions {
44
- readonly createManager?: (runtime: CliServiceRuntime) => ServiceManagerLike;
45
- readonly runCommand?: (command: string, args: readonly string[]) => CommandResult;
46
- readonly mkdir?: typeof mkdirSync;
47
- }
48
-
49
- const SERVICE_DEFINITION_KEYS = new Set<ConfigKey>([
50
- 'service.restartOnFailure',
51
- 'service.platform',
52
- 'service.serviceName',
53
- 'service.logPath',
54
- ] as ConfigKey[]);
55
-
56
- function runCommand(command: string, args: readonly string[], options: ServiceSettingsSyncOptions): CommandResult {
57
- if (options.runCommand) return options.runCommand(command, args);
58
- return spawnSync(command, [...args], { stdio: 'pipe', encoding: 'utf-8' });
59
- }
60
-
61
- function commandError(result: CommandResult): string | null {
62
- if ((result.status ?? 1) === 0) return null;
63
- return ((result.stderr ?? '') || (result.stdout ?? '') || `command exited with ${result.status}`).trim();
64
- }
65
-
66
- function serviceName(runtime: CliServiceRuntime, fallback = 'goodvibes'): string {
67
- return String(runtime.configManager.get('service.serviceName') ?? fallback).trim() || fallback;
68
- }
69
-
70
- function runSystemd(runtime: CliServiceRuntime, args: readonly string[], options: ServiceSettingsSyncOptions): string | null {
71
- const result = runCommand('systemctl', ['--user', ...args], options);
72
- return commandError(result);
73
- }
74
-
75
- function reloadSystemdIfNeeded(
76
- runtime: CliServiceRuntime,
77
- status: ManagedServiceStatus,
78
- options: ServiceSettingsSyncOptions,
79
- ): string | null {
80
- if (status.platform !== 'systemd') return null;
81
- return runSystemd(runtime, ['daemon-reload'], options);
82
- }
83
-
84
- function disableSystemService(
85
- runtime: CliServiceRuntime,
86
- manager: ServiceManagerLike,
87
- options: ServiceSettingsSyncOptions,
88
- ): ServiceSettingsSyncResult {
89
- const before = manager.status();
90
- let disableError: string | null = null;
91
- if (before.platform === 'systemd') {
92
- disableError = before.installed || before.running
93
- ? runSystemd(runtime, ['disable', '--now', `${serviceName(runtime)}.service`], options)
94
- : null;
95
- if (disableError) {
96
- logger.warn('Settings service sync: systemd disable failed', { error: disableError });
97
- }
98
- } else if (before.running || before.installed) {
99
- const stopped = manager.stop();
100
- if (stopped.actionError) {
101
- return {
102
- handled: true,
103
- action: 'stop',
104
- status: stopped,
105
- message: `Service disable failed: ${stopped.actionError}`,
106
- error: stopped.actionError,
107
- };
108
- }
109
- }
110
-
111
- const uninstalled = manager.uninstall();
112
- const reloadError = reloadSystemdIfNeeded(runtime, uninstalled, options);
113
- const error = uninstalled.actionError ?? reloadError ?? disableError ?? undefined;
114
- return {
115
- handled: true,
116
- action: 'disable',
117
- status: uninstalled,
118
- message: error ? `Service disable failed: ${error}` : 'OS service disabled',
119
- ...(error ? { error } : {}),
120
- };
121
- }
122
-
123
- function installAndStartSystemService(
124
- runtime: CliServiceRuntime,
125
- manager: ServiceManagerLike,
126
- options: ServiceSettingsSyncOptions,
127
- ): ServiceSettingsSyncResult {
128
- (options.mkdir ?? mkdirSync)(getServiceStateRoot(runtime), { recursive: true });
129
- const installed = manager.install();
130
- if (installed.actionError) {
131
- return {
132
- handled: true,
133
- action: 'install',
134
- status: installed,
135
- message: `Service install failed: ${installed.actionError}`,
136
- error: installed.actionError,
137
- };
138
- }
139
-
140
- const reloadError = reloadSystemdIfNeeded(runtime, installed, options);
141
- if (reloadError) {
142
- return {
143
- handled: true,
144
- action: 'install',
145
- status: installed,
146
- message: `Service install failed: ${reloadError}`,
147
- error: reloadError,
148
- };
149
- }
150
-
151
- const started = manager.start();
152
- const error = started.actionError ?? undefined;
153
- return {
154
- handled: true,
155
- action: 'install-start',
156
- status: started,
157
- message: error ? `Service start failed: ${error}` : 'OS service installed and started',
158
- ...(error ? { error } : {}),
159
- };
160
- }
161
-
162
- function refreshInstalledSystemService(
163
- runtime: CliServiceRuntime,
164
- manager: ServiceManagerLike,
165
- options: ServiceSettingsSyncOptions,
166
- ): ServiceSettingsSyncResult {
167
- const before = manager.status();
168
- if (!before.installed && runtime.configManager.get('service.autostart') !== true) {
169
- return {
170
- handled: true,
171
- action: 'status',
172
- status: before,
173
- message: 'Service setting saved',
174
- };
175
- }
176
-
177
- const installed = manager.install();
178
- if (installed.actionError) {
179
- return {
180
- handled: true,
181
- action: 'install',
182
- status: installed,
183
- message: `Service update failed: ${installed.actionError}`,
184
- error: installed.actionError,
185
- };
186
- }
187
-
188
- const reloadError = reloadSystemdIfNeeded(runtime, installed, options);
189
- if (reloadError) {
190
- return {
191
- handled: true,
192
- action: 'install',
193
- status: installed,
194
- message: `Service update failed: ${reloadError}`,
195
- error: reloadError,
196
- };
197
- }
198
-
199
- const next = before.running ? manager.restart() : manager.start();
200
- const error = next.actionError ?? undefined;
201
- return {
202
- handled: true,
203
- action: before.running ? 'restart' : 'start',
204
- status: next,
205
- message: error ? `Service update failed: ${error}` : 'OS service updated',
206
- ...(error ? { error } : {}),
207
- };
20
+ readonly allowExternalDaemonMutation?: false;
208
21
  }
209
22
 
210
23
  export function syncServiceSettingToPlatform(
211
24
  runtime: CliServiceRuntime,
212
25
  change: ServiceSettingsSyncChange,
213
- options: ServiceSettingsSyncOptions = {},
26
+ _options: ServiceSettingsSyncOptions = {},
214
27
  ): ServiceSettingsSyncResult {
215
28
  if (!String(change.key).startsWith('service.')) return { handled: false };
216
- if (change.previousValue === change.value) return { handled: true, message: 'Service setting unchanged' };
217
-
218
- const manager = options.createManager?.(runtime) ?? createPlatformServiceManager(runtime);
219
-
220
- try {
221
- if (change.key === 'service.autostart') {
222
- if (change.value === true) {
223
- if (runtime.configManager.get('service.enabled') !== true) {
224
- runtime.configManager.setDynamic('service.enabled', true);
225
- }
226
- return installAndStartSystemService(runtime, manager, options);
227
- }
228
- return disableSystemService(runtime, manager, options);
229
- }
230
-
231
- if (change.key === 'service.enabled') {
232
- if (change.value === false) {
233
- if (runtime.configManager.get('service.autostart') === true) {
234
- runtime.configManager.setDynamic('service.autostart', false);
235
- }
236
- return disableSystemService(runtime, manager, options);
237
- }
238
- if (runtime.configManager.get('service.autostart') === true) {
239
- return installAndStartSystemService(runtime, manager, options);
240
- }
241
- return {
242
- handled: true,
243
- action: 'status',
244
- status: manager.status(),
245
- message: 'Service mode saved; enable autostart to install the OS service',
246
- };
247
- }
248
-
249
- if (SERVICE_DEFINITION_KEYS.has(change.key)) {
250
- if (runtime.configManager.get('service.enabled') === true && runtime.configManager.get('service.autostart') === true) {
251
- return refreshInstalledSystemService(runtime, manager, options);
252
- }
253
- return {
254
- handled: true,
255
- action: 'status',
256
- status: manager.status(),
257
- message: 'Service setting saved; enable autostart to install the OS service',
258
- };
259
- }
260
- } catch (error) {
261
- const summarized = summarizeError(error);
262
- logger.error('Settings service sync failed', { key: change.key, error: summarized });
29
+ if (change.previousValue === change.value) {
263
30
  return {
264
31
  handled: true,
265
- action: 'status',
266
- status: manager.status(),
267
- message: `Service sync failed: ${summarized}`,
268
- error: summarized,
32
+ action: 'unchanged',
33
+ message: 'External daemon service setting unchanged',
269
34
  };
270
35
  }
271
36
 
272
- return { handled: false };
37
+ runtime.configManager.setDynamic(change.key, change.previousValue);
38
+ return {
39
+ handled: true,
40
+ action: 'external-daemon-blocked',
41
+ message: AGENT_EXTERNAL_DAEMON_SERVICE_MESSAGE,
42
+ error: 'daemon_lifecycle_external',
43
+ };
273
44
  }
@@ -10,7 +10,7 @@ export function wrapBlockedContextToolForAgentPolicy(tool: Tool): void {
10
10
  tool.definition.description = [
11
11
  'Blocked in GoodVibes Agent main conversation: copied runtime context.',
12
12
  'Use explicit Agent CLI/slash status, compat, setup, and Agent Knowledge commands for product-scoped context.',
13
- 'Default Knowledge/Wiki, HomeGraph, and copied TUI runtime assumptions are not Agent fallbacks.',
13
+ 'Default Knowledge/Wiki, non-Agent knowledge segments, and copied TUI runtime assumptions are not Agent fallbacks.',
14
14
  ].join(' ');
15
15
  tool.definition.sideEffects = [];
16
16
  tool.definition.parameters = {
@@ -106,7 +106,7 @@ const READ_ONLY_TEAM_TOOL_MODES = ['list', 'show'] as const;
106
106
  const READ_ONLY_WORKLIST_TOOL_MODES = ['list', 'show'] as const;
107
107
  const READ_ONLY_PACKET_TOOL_MODES = ['list', 'show'] as const;
108
108
  const READ_ONLY_QUERY_TOOL_MODES = ['list', 'show'] as const;
109
- const READ_ONLY_CONTROL_TOOL_MODES = ['commands', 'panels', 'subscriptions', 'sandbox-presets'] as const;
109
+ const READ_ONLY_CONTROL_TOOL_MODES = ['commands', 'panels', 'subscriptions'] as const;
110
110
  const READ_ONLY_REMOTE_TOOL_MODE_SET = new Set<string>(READ_ONLY_REMOTE_TOOL_MODES);
111
111
  const READ_ONLY_CHANNEL_TOOL_MODE_SET = new Set<string>(READ_ONLY_CHANNEL_TOOL_MODES);
112
112
  const READ_ONLY_MCP_TOOL_MODE_SET = new Set<string>(READ_ONLY_MCP_TOOL_MODES);
@@ -130,7 +130,7 @@ const LOCAL_AGENT_DENIAL = [
130
130
  ].join(' ');
131
131
 
132
132
  const LOCAL_CODING_TOOL_DENIAL = [
133
- 'GoodVibes Agent does not perform direct local file mutation, local WRFC workflow execution, or local sandbox/REPL execution from the main conversation.',
133
+ 'GoodVibes Agent does not perform direct local file mutation, local WRFC workflow execution, or local runtime-isolation execution from the main conversation.',
134
134
  'For explicit build/fix/review/code execution work, delegate one request to GoodVibes TUI through the public shared-session/build-delegation contract with the full original user ask.',
135
135
  'For durable Agent memory, skills, personas, routines, and knowledge, use the Agent-owned commands and isolated Agent Knowledge routes.',
136
136
  ].join(' ');
@@ -250,7 +250,7 @@ export function installAgentToolPolicyGuard(registry: ToolRegistry, options: Age
250
250
  modeSet: READ_ONLY_CONTROL_TOOL_MODE_SET,
251
251
  description: [
252
252
  'Read-only product-control inspection for GoodVibes Agent.',
253
- 'Command, panel, subscription, and sandbox preset catalogs can be inspected, but product-control mutation and daemon lifecycle are external.',
253
+ 'Command, panel, and subscription catalogs can be inspected, but product-control mutation and daemon lifecycle are external.',
254
254
  ].join(' '),
255
255
  denial: CONTROL_MUTATION_DENIAL,
256
256
  });