@pellux/goodvibes-agent 1.1.7 → 1.3.0

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 (274) hide show
  1. package/CHANGELOG.md +329 -0
  2. package/README.md +46 -30
  3. package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-swtppvy9.node} +0 -0
  4. package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-ttfcdtap.node} +0 -0
  5. package/dist/package/main.js +138903 -91477
  6. package/docs/README.md +14 -7
  7. package/docs/channels-remote-and-api.md +8 -5
  8. package/docs/connected-host.md +14 -12
  9. package/docs/getting-started.md +58 -30
  10. package/docs/knowledge-artifacts-and-multimodal.md +7 -5
  11. package/docs/project-planning.md +2 -2
  12. package/docs/providers-and-routing.md +11 -3
  13. package/docs/tools-and-commands.md +116 -45
  14. package/docs/voice-and-live-tts.md +3 -1
  15. package/package.json +3 -2
  16. package/release/release-notes.md +142 -5
  17. package/release/release-readiness.json +124 -94
  18. package/src/agent/assistant-cockpit.ts +247 -0
  19. package/src/agent/autonomy-schedule-format.ts +96 -0
  20. package/src/agent/autonomy-schedule.ts +514 -0
  21. package/src/agent/channel-delivery-receipts.ts +292 -0
  22. package/src/agent/competitive-feature-inventory.ts +294 -0
  23. package/src/agent/document-registry-types.ts +106 -0
  24. package/src/agent/document-registry.ts +734 -0
  25. package/src/agent/harness-control.ts +2 -2
  26. package/src/agent/memory-prompt.ts +2 -2
  27. package/src/agent/operator-actions.ts +50 -6
  28. package/src/agent/persona-registry.ts +8 -0
  29. package/src/agent/project-context-files.ts +273 -0
  30. package/src/agent/prompt-context-receipts.ts +502 -0
  31. package/src/agent/reminder-schedule-format.ts +16 -2
  32. package/src/agent/research-run-registry.ts +582 -0
  33. package/src/agent/research-source-registry.ts +441 -0
  34. package/src/agent/routine-registry.ts +19 -3
  35. package/src/agent/routine-schedule-format.ts +27 -2
  36. package/src/agent/runtime-profile-starters.ts +7 -0
  37. package/src/agent/runtime-profile.ts +106 -4
  38. package/src/agent/schedule-edit-format.ts +129 -0
  39. package/src/agent/schedule-edit.ts +496 -0
  40. package/src/agent/schedule-next-routes.ts +42 -0
  41. package/src/agent/setup-wizard-artifact-receipts.ts +366 -0
  42. package/src/agent/setup-wizard-checkpoint.ts +140 -0
  43. package/src/agent/setup-wizard.ts +683 -0
  44. package/src/agent/skill-registry-types.ts +102 -0
  45. package/src/agent/skill-registry.ts +81 -107
  46. package/src/agent/vibe-confirmation-routes.ts +62 -0
  47. package/src/agent/vibe-file.ts +285 -0
  48. package/src/cli/agent-knowledge-command.ts +45 -2
  49. package/src/cli/help.ts +3 -0
  50. package/src/cli/profiles-command.ts +25 -11
  51. package/src/config/agent-settings-policy.ts +1 -18
  52. package/src/input/agent-workspace-activation.ts +53 -0
  53. package/src/input/agent-workspace-artifact-browser-editor.ts +494 -0
  54. package/src/input/agent-workspace-artifact-metadata.ts +17 -0
  55. package/src/input/agent-workspace-basic-command-editors.ts +5 -1
  56. package/src/input/agent-workspace-categories.ts +153 -155
  57. package/src/input/agent-workspace-channel-triage.ts +481 -0
  58. package/src/input/agent-workspace-channels.ts +263 -0
  59. package/src/input/agent-workspace-command-editor.ts +152 -0
  60. package/src/input/agent-workspace-context-snapshot.ts +349 -0
  61. package/src/input/agent-workspace-delegation-editor-submission.ts +8 -0
  62. package/src/input/agent-workspace-document-editor.ts +502 -0
  63. package/src/input/agent-workspace-document-ops-editor.ts +523 -0
  64. package/src/input/agent-workspace-host-category.ts +1 -1
  65. package/src/input/agent-workspace-local-library-snapshot.ts +167 -0
  66. package/src/input/agent-workspace-model-compare-editor.ts +376 -0
  67. package/src/input/agent-workspace-model-compare-prompt-submission.ts +552 -0
  68. package/src/input/agent-workspace-model-compare-types.ts +82 -0
  69. package/src/input/agent-workspace-model-compare-utils.ts +35 -0
  70. package/src/input/agent-workspace-onboarding-categories.ts +141 -0
  71. package/src/input/agent-workspace-operations-command-editor-submission.ts +53 -0
  72. package/src/input/agent-workspace-operations-command-editors.ts +22 -0
  73. package/src/input/agent-workspace-research-report-editor.ts +212 -0
  74. package/src/input/agent-workspace-research-run-editor.ts +144 -0
  75. package/src/input/agent-workspace-research-source-editor.ts +167 -0
  76. package/src/input/agent-workspace-review-packet-snapshot.ts +593 -0
  77. package/src/input/agent-workspace-review-packet-utils.ts +265 -0
  78. package/src/input/agent-workspace-settings.ts +313 -30
  79. package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
  80. package/src/input/agent-workspace-setup-snapshot.ts +217 -0
  81. package/src/input/agent-workspace-setup.ts +61 -1
  82. package/src/input/agent-workspace-snapshot.ts +184 -149
  83. package/src/input/agent-workspace-types.ts +287 -2
  84. package/src/input/agent-workspace.ts +23 -1
  85. package/src/input/command-registry.ts +9 -2
  86. package/src/input/commands/agent-runtime-profile-runtime.ts +28 -13
  87. package/src/input/commands/channels-runtime.ts +102 -114
  88. package/src/input/commands/delegation-runtime.ts +87 -24
  89. package/src/input/commands/knowledge-browser-flags.ts +12 -0
  90. package/src/input/commands/knowledge.ts +28 -14
  91. package/src/input/commands/operator-actions-runtime.ts +6 -3
  92. package/src/input/commands/schedule-runtime.ts +71 -14
  93. package/src/input/commands/session-content.ts +2 -2
  94. package/src/input/commands/shell-core.ts +2 -0
  95. package/src/input/commands/vibe-runtime.ts +140 -0
  96. package/src/input/commands.ts +2 -0
  97. package/src/input/connected-host-routes.ts +123 -0
  98. package/src/input/settings-modal-types.ts +14 -0
  99. package/src/input/setup-wizard-live-receipts.ts +76 -0
  100. package/src/main.ts +15 -15
  101. package/src/panels/qr-panel.ts +2 -2
  102. package/src/renderer/agent-workspace-context-lines.ts +701 -0
  103. package/src/renderer/agent-workspace.ts +68 -421
  104. package/src/renderer/settings-modal-helpers.ts +12 -0
  105. package/src/renderer/settings-modal.ts +12 -0
  106. package/src/runtime/bootstrap-command-context.ts +11 -1
  107. package/src/runtime/bootstrap-command-parts.ts +14 -3
  108. package/src/runtime/bootstrap-core.ts +39 -1
  109. package/src/runtime/bootstrap-shell.ts +6 -0
  110. package/src/runtime/bootstrap.ts +113 -30
  111. package/src/runtime/connected-host-auth.ts +3 -2
  112. package/src/runtime/execution-ledger.ts +231 -0
  113. package/src/runtime/services.ts +88 -10
  114. package/src/runtime/tool-permission-safety.ts +199 -5
  115. package/src/shell/session-continuity-hints.ts +39 -0
  116. package/src/tools/agent-artifacts-tool.ts +606 -0
  117. package/src/tools/agent-audit-tool.ts +155 -0
  118. package/src/tools/agent-autonomy-schedule-tool.ts +238 -0
  119. package/src/tools/agent-autonomy-tool.ts +140 -0
  120. package/src/tools/agent-channel-send-tool.ts +24 -2
  121. package/src/tools/agent-channels-tool.ts +140 -0
  122. package/src/tools/agent-computer-tool.ts +168 -0
  123. package/src/tools/agent-context-policy.ts +137 -7
  124. package/src/tools/agent-context-tool.ts +143 -0
  125. package/src/tools/agent-delegation-tool.ts +128 -0
  126. package/src/tools/agent-device-tool.ts +240 -0
  127. package/src/tools/agent-documents-tool.ts +684 -0
  128. package/src/tools/agent-execution-tool.ts +230 -0
  129. package/src/tools/agent-harness-agent-orchestration-policy.ts +75 -0
  130. package/src/tools/agent-harness-agent-orchestration.ts +791 -0
  131. package/src/tools/agent-harness-autonomy-intake.ts +785 -0
  132. package/src/tools/agent-harness-autonomy-live-records.ts +742 -0
  133. package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
  134. package/src/tools/agent-harness-autonomy-queue.ts +571 -0
  135. package/src/tools/agent-harness-autonomy-watcher-read-models.ts +509 -0
  136. package/src/tools/agent-harness-background-processes-types.ts +35 -0
  137. package/src/tools/agent-harness-background-processes.ts +798 -0
  138. package/src/tools/agent-harness-browser-cockpit-route.ts +373 -0
  139. package/src/tools/agent-harness-browser-control.ts +346 -0
  140. package/src/tools/agent-harness-browser-pwa-read-models.ts +622 -0
  141. package/src/tools/agent-harness-channel-metadata.ts +168 -10
  142. package/src/tools/agent-harness-cli-command-policy.ts +110 -0
  143. package/src/tools/agent-harness-command-catalog.ts +4 -2
  144. package/src/tools/agent-harness-command-runner.ts +42 -0
  145. package/src/tools/agent-harness-connected-host-status.ts +7 -4
  146. package/src/tools/agent-harness-delegation-posture.ts +234 -19
  147. package/src/tools/agent-harness-device-live-read-models.ts +366 -0
  148. package/src/tools/agent-harness-document-ops-reviewer-readiness.ts +234 -0
  149. package/src/tools/agent-harness-document-ops-types.ts +72 -0
  150. package/src/tools/agent-harness-document-ops.ts +671 -0
  151. package/src/tools/agent-harness-execution-history.ts +489 -0
  152. package/src/tools/agent-harness-execution-posture.ts +385 -0
  153. package/src/tools/agent-harness-file-recovery.ts +135 -0
  154. package/src/tools/agent-harness-interactive-runtime-records.ts +421 -0
  155. package/src/tools/agent-harness-keybinding-metadata.ts +16 -12
  156. package/src/tools/agent-harness-learning-curator-common.ts +102 -0
  157. package/src/tools/agent-harness-learning-curator-consolidation.ts +295 -0
  158. package/src/tools/agent-harness-learning-curator-proposals.ts +606 -0
  159. package/src/tools/agent-harness-learning-curator-types.ts +151 -0
  160. package/src/tools/agent-harness-learning-curator.ts +417 -0
  161. package/src/tools/agent-harness-local-model-benchmarks.ts +269 -0
  162. package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
  163. package/src/tools/agent-harness-local-model-endpoints.ts +788 -0
  164. package/src/tools/agent-harness-local-model-smoke.ts +277 -0
  165. package/src/tools/agent-harness-local-model-url.ts +78 -0
  166. package/src/tools/agent-harness-media-posture.ts +223 -2
  167. package/src/tools/agent-harness-memory-external-providers.ts +796 -0
  168. package/src/tools/agent-harness-memory-posture.ts +672 -0
  169. package/src/tools/agent-harness-memory-provider-certification.ts +219 -0
  170. package/src/tools/agent-harness-memory-refinement.ts +340 -0
  171. package/src/tools/agent-harness-metadata.ts +100 -168
  172. package/src/tools/agent-harness-mode-catalog.ts +86 -33
  173. package/src/tools/agent-harness-model-catalog.ts +162 -0
  174. package/src/tools/agent-harness-model-provider-health.ts +283 -0
  175. package/src/tools/agent-harness-model-readiness.ts +432 -0
  176. package/src/tools/agent-harness-model-routing-types.ts +327 -0
  177. package/src/tools/agent-harness-model-routing-utils.ts +30 -0
  178. package/src/tools/agent-harness-model-routing.ts +165 -193
  179. package/src/tools/agent-harness-operator-methods.ts +115 -133
  180. package/src/tools/agent-harness-pairing-posture.ts +452 -18
  181. package/src/tools/agent-harness-personal-ops-certification.ts +116 -0
  182. package/src/tools/agent-harness-personal-ops-discovery.ts +533 -0
  183. package/src/tools/agent-harness-personal-ops-intake.ts +385 -0
  184. package/src/tools/agent-harness-personal-ops-lanes.ts +270 -0
  185. package/src/tools/agent-harness-personal-ops-operations.ts +225 -0
  186. package/src/tools/agent-harness-personal-ops-provider-records.ts +358 -0
  187. package/src/tools/agent-harness-personal-ops-provider-task-records.ts +321 -0
  188. package/src/tools/agent-harness-personal-ops-records.ts +684 -0
  189. package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
  190. package/src/tools/agent-harness-personal-ops-types.ts +240 -0
  191. package/src/tools/agent-harness-personal-ops.ts +613 -0
  192. package/src/tools/agent-harness-project-context.ts +144 -0
  193. package/src/tools/agent-harness-prompt-context.ts +589 -0
  194. package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
  195. package/src/tools/agent-harness-release-evidence.ts +9 -7
  196. package/src/tools/agent-harness-release-readiness.ts +9 -7
  197. package/src/tools/agent-harness-remote-read-models.ts +541 -0
  198. package/src/tools/agent-harness-research-briefing.ts +446 -0
  199. package/src/tools/agent-harness-research-live-read-models.ts +500 -0
  200. package/src/tools/agent-harness-research-queue.ts +250 -0
  201. package/src/tools/agent-harness-research-runs.ts +307 -0
  202. package/src/tools/agent-harness-research-workflow.ts +395 -0
  203. package/src/tools/agent-harness-security-posture.ts +2 -2
  204. package/src/tools/agent-harness-service-posture.ts +9 -9
  205. package/src/tools/agent-harness-session-metadata.ts +3 -3
  206. package/src/tools/agent-harness-setup-connected-host.ts +501 -0
  207. package/src/tools/agent-harness-setup-describe.ts +557 -0
  208. package/src/tools/agent-harness-setup-handoffs.ts +502 -0
  209. package/src/tools/agent-harness-setup-model-helpers.ts +102 -0
  210. package/src/tools/agent-harness-setup-plan.ts +253 -0
  211. package/src/tools/agent-harness-setup-posture-types.ts +218 -0
  212. package/src/tools/agent-harness-setup-posture-utils.ts +173 -0
  213. package/src/tools/agent-harness-setup-posture.ts +449 -221
  214. package/src/tools/agent-harness-setup-smoke.ts +533 -0
  215. package/src/tools/agent-harness-sudo-posture.ts +114 -0
  216. package/src/tools/agent-harness-tool-schema.ts +142 -7
  217. package/src/tools/agent-harness-tool-types.ts +83 -0
  218. package/src/tools/agent-harness-tool-utils.ts +43 -0
  219. package/src/tools/agent-harness-tool.ts +319 -370
  220. package/src/tools/agent-harness-ui-surface-metadata.ts +76 -69
  221. package/src/tools/agent-harness-ui-surface-types.ts +46 -0
  222. package/src/tools/agent-harness-vibe-health.ts +105 -0
  223. package/src/tools/agent-harness-workspace-action-runner.ts +149 -0
  224. package/src/tools/agent-harness-workspace-actions.ts +114 -8
  225. package/src/tools/agent-harness-workspace-editor-execution.ts +214 -0
  226. package/src/tools/agent-harness-workspace-editor-runner.ts +755 -0
  227. package/src/tools/agent-host-tool.ts +159 -0
  228. package/src/tools/agent-knowledge-ingest-tool.ts +34 -1
  229. package/src/tools/agent-learning-consolidation-core.ts +327 -0
  230. package/src/tools/agent-learning-consolidation-tool.ts +758 -0
  231. package/src/tools/agent-memory-tool.ts +253 -0
  232. package/src/tools/agent-model-compare-export.ts +315 -0
  233. package/src/tools/agent-model-compare-handoff.ts +592 -0
  234. package/src/tools/agent-model-compare-judgment.ts +633 -0
  235. package/src/tools/agent-model-compare-run.ts +735 -0
  236. package/src/tools/agent-model-compare-tool.ts +698 -0
  237. package/src/tools/agent-model-compare-types.ts +191 -0
  238. package/src/tools/agent-model-compare-utils.ts +93 -0
  239. package/src/tools/agent-models-tool.ts +208 -0
  240. package/src/tools/agent-operator-action-tool.ts +1 -1
  241. package/src/tools/agent-operator-method-tool.ts +643 -0
  242. package/src/tools/agent-personal-ops-tool.ts +197 -0
  243. package/src/tools/agent-policy-explanation.ts +415 -0
  244. package/src/tools/agent-research-report-tool.ts +608 -0
  245. package/src/tools/agent-research-runner.ts +367 -0
  246. package/src/tools/agent-research-runs-tool.ts +434 -0
  247. package/src/tools/agent-research-sources-tool.ts +443 -0
  248. package/src/tools/agent-research-tool.ts +515 -0
  249. package/src/tools/agent-review-packet-presets-core.ts +757 -0
  250. package/src/tools/agent-review-packet-presets-tool.ts +466 -0
  251. package/src/tools/agent-review-packet-share-tool.ts +305 -0
  252. package/src/tools/agent-route-planner-candidates-setup.ts +411 -0
  253. package/src/tools/agent-route-planner-candidates-surfaces.ts +432 -0
  254. package/src/tools/agent-route-planner-candidates-work.ts +251 -0
  255. package/src/tools/agent-route-planner-helpers.ts +667 -0
  256. package/src/tools/agent-route-planner.ts +185 -0
  257. package/src/tools/agent-route-tool.ts +105 -0
  258. package/src/tools/agent-schedule-edit-tool.ts +210 -0
  259. package/src/tools/agent-schedule-tool.ts +282 -0
  260. package/src/tools/agent-security-tool.ts +145 -0
  261. package/src/tools/agent-sessions-tool.ts +122 -0
  262. package/src/tools/agent-settings-import-tool.ts +104 -0
  263. package/src/tools/agent-settings-tool.ts +176 -0
  264. package/src/tools/agent-setup-tool.ts +226 -0
  265. package/src/tools/agent-support-tool.ts +122 -0
  266. package/src/tools/agent-terminal-process-tools.ts +167 -0
  267. package/src/tools/agent-tool-policy-guard-types.ts +77 -0
  268. package/src/tools/agent-tool-policy-guard.ts +106 -85
  269. package/src/tools/agent-vibe-tool.ts +297 -0
  270. package/src/tools/agent-work-plan-tool.ts +265 -6
  271. package/src/tools/agent-workspace-tool.ts +305 -0
  272. package/src/tools/artifact-archive.ts +169 -0
  273. package/src/tools/tool-definition-compaction.ts +36 -0
  274. package/src/version.ts +1 -1
