failproofai 0.0.10-beta.2 → 0.0.10-beta.4
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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -2
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +2 -2
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js +2 -2
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +3 -3
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +2 -2
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06.arfm._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__i0h0._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0dtn9lr._.js → [root-of-the-server]__0d_ob4n._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fe7_q_._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fjhqi9._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fw.e.h._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kjo7d_._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0pxn0e1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xv0jh2._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__010i6f5._.js → [root-of-the-server]__0z-180.._.js} +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0dl0kgt._.js → [root-of-the-server]__01hj~sd._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0s~gy6y._.js → [root-of-the-server]__02r6nu-._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0bz245.._.js → [root-of-the-server]__04dywib._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0gmhxyo._.js → [root-of-the-server]__06sb2gn._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0tt8-uq._.js → [root-of-the-server]__092oklx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0-2wr.c._.js → [root-of-the-server]__09jpajs._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ils1oq._.js → [root-of-the-server]__0bemgh7._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0qbpe_v._.js → [root-of-the-server]__0jm6jnh._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0709m8.._.js → [root-of-the-server]__0joez.y._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ohb3gc._.js → [root-of-the-server]__0mi5ejy._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u1i~9~._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__09y9okz._.js → [root-of-the-server]__0x5limi._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ymlddl._.js +5 -3
- package/.next/standalone/.next/server/chunks/ssr/_10lm7or._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_0cdqd9w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/pages/404.html +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +9 -9
- package/.next/standalone/.next/static/chunks/{0yzl~f-qji0...js → 0csfsu88oqir8.js} +2 -2
- package/.next/standalone/.next/static/chunks/{0y8oyen~jnjl3.js → 0fvemi0q_n349.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0a_w-lcg.0tl7.js → 0ilx6hm27porg.js} +1 -1
- package/.next/standalone/.next/static/chunks/0kxi65pnos15e.js +1 -0
- package/.next/standalone/.next/static/chunks/{0-dltnti0ew4y.js → 12mx5dzs_vf1w.js} +1 -1
- package/.next/standalone/.next/static/chunks/{17o7-pn_xzt-t.js → 14p_4ajxz0ifs.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0lscbfo_2_h14.js → 16ydic9u8kagt.js} +2 -2
- package/.next/standalone/.next/static/chunks/{02h_cfxpk4x9..js → 18daqyhykpw8z.js} +1 -1
- package/.next/standalone/app/api/download/[project]/[session]/route.ts +26 -10
- package/.next/standalone/app/components/session-hooks-panel.tsx +3 -0
- package/.next/standalone/app/policies/hooks-client.tsx +3 -0
- package/.next/standalone/app/project/[name]/session/[sessionId]/page.tsx +8 -10
- package/.next/standalone/lib/download-session.ts +92 -0
- package/.next/standalone/lib/opencode-sessions.ts +42 -0
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/server.js +1 -1
- package/dist/cli.mjs +1281 -305
- package/lib/download-session.ts +92 -0
- package/lib/opencode-sessions.ts +42 -0
- package/package.json +1 -1
- package/src/hooks/builtin-policies.ts +4 -3
- package/src/hooks/handler.ts +22 -12
- package/src/hooks/integrations.ts +2 -0
- package/src/hooks/policy-evaluator.ts +47 -6
- package/src/hooks/resolve-transcript-path.ts +69 -0
- package/src/hooks/types.ts +73 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b57.gk._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0z4c5dj._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0.~m-w2._.js +0 -4
- package/.next/standalone/.next/static/chunks/16k5y9ruha2v4.js +0 -1
- /package/.next/standalone/.next/static/{EBbXdrT2rHib3zGLSuY7Q → Z3pK8z9QuEdJFE28LwB5Y}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{EBbXdrT2rHib3zGLSuY7Q → Z3pK8z9QuEdJFE28LwB5Y}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{EBbXdrT2rHib3zGLSuY7Q → Z3pK8z9QuEdJFE28LwB5Y}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-CLI dispatcher for the dashboard's Download Logs endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Returns either a real on-disk path (so the route can `createReadStream` and
|
|
5
|
+
* stream the bytes verbatim) or a synthesized JSONL body (used only by
|
|
6
|
+
* OpenCode, whose transcripts live in SQLite rather than on disk).
|
|
7
|
+
*
|
|
8
|
+
* Per-CLI session loaders / transcript finders already exist in their own
|
|
9
|
+
* files; this module is the thin glue that picks the right one. Imports of
|
|
10
|
+
* the per-CLI modules are dynamic so callers that only need the dispatch
|
|
11
|
+
* type can avoid pulling Node-only deps into client bundles.
|
|
12
|
+
*/
|
|
13
|
+
import { resolveSessionFilePath, UUID_RE } from "./projects";
|
|
14
|
+
import type { CliId } from "./cli-registry";
|
|
15
|
+
|
|
16
|
+
export const OPENCODE_SESSION_RE = /^ses_[A-Za-z0-9]+$/;
|
|
17
|
+
|
|
18
|
+
export type DownloadSource =
|
|
19
|
+
| { kind: "file"; path: string }
|
|
20
|
+
| { kind: "synthesized"; body: string; contentType: string; extension: string };
|
|
21
|
+
|
|
22
|
+
/** Validate a session ID against the per-CLI shape. OpenCode uses `ses_*`
|
|
23
|
+
* prefixes; everyone else is a UUID. */
|
|
24
|
+
export function isValidSessionId(cli: CliId, sessionId: string): boolean {
|
|
25
|
+
if (cli === "opencode") return OPENCODE_SESSION_RE.test(sessionId);
|
|
26
|
+
return UUID_RE.test(sessionId);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a download source for `(cli, sessionId)`. `project` is only
|
|
31
|
+
* meaningful for Claude (path-traversal validation under the projects root);
|
|
32
|
+
* the other CLIs key sessions by ID alone.
|
|
33
|
+
*
|
|
34
|
+
* Returns `null` when the session can't be located. Throws RangeError when
|
|
35
|
+
* the inputs fail validation (caller should map to 400).
|
|
36
|
+
*/
|
|
37
|
+
export async function resolveDownloadSource(
|
|
38
|
+
cli: CliId,
|
|
39
|
+
project: string,
|
|
40
|
+
sessionId: string,
|
|
41
|
+
): Promise<DownloadSource | null> {
|
|
42
|
+
if (!isValidSessionId(cli, sessionId)) {
|
|
43
|
+
throw new RangeError("Invalid session ID");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (cli === "claude") {
|
|
47
|
+
// resolveSessionFilePath validates project and joins under the Claude root.
|
|
48
|
+
return { kind: "file", path: resolveSessionFilePath(project, sessionId) };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (cli === "codex") {
|
|
52
|
+
const { findCodexTranscript } = await import("./codex-sessions");
|
|
53
|
+
const path = findCodexTranscript(sessionId);
|
|
54
|
+
return path ? { kind: "file", path } : null;
|
|
55
|
+
}
|
|
56
|
+
if (cli === "copilot") {
|
|
57
|
+
const { findCopilotTranscript } = await import("./copilot-sessions");
|
|
58
|
+
const path = findCopilotTranscript(sessionId);
|
|
59
|
+
return path ? { kind: "file", path } : null;
|
|
60
|
+
}
|
|
61
|
+
if (cli === "cursor") {
|
|
62
|
+
const { findCursorTranscript } = await import("./cursor-sessions");
|
|
63
|
+
const path = findCursorTranscript(sessionId);
|
|
64
|
+
return path ? { kind: "file", path } : null;
|
|
65
|
+
}
|
|
66
|
+
if (cli === "pi") {
|
|
67
|
+
const { findPiTranscript } = await import("./pi-sessions");
|
|
68
|
+
const path = findPiTranscript(sessionId);
|
|
69
|
+
return path ? { kind: "file", path } : null;
|
|
70
|
+
}
|
|
71
|
+
if (cli === "gemini") {
|
|
72
|
+
const { findGeminiTranscript } = await import("./gemini-sessions");
|
|
73
|
+
const path = findGeminiTranscript(sessionId);
|
|
74
|
+
return path ? { kind: "file", path } : null;
|
|
75
|
+
}
|
|
76
|
+
if (cli === "opencode") {
|
|
77
|
+
// OpenCode keeps sessions in SQLite (~/.local/share/opencode/opencode.db)
|
|
78
|
+
// across three tables: session / message / part. Export all three so
|
|
79
|
+
// users get a faithful snapshot of the underlying structure rather than
|
|
80
|
+
// a collapsed single-stream that loses parts.
|
|
81
|
+
const { getOpenCodeSessionExport } = await import("./opencode-sessions");
|
|
82
|
+
const result = await getOpenCodeSessionExport(sessionId);
|
|
83
|
+
if (!result) return null;
|
|
84
|
+
const body = JSON.stringify(result, null, 2) + "\n";
|
|
85
|
+
return { kind: "synthesized", body, contentType: "application/json", extension: "json" };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Exhaustive — but TypeScript can't always see CliId is exhausted across the
|
|
89
|
+
// if-chain above, so guard with a runtime fallback.
|
|
90
|
+
const _exhaustive: never = cli;
|
|
91
|
+
return _exhaustive;
|
|
92
|
+
}
|
package/lib/opencode-sessions.ts
CHANGED
|
@@ -235,3 +235,45 @@ export const getCachedOpenCodeSessionLog = runtimeCache(
|
|
|
235
235
|
30,
|
|
236
236
|
{ maxSize: 50 },
|
|
237
237
|
);
|
|
238
|
+
|
|
239
|
+
// ── Export shape ──
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Snapshot of an OpenCode session as it lives in the SQLite store: one
|
|
243
|
+
* `session` row, all of its `message` rows, all of its `part` rows. The JSON
|
|
244
|
+
* `data` column on each message/part is parsed (when valid) so consumers
|
|
245
|
+
* don't have to double-parse; malformed JSON survives as the raw string.
|
|
246
|
+
*
|
|
247
|
+
* Used by the dashboard's Download Logs feature so the export mirrors the
|
|
248
|
+
* underlying schema rather than collapsing parts into a single per-message
|
|
249
|
+
* record (which is what the viewer-facing `getOpenCodeSessionLog` does).
|
|
250
|
+
*/
|
|
251
|
+
export interface OpenCodeSessionExportData {
|
|
252
|
+
session: OpenCodeSessionRow;
|
|
253
|
+
messages: Array<Omit<OpenCodeMessageRow, "data"> & { data: Record<string, unknown> | string | null }>;
|
|
254
|
+
parts: Array<Omit<OpenCodePartRow, "data"> & { data: Record<string, unknown> | string | null }>;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export async function getOpenCodeSessionExport(sessionId: string): Promise<OpenCodeSessionExportData | null> {
|
|
258
|
+
if (!sessionId || !/^[A-Za-z0-9_-]+$/.test(sessionId)) return null;
|
|
259
|
+
const sessions = runOpenCodeDb<OpenCodeSessionRow>(
|
|
260
|
+
`SELECT id, project_id, slug, directory, title, time_created, time_updated FROM session WHERE id = '${sessionId}'`,
|
|
261
|
+
);
|
|
262
|
+
if (!sessions || sessions.length === 0) return null;
|
|
263
|
+
// Don't coalesce a `null` return (query failure) into `[]` — that would
|
|
264
|
+
// silently serve an "empty session" export. A genuinely empty session has
|
|
265
|
+
// an `[]` from the DB; a query failure has `null`. Treat the latter as
|
|
266
|
+
// not-found so the route returns 404 rather than a misleading 200.
|
|
267
|
+
const messages = runOpenCodeDb<OpenCodeMessageRow>(
|
|
268
|
+
`SELECT id, session_id, time_created, time_updated, data FROM message WHERE session_id = '${sessionId}' ORDER BY time_created ASC`,
|
|
269
|
+
);
|
|
270
|
+
const parts = runOpenCodeDb<OpenCodePartRow>(
|
|
271
|
+
`SELECT id, message_id, session_id, time_created, time_updated, data FROM part WHERE session_id = '${sessionId}' ORDER BY time_created ASC`,
|
|
272
|
+
);
|
|
273
|
+
if (messages === null || parts === null) return null;
|
|
274
|
+
return {
|
|
275
|
+
session: sessions[0],
|
|
276
|
+
messages: messages.map((m) => ({ ...m, data: parseDataColumn(m.data) ?? m.data })),
|
|
277
|
+
parts: parts.map((p) => ({ ...p, data: parseDataColumn(p.data) ?? p.data })),
|
|
278
|
+
};
|
|
279
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "failproofai",
|
|
3
|
-
"version": "0.0.10-beta.
|
|
3
|
+
"version": "0.0.10-beta.4",
|
|
4
4
|
"description": "The easiest way to manage policies that keep your AI agents reliable, on-task, and running autonomously — for Claude Code & the Agents SDK",
|
|
5
5
|
"bin": {
|
|
6
6
|
"failproofai": "./dist/cli.mjs"
|
|
@@ -180,7 +180,7 @@ const SECRET_FILE_ID_RSA_RE = /id_rsa/;
|
|
|
180
180
|
const SECRET_FILE_CREDENTIALS_RE = /credentials/;
|
|
181
181
|
|
|
182
182
|
// blockWorkOnMain
|
|
183
|
-
const GIT_COMMIT_MERGE_RE = /git\s+(
|
|
183
|
+
const GIT_COMMIT_MERGE_RE = /git\s+(commit|merge|rebase|cherry-pick)\b/;
|
|
184
184
|
|
|
185
185
|
// blockFailproofaiCommands
|
|
186
186
|
const FAILPROOFAI_CLI_RE = /(?:^|;|&&|\|\||\|)\s*failproofai(?:\s|$)/;
|
|
@@ -822,7 +822,8 @@ function blockReadOutsideCwd(ctx: PolicyContext): PolicyResult {
|
|
|
822
822
|
function blockWorkOnMain(ctx: PolicyContext): PolicyResult {
|
|
823
823
|
if (ctx.toolName !== "Bash") return allow();
|
|
824
824
|
const cmd = getCommand(ctx);
|
|
825
|
-
|
|
825
|
+
const match = cmd.match(GIT_COMMIT_MERGE_RE);
|
|
826
|
+
if (!match) return allow();
|
|
826
827
|
|
|
827
828
|
const cwd = ctx.session?.cwd;
|
|
828
829
|
if (!cwd) return allow();
|
|
@@ -833,7 +834,7 @@ function blockWorkOnMain(ctx: PolicyContext): PolicyResult {
|
|
|
833
834
|
const protectedBranches = ((ctx.params?.protectedBranches ?? ["main", "master"]) as string[]);
|
|
834
835
|
if (protectedBranches.includes(branch)) {
|
|
835
836
|
return deny(
|
|
836
|
-
`Git ${
|
|
837
|
+
`Git ${match[1]} on ${branch} is blocked. Create a feature branch first.`,
|
|
837
838
|
);
|
|
838
839
|
}
|
|
839
840
|
return allow();
|
package/src/hooks/handler.ts
CHANGED
|
@@ -14,7 +14,16 @@ import type {
|
|
|
14
14
|
PiHookEventType,
|
|
15
15
|
GeminiHookEventType,
|
|
16
16
|
} from "./types";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
CODEX_EVENT_MAP,
|
|
19
|
+
CURSOR_EVENT_MAP,
|
|
20
|
+
PI_EVENT_MAP,
|
|
21
|
+
GEMINI_EVENT_MAP,
|
|
22
|
+
GEMINI_TOOL_MAP,
|
|
23
|
+
COPILOT_TOOL_MAP,
|
|
24
|
+
CURSOR_TOOL_MAP,
|
|
25
|
+
CODEX_TOOL_MAP,
|
|
26
|
+
} from "./types";
|
|
18
27
|
import type { PolicyFunction, PolicyResult } from "./policy-types";
|
|
19
28
|
import { readMergedHooksConfig } from "./hooks-config";
|
|
20
29
|
import { registerBuiltinPolicies } from "./builtin-policies";
|
|
@@ -25,6 +34,7 @@ import type { CustomHook } from "./policy-types";
|
|
|
25
34
|
import { persistHookActivity } from "./hook-activity-store";
|
|
26
35
|
import { trackHookEvent } from "./hook-telemetry";
|
|
27
36
|
import { resolvePermissionMode } from "./resolve-permission-mode";
|
|
37
|
+
import { resolveTranscriptPath } from "./resolve-transcript-path";
|
|
28
38
|
import { getInstanceId } from "../../lib/telemetry-id";
|
|
29
39
|
import { hookLogInfo, hookLogWarn } from "./hook-logger";
|
|
30
40
|
|
|
@@ -70,10 +80,12 @@ function canonicalizeEventType(raw: string, cli: IntegrationType): HookEventType
|
|
|
70
80
|
*
|
|
71
81
|
* Per-CLI tool-name shapes (verified from in-repo evidence and vendor docs):
|
|
72
82
|
* • Claude: PascalCase native — passthrough
|
|
73
|
-
* • Codex: PascalCase
|
|
74
|
-
*
|
|
75
|
-
* • Copilot: lowercase IDs (`bash`, `read`, …) — COPILOT_TOOL_MAP
|
|
76
|
-
* • Cursor: PascalCase per Cursor docs
|
|
83
|
+
* • Codex: `Bash` PascalCase passthrough; `apply_patch` → `Edit`,
|
|
84
|
+
* `write_stdin` → `Bash` via CODEX_TOOL_MAP
|
|
85
|
+
* • Copilot: lowercase IDs (`bash`, `read`, `view`, …) — COPILOT_TOOL_MAP
|
|
86
|
+
* • Cursor: PascalCase per Cursor docs but uses `Shell` for the bash-
|
|
87
|
+
* equivalent — CURSOR_TOOL_MAP rewrites `Shell → Bash`; other
|
|
88
|
+
* tool names already canonical and pass through
|
|
77
89
|
* • OpenCode: handled in the OpenCode plugin shim (in-process,
|
|
78
90
|
* self-contained) before the JSON crosses to this binary
|
|
79
91
|
* • Pi: handled in the Pi extension shim (same)
|
|
@@ -84,12 +96,10 @@ function canonicalizeEventType(raw: string, cli: IntegrationType): HookEventType
|
|
|
84
96
|
*/
|
|
85
97
|
function canonicalizeToolName(raw: string | undefined, cli: IntegrationType): string | undefined {
|
|
86
98
|
if (!raw) return raw;
|
|
87
|
-
if (cli === "copilot")
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (cli === "gemini")
|
|
91
|
-
return GEMINI_TOOL_MAP[raw] ?? raw;
|
|
92
|
-
}
|
|
99
|
+
if (cli === "copilot") return COPILOT_TOOL_MAP[raw] ?? raw;
|
|
100
|
+
if (cli === "cursor") return CURSOR_TOOL_MAP[raw] ?? raw;
|
|
101
|
+
if (cli === "codex") return CODEX_TOOL_MAP[raw] ?? raw;
|
|
102
|
+
if (cli === "gemini") return GEMINI_TOOL_MAP[raw] ?? raw;
|
|
93
103
|
return raw;
|
|
94
104
|
}
|
|
95
105
|
|
|
@@ -153,7 +163,7 @@ export async function handleHookEvent(
|
|
|
153
163
|
const sessionId = parsed.session_id as string | undefined;
|
|
154
164
|
const session: SessionMetadata = {
|
|
155
165
|
sessionId,
|
|
156
|
-
transcriptPath: parsed
|
|
166
|
+
transcriptPath: resolveTranscriptPath(cli, parsed, sessionId),
|
|
157
167
|
cwd: parsed.cwd as string | undefined,
|
|
158
168
|
permissionMode: resolvePermissionMode(cli, parsed, sessionId),
|
|
159
169
|
hookEventName: parsed.hook_event_name as string | undefined,
|
|
@@ -736,10 +736,12 @@ const TOOL_NAME_MAP = {
|
|
|
736
736
|
read: "Read",
|
|
737
737
|
write: "Write",
|
|
738
738
|
edit: "Edit",
|
|
739
|
+
apply_patch: "Edit",
|
|
739
740
|
glob: "Glob",
|
|
740
741
|
grep: "Grep",
|
|
741
742
|
list: "LS",
|
|
742
743
|
webfetch: "WebFetch",
|
|
744
|
+
websearch: "WebSearch",
|
|
743
745
|
todowrite: "TodoWrite",
|
|
744
746
|
todoread: "TodoRead",
|
|
745
747
|
};
|
|
@@ -264,11 +264,32 @@ export async function evaluatePolicies(
|
|
|
264
264
|
};
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
if (eventType === "Stop") {
|
|
267
|
+
if (eventType === "Stop" || eventType === "SubagentStop") {
|
|
268
|
+
const reasonText = `MANDATORY ACTION REQUIRED from failproofai (policy: ${policy.name}): ${reason}\n\nYou MUST complete the above action NOW. Do NOT ask the user for confirmation — execute the required action, then attempt to finish your task again.`;
|
|
269
|
+
// Copilot CLI: `agentStop` and `subagentStop` both honor
|
|
270
|
+
// `{decision: "block", reason}` JSON on stdout — the reason becomes the
|
|
271
|
+
// next-turn prompt and the agent (or subagent) retries. Exit-2 is logged
|
|
272
|
+
// as `[WARNING] Hook warning: ...` (verified empirically against Copilot
|
|
273
|
+
// CLI 1.0.41 events.jsonl) but does NOT trigger retry. We branch on both
|
|
274
|
+
// event types so that custom policies matching SubagentStop also enforce
|
|
275
|
+
// on Copilot subagent boundaries; the 5 builtin require-*-before-stop
|
|
276
|
+
// policies still match Stop only by design — they are session-completion
|
|
277
|
+
// gates (commit/push/PR/conflicts/CI), not subagent-return gates.
|
|
278
|
+
// Ref: https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-hooks-reference
|
|
279
|
+
if (session?.cli === "copilot") {
|
|
280
|
+
return {
|
|
281
|
+
exitCode: 0,
|
|
282
|
+
stdout: JSON.stringify({ decision: "block", reason: reasonText }),
|
|
283
|
+
stderr: "",
|
|
284
|
+
policyName: policy.name,
|
|
285
|
+
reason,
|
|
286
|
+
decision: "deny",
|
|
287
|
+
};
|
|
288
|
+
}
|
|
268
289
|
return {
|
|
269
290
|
exitCode: 2,
|
|
270
291
|
stdout: "",
|
|
271
|
-
stderr:
|
|
292
|
+
stderr: reasonText,
|
|
272
293
|
policyName: policy.name,
|
|
273
294
|
reason,
|
|
274
295
|
decision: "deny",
|
|
@@ -433,16 +454,36 @@ export async function evaluatePolicies(
|
|
|
433
454
|
};
|
|
434
455
|
}
|
|
435
456
|
|
|
436
|
-
if (eventType === "Stop") {
|
|
437
|
-
// Stop
|
|
438
|
-
//
|
|
457
|
+
if (eventType === "Stop" || eventType === "SubagentStop") {
|
|
458
|
+
// Stop/SubagentStop instruct: exitCode 2 + stderr forces Claude to retry
|
|
459
|
+
// the agent (or subagent) loop with the reason as context. Same widening
|
|
460
|
+
// as the deny branch above — custom policies subscribing to
|
|
461
|
+
// SubagentStop need the same retry semantics; the 5 builtin
|
|
462
|
+
// require-*-before-stop policies still match Stop only by design.
|
|
439
463
|
const policyAttribution = policyNames.length === 1
|
|
440
464
|
? `policy: ${policyNames[0]}`
|
|
441
465
|
: `policies: ${policyNames.join(", ")}`;
|
|
466
|
+
const reasonText = `MANDATORY ACTION REQUIRED from failproofai (${policyAttribution}): ${combined}\n\nYou MUST complete the above action(s) NOW. Do NOT ask the user for confirmation — execute the required action(s), then attempt to finish your task again.`;
|
|
467
|
+
// Copilot CLI: exit-2 from agentStop / subagentStop is logged as
|
|
468
|
+
// `[WARNING] Hook warning: ...` but does NOT trigger retry. The
|
|
469
|
+
// documented retry shape is `{decision: "block", reason}` JSON on
|
|
470
|
+
// stdout (exit 0). Mirrors the cli==="copilot" branch in the deny
|
|
471
|
+
// path at line ~279 so custom instruct policies enforce on Copilot.
|
|
472
|
+
if (session?.cli === "copilot") {
|
|
473
|
+
return {
|
|
474
|
+
exitCode: 0,
|
|
475
|
+
stdout: JSON.stringify({ decision: "block", reason: reasonText }),
|
|
476
|
+
stderr: "",
|
|
477
|
+
policyName: policyNames[0],
|
|
478
|
+
policyNames,
|
|
479
|
+
reason: combined,
|
|
480
|
+
decision: "instruct",
|
|
481
|
+
};
|
|
482
|
+
}
|
|
442
483
|
return {
|
|
443
484
|
exitCode: 2,
|
|
444
485
|
stdout: "",
|
|
445
|
-
stderr:
|
|
486
|
+
stderr: reasonText,
|
|
446
487
|
policyName: policyNames[0],
|
|
447
488
|
policyNames,
|
|
448
489
|
reason: combined,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-CLI transcript-path resolver.
|
|
3
|
+
*
|
|
4
|
+
* • Claude Code: `transcript_path` arrives on the hook stdin payload —
|
|
5
|
+
* passthrough.
|
|
6
|
+
*
|
|
7
|
+
* • Codex: stdin doesn't carry transcript_path. Discover via
|
|
8
|
+
* ~/.codex/sessions/<YYYY>/<MM>/<DD>/<file containing sessionId>.jsonl.
|
|
9
|
+
*
|
|
10
|
+
* • Copilot: stdin doesn't carry transcript_path. Discover at
|
|
11
|
+
* ~/.copilot/session-state/<sessionId>/events.jsonl.
|
|
12
|
+
*
|
|
13
|
+
* • Cursor: stdin doesn't carry transcript_path. Discover under
|
|
14
|
+
* ~/.cursor/projects/<encoded-cwd>/agent-transcripts/<sessionId>/<sessionId>.jsonl
|
|
15
|
+
* (with legacy fallbacks).
|
|
16
|
+
*
|
|
17
|
+
* • OpenCode: transcripts live in SQLite at
|
|
18
|
+
* ~/.local/share/opencode/opencode.db, not on disk. Synthesize an
|
|
19
|
+
* `opencode-db://<sessionId>` marker so the dashboard renders something
|
|
20
|
+
* meaningful and the value is distinguishable from a genuine miss.
|
|
21
|
+
*
|
|
22
|
+
* • Pi: shim doesn't forward transcript_path. Discover at
|
|
23
|
+
* ~/.pi/agent/sessions/<encodedCwd>/<isoTimestamp>_<sessionId>.jsonl.
|
|
24
|
+
*
|
|
25
|
+
* • Gemini: docs say stdin carries transcript_path, but coverage is uneven
|
|
26
|
+
* across versions. Trust stdin first; fall back to discovery under
|
|
27
|
+
* ~/.gemini/tmp/<projectHash>/chats/<sessionId>.json.
|
|
28
|
+
*
|
|
29
|
+
* Mirrors the dispatch pattern of `resolve-permission-mode.ts`. Each
|
|
30
|
+
* `find*Transcript` helper performs its own existsSync + path-traversal
|
|
31
|
+
* containment check, so passing in a malformed sessionId is safe (returns
|
|
32
|
+
* null → undefined).
|
|
33
|
+
*/
|
|
34
|
+
import { findCodexTranscript } from "../../lib/codex-sessions";
|
|
35
|
+
import { findCopilotTranscript } from "../../lib/copilot-sessions";
|
|
36
|
+
import { findCursorTranscript } from "../../lib/cursor-sessions";
|
|
37
|
+
import { findPiTranscript } from "../../lib/pi-sessions";
|
|
38
|
+
import { findGeminiTranscript } from "../../lib/gemini-sessions";
|
|
39
|
+
import type { IntegrationType } from "./types";
|
|
40
|
+
|
|
41
|
+
export function resolveTranscriptPath(
|
|
42
|
+
integration: IntegrationType,
|
|
43
|
+
parsed: Record<string, unknown>,
|
|
44
|
+
sessionId: string | undefined,
|
|
45
|
+
): string | undefined {
|
|
46
|
+
const stdinPath =
|
|
47
|
+
typeof parsed.transcript_path === "string" ? parsed.transcript_path : undefined;
|
|
48
|
+
if (stdinPath) return stdinPath;
|
|
49
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) return undefined;
|
|
50
|
+
|
|
51
|
+
switch (integration) {
|
|
52
|
+
case "claude":
|
|
53
|
+
return undefined;
|
|
54
|
+
case "codex":
|
|
55
|
+
return findCodexTranscript(sessionId) ?? undefined;
|
|
56
|
+
case "copilot":
|
|
57
|
+
return findCopilotTranscript(sessionId) ?? undefined;
|
|
58
|
+
case "cursor":
|
|
59
|
+
return findCursorTranscript(sessionId) ?? undefined;
|
|
60
|
+
case "pi":
|
|
61
|
+
return findPiTranscript(sessionId) ?? undefined;
|
|
62
|
+
case "gemini":
|
|
63
|
+
return findGeminiTranscript(sessionId) ?? undefined;
|
|
64
|
+
case "opencode":
|
|
65
|
+
return `opencode-db://${sessionId}`;
|
|
66
|
+
default:
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/hooks/types.ts
CHANGED
|
@@ -30,6 +30,21 @@ export const CODEX_EVENT_MAP: Record<CodexHookEventType, HookEventType> = {
|
|
|
30
30
|
stop: "Stop",
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Codex's per-tool canonicalization. Per
|
|
35
|
+
* https://developers.openai.com/codex/hooks the hook payload reports
|
|
36
|
+
* `tool_name: "Bash"` already PascalCase (passthrough) and `tool_name:
|
|
37
|
+
* "apply_patch"` for file edits even when matchers say `Edit`/`Write`.
|
|
38
|
+
* Local Codex sessions also expose `write_stdin` (sends input to a running
|
|
39
|
+
* shell — same risk class as Bash). Map the two non-canonical names so
|
|
40
|
+
* builtin policies fire; everything else (MCP `mcp__*`, future tools)
|
|
41
|
+
* passes through.
|
|
42
|
+
*/
|
|
43
|
+
export const CODEX_TOOL_MAP: Record<string, string> = {
|
|
44
|
+
apply_patch: "Edit",
|
|
45
|
+
write_stdin: "Bash",
|
|
46
|
+
};
|
|
47
|
+
|
|
33
48
|
// ── GitHub Copilot CLI ─────────────────────────────────────────────────────
|
|
34
49
|
//
|
|
35
50
|
// Copilot CLI accepts two payload formats. We install with PascalCase event
|
|
@@ -37,6 +52,13 @@ export const CODEX_EVENT_MAP: Record<CodexHookEventType, HookEventType> = {
|
|
|
37
52
|
// `hook_event_name` plus snake_case fields — same shape Claude already uses
|
|
38
53
|
// at the WRAPPER level (no event-name canonicalization needed).
|
|
39
54
|
//
|
|
55
|
+
// Empirically verified (Copilot CLI 1.0.41 against
|
|
56
|
+
// `~/.copilot/session-state/<id>/events.jsonl`): the user-scope PascalCase
|
|
57
|
+
// `Stop` entry IS dispatched on Copilot's native camelCase `agentStop` event
|
|
58
|
+
// — Copilot performs the alias mapping and case-fold internally so failproofai's
|
|
59
|
+
// `--hook Stop --cli copilot` invocation is what actually receives `agentStop`
|
|
60
|
+
// firings. Same alias rule applies to `SubagentStop` ↔ `subagentStop`.
|
|
61
|
+
//
|
|
40
62
|
// Tool names are a separate matter: Copilot's tool registry uses lowercase
|
|
41
63
|
// IDs (`bash`, `read`, `write`, `edit`, …) — confirmed by the session-log
|
|
42
64
|
// shape at `lib/copilot-sessions.ts:257` and the unit-test fixture at
|
|
@@ -45,6 +67,15 @@ export const CODEX_EVENT_MAP: Record<CodexHookEventType, HookEventType> = {
|
|
|
45
67
|
// without canonicalization every Bash/Read/Write/Edit builtin silently
|
|
46
68
|
// no-ops under Copilot. COPILOT_TOOL_MAP below is the source of truth.
|
|
47
69
|
//
|
|
70
|
+
// **Stop block semantics** (verified against Copilot CLI 1.0.41 + docs at
|
|
71
|
+
// https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-hooks-reference):
|
|
72
|
+
// `agentStop` accepts `{decision: "block", reason}` JSON on stdout — the reason
|
|
73
|
+
// becomes the next-turn prompt and the agent retries. **Exit-2 + stderr is NOT
|
|
74
|
+
// honored** — the session log shows it surfaced as `[WARNING] Hook warning: ...`
|
|
75
|
+
// to the user but the agent stops cleanly without retrying. policy-evaluator.ts
|
|
76
|
+
// has a `cli === "copilot"` Stop branch that emits the JSON-block shape so the
|
|
77
|
+
// 5 require-*-before-stop builtins actually enforce on Copilot sessions.
|
|
78
|
+
//
|
|
48
79
|
// Settings paths:
|
|
49
80
|
// user → ~/.copilot/hooks/failproofai.json
|
|
50
81
|
// project → <cwd>/.github/hooks/failproofai.json (also where the cloud agent reads)
|
|
@@ -60,6 +91,7 @@ export const COPILOT_HOOK_EVENT_TYPES = [
|
|
|
60
91
|
"PreToolUse",
|
|
61
92
|
"PostToolUse",
|
|
62
93
|
"Stop",
|
|
94
|
+
"SubagentStop",
|
|
63
95
|
] as const;
|
|
64
96
|
export type CopilotHookEventType = (typeof COPILOT_HOOK_EVENT_TYPES)[number];
|
|
65
97
|
|
|
@@ -76,13 +108,39 @@ export type CopilotHookEventType = (typeof COPILOT_HOOK_EVENT_TYPES)[number];
|
|
|
76
108
|
*/
|
|
77
109
|
export const COPILOT_TOOL_MAP: Record<string, string> = {
|
|
78
110
|
bash: "Bash",
|
|
111
|
+
// Windows shell + the *_bash / *_powershell session-management tools all
|
|
112
|
+
// execute or interact with shell commands, so they map to the same risk
|
|
113
|
+
// class as bash. Without this `block-sudo`, `block-rm-rf`,
|
|
114
|
+
// `block-read-outside-cwd` (Bash branch), etc. silently no-op for any
|
|
115
|
+
// command Copilot routes through powershell or a long-lived shell session.
|
|
116
|
+
powershell: "Bash",
|
|
117
|
+
list_bash: "Bash",
|
|
118
|
+
read_bash: "Bash",
|
|
119
|
+
stop_bash: "Bash",
|
|
120
|
+
write_bash: "Bash",
|
|
121
|
+
list_powershell: "Bash",
|
|
122
|
+
read_powershell: "Bash",
|
|
123
|
+
stop_powershell: "Bash",
|
|
124
|
+
write_powershell: "Bash",
|
|
79
125
|
read: "Read",
|
|
126
|
+
// `view` reads files OR lists directories
|
|
127
|
+
// (`{"toolName":"view","arguments":{"path":"/some/dir"}}` — verified
|
|
128
|
+
// empirically against Copilot CLI 1.0.39). Mapping to Read makes
|
|
129
|
+
// block-read-outside-cwd fire on `view` calls; the policy reads
|
|
130
|
+
// toolInput.path as a fallback to file_path so directory listings get
|
|
131
|
+
// covered by the same path check.
|
|
132
|
+
view: "Read",
|
|
133
|
+
show_file: "Read",
|
|
80
134
|
write: "Write",
|
|
135
|
+
create: "Write",
|
|
81
136
|
edit: "Edit",
|
|
137
|
+
apply_patch: "Edit",
|
|
82
138
|
str_replace_editor: "Edit",
|
|
83
139
|
glob: "Glob",
|
|
84
140
|
grep: "Grep",
|
|
141
|
+
rg: "Grep",
|
|
85
142
|
ls: "LS",
|
|
143
|
+
web_fetch: "WebFetch",
|
|
86
144
|
};
|
|
87
145
|
|
|
88
146
|
// ── Cursor Agent CLI ───────────────────────────────────────────────────────
|
|
@@ -122,6 +180,19 @@ export const CURSOR_EVENT_MAP: Record<CursorHookEventType, HookEventType> = {
|
|
|
122
180
|
stop: "Stop",
|
|
123
181
|
};
|
|
124
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Cursor delivers PascalCase tool names per https://cursor.com/docs/hooks
|
|
185
|
+
* (`Shell | Read | Write | Grep | Delete | Task | MCP:*`). All but `Shell`
|
|
186
|
+
* are already canonical (`Read`, `Write`, `Grep` match Claude verbatim) or
|
|
187
|
+
* have no Claude equivalent (`Delete`, `Task`, `MCP:*`) so passthrough is
|
|
188
|
+
* fine. `Shell` is Cursor's name for what Claude calls `Bash`; without this
|
|
189
|
+
* map every Bash builtin (`block-sudo`, `block-rm-rf`,
|
|
190
|
+
* `block-read-outside-cwd`, …) silently no-ops on Cursor sessions.
|
|
191
|
+
*/
|
|
192
|
+
export const CURSOR_TOOL_MAP: Record<string, string> = {
|
|
193
|
+
Shell: "Bash",
|
|
194
|
+
};
|
|
195
|
+
|
|
125
196
|
// ── OpenCode (sst/opencode) ─────────────────────────────────────────────────
|
|
126
197
|
//
|
|
127
198
|
// OpenCode's plugin model is fundamentally different from the other four CLIs:
|
|
@@ -193,10 +264,12 @@ export const OPENCODE_TOOL_MAP: Record<string, string> = {
|
|
|
193
264
|
read: "Read",
|
|
194
265
|
write: "Write",
|
|
195
266
|
edit: "Edit",
|
|
267
|
+
apply_patch: "Edit",
|
|
196
268
|
glob: "Glob",
|
|
197
269
|
grep: "Grep",
|
|
198
270
|
list: "LS",
|
|
199
271
|
webfetch: "WebFetch",
|
|
272
|
+
websearch: "WebSearch",
|
|
200
273
|
todowrite: "TodoWrite",
|
|
201
274
|
todoread: "TodoRead",
|
|
202
275
|
};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[88947,(e,t,r)=>{t.exports=e.x("stream",()=>require("stream"))},9311,e=>{"use strict";var t=e.i(47909),r=e.i(74017),a=e.i(96250),n=e.i(59756),o=e.i(61916),i=e.i(74677),s=e.i(69741),l=e.i(16795),d=e.i(87718),u=e.i(95169),c=e.i(47587),p=e.i(66012),f=e.i(70101),h=e.i(26937),m=e.i(10372),g=e.i(93695);e.i(20232);var R=e.i(220),E=e.i(89171),w=e.i(22734),v=e.i(24868),y=e.i(88947),C=e.i(40911),A=e.i(12714),x=e.i(50227),T=e.i(81580),j=e.i(83534),M=e.i(71809),P=e.i(28557);let N=/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;async function b(e,t){try{return(await (0,A.stat)(e)).mtime}catch(e){return(0,C.logWarn)(`Failed to stat ${t}:`,e),new Date(0)}}async function S(e){try{if(!(await (0,A.stat)(e)).isDirectory())return null;return await (0,A.readdir)(e,{withFileTypes:!0})}catch{return null}}async function O(){try{let e=(0,T.getClaudeProjectsPath)(),t=await S(e);if(!t)return[];let r=(await (0,M.batchAll)(t.filter(e=>e.isDirectory()).map(t=>async()=>{let r=(0,x.join)(e,t.name),a=await b(r,t.name);return{name:t.name,path:r,isDirectory:!0,lastModified:a,lastModifiedFormatted:(0,P.formatDate)(a),cli:["claude"]}}),16)).filter(e=>"fulfilled"===e.status).map(e=>e.value);return r.sort((e,t)=>t.lastModified.getTime()-e.lastModified.getTime()),r}catch(e){return(0,C.logError)("Error reading Claude project folders:",e),[]}}async function _(){let[{getCodexProjects:t},{getCopilotProjects:r},{getCursorProjects:a},{getOpenCodeProjects:n},{getPiProjects:o},{getGeminiProjects:i}]=await Promise.all([e.A(37352),e.A(5807),e.A(97452),e.A(82978),e.A(45093),e.A(61489)]),[s,l,d,u,c,p,f]=await Promise.all([O(),t().catch(e=>((0,C.logError)("Error reading Codex projects:",e),[])),r().catch(e=>((0,C.logError)("Error reading Copilot projects:",e),[])),a().catch(e=>((0,C.logError)("Error reading Cursor projects:",e),[])),n().catch(e=>((0,C.logError)("Error reading OpenCode projects:",e),[])),o().catch(e=>((0,C.logError)("Error reading Pi projects:",e),[])),i().catch(e=>((0,C.logError)("Error reading Gemini projects:",e),[]))]);return function(...e){let t=new Map;for(let r of e)for(let e of r){let r=t.get(e.name);if(!r){t.set(e.name,{...e,cli:[...e.cli]});continue}let a=[...r.cli];for(let t of e.cli)a.includes(t)||a.push(t);let n=e.lastModified.getTime()>r.lastModified.getTime()?e:r;t.set(e.name,{...r,cli:a,lastModified:n.lastModified,lastModifiedFormatted:n.lastModifiedFormatted})}let r=Array.from(t.values());return r.sort((e,t)=>t.lastModified.getTime()-e.lastModified.getTime()),r}(s,l,d,u,c,p,f)}function D(e){let t=e.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);return t?t[0]:void 0}async function I(e){try{let t=await S(e);if(!t)return[];let r=t.filter(e=>e.isFile()&&e.name.endsWith(".jsonl")&&D(e.name)),a=(await (0,M.batchAll)(r.map(t=>async()=>{let r=(0,x.join)(e,t.name),a=await b(r,t.name);return{name:t.name,path:r,lastModified:a,lastModifiedFormatted:(0,P.formatDate)(a),sessionId:D(t.name),cli:"claude"}}),16)).filter(e=>"fulfilled"===e.status).map(e=>e.value);return a.sort((e,t)=>t.lastModified.getTime()-e.lastModified.getTime()),a}catch(e){return(0,C.logError)("Error reading session files:",e),[]}}function q(e,t){return E.NextResponse.json({error:e},{status:t})}async function H(e,{params:t}){let r,{project:a,session:n}=await t;try{r=function(e,t){if(!N.test(t))throw RangeError("Invalid session ID");let r=function(e){if(!e)throw RangeError("Empty project name");if(/^[/\\]/.test(e))throw RangeError("Absolute project name");let t=(0,x.resolve)((0,T.getClaudeProjectsPath)()),r=(0,x.resolve)((0,x.join)(t,e));if(!r.startsWith(t+x.sep))throw RangeError("Project path escapes root");return r}(e);return(0,x.join)(r,`${t}.jsonl`)}(a,n)}catch{return q("Invalid project or session",400)}(0,C.logActivity)("anonymous","download-log",`project=${a} session=${n}`);try{await (0,v.stat)(r);let e=(0,w.createReadStream)(r),t=y.Readable.toWeb(e);return new E.NextResponse(t,{headers:{"Content-Type":"application/x-ndjson","Content-Disposition":`attachment; filename="${n}.jsonl"`}})}catch(e){if("ENOENT"===e.code||e instanceof RangeError)return q("Session log not found",404);return q("Failed to read session log",500)}}(0,j.runtimeCache)(_,30),(0,j.runtimeCache)(e=>I(e),30),e.s(["GET",0,H],32525);var F=e.i(32525);let U=new t.AppRouteRouteModule({definition:{kind:r.RouteKind.APP_ROUTE,page:"/api/download/[project]/[session]/route",pathname:"/api/download/[project]/[session]",filename:"route",bundlePath:""},distDir:".next",relativeProjectDir:"",resolvedPagePath:"[project]/app/api/download/[project]/[session]/route.ts",nextConfigOutput:"standalone",userland:F,...{}}),{workAsyncStorage:$,workUnitAsyncStorage:k,serverHooks:K}=U;async function W(e,t,a){a.requestMeta&&(0,n.setRequestMeta)(e,a.requestMeta),U.isDev&&(0,n.addRequestMeta)(e,"devRequestTimingInternalsEnd",process.hrtime.bigint());let E="/api/download/[project]/[session]/route";E=E.replace(/\/index$/,"")||"/";let w=await U.prepare(e,t,{srcPage:E,multiZoneDraftMode:!1});if(!w)return t.statusCode=400,t.end("Bad Request"),null==a.waitUntil||a.waitUntil.call(a,Promise.resolve()),null;let{buildId:v,params:y,nextConfig:C,parsedUrl:A,isDraftMode:x,prerenderManifest:T,routerServerContext:j,isOnDemandRevalidate:M,revalidateOnlyGenerated:P,resolvedPathname:N,clientReferenceManifest:b,serverActionsManifest:S}=w,O=(0,s.normalizeAppPath)(E),_=!!(T.dynamicRoutes[O]||T.routes[N]),D=async()=>((null==j?void 0:j.render404)?await j.render404(e,t,A,!1):t.end("This page could not be found"),null);if(_&&!x){let e=!!T.routes[N],t=T.dynamicRoutes[O];if(t&&!1===t.fallback&&!e){if(C.adapterPath)return await D();throw new g.NoFallbackError}}let I=null;!_||U.isDev||x||(I="/index"===(I=N)?"/":I);let q=!0===U.isDev||!_,H=_&&!q;S&&b&&(0,i.setManifestsSingleton)({page:E,clientReferenceManifest:b,serverActionsManifest:S});let F=e.method||"GET",$=(0,o.getTracer)(),k=$.getActiveScopeSpan(),K=!!(null==j?void 0:j.isWrappedByNextServer),W=!!(0,n.getRequestMeta)(e,"minimalMode"),B=(0,n.getRequestMeta)(e,"incrementalCache")||await U.getIncrementalCache(e,C,T,W);null==B||B.resetRequestCache(),globalThis.__incrementalCache=B;let G={params:y,previewProps:T.preview,renderOpts:{experimental:{authInterrupts:!!C.experimental.authInterrupts},cacheComponents:!!C.cacheComponents,supportsDynamicResponse:q,incrementalCache:B,cacheLifeProfiles:C.cacheLife,waitUntil:a.waitUntil,onClose:e=>{t.on("close",e)},onAfterTaskError:void 0,onInstrumentationRequestError:(t,r,a,n)=>U.onRequestError(e,t,a,n,j)},sharedContext:{buildId:v}},L=new l.NodeNextRequest(e),V=new l.NodeNextResponse(t),X=d.NextRequestAdapter.fromNodeNextRequest(L,(0,d.signalFromNodeResponse)(t));try{let n,i=async e=>U.handle(X,G).finally(()=>{if(!e)return;e.setAttributes({"http.status_code":t.statusCode,"next.rsc":!1});let r=$.getRootSpanAttributes();if(!r)return;if(r.get("next.span_type")!==u.BaseServerSpan.handleRequest)return void console.warn(`Unexpected root span type '${r.get("next.span_type")}'. Please report this Next.js issue https://github.com/vercel/next.js`);let a=r.get("next.route");if(a){let t=`${F} ${a}`;e.setAttributes({"next.route":a,"http.route":a,"next.span_name":t}),e.updateName(t),n&&n!==e&&(n.setAttribute("http.route",a),n.updateName(t))}else e.updateName(`${F} ${E}`)}),s=async n=>{var o,s;let l=async({previousCacheEntry:r})=>{try{if(!W&&M&&P&&!r)return t.statusCode=404,t.setHeader("x-nextjs-cache","REVALIDATED"),t.end("This page could not be found"),null;let o=await i(n);e.fetchMetrics=G.renderOpts.fetchMetrics;let s=G.renderOpts.pendingWaitUntil;s&&a.waitUntil&&(a.waitUntil(s),s=void 0);let l=G.renderOpts.collectedTags;if(!_)return await (0,p.sendResponse)(L,V,o,G.renderOpts.pendingWaitUntil),null;{let e=await o.blob(),t=(0,f.toNodeOutgoingHttpHeaders)(o.headers);l&&(t[m.NEXT_CACHE_TAGS_HEADER]=l),!t["content-type"]&&e.type&&(t["content-type"]=e.type);let r=void 0!==G.renderOpts.collectedRevalidate&&!(G.renderOpts.collectedRevalidate>=m.INFINITE_CACHE)&&G.renderOpts.collectedRevalidate,a=void 0===G.renderOpts.collectedExpire||G.renderOpts.collectedExpire>=m.INFINITE_CACHE?void 0:G.renderOpts.collectedExpire;return{value:{kind:R.CachedRouteKind.APP_ROUTE,status:o.status,body:Buffer.from(await e.arrayBuffer()),headers:t},cacheControl:{revalidate:r,expire:a}}}}catch(t){throw(null==r?void 0:r.isStale)&&await U.onRequestError(e,t,{routerKind:"App Router",routePath:E,routeType:"route",revalidateReason:(0,c.getRevalidateReason)({isStaticGeneration:H,isOnDemandRevalidate:M})},!1,j),t}},d=await U.handleResponse({req:e,nextConfig:C,cacheKey:I,routeKind:r.RouteKind.APP_ROUTE,isFallback:!1,prerenderManifest:T,isRoutePPREnabled:!1,isOnDemandRevalidate:M,revalidateOnlyGenerated:P,responseGenerator:l,waitUntil:a.waitUntil,isMinimalMode:W});if(!_)return null;if((null==d||null==(o=d.value)?void 0:o.kind)!==R.CachedRouteKind.APP_ROUTE)throw Object.defineProperty(Error(`Invariant: app-route received invalid cache entry ${null==d||null==(s=d.value)?void 0:s.kind}`),"__NEXT_ERROR_CODE",{value:"E701",enumerable:!1,configurable:!0});W||t.setHeader("x-nextjs-cache",M?"REVALIDATED":d.isMiss?"MISS":d.isStale?"STALE":"HIT"),x&&t.setHeader("Cache-Control","private, no-cache, no-store, max-age=0, must-revalidate");let u=(0,f.fromNodeOutgoingHttpHeaders)(d.value.headers);return W&&_||u.delete(m.NEXT_CACHE_TAGS_HEADER),!d.cacheControl||t.getHeader("Cache-Control")||u.get("Cache-Control")||u.set("Cache-Control",(0,h.getCacheControlHeader)(d.cacheControl)),await (0,p.sendResponse)(L,V,new Response(d.value.body,{headers:u,status:d.value.status||200})),null};K&&k?await s(k):(n=$.getActiveScopeSpan(),await $.withPropagatedContext(e.headers,()=>$.trace(u.BaseServerSpan.handleRequest,{spanName:`${F} ${E}`,kind:o.SpanKind.SERVER,attributes:{"http.method":F,"http.target":e.url}},s),void 0,!K))}catch(t){if(t instanceof g.NoFallbackError||await U.onRequestError(e,t,{routerKind:"App Router",routePath:O,routeType:"route",revalidateReason:(0,c.getRevalidateReason)({isStaticGeneration:H,isOnDemandRevalidate:M})},!1,j),_)throw t;return await (0,p.sendResponse)(L,V,new Response(null,{status:500})),null}}e.s(["handler",0,W,"patchFetch",0,function(){return(0,a.patchFetch)({workAsyncStorage:$,workUnitAsyncStorage:k})},"routeModule",0,U,"serverHooks",0,K,"workAsyncStorage",0,$,"workUnitAsyncStorage",0,k],9311)}];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__0b57.gk._.js.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[18622,(e,r,t)=>{r.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"))},56704,(e,r,t)=>{r.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,r,t)=>{r.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"))},24725,(e,r,t)=>{r.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"))},70406,(e,r,t)=>{r.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},93695,(e,r,t)=>{r.exports=e.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},50227,(e,r,t)=>{r.exports=e.x("node:path",()=>require("node:path"))},14747,(e,r,t)=>{r.exports=e.x("path",()=>require("path"))},46786,(e,r,t)=>{r.exports=e.x("os",()=>require("os"))},12714,(e,r,t)=>{r.exports=e.x("node:fs/promises",()=>require("node:fs/promises"))},40911,e=>{"use strict";let r={info:0,warn:1,error:2};function t(e){return r[e]>=r.warn}function s(e){return`[failproofai${new Date().toISOString()}] ${e}`}e.s(["logActivity",0,function(e,r,n){if(!t("info"))return;let o=[`user=${e}`,`action=${r}`];n&&o.push(n),console.log(s("ACTIVITY"),o.join(" "))},"logError",0,function(e,r){void 0!==r?console.error(s("ERROR"),e,r):console.error(s("ERROR"),e)},"logWarn",0,function(e,r){t("warn")&&(void 0!==r?console.warn(s("WARN"),e,r):console.warn(s("WARN"),e))}])},81580,e=>{"use strict";var r=e.i(46786),t=e.i(14747);e.s(["decodeFolderName",0,function(e){return/^[A-Za-z]--/.test(e)?e[0]+":/"+e.slice(3).replace(/-/g,"/"):e.replace(/-/g,"/")},"encodeFolderName",0,function(e){let r=/^([A-Za-z]):[\\/](.*)$/.exec(e);return r?r[1]+"--"+r[2].replace(/[\\/]/g,"-"):e.replace(/[\\/]/g,"-")},"getClaudeProjectsPath",0,function(){let e=process.env.CLAUDE_PROJECTS_PATH;return e||(0,t.join)((0,r.homedir)(),".claude","projects")}])},83534,28557,e=>{"use strict";e.s(["runtimeCache",0,function(e,r,t){let s=new Map,n=new Map,o=t?.maxSize;return async(...t)=>{let a=JSON.stringify(t),i=s.get(a);if(i&&Date.now()<i.expiry)return i.data;let l=n.get(a);if(l)return l;let u=e(...t).then(e=>{if(n.delete(a),o&&s.size>=o){let e=s.keys().next().value;s.delete(e)}return s.set(a,{data:e,expiry:Date.now()+1e3*r}),e},e=>{throw n.delete(a),e});return n.set(a,u),u}}],83534),e.s(["formatDate",0,function(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).format(e)}],28557)},71809,e=>{"use strict";async function r(e,r){let t=Array(e.length),s=0;async function n(){for(;s<e.length;){let r=s++;try{t[r]={status:"fulfilled",value:await e[r]()}}catch(e){t[r]={status:"rejected",reason:e}}}}let o=Array.from({length:Math.min(r,e.length)},()=>n());return await Promise.all(o),t}e.s(["batchAll",0,r])},24868,(e,r,t)=>{r.exports=e.x("fs/promises",()=>require("fs/promises"))},22734,(e,r,t)=>{r.exports=e.x("fs",()=>require("fs"))},37352,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0wu7fr7._.js"].map(r=>e.l(r))).then(()=>r(36203)))},5807,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0.~nmr9._.js"].map(r=>e.l(r))).then(()=>r(55851)))},97452,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0zso~62._.js"].map(r=>e.l(r))).then(()=>r(46413)))},82978,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0yfq1yr._.js"].map(r=>e.l(r))).then(()=>r(35435)))},45093,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__08px0ym._.js"].map(r=>e.l(r))).then(()=>r(19791)))},61489,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0vlhtkc._.js"].map(r=>e.l(r))).then(()=>r(90172)))}];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__0z4c5dj._.js.map
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
module.exports=[50227,(a,b,c)=>{b.exports=a.x("node:path",()=>require("node:path"))},60526,(a,b,c)=>{b.exports=a.x("node:os",()=>require("node:os"))},12714,(a,b,c)=>{b.exports=a.x("node:fs/promises",()=>require("node:fs/promises"))},74533,(a,b,c)=>{b.exports=a.x("node:child_process",()=>require("node:child_process"))},2157,(a,b,c)=>{b.exports=a.x("node:fs",()=>require("node:fs"))},66680,(a,b,c)=>{b.exports=a.x("node:crypto",()=>require("node:crypto"))},37936,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"registerServerReference",{enumerable:!0,get:function(){return d.registerServerReference}});let d=a.r(11857)},12072,(a,b,c)=>{b.exports={name:"failproofai",version:"0.0.10-beta.2",description:"The easiest way to manage policies that keep your AI agents reliable, on-task, and running autonomously — for Claude Code & the Agents SDK",bin:{failproofai:"./dist/cli.mjs"},files:["bin/","src/","scripts/","lib/","pi-extension/",".next/standalone/","dist/","README.md"],engines:{node:">=20.9.0",bun:">=1.3.0"},scripts:{predev:"bun run build:cli && bun link",dev:"FAILPROOFAI_TELEMETRY_DISABLED=1 bun scripts/dev.ts --port 8020","build:cli":"bun build --target=node --format=esm --outfile=dist/cli.mjs bin/failproofai.mjs --external posthog-node && node -e \"const fs=require('fs');const c=fs.readFileSync('dist/cli.mjs','utf8');fs.writeFileSync('dist/cli.mjs',c.replace('#!/usr/bin/env bun','#!/usr/bin/env node').replace('// @bun\\n',''))\"",build:"bun build --target=node --format=cjs --outfile=dist/index.js src/index.ts && bun run build:cli && bun --bun next build && node -e \"const {cpSync}=require('fs');cpSync('.next/static','.next/standalone/.next/static',{recursive:true});\" && node scripts/prune-standalone.mjs",prestart:"bun run build:cli && bun link",start:"FAILPROOFAI_TELEMETRY_DISABLED=1 bun scripts/start.ts",test:"vitest","test:run":"vitest run",lint:"eslint . --config eslint.config.mjs",postinstall:"node scripts/postinstall.mjs",preuninstall:"node scripts/preuninstall.mjs",prepare:"bun run build","test:e2e":"vitest run --config vitest.config.e2e.mts","test:e2e:watch":"vitest --config vitest.config.e2e.mts",translate:"bun scripts/translate-docs/cli.ts","translate:readme":"bun scripts/translate-docs/cli.ts --readme-only","translate:docs":"bun scripts/translate-docs/cli.ts --docs-only","translate:dry-run":"bun scripts/translate-docs/cli.ts --dry-run","translate:validate":"bun scripts/translate-docs/cli.ts --validate"},keywords:["claude","claude-code","claude-agents-sdk","anthropic","ai-agent","agent-reliability","agent-monitoring","autonomous-agent","failure-prevention","developer-tools","devtools","cli","local-first","hooks","policies"],author:"ExosphereHost Inc. <failproofai@exosphere.host>",license:"SEE LICENSE IN LICENSE",homepage:"https://github.com/exospherehost/failproofai",repository:{type:"git",url:"https://github.com/exospherehost/failproofai.git"},bugs:{url:"https://github.com/exospherehost/failproofai/issues"},publishConfig:{access:"public"},devDependencies:{"@tailwindcss/postcss":"^4.1.18","@tanstack/react-virtual":"^3.13.18","@testing-library/jest-dom":"^6.9.1","@testing-library/react":"^16.3.2","@testing-library/user-event":"^14.6.1","@types/node":"^25.5.2","@types/react":"^19.2.13","@types/react-dom":"^19.2.3","@vitejs/plugin-react":"^6.0.1",clsx:"^2.1.1",eslint:"^10.2.0","eslint-config-next":"^16.2.2","happy-dom":"^20.7.0","lucide-react":"^1.0.1",next:"^16.2.2",react:"^19.2.4","react-dom":"^19.2.4","tailwind-merge":"^3.4.0",tailwindcss:"^4.1.18",typescript:"^6.0.2","@anthropic-ai/sdk":"^0.93.0",vitest:"^4.0.18"},dependencies:{"posthog-node":"^5.28.11"}}},13095,(a,b,c)=>{"use strict";function d(a){for(let b=0;b<a.length;b++){let c=a[b];if("function"!=typeof c)throw Object.defineProperty(Error(`A "use server" file can only export async functions, found ${typeof c}.
|
|
2
|
-
Read more: https://nextjs.org/docs/messages/invalid-use-server-value`),"__NEXT_ERROR_CODE",{value:"E352",enumerable:!1,configurable:!0})}}Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"ensureServerEntryExports",{enumerable:!0,get:function(){return d}})},36359,69839,79779,a=>{"use strict";let b;var c=a.i(37936),d=a.i(2157),e=a.i(50227),f=a.i(60526),g=a.i(66680);a.i(74533);let h=e.default.join(f.default.homedir(),".failproofai"),i=e.default.join(h,"instance-id");function j(a){return g.default.createHmac("sha256","failproofai-telemetry-v1").update(a).digest("hex")}function k(){if(b)return b;let a=function(){try{for(let a of(f.default.platform(),["/etc/machine-id","/var/lib/dbus/machine-id"]))try{let b=d.default.readFileSync(a,"utf-8").trim();if(b)return b}catch{}}catch{}}();if(a)return b=j(a);let c=[f.default.hostname(),f.default.homedir(),f.default.platform(),f.default.arch(),f.default.cpus()[0]?.model??""].join(":");return b=c?j(c):function(){try{let a=d.default.readFileSync(i,"utf-8").trim();if(a)return a}catch{}let a=g.default.randomUUID();try{d.default.mkdirSync(h,{recursive:!0}),d.default.writeFileSync(i,a,"utf-8")}catch{}return a}()}a.s(["getInstanceId",0,k,"hashToId",0,j],69839),a.s(["POSTHOG_API_KEY",0,"phc_Ac1Ww1GqKc0z1SyrRWbmatEeQdlOQIsDEEdP8l8JRgX"],79779);var l=a.i(12072);async function m(){let a="1"!==process.env.FAILPROOFAI_TELEMETRY_DISABLED;return{enabled:a,distinctId:a?k():"",apiKey:process.env.FAILPROOFAI_POSTHOG_KEY??"phc_Ac1Ww1GqKc0z1SyrRWbmatEeQdlOQIsDEEdP8l8JRgX",host:process.env.FAILPROOFAI_POSTHOG_HOST??"https://us.i.posthog.com",version:l.version}}(0,a.i(13095).ensureServerEntryExports)([m]),(0,c.registerServerReference)(m,"0093ba850168e5577955a082a23dfc9130f1ac1407",null),a.s(["getTelemetryConfig",0,m],36359)},24868,(a,b,c)=>{b.exports=a.x("fs/promises",()=>require("fs/promises"))},1457,(a,b,c)=>{b.exports=a.x("node:readline",()=>require("node:readline"))},7292,a=>{"use strict";var b=a.i(37936),c=a.i(2157),d=a.i(50227),e=a.i(60526);let f=(0,d.join)((0,e.homedir)(),".failproofai","cache","hook-activity"),g="current.jsonl";function h(){(0,c.existsSync)(f)||(0,c.mkdirSync)(f,{recursive:!0})}function i(){let a=function(){try{return JSON.parse((0,c.readFileSync)((0,d.join)(f,"stats.json"),"utf-8"))}catch{return{totalEvents:0,denyCount:0,policyMap:{}}}}(),b=null,e=0;for(let[c,d]of Object.entries(a.policyMap))d>e&&(b=c,e=d);return{totalEvents:a.totalEvents,denyCount:a.denyCount,topPolicy:b,topPolicyCount:e}}function j(a){let b=function(a){try{return(0,c.readFileSync)(a,"utf-8")}catch{return""}}(a);if(!b.trim())return[];let d=[];for(let a of b.trim().split("\n"))try{d.push(JSON.parse(a))}catch{}return d}function k(){try{return(0,c.readdirSync)(f).filter(a=>a.startsWith("page-")&&a.endsWith(".jsonl")).sort((a,b)=>{let c=a.slice(5,-6).split("-"),d=b.slice(5,-6).split("-"),e=parseInt(c[0],10),f=parseInt(d[0],10);if(e!==f)return f-e;let g=c.length>1?parseInt(c[1],10):0;return(d.length>1?parseInt(d[1],10):0)-g})}catch{return[]}}async function l(a){let b;return b=function(a){if(h(),a<1)return[];if(1===a)return j((0,d.join)(f,g)).reverse();let b=k(),c=a-2;return c>=b.length?[]:j((0,d.join)(f,b[c])).reverse()}(a),h(),{entries:b,totalPages:1+k().length,page:a,stats:i()}}async function m(a,b){let c,e,l;return e=Math.max(1,Math.ceil((c=(function(){h();let a=j((0,d.join)(f,g)).reverse(),b=k(),c=[];for(let a of b){let b=j((0,d.join)(f,a));c.push(...b.reverse())}return[...a,...c]})().filter(b=>(!a.decision||b.decision===a.decision)&&(!a.eventType||b.eventType===a.eventType)&&(!a.policyName||!!b.policyName&&!!b.policyName.toLowerCase().includes(a.policyName.toLowerCase()))&&(!a.sessionId||!!b.sessionId&&!!b.sessionId.toLowerCase().includes(a.sessionId.toLowerCase()))&&(!a.integration||b.integration===a.integration))).length/25)),l=(b-1)*25,{entries:c.slice(l,l+25),totalPages:e,page:b,stats:i()}}(0,a.i(13095).ensureServerEntryExports)([l,m]),(0,b.registerServerReference)(l,"403eae75122453abcf4043a6ec0d83422ce1d566d8",null),(0,b.registerServerReference)(m,"60139a5cfb4041468f75d94ed2d3844ae7e54239ef",null),a.s(["getHookActivityAction",0,l,"searchHookActivityAction",0,m],7292)},2726,a=>{a.v(b=>Promise.all(["server/chunks/ssr/[externals]_node_async_hooks_0v0ln8c._.js","server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mebn66._.js"].map(b=>a.l(b))).then(()=>b(74493)))}];
|
|
3
|
-
|
|
4
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__0.~m-w2._.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,53348,e=>{"use strict";var r=e.i(43476),t=e.i(71645),n=e.i(23328),i=e.i(9969);e.s(["default",0,function({error:e,reset:o}){return(0,t.useEffect)(()=>{(0,n.getTelemetryConfig)().then(r=>{(0,i.setClientTelemetryConfig)(r),(0,i.captureClientEvent)("client_error",{error_message:e.message,error_name:e.name,error_digest:e.digest,boundary:"global"})}).catch(()=>{})},[e]),(0,r.jsx)("html",{children:(0,r.jsx)("body",{children:(0,r.jsx)("main",{style:{minHeight:"100vh",display:"flex",alignItems:"center",justifyContent:"center",background:"#031035",color:"#f8fafc",fontFamily:"system-ui, sans-serif"},children:(0,r.jsxs)("div",{style:{textAlign:"center",padding:"2rem",border:"1px solid rgba(239,68,68,0.4)",borderRadius:"0.5rem",maxWidth:"500px"},children:[(0,r.jsx)("h2",{style:{color:"#ef4444",marginBottom:"0.5rem",fontSize:"1.25rem"},children:"Something went wrong"}),(0,r.jsx)("p",{style:{color:"#94a3b8",marginBottom:"1.5rem"},children:e.message||"An unexpected error occurred."}),(0,r.jsx)("button",{onClick:o,style:{padding:"0.5rem 1.25rem",background:"#3b82f6",color:"white",border:"none",borderRadius:"0.375rem",cursor:"pointer",fontSize:"0.875rem"},children:"Try again"})]})})})})}])}]);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|