failproofai 1.0.2-beta.8 → 1.0.2

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 (165) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +4 -4
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  10. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  11. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
  18. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  21. package/.next/standalone/.next/server/app/api/audit/invite/route.js +3 -2
  22. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -3
  24. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +2 -2
  27. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +4 -3
  29. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/logout/route.js +4 -4
  31. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/auth/status/route.js +4 -4
  33. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  36. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  38. package/.next/standalone/.next/server/app/index.html +1 -1
  39. package/.next/standalone/.next/server/app/index.rsc +14 -14
  40. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
  41. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  42. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  43. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  44. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  47. package/.next/standalone/.next/server/app/policies/page.js +4 -4
  48. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  50. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  51. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  54. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  55. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  58. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  60. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
  61. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/chunks/[externals]__0-9ti7z._.js +3 -0
  64. package/.next/standalone/.next/server/chunks/{[externals]__1lt47k4._.js → [externals]__0sg9-3p._.js} +1 -1
  65. package/.next/standalone/.next/server/chunks/[externals]__0u3wrvq._.js +3 -0
  66. package/.next/standalone/.next/server/chunks/[root-of-the-server]__01eqny5._.js +3 -0
  67. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1p8poxd._.js → [root-of-the-server]__0igxt32._.js} +2 -2
  68. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  69. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zlqo2t._.js +3 -0
  70. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1anxb5k._.js +3 -0
  71. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1le9jqc._.js +1 -1
  72. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1p-qi2t._.js +5 -0
  73. package/.next/standalone/.next/server/chunks/_09dz7xv._.js +27 -0
  74. package/.next/standalone/.next/server/chunks/_0bs-v8p._.js +3 -0
  75. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +3 -0
  76. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +3 -0
  77. package/.next/standalone/.next/server/chunks/{_19uwam-._.js → _1-akg6w._.js} +2 -2
  78. package/.next/standalone/.next/server/chunks/_185gyk9._.js +3 -0
  79. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +5 -7
  80. package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_09d5c79._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_04op_ou._.js} +1 -1
  81. package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_1d2g73o._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_0dr20uz._.js} +1 -1
  82. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  83. package/.next/standalone/.next/server/chunks/src_hooks_0iu54mz._.js +3 -0
  84. package/.next/standalone/.next/server/chunks/src_hooks_custom-hooks-loader_ts_0lnb3n3._.js +10 -0
  85. package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
  87. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
  88. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
  89. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
  90. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
  91. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n_lxhg._.js +5 -0
  92. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
  93. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
  94. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
  95. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
  96. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1yh7hlv._.js +3 -0
  97. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  98. package/.next/standalone/.next/server/chunks/ssr/_0ehudfr._.js +23 -0
  99. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1n2ywfz._.js → _1es2j7i._.js} +4 -4
  100. package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
  101. package/.next/standalone/.next/server/chunks/ssr/{_1h33neq._.js → _1un1pug._.js} +1 -1
  102. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +9 -9
  104. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  106. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  107. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1cv9_c4._.js +10 -0
  109. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
  110. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  111. package/.next/standalone/.next/server/middleware.js +1 -1
  112. package/.next/standalone/.next/server/pages/404.html +1 -1
  113. package/.next/standalone/.next/server/pages/500.html +1 -1
  114. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  115. package/.next/standalone/.next/server/server-reference-manifest.json +19 -19
  116. package/.next/standalone/.next/static/chunks/0nkpwjk01ei3t.js +1 -0
  117. package/.next/standalone/.next/static/chunks/{2iryw37qfqy5y.js → 0ofdelz65_517.js} +1 -1
  118. package/.next/standalone/.next/static/chunks/{34j7nmidlcuni.js → 12uhnpwgsmcev.js} +1 -1
  119. package/.next/standalone/.next/static/chunks/{0i3a6wf-f_yky.js → 1_1eb_149xyt9.js} +1 -1
  120. package/.next/standalone/.next/static/chunks/{3927pu4ss_l4k.js → 1tx9pnxyjrkoj.js} +1 -1
  121. package/.next/standalone/.next/static/chunks/{1n04wzsaes73g.js → 1x0jrl3a4_i2m.js} +1 -1
  122. package/.next/standalone/.next/static/chunks/{3r0udrtpn78-e.js → 1zpv6omeln7al.js} +1 -1
  123. package/.next/standalone/.next/static/chunks/{416zumre3fvfw.js → 20hbg-r3io_ip.js} +1 -1
  124. package/.next/standalone/.next/static/chunks/{11a_m8yksthtf.js → 32bhi32ym8yrz.js} +2 -2
  125. package/.next/standalone/.next/static/chunks/{0u2ojcw25c_np.js → 3fr78ugeb4tjc.js} +1 -1
  126. package/.next/standalone/app/actions/get-hooks-config.ts +8 -1
  127. package/.next/standalone/app/actions/pack-actions.ts +12 -1
  128. package/.next/standalone/app/policies/hooks-client.tsx +41 -4
  129. package/.next/standalone/fp-cloud-cli/tests/test_pagination.py +204 -0
  130. package/.next/standalone/package.json +9 -9
  131. package/.next/standalone/server.js +1 -1
  132. package/README.md +58 -13
  133. package/bin/failproofai.mjs +10 -1
  134. package/dist/cli.mjs +22429 -21292
  135. package/dist/worker.mjs +1247 -540
  136. package/package.json +9 -9
  137. package/src/audit/index.ts +24 -4
  138. package/src/hooks/builtin-policies.ts +933 -8
  139. package/src/hooks/custom-hooks-loader.ts +98 -8
  140. package/src/hooks/handler.ts +26 -14
  141. package/src/hooks/manager.ts +36 -2
  142. package/src/hooks/pack-cli.ts +415 -42
  143. package/src/hooks/pack-failclosed.ts +100 -4
  144. package/src/hooks/pack-manifest.ts +29 -0
  145. package/src/hooks/pack-param-key.ts +36 -0
  146. package/src/hooks/pack-store.ts +101 -9
  147. package/src/hooks/policy-catalog.ts +9 -1
  148. package/src/hooks/policy-evaluator.ts +77 -1
  149. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06cuf1y._.js +0 -3
  150. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_usx0j._.js +0 -3
  151. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_zk340._.js +0 -3
  152. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jnjf2t._.js +0 -3
  153. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oy4kxb._.js +0 -3
  154. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zf034w._.js +0 -3
  155. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tg4pu6._.js +0 -3
  156. package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +0 -3
  157. package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +0 -3
  158. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0mgrjnx._.js +0 -10
  159. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-wzs7f._.js +0 -3
  160. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1wlvpe5._.js +0 -5
  161. package/.next/standalone/.next/server/chunks/ssr/_0l7zv8b._.js +0 -23
  162. package/.next/standalone/.next/static/chunks/1ch5l9t2p16y4.js +0 -1
  163. /package/.next/standalone/.next/static/{NgD5HvuyPxwgrpeIiafJL → 5-xDMxcnrcXDFPQiy3yhg}/_buildManifest.js +0 -0
  164. /package/.next/standalone/.next/static/{NgD5HvuyPxwgrpeIiafJL → 5-xDMxcnrcXDFPQiy3yhg}/_clientMiddlewareManifest.js +0 -0
  165. /package/.next/standalone/.next/static/{NgD5HvuyPxwgrpeIiafJL → 5-xDMxcnrcXDFPQiy3yhg}/_ssgManifest.js +0 -0
@@ -59,16 +59,40 @@ export const PERMANENT_LOAD_FAILURES: ReadonlySet<string> = new Set([
59
59
  "path_missing",
60
60
  ]);
61
61
 
