failproofai 1.0.5-beta.0 → 1.0.5-beta.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 (166) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +6 -6
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  6. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  11. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  12. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  15. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  16. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
  20. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  21. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
  22. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -4
  25. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  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.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
  32. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
  34. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  35. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/index.html +1 -1
  38. package/.next/standalone/.next/server/app/index.rsc +14 -14
  39. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
  40. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  41. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  42. package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
  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/build-manifest.json +3 -3
  47. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  48. package/.next/standalone/.next/server/app/policies/page.js +1 -1
  49. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
  52. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  53. package/.next/standalone/.next/server/app/project/[name]/page.js +2 -2
  54. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
  57. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  58. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  59. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +2 -2
  60. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  61. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
  63. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  64. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +3 -3
  67. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
  68. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  69. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  70. package/.next/standalone/.next/server/chunks/{[externals]__0-9ti7z._.js → [externals]__1_bftcl._.js} +1 -1
  71. package/.next/standalone/.next/server/chunks/{[externals]__0u3wrvq._.js → [externals]__1msfs-h._.js} +1 -1
  72. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfu._.js +1 -1
  73. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0faqz9x._.js +22 -0
  74. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  75. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zyc_nm._.js +3 -0
  76. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1p-qi2t._.js → [root-of-the-server]__112b4go._.js} +22 -3
  77. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1l71g3y._.js +22 -0
  78. package/.next/standalone/.next/server/chunks/_09dz7xv._.js +1 -1
  79. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  80. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/{_1-akg6w._.js → _1c3k-8x._.js} +2 -2
  82. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +1 -1
  83. package/.next/standalone/.next/server/chunks/_1vslkoe._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/lib_openclaw-projects_ts_0gc-p24._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1sc84bb._.js → [root-of-the-server]__00y9ww2._.js} +21 -2
  87. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
  88. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
  89. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
  90. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0n_lxhg._.js → [root-of-the-server]__0bym1os._.js} +1 -1
  91. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
  92. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
  93. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
  94. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
  95. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
  96. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__190won8._.js → [root-of-the-server]__0sz_5na._.js} +1 -1
  97. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +1 -1
  98. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1kaotix._.js +22 -0
  99. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
  100. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__00-s7h8._.js → [root-of-the-server]__1u6sn69._.js} +1 -1
  101. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0x1aj1_._.js → [root-of-the-server]__1xu5t8b._.js} +2 -2
  102. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/ssr/{_1if9ixi._.js → _14c6q09._.js} +21 -2
  104. package/.next/standalone/.next/server/chunks/ssr/_1_ozgif._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/_1es2j7i._.js +2 -2
  106. package/.next/standalone/.next/server/chunks/ssr/{_0zs_4uu._.js → _1mo4bp9._.js} +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/{_0u3xxgc._.js → _1olen4g._.js} +2 -2
  108. package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  110. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
  111. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  112. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  113. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  114. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
  115. package/.next/standalone/.next/server/chunks/ssr/lib_openclaw-projects_ts_0qxq3bp._.js +1 -1
  116. package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
  117. package/.next/standalone/.next/server/pages/404.html +1 -1
  118. package/.next/standalone/.next/server/pages/500.html +1 -1
  119. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  120. package/.next/standalone/.next/server/server-reference-manifest.json +19 -19
  121. package/.next/standalone/.next/static/chunks/{0oos8qpc1ugos.js → 04cawl3i7gqi5.js} +1 -1
  122. package/.next/standalone/.next/static/chunks/{0hw6-c206lsma.js → 0671mdu5plc8o.js} +1 -1
  123. package/.next/standalone/.next/static/chunks/{33umhy-x204qj.js → 0cn62s92buqr1.js} +2 -2
  124. package/.next/standalone/.next/static/chunks/{2zafgs90r_leq.js → 0h95tsad4_-gr.js} +1 -1
  125. package/.next/standalone/.next/static/chunks/{3nux7kkrc3eps.js → 0pdmk3xha1zih.js} +1 -1
  126. package/.next/standalone/.next/static/chunks/{40tpgs4fjct5p.js → 1oey07bwm1ayr.js} +1 -1
  127. package/.next/standalone/.next/static/chunks/{0unrx9g_x0u7j.js → 1qwk_vp6dsat_.js} +1 -1
  128. package/.next/standalone/.next/static/chunks/{40uih96wnkowy.js → 2pnvnpg-kdbyt.js} +1 -1
  129. package/.next/standalone/.next/static/chunks/{3i8rg2fv9nd6e.js → 315zh293r-n7v.js} +1 -1
  130. package/.next/standalone/.next/static/chunks/{2xbxkaszi1xnw.js → 3aoj_ov89ym_h.js} +1 -1
  131. package/.next/standalone/.next/static/chunks/{2qjn-leir0x_s.js → 3gfi5ixrc6v1z.js} +1 -1
  132. package/.next/standalone/.next/static/chunks/{0m9sx3khjrl1q.js → 3k3g_4k13t9za.js} +1 -1
  133. package/.next/standalone/.next/static/chunks/{turbopack-3p73obe0xmrxm.js → turbopack-44avr18ueo9ob.js} +1 -1
  134. package/.next/standalone/fp-cloud-cli/CHANGELOG.md +7 -0
  135. package/.next/standalone/fp-cloud-cli/fp_cli/_version.py +1 -1
  136. package/.next/standalone/lib/download-session.ts +58 -13
  137. package/.next/standalone/lib/openclaw-db.ts +271 -0
  138. package/.next/standalone/lib/openclaw-profiles.ts +78 -0
  139. package/.next/standalone/lib/openclaw-projects.ts +57 -21
  140. package/.next/standalone/lib/openclaw-sessions.ts +75 -17
  141. package/.next/standalone/lib/sqlite-reader.ts +165 -9
  142. package/.next/standalone/package.json +9 -9
  143. package/.next/standalone/sdk/python/CHANGELOG.md +7 -0
  144. package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
  145. package/.next/standalone/server.js +1 -1
  146. package/dist/cli.mjs +1065 -693
  147. package/dist/worker.mjs +425 -102
  148. package/lib/download-session.ts +58 -13
  149. package/lib/openclaw-db.ts +271 -0
  150. package/lib/openclaw-profiles.ts +78 -0
  151. package/lib/openclaw-projects.ts +57 -21
  152. package/lib/openclaw-sessions.ts +75 -17
  153. package/lib/sqlite-reader.ts +165 -9
  154. package/openclaw-plugin/index.js +22 -12
  155. package/openclaw-plugin/instruct-retry-gate.js +89 -0
  156. package/openclaw-plugin/workspace-context.js +93 -0
  157. package/package.json +9 -9
  158. package/src/hooks/integrations.ts +22 -14
  159. package/src/hooks/policy-evaluator.ts +22 -3
  160. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +0 -3
  161. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +0 -3
  162. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1le9jqc._.js +0 -3
  163. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +0 -3
  164. /package/.next/standalone/.next/static/{4_QeL7mSPYsuiSVJmBOTj → GDwSJ81wNHeh1pQdxpvk_}/_buildManifest.js +0 -0
  165. /package/.next/standalone/.next/static/{4_QeL7mSPYsuiSVJmBOTj → GDwSJ81wNHeh1pQdxpvk_}/_clientMiddlewareManifest.js +0 -0
  166. /package/.next/standalone/.next/static/{4_QeL7mSPYsuiSVJmBOTj → GDwSJ81wNHeh1pQdxpvk_}/_ssgManifest.js +0 -0
