@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
@@ -5,8 +5,14 @@ import { CONFIG_SCHEMA, DEFAULT_CONFIG } from '../../config/index.ts';
5
5
  import {
6
6
  createAgentRuntimeProfile,
7
7
  getAgentRuntimeProfileTemplate,
8
+ getAgentRuntimeProfileSelectionPath,
9
+ readAgentRuntimeProfileSelection,
8
10
  resolveAgentRuntimeProfileHome,
11
+ setAgentRuntimeProfileSelection,
9
12
  } from '../../agent/runtime-profile.ts';
13
+ import { AgentPersonaRegistry, assertNoSecretLikeText } from '../../agent/persona-registry.ts';
14
+ import { AgentRoutineRegistry } from '../../agent/routine-registry.ts';
15
+ import { AgentSkillRegistry } from '../../agent/skill-registry.ts';
10
16
  import type { FeatureFlagConfigKey } from '../surface-feature-flags.ts';
11
17
  import {
12
18
  getOnboardingRuntimeStatePath,
@@ -222,6 +228,65 @@ function validateCreateAgentProfileOperation(
222
228
  if (templateId) getAgentRuntimeProfileTemplate(templateId, deps.shellPaths.homeDirectory);
223
229
  }
224
230
 
231
+ function validateSelectAgentProfileOperation(
232
+ deps: OnboardingApplyDependencies,
233
+ operation: Extract<OnboardingApplyOperation, { kind: 'select-agent-profile' }>,
234
+ ): void {
235
+ const name = operation.name.trim();
236
+ if (name.length === 0) throw new Error('Agent profile name is required.');
237
+ const resolution = resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, name);
238
+ if (!existsSync(resolution.homeDirectory)) {
239
+ throw new Error(`Agent profile does not exist: ${resolution.id}`);
240
+ }
241
+ }
242
+
243
+ function validateCreateLocalPersonaOperation(
244
+ deps: OnboardingApplyDependencies,
245
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-persona' }>,
246
+ ): void {
247
+ const name = operation.name.trim();
248
+ const description = operation.description.trim();
249
+ const body = operation.body.trim();
250
+ if (!name) throw new Error('Persona name is required.');
251
+ if (!description) throw new Error('Persona description is required.');
252
+ if (!body) throw new Error('Persona body is required.');
253
+ assertNoSecretLikeText([name, description, body]);
254
+ const duplicate = AgentPersonaRegistry.fromShellPaths(deps.shellPaths).get(name);
255
+ if (duplicate) throw new Error(`Persona already exists: ${duplicate.id}`);
256
+ }
257
+
258
+ function validateCreateLocalSkillOperation(
259
+ deps: OnboardingApplyDependencies,
260
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-skill' }>,
261
+ ): void {
262
+ const registry = AgentSkillRegistry.fromShellPaths(deps.shellPaths);
263
+ const name = operation.name.trim();
264
+ const description = operation.description.trim();
265
+ const procedure = operation.procedure.trim();
266
+ if (!name) throw new Error('Skill name is required.');
267
+ if (!description) throw new Error('Skill description is required.');
268
+ if (!procedure) throw new Error('Skill procedure is required.');
269
+ assertNoSecretLikeText([name, description, procedure]);
270
+ const duplicate = registry.get(name);
271
+ if (duplicate) throw new Error(`Skill already exists: ${duplicate.id}`);
272
+ }
273
+
274
+ function validateCreateLocalRoutineOperation(
275
+ deps: OnboardingApplyDependencies,
276
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-routine' }>,
277
+ ): void {
278
+ const registry = AgentRoutineRegistry.fromShellPaths(deps.shellPaths);
279
+ const name = operation.name.trim();
280
+ const description = operation.description.trim();
281
+ const steps = operation.steps.trim();
282
+ if (!name) throw new Error('Routine name is required.');
283
+ if (!description) throw new Error('Routine description is required.');
284
+ if (!steps) throw new Error('Routine steps are required.');
285
+ assertNoSecretLikeText([name, description, steps]);
286
+ const duplicate = registry.get(name);
287
+ if (duplicate) throw new Error(`Routine already exists: ${duplicate.id}`);
288
+ }
289
+
225
290
  function applyConfigOperation(
226
291
  deps: OnboardingApplyDependencies,
227
292
  operation: Extract<OnboardingApplyOperation, { kind: 'set-config' }>,
@@ -322,6 +387,26 @@ async function buildRollbackAction(
322
387
  };
323
388
  }