@@ -0,0 +1,292 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
3
+ import { dirname } from 'node:path';
4
+ import type { ShellPathService } from '@/runtime/index.ts';
5
+ import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
6
+ import type { AgentChannelDeliveryInput, AgentChannelDeliveryResult } from './channel-delivery.ts';
7
+
8
+ export type AgentChannelDeliveryReceiptSource = 'command' | 'model-tool';
9
+ export type AgentChannelDeliveryReceiptStatus = 'sent';
10
+
11
+ export interface AgentChannelDeliveryReceiptTarget {
12
+ readonly kind: string;
13
+ readonly display: string;
14
+ readonly surfaceKind?: string;
15
+ readonly routeId?: string;
16
+ readonly label?: string;
17
+ readonly addressHost?: string;
18
+ readonly addressScheme?: string;
19
+ readonly addressDigest?: string;
20
+ readonly redactedAddress?: boolean;
21
+ }
22
+
23
+ export interface AgentChannelDeliveryReceipt {
24
+ readonly version: 1;
25
+ readonly id: string;
26
+ readonly createdAt: string;
27
+ readonly source: AgentChannelDeliveryReceiptSource;
28
+ readonly status: AgentChannelDeliveryReceiptStatus;
29
+ readonly title: string;
30
+ readonly target: AgentChannelDeliveryReceiptTarget;
31
+ readonly messagePreview: string;
32
+ readonly messageLength: number;
33
+ readonly messageDigest: string;
34
+ readonly strategyCount: number;
35
+ readonly responseId?: string;
36
+ readonly authorization: 'explicit-user-confirmed';
37
+ readonly userRoute: string;
38
+ readonly modelRoute: string;
39
+ }
40
+
41
+ export interface AgentChannelDeliveryReceiptSnapshot {
42
+ readonly path: string;
43
+ readonly exists: boolean;
44
+ readonly receipts: readonly AgentChannelDeliveryReceipt[];
45
+ readonly parseError?: string;
46
+ }
47
+
48
+ interface AgentChannelDeliveryReceiptFile {
49
+ readonly version: 1;
50
+ readonly receipts: readonly AgentChannelDeliveryReceipt[];
51
+ }
52
+
53
+ type AgentChannelDeliveryReceiptShellPaths = Pick<ShellPathService, 'resolveUserPath'>;
54
+
55
+ const RECEIPT_VERSION = 1;
56
+ const RECEIPT_LIMIT = 100;
57
+ const MESSAGE_PREVIEW_LIMIT = 120;
58
+
59
+ function isRecord(value: unknown): value is Record<string, unknown> {
60
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
61
+ }
62
+
63
+ function readString(value: unknown): string {
64
+ return typeof value === 'string' ? value.trim() : '';
65
+ }
66
+
67
+ function readNumber(value: unknown): number | null {
68
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
69
+ }
70
+
71
+ function digest(value: string): string {
72
+ return createHash('sha256').update(value).digest('hex').slice(0, 16);
73
+ }
74
+
75
+ function normalizeWhitespace(value: string): string {
76
+ return value.trim().replace(/\s+/g, ' ');
77
+ }
78
+
79
+ function redactSecretLikeText(value: string): string {
80
+ return value
81
+ .replace(/\bhttps?:\/\/\S+/gi, (raw) => {
82
+ try {
83
+ const url = new URL(raw);
84
+ return `${url.protocol}//${url.host}/...`;
85
+ } catch {
86
+ return '[redacted-url]';
87
+ }
88
+ })
89
+ .replace(/\b(xox[baprs]-[A-Za-z0-9-]{8,})\b/g, '[redacted-token]')
90
+ .replace(/\b([A-Za-z0-9_-]{24,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,})\b/g, '[redacted-token]')
91
+ .replace(/\b(api[_-]?key|token|secret|password)\s*[:=]\s*\S+/gi, '$1=[redacted]');
92
+ }
93
+
94
+ function previewMessage(message: string): string {
95
+ const safe = redactSecretLikeText(normalizeWhitespace(message));
96
+ return safe.length > MESSAGE_PREVIEW_LIMIT ? `${safe.slice(0, MESSAGE_PREVIEW_LIMIT - 1)}...` : safe;
97
+ }
98
+
99
+ function safeRouteArg(value: string): string {
100
+ return normalizeWhitespace(value).replace(/"/g, '\\"');
101
+ }
102
+
103
+ function summarizeAddress(address: string | undefined, kind: string): AgentChannelDeliveryReceiptTarget {
104
+ const normalized = readString(address);
105
+ if (!normalized) return { kind, display: kind, redactedAddress: true };
106
+ try {
107
+ const url = new URL(normalized);
108
+ return {
109
+ kind,
110
+ display: `${kind} ${url.protocol}//${url.host}/...`,
111
+ addressHost: url.host,
112
+ addressScheme: url.protocol.replace(/:$/, ''),
113
+ addressDigest: digest(normalized),
114
+ redactedAddress: true,
115
+ };
116
+ } catch {
117
+ return {
118
+ kind,
119
+ display: `${kind} [redacted-target]`,
120
+ addressDigest: digest(normalized),
121
+ redactedAddress: true,
122
+ };
123
+ }
124
+ }
125
+
126
+ function summarizeTarget(result: AgentChannelDeliveryResult): AgentChannelDeliveryReceiptTarget {
127
+ const target = result.target;
128
+ if (target.kind === 'surface') {
129
+ const surfaceKind = readString(target.surfaceKind) || 'route';
130
+ const details = [
131
+ target.routeId ? `route ${target.routeId}` : '',
132
+ target.label ? `label ${target.label}` : '',
133
+ ].filter(Boolean);
134
+ return {
135
+ kind: 'surface',
136
+ display: `${surfaceKind}${details.length > 0 ? ` (${details.join(', ')})` : ''}`,
137
+ surfaceKind,
138
+ ...(target.routeId ? { routeId: target.routeId } : {}),
139
+ ...(target.label ? { label: target.label } : {}),
140
+ };
141
+ }
142
+ return summarizeAddress(target.address, target.kind);
143
+ }
144
+
145
+ function targetInput(input: AgentChannelDeliveryInput): string {
146
+ if (input.channel) return `--channel "${safeRouteArg(input.channel)}"`;
147
+ if (input.route) return `--route "${safeRouteArg(input.route)}"`;
148
+ if (input.webhook) return '--webhook "[redacted-webhook]"';
149
+ if (input.link) return '--link "[redacted-link]"';
150
+ return '--channel "<target>"';
151
+ }
152
+
153
+ function parseTarget(value: unknown): AgentChannelDeliveryReceiptTarget | null {
154
+ if (!isRecord(value)) return null;
155
+ const kind = readString(value.kind);
156
+ const display = readString(value.display);
157
+ if (!kind || !display) return null;
158
+ const surfaceKind = readString(value.surfaceKind);
159
+ const routeId = readString(value.routeId);
160
+ const label = readString(value.label);
161
+ const addressHost = readString(value.addressHost);
162
+ const addressScheme = readString(value.addressScheme);
163
+ const addressDigest = readString(value.addressDigest);
164
+ return {
165
+ kind,
166
+ display,
167
+ ...(surfaceKind ? { surfaceKind } : {}),
168
+ ...(routeId ? { routeId } : {}),
169
+ ...(label ? { label } : {}),
170
+ ...(addressHost ? { addressHost } : {}),
171
+ ...(addressScheme ? { addressScheme } : {}),
172
+ ...(addressDigest ? { addressDigest } : {}),
173
+ ...(value.redactedAddress === true ? { redactedAddress: true } : {}),
174
+ };
175
+ }
176
+
177
+ function parseReceipt(value: unknown): AgentChannelDeliveryReceipt | null {
178
+ if (!isRecord(value) || value.version !== RECEIPT_VERSION) return null;
179
+ const id = readString(value.id);
180
+ const createdAt = readString(value.createdAt);
181
+ const source = value.source === 'model-tool' ? 'model-tool' : value.source === 'command' ? 'command' : null;
182
+ const status = value.status === 'sent' ? 'sent' : null;
183
+ const title = readString(value.title);
184
+ const target = parseTarget(value.target);
185
+ const messagePreview = readString(value.messagePreview);
186
+ const messageLength = readNumber(value.messageLength);
187
+ const messageDigest = readString(value.messageDigest);
188
+ const strategyCount = readNumber(value.strategyCount);
189
+ const userRoute = readString(value.userRoute);
190
+ const modelRoute = readString(value.modelRoute);
191
+ if (!id || !createdAt || Number.isNaN(Date.parse(createdAt)) || !source || !status || !title || !target || messageLength === null || !messageDigest || strategyCount === null || !userRoute || !modelRoute) {
192
+ return null;
193
+ }
194
+ const responseId = readString(value.responseId);
195
+ return {
196
+ version: RECEIPT_VERSION,
197
+ id,
198
+ createdAt,
199
+ source,
200
+ status,
201
+ title,
202
+ target,
203
+ messagePreview,
204
+ messageLength,
205
+ messageDigest,
206
+ strategyCount,
207
+ ...(responseId ? { responseId } : {}),
208
+ authorization: 'explicit-user-confirmed',
209
+ userRoute,
210
+ modelRoute,
211
+ };
212
+ }
213
+
214
+ function parseReceiptFile(value: unknown): AgentChannelDeliveryReceiptFile {
215
+ if (!isRecord(value)) return { version: RECEIPT_VERSION, receipts: [] };
216
+ const receipts = Array.isArray(value.receipts)
217
+ ? value.receipts.map(parseReceipt).filter((entry): entry is AgentChannelDeliveryReceipt => entry !== null)
218
+ : [];
219
+ return { version: RECEIPT_VERSION, receipts };
220
+ }
221
+
222
+ export function agentChannelDeliveryReceiptPath(shellPaths: AgentChannelDeliveryReceiptShellPaths): string {
223
+ return shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'channels', 'delivery-receipts.json');
224
+ }
225
+
226
+ export function readAgentChannelDeliveryReceipts(shellPaths: AgentChannelDeliveryReceiptShellPaths): AgentChannelDeliveryReceiptSnapshot {
227
+ const path = agentChannelDeliveryReceiptPath(shellPaths);
228
+ if (!existsSync(path)) return { path, exists: false, receipts: [] };
229
+ try {
230
+ const parsed = JSON.parse(readFileSync(path, 'utf-8')) as unknown;
231
+ return { path, exists: true, receipts: parseReceiptFile(parsed).receipts };
232
+ } catch (error) {
233
+ return {
234
+ path,
235
+ exists: true,
236
+ receipts: [],
237
+ parseError: error instanceof Error ? error.message : String(error),
238
+ };
239
+ }
240
+ }
241
+
242
+ export function recordAgentChannelDeliveryReceipt(
243
+ shellPaths: AgentChannelDeliveryReceiptShellPaths,
244
+ input: {
245
+ readonly source: AgentChannelDeliveryReceiptSource;
246
+ readonly deliveryInput: AgentChannelDeliveryInput;
247
+ readonly result: AgentChannelDeliveryResult;
248
+ },
249
+ ): AgentChannelDeliveryReceipt {
250
+ const path = agentChannelDeliveryReceiptPath(shellPaths);
251
+ const title = previewMessage(input.result.title || 'GoodVibes Agent message');
252
+ const receipt: AgentChannelDeliveryReceipt = {
253
+ version: RECEIPT_VERSION,
254
+ id: `channel-delivery-${new Date().toISOString().replace(/[^0-9]/g, '').slice(0, 14)}-${randomUUID().slice(0, 8)}`,
255
+ createdAt: new Date().toISOString(),
256
+ source: input.source,
257
+ status: 'sent',
258
+ title,
259
+ target: summarizeTarget(input.result),
260
+ messagePreview: previewMessage(input.result.message),
261
+ messageLength: input.result.message.length,
262
+ messageDigest: digest(input.result.message),
263
+ strategyCount: input.result.strategyCount,
264
+ ...(input.result.responseId ? { responseId: input.result.responseId } : {}),
265
+ authorization: 'explicit-user-confirmed',
266
+ userRoute: `/channels send --title "${safeRouteArg(title)}" ${targetInput(input.deliveryInput)} --message "[redacted]" --yes`,
267
+ modelRoute: 'agent_channel_send confirm:true explicitUserRequest:"..."',
268
+ };
269
+ const current = readAgentChannelDeliveryReceipts(shellPaths).receipts;
270
+ const next: AgentChannelDeliveryReceiptFile = {
271
+ version: RECEIPT_VERSION,
272
+ receipts: [receipt, ...current].slice(0, RECEIPT_LIMIT),
273
+ };
274
+ mkdirSync(dirname(path), { recursive: true });
275
+ const tempPath = `${path}.tmp`;
276
+ writeFileSync(tempPath, `${JSON.stringify(next, null, 2)}\n`, 'utf-8');
277
+ renameSync(tempPath, path);
278
+ return receipt;
279
+ }
280
+
281
+ export function formatAgentChannelDeliveryReceiptLine(receipt: AgentChannelDeliveryReceipt): string {
282
+ return [
283
+ `${receipt.createdAt} ${receipt.id}`,
284
+ receipt.status,
285
+ receipt.source,
286
+ `target=${receipt.target.display}`,
287
+ `title=${receipt.title}`,
288
+ receipt.responseId ? `response=${receipt.responseId}` : '',
289
+ `message=${receipt.messageLength} chars sha256:${receipt.messageDigest}`,
290
+ receipt.messagePreview ? `preview="${receipt.messagePreview}"` : '',
291
+ ].filter(Boolean).join(' ');
292
+ }