@@ -1,11 +1,9 @@
1
1
  /**
2
2
  * OpenClaw (openclaw gateway) session transcript loader + parser.
3
3
  *
4
- * AUDIT-ONLY (Pillar 2). OpenClaw writes one JSONL transcript per session at
5
- * `~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl` (sessionId is a
6
- * UUID), alongside a much larger `<sessionId>.trajectory.jsonl` OTel trace we
7
- * IGNORE, and a `sessions.json` index keyed by sessionKey. Verified live
8
- * against openclaw v2026.7.1.
4
+ * Legacy OpenClaw writes one JSONL transcript per session under `sessions/`;
5
+ * 2026.9.2+ stores the same logical records as `event_json` rows in each
6
+ * agent's `agent/openclaw-agent.sqlite`. SQLite is preferred when both exist.
9
7
  *
10
8
  * The transcript is type-discriminated JSONL:
11
9
  * {type:"session", cwd, …} — header (carries cwd)
@@ -18,8 +16,8 @@
18
16
  * `toolResult` by `toolCallId` (mirrors lib/hermes-sessions.ts) and is PURE, so
19
17
  * it is unit-testable with plain line objects.
20
18
  *
21
- * Home override: set `OPENCLAW_HOME` (used by tests / to point at a copied
22
- * gateway config dir).
19
+ * Home override: `OPENCLAW_STATE_DIR`, then `OPENCLAW_HOME` (used by tests /
20
+ * to point at a copied gateway config dir).
23
21
  */
