@phigon/observer 8.0.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 (284) hide show
  1. package/README.md +303 -0
  2. package/dist/bin/guardian-runner-darwin-amd64 +0 -0
  3. package/dist/bin/guardian-runner-darwin-arm64 +0 -0
  4. package/dist/bin/guardian-runner-linux-amd64 +0 -0
  5. package/dist/bin/guardian-runner-linux-arm64 +0 -0
  6. package/dist/bin/guardian-runner-windows-amd64.exe +0 -0
  7. package/dist/bin/guardian-runner-windows-arm64.exe +0 -0
  8. package/dist/src/action-policy.d.ts +38 -0
  9. package/dist/src/action-policy.d.ts.map +1 -0
  10. package/dist/src/action-policy.js +269 -0
  11. package/dist/src/action-policy.js.map +1 -0
  12. package/dist/src/activity/adapters/claude.d.ts +3 -0
  13. package/dist/src/activity/adapters/claude.d.ts.map +1 -0
  14. package/dist/src/activity/adapters/claude.js +89 -0
  15. package/dist/src/activity/adapters/claude.js.map +1 -0
  16. package/dist/src/activity/adapters/codex.d.ts +3 -0
  17. package/dist/src/activity/adapters/codex.d.ts.map +1 -0
  18. package/dist/src/activity/adapters/codex.js +277 -0
  19. package/dist/src/activity/adapters/codex.js.map +1 -0
  20. package/dist/src/activity/adapters/copilot.d.ts +2 -0
  21. package/dist/src/activity/adapters/copilot.d.ts.map +1 -0
  22. package/dist/src/activity/adapters/copilot.js +4 -0
  23. package/dist/src/activity/adapters/copilot.js.map +1 -0
  24. package/dist/src/activity/adapters/generic.d.ts +2 -0
  25. package/dist/src/activity/adapters/generic.d.ts.map +1 -0
  26. package/dist/src/activity/adapters/generic.js +4 -0
  27. package/dist/src/activity/adapters/generic.js.map +1 -0
  28. package/dist/src/activity/adapters/hermes.d.ts +2 -0
  29. package/dist/src/activity/adapters/hermes.d.ts.map +1 -0
  30. package/dist/src/activity/adapters/hermes.js +4 -0
  31. package/dist/src/activity/adapters/hermes.js.map +1 -0
  32. package/dist/src/activity/adapters/openai-compatible.d.ts +4 -0
  33. package/dist/src/activity/adapters/openai-compatible.d.ts.map +1 -0
  34. package/dist/src/activity/adapters/openai-compatible.js +116 -0
  35. package/dist/src/activity/adapters/openai-compatible.js.map +1 -0
  36. package/dist/src/activity/adapters/openclaw.d.ts +2 -0
  37. package/dist/src/activity/adapters/openclaw.d.ts.map +1 -0
  38. package/dist/src/activity/adapters/openclaw.js +4 -0
  39. package/dist/src/activity/adapters/openclaw.js.map +1 -0
  40. package/dist/src/activity/adapters/opencode.d.ts +3 -0
  41. package/dist/src/activity/adapters/opencode.d.ts.map +1 -0
  42. package/dist/src/activity/adapters/opencode.js +137 -0
  43. package/dist/src/activity/adapters/opencode.js.map +1 -0
  44. package/dist/src/activity/bridges.d.ts +7 -0
  45. package/dist/src/activity/bridges.d.ts.map +1 -0
  46. package/dist/src/activity/bridges.js +17 -0
  47. package/dist/src/activity/bridges.js.map +1 -0
  48. package/dist/src/activity/collector.d.ts +90 -0
  49. package/dist/src/activity/collector.d.ts.map +1 -0
  50. package/dist/src/activity/collector.js +706 -0
  51. package/dist/src/activity/collector.js.map +1 -0
  52. package/dist/src/activity/index.d.ts +14 -0
  53. package/dist/src/activity/index.d.ts.map +1 -0
  54. package/dist/src/activity/index.js +14 -0
  55. package/dist/src/activity/index.js.map +1 -0
  56. package/dist/src/activity/ingest.d.ts +15 -0
  57. package/dist/src/activity/ingest.d.ts.map +1 -0
  58. package/dist/src/activity/ingest.js +103 -0
  59. package/dist/src/activity/ingest.js.map +1 -0
  60. package/dist/src/activity/native-capabilities.d.ts +14 -0
  61. package/dist/src/activity/native-capabilities.d.ts.map +1 -0
  62. package/dist/src/activity/native-capabilities.js +85 -0
  63. package/dist/src/activity/native-capabilities.js.map +1 -0
  64. package/dist/src/activity/normalize.d.ts +17 -0
  65. package/dist/src/activity/normalize.d.ts.map +1 -0
  66. package/dist/src/activity/normalize.js +416 -0
  67. package/dist/src/activity/normalize.js.map +1 -0
  68. package/dist/src/activity/opencode-sqlite-source.d.ts +19 -0
  69. package/dist/src/activity/opencode-sqlite-source.d.ts.map +1 -0
  70. package/dist/src/activity/opencode-sqlite-source.js +305 -0
  71. package/dist/src/activity/opencode-sqlite-source.js.map +1 -0
  72. package/dist/src/activity/policy.d.ts +48 -0
  73. package/dist/src/activity/policy.d.ts.map +1 -0
  74. package/dist/src/activity/policy.js +436 -0
  75. package/dist/src/activity/policy.js.map +1 -0
  76. package/dist/src/activity/record.d.ts +7 -0
  77. package/dist/src/activity/record.d.ts.map +1 -0
  78. package/dist/src/activity/record.js +61 -0
  79. package/dist/src/activity/record.js.map +1 -0
  80. package/dist/src/activity/source-reader.d.ts +46 -0
  81. package/dist/src/activity/source-reader.d.ts.map +1 -0
  82. package/dist/src/activity/source-reader.js +594 -0
  83. package/dist/src/activity/source-reader.js.map +1 -0
  84. package/dist/src/activity/types.d.ts +21 -0
  85. package/dist/src/activity/types.d.ts.map +1 -0
  86. package/dist/src/activity/types.js +2 -0
  87. package/dist/src/activity/types.js.map +1 -0
  88. package/dist/src/agent-action-executor.d.ts +21 -0
  89. package/dist/src/agent-action-executor.d.ts.map +1 -0
  90. package/dist/src/agent-action-executor.js +248 -0
  91. package/dist/src/agent-action-executor.js.map +1 -0
  92. package/dist/src/agentic-guardian.d.ts +50 -0
  93. package/dist/src/agentic-guardian.d.ts.map +1 -0
  94. package/dist/src/agentic-guardian.js +220 -0
  95. package/dist/src/agentic-guardian.js.map +1 -0
  96. package/dist/src/atomic-replace.d.ts +4 -0
  97. package/dist/src/atomic-replace.d.ts.map +1 -0
  98. package/dist/src/atomic-replace.js +18 -0
  99. package/dist/src/atomic-replace.js.map +1 -0
  100. package/dist/src/cli.d.ts +11 -0
  101. package/dist/src/cli.d.ts.map +1 -0
  102. package/dist/src/cli.js +1244 -0
  103. package/dist/src/cli.js.map +1 -0
  104. package/dist/src/config.d.ts +68 -0
  105. package/dist/src/config.d.ts.map +1 -0
  106. package/dist/src/config.js +260 -0
  107. package/dist/src/config.js.map +1 -0
  108. package/dist/src/credential-store.d.ts +22 -0
  109. package/dist/src/credential-store.d.ts.map +1 -0
  110. package/dist/src/credential-store.js +91 -0
  111. package/dist/src/credential-store.js.map +1 -0
  112. package/dist/src/custom-agent-registry.d.ts +26 -0
  113. package/dist/src/custom-agent-registry.d.ts.map +1 -0
  114. package/dist/src/custom-agent-registry.js +288 -0
  115. package/dist/src/custom-agent-registry.js.map +1 -0
  116. package/dist/src/discovery/adapters/claude.d.ts +3 -0
  117. package/dist/src/discovery/adapters/claude.d.ts.map +1 -0
  118. package/dist/src/discovery/adapters/claude.js +26 -0
  119. package/dist/src/discovery/adapters/claude.js.map +1 -0
  120. package/dist/src/discovery/adapters/codex.d.ts +3 -0
  121. package/dist/src/discovery/adapters/codex.d.ts.map +1 -0
  122. package/dist/src/discovery/adapters/codex.js +23 -0
  123. package/dist/src/discovery/adapters/codex.js.map +1 -0
  124. package/dist/src/discovery/adapters/custom.d.ts +4 -0
  125. package/dist/src/discovery/adapters/custom.d.ts.map +1 -0
  126. package/dist/src/discovery/adapters/custom.js +24 -0
  127. package/dist/src/discovery/adapters/custom.js.map +1 -0
  128. package/dist/src/discovery/adapters/generic.d.ts +3 -0
  129. package/dist/src/discovery/adapters/generic.d.ts.map +1 -0
  130. package/dist/src/discovery/adapters/generic.js +126 -0
  131. package/dist/src/discovery/adapters/generic.js.map +1 -0
  132. package/dist/src/discovery/adapters/hermes.d.ts +3 -0
  133. package/dist/src/discovery/adapters/hermes.d.ts.map +1 -0
  134. package/dist/src/discovery/adapters/hermes.js +22 -0
  135. package/dist/src/discovery/adapters/hermes.js.map +1 -0
  136. package/dist/src/discovery/adapters/openclaw.d.ts +3 -0
  137. package/dist/src/discovery/adapters/openclaw.d.ts.map +1 -0
  138. package/dist/src/discovery/adapters/openclaw.js +22 -0
  139. package/dist/src/discovery/adapters/openclaw.js.map +1 -0
  140. package/dist/src/discovery/engine.d.ts +17 -0
  141. package/dist/src/discovery/engine.d.ts.map +1 -0
  142. package/dist/src/discovery/engine.js +164 -0
  143. package/dist/src/discovery/engine.js.map +1 -0
  144. package/dist/src/discovery/evidence.d.ts +29 -0
  145. package/dist/src/discovery/evidence.d.ts.map +1 -0
  146. package/dist/src/discovery/evidence.js +2 -0
  147. package/dist/src/discovery/evidence.js.map +1 -0
  148. package/dist/src/discovery/index.d.ts +11 -0
  149. package/dist/src/discovery/index.d.ts.map +1 -0
  150. package/dist/src/discovery/index.js +11 -0
  151. package/dist/src/discovery/index.js.map +1 -0
  152. package/dist/src/discovery/known-agent.d.ts +17 -0
  153. package/dist/src/discovery/known-agent.d.ts.map +1 -0
  154. package/dist/src/discovery/known-agent.js +193 -0
  155. package/dist/src/discovery/known-agent.js.map +1 -0
  156. package/dist/src/discovery/process-identity.d.ts +19 -0
  157. package/dist/src/discovery/process-identity.d.ts.map +1 -0
  158. package/dist/src/discovery/process-identity.js +73 -0
  159. package/dist/src/discovery/process-identity.js.map +1 -0
  160. package/dist/src/discovery/system-evidence.d.ts +9 -0
  161. package/dist/src/discovery/system-evidence.d.ts.map +1 -0
  162. package/dist/src/discovery/system-evidence.js +270 -0
  163. package/dist/src/discovery/system-evidence.js.map +1 -0
  164. package/dist/src/discovery/types.d.ts +21 -0
  165. package/dist/src/discovery/types.d.ts.map +1 -0
  166. package/dist/src/discovery/types.js +2 -0
  167. package/dist/src/discovery/types.js.map +1 -0
  168. package/dist/src/event-queue.d.ts +32 -0
  169. package/dist/src/event-queue.d.ts.map +1 -0
  170. package/dist/src/event-queue.js +125 -0
  171. package/dist/src/event-queue.js.map +1 -0
  172. package/dist/src/event-spool.d.ts +19 -0
  173. package/dist/src/event-spool.d.ts.map +1 -0
  174. package/dist/src/event-spool.js +350 -0
  175. package/dist/src/event-spool.js.map +1 -0
  176. package/dist/src/generated/phigon/v1/action_pb.d.ts +223 -0
  177. package/dist/src/generated/phigon/v1/action_pb.d.ts.map +1 -0
  178. package/dist/src/generated/phigon/v1/action_pb.js +96 -0
  179. package/dist/src/generated/phigon/v1/action_pb.js.map +1 -0
  180. package/dist/src/generated/phigon/v1/common_pb.d.ts +255 -0
  181. package/dist/src/generated/phigon/v1/common_pb.d.ts.map +1 -0
  182. package/dist/src/generated/phigon/v1/common_pb.js +242 -0
  183. package/dist/src/generated/phigon/v1/common_pb.js.map +1 -0
  184. package/dist/src/generated/phigon/v1/history_sync_pb.d.ts +119 -0
  185. package/dist/src/generated/phigon/v1/history_sync_pb.d.ts.map +1 -0
  186. package/dist/src/generated/phigon/v1/history_sync_pb.js +46 -0
  187. package/dist/src/generated/phigon/v1/history_sync_pb.js.map +1 -0
  188. package/dist/src/generated/phigon/v1/identity_pb.d.ts +235 -0
  189. package/dist/src/generated/phigon/v1/identity_pb.d.ts.map +1 -0
  190. package/dist/src/generated/phigon/v1/identity_pb.js +31 -0
  191. package/dist/src/generated/phigon/v1/identity_pb.js.map +1 -0
  192. package/dist/src/generated/phigon/v1/observer_service_pb.d.ts +362 -0
  193. package/dist/src/generated/phigon/v1/observer_service_pb.d.ts.map +1 -0
  194. package/dist/src/generated/phigon/v1/observer_service_pb.js +120 -0
  195. package/dist/src/generated/phigon/v1/observer_service_pb.js.map +1 -0
  196. package/dist/src/generated/phigon/v1/policy_pb.d.ts +456 -0
  197. package/dist/src/generated/phigon/v1/policy_pb.d.ts.map +1 -0
  198. package/dist/src/generated/phigon/v1/policy_pb.js +161 -0
  199. package/dist/src/generated/phigon/v1/policy_pb.js.map +1 -0
  200. package/dist/src/generated/phigon/v1/supervision_pb.d.ts +849 -0
  201. package/dist/src/generated/phigon/v1/supervision_pb.d.ts.map +1 -0
  202. package/dist/src/generated/phigon/v1/supervision_pb.js +384 -0
  203. package/dist/src/generated/phigon/v1/supervision_pb.js.map +1 -0
  204. package/dist/src/generated/phigon/v1/telemetry_pb.d.ts +761 -0
  205. package/dist/src/generated/phigon/v1/telemetry_pb.d.ts.map +1 -0
  206. package/dist/src/generated/phigon/v1/telemetry_pb.js +309 -0
  207. package/dist/src/generated/phigon/v1/telemetry_pb.js.map +1 -0
  208. package/dist/src/guardian-containment.d.ts +30 -0
  209. package/dist/src/guardian-containment.d.ts.map +1 -0
  210. package/dist/src/guardian-containment.js +113 -0
  211. package/dist/src/guardian-containment.js.map +1 -0
  212. package/dist/src/guardian-decision-journal.d.ts +29 -0
  213. package/dist/src/guardian-decision-journal.d.ts.map +1 -0
  214. package/dist/src/guardian-decision-journal.js +55 -0
  215. package/dist/src/guardian-decision-journal.js.map +1 -0
  216. package/dist/src/guardian-execution-manifest.d.ts +29 -0
  217. package/dist/src/guardian-execution-manifest.d.ts.map +1 -0
  218. package/dist/src/guardian-execution-manifest.js +95 -0
  219. package/dist/src/guardian-execution-manifest.js.map +1 -0
  220. package/dist/src/guardian-hosted-client.d.ts +10 -0
  221. package/dist/src/guardian-hosted-client.d.ts.map +1 -0
  222. package/dist/src/guardian-hosted-client.js +45 -0
  223. package/dist/src/guardian-hosted-client.js.map +1 -0
  224. package/dist/src/guardian-managed-exec.d.ts +21 -0
  225. package/dist/src/guardian-managed-exec.d.ts.map +1 -0
  226. package/dist/src/guardian-managed-exec.js +249 -0
  227. package/dist/src/guardian-managed-exec.js.map +1 -0
  228. package/dist/src/guardian-model-bridge.d.ts +13 -0
  229. package/dist/src/guardian-model-bridge.d.ts.map +1 -0
  230. package/dist/src/guardian-model-bridge.js +87 -0
  231. package/dist/src/guardian-model-bridge.js.map +1 -0
  232. package/dist/src/guardian-native.d.ts +3 -0
  233. package/dist/src/guardian-native.d.ts.map +1 -0
  234. package/dist/src/guardian-native.js +13 -0
  235. package/dist/src/guardian-native.js.map +1 -0
  236. package/dist/src/guardian-process-monitor.d.ts +20 -0
  237. package/dist/src/guardian-process-monitor.d.ts.map +1 -0
  238. package/dist/src/guardian-process-monitor.js +98 -0
  239. package/dist/src/guardian-process-monitor.js.map +1 -0
  240. package/dist/src/health.d.ts +35 -0
  241. package/dist/src/health.d.ts.map +1 -0
  242. package/dist/src/health.js +41 -0
  243. package/dist/src/health.js.map +1 -0
  244. package/dist/src/historical-identity-store.d.ts +20 -0
  245. package/dist/src/historical-identity-store.d.ts.map +1 -0
  246. package/dist/src/historical-identity-store.js +391 -0
  247. package/dist/src/historical-identity-store.js.map +1 -0
  248. package/dist/src/index.d.ts +14 -0
  249. package/dist/src/index.d.ts.map +1 -0
  250. package/dist/src/index.js +14 -0
  251. package/dist/src/index.js.map +1 -0
  252. package/dist/src/installation.d.ts +2 -0
  253. package/dist/src/installation.d.ts.map +1 -0
  254. package/dist/src/installation.js +44 -0
  255. package/dist/src/installation.js.map +1 -0
  256. package/dist/src/machine-command-executor.d.ts +28 -0
  257. package/dist/src/machine-command-executor.d.ts.map +1 -0
  258. package/dist/src/machine-command-executor.js +166 -0
  259. package/dist/src/machine-command-executor.js.map +1 -0
  260. package/dist/src/pair.d.ts +21 -0
  261. package/dist/src/pair.d.ts.map +1 -0
  262. package/dist/src/pair.js +125 -0
  263. package/dist/src/pair.js.map +1 -0
  264. package/dist/src/remove-machine.d.ts +15 -0
  265. package/dist/src/remove-machine.d.ts.map +1 -0
  266. package/dist/src/remove-machine.js +77 -0
  267. package/dist/src/remove-machine.js.map +1 -0
  268. package/dist/src/stream-client.d.ts +42 -0
  269. package/dist/src/stream-client.d.ts.map +1 -0
  270. package/dist/src/stream-client.js +867 -0
  271. package/dist/src/stream-client.js.map +1 -0
  272. package/dist/src/stream-state.d.ts +13 -0
  273. package/dist/src/stream-state.d.ts.map +1 -0
  274. package/dist/src/stream-state.js +128 -0
  275. package/dist/src/stream-state.js.map +1 -0
  276. package/dist/src/windows-process.d.ts +7 -0
  277. package/dist/src/windows-process.d.ts.map +1 -0
  278. package/dist/src/windows-process.js +17 -0
  279. package/dist/src/windows-process.js.map +1 -0
  280. package/package.json +78 -0
  281. package/scripts/install.mjs +308 -0
  282. package/scripts/managed-service.mjs +132 -0
  283. package/scripts/verify-guardian-release.mjs +42 -0
  284. package/scripts/windows-app-control.mjs +117 -0
