failproofai 0.0.10-beta.2 → 0.0.10-beta.3

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 (121) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
  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 +2 -2
  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/_head.segment.rsc +3 -3
  14. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  15. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  16. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
  18. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  21. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  22. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  23. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  24. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
  25. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  26. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  27. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  28. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -2
  29. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/index.html +1 -1
  31. package/.next/standalone/.next/server/app/index.rsc +15 -15
  32. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  33. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  34. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  35. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  36. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  37. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  38. package/.next/standalone/.next/server/app/page.js +2 -2
  39. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  41. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
  42. package/.next/standalone/.next/server/app/policies/page.js +2 -2
  43. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  46. package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
  47. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  50. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  51. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +3 -3
  52. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  55. package/.next/standalone/.next/server/app/projects/page.js +2 -2
  56. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06.arfm._.js +3 -0
  59. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__i0h0._.js +3 -0
  60. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0dtn9lr._.js → [root-of-the-server]__0d_ob4n._.js} +2 -2
  61. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fe7_q_._.js +3 -0
  62. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fjhqi9._.js +3 -0
  63. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fw.e.h._.js +3 -0
  64. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kjo7d_._.js +1 -1
  65. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0pxn0e1._.js +3 -0
  66. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xv0jh2._.js +3 -0
  67. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__010i6f5._.js → [root-of-the-server]__0z-180.._.js} +2 -2
  68. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
  69. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0dl0kgt._.js → [root-of-the-server]__01hj~sd._.js} +3 -3
  70. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0s~gy6y._.js → [root-of-the-server]__02r6nu-._.js} +2 -2
  71. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0bz245.._.js → [root-of-the-server]__04dywib._.js} +3 -3
  72. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0gmhxyo._.js → [root-of-the-server]__06sb2gn._.js} +3 -3
  73. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0-2wr.c._.js → [root-of-the-server]__09jpajs._.js} +3 -3
  74. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0tt8-uq._.js → [root-of-the-server]__0_w9zxm._.js} +2 -2
  75. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0qbpe_v._.js → [root-of-the-server]__0jm6jnh._.js} +2 -2
  76. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0709m8.._.js → [root-of-the-server]__0joez.y._.js} +3 -3
  77. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ohb3gc._.js → [root-of-the-server]__0mi5ejy._.js} +3 -3
  78. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u1i~9~._.js +4 -0
  79. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ils1oq._.js → [root-of-the-server]__0ubu8l-._.js} +2 -2
  80. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__09y9okz._.js → [root-of-the-server]__0x5limi._.js} +2 -2
  81. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ymlddl._.js +4 -2
  82. package/.next/standalone/.next/server/chunks/ssr/_10lm7or._.js +2 -2
  83. package/.next/standalone/.next/server/chunks/ssr/app_0cdqd9w._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
  85. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +1 -1
  86. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  87. package/.next/standalone/.next/server/pages/404.html +2 -2
  88. package/.next/standalone/.next/server/pages/500.html +1 -1
  89. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  90. package/.next/standalone/.next/server/server-reference-manifest.json +9 -9
  91. package/.next/standalone/.next/static/chunks/{0yzl~f-qji0...js → 07eq~npz7kgfj.js} +2 -2
  92. package/.next/standalone/.next/static/chunks/{02h_cfxpk4x9..js → 09641cc.__kew.js} +1 -1
  93. package/.next/standalone/.next/static/chunks/{0a_w-lcg.0tl7.js → 0f71_v2xuw72j.js} +1 -1
  94. package/.next/standalone/.next/static/chunks/{0-dltnti0ew4y.js → 0hi_rm16gd38u.js} +1 -1
  95. package/.next/standalone/.next/static/chunks/{16k5y9ruha2v4.js → 0j_iidagrrk~f.js} +1 -1
  96. package/.next/standalone/.next/static/chunks/{0y8oyen~jnjl3.js → 0ojx~vrd~imo5.js} +1 -1
  97. package/.next/standalone/.next/static/chunks/{0lscbfo_2_h14.js → 0ut-9awqc4eg7.js} +2 -2
  98. package/.next/standalone/.next/static/chunks/{17o7-pn_xzt-t.js → 12lph7otiljrs.js} +1 -1
  99. package/.next/standalone/app/api/download/[project]/[session]/route.ts +26 -10
  100. package/.next/standalone/app/components/session-hooks-panel.tsx +3 -0
  101. package/.next/standalone/app/policies/hooks-client.tsx +3 -0
  102. package/.next/standalone/app/project/[name]/session/[sessionId]/page.tsx +8 -10
  103. package/.next/standalone/lib/download-session.ts +92 -0
  104. package/.next/standalone/lib/opencode-sessions.ts +42 -0
  105. package/.next/standalone/package.json +1 -1
  106. package/.next/standalone/server.js +1 -1
  107. package/dist/cli.mjs +1275 -323
  108. package/lib/download-session.ts +92 -0
  109. package/lib/opencode-sessions.ts +42 -0
  110. package/package.json +1 -1
  111. package/src/hooks/builtin-policies.ts +4 -3
  112. package/src/hooks/handler.ts +22 -12
  113. package/src/hooks/integrations.ts +2 -0
  114. package/src/hooks/resolve-transcript-path.ts +69 -0
  115. package/src/hooks/types.ts +56 -0
  116. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b57.gk._.js +0 -3
  117. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0z4c5dj._.js +0 -3
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0.~m-w2._.js +0 -4
  119. /package/.next/standalone/.next/static/{EBbXdrT2rHib3zGLSuY7Q → -I0-MyujalFaOVem9w5Bf}/_buildManifest.js +0 -0
  120. /package/.next/standalone/.next/static/{EBbXdrT2rHib3zGLSuY7Q → -I0-MyujalFaOVem9w5Bf}/_clientMiddlewareManifest.js +0 -0
  121. /package/.next/standalone/.next/static/{EBbXdrT2rHib3zGLSuY7Q → -I0-MyujalFaOVem9w5Bf}/_ssgManifest.js +0 -0