324
389
 
390
+ if (operation.kind === 'select-agent-profile') {
391
+ const path = getAgentRuntimeProfileSelectionPath(deps.shellPaths.homeDirectory);
392
+ return snapshotFileRollback(path);
393
+ }
394
+
395
+ if (operation.kind === 'create-local-persona') {
396
+ const registry = AgentPersonaRegistry.fromShellPaths(deps.shellPaths);
397
+ return snapshotFileRollback(registry.snapshot().path);
398
+ }
399
+
400
+ if (operation.kind === 'create-local-skill') {
401
+ const registry = AgentSkillRegistry.fromShellPaths(deps.shellPaths);
402
+ return snapshotFileRollback(registry.snapshot().path);
403
+ }
404
+
405
+ if (operation.kind === 'create-local-routine') {
406
+ const registry = AgentRoutineRegistry.fromShellPaths(deps.shellPaths);
407
+ return snapshotFileRollback(registry.snapshot().path);
408
+ }
409
+
325
410
  const neverOperation: never = operation;
326
411
  throw new Error(`Unsupported onboarding operation: ${JSON.stringify(neverOperation)}`);
327
412
  }
@@ -364,6 +449,73 @@ function applyCreateAgentProfileOperation(
364
449
  };
365
450
  }
366
451
 
452
+ function applySelectAgentProfileOperation(
453
+ deps: OnboardingApplyDependencies,
454
+ operation: Extract<OnboardingApplyOperation, { kind: 'select-agent-profile' }>,
455
+ ): OnboardingAppliedOperation {
456
+ validateSelectAgentProfileOperation(deps, operation);
457
+ const selection = setAgentRuntimeProfileSelection(deps.shellPaths.homeDirectory, operation.name);
458
+ return {
459
+ kind: operation.kind,
460
+ summary: `Selected Agent profile ${selection.id} for future launches.`,
461
+ };
462
+ }
463
+
464
+ function applyCreateLocalPersonaOperation(
465
+ deps: OnboardingApplyDependencies,
466
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-persona' }>,
467
+ ): OnboardingAppliedOperation {
468
+ const registry = AgentPersonaRegistry.fromShellPaths(deps.shellPaths);
469
+ const persona = registry.create({
470
+ name: operation.name,
471
+ description: operation.description,
472
+ body: operation.body,
473
+ source: 'user',
474
+ provenance: 'onboarding',
475
+ });
476
+ if (operation.activate !== false) registry.setActive(persona.id);
477
+ return {
478
+ kind: operation.kind,
479
+ summary: `Created local Agent persona ${persona.id}.`,
480
+ };
481
+ }
482
+
483
+ function applyCreateLocalSkillOperation(
484
+ deps: OnboardingApplyDependencies,
485
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-skill' }>,
486
+ ): OnboardingAppliedOperation {
487
+ const skill = AgentSkillRegistry.fromShellPaths(deps.shellPaths).create({
488
+ name: operation.name,
489
+ description: operation.description,
490
+ procedure: operation.procedure,
491
+ enabled: operation.enabled !== false,
492
+ source: 'user',
493
+ provenance: 'onboarding',
494
+ });
495
+ return {
496
+ kind: operation.kind,
497
+ summary: `Created local Agent skill ${skill.id}.`,
498
+ };
499
+ }
500
+
501
+ function applyCreateLocalRoutineOperation(
502
+ deps: OnboardingApplyDependencies,
503
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-routine' }>,
504
+ ): OnboardingAppliedOperation {
505
+ const routine = AgentRoutineRegistry.fromShellPaths(deps.shellPaths).create({
506
+ name: operation.name,
507
+ description: operation.description,
508
+ steps: operation.steps,
509
+ enabled: operation.enabled !== false,
510
+ source: 'user',
511
+ provenance: 'onboarding',
512
+ });
513
+ return {
514
+ kind: operation.kind,
515
+ summary: `Created local Agent routine ${routine.id}.`,
516
+ };
517
+ }
518
+
367
519
  function orderApplyOperations(
368
520
  operations: readonly OnboardingApplyOperation[],
369
521
  ): readonly OnboardingApplyOperation[] {
@@ -376,6 +528,12 @@ function orderApplyOperations(
376
528
  operation.kind === 'set-config' && operation.key !== 'storage.secretPolicy'
377
529
  ));