62
+ /**
63
+ * A declared list, or null when it cannot be read as one.
64
+ *
65
+ * Null means UNKNOWN, and unknown has to widen the deny rather than narrow it —
66
+ * this whole function exists to say where a missing guard applied, and a
67
+ * narrowing derived from metadata nobody can parse says nothing true.
68
+ *
69
+ * A malformed list is not hypothetical: `match` was validated only as
70
+ * `typeof === "object"`, so a manifest declaring `events: "PreToolUse"` reached
71
+ * here as a STRING, was iterated character by character, and narrowed the
72
+ * fail-closed deny to `["P","r","e","T","o","l","U","s"]` — a set matching no
73
+ * event that exists. The pack failed to load, the guard fired on nothing, and
74
+ * the machine went on running unguarded with a deny it never used. `events: 5`
75
+ * was worse still: `for (const e of 5)` throws, on the hook path.
76
+ */
77
+ function declaredList(value: unknown): string[] | null {
78
+ if (value === undefined || value === null) return null;
79
+ if (!Array.isArray(value)) return null;
80
+ if (value.some((entry) => typeof entry !== "string" || entry.length === 0)) return null;
81
+ return value as string[];
82
+ }
83
+
62
84
  function unionMatch(matchers: PolicyMatcher[]): PolicyMatcher {
63
85
  const events = new Set<HookEventType>();
64
86
  const toolNames = new Set<string>();
65
87
  let anyEvent = false;
66
88
  let anyTool = false;
67
89
  for (const m of matchers) {
68
- if (!m.events || m.events.length === 0) anyEvent = true;
69
- else for (const e of m.events) events.add(e);
70
- if (!m.toolNames || m.toolNames.length === 0) anyTool = true;
71
- else for (const t of m.toolNames) toolNames.add(t);
90
+ const declaredEvents = declaredList(m?.events);
91
+ const declaredTools = declaredList(m?.toolNames);
92
+ if (!declaredEvents || declaredEvents.length === 0) anyEvent = true;
93
+ else for (const e of declaredEvents) events.add(e as HookEventType);
94
+ if (!declaredTools || declaredTools.length === 0) anyTool = true;
95
+ else for (const t of declaredTools) toolNames.add(t);
72
96
  }
73
97
  const scoped: PolicyMatcher = {};
74
98
  // Every declared event is kept, INCLUDING UserPromptSubmit. This says where
@@ -88,6 +112,26 @@ function unionMatch(matchers: PolicyMatcher[]): PolicyMatcher {
88
112
  * user took 3 of 40 from is not a failure because the other 37 did not load.
89
113
  * `disabled` is the `disabledCustomPolicies` set, keyed `pack:<id>@<ver>:<name>`.
90
114
  */
115
+ /**
116
+ * True when a pack scoped to specific agents does not cover the one running.
117
+ *
118
+ * The registration path already skips a pack whose `clis` excludes this agent;
119
+ * the fail-closed path did not, so a pack scoped to `codex` that failed to load
120
+ * denied on `claude` too — locking an agent out over enforcement it was never
121
+ * configured to have, until a human repaired a pack it does not use. `null` or
122
+ * absent means every agent, as it does everywhere else.
123
+ */
124
+ function outOfScope(clis: string[] | null | undefined, cli: string | undefined): boolean {
125
+ if (!cli) return false;
126
+ // `Array.isArray`, not truthiness. A `clis` of `"codex"` is a truthy value
127
+ // with a `length` and an `includes`, so a string scope silently narrowed this
128
+ // to nothing and skipped the guard for every agent — a check meant to stop
129
+ // over-denying turning into the thing that under-denies. Unreadable scope
130
+ // means every agent, exactly as an unreadable `match` means every event.
131
+ if (!Array.isArray(clis) || clis.length === 0) return false;
132
+ return !clis.every((c) => typeof c === "string") ? false : !clis.includes(cli);
133
+ }
134
+
91
135
  export function missingGuards(input: {
92
136
  errors: PackError[];
93
137
  packs: ResolvedPack[];
@@ -96,6 +140,8 @@ export function missingGuards(input: {
96
140
  /** Packs handed to the loader whose entry artifact failed to import. */
97
141
  failed: Map<string, PolicyLoadFailure>;
98
142
  disabled: ReadonlySet<string>;
143
+ /** The agent this evaluation is for, so a pack scoped away from it stays quiet. */
144
+ cli?: string;
99
145
  }): MissingGuard[] {
100
146
  const out: MissingGuard[] = [];
101
147
 
@@ -104,6 +150,7 @@ export function missingGuards(input: {
104
150
  // An observe pack denying on failure would deny for something that, had it
105
151
  // loaded, would have allowed.
106
152
  if (err.effect === "observe") continue;
153
+ if (outOfScope(err.clis, input.cli)) continue;
107
154
  const declared = err.declared ?? [];
108
155
  out.push({
109
156
  packId: err.id ?? "(unnamed pack)",
@@ -119,6 +166,7 @@ export function missingGuards(input: {
119
166
  // (c) Resolved, but registered less than it declared.
120
167
  for (const pack of input.packs) {
121
168
  if (pack.effect === "observe") continue;
169
+ if (outOfScope(pack.clis, input.cli)) continue;
122
170
  const loadFailure = input.failed.get(pack.id);
123
171
  if (loadFailure && PERMANENT_LOAD_FAILURES.has(loadFailure.type)) {
124
172
  const taken = pack.enabled ?? pack.policies.map((p) => p.name);
@@ -172,6 +220,54 @@ export function missingGuards(input: {
172
220
  * because the agent cannot run it: `block-failproofai-commands` denies every
173
221
  * `failproofai` invocation from a tool call, deliberately and unconditionally.
174
222
  */
223
+ /**
224
+ * One matcher covering every missing guard, for the single policy that stands
225
+ * in for all of them.
226
+ *
227
+ * Narrow only where EVERY guard is narrow: a guard that declared no events
228
+ * applied everywhere, so a union that dropped it would deny less than the packs
229
+ * did. Both axes by the same rule — `toolNames` used to be left out of the
230
+ * combined object entirely, which reads as "every tool", so two failed packs
231
+ * each scoped to Bash denied Write and Read as well. One failed pack narrowed
232
+ * correctly and two widened to everything, which is the wrong way round:
233
+ * combining two limited scopes cannot produce a larger one.
234
+ */
235
+ /**
236
+ * True when at least one guard actually applied to this event and tool.
237
+ *
238
+ * `combinedGuardMatch` unions the two axes independently, and the registry ANDs
239
+ * them — so guards scoped to (PreToolUse, Bash) and (PostToolUse, Write) produce
240
+ * a matcher that also catches (PreToolUse, Write) and (PostToolUse, Bash), pairs
241
+ * neither pack ever asked to guard. The union cannot be tightened without
242
+ * losing dispatch: the matcher has to be a SUPERSET or the policy is never
243
+ * reached. So the matcher stays wide enough to be called, and the pairing is
244
+ * checked here, where the real event and tool are known.
245
+ */
246
+ export function guardsCover(
247
+ guards: MissingGuard[],
248
+ eventType: string,
249
+ toolName: string | undefined,
250
+ ): boolean {
251
+ return guards.some((g) => {
252
+ const events = g.match.events;
253
+ if (events && events.length > 0 && !events.includes(eventType as (typeof events)[number])) {
254
+ return false;
255
+ }
256
+ const tools = g.match.toolNames;
257
+ if (tools && tools.length > 0 && (!toolName || !tools.includes(toolName))) return false;
258
+ return true;
259
+ });
260
+ }
261
+
262
+ export function combinedGuardMatch(guards: MissingGuard[]): PolicyMatcher {
263
+ if (guards.length === 1) return guards[0].match;
264
+ const axis = <K extends "events" | "toolNames">(key: K): PolicyMatcher[K] | undefined =>
265
+ guards.every((g) => g.match[key]?.length)
266
+ ? ([...new Set(guards.flatMap((g) => g.match[key] ?? []))] as PolicyMatcher[K])
267
+ : undefined;
268
+ return { events: axis("events"), toolNames: axis("toolNames") };
269
+ }
270
+
175
271
  export function packFailureReason(guards: MissingGuard[]): string {
176
272
  const named = guards
177
273
  .map((g) => {
@@ -157,6 +157,14 @@ export interface PackError {
157
157
  * Lets the deny name what is missing instead of being blanket.
158
158
  */
159
159
  declared?: PolicyCatalogEntry[];
160
+ /**
161
+ * The agents this pack was scoped to, when the manifest got far enough to say.
162
+ *
163
+ * Carried for the same reason `effect` is. A pack scoped to one CLI that fails
164
+ * to load must not deny on the others: they were never guarded by it, so a
165
+ * deny on their behalf locks an agent out over enforcement it never had.
166
+ */
167
+ clis?: string[] | null;
160
168
  }
161
169
 
162
170
  export interface PackReadResult {
@@ -253,6 +261,19 @@ export function parsePackPolicy(packId: string, value: unknown, index: number):
253
261
  if (!raw.match || typeof raw.match !== "object") {
254
262
  throw new Error(`${where} is missing a match`);
255
263
  }
264
+ // The SHAPE, not just the presence. `match` was accepted as any object, so a
265
+ // manifest declaring `events: "PreToolUse"` installed cleanly and then
266
+ // narrowed the fail-closed deny to the letters of that string — a guard
267
+ // matching no event that exists. Refused at install now, where the publisher
268
+ // can still fix it, rather than surviving as metadata nothing can read.
269
+ const matchShape = raw.match as { events?: unknown; toolNames?: unknown };
270
+ for (const key of ["events", "toolNames"] as const) {
271
+ const value = matchShape[key];
272
+ if (value === undefined) continue;
273
+ if (!Array.isArray(value) || value.some((e) => typeof e !== "string" || e.length === 0)) {
274
+ throw new Error(`${where} has a match.${key} that is not a list of names`);
275
+ }
276
+ }
256
277
  return raw as unknown as PolicyCatalogEntry;
257
278
  }
258
279
 
@@ -390,6 +411,14 @@ export function readInstalledPacks(): PackReadResult {
390
411
  // Best effort: an entry too malformed to list policies yields nothing
391
412
  // here, and a deny built from it is unavoidably blanket.
392
413
  ...(Array.isArray(rec?.policies) ? { declared: safeDeclared(rec.policies) } : {}),
414
+ // A list of names, or nothing. Anything else is unreadable scope, and
415
+ // unreadable scope has to mean "every agent" — the same reasoning that
416
+ // widens an unreadable `match`: a narrowing nobody can parse says
417
+ // nothing true, and here the narrowing would be the thing that lets an
418
+ // unguarded agent through.
419
+ ...(Array.isArray(rec?.clis) && rec.clis.every((c) => typeof c === "string")
420
+ ? { clis: rec.clis }
421
+ : {}),
393
422
  });
394
423
  }
395
424
  }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The config key a pack policy's parameters are stored under.
3
+ *
4
+ * A LEAF module on purpose: no imports at all, so it can be reached from the
5
+ * browser. `packPolicyParamKey` used to live in `policy-evaluator.ts`, which
6
+ * the dashboard's client component then imported — dragging `pack-store` and
7
+ * its `node:fs` into the browser bundle and failing the Next build with
8
+ * `Module not found: Can't resolve 'fs/promises'`. The key is pure string
9
+ * formatting and belongs where both sides can have it.
10
+ *
11
+ * VERSION-LESS, and that is the whole design. A pack policy registers as
12
+ * `pack/<id>@<version>/<name>`, so a key carrying the version would be orphaned
13
+ * by the publisher's next release — a parameter somebody set would silently
14
+ * revert to its default on upgrade, which is the same failure `enabled` avoids
15
+ * by outliving the version it was chosen against.
16
+ */
17
+ export function packPolicyParamKey(packId: string, policyName: string): string {
18
+ return `pack/${packId}/${policyName}`;
19
+ }
20
+
21
+ /** `pack/<id>@<version>/<name>` split back into the parts a key is built from,
22
+ * or null when the name is not a pack policy's. */
23
+ export function parsePackPolicyName(
24
+ canonicalName: string,
25
+ ): { packId: string; name: string } | null {
26
+ if (!canonicalName.startsWith("pack/")) return null;
27
+ const rest = canonicalName.slice("pack/".length);
28
+ const slash = rest.lastIndexOf("/");
29
+ if (slash <= 0) return null;
30
+ const idWithVersion = rest.slice(0, slash);
31
+ const at = idWithVersion.lastIndexOf("@");
32
+ return {
33
+ packId: at > 0 ? idWithVersion.slice(0, at) : idWithVersion,
34
+ name: rest.slice(slash + 1),
35
+ };
36
+ }
@@ -906,8 +906,15 @@ export async function addPack(
906
906
  const at = source.lastIndexOf("@");
907
907
  return at > source.indexOf(":") ? source.slice(0, at) : source;
908
908
  };
909
+ // Only when it is the SAME id. This binds an id to the origin it first came
910
+ // from, and `priorRecordFor` also answers with a same-DIGEST record under a
911
+ // different id — for which the check is not just unnecessary but wrong: a
912
+ // second pack that happens to ship identical bytes from another repository is
913
+ // not the installed one being hijacked, and refusing it said `pack id X is
914
+ // already installed from Y` while naming an id the user never asked for.
909
915
  if (
910
916
  prior &&
917
+ prior.id === fetched.id &&
911
918
  !prior.source.startsWith("bundled:") &&
912
919
  repoOf(prior.source) !== repoOf(formatPackSpec(spec))
913
920
  ) {
@@ -954,7 +961,12 @@ export async function addPack(
954
961
  : {}),
955
962
  };
956
963
 
957
- const absorbed = upsertInstalled(record);
964
+ // `--all` is an ANSWER, not a silence. `upsertInstalled` carries an absorbed
965
+ // row's narrower selection onto a record that names none — which is right for
966
+ // a rename nobody expressed an opinion about, and wrong for a caller who just
967
+ // said "everything". Left ungated, `policies add <renamed pack> --all`
968
+ // reported the whole catalog and wrote the old id's one-policy list.
969
+ const absorbed = upsertInstalled(record, reason !== "all");
958
970
  return {
959
971
  replaced: absorbed,
960
972
  id: fetched.id,
@@ -1008,23 +1020,93 @@ export function setPackPolicyEnabled(
1008
1020
  return { ok: true };
1009
1021
  }
1010
1022
 
1011
- export function removePack(id: string): boolean {
1023
+ /**
1024
+ * The spellings of a pack id that `remove` accepts.
1025
+ *
1026
+ * Exactly one used to work — the stored id, byte for byte — and it was a form
1027
+ * shown nowhere on its own, so every spelling a user could SEE or had TYPED
1028
+ * failed:
1029
+ *
1030
+ * add failproofai/policies stores `FailproofAI/policies`
1031
+ * remove failproofai/policies no installed pack with id …
1032
+ * remove FailproofAI/policies@06b802b63f4f no installed pack with id …
1033
+ *
1034
+ * The first is what they installed it with — GitHub is case-insensitive, so
1035
+ * `add` accepts any case and then records the CANONICAL id off the manifest.
1036
+ * The second is the listing's own heading, copied. Both are refused, and the
1037
+ * one that works appears only as half of that heading. A pack whose owner
1038
+ * happens to be lowercase (`chhhee10/deploy-guard`) removes on the first try,
1039
+ * which is what makes this look like the core pack being unremovable rather
1040
+ * than a name-matching bug.
1041
+ *
1042
+ * So: case-insensitive, and an `@<version>` suffix is dropped. A pack id cannot
1043
+ * contain `@` — `PACK_ID_RE` forbids it — so splitting at the last one is
1044
+ * unambiguous. The version is not checked against what is installed: there is
1045
+ * only ever one row per id, and refusing `pack@1.0.0` because 1.0.1 is
1046
+ * installed would be the same unhelpfulness in a new hat.
1047
+ */
1048
+ function packIdMatches(stored: string, typed: string): boolean {
1049
+ return bareId(stored).toLowerCase() === bareId(typed).toLowerCase();
1050
+ }
1051
+
1052
+ /** The id with any `@<version>` suffix and surrounding space removed, CASE
1053
+ * INTACT — the exact-match pass needs the original spelling. */
1054
+ function bareId(value: string): string {
1055
+ const trimmed = value.trim();
1056
+ const at = trimmed.lastIndexOf("@");
1057
+ return (at > 0 ? trimmed.slice(0, at) : trimmed).trim();
1058
+ }
1059
+
1060
+ /** Two installed packs answer to one loosely-typed name. Thrown rather than
1061
+ * guessed at: the caller prints the canonical ids so the user can say which. */
1062
+ export class AmbiguousPackId extends Error {
1063
+ constructor(readonly candidates: string[], typed: string) {
1064
+ super(
1065
+ `${typed} matches ${candidates.length} installed packs: ${candidates.join(", ")}. ` +
1066
+ `Name one of them exactly.`,
1067
+ );
1068
+ this.name = "AmbiguousPackId";
1069
+ }
1070
+ }
1071
+
1072
+ /** The id actually removed — the CANONICAL one, not the spelling that was
1073
+ * typed — or null when nothing matched. Callers report it back so a user who
1074
+ * typed a different case learns the name the machine holds. */
1075
+ export function removePack(id: string): string | null {
1012
1076
  const manifestPath = resolve(packsRoot(), "installed.json");
1013
- if (!existsSync(manifestPath)) return false;
1077
+ if (!existsSync(manifestPath)) return null;
1014
1078
  let raw: { schemaVersion?: number; packs?: InstalledPackRecord[] };
1015
1079
  try {
1016
1080
  raw = JSON.parse(readFileSync(manifestPath, "utf8"));
1017
1081
  } catch {
1018
- return false;
1082
+ return null;
1019
1083
  }
1020
1084
  const packs = Array.isArray(raw.packs) ? raw.packs : [];
1021
- const remaining = packs.filter((p) => p?.id !== id);
1022
- if (remaining.length === packs.length) return false;
1085
+ // EXACT first, and a loose match only when it is the only one.
1086
+ //
1087
+ // Ids are stored and upserted with `===`, so `Acme/guard` and `acme/guard`
1088
+ // are two rows on one machine — and a `find()` over the loose matcher then
1089
+ // removed whichever happened to sit first, which is not the pack that was
1090
+ // named. A convenience for typing a name is not worth uninstalling something
1091
+ // else, so an ambiguous name is REFUSED and the candidates are printed:
1092
+ // asking again with the exact id is a keystroke, and the alternative is
1093
+ // silently deactivating a pack the user still wanted enforcing.
1094
+ const exact = packs.find((p) => p?.id === bareId(id));
1095
+ const loose = packs.filter((p) => p?.id && packIdMatches(p.id, id));
1096
+ if (!exact && loose.length > 1) {
1097
+ throw new AmbiguousPackId(
1098
+ loose.map((p) => p.id).filter((v): v is string => typeof v === "string"),
1099
+ id,
1100
+ );
1101
+ }
1102
+ const removed = exact ?? loose[0];
1103
+ const remaining = packs.filter((p) => p !== removed);
1104
+ if (!removed || remaining.length === packs.length) return null;
1023
1105
  // The artifact is left on disk deliberately: it is content-addressed and inert
1024
1106
  // once nothing points at it, so keeping it makes a re-add offline-safe. Same
1025
1107
  // choice the cloud reconciler makes.
1026
1108
  writeAtomic(manifestPath, JSON.stringify({ schemaVersion: 1, packs: remaining }, null, 2) + "\n");
1027
- return true;
1109
+ return removed.id;
1028
1110
  }
1029
1111
 
1030
1112
  /**
@@ -1047,7 +1129,17 @@ export function removePack(id: string): boolean {
1047
1129
  * say so — an earlier version deleted the old row silently, taking the user's
1048
1130
  * selection and the enforcement it gave them with it.
1049
1131
  */
1050
- function upsertInstalled(record: InstalledPackRecord): string[] {
1132
+ function upsertInstalled(
1133
+ record: InstalledPackRecord,
1134
+ /**
1135
+ * False when the record's absent `enabled` is an EXPRESSED "everything"
1136
+ * (`--all`) rather than an unexpressed one. Carrying there overrides the
1137
+ * user's own answer with a set they left behind under the old id, and the
1138
+ * returned `AddedPack` still reports the whole catalog — installed says
1139
+ * three, disk enforces one.
1140
+ */
1141
+ carryAbsorbedSelection = true,
1142
+ ): string[] {
1051
1143
  const manifestPath = resolve(packsRoot(), "installed.json");
1052
1144
  let packs: InstalledPackRecord[] = [];
1053
1145
  if (existsSync(manifestPath)) {
@@ -1068,7 +1160,7 @@ function upsertInstalled(record: InstalledPackRecord): string[] {
1068
1160
  .map((p) => p.id);
1069
1161
  // The selection the user had under the old id is theirs — carry it, rather
1070
1162
  // than resetting them to defaults because a publisher renamed something.
1071
- if (!record.enabled) {
1163
+ if (carryAbsorbedSelection && !record.enabled) {
1072
1164
  const prior = packs.find((p) => absorbed.includes(p?.id));
1073
1165
  const carried = prior?.enabled?.filter((n) =>
1074
1166
  (record.policies as Array<{ name?: unknown }> | undefined)?.some((rp) => rp?.name === n),
@@ -169,7 +169,15 @@ export const POLICY_CATALOG: PolicyCatalogEntry[] = [
169
169
  // PermissionRequest is carried over from the merged-in `block-self-pause`.
170
170
  // It is a real enforcement point on Copilot and Devin, and dropping it would
171
171
  // have left this guard blind on both.
172
- match: { events: ["PreToolUse", "PermissionRequest"], toolNames: ["Bash"] },
172
+ // Write/Edit are here because the Bash-only surface left the shortest way
173
+ // through this guard unguarded: the agent never needs a shell to overwrite
174
+ // `~/.failproofai/policies-config.json` with `{"enabledPolicies":[]}` — it
175
+ // just writes the file. Every CLI canonicalizes its own file tool's path
176
+ // key to `file_path`, so one branch covers all of them.
177
+ match: {
178
+ events: ["PreToolUse", "PermissionRequest"],
179
+ toolNames: ["Bash", "Write", "Edit", "NotebookEdit"],
180
+ },
173
181
  defaultEnabled: true,
174
182
  alwaysOn: true,
175
183
  category: "Dangerous Commands",
@@ -4,6 +4,16 @@
4
4
  */
5
5
  import type { HookEventType, SessionMetadata } from "./types";
6
6
  import type { PolicyContext, HooksConfig } from "./policy-types";
7
+ // Read from the layer that owns it rather than restated here — restating a
8
+ // pack id is exactly how `failproofai/builtins` and `failproofai/core` both
9
+ // outlived their rename. This is on the hook path, so the cost was measured
10
+ // rather than assumed: bundling policy-evaluator with this import is 38,627
11
+ // bytes against 37,491 without it, because only the constant survives
12
+ // tree-shaking. 1.1 KB is not worth a second copy of a name that has already
13
+ // drifted twice.
14
+ import { CORE_SOURCE } from "./pack-store";
15
+ import { packPolicyParamKey, parsePackPolicyName } from "./pack-param-key";
16
+ export { packPolicyParamKey } from "./pack-param-key";
7
17
  import { DEFAULT_POLICY_NAMESPACE, getPoliciesForEvent } from "./policy-registry";
8
18
  import { hookLogInfo, hookLogWarn } from "./hook-logger";
9
19
  import { trackHookEvent } from "./hook-telemetry";
@@ -28,6 +38,61 @@ export interface EvaluationResult {
28
38
  }
29
39
 
30
40
 
41
+ /**
42
+ * The config key a PACK policy's parameters are stored under.
43
+ *
44
+ * Version-less on purpose. A pack policy registers as
45
+ * `pack/<id>@<version>/<name>`, so a key carrying the version would be orphaned
46
+ * by every republish — the parameters would read as unset the moment the pack
47
+ * was upgraded, which is the same failure `enabled` avoids by outliving the
48
+ * version it was chosen against.
49
+ *
50
+ * Exported because the DASHBOARD writes this key and the evaluator reads it.
51
+ * They disagreed before — the dashboard wrote the bare policy name while the
52
+ * evaluator looked up the fully qualified one and fell back to bare only inside
53
+ * the `failproofai/` namespace — so a parameter saved through the UI was
54
+ * displayed as saved and ignored at runtime, on every pack including our own.
55
+ * One function so the two cannot drift again.
56
+ */
57
+
58
+ /**
59
+ * The parameters a PACK policy actually runs with, resolved out of a config's
60
+ * `policyParams` map: the stable qualified key first, then the BARE name for
61
+ * our own pack alone.
62
+ *
63
+ * The bare read is the migration. Every `policyParams["block-sudo"]` already on
64
+ * disk — written by a build that predates packs, or by the dashboard before it
65
+ * qualified its keys — means the builtin under the name it always had.
66
+ *
67
+ * It is scoped to our pack because a policy name is unique only WITHIN a pack:
68
+ * two installed packs may each declare a `block-sudo`, and a bare key cannot
69
+ * say which was meant. Handing a stranger's pack our pack's configuration runs
70
+ * a third party's code on parameters chosen for ours.
71
+ *
72
+ * Exported because the DASHBOARD's read side resolves the same lookup, and it
73
+ * resolved it differently — an UNSCOPED bare fallback — so a stranger's pack
74
+ * declaring `block-sudo` was SHOWN our saved parameters while this function
75
+ * handed that policy the schema defaults. The config modal seeds its inputs
76
+ * from what was shown and Save writes them back under the stranger's own key,
77
+ * which is the point a display lie turns into configuration that really runs.
78
+ * One function so the two cannot diverge again.
79
+ */
80
+ export function readPackPolicyParams(
81
+ policyParams: Record<string, Record<string, unknown>> | undefined,
82
+ packId: string,
83
+ policyName: string,
84
+ ): Record<string, unknown> | undefined {
85
+ if (!policyParams) return undefined;
86
+ const qualified = policyParams[packPolicyParamKey(packId, policyName)];
87
+ if (qualified) return qualified;
88
+ // Case-insensitively: the id reaches here from a manifest and from a source
89
+ // somebody typed, and GitHub treats `failproofai/policies` and
90
+ // `FailproofAI/policies` as one repository.
91
+ if (packId.toLowerCase() === CORE_SOURCE.toLowerCase()) return policyParams[policyName];
92
+ return undefined;
93
+ }
94
+
95
+
31
96
  /**
32
97
  * Look up policy params for a canonical policy name in the user config,
33
98
  * tolerating either flat ("block-force-push") or qualified
@@ -35,7 +100,9 @@ export interface EvaluationResult {
35
100
  *
36
101
  * The flat-key fallback is intentionally limited to the default namespace
37
102
  * so namespace isolation is preserved: `policyParams.foo` only matches
38
- * `failproofai/foo`, never `myorg/foo` or `custom/foo`.
103
+ * `failproofai/foo`, never `myorg/foo` or `custom/foo`. A `pack/...` name gets
104
+ * the same isolation from `readPackPolicyParams` and returns before reaching
105
+ * that branch, so the two fallbacks never both apply to one name.
39
106
  */
40
107
  function getConfigParamsFor(
41
108
  config: HooksConfig | undefined,
@@ -44,6 +111,15 @@ function getConfigParamsFor(
44
111
  if (!config?.policyParams) return undefined;
45
112
  const canonicalParams = config.policyParams[canonicalName];
46
113
  if (canonicalParams) return canonicalParams;
114
+
115
+ // A pack policy: qualified key, then the bare name for our pack only. Shared
116
+ // with the dashboard's read side rather than restated, so what is displayed
117
+ // stays what runs.
118
+ const packPolicy = parsePackPolicyName(canonicalName);
119
+ if (packPolicy) {
120
+ return readPackPolicyParams(config.policyParams, packPolicy.packId, packPolicy.name);
121
+ }
122
+
47
123
  const defaultPrefix = `${DEFAULT_POLICY_NAMESPACE}/`;
48
124
  if (!canonicalName.startsWith(defaultPrefix)) return undefined;
49
125
  return config.policyParams[canonicalName.slice(defaultPrefix.length)];
@@ -1,3 +0,0 @@
1
- module.exports=[66680,(e,t,s)=>{t.exports=e.x("node:crypto",()=>require("node:crypto"))},2157,(e,t,s)=>{t.exports=e.x("node:fs",()=>require("node:fs"))},60526,(e,t,s)=>{t.exports=e.x("node:os",()=>require("node:os"))},64828,e=>{"use strict";var t=e.i(79708),s=e.i(3605),n=e.i(28898),i=e.i(83534),r=e.i(28557);async function a(){let e=[];for(let{profile:t,dbPath:n}of(0,s.hermesDbPaths)())e.push(...await o(n,t));return e.sort((e,t)=>t.mtimeMs-e.mtimeMs),e}async function o(e,n){let i=await (0,t.openSqliteReadonly)(e);if(!i)return[];try{return i.query("SELECT s.id, s.source, s.cwd, s.title, s.user_id, s.chat_id, s.chat_type, s.started_at, s.ended_at, s.message_count, lm.last_activity FROM sessions s LEFT JOIN (SELECT session_id, MAX(timestamp) AS last_activity FROM messages GROUP BY session_id) lm ON lm.session_id = s.id ORDER BY lm.last_activity DESC").map(e=>({sessionId:e.id,profile:n,source:e.source??void 0,cwd:e.cwd??void 0,title:e.title??void 0,userId:e.user_id??void 0,chatId:e.chat_id??void 0,chatType:e.chat_type??void 0,mtimeMs:(0,s.epochToMs)(e.last_activity??e.ended_at??e.started_at),messageCount:"number"==typeof e.message_count?e.message_count:0,hasMessages:null!=e.last_activity}))}catch{return[]}finally{i.close()}}let l=(0,i.runtimeCache)(a,2);async function u(){let e=await a(),t=new Map;for(let s of e){if(s.messageCount<=0&&!s.hasMessages)continue;let e=s.profile||n.HERMES_DEFAULT_PROFILE,i=s.source??"unknown",r=JSON.stringify([e,i]),a=t.get(r);a?(a.latest=Math.max(a.latest,s.mtimeMs),a.count+=1):t.set(r,{profile:e,source:i,latest:s.mtimeMs,count:1})}let s=[];for(let{profile:e,source:i,latest:a,count:o}of t.values()){let t=new Date(a);s.push({name:(0,n.hermesProjectName)(e,i),path:(0,n.hermesProjectPath)(e,i),isDirectory:!0,lastModified:t,lastModifiedFormatted:(0,r.formatDate)(t),cli:["hermes"],sessionCount:o})}return s.sort((e,t)=>t.lastModified.getTime()-e.lastModified.getTime()),s}async function m(e){let t=(0,n.hermesProjectNameCandidates)(e);if(0===t.length)return{cwd:null,sessions:[]};let s=await a(),i=e=>s.filter(t=>(t.messageCount>0||t.hasMessages)&&(t.profile||n.HERMES_DEFAULT_PROFILE)===e.profile&&(t.source??"unknown")===e.source),o=t[0],l=i(o);if(0===l.length)for(let e of t.slice(1)){let t=i(e);if(t.length>0){o=e,l=t;break}}let{profile:u,source:m}=o;return{cwd:(0,n.hermesProjectPath)(u,m),sessions:l.map(e=>{let t=new Date(e.mtimeMs);return{name:e.title??e.sessionId,path:`hermes://${e.sessionId}`,lastModified:t,lastModifiedFormatted:(0,r.formatDate)(t),sessionId:e.sessionId,cli:"hermes",userId:e.userId,channelId:e.chatId,channelType:e.chatType}})}}let c=(0,i.runtimeCache)(u,2),f=(0,i.runtimeCache)(e=>m(e),2,{maxSize:50});e.s(["getCachedHermesProjects",0,c,"getCachedHermesSessions",0,l,"getCachedHermesSessionsByEncodedName",0,f,"getHermesProjects",0,u,"getHermesSessions",0,a,"getHermesSessionsByEncodedName",0,m])},3605,28898,e=>{"use strict";var t=e.i(50227),s=e.i(79708),n=e.i(2157),i=e.i(60526);let r="profiles",a="default";function o(){let e,s=function(){let e=(process.env.HERMES_HOME||"").trim();if(e){let s=(0,t.resolve)(e),n=(0,t.dirname)(s);return(0,t.basename)(n)===r?(0,t.dirname)(n):s}return(0,t.join)((0,i.homedir)(),".hermes")}(),o=[{name:a,home:s}],l=new Set([a]);try{e=(0,n.readdirSync)((0,t.join)(s,r),{withFileTypes:!0}).filter(e=>(e.isDirectory()||e.isSymbolicLink())&&!e.name.startsWith(".")).map(e=>e.name).sort()}catch{return o}for(let n of e)l.has(n)||(l.add(n),o.push({name:n,home:(0,t.join)(s,r,n)}));return o}function l(e,t){return`hermes:${e}:${t}`}e.s(["HERMES_DEFAULT_PROFILE",0,a,"hermesProjectName",0,function(e,t){return`hermes-${e}-${t}`},"hermesProjectNameCandidates",0,function(e){if(!e.startsWith("hermes-"))return[];let t=e.slice(7);if(!t)return[];let s=[];for(let e of o().map(e=>e.name).sort((e,t)=>t.length-e.length)){let n=`${e}-`;t.startsWith(n)&&t.length>n.length&&s.push({profile:e,source:t.slice(n.length)})}return s.push({profile:a,source:t}),s},"hermesProjectPath",0,l,"listHermesProfiles",0,o],28898);var u=e.i(83534),m=e.i(54214),c=e.i(67405);function f(){let e=process.env.HERMES_DB_PATH;return e?[{profile:a,dbPath:e}]:o().map(e=>({profile:e.name,dbPath:(0,t.join)(e.home,"state.db")}))}function d(e){if("string"==typeof e&&0!==e.length)try{return JSON.parse(e)}catch{return}}function p(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function h(e){return"string"==typeof e?e:Array.isArray(e)?e.map(e=>p(e)&&"string"==typeof e.text?e.text:"").filter(Boolean).join("\n"):""}async function y(e){if(!e||!/^[A-Za-z0-9_-]+$/.test(e))return null;for(let{profile:t,dbPath:s}of f()){let n=await g(s,t,e);if(n)return n}return null}async function g(e,t,n){let i=await (0,s.openSqliteReadonly)(e);if(!i)return null;try{let e=i.query("SELECT source, cwd FROM sessions WHERE id = ?",[n]);if(0===e.length)return null;let{source:s,cwd:r}=e[0],a=i.query("SELECT id, role, content, tool_call_id, tool_calls, tool_name, timestamp FROM messages WHERE session_id = ? ORDER BY timestamp ASC",[n]),o=function(e,t="session"){let s=[],n=new Map,i=new Map,r=Date.now();for(let a=0;a<e.length;a++){let o=e[a];if(!p(o))continue;let l="string"==typeof o.role?o.role:"system",u=function(e,t){if("number"==typeof e&&Number.isFinite(e)){if(e>1e12)return new Date(e);if(e>1e9)return new Date(1e3*e)}if("string"==typeof e){let t=Date.parse(e);if(!Number.isNaN(t))return new Date(t)}return new Date(t)}(o.timestamp??o.time_created,r+a),f=u.toISOString(),y={uuid:null!=o.id?String(o.id):`hermes-${a}`,parentUuid:null},g=(0,m.baseEntry)(y,f,u,t);if("user"===l){s.push({type:"user",...g,message:{role:"user",content:h(o.content)}});continue}if("assistant"===l){let e=[],t=h(o.content);for(let s of(t&&e.push({type:"text",text:t}),function(e){let t=Array.isArray(e)?e:d(e);if(!Array.isArray(t))return[];let s=[];for(let e of t){if(!p(e))continue;let t=p(e.function)?e.function:{},n="string"==typeof t.name?t.name:"string"==typeof e.name?e.name:"tool",i="string"==typeof e.id&&e.id||"string"==typeof e.call_id&&e.call_id||`${n}-${s.length}`,r=p(t.arguments)?t.arguments:d(t.arguments);s.push({id:i,name:n,input:p(r)?r:{}})}return s}(o.tool_calls))){let t={type:"tool_use",id:s.id,name:s.name,input:s.input};e.push(t),n.set(s.id,t),i.set(s.id,u.getTime())}if(0===e.length)continue;s.push({type:"assistant",...g,message:{role:"assistant",content:e}});continue}if("tool"===l){let e="string"==typeof o.tool_call_id?o.tool_call_id:void 0,t=e?n.get(e):void 0;if(t){let s=e&&i.get(e)||u.getTime(),n=Math.max(0,u.getTime()-s);t.result={timestamp:f,timestampFormatted:(0,m.formatTimestamp)(u),content:h(o.content),durationMs:n,durationFormatted:(0,c.formatDuration)(n)};continue}}s.push({type:"system",...g,raw:y})}return s.sort((e,t)=>e.timestampMs-t.timestampMs),s}(a,"session"),u=r&&r.length>0?r:s?l(t,s):void 0;return{entries:o,rawLines:a,cwd:u,filePath:`hermes://${n}`,profile:t}}catch{return null}finally{i.close()}}(0,u.runtimeCache)(e=>y(e),2,{maxSize:50}),e.s(["epochToMs",0,function(e){if("number"==typeof e&&Number.isFinite(e)){if(e>1e12)return e;if(e>1e9)return 1e3*e}return Date.now()},"getHermesSessionLog",0,y,"hermesDbPaths",0,f],3605)},54214,67405,e=>{"use strict";var t=e.i(24868),s=e.i(14747),n=e.i(81580),i=e.i(56936);async function r(e,n,i,r){let a=`agent-${r}.jsonl`;for(let r of[(0,s.join)(e,n,a),(0,s.join)(e,n,i,a),(0,s.join)(e,n,i,"subagents",a)])if(!(0,s.relative)(e,r).startsWith(".."))try{return await (0,t.access)(r),r}catch(e){if("ENOENT"===e.code)continue;break}return null}var a=e.i(83534),o=e.i(71809),l=e.i(28557);function u(e){if(e<1e3)return`${e}ms`;let t=Math.round(e/100);if(t<600)return`${(t/10).toFixed(1)}s`;let s=Math.round(e/1e3);if(s<3600){let e=Math.floor(s/60);return`${e}m ${s%60}s`}let n=Math.round(e/6e4),i=Math.floor(n/60);return`${i}h ${n%60}m`}function m(e){let t=(0,l.formatDate)(e),s=e.getMilliseconds().toString().padStart(3,"0");return`${t}.${s}`}function c(e,t,s,n){return{_source:n,uuid:e.uuid||"",parentUuid:e.parentUuid??null,timestamp:t,timestampMs:s.getTime(),timestampFormatted:m(s)}}async function f(e,t){let s=e.split("\n").filter(e=>""!==e.trim()),n=new Map,i=[],r=[],a=new Set,o=!1;for(let e=0;e<s.length;e++){let l;e>0&&e%200==0&&await new Promise(e=>setImmediate(e));let u=s[e];try{l=JSON.parse(u)}catch{continue}let m={...l,_source:t};r.push(m);let f=l.type,d=l.timestamp;if(!d)continue;let p=new Date(d),h=p.getTime();if("user"===f){let e=l.message;if(Array.isArray(e?.content)){let t=e.content;if(t.some(e=>"tool_result"===e.type)){let e=l.toolUseResult,s="string"==typeof e?.agentId?e.agentId:void 0;for(let e of(s&&/^[a-f0-9]+$/.test(s)&&a.add(s),t)){if("tool_result"!==e.type)continue;let t=e.tool_use_id;if(!t)continue;let{text:i,images:r}=function(e){let t=e.content;if("string"==typeof t)return{text:t};if(Array.isArray(t)){let e=t.filter(e=>"text"===e.type).map(e=>e.text),s=t.filter(e=>"image"===e.type).map(e=>{let t=e.source;return{base64:t.data,mediaType:t.media_type}}).filter(e=>e.base64&&e.mediaType);return{text:e.length>0?e.join("\n"):void 0,images:s.length>0?s:void 0}}return{}}(e);n.set(t,{timestamp:d,timestampMs:h,content:i,images:r,agentId:s})}continue}}let s="string"==typeof e?.content?e.content:"";i.push({type:"user",...c(l,d,p,t),message:{role:"user",content:s}});continue}if("assistant"===f){let e=l.message,s=[];if(Array.isArray(e?.content)&&(s=e.content.filter(e=>["text","tool_use","thinking"].includes(e.type)).map(e=>{if("text"===e.type)return{type:"text",text:e.text};if("tool_use"===e.type){let t=e.input;return{type:"tool_use",id:e.id,name:e.name,input:e.input??{},..."Task"===e.name&&t?{subagentType:t.subagent_type,subagentDescription:t.description}:{}}}return{type:"thinking",thinking:e.thinking,signature:e.signature}})),0===s.length)continue;i.push({type:"assistant",...c(l,d,p,t),message:{role:"assistant",content:s,model:e?.model}});continue}if("file-history-snapshot"===f||"progress"===f||"system"===f){i.push({type:f,...c(l,d,p,t),raw:{...l}});continue}if("queue-operation"===f){let e=o?"Session Resumed":"Session Started";o=!0,i.push({type:"queue-operation",...c(l,d,p,t),label:e});continue}}let l=0;for(let e of i)if("assistant"===e.type)for(let t of(++l%200==0&&await new Promise(e=>setImmediate(e)),e.message.content)){if("tool_use"!==t.type)continue;let s=n.get(t.id);if(!s)continue;let i=new Date(s.timestamp),r=Math.max(0,s.timestampMs-e.timestampMs);t.result={timestamp:s.timestamp,timestampFormatted:m(i),content:s.content,images:s.images,durationMs:r,durationFormatted:u(r)},s.agentId&&(t.subagentId=s.agentId)}return i.length>500&&await new Promise(e=>setImmediate(e)),i.sort((e,t)=>e.timestampMs-t.timestampMs),{entries:i,rawLines:r,subagentIds:Array.from(a)}}async function d(e,t="session"){return(await f(e,t)).entries}async function p(e,a){let l=(0,i.resolveProjectPath)(e),u=(0,n.getClaudeProjectsPath)(),m=(0,s.join)(l,`${a}.jsonl`),c=await (0,t.readFile)(m,"utf-8"),{entries:d,rawLines:p,subagentIds:h}=await f(c,"session");if(0===h.length)return{entries:d,rawLines:p,subagentIds:[]};let y=await (0,o.batchAll)(h.map(s=>async()=>{let n=`agent-${s}`,i=await r(u,e,a,s);if(!i)return null;let o=await (0,t.readFile)(i,"utf-8"),{entries:l,rawLines:m}=await f(o,n);return{entries:l,rawLines:m}}),4),g=[...d],_=[...p];for(let e of y)"fulfilled"===e.status&&e.value&&(g.push(...e.value.entries),_.push(...e.value.rawLines));return g.length>500&&await new Promise(e=>setImmediate(e)),g.sort((e,t)=>e.timestampMs-t.timestampMs),{entries:g,rawLines:_,subagentIds:h}}e.s(["formatDuration",0,u],67405),(0,a.runtimeCache)((e,t)=>p(e,t),60,{maxSize:50}),e.s(["baseEntry",0,c,"formatTimestamp",0,m,"parseLogContent",0,d,"parseRawLines",0,function(e,t){return e.split("\n").filter(e=>""!==e.trim()).flatMap(e=>{try{let s=JSON.parse(e);return void 0!==t&&(s._source=t),[s]}catch{return[]}})}],54214)}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__06cuf1y._.js.map
@@ -1,3 +0,0 @@
1
- module.exports=[70406,(e,t,r)=>{t.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},18622,(e,t,r)=>{t.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},20635,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/action-async-storage.external.js",()=>require("next/dist/server/app-render/action-async-storage.external.js"))},24725,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},56704,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},59043,(e,t,r)=>{t.exports=e.x("next/dist/server/runtime-reacts.external.js",()=>require("next/dist/server/runtime-reacts.external.js"))},93695,(e,t,r)=>{t.exports=e.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},74533,(e,t,r)=>{t.exports=e.x("node:child_process",()=>require("node:child_process"))},66680,(e,t,r)=>{t.exports=e.x("node:crypto",()=>require("node:crypto"))},2157,(e,t,r)=>{t.exports=e.x("node:fs",()=>require("node:fs"))},60526,(e,t,r)=>{t.exports=e.x("node:os",()=>require("node:os"))},50227,(e,t,r)=>{t.exports=e.x("node:path",()=>require("node:path"))},81111,(e,t,r)=>{t.exports=e.x("node:stream",()=>require("node:stream"))},94930,e=>{"use strict";var t=e.i(2157),r=e.i(50227),n=e.i(66680);e.s(["writeJsonAtomically",0,function(e,s,o={}){let a=o.mode??384,i=o.dirMode??448,c=(0,r.dirname)(e);(0,t.existsSync)(c)||(0,t.mkdirSync)(c,{recursive:!0,mode:i});let u=`${e}.${process.pid}.${(0,n.randomBytes)(6).toString("hex")}.tmp`;try{(0,t.writeFileSync)(u,JSON.stringify(s,null,2),{mode:a});try{(63&(0,t.statSync)(u).mode)!=0&&(0,t.chmodSync)(u,a)}catch{}(0,t.renameSync)(u,e);try{(63&(0,t.statSync)(e).mode)!=0&&(0,t.chmodSync)(e,a)}catch{}}catch(e){try{(0,t.rmSync)(u,{force:!0})}catch{}throw e}}])},6375,e=>{"use strict";var t=e.i(46501);function r(){return(process.env.FAILPROOF_API_URL??process.env.FAILPROOFAI_API_URL??"https://api.befailproof.ai").replace(/\/+$/,"")}class n extends Error{status;code;retryAfterSecs;constructor(e,t,r,n){super(r),this.status=e,this.code=t,this.retryAfterSecs=n,this.name="AuthApiError"}}async function s(e){let t={};try{t=await e.json()}catch{}let r=t.code??`http_${e.status}`,s=t.message??t.detail??e.statusText??"request failed",o=t.retry_after_secs;if(void 0===o){let t=e.headers.get("retry-after");if(t){let e=Number(t);Number.isFinite(e)&&(o=e)}}return void 0!==o&&(o=Math.max(0,Math.min(86400,o))),new n(e.status,r,s,o)}async function o(e,r){try{return await fetch(e,{...r,signal:function(e){let t=AbortSignal.timeout(1e4);if(!e)return t;let r=AbortSignal.any;if(r)return r([t,e]);let n=new AbortController;if(t.aborted)n.abort(t.reason);else t.addEventListener("abort",()=>n.abort(t.reason),{once:!0});if(e.aborted)n.abort(e.reason);else e.addEventListener("abort",()=>n.abort(e.reason),{once:!0});return n.signal}(r.signal??void 0)})}catch(o){let s=function(e){if(null===e||"object"!=typeof e)return!1;let t=e.name;return"AbortError"===t||"TimeoutError"===t}(o);if((0,t.trackEvent)("api_server_unreachable",{kind:s?"timeout":"network",path:function(e){try{return new URL(e).pathname}catch{return e}}(e),method:"string"==typeof r.method?r.method:"GET"}),s)throw new n(0,"timeout",`request to ${e} timed out after 10000ms`);throw o}}async function a(e,t,n){let a={"content-type":"application/json"};n?.accessToken&&(a.authorization=`Bearer ${n.accessToken}`);let i=await o(`${r()}${e}`,{method:"POST",headers:a,body:JSON.stringify(t)});if(204!==i.status){if(!i.ok)throw await s(i);return await i.json()}}async function i(e,t){let n=await o(`${r()}${e}`,{method:"GET",headers:{authorization:`Bearer ${t}`}});if(!n.ok)throw await s(n);return await n.json()}async function c(e){return a("/v0/auth/login/request",{email:e})}async function u(e,t){return a("/v0/auth/login/verify",{email:e,code:t})}async function l(e){return a("/v0/auth/token/refresh",{refresh_token:e})}async function f(e,t){await a("/v0/auth/logout",{refresh_token:t},{accessToken:e})}async function d(e){return i("/v0/auth/me",e)}async function p(e,t,r){return a("/v0/invite",void 0===r?{to:t}:{to:t,score:r},{accessToken:e})}e.s(["AuthApiError",0,n,"fetchMe",0,d,"logoutSession",0,f,"refreshAccessToken",0,l,"requestLoginCode",0,c,"sendInvites",0,p,"verifyLoginCode",0,u],6375)},17707,e=>{"use strict";var t=e.i(2157),r=e.i(50227),n=e.i(94930),s=e.i(79857),o=e.i(6375);function a(){let e=process.env.FAILPROOFAI_AUTH_DIR;return e?(0,r.join)(e,"session.json"):(0,s.auditSessionFile)()}function i(){let e=a();if(!(0,t.existsSync)(e))return null;try{let r=(0,t.readFileSync)(e,"utf-8"),n=JSON.parse(r);if("string"!=typeof n.access_token||"string"!=typeof n.refresh_token||"number"!=typeof n.access_expires_at||"object"!=typeof n.user||!n.user||"string"!=typeof n.user.id||"string"!=typeof n.user.email)return null;return{access_token:n.access_token,refresh_token:n.refresh_token,access_expires_at:n.access_expires_at,refresh_expires_at:"number"==typeof n.refresh_expires_at?n.refresh_expires_at:n.access_expires_at,user:{id:n.user.id,email:n.user.email}}}catch{return null}}function c(e){(0,n.writeJsonAtomically)(a(),e)}function u(){let e=a();(0,t.existsSync)(e)&&(0,t.rmSync)(e,{force:!0});try{let e=(0,s.migrationsDir)();if(!(0,t.existsSync)(e))return;for(let n of(0,t.readdirSync)(e)){if(!n.startsWith("backup-layout"))continue;let s=(0,r.resolve)(e,n,"auth.json");(0,t.existsSync)(s)&&(0,t.rmSync)(s,{force:!0})}}catch{}}function l(e,t){let r=Math.floor(Date.now()/1e3),n=e.user??t;if(!n)throw Error("authFromTokenResponse: missing user identity");return{access_token:e.access_token,refresh_token:e.refresh_token,access_expires_at:r+e.access_expires_in,refresh_expires_at:r+e.refresh_expires_in,user:n}}let f=new Map;async function d(e){let t=f.get(e.refresh_token);if(t)return t;let r=(async()=>{let t=l(await (0,o.refreshAccessToken)(e.refresh_token),e.user);return c(t),t})();f.set(e.refresh_token,r);try{return await r}finally{f.delete(e.refresh_token)}}async function p(){let e=i();if(!e)return null;let t=Math.floor(Date.now()/1e3);if(e.access_expires_at-t>60)return e;try{return await d(e)}catch(e){return e instanceof o.AuthApiError&&401===e.status&&u(),null}}async function h(){let e=await p();if(!e)return null;try{return{me:await (0,o.fetchMe)(e.access_token),auth:e}}catch(e){if(e instanceof o.AuthApiError&&401===e.status){let e=i();if(!e)return null;try{let t=await d(e);return{me:await (0,o.fetchMe)(t.access_token),auth:t}}catch(e){e instanceof o.AuthApiError&&401===e.status&&u()}}return null}}e.s(["authFromTokenResponse",0,l,"deleteAuth",0,u,"readAuth",0,i,"whoAmI",0,h,"writeAuth",0,c])},78081,e=>{e.v(t=>Promise.all(["server/chunks/[externals]__0qxhecv._.js","server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js"].map(t=>e.l(t))).then(()=>t(39702)))}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0_usx0j._.js.map
@@ -1,3 +0,0 @@
1
- module.exports=[70406,(e,t,r)=>{t.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},18622,(e,t,r)=>{t.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},20635,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/action-async-storage.external.js",()=>require("next/dist/server/app-render/action-async-storage.external.js"))},24725,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},56704,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},59043,(e,t,r)=>{t.exports=e.x("next/dist/server/runtime-reacts.external.js",()=>require("next/dist/server/runtime-reacts.external.js"))},93695,(e,t,r)=>{t.exports=e.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},74533,(e,t,r)=>{t.exports=e.x("node:child_process",()=>require("node:child_process"))},66680,(e,t,r)=>{t.exports=e.x("node:crypto",()=>require("node:crypto"))},2157,(e,t,r)=>{t.exports=e.x("node:fs",()=>require("node:fs"))},60526,(e,t,r)=>{t.exports=e.x("node:os",()=>require("node:os"))},50227,(e,t,r)=>{t.exports=e.x("node:path",()=>require("node:path"))},81111,(e,t,r)=>{t.exports=e.x("node:stream",()=>require("node:stream"))},94930,e=>{"use strict";var t=e.i(2157),r=e.i(50227),n=e.i(66680);e.s(["writeJsonAtomically",0,function(e,s,o={}){let a=o.mode??384,i=o.dirMode??448,c=(0,r.dirname)(e);(0,t.existsSync)(c)||(0,t.mkdirSync)(c,{recursive:!0,mode:i});let u=`${e}.${process.pid}.${(0,n.randomBytes)(6).toString("hex")}.tmp`;try{(0,t.writeFileSync)(u,JSON.stringify(s,null,2),{mode:a});try{(63&(0,t.statSync)(u).mode)!=0&&(0,t.chmodSync)(u,a)}catch{}(0,t.renameSync)(u,e);try{(63&(0,t.statSync)(e).mode)!=0&&(0,t.chmodSync)(e,a)}catch{}}catch(e){try{(0,t.rmSync)(u,{force:!0})}catch{}throw e}}])},6375,e=>{"use strict";var t=e.i(46501);function r(){return(process.env.FAILPROOF_API_URL??process.env.FAILPROOFAI_API_URL??"https://api.befailproof.ai").replace(/\/+$/,"")}class n extends Error{status;code;retryAfterSecs;constructor(e,t,r,n){super(r),this.status=e,this.code=t,this.retryAfterSecs=n,this.name="AuthApiError"}}async function s(e){let t={};try{t=await e.json()}catch{}let r=t.code??`http_${e.status}`,s=t.message??t.detail??e.statusText??"request failed",o=t.retry_after_secs;if(void 0===o){let t=e.headers.get("retry-after");if(t){let e=Number(t);Number.isFinite(e)&&(o=e)}}return void 0!==o&&(o=Math.max(0,Math.min(86400,o))),new n(e.status,r,s,o)}async function o(e,r){try{return await fetch(e,{...r,signal:function(e){let t=AbortSignal.timeout(1e4);if(!e)return t;let r=AbortSignal.any;if(r)return r([t,e]);let n=new AbortController;if(t.aborted)n.abort(t.reason);else t.addEventListener("abort",()=>n.abort(t.reason),{once:!0});if(e.aborted)n.abort(e.reason);else e.addEventListener("abort",()=>n.abort(e.reason),{once:!0});return n.signal}(r.signal??void 0)})}catch(o){let s=function(e){if(null===e||"object"!=typeof e)return!1;let t=e.name;return"AbortError"===t||"TimeoutError"===t}(o);if((0,t.trackEvent)("api_server_unreachable",{kind:s?"timeout":"network",path:function(e){try{return new URL(e).pathname}catch{return e}}(e),method:"string"==typeof r.method?r.method:"GET"}),s)throw new n(0,"timeout",`request to ${e} timed out after 10000ms`);throw o}}async function a(e,t,n){let a={"content-type":"application/json"};n?.accessToken&&(a.authorization=`Bearer ${n.accessToken}`);let i=await o(`${r()}${e}`,{method:"POST",headers:a,body:JSON.stringify(t)});if(204!==i.status){if(!i.ok)throw await s(i);return await i.json()}}async function i(e,t){let n=await o(`${r()}${e}`,{method:"GET",headers:{authorization:`Bearer ${t}`}});if(!n.ok)throw await s(n);return await n.json()}async function c(e){return a("/v0/auth/login/request",{email:e})}async function u(e,t){return a("/v0/auth/login/verify",{email:e,code:t})}async function l(e){return a("/v0/auth/token/refresh",{refresh_token:e})}async function f(e,t){await a("/v0/auth/logout",{refresh_token:t},{accessToken:e})}async function d(e){return i("/v0/auth/me",e)}async function p(e,t,r){return a("/v0/invite",void 0===r?{to:t}:{to:t,score:r},{accessToken:e})}e.s(["AuthApiError",0,n,"fetchMe",0,d,"logoutSession",0,f,"refreshAccessToken",0,l,"requestLoginCode",0,c,"sendInvites",0,p,"verifyLoginCode",0,u],6375)},17707,e=>{"use strict";var t=e.i(2157),r=e.i(50227),n=e.i(94930),s=e.i(79857),o=e.i(6375);function a(){let e=process.env.FAILPROOFAI_AUTH_DIR;return e?(0,r.join)(e,"session.json"):(0,s.auditSessionFile)()}function i(){let e=a();if(!(0,t.existsSync)(e))return null;try{let r=(0,t.readFileSync)(e,"utf-8"),n=JSON.parse(r);if("string"!=typeof n.access_token||"string"!=typeof n.refresh_token||"number"!=typeof n.access_expires_at||"object"!=typeof n.user||!n.user||"string"!=typeof n.user.id||"string"!=typeof n.user.email)return null;return{access_token:n.access_token,refresh_token:n.refresh_token,access_expires_at:n.access_expires_at,refresh_expires_at:"number"==typeof n.refresh_expires_at?n.refresh_expires_at:n.access_expires_at,user:{id:n.user.id,email:n.user.email}}}catch{return null}}function c(e){(0,n.writeJsonAtomically)(a(),e)}function u(){let e=a();(0,t.existsSync)(e)&&(0,t.rmSync)(e,{force:!0});try{let e=(0,s.migrationsDir)();if(!(0,t.existsSync)(e))return;for(let n of(0,t.readdirSync)(e)){if(!n.startsWith("backup-layout"))continue;let s=(0,r.resolve)(e,n,"auth.json");(0,t.existsSync)(s)&&(0,t.rmSync)(s,{force:!0})}}catch{}}function l(e,t){let r=Math.floor(Date.now()/1e3),n=e.user??t;if(!n)throw Error("authFromTokenResponse: missing user identity");return{access_token:e.access_token,refresh_token:e.refresh_token,access_expires_at:r+e.access_expires_in,refresh_expires_at:r+e.refresh_expires_in,user:n}}let f=new Map;async function d(e){let t=f.get(e.refresh_token);if(t)return t;let r=(async()=>{let t=l(await (0,o.refreshAccessToken)(e.refresh_token),e.user);return c(t),t})();f.set(e.refresh_token,r);try{return await r}finally{f.delete(e.refresh_token)}}async function p(){let e=i();if(!e)return null;let t=Math.floor(Date.now()/1e3);if(e.access_expires_at-t>60)return e;try{return await d(e)}catch(e){return e instanceof o.AuthApiError&&401===e.status&&u(),null}}async function h(){let e=await p();if(!e)return null;try{return{me:await (0,o.fetchMe)(e.access_token),auth:e}}catch(e){if(e instanceof o.AuthApiError&&401===e.status){let e=i();if(!e)return null;try{let t=await d(e);return{me:await (0,o.fetchMe)(t.access_token),auth:t}}catch(e){e instanceof o.AuthApiError&&401===e.status&&u()}}return null}}e.s(["authFromTokenResponse",0,l,"deleteAuth",0,u,"readAuth",0,i,"whoAmI",0,h,"writeAuth",0,c])},78081,e=>{e.v(t=>Promise.all(["server/chunks/[externals]__0qxhecv._.js","server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js"].map(t=>e.l(t))).then(()=>t(39702)))}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0_zk340._.js.map
@@ -1,3 +0,0 @@
1
- module.exports=[66680,(e,t,n)=>{t.exports=e.x("node:crypto",()=>require("node:crypto"))},2157,(e,t,n)=>{t.exports=e.x("node:fs",()=>require("node:fs"))},60526,(e,t,n)=>{t.exports=e.x("node:os",()=>require("node:os"))},3605,28898,e=>{"use strict";var t=e.i(50227),n=e.i(79708),i=e.i(2157),r=e.i(60526);let s="profiles",a="default";function o(){let e,n=function(){let e=(process.env.HERMES_HOME||"").trim();if(e){let n=(0,t.resolve)(e),i=(0,t.dirname)(n);return(0,t.basename)(i)===s?(0,t.dirname)(i):n}return(0,t.join)((0,r.homedir)(),".hermes")}(),o=[{name:a,home:n}],u=new Set([a]);try{e=(0,i.readdirSync)((0,t.join)(n,s),{withFileTypes:!0}).filter(e=>(e.isDirectory()||e.isSymbolicLink())&&!e.name.startsWith(".")).map(e=>e.name).sort()}catch{return o}for(let i of e)u.has(i)||(u.add(i),o.push({name:i,home:(0,t.join)(n,s,i)}));return o}function u(e,t){return`hermes:${e}:${t}`}e.s(["HERMES_DEFAULT_PROFILE",0,a,"hermesProjectName",0,function(e,t){return`hermes-${e}-${t}`},"hermesProjectNameCandidates",0,function(e){if(!e.startsWith("hermes-"))return[];let t=e.slice(7);if(!t)return[];let n=[];for(let e of o().map(e=>e.name).sort((e,t)=>t.length-e.length)){let i=`${e}-`;t.startsWith(i)&&t.length>i.length&&n.push({profile:e,source:t.slice(i.length)})}return n.push({profile:a,source:t}),n},"hermesProjectPath",0,u,"listHermesProfiles",0,o],28898);var l=e.i(83534),m=e.i(54214),f=e.i(67405);function p(){let e=process.env.HERMES_DB_PATH;return e?[{profile:a,dbPath:e}]:o().map(e=>({profile:e.name,dbPath:(0,t.join)(e.home,"state.db")}))}function c(e){if("string"==typeof e&&0!==e.length)try{return JSON.parse(e)}catch{return}}function d(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function y(e){return"string"==typeof e?e:Array.isArray(e)?e.map(e=>d(e)&&"string"==typeof e.text?e.text:"").filter(Boolean).join("\n"):""}async function h(e){if(!e||!/^[A-Za-z0-9_-]+$/.test(e))return null;for(let{profile:t,dbPath:n}of p()){let i=await g(n,t,e);if(i)return i}return null}async function g(e,t,i){let r=await (0,n.openSqliteReadonly)(e);if(!r)return null;try{let e=r.query("SELECT source, cwd FROM sessions WHERE id = ?",[i]);if(0===e.length)return null;let{source:n,cwd:s}=e[0],a=r.query("SELECT id, role, content, tool_call_id, tool_calls, tool_name, timestamp FROM messages WHERE session_id = ? ORDER BY timestamp ASC",[i]),o=function(e,t="session"){let n=[],i=new Map,r=new Map,s=Date.now();for(let a=0;a<e.length;a++){let o=e[a];if(!d(o))continue;let u="string"==typeof o.role?o.role:"system",l=function(e,t){if("number"==typeof e&&Number.isFinite(e)){if(e>1e12)return new Date(e);if(e>1e9)return new Date(1e3*e)}if("string"==typeof e){let t=Date.parse(e);if(!Number.isNaN(t))return new Date(t)}return new Date(t)}(o.timestamp??o.time_created,s+a),p=l.toISOString(),h={uuid:null!=o.id?String(o.id):`hermes-${a}`,parentUuid:null},g=(0,m.baseEntry)(h,p,l,t);if("user"===u){n.push({type:"user",...g,message:{role:"user",content:y(o.content)}});continue}if("assistant"===u){let e=[],t=y(o.content);for(let n of(t&&e.push({type:"text",text:t}),function(e){let t=Array.isArray(e)?e:c(e);if(!Array.isArray(t))return[];let n=[];for(let e of t){if(!d(e))continue;let t=d(e.function)?e.function:{},i="string"==typeof t.name?t.name:"string"==typeof e.name?e.name:"tool",r="string"==typeof e.id&&e.id||"string"==typeof e.call_id&&e.call_id||`${i}-${n.length}`,s=d(t.arguments)?t.arguments:c(t.arguments);n.push({id:r,name:i,input:d(s)?s:{}})}return n}(o.tool_calls))){let t={type:"tool_use",id:n.id,name:n.name,input:n.input};e.push(t),i.set(n.id,t),r.set(n.id,l.getTime())}if(0===e.length)continue;n.push({type:"assistant",...g,message:{role:"assistant",content:e}});continue}if("tool"===u){let e="string"==typeof o.tool_call_id?o.tool_call_id:void 0,t=e?i.get(e):void 0;if(t){let n=e&&r.get(e)||l.getTime(),i=Math.max(0,l.getTime()-n);t.result={timestamp:p,timestampFormatted:(0,m.formatTimestamp)(l),content:y(o.content),durationMs:i,durationFormatted:(0,f.formatDuration)(i)};continue}}n.push({type:"system",...g,raw:h})}return n.sort((e,t)=>e.timestampMs-t.timestampMs),n}(a,"session"),l=s&&s.length>0?s:n?u(t,n):void 0;return{entries:o,rawLines:a,cwd:l,filePath:`hermes://${i}`,profile:t}}catch{return null}finally{r.close()}}(0,l.runtimeCache)(e=>h(e),2,{maxSize:50}),e.s(["epochToMs",0,function(e){if("number"==typeof e&&Number.isFinite(e)){if(e>1e12)return e;if(e>1e9)return 1e3*e}return Date.now()},"getHermesSessionLog",0,h,"hermesDbPaths",0,p],3605)},54214,67405,e=>{"use strict";var t=e.i(24868),n=e.i(14747),i=e.i(81580),r=e.i(56936);async function s(e,i,r,s){let a=`agent-${s}.jsonl`;for(let s of[(0,n.join)(e,i,a),(0,n.join)(e,i,r,a),(0,n.join)(e,i,r,"subagents",a)])if(!(0,n.relative)(e,s).startsWith(".."))try{return await (0,t.access)(s),s}catch(e){if("ENOENT"===e.code)continue;break}return null}var a=e.i(83534),o=e.i(71809),u=e.i(28557);function l(e){if(e<1e3)return`${e}ms`;let t=Math.round(e/100);if(t<600)return`${(t/10).toFixed(1)}s`;let n=Math.round(e/1e3);if(n<3600){let e=Math.floor(n/60);return`${e}m ${n%60}s`}let i=Math.round(e/6e4),r=Math.floor(i/60);return`${r}h ${i%60}m`}function m(e){let t=(0,u.formatDate)(e),n=e.getMilliseconds().toString().padStart(3,"0");return`${t}.${n}`}function f(e,t,n,i){return{_source:i,uuid:e.uuid||"",parentUuid:e.parentUuid??null,timestamp:t,timestampMs:n.getTime(),timestampFormatted:m(n)}}async function p(e,t){let n=e.split("\n").filter(e=>""!==e.trim()),i=new Map,r=[],s=[],a=new Set,o=!1;for(let e=0;e<n.length;e++){let u;e>0&&e%200==0&&await new Promise(e=>setImmediate(e));let l=n[e];try{u=JSON.parse(l)}catch{continue}let m={...u,_source:t};s.push(m);let p=u.type,c=u.timestamp;if(!c)continue;let d=new Date(c),y=d.getTime();if("user"===p){let e=u.message;if(Array.isArray(e?.content)){let t=e.content;if(t.some(e=>"tool_result"===e.type)){let e=u.toolUseResult,n="string"==typeof e?.agentId?e.agentId:void 0;for(let e of(n&&/^[a-f0-9]+$/.test(n)&&a.add(n),t)){if("tool_result"!==e.type)continue;let t=e.tool_use_id;if(!t)continue;let{text:r,images:s}=function(e){let t=e.content;if("string"==typeof t)return{text:t};if(Array.isArray(t)){let e=t.filter(e=>"text"===e.type).map(e=>e.text),n=t.filter(e=>"image"===e.type).map(e=>{let t=e.source;return{base64:t.data,mediaType:t.media_type}}).filter(e=>e.base64&&e.mediaType);return{text:e.length>0?e.join("\n"):void 0,images:n.length>0?n:void 0}}return{}}(e);i.set(t,{timestamp:c,timestampMs:y,content:r,images:s,agentId:n})}continue}}let n="string"==typeof e?.content?e.content:"";r.push({type:"user",...f(u,c,d,t),message:{role:"user",content:n}});continue}if("assistant"===p){let e=u.message,n=[];if(Array.isArray(e?.content)&&(n=e.content.filter(e=>["text","tool_use","thinking"].includes(e.type)).map(e=>{if("text"===e.type)return{type:"text",text:e.text};if("tool_use"===e.type){let t=e.input;return{type:"tool_use",id:e.id,name:e.name,input:e.input??{},..."Task"===e.name&&t?{subagentType:t.subagent_type,subagentDescription:t.description}:{}}}return{type:"thinking",thinking:e.thinking,signature:e.signature}})),0===n.length)continue;r.push({type:"assistant",...f(u,c,d,t),message:{role:"assistant",content:n,model:e?.model}});continue}if("file-history-snapshot"===p||"progress"===p||"system"===p){r.push({type:p,...f(u,c,d,t),raw:{...u}});continue}if("queue-operation"===p){let e=o?"Session Resumed":"Session Started";o=!0,r.push({type:"queue-operation",...f(u,c,d,t),label:e});continue}}let u=0;for(let e of r)if("assistant"===e.type)for(let t of(++u%200==0&&await new Promise(e=>setImmediate(e)),e.message.content)){if("tool_use"!==t.type)continue;let n=i.get(t.id);if(!n)continue;let r=new Date(n.timestamp),s=Math.max(0,n.timestampMs-e.timestampMs);t.result={timestamp:n.timestamp,timestampFormatted:m(r),content:n.content,images:n.images,durationMs:s,durationFormatted:l(s)},n.agentId&&(t.subagentId=n.agentId)}return r.length>500&&await new Promise(e=>setImmediate(e)),r.sort((e,t)=>e.timestampMs-t.timestampMs),{entries:r,rawLines:s,subagentIds:Array.from(a)}}async function c(e,t="session"){return(await p(e,t)).entries}async function d(e,a){let u=(0,r.resolveProjectPath)(e),l=(0,i.getClaudeProjectsPath)(),m=(0,n.join)(u,`${a}.jsonl`),f=await (0,t.readFile)(m,"utf-8"),{entries:c,rawLines:d,subagentIds:y}=await p(f,"session");if(0===y.length)return{entries:c,rawLines:d,subagentIds:[]};let h=await (0,o.batchAll)(y.map(n=>async()=>{let i=`agent-${n}`,r=await s(l,e,a,n);if(!r)return null;let o=await (0,t.readFile)(r,"utf-8"),{entries:u,rawLines:m}=await p(o,i);return{entries:u,rawLines:m}}),4),g=[...c],w=[...d];for(let e of h)"fulfilled"===e.status&&e.value&&(g.push(...e.value.entries),w.push(...e.value.rawLines));return g.length>500&&await new Promise(e=>setImmediate(e)),g.sort((e,t)=>e.timestampMs-t.timestampMs),{entries:g,rawLines:w,subagentIds:y}}e.s(["formatDuration",0,l],67405),(0,a.runtimeCache)((e,t)=>d(e,t),60,{maxSize:50}),e.s(["baseEntry",0,f,"formatTimestamp",0,m,"parseLogContent",0,c,"parseRawLines",0,function(e,t){return e.split("\n").filter(e=>""!==e.trim()).flatMap(e=>{try{let n=JSON.parse(e);return void 0!==t&&(n._source=t),[n]}catch{return[]}})}],54214)}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0jnjf2t._.js.map