failproofai 0.0.14-beta.0 → 0.0.14-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.codex/hooks.json +6 -6
- package/.next/standalone/.cursor/hooks.json +6 -6
- package/.next/standalone/.factory/hooks.json +9 -9
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0--lkk6._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06cuf1y._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08w4wmd._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g6bbuw._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jnjf2t._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q0qzx1._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q2nbsl._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xuaoik._.js +3 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__16le-kd._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ffkmds._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1mrihkj._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qb590j._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1shcqgr._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xuedea._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +4 -4
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00cz9as._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__015_i4t._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__030k0c6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__03lv-pe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__042d3cd._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__05r_17v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09q1168._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__07qfsfa._.js → [root-of-the-server]__09v9cwb._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e2l3c1._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h12me5._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hci7t3._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hdsupo._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p84xee._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qeuy9c._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s89hoe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0twi4fj._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ynf7tx._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11rtg6s._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__170799-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17ai7sy._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1dky4g0._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tkjqka._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__212nf49._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1kje4fm._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_087bt9w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_1fvisnp._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_209u41o._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/lib_0xkhw_v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_0g5r64e.js → node_modules_html-to-image_es_index_06xsmte.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0-uvagv.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_03c7gi5.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_09p-8om.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0v-kfiu.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0xrgzyz.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1806lsc.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1j6dd-e.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1sa65r-.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +10 -10
- package/.next/standalone/.next/static/chunks/{13f1kmjea-0md.js → 02jcotghcxrbu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1374x9bv_s_vg.js → 0h-6ymo9v86b0.js} +2 -2
- package/.next/standalone/.next/static/chunks/0pndjhcxfu-0t.js +1 -0
- package/.next/standalone/.next/static/chunks/1-33f82_l32or.js +1 -0
- package/.next/standalone/.next/static/chunks/{003uz088wbmz7.js → 1bg_g3g359c_d.js} +1 -1
- package/.next/standalone/.next/static/chunks/{454dyizqik6t9.js → 1gg-8e9q_m__9.js} +2 -2
- package/.next/standalone/.next/static/chunks/{2ufuwhv03yvtb.js → 29zkom4s9de2d.js} +1 -1
- package/.next/standalone/.next/static/chunks/{17sdztgbcc0fi.js → 2llkdafnaejw_.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0iinhn4417nk1.js → 3-ogr79xqbw0h.js} +1 -1
- package/.next/standalone/.next/static/chunks/36j05kb2x323i.css +2 -0
- package/.next/standalone/.next/static/chunks/{43weu8f59tlix.js → 388hgfqye67xa.js} +1 -1
- package/.next/standalone/.next/static/chunks/396764jgd7-9j.js +1 -0
- package/.next/standalone/.next/static/chunks/3w7g0n0iwwnbs.js +1 -0
- package/.next/standalone/.next/static/chunks/{turbopack-0vavqo2d-tlt3.js → turbopack-10hj8t5pf33tu.js} +1 -1
- package/.next/standalone/.opencode/plugins/failproofai.mjs +30 -11
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +11 -2
- package/.next/standalone/app/components/copy-button.tsx +22 -6
- package/.next/standalone/app/components/global-error-listeners.tsx +27 -0
- package/.next/standalone/components/reach-developers.tsx +1 -1
- package/.next/standalone/docker-hook-sync/Dockerfile +8 -4
- package/.next/standalone/integration-suite/Dockerfile +47 -0
- package/.next/standalone/integration-suite/README.md +87 -0
- package/.next/standalone/integration-suite/canary-policies.mjs +45 -0
- package/.next/standalone/integration-suite/capture-tokens.sh +48 -0
- package/.next/standalone/integration-suite/ci-entrypoint.sh +164 -0
- package/.next/standalone/integration-suite/inject-tokens.sh +44 -0
- package/.next/standalone/integration-suite/install-clis.sh +91 -0
- package/.next/standalone/integration-suite/probe-cli.sh +208 -0
- package/.next/standalone/integration-suite/report.js +74 -0
- package/.next/standalone/integration-suite/run.sh +107 -0
- package/.next/standalone/lib/error-origin.ts +67 -0
- package/.next/standalone/lib/format-duration.ts +23 -9
- package/.next/standalone/lib/install-check.ts +231 -0
- package/.next/standalone/package.json +1 -3
- package/.next/standalone/server.js +1 -1
- package/README.md +1 -17
- package/bin/failproofai.mjs +11 -1
- package/dist/cli.mjs +818 -320
- package/lib/error-origin.ts +67 -0
- package/lib/format-duration.ts +23 -9
- package/lib/install-check.ts +231 -0
- package/package.json +1 -3
- package/scripts/dev-hook.mjs +292 -0
- package/scripts/install-diagnosis.mjs +5 -8
- package/scripts/install-telemetry.mjs +12 -4
- package/scripts/translate-docs/cli.ts +53 -1
- package/scripts/translate-docs/mdx-translator.ts +158 -18
- package/scripts/translate-docs/readme-translator.ts +36 -18
- package/scripts/translate-docs/translator.ts +180 -9
- package/scripts/translate-docs/types.ts +6 -0
- package/scripts/translate-docs/validate-translation.ts +132 -0
- package/scripts/validate-mdx.ts +92 -15
- package/src/audit/cli.ts +53 -15
- package/src/auth/cli.ts +14 -5
- package/src/hooks/builtin-policies.ts +168 -50
- package/src/hooks/configure-wizard.ts +238 -22
- package/src/hooks/custom-hooks-loader.ts +70 -4
- package/src/hooks/handler.ts +4 -1
- package/src/hooks/policy-types.ts +8 -0
- package/src/hooks/tui.ts +96 -29
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ge8e7w._.js +0 -3
- package/.next/standalone/.next/static/chunks/0405htbxay9vd.js +0 -1
- package/.next/standalone/.next/static/chunks/2m_tbl39fcedn.js +0 -1
- package/.next/standalone/.next/static/chunks/2o3ql0n5owqsw.js +0 -1
- package/.next/standalone/.next/static/chunks/35-90m9py64d4.js +0 -1
- package/.next/standalone/.next/static/chunks/3r--yyjkp9_7b.css +0 -2
- package/scripts/postinstall.mjs +0 -242
- package/scripts/preuninstall.mjs +0 -131
- /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → YKxI22hC-F_nHp7MEKfb1}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → YKxI22hC-F_nHp7MEKfb1}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → YKxI22hC-F_nHp7MEKfb1}/_ssgManifest.js +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -19,7 +19,7 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
19
19
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
20
20
|
|
|
21
21
|
// package.json
|
|
22
|
-
var version2 = "0.0.14-beta.
|
|
22
|
+
var version2 = "0.0.14-beta.2";
|
|
23
23
|
var init_package = () => {};
|
|
24
24
|
|
|
25
25
|
// src/posthog-key.ts
|
|
@@ -727,6 +727,22 @@ function readMergedHooksConfig(cwd) {
|
|
|
727
727
|
...llm !== undefined ? { llm } : {}
|
|
728
728
|
};
|
|
729
729
|
}
|
|
730
|
+
function getConfigPath() {
|
|
731
|
+
return resolve(homedir2(), ".failproofai", "policies-config.json");
|
|
732
|
+
}
|
|
733
|
+
function readHooksConfig() {
|
|
734
|
+
const configPath = getConfigPath();
|
|
735
|
+
if (!existsSync2(configPath)) {
|
|
736
|
+
return { enabledPolicies: [] };
|
|
737
|
+
}
|
|
738
|
+
try {
|
|
739
|
+
const raw = readFileSync(configPath, "utf8");
|
|
740
|
+
return JSON.parse(raw);
|
|
741
|
+
} catch (err) {
|
|
742
|
+
hookLogWarn(`failed to parse config at ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
743
|
+
return { enabledPolicies: [] };
|
|
744
|
+
}
|
|
745
|
+
}
|
|
730
746
|
function getConfigPathForScope(scope, cwd) {
|
|
731
747
|
switch (scope) {
|
|
732
748
|
case "user":
|
|
@@ -1178,28 +1194,73 @@ function blockPushMaster(ctx) {
|
|
|
1178
1194
|
}
|
|
1179
1195
|
return allow();
|
|
1180
1196
|
}
|
|
1181
|
-
function
|
|
1182
|
-
|
|
1197
|
+
function expandHomePrefix(path2) {
|
|
1198
|
+
const m = path2.match(/^(?:~|\$HOME|\$\{HOME\})(?=$|\/)/);
|
|
1199
|
+
return m ? homedir3() + path2.slice(m[0].length) : path2;
|
|
1200
|
+
}
|
|
1201
|
+
function stripTrailingGlob(path2) {
|
|
1202
|
+
return path2.replace(/\/\*$/, "").replace(/\/+$/, "");
|
|
1203
|
+
}
|
|
1204
|
+
function isCatastrophicTarget(token) {
|
|
1205
|
+
const raw = token.replace(/^['"]|['"]$/g, "");
|
|
1206
|
+
if (raw === "")
|
|
1183
1207
|
return false;
|
|
1184
|
-
const
|
|
1185
|
-
if (
|
|
1208
|
+
const homePrefix = raw.match(HOME_PREFIX_RE);
|
|
1209
|
+
if (!homePrefix && /^[$`]/.test(raw))
|
|
1210
|
+
return true;
|
|
1211
|
+
const belowRoot = homePrefix ? raw.slice(homePrefix[0].length) : raw.startsWith("/") ? raw : null;
|
|
1212
|
+
if (belowRoot === null)
|
|
1186
1213
|
return false;
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1214
|
+
const segments = stripTrailingGlob(belowRoot).split("/").filter(Boolean);
|
|
1215
|
+
if (!homePrefix && SCRATCH_ROOTS.some((r) => `/${segments.join("/")}`.startsWith(`${r}/`)))
|
|
1216
|
+
return false;
|
|
1217
|
+
return segments.length <= CATASTROPHIC_DEPTH;
|
|
1218
|
+
}
|
|
1219
|
+
function recursiveDeletionTargets(seg) {
|
|
1220
|
+
const tokens = parseArgvTokens(seg);
|
|
1221
|
+
const findIdx = tokens.findIndex((t) => FIND_CMD_RE.test(t));
|
|
1222
|
+
if (findIdx >= 0) {
|
|
1223
|
+
const expr = tokens.slice(findIdx + 1);
|
|
1224
|
+
const execIdx = expr.findIndex((t) => FIND_EXEC_RE.test(t));
|
|
1225
|
+
const deletes = expr.includes("-delete") || execIdx >= 0 && RM_CMD_RE.test(expr[execIdx + 1] ?? "");
|
|
1226
|
+
if (deletes) {
|
|
1227
|
+
let start = 0;
|
|
1228
|
+
while (start < expr.length && FIND_GLOBAL_OPT_RE.test(expr[start])) {
|
|
1229
|
+
start += expr[start] === "-D" ? 2 : 1;
|
|
1230
|
+
}
|
|
1231
|
+
const rest = expr.slice(start);
|
|
1232
|
+
const end = rest.findIndex((t) => FIND_EXPR_START_RE.test(t));
|
|
1233
|
+
return end < 0 ? rest : rest.slice(0, end);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
const rmIdx = tokens.findIndex((t) => RM_CMD_RE.test(t));
|
|
1237
|
+
if (rmIdx >= 0) {
|
|
1238
|
+
const args = tokens.slice(rmIdx + 1);
|
|
1239
|
+
const shortFlags = args.filter((t) => /^-[^-]/.test(t)).join("");
|
|
1240
|
+
const longFlags = args.filter((t) => /^--/.test(t));
|
|
1241
|
+
const recursive = /r/i.test(shortFlags) || longFlags.some((f) => /^--recursive$/i.test(f));
|
|
1242
|
+
const force = /f/.test(shortFlags) || longFlags.some((f) => /^--force$/i.test(f));
|
|
1243
|
+
if (recursive && force)
|
|
1244
|
+
return args.filter((t) => !t.startsWith("-"));
|
|
1245
|
+
}
|
|
1246
|
+
return null;
|
|
1247
|
+
}
|
|
1248
|
+
function shellSegments(cmd) {
|
|
1249
|
+
return cmd.split(/&&|\|\||[|;\n]/).map((s) => s.trim()).filter((s) => s !== "");
|
|
1250
|
+
}
|
|
1251
|
+
function deletionTargetIsAllowed(cmd, allowPaths) {
|
|
1252
|
+
if (allowPaths.length === 0)
|
|
1253
|
+
return false;
|
|
1254
|
+
const normalizedAllowPaths = allowPaths.map((p) => stripTrailingGlob(expandHomePrefix(p)) || "/");
|
|
1255
|
+
let sawRecursiveDelete = false;
|
|
1256
|
+
for (const seg of shellSegments(cmd)) {
|
|
1257
|
+
const targets = recursiveDeletionTargets(seg);
|
|
1258
|
+
if (targets === null)
|
|
1195
1259
|
continue;
|
|
1196
|
-
|
|
1197
|
-
for (const target of
|
|
1198
|
-
const normalized =
|
|
1199
|
-
const covered =
|
|
1200
|
-
const np = p.replace(/\/+$/, "") || "/";
|
|
1201
|
-
return normalized === np || normalized.startsWith(np + "/");
|
|
1202
|
-
});
|
|
1260
|
+
sawRecursiveDelete = true;
|
|
1261
|
+
for (const target of targets) {
|
|
1262
|
+
const normalized = stripTrailingGlob(expandHomePrefix(target)) || "/";
|
|
1263
|
+
const covered = normalizedAllowPaths.some((np) => normalized === np || normalized.startsWith(np + "/"));
|
|
1203
1264
|
if (!covered) {
|
|
1204
1265
|
const segCovered = allowPaths.some((p) => {
|
|
1205
1266
|
const escaped = p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -1210,35 +1271,22 @@ function rmTargetIsAllowed(cmd, allowPaths) {
|
|
|
1210
1271
|
}
|
|
1211
1272
|
}
|
|
1212
1273
|
}
|
|
1213
|
-
return
|
|
1274
|
+
return sawRecursiveDelete;
|
|
1214
1275
|
}
|
|
1215
1276
|
function blockRmRf(ctx) {
|
|
1216
1277
|
if (ctx.toolName !== "Bash")
|
|
1217
1278
|
return allow();
|
|
1218
1279
|
const cmd = getCommand(ctx);
|
|
1219
|
-
const
|
|
1220
|
-
const
|
|
1221
|
-
return
|
|
1280
|
+
const hasCatastrophicTarget = shellSegments(cmd).some((seg) => {
|
|
1281
|
+
const targets = recursiveDeletionTargets(seg);
|
|
1282
|
+
return targets !== null && targets.some(isCatastrophicTarget);
|
|
1222
1283
|
});
|
|
1223
|
-
if (
|
|
1284
|
+
if (hasCatastrophicTarget) {
|
|
1224
1285
|
const allowPaths = ctx.params?.allowPaths ?? [];
|
|
1225
|
-
if (
|
|
1286
|
+
if (deletionTargetIsAllowed(cmd, allowPaths))
|
|
1226
1287
|
return allow();
|
|
1227
1288
|
return deny("Catastrophic deletion blocked");
|
|
1228
1289
|
}
|
|
1229
|
-
if (hasDestructivePath && /\brm\b/.test(cmd)) {
|
|
1230
|
-
const tokens = parseArgvTokens(cmd);
|
|
1231
|
-
const shortFlags = tokens.filter((t) => /^-[^-]/.test(t)).join("");
|
|
1232
|
-
const longFlags = tokens.filter((t) => /^--/.test(t));
|
|
1233
|
-
const hasRecursive = /r/i.test(shortFlags) || longFlags.some((f) => /^--recursive$/i.test(f));
|
|
1234
|
-
const hasForce = /f/.test(shortFlags) || longFlags.some((f) => /^--force$/i.test(f));
|
|
1235
|
-
if (hasRecursive && hasForce) {
|
|
1236
|
-
const allowPaths = ctx.params?.allowPaths ?? [];
|
|
1237
|
-
if (rmTargetIsAllowed(cmd, allowPaths))
|
|
1238
|
-
return allow();
|
|
1239
|
-
return deny("Catastrophic deletion blocked");
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
1290
|
if (/Remove-Item\s+.*-Recurse.*-Force.*(?:[A-Z]:\\(?:\s|$)|\\\*)/i.test(cmd)) {
|
|
1243
1291
|
return deny("Catastrophic deletion blocked");
|
|
1244
1292
|
}
|
|
@@ -1250,12 +1298,31 @@ function blockRmRf(ctx) {
|
|
|
1250
1298
|
function blockForcePush(ctx) {
|
|
1251
1299
|
if (ctx.toolName !== "Bash")
|
|
1252
1300
|
return allow();
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1301
|
+
for (const segment of extractGitPushArgs(getCommand(ctx))) {
|
|
1302
|
+
let sawEndOfOptions = false;
|
|
1303
|
+
for (const token of segment.split(/\s+/)) {
|
|
1304
|
+
if (token === "--") {
|
|
1305
|
+
sawEndOfOptions = true;
|
|
1306
|
+
continue;
|
|
1307
|
+
}
|
|
1308
|
+
if (sawEndOfOptions)
|
|
1309
|
+
continue;
|
|
1310
|
+
if (isForcePushFlag(token)) {
|
|
1311
|
+
return deny("Force-pushing is blocked");
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1256
1314
|
}
|
|
1257
1315
|
return allow();
|
|
1258
1316
|
}
|
|
1317
|
+
function isForcePushFlag(token) {
|
|
1318
|
+
if (token === "--force")
|
|
1319
|
+
return true;
|
|
1320
|
+
if (SAFE_FORCE_PREFIXES.some((prefix) => token.startsWith(prefix)))
|
|
1321
|
+
return false;
|
|
1322
|
+
if (token.startsWith("--force"))
|
|
1323
|
+
return true;
|
|
1324
|
+
return SHORT_FLAG_BUNDLE_RE.test(token);
|
|
1325
|
+
}
|
|
1259
1326
|
function blockSecretsWrite(ctx) {
|
|
1260
1327
|
if (ctx.toolName !== "Write")
|
|
1261
1328
|
return allow();
|
|
@@ -1836,7 +1903,7 @@ function registerBuiltinPolicies(enabledNames) {
|
|
|
1836
1903
|
}
|
|
1837
1904
|
}
|
|
1838
1905
|
}
|
|
1839
|
-
var isClaudeInternalPath, isClaudeSettingsFile, SHELL_OPERATORS, SHELL_METACHAR_RE, JWT_RE, API_KEY_PATTERNS, CONNECTION_STRING_RE, PRIVATE_KEY_RE, BEARER_TOKEN_RE, SQL_TOOL_RE, DESTRUCTIVE_SQL_RE, DELETE_NO_WHERE_RE, SQL_WHERE_RE, SCHEMA_ALTER_RE, PUBLISH_CMD_RE, ENV_PRINTENV_RE, ECHO_ENV_RE, EXPORT_RE, PS_ENV_VAR_RE, PS_CHILDITEM_ENV_RE, DOTNET_GETENV_RE, CMD_ECHO_ENV_RE, ENV_FILE_PATH_RE, ENV_CMD_RE, SUDO_RE, PS_ELEVATION_RE, RUNAS_RE, CURL_PIPE_SH_RE, PS_WEB_PIPE_RE,
|
|
1906
|
+
var isClaudeInternalPath, isClaudeSettingsFile, SHELL_OPERATORS, SHELL_METACHAR_RE, JWT_RE, API_KEY_PATTERNS, CONNECTION_STRING_RE, PRIVATE_KEY_RE, BEARER_TOKEN_RE, SQL_TOOL_RE, DESTRUCTIVE_SQL_RE, DELETE_NO_WHERE_RE, SQL_WHERE_RE, SCHEMA_ALTER_RE, PUBLISH_CMD_RE, ENV_PRINTENV_RE, ECHO_ENV_RE, EXPORT_RE, PS_ENV_VAR_RE, PS_CHILDITEM_ENV_RE, DOTNET_GETENV_RE, CMD_ECHO_ENV_RE, ENV_FILE_PATH_RE, ENV_CMD_RE, SUDO_RE, PS_ELEVATION_RE, RUNAS_RE, CURL_PIPE_SH_RE, PS_WEB_PIPE_RE, SHORT_FLAG_BUNDLE_RE, SAFE_FORCE_PREFIXES, SECRET_FILE_RE, SECRET_FILE_ID_RSA_RE, SECRET_FILE_CREDENTIALS_RE, GIT_COMMIT_MERGE_RE, FAILPROOFAI_CLI_RE, FAILPROOFAI_UNINSTALL_RE, GIT_AMEND_RE, GIT_STASH_DROP_RE, GIT_ADD_ALL_RE, NPM_GLOBAL_RE, YARN_GLOBAL_RE, PNPM_GLOBAL_RE, BUN_GLOBAL_RE, CARGO_INSTALL_RE, PIP_SYSTEM_RE, PKG_MANAGER_DETECTORS, NOHUP_RE, SCREEN_DETACH_RE, TMUX_DETACH_RE, DISOWN_RE, BACKGROUND_AMPERSAND_RE, KUBECTL_RE, TERRAFORM_RE, AWS_CLI_RE, GCLOUD_RE, AZ_CLI_RE, HELM_RE, GH_PIPELINE_RE, gitBranchCache, HOME_PREFIX_RE, RM_CMD_RE, FIND_CMD_RE, FIND_EXEC_RE, FIND_GLOBAL_OPT_RE, FIND_EXPR_START_RE, SCRATCH_ROOTS, CATASTROPHIC_DEPTH = 2, READ_LIKE_CMDS, TOOL_CALL_TRACKER_MAX_BYTES = 65536, SEGMENT_SPLIT_RE, BUILTIN_POLICIES;
|
|
1840
1907
|
var init_builtin_policies = __esm(() => {
|
|
1841
1908
|
init_hook_logger();
|
|
1842
1909
|
isClaudeInternalPath = isAgentInternalPath;
|
|
@@ -1878,7 +1945,8 @@ var init_builtin_policies = __esm(() => {
|
|
|
1878
1945
|
RUNAS_RE = /(?:^|;|&&|\|\|)\s*runas\s/i;
|
|
1879
1946
|
CURL_PIPE_SH_RE = /(?:curl|wget)\s.*\|\s*(?:sh|bash|zsh|dash|ksh|csh|tcsh|fish|ash)\b/;
|
|
1880
1947
|
PS_WEB_PIPE_RE = /(?:Invoke-WebRequest|iwr|Invoke-RestMethod|irm)\s+.*\|\s*(?:Invoke-Expression|iex)/i;
|
|
1881
|
-
|
|
1948
|
+
SHORT_FLAG_BUNDLE_RE = /^-[a-zA-Z]*f[a-zA-Z]*$/;
|
|
1949
|
+
SAFE_FORCE_PREFIXES = ["--force-with-lease", "--force-if-includes"];
|
|
1882
1950
|
SECRET_FILE_RE = /\.(?:pem|key)$/;
|
|
1883
1951
|
SECRET_FILE_ID_RSA_RE = /id_rsa/;
|
|
1884
1952
|
SECRET_FILE_CREDENTIALS_RE = /credentials/;
|
|
@@ -1919,6 +1987,13 @@ var init_builtin_policies = __esm(() => {
|
|
|
1919
1987
|
HELM_RE = /(?:^|[;\n]|&&|\|\|?|&)\s*helm(?:\s|$)/;
|
|
1920
1988
|
GH_PIPELINE_RE = /(?:^|[;\n]|&&|\|\|?|&)\s*gh\s+(?:workflow\s+(?:run|enable|disable)|run\s+(?:rerun|cancel)|pr\s+merge|release\s+(?:create|delete)|cache\s+delete|secret\s+(?:set|delete))\b/;
|
|
1921
1989
|
gitBranchCache = new Map;
|
|
1990
|
+
HOME_PREFIX_RE = /^(?:~[A-Za-z0-9_.-]*|\$HOME|\$\{HOME\})(?=$|\/)/;
|
|
1991
|
+
RM_CMD_RE = /^(?:\/\S*\/)?rm$/;
|
|
1992
|
+
FIND_CMD_RE = /^(?:\/\S*\/)?find$/;
|
|
1993
|
+
FIND_EXEC_RE = /^-(?:exec|execdir|ok|okdir)$/;
|
|
1994
|
+
FIND_GLOBAL_OPT_RE = /^-(?:[HLP]|D|O\d*)$/;
|
|
1995
|
+
FIND_EXPR_START_RE = /^(?:-|\\?[(!])/;
|
|
1996
|
+
SCRATCH_ROOTS = ["/tmp", "/var/tmp"];
|
|
1922
1997
|
READ_LIKE_CMDS = /(?:^|;|&&|\|\||\|)\s*(?:ls|find|cat|head|tail|less|more|wc|file|stat|tree|du)\s/;
|
|
1923
1998
|
SEGMENT_SPLIT_RE = /\s*(?:&&|\|\||\||;)\s*/;
|
|
1924
1999
|
BUILTIN_POLICIES = [
|
|
@@ -3435,6 +3510,15 @@ function discoverPolicyFiles(dir) {
|
|
|
3435
3510
|
return [];
|
|
3436
3511
|
}
|
|
3437
3512
|
}
|
|
3513
|
+
function findSkippedPolicyFiles(dir) {
|
|
3514
|
+
if (!existsSync3(dir))
|
|
3515
|
+
return [];
|
|
3516
|
+
try {
|
|
3517
|
+
return readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && LOADABLE_EXT_RE.test(e.name) && !CONVENTION_FILE_RE.test(e.name) && !e.name.endsWith(".d.ts")).map((e) => e.name).sort((a, b) => a.localeCompare(b));
|
|
3518
|
+
} catch {
|
|
3519
|
+
return [];
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3438
3522
|
async function loadSingleFile(absPath, opts) {
|
|
3439
3523
|
const g = globalThis;
|
|
3440
3524
|
g[LOADING_KEY] = true;
|
|
@@ -3477,10 +3561,18 @@ async function loadCustomHooks(customPoliciesPath, opts) {
|
|
|
3477
3561
|
await loadSingleFile(absPath, opts);
|
|
3478
3562
|
return getCustomHooks();
|
|
3479
3563
|
}
|
|
3564
|
+
function warnSkippedPolicyFiles(dir, scope) {
|
|
3565
|
+
const skipped = findSkippedPolicyFiles(dir);
|
|
3566
|
+
if (skipped.length === 0)
|
|
3567
|
+
return;
|
|
3568
|
+
const suggest = (n) => n.replace(/\.(js|mjs|ts)$/, "-policies.$1");
|
|
3569
|
+
hookLogWarn(`${scope} policies: ${skipped.length} file(s) in ${dir} are NOT loaded — ` + `the convention only loads names ending in "policies.js|mjs|ts". ` + skipped.map((n) => `${n} → rename to ${suggest(n)}`).join("; "));
|
|
3570
|
+
}
|
|
3480
3571
|
async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
3481
3572
|
clearCustomHooks();
|
|
3482
3573
|
const conventionSources = [];
|
|
3483
3574
|
const projectRoot = findProjectConfigDir(opts?.sessionCwd ?? process.cwd());
|
|
3575
|
+
const conventionEnabled = opts?.customPoliciesEnabled !== false;
|
|
3484
3576
|
if (customPoliciesPath) {
|
|
3485
3577
|
const absPath = isAbsolute(customPoliciesPath) ? customPoliciesPath : resolve4(projectRoot, customPoliciesPath);
|
|
3486
3578
|
if (existsSync3(absPath)) {
|
|
@@ -3491,7 +3583,9 @@ async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
|
3491
3583
|
}
|
|
3492
3584
|
const hooksBeforeConvention = getCustomHooks().length;
|
|
3493
3585
|
const projectDir = resolve4(projectRoot, ".failproofai", "policies");
|
|
3494
|
-
|
|
3586
|
+
if (conventionEnabled)
|
|
3587
|
+
warnSkippedPolicyFiles(projectDir, "project");
|
|
3588
|
+
const projectFiles = conventionEnabled ? discoverPolicyFiles(projectDir) : [];
|
|
3495
3589
|
for (const file of projectFiles) {
|
|
3496
3590
|
const hooksBefore = getCustomHooks().length;
|
|
3497
3591
|
await loadSingleFile(file, { conventionScope: "project" });
|
|
@@ -3505,7 +3599,9 @@ async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
|
3505
3599
|
}
|
|
3506
3600
|
}
|
|
3507
3601
|
const userDir = resolve4(homedir4(), ".failproofai", "policies");
|
|
3508
|
-
|
|
3602
|
+
if (conventionEnabled)
|
|
3603
|
+
warnSkippedPolicyFiles(userDir, "user");
|
|
3604
|
+
const userFiles = conventionEnabled ? discoverPolicyFiles(userDir) : [];
|
|
3509
3605
|
for (const file of userFiles) {
|
|
3510
3606
|
const hooksBefore = getCustomHooks().length;
|
|
3511
3607
|
await loadSingleFile(file, { conventionScope: "user" });
|
|
@@ -3520,7 +3616,9 @@ async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
|
3520
3616
|
}
|
|
3521
3617
|
const allHooks = getCustomHooks();
|
|
3522
3618
|
const conventionCount = allHooks.length - hooksBeforeConvention;
|
|
3523
|
-
if (
|
|
3619
|
+
if (!conventionEnabled) {
|
|
3620
|
+
hookLogInfo("convention policies: DISABLED via customPoliciesEnabled:false — " + "no .failproofai/policies/ files loaded");
|
|
3621
|
+
} else if (projectFiles.length > 0 || userFiles.length > 0) {
|
|
3524
3622
|
hookLogInfo(`convention policies: ${projectFiles.length} project file(s), ${userFiles.length} user file(s), ${conventionCount} hook(s)`);
|
|
3525
3623
|
}
|
|
3526
3624
|
const hookNameToScope = new Map;
|
|
@@ -3540,7 +3638,7 @@ async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
|
3540
3638
|
}
|
|
3541
3639
|
return { hooks: allHooks, conventionSources };
|
|
3542
3640
|
}
|
|
3543
|
-
var LOADING_KEY = "__FAILPROOFAI_LOADING_HOOKS__", CONVENTION_FILE_RE;
|
|
3641
|
+
var LOADING_KEY = "__FAILPROOFAI_LOADING_HOOKS__", CONVENTION_FILE_RE, LOADABLE_EXT_RE;
|
|
3544
3642
|
var init_custom_hooks_loader = __esm(() => {
|
|
3545
3643
|
init_hook_logger();
|
|
3546
3644
|
init_custom_hooks_registry();
|
|
@@ -3549,6 +3647,7 @@ var init_custom_hooks_loader = __esm(() => {
|
|
|
3549
3647
|
init_hook_telemetry2();
|
|
3550
3648
|
init_telemetry_id2();
|
|
3551
3649
|
CONVENTION_FILE_RE = /policies\.(js|mjs|ts)$/;
|
|
3650
|
+
LOADABLE_EXT_RE = /\.(js|mjs|ts)$/;
|
|
3552
3651
|
});
|
|
3553
3652
|
|
|
3554
3653
|
// src/hooks/hook-activity-store.ts
|
|
@@ -4761,17 +4860,20 @@ var init_sqlite_reader = () => {};
|
|
|
4761
4860
|
function formatDuration(ms) {
|
|
4762
4861
|
if (ms < 1000)
|
|
4763
4862
|
return `${ms}ms`;
|
|
4764
|
-
const
|
|
4765
|
-
if (
|
|
4766
|
-
return `${
|
|
4767
|
-
const totalMinutes = Math.floor(seconds / 60);
|
|
4768
|
-
if (totalMinutes >= 60) {
|
|
4769
|
-
const hours = Math.floor(totalMinutes / 60);
|
|
4770
|
-
const remainingMinutes = totalMinutes % 60;
|
|
4771
|
-
return `${hours}h ${remainingMinutes}m`;
|
|
4863
|
+
const deciseconds = Math.round(ms / 100);
|
|
4864
|
+
if (deciseconds < 600) {
|
|
4865
|
+
return `${(deciseconds / 10).toFixed(1)}s`;
|
|
4772
4866
|
}
|
|
4773
|
-
const
|
|
4774
|
-
|
|
4867
|
+
const totalSeconds = Math.round(ms / 1000);
|
|
4868
|
+
if (totalSeconds < 3600) {
|
|
4869
|
+
const minutes2 = Math.floor(totalSeconds / 60);
|
|
4870
|
+
const seconds = totalSeconds % 60;
|
|
4871
|
+
return `${minutes2}m ${seconds}s`;
|
|
4872
|
+
}
|
|
4873
|
+
const totalMinutes = Math.round(ms / 60000);
|
|
4874
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
4875
|
+
const minutes = totalMinutes % 60;
|
|
4876
|
+
return `${hours}h ${minutes}m`;
|
|
4775
4877
|
}
|
|
4776
4878
|
|
|
4777
4879
|
// lib/hermes-sessions.ts
|
|
@@ -8191,7 +8293,10 @@ async function handleHookEvent(eventType, cli = "claude") {
|
|
|
8191
8293
|
const config = readMergedHooksConfig(session.cwd);
|
|
8192
8294
|
clearPolicies();
|
|
8193
8295
|
registerBuiltinPolicies(config.enabledPolicies);
|
|
8194
|
-
const loadResult = await loadAllCustomHooks(config.customPoliciesPath, {
|
|
8296
|
+
const loadResult = await loadAllCustomHooks(config.customPoliciesPath, {
|
|
8297
|
+
sessionCwd: session.cwd,
|
|
8298
|
+
customPoliciesEnabled: config.customPoliciesEnabled
|
|
8299
|
+
});
|
|
8195
8300
|
const customHooksList = loadResult.hooks;
|
|
8196
8301
|
const conventionHookNames = new Set(loadResult.conventionSources.flatMap((s) => s.hookNames));
|
|
8197
8302
|
for (const hook of customHooksList) {
|
|
@@ -8314,6 +8419,242 @@ var init_handler = __esm(() => {
|
|
|
8314
8419
|
init_hook_logger();
|
|
8315
8420
|
});
|
|
8316
8421
|
|
|
8422
|
+
// scripts/install-telemetry.mjs
|
|
8423
|
+
import { createHmac, randomUUID } from "node:crypto";
|
|
8424
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
8425
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5 } from "node:fs";
|
|
8426
|
+
import { homedir as homedir21, platform, arch, hostname, cpus } from "node:os";
|
|
8427
|
+
import { join as join24 } from "node:path";
|
|
8428
|
+
function hashToId3(raw) {
|
|
8429
|
+
return createHmac("sha256", NAMESPACE3).update(raw).digest("hex");
|
|
8430
|
+
}
|
|
8431
|
+
function getInstanceId3() {
|
|
8432
|
+
const idDir = join24(homedir21(), ".failproofai");
|
|
8433
|
+
const idFile = join24(idDir, "instance-id");
|
|
8434
|
+
try {
|
|
8435
|
+
const existing = readFileSync10(idFile, "utf-8").trim();
|
|
8436
|
+
if (existing)
|
|
8437
|
+
return existing;
|
|
8438
|
+
} catch {}
|
|
8439
|
+
try {
|
|
8440
|
+
const p = platform();
|
|
8441
|
+
if (p === "linux") {
|
|
8442
|
+
for (const machineIdPath of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
8443
|
+
try {
|
|
8444
|
+
const id2 = readFileSync10(machineIdPath, "utf-8").trim();
|
|
8445
|
+
if (id2)
|
|
8446
|
+
return hashToId3(id2);
|
|
8447
|
+
} catch {}
|
|
8448
|
+
}
|
|
8449
|
+
} else if (p === "darwin") {
|
|
8450
|
+
const out = execSync4("ioreg -rd1 -c IOPlatformExpertDevice", {
|
|
8451
|
+
encoding: "utf-8",
|
|
8452
|
+
timeout: 3000
|
|
8453
|
+
});
|
|
8454
|
+
const m = out.match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/);
|
|
8455
|
+
if (m?.[1])
|
|
8456
|
+
return hashToId3(m[1]);
|
|
8457
|
+
} else if (p === "win32") {
|
|
8458
|
+
const out = execSync4('reg query "HKLM\\SOFTWARE\\Microsoft\\Cryptography" /v MachineGuid', { encoding: "utf-8", timeout: 3000 });
|
|
8459
|
+
const m = out.match(/MachineGuid\s+REG_SZ\s+(\S+)/);
|
|
8460
|
+
if (m?.[1])
|
|
8461
|
+
return hashToId3(m[1]);
|
|
8462
|
+
}
|
|
8463
|
+
} catch {}
|
|
8464
|
+
try {
|
|
8465
|
+
const sysProps = [
|
|
8466
|
+
hostname(),
|
|
8467
|
+
homedir21(),
|
|
8468
|
+
platform(),
|
|
8469
|
+
arch(),
|
|
8470
|
+
cpus()[0]?.model ?? ""
|
|
8471
|
+
].join(":");
|
|
8472
|
+
return hashToId3(sysProps);
|
|
8473
|
+
} catch {}
|
|
8474
|
+
const id = randomUUID();
|
|
8475
|
+
try {
|
|
8476
|
+
mkdirSync5(idDir, { recursive: true });
|
|
8477
|
+
writeFileSync4(idFile, id, "utf-8");
|
|
8478
|
+
} catch {}
|
|
8479
|
+
return id;
|
|
8480
|
+
}
|
|
8481
|
+
async function trackInstallEvent(event, properties = {}, opts = {}) {
|
|
8482
|
+
if (process.env.FAILPROOFAI_TELEMETRY_DISABLED === "1")
|
|
8483
|
+
return;
|
|
8484
|
+
const version3 = opts.version ?? process.env.npm_package_version ?? "unknown";
|
|
8485
|
+
const body = JSON.stringify({
|
|
8486
|
+
api_key: process.env.FAILPROOFAI_POSTHOG_KEY ?? API_KEY3,
|
|
8487
|
+
event,
|
|
8488
|
+
distinct_id: getInstanceId3(),
|
|
8489
|
+
properties: {
|
|
8490
|
+
...properties,
|
|
8491
|
+
$lib: "failproofai-install",
|
|
8492
|
+
failproofai_version: version3,
|
|
8493
|
+
product: PRODUCT
|
|
8494
|
+
}
|
|
8495
|
+
});
|
|
8496
|
+
await fetch(process.env.FAILPROOFAI_POSTHOG_HOST ? `${process.env.FAILPROOFAI_POSTHOG_HOST}/capture/` : CAPTURE_URL3, {
|
|
8497
|
+
method: "POST",
|
|
8498
|
+
headers: { "Content-Type": "application/json" },
|
|
8499
|
+
body,
|
|
8500
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? 5000)
|
|
8501
|
+
});
|
|
8502
|
+
}
|
|
8503
|
+
var NAMESPACE3 = "failproofai-telemetry-v1", API_KEY3 = "phc_Ac1Ww1GqKc0z1SyrRWbmatEeQdlOQIsDEEdP8l8JRgX", CAPTURE_URL3 = "https://us.i.posthog.com/capture/", PRODUCT = "failproofai-oss";
|
|
8504
|
+
var init_install_telemetry = () => {};
|
|
8505
|
+
|
|
8506
|
+
// lib/install-check.ts
|
|
8507
|
+
var exports_install_check = {};
|
|
8508
|
+
__export(exports_install_check, {
|
|
8509
|
+
maybeReportInstall: () => maybeReportInstall,
|
|
8510
|
+
compareSemver: () => compareSemver,
|
|
8511
|
+
checkHooks: () => checkHooks
|
|
8512
|
+
});
|
|
8513
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6 } from "node:fs";
|
|
8514
|
+
import { resolve as resolve9 } from "node:path";
|
|
8515
|
+
import { platform as platform2, arch as arch2, release, homedir as homedir22, hostname as hostname2 } from "node:os";
|
|
8516
|
+
import { createHmac as createHmac2 } from "node:crypto";
|
|
8517
|
+
function hashToId4(raw) {
|
|
8518
|
+
return createHmac2("sha256", NAMESPACE4).update(raw).digest("hex");
|
|
8519
|
+
}
|
|
8520
|
+
function lastVersionPath() {
|
|
8521
|
+
return resolve9(homedir22(), ".failproofai", "last-version");
|
|
8522
|
+
}
|
|
8523
|
+
function compareSemver(a, b) {
|
|
8524
|
+
const parse = (v) => {
|
|
8525
|
+
const m = /^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/.exec(v);
|
|
8526
|
+
if (!m)
|
|
8527
|
+
return null;
|
|
8528
|
+
return { nums: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] ?? null };
|
|
8529
|
+
};
|
|
8530
|
+
const pa = parse(a);
|
|
8531
|
+
const pb = parse(b);
|
|
8532
|
+
if (!pa || !pb)
|
|
8533
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
8534
|
+
for (let i = 0;i < 3; i++) {
|
|
8535
|
+
if (pa.nums[i] !== pb.nums[i])
|
|
8536
|
+
return pa.nums[i] < pb.nums[i] ? -1 : 1;
|
|
8537
|
+
}
|
|
8538
|
+
if (pa.pre === null && pb.pre === null)
|
|
8539
|
+
return 0;
|
|
8540
|
+
if (pa.pre === null)
|
|
8541
|
+
return 1;
|
|
8542
|
+
if (pb.pre === null)
|
|
8543
|
+
return -1;
|
|
8544
|
+
const ax = pa.pre.split(".");
|
|
8545
|
+
const bx = pb.pre.split(".");
|
|
8546
|
+
for (let i = 0;i < Math.max(ax.length, bx.length); i++) {
|
|
8547
|
+
const ai = ax[i], bi = bx[i];
|
|
8548
|
+
if (ai === undefined)
|
|
8549
|
+
return -1;
|
|
8550
|
+
if (bi === undefined)
|
|
8551
|
+
return 1;
|
|
8552
|
+
const aNum = /^\d+$/.test(ai), bNum = /^\d+$/.test(bi);
|
|
8553
|
+
if (aNum && bNum) {
|
|
8554
|
+
const d = Number(ai) - Number(bi);
|
|
8555
|
+
if (d !== 0)
|
|
8556
|
+
return d < 0 ? -1 : 1;
|
|
8557
|
+
} else if (aNum) {
|
|
8558
|
+
return -1;
|
|
8559
|
+
} else if (bNum) {
|
|
8560
|
+
return 1;
|
|
8561
|
+
} else if (ai !== bi) {
|
|
8562
|
+
return ai < bi ? -1 : 1;
|
|
8563
|
+
}
|
|
8564
|
+
}
|
|
8565
|
+
return 0;
|
|
8566
|
+
}
|
|
8567
|
+
function checkHooks() {
|
|
8568
|
+
const hooksConfigPath = resolve9(homedir22(), ".failproofai", "policies-config.json");
|
|
8569
|
+
if (!existsSync10(hooksConfigPath)) {
|
|
8570
|
+
return { configured: false, registered: false, policyCount: 0 };
|
|
8571
|
+
}
|
|
8572
|
+
let config;
|
|
8573
|
+
try {
|
|
8574
|
+
config = JSON.parse(readFileSync11(hooksConfigPath, "utf8"));
|
|
8575
|
+
} catch {
|
|
8576
|
+
return { configured: false, registered: false, policyCount: 0 };
|
|
8577
|
+
}
|
|
8578
|
+
if (!Array.isArray(config.enabledPolicies) || config.enabledPolicies.length === 0) {
|
|
8579
|
+
return { configured: false, registered: false, policyCount: 0 };
|
|
8580
|
+
}
|
|
8581
|
+
const policyCount = config.enabledPolicies.length;
|
|
8582
|
+
const settingsPath = resolve9(homedir22(), ".claude", "settings.json");
|
|
8583
|
+
if (!existsSync10(settingsPath))
|
|
8584
|
+
return { configured: true, registered: false, policyCount };
|
|
8585
|
+
let settings;
|
|
8586
|
+
try {
|
|
8587
|
+
settings = JSON.parse(readFileSync11(settingsPath, "utf8"));
|
|
8588
|
+
} catch {
|
|
8589
|
+
return { configured: true, registered: false, policyCount };
|
|
8590
|
+
}
|
|
8591
|
+
if (!settings?.hooks)
|
|
8592
|
+
return { configured: true, registered: false, policyCount };
|
|
8593
|
+
for (const matchers of Object.values(settings.hooks)) {
|
|
8594
|
+
if (!Array.isArray(matchers))
|
|
8595
|
+
continue;
|
|
8596
|
+
for (const matcher of matchers) {
|
|
8597
|
+
if (!matcher?.hooks)
|
|
8598
|
+
continue;
|
|
8599
|
+
if (matcher.hooks.some((h) => h[FAILPROOFAI_HOOK_MARKER2] === true)) {
|
|
8600
|
+
return { configured: true, registered: true, policyCount };
|
|
8601
|
+
}
|
|
8602
|
+
}
|
|
8603
|
+
}
|
|
8604
|
+
return { configured: true, registered: false, policyCount };
|
|
8605
|
+
}
|
|
8606
|
+
async function maybeReportInstall(version3) {
|
|
8607
|
+
try {
|
|
8608
|
+
const versionFile = lastVersionPath();
|
|
8609
|
+
let previousVersion = null;
|
|
8610
|
+
try {
|
|
8611
|
+
if (existsSync10(versionFile)) {
|
|
8612
|
+
previousVersion = readFileSync11(versionFile, "utf8").trim() || null;
|
|
8613
|
+
}
|
|
8614
|
+
} catch {}
|
|
8615
|
+
if (previousVersion === version3)
|
|
8616
|
+
return;
|
|
8617
|
+
const hooks = checkHooks();
|
|
8618
|
+
const events = [];
|
|
8619
|
+
if (previousVersion === null) {
|
|
8620
|
+
events.push(trackInstallEvent("first_install", {
|
|
8621
|
+
platform: platform2(),
|
|
8622
|
+
arch: arch2(),
|
|
8623
|
+
os_release: release(),
|
|
8624
|
+
node_version: process.versions.node
|
|
8625
|
+
}, { version: version3, timeoutMs: REPORT_TIMEOUT_MS }));
|
|
8626
|
+
} else {
|
|
8627
|
+
const cmp = compareSemver(previousVersion, version3);
|
|
8628
|
+
events.push(trackInstallEvent("version_changed", {
|
|
8629
|
+
from_version: previousVersion,
|
|
8630
|
+
to_version: version3,
|
|
8631
|
+
direction: cmp < 0 ? "upgrade" : "downgrade",
|
|
8632
|
+
platform: platform2(),
|
|
8633
|
+
arch: arch2()
|
|
8634
|
+
}, { version: version3, timeoutMs: REPORT_TIMEOUT_MS }));
|
|
8635
|
+
}
|
|
8636
|
+
events.push(trackInstallEvent("package_installed", {
|
|
8637
|
+
platform: platform2(),
|
|
8638
|
+
arch: arch2(),
|
|
8639
|
+
os_release: release(),
|
|
8640
|
+
node_version: process.versions.node,
|
|
8641
|
+
hostname_hash: hashToId4(hostname2()),
|
|
8642
|
+
hooks_configured: hooks.configured,
|
|
8643
|
+
hooks_registered: hooks.registered,
|
|
8644
|
+
enabled_policy_count: hooks.policyCount
|
|
8645
|
+
}, { version: version3, timeoutMs: REPORT_TIMEOUT_MS }));
|
|
8646
|
+
try {
|
|
8647
|
+
mkdirSync6(resolve9(homedir22(), ".failproofai"), { recursive: true });
|
|
8648
|
+
writeFileSync5(versionFile, version3, "utf8");
|
|
8649
|
+
} catch {}
|
|
8650
|
+
await Promise.all(events.map((p) => p.catch(() => {})));
|
|
8651
|
+
} catch {}
|
|
8652
|
+
}
|
|
8653
|
+
var FAILPROOFAI_HOOK_MARKER2 = "__failproofai_hook__", NAMESPACE4 = "failproofai-telemetry-v1", REPORT_TIMEOUT_MS = 5000;
|
|
8654
|
+
var init_install_check = __esm(() => {
|
|
8655
|
+
init_install_telemetry();
|
|
8656
|
+
});
|
|
8657
|
+
|
|
8317
8658
|
// node_modules/yaml/dist/nodes/identity.js
|
|
8318
8659
|
var require_identity = __commonJS((exports) => {
|
|
8319
8660
|
var ALIAS = Symbol.for("yaml.alias");
|
|
@@ -15305,32 +15646,32 @@ var init_dist = __esm(() => {
|
|
|
15305
15646
|
});
|
|
15306
15647
|
|
|
15307
15648
|
// src/hooks/integrations.ts
|
|
15308
|
-
import { execSync as
|
|
15309
|
-
import { readFileSync as
|
|
15310
|
-
import { resolve as
|
|
15649
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
15650
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync6, existsSync as existsSync11, mkdirSync as mkdirSync7, unlinkSync as unlinkSync2 } from "node:fs";
|
|
15651
|
+
import { resolve as resolve10, dirname as dirname4 } from "node:path";
|
|
15311
15652
|
import { fileURLToPath } from "node:url";
|
|
15312
|
-
import { homedir as
|
|
15653
|
+
import { homedir as homedir23 } from "node:os";
|
|
15313
15654
|
function readJsonFile(path3) {
|
|
15314
|
-
if (!
|
|
15655
|
+
if (!existsSync11(path3))
|
|
15315
15656
|
return {};
|
|
15316
|
-
const raw =
|
|
15657
|
+
const raw = readFileSync12(path3, "utf8");
|
|
15317
15658
|
return JSON.parse(raw);
|
|
15318
15659
|
}
|
|
15319
15660
|
function writeJsonFile(path3, data) {
|
|
15320
|
-
|
|
15321
|
-
|
|
15661
|
+
mkdirSync7(dirname4(path3), { recursive: true });
|
|
15662
|
+
writeFileSync6(path3, JSON.stringify(data, null, 2) + `
|
|
15322
15663
|
`, "utf8");
|
|
15323
15664
|
}
|
|
15324
15665
|
function readYamlDoc(path3) {
|
|
15325
15666
|
try {
|
|
15326
|
-
return
|
|
15667
|
+
return existsSync11(path3) ? $parseDocument(readFileSync12(path3, "utf8")) : $parseDocument("");
|
|
15327
15668
|
} catch {
|
|
15328
15669
|
return $parseDocument("");
|
|
15329
15670
|
}
|
|
15330
15671
|
}
|
|
15331
15672
|
function writeYamlDoc(path3, doc) {
|
|
15332
|
-
|
|
15333
|
-
|
|
15673
|
+
mkdirSync7(dirname4(path3), { recursive: true });
|
|
15674
|
+
writeFileSync6(path3, doc.toString(), "utf8");
|
|
15334
15675
|
}
|
|
15335
15676
|
function isMarkedHook(hook) {
|
|
15336
15677
|
if (!hook || typeof hook !== "object")
|
|
@@ -15351,7 +15692,7 @@ function stripLegacyVersion(settings) {
|
|
|
15351
15692
|
function binaryExists(name) {
|
|
15352
15693
|
try {
|
|
15353
15694
|
const cmd = process.platform === "win32" ? `where ${name}` : `which ${name}`;
|
|
15354
|
-
|
|
15695
|
+
execSync5(cmd, { encoding: "utf8", stdio: "pipe" });
|
|
15355
15696
|
return true;
|
|
15356
15697
|
} catch {
|
|
15357
15698
|
return false;
|
|
@@ -15369,7 +15710,7 @@ function isMarkedCopilotHook(hook) {
|
|
|
15369
15710
|
return false;
|
|
15370
15711
|
}
|
|
15371
15712
|
function opencodePluginFilePath(settingsPath) {
|
|
15372
|
-
return
|
|
15713
|
+
return resolve10(dirname4(settingsPath), "plugins", "failproofai.mjs");
|
|
15373
15714
|
}
|
|
15374
15715
|
function buildOpenCodePluginShim(binaryPath, scope) {
|
|
15375
15716
|
const useNpx = scope === "project";
|
|
@@ -15584,8 +15925,8 @@ export default async function failproofaiPlugin({ client, directory }) {
|
|
|
15584
15925
|
function getPiExtensionPath() {
|
|
15585
15926
|
const fromEnv = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
15586
15927
|
if (fromEnv)
|
|
15587
|
-
return
|
|
15588
|
-
return
|
|
15928
|
+
return resolve10(fromEnv, "pi-extension");
|
|
15929
|
+
return resolve10(fileURLToPath(import.meta.url), "..", "..", "..", "pi-extension");
|
|
15589
15930
|
}
|
|
15590
15931
|
function isFailproofaiPiEntry(source) {
|
|
15591
15932
|
if (typeof source !== "string")
|
|
@@ -15596,8 +15937,8 @@ function isFailproofaiPiEntry(source) {
|
|
|
15596
15937
|
}
|
|
15597
15938
|
function makePiProjectRelativeEntry(extPath) {
|
|
15598
15939
|
const cwd = process.cwd();
|
|
15599
|
-
const cwdResolved =
|
|
15600
|
-
const extResolved =
|
|
15940
|
+
const cwdResolved = resolve10(cwd);
|
|
15941
|
+
const extResolved = resolve10(extPath);
|
|
15601
15942
|
if (extResolved.startsWith(cwdResolved + "/") || extResolved === cwdResolved) {
|
|
15602
15943
|
const fromSettingsDir = "../" + extResolved.slice(cwdResolved.length + 1);
|
|
15603
15944
|
return fromSettingsDir;
|
|
@@ -15607,8 +15948,8 @@ function makePiProjectRelativeEntry(extPath) {
|
|
|
15607
15948
|
function getOpenClawPluginPath() {
|
|
15608
15949
|
const fromEnv = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
15609
15950
|
if (fromEnv)
|
|
15610
|
-
return
|
|
15611
|
-
return
|
|
15951
|
+
return resolve10(fromEnv, "openclaw-plugin");
|
|
15952
|
+
return resolve10(fileURLToPath(import.meta.url), "..", "..", "..", "openclaw-plugin");
|
|
15612
15953
|
}
|
|
15613
15954
|
function isFailproofaiOpenClawPath(p) {
|
|
15614
15955
|
if (typeof p !== "string")
|
|
@@ -15644,14 +15985,14 @@ var init_integrations = __esm(() => {
|
|
|
15644
15985
|
scopes: HOOK_SCOPES,
|
|
15645
15986
|
eventTypes: HOOK_EVENT_TYPES,
|
|
15646
15987
|
getSettingsPath(scope, cwd) {
|
|
15647
|
-
const base = cwd ?
|
|
15988
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
15648
15989
|
switch (scope) {
|
|
15649
15990
|
case "user":
|
|
15650
|
-
return
|
|
15991
|
+
return resolve10(homedir23(), ".claude", "settings.json");
|
|
15651
15992
|
case "project":
|
|
15652
|
-
return
|
|
15993
|
+
return resolve10(base, ".claude", "settings.json");
|
|
15653
15994
|
case "local":
|
|
15654
|
-
return
|
|
15995
|
+
return resolve10(base, ".claude", "settings.local.json");
|
|
15655
15996
|
}
|
|
15656
15997
|
},
|
|
15657
15998
|
readSettings(settingsPath) {
|
|
@@ -15723,7 +16064,7 @@ var init_integrations = __esm(() => {
|
|
|
15723
16064
|
},
|
|
15724
16065
|
hooksInstalledInSettings(scope, cwd) {
|
|
15725
16066
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
15726
|
-
if (!
|
|
16067
|
+
if (!existsSync11(settingsPath))
|
|
15727
16068
|
return false;
|
|
15728
16069
|
try {
|
|
15729
16070
|
const settings = this.readSettings(settingsPath);
|
|
@@ -15752,14 +16093,14 @@ var init_integrations = __esm(() => {
|
|
|
15752
16093
|
scopes: CODEX_HOOK_SCOPES,
|
|
15753
16094
|
eventTypes: CODEX_HOOK_EVENT_TYPES,
|
|
15754
16095
|
getSettingsPath(scope, cwd) {
|
|
15755
|
-
const base = cwd ?
|
|
16096
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
15756
16097
|
switch (scope) {
|
|
15757
16098
|
case "user":
|
|
15758
|
-
return
|
|
16099
|
+
return resolve10(homedir23(), ".codex", "hooks.json");
|
|
15759
16100
|
case "project":
|
|
15760
|
-
return
|
|
16101
|
+
return resolve10(base, ".codex", "hooks.json");
|
|
15761
16102
|
case "local":
|
|
15762
|
-
return
|
|
16103
|
+
return resolve10(base, ".codex", "hooks.json");
|
|
15763
16104
|
}
|
|
15764
16105
|
},
|
|
15765
16106
|
readSettings(settingsPath) {
|
|
@@ -15839,7 +16180,7 @@ var init_integrations = __esm(() => {
|
|
|
15839
16180
|
},
|
|
15840
16181
|
hooksInstalledInSettings(scope, cwd) {
|
|
15841
16182
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
15842
|
-
if (!
|
|
16183
|
+
if (!existsSync11(settingsPath))
|
|
15843
16184
|
return false;
|
|
15844
16185
|
try {
|
|
15845
16186
|
const settings = this.readSettings(settingsPath);
|
|
@@ -15868,14 +16209,14 @@ var init_integrations = __esm(() => {
|
|
|
15868
16209
|
scopes: COPILOT_HOOK_SCOPES,
|
|
15869
16210
|
eventTypes: COPILOT_HOOK_EVENT_TYPES,
|
|
15870
16211
|
getSettingsPath(scope, cwd) {
|
|
15871
|
-
const base = cwd ?
|
|
16212
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
15872
16213
|
switch (scope) {
|
|
15873
16214
|
case "user":
|
|
15874
|
-
return
|
|
16215
|
+
return resolve10(homedir23(), ".copilot", "hooks", "failproofai.json");
|
|
15875
16216
|
case "project":
|
|
15876
|
-
return
|
|
16217
|
+
return resolve10(base, ".github", "hooks", "failproofai.json");
|
|
15877
16218
|
case "local":
|
|
15878
|
-
return
|
|
16219
|
+
return resolve10(base, ".github", "hooks", "failproofai.json");
|
|
15879
16220
|
}
|
|
15880
16221
|
},
|
|
15881
16222
|
readSettings(settingsPath) {
|
|
@@ -15953,7 +16294,7 @@ var init_integrations = __esm(() => {
|
|
|
15953
16294
|
},
|
|
15954
16295
|
hooksInstalledInSettings(scope, cwd) {
|
|
15955
16296
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
15956
|
-
if (!
|
|
16297
|
+
if (!existsSync11(settingsPath))
|
|
15957
16298
|
return false;
|
|
15958
16299
|
try {
|
|
15959
16300
|
const settings = this.readSettings(settingsPath);
|
|
@@ -15982,14 +16323,14 @@ var init_integrations = __esm(() => {
|
|
|
15982
16323
|
scopes: CURSOR_HOOK_SCOPES,
|
|
15983
16324
|
eventTypes: CURSOR_HOOK_EVENT_TYPES,
|
|
15984
16325
|
getSettingsPath(scope, cwd) {
|
|
15985
|
-
const base = cwd ?
|
|
16326
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
15986
16327
|
switch (scope) {
|
|
15987
16328
|
case "user":
|
|
15988
|
-
return
|
|
16329
|
+
return resolve10(homedir23(), ".cursor", "hooks.json");
|
|
15989
16330
|
case "project":
|
|
15990
|
-
return
|
|
16331
|
+
return resolve10(base, ".cursor", "hooks.json");
|
|
15991
16332
|
case "local":
|
|
15992
|
-
return
|
|
16333
|
+
return resolve10(base, ".cursor", "hooks.json");
|
|
15993
16334
|
}
|
|
15994
16335
|
},
|
|
15995
16336
|
readSettings(settingsPath) {
|
|
@@ -16056,7 +16397,7 @@ var init_integrations = __esm(() => {
|
|
|
16056
16397
|
},
|
|
16057
16398
|
hooksInstalledInSettings(scope, cwd) {
|
|
16058
16399
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
16059
|
-
if (!
|
|
16400
|
+
if (!existsSync11(settingsPath))
|
|
16060
16401
|
return false;
|
|
16061
16402
|
try {
|
|
16062
16403
|
const settings = this.readSettings(settingsPath);
|
|
@@ -16081,14 +16422,14 @@ var init_integrations = __esm(() => {
|
|
|
16081
16422
|
scopes: OPENCODE_HOOK_SCOPES,
|
|
16082
16423
|
eventTypes: OPENCODE_HOOK_EVENT_TYPES,
|
|
16083
16424
|
getSettingsPath(scope, cwd) {
|
|
16084
|
-
const base = cwd ?
|
|
16425
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
16085
16426
|
switch (scope) {
|
|
16086
16427
|
case "user":
|
|
16087
|
-
return
|
|
16428
|
+
return resolve10(homedir23(), ".config", "opencode", "opencode.json");
|
|
16088
16429
|
case "project":
|
|
16089
|
-
return
|
|
16430
|
+
return resolve10(base, ".opencode", "opencode.json");
|
|
16090
16431
|
case "local":
|
|
16091
|
-
return
|
|
16432
|
+
return resolve10(base, ".opencode", "opencode.json");
|
|
16092
16433
|
}
|
|
16093
16434
|
},
|
|
16094
16435
|
readSettings(settingsPath) {
|
|
@@ -16099,7 +16440,7 @@ var init_integrations = __esm(() => {
|
|
|
16099
16440
|
},
|
|
16100
16441
|
buildHookEntry(_binaryPath, _eventType, scope) {
|
|
16101
16442
|
if (scope === "user") {
|
|
16102
|
-
const abs =
|
|
16443
|
+
const abs = resolve10(homedir23(), ".config", "opencode", "plugins", "failproofai.mjs");
|
|
16103
16444
|
return { spec: `file://${abs}`, [FAILPROOFAI_HOOK_MARKER]: true };
|
|
16104
16445
|
}
|
|
16105
16446
|
return { spec: OPENCODE_PLUGIN_REL_PATH, [FAILPROOFAI_HOOK_MARKER]: true };
|
|
@@ -16114,10 +16455,10 @@ var init_integrations = __esm(() => {
|
|
|
16114
16455
|
writeHookEntries(settings, binaryPath, scope) {
|
|
16115
16456
|
const s = settings;
|
|
16116
16457
|
const effectiveScope = scope ?? "project";
|
|
16117
|
-
const settingsPath = effectiveScope === "user" ?
|
|
16458
|
+
const settingsPath = effectiveScope === "user" ? resolve10(homedir23(), ".config", "opencode", "opencode.json") : resolve10(process.cwd(), ".opencode", "opencode.json");
|
|
16118
16459
|
const pluginPath = opencodePluginFilePath(settingsPath);
|
|
16119
|
-
|
|
16120
|
-
|
|
16460
|
+
mkdirSync7(dirname4(pluginPath), { recursive: true });
|
|
16461
|
+
writeFileSync6(pluginPath, buildOpenCodePluginShim(binaryPath, effectiveScope), "utf8");
|
|
16121
16462
|
if (!Array.isArray(s.plugin))
|
|
16122
16463
|
s.plugin = [];
|
|
16123
16464
|
const desired = effectiveScope === "user" ? `file://${pluginPath}` : OPENCODE_PLUGIN_REL_PATH;
|
|
@@ -16140,9 +16481,9 @@ var init_integrations = __esm(() => {
|
|
|
16140
16481
|
}
|
|
16141
16482
|
this.writeSettings(settingsPath, settings);
|
|
16142
16483
|
const pluginPath = opencodePluginFilePath(settingsPath);
|
|
16143
|
-
if (
|
|
16484
|
+
if (existsSync11(pluginPath)) {
|
|
16144
16485
|
try {
|
|
16145
|
-
const content =
|
|
16486
|
+
const content = readFileSync12(pluginPath, "utf8");
|
|
16146
16487
|
if (content.includes(FAILPROOFAI_HOOK_MARKER)) {
|
|
16147
16488
|
unlinkSync2(pluginPath);
|
|
16148
16489
|
if (removed === 0)
|
|
@@ -16154,7 +16495,7 @@ var init_integrations = __esm(() => {
|
|
|
16154
16495
|
},
|
|
16155
16496
|
hooksInstalledInSettings(scope, cwd) {
|
|
16156
16497
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
16157
|
-
if (!
|
|
16498
|
+
if (!existsSync11(settingsPath))
|
|
16158
16499
|
return false;
|
|
16159
16500
|
try {
|
|
16160
16501
|
const settings = this.readSettings(settingsPath);
|
|
@@ -16164,9 +16505,9 @@ var init_integrations = __esm(() => {
|
|
|
16164
16505
|
if (!hasEntry)
|
|
16165
16506
|
return false;
|
|
16166
16507
|
const pluginPath = opencodePluginFilePath(settingsPath);
|
|
16167
|
-
if (!
|
|
16508
|
+
if (!existsSync11(pluginPath))
|
|
16168
16509
|
return false;
|
|
16169
|
-
const content =
|
|
16510
|
+
const content = readFileSync12(pluginPath, "utf8");
|
|
16170
16511
|
return content.includes(FAILPROOFAI_HOOK_MARKER);
|
|
16171
16512
|
} catch {
|
|
16172
16513
|
return false;
|
|
@@ -16182,14 +16523,14 @@ var init_integrations = __esm(() => {
|
|
|
16182
16523
|
scopes: PI_HOOK_SCOPES,
|
|
16183
16524
|
eventTypes: PI_HOOK_EVENT_TYPES,
|
|
16184
16525
|
getSettingsPath(scope, cwd) {
|
|
16185
|
-
const base = cwd ?
|
|
16526
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
16186
16527
|
switch (scope) {
|
|
16187
16528
|
case "user":
|
|
16188
|
-
return
|
|
16529
|
+
return resolve10(homedir23(), ".pi", "agent", "settings.json");
|
|
16189
16530
|
case "project":
|
|
16190
|
-
return
|
|
16531
|
+
return resolve10(base, ".pi", "settings.json");
|
|
16191
16532
|
case "local":
|
|
16192
|
-
return
|
|
16533
|
+
return resolve10(base, ".pi", "settings.json");
|
|
16193
16534
|
}
|
|
16194
16535
|
},
|
|
16195
16536
|
readSettings(settingsPath) {
|
|
@@ -16231,7 +16572,7 @@ var init_integrations = __esm(() => {
|
|
|
16231
16572
|
}
|
|
16232
16573
|
},
|
|
16233
16574
|
removeHooksFromFile(settingsPath) {
|
|
16234
|
-
if (!
|
|
16575
|
+
if (!existsSync11(settingsPath))
|
|
16235
16576
|
return 0;
|
|
16236
16577
|
const settings = this.readSettings(settingsPath);
|
|
16237
16578
|
if (!Array.isArray(settings.packages))
|
|
@@ -16246,7 +16587,7 @@ var init_integrations = __esm(() => {
|
|
|
16246
16587
|
},
|
|
16247
16588
|
hooksInstalledInSettings(scope, cwd) {
|
|
16248
16589
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
16249
|
-
if (!
|
|
16590
|
+
if (!existsSync11(settingsPath))
|
|
16250
16591
|
return false;
|
|
16251
16592
|
try {
|
|
16252
16593
|
const settings = this.readSettings(settingsPath);
|
|
@@ -16267,7 +16608,7 @@ var init_integrations = __esm(() => {
|
|
|
16267
16608
|
scopes: HERMES_HOOK_SCOPES,
|
|
16268
16609
|
eventTypes: HERMES_HOOK_EVENT_TYPES,
|
|
16269
16610
|
getSettingsPath() {
|
|
16270
|
-
return
|
|
16611
|
+
return resolve10(homedir23(), ".hermes", "config.yaml");
|
|
16271
16612
|
},
|
|
16272
16613
|
readSettings(settingsPath) {
|
|
16273
16614
|
return readYamlDoc(settingsPath);
|
|
@@ -16302,7 +16643,7 @@ var init_integrations = __esm(() => {
|
|
|
16302
16643
|
doc.set("hooks_auto_accept", true);
|
|
16303
16644
|
},
|
|
16304
16645
|
removeHooksFromFile(settingsPath) {
|
|
16305
|
-
if (!
|
|
16646
|
+
if (!existsSync11(settingsPath))
|
|
16306
16647
|
return 0;
|
|
16307
16648
|
const doc = readYamlDoc(settingsPath);
|
|
16308
16649
|
const js = doc.toJS() ?? {};
|
|
@@ -16335,7 +16676,7 @@ var init_integrations = __esm(() => {
|
|
|
16335
16676
|
},
|
|
16336
16677
|
hooksInstalledInSettings(scope, cwd) {
|
|
16337
16678
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
16338
|
-
if (!
|
|
16679
|
+
if (!existsSync11(settingsPath))
|
|
16339
16680
|
return false;
|
|
16340
16681
|
try {
|
|
16341
16682
|
const doc = readYamlDoc(settingsPath);
|
|
@@ -16360,7 +16701,7 @@ var init_integrations = __esm(() => {
|
|
|
16360
16701
|
scopes: OPENCLAW_HOOK_SCOPES,
|
|
16361
16702
|
eventTypes: OPENCLAW_HOOK_EVENT_TYPES,
|
|
16362
16703
|
getSettingsPath() {
|
|
16363
|
-
return
|
|
16704
|
+
return resolve10(homedir23(), ".openclaw", "openclaw.json");
|
|
16364
16705
|
},
|
|
16365
16706
|
readSettings(settingsPath) {
|
|
16366
16707
|
return readJsonFile(settingsPath);
|
|
@@ -16405,7 +16746,7 @@ var init_integrations = __esm(() => {
|
|
|
16405
16746
|
hooks.allowConversationAccess = true;
|
|
16406
16747
|
},
|
|
16407
16748
|
removeHooksFromFile(settingsPath) {
|
|
16408
|
-
if (!
|
|
16749
|
+
if (!existsSync11(settingsPath))
|
|
16409
16750
|
return 0;
|
|
16410
16751
|
const settings = this.readSettings(settingsPath);
|
|
16411
16752
|
const plugins = settings.plugins;
|
|
@@ -16434,7 +16775,7 @@ var init_integrations = __esm(() => {
|
|
|
16434
16775
|
},
|
|
16435
16776
|
hooksInstalledInSettings(scope, cwd) {
|
|
16436
16777
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
16437
|
-
if (!
|
|
16778
|
+
if (!existsSync11(settingsPath))
|
|
16438
16779
|
return false;
|
|
16439
16780
|
try {
|
|
16440
16781
|
const settings = this.readSettings(settingsPath);
|
|
@@ -16456,14 +16797,14 @@ var init_integrations = __esm(() => {
|
|
|
16456
16797
|
scopes: FACTORY_HOOK_SCOPES,
|
|
16457
16798
|
eventTypes: FACTORY_HOOK_EVENT_TYPES,
|
|
16458
16799
|
getSettingsPath(scope, cwd) {
|
|
16459
|
-
const base = cwd ?
|
|
16800
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
16460
16801
|
switch (scope) {
|
|
16461
16802
|
case "user":
|
|
16462
|
-
return
|
|
16803
|
+
return resolve10(homedir23(), ".factory", "hooks.json");
|
|
16463
16804
|
case "project":
|
|
16464
|
-
return
|
|
16805
|
+
return resolve10(base, ".factory", "hooks.json");
|
|
16465
16806
|
case "local":
|
|
16466
|
-
return
|
|
16807
|
+
return resolve10(base, ".factory", "hooks.json");
|
|
16467
16808
|
}
|
|
16468
16809
|
},
|
|
16469
16810
|
readSettings(settingsPath) {
|
|
@@ -16531,7 +16872,7 @@ var init_integrations = __esm(() => {
|
|
|
16531
16872
|
},
|
|
16532
16873
|
hooksInstalledInSettings(scope, cwd) {
|
|
16533
16874
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
16534
|
-
if (!
|
|
16875
|
+
if (!existsSync11(settingsPath))
|
|
16535
16876
|
return false;
|
|
16536
16877
|
try {
|
|
16537
16878
|
const settings = this.readSettings(settingsPath);
|
|
@@ -16558,14 +16899,14 @@ var init_integrations = __esm(() => {
|
|
|
16558
16899
|
scopes: DEVIN_HOOK_SCOPES,
|
|
16559
16900
|
eventTypes: DEVIN_HOOK_EVENT_TYPES,
|
|
16560
16901
|
getSettingsPath(scope, cwd) {
|
|
16561
|
-
const base = cwd ?
|
|
16902
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
16562
16903
|
switch (scope) {
|
|
16563
16904
|
case "user":
|
|
16564
|
-
return
|
|
16905
|
+
return resolve10(homedir23(), ".config", "devin", "config.json");
|
|
16565
16906
|
case "project":
|
|
16566
|
-
return
|
|
16907
|
+
return resolve10(base, ".devin", "config.json");
|
|
16567
16908
|
case "local":
|
|
16568
|
-
return
|
|
16909
|
+
return resolve10(base, ".devin", "config.json");
|
|
16569
16910
|
}
|
|
16570
16911
|
},
|
|
16571
16912
|
readSettings(settingsPath) {
|
|
@@ -16637,7 +16978,7 @@ var init_integrations = __esm(() => {
|
|
|
16637
16978
|
},
|
|
16638
16979
|
hooksInstalledInSettings(scope, cwd) {
|
|
16639
16980
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
16640
|
-
if (!
|
|
16981
|
+
if (!existsSync11(settingsPath))
|
|
16641
16982
|
return false;
|
|
16642
16983
|
try {
|
|
16643
16984
|
const settings = this.readSettings(settingsPath);
|
|
@@ -16667,14 +17008,14 @@ var init_integrations = __esm(() => {
|
|
|
16667
17008
|
scopes: ANTIGRAVITY_HOOK_SCOPES,
|
|
16668
17009
|
eventTypes: ANTIGRAVITY_HOOK_EVENT_TYPES,
|
|
16669
17010
|
getSettingsPath(scope, cwd) {
|
|
16670
|
-
const base = cwd ?
|
|
17011
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
16671
17012
|
switch (scope) {
|
|
16672
17013
|
case "user":
|
|
16673
|
-
return
|
|
17014
|
+
return resolve10(homedir23(), ".gemini", "config", "hooks.json");
|
|
16674
17015
|
case "project":
|
|
16675
|
-
return
|
|
17016
|
+
return resolve10(base, ".agents", "hooks.json");
|
|
16676
17017
|
case "local":
|
|
16677
|
-
return
|
|
17018
|
+
return resolve10(base, ".agents", "hooks.json");
|
|
16678
17019
|
}
|
|
16679
17020
|
},
|
|
16680
17021
|
readSettings(settingsPath) {
|
|
@@ -16776,7 +17117,7 @@ var init_integrations = __esm(() => {
|
|
|
16776
17117
|
},
|
|
16777
17118
|
hooksInstalledInSettings(scope, cwd) {
|
|
16778
17119
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
16779
|
-
if (!
|
|
17120
|
+
if (!existsSync11(settingsPath))
|
|
16780
17121
|
return false;
|
|
16781
17122
|
try {
|
|
16782
17123
|
const settings = this.readSettings(settingsPath);
|
|
@@ -16808,14 +17149,14 @@ var init_integrations = __esm(() => {
|
|
|
16808
17149
|
scopes: GOOSE_HOOK_SCOPES,
|
|
16809
17150
|
eventTypes: GOOSE_HOOK_EVENT_TYPES,
|
|
16810
17151
|
getSettingsPath(scope, cwd) {
|
|
16811
|
-
const base = cwd ?
|
|
17152
|
+
const base = cwd ? resolve10(cwd) : process.cwd();
|
|
16812
17153
|
switch (scope) {
|
|
16813
17154
|
case "user":
|
|
16814
|
-
return
|
|
17155
|
+
return resolve10(homedir23(), ".agents", "plugins", "failproofai", "hooks", "hooks.json");
|
|
16815
17156
|
case "project":
|
|
16816
|
-
return
|
|
17157
|
+
return resolve10(base, ".agents", "plugins", "failproofai", "hooks", "hooks.json");
|
|
16817
17158
|
case "local":
|
|
16818
|
-
return
|
|
17159
|
+
return resolve10(base, ".agents", "plugins", "failproofai", "hooks", "hooks.json");
|
|
16819
17160
|
}
|
|
16820
17161
|
},
|
|
16821
17162
|
readSettings(settingsPath) {
|
|
@@ -16882,7 +17223,7 @@ var init_integrations = __esm(() => {
|
|
|
16882
17223
|
},
|
|
16883
17224
|
hooksInstalledInSettings(scope, cwd) {
|
|
16884
17225
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
16885
|
-
if (!
|
|
17226
|
+
if (!existsSync11(settingsPath))
|
|
16886
17227
|
return false;
|
|
16887
17228
|
try {
|
|
16888
17229
|
const settings = this.readSettings(settingsPath);
|
|
@@ -16926,6 +17267,11 @@ import * as readline from "node:readline";
|
|
|
16926
17267
|
function colorsEnabled(out) {
|
|
16927
17268
|
return !!out.isTTY && !process.env.NO_COLOR;
|
|
16928
17269
|
}
|
|
17270
|
+
function brandAnsi(role) {
|
|
17271
|
+
const h = HUES[role];
|
|
17272
|
+
const code = truecolorEnabled() ? `38;2;${h.rgb.join(";")}` : h.basic;
|
|
17273
|
+
return `${ESC}[${code}m`;
|
|
17274
|
+
}
|
|
16929
17275
|
function truecolorEnabled() {
|
|
16930
17276
|
return /truecolor|24bit/i.test(process.env.COLORTERM || "");
|
|
16931
17277
|
}
|
|
@@ -17050,7 +17396,7 @@ function renderLaunchBanner(version3, stdout = process.stdout) {
|
|
|
17050
17396
|
row("version", c.pink(version3)),
|
|
17051
17397
|
row("star", c.dim("https://github.com/failproofai/failproofai")),
|
|
17052
17398
|
row("docs", c.dim("https://docs.befailproof.ai/introduction")),
|
|
17053
|
-
row("discord", c.dim("https://discord.
|
|
17399
|
+
row("discord", c.dim("https://discord.befailproof.ai/")),
|
|
17054
17400
|
""
|
|
17055
17401
|
];
|
|
17056
17402
|
}
|
|
@@ -17145,7 +17491,7 @@ function runPrompt(p) {
|
|
|
17145
17491
|
`${c.dim(BAR)} ${c.dim(p.summaryFor(result))}`
|
|
17146
17492
|
]);
|
|
17147
17493
|
};
|
|
17148
|
-
return new Promise((
|
|
17494
|
+
return new Promise((resolve11) => {
|
|
17149
17495
|
hideCursor(stdout);
|
|
17150
17496
|
repaint(stdout, region, build());
|
|
17151
17497
|
readline.emitKeypressEvents(stdin);
|
|
@@ -17161,7 +17507,7 @@ function runPrompt(p) {
|
|
|
17161
17507
|
const finish = (result) => {
|
|
17162
17508
|
cleanup();
|
|
17163
17509
|
collapse(result);
|
|
17164
|
-
|
|
17510
|
+
resolve11(result);
|
|
17165
17511
|
};
|
|
17166
17512
|
function onKey(_s, key) {
|
|
17167
17513
|
if (!key)
|
|
@@ -17222,7 +17568,7 @@ function multiSelect(opts) {
|
|
|
17222
17568
|
const choices = opts.choices;
|
|
17223
17569
|
const minSelected = opts.minSelected ?? 0;
|
|
17224
17570
|
const noun = opts.summaryNoun ?? "selected";
|
|
17225
|
-
const checked = choices.map((ch) => !!ch.checked);
|
|
17571
|
+
const checked = choices.map((ch) => ch.locked ? ch.checked ?? true : !!ch.checked);
|
|
17226
17572
|
if (!stdin.isTTY || !stdout.isTTY) {
|
|
17227
17573
|
return Promise.resolve(choices.filter((_, i) => checked[i]).map((ch) => ch.value));
|
|
17228
17574
|
}
|
|
@@ -17238,7 +17584,7 @@ function multiSelect(opts) {
|
|
|
17238
17584
|
renderRow: (index, active, budget) => {
|
|
17239
17585
|
const choice = choices[index];
|
|
17240
17586
|
const caret = active ? c.pink(CARET) : " ";
|
|
17241
|
-
const box = checked[index] ? c.pink(CHECK_ON) : c.dim(CHECK_OFF);
|
|
17587
|
+
const box = choice.locked ? checked[index] ? c.guide(CHECK_ON) : c.dim(CHECK_OFF) : checked[index] ? c.pink(CHECK_ON) : c.dim(CHECK_OFF);
|
|
17242
17588
|
const rawLabel = choice.label.padEnd(nameCol);
|
|
17243
17589
|
const label = active ? c.pinkBold(rawLabel) : checked[index] ? rawLabel : c.dim(rawLabel);
|
|
17244
17590
|
const hint = choice.hint ? ` ${c.dim(ellipsize(choice.hint, budget))}` : "";
|
|
@@ -17248,19 +17594,23 @@ function multiSelect(opts) {
|
|
|
17248
17594
|
footer: opts.hint ?? "↑/↓ move · space select · ctrl+a all · enter confirm",
|
|
17249
17595
|
onKey: (key, cursor2) => {
|
|
17250
17596
|
if (key.name === "space") {
|
|
17597
|
+
if (choices[cursor2]?.locked)
|
|
17598
|
+
return "redraw";
|
|
17251
17599
|
checked[cursor2] = !checked[cursor2];
|
|
17252
17600
|
warn = false;
|
|
17253
17601
|
return "redraw";
|
|
17254
17602
|
}
|
|
17255
17603
|
if (key.ctrl && key.name === "a") {
|
|
17256
|
-
const allOn =
|
|
17257
|
-
for (let i = 0;i < checked.length; i++)
|
|
17258
|
-
checked[i] = !allOn;
|
|
17604
|
+
const allOn = choices.every((ch, i) => checked[i] || ch.locked);
|
|
17605
|
+
for (let i = 0;i < checked.length; i++) {
|
|
17606
|
+
checked[i] = choices[i]?.locked ? true : !allOn;
|
|
17607
|
+
}
|
|
17259
17608
|
return "redraw";
|
|
17260
17609
|
}
|
|
17261
17610
|
if (key.name === "return") {
|
|
17262
17611
|
const selected = choices.filter((_, i) => checked[i]).map((ch) => ch.value);
|
|
17263
|
-
|
|
17612
|
+
const chosen = choices.filter((ch, i) => checked[i] && !ch.locked).length;
|
|
17613
|
+
if (chosen < minSelected) {
|
|
17264
17614
|
warn = true;
|
|
17265
17615
|
return "redraw";
|
|
17266
17616
|
}
|
|
@@ -17268,10 +17618,10 @@ function multiSelect(opts) {
|
|
|
17268
17618
|
}
|
|
17269
17619
|
return;
|
|
17270
17620
|
},
|
|
17271
|
-
summaryFor: (values) => values === null ? "cancelled" : summarize(choices.filter((ch) => values.includes(ch.value)).map((ch) => ch.label), noun)
|
|
17621
|
+
summaryFor: (values) => values === null ? "cancelled" : summarize(choices.filter((ch) => values.includes(ch.value) && !ch.summaryExclude).map((ch) => ch.label), noun)
|
|
17272
17622
|
});
|
|
17273
17623
|
}
|
|
17274
|
-
var ESC = "\x1B", BAR = "│", BAR_END = "└", STEP_ACTIVE = "◆", STEP_DONE = "◇", RADIO_ON = "●", RADIO_OFF = "○", CHECK_ON = "◼", CHECK_OFF = "◻", CARET = "❯", FLOWER = "❋", HUES, LOGO_MIN_COLS = 22, TAGLINE = "end-to-end failure layer for ai agents", LOGO_GRID, LOGO_TEAL, LOGO_PINK, WINDOW = 8;
|
|
17624
|
+
var ESC = "\x1B", BAR = "│", BAR_END = "└", STEP_ACTIVE = "◆", STEP_DONE = "◇", RADIO_ON = "●", RADIO_OFF = "○", CHECK_ON = "◼", CHECK_OFF = "◻", CARET = "❯", FLOWER = "❋", HUES, ANSI_RESET, ANSI_BOLD, ANSI_DIM, LOGO_MIN_COLS = 22, TAGLINE = "end-to-end failure layer for ai agents", LOGO_GRID, LOGO_TEAL, LOGO_PINK, WINDOW = 8;
|
|
17275
17625
|
var init_tui = __esm(() => {
|
|
17276
17626
|
HUES = {
|
|
17277
17627
|
guide: { rgb: [102, 209, 181], basic: "36" },
|
|
@@ -17280,29 +17630,30 @@ var init_tui = __esm(() => {
|
|
|
17280
17630
|
warn: { rgb: [227, 179, 65], basic: "33" },
|
|
17281
17631
|
dim: { rgb: [107, 118, 132], basic: "2" }
|
|
17282
17632
|
};
|
|
17633
|
+
ANSI_RESET = `${ESC}[0m`;
|
|
17634
|
+
ANSI_BOLD = `${ESC}[1m`;
|
|
17635
|
+
ANSI_DIM = `${ESC}[2m`;
|
|
17283
17636
|
LOGO_GRID = [
|
|
17284
|
-
"...tt
|
|
17285
|
-
"..tttt
|
|
17286
|
-
".tttttt
|
|
17287
|
-
".tttttt
|
|
17288
|
-
"..tttt
|
|
17289
|
-
"...tt
|
|
17290
|
-
"
|
|
17291
|
-
"
|
|
17292
|
-
"..pppp
|
|
17293
|
-
"..pppp
|
|
17294
|
-
"..pppp
|
|
17295
|
-
".pppppp
|
|
17296
|
-
".pppppp
|
|
17297
|
-
".pppppp
|
|
17298
|
-
".pppppp
|
|
17299
|
-
"..pppp
|
|
17300
|
-
"..
|
|
17301
|
-
"..
|
|
17302
|
-
"..
|
|
17303
|
-
"..
|
|
17304
|
-
"..ppppppppppppp.",
|
|
17305
|
-
"..ppppppppppppp."
|
|
17637
|
+
"...tt........",
|
|
17638
|
+
"..tttt.......",
|
|
17639
|
+
".tttttt..pppp",
|
|
17640
|
+
".tttttt..pppp",
|
|
17641
|
+
"..tttt...pppp",
|
|
17642
|
+
"...tt....pppp",
|
|
17643
|
+
".........pppp",
|
|
17644
|
+
".........pppp",
|
|
17645
|
+
"..pppp...pppp",
|
|
17646
|
+
"..pppp...pppp",
|
|
17647
|
+
"..pppp...pppp",
|
|
17648
|
+
".pppppp..pppp",
|
|
17649
|
+
".pppppp..pppp",
|
|
17650
|
+
".pppppp..pppp",
|
|
17651
|
+
".pppppp..pppp",
|
|
17652
|
+
"..pppp...pppp",
|
|
17653
|
+
"..ppppppppppp",
|
|
17654
|
+
"..ppppppppppp",
|
|
17655
|
+
"..ppppppppppp",
|
|
17656
|
+
"..ppppppppppp"
|
|
17306
17657
|
];
|
|
17307
17658
|
LOGO_TEAL = HUES.guide.rgb;
|
|
17308
17659
|
LOGO_PINK = HUES.logoPink.rgb;
|
|
@@ -17457,7 +17808,7 @@ async function promptPolicySelection(preSelected, options = {}) {
|
|
|
17457
17808
|
`);
|
|
17458
17809
|
lastLineCount = lines.length;
|
|
17459
17810
|
}
|
|
17460
|
-
return new Promise((
|
|
17811
|
+
return new Promise((resolve11) => {
|
|
17461
17812
|
render();
|
|
17462
17813
|
process.stdin.setRawMode(true);
|
|
17463
17814
|
process.stdin.resume();
|
|
@@ -17494,7 +17845,7 @@ async function promptPolicySelection(preSelected, options = {}) {
|
|
|
17494
17845
|
${dim(STEP_DONE)} Policies
|
|
17495
17846
|
${dim(BAR)} ${dim(`${selected.length} selected`)}
|
|
17496
17847
|
`);
|
|
17497
|
-
|
|
17848
|
+
resolve11(selected);
|
|
17498
17849
|
} else if (key.name === "escape") {
|
|
17499
17850
|
search = "";
|
|
17500
17851
|
cursor2 = 0;
|
|
@@ -17555,10 +17906,10 @@ __export(exports_manager, {
|
|
|
17555
17906
|
hooksInstalledInSettings: () => hooksInstalledInSettings,
|
|
17556
17907
|
getSettingsPath: () => getSettingsPath
|
|
17557
17908
|
});
|
|
17558
|
-
import { execSync as
|
|
17559
|
-
import { existsSync as
|
|
17560
|
-
import { resolve as
|
|
17561
|
-
import { homedir as
|
|
17909
|
+
import { execSync as execSync6 } from "node:child_process";
|
|
17910
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
17911
|
+
import { resolve as resolve11, basename as basename3 } from "node:path";
|
|
17912
|
+
import { homedir as homedir24, platform as platform3, arch as arch3, release as release2, hostname as hostname3 } from "node:os";
|
|
17562
17913
|
function getSettingsPath(scope, cwd) {
|
|
17563
17914
|
return claudeCode.getSettingsPath(scope, cwd);
|
|
17564
17915
|
}
|
|
@@ -17578,7 +17929,7 @@ function resolveFailproofaiBinary() {
|
|
|
17578
17929
|
return override.trim();
|
|
17579
17930
|
try {
|
|
17580
17931
|
const cmd = process.platform === "win32" ? "where failproofai" : "which failproofai";
|
|
17581
|
-
const result =
|
|
17932
|
+
const result = execSync6(cmd, { encoding: "utf8" }).trim();
|
|
17582
17933
|
return result.split(`
|
|
17583
17934
|
`)[0].trim();
|
|
17584
17935
|
} catch {
|
|
@@ -17664,7 +18015,7 @@ async function installHooksImpl(policyNames, scope = "user", cwd, includeBeta =
|
|
|
17664
18015
|
if (removeCustomHooks) {
|
|
17665
18016
|
delete configToWrite.customPoliciesPath;
|
|
17666
18017
|
} else if (customPoliciesPath) {
|
|
17667
|
-
configToWrite.customPoliciesPath =
|
|
18018
|
+
configToWrite.customPoliciesPath = resolve11(customPoliciesPath);
|
|
17668
18019
|
let validatedHooks = [];
|
|
17669
18020
|
try {
|
|
17670
18021
|
validatedHooks = await loadCustomHooks(configToWrite.customPoliciesPath, { strict: true });
|
|
@@ -17736,10 +18087,10 @@ Enabled ${selectedPolicies.length} policy(ies): ${selectedPolicies.join(", ")}
|
|
|
17736
18087
|
policies_added: policiesAdded,
|
|
17737
18088
|
policies_removed: policiesRemoved,
|
|
17738
18089
|
...source ? { source } : {},
|
|
17739
|
-
platform:
|
|
17740
|
-
arch:
|
|
17741
|
-
os_release:
|
|
17742
|
-
hostname_hash: hashToId2(
|
|
18090
|
+
platform: platform3(),
|
|
18091
|
+
arch: arch3(),
|
|
18092
|
+
os_release: release2(),
|
|
18093
|
+
hostname_hash: hashToId2(hostname3()),
|
|
17743
18094
|
has_custom_hooks_path: !!configToWrite.customPoliciesPath,
|
|
17744
18095
|
has_policy_params: !!(configToWrite.policyParams && Object.keys(configToWrite.policyParams).length > 0),
|
|
17745
18096
|
param_policy_names: configToWrite.policyParams ? Object.keys(configToWrite.policyParams) : [],
|
|
@@ -17826,10 +18177,10 @@ async function removeHooks(policyNames, scope = "user", cwd, opts) {
|
|
|
17826
18177
|
policies_removed: actuallyRemoved,
|
|
17827
18178
|
removed_count: actuallyRemoved.length,
|
|
17828
18179
|
...opts?.source ? { source: opts.source } : {},
|
|
17829
|
-
platform:
|
|
17830
|
-
arch:
|
|
17831
|
-
os_release:
|
|
17832
|
-
hostname_hash: hashToId2(
|
|
18180
|
+
platform: platform3(),
|
|
18181
|
+
arch: arch3(),
|
|
18182
|
+
os_release: release2(),
|
|
18183
|
+
hostname_hash: hashToId2(hostname3())
|
|
17833
18184
|
});
|
|
17834
18185
|
} catch {}
|
|
17835
18186
|
console.log(`Disabled ${policyNames.length - notEnabled.length} policy(ies).`);
|
|
@@ -17844,7 +18195,7 @@ async function removeHooks(policyNames, scope = "user", cwd, opts) {
|
|
|
17844
18195
|
const scopesToRemove = scope === "all" ? [...integration.scopes] : integration.scopes.includes(scope) ? [scope] : [];
|
|
17845
18196
|
for (const s of scopesToRemove) {
|
|
17846
18197
|
const settingsPath = integration.getSettingsPath(s, cwd);
|
|
17847
|
-
if (!
|
|
18198
|
+
if (!existsSync12(settingsPath)) {
|
|
17848
18199
|
if (scope !== "all" && selectedClis.length === 1) {
|
|
17849
18200
|
console.log("No settings file found. Nothing to remove.");
|
|
17850
18201
|
nothingToReport = true;
|
|
@@ -17884,10 +18235,10 @@ async function removeHooks(policyNames, scope = "user", cwd, opts) {
|
|
|
17884
18235
|
policies_removed: configBeforeRemoval.enabledPolicies,
|
|
17885
18236
|
removed_count: totalRemoved,
|
|
17886
18237
|
...opts?.source ? { source: opts.source } : {},
|
|
17887
|
-
platform:
|
|
17888
|
-
arch:
|
|
17889
|
-
os_release:
|
|
17890
|
-
hostname_hash: hashToId2(
|
|
18238
|
+
platform: platform3(),
|
|
18239
|
+
arch: arch3(),
|
|
18240
|
+
os_release: release2(),
|
|
18241
|
+
hostname_hash: hashToId2(hostname3())
|
|
17891
18242
|
});
|
|
17892
18243
|
} catch {}
|
|
17893
18244
|
if (scope === "all") {
|
|
@@ -18033,7 +18384,7 @@ Failproof AI Hook Policies
|
|
|
18033
18384
|
if (config.customPoliciesPath) {
|
|
18034
18385
|
console.log(`
|
|
18035
18386
|
── Custom Policies (${config.customPoliciesPath}) ───────────────────────`);
|
|
18036
|
-
if (!
|
|
18387
|
+
if (!existsSync12(config.customPoliciesPath)) {
|
|
18037
18388
|
console.log(` \x1B[31m✗ File not found: ${config.customPoliciesPath}\x1B[0m`);
|
|
18038
18389
|
} else {
|
|
18039
18390
|
const hooks = await loadCustomHooks(config.customPoliciesPath);
|
|
@@ -18048,10 +18399,10 @@ Failproof AI Hook Policies
|
|
|
18048
18399
|
}
|
|
18049
18400
|
console.log();
|
|
18050
18401
|
}
|
|
18051
|
-
const base = cwd ?
|
|
18402
|
+
const base = cwd ? resolve11(cwd) : process.cwd();
|
|
18052
18403
|
const conventionDirs = [
|
|
18053
|
-
{ label: "Project", dir:
|
|
18054
|
-
{ label: "User", dir:
|
|
18404
|
+
{ label: "Project", dir: resolve11(base, ".failproofai", "policies") },
|
|
18405
|
+
{ label: "User", dir: resolve11(homedir24(), ".failproofai", "policies") }
|
|
18055
18406
|
];
|
|
18056
18407
|
for (const { label, dir } of conventionDirs) {
|
|
18057
18408
|
const files = discoverPolicyFiles(dir);
|
|
@@ -18253,7 +18604,7 @@ async function promptCliTargetSelection(detected, action = "install") {
|
|
|
18253
18604
|
lastLineCount = lines.length;
|
|
18254
18605
|
}
|
|
18255
18606
|
const itemCount = options.length;
|
|
18256
|
-
return new Promise((
|
|
18607
|
+
return new Promise((resolve12) => {
|
|
18257
18608
|
render();
|
|
18258
18609
|
readline3.emitKeypressEvents(process.stdin);
|
|
18259
18610
|
const wasRaw = process.stdin.isRaw;
|
|
@@ -18286,7 +18637,7 @@ async function promptCliTargetSelection(detected, action = "install") {
|
|
|
18286
18637
|
cleanup();
|
|
18287
18638
|
process.stdout.write(`
|
|
18288
18639
|
`);
|
|
18289
|
-
|
|
18640
|
+
resolve12(options[cursor2].value);
|
|
18290
18641
|
}
|
|
18291
18642
|
}
|
|
18292
18643
|
process.stdin.on("keypress", onKey);
|
|
@@ -18439,7 +18790,7 @@ async function promptPolicySelection2(preSelected, options = {}) {
|
|
|
18439
18790
|
`);
|
|
18440
18791
|
lastLineCount = lines.length;
|
|
18441
18792
|
}
|
|
18442
|
-
return new Promise((
|
|
18793
|
+
return new Promise((resolve12) => {
|
|
18443
18794
|
render();
|
|
18444
18795
|
process.stdin.setRawMode(true);
|
|
18445
18796
|
process.stdin.resume();
|
|
@@ -18476,7 +18827,7 @@ async function promptPolicySelection2(preSelected, options = {}) {
|
|
|
18476
18827
|
${dim(STEP_DONE)} Policies
|
|
18477
18828
|
${dim(BAR)} ${dim(`${selected.length} selected`)}
|
|
18478
18829
|
`);
|
|
18479
|
-
|
|
18830
|
+
resolve12(selected);
|
|
18480
18831
|
} else if (key.name === "escape") {
|
|
18481
18832
|
search = "";
|
|
18482
18833
|
cursor2 = 0;
|
|
@@ -18656,12 +19007,12 @@ var init_api_server_client = __esm(() => {
|
|
|
18656
19007
|
// lib/atomic-write.ts
|
|
18657
19008
|
import {
|
|
18658
19009
|
chmodSync,
|
|
18659
|
-
existsSync as
|
|
18660
|
-
mkdirSync as
|
|
19010
|
+
existsSync as existsSync13,
|
|
19011
|
+
mkdirSync as mkdirSync8,
|
|
18661
19012
|
renameSync as renameSync3,
|
|
18662
19013
|
rmSync,
|
|
18663
19014
|
statSync as statSync11,
|
|
18664
|
-
writeFileSync as
|
|
19015
|
+
writeFileSync as writeFileSync7
|
|
18665
19016
|
} from "node:fs";
|
|
18666
19017
|
import { dirname as dirname5 } from "node:path";
|
|
18667
19018
|
import { randomBytes } from "node:crypto";
|
|
@@ -18669,11 +19020,11 @@ function writeJsonAtomically(filePath, value, opts = {}) {
|
|
|
18669
19020
|
const mode = opts.mode ?? 384;
|
|
18670
19021
|
const dirMode = opts.dirMode ?? 448;
|
|
18671
19022
|
const dir = dirname5(filePath);
|
|
18672
|
-
if (!
|
|
18673
|
-
|
|
19023
|
+
if (!existsSync13(dir))
|
|
19024
|
+
mkdirSync8(dir, { recursive: true, mode: dirMode });
|
|
18674
19025
|
const tmp = `${filePath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
18675
19026
|
try {
|
|
18676
|
-
|
|
19027
|
+
writeFileSync7(tmp, JSON.stringify(value, null, 2), { mode });
|
|
18677
19028
|
try {
|
|
18678
19029
|
if ((statSync11(tmp).mode & 63) !== 0)
|
|
18679
19030
|
chmodSync(tmp, mode);
|
|
@@ -18693,24 +19044,24 @@ function writeJsonAtomically(filePath, value, opts = {}) {
|
|
|
18693
19044
|
var init_atomic_write = () => {};
|
|
18694
19045
|
|
|
18695
19046
|
// lib/auth/auth-store.ts
|
|
18696
|
-
import { existsSync as
|
|
18697
|
-
import { homedir as
|
|
18698
|
-
import { join as
|
|
19047
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, rmSync as rmSync2 } from "node:fs";
|
|
19048
|
+
import { homedir as homedir25 } from "node:os";
|
|
19049
|
+
import { join as join25 } from "node:path";
|
|
18699
19050
|
function getAuthDir() {
|
|
18700
19051
|
const override = process.env.FAILPROOFAI_AUTH_DIR;
|
|
18701
19052
|
if (override)
|
|
18702
19053
|
return override;
|
|
18703
|
-
return
|
|
19054
|
+
return join25(homedir25(), ".failproofai");
|
|
18704
19055
|
}
|
|
18705
19056
|
function getAuthFilePath() {
|
|
18706
|
-
return
|
|
19057
|
+
return join25(getAuthDir(), "auth.json");
|
|
18707
19058
|
}
|
|
18708
19059
|
function readAuth() {
|
|
18709
19060
|
const p = getAuthFilePath();
|
|
18710
|
-
if (!
|
|
19061
|
+
if (!existsSync14(p))
|
|
18711
19062
|
return null;
|
|
18712
19063
|
try {
|
|
18713
|
-
const raw =
|
|
19064
|
+
const raw = readFileSync13(p, "utf-8");
|
|
18714
19065
|
const parsed = JSON.parse(raw);
|
|
18715
19066
|
if (typeof parsed.access_token !== "string" || typeof parsed.refresh_token !== "string" || typeof parsed.access_expires_at !== "number" || typeof parsed.user !== "object" || !parsed.user || typeof parsed.user.id !== "string" || typeof parsed.user.email !== "string") {
|
|
18716
19067
|
return null;
|
|
@@ -18734,7 +19085,7 @@ function writeAuth(auth) {
|
|
|
18734
19085
|
}
|
|
18735
19086
|
function deleteAuth() {
|
|
18736
19087
|
const p = getAuthFilePath();
|
|
18737
|
-
if (
|
|
19088
|
+
if (existsSync14(p))
|
|
18738
19089
|
rmSync2(p, { force: true });
|
|
18739
19090
|
}
|
|
18740
19091
|
function authFromTokenResponse(token, existingUser) {
|
|
@@ -18811,13 +19162,13 @@ function prompt(question, opts = {}) {
|
|
|
18811
19162
|
orig(s);
|
|
18812
19163
|
};
|
|
18813
19164
|
}
|
|
18814
|
-
return new Promise((
|
|
19165
|
+
return new Promise((resolve12) => {
|
|
18815
19166
|
rl.question(question, (answer) => {
|
|
18816
19167
|
rl.close();
|
|
18817
19168
|
if (opts.hidden && process.stdin.isTTY)
|
|
18818
19169
|
process.stdout.write(`
|
|
18819
19170
|
`);
|
|
18820
|
-
|
|
19171
|
+
resolve12(answer.trim());
|
|
18821
19172
|
});
|
|
18822
19173
|
});
|
|
18823
19174
|
}
|
|
@@ -19023,11 +19374,12 @@ async function runAuthCli(args) {
|
|
|
19023
19374
|
return runLogout();
|
|
19024
19375
|
return runWhoami();
|
|
19025
19376
|
}
|
|
19026
|
-
var HELP, LEGACY_FLAG_TO_SUB, SUBCOMMANDS, DIM
|
|
19377
|
+
var HELP, LEGACY_FLAG_TO_SUB, SUBCOMMANDS, COLOR, DIM, RESET, PINK, GREEN, RED;
|
|
19027
19378
|
var init_cli = __esm(() => {
|
|
19028
19379
|
init_api_server_client();
|
|
19029
19380
|
init_auth_store();
|
|
19030
19381
|
init_cli_error();
|
|
19382
|
+
init_tui();
|
|
19031
19383
|
init_hook_telemetry2();
|
|
19032
19384
|
init_telemetry_id2();
|
|
19033
19385
|
HELP = `
|
|
@@ -19056,11 +19408,17 @@ EXAMPLES
|
|
|
19056
19408
|
"--whoami": "whoami"
|
|
19057
19409
|
};
|
|
19058
19410
|
SUBCOMMANDS = new Set(["login", "logout", "whoami", "help"]);
|
|
19411
|
+
COLOR = colorsEnabled(process.stdout);
|
|
19412
|
+
DIM = COLOR ? ANSI_DIM : "";
|
|
19413
|
+
RESET = COLOR ? ANSI_RESET : "";
|
|
19414
|
+
PINK = COLOR ? brandAnsi("pink") : "";
|
|
19415
|
+
GREEN = COLOR ? brandAnsi("guide") : "";
|
|
19416
|
+
RED = COLOR ? brandAnsi("warn") : "";
|
|
19059
19417
|
});
|
|
19060
19418
|
|
|
19061
19419
|
// lib/claude-sessions.ts
|
|
19062
|
-
import { readdirSync as readdirSync10, statSync as statSync12, existsSync as
|
|
19063
|
-
import { join as
|
|
19420
|
+
import { readdirSync as readdirSync10, statSync as statSync12, existsSync as existsSync15 } from "node:fs";
|
|
19421
|
+
import { join as join26, basename as basename4 } from "node:path";
|
|
19064
19422
|
function getClaudeProjectsRoot() {
|
|
19065
19423
|
return getClaudeProjectsPath();
|
|
19066
19424
|
}
|
|
@@ -19075,7 +19433,7 @@ function listClaudeProjects() {
|
|
|
19075
19433
|
return entries.filter((e) => e.isDirectory()).map((e) => ({
|
|
19076
19434
|
name: e.name,
|
|
19077
19435
|
cwd: decodeFolderName(e.name),
|
|
19078
|
-
path:
|
|
19436
|
+
path: join26(root, e.name)
|
|
19079
19437
|
}));
|
|
19080
19438
|
}
|
|
19081
19439
|
function listClaudeTranscripts(project) {
|
|
@@ -19091,7 +19449,7 @@ function listClaudeTranscripts(project) {
|
|
|
19091
19449
|
const sessionId = entry.name.slice(0, -".jsonl".length);
|
|
19092
19450
|
if (!UUID_RE2.test(sessionId))
|
|
19093
19451
|
continue;
|
|
19094
|
-
const transcriptPath =
|
|
19452
|
+
const transcriptPath = join26(project.path, entry.name);
|
|
19095
19453
|
try {
|
|
19096
19454
|
const s = statSync12(transcriptPath);
|
|
19097
19455
|
out.push({
|
|
@@ -19105,8 +19463,8 @@ function listClaudeTranscripts(project) {
|
|
|
19105
19463
|
});
|
|
19106
19464
|
} catch {}
|
|
19107
19465
|
} else if (entry.isDirectory() && UUID_RE2.test(entry.name)) {
|
|
19108
|
-
const subDir =
|
|
19109
|
-
if (!
|
|
19466
|
+
const subDir = join26(project.path, entry.name, "subagents");
|
|
19467
|
+
if (!existsSync15(subDir))
|
|
19110
19468
|
continue;
|
|
19111
19469
|
let subEntries;
|
|
19112
19470
|
try {
|
|
@@ -19118,7 +19476,7 @@ function listClaudeTranscripts(project) {
|
|
|
19118
19476
|
if (!sub.isFile() || !sub.name.endsWith(".jsonl"))
|
|
19119
19477
|
continue;
|
|
19120
19478
|
const agentId = sub.name.slice(0, -".jsonl".length);
|
|
19121
|
-
const transcriptPath =
|
|
19479
|
+
const transcriptPath = join26(subDir, sub.name);
|
|
19122
19480
|
try {
|
|
19123
19481
|
const s = statSync12(transcriptPath);
|
|
19124
19482
|
out.push({
|
|
@@ -20372,9 +20730,9 @@ var init_features = __esm(() => {
|
|
|
20372
20730
|
|
|
20373
20731
|
// src/audit/cache.ts
|
|
20374
20732
|
import { createHash } from "node:crypto";
|
|
20375
|
-
import { existsSync as
|
|
20376
|
-
import { join as
|
|
20377
|
-
import { homedir as
|
|
20733
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync8, chmodSync as chmodSync2 } from "node:fs";
|
|
20734
|
+
import { join as join27 } from "node:path";
|
|
20735
|
+
import { homedir as homedir26 } from "node:os";
|
|
20378
20736
|
function getEngineVersion() {
|
|
20379
20737
|
if (cachedEngineVersion)
|
|
20380
20738
|
return cachedEngineVersion;
|
|
@@ -20392,18 +20750,18 @@ function getDetectorVersion() {
|
|
|
20392
20750
|
return cachedDetectorVersion;
|
|
20393
20751
|
}
|
|
20394
20752
|
function getCachePathFor(transcriptPath) {
|
|
20395
|
-
const root =
|
|
20753
|
+
const root = join27(homedir26(), ".failproofai", "cache", "audit");
|
|
20396
20754
|
const key = createHash("sha1").update(transcriptPath).digest("hex");
|
|
20397
|
-
return
|
|
20755
|
+
return join27(root, `${key}.json`);
|
|
20398
20756
|
}
|
|
20399
20757
|
function readCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes) {
|
|
20400
20758
|
if (sizeBytes === 0)
|
|
20401
20759
|
return null;
|
|
20402
20760
|
const cachePath = getCachePathFor(transcriptPath);
|
|
20403
|
-
if (!
|
|
20761
|
+
if (!existsSync16(cachePath))
|
|
20404
20762
|
return null;
|
|
20405
20763
|
try {
|
|
20406
|
-
const raw =
|
|
20764
|
+
const raw = readFileSync14(cachePath, "utf-8");
|
|
20407
20765
|
const entry = JSON.parse(raw);
|
|
20408
20766
|
if (entry.schemaVersion !== CACHE_SCHEMA_VERSION)
|
|
20409
20767
|
return null;
|
|
@@ -20427,7 +20785,7 @@ function writeCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes, result)
|
|
|
20427
20785
|
return;
|
|
20428
20786
|
const cachePath = getCachePathFor(transcriptPath);
|
|
20429
20787
|
try {
|
|
20430
|
-
|
|
20788
|
+
mkdirSync9(join27(homedir26(), ".failproofai", "cache", "audit"), { recursive: true });
|
|
20431
20789
|
const entry = {
|
|
20432
20790
|
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
20433
20791
|
cachedAt: Date.now(),
|
|
@@ -20437,7 +20795,7 @@ function writeCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes, result)
|
|
|
20437
20795
|
detectorVersion: getDetectorVersion(),
|
|
20438
20796
|
result
|
|
20439
20797
|
};
|
|
20440
|
-
|
|
20798
|
+
writeFileSync8(cachePath, JSON.stringify(entry), { encoding: "utf-8", mode: 384 });
|
|
20441
20799
|
try {
|
|
20442
20800
|
chmodSync2(cachePath, 384);
|
|
20443
20801
|
} catch {}
|
|
@@ -20799,10 +21157,10 @@ var init_audit = __esm(() => {
|
|
|
20799
21157
|
});
|
|
20800
21158
|
|
|
20801
21159
|
// src/audit/dashboard-cache.ts
|
|
20802
|
-
import { join as
|
|
20803
|
-
import { homedir as
|
|
21160
|
+
import { join as join28 } from "node:path";
|
|
21161
|
+
import { homedir as homedir27 } from "node:os";
|
|
20804
21162
|
function getCachePath() {
|
|
20805
|
-
return
|
|
21163
|
+
return join28(homedir27(), ".failproofai", "audit-dashboard.json");
|
|
20806
21164
|
}
|
|
20807
21165
|
function writeDashboardCache(params, result) {
|
|
20808
21166
|
try {
|
|
@@ -20892,14 +21250,14 @@ var POLL_INTERVAL_MS = 150, POLL_TIMEOUT_MS = 30000;
|
|
|
20892
21250
|
var init_open_browser = () => {};
|
|
20893
21251
|
|
|
20894
21252
|
// scripts/parse-script-args.ts
|
|
20895
|
-
import { resolve as
|
|
21253
|
+
import { resolve as resolve12 } from "path";
|
|
20896
21254
|
function parseStringFlag(flagName, errorLabel, inlineValue, args, index, options) {
|
|
20897
21255
|
const raw = inlineValue ?? args[index + 1];
|
|
20898
21256
|
if (raw === undefined || inlineValue === null && raw.startsWith("-")) {
|
|
20899
21257
|
console.error(`Error: ${flagName} requires ${errorLabel}`);
|
|
20900
21258
|
process.exit(1);
|
|
20901
21259
|
}
|
|
20902
|
-
const value = options?.resolve ?
|
|
21260
|
+
const value = options?.resolve ? resolve12(raw) : raw;
|
|
20903
21261
|
return { value, spliceCount: inlineValue !== null ? 1 : 2 };
|
|
20904
21262
|
}
|
|
20905
21263
|
function parseScriptArgs(argv) {
|
|
@@ -20947,21 +21305,21 @@ function parseScriptArgs(argv) {
|
|
|
20947
21305
|
var init_parse_script_args = () => {};
|
|
20948
21306
|
|
|
20949
21307
|
// scripts/install-diagnosis.mjs
|
|
20950
|
-
import { existsSync as
|
|
20951
|
-
import { dirname as dirname6, resolve as
|
|
20952
|
-
import { homedir as
|
|
21308
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15, realpathSync } from "node:fs";
|
|
21309
|
+
import { dirname as dirname6, resolve as resolve13 } from "node:path";
|
|
21310
|
+
import { homedir as homedir28, platform as platform4 } from "node:os";
|
|
20953
21311
|
import { spawnSync } from "node:child_process";
|
|
20954
21312
|
function findPackageRoot(start) {
|
|
20955
21313
|
try {
|
|
20956
21314
|
let dir = realpathSync(start);
|
|
20957
|
-
if (
|
|
21315
|
+
if (existsSync17(dir) && !existsSync17(resolve13(dir, "package.json"))) {
|
|
20958
21316
|
dir = dirname6(dir);
|
|
20959
21317
|
}
|
|
20960
21318
|
while (true) {
|
|
20961
|
-
const pkgPath =
|
|
20962
|
-
if (
|
|
21319
|
+
const pkgPath = resolve13(dir, "package.json");
|
|
21320
|
+
if (existsSync17(pkgPath)) {
|
|
20963
21321
|
try {
|
|
20964
|
-
const pkg = JSON.parse(
|
|
21322
|
+
const pkg = JSON.parse(readFileSync15(pkgPath, "utf8"));
|
|
20965
21323
|
if (pkg.name === PKG_NAME)
|
|
20966
21324
|
return dir;
|
|
20967
21325
|
} catch {}
|
|
@@ -20979,7 +21337,7 @@ function readPackageVersion(packageRoot) {
|
|
|
20979
21337
|
if (!packageRoot)
|
|
20980
21338
|
return null;
|
|
20981
21339
|
try {
|
|
20982
|
-
const pkg = JSON.parse(
|
|
21340
|
+
const pkg = JSON.parse(readFileSync15(resolve13(packageRoot, "package.json"), "utf8"));
|
|
20983
21341
|
return typeof pkg.version === "string" ? pkg.version : null;
|
|
20984
21342
|
} catch {
|
|
20985
21343
|
return null;
|
|
@@ -20987,7 +21345,7 @@ function readPackageVersion(packageRoot) {
|
|
|
20987
21345
|
}
|
|
20988
21346
|
function resolvePathFirstBinary() {
|
|
20989
21347
|
try {
|
|
20990
|
-
const isWin =
|
|
21348
|
+
const isWin = platform4() === "win32";
|
|
20991
21349
|
const res = isWin ? spawnSync("where", [PKG_NAME], { encoding: "utf8" }) : spawnSync("sh", ["-c", `command -v ${PKG_NAME}`], { encoding: "utf8" });
|
|
20992
21350
|
if (res.status !== 0)
|
|
20993
21351
|
return null;
|
|
@@ -21005,16 +21363,16 @@ function locateNpmGlobal() {
|
|
|
21005
21363
|
const root = (res.stdout || "").trim();
|
|
21006
21364
|
if (!root)
|
|
21007
21365
|
return null;
|
|
21008
|
-
const candidate =
|
|
21009
|
-
return
|
|
21366
|
+
const candidate = resolve13(root, PKG_NAME);
|
|
21367
|
+
return existsSync17(resolve13(candidate, "package.json")) ? candidate : null;
|
|
21010
21368
|
} catch {
|
|
21011
21369
|
return null;
|
|
21012
21370
|
}
|
|
21013
21371
|
}
|
|
21014
21372
|
function locateBunGlobal() {
|
|
21015
21373
|
try {
|
|
21016
|
-
const candidate =
|
|
21017
|
-
return
|
|
21374
|
+
const candidate = resolve13(homedir28(), ".bun", "install", "global", "node_modules", PKG_NAME);
|
|
21375
|
+
return existsSync17(resolve13(candidate, "package.json")) ? candidate : null;
|
|
21018
21376
|
} catch {
|
|
21019
21377
|
return null;
|
|
21020
21378
|
}
|
|
@@ -21022,8 +21380,8 @@ function locateBunGlobal() {
|
|
|
21022
21380
|
function buildRecommendation(pathFirstBin) {
|
|
21023
21381
|
if (!pathFirstBin)
|
|
21024
21382
|
return null;
|
|
21025
|
-
const bunBinPrefix =
|
|
21026
|
-
const bunGlobalPrefix =
|
|
21383
|
+
const bunBinPrefix = resolve13(homedir28(), ".bun", "bin") + "/";
|
|
21384
|
+
const bunGlobalPrefix = resolve13(homedir28(), ".bun", "install", "global") + "/";
|
|
21027
21385
|
const isBun = pathFirstBin.startsWith(bunBinPrefix) || pathFirstBin.startsWith(bunGlobalPrefix);
|
|
21028
21386
|
if (isBun) {
|
|
21029
21387
|
return `rm -f ~/.bun/bin/${PKG_NAME} && rm -rf ~/.bun/install/global/node_modules/${PKG_NAME}`;
|
|
@@ -21103,8 +21461,8 @@ __export(exports_launch, {
|
|
|
21103
21461
|
launch: () => launch
|
|
21104
21462
|
});
|
|
21105
21463
|
import { spawn as spawn2 } from "child_process";
|
|
21106
|
-
import { realpathSync as realpathSync2, existsSync as
|
|
21107
|
-
import { resolve as
|
|
21464
|
+
import { realpathSync as realpathSync2, existsSync as existsSync18 } from "node:fs";
|
|
21465
|
+
import { resolve as resolve14, dirname as dirname7 } from "node:path";
|
|
21108
21466
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
21109
21467
|
import { createInterface as createInterface2 } from "node:readline";
|
|
21110
21468
|
function launch(mode) {
|
|
@@ -21119,9 +21477,9 @@ function launch(mode) {
|
|
|
21119
21477
|
process.env.PORT = port;
|
|
21120
21478
|
process.env.HOSTNAME = "0.0.0.0";
|
|
21121
21479
|
cmd = "node";
|
|
21122
|
-
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ??
|
|
21123
|
-
const serverJsPath =
|
|
21124
|
-
if (!
|
|
21480
|
+
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve14(dirname7(realpathSync2(fileURLToPath2(import.meta.url))), "..");
|
|
21481
|
+
const serverJsPath = resolve14(packageRoot, ".next/standalone/server.js");
|
|
21482
|
+
if (!existsSync18(serverJsPath)) {
|
|
21125
21483
|
let shadowMessage = null;
|
|
21126
21484
|
try {
|
|
21127
21485
|
const diag = diagnoseShadow({ selfPackageRoot: packageRoot, selfVersion: version2 });
|
|
@@ -21332,9 +21690,20 @@ function printSummary(result) {
|
|
|
21332
21690
|
process.stdout.write(` ${line}
|
|
21333
21691
|
`);
|
|
21334
21692
|
}
|
|
21693
|
+
function auditCompletedProps(source, result) {
|
|
21694
|
+
return {
|
|
21695
|
+
source,
|
|
21696
|
+
events_scanned: result.eventsScanned,
|
|
21697
|
+
sessions_scanned: result.transcripts.scanned,
|
|
21698
|
+
total_hits: result.totals.hits,
|
|
21699
|
+
findings: result.results.length
|
|
21700
|
+
};
|
|
21701
|
+
}
|
|
21335
21702
|
async function runPostSetupAudit() {
|
|
21336
21703
|
if (process.env.FAILPROOFAI_NO_AUTO_AUDIT === "1")
|
|
21337
21704
|
return;
|
|
21705
|
+
const instanceId = getInstanceId2();
|
|
21706
|
+
trackHookEvent2(instanceId, "cli_audit_started", { source: "onboarding" });
|
|
21338
21707
|
process.stdout.write(`
|
|
21339
21708
|
${c(PINK2, "✦")} ${c(BOLD, "failproofai audit now running")} ${c(DIM2, "· ctrl+c to stop")}
|
|
21340
21709
|
|
|
@@ -21342,12 +21711,18 @@ async function runPostSetupAudit() {
|
|
|
21342
21711
|
let result;
|
|
21343
21712
|
try {
|
|
21344
21713
|
result = await runWithProgress({});
|
|
21345
|
-
} catch {
|
|
21714
|
+
} catch (err) {
|
|
21715
|
+
await trackHookEvent2(instanceId, "cli_audit_failed", {
|
|
21716
|
+
source: "onboarding",
|
|
21717
|
+
error_type: err instanceof Error ? err.name : "unknown",
|
|
21718
|
+
error_message: sanitizeErrorMessage(err)
|
|
21719
|
+
});
|
|
21346
21720
|
process.stdout.write(` ${c(PINK2, "!")} ${c(DIM2, "audit couldn't finish — run")} ${c(CYAN, "failproofai audit")} ${c(DIM2, "later.")}
|
|
21347
21721
|
|
|
21348
21722
|
`);
|
|
21349
21723
|
return;
|
|
21350
21724
|
}
|
|
21725
|
+
await trackHookEvent2(instanceId, "cli_audit_completed", auditCompletedProps("onboarding", result));
|
|
21351
21726
|
if (result.eventsScanned === 0) {
|
|
21352
21727
|
process.stdout.write(`
|
|
21353
21728
|
${c(DIM2, "no agent sessions to audit yet — come back after using your agent.")}
|
|
@@ -21386,13 +21761,7 @@ async function runAuditCli(args) {
|
|
|
21386
21761
|
die(`Audit failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
21387
21762
|
}
|
|
21388
21763
|
printSummary(result);
|
|
21389
|
-
await trackHookEvent2(instanceId, "cli_audit_completed",
|
|
21390
|
-
source: "cli",
|
|
21391
|
-
events_scanned: result.eventsScanned,
|
|
21392
|
-
sessions_scanned: result.transcripts.scanned,
|
|
21393
|
-
total_hits: result.totals.hits,
|
|
21394
|
-
findings: result.results.length
|
|
21395
|
-
});
|
|
21764
|
+
await trackHookEvent2(instanceId, "cli_audit_completed", auditCompletedProps("cli", result));
|
|
21396
21765
|
if (result.eventsScanned === 0) {
|
|
21397
21766
|
process.stdout.write(`
|
|
21398
21767
|
${c(DIM2, "no agent sessions found yet.")}
|
|
@@ -21418,7 +21787,7 @@ async function runAuditCli(args) {
|
|
|
21418
21787
|
const { launch: launch2 } = await Promise.resolve().then(() => (init_launch(), exports_launch));
|
|
21419
21788
|
launch2("start");
|
|
21420
21789
|
}
|
|
21421
|
-
var DASHBOARD_PORT = 8020, AUDIT_STAGES, HELP2, RESET2
|
|
21790
|
+
var DASHBOARD_PORT = 8020, AUDIT_STAGES, HELP2, RESET2, DIM2, BOLD, PINK2, GREEN2, CYAN, SPINNER;
|
|
21422
21791
|
var init_cli2 = __esm(() => {
|
|
21423
21792
|
init_audit();
|
|
21424
21793
|
init_dashboard_cache();
|
|
@@ -21426,6 +21795,7 @@ var init_cli2 = __esm(() => {
|
|
|
21426
21795
|
init_telemetry_id2();
|
|
21427
21796
|
init_telemetry_sanitize();
|
|
21428
21797
|
init_open_browser();
|
|
21798
|
+
init_tui();
|
|
21429
21799
|
AUDIT_STAGES = [
|
|
21430
21800
|
{ label: "discovering transcripts", detail: "walking ~/.claude, ~/.codex, ~/.cursor, …" },
|
|
21431
21801
|
{ label: "parsing session logs", detail: "reading JSONL + sqlite session stores" },
|
|
@@ -21449,13 +21819,19 @@ WHAT IT DOES
|
|
|
21449
21819
|
Runs fully offline — no account or network required. Press Ctrl+C to stop the
|
|
21450
21820
|
dashboard server when you're done.
|
|
21451
21821
|
`.trimStart();
|
|
21822
|
+
RESET2 = ANSI_RESET;
|
|
21823
|
+
DIM2 = ANSI_DIM;
|
|
21824
|
+
BOLD = ANSI_BOLD;
|
|
21825
|
+
PINK2 = brandAnsi("pink");
|
|
21826
|
+
GREEN2 = brandAnsi("guide");
|
|
21827
|
+
CYAN = brandAnsi("guide");
|
|
21452
21828
|
SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
21453
21829
|
});
|
|
21454
21830
|
|
|
21455
21831
|
// src/hooks/manager.ts
|
|
21456
|
-
import { execSync as
|
|
21457
|
-
import { resolve as
|
|
21458
|
-
import { homedir as
|
|
21832
|
+
import { execSync as execSync7 } from "node:child_process";
|
|
21833
|
+
import { resolve as resolve15, basename as basename5 } from "node:path";
|
|
21834
|
+
import { homedir as homedir29, platform as platform5, arch as arch4, release as release3, hostname as hostname4 } from "node:os";
|
|
21459
21835
|
function getSettingsPath2(scope, cwd) {
|
|
21460
21836
|
return claudeCode.getSettingsPath(scope, cwd);
|
|
21461
21837
|
}
|
|
@@ -21475,7 +21851,7 @@ function resolveFailproofaiBinary2() {
|
|
|
21475
21851
|
return override.trim();
|
|
21476
21852
|
try {
|
|
21477
21853
|
const cmd = process.platform === "win32" ? "where failproofai" : "which failproofai";
|
|
21478
|
-
const result =
|
|
21854
|
+
const result = execSync7(cmd, { encoding: "utf8" }).trim();
|
|
21479
21855
|
return result.split(`
|
|
21480
21856
|
`)[0].trim();
|
|
21481
21857
|
} catch {
|
|
@@ -21561,7 +21937,7 @@ async function installHooksImpl2(policyNames, scope = "user", cwd, includeBeta =
|
|
|
21561
21937
|
if (removeCustomHooks) {
|
|
21562
21938
|
delete configToWrite.customPoliciesPath;
|
|
21563
21939
|
} else if (customPoliciesPath) {
|
|
21564
|
-
configToWrite.customPoliciesPath =
|
|
21940
|
+
configToWrite.customPoliciesPath = resolve15(customPoliciesPath);
|
|
21565
21941
|
let validatedHooks = [];
|
|
21566
21942
|
try {
|
|
21567
21943
|
validatedHooks = await loadCustomHooks(configToWrite.customPoliciesPath, { strict: true });
|
|
@@ -21633,10 +22009,10 @@ Enabled ${selectedPolicies.length} policy(ies): ${selectedPolicies.join(", ")}
|
|
|
21633
22009
|
policies_added: policiesAdded,
|
|
21634
22010
|
policies_removed: policiesRemoved,
|
|
21635
22011
|
...source ? { source } : {},
|
|
21636
|
-
platform:
|
|
21637
|
-
arch:
|
|
21638
|
-
os_release:
|
|
21639
|
-
hostname_hash: hashToId2(
|
|
22012
|
+
platform: platform5(),
|
|
22013
|
+
arch: arch4(),
|
|
22014
|
+
os_release: release3(),
|
|
22015
|
+
hostname_hash: hashToId2(hostname4()),
|
|
21640
22016
|
has_custom_hooks_path: !!configToWrite.customPoliciesPath,
|
|
21641
22017
|
has_policy_params: !!(configToWrite.policyParams && Object.keys(configToWrite.policyParams).length > 0),
|
|
21642
22018
|
param_policy_names: configToWrite.policyParams ? Object.keys(configToWrite.policyParams) : [],
|
|
@@ -21881,9 +22257,20 @@ function printSummary2(result) {
|
|
|
21881
22257
|
process.stdout.write(` ${line}
|
|
21882
22258
|
`);
|
|
21883
22259
|
}
|
|
22260
|
+
function auditCompletedProps2(source, result) {
|
|
22261
|
+
return {
|
|
22262
|
+
source,
|
|
22263
|
+
events_scanned: result.eventsScanned,
|
|
22264
|
+
sessions_scanned: result.transcripts.scanned,
|
|
22265
|
+
total_hits: result.totals.hits,
|
|
22266
|
+
findings: result.results.length
|
|
22267
|
+
};
|
|
22268
|
+
}
|
|
21884
22269
|
async function runPostSetupAudit2() {
|
|
21885
22270
|
if (process.env.FAILPROOFAI_NO_AUTO_AUDIT === "1")
|
|
21886
22271
|
return;
|
|
22272
|
+
const instanceId = getInstanceId2();
|
|
22273
|
+
trackHookEvent2(instanceId, "cli_audit_started", { source: "onboarding" });
|
|
21887
22274
|
process.stdout.write(`
|
|
21888
22275
|
${c2(PINK3, "✦")} ${c2(BOLD2, "failproofai audit now running")} ${c2(DIM3, "· ctrl+c to stop")}
|
|
21889
22276
|
|
|
@@ -21891,12 +22278,18 @@ async function runPostSetupAudit2() {
|
|
|
21891
22278
|
let result;
|
|
21892
22279
|
try {
|
|
21893
22280
|
result = await runWithProgress2({});
|
|
21894
|
-
} catch {
|
|
22281
|
+
} catch (err) {
|
|
22282
|
+
await trackHookEvent2(instanceId, "cli_audit_failed", {
|
|
22283
|
+
source: "onboarding",
|
|
22284
|
+
error_type: err instanceof Error ? err.name : "unknown",
|
|
22285
|
+
error_message: sanitizeErrorMessage(err)
|
|
22286
|
+
});
|
|
21895
22287
|
process.stdout.write(` ${c2(PINK3, "!")} ${c2(DIM3, "audit couldn't finish — run")} ${c2(CYAN2, "failproofai audit")} ${c2(DIM3, "later.")}
|
|
21896
22288
|
|
|
21897
22289
|
`);
|
|
21898
22290
|
return;
|
|
21899
22291
|
}
|
|
22292
|
+
await trackHookEvent2(instanceId, "cli_audit_completed", auditCompletedProps2("onboarding", result));
|
|
21900
22293
|
if (result.eventsScanned === 0) {
|
|
21901
22294
|
process.stdout.write(`
|
|
21902
22295
|
${c2(DIM3, "no agent sessions to audit yet — come back after using your agent.")}
|
|
@@ -21935,13 +22328,7 @@ async function runAuditCli2(args) {
|
|
|
21935
22328
|
die2(`Audit failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
21936
22329
|
}
|
|
21937
22330
|
printSummary2(result);
|
|
21938
|
-
await trackHookEvent2(instanceId, "cli_audit_completed",
|
|
21939
|
-
source: "cli",
|
|
21940
|
-
events_scanned: result.eventsScanned,
|
|
21941
|
-
sessions_scanned: result.transcripts.scanned,
|
|
21942
|
-
total_hits: result.totals.hits,
|
|
21943
|
-
findings: result.results.length
|
|
21944
|
-
});
|
|
22331
|
+
await trackHookEvent2(instanceId, "cli_audit_completed", auditCompletedProps2("cli", result));
|
|
21945
22332
|
if (result.eventsScanned === 0) {
|
|
21946
22333
|
process.stdout.write(`
|
|
21947
22334
|
${c2(DIM3, "no agent sessions found yet.")}
|
|
@@ -21967,7 +22354,7 @@ async function runAuditCli2(args) {
|
|
|
21967
22354
|
const { launch: launch2 } = await Promise.resolve().then(() => (init_launch(), exports_launch));
|
|
21968
22355
|
launch2("start");
|
|
21969
22356
|
}
|
|
21970
|
-
var DASHBOARD_PORT2 = 8020, AUDIT_STAGES2, HELP3, RESET3
|
|
22357
|
+
var DASHBOARD_PORT2 = 8020, AUDIT_STAGES2, HELP3, RESET3, DIM3, BOLD2, PINK3, GREEN3, CYAN2, SPINNER2;
|
|
21971
22358
|
var init_cli3 = __esm(() => {
|
|
21972
22359
|
init_audit();
|
|
21973
22360
|
init_dashboard_cache();
|
|
@@ -21975,6 +22362,7 @@ var init_cli3 = __esm(() => {
|
|
|
21975
22362
|
init_telemetry_id2();
|
|
21976
22363
|
init_telemetry_sanitize();
|
|
21977
22364
|
init_open_browser();
|
|
22365
|
+
init_tui();
|
|
21978
22366
|
AUDIT_STAGES2 = [
|
|
21979
22367
|
{ label: "discovering transcripts", detail: "walking ~/.claude, ~/.codex, ~/.cursor, …" },
|
|
21980
22368
|
{ label: "parsing session logs", detail: "reading JSONL + sqlite session stores" },
|
|
@@ -21998,32 +22386,41 @@ WHAT IT DOES
|
|
|
21998
22386
|
Runs fully offline — no account or network required. Press Ctrl+C to stop the
|
|
21999
22387
|
dashboard server when you're done.
|
|
22000
22388
|
`.trimStart();
|
|
22389
|
+
RESET3 = ANSI_RESET;
|
|
22390
|
+
DIM3 = ANSI_DIM;
|
|
22391
|
+
BOLD2 = ANSI_BOLD;
|
|
22392
|
+
PINK3 = brandAnsi("pink");
|
|
22393
|
+
GREEN3 = brandAnsi("guide");
|
|
22394
|
+
CYAN2 = brandAnsi("guide");
|
|
22001
22395
|
SPINNER2 = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
22002
22396
|
});
|
|
22003
22397
|
|
|
22004
22398
|
// src/hooks/configure-wizard.ts
|
|
22005
22399
|
var exports_configure_wizard = {};
|
|
22006
22400
|
__export(exports_configure_wizard, {
|
|
22401
|
+
setCustomPoliciesEnabled: () => setCustomPoliciesEnabled,
|
|
22007
22402
|
runConfigureWizard: () => runConfigureWizard,
|
|
22008
22403
|
reviewLines: () => reviewLines,
|
|
22009
22404
|
resolvePresetSelection: () => resolvePresetSelection,
|
|
22010
22405
|
maybeFirstRunConfigure: () => maybeFirstRunConfigure,
|
|
22011
22406
|
markLauncherSeen: () => markLauncherSeen,
|
|
22012
22407
|
hasSeenLauncher: () => hasSeenLauncher,
|
|
22408
|
+
describeCustomPolicies: () => describeCustomPolicies,
|
|
22409
|
+
clisSupportingScope: () => clisSupportingScope,
|
|
22013
22410
|
buildScopeChoices: () => buildScopeChoices,
|
|
22014
22411
|
buildPresetChoices: () => buildPresetChoices,
|
|
22015
22412
|
buildAgentChoices: () => buildAgentChoices
|
|
22016
22413
|
});
|
|
22017
|
-
import { existsSync as
|
|
22018
|
-
import { homedir as
|
|
22019
|
-
import { resolve as
|
|
22414
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync10, writeFileSync as writeFileSync9, readFileSync as readFileSync16 } from "node:fs";
|
|
22415
|
+
import { homedir as homedir30 } from "node:os";
|
|
22416
|
+
import { resolve as resolve16, sep as sep5 } from "node:path";
|
|
22020
22417
|
async function emit(event, props) {
|
|
22021
22418
|
try {
|
|
22022
22419
|
await trackHookEvent2(getInstanceId2(), event, props);
|
|
22023
22420
|
} catch {}
|
|
22024
22421
|
}
|
|
22025
22422
|
function homeify(p) {
|
|
22026
|
-
const home =
|
|
22423
|
+
const home = homedir30();
|
|
22027
22424
|
if (p === home)
|
|
22028
22425
|
return "~";
|
|
22029
22426
|
if (p.startsWith(home + sep5))
|
|
@@ -22044,6 +22441,9 @@ function buildScopeChoices(cwd) {
|
|
|
22044
22441
|
}
|
|
22045
22442
|
];
|
|
22046
22443
|
}
|
|
22444
|
+
function clisSupportingScope(scope) {
|
|
22445
|
+
return INTEGRATION_TYPES.filter((id) => getIntegration(id).scopes.includes(scope));
|
|
22446
|
+
}
|
|
22047
22447
|
function buildAgentChoices(scope, cwd) {
|
|
22048
22448
|
const detected = new Set(detectInstalledClis());
|
|
22049
22449
|
const ordered = [
|
|
@@ -22053,6 +22453,17 @@ function buildAgentChoices(scope, cwd) {
|
|
|
22053
22453
|
return ordered.map((id) => {
|
|
22054
22454
|
const integration = getIntegration(id);
|
|
22055
22455
|
const isDetected = detected.has(id);
|
|
22456
|
+
const supported = integration.scopes.includes(scope);
|
|
22457
|
+
if (!supported) {
|
|
22458
|
+
return {
|
|
22459
|
+
label: integration.displayName,
|
|
22460
|
+
value: id,
|
|
22461
|
+
checked: false,
|
|
22462
|
+
locked: true,
|
|
22463
|
+
section: "Global only · not configurable per-project",
|
|
22464
|
+
hint: `supports ${integration.scopes.join(", ")} scope — rerun with "Everywhere I code"`
|
|
22465
|
+
};
|
|
22466
|
+
}
|
|
22056
22467
|
let installedHere = false;
|
|
22057
22468
|
try {
|
|
22058
22469
|
installedHere = integration.hooksInstalledInSettings(scope, cwd);
|
|
@@ -22068,28 +22479,102 @@ function buildAgentChoices(scope, cwd) {
|
|
|
22068
22479
|
};
|
|
22069
22480
|
});
|
|
22070
22481
|
}
|
|
22071
|
-
function buildPresetChoices() {
|
|
22072
|
-
const choices = POLICY_PRESETS.map((p) => ({
|
|
22482
|
+
function buildPresetChoices(cwd = process.cwd(), enabled = true) {
|
|
22483
|
+
const choices = POLICY_PRESETS.map((p) => ({
|
|
22484
|
+
label: p.label,
|
|
22485
|
+
value: p.id,
|
|
22486
|
+
hint: p.description
|
|
22487
|
+
}));
|
|
22073
22488
|
choices.push({
|
|
22074
22489
|
label: "Everything",
|
|
22075
22490
|
value: EVERYTHING,
|
|
22076
22491
|
hint: `all ${resolveEverything().length} policies`
|
|
22077
22492
|
});
|
|
22493
|
+
const custom = describeCustomPolicies(cwd);
|
|
22494
|
+
const skipped = custom.warnings.length;
|
|
22495
|
+
const plural = (n) => `${n} file${n === 1 ? "" : "s"}`;
|
|
22496
|
+
const skippedNote = skipped > 0 ? ` · ${skipped} skipped, see next screen` : "";
|
|
22497
|
+
if (custom.fileCount > 0) {
|
|
22498
|
+
choices.push({
|
|
22499
|
+
label: "Custom",
|
|
22500
|
+
value: CUSTOM,
|
|
22501
|
+
checked: enabled,
|
|
22502
|
+
hint: `${plural(custom.fileCount)} in ${custom.scopes.join(" + ")}${skippedNote}`
|
|
22503
|
+
});
|
|
22504
|
+
} else {
|
|
22505
|
+
choices.push({
|
|
22506
|
+
label: "Custom",
|
|
22507
|
+
value: CUSTOM,
|
|
22508
|
+
locked: true,
|
|
22509
|
+
checked: false,
|
|
22510
|
+
summaryExclude: true,
|
|
22511
|
+
hint: skipped > 0 ? `${plural(skipped)} found but NOT loaded — see next screen` : "none yet · drop *-policies.mjs in .failproofai/policies/"
|
|
22512
|
+
});
|
|
22513
|
+
}
|
|
22078
22514
|
return choices;
|
|
22079
22515
|
}
|
|
22080
22516
|
function resolvePresetSelection(values) {
|
|
22081
|
-
|
|
22517
|
+
const selected = values.filter((v) => v !== CUSTOM);
|
|
22518
|
+
if (selected.includes(EVERYTHING))
|
|
22082
22519
|
return resolveEverything();
|
|
22083
|
-
return [...new Set(
|
|
22520
|
+
return [...new Set(selected.flatMap((id) => resolvePreset(id)))];
|
|
22521
|
+
}
|
|
22522
|
+
function setCustomPoliciesEnabled(scope, cwd, enabled) {
|
|
22523
|
+
if (enabled === undefined)
|
|
22524
|
+
return;
|
|
22525
|
+
const path3 = getConfigPathForScope(scope, cwd);
|
|
22526
|
+
let config = {};
|
|
22527
|
+
try {
|
|
22528
|
+
if (existsSync19(path3))
|
|
22529
|
+
config = JSON.parse(readFileSync16(path3, "utf8"));
|
|
22530
|
+
} catch {
|
|
22531
|
+
return;
|
|
22532
|
+
}
|
|
22533
|
+
if (enabled)
|
|
22534
|
+
delete config.customPoliciesEnabled;
|
|
22535
|
+
else
|
|
22536
|
+
config.customPoliciesEnabled = false;
|
|
22537
|
+
try {
|
|
22538
|
+
writeFileSync9(path3, JSON.stringify(config, null, 2) + `
|
|
22539
|
+
`, "utf8");
|
|
22540
|
+
} catch {}
|
|
22541
|
+
}
|
|
22542
|
+
function describeCustomPolicies(cwd) {
|
|
22543
|
+
const active = [];
|
|
22544
|
+
const warnings = [];
|
|
22545
|
+
const scopes = [];
|
|
22546
|
+
let fileCount = 0;
|
|
22547
|
+
const dirs = [
|
|
22548
|
+
{ dir: resolve16(cwd, ".failproofai", "policies"), label: "project" },
|
|
22549
|
+
{ dir: resolve16(homedir30(), ".failproofai", "policies"), label: "global" }
|
|
22550
|
+
];
|
|
22551
|
+
for (const { dir, label } of dirs) {
|
|
22552
|
+
const found = discoverPolicyFiles(dir);
|
|
22553
|
+
if (found.length > 0) {
|
|
22554
|
+
active.push(`${found.length} file${found.length === 1 ? "" : "s"} (${label})`);
|
|
22555
|
+
scopes.push(label);
|
|
22556
|
+
fileCount += found.length;
|
|
22557
|
+
}
|
|
22558
|
+
for (const name of findSkippedPolicyFiles(dir)) {
|
|
22559
|
+
warnings.push(`! ${homeify(resolve16(dir, name))} is NOT loaded — rename to ` + `${name.replace(/\.(js|mjs|ts)$/, "-policies.$1")}`);
|
|
22560
|
+
}
|
|
22561
|
+
}
|
|
22562
|
+
return { active, warnings, fileCount, scopes };
|
|
22084
22563
|
}
|
|
22085
22564
|
function reviewLines(state) {
|
|
22086
|
-
const { scope, clis, policies, cwd } = state;
|
|
22565
|
+
const { scope, clis, policies, cwd, customEnabled } = state;
|
|
22087
22566
|
const where = scope === "project" ? `This project (${homeify(cwd)})` : "Everywhere (global)";
|
|
22088
22567
|
const lines = [];
|
|
22089
22568
|
const assistantNames = clis.map((c3) => getIntegration(c3).displayName);
|
|
22090
22569
|
lines.push(` Where : ${where}`);
|
|
22091
22570
|
lines.push(` Assistants : ${assistantNames.length ? summarize(assistantNames, "assistants") : "(none)"}`);
|
|
22092
22571
|
lines.push(` Policies : ${policies.length} enabled`);
|
|
22572
|
+
const custom = describeCustomPolicies(cwd);
|
|
22573
|
+
if (custom.active.length > 0) {
|
|
22574
|
+
lines.push(` Custom : ${custom.active.join(" · ")} ${customEnabled === false ? "— DISABLED, will not load" : DIM_NOTE}`);
|
|
22575
|
+
}
|
|
22576
|
+
for (const warning of custom.warnings)
|
|
22577
|
+
lines.push(` ${warning}`);
|
|
22093
22578
|
lines.push("");
|
|
22094
22579
|
lines.push(" This will update:");
|
|
22095
22580
|
for (const cli of clis) {
|
|
@@ -22100,15 +22585,15 @@ function reviewLines(state) {
|
|
|
22100
22585
|
return lines;
|
|
22101
22586
|
}
|
|
22102
22587
|
function firstRunMarkerPath() {
|
|
22103
|
-
return
|
|
22588
|
+
return resolve16(homedir30(), ".failproofai", ".launcher-configured");
|
|
22104
22589
|
}
|
|
22105
22590
|
function hasSeenLauncher() {
|
|
22106
|
-
return
|
|
22591
|
+
return existsSync19(firstRunMarkerPath());
|
|
22107
22592
|
}
|
|
22108
22593
|
function markLauncherSeen() {
|
|
22109
22594
|
try {
|
|
22110
|
-
|
|
22111
|
-
|
|
22595
|
+
mkdirSync10(resolve16(homedir30(), ".failproofai"), { recursive: true });
|
|
22596
|
+
writeFileSync9(firstRunMarkerPath(), "1", "utf8");
|
|
22112
22597
|
} catch {}
|
|
22113
22598
|
}
|
|
22114
22599
|
function anyHooksInstalledGlobally() {
|
|
@@ -22179,7 +22664,8 @@ Use the flag form instead, e.g.:
|
|
|
22179
22664
|
{
|
|
22180
22665
|
label: "Everything available",
|
|
22181
22666
|
value: ALL_CLIS,
|
|
22182
|
-
hint: `protect all ${
|
|
22667
|
+
hint: `protect all ${clisSupportingScope(scope).length} CLIs configurable here`,
|
|
22668
|
+
summaryExclude: true
|
|
22183
22669
|
},
|
|
22184
22670
|
...buildAgentChoices(scope, cwd)
|
|
22185
22671
|
],
|
|
@@ -22191,10 +22677,14 @@ Use the flag form instead, e.g.:
|
|
|
22191
22677
|
});
|
|
22192
22678
|
if (clisSel === null)
|
|
22193
22679
|
return cancel();
|
|
22194
|
-
const
|
|
22680
|
+
const supported = new Set(clisSupportingScope(scope));
|
|
22681
|
+
const clis = (clisSel.includes(ALL_CLIS) ? [...INTEGRATION_TYPES] : clisSel.filter((v) => v !== ALL_CLIS)).filter((id) => supported.has(id));
|
|
22682
|
+
const customEnabledBefore = readHooksConfig().customPoliciesEnabled !== false;
|
|
22683
|
+
const presetChoices = buildPresetChoices(cwd, customEnabledBefore);
|
|
22684
|
+
const hasCustomFiles = describeCustomPolicies(cwd).fileCount > 0;
|
|
22195
22685
|
const presets = await multiSelect({
|
|
22196
22686
|
message: "What should we guard against?",
|
|
22197
|
-
choices:
|
|
22687
|
+
choices: presetChoices,
|
|
22198
22688
|
minSelected: 1,
|
|
22199
22689
|
summaryNoun: "bundles",
|
|
22200
22690
|
hint: "space toggles · combine presets · ↵ confirm",
|
|
@@ -22204,9 +22694,10 @@ Use the flag form instead, e.g.:
|
|
|
22204
22694
|
if (presets === null)
|
|
22205
22695
|
return cancel();
|
|
22206
22696
|
const policies = resolvePresetSelection(presets);
|
|
22697
|
+
const customEnabled = hasCustomFiles ? presets.includes(CUSTOM) : undefined;
|
|
22207
22698
|
const decision = await selectOne({
|
|
22208
22699
|
message: "Ready to apply?",
|
|
22209
|
-
body: reviewLines({ scope, clis, policies, cwd }),
|
|
22700
|
+
body: reviewLines({ scope, clis, policies, cwd, customEnabled }),
|
|
22210
22701
|
choices: [
|
|
22211
22702
|
{ label: "Yes, apply now", value: "apply", hint: "write the config" },
|
|
22212
22703
|
{ label: "Cancel", value: "cancel", hint: "quit, no changes" }
|
|
@@ -22224,13 +22715,15 @@ Use the flag form instead, e.g.:
|
|
|
22224
22715
|
source: presets.join("+")
|
|
22225
22716
|
});
|
|
22226
22717
|
await installHooks2(policies, scope, cwd, false, "configure-wizard", undefined, false, clis, { replace: true, quiet: true });
|
|
22718
|
+
setCustomPoliciesEnabled(scope, cwd, customEnabled);
|
|
22227
22719
|
await applied;
|
|
22228
22720
|
markLauncherSeen();
|
|
22229
|
-
const
|
|
22230
|
-
|
|
22721
|
+
const customNote = customEnabled === true ? " + your custom policies" : customEnabled === false ? " · custom policies DISABLED" : "";
|
|
22722
|
+
const assistants = `${clis.length} assistant${clis.length === 1 ? "" : "s"}`;
|
|
22723
|
+
outro(`Setup complete — ${policies.length} policies${customNote} · ${assistants}`, { ok: true }, stdout);
|
|
22231
22724
|
return { applied: true, scope, clis, policies };
|
|
22232
22725
|
}
|
|
22233
|
-
var EVERYTHING = "__everything__", ALL_CLIS = "__all_clis__";
|
|
22726
|
+
var EVERYTHING = "__everything__", ALL_CLIS = "__all_clis__", CUSTOM = "__custom__", DIM_NOTE = "(auto-loaded)";
|
|
22234
22727
|
var init_configure_wizard = __esm(() => {
|
|
22235
22728
|
init_tui();
|
|
22236
22729
|
init_integrations();
|
|
@@ -22238,6 +22731,7 @@ var init_configure_wizard = __esm(() => {
|
|
|
22238
22731
|
init_manager2();
|
|
22239
22732
|
init_hooks_config();
|
|
22240
22733
|
init_policy_presets();
|
|
22734
|
+
init_custom_hooks_loader();
|
|
22241
22735
|
init_hook_telemetry2();
|
|
22242
22736
|
init_telemetry_id2();
|
|
22243
22737
|
});
|
|
@@ -22248,8 +22742,8 @@ __export(exports_launch2, {
|
|
|
22248
22742
|
launch: () => launch2
|
|
22249
22743
|
});
|
|
22250
22744
|
import { spawn as spawn3 } from "child_process";
|
|
22251
|
-
import { realpathSync as realpathSync3, existsSync as
|
|
22252
|
-
import { resolve as
|
|
22745
|
+
import { realpathSync as realpathSync3, existsSync as existsSync20 } from "node:fs";
|
|
22746
|
+
import { resolve as resolve17, dirname as dirname8 } from "node:path";
|
|
22253
22747
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
22254
22748
|
import { createInterface as createInterface3 } from "node:readline";
|
|
22255
22749
|
function launch2(mode) {
|
|
@@ -22264,9 +22758,9 @@ function launch2(mode) {
|
|
|
22264
22758
|
process.env.PORT = port;
|
|
22265
22759
|
process.env.HOSTNAME = "0.0.0.0";
|
|
22266
22760
|
cmd = "node";
|
|
22267
|
-
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ??
|
|
22268
|
-
const serverJsPath =
|
|
22269
|
-
if (!
|
|
22761
|
+
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve17(dirname8(realpathSync3(fileURLToPath3(import.meta.url))), "..");
|
|
22762
|
+
const serverJsPath = resolve17(packageRoot, ".next/standalone/server.js");
|
|
22763
|
+
if (!existsSync20(serverJsPath)) {
|
|
22270
22764
|
let shadowMessage = null;
|
|
22271
22765
|
try {
|
|
22272
22766
|
const diag = diagnoseShadow({ selfPackageRoot: packageRoot, selfVersion: version2 });
|
|
@@ -22360,17 +22854,17 @@ var init_cli_error2 = __esm(() => {
|
|
|
22360
22854
|
|
|
22361
22855
|
// bin/failproofai.mjs
|
|
22362
22856
|
import { realpathSync as realpathSync4 } from "fs";
|
|
22363
|
-
import { dirname as dirname9, resolve as
|
|
22857
|
+
import { dirname as dirname9, resolve as resolve18 } from "path";
|
|
22364
22858
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
22365
22859
|
// package.json
|
|
22366
|
-
var version = "0.0.14-beta.
|
|
22860
|
+
var version = "0.0.14-beta.2";
|
|
22367
22861
|
|
|
22368
22862
|
// bin/failproofai.mjs
|
|
22369
22863
|
if (!process.env.FAILPROOFAI_PACKAGE_ROOT) {
|
|
22370
|
-
process.env.FAILPROOFAI_PACKAGE_ROOT =
|
|
22864
|
+
process.env.FAILPROOFAI_PACKAGE_ROOT = resolve18(dirname9(realpathSync4(fileURLToPath4(import.meta.url))), "..");
|
|
22371
22865
|
}
|
|
22372
22866
|
if (!process.env.FAILPROOFAI_DIST_PATH) {
|
|
22373
|
-
process.env.FAILPROOFAI_DIST_PATH =
|
|
22867
|
+
process.env.FAILPROOFAI_DIST_PATH = resolve18(dirname9(realpathSync4(fileURLToPath4(import.meta.url))), "..", "dist");
|
|
22374
22868
|
}
|
|
22375
22869
|
var args = process.argv.slice(2);
|
|
22376
22870
|
if (args[0] === "p")
|
|
@@ -22423,6 +22917,10 @@ if (hookIdx >= 0) {
|
|
|
22423
22917
|
}
|
|
22424
22918
|
}
|
|
22425
22919
|
async function runCli() {
|
|
22920
|
+
try {
|
|
22921
|
+
const { maybeReportInstall: maybeReportInstall2 } = await Promise.resolve().then(() => (init_install_check(), exports_install_check));
|
|
22922
|
+
await maybeReportInstall2(version);
|
|
22923
|
+
} catch {}
|
|
22426
22924
|
const SUBCOMMANDS2 = ["policies", "policy", "auth", "audit", "config"];
|
|
22427
22925
|
if ((args.includes("--help") || args.includes("-h")) && !SUBCOMMANDS2.includes(args[0])) {
|
|
22428
22926
|
const extraArgs = args.filter((a) => a !== "--help" && a !== "-h");
|
|
@@ -22508,7 +23006,7 @@ EXAMPLES
|
|
|
22508
23006
|
LINKS
|
|
22509
23007
|
\u2B50 Star us: https://github.com/failproofai/failproofai
|
|
22510
23008
|
\uD83D\uDCD6 Docs: https://docs.befailproof.ai/introduction
|
|
22511
|
-
\uD83D\uDCAC Discord: https://discord.
|
|
23009
|
+
\uD83D\uDCAC Discord: https://discord.befailproof.ai/
|
|
22512
23010
|
`.trimStart());
|
|
22513
23011
|
process.exit(0);
|
|
22514
23012
|
}
|