@@ -0,0 +1,706 @@
1
+ import { createHash } from "node:crypto";
2
+ import { join } from "node:path";
3
+ import { create, toBinary } from "@bufbuild/protobuf";
4
+ import { timestampFromDate } from "@bufbuild/protobuf/wkt";
5
+ import { ActivityKind, AgentKind, AgentState, } from "../generated/phigon/v1/common_pb.js";
6
+ import { AgentIdentitySchema, } from "../generated/phigon/v1/identity_pb.js";
7
+ import { mergeInventoryWithHistoricalIdentities } from "../historical-identity-store.js";
8
+ import { EventEnvelopeSchema, } from "../generated/phigon/v1/telemetry_pb.js";
9
+ import { claudeActivityAdapter } from "./adapters/claude.js";
10
+ import { codexActivityAdapter } from "./adapters/codex.js";
11
+ import { copilotActivityAdapter } from "./adapters/copilot.js";
12
+ import { hermesActivityAdapter } from "./adapters/hermes.js";
13
+ import { openClawActivityAdapter } from "./adapters/openclaw.js";
14
+ import { openCodeActivityAdapter } from "./adapters/opencode.js";
15
+ import { createOpenAICompatibleAdapter } from "./adapters/openai-compatible.js";
16
+ import { activityBridgeAgents } from "./bridges.js";
17
+ import { genericActivityAdapter } from "./adapters/generic.js";
18
+ import { LocalPolicyEngine } from "./policy.js";
19
+ import { vendorDraft } from "./normalize.js";
20
+ import { objectValue, recordObservedAt, stringField, } from "./record.js";
21
+ import { JSONLSourceReader, } from "./source-reader.js";
22
+ import { processKeyCapability } from "../discovery/process-identity.js";
23
+ const maxEnvelopeBytes = 1 << 20;
24
+ const maxPendingCheckpoints = 256;
25
+ export const historySyncQueueHeadroom = 1_024;
26
+ const maxDraftsPerRecord = 32;
27
+ const adapters = new Map([
28
+ ["claude", claudeActivityAdapter],
29
+ ["codex", codexActivityAdapter],
30
+ ["copilot", copilotActivityAdapter],
31
+ ["hermes", hermesActivityAdapter],
32
+ ["openclaw", openClawActivityAdapter],
33
+ ...activityBridgeAgents.map((agent) => [
34
+ agent.id,
35
+ createOpenAICompatibleAdapter(agent.id, AgentKind.GENERIC, agent.displayName),
36
+ ]),
37
+ // Keep the flexible generic parser after the generated bridge adapters so
38
+ // the generic bridge cannot accidentally replace it with a fixed label.
39
+ ["generic", genericActivityAdapter],
40
+ ["opencode", openCodeActivityAdapter],
41
+ ]);
42
+ export class ActivityCollector {
43
+ #config;
44
+ #credential;
45
+ #emit;
46
+ #sources;
47
+ #additionalSources;
48
+ #reader;
49
+ #historyReader;
50
+ #historyWork = Promise.resolve();
51
+ #clock;
52
+ #canCollect;
53
+ #canSyncHistory;
54
+ #onSourceIdentity;
55
+ #policy;
56
+ #limiter;
57
+ #agentsByKind = new Map();
58
+ #sourceIdentities = new Map();
59
+ #lastSequence;
60
+ #sourceRecords = 0;
61
+ #malformedRecords = 0;
62
+ #oversizedRecords = 0;
63
+ #emittedEvents = 0;
64
+ #rateLimitedEvents = 0;
65
+ #oversizedEvents = 0;
66
+ #acknowledgedSequence;
67
+ #durableDelivery;
68
+ #pendingCheckpoints = [];
69
+ #checkpointSave = Promise.resolve();
70
+ #sourceIdentitySaves = [];
71
+ #backpressuredScans = 0;
72
+ #scanWork = Promise.resolve();
73
+ constructor(options) {
74
+ this.#config = options.config;
75
+ this.#credential = options.credential;
76
+ this.#emit = options.emit;
77
+ this.#sources = options.sources ?? configuredSources(options.config);
78
+ this.#additionalSources = options.additionalSources ?? (async () => []);
79
+ this.#reader =
80
+ options.reader ??
81
+ new JSONLSourceReader(options.config.dataDirectory, options.config.activityReplayOnFirstStart, options.config.activityInitialReplayBytes, options.config.activityInitialReplaySessions);
82
+ this.#historyReader = new JSONLSourceReader(join(options.config.dataDirectory, "history-sync"), false, options.config.activityInitialReplayBytes, 1, "history");
83
+ this.#clock = options.clock ?? (() => new Date());
84
+ this.#canCollect = options.canCollect ?? (() => true);
85
+ this.#canSyncHistory = options.canSyncHistory ?? this.#canCollect;
86
+ this.#onSourceIdentity = options.onSourceIdentity ?? (() => undefined);
87
+ this.#policy = new LocalPolicyEngine(options.policy ?? options.config.policy, options.config.redactionPathPatterns);
88
+ this.#limiter = new MinuteRateLimiter(options.config.activityRateLimitPerMinute);
89
+ this.#lastSequence = options.initialSequence;
90
+ this.#acknowledgedSequence =
91
+ options.initialAcknowledgedSequence ?? options.initialSequence;
92
+ if (this.#acknowledgedSequence < 0n ||
93
+ this.#acknowledgedSequence > this.#lastSequence) {
94
+ throw new Error("Initial activity acknowledgement is invalid.");
95
+ }
96
+ this.#durableDelivery = options.durableDelivery ?? false;
97
+ }
98
+ updateInventory(inventory) {
99
+ this.#agentsByKind.clear();
100
+ for (const agent of inventory.agents)
101
+ this.#rememberAgent(agent);
102
+ }
103
+ updatePolicy(policy) {
104
+ this.#policy = new LocalPolicyEngine(policy, this.#config.redactionPathPatterns);
105
+ }
106
+ resetSequence(acknowledgedSequence, allocationSequence = acknowledgedSequence) {
107
+ if (acknowledgedSequence < 0n || allocationSequence < 0n) {
108
+ throw new Error("Activity sequence must not be negative.");
109
+ }
110
+ this.#acknowledgedSequence = acknowledgedSequence;
111
+ this.#lastSequence =
112
+ allocationSequence < acknowledgedSequence
113
+ ? acknowledgedSequence
114
+ : allocationSequence;
115
+ }
116
+ async acknowledge(sequence) {
117
+ if (sequence <= this.#acknowledgedSequence)
118
+ return;
119
+ this.#acknowledgedSequence = sequence;
120
+ this.#scheduleCheckpointSave();
121
+ await this.#checkpointSave;
122
+ }
123
+ async scanOnce() {
124
+ const pass = await this.#withScanLock(() => this.#collectOnce(this.#reader, false));
125
+ return pass.metrics;
126
+ }
127
+ async syncHistory(signal) {
128
+ const operation = () => this.#syncHistory(signal);
129
+ const result = this.#historyWork.then(operation, operation);
130
+ this.#historyWork = result.catch(() => undefined);
131
+ return result;
132
+ }
133
+ async #syncHistory(signal) {
134
+ let eventsUploaded = 0;
135
+ let recordsScanned = 0;
136
+ let filesDiscovered = 0;
137
+ let complete = false;
138
+ while (!complete) {
139
+ if (signal?.aborted === true) {
140
+ throw new Error("History sync expired before all available records were uploaded.");
141
+ }
142
+ if (!this.#canSyncHistory()) {
143
+ await abortableDelay(250, signal ?? new AbortController().signal);
144
+ continue;
145
+ }
146
+ // Release the collection lock between bounded batches. A large archive
147
+ // must not prevent the live reader from following current work.
148
+ const pass = await this.#withScanLock(async () => {
149
+ const before = this.#emittedEvents;
150
+ const result = await this.#collectOnce(this.#historyReader, true);
151
+ eventsUploaded += this.#emittedEvents - before;
152
+ return result;
153
+ });
154
+ recordsScanned += pass.sourceRecords;
155
+ filesDiscovered = Math.max(filesDiscovered, pass.discoveredFiles);
156
+ complete = pass.complete;
157
+ if (!complete && pass.sourceRecords === 0) {
158
+ await abortableDelay(100, signal ?? new AbortController().signal);
159
+ }
160
+ }
161
+ return Object.freeze({
162
+ filesDiscovered,
163
+ recordsScanned,
164
+ eventsUploaded,
165
+ throughSequence: this.#lastSequence,
166
+ });
167
+ }
168
+ async #collectOnce(reader, historical) {
169
+ const allowance = historical
170
+ ? Math.min(historySyncQueueHeadroom, this.#config.activityQueueCapacity)
171
+ : this.#limiter.remaining(this.#clock());
172
+ if (!(historical ? this.#canSyncHistory() : this.#canCollect()) || allowance === 0) {
173
+ this.#backpressuredScans++;
174
+ return {
175
+ complete: false,
176
+ metrics: this.metrics(),
177
+ sourceRecords: 0,
178
+ discoveredFiles: 0,
179
+ };
180
+ }
181
+ if (this.#pendingCheckpoints.length >= maxPendingCheckpoints) {
182
+ return {
183
+ complete: false,
184
+ metrics: this.metrics(),
185
+ sourceRecords: 0,
186
+ discoveredFiles: 0,
187
+ };
188
+ }
189
+ const scan = await reader.scan([
190
+ ...this.#sources,
191
+ ...await this.#additionalSources(),
192
+ ], Math.max(1, Math.floor(allowance / maxDraftsPerRecord)));
193
+ this.#sourceRecords += scan.metrics.records;
194
+ this.#malformedRecords += scan.metrics.malformed;
195
+ this.#oversizedRecords += scan.metrics.oversized;
196
+ const now = this.#clock();
197
+ for (const record of scan.records) {
198
+ const adapter = adapters.get(record.adapterId);
199
+ if (adapter === undefined)
200
+ continue;
201
+ const sessionID = reportedSessionID(record.adapterId, record.value, record.sourceId);
202
+ const drafts = adapter.parse(record.value, {
203
+ sessionId: sessionID,
204
+ observedAt: record.observedAt,
205
+ policy: this.#policy,
206
+ });
207
+ const context = {
208
+ sessionId: sessionID,
209
+ observedAt: recordObservedAt(record.value, record.observedAt),
210
+ policy: this.#policy,
211
+ };
212
+ const genericAgent = record.adapterId === "generic"
213
+ ? reportedGenericAgentIdentity(record.value, record.sourceDisplayName)
214
+ : undefined;
215
+ const nativeDraft = vendorDraft(adapter.agentKind, context, genericAgent?.hint !== undefined
216
+ ? genericAgent.hint
217
+ : adapter.id, vendorType(record.value), record.value);
218
+ const candidateDrafts = [nativeDraft, ...drafts.slice(0, 31)];
219
+ const permittedDrafts = !historical && record.initialReplay === true &&
220
+ this.#config.activityInitialReplayMode === "messages"
221
+ ? candidateDrafts.filter((draft) => draft.payload.case === "activity" &&
222
+ (draft.payload.value.kind === ActivityKind.PROMPT ||
223
+ draft.payload.value.kind === ActivityKind.RESPONSE))
224
+ : candidateDrafts;
225
+ // A source record is atomic: never advance its cursor after dropping
226
+ // part of its normalized activity. One record may use the final budget
227
+ // plus a bounded burst; the next scan waits for replenishment.
228
+ if (!historical)
229
+ this.#limiter.consume(now, permittedDrafts.length);
230
+ for (const [draftIndex, draft] of permittedDrafts.entries()) {
231
+ const nextSequence = this.#lastSequence + 1n;
232
+ const event = create(EventEnvelopeSchema, {
233
+ tenantId: this.#credential.tenantId,
234
+ machineId: this.#credential.machineId,
235
+ agentId: this.#agentID(draft.agentKind, record.adapterId, record.sourceId, record.value, record.observedAt, genericAgent?.displayName),
236
+ sessionId: draft.sessionId,
237
+ sequence: nextSequence,
238
+ observedAt: timestampFromDate(clampObservedAt(draft.observedAt, now)),
239
+ schemaVersion: 1,
240
+ privacyClass: draft.privacyClass,
241
+ sourceEventId: createHash("sha256")
242
+ .update(`${record.sourceRecordId}\u0000${draftIndex}\u0000${draft.payload.case}`)
243
+ .digest("hex"),
244
+ payload: draft.payload,
245
+ });
246
+ if (toBinary(EventEnvelopeSchema, event).byteLength >
247
+ maxEnvelopeBytes) {
248
+ this.#oversizedEvents++;
249
+ continue;
250
+ }
251
+ this.#lastSequence = nextSequence;
252
+ this.#emit(event);
253
+ this.#emittedEvents++;
254
+ }
255
+ }
256
+ await this.#flushSourceIdentitySaves();
257
+ const pending = {
258
+ throughSequence: this.#lastSequence,
259
+ checkpoint: scan.checkpoint,
260
+ reader,
261
+ };
262
+ const sameSequence = this.#pendingCheckpoints.findIndex((candidate) => candidate.throughSequence === pending.throughSequence &&
263
+ candidate.reader === pending.reader);
264
+ this.#pendingCheckpoints =
265
+ sameSequence < 0
266
+ ? [...this.#pendingCheckpoints, pending]
267
+ : this.#pendingCheckpoints.map((candidate, index) => index === sameSequence ? pending : candidate);
268
+ this.#scheduleCheckpointSave();
269
+ await this.#checkpointSave;
270
+ return {
271
+ complete: scan.complete,
272
+ metrics: this.metrics(),
273
+ sourceRecords: scan.metrics.records,
274
+ discoveredFiles: scan.metrics.discoveredFiles,
275
+ };
276
+ }
277
+ async run(signal) {
278
+ while (!signal.aborted) {
279
+ await this.scanOnce();
280
+ await abortableDelay(this.#config.activityScanIntervalMs, signal);
281
+ }
282
+ }
283
+ metrics() {
284
+ return Object.freeze({
285
+ sourceRecords: this.#sourceRecords,
286
+ malformedRecords: this.#malformedRecords,
287
+ oversizedRecords: this.#oversizedRecords,
288
+ emittedEvents: this.#emittedEvents,
289
+ rateLimitedEvents: this.#rateLimitedEvents,
290
+ oversizedEvents: this.#oversizedEvents,
291
+ lastSequence: this.#lastSequence,
292
+ pendingCheckpoints: this.#pendingCheckpoints.length,
293
+ backpressuredScans: this.#backpressuredScans,
294
+ });
295
+ }
296
+ sourceIdentities() {
297
+ return [...this.#sourceIdentities.values()].sort((left, right) => left.agentId.localeCompare(right.agentId));
298
+ }
299
+ #scheduleCheckpointSave() {
300
+ const durableThrough = this.#durableDelivery
301
+ ? this.#lastSequence
302
+ : this.#acknowledgedSequence;
303
+ const eligible = this.#pendingCheckpoints.filter((candidate) => candidate.throughSequence <= durableThrough);
304
+ if (eligible.length === 0)
305
+ return;
306
+ this.#checkpointSave = this.#checkpointSave
307
+ .catch(() => undefined)
308
+ .then(async () => {
309
+ const currentDurableThrough = this.#durableDelivery
310
+ ? this.#lastSequence
311
+ : this.#acknowledgedSequence;
312
+ const committed = new Set();
313
+ for (const pending of eligible) {
314
+ if (pending.throughSequence > currentDurableThrough)
315
+ continue;
316
+ await pending.reader.commit(pending.checkpoint);
317
+ committed.add(pending);
318
+ }
319
+ this.#pendingCheckpoints = this.#pendingCheckpoints.filter((candidate) => !committed.has(candidate));
320
+ });
321
+ }
322
+ async #withScanLock(operation) {
323
+ const result = this.#scanWork.then(operation, operation);
324
+ this.#scanWork = result.then(() => undefined, () => undefined);
325
+ return await result;
326
+ }
327
+ #rememberAgent(agent) {
328
+ if (agent.kind === AgentKind.UNSPECIFIED ||
329
+ agent.agentId.length === 0)
330
+ return;
331
+ const agents = this.#agentsByKind.get(agent.kind) ?? [];
332
+ const existing = agents.findIndex((candidate) => candidate.agentId === agent.agentId);
333
+ if (existing >= 0) {
334
+ agents[existing] = agent;
335
+ }
336
+ else {
337
+ agents.push(agent);
338
+ }
339
+ agents.sort((left, right) => left.agentId.localeCompare(right.agentId));
340
+ this.#agentsByKind.set(agent.kind, agents);
341
+ }
342
+ #agentID(kind, adapterId, sourceId, record, observedAt, sourceDisplayName) {
343
+ const agents = this.#agentsByKind.get(kind) ?? [];
344
+ const fallback = fallbackAgentID(kind, adapterId, sourceId);
345
+ const attributed = attributedRuntimeAgentID(agents, record);
346
+ if (attributed !== undefined)
347
+ return attributed;
348
+ this.#rememberSourceIdentity(fallback, kind, adapterId, sourceId, observedAt, sourceDisplayName);
349
+ return fallback;
350
+ }
351
+ #rememberSourceIdentity(agentID, kind, adapterID, sourceID, observedAt, sourceDisplayName) {
352
+ if (this.#sourceIdentities.has(agentID))
353
+ return;
354
+ if (this.#sourceIdentities.size >= 256) {
355
+ const oldest = this.#sourceIdentities.keys().next().value;
356
+ if (oldest !== undefined)
357
+ this.#sourceIdentities.delete(oldest);
358
+ }
359
+ const identity = create(AgentIdentitySchema, {
360
+ agentId: agentID,
361
+ kind,
362
+ displayName: sourceIdentityDisplayName(adapterID, sourceID, sourceDisplayName),
363
+ state: AgentState.UNKNOWN,
364
+ processId: 0n,
365
+ lastObservedAt: timestampFromDate(observedAt),
366
+ capabilities: ["activity", "source-isolated", "unattributed"],
367
+ });
368
+ this.#sourceIdentities.set(agentID, identity);
369
+ try {
370
+ this.#sourceIdentitySaves.push(Promise.resolve(this.#onSourceIdentity(identity)));
371
+ }
372
+ catch (error) {
373
+ this.#sourceIdentitySaves.push(Promise.reject(error));
374
+ }
375
+ }
376
+ async #flushSourceIdentitySaves() {
377
+ const pending = this.#sourceIdentitySaves.splice(0);
378
+ if (pending.length === 0)
379
+ return;
380
+ const results = await Promise.allSettled(pending);
381
+ const failure = results.find((result) => result.status === "rejected");
382
+ if (failure !== undefined)
383
+ throw failure.reason;
384
+ }
385
+ }
386
+ export function mergeInventoryWithSourceIdentities(inventory, sourceIdentities) {
387
+ return mergeInventoryWithHistoricalIdentities(inventory, sourceIdentities);
388
+ }
389
+ export function attributedRuntimeAgentID(agents, record) {
390
+ const reported = reportedProcessIdentity(record);
391
+ if (!reported.coverageComplete ||
392
+ reported.conflict ||
393
+ reported.processKey === undefined) {
394
+ return undefined;
395
+ }
396
+ const keyCapability = processKeyCapability(reported.processKey);
397
+ if (keyCapability === undefined)
398
+ return undefined;
399
+ const matches = agents.filter((agent) => agent.state === AgentState.RUNNING &&
400
+ agent.capabilities.includes("process-instance") &&
401
+ agent.capabilities.includes(keyCapability));
402
+ if (matches.length !== 1)
403
+ return undefined;
404
+ const matched = matches[0];
405
+ if (matched === undefined ||
406
+ (reported.processID !== undefined &&
407
+ matched.processId !== reported.processID)) {
408
+ return undefined;
409
+ }
410
+ return matched.agentId;
411
+ }
412
+ /**
413
+ * Keeps agent-native process claims independent from inventory/OS evidence.
414
+ * A PID can reject a contradictory match, but can never create one.
415
+ */
416
+ export function reportedProcessIdentity(record) {
417
+ const object = objectValue(record);
418
+ if (object === null) {
419
+ return { conflict: false, coverageComplete: false };
420
+ }
421
+ const metadata = objectValue(object["metadata"]);
422
+ const keyValues = new Set();
423
+ let invalidKeyClaim = false;
424
+ for (const candidate of [
425
+ object["process_key"],
426
+ object["processKey"],
427
+ metadata?.["process_key"],
428
+ metadata?.["processKey"],
429
+ ]) {
430
+ if (candidate === undefined)
431
+ continue;
432
+ if (typeof candidate !== "string" ||
433
+ candidate.length === 0 ||
434
+ candidate !== candidate.trim() ||
435
+ Buffer.byteLength(candidate, "utf8") > 256 ||
436
+ /[\u0000-\u001f\u007f]/u.test(candidate)) {
437
+ invalidKeyClaim = true;
438
+ continue;
439
+ }
440
+ keyValues.add(candidate);
441
+ }
442
+ const processIDs = new Set();
443
+ let invalidProcessID = false;
444
+ for (const candidate of [
445
+ object["process_id"],
446
+ object["processId"],
447
+ object["pid"],
448
+ metadata?.["process_id"],
449
+ metadata?.["processId"],
450
+ metadata?.["pid"],
451
+ ]) {
452
+ if (typeof candidate === "number" &&
453
+ Number.isSafeInteger(candidate) &&
454
+ candidate > 0) {
455
+ processIDs.add(BigInt(candidate));
456
+ continue;
457
+ }
458
+ if (typeof candidate === "string" &&
459
+ /^[1-9][0-9]{0,18}$/u.test(candidate)) {
460
+ try {
461
+ processIDs.add(BigInt(candidate));
462
+ }
463
+ catch {
464
+ invalidProcessID = true;
465
+ }
466
+ continue;
467
+ }
468
+ if (candidate !== undefined)
469
+ invalidProcessID = true;
470
+ }
471
+ const conflict = keyValues.size > 1 || processIDs.size > 1;
472
+ return {
473
+ ...(keyValues.size === 1
474
+ ? { processKey: [...keyValues][0] }
475
+ : {}),
476
+ ...(processIDs.size === 1
477
+ ? { processID: [...processIDs][0] }
478
+ : {}),
479
+ conflict,
480
+ coverageComplete: keyValues.size === 1 &&
481
+ !invalidKeyClaim &&
482
+ !invalidProcessID &&
483
+ !conflict,
484
+ };
485
+ }
486
+ const embeddedSessionAdapters = new Set(["generic", "opencode"]);
487
+ /**
488
+ * Uses a provider-reported session only on adapters whose records carry that
489
+ * identity per event. Missing, invalid, or conflicting claims fail closed to
490
+ * the source-file identity so concurrent transcripts are never guessed into
491
+ * one conversation.
492
+ */
493
+ export function reportedSessionID(adapterID, record, sourceID) {
494
+ if (!embeddedSessionAdapters.has(adapterID))
495
+ return sourceID;
496
+ const object = objectValue(record);
497
+ if (object === null)
498
+ return sourceID;
499
+ const metadata = objectValue(object["metadata"]);
500
+ const values = new Set();
501
+ for (const candidate of [
502
+ object["session_id"],
503
+ object["sessionId"],
504
+ object["sessionID"],
505
+ object["thread_id"],
506
+ object["threadId"],
507
+ object["conversation_id"],
508
+ object["conversationId"],
509
+ metadata?.["session_id"],
510
+ metadata?.["sessionId"],
511
+ metadata?.["sessionID"],
512
+ metadata?.["thread_id"],
513
+ metadata?.["threadId"],
514
+ ]) {
515
+ if (typeof candidate === "string" &&
516
+ candidate === candidate.trim() &&
517
+ Buffer.byteLength(candidate, "utf8") <= 128 &&
518
+ /^[^\u0000-\u001f\u007f]+$/u.test(candidate)) {
519
+ values.add(candidate);
520
+ }
521
+ }
522
+ return values.size === 1 ? [...values][0] ?? sourceID : sourceID;
523
+ }
524
+ function vendorType(record) {
525
+ const object = objectValue(record);
526
+ if (object === null)
527
+ return "record";
528
+ const outer = stringField(object, "type") || "record";
529
+ const payload = objectValue(object["payload"]);
530
+ const inner = stringField(payload, "type");
531
+ return inner === "" || inner === outer ? outer : `${outer}/${inner}`;
532
+ }
533
+ function configuredSources(config) {
534
+ return [
535
+ {
536
+ adapterId: "codex",
537
+ roots: config.activitySourceDirectories.codex,
538
+ },
539
+ {
540
+ adapterId: "claude",
541
+ roots: config.activitySourceDirectories.claude,
542
+ },
543
+ {
544
+ adapterId: "hermes",
545
+ roots: config.activitySourceDirectories.hermes,
546
+ },
547
+ {
548
+ adapterId: "openclaw",
549
+ roots: config.activitySourceDirectories.openclaw,
550
+ },
551
+ {
552
+ adapterId: "copilot",
553
+ roots: config.activitySourceDirectories.copilot,
554
+ },
555
+ {
556
+ adapterId: "opencode",
557
+ roots: config.activitySourceDirectories.opencode,
558
+ format: "opencode-sqlite",
559
+ },
560
+ {
561
+ adapterId: "generic",
562
+ roots: config.activitySourceDirectories.generic,
563
+ },
564
+ ...activityBridgeAgents.map((agent) => ({
565
+ adapterId: agent.id,
566
+ roots: [join(config.dataDirectory, "bridges", agent.id)],
567
+ })),
568
+ ];
569
+ }
570
+ class MinuteRateLimiter {
571
+ #limit;
572
+ #accepted = [];
573
+ constructor(limit) {
574
+ this.#limit = limit;
575
+ }
576
+ remaining(now) {
577
+ const threshold = now.getTime() - 60_000;
578
+ while (this.#accepted.length > 0 &&
579
+ (this.#accepted[0] ?? 0) <= threshold) {
580
+ this.#accepted.shift();
581
+ }
582
+ return Math.max(0, this.#limit - this.#accepted.length);
583
+ }
584
+ consume(now, count) {
585
+ for (let index = 0; index < count; index++)
586
+ this.#accepted.push(now.getTime());
587
+ }
588
+ }
589
+ function fallbackAgentID(kind, adapterId, sourceId) {
590
+ return `agt_${createHash("sha256")
591
+ .update(`phigon-activity-v2:${kind}:${adapterId}:${sourceId}`)
592
+ .digest("hex")
593
+ .slice(0, 32)}`;
594
+ }
595
+ function sourceIdentityDisplayName(adapterID, sourceID, sourceDisplayName) {
596
+ const configured = activityBridgeAgents.find((agent) => agent.id === adapterID)?.displayName;
597
+ const product = sourceDisplayName ?? configured ?? (() => {
598
+ switch (adapterID) {
599
+ case "claude": return "Claude Code";
600
+ case "codex": return "OpenAI Codex";
601
+ case "copilot": return "GitHub Copilot CLI";
602
+ case "hermes": return "Hermes Agent";
603
+ case "openclaw": return "OpenClaw";
604
+ case "opencode": return "OpenCode";
605
+ default: return "Agent activity";
606
+ }
607
+ })();
608
+ const sourceSuffix = sourceID.replace(/[^a-zA-Z0-9]/gu, "").slice(-8);
609
+ return `${product} · Source ${sourceSuffix || "unknown"} (unattributed)`
610
+ .slice(0, 128);
611
+ }
612
+ /**
613
+ * Keeps user-provided custom bridge identity independent from vendor claims.
614
+ * A single consistent label can name an unattributed source, while conflicts,
615
+ * invalid claims, and missing evidence always fail closed.
616
+ */
617
+ export function reportedGenericAgentIdentity(record, configuredDisplayName) {
618
+ const object = objectValue(record);
619
+ if (object === null) {
620
+ return { conflict: false, coverageComplete: false };
621
+ }
622
+ const metadata = objectValue(object["metadata"]);
623
+ const values = new Map();
624
+ let invalidClaim = false;
625
+ for (const candidate of [
626
+ configuredDisplayName,
627
+ object["phigon_agent_name"],
628
+ object["agent_id"],
629
+ object["agentId"],
630
+ object["agent"],
631
+ object["agent_name"],
632
+ object["agentName"],
633
+ object["source"],
634
+ object["provider"],
635
+ metadata?.["agent"],
636
+ metadata?.["source"],
637
+ ]) {
638
+ if (candidate === undefined)
639
+ continue;
640
+ if (typeof candidate !== "string" ||
641
+ candidate !== candidate.trim() ||
642
+ candidate.length === 0 ||
643
+ Buffer.byteLength(candidate, "utf8") > 128 ||
644
+ /[\u0000-\u001f\u007f]/u.test(candidate)) {
645
+ invalidClaim = true;
646
+ continue;
647
+ }
648
+ const hint = normalizeAgentHint(candidate);
649
+ if (hint === "") {
650
+ invalidClaim = true;
651
+ continue;
652
+ }
653
+ if (!values.has(hint))
654
+ values.set(hint, candidate);
655
+ }
656
+ if (invalidClaim || values.size !== 1) {
657
+ return {
658
+ conflict: values.size > 1,
659
+ coverageComplete: false,
660
+ };
661
+ }
662
+ const [hint, displayName] = values.entries().next().value ?? [];
663
+ if (hint === undefined || displayName === undefined) {
664
+ return { conflict: false, coverageComplete: false };
665
+ }
666
+ return {
667
+ hint,
668
+ displayName,
669
+ conflict: false,
670
+ coverageComplete: true,
671
+ };
672
+ }
673
+ export function registeredAgentActivitySources(registrations) {
674
+ return registrations
675
+ .filter((registration) => registration.activityDirectories.length > 0)
676
+ .map((registration) => ({
677
+ adapterId: "generic",
678
+ roots: registration.activityDirectories,
679
+ sourceDisplayName: registration.displayName,
680
+ }));
681
+ }
682
+ function normalizeAgentHint(value) {
683
+ return value
684
+ .toLowerCase()
685
+ .replace(/[^a-z0-9]+/gu, "-")
686
+ .replace(/^-+|-+$/gu, "");
687
+ }
688
+ function clampObservedAt(value, now) {
689
+ if (Number.isNaN(value.getTime()))
690
+ return now;
691
+ if (value.getTime() > now.getTime() + 5 * 60_000)
692
+ return now;
693
+ return value;
694
+ }
695
+ async function abortableDelay(milliseconds, signal) {
696
+ if (signal.aborted)
697
+ return;
698
+ await new Promise((resolve) => {
699
+ const timeout = setTimeout(resolve, milliseconds);
700
+ signal.addEventListener("abort", () => {
701
+ clearTimeout(timeout);
702
+ resolve();
703
+ }, { once: true });
704
+ });
705
+ }
706
+ //# sourceMappingURL=collector.js.map