24
22
  import { readFile } from "node:fs/promises";
25
23
  import { readdirSync, statSync } from "node:fs";
@@ -39,13 +37,18 @@ import {
39
37
  type LogSource,
40
38
  } from "./log-entries";
41
39
  import { formatDuration } from "./format-duration";
40
+ import { readOpenClawSqliteTranscript } from "./openclaw-db";
42
41
 
43
42
  /** OpenClaw sessions are stored under UUID filenames. */
44
43
  export const OPENCLAW_SESSION_ID_RE = /^[0-9a-fA-F-]{36}$/;
45
44
 
46
- /** Absolute path to OpenClaw's config home (override with OPENCLAW_HOME). */
45
+ /** Absolute path to OpenClaw's state home. */
47
46
  export function openclawHome(): string {
48
- return process.env.OPENCLAW_HOME || join(homedir(), ".openclaw");
47
+ return (
48
+ process.env.OPENCLAW_STATE_DIR ||
49
+ process.env.OPENCLAW_HOME ||
50
+ join(homedir(), ".openclaw")
51
+ );
49
52
  }
50
53
 
51
54
  // ── Parsing helpers ──
@@ -60,7 +63,11 @@ function extractText(content: unknown): string {
60
63
  if (typeof content === "string") return content;
61
64
  if (Array.isArray(content)) {
62
65
  return content
63
- .map((c) => (isPlainObject(c) && typeof c.text === "string" ? (c.text as string) : ""))
66
+ .map((c) =>
67
+ isPlainObject(c) && typeof c.text === "string"
68
+ ? (c.text as string)
69
+ : "",
70
+ )
64
71
  .filter(Boolean)
65
72
  .join("\n");
66
73
  }
@@ -134,7 +141,10 @@ export function openclawLinesToLogEntries(
134
141
  if (b.type === "text" && typeof b.text === "string") {
135
142
  blocks.push({ type: "text", text: b.text });
136
143
  } else if (b.type === "toolCall") {
137
- const id = typeof b.id === "string" ? b.id : `${String(b.name ?? "tool")}-${blocks.length}`;
144
+ const id =
145
+ typeof b.id === "string"
146
+ ? b.id
147
+ : `${String(b.name ?? "tool")}-${blocks.length}`;
138
148
  const name = typeof b.name === "string" ? b.name : "tool";
139
149
  const input = isPlainObject(b.arguments) ? b.arguments : {};
140
150
  const block: ToolUseBlock = { type: "tool_use", id, name, input };
@@ -151,17 +161,23 @@ export function openclawLinesToLogEntries(
151
161
  entries.push({
152
162
  type: "assistant",
153
163
  ...base,
154
- message: { role: "assistant", content: blocks, model: typeof m.model === "string" ? m.model : undefined },
164
+ message: {
165
+ role: "assistant",
166
+ content: blocks,
167
+ model: typeof m.model === "string" ? m.model : undefined,
168
+ },
155
169
  } satisfies AssistantEntry);
156
170
  continue;
157
171
  }
158
172
 
159
173
  if (role === "toolResult") {
160
- const callId = typeof m.toolCallId === "string" ? m.toolCallId : undefined;
174
+ const callId =
175
+ typeof m.toolCallId === "string" ? m.toolCallId : undefined;
161
176
  const block = callId ? toolUseById.get(callId) : undefined;
162
177
  if (block) {
163
178
  const details = isPlainObject(m.details) ? m.details : undefined;
164
- const startMs = (callId && toolUseStartMs.get(callId)) || date.getTime();
179
+ const startMs =
180
+ (callId && toolUseStartMs.get(callId)) || date.getTime();
165
181
  const durationMs =
166
182
  details && typeof details.durationMs === "number"
167
183
  ? details.durationMs
@@ -238,13 +254,20 @@ export function listOpenClawTranscripts(): OpenClawTranscriptFile[] {
238
254
  }
239
255
  for (const file of files) {
240
256
  // Only `<uuid>.jsonl` — not `<uuid>.trajectory.jsonl` / `.trajectory-path.json`.
241
- if (!file.endsWith(".jsonl") || file.endsWith(".trajectory.jsonl")) continue;
257
+ if (!file.endsWith(".jsonl") || file.endsWith(".trajectory.jsonl"))
258
+ continue;
242
259
  const sessionId = file.slice(0, -".jsonl".length);
243
260
  if (!OPENCLAW_SESSION_ID_RE.test(sessionId)) continue;
244
261
  const transcriptPath = join(sessionsDir, file);
245
262
  try {
246
263
  const st = statSync(transcriptPath);
247
- out.push({ agentId, sessionId, transcriptPath, mtimeMs: st.mtimeMs, sizeBytes: st.size });
264
+ out.push({
265
+ agentId,
266
+ sessionId,
267
+ transcriptPath,
268
+ mtimeMs: st.mtimeMs,
269
+ sizeBytes: st.size,
270
+ });
248
271
  } catch {
249
272
  // skip unreadable
250
273
  }
@@ -276,6 +299,36 @@ export interface OpenClawSessionLogData {
276
299
  export async function getOpenClawSessionLog(
277
300
  sessionId: string,
278
301
  ): Promise<OpenClawSessionLogData | null> {
302
+ if (!OPENCLAW_SESSION_ID_RE.test(sessionId)) return null;
303
+
304
+ // New OpenClaw versions keep live transcripts in SQLite. Prefer that copy
305
+ // when an archived JSONL with the same UUID also exists.
306
+ const sqlite = await readOpenClawSqliteTranscript(
307
+ openclawHome(),
308
+ listOpenClawAgents(),
309
+ sessionId,
310
+ );
311
+ if (sqlite) {
312
+ const entries = openclawLinesToLogEntries(sqlite.rawLines, "session");
313
+ let cwd: string | undefined;
314
+ for (const line of sqlite.rawLines) {
315
+ if (
316
+ line.type === "session" &&
317
+ typeof line.cwd === "string" &&
318
+ line.cwd.length > 0
319
+ ) {
320
+ cwd = line.cwd;
321
+ break;
322
+ }
323
+ }
324
+ return {
325
+ entries,
326
+ rawLines: sqlite.rawLines,
327
+ cwd,
328
+ filePath: sqlite.filePath,
329
+ };
330
+ }
331
+
279
332
  const filePath = findOpenClawTranscript(sessionId);
280
333
  if (!filePath) return null;
281
334
  let content: string;
@@ -289,7 +342,12 @@ export async function getOpenClawSessionLog(
289
342
  // cwd lives on the `type:"session"` header line.
290
343
  let cwd: string | undefined;
291
344
  for (const line of rawLines) {
292
- if (isPlainObject(line) && line.type === "session" && typeof line.cwd === "string" && line.cwd.length > 0) {
345
+ if (
346
+ isPlainObject(line) &&
347
+ line.type === "session" &&
348
+ typeof line.cwd === "string" &&
349
+ line.cwd.length > 0
350
+ ) {
293
351
  cwd = line.cwd;
294
352
  break;
295
353
  }
@@ -6,10 +6,10 @@
6
6
  * 1. `node:sqlite` — a real connection that reads main DB + WAL together, so
7
7
  * brand-new rows are visible immediately. Built into Node ≥ 22.5 (no native
8
8
  * module, no flag on recent 22.x). Preferred.
9
- * 2. `sql.js` (pure-JS/asm) — portable fallback for older Node. Reads the main
10
- * DB file's bytes only, so it reflects a snapshot up to the last WAL
11
- * checkpoint (very recent rows may lag). No native module — survives
12
- * `npm install --ignore-scripts`.
9
+ * 2. `sql.js` (pure-JS/asm) — portable fallback for older Node. Builds a
10
+ * consistent in-memory snapshot from the main DB plus committed WAL
11
+ * frames, so live rows are visible on Node 20 too. No native module —
12
+ * survives `npm install --ignore-scripts`.
13
13
  *
14
14
  * Either way: read-only, and `null` on any failure (fail-open, so an absent or
15
15
  * locked DB makes the audit skip that agent rather than crash).
@@ -17,7 +17,7 @@
17
17
  * NOTE: opencode and every CLI that already ships keep their existing CLI
18
18
  * shell-out — this layer is only for new SQLite integrations.
19
19
  */
20
- import { existsSync, readFileSync } from "node:fs";
20
+ import { existsSync, readFileSync, statSync } from "node:fs";
21
21
  import initSqlJs, { type SqlJsStatic } from "sql.js/dist/sql-asm.js";
22
22
 
23
23
  export interface SqliteReader {
@@ -26,6 +26,11 @@ export interface SqliteReader {
26
26
  close(): void;
27
27
  }
28
28
 
29
+ export interface SqliteReaderOptions {
30
+ /** Exercise the Node-20-compatible reader even when `node:sqlite` exists. */
31
+ forcePortable?: boolean;
32
+ }
33
+
29
34
  // ── Tier 1: node:sqlite (WAL-aware, Node ≥ 22.5) ──
30
35
 
31
36
  interface NodeSqliteStmt {
@@ -58,7 +63,7 @@ async function tryNodeSqlite(dbPath: string): Promise<SqliteReader | null> {
58
63
  }
59
64
  }
60
65
 
61
- // ── Tier 2: sql.js (portable snapshot) ──
66
+ // ── Tier 2: sql.js (portable, WAL-aware snapshot) ──
62
67
 
63
68
  let sqlPromise: Promise<SqlJsStatic> | null = null;
64
69
  function loadSqlJs(): Promise<SqlJsStatic> {
@@ -66,10 +71,154 @@ function loadSqlJs(): Promise<SqlJsStatic> {
66
71
  return sqlPromise;
67
72
  }
68
73
 
74
+ interface FileVersion {
75
+ size: number;
76
+ mtimeMs: number;
77
+ ctimeMs: number;
78
+ }
79
+
80
+ function fileVersion(path: string): FileVersion {
81
+ const stat = statSync(path);
82
+ return { size: stat.size, mtimeMs: stat.mtimeMs, ctimeMs: stat.ctimeMs };
83
+ }
84
+
85
+ function sameVersion(a: FileVersion, b: FileVersion): boolean {
86
+ return a.size === b.size && a.mtimeMs === b.mtimeMs && a.ctimeMs === b.ctimeMs;
87
+ }
88
+
89
+ function sqlitePageSize(db: Uint8Array): number | null {
90
+ if (db.length < 100) return null;
91
+ if (Buffer.from(db.subarray(0, 16)).toString("binary") !== "SQLite format 3\0") return null;
92
+ const encoded = (db[16] << 8) | db[17];
93
+ const pageSize = encoded === 1 ? 65_536 : encoded;
94
+ return pageSize >= 512 && pageSize <= 65_536 && (pageSize & (pageSize - 1)) === 0
95
+ ? pageSize
96
+ : null;
97
+ }
98
+
99
+ function walChecksum(
100
+ bytes: Uint8Array,
101
+ offset: number,
102
+ length: number,
103
+ bigEndian: boolean,
104
+ initial: readonly [number, number] = [0, 0],
105
+ ): [number, number] {
106
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
107
+ let [sum1, sum2] = initial;
108
+ for (let cursor = offset; cursor < offset + length; cursor += 8) {
109
+ const first = view.getUint32(cursor, !bigEndian);
110
+ const second = view.getUint32(cursor + 4, !bigEndian);
111
+ sum1 = (sum1 + first + sum2) >>> 0;
112
+ sum2 = (sum2 + second + sum1) >>> 0;
113
+ }
114
+ return [sum1, sum2];
115
+ }
116
+
117
+ /** Overlay every valid frame through the WAL's last committed transaction. */
118
+ function applyCommittedWal(db: Uint8Array, wal: Uint8Array): Uint8Array {
119
+ const pageSize = sqlitePageSize(db);
120
+ if (pageSize === null || wal.length < 32) return db;
121
+
122
+ const view = new DataView(wal.buffer, wal.byteOffset, wal.byteLength);
123
+ const magic = view.getUint32(0, false);
124
+ if (magic !== 0x377f0682 && magic !== 0x377f0683) return db;
125
+ if (view.getUint32(4, false) !== 3_007_000) return db;
126
+ if (view.getUint32(8, false) !== pageSize) return db;
127
+
128
+ const checksumBigEndian = (magic & 1) === 1;
129
+ let checksum = walChecksum(wal, 0, 24, checksumBigEndian);
130
+ if (view.getUint32(24, false) !== checksum[0] || view.getUint32(28, false) !== checksum[1]) {
131
+ return db;
132
+ }
133
+
134
+ const salt1 = view.getUint32(16, false);
135
+ const salt2 = view.getUint32(20, false);
136
+ const frameSize = 24 + pageSize;
137
+ const frameCount = Math.floor((wal.length - 32) / frameSize);
138
+ let lastCommit = -1;
139
+ let committedPages = 0;
140
+
141
+ for (let index = 0; index < frameCount; index += 1) {
142
+ const offset = 32 + index * frameSize;
143
+ const pageNumber = view.getUint32(offset, false);
144
+ if (
145
+ pageNumber === 0 ||
146
+ view.getUint32(offset + 8, false) !== salt1 ||
147
+ view.getUint32(offset + 12, false) !== salt2
148
+ ) {
149
+ break;
150
+ }
151
+ checksum = walChecksum(wal, offset, 8, checksumBigEndian, checksum);
152
+ checksum = walChecksum(wal, offset + 24, pageSize, checksumBigEndian, checksum);
153
+ if (
154
+ view.getUint32(offset + 16, false) !== checksum[0] ||
155
+ view.getUint32(offset + 20, false) !== checksum[1]
156
+ ) {
157
+ break;
158
+ }
159
+ const databasePages = view.getUint32(offset + 4, false);
160
+ if (databasePages > 0) {
161
+ lastCommit = index;
162
+ committedPages = databasePages;
163
+ }
164
+ }
165
+
166
+ if (lastCommit < 0 || committedPages === 0) return db;
167
+ const targetSize = committedPages * pageSize;
168
+ // A corrupt WAL must not be allowed to request an unbounded allocation.
169
+ if (!Number.isSafeInteger(targetSize) || targetSize > db.length + frameCount * pageSize) {
170
+ return db;
171
+ }
172
+
173
+ const snapshot = new Uint8Array(targetSize);
174
+ snapshot.set(db.subarray(0, targetSize));
175
+ for (let index = 0; index <= lastCommit; index += 1) {
176
+ const offset = 32 + index * frameSize;
177
+ const pageNumber = view.getUint32(offset, false);
178
+ const destination = (pageNumber - 1) * pageSize;
179
+ // An earlier transaction in the same WAL may have grown the database and
180
+ // a later committed transaction may have truncated it again. Frames above
181
+ // the final committed page count are valid history, but not part of the
182
+ // snapshot sql.js should open.
183
+ if (destination >= targetSize) continue;
184
+ snapshot.set(wal.subarray(offset + 24, offset + frameSize), destination);
185
+ }
186
+ return snapshot;
187
+ }
188
+
189
+ /**
190
+ * Read the main file before the WAL and verify that no checkpoint changed the
191
+ * main file in between. WAL appends are safe: only complete committed frames
192
+ * present in the bytes we read are applied. A checkpoint/reset changes the
193
+ * main file, which makes us retry instead of combining different generations.
194
+ */
195
+ function readPortableSnapshot(dbPath: string): Uint8Array {
196
+ const walPath = `${dbPath}-wal`;
197
+ for (let attempt = 0; attempt < 3; attempt += 1) {
198
+ const before = fileVersion(dbPath);
199
+ const main = readFileSync(dbPath);
200
+ const afterMain = fileVersion(dbPath);
201
+ if (!sameVersion(before, afterMain)) continue;
202
+
203
+ let wal: Uint8Array | null = null;
204
+ try {
205
+ wal = readFileSync(walPath);
206
+ } catch (error) {
207
+ // A missing WAL is an ordinary checkpointed database.
208
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
209
+ }
210
+
211
+ const afterWal = fileVersion(dbPath);
212
+ if (!sameVersion(before, afterWal)) continue;
213
+ return wal ? applyCommittedWal(main, wal) : main;
214
+ }
215
+ throw new Error(`SQLite database changed while reading: ${dbPath}`);
216
+ }
217
+
69
218
  async function trySqlJs(dbPath: string): Promise<SqliteReader | null> {
70
219
  try {
71
220
  const SQL = await loadSqlJs();
72
- const db = new SQL.Database(readFileSync(dbPath));
221
+ const db = new SQL.Database(readPortableSnapshot(dbPath));
73
222
  return {
74
223
  query<T = Record<string, unknown>>(sql: string, params?: unknown[]): T[] {
75
224
  const stmt = db.prepare(sql);
@@ -96,7 +245,14 @@ async function trySqlJs(dbPath: string): Promise<SqliteReader | null> {
96
245
  * connection (live data), falls back to a `sql.js` snapshot. Returns `null` on
97
246
  * any failure. Always `close()` the reader when done.
98
247
  */
99
- export async function openSqliteReadonly(dbPath: string): Promise<SqliteReader | null> {
248
+ export async function openSqliteReadonly(
249
+ dbPath: string,
250
+ options: SqliteReaderOptions = {},
251
+ ): Promise<SqliteReader | null> {
100
252
  if (!existsSync(dbPath)) return null;
101
- return (await tryNodeSqlite(dbPath)) ?? (await trySqlJs(dbPath));
253
+ if (!options.forcePortable) {
254
+ const native = await tryNodeSqlite(dbPath);
255
+ if (native) return native;
256
+ }
257
+ return trySqlJs(dbPath);
102
258
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "failproofai",
3
- "version": "1.0.5-beta.0",
3
+ "version": "1.0.5-beta.2",
4
4
  "description": "Observability and enforcement for AI agent harnesses. 39 built-in policies hooked into 12 of them — Claude Code, Codex, Cursor, Hermes, OpenClaw and more — blocking the tool call before it runs. Local dashboard included, no account needed.",
5
5
  "bin": {
6
6
  "failproofai": "./dist/cli.mjs",
@@ -121,15 +121,15 @@
121
121
  "browserslist": "4.28.8"
122
122
  },
123
123
  "optionalDependencies": {
124
- "@failproofai/failproofaid-linux-x64": "1.0.5-beta.0",
125
- "@failproofai/failproofaid-linux-arm64": "1.0.5-beta.0",
126
- "@failproofai/failproofaid-darwin-x64": "1.0.5-beta.0",
127
- "@failproofai/failproofaid-darwin-arm64": "1.0.5-beta.0"
124
+ "@failproofai/failproofaid-linux-x64": "1.0.5-beta.2",
125
+ "@failproofai/failproofaid-linux-arm64": "1.0.5-beta.2",
126
+ "@failproofai/failproofaid-darwin-x64": "1.0.5-beta.2",
127
+ "@failproofai/failproofaid-darwin-arm64": "1.0.5-beta.2"
128
128
  },
129
129
  "failproofaidBinaries": {
130
- "linux-x64": "b5ab25cc1af4cf60a1f62c955c58c0517ff93e87b8615b306e77a8ae9722299e",
131
- "linux-arm64": "7ae78dc25a0878599cc6175ae20749ce7329430d40c7d0dd3a761d17548deb31",
132
- "darwin-x64": "1a064b7db93ad8a127994a2a3b8494069c444e3ea9bafa72b3c6a8a9b31f9c57",
133
- "darwin-arm64": "2822370952b3355039bf3ac7f7730a626a4906655379eae4be24e00e2e42efa5"
130
+ "linux-x64": "cce0b612f53a28591a0eb6f3e1abe7cadfc490afedff85c8f55772e76c7be566",
131
+ "linux-arm64": "20ead289387082e38e456cef27271ff74df368ec90389ce4f818af73af24cfa1",
132
+ "darwin-x64": "9a6fc5c2aa250224aea7fa7b945230636d34e7aea454177c131d40a5f56e17a1",
133
+ "darwin-arm64": "fb26aa5ffbbc971b9923593dc6f5a05f1d20b7d5e9953172b81318038252a240"
134
134
  }
135
135
  }
@@ -9,6 +9,13 @@ in `failproofai_sdk/_version.py` becomes that release's GitHub Release body. A
9
9
  release whose section is missing or empty is refused before anything is built —
10
10
  see `scripts/changelog-section.py`.
11
11
 
12
+ ## 0.0.1b4 — 2026-09-12
13
+
14
+ Open for the next release. `0.0.1b3` published on 2026-09-12 and the `bump` job
15
+ moved the version here automatically; nothing has landed against `0.0.1b4` yet.
16
+ Add entries as changes merge — this section becomes the GitHub Release body when
17
+ it ships.
18
+
12
19
  ## 0.0.1b3 — 2026-09-08
13
20
 
14
21
  ### Fixes
@@ -1 +1 @@
1
- __version__ = "0.0.1b3"
1
+ __version__ = "0.0.1b4"
@@ -9,7 +9,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
9
9
  const hostname = process.env.HOSTNAME || '0.0.0.0'
10
10
 
11
11
  let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
12
- const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"1.0.5-beta.0"},"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"instrumentationClientInject":[],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/failproofai/failproofai","enablePrerenderSourceMaps":true,"cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":true,"coldCacheBadge":false,"devValidationWorker":true,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"dynamicOnHover":false,"useOffline":false,"varyParams":true,"optimisticRouting":true,"instrumentationClientRouterTransitionEvents":false,"prefetchInlining":{"maxSize":2048,"maxBundleSize":10240},"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptOperationCache":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"devMemoryThresholdRestart":true,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"requestInsights":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"useTypeScriptCli":true,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":true,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"serverComponentsHmrCancellation":false,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":true,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","turbopackMemoryEvictionMode":"auto","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"useCacheTimeout":54,"instantInsights":{"validationLevel":"warning"},"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","outputFileTracingExcludes":{"*":["node_modules/@img/**","node_modules/sharp/**"]},"turbopack":{"root":"/home/runner/work/failproofai/failproofai"},"repoRoot":"/home/runner/work/failproofai/failproofai","distDirRoot":".next"}
12
+ const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"1.0.5-beta.2"},"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"instrumentationClientInject":[],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/failproofai/failproofai","enablePrerenderSourceMaps":true,"cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":true,"coldCacheBadge":false,"devValidationWorker":true,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"dynamicOnHover":false,"useOffline":false,"varyParams":true,"optimisticRouting":true,"instrumentationClientRouterTransitionEvents":false,"prefetchInlining":{"maxSize":2048,"maxBundleSize":10240},"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptOperationCache":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"devMemoryThresholdRestart":true,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"requestInsights":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"useTypeScriptCli":true,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":true,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"serverComponentsHmrCancellation":false,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":true,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","turbopackMemoryEvictionMode":"auto","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"useCacheTimeout":54,"instantInsights":{"validationLevel":"warning"},"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","outputFileTracingExcludes":{"*":["node_modules/@img/**","node_modules/sharp/**"]},"turbopack":{"root":"/home/runner/work/failproofai/failproofai"},"repoRoot":"/home/runner/work/failproofai/failproofai","distDirRoot":".next"}
13
13
 
14
14
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
15
15