@pellux/goodvibes-agent 1.2.0 → 1.4.1

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 (85) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/dist/package/{ast-grep-napi.linux-x64-gnu-swtppvy9.node → ast-grep-napi.linux-x64-gnu-mkk8xwww.node} +0 -0
  3. package/dist/package/{ast-grep-napi.linux-x64-musl-ttfcdtap.node → ast-grep-napi.linux-x64-musl-ryqtgdv6.node} +0 -0
  4. package/dist/package/main.js +65740 -57156
  5. package/docs/README.md +3 -3
  6. package/docs/connected-host.md +2 -2
  7. package/docs/getting-started.md +11 -9
  8. package/docs/tools-and-commands.md +12 -10
  9. package/docs/voice-and-live-tts.md +2 -2
  10. package/package.json +1 -1
  11. package/release/release-notes.md +15 -144
  12. package/release/release-readiness.json +36 -36
  13. package/src/agent/competitive-feature-inventory.ts +42 -44
  14. package/src/agent/setup-wizard-artifact-receipts.ts +366 -0
  15. package/src/agent/setup-wizard.ts +267 -24
  16. package/src/cli/tui-startup.ts +2 -2
  17. package/src/input/agent-workspace-activation.ts +2 -2
  18. package/src/input/agent-workspace-categories.ts +2 -2
  19. package/src/input/agent-workspace-onboarding-categories.ts +4 -4
  20. package/src/input/agent-workspace-onboarding-finish.ts +21 -0
  21. package/src/input/agent-workspace-settings.ts +47 -1
  22. package/src/input/agent-workspace-setup-snapshot.ts +17 -6
  23. package/src/input/agent-workspace-setup.ts +20 -26
  24. package/src/input/agent-workspace-snapshot.ts +16 -3
  25. package/src/input/agent-workspace-types.ts +5 -2
  26. package/src/input/agent-workspace.ts +21 -6
  27. package/src/input/handler.ts +67 -5
  28. package/src/input/setup-wizard-live-receipts.ts +76 -0
  29. package/src/renderer/agent-workspace-context-lines.ts +17 -33
  30. package/src/renderer/agent-workspace.ts +434 -21
  31. package/src/runtime/tool-permission-safety.ts +1 -1
  32. package/src/tools/agent-harness-agent-orchestration-policy.ts +75 -0
  33. package/src/tools/agent-harness-agent-orchestration.ts +216 -128
  34. package/src/tools/agent-harness-autonomy-live-records.ts +154 -0
  35. package/src/tools/agent-harness-autonomy-queue-types.ts +1 -1
  36. package/src/tools/agent-harness-autonomy-queue.ts +19 -8
  37. package/src/tools/agent-harness-autonomy-watcher-read-models.ts +509 -0
  38. package/src/tools/agent-harness-background-processes.ts +8 -4
  39. package/src/tools/agent-harness-browser-cockpit-route.ts +188 -34
  40. package/src/tools/agent-harness-browser-control.ts +12 -4
  41. package/src/tools/agent-harness-browser-pwa-read-models.ts +622 -0
  42. package/src/tools/agent-harness-device-live-read-models.ts +366 -0
  43. package/src/tools/agent-harness-execution-posture.ts +3 -0
  44. package/src/tools/agent-harness-interactive-runtime-records.ts +421 -0
  45. package/src/tools/agent-harness-local-model-benchmarks.ts +71 -1
  46. package/src/tools/agent-harness-local-model-endpoints.ts +469 -354
  47. package/src/tools/agent-harness-local-model-smoke.ts +277 -0
  48. package/src/tools/agent-harness-local-model-url.ts +78 -0
  49. package/src/tools/agent-harness-media-posture.ts +27 -12
  50. package/src/tools/agent-harness-memory-external-providers.ts +796 -0
  51. package/src/tools/agent-harness-memory-posture.ts +253 -137
  52. package/src/tools/agent-harness-memory-provider-certification.ts +219 -0
  53. package/src/tools/agent-harness-memory-refinement.ts +340 -0
  54. package/src/tools/agent-harness-mode-catalog.ts +4 -2
  55. package/src/tools/agent-harness-model-provider-health.ts +139 -42
  56. package/src/tools/agent-harness-model-readiness.ts +31 -5
  57. package/src/tools/agent-harness-model-routing-types.ts +61 -0
  58. package/src/tools/agent-harness-model-routing.ts +31 -6
  59. package/src/tools/agent-harness-pairing-posture.ts +30 -9
  60. package/src/tools/agent-harness-personal-ops-certification.ts +116 -0
  61. package/src/tools/agent-harness-personal-ops-lanes.ts +81 -15
  62. package/src/tools/agent-harness-personal-ops-operations.ts +225 -0
  63. package/src/tools/agent-harness-personal-ops-provider-records.ts +358 -0
  64. package/src/tools/agent-harness-personal-ops-provider-task-records.ts +321 -0
  65. package/src/tools/agent-harness-personal-ops-records.ts +176 -224
  66. package/src/tools/agent-harness-personal-ops-types.ts +19 -1
  67. package/src/tools/agent-harness-personal-ops.ts +18 -11
  68. package/src/tools/agent-harness-remote-read-models.ts +541 -0
  69. package/src/tools/agent-harness-research-briefing.ts +26 -7
  70. package/src/tools/agent-harness-research-live-read-models.ts +500 -0
  71. package/src/tools/agent-harness-research-runs.ts +15 -3
  72. package/src/tools/agent-harness-research-workflow.ts +92 -19
  73. package/src/tools/agent-harness-setup-model-helpers.ts +1 -0
  74. package/src/tools/agent-harness-setup-posture.ts +7 -7
  75. package/src/tools/agent-harness-setup-smoke.ts +26 -1
  76. package/src/tools/agent-harness-tool-schema.ts +23 -1
  77. package/src/tools/agent-harness-tool-types.ts +5 -0
  78. package/src/tools/agent-harness-tool.ts +9 -1
  79. package/src/tools/agent-harness-workspace-actions.ts +1 -1
  80. package/src/tools/agent-memory-tool.ts +40 -1
  81. package/src/tools/agent-model-compare-run.ts +13 -0
  82. package/src/tools/agent-research-runner.ts +367 -0
  83. package/src/tools/agent-research-tool.ts +7 -179
  84. package/src/tools/agent-route-planner-candidates-surfaces.ts +1 -1
  85. package/src/version.ts +1 -1