378
530
  const agentProfileOperations = operations.filter((operation) => operation.kind === 'create-agent-profile');
531
+ const agentProfileSelectionOperations = operations.filter((operation) => operation.kind === 'select-agent-profile');
532
+ const localBehaviorOperations = operations.filter((operation) => (
533
+ operation.kind === 'create-local-persona'
534
+ || operation.kind === 'create-local-skill'
535
+ || operation.kind === 'create-local-routine'
536
+ ));
379
537
  const finalOperations = operations.filter((operation) => (
380
538
  operation.kind === 'acknowledge'
381
539
  ));
@@ -386,6 +544,8 @@ function orderApplyOperations(
386
544
  ...secretOperations,
387
545
  ...configOperations,
388
546
  ...agentProfileOperations,
547
+ ...agentProfileSelectionOperations,
548
+ ...localBehaviorOperations,
389
549
  ...finalOperations,
390
550
  ];
391
551
  }
@@ -427,6 +587,31 @@ function prevalidateApplyRequest(
427
587
  continue;
428
588
  }
429
589
 
590
+ if (operation.kind === 'select-agent-profile') {
591
+ const createdEarlier = orderedOperations.some((candidate) => (
592
+ candidate.kind === 'create-agent-profile'
593
+ && resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, candidate.name).id
594
+ === resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, operation.name).id
595
+ ));
596
+ if (!createdEarlier) validateSelectAgentProfileOperation(deps, operation);
597
+ continue;
598
+ }
599
+
600
+ if (operation.kind === 'create-local-persona') {
601
+ validateCreateLocalPersonaOperation(deps, operation);
602
+ continue;
603
+ }
604
+
605
+ if (operation.kind === 'create-local-skill') {
606
+ validateCreateLocalSkillOperation(deps, operation);
607
+ continue;
608
+ }
609
+
610
+ if (operation.kind === 'create-local-routine') {
611
+ validateCreateLocalRoutineOperation(deps, operation);
612
+ continue;
613
+ }
614
+
430
615
  const neverOperation: never = operation;
431
616
  throw new Error(`Unsupported onboarding operation: ${JSON.stringify(neverOperation)}`);