package/dist/cli.mjs CHANGED
@@ -16,7 +16,7 @@ var __export = (target, all) => {
16
16
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
17
 
18
18
  // src/hooks/types.ts
19
- var HOOK_SCOPES, INTEGRATION_TYPES, CODEX_HOOK_SCOPES, CODEX_HOOK_EVENT_TYPES, CODEX_EVENT_MAP, COPILOT_HOOK_SCOPES, COPILOT_HOOK_EVENT_TYPES, COPILOT_TOOL_MAP, CURSOR_HOOK_SCOPES, CURSOR_HOOK_EVENT_TYPES, CURSOR_EVENT_MAP, OPENCODE_HOOK_SCOPES, OPENCODE_HOOK_EVENT_TYPES, PI_HOOK_SCOPES, PI_HOOK_EVENT_TYPES, PI_EVENT_MAP, GEMINI_HOOK_SCOPES, GEMINI_HOOK_EVENT_TYPES, GEMINI_EVENT_MAP, GEMINI_TOOL_MAP, HOOK_EVENT_TYPES, FAILPROOFAI_HOOK_MARKER = "__failproofai_hook__";
19
+ var HOOK_SCOPES, INTEGRATION_TYPES, CODEX_HOOK_SCOPES, CODEX_HOOK_EVENT_TYPES, CODEX_EVENT_MAP, CODEX_TOOL_MAP, COPILOT_HOOK_SCOPES, COPILOT_HOOK_EVENT_TYPES, COPILOT_TOOL_MAP, CURSOR_HOOK_SCOPES, CURSOR_HOOK_EVENT_TYPES, CURSOR_EVENT_MAP, CURSOR_TOOL_MAP, OPENCODE_HOOK_SCOPES, OPENCODE_HOOK_EVENT_TYPES, PI_HOOK_SCOPES, PI_HOOK_EVENT_TYPES, PI_EVENT_MAP, GEMINI_HOOK_SCOPES, GEMINI_HOOK_EVENT_TYPES, GEMINI_EVENT_MAP, GEMINI_TOOL_MAP, HOOK_EVENT_TYPES, FAILPROOFAI_HOOK_MARKER = "__failproofai_hook__";
20
20
  var init_types = __esm(() => {
21
21
  HOOK_SCOPES = ["user", "project", "local"];
22
22
  INTEGRATION_TYPES = ["claude", "codex", "copilot", "cursor", "opencode", "pi", "gemini"];
@@ -37,6 +37,10 @@ var init_types = __esm(() => {
37
37
  user_prompt_submit: "UserPromptSubmit",
38
38
  stop: "Stop"
39
39
  };
40
+ CODEX_TOOL_MAP = {
41
+ apply_patch: "Edit",
42
+ write_stdin: "Bash"
43
+ };
40
44
  COPILOT_HOOK_SCOPES = ["user", "project"];
41
45
  COPILOT_HOOK_EVENT_TYPES = [
42
46
  "SessionStart",
@@ -48,13 +52,28 @@ var init_types = __esm(() => {
48
52
  ];
49
53
  COPILOT_TOOL_MAP = {
50
54
  bash: "Bash",
55
+ powershell: "Bash",
56
+ list_bash: "Bash",
57
+ read_bash: "Bash",
58
+ stop_bash: "Bash",
59
+ write_bash: "Bash",
60
+ list_powershell: "Bash",
61
+ read_powershell: "Bash",
62
+ stop_powershell: "Bash",
63
+ write_powershell: "Bash",
51
64
  read: "Read",
65
+ view: "Read",
66
+ show_file: "Read",
52
67
  write: "Write",
68
+ create: "Write",
53
69
  edit: "Edit",
70
+ apply_patch: "Edit",
54
71
  str_replace_editor: "Edit",
55
72
  glob: "Glob",
56
73
  grep: "Grep",
57
- ls: "LS"
74
+ rg: "Grep",
75
+ ls: "LS",
76
+ web_fetch: "WebFetch"
58
77
  };
59
78
  CURSOR_HOOK_SCOPES = ["user", "project"];
60
79
  CURSOR_HOOK_EVENT_TYPES = [
@@ -73,6 +92,9 @@ var init_types = __esm(() => {
73
92
  postToolUse: "PostToolUse",
74
93
  stop: "Stop"
75
94
  };
95
+ CURSOR_TOOL_MAP = {
96
+ Shell: "Bash"
97
+ };
76
98
  OPENCODE_HOOK_SCOPES = ["user", "project"];
77
99
  OPENCODE_HOOK_EVENT_TYPES = [
78
100
  "tool.execute.before",
@@ -956,7 +978,8 @@ function blockWorkOnMain(ctx) {
956
978
  if (ctx.toolName !== "Bash")
957
979
  return allow();
958
980
  const cmd = getCommand(ctx);
959
- if (!GIT_COMMIT_MERGE_RE.test(cmd))
981
+ const match = cmd.match(GIT_COMMIT_MERGE_RE);
982
+ if (!match)
960
983
  return allow();
961
984
  const cwd = ctx.session?.cwd;
962
985
  if (!cwd)
@@ -966,7 +989,7 @@ function blockWorkOnMain(ctx) {
966
989
  return allow();
967
990
  const protectedBranches = ctx.params?.protectedBranches ?? ["main", "master"];
968
991
  if (protectedBranches.includes(branch)) {
969
- return deny(`Git ${cmd.match(/git\s+(\S+)/)?.[1] ?? "operation"} on ${branch} is blocked. Create a feature branch first.`);
992
+ return deny(`Git ${match[1]} on ${branch} is blocked. Create a feature branch first.`);
970
993
  }
971
994
  return allow();
972
995
  }
@@ -1459,7 +1482,7 @@ var init_builtin_policies = __esm(() => {
1459
1482
  SECRET_FILE_RE = /\.(?:pem|key)$/;
1460
1483
  SECRET_FILE_ID_RSA_RE = /id_rsa/;
1461
1484
  SECRET_FILE_CREDENTIALS_RE = /credentials/;
1462
- GIT_COMMIT_MERGE_RE = /git\s+(?:commit|merge|rebase|cherry-pick)\b/;
1485
+ GIT_COMMIT_MERGE_RE = /git\s+(commit|merge|rebase|cherry-pick)\b/;
1463
1486
  FAILPROOFAI_CLI_RE = /(?:^|;|&&|\|\||\|)\s*failproofai(?:\s|$)/;
1464
1487
  FAILPROOFAI_UNINSTALL_RE = /(?:npm\s+(?:uninstall|remove|un|r)\s.*failproofai|bun\s+remove\s.*failproofai|yarn\s+global\s+remove\s+failproofai|pnpm\s+(?:remove|uninstall|un)\s.*failproofai)/;
1465
1488
  GIT_AMEND_RE = /\bgit\s+commit\b.*--amend\b/;
@@ -2770,7 +2793,7 @@ var init_hook_activity_store = __esm(() => {
2770
2793
  });
2771
2794
 
2772
2795
  // package.json
2773
- var version2 = "0.0.10-beta.2";
2796
+ var version2 = "0.0.10-beta.3";
2774
2797
  var init_package = () => {};
2775
2798
 
2776
2799
  // src/posthog-key.ts
@@ -4713,183 +4736,1107 @@ var init_resolve_permission_mode = __esm(() => {
4713
4736
  init_codex_sessions();
4714
4737
  });
4715
4738
 
4716
- // lib/telemetry-id.ts
4717
- import fs from "node:fs";
4718
- import path from "node:path";
4719
- import os from "node:os";
4720
- import crypto from "node:crypto";
4721
- import { execSync as execSync2 } from "node:child_process";
4722
- function hashToId(raw) {
4723
- return crypto.createHmac("sha256", NAMESPACE).update(raw).digest("hex");
4724
- }
4725
- function getPlatformMachineId() {
4726
- try {
4727
- const platform = os.platform();
4728
- if (platform === "linux") {
4729
- for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
4730
- try {
4731
- const id = fs.readFileSync(p, "utf-8").trim();
4732
- if (id)
4733
- return id;
4734
- } catch {}
4735
- }
4736
- } else if (platform === "darwin") {
4737
- const out = execSync2("ioreg -rd1 -c IOPlatformExpertDevice", {
4738
- encoding: "utf-8",
4739
- timeout: 3000
4740
- });
4741
- const m = out.match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/);
4742
- if (m?.[1])
4743
- return m[1];
4744
- } else if (platform === "win32") {
4745
- const out = execSync2('reg query "HKLM\\SOFTWARE\\Microsoft\\Cryptography" /v MachineGuid', { encoding: "utf-8", timeout: 3000 });
4746
- const m = out.match(/MachineGuid\s+REG_SZ\s+(\S+)/);
4747
- if (m?.[1])
4748
- return m[1];
4749
- }
4750
- } catch {}
4751
- return;
4739
+ // lib/copilot-sessions.ts
4740
+ import { readFileSync as readFileSync5, readdirSync as readdirSync4, existsSync as existsSync6, statSync as statSync5 } from "node:fs";
4741
+ import { readFile as readFile9 } from "node:fs/promises";
4742
+ import { join as join14, resolve as resolve6, sep as sep2 } from "node:path";
4743
+ import { homedir as homedir13 } from "node:os";
4744
+ function getCopilotHome() {
4745
+ return process.env.COPILOT_HOME || join14(homedir13(), ".copilot");
4752
4746
  }
4753
- function getSystemPropertiesId() {
4754
- return [
4755
- os.hostname(),
4756
- os.homedir(),
4757
- os.platform(),
4758
- os.arch(),
4759
- os.cpus()[0]?.model ?? ""
4760
- ].join(":");
4747
+ function getCopilotSessionStateRoot2() {
4748
+ return join14(getCopilotHome(), "session-state");
4761
4749
  }
4762
- function getFileBasedId() {
4763
- try {
4764
- const existing = fs.readFileSync(ID_FILE, "utf-8").trim();
4765
- if (existing)
4766
- return existing;
4767
- } catch {}
4768
- const id = crypto.randomUUID();
4769
- try {
4770
- fs.mkdirSync(ID_DIR, { recursive: true });
4771
- fs.writeFileSync(ID_FILE, id, "utf-8");
4772
- } catch {}
4773
- return id;
4750
+ function getCopilotSessionDir(sessionId) {
4751
+ if (!sessionId)
4752
+ return null;
4753
+ const root = resolve6(getCopilotSessionStateRoot2());
4754
+ const candidate = resolve6(root, sessionId);
4755
+ if (candidate === root || !candidate.startsWith(`${root}${sep2}`))
4756
+ return null;
4757
+ return candidate;
4774
4758
  }
4775
- function getInstanceId() {
4776
- if (cachedId)
4777
- return cachedId;
4778
- const machineId = getPlatformMachineId();
4779
- if (machineId) {
4780
- cachedId = hashToId(machineId);
4781
- return cachedId;
4782
- }
4783
- const sysProps = getSystemPropertiesId();
4784
- if (sysProps) {
4785
- cachedId = hashToId(sysProps);
4786
- return cachedId;
4787
- }
4788
- cachedId = getFileBasedId();
4789
- return cachedId;
4759
+ function resolveSessionFile(sessionId, filename) {
4760
+ const dir = getCopilotSessionDir(sessionId);
4761
+ if (!dir)
4762
+ return null;
4763
+ return join14(dir, filename);
4790
4764
  }
4791
- var NAMESPACE = "failproofai-telemetry-v1", ID_DIR, ID_FILE, cachedId;
4792
- var init_telemetry_id = __esm(() => {
4793
- ID_DIR = path.join(os.homedir(), ".failproofai");
4794
- ID_FILE = path.join(ID_DIR, "instance-id");
4795
- });
4796
-
4797
- // src/auth/token-store.ts
4798
- import {
4799
- readFileSync as readFileSync5,
4800
- writeFileSync as writeFileSync4,
4801
- existsSync as existsSync6,
4802
- mkdirSync as mkdirSync5,
4803
- unlinkSync as unlinkSync2,
4804
- renameSync as renameSync3,
4805
- openSync,
4806
- closeSync
4807
- } from "node:fs";
4808
- import { join as join14 } from "node:path";
4809
- import { homedir as homedir13 } from "node:os";
4810
- function ensureAuthDir() {
4811
- if (!existsSync6(AUTH_DIR))
4812
- mkdirSync5(AUTH_DIR, { recursive: true, mode: 448 });
4765
+ function findCopilotTranscript(sessionId) {
4766
+ const candidate = resolveSessionFile(sessionId, "events.jsonl");
4767
+ if (!candidate)
4768
+ return null;
4769
+ return existsSync6(candidate) ? candidate : null;
4813
4770
  }
4814
- function readTokens() {
4815
- if (!existsSync6(AUTH_FILE))
4771
+ function findCopilotWorkspace(sessionId) {
4772
+ const candidate = resolveSessionFile(sessionId, "workspace.yaml");
4773
+ if (!candidate)
4816
4774
  return null;
4775
+ return existsSync6(candidate) ? candidate : null;
4776
+ }
4777
+ function readYamlScalar(path, key) {
4817
4778
  try {
4818
- const raw = readFileSync5(AUTH_FILE, "utf8");
4819
- return JSON.parse(raw);
4779
+ const text = readFileSync5(path, "utf-8");
4780
+ const re = new RegExp(`^${key}\\s*:\\s*(.+?)\\s*$`, "m");
4781
+ const m = text.match(re);
4782
+ if (!m)
4783
+ return;
4784
+ return m[1].replace(/^['"]|['"]$/g, "");
4820
4785
  } catch {
4821
- return null;
4786
+ return;
4822
4787
  }
4823
4788
  }
4824
- function writeTokens(tokens) {
4825
- ensureAuthDir();
4826
- const tmpPath = `${AUTH_FILE}.tmp`;
4827
- const fd = openSync(tmpPath, "w", 384);
4828
- try {
4829
- writeFileSync4(fd, JSON.stringify(tokens, null, 2));
4830
- } finally {
4831
- closeSync(fd);
4832
- }
4833
- renameSync3(tmpPath, AUTH_FILE);
4789
+ function readCopilotWorkspaceCwd(sessionId) {
4790
+ const path = findCopilotWorkspace(sessionId);
4791
+ if (!path)
4792
+ return;
4793
+ return readYamlScalar(path, "cwd");
4834
4794
  }
4835
- function clearTokens() {
4836
- if (existsSync6(AUTH_FILE))
4837
- unlinkSync2(AUTH_FILE);
4795
+ async function parseCopilotLog(fileContent, source = "session") {
4796
+ const lines = fileContent.split(`
4797
+ `).filter((line) => line.trim() !== "");
4798
+ const entries = [];
4799
+ const rawLines = [];
4800
+ const toolUseById = new Map;
4801
+ const toolUseStartMs = new Map;
4802
+ let cwd;
4803
+ let seenSessionStart = false;
4804
+ for (let i = 0;i < lines.length; i++) {
4805
+ if (i > 0 && i % 200 === 0)
4806
+ await new Promise((r) => setImmediate(r));
4807
+ const line = lines[i];
4808
+ let raw;
4809
+ try {
4810
+ raw = JSON.parse(line);
4811
+ } catch {
4812
+ continue;
4813
+ }
4814
+ const rawCopy = { ...raw, _source: source };
4815
+ rawLines.push(rawCopy);
4816
+ const timestampStr = raw.timestamp;
4817
+ if (!timestampStr)
4818
+ continue;
4819
+ const date = new Date(timestampStr);
4820
+ if (Number.isNaN(date.getTime()))
4821
+ continue;
4822
+ const timestamp = date.toISOString();
4823
+ const recType = raw.type;
4824
+ const data = raw.data ?? {};
4825
+ if (recType === "session.start") {
4826
+ const ctx = data.context;
4827
+ const c = ctx?.cwd;
4828
+ if (typeof c === "string" && !cwd)
4829
+ cwd = c;
4830
+ const label = seenSessionStart ? "Session Resumed" : "Session Started";
4831
+ seenSessionStart = true;
4832
+ entries.push({
4833
+ type: "queue-operation",
4834
+ ...baseEntry(rawCopy, timestamp, date, source),
4835
+ label
4836
+ });
4837
+ continue;
4838
+ }
4839
+ if (recType === "user.message") {
4840
+ const text = data.content ?? "";
4841
+ if (!text)
4842
+ continue;
4843
+ entries.push({
4844
+ type: "user",
4845
+ ...baseEntry(rawCopy, timestamp, date, source),
4846
+ message: { role: "user", content: text }
4847
+ });
4848
+ continue;
4849
+ }
4850
+ if (recType === "system.message") {
4851
+ entries.push({
4852
+ type: "system",
4853
+ ...baseEntry(rawCopy, timestamp, date, source),
4854
+ raw: rawCopy
4855
+ });
4856
+ continue;
4857
+ }
4858
+ if (recType === "assistant.message") {
4859
+ const text = data.content ?? "";
4860
+ if (!text) {
4861
+ entries.push({
4862
+ type: "system",
4863
+ ...baseEntry(rawCopy, timestamp, date, source),
4864
+ raw: rawCopy
4865
+ });
4866
+ continue;
4867
+ }
4868
+ const blocks = [{ type: "text", text }];
4869
+ entries.push({
4870
+ type: "assistant",
4871
+ ...baseEntry(rawCopy, timestamp, date, source),
4872
+ message: { role: "assistant", content: blocks }
4873
+ });
4874
+ continue;
4875
+ }
4876
+ if (recType === "tool.execution_start") {
4877
+ const callId = data.toolCallId;
4878
+ const name = data.toolName ?? "tool";
4879
+ const args = data.arguments ?? {};
4880
+ const id = callId ?? `${date.getTime()}-${name}`;
4881
+ const toolUse = {
4882
+ type: "tool_use",
4883
+ id,
4884
+ name,
4885
+ input: args
4886
+ };
4887
+ const entry = {
4888
+ type: "assistant",
4889
+ ...baseEntry(rawCopy, timestamp, date, source),
4890
+ message: { role: "assistant", content: [toolUse] }
4891
+ };
4892
+ entries.push(entry);
4893
+ if (callId) {
4894
+ toolUseById.set(callId, toolUse);
4895
+ toolUseStartMs.set(callId, date.getTime());
4896
+ }
4897
+ continue;
4898
+ }
4899
+ if (recType === "tool.execution_complete") {
4900
+ const callId = data.toolCallId;
4901
+ const block = callId ? toolUseById.get(callId) : undefined;
4902
+ if (block) {
4903
+ const startMs = toolUseStartMs.get(callId) ?? date.getTime();
4904
+ const result = data.result ?? {};
4905
+ const telemetry = data.toolTelemetry ?? {};
4906
+ const reportedMs = telemetry.metrics?.commandTimeMs ?? telemetry.metrics?.durationMs ?? null;
4907
+ const durationMs = typeof reportedMs === "number" && reportedMs >= 0 ? reportedMs : Math.max(0, date.getTime() - startMs);
4908
+ const content = result.detailedContent ?? result.content ?? "";
4909
+ block.result = {
4910
+ timestamp,
4911
+ timestampFormatted: formatTimestamp(date),
4912
+ content: typeof content === "string" ? content : JSON.stringify(content),
4913
+ durationMs,
4914
+ durationFormatted: formatDuration(durationMs)
4915
+ };
4916
+ continue;
4917
+ }
4918
+ entries.push({
4919
+ type: "system",
4920
+ ...baseEntry(rawCopy, timestamp, date, source),
4921
+ raw: rawCopy
4922
+ });
4923
+ continue;
4924
+ }
4925
+ entries.push({
4926
+ type: "system",
4927
+ ...baseEntry(rawCopy, timestamp, date, source),
4928
+ raw: rawCopy
4929
+ });
4930
+ }
4931
+ if (entries.length > 500)
4932
+ await new Promise((r) => setImmediate(r));
4933
+ entries.sort((a, b) => a.timestampMs - b.timestampMs);
4934
+ return { entries, rawLines, cwd };
4838
4935
  }
4839
- function isLoggedIn() {
4840
- return existsSync6(AUTH_FILE);
4936
+ async function getCopilotSessionLog(sessionId) {
4937
+ const filePath = findCopilotTranscript(sessionId);
4938
+ if (!filePath)
4939
+ return null;
4940
+ let fileContent;
4941
+ try {
4942
+ fileContent = await readFile9(filePath, "utf-8");
4943
+ } catch {
4944
+ return null;
4945
+ }
4946
+ const { entries, rawLines, cwd } = await parseCopilotLog(fileContent, "session");
4947
+ const resolvedCwd = cwd ?? readCopilotWorkspaceCwd(sessionId);
4948
+ return { entries, rawLines, cwd: resolvedCwd, filePath };
4841
4949
  }
4842
- var AUTH_DIR, AUTH_FILE;
4843
- var init_token_store = __esm(() => {
4844
- AUTH_DIR = join14(homedir13(), ".failproofai");
4845
- AUTH_FILE = join14(AUTH_DIR, "auth.json");
4950
+ var getCachedCopilotSessionLog;
4951
+ var init_copilot_sessions = __esm(() => {
4952
+ init_log_entries();
4953
+ getCachedCopilotSessionLog = runtimeCache((sessionId) => getCopilotSessionLog(sessionId), 60, { maxSize: 50 });
4846
4954
  });
4847
4955
 
4848
- // src/relay/queue.ts
4849
- var exports_queue = {};
4850
- __export(exports_queue, {
4851
- readProcessingFile: () => readProcessingFile,
4852
- queueSizeBytes: () => queueSizeBytes,
4853
- findOrphanProcessingFiles: () => findOrphanProcessingFiles,
4854
- deleteProcessingFile: () => deleteProcessingFile,
4855
- claimPendingBatch: () => claimPendingBatch,
4856
- appendToServerQueue: () => appendToServerQueue
4857
- });
4858
- import {
4859
- appendFileSync as appendFileSync3,
4860
- mkdirSync as mkdirSync6,
4861
- existsSync as existsSync7,
4862
- readFileSync as readFileSync6,
4863
- statSync as statSync5,
4864
- renameSync as renameSync4,
4865
- unlinkSync as unlinkSync3,
4866
- readdirSync as readdirSync4,
4867
- chmodSync
4868
- } from "node:fs";
4869
- import { join as join15 } from "node:path";
4956
+ // lib/cursor-sessions.ts
4957
+ import { readFileSync as readFileSync6, readdirSync as readdirSync5, existsSync as existsSync7, statSync as statSync6 } from "node:fs";
4958
+ import { readFile as readFile10 } from "node:fs/promises";
4959
+ import { basename as basename3, join as join15, resolve as resolve7, sep as sep3 } from "node:path";
4870
4960
  import { homedir as homedir14 } from "node:os";
4871
- import { createHash, randomUUID } from "node:crypto";
4872
- function hashCwd(cwd) {
4873
- if (!cwd)
4961
+ function getCursorHome2() {
4962
+ return process.env.CURSOR_HOME || join15(homedir14(), ".cursor");
4963
+ }
4964
+ function getCursorSessionDir(sessionId) {
4965
+ if (!sessionId)
4874
4966
  return null;
4875
- return createHash("sha256").update(cwd).digest("hex");
4967
+ const home = resolve7(getCursorHome2());
4968
+ const projectsRoot = resolve7(home, NEW_PROJECTS_DIR2);
4969
+ let projectEntries = [];
4970
+ try {
4971
+ projectEntries = readdirSync5(projectsRoot, { withFileTypes: true });
4972
+ } catch {}
4973
+ for (const entry of projectEntries) {
4974
+ if (!entry.isDirectory())
4975
+ continue;
4976
+ const candidate = resolve7(projectsRoot, entry.name, NEW_AGENT_TRANSCRIPTS_DIR2, sessionId);
4977
+ const transcriptRoot = resolve7(projectsRoot, entry.name, NEW_AGENT_TRANSCRIPTS_DIR2);
4978
+ if (candidate === transcriptRoot || !candidate.startsWith(`${transcriptRoot}${sep3}`))
4979
+ continue;
4980
+ if (existsSync7(candidate))
4981
+ return candidate;
4982
+ }
4983
+ for (const sub of LEGACY_SESSION_ROOT_CANDIDATES2) {
4984
+ const root = resolve7(home, sub);
4985
+ const candidate = resolve7(root, sessionId);
4986
+ if (candidate === root || !candidate.startsWith(`${root}${sep3}`))
4987
+ continue;
4988
+ if (existsSync7(candidate))
4989
+ return candidate;
4990
+ }
4991
+ return null;
4876
4992
  }
4877
- function redactReason(reason) {
4878
- if (!reason)
4879
- return reason ?? null;
4880
- return reason.replace(/AKIA[0-9A-Z]{16}/g, "[REDACTED-AWS-KEY]").replace(/eyJ[A-Za-z0-9_=-]+\.[A-Za-z0-9_=-]+\.[A-Za-z0-9_=-]+/g, "[REDACTED-JWT]").replace(/ghp_[A-Za-z0-9]{36,}/g, "[REDACTED-GH-TOKEN]").replace(/sk-[A-Za-z0-9]{20,}/g, "[REDACTED-API-KEY]").replace(/Bearer\s+[A-Za-z0-9_.=+-]+/gi, "Bearer [REDACTED]");
4993
+ function findCursorTranscript(sessionId) {
4994
+ const dir = getCursorSessionDir(sessionId);
4995
+ if (!dir)
4996
+ return null;
4997
+ const newCandidate = join15(dir, `${basename3(dir)}.jsonl`);
4998
+ if (existsSync7(newCandidate))
4999
+ return newCandidate;
5000
+ for (const name of LEGACY_TRANSCRIPT_FILE_CANDIDATES2) {
5001
+ const candidate = join15(dir, name);
5002
+ if (existsSync7(candidate))
5003
+ return candidate;
5004
+ }
5005
+ return null;
4881
5006
  }
4882
- function sanitize(entry) {
4883
- return {
4884
- client_event_id: randomUUID(),
4885
- timestamp: entry.timestamp,
4886
- event_type: entry.eventType,
4887
- tool_name: entry.toolName ?? null,
4888
- policy_name: entry.policyName ?? null,
4889
- policy_names: entry.policyNames ?? [],
4890
- decision: entry.decision,
4891
- reason: redactReason(entry.reason),
4892
- duration_ms: entry.durationMs,
5007
+ async function parseCursorLog(fileContent, source = "session") {
5008
+ const lines = fileContent.split(`
5009
+ `).filter((line) => line.trim() !== "");
5010
+ const entries = [];
5011
+ const rawLines = [];
5012
+ const toolUseById = new Map;
5013
+ const toolUseStartMs = new Map;
5014
+ let cwd;
5015
+ let seenSessionStart = false;
5016
+ const SYNTH_T0 = Date.now();
5017
+ for (let i = 0;i < lines.length; i++) {
5018
+ if (i > 0 && i % 200 === 0)
5019
+ await new Promise((r) => setImmediate(r));
5020
+ const line = lines[i];
5021
+ let raw;
5022
+ try {
5023
+ raw = JSON.parse(line);
5024
+ } catch {
5025
+ continue;
5026
+ }
5027
+ const rawCopy = { ...raw, _source: source };
5028
+ rawLines.push(rawCopy);
5029
+ if (!raw.type && raw.role && raw.message?.content) {
5030
+ const synthDate = new Date(SYNTH_T0 + i);
5031
+ const synthTs = synthDate.toISOString();
5032
+ const textParts = raw.message.content.filter((c) => c?.type === "text" && typeof c.text === "string").map((c) => c.text).join("");
5033
+ if (raw.role === "user") {
5034
+ const queryMatch = /<user_query>\s*([\s\S]*?)\s*<\/user_query>/.exec(textParts);
5035
+ const text = queryMatch ? queryMatch[1] : textParts;
5036
+ if (text) {
5037
+ entries.push({
5038
+ type: "user",
5039
+ ...baseEntry(rawCopy, synthTs, synthDate, source),
5040
+ message: { role: "user", content: text }
5041
+ });
5042
+ }
5043
+ continue;
5044
+ }
5045
+ if (raw.role === "assistant") {
5046
+ const blocks = textParts ? [{ type: "text", text: textParts }] : [];
5047
+ if (blocks.length === 0) {
5048
+ entries.push({
5049
+ type: "system",
5050
+ ...baseEntry(rawCopy, synthTs, synthDate, source),
5051
+ raw: rawCopy
5052
+ });
5053
+ } else {
5054
+ entries.push({
5055
+ type: "assistant",
5056
+ ...baseEntry(rawCopy, synthTs, synthDate, source),
5057
+ message: { role: "assistant", content: blocks }
5058
+ });
5059
+ }
5060
+ continue;
5061
+ }
5062
+ entries.push({
5063
+ type: "system",
5064
+ ...baseEntry(rawCopy, synthTs, synthDate, source),
5065
+ raw: rawCopy
5066
+ });
5067
+ continue;
5068
+ }
5069
+ const timestampStr = raw.timestamp;
5070
+ if (!timestampStr)
5071
+ continue;
5072
+ const date = new Date(timestampStr);
5073
+ if (Number.isNaN(date.getTime()))
5074
+ continue;
5075
+ const timestamp = date.toISOString();
5076
+ const recType = raw.type;
5077
+ const data = raw.data ?? {};
5078
+ if (recType === "session.start" || recType === "sessionStart" || recType === "session_start") {
5079
+ const ctx = data.context ?? data;
5080
+ const c = ctx.cwd;
5081
+ if (typeof c === "string" && !cwd)
5082
+ cwd = c;
5083
+ if (!cwd && Array.isArray(ctx.workspace_roots) && typeof ctx.workspace_roots[0] === "string") {
5084
+ cwd = ctx.workspace_roots[0];
5085
+ }
5086
+ const label = seenSessionStart ? "Session Resumed" : "Session Started";
5087
+ seenSessionStart = true;
5088
+ entries.push({
5089
+ type: "queue-operation",
5090
+ ...baseEntry(rawCopy, timestamp, date, source),
5091
+ label
5092
+ });
5093
+ continue;
5094
+ }
5095
+ if (recType === "user.message" || recType === "userMessage") {
5096
+ const text = typeof data.content === "string" ? data.content : typeof data.text === "string" ? data.text : "";
5097
+ if (!text)
5098
+ continue;
5099
+ entries.push({
5100
+ type: "user",
5101
+ ...baseEntry(rawCopy, timestamp, date, source),
5102
+ message: { role: "user", content: text }
5103
+ });
5104
+ continue;
5105
+ }
5106
+ if (recType === "system.message" || recType === "systemMessage") {
5107
+ entries.push({
5108
+ type: "system",
5109
+ ...baseEntry(rawCopy, timestamp, date, source),
5110
+ raw: rawCopy
5111
+ });
5112
+ continue;
5113
+ }
5114
+ if (recType === "assistant.message" || recType === "assistantMessage") {
5115
+ const text = typeof data.content === "string" ? data.content : typeof data.text === "string" ? data.text : "";
5116
+ if (!text) {
5117
+ entries.push({
5118
+ type: "system",
5119
+ ...baseEntry(rawCopy, timestamp, date, source),
5120
+ raw: rawCopy
5121
+ });
5122
+ continue;
5123
+ }
5124
+ const blocks = [{ type: "text", text }];
5125
+ entries.push({
5126
+ type: "assistant",
5127
+ ...baseEntry(rawCopy, timestamp, date, source),
5128
+ message: { role: "assistant", content: blocks }
5129
+ });
5130
+ continue;
5131
+ }
5132
+ if (recType === "tool.execution_start" || recType === "tool.executionStart" || recType === "preToolUse") {
5133
+ const callId = data.toolCallId ?? data.tool_use_id;
5134
+ const name = data.toolName ?? data.tool_name ?? "tool";
5135
+ const args = data.arguments ?? data.tool_input ?? {};
5136
+ const id = callId ?? `${date.getTime()}-${name}`;
5137
+ const toolUse = {
5138
+ type: "tool_use",
5139
+ id,
5140
+ name,
5141
+ input: args
5142
+ };
5143
+ const entry = {
5144
+ type: "assistant",
5145
+ ...baseEntry(rawCopy, timestamp, date, source),
5146
+ message: { role: "assistant", content: [toolUse] }
5147
+ };
5148
+ entries.push(entry);
5149
+ if (callId) {
5150
+ toolUseById.set(callId, toolUse);
5151
+ toolUseStartMs.set(callId, date.getTime());
5152
+ }
5153
+ continue;
5154
+ }
5155
+ if (recType === "tool.execution_complete" || recType === "tool.executionComplete" || recType === "postToolUse") {
5156
+ const callId = data.toolCallId ?? data.tool_use_id;
5157
+ const block = callId ? toolUseById.get(callId) : undefined;
5158
+ if (block) {
5159
+ const startMs = toolUseStartMs.get(callId) ?? date.getTime();
5160
+ const result = data.result ?? {};
5161
+ const reportedMs = data.duration;
5162
+ const durationMs = typeof reportedMs === "number" && reportedMs >= 0 ? reportedMs : Math.max(0, date.getTime() - startMs);
5163
+ const content = result.detailedContent ?? result.content ?? data.tool_output ?? "";
5164
+ block.result = {
5165
+ timestamp,
5166
+ timestampFormatted: formatTimestamp(date),
5167
+ content: typeof content === "string" ? content : JSON.stringify(content),
5168
+ durationMs,
5169
+ durationFormatted: formatDuration(durationMs)
5170
+ };
5171
+ continue;
5172
+ }
5173
+ entries.push({
5174
+ type: "system",
5175
+ ...baseEntry(rawCopy, timestamp, date, source),
5176
+ raw: rawCopy
5177
+ });
5178
+ continue;
5179
+ }
5180
+ entries.push({
5181
+ type: "system",
5182
+ ...baseEntry(rawCopy, timestamp, date, source),
5183
+ raw: rawCopy
5184
+ });
5185
+ }
5186
+ if (entries.length > 500)
5187
+ await new Promise((r) => setImmediate(r));
5188
+ entries.sort((a, b) => a.timestampMs - b.timestampMs);
5189
+ return { entries, rawLines, cwd };
5190
+ }
5191
+ async function getCursorSessionLog(sessionId) {
5192
+ const filePath = findCursorTranscript(sessionId);
5193
+ if (!filePath)
5194
+ return null;
5195
+ let fileContent;
5196
+ try {
5197
+ fileContent = await readFile10(filePath, "utf-8");
5198
+ } catch {
5199
+ return null;
5200
+ }
5201
+ const { entries, rawLines, cwd } = await parseCursorLog(fileContent, "session");
5202
+ return { entries, rawLines, cwd, filePath };
5203
+ }
5204
+ var LEGACY_SESSION_ROOT_CANDIDATES2, LEGACY_TRANSCRIPT_FILE_CANDIDATES2, NEW_PROJECTS_DIR2 = "projects", NEW_AGENT_TRANSCRIPTS_DIR2 = "agent-transcripts", getCachedCursorSessionLog;
5205
+ var init_cursor_sessions = __esm(() => {
5206
+ init_log_entries();
5207
+ LEGACY_SESSION_ROOT_CANDIDATES2 = ["agent-sessions", "conversations", "sessions"];
5208
+ LEGACY_TRANSCRIPT_FILE_CANDIDATES2 = ["events.jsonl", "transcript.jsonl", "messages.jsonl"];
5209
+ getCachedCursorSessionLog = runtimeCache((sessionId) => getCursorSessionLog(sessionId), 60, { maxSize: 50 });
5210
+ });
5211
+
5212
+ // lib/pi-sessions.ts
5213
+ import { readFileSync as readFileSync7, readdirSync as readdirSync6, existsSync as existsSync8, statSync as statSync7 } from "node:fs";
5214
+ import { readFile as readFile11 } from "node:fs/promises";
5215
+ import { join as join16, resolve as resolve8, sep as sep4 } from "node:path";
5216
+ import { homedir as homedir15 } from "node:os";
5217
+ function getPiSessionStateRoot() {
5218
+ return process.env.PI_SESSIONS_DIR || join16(homedir15(), ".pi", "agent", "sessions");
5219
+ }
5220
+ function isSafeSessionId(sessionId) {
5221
+ return UUID_RE.test(sessionId);
5222
+ }
5223
+ function findPiTranscript(sessionId) {
5224
+ if (!isSafeSessionId(sessionId))
5225
+ return null;
5226
+ const root = resolve8(getPiSessionStateRoot());
5227
+ let cwdDirs;
5228
+ try {
5229
+ cwdDirs = readdirSync6(root);
5230
+ } catch {
5231
+ return null;
5232
+ }
5233
+ for (const cwdDir of cwdDirs) {
5234
+ const cwdPath = resolve8(root, cwdDir);
5235
+ if (!cwdPath.startsWith(`${root}${sep4}`))
5236
+ continue;
5237
+ let files;
5238
+ try {
5239
+ files = readdirSync6(cwdPath);
5240
+ } catch {
5241
+ continue;
5242
+ }
5243
+ for (const f of files) {
5244
+ const m = SESSION_FILE_RE3.exec(f);
5245
+ if (!m || m[1].toLowerCase() !== sessionId.toLowerCase())
5246
+ continue;
5247
+ const candidate = resolve8(cwdPath, f);
5248
+ if (!candidate.startsWith(`${cwdPath}${sep4}`))
5249
+ continue;
5250
+ if (existsSync8(candidate))
5251
+ return candidate;
5252
+ }
5253
+ }
5254
+ return null;
5255
+ }
5256
+ function extractMessageText(content) {
5257
+ if (!Array.isArray(content))
5258
+ return "";
5259
+ const parts = [];
5260
+ for (const block of content) {
5261
+ if (block?.type === "text" && typeof block.text === "string")
5262
+ parts.push(block.text);
5263
+ }
5264
+ return parts.join(`
5265
+
5266
+ `);
5267
+ }
5268
+ function buildAssistantContent(content) {
5269
+ if (!Array.isArray(content))
5270
+ return [];
5271
+ const blocks = [];
5272
+ for (const block of content) {
5273
+ if (block?.type === "text" && typeof block.text === "string" && block.text.length > 0) {
5274
+ blocks.push({ type: "text", text: block.text });
5275
+ }
5276
+ if (block?.type === "thinking" && typeof block.thinking === "string" && block.thinking.length > 0) {
5277
+ blocks.push({ type: "text", text: `[thinking] ${block.thinking}` });
5278
+ }
5279
+ }
5280
+ return blocks;
5281
+ }
5282
+ async function parsePiLog(fileContent, source = "session") {
5283
+ const lines = fileContent.split(`
5284
+ `).filter((line) => line.trim() !== "");
5285
+ const entries = [];
5286
+ const rawLines = [];
5287
+ let cwd;
5288
+ let seenSessionStart = false;
5289
+ for (let i = 0;i < lines.length; i++) {
5290
+ if (i > 0 && i % 200 === 0)
5291
+ await new Promise((r) => setImmediate(r));
5292
+ const line = lines[i];
5293
+ let raw;
5294
+ try {
5295
+ raw = JSON.parse(line);
5296
+ } catch {
5297
+ continue;
5298
+ }
5299
+ const rawCopy = { ...raw, _source: source };
5300
+ rawLines.push(rawCopy);
5301
+ const timestampStr = raw.timestamp;
5302
+ if (!timestampStr)
5303
+ continue;
5304
+ const date = new Date(timestampStr);
5305
+ if (Number.isNaN(date.getTime()))
5306
+ continue;
5307
+ const timestamp = date.toISOString();
5308
+ const recType = raw.type;
5309
+ if (recType === "session") {
5310
+ if (typeof raw.cwd === "string" && !cwd)
5311
+ cwd = raw.cwd;
5312
+ const label = seenSessionStart ? "Session Resumed" : "Session Started";
5313
+ seenSessionStart = true;
5314
+ entries.push({
5315
+ type: "queue-operation",
5316
+ ...baseEntry(rawCopy, timestamp, date, source),
5317
+ label
5318
+ });
5319
+ continue;
5320
+ }
5321
+ if (recType === "message" && raw.message && typeof raw.message === "object") {
5322
+ const role = raw.message.role;
5323
+ const content = raw.message.content;
5324
+ if (role === "user") {
5325
+ const text = extractMessageText(content);
5326
+ if (!text)
5327
+ continue;
5328
+ entries.push({
5329
+ type: "user",
5330
+ ...baseEntry(rawCopy, timestamp, date, source),
5331
+ message: { role: "user", content: text }
5332
+ });
5333
+ continue;
5334
+ }
5335
+ if (role === "assistant") {
5336
+ const blocks = buildAssistantContent(content);
5337
+ if (blocks.length === 0) {
5338
+ entries.push({
5339
+ type: "system",
5340
+ ...baseEntry(rawCopy, timestamp, date, source),
5341
+ raw: rawCopy
5342
+ });
5343
+ continue;
5344
+ }
5345
+ entries.push({
5346
+ type: "assistant",
5347
+ ...baseEntry(rawCopy, timestamp, date, source),
5348
+ message: { role: "assistant", content: blocks }
5349
+ });
5350
+ continue;
5351
+ }
5352
+ entries.push({
5353
+ type: "system",
5354
+ ...baseEntry(rawCopy, timestamp, date, source),
5355
+ raw: rawCopy
5356
+ });
5357
+ continue;
5358
+ }
5359
+ entries.push({
5360
+ type: "system",
5361
+ ...baseEntry(rawCopy, timestamp, date, source),
5362
+ raw: rawCopy
5363
+ });
5364
+ }
5365
+ if (entries.length > 500)
5366
+ await new Promise((r) => setImmediate(r));
5367
+ entries.sort((a, b) => a.timestampMs - b.timestampMs);
5368
+ return { entries, rawLines, cwd };
5369
+ }
5370
+ async function getPiSessionLog(sessionId) {
5371
+ const filePath = findPiTranscript(sessionId);
5372
+ if (!filePath)
5373
+ return null;
5374
+ let fileContent;
5375
+ try {
5376
+ fileContent = await readFile11(filePath, "utf-8");
5377
+ } catch {
5378
+ return null;
5379
+ }
5380
+ let parsed;
5381
+ try {
5382
+ parsed = await parsePiLog(fileContent, "session");
5383
+ } catch {
5384
+ return null;
5385
+ }
5386
+ return {
5387
+ entries: parsed.entries,
5388
+ rawLines: parsed.rawLines,
5389
+ cwd: parsed.cwd,
5390
+ filePath
5391
+ };
5392
+ }
5393
+ var UUID_RE, SESSION_FILE_RE3, getCachedPiSessionLog;
5394
+ var init_pi_sessions = __esm(() => {
5395
+ init_log_entries();
5396
+ UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5397
+ SESSION_FILE_RE3 = /^[\d-]+T[\d-]+Z_([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i;
5398
+ getCachedPiSessionLog = runtimeCache((sessionId) => getPiSessionLog(sessionId), 60, { maxSize: 50 });
5399
+ });
5400
+
5401
+ // lib/gemini-sessions.ts
5402
+ import { closeSync, openSync, readFileSync as readFileSync8, readSync, readdirSync as readdirSync7, existsSync as existsSync9, statSync as statSync8 } from "node:fs";
5403
+ import { readFile as readFile12 } from "node:fs/promises";
5404
+ import { join as join17, resolve as resolve9, sep as sep5 } from "node:path";
5405
+ import { homedir as homedir16 } from "node:os";
5406
+ function getGeminiSessionStateRoot() {
5407
+ return process.env.GEMINI_SESSIONS_DIR || join17(homedir16(), ".gemini", "tmp");
5408
+ }
5409
+ function isSafeSessionId2(sessionId) {
5410
+ return UUID_RE2.test(sessionId);
5411
+ }
5412
+ function readFirstLineSync(path) {
5413
+ let fd;
5414
+ try {
5415
+ fd = openSync(path, "r");
5416
+ } catch {
5417
+ return null;
5418
+ }
5419
+ try {
5420
+ const buf = Buffer.alloc(4096);
5421
+ const bytesRead = readSync(fd, buf, 0, buf.length, 0);
5422
+ if (bytesRead === 0)
5423
+ return null;
5424
+ const text = buf.subarray(0, bytesRead).toString("utf-8");
5425
+ const nl = text.indexOf(`
5426
+ `);
5427
+ return nl >= 0 ? text.slice(0, nl) : text;
5428
+ } catch {
5429
+ return null;
5430
+ } finally {
5431
+ try {
5432
+ closeSync(fd);
5433
+ } catch {}
5434
+ }
5435
+ }
5436
+ function findGeminiTranscript(sessionId) {
5437
+ if (!isSafeSessionId2(sessionId))
5438
+ return null;
5439
+ const root = resolve9(getGeminiSessionStateRoot());
5440
+ const wantPrefix = sessionId.slice(0, 8).toLowerCase();
5441
+ let projectDirs;
5442
+ try {
5443
+ projectDirs = readdirSync7(root);
5444
+ } catch {
5445
+ return null;
5446
+ }
5447
+ for (const projectDir of projectDirs) {
5448
+ const projectPath = resolve9(root, projectDir);
5449
+ if (!projectPath.startsWith(`${root}${sep5}`))
5450
+ continue;
5451
+ const chatsDir = resolve9(projectPath, "chats");
5452
+ let files;
5453
+ try {
5454
+ files = readdirSync7(chatsDir);
5455
+ } catch {
5456
+ continue;
5457
+ }
5458
+ for (const f of files) {
5459
+ const m = SESSION_FILE_RE4.exec(f);
5460
+ if (!m || m[2].toLowerCase() !== wantPrefix)
5461
+ continue;
5462
+ const candidate = resolve9(chatsDir, f);
5463
+ if (!candidate.startsWith(`${chatsDir}${sep5}`))
5464
+ continue;
5465
+ if (!existsSync9(candidate))
5466
+ continue;
5467
+ const firstLine = readFirstLineSync(candidate);
5468
+ if (!firstLine)
5469
+ continue;
5470
+ try {
5471
+ const meta = JSON.parse(firstLine);
5472
+ if (typeof meta.sessionId === "string" && meta.sessionId.toLowerCase() === sessionId.toLowerCase()) {
5473
+ return candidate;
5474
+ }
5475
+ } catch {
5476
+ continue;
5477
+ }
5478
+ }
5479
+ }
5480
+ return null;
5481
+ }
5482
+ function extractMessageText2(content) {
5483
+ if (!Array.isArray(content))
5484
+ return "";
5485
+ const parts = [];
5486
+ for (const block of content) {
5487
+ if (typeof block?.text === "string")
5488
+ parts.push(block.text);
5489
+ }
5490
+ return parts.join(`
5491
+
5492
+ `);
5493
+ }
5494
+ function buildAssistantContent2(content) {
5495
+ if (!Array.isArray(content))
5496
+ return [];
5497
+ const blocks = [];
5498
+ for (const block of content) {
5499
+ if (typeof block?.text === "string" && block.text.length > 0) {
5500
+ blocks.push({ type: "text", text: block.text });
5501
+ }
5502
+ }
5503
+ return blocks;
5504
+ }
5505
+ async function parseGeminiLog(fileContent, source = "session", cwdHint) {
5506
+ const lines = fileContent.split(`
5507
+ `).filter((line) => line.trim() !== "");
5508
+ const entries = [];
5509
+ const rawLines = [];
5510
+ let cwd = cwdHint;
5511
+ let seenStart = false;
5512
+ for (let i = 0;i < lines.length; i++) {
5513
+ if (i > 0 && i % 200 === 0)
5514
+ await new Promise((r) => setImmediate(r));
5515
+ const line = lines[i];
5516
+ let raw;
5517
+ try {
5518
+ raw = JSON.parse(line);
5519
+ } catch {
5520
+ continue;
5521
+ }
5522
+ const rawCopy = { ...raw, _source: source };
5523
+ rawLines.push(rawCopy);
5524
+ if (typeof raw.sessionId === "string" && typeof raw.startTime === "string") {
5525
+ const date2 = new Date(raw.startTime);
5526
+ if (!Number.isNaN(date2.getTime())) {
5527
+ const label = seenStart ? "Session Resumed" : "Session Started";
5528
+ seenStart = true;
5529
+ entries.push({
5530
+ type: "queue-operation",
5531
+ ...baseEntry(rawCopy, date2.toISOString(), date2, source),
5532
+ label
5533
+ });
5534
+ }
5535
+ continue;
5536
+ }
5537
+ if (raw.$set)
5538
+ continue;
5539
+ const timestampStr = raw.timestamp;
5540
+ if (!timestampStr)
5541
+ continue;
5542
+ const date = new Date(timestampStr);
5543
+ if (Number.isNaN(date.getTime()))
5544
+ continue;
5545
+ const timestamp = date.toISOString();
5546
+ const recType = raw.type;
5547
+ if (recType === "user") {
5548
+ const text = extractMessageText2(raw.content);
5549
+ if (!text)
5550
+ continue;
5551
+ entries.push({
5552
+ type: "user",
5553
+ ...baseEntry(rawCopy, timestamp, date, source),
5554
+ message: { role: "user", content: text }
5555
+ });
5556
+ continue;
5557
+ }
5558
+ if (recType === "assistant" || recType === "model") {
5559
+ const blocks = buildAssistantContent2(raw.content);
5560
+ if (blocks.length === 0) {
5561
+ entries.push({
5562
+ type: "system",
5563
+ ...baseEntry(rawCopy, timestamp, date, source),
5564
+ raw: rawCopy
5565
+ });
5566
+ continue;
5567
+ }
5568
+ entries.push({
5569
+ type: "assistant",
5570
+ ...baseEntry(rawCopy, timestamp, date, source),
5571
+ message: { role: "assistant", content: blocks }
5572
+ });
5573
+ continue;
5574
+ }
5575
+ entries.push({
5576
+ type: "system",
5577
+ ...baseEntry(rawCopy, timestamp, date, source),
5578
+ raw: rawCopy
5579
+ });
5580
+ }
5581
+ if (entries.length > 500)
5582
+ await new Promise((r) => setImmediate(r));
5583
+ entries.sort((a, b) => a.timestampMs - b.timestampMs);
5584
+ return { entries, rawLines, cwd };
5585
+ }
5586
+ function readSiblingProjectRoot(transcriptPath) {
5587
+ const chatsDir = resolve9(transcriptPath, "..");
5588
+ const projectDir = resolve9(chatsDir, "..");
5589
+ const rootFile = join17(projectDir, ".project_root");
5590
+ try {
5591
+ const text = readFileSync8(rootFile, "utf-8").trim();
5592
+ return text.length > 0 ? text : undefined;
5593
+ } catch {
5594
+ return;
5595
+ }
5596
+ }
5597
+ async function getGeminiSessionLog(sessionId) {
5598
+ const filePath = findGeminiTranscript(sessionId);
5599
+ if (!filePath)
5600
+ return null;
5601
+ let fileContent;
5602
+ try {
5603
+ fileContent = await readFile12(filePath, "utf-8");
5604
+ } catch {
5605
+ return null;
5606
+ }
5607
+ const cwdHint = readSiblingProjectRoot(filePath);
5608
+ let parsed;
5609
+ try {
5610
+ parsed = await parseGeminiLog(fileContent, "session", cwdHint);
5611
+ } catch {
5612
+ return null;
5613
+ }
5614
+ return {
5615
+ entries: parsed.entries,
5616
+ rawLines: parsed.rawLines,
5617
+ cwd: parsed.cwd,
5618
+ filePath
5619
+ };
5620
+ }
5621
+ var UUID_RE2, SESSION_FILE_RE4, getCachedGeminiSessionLog;
5622
+ var init_gemini_sessions = __esm(() => {
5623
+ init_log_entries();
5624
+ UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5625
+ SESSION_FILE_RE4 = /^session-(.+)-([0-9a-f]{8})\.jsonl$/i;
5626
+ getCachedGeminiSessionLog = runtimeCache((sessionId) => getGeminiSessionLog(sessionId), 60, { maxSize: 50 });
5627
+ });
5628
+
5629
+ // src/hooks/resolve-transcript-path.ts
5630
+ function resolveTranscriptPath(integration, parsed, sessionId) {
5631
+ const stdinPath = typeof parsed.transcript_path === "string" ? parsed.transcript_path : undefined;
5632
+ if (stdinPath)
5633
+ return stdinPath;
5634
+ if (typeof sessionId !== "string" || sessionId.length === 0)
5635
+ return;
5636
+ switch (integration) {
5637
+ case "claude":
5638
+ return;
5639
+ case "codex":
5640
+ return findCodexTranscript(sessionId) ?? undefined;
5641
+ case "copilot":
5642
+ return findCopilotTranscript(sessionId) ?? undefined;
5643
+ case "cursor":
5644
+ return findCursorTranscript(sessionId) ?? undefined;
5645
+ case "pi":
5646
+ return findPiTranscript(sessionId) ?? undefined;
5647
+ case "gemini":
5648
+ return findGeminiTranscript(sessionId) ?? undefined;
5649
+ case "opencode":
5650
+ return `opencode-db://${sessionId}`;
5651
+ default:
5652
+ return;
5653
+ }
5654
+ }
5655
+ var init_resolve_transcript_path = __esm(() => {
5656
+ init_codex_sessions();
5657
+ init_copilot_sessions();
5658
+ init_cursor_sessions();
5659
+ init_pi_sessions();
5660
+ init_gemini_sessions();
5661
+ });
5662
+
5663
+ // lib/telemetry-id.ts
5664
+ import fs from "node:fs";
5665
+ import path from "node:path";
5666
+ import os from "node:os";
5667
+ import crypto from "node:crypto";
5668
+ import { execSync as execSync2 } from "node:child_process";
5669
+ function hashToId(raw) {
5670
+ return crypto.createHmac("sha256", NAMESPACE).update(raw).digest("hex");
5671
+ }
5672
+ function getPlatformMachineId() {
5673
+ try {
5674
+ const platform = os.platform();
5675
+ if (platform === "linux") {
5676
+ for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
5677
+ try {
5678
+ const id = fs.readFileSync(p, "utf-8").trim();
5679
+ if (id)
5680
+ return id;
5681
+ } catch {}
5682
+ }
5683
+ } else if (platform === "darwin") {
5684
+ const out = execSync2("ioreg -rd1 -c IOPlatformExpertDevice", {
5685
+ encoding: "utf-8",
5686
+ timeout: 3000
5687
+ });
5688
+ const m = out.match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/);
5689
+ if (m?.[1])
5690
+ return m[1];
5691
+ } else if (platform === "win32") {
5692
+ const out = execSync2('reg query "HKLM\\SOFTWARE\\Microsoft\\Cryptography" /v MachineGuid', { encoding: "utf-8", timeout: 3000 });
5693
+ const m = out.match(/MachineGuid\s+REG_SZ\s+(\S+)/);
5694
+ if (m?.[1])
5695
+ return m[1];
5696
+ }
5697
+ } catch {}
5698
+ return;
5699
+ }
5700
+ function getSystemPropertiesId() {
5701
+ return [
5702
+ os.hostname(),
5703
+ os.homedir(),
5704
+ os.platform(),
5705
+ os.arch(),
5706
+ os.cpus()[0]?.model ?? ""
5707
+ ].join(":");
5708
+ }
5709
+ function getFileBasedId() {
5710
+ try {
5711
+ const existing = fs.readFileSync(ID_FILE, "utf-8").trim();
5712
+ if (existing)
5713
+ return existing;
5714
+ } catch {}
5715
+ const id = crypto.randomUUID();
5716
+ try {
5717
+ fs.mkdirSync(ID_DIR, { recursive: true });
5718
+ fs.writeFileSync(ID_FILE, id, "utf-8");
5719
+ } catch {}
5720
+ return id;
5721
+ }
5722
+ function getInstanceId() {
5723
+ if (cachedId)
5724
+ return cachedId;
5725
+ const machineId = getPlatformMachineId();
5726
+ if (machineId) {
5727
+ cachedId = hashToId(machineId);
5728
+ return cachedId;
5729
+ }
5730
+ const sysProps = getSystemPropertiesId();
5731
+ if (sysProps) {
5732
+ cachedId = hashToId(sysProps);
5733
+ return cachedId;
5734
+ }
5735
+ cachedId = getFileBasedId();
5736
+ return cachedId;
5737
+ }
5738
+ var NAMESPACE = "failproofai-telemetry-v1", ID_DIR, ID_FILE, cachedId;
5739
+ var init_telemetry_id = __esm(() => {
5740
+ ID_DIR = path.join(os.homedir(), ".failproofai");
5741
+ ID_FILE = path.join(ID_DIR, "instance-id");
5742
+ });
5743
+
5744
+ // src/auth/token-store.ts
5745
+ import {
5746
+ readFileSync as readFileSync9,
5747
+ writeFileSync as writeFileSync4,
5748
+ existsSync as existsSync10,
5749
+ mkdirSync as mkdirSync5,
5750
+ unlinkSync as unlinkSync2,
5751
+ renameSync as renameSync3,
5752
+ openSync as openSync2,
5753
+ closeSync as closeSync2
5754
+ } from "node:fs";
5755
+ import { join as join18 } from "node:path";
5756
+ import { homedir as homedir17 } from "node:os";
5757
+ function ensureAuthDir() {
5758
+ if (!existsSync10(AUTH_DIR))
5759
+ mkdirSync5(AUTH_DIR, { recursive: true, mode: 448 });
5760
+ }
5761
+ function readTokens() {
5762
+ if (!existsSync10(AUTH_FILE))
5763
+ return null;
5764
+ try {
5765
+ const raw = readFileSync9(AUTH_FILE, "utf8");
5766
+ return JSON.parse(raw);
5767
+ } catch {
5768
+ return null;
5769
+ }
5770
+ }
5771
+ function writeTokens(tokens) {
5772
+ ensureAuthDir();
5773
+ const tmpPath = `${AUTH_FILE}.tmp`;
5774
+ const fd = openSync2(tmpPath, "w", 384);
5775
+ try {
5776
+ writeFileSync4(fd, JSON.stringify(tokens, null, 2));
5777
+ } finally {
5778
+ closeSync2(fd);
5779
+ }
5780
+ renameSync3(tmpPath, AUTH_FILE);
5781
+ }
5782
+ function clearTokens() {
5783
+ if (existsSync10(AUTH_FILE))
5784
+ unlinkSync2(AUTH_FILE);
5785
+ }
5786
+ function isLoggedIn() {
5787
+ return existsSync10(AUTH_FILE);
5788
+ }
5789
+ var AUTH_DIR, AUTH_FILE;
5790
+ var init_token_store = __esm(() => {
5791
+ AUTH_DIR = join18(homedir17(), ".failproofai");
5792
+ AUTH_FILE = join18(AUTH_DIR, "auth.json");
5793
+ });
5794
+
5795
+ // src/relay/queue.ts
5796
+ var exports_queue = {};
5797
+ __export(exports_queue, {
5798
+ readProcessingFile: () => readProcessingFile,
5799
+ queueSizeBytes: () => queueSizeBytes,
5800
+ findOrphanProcessingFiles: () => findOrphanProcessingFiles,
5801
+ deleteProcessingFile: () => deleteProcessingFile,
5802
+ claimPendingBatch: () => claimPendingBatch,
5803
+ appendToServerQueue: () => appendToServerQueue
5804
+ });
5805
+ import {
5806
+ appendFileSync as appendFileSync3,
5807
+ mkdirSync as mkdirSync6,
5808
+ existsSync as existsSync11,
5809
+ readFileSync as readFileSync10,
5810
+ statSync as statSync9,
5811
+ renameSync as renameSync4,
5812
+ unlinkSync as unlinkSync3,
5813
+ readdirSync as readdirSync8,
5814
+ chmodSync
5815
+ } from "node:fs";
5816
+ import { join as join19 } from "node:path";
5817
+ import { homedir as homedir18 } from "node:os";
5818
+ import { createHash, randomUUID } from "node:crypto";
5819
+ function hashCwd(cwd) {
5820
+ if (!cwd)
5821
+ return null;
5822
+ return createHash("sha256").update(cwd).digest("hex");
5823
+ }
5824
+ function redactReason(reason) {
5825
+ if (!reason)
5826
+ return reason ?? null;
5827
+ return reason.replace(/AKIA[0-9A-Z]{16}/g, "[REDACTED-AWS-KEY]").replace(/eyJ[A-Za-z0-9_=-]+\.[A-Za-z0-9_=-]+\.[A-Za-z0-9_=-]+/g, "[REDACTED-JWT]").replace(/ghp_[A-Za-z0-9]{36,}/g, "[REDACTED-GH-TOKEN]").replace(/sk-[A-Za-z0-9]{20,}/g, "[REDACTED-API-KEY]").replace(/Bearer\s+[A-Za-z0-9_.=+-]+/gi, "Bearer [REDACTED]");
5828
+ }
5829
+ function sanitize(entry) {
5830
+ return {
5831
+ client_event_id: randomUUID(),
5832
+ timestamp: entry.timestamp,
5833
+ event_type: entry.eventType,
5834
+ tool_name: entry.toolName ?? null,
5835
+ policy_name: entry.policyName ?? null,
5836
+ policy_names: entry.policyNames ?? [],
5837
+ decision: entry.decision,
5838
+ reason: redactReason(entry.reason),
5839
+ duration_ms: entry.durationMs,
4893
5840
  session_id: entry.sessionId ?? null,
4894
5841
  cwd_hash: hashCwd(entry.cwd),
4895
5842
  permission_mode: entry.permissionMode ?? null,
@@ -4897,7 +5844,7 @@ function sanitize(entry) {
4897
5844
  };
4898
5845
  }
4899
5846
  function ensureDir2() {
4900
- if (!existsSync7(QUEUE_DIR)) {
5847
+ if (!existsSync11(QUEUE_DIR)) {
4901
5848
  mkdirSync6(QUEUE_DIR, { recursive: true, mode: 448 });
4902
5849
  }
4903
5850
  }
@@ -4906,7 +5853,7 @@ function appendToServerQueue(entry) {
4906
5853
  return;
4907
5854
  ensureDir2();
4908
5855
  try {
4909
- if (existsSync7(PENDING_FILE) && statSync5(PENDING_FILE).size > MAX_QUEUE_BYTES) {
5856
+ if (existsSync11(PENDING_FILE) && statSync9(PENDING_FILE).size > MAX_QUEUE_BYTES) {
4910
5857
  return;
4911
5858
  }
4912
5859
  } catch {}
@@ -4919,23 +5866,23 @@ function appendToServerQueue(entry) {
4919
5866
  }
4920
5867
  function queueSizeBytes() {
4921
5868
  try {
4922
- return statSync5(PENDING_FILE).size;
5869
+ return statSync9(PENDING_FILE).size;
4923
5870
  } catch {
4924
5871
  return 0;
4925
5872
  }
4926
5873
  }
4927
5874
  function claimPendingBatch() {
4928
- if (!existsSync7(PENDING_FILE))
5875
+ if (!existsSync11(PENDING_FILE))
4929
5876
  return null;
4930
5877
  try {
4931
- const size = statSync5(PENDING_FILE).size;
5878
+ const size = statSync9(PENDING_FILE).size;
4932
5879
  if (size === 0)
4933
5880
  return null;
4934
5881
  } catch {
4935
5882
  return null;
4936
5883
  }
4937
5884
  const seq = `${Date.now()}-${process.pid}`;
4938
- const processingFile = join15(QUEUE_DIR, `${PROCESSING_PREFIX}${seq}.jsonl`);
5885
+ const processingFile = join19(QUEUE_DIR, `${PROCESSING_PREFIX}${seq}.jsonl`);
4939
5886
  try {
4940
5887
  renameSync4(PENDING_FILE, processingFile);
4941
5888
  try {
@@ -4952,15 +5899,15 @@ function claimPendingBatch() {
4952
5899
  function findOrphanProcessingFiles() {
4953
5900
  ensureDir2();
4954
5901
  try {
4955
- return readdirSync4(QUEUE_DIR).filter((n) => n.startsWith(PROCESSING_PREFIX) && n.endsWith(".jsonl")).map((n) => join15(QUEUE_DIR, n)).sort();
5902
+ return readdirSync8(QUEUE_DIR).filter((n) => n.startsWith(PROCESSING_PREFIX) && n.endsWith(".jsonl")).map((n) => join19(QUEUE_DIR, n)).sort();
4956
5903
  } catch {
4957
5904
  return [];
4958
5905
  }
4959
5906
  }
4960
5907
  function readProcessingFile(path2) {
4961
- if (!existsSync7(path2))
5908
+ if (!existsSync11(path2))
4962
5909
  return [];
4963
- const content = readFileSync6(path2, "utf8");
5910
+ const content = readFileSync10(path2, "utf8");
4964
5911
  const out = [];
4965
5912
  for (const line of content.split(`
4966
5913
  `)) {
@@ -4981,20 +5928,20 @@ function deleteProcessingFile(path2) {
4981
5928
  var QUEUE_DIR, PENDING_FILE, PROCESSING_PREFIX = "processing-", MAX_QUEUE_BYTES;
4982
5929
  var init_queue = __esm(() => {
4983
5930
  init_token_store();
4984
- QUEUE_DIR = join15(homedir14(), ".failproofai", "cache", "server-queue");
4985
- PENDING_FILE = join15(QUEUE_DIR, "pending.jsonl");
5931
+ QUEUE_DIR = join19(homedir18(), ".failproofai", "cache", "server-queue");
5932
+ PENDING_FILE = join19(QUEUE_DIR, "pending.jsonl");
4986
5933
  MAX_QUEUE_BYTES = 50 * 1024 * 1024;
4987
5934
  });
4988
5935
 
4989
5936
  // src/relay/pid.ts
4990
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync8, unlinkSync as unlinkSync4, mkdirSync as mkdirSync7 } from "node:fs";
4991
- import { join as join16, dirname as dirname4 } from "node:path";
4992
- import { homedir as homedir15 } from "node:os";
5937
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync5, existsSync as existsSync12, unlinkSync as unlinkSync4, mkdirSync as mkdirSync7 } from "node:fs";
5938
+ import { join as join20, dirname as dirname4 } from "node:path";
5939
+ import { homedir as homedir19 } from "node:os";
4993
5940
  function readPid() {
4994
- if (!existsSync8(PID_FILE))
5941
+ if (!existsSync12(PID_FILE))
4995
5942
  return null;
4996
5943
  try {
4997
- const raw = readFileSync7(PID_FILE, "utf8").trim();
5944
+ const raw = readFileSync11(PID_FILE, "utf8").trim();
4998
5945
  const pid = parseInt(raw, 10);
4999
5946
  if (Number.isNaN(pid) || pid <= 0)
5000
5947
  return null;
@@ -5005,12 +5952,12 @@ function readPid() {
5005
5952
  }
5006
5953
  function writePid(pid) {
5007
5954
  const dir = dirname4(PID_FILE);
5008
- if (!existsSync8(dir))
5955
+ if (!existsSync12(dir))
5009
5956
  mkdirSync7(dir, { recursive: true, mode: 448 });
5010
5957
  writeFileSync5(PID_FILE, String(pid));
5011
5958
  }
5012
5959
  function clearPid() {
5013
- if (existsSync8(PID_FILE))
5960
+ if (existsSync12(PID_FILE))
5014
5961
  unlinkSync4(PID_FILE);
5015
5962
  }
5016
5963
  function isProcessAlive(pid) {
@@ -5042,7 +5989,7 @@ function stopRelay() {
5042
5989
  }
5043
5990
  var PID_FILE;
5044
5991
  var init_pid = __esm(() => {
5045
- PID_FILE = join16(homedir15(), ".failproofai", "relay.pid");
5992
+ PID_FILE = join20(homedir19(), ".failproofai", "relay.pid");
5046
5993
  });
5047
5994
 
5048
5995
  // src/relay/daemon.ts
@@ -5054,9 +6001,9 @@ __export(exports_daemon, {
5054
6001
  ensureRelayRunning: () => ensureRelayRunning
5055
6002
  });
5056
6003
  import { spawn } from "node:child_process";
5057
- import { existsSync as existsSync9 } from "node:fs";
5058
- import { join as join17 } from "node:path";
5059
- import { homedir as homedir16 } from "node:os";
6004
+ import { existsSync as existsSync13 } from "node:fs";
6005
+ import { join as join21 } from "node:path";
6006
+ import { homedir as homedir20 } from "node:os";
5060
6007
  import { randomUUID as randomUUID2 } from "node:crypto";
5061
6008
  function ensureRelayRunning() {
5062
6009
  if (!isLoggedIn())
@@ -5136,16 +6083,16 @@ class Relay {
5136
6083
  try {
5137
6084
  const msg = JSON.parse(data);
5138
6085
  if (msg.ack && this.pendingAcks.has(msg.ack)) {
5139
- const resolve6 = this.pendingAcks.get(msg.ack);
6086
+ const resolve10 = this.pendingAcks.get(msg.ack);
5140
6087
  this.pendingAcks.delete(msg.ack);
5141
- resolve6(true);
6088
+ resolve10(true);
5142
6089
  }
5143
6090
  } catch {}
5144
6091
  }
5145
6092
  handleClose() {
5146
6093
  this.closed = true;
5147
- for (const [, resolve6] of this.pendingAcks) {
5148
- resolve6(false);
6094
+ for (const [, resolve10] of this.pendingAcks) {
6095
+ resolve10(false);
5149
6096
  }
5150
6097
  this.pendingAcks.clear();
5151
6098
  }
@@ -5161,11 +6108,11 @@ class Relay {
5161
6108
  if (this.closed)
5162
6109
  return false;
5163
6110
  const batchId = randomUUID2();
5164
- const ackPromise = new Promise((resolve6) => {
5165
- this.pendingAcks.set(batchId, resolve6);
6111
+ const ackPromise = new Promise((resolve10) => {
6112
+ this.pendingAcks.set(batchId, resolve10);
5166
6113
  setTimeout(() => {
5167
6114
  if (this.pendingAcks.delete(batchId))
5168
- resolve6(false);
6115
+ resolve10(false);
5169
6116
  }, ACK_TIMEOUT_MS);
5170
6117
  });
5171
6118
  try {
@@ -5183,7 +6130,7 @@ async function connect(wsUrl, token) {
5183
6130
  throw new Error("WebSocket not available in this Node version. Requires Node 22+.");
5184
6131
  }
5185
6132
  const ws = new WSCtor(wsUrl);
5186
- await new Promise((resolve6, reject) => {
6133
+ await new Promise((resolve10, reject) => {
5187
6134
  let settled = false;
5188
6135
  const timeout = setTimeout(() => {
5189
6136
  if (settled)
@@ -5201,7 +6148,7 @@ async function connect(wsUrl, token) {
5201
6148
  clearTimeout(timeout);
5202
6149
  try {
5203
6150
  ws.send(token);
5204
- resolve6();
6151
+ resolve10();
5205
6152
  } catch (e) {
5206
6153
  reject(e);
5207
6154
  }
@@ -5273,7 +6220,7 @@ async function runDaemon() {
5273
6220
  }
5274
6221
  relay.close();
5275
6222
  } catch {}
5276
- if (existsSync9(QUEUE_DIR2)) {}
6223
+ if (existsSync13(QUEUE_DIR2)) {}
5277
6224
  await new Promise((r) => setTimeout(r, reconnectDelay));
5278
6225
  reconnectDelay = Math.min(reconnectDelay * 2, RECONNECT_MAX_MS);
5279
6226
  }
@@ -5323,7 +6270,7 @@ var init_daemon = __esm(() => {
5323
6270
  init_token_store();
5324
6271
  init_pid();
5325
6272
  init_queue();
5326
- QUEUE_DIR2 = join17(homedir16(), ".failproofai", "cache", "server-queue");
6273
+ QUEUE_DIR2 = join21(homedir20(), ".failproofai", "cache", "server-queue");
5327
6274
  });
5328
6275
 
5329
6276
  // src/hooks/handler.ts
@@ -5357,12 +6304,14 @@ function canonicalizeEventType(raw, cli) {
5357
6304
  function canonicalizeToolName(raw, cli) {
5358
6305
  if (!raw)
5359
6306
  return raw;
5360
- if (cli === "copilot") {
6307
+ if (cli === "copilot")
5361
6308
  return COPILOT_TOOL_MAP[raw] ?? raw;
5362
- }
5363
- if (cli === "gemini") {
6309
+ if (cli === "cursor")
6310
+ return CURSOR_TOOL_MAP[raw] ?? raw;
6311
+ if (cli === "codex")
6312
+ return CODEX_TOOL_MAP[raw] ?? raw;
6313
+ if (cli === "gemini")
5364
6314
  return GEMINI_TOOL_MAP[raw] ?? raw;
5365
- }
5366
6315
  return raw;
5367
6316
  }
5368
6317
  async function handleHookEvent(eventType, cli = "claude") {
@@ -5370,7 +6319,7 @@ async function handleHookEvent(eventType, cli = "claude") {
5370
6319
  const MAX_STDIN_BYTES = 1048576;
5371
6320
  let payload = "";
5372
6321
  try {
5373
- payload = await new Promise((resolve6, reject) => {
6322
+ payload = await new Promise((resolve10, reject) => {
5374
6323
  const chunks = [];
5375
6324
  let totalBytes = 0;
5376
6325
  process.stdin.setEncoding("utf8");
@@ -5379,15 +6328,15 @@ async function handleHookEvent(eventType, cli = "claude") {
5379
6328
  if (totalBytes > MAX_STDIN_BYTES) {
5380
6329
  hookLogWarn(`stdin payload exceeds 1 MB for ${eventType}, discarding`);
5381
6330
  process.stdin.destroy();
5382
- resolve6("");
6331
+ resolve10("");
5383
6332
  return;
5384
6333
  }
5385
6334
  chunks.push(chunk);
5386
6335
  });
5387
- process.stdin.on("end", () => resolve6(chunks.join("")));
6336
+ process.stdin.on("end", () => resolve10(chunks.join("")));
5388
6337
  process.stdin.on("error", reject);
5389
6338
  if (process.stdin.readableEnded)
5390
- resolve6("");
6339
+ resolve10("");
5391
6340
  });
5392
6341
  } catch {
5393
6342
  hookLogWarn(`stdin read failed for ${eventType}`);
@@ -5409,7 +6358,7 @@ async function handleHookEvent(eventType, cli = "claude") {
5409
6358
  const sessionId = parsed.session_id;
5410
6359
  const session = {
5411
6360
  sessionId,
5412
- transcriptPath: parsed.transcript_path,
6361
+ transcriptPath: resolveTranscriptPath(cli, parsed, sessionId),
5413
6362
  cwd: parsed.cwd,
5414
6363
  permissionMode: resolvePermissionMode(cli, parsed, sessionId),
5415
6364
  hookEventName: parsed.hook_event_name,
@@ -5541,6 +6490,7 @@ var init_handler = __esm(() => {
5541
6490
  init_hook_activity_store();
5542
6491
  init_hook_telemetry();
5543
6492
  init_resolve_permission_mode();
6493
+ init_resolve_transcript_path();
5544
6494
  init_telemetry_id();
5545
6495
  init_hook_logger();
5546
6496
  });
@@ -5554,9 +6504,9 @@ __export(exports_daemon2, {
5554
6504
  ensureRelayRunning: () => ensureRelayRunning2
5555
6505
  });
5556
6506
  import { spawn as spawn2 } from "node:child_process";
5557
- import { existsSync as existsSync10 } from "node:fs";
5558
- import { join as join18 } from "node:path";
5559
- import { homedir as homedir17 } from "node:os";
6507
+ import { existsSync as existsSync14 } from "node:fs";
6508
+ import { join as join22 } from "node:path";
6509
+ import { homedir as homedir21 } from "node:os";
5560
6510
  import { randomUUID as randomUUID3 } from "node:crypto";
5561
6511
  function ensureRelayRunning2() {
5562
6512
  if (!isLoggedIn())
@@ -5636,16 +6586,16 @@ class Relay2 {
5636
6586
  try {
5637
6587
  const msg = JSON.parse(data);
5638
6588
  if (msg.ack && this.pendingAcks.has(msg.ack)) {
5639
- const resolve6 = this.pendingAcks.get(msg.ack);
6589
+ const resolve10 = this.pendingAcks.get(msg.ack);
5640
6590
  this.pendingAcks.delete(msg.ack);
5641
- resolve6(true);
6591
+ resolve10(true);
5642
6592
  }
5643
6593
  } catch {}
5644
6594
  }
5645
6595
  handleClose() {
5646
6596
  this.closed = true;
5647
- for (const [, resolve6] of this.pendingAcks) {
5648
- resolve6(false);
6597
+ for (const [, resolve10] of this.pendingAcks) {
6598
+ resolve10(false);
5649
6599
  }
5650
6600
  this.pendingAcks.clear();
5651
6601
  }
@@ -5661,11 +6611,11 @@ class Relay2 {
5661
6611
  if (this.closed)
5662
6612
  return false;
5663
6613
  const batchId = randomUUID3();
5664
- const ackPromise = new Promise((resolve6) => {
5665
- this.pendingAcks.set(batchId, resolve6);
6614
+ const ackPromise = new Promise((resolve10) => {
6615
+ this.pendingAcks.set(batchId, resolve10);
5666
6616
  setTimeout(() => {
5667
6617
  if (this.pendingAcks.delete(batchId))
5668
- resolve6(false);
6618
+ resolve10(false);
5669
6619
  }, ACK_TIMEOUT_MS2);
5670
6620
  });
5671
6621
  try {
@@ -5683,7 +6633,7 @@ async function connect2(wsUrl, token) {
5683
6633
  throw new Error("WebSocket not available in this Node version. Requires Node 22+.");
5684
6634
  }
5685
6635
  const ws = new WSCtor(wsUrl);
5686
- await new Promise((resolve6, reject) => {
6636
+ await new Promise((resolve10, reject) => {
5687
6637
  let settled = false;
5688
6638
  const timeout = setTimeout(() => {
5689
6639
  if (settled)
@@ -5701,7 +6651,7 @@ async function connect2(wsUrl, token) {
5701
6651
  clearTimeout(timeout);
5702
6652
  try {
5703
6653
  ws.send(token);
5704
- resolve6();
6654
+ resolve10();
5705
6655
  } catch (e) {
5706
6656
  reject(e);
5707
6657
  }
@@ -5773,7 +6723,7 @@ async function runDaemon2() {
5773
6723
  }
5774
6724
  relay.close();
5775
6725
  } catch {}
5776
- if (existsSync10(QUEUE_DIR3)) {}
6726
+ if (existsSync14(QUEUE_DIR3)) {}
5777
6727
  await new Promise((r) => setTimeout(r, reconnectDelay));
5778
6728
  reconnectDelay = Math.min(reconnectDelay * 2, RECONNECT_MAX_MS2);
5779
6729
  }
@@ -5823,19 +6773,19 @@ var init_daemon2 = __esm(() => {
5823
6773
  init_token_store();
5824
6774
  init_pid();
5825
6775
  init_queue();
5826
- QUEUE_DIR3 = join18(homedir17(), ".failproofai", "cache", "server-queue");
6776
+ QUEUE_DIR3 = join22(homedir21(), ".failproofai", "cache", "server-queue");
5827
6777
  });
5828
6778
 
5829
6779
  // src/hooks/integrations.ts
5830
6780
  import { execSync as execSync3 } from "node:child_process";
5831
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync11, mkdirSync as mkdirSync8, unlinkSync as unlinkSync5 } from "node:fs";
5832
- import { resolve as resolve6, dirname as dirname5 } from "node:path";
6781
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync6, existsSync as existsSync15, mkdirSync as mkdirSync8, unlinkSync as unlinkSync5 } from "node:fs";
6782
+ import { resolve as resolve10, dirname as dirname5 } from "node:path";
5833
6783
  import { fileURLToPath } from "node:url";
5834
- import { homedir as homedir18 } from "node:os";
6784
+ import { homedir as homedir22 } from "node:os";
5835
6785
  function readJsonFile(path2) {
5836
- if (!existsSync11(path2))
6786
+ if (!existsSync15(path2))
5837
6787
  return {};
5838
- const raw = readFileSync8(path2, "utf8");
6788
+ const raw = readFileSync12(path2, "utf8");
5839
6789
  return JSON.parse(raw);
5840
6790
  }
5841
6791
  function writeJsonFile(path2, data) {
@@ -5873,7 +6823,7 @@ function isMarkedCopilotHook(hook) {
5873
6823
  return false;
5874
6824
  }
5875
6825
  function opencodePluginFilePath(settingsPath) {
5876
- return resolve6(dirname5(settingsPath), "plugins", "failproofai.mjs");
6826
+ return resolve10(dirname5(settingsPath), "plugins", "failproofai.mjs");
5877
6827
  }
5878
6828
  function buildOpenCodePluginShim(binaryPath, scope) {
5879
6829
  const useNpx = scope === "project";
@@ -5906,10 +6856,12 @@ const TOOL_NAME_MAP = {
5906
6856
  read: "Read",
5907
6857
  write: "Write",
5908
6858
  edit: "Edit",
6859
+ apply_patch: "Edit",
5909
6860
  glob: "Glob",
5910
6861
  grep: "Grep",
5911
6862
  list: "LS",
5912
6863
  webfetch: "WebFetch",
6864
+ websearch: "WebSearch",
5913
6865
  todowrite: "TodoWrite",
5914
6866
  todoread: "TodoRead",
5915
6867
  };
@@ -6053,8 +7005,8 @@ export default async function failproofaiPlugin({ client, directory }) {
6053
7005
  function getPiExtensionPath() {
6054
7006
  const fromEnv = process.env.FAILPROOFAI_PACKAGE_ROOT;
6055
7007
  if (fromEnv)
6056
- return resolve6(fromEnv, "pi-extension");
6057
- return resolve6(fileURLToPath(import.meta.url), "..", "..", "..", "pi-extension");
7008
+ return resolve10(fromEnv, "pi-extension");
7009
+ return resolve10(fileURLToPath(import.meta.url), "..", "..", "..", "pi-extension");
6058
7010
  }
6059
7011
  function isFailproofaiPiEntry(source) {
6060
7012
  if (typeof source !== "string")
@@ -6065,8 +7017,8 @@ function isFailproofaiPiEntry(source) {
6065
7017
  }
6066
7018
  function makePiProjectRelativeEntry(extPath) {
6067
7019
  const cwd = process.cwd();
6068
- const cwdResolved = resolve6(cwd);
6069
- const extResolved = resolve6(extPath);
7020
+ const cwdResolved = resolve10(cwd);
7021
+ const extResolved = resolve10(extPath);
6070
7022
  if (extResolved.startsWith(cwdResolved + "/") || extResolved === cwdResolved) {
6071
7023
  const fromSettingsDir = "../" + extResolved.slice(cwdResolved.length + 1);
6072
7024
  return fromSettingsDir;
@@ -6092,14 +7044,14 @@ var init_integrations = __esm(() => {
6092
7044
  scopes: HOOK_SCOPES,
6093
7045
  eventTypes: HOOK_EVENT_TYPES,
6094
7046
  getSettingsPath(scope, cwd) {
6095
- const base = cwd ? resolve6(cwd) : process.cwd();
7047
+ const base = cwd ? resolve10(cwd) : process.cwd();
6096
7048
  switch (scope) {
6097
7049
  case "user":
6098
- return resolve6(homedir18(), ".claude", "settings.json");
7050
+ return resolve10(homedir22(), ".claude", "settings.json");
6099
7051
  case "project":
6100
- return resolve6(base, ".claude", "settings.json");
7052
+ return resolve10(base, ".claude", "settings.json");
6101
7053
  case "local":
6102
- return resolve6(base, ".claude", "settings.local.json");
7054
+ return resolve10(base, ".claude", "settings.local.json");
6103
7055
  }
6104
7056
  },
6105
7057
  readSettings(settingsPath) {
@@ -6171,7 +7123,7 @@ var init_integrations = __esm(() => {
6171
7123
  },
6172
7124
  hooksInstalledInSettings(scope, cwd) {
6173
7125
  const settingsPath = this.getSettingsPath(scope, cwd);
6174
- if (!existsSync11(settingsPath))
7126
+ if (!existsSync15(settingsPath))
6175
7127
  return false;
6176
7128
  try {
6177
7129
  const settings = this.readSettings(settingsPath);
@@ -6200,14 +7152,14 @@ var init_integrations = __esm(() => {
6200
7152
  scopes: CODEX_HOOK_SCOPES,
6201
7153
  eventTypes: CODEX_HOOK_EVENT_TYPES,
6202
7154
  getSettingsPath(scope, cwd) {
6203
- const base = cwd ? resolve6(cwd) : process.cwd();
7155
+ const base = cwd ? resolve10(cwd) : process.cwd();
6204
7156
  switch (scope) {
6205
7157
  case "user":
6206
- return resolve6(homedir18(), ".codex", "hooks.json");
7158
+ return resolve10(homedir22(), ".codex", "hooks.json");
6207
7159
  case "project":
6208
- return resolve6(base, ".codex", "hooks.json");
7160
+ return resolve10(base, ".codex", "hooks.json");
6209
7161
  case "local":
6210
- return resolve6(base, ".codex", "hooks.json");
7162
+ return resolve10(base, ".codex", "hooks.json");
6211
7163
  }
6212
7164
  },
6213
7165
  readSettings(settingsPath) {
@@ -6285,7 +7237,7 @@ var init_integrations = __esm(() => {
6285
7237
  },
6286
7238
  hooksInstalledInSettings(scope, cwd) {
6287
7239
  const settingsPath = this.getSettingsPath(scope, cwd);
6288
- if (!existsSync11(settingsPath))
7240
+ if (!existsSync15(settingsPath))
6289
7241
  return false;
6290
7242
  try {
6291
7243
  const settings = this.readSettings(settingsPath);
@@ -6314,14 +7266,14 @@ var init_integrations = __esm(() => {
6314
7266
  scopes: COPILOT_HOOK_SCOPES,
6315
7267
  eventTypes: COPILOT_HOOK_EVENT_TYPES,
6316
7268
  getSettingsPath(scope, cwd) {
6317
- const base = cwd ? resolve6(cwd) : process.cwd();
7269
+ const base = cwd ? resolve10(cwd) : process.cwd();
6318
7270
  switch (scope) {
6319
7271
  case "user":
6320
- return resolve6(homedir18(), ".copilot", "hooks", "failproofai.json");
7272
+ return resolve10(homedir22(), ".copilot", "hooks", "failproofai.json");
6321
7273
  case "project":
6322
- return resolve6(base, ".github", "hooks", "failproofai.json");
7274
+ return resolve10(base, ".github", "hooks", "failproofai.json");
6323
7275
  case "local":
6324
- return resolve6(base, ".github", "hooks", "failproofai.json");
7276
+ return resolve10(base, ".github", "hooks", "failproofai.json");
6325
7277
  }
6326
7278
  },
6327
7279
  readSettings(settingsPath) {
@@ -6399,7 +7351,7 @@ var init_integrations = __esm(() => {
6399
7351
  },
6400
7352
  hooksInstalledInSettings(scope, cwd) {
6401
7353
  const settingsPath = this.getSettingsPath(scope, cwd);
6402
- if (!existsSync11(settingsPath))
7354
+ if (!existsSync15(settingsPath))
6403
7355
  return false;
6404
7356
  try {
6405
7357
  const settings = this.readSettings(settingsPath);
@@ -6428,14 +7380,14 @@ var init_integrations = __esm(() => {
6428
7380
  scopes: CURSOR_HOOK_SCOPES,
6429
7381
  eventTypes: CURSOR_HOOK_EVENT_TYPES,
6430
7382
  getSettingsPath(scope, cwd) {
6431
- const base = cwd ? resolve6(cwd) : process.cwd();
7383
+ const base = cwd ? resolve10(cwd) : process.cwd();
6432
7384
  switch (scope) {
6433
7385
  case "user":
6434
- return resolve6(homedir18(), ".cursor", "hooks.json");
7386
+ return resolve10(homedir22(), ".cursor", "hooks.json");
6435
7387
  case "project":
6436
- return resolve6(base, ".cursor", "hooks.json");
7388
+ return resolve10(base, ".cursor", "hooks.json");
6437
7389
  case "local":
6438
- return resolve6(base, ".cursor", "hooks.json");
7390
+ return resolve10(base, ".cursor", "hooks.json");
6439
7391
  }
6440
7392
  },
6441
7393
  readSettings(settingsPath) {
@@ -6502,7 +7454,7 @@ var init_integrations = __esm(() => {
6502
7454
  },
6503
7455
  hooksInstalledInSettings(scope, cwd) {
6504
7456
  const settingsPath = this.getSettingsPath(scope, cwd);
6505
- if (!existsSync11(settingsPath))
7457
+ if (!existsSync15(settingsPath))
6506
7458
  return false;
6507
7459
  try {
6508
7460
  const settings = this.readSettings(settingsPath);
@@ -6527,14 +7479,14 @@ var init_integrations = __esm(() => {
6527
7479
  scopes: OPENCODE_HOOK_SCOPES,
6528
7480
  eventTypes: OPENCODE_HOOK_EVENT_TYPES,
6529
7481
  getSettingsPath(scope, cwd) {
6530
- const base = cwd ? resolve6(cwd) : process.cwd();
7482
+ const base = cwd ? resolve10(cwd) : process.cwd();
6531
7483
  switch (scope) {
6532
7484
  case "user":
6533
- return resolve6(homedir18(), ".config", "opencode", "opencode.json");
7485
+ return resolve10(homedir22(), ".config", "opencode", "opencode.json");
6534
7486
  case "project":
6535
- return resolve6(base, ".opencode", "opencode.json");
7487
+ return resolve10(base, ".opencode", "opencode.json");
6536
7488
  case "local":
6537
- return resolve6(base, ".opencode", "opencode.json");
7489
+ return resolve10(base, ".opencode", "opencode.json");
6538
7490
  }
6539
7491
  },
6540
7492
  readSettings(settingsPath) {
@@ -6545,7 +7497,7 @@ var init_integrations = __esm(() => {
6545
7497
  },
6546
7498
  buildHookEntry(_binaryPath, _eventType, scope) {
6547
7499
  if (scope === "user") {
6548
- const abs = resolve6(homedir18(), ".config", "opencode", "plugins", "failproofai.mjs");
7500
+ const abs = resolve10(homedir22(), ".config", "opencode", "plugins", "failproofai.mjs");
6549
7501
  return { spec: `file://${abs}`, [FAILPROOFAI_HOOK_MARKER]: true };
6550
7502
  }
6551
7503
  return { spec: OPENCODE_PLUGIN_REL_PATH, [FAILPROOFAI_HOOK_MARKER]: true };
@@ -6560,7 +7512,7 @@ var init_integrations = __esm(() => {
6560
7512
  writeHookEntries(settings, binaryPath, scope) {
6561
7513
  const s = settings;
6562
7514
  const effectiveScope = scope ?? "project";
6563
- const settingsPath = effectiveScope === "user" ? resolve6(homedir18(), ".config", "opencode", "opencode.json") : resolve6(process.cwd(), ".opencode", "opencode.json");
7515
+ const settingsPath = effectiveScope === "user" ? resolve10(homedir22(), ".config", "opencode", "opencode.json") : resolve10(process.cwd(), ".opencode", "opencode.json");
6564
7516
  const pluginPath = opencodePluginFilePath(settingsPath);
6565
7517
  mkdirSync8(dirname5(pluginPath), { recursive: true });
6566
7518
  writeFileSync6(pluginPath, buildOpenCodePluginShim(binaryPath, effectiveScope), "utf8");
@@ -6586,9 +7538,9 @@ var init_integrations = __esm(() => {
6586
7538
  }
6587
7539
  this.writeSettings(settingsPath, settings);
6588
7540
  const pluginPath = opencodePluginFilePath(settingsPath);
6589
- if (existsSync11(pluginPath)) {
7541
+ if (existsSync15(pluginPath)) {
6590
7542
  try {
6591
- const content = readFileSync8(pluginPath, "utf8");
7543
+ const content = readFileSync12(pluginPath, "utf8");
6592
7544
  if (content.includes(FAILPROOFAI_HOOK_MARKER)) {
6593
7545
  unlinkSync5(pluginPath);
6594
7546
  if (removed === 0)
@@ -6600,7 +7552,7 @@ var init_integrations = __esm(() => {
6600
7552
  },
6601
7553
  hooksInstalledInSettings(scope, cwd) {
6602
7554
  const settingsPath = this.getSettingsPath(scope, cwd);
6603
- if (!existsSync11(settingsPath))
7555
+ if (!existsSync15(settingsPath))
6604
7556
  return false;
6605
7557
  try {
6606
7558
  const settings = this.readSettings(settingsPath);
@@ -6610,9 +7562,9 @@ var init_integrations = __esm(() => {
6610
7562
  if (!hasEntry)
6611
7563
  return false;
6612
7564
  const pluginPath = opencodePluginFilePath(settingsPath);
6613
- if (!existsSync11(pluginPath))
7565
+ if (!existsSync15(pluginPath))
6614
7566
  return false;
6615
- const content = readFileSync8(pluginPath, "utf8");
7567
+ const content = readFileSync12(pluginPath, "utf8");
6616
7568
  return content.includes(FAILPROOFAI_HOOK_MARKER);
6617
7569
  } catch {
6618
7570
  return false;
@@ -6628,14 +7580,14 @@ var init_integrations = __esm(() => {
6628
7580
  scopes: PI_HOOK_SCOPES,
6629
7581
  eventTypes: PI_HOOK_EVENT_TYPES,
6630
7582
  getSettingsPath(scope, cwd) {
6631
- const base = cwd ? resolve6(cwd) : process.cwd();
7583
+ const base = cwd ? resolve10(cwd) : process.cwd();
6632
7584
  switch (scope) {
6633
7585
  case "user":
6634
- return resolve6(homedir18(), ".pi", "agent", "settings.json");
7586
+ return resolve10(homedir22(), ".pi", "agent", "settings.json");
6635
7587
  case "project":
6636
- return resolve6(base, ".pi", "settings.json");
7588
+ return resolve10(base, ".pi", "settings.json");
6637
7589
  case "local":
6638
- return resolve6(base, ".pi", "settings.json");
7590
+ return resolve10(base, ".pi", "settings.json");
6639
7591
  }
6640
7592
  },
6641
7593
  readSettings(settingsPath) {
@@ -6677,7 +7629,7 @@ var init_integrations = __esm(() => {
6677
7629
  }
6678
7630
  },
6679
7631
  removeHooksFromFile(settingsPath) {
6680
- if (!existsSync11(settingsPath))
7632
+ if (!existsSync15(settingsPath))
6681
7633
  return 0;
6682
7634
  const settings = this.readSettings(settingsPath);
6683
7635
  if (!Array.isArray(settings.packages))
@@ -6692,7 +7644,7 @@ var init_integrations = __esm(() => {
6692
7644
  },
6693
7645
  hooksInstalledInSettings(scope, cwd) {
6694
7646
  const settingsPath = this.getSettingsPath(scope, cwd);
6695
- if (!existsSync11(settingsPath))
7647
+ if (!existsSync15(settingsPath))
6696
7648
  return false;
6697
7649
  try {
6698
7650
  const settings = this.readSettings(settingsPath);
@@ -6713,14 +7665,14 @@ var init_integrations = __esm(() => {
6713
7665
  scopes: GEMINI_HOOK_SCOPES,
6714
7666
  eventTypes: GEMINI_HOOK_EVENT_TYPES,
6715
7667
  getSettingsPath(scope, cwd) {
6716
- const base = cwd ? resolve6(cwd) : process.cwd();
7668
+ const base = cwd ? resolve10(cwd) : process.cwd();
6717
7669
  switch (scope) {
6718
7670
  case "user":
6719
- return resolve6(homedir18(), ".gemini", "settings.json");
7671
+ return resolve10(homedir22(), ".gemini", "settings.json");
6720
7672
  case "project":
6721
- return resolve6(base, ".gemini", "settings.json");
7673
+ return resolve10(base, ".gemini", "settings.json");
6722
7674
  case "local":
6723
- return resolve6(base, ".gemini", "settings.json");
7675
+ return resolve10(base, ".gemini", "settings.json");
6724
7676
  }
6725
7677
  },
6726
7678
  readSettings(settingsPath) {
@@ -6792,7 +7744,7 @@ var init_integrations = __esm(() => {
6792
7744
  },
6793
7745
  hooksInstalledInSettings(scope, cwd) {
6794
7746
  const settingsPath = this.getSettingsPath(scope, cwd);
6795
- if (!existsSync11(settingsPath))
7747
+ if (!existsSync15(settingsPath))
6796
7748
  return false;
6797
7749
  try {
6798
7750
  const settings = this.readSettings(settingsPath);
@@ -7014,7 +7966,7 @@ async function promptPolicySelection(preSelected, options = {}) {
7014
7966
  process.stdout.write(output);
7015
7967
  lastLineCount = lines.length;
7016
7968
  }
7017
- return new Promise((resolve7) => {
7969
+ return new Promise((resolve11) => {
7018
7970
  render();
7019
7971
  process.stdin.setRawMode(true);
7020
7972
  process.stdin.resume();
@@ -7056,7 +8008,7 @@ async function promptPolicySelection(preSelected, options = {}) {
7056
8008
  const selected = items.filter((i) => i.selected).map((i) => i.name);
7057
8009
  process.stdout.write(`
7058
8010
  `);
7059
- resolve7(selected);
8011
+ resolve11(selected);
7060
8012
  } else if (key.name === "backspace" || key.name === "delete") {
7061
8013
  if (search.length > 0) {
7062
8014
  search = search.slice(0, -1);
@@ -7106,9 +8058,9 @@ __export(exports_manager, {
7106
8058
  getSettingsPath: () => getSettingsPath
7107
8059
  });
7108
8060
  import { execSync as execSync4 } from "node:child_process";
7109
- import { existsSync as existsSync12 } from "node:fs";
7110
- import { resolve as resolve7, basename as basename3 } from "node:path";
7111
- import { homedir as homedir19, platform, arch, release, hostname } from "node:os";
8061
+ import { existsSync as existsSync16 } from "node:fs";
8062
+ import { resolve as resolve11, basename as basename4 } from "node:path";
8063
+ import { homedir as homedir23, platform, arch, release, hostname } from "node:os";
7112
8064
  function getSettingsPath(scope, cwd) {
7113
8065
  return claudeCode.getSettingsPath(scope, cwd);
7114
8066
  }
@@ -7194,7 +8146,7 @@ async function installHooks(policyNames, scope = "user", cwd, includeBeta = fals
7194
8146
  if (removeCustomHooks) {
7195
8147
  delete configToWrite.customPoliciesPath;
7196
8148
  } else if (customPoliciesPath) {
7197
- configToWrite.customPoliciesPath = resolve7(customPoliciesPath);
8149
+ configToWrite.customPoliciesPath = resolve11(customPoliciesPath);
7198
8150
  let validatedHooks = [];
7199
8151
  try {
7200
8152
  validatedHooks = await loadCustomHooks(configToWrite.customPoliciesPath, { strict: true });
@@ -7329,7 +8281,7 @@ async function removeHooks(policyNames, scope = "user", cwd, opts) {
7329
8281
  const scopesToRemove = scope === "all" ? [...integration.scopes] : integration.scopes.includes(scope) ? [scope] : [];
7330
8282
  for (const s of scopesToRemove) {
7331
8283
  const settingsPath = integration.getSettingsPath(s, cwd);
7332
- if (!existsSync12(settingsPath)) {
8284
+ if (!existsSync16(settingsPath)) {
7333
8285
  if (scope !== "all" && selectedClis.length === 1) {
7334
8286
  console.log("No settings file found. Nothing to remove.");
7335
8287
  nothingToReport = true;
@@ -7508,7 +8460,7 @@ Failproof AI Hook Policies
7508
8460
  if (config.customPoliciesPath) {
7509
8461
  console.log(`
7510
8462
  ── Custom Policies (${config.customPoliciesPath}) ───────────────────────`);
7511
- if (!existsSync12(config.customPoliciesPath)) {
8463
+ if (!existsSync16(config.customPoliciesPath)) {
7512
8464
  console.log(` \x1B[31m✗ File not found: ${config.customPoliciesPath}\x1B[0m`);
7513
8465
  } else {
7514
8466
  const hooks = await loadCustomHooks(config.customPoliciesPath);
@@ -7523,10 +8475,10 @@ Failproof AI Hook Policies
7523
8475
  }
7524
8476
  console.log();
7525
8477
  }
7526
- const base = cwd ? resolve7(cwd) : process.cwd();
8478
+ const base = cwd ? resolve11(cwd) : process.cwd();
7527
8479
  const conventionDirs = [
7528
- { label: "Project", dir: resolve7(base, ".failproofai", "policies") },
7529
- { label: "User", dir: resolve7(homedir19(), ".failproofai", "policies") }
8480
+ { label: "Project", dir: resolve11(base, ".failproofai", "policies") },
8481
+ { label: "User", dir: resolve11(homedir23(), ".failproofai", "policies") }
7530
8482
  ];
7531
8483
  for (const { label, dir } of conventionDirs) {
7532
8484
  const files = discoverPolicyFiles(dir);
@@ -7538,15 +8490,15 @@ Failproof AI Hook Policies
7538
8490
  try {
7539
8491
  const hooks = await loadCustomHooks(file);
7540
8492
  if (hooks.length === 0) {
7541
- const filename = basename3(file);
8493
+ const filename = basename4(file);
7542
8494
  console.log(` \x1B[31m✗\x1B[0m ${filename.padEnd(nameColWidth)}\x1B[31mfailed to load\x1B[0m`);
7543
8495
  } else {
7544
- const filename = basename3(file);
8496
+ const filename = basename4(file);
7545
8497
  const hookSummary = hooks.map((h) => h.name).join(", ");
7546
8498
  console.log(` \x1B[32m✓\x1B[0m ${filename.padEnd(nameColWidth)}${hooks.length} hook(s): ${hookSummary}`);
7547
8499
  }
7548
8500
  } catch {
7549
- const filename = basename3(file);
8501
+ const filename = basename4(file);
7550
8502
  console.log(` \x1B[31m✗\x1B[0m ${filename.padEnd(nameColWidth)}\x1B[31merror\x1B[0m`);
7551
8503
  }
7552
8504
  }
@@ -7675,7 +8627,7 @@ async function promptCliTargetSelection(detected, action = "install") {
7675
8627
  process.stdout.write(output);
7676
8628
  lastLineCount = lines.length;
7677
8629
  }
7678
- return new Promise((resolve8) => {
8630
+ return new Promise((resolve12) => {
7679
8631
  render();
7680
8632
  readline2.emitKeypressEvents(process.stdin);
7681
8633
  const wasRaw = process.stdin.isRaw;
@@ -7708,7 +8660,7 @@ async function promptCliTargetSelection(detected, action = "install") {
7708
8660
  cleanup();
7709
8661
  process.stdout.write(`
7710
8662
  `);
7711
- resolve8(options[cursor2].value);
8663
+ resolve12(options[cursor2].value);
7712
8664
  }
7713
8665
  }
7714
8666
  process.stdin.on("keypress", onKey);
@@ -7900,7 +8852,7 @@ async function promptPolicySelection2(preSelected, options = {}) {
7900
8852
  process.stdout.write(output);
7901
8853
  lastLineCount = lines.length;
7902
8854
  }
7903
- return new Promise((resolve8) => {
8855
+ return new Promise((resolve12) => {
7904
8856
  render();
7905
8857
  process.stdin.setRawMode(true);
7906
8858
  process.stdin.resume();
@@ -7942,7 +8894,7 @@ async function promptPolicySelection2(preSelected, options = {}) {
7942
8894
  const selected = items.filter((i) => i.selected).map((i) => i.name);
7943
8895
  process.stdout.write(`
7944
8896
  `);
7945
- resolve8(selected);
8897
+ resolve12(selected);
7946
8898
  } else if (key.name === "backspace" || key.name === "delete") {
7947
8899
  if (search.length > 0) {
7948
8900
  search = search.slice(0, -1);
@@ -8104,14 +9056,14 @@ __export(exports_pid, {
8104
9056
  isProcessAlive: () => isProcessAlive2,
8105
9057
  clearPid: () => clearPid2
8106
9058
  });
8107
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, existsSync as existsSync13, unlinkSync as unlinkSync6, mkdirSync as mkdirSync9 } from "node:fs";
8108
- import { join as join19, dirname as dirname6 } from "node:path";
8109
- import { homedir as homedir20 } from "node:os";
9059
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync7, existsSync as existsSync17, unlinkSync as unlinkSync6, mkdirSync as mkdirSync9 } from "node:fs";
9060
+ import { join as join23, dirname as dirname6 } from "node:path";
9061
+ import { homedir as homedir24 } from "node:os";
8110
9062
  function readPid2() {
8111
- if (!existsSync13(PID_FILE2))
9063
+ if (!existsSync17(PID_FILE2))
8112
9064
  return null;
8113
9065
  try {
8114
- const raw = readFileSync9(PID_FILE2, "utf8").trim();
9066
+ const raw = readFileSync13(PID_FILE2, "utf8").trim();
8115
9067
  const pid = parseInt(raw, 10);
8116
9068
  if (Number.isNaN(pid) || pid <= 0)
8117
9069
  return null;
@@ -8122,12 +9074,12 @@ function readPid2() {
8122
9074
  }
8123
9075
  function writePid2(pid) {
8124
9076
  const dir = dirname6(PID_FILE2);
8125
- if (!existsSync13(dir))
9077
+ if (!existsSync17(dir))
8126
9078
  mkdirSync9(dir, { recursive: true, mode: 448 });
8127
9079
  writeFileSync7(PID_FILE2, String(pid));
8128
9080
  }
8129
9081
  function clearPid2() {
8130
- if (existsSync13(PID_FILE2))
9082
+ if (existsSync17(PID_FILE2))
8131
9083
  unlinkSync6(PID_FILE2);
8132
9084
  }
8133
9085
  function isProcessAlive2(pid) {
@@ -8165,18 +9117,18 @@ function relayStatus() {
8165
9117
  }
8166
9118
  var PID_FILE2;
8167
9119
  var init_pid2 = __esm(() => {
8168
- PID_FILE2 = join19(homedir20(), ".failproofai", "relay.pid");
9120
+ PID_FILE2 = join23(homedir24(), ".failproofai", "relay.pid");
8169
9121
  });
8170
9122
 
8171
9123
  // scripts/parse-script-args.ts
8172
- import { resolve as resolve8 } from "path";
9124
+ import { resolve as resolve12 } from "path";
8173
9125
  function parseStringFlag(flagName, errorLabel, inlineValue, args, index, options) {
8174
9126
  const raw = inlineValue ?? args[index + 1];
8175
9127
  if (raw === undefined || inlineValue === null && raw.startsWith("-")) {
8176
9128
  console.error(`Error: ${flagName} requires ${errorLabel}`);
8177
9129
  process.exit(1);
8178
9130
  }
8179
- const value = options?.resolve ? resolve8(raw) : raw;
9131
+ const value = options?.resolve ? resolve12(raw) : raw;
8180
9132
  return { value, spliceCount: inlineValue !== null ? 1 : 2 };
8181
9133
  }
8182
9134
  function parseScriptArgs(argv) {
@@ -8232,21 +9184,21 @@ function parseScriptArgs(argv) {
8232
9184
  var init_parse_script_args = () => {};
8233
9185
 
8234
9186
  // scripts/install-diagnosis.mjs
8235
- import { existsSync as existsSync14, readFileSync as readFileSync10, realpathSync } from "node:fs";
8236
- import { dirname as dirname7, resolve as resolve9 } from "node:path";
8237
- import { homedir as homedir21, platform as platform3 } from "node:os";
9187
+ import { existsSync as existsSync18, readFileSync as readFileSync14, realpathSync } from "node:fs";
9188
+ import { dirname as dirname7, resolve as resolve13 } from "node:path";
9189
+ import { homedir as homedir25, platform as platform3 } from "node:os";
8238
9190
  import { spawnSync } from "node:child_process";
8239
9191
  function findPackageRoot(start) {
8240
9192
  try {
8241
9193
  let dir = realpathSync(start);
8242
- if (existsSync14(dir) && !existsSync14(resolve9(dir, "package.json"))) {
9194
+ if (existsSync18(dir) && !existsSync18(resolve13(dir, "package.json"))) {
8243
9195
  dir = dirname7(dir);
8244
9196
  }
8245
9197
  while (true) {
8246
- const pkgPath = resolve9(dir, "package.json");
8247
- if (existsSync14(pkgPath)) {
9198
+ const pkgPath = resolve13(dir, "package.json");
9199
+ if (existsSync18(pkgPath)) {
8248
9200
  try {
8249
- const pkg = JSON.parse(readFileSync10(pkgPath, "utf8"));
9201
+ const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
8250
9202
  if (pkg.name === PKG_NAME)
8251
9203
  return dir;
8252
9204
  } catch {}
@@ -8264,7 +9216,7 @@ function readPackageVersion(packageRoot) {
8264
9216
  if (!packageRoot)
8265
9217
  return null;
8266
9218
  try {
8267
- const pkg = JSON.parse(readFileSync10(resolve9(packageRoot, "package.json"), "utf8"));
9219
+ const pkg = JSON.parse(readFileSync14(resolve13(packageRoot, "package.json"), "utf8"));
8268
9220
  return typeof pkg.version === "string" ? pkg.version : null;
8269
9221
  } catch {
8270
9222
  return null;
@@ -8290,16 +9242,16 @@ function locateNpmGlobal() {
8290
9242
  const root = (res.stdout || "").trim();
8291
9243
  if (!root)
8292
9244
  return null;
8293
- const candidate = resolve9(root, PKG_NAME);
8294
- return existsSync14(resolve9(candidate, "package.json")) ? candidate : null;
9245
+ const candidate = resolve13(root, PKG_NAME);
9246
+ return existsSync18(resolve13(candidate, "package.json")) ? candidate : null;
8295
9247
  } catch {
8296
9248
  return null;
8297
9249
  }
8298
9250
  }
8299
9251
  function locateBunGlobal() {
8300
9252
  try {
8301
- const candidate = resolve9(homedir21(), ".bun", "install", "global", "node_modules", PKG_NAME);
8302
- return existsSync14(resolve9(candidate, "package.json")) ? candidate : null;
9253
+ const candidate = resolve13(homedir25(), ".bun", "install", "global", "node_modules", PKG_NAME);
9254
+ return existsSync18(resolve13(candidate, "package.json")) ? candidate : null;
8303
9255
  } catch {
8304
9256
  return null;
8305
9257
  }
@@ -8307,8 +9259,8 @@ function locateBunGlobal() {
8307
9259
  function buildRecommendation(pathFirstBin) {
8308
9260
  if (!pathFirstBin)
8309
9261
  return null;
8310
- const bunBinPrefix = resolve9(homedir21(), ".bun", "bin") + "/";
8311
- const bunGlobalPrefix = resolve9(homedir21(), ".bun", "install", "global") + "/";
9262
+ const bunBinPrefix = resolve13(homedir25(), ".bun", "bin") + "/";
9263
+ const bunGlobalPrefix = resolve13(homedir25(), ".bun", "install", "global") + "/";
8312
9264
  const isBun = pathFirstBin.startsWith(bunBinPrefix) || pathFirstBin.startsWith(bunGlobalPrefix);
8313
9265
  if (isBun) {
8314
9266
  return `rm -f ~/.bun/bin/${PKG_NAME} && rm -rf ~/.bun/install/global/node_modules/${PKG_NAME}`;
@@ -8369,8 +9321,8 @@ __export(exports_launch, {
8369
9321
  launch: () => launch
8370
9322
  });
8371
9323
  import { spawn as spawn4 } from "child_process";
8372
- import { realpathSync as realpathSync2, existsSync as existsSync15 } from "node:fs";
8373
- import { resolve as resolve10, dirname as dirname8 } from "node:path";
9324
+ import { realpathSync as realpathSync2, existsSync as existsSync19 } from "node:fs";
9325
+ import { resolve as resolve14, dirname as dirname8 } from "node:path";
8374
9326
  import { fileURLToPath as fileURLToPath2 } from "node:url";
8375
9327
  function launch(mode) {
8376
9328
  const { claudeProjectsPath: parsedPath, loggingLevel, disableTelemetry, allowedDevOrigins, remainingArgs } = parseScriptArgs(process.argv.slice(2));
@@ -8402,9 +9354,9 @@ function launch(mode) {
8402
9354
  process.env.PORT = port;
8403
9355
  process.env.HOSTNAME = "0.0.0.0";
8404
9356
  cmd = "node";
8405
- const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve10(dirname8(realpathSync2(fileURLToPath2(import.meta.url))), "..");
8406
- const serverJsPath = resolve10(packageRoot, ".next/standalone/server.js");
8407
- if (!existsSync15(serverJsPath)) {
9357
+ const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve14(dirname8(realpathSync2(fileURLToPath2(import.meta.url))), "..");
9358
+ const serverJsPath = resolve14(packageRoot, ".next/standalone/server.js");
9359
+ if (!existsSync19(serverJsPath)) {
8408
9360
  let shadowMessage = null;
8409
9361
  try {
8410
9362
  const diag = diagnoseShadow({ selfPackageRoot: packageRoot, selfVersion: version2 });
@@ -8481,17 +9433,17 @@ var init_cli_error2 = __esm(() => {
8481
9433
 
8482
9434
  // bin/failproofai.mjs
8483
9435
  import { realpathSync as realpathSync3 } from "fs";
8484
- import { dirname as dirname9, resolve as resolve11 } from "path";
9436
+ import { dirname as dirname9, resolve as resolve15 } from "path";
8485
9437
  import { fileURLToPath as fileURLToPath3 } from "url";
8486
9438
  // package.json
8487
- var version = "0.0.10-beta.2";
9439
+ var version = "0.0.10-beta.3";
8488
9440
 
8489
9441
  // bin/failproofai.mjs
8490
9442
  if (!process.env.FAILPROOFAI_PACKAGE_ROOT) {
8491
- process.env.FAILPROOFAI_PACKAGE_ROOT = resolve11(dirname9(realpathSync3(fileURLToPath3(import.meta.url))), "..");
9443
+ process.env.FAILPROOFAI_PACKAGE_ROOT = resolve15(dirname9(realpathSync3(fileURLToPath3(import.meta.url))), "..");
8492
9444
  }
8493
9445
  if (!process.env.FAILPROOFAI_DIST_PATH) {
8494
- process.env.FAILPROOFAI_DIST_PATH = resolve11(dirname9(realpathSync3(fileURLToPath3(import.meta.url))), "..", "dist");
9446
+ process.env.FAILPROOFAI_DIST_PATH = resolve15(dirname9(realpathSync3(fileURLToPath3(import.meta.url))), "..", "dist");
8495
9447
  }
8496
9448
  var args = process.argv.slice(2);
8497
9449
  if (args[0] === "p")