@@ -1,4 +1,5 @@
1
1
  import type { CommandContext } from '../input/command-registry.ts';
2
+ import type { ArtifactDescriptor } from '@pellux/goodvibes-sdk/platform/artifacts';
2
3
  import { buildAgentWorkspaceRuntimeSnapshot } from '../input/agent-workspace-snapshot.ts';
3
4
  import { previewHarnessText } from './agent-harness-text.ts';
4
5
  import type { UiAutomationSnapshot, UiTasksSnapshot } from '../runtime/ui-read-models.ts';
@@ -22,6 +23,10 @@ function formatTimeFragment(label: string, value: number | undefined): string {
22
23
  return formatted ? `${label} ${formatted}` : '';
23
24
  }
24
25
 
26
+ function readString(value: unknown): string {
27
+ return typeof value === 'string' ? value.trim() : '';
28
+ }
29
+
25
30
  const SENSITIVE_TEXT_PATTERNS: readonly [RegExp, string][] = [
26
31
  [/("?\b(?:api[-_]?key|apikey|token|secret|password|passwd|credential|authorization)\b"?\s*:\s*)("[^"]*"|'[^']*'|[^\s,}]+)/gi, '$1"<redacted>"'],
27
32
  [/\b([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTHORIZATION|BEARER)[A-Z0-9_]*)=("[^"]*"|'[^']*'|[^\s]+)/gi, '$1=<redacted>'],
@@ -30,6 +35,20 @@ const SENSITIVE_TEXT_PATTERNS: readonly [RegExp, string][] = [
30
35
  [/(\s--(?:token|password|secret|api-key|api_key)\s+)("[^"]*"|'[^']*'|[^\s]+)/gi, '$1<redacted>'],
31
36
  ];
32
37
 
38
+ const WATCHER_RECEIPT_PURPOSES = new Set([
39
+ 'watcher-receipt',
40
+ 'watcher-run-receipt',
41
+ 'automation-watcher-receipt',
42
+ 'automation-run-history-receipt',
43
+ 'durable-run-history-receipt',
44
+ 'agent-watcher-receipt',
45
+ 'agent-watcher-run-receipt',
46
+ 'connected-host-watcher-receipt',
47
+ 'connected-host-watcher-run-receipt',
48
+ 'connected-host-automation-run-history-receipt',
49
+ 'provider-source-record-receipt',
50
+ ]);
51
+
33
52
  function redactHarnessOutputText(value: string): string {
34
53
  return SENSITIVE_TEXT_PATTERNS.reduce((text, [pattern, replacement]) => text.replace(pattern, replacement), value);
35
54
  }
@@ -45,6 +64,64 @@ function compactUnknown(value: unknown): string {
45
64
  }
46
65
  }
47
66
 
67
+ function artifactMetadata(artifact: ArtifactDescriptor): Readonly<Record<string, unknown>> {
68
+ return artifact.metadata && typeof artifact.metadata === 'object'
69
+ ? artifact.metadata as Readonly<Record<string, unknown>>
70
+ : {};
71
+ }
72
+
73
+ function artifactMetadataString(artifact: ArtifactDescriptor, key: string): string {
74
+ return readString(artifactMetadata(artifact)[key]);
75
+ }
76
+
77
+ function artifactMetadataBoolean(artifact: ArtifactDescriptor, key: string): boolean | null {
78
+ const value = artifactMetadata(artifact)[key];
79
+ if (typeof value === 'boolean') return value;
80
+ if (typeof value === 'string') {
81
+ const normalized = value.trim().toLowerCase();
82
+ if (normalized === 'true') return true;
83
+ if (normalized === 'false') return false;
84
+ }
85
+ return null;
86
+ }
87
+
88
+ function artifactTimestamp(artifact: ArtifactDescriptor): number {
89
+ const explicit = artifactMetadataString(artifact, 'createdAt')
90
+ || artifactMetadataString(artifact, 'recordedAt')
91
+ || artifactMetadataString(artifact, 'completedAt')
92
+ || artifactMetadataString(artifact, 'timestamp');
93
+ if (explicit) {
94
+ const parsed = Date.parse(explicit);
95
+ if (Number.isFinite(parsed)) return parsed;
96
+ }
97
+ return typeof artifact.createdAt === 'number' && Number.isFinite(artifact.createdAt) ? artifact.createdAt : 0;
98
+ }
99
+
100
+ function normalizedReceiptStatus(artifact: ArtifactDescriptor): string {
101
+ const raw = (artifactMetadataString(artifact, 'status')
102
+ || artifactMetadataString(artifact, 'outcome')
103
+ || artifactMetadataString(artifact, 'result')).toLowerCase();
104
+ if (!raw) return 'unknown';
105
+ if (['ok', 'ready', 'success', 'succeeded', 'complete', 'completed', 'delivered', 'captured', 'recorded'].includes(raw)) return 'succeeded';
106
+ if (['queued', 'scheduled', 'running', 'pending', 'in-progress', 'in_progress'].includes(raw)) return raw.replace('_', '-');
107
+ if (['blocked', 'needs-review', 'needs_setup', 'needs-setup'].includes(raw)) return 'blocked';
108
+ if (['fail', 'failed', 'error', 'errored'].includes(raw)) return 'failed';
109
+ return raw;
110
+ }
111
+
112
+ function watcherReceiptArtifacts(context: CommandContext): readonly ArtifactDescriptor[] {
113
+ const store = context.platform.artifactStore;
114
+ if (!store?.list) return [];
115
+ try {
116
+ return store.list(100)
117
+ .filter((artifact) => WATCHER_RECEIPT_PURPOSES.has(artifactMetadataString(artifact, 'purpose')))
118
+ .sort((left, right) => artifactTimestamp(right) - artifactTimestamp(left))
119
+ .slice(0, 20);
120
+ } catch {
121
+ return [];
122
+ }
123
+ }
124
+
48
125
  function formatIntervalMs(value: number): string {
49
126
  if (!Number.isFinite(value) || value <= 0) return `${value}ms`;
50
127
  const units: ReadonlyArray<readonly [number, string]> = [
@@ -462,6 +539,83 @@ export function automationRunLiveRecords(context: CommandContext): readonly Auto
462
539
  });
463
540
  }
464
541
 
542
+ export function watcherReceiptLiveRecords(context: CommandContext): readonly AutonomyQueueLiveRecord[] {
543
+ return watcherReceiptArtifacts(context).map((artifact) => {
544
+ const purpose = artifactMetadataString(artifact, 'purpose');
545
+ const operation = artifactMetadataString(artifact, 'operation')
546
+ || artifactMetadataString(artifact, 'action')
547
+ || artifactMetadataString(artifact, 'event')
548
+ || 'watcher-run';
549
+ const status = normalizedReceiptStatus(artifact);
550
+ const watcherId = artifactMetadataString(artifact, 'watcherId')
551
+ || artifactMetadataString(artifact, 'sourceId')
552
+ || artifactMetadataString(artifact, 'providerSourceId');
553
+ const runId = artifactMetadataString(artifact, 'runId')
554
+ || artifactMetadataString(artifact, 'jobRunId')
555
+ || artifactMetadataString(artifact, 'automationRunId');
556
+ const provider = artifactMetadataString(artifact, 'providerId')
557
+ || artifactMetadataString(artifact, 'provider')
558
+ || artifactMetadataString(artifact, 'sourceProvider');
559
+ const trigger = artifactMetadataString(artifact, 'trigger')
560
+ || artifactMetadataString(artifact, 'triggerKind')
561
+ || artifactMetadataString(artifact, 'eventKind');
562
+ const correlationId = artifactMetadataString(artifact, 'correlationId')
563
+ || artifactMetadataString(artifact, 'turnId')
564
+ || artifactMetadataString(artifact, 'sessionId');
565
+ const redaction = artifactMetadataString(artifact, 'redaction')
566
+ || artifactMetadataString(artifact, 'redactionPolicy')
567
+ || 'metadata-only';
568
+ const failureReason = artifactMetadataString(artifact, 'failureReason')
569
+ || artifactMetadataString(artifact, 'error');
570
+ const sourceTool = artifactMetadataString(artifact, 'sourceTool')
571
+ || artifactMetadataString(artifact, 'qualifiedName');
572
+ const payloadRedacted = artifactMetadataBoolean(artifact, 'payloadRedacted');
573
+ const artifactRoute = `agent_artifacts show artifactId:"${artifact.id}" includeContent:false`;
574
+ const queueRoute = 'autonomy action:"item" queueItemId:"automation-runs" includeParameters:true';
575
+ return {
576
+ id: `watcher-receipt:${artifact.id}`,
577
+ label: `Watcher receipt: ${operation.replace(/[-_]+/g, ' ')}`,
578
+ status,
579
+ phase: trigger || operation,
580
+ updatedAt: formatEpochMs(artifactTimestamp(artifact)),
581
+ summary: [
582
+ `Durable watcher/run receipt ${artifact.id} reports ${operation} ${status}.`,
583
+ `Redaction ${redaction}.`,
584
+ payloadRedacted === true ? 'Payload redacted.' : payloadRedacted === false ? 'Payload redaction not asserted.' : '',
585
+ provider ? `Provider ${provider}.` : '',
586
+ watcherId ? `Watcher ${compactUnknown(watcherId)}.` : '',
587
+ runId ? `Run ${compactUnknown(runId)}.` : '',
588
+ trigger ? `Trigger ${compactUnknown(trigger)}.` : '',
589
+ failureReason ? `Failure ${compactUnknown(failureReason)}.` : '',
590
+ sourceTool ? `Source ${sourceTool}.` : '',
591
+ ].filter(Boolean).join(' '),
592
+ inspectRoute: artifactRoute,
593
+ nextSteps: [
594
+ artifactRoute,
595
+ queueRoute,
596
+ ],
597
+ sourceIds: [
598
+ watcherId,
599
+ runId,
600
+ provider,
601
+ trigger,
602
+ correlationId,
603
+ ].filter((value): value is string => typeof value === 'string' && value.length > 0),
604
+ diagnostics: [
605
+ `purpose ${purpose}`,
606
+ `receipt artifact ${artifact.id}`,
607
+ `redaction ${redaction}`,
608
+ failureReason ? `failure ${compactUnknown(failureReason)}` : '',
609
+ ].filter((value): value is string => value.length > 0),
610
+ ...(failureReason ? { logTail: [compactUnknown(failureReason)] } : {}),
611
+ controls: [
612
+ availableControl('inspect', 'Inspect watcher receipt', 'read-only', artifactRoute),
613
+ availableControl('queue', 'Inspect automation queue', 'read-only', queueRoute),
614
+ ],
615
+ };
616
+ });
617
+ }
618
+
465
619
  export function scheduleLiveRecords(context: CommandContext): readonly AutonomyQueueLiveRecord[] {
466
620
  const snapshot = readSnapshot(context.platform.readModels?.automation);
467
621
  return [...(snapshot?.jobs ?? [])]
@@ -63,7 +63,7 @@ export interface AutonomyQueueLiveRecord {
63
63
  export interface AutonomyQueueRecordOutput {
64
64
  readonly status: 'preview' | 'route-only';
65
65
  readonly route: string;
66
- readonly source: 'runtime-task-result' | 'runtime-task-error' | 'not-published';
66
+ readonly source: 'runtime-task-result' | 'runtime-task-error' | 'host-output-chunk' | 'provider-source-preview' | 'not-published';
67
67
  readonly preview?: string;
68
68
  readonly policy: string;
69
69
  }
@@ -1,7 +1,8 @@
1
1
  import { getOperatorContract } from '@pellux/goodvibes-sdk/contracts';
2
2
  import type { CommandContext } from '../input/command-registry.ts';
3
3
  import { buildAgentWorkspaceRuntimeSnapshot } from '../input/agent-workspace-snapshot.ts';
4
- import { automationRunLiveRecords, approvalLiveRecords, controlAvailable, firstAvailableControlRoute, researchRunLiveRecords, scheduleLiveRecords, taskLiveRecords } from './agent-harness-autonomy-live-records.ts';
4
+ import { automationRunLiveRecords, approvalLiveRecords, controlAvailable, firstAvailableControlRoute, researchRunLiveRecords, scheduleLiveRecords, taskLiveRecords, watcherReceiptLiveRecords } from './agent-harness-autonomy-live-records.ts';
5
+ import { watcherReadModelLiveRecords } from './agent-harness-autonomy-watcher-read-models.ts';
5
6
  import type { AgentHarnessAutonomyQueueArgs, AutonomyQueueItem, AutonomyQueueLiveRecord, AutonomyQueueRecordControl, AutonomyQueueRecordOutput, AutonomyQueueResolution, AutonomyQueueStatus, OperatorContractMethod } from './agent-harness-autonomy-queue-types.ts';
6
7
  export type { AutonomyQueueResolution } from './agent-harness-autonomy-queue-types.ts';
7
8
  import { previewHarnessText } from './agent-harness-text.ts';
@@ -196,7 +197,10 @@ function buildQueueItems(context: CommandContext): readonly AutonomyQueueItem[]
196
197
  const researchRuns = researchRunLiveRecords(snapshot);
197
198
  const taskRecords = taskLiveRecords(context);
198
199
  const approvalRecords = approvalLiveRecords(context);
199
- const automationRecords = automationRunLiveRecords(context);
200
+ const automationReadModelRecords = automationRunLiveRecords(context);
201
+ const watcherReadModelRecords = watcherReadModelLiveRecords(context);
202
+ const watcherReceiptRecords = watcherReceiptLiveRecords(context);
203
+ const automationRecords = [...automationReadModelRecords, ...watcherReadModelRecords, ...watcherReceiptRecords];
200
204
  const scheduleRecords = scheduleLiveRecords(context);
201
205
  const latestResearchRun = researchRuns[0];
202
206
  const taskCancelRoute = firstAvailableControlRoute(taskRecords, 'cancel');
@@ -212,11 +216,12 @@ function buildQueueItems(context: CommandContext): readonly AutonomyQueueItem[]
212
216
  : approvalMethods.length > 0
213
217
  ? 'ready'
214
218
  : 'needs-setup';
215
- const automationStatus: AutonomyQueueStatus = automationRecords.some((record) => record.status === 'failed')
219
+ const automationStatus: AutonomyQueueStatus = automationRecords.some((record) => record.status === 'failed' || record.status === 'blocked')
216
220
  ? 'attention'
217
- : automationRecords.some((record) => record.status === 'queued' || record.status === 'running')
221
+ : automationReadModelRecords.some((record) => record.status === 'queued' || record.status === 'running')
222
+ || watcherReadModelRecords.some((record) => record.status === 'queued' || record.status === 'running')
218
223
  ? 'active'
219
- : automationMethods.length > 0
224
+ : automationMethods.length > 0 || watcherReadModelRecords.length > 0 || watcherReceiptRecords.length > 0
220
225
  ? 'ready'
221
226
  : 'needs-setup';
222
227
  const scheduleStatus: AutonomyQueueStatus = scheduleRecords.some((record) => record.status === 'error')
@@ -345,13 +350,19 @@ function buildQueueItems(context: CommandContext): readonly AutonomyQueueItem[]
345
350
  cancellable: true,
346
351
  count: automationRecords.length > 0 ? automationRecords.length : automationMethods.length,
347
352
  current: automationRecords.length > 0
348
- ? `${automationRecords.length} recent automation run record(s); active, failed, and retryable runs expose exact control routes.`
353
+ ? `${automationReadModelRecords.length} recent automation run record(s), ${watcherReadModelRecords.length} live watcher run/source record(s), ${watcherReceiptRecords.length} durable watcher/run receipt(s); active, failed, and retryable live runs expose exact control routes while receipt records stay read-only.`
349
354
  : `${automationMethods.length} automation daemon method(s) are present; run, pause, resume, cancel, and retry actions are confirmed forms.`,
350
355
  next: automationRecords.some((record) => record.status === 'failed')
351
356
  ? 'Inspect failed automation runs, then retry or leave them alone only through exact confirmed run routes.'
352
- : automationRecords.some((record) => record.status === 'queued' || record.status === 'running')
357
+ : automationReadModelRecords.some((record) => record.status === 'queued' || record.status === 'running')
353
358
  ? 'Inspect active automation runs and cancel only the exact run id the user authorizes.'
354
- : 'Inspect automation posture first. Use exact run/job ids for confirmed run control.',
359
+ : watcherReadModelRecords.some((record) => record.status === 'queued' || record.status === 'running')
360
+ ? 'Inspect live watcher/source records and use exact published watcher controls only for the run id the user authorizes.'
361
+ : watcherReadModelRecords.length > 0
362
+ ? 'Review live watcher/source read models and durable receipts; mutate only through exact confirmed routes published by the host.'
363
+ : watcherReceiptRecords.length > 0
364
+ ? 'Review durable watcher/run receipts, then wait for live SDK/daemon run records before controlling any run.'
365
+ : 'Inspect automation posture first. Use exact run/job ids for confirmed run control.',
355
366
  inspectRoute: 'host action:"methods" query:"automation"',
356
367
  modelRoute: 'workspace action:"actions" categoryId:"automation"',
357
368
  cancelRoute: 'workspace action:"run" actionId:"automation-run-cancel" confirm:true explicitUserRequest:"..."',