432
617
  } catch (error) {
@@ -446,6 +631,10 @@ function getVerificationFailureKind(itemId: string): OnboardingApplyOperation['k
446
631
  if (itemId.startsWith('auth:')) return 'ensure-auth-user';
447
632
  if (itemId.startsWith('acknowledge:')) return 'acknowledge';
448
633
  if (itemId.startsWith('agent-profile:')) return 'create-agent-profile';
634
+ if (itemId.startsWith('selected-agent-profile:')) return 'select-agent-profile';
635
+ if (itemId.startsWith('local-persona:')) return 'create-local-persona';
636
+ if (itemId.startsWith('local-skill:')) return 'create-local-skill';
637
+ if (itemId.startsWith('local-routine:')) return 'create-local-routine';
449
638
  return 'set-config';
450
639
  }
451
640
 
@@ -502,6 +691,30 @@ export async function applyOnboardingRequest(
502
691
  continue;
503
692
  }
504
693
 
694
+ if (operation.kind === 'select-agent-profile') {
695
+ applied.push(applySelectAgentProfileOperation(deps, operation));
696
+ rollbacks.push(rollback);
697
+ continue;
698
+ }
699
+
700
+ if (operation.kind === 'create-local-persona') {
701
+ applied.push(applyCreateLocalPersonaOperation(deps, operation));
702
+ rollbacks.push(rollback);
703
+ continue;
704
+ }
705
+
706
+ if (operation.kind === 'create-local-skill') {
707
+ applied.push(applyCreateLocalSkillOperation(deps, operation));
708
+ rollbacks.push(rollback);
709
+ continue;
710
+ }
711
+
712
+ if (operation.kind === 'create-local-routine') {
713
+ applied.push(applyCreateLocalRoutineOperation(deps, operation));
714
+ rollbacks.push(rollback);
715
+ continue;
716
+ }
717
+
505
718
  const neverOperation: never = operation;
506
719
  throw new Error(`Unsupported onboarding operation: ${JSON.stringify(neverOperation)}`);
507
720
  } catch (error) {
@@ -211,7 +211,8 @@ function hasExternalIntegrations(snapshot: OnboardingSnapshotState): boolean {
211
211
  function hasLocalBehaviorCustomization(snapshot: OnboardingSnapshotState): boolean {
212
212
  return hasCustomizedWorkspaceDefaults(snapshot)
213
213
  || countPermissionToolOverrides(snapshot) > 0
214
- || snapshot.runtimeDefaults.secretStoragePolicy !== DEFAULT_CONFIG.storage.secretPolicy;
214
+ || snapshot.runtimeDefaults.secretStoragePolicy !== DEFAULT_CONFIG.storage.secretPolicy
215
+ || countDiscoveredLocalBehavior(snapshot) > 0;
215
216
  }
216
217
 
217
218
  function hasCommunicationChannelSignals(snapshot: OnboardingSnapshotState): boolean {
@@ -223,7 +224,7 @@ function hasAutomationReviewSignals(snapshot: OnboardingSnapshotState): boolean
223
224
  }
224
225
 
225
226
  function describeOperatorTerminal(): string {
226
- return 'Use GoodVibes Agent as the terminal operator while connecting to existing GoodVibes services. Agent setup does not create new entrypoints.';
227
+ return 'Use GoodVibes Agent as the terminal operator while connecting to an existing GoodVibes host. Agent setup does not create new entrypoints.';
227
228
  }
228
229
 
229
230
  function describeProviderAccess(snapshot: OnboardingSnapshotState): string {
@@ -240,6 +241,18 @@ function describeAgentKnowledge(): string {
240
241
  }
241
242
 
242
243
  function describeLocalBehavior(snapshot: OnboardingSnapshotState): string {
244
+ const discoveredCount = countDiscoveredLocalBehavior(snapshot);
245
+ if (discoveredCount > 0) {
246
+ const discovery = snapshot.localBehaviorDiscovery;
247
+ const samples = [
248
+ ...discovery.personas.names,
249
+ ...discovery.skills.names,
250
+ ...discovery.routines.names,
251
+ ].slice(0, 4);
252
+ const sampleText = samples.length > 0 ? ` Found: ${samples.join(', ')}.` : '';
253
+ return `Import ${discoveredCount} discovered Agent persona/skill/routine file(s) from local Agent folders before creating blank behavior.${sampleText}`;
254
+ }
255
+
243
256
  if (!hasLocalBehaviorCustomization(snapshot)) {
244
257
  return 'Configure local memory, routines, skills, personas, permissions, and secret handling before the Agent starts doing useful work.';
245
258
  }
@@ -247,6 +260,12 @@ function describeLocalBehavior(snapshot: OnboardingSnapshotState): string {
247
260
  return 'Review existing local behavior, permission, display, or secret-handling choices before applying Agent setup.';
248
261
  }
249
262
 
263
+ function countDiscoveredLocalBehavior(snapshot: OnboardingSnapshotState): number {
264
+ return snapshot.localBehaviorDiscovery.personas.count
265
+ + snapshot.localBehaviorDiscovery.skills.count
266
+ + snapshot.localBehaviorDiscovery.routines.count;
267
+ }
268
+
250
269
  function describeCommunicationChannels(snapshot: OnboardingSnapshotState): string {
251
270
  const integrationCount = new Set<string>([
252
271
  ...getExternalIntegrationServiceIds(snapshot),
@@ -439,23 +458,23 @@ export function deriveReopenEditAcknowledgementState(
439
458
  snapshot,
440
459
  'auth',
441
460
  'bootstrap-credential',
442
- 'A connected-service bootstrap credential signal is still visible to Agent.',
461
+ 'A connected-host bootstrap credential signal is still visible to Agent.',
443
462
  )
444
463
  : authSessionCount > 0
445
464
  ? buildRequiredAcknowledgement(
446
465
  snapshot,
447
466
  'auth',
448
467
  'active-sessions',
449
- `${authSessionCount} connected-service auth session signal(s) are currently visible.`,
468
+ `${authSessionCount} connected-host auth session signal(s) are currently visible.`,
450
469
  )
451
470
  : authUserCount > 0
452
471
  ? buildRequiredAcknowledgement(
453
472
  snapshot,
454
473
  'auth',
455
474
  'auth-state',
456
- `${authUserCount} connected-service auth user signal(s) are already visible.`,
475
+ `${authUserCount} connected-host auth user signal(s) are already visible.`,
457
476
  )
458
- : buildNotNeededAcknowledgement(snapshot, 'auth', 'No connected-service auth signal needs confirmation.');
477
+ : buildNotNeededAcknowledgement(snapshot, 'auth', 'No connected-host auth signal needs confirmation.');
459
478
 
460
479
  return {
461
480
  providers,
@@ -1,6 +1,7 @@
1
1
  import type { SecretStorageReview } from '../../config/secrets.ts';
2
2
  import { getProviderIdFromModel } from '../../config/provider-model.ts';
3
3
  import type { LocalAuthSnapshot } from '@pellux/goodvibes-sdk/platform/security';
4
+ import { summarizeAgentBehaviorDiscovery } from '../../agent/behavior-discovery-summary.ts';
4
5
  import { readOnboardingRuntimeState } from './state.ts';
5
6
  import type {
6
7
  OnboardingAcknowledgementSnapshot,
@@ -98,7 +99,7 @@ async function buildServicesSnapshot(
98
99
  },
99
100
  issues: [
100
101
  {
101
- area: 'services',
102
+ area: 'host',
102
103
  message: error instanceof Error ? error.message : String(error),
103
104
  },
104
105
  ],
@@ -145,7 +146,7 @@ async function buildServicesSnapshot(
145
146
  hasAppToken: false,
146
147
  } satisfies OnboardingServiceState,
147
148
  issue: {
148
- area: 'services',
149
+ area: 'host',
149
150
  message: `${name}: ${error instanceof Error ? error.message : String(error)}`,
150
151
  } satisfies OnboardingSnapshotCollectionIssue,
151
152
  };
@@ -400,6 +401,7 @@ export async function collectOnboardingSnapshot(
400
401
  records: sortSurfaceRecords(surfaceResult.value),
401
402
  },
402
403
  providerAccounts: providerAccountsResult.value,
404
+ localBehaviorDiscovery: summarizeAgentBehaviorDiscovery(deps.shellPaths),
403
405
  collectionIssues,
404
406
  };
405
407
  }
@@ -8,6 +8,7 @@ import type {
8
8
  ServiceInspectionQuery,
9
9
  SubscriptionAccessQuery,
10
10
  } from '../ui-service-queries.ts';
11
+ import type { AgentBehaviorDiscoverySnapshot } from '../../agent/behavior-discovery-summary.ts';
11
12
 
12
13
  export type OnboardingMode = 'new' | 'edit' | 'reopen';
13
14
 
@@ -161,7 +162,7 @@ export interface OnboardingAcknowledgementSnapshot {
161
162
  }
162
163
 
163
164
  export type OnboardingSnapshotCollectionIssueArea =
164
- | 'services'
165
+ | 'host'
165
166
  | 'subscriptions-active'
166
167
  | 'subscriptions-pending'
167
168
  | 'auth'
@@ -189,6 +190,7 @@ export interface OnboardingSnapshotState {
189
190
  readonly bindSettings: OnboardingBindSettingsSnapshot;
190
191
  readonly surfaces: OnboardingSurfacesSnapshot;
191
192
  readonly providerAccounts: OnboardingProviderAccountsSnapshot | null;
193
+ readonly localBehaviorDiscovery: AgentBehaviorDiscoverySnapshot;
192
194
  readonly collectionIssues: readonly OnboardingSnapshotCollectionIssue[];
193
195
  }
194
196
 
@@ -269,6 +271,31 @@ export type OnboardingApplyOperation =
269
271
  readonly kind: 'create-agent-profile';
270
272
  readonly name: string;
271
273
  readonly templateId?: string;
274
+ }
275
+ | {
276
+ readonly kind: 'select-agent-profile';
277
+ readonly name: string;
278
+ }
279
+ | {
280
+ readonly kind: 'create-local-persona';
281
+ readonly name: string;
282
+ readonly description: string;
283
+ readonly body: string;
284
+ readonly activate?: boolean;
285
+ }
286
+ | {
287
+ readonly kind: 'create-local-skill';
288
+ readonly name: string;
289
+ readonly description: string;
290
+ readonly procedure: string;
291
+ readonly enabled?: boolean;
292
+ }
293
+ | {
294
+ readonly kind: 'create-local-routine';
295
+ readonly name: string;
296
+ readonly description: string;
297
+ readonly steps: string;
298
+ readonly enabled?: boolean;
272
299
  };
273
300
 
274
301
  export interface OnboardingApplyRequest {
@@ -1,7 +1,10 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { isSecretRefInput } from '@pellux/goodvibes-sdk/platform/config';
4
- import { resolveAgentRuntimeProfileHome } from '../../agent/runtime-profile.ts';
4
+ import { AgentPersonaRegistry } from '../../agent/persona-registry.ts';
5
+ import { AgentRoutineRegistry } from '../../agent/routine-registry.ts';
6
+ import { readAgentRuntimeProfileSelection, resolveAgentRuntimeProfileHome } from '../../agent/runtime-profile.ts';
7
+ import { AgentSkillRegistry } from '../../agent/skill-registry.ts';
5
8
  import { readOnboardingRuntimeState } from './state.ts';
6
9
  import type {
7
10
  OnboardingApplyOperation,
@@ -144,6 +147,78 @@ function verifyCreateAgentProfileOperation(
144
147
  };
145
148
  }
146
149
 
150
+ function verifySelectAgentProfileOperation(
151
+ deps: OnboardingVerificationDependencies,
152
+ operation: Extract<OnboardingApplyOperation, { kind: 'select-agent-profile' }>,
153
+ ): OnboardingVerificationItem {
154
+ const resolution = resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, operation.name);
155
+ const selection = readAgentRuntimeProfileSelection(deps.shellPaths.homeDirectory);
156
+ const ok = selection?.id === resolution.id && selection.exists;
157
+ return {
158
+ id: `selected-agent-profile:${resolution.id}`,
159
+ status: ok ? 'pass' : 'fail',
160
+ message: ok
161
+ ? `${resolution.id} Agent profile is selected for future launches.`
162
+ : `${resolution.id} Agent profile is not selected for future launches.`,
163
+ target: resolution.id,
164
+ };
165
+ }
166
+
167
+ function verifyCreateLocalPersonaOperation(
168
+ deps: OnboardingVerificationDependencies,
169
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-persona' }>,
170
+ ): OnboardingVerificationItem {
171
+ const registry = AgentPersonaRegistry.fromShellPaths(deps.shellPaths);
172
+ const persona = registry.get(operation.name);
173
+ const activeOk = operation.activate === false || registry.snapshot().activePersonaId === persona?.id;
174
+ const ok = persona !== null && activeOk;
175
+ const target = persona?.id ?? operation.name.trim();
176
+ return {
177
+ id: `local-persona:${target}`,
178
+ status: ok ? 'pass' : 'fail',
179
+ message: ok
180
+ ? `${target} local Agent persona exists${operation.activate === false ? '' : ' and is active'}.`
181
+ : `${target} local Agent persona was not created${operation.activate === false ? '' : ' or activated'}.`,
182
+ target,
183
+ };
184
+ }
185
+
186
+ function verifyCreateLocalSkillOperation(
187
+ deps: OnboardingVerificationDependencies,
188
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-skill' }>,
189
+ ): OnboardingVerificationItem {
190
+ const skill = AgentSkillRegistry.fromShellPaths(deps.shellPaths).get(operation.name);
191
+ const enabledOk = operation.enabled === false || skill?.enabled === true;
192
+ const ok = skill !== null && enabledOk;
193
+ const target = skill?.id ?? operation.name.trim();
194
+ return {
195
+ id: `local-skill:${target}`,
196
+ status: ok ? 'pass' : 'fail',
197
+ message: ok
198
+ ? `${target} local Agent skill exists${operation.enabled === false ? '' : ' and is enabled'}.`
199
+ : `${target} local Agent skill was not created${operation.enabled === false ? '' : ' or enabled'}.`,
200
+ target,
201
+ };
202
+ }
203
+
204
+ function verifyCreateLocalRoutineOperation(
205
+ deps: OnboardingVerificationDependencies,
206
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-routine' }>,
207
+ ): OnboardingVerificationItem {
208
+ const routine = AgentRoutineRegistry.fromShellPaths(deps.shellPaths).get(operation.name);
209
+ const enabledOk = operation.enabled === false || routine?.enabled === true;
210
+ const ok = routine !== null && enabledOk;
211
+ const target = routine?.id ?? operation.name.trim();
212
+ return {
213
+ id: `local-routine:${target}`,
214
+ status: ok ? 'pass' : 'fail',
215
+ message: ok
216
+ ? `${target} local Agent routine exists${operation.enabled === false ? '' : ' and is enabled'}.`
217
+ : `${target} local Agent routine was not created${operation.enabled === false ? '' : ' or enabled'}.`,
218
+ target,
219
+ };
220
+ }
221
+
147
222
  async function verifyOperation(
148
223
  deps: OnboardingVerificationDependencies,
149
224
  operation: OnboardingApplyOperation,
@@ -152,7 +227,11 @@ async function verifyOperation(
152
227
  if (operation.kind === 'set-secret') return verifySecretOperation(deps, operation);
153
228
  if (operation.kind === 'ensure-auth-user') return verifyAuthOperation(deps, operation);
154
229
  if (operation.kind === 'acknowledge') return verifyAcknowledgementOperation(deps, operation);
155
- return verifyCreateAgentProfileOperation(deps, operation);
230
+ if (operation.kind === 'create-agent-profile') return verifyCreateAgentProfileOperation(deps, operation);
231
+ if (operation.kind === 'select-agent-profile') return verifySelectAgentProfileOperation(deps, operation);
232
+ if (operation.kind === 'create-local-persona') return verifyCreateLocalPersonaOperation(deps, operation);
233
+ if (operation.kind === 'create-local-skill') return verifyCreateLocalSkillOperation(deps, operation);
234
+ return verifyCreateLocalRoutineOperation(deps, operation);
156
235
  }
157
236
 
158
237
  export async function verifyOnboardingRequest(
@@ -4,10 +4,10 @@
4
4
  * Shared helper that enumerates the legacy workspace-scoped `operator-tokens.json`
5
5
  * locations earlier GoodVibes builds may have written. Used by the in-process
6
6
  * bootstrap path so stale-token pruning has a single source of truth for where
7
- * to look. GoodVibes Agent itself does not own daemon startup.
7
+ * to look. GoodVibes Agent itself does not own connected-host startup.
8
8
  *
9
9
  * Adding a new legacy location: append to `workspaceOperatorTokenCandidates` and
10
- * the new path will be inspected on the next daemon boot.
10
+ * the new path will be inspected on the next connected-host boot.
11
11
  */
12
12
 
13
13
  import { join } from 'node:path';
@@ -23,7 +23,7 @@ import { MediaProviderRegistry, ensureBuiltinMediaProviders } from '@pellux/good
23
23
  import { MultimodalService } from '@pellux/goodvibes-sdk/platform/multimodal';
24
24
  import { AgentManager } from '@pellux/goodvibes-sdk/platform/tools';
25
25
  import { AgentMessageBus } from '@pellux/goodvibes-sdk/platform/agents';
26
- import { WrfcController } from '@pellux/goodvibes-sdk/platform/agents';
26
+ import type { WrfcController } from '@pellux/goodvibes-sdk/platform/agents';
27
27
  import { AgentOrchestrator } from '@pellux/goodvibes-sdk/platform/agents';
28
28
  import { ArchetypeLoader } from '@pellux/goodvibes-sdk/platform/agents';
29
29
  import { ProcessManager } from '@pellux/goodvibes-sdk/platform/tools';
@@ -73,7 +73,7 @@ import { IdempotencyStore } from '@/runtime/index.ts';
73
73
  import { OverflowHandler } from '@pellux/goodvibes-sdk/platform/tools';
74
74
  import { ToolLLM } from '@pellux/goodvibes-sdk/platform/config';
75
75
  import { ComponentHealthMonitor } from '@/runtime/index.ts';
76
- import { WorktreeRegistry } from '@/runtime/index.ts';
76
+ import type { WorktreeRegistry } from '@/runtime/index.ts';
77
77
  import { SandboxSessionRegistry } from '@/runtime/index.ts';
78
78
  import { createShellPathService, type ShellPathService } from '@/runtime/index.ts';
79
79
  import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
@@ -101,7 +101,7 @@ function buildFallbackModelDefinition(provider: string, modelId: string): ModelD
101
101
  description: 'Configured model available before the model catalog cache has loaded.',
102
102
  capabilities: {
103
103
  toolCalling: true,
104
- codeEditing: true,
104
+ codeEditing: false,
105
105
  reasoning: isReasoningProvider,
106
106
  multimodal: isReasoningProvider,
107
107
  },
@@ -113,6 +113,24 @@ function buildFallbackModelDefinition(provider: string, modelId: string): ModelD
113
113
  };
114
114
  }
115
115
 
116
+ function createDisabledAgentWorktreeRegistry(): WorktreeRegistry {
117
+ const registry: Pick<WorktreeRegistry, 'list' | 'attach' | 'setState' | 'cleanup'> = {
118
+ async list() {
119
+ return [];
120
+ },
121
+ attach(_path, _target) {
122
+ throw new Error('GoodVibes Agent does not own local worktree attachment. Delegate build, fix, and review work to GoodVibes TUI.');
123
+ },
124
+ setState(_path, _state) {
125
+ throw new Error('GoodVibes Agent does not own local worktree state. Delegate build, fix, and review work to GoodVibes TUI.');
126
+ },
127
+ async cleanup(_path) {
128
+ throw new Error('GoodVibes Agent does not own local worktree cleanup. Delegate build, fix, and review work to GoodVibes TUI.');
129
+ },
130
+ };
131
+ return registry as unknown as WorktreeRegistry;
132
+ }
133
+
116
134
  function ensureConfiguredModelIsRoutable(providerRegistry: ProviderRegistry, configManager: ConfigManager): void {
117
135
  const configuredModel = String(configManager.get('provider.model') ?? '').trim();
118
136
  if (!configuredModel.includes(':')) return;
@@ -335,7 +353,7 @@ export interface RuntimeServices {
335
353
  readonly agentManager: AgentManager;
336
354
  readonly agentMessageBus: AgentMessageBus;
337
355
  readonly agentOrchestrator: AgentOrchestrator;
338
- readonly wrfcController: WrfcController;
356
+ readonly wrfcController: Pick<WrfcController, 'listChains'>;
339
357
  readonly processManager: ProcessManager;
340
358
  readonly modeManager: ModeManager;
341
359
  readonly fileUndoManager: FileUndoManager;
@@ -345,7 +363,7 @@ export interface RuntimeServices {
345
363
  * Agent memory is home/profile-owned and intentionally does not move on workspace swap.
346
364
  * Called by WorkspaceSwapManager after the new directory has been verified.
347
365
  * Stores that require a process restart emit a warn-level log; they continue serving
348
- * the old path until the daemon restarts with the new --working-dir.
366
+ * the old path until the externally owned GoodVibes host restarts with the new --working-dir.
349
367
  */
350
368
  rerootStores(newWorkingDir: string): Promise<void>;
351
369
  }
@@ -443,12 +461,9 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
443
461
  configManager,
444
462
  });
445
463
  agentManager.setRuntimeBus(options.runtimeBus);
446
- const wrfcController = new WrfcController(options.runtimeBus, agentMessageBus, {
447
- agentManager,
448
- configManager,
449
- projectRoot: workingDirectory,
450
- });
451
- agentManager.setWrfcController(wrfcController);
464
+ const wrfcController: Pick<WrfcController, 'listChains'> = {
465
+ listChains: () => [],
466
+ };
452
467
  const hookDispatcher = new HookDispatcher({ toolLLM, projectRoot: workingDirectory }, hookActivityTracker);
453
468
  configManager.attachHookDispatcher(hookDispatcher);
454
469
  const hookWorkbench = createHookWorkbench({
@@ -578,7 +593,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
578
593
  mcpRegistry.setSandboxRuntime(configManager, sandboxSessionRegistry);
579
594
  const tokenAuditor = new ApiTokenAuditor({ managed: false });
580
595
  const componentHealthMonitor = new ComponentHealthMonitor();
581
- const worktreeRegistry = new WorktreeRegistry(workingDirectory);
596
+ const worktreeRegistry = createDisabledAgentWorktreeRegistry();
582
597
  const webhookNotifier = new WebhookNotifier();
583
598
  const replayEngine = new DeterministicReplayEngine(workingDirectory);
584
599
  const providerOptimizer = new ProviderOptimizer(providerRegistry, providerCapabilityRegistry, false);