failproofai 1.0.2-beta.1 → 1.0.2-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +5 -5
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
  6. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  11. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  12. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
  15. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  16. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
  20. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  21. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
  22. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
  32. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  33. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  35. package/.next/standalone/.next/server/app/index.html +1 -1
  36. package/.next/standalone/.next/server/app/index.rsc +14 -14
  37. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
  38. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  39. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  40. package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
  41. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  42. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
  45. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  46. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  48. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
  49. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  50. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
  53. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  54. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  55. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
  58. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  59. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +2 -2
  62. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
  63. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  65. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  66. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  67. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  68. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  69. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
  70. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
  71. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
  72. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__07gm3zl._.js +3 -3
  73. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0l4748x._.js → [root-of-the-server]__090sxxw._.js} +2 -2
  74. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
  75. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
  76. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
  77. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
  78. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
  79. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
  80. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/ssr/{_0bwu160._.js → _0wb8osu._.js} +2 -2
  82. package/.next/standalone/.next/server/chunks/ssr/{_0ns6k3a._.js → _1oggjel._.js} +1 -1
  83. package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  85. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  87. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
  89. package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
  90. package/.next/standalone/.next/server/pages/404.html +1 -1
  91. package/.next/standalone/.next/server/pages/500.html +1 -1
  92. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  93. package/.next/standalone/.next/server/server-reference-manifest.json +19 -19
  94. package/.next/standalone/.next/static/chunks/{1tynnrrh711lr.js → 0nnbtp0w4sxrr.js} +1 -1
  95. package/.next/standalone/.next/static/chunks/{22rqvlr7p_1mv.js → 0ykd_go4oahan.js} +1 -1
  96. package/.next/standalone/.next/static/chunks/{3tbbs_d8xrvyp.js → 140ip21rqmelt.js} +1 -1
  97. package/.next/standalone/.next/static/chunks/{0izgu7nqh2zp-.js → 1da5a_a-3btas.js} +1 -1
  98. package/.next/standalone/.next/static/chunks/{1oml7c7env4-g.js → 1fac8krph-zgp.js} +1 -1
  99. package/.next/standalone/.next/static/chunks/{2whxqyskpirbk.js → 1nzy5jc_vf9e0.js} +1 -1
  100. package/.next/standalone/.next/static/chunks/1yw71gn8vqco1.js +6 -0
  101. package/.next/standalone/.next/static/chunks/29eh4k77otcw6.js +1 -0
  102. package/.next/standalone/.next/static/chunks/2axi5ehjbld9h.js +1 -0
  103. package/.next/standalone/.next/static/chunks/{3ms6gxfm82t6s.js → 2fzxl7n717pbc.js} +1 -1
  104. package/.next/standalone/.next/static/chunks/{01u1cf8js2yd6.js → 3jjmdqqzem21x.js} +1 -1
  105. package/.next/standalone/.next/static/chunks/{turbopack-3kjgdgwci4tqf.js → turbopack-2vqpa-dts1gy4.js} +1 -1
  106. package/.next/standalone/package.json +9 -9
  107. package/.next/standalone/server.js +1 -1
  108. package/bin/failproofai.mjs +4 -4
  109. package/dist/cli.mjs +95 -154
  110. package/dist/worker.mjs +1 -2
  111. package/package.json +9 -9
  112. package/src/hooks/configure-wizard.ts +22 -86
  113. package/src/hooks/fp-reset.ts +9 -26
  114. package/src/hooks/manager.ts +44 -16
  115. package/src/hooks/pack-cli.ts +65 -0
  116. package/src/hooks/tui.ts +24 -8
  117. package/.next/standalone/.next/static/chunks/0u4-org_e7zde.js +0 -1
  118. package/.next/standalone/.next/static/chunks/31mwk8k0q3_3g.js +0 -6
  119. package/.next/standalone/.next/static/chunks/43nlc236oo898.js +0 -1
  120. /package/.next/standalone/.next/static/{I5kEb9kSgYS63j4iqfVLO → A7czO1PZdTcNzLGa_H1sm}/_buildManifest.js +0 -0
  121. /package/.next/standalone/.next/static/{I5kEb9kSgYS63j4iqfVLO → A7czO1PZdTcNzLGa_H1sm}/_clientMiddlewareManifest.js +0 -0
  122. /package/.next/standalone/.next/static/{I5kEb9kSgYS63j4iqfVLO → A7czO1PZdTcNzLGa_H1sm}/_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 = "1.0.2-beta.1", package_default;
22
+ var version2 = "1.0.2-beta.2", package_default;
23
23
  var init_package = __esm(() => {
24
24
  package_default = {
25
25
  name: "failproofai",
@@ -143,16 +143,16 @@ var init_package = __esm(() => {
143
143
  sharp: "0.35.0"
144
144
  },
145
145
  optionalDependencies: {
146
- "@failproofai/failproofaid-linux-x64": "1.0.2-beta.1",
147
- "@failproofai/failproofaid-linux-arm64": "1.0.2-beta.1",
148
- "@failproofai/failproofaid-darwin-x64": "1.0.2-beta.1",
149
- "@failproofai/failproofaid-darwin-arm64": "1.0.2-beta.1"
146
+ "@failproofai/failproofaid-linux-x64": "1.0.2-beta.2",
147
+ "@failproofai/failproofaid-linux-arm64": "1.0.2-beta.2",
148
+ "@failproofai/failproofaid-darwin-x64": "1.0.2-beta.2",
149
+ "@failproofai/failproofaid-darwin-arm64": "1.0.2-beta.2"
150
150
  },
151
151
  failproofaidBinaries: {
152
- "linux-x64": "a8c695cfe728e56403f981bd5ea2dc838cb862bd7349354946afead12fe0c36a",
153
- "linux-arm64": "674b596fe496ea51bf98864be7105fe1e34aacf0d588e35e2e3b455839837d94",
154
- "darwin-x64": "c56e5f68a509ec493d6d497ce0d221ab2fb9ff493ec3dd7dca49a41de8621b1e",
155
- "darwin-arm64": "73e80759bfd47c3473167f39b77bb2df3ab8fc1e891a8a3b3cefa9c1d83f6885"
152
+ "linux-x64": "fcfa5ae234e66eb6b57ec28445900c5f5a231f5f3a1fb0aeaca281d81f74c81e",
153
+ "linux-arm64": "a2bb9894d311a86740170128a706a9503fecc15ac5cbbc4587243151175a671c",
154
+ "darwin-x64": "97c1054b6229824ff7a9cbee67f3c1e2608db9e0b38a0dfc1adb21bf772a9666",
155
+ "darwin-arm64": "eb60b5fd3c1727f0d5406961367e2ea9b6c7fbc0b975247e7db664d502863f13"
156
156
  }
157
157
  };
158
158
  });
@@ -1589,22 +1589,6 @@ function readMergedHooksConfig(cwd) {
1589
1589
  ...llm !== undefined ? { llm } : {}
1590
1590
  };
1591
1591
  }
1592
- function getConfigPath() {
1593
- return globalPolicyConfigFile();
1594
- }
1595
- function readHooksConfig() {
1596
- const configPath = getConfigPath();
1597
- if (!existsSync4(configPath)) {
1598
- return { enabledPolicies: [] };
1599
- }
1600
- try {
1601
- const raw = readFileSync2(configPath, "utf8");
1602
- return JSON.parse(raw);
1603
- } catch (err) {
1604
- hookLogWarn(`failed to parse config at ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
1605
- return { enabledPolicies: [] };
1606
- }
1607
- }
1608
1592
  function getConfigPathForScope(scope, cwd) {
1609
1593
  switch (scope) {
1610
1594
  case "user":
@@ -11858,14 +11842,6 @@ function resetHome(from, to = LAYOUT_VERSION) {
11858
11842
  writeConfig(pendingConfig);
11859
11843
  if (telemetryOptOut)
11860
11844
  updateConfig({ telemetry: { enabled: false } });
11861
- const carried = (() => {
11862
- try {
11863
- const names = readHooksConfig().enabledPolicies ?? [];
11864
- return names.length > 0 ? { only: names } : undefined;
11865
- } catch {
11866
- return;
11867
- }
11868
- })();
11869
11845
  writeVersionFile({ layout: to });
11870
11846
  return { removed, migrated, activity, policyConfig, spooled, from };
11871
11847
  }
@@ -11886,7 +11862,6 @@ var init_fp_reset = __esm(() => {
11886
11862
  init_fp_home();
11887
11863
  init_fp_config();
11888
11864
  init_daemon_service();
11889
- init_hooks_config();
11890
11865
  RETIRED_POLICY_CONFIG_KEYS = ["collector"];
11891
11866
  });
11892
11867
 
@@ -13173,14 +13148,6 @@ function resetHome2(from, to = LAYOUT_VERSION) {
13173
13148
  writeConfig(pendingConfig);
13174
13149
  if (telemetryOptOut)
13175
13150
  updateConfig({ telemetry: { enabled: false } });
13176
- const carried = (() => {
13177
- try {
13178
- const names = readHooksConfig().enabledPolicies ?? [];
13179
- return names.length > 0 ? { only: names } : undefined;
13180
- } catch {
13181
- return;
13182
- }
13183
- })();
13184
13151
  writeVersionFile({ layout: to });
13185
13152
  return { removed, migrated, activity, policyConfig, spooled, from };
13186
13153
  }
@@ -13366,7 +13333,6 @@ var init_fp_reset2 = __esm(() => {
13366
13333
  init_fp_home();
13367
13334
  init_fp_config();
13368
13335
  init_daemon_service();
13369
- init_hooks_config();
13370
13336
  RETIRED_POLICY_CONFIG_KEYS2 = ["collector"];
13371
13337
  });
13372
13338
 
@@ -13755,7 +13721,7 @@ function renderBrandLogo(stdout = process.stdout) {
13755
13721
  const c = paint(colorsEnabled(stdout));
13756
13722
  const cols = stdout.columns || 80;
13757
13723
  if (cols < LOGO_MIN_COLS) {
13758
- return [`${c.guide(FLOWER)} fa${c.pink("il")}proof ai ${c.dim("· " + TAGLINE)}`];
13724
+ return [`${c.pink(MARK)} fa${c.pink("il")}proof ai ${c.dim("· " + TAGLINE)}`];
13759
13725
  }
13760
13726
  const tier = colorsEnabled(stdout) ? colorTier() : "basic";
13761
13727
  const lines = renderLogo(tier).map((l) => ` ${l}`);
@@ -13823,9 +13789,12 @@ function outro(message, opts = {}, stdout = process.stdout) {
13823
13789
  writeLines(stdout, [c.dim(BAR), `${end} ${text}`]);
13824
13790
  }
13825
13791
  function repaint(out, region, lines) {
13826
- if (region.lastCount > 0)
13827
- out.write(`${ESC}[${region.lastCount}A${ESC}[J`);
13828
- writeLines(out, lines);
13792
+ const cols = out.columns || 80;
13793
+ const body = lines.map((l) => l === "" ? l : truncate(l, cols)).join(`
13794
+ `) + `
13795
+ `;
13796
+ const clear = region.lastCount > 0 ? `${ESC}[${region.lastCount}A${ESC}[J` : "";
13797
+ out.write(`${ESC}[?2026h${clear}${body}${ESC}[?2026l`);
13829
13798
  region.lastCount = lines.length;
13830
13799
  }
13831
13800
  function hideCursor(out) {
@@ -14296,9 +14265,9 @@ function rule(label, opts) {
14296
14265
  const width = Math.max(4, cols - INDENT.length * 2);
14297
14266
  if (!label)
14298
14267
  return [`${INDENT}${c.dim("─".repeat(width))}`];
14299
- const head = `── ${label} `;
14268
+ const head = `━━ ${label} `;
14300
14269
  const tail = Math.max(3, width - head.length);
14301
- return [`${INDENT}${c.dim(head + "".repeat(tail))}`];
14270
+ return [`${INDENT}${c.dim(head + "".repeat(tail))}`];
14302
14271
  }
14303
14272
  function rows(items, opts) {
14304
14273
  const { cols, c } = ctx(opts);
@@ -14411,12 +14380,12 @@ function gutterBlock(symbol, lines, opts) {
14411
14380
  }
14412
14381
  function warning(lines, opts) {
14413
14382
  const { c } = ctx(opts);
14414
- return gutterBlock(c.warn(""), lines, opts);
14383
+ return gutterBlock(c.warn(""), lines, opts);
14415
14384
  }
14416
14385
  function emptyState(spec, opts) {
14417
14386
  return stack(note(spec.what, opts), spec.cmd ? nextStep(spec.cmd, spec.hint, opts) : null);
14418
14387
  }
14419
- 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, BACK, INDENT = " ", CHIP_LABELS, CHIP_WIDTH;
14388
+ var ESC = "\x1B", BAR = "│", BAR_END = "└", STEP_ACTIVE = "◆", STEP_DONE = "◇", RADIO_ON = "●", RADIO_OFF = "○", CHECK_ON = "◼", CHECK_OFF = "◻", CARET = "❯", MARK = "▮▮", 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, BACK, INDENT = " ", CHIP_LABELS, CHIP_WIDTH;
14420
14389
  var init_tui = __esm(() => {
14421
14390
  HUES = {
14422
14391
  guide: { rgb: [102, 209, 181], c256: 79, basic: "36" },
@@ -14459,7 +14428,7 @@ var init_tui = __esm(() => {
14459
14428
  locked: "✓ LOCK",
14460
14429
  cloud: "✓ CLOUD",
14461
14430
  pack: "✓ PACK",
14462
- failed: " FAIL",
14431
+ failed: " FAIL",
14463
14432
  observe: "◉ OBS"
14464
14433
  };
14465
14434
  CHIP_WIDTH = Math.max(...Object.values(CHIP_LABELS).map((l) => l.length));
@@ -24693,37 +24662,6 @@ function detectSetupState(cwd = process.cwd(), home = homedir23()) {
24693
24662
  function isConfigured(state = detectSetupState()) {
24694
24663
  return state.hasGlobalConfig || state.hasGlobalHooks || state.hasLegacyMarker;
24695
24664
  }
24696
- function buildTargetChoices(state) {
24697
- const globalRow = {
24698
- label: state.hasGlobalConfig ? "Update my global policies" : "Set up global policies",
24699
- value: "user",
24700
- hint: "applies in every project on this machine",
24701
- existing: state.hasGlobalConfig
24702
- };
24703
- if (state.inHomeDir || state.projectRoot === state.home) {
24704
- return [globalRow];
24705
- }
24706
- const projectRow = {
24707
- label: state.hasProjectConfig ? "Update this project's policies" : "Set up this project's policies",
24708
- value: "project",
24709
- hint: homeify(state.projectRoot, state.home),
24710
- existing: state.hasProjectConfig
24711
- };
24712
- const bothRow = {
24713
- label: "Both",
24714
- value: "both",
24715
- hint: "global defaults, plus overrides for this project",
24716
- existing: state.hasGlobalConfig && state.hasProjectConfig
24717
- };
24718
- return state.hasGlobalConfig ? [projectRow, globalRow, bothRow] : [globalRow, projectRow, bothRow];
24719
- }
24720
- function homeify(path3, home = homedir23()) {
24721
- const resolvedHome = resolve23(home);
24722
- const resolvedPath = resolve23(path3);
24723
- if (resolvedPath === resolvedHome)
24724
- return "~";
24725
- return resolvedPath.startsWith(resolvedHome + "/") ? `~${resolvedPath.slice(resolvedHome.length)}` : resolvedPath;
24726
- }
24727
24665
  function scopesFor(target) {
24728
24666
  return target === "both" ? ["user", "project"] : [target];
24729
24667
  }
@@ -28645,7 +28583,7 @@ async function emit(event, props) {
28645
28583
  await trackHookEvent2(getInstanceId2(), event, props);
28646
28584
  } catch {}
28647
28585
  }
28648
- function homeify2(p) {
28586
+ function homeify(p) {
28649
28587
  const home = homedir27();
28650
28588
  if (p === home)
28651
28589
  return "~";
@@ -28758,7 +28696,7 @@ function describeCustomPolicies(cwd) {
28758
28696
  fileCount += found.length;
28759
28697
  }
28760
28698
  for (const name of findSkippedPolicyFiles(dir)) {
28761
- warnings.push(`! ${homeify2(resolve29(dir, name))} is NOT loaded — rename to ` + `${name.replace(/\.(js|mjs|ts)$/, "-policies.$1")}`);
28699
+ warnings.push(`! ${homeify(resolve29(dir, name))} is NOT loaded — rename to ` + `${name.replace(/\.(js|mjs|ts)$/, "-policies.$1")}`);
28762
28700
  }
28763
28701
  }
28764
28702
  return { active, warnings, fileCount, scopes };
@@ -28797,7 +28735,7 @@ function describeSelection(policiesCount) {
28797
28735
  function reviewLines(state) {
28798
28736
  const { target, clis, policies, cwd, customEnabled, installDaemon, connect } = state;
28799
28737
  const scopes = scopesFor(target);
28800
- const where = target === "both" ? `Global, plus this project (${homeify2(cwd)})` : target === "project" ? `This project (${homeify2(cwd)})` : "Everywhere (global)";
28738
+ const where = target === "both" ? `Global, plus this project (${homeify(cwd)})` : target === "project" ? `This project (${homeify(cwd)})` : "Everywhere (global)";
28801
28739
  const lines = [];
28802
28740
  const harnessNames = clis.map((c2) => getIntegration(c2).displayName);
28803
28741
  lines.push(` Where : ${where}`);
@@ -28828,7 +28766,7 @@ function reviewLines(state) {
28828
28766
  if (seen.has(p))
28829
28767
  continue;
28830
28768
  seen.add(p);
28831
- lines.push(` ${homeify2(p)} ${integration.displayName} hooks`);
28769
+ lines.push(` ${homeify(p)} ${integration.displayName} hooks`);
28832
28770
  }
28833
28771
  }
28834
28772
  }
@@ -28837,12 +28775,12 @@ function reviewLines(state) {
28837
28775
  if (seen.has(configPath))
28838
28776
  continue;
28839
28777
  seen.add(configPath);
28840
- lines.push(` ${homeify2(configPath)} ${policies.length} policies`);
28778
+ lines.push(` ${homeify(configPath)} ${policies.length} policies`);
28841
28779
  }
28842
28780
  if (installDaemon && isDaemonSupportedPlatform()) {
28843
28781
  const servicePath = daemonServiceFilePath();
28844
28782
  if (servicePath)
28845
- lines.push(` ${homeify2(servicePath)} failproofaid service (needs root)`);
28783
+ lines.push(` ${homeify(servicePath)} failproofaid service (needs root)`);
28846
28784
  }
28847
28785
  return lines;
28848
28786
  }
@@ -29017,61 +28955,14 @@ refreshed. Re-run \`failproofai config\` once you can use sudo.
29017
28955
 
29018
28956
  `);
29019
28957
  }
29020
- const detectedNow = detectInstalledClis();
29021
- const recommendedClis = detectedNow.filter((id) => clisSupportingScope("user").includes(id));
29022
- const mode = await selectOne({
29023
- message: "Set up failproofai",
29024
- choices: [
29025
- {
29026
- label: "Recommended",
29027
- value: "recommended",
29028
- hint: recommendedClis.length ? `${recommendedClis.length} detected ${recommendedClis.length === 1 ? "CLI" : "CLIs"} · global` : "global"
29029
- },
29030
- {
29031
- label: "Customize",
29032
- value: "customize",
29033
- hint: "choose scope and harnesses"
29034
- }
29035
- ],
29036
- stdin,
29037
- stdout
29038
- });
29039
- if (mode === null)
29040
- return cancel();
29041
- const setupState = detectSetupState(cwd);
29042
- const targetChoices = buildTargetChoices(setupState);
29043
- let target;
29044
- if (mode === "recommended") {
29045
- target = "user";
29046
- } else if (targetChoices.length === 1) {
29047
- target = targetChoices[0].value;
29048
- stdout.write(`Configuring ${targetChoices[0].label.toLowerCase()} — ${targetChoices[0].hint}.
29049
-
29050
- `);
29051
- } else {
29052
- const chosen = await selectOne({
29053
- message: "What are we configuring?",
29054
- choices: targetChoices.map((c2) => ({
29055
- label: c2.label,
29056
- value: c2.value,
29057
- hint: c2.hint
29058
- })),
29059
- stdin,
29060
- stdout
29061
- });
29062
- if (chosen === null)
29063
- return cancel();
29064
- target = chosen;
29065
- }
28958
+ const target = "user";
29066
28959
  const scopes = scopesFor(target);
29067
28960
  const primaryScope = scopes.includes("project") ? "project" : "user";
29068
28961
  const enabledHere = readScopedHooksConfig(primaryScope, cwd).enabledPolicies ?? [];
29069
28962
  const policies = enabledHere;
29070
28963
  const customEnabled = undefined;
29071
28964
  let clisSel;
29072
- if (mode === "recommended") {
29073
- clisSel = recommendedClis;
29074
- } else {
28965
+ {
29075
28966
  const picked = await multiSelect({
29076
28967
  message: "Which harnesses should it protect?",
29077
28968
  choices: [
@@ -30048,6 +29939,32 @@ function effectFlagFrom(rest) {
30048
29939
  async function runPublishCommand(rest) {
30049
29940
  return publish(rest);
30050
29941
  }
29942
+ async function pickFromSource(source, io) {
29943
+ const preview = await fetchPackPreview(source);
29944
+ const categories = [...new Set(preview.policies.map((p) => p.category))];
29945
+ const rows2 = [];
29946
+ for (const category of categories) {
29947
+ for (const policy of preview.policies.filter((p) => p.category === category)) {
29948
+ rows2.push({
29949
+ label: policy.name,
29950
+ value: policy.name,
29951
+ hint: policy.description,
29952
+ checked: policy.defaultEnabled,
29953
+ section: `${category} · ${slugifyCategory(category)}`
29954
+ });
29955
+ }
29956
+ }
29957
+ const on = preview.policies.filter((p) => p.defaultEnabled).length;
29958
+ const picked = await multiSelect({
29959
+ message: `${preview.id}@${preview.version} — which of these should be on?`,
29960
+ choices: rows2,
29961
+ summaryNoun: "policies",
29962
+ hint: `space toggles · ctrl+a all · ↵ confirm · ${on} of ${rows2.length} are the publisher's defaults`,
29963
+ stdin: io.stdin,
29964
+ stdout: io.stdout
29965
+ });
29966
+ return picked;
29967
+ }
30051
29968
  async function add(rest) {
30052
29969
  const source = packAddSource(rest);
30053
29970
  const selection = selectionFrom(rest);
@@ -30061,6 +29978,16 @@ async function add(rest) {
30061
29978
  if (selection.categories && selection.categories.length === 0) {
30062
29979
  return fail(["--category needs at least one category, comma-separated"]);
30063
29980
  }
29981
+ const io = { stdin: process.stdin, stdout: process.stdout };
29982
+ const chose = !selection.only && !selection.categories && !selection.all;
29983
+ if (chose && io.stdin.isTTY && io.stdout.isTTY) {
29984
+ const picked = await pickFromSource(resolvedSource, io);
29985
+ if (picked === null)
29986
+ return ok(["Nothing installed."]);
29987
+ selection.only = picked;
29988
+ if (picked.length === 0)
29989
+ selection.only = [];
29990
+ }
30064
29991
  try {
30065
29992
  const result = await addPack(resolvedSource, selection);
30066
29993
  const lines = [
@@ -32401,7 +32328,7 @@ function renderBrandLogo2(stdout = process.stdout) {
32401
32328
  const c2 = paint2(colorsEnabled2(stdout));
32402
32329
  const cols = stdout.columns || 80;
32403
32330
  if (cols < LOGO_MIN_COLS2) {
32404
- return [`${c2.guide(FLOWER2)} fa${c2.pink("il")}proof ai ${c2.dim("· " + TAGLINE2)}`];
32331
+ return [`${c2.pink(MARK2)} fa${c2.pink("il")}proof ai ${c2.dim("· " + TAGLINE2)}`];
32405
32332
  }
32406
32333
  const tier = colorsEnabled2(stdout) ? colorTier2() : "basic";
32407
32334
  const lines = renderLogo2(tier).map((l) => ` ${l}`);
@@ -32469,9 +32396,12 @@ function outro2(message, opts = {}, stdout = process.stdout) {
32469
32396
  writeLines2(stdout, [c2.dim(BAR2), `${end} ${text}`]);
32470
32397
  }
32471
32398
  function repaint2(out, region, lines) {
32472
- if (region.lastCount > 0)
32473
- out.write(`${ESC2}[${region.lastCount}A${ESC2}[J`);
32474
- writeLines2(out, lines);
32399
+ const cols = out.columns || 80;
32400
+ const body = lines.map((l) => l === "" ? l : truncate2(l, cols)).join(`
32401
+ `) + `
32402
+ `;
32403
+ const clear = region.lastCount > 0 ? `${ESC2}[${region.lastCount}A${ESC2}[J` : "";
32404
+ out.write(`${ESC2}[?2026h${clear}${body}${ESC2}[?2026l`);
32475
32405
  region.lastCount = lines.length;
32476
32406
  }
32477
32407
  function hideCursor2(out) {
@@ -32942,9 +32872,9 @@ function rule2(label, opts) {
32942
32872
  const width = Math.max(4, cols - INDENT2.length * 2);
32943
32873
  if (!label)
32944
32874
  return [`${INDENT2}${c2.dim("─".repeat(width))}`];
32945
- const head = `── ${label} `;
32875
+ const head = `━━ ${label} `;
32946
32876
  const tail = Math.max(3, width - head.length);
32947
- return [`${INDENT2}${c2.dim(head + "".repeat(tail))}`];
32877
+ return [`${INDENT2}${c2.dim(head + "".repeat(tail))}`];
32948
32878
  }
32949
32879
  function rows2(items, opts) {
32950
32880
  const { cols, c: c2 } = ctx2(opts);
@@ -33071,7 +33001,7 @@ function gutterBlock2(symbol, lines, opts) {
33071
33001
  }
33072
33002
  function warning2(lines, opts) {
33073
33003
  const { c: c2 } = ctx2(opts);
33074
- return gutterBlock2(c2.warn(""), lines, opts);
33004
+ return gutterBlock2(c2.warn(""), lines, opts);
33075
33005
  }
33076
33006
  function danger(lines, opts) {
33077
33007
  const { c: c2 } = ctx2(opts);
@@ -33110,7 +33040,7 @@ function helpBlock(spec, opts) {
33110
33040
  };
33111
33041
  return stack2(spec.lead ? spec.lead.map((l) => `${INDENT2}${l}`) : null, section("USAGE", entryLines(spec.usage)), section("OPTIONS", entryLines(spec.options ?? [])), section("EXAMPLES", (spec.examples ?? []).map((e) => `${INDENT2}${e}`)));
33112
33042
  }
33113
- var ESC2 = "\x1B", BAR2 = "│", BAR_END2 = "└", STEP_ACTIVE2 = "◆", STEP_DONE2 = "◇", RADIO_ON2 = "●", RADIO_OFF2 = "○", CHECK_ON2 = "◼", CHECK_OFF2 = "◻", CARET2 = "❯", FLOWER2 = "", HUES2, ANSI_RESET2, ANSI_BOLD2, ANSI_DIM2, LOGO_MIN_COLS2 = 22, TAGLINE2 = "end-to-end failure layer for ai agents", LOGO_GRID2, LOGO_TEAL2, LOGO_PINK2, WINDOW3 = 8, BACK2, INDENT2 = " ", CHIP_LABELS2, CHIP_WIDTH2;
33043
+ var ESC2 = "\x1B", BAR2 = "│", BAR_END2 = "└", STEP_ACTIVE2 = "◆", STEP_DONE2 = "◇", RADIO_ON2 = "●", RADIO_OFF2 = "○", CHECK_ON2 = "◼", CHECK_OFF2 = "◻", CARET2 = "❯", MARK2 = "▮▮", HUES2, ANSI_RESET2, ANSI_BOLD2, ANSI_DIM2, LOGO_MIN_COLS2 = 22, TAGLINE2 = "end-to-end failure layer for ai agents", LOGO_GRID2, LOGO_TEAL2, LOGO_PINK2, WINDOW3 = 8, BACK2, INDENT2 = " ", CHIP_LABELS2, CHIP_WIDTH2;
33114
33044
  var init_tui2 = __esm(() => {
33115
33045
  HUES2 = {
33116
33046
  guide: { rgb: [102, 209, 181], c256: 79, basic: "36" },
@@ -33153,7 +33083,7 @@ var init_tui2 = __esm(() => {
33153
33083
  locked: "✓ LOCK",
33154
33084
  cloud: "✓ CLOUD",
33155
33085
  pack: "✓ PACK",
33156
- failed: " FAIL",
33086
+ failed: " FAIL",
33157
33087
  observe: "◉ OBS"
33158
33088
  };
33159
33089
  CHIP_WIDTH2 = Math.max(...Object.values(CHIP_LABELS2).map((l) => l.length));
@@ -34559,9 +34489,20 @@ async function listHooks(cwd) {
34559
34489
  return 0;
34560
34490
  }
34561
34491
  })();
34562
- groups.push(title("failproofai policies", installedScopes.length === 0 ? "not installed" : `${installedScopes.join(" + ")} · ${packCount} on`, opts));
34492
+ const packsPresent = (() => {
34493
+ try {
34494
+ return readInstalledPacks().packs.length > 0;
34495
+ } catch {
34496
+ return false;
34497
+ }
34498
+ })();
34499
+ const subtitle = installedScopes.length > 0 ? `${installedScopes.join(" + ")} · ${packCount} on` : packsPresent ? `${packCount} on · NOT ENFORCING` : "nothing installed";
34500
+ groups.push(title("failproofai policies", subtitle, opts));
34563
34501
  if (installedScopes.length === 0) {
34564
- groups.push(nextStep("failproofai policies --install", config.enabledPolicies.length > 0 ? "These are configured but NOT installed — no hook is running them:" : "Nothing is installed yet. Get started with:", opts));
34502
+ groups.push(packsPresent ? warning([
34503
+ "These policies are installed but NOTHING is running them. No agent " + "CLI on this machine is wired to call failproofai, so every policy " + "below is inert. Wire it up with:",
34504
+ " failproofai config"
34505
+ ], opts) : nextStep("failproofai config", config.enabledPolicies.length > 0 ? "These are configured but NOT installed — no hook is running them:" : "Nothing is set up yet. Get started with:", opts));
34565
34506
  }
34566
34507
  const footer = [note(`Config: ${globalPolicyConfigFile()}`, opts)];
34567
34508
  if (installedScopes.length > 1) {
@@ -35614,7 +35555,7 @@ import { realpathSync as realpathSync6 } from "fs";
35614
35555
  import { dirname as dirname26, resolve as resolve38 } from "path";
35615
35556
  import { fileURLToPath as fileURLToPath4 } from "url";
35616
35557
  // package.json
35617
- var version = "1.0.2-beta.1";
35558
+ var version = "1.0.2-beta.2";
35618
35559
 
35619
35560
  // bin/failproofai.mjs
35620
35561
  if (!process.env.FAILPROOFAI_PACKAGE_ROOT) {
@@ -35798,22 +35739,22 @@ Run \`failproofai help\` for usage.`);
35798
35739
  console.log(`
35799
35740
  failproofai v${version} -v version -h this screen
35800
35741
  Usage failproofai <command> [options] Detail failproofai help <command>
35801
- \u2500\u2500 1 GET IT RUNNING \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
35742
+ \u2501\u2501 1 GET IT RUNNING \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
35802
35743
  config, setup Interactive setup: agents, daemon, cloud
35803
35744
  update Finish an npm upgrade: migrate home, match daemon
35804
- \u2500\u2500 2 CHOOSE WHAT IT ENFORCES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
35745
+ \u2501\u2501 2 CHOOSE WHAT IT ENFORCES \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
35805
35746
  policies Every policy on this machine, and whether it is on
35806
35747
  policies add Pick from a list, or name one: <policy> or <owner>/<repo>
35807
35748
  policies remove Turn one policy off, or uninstall a whole pack
35808
35749
  policies show What a pack contains, before you install it
35809
35750
  policies -i / -u Wire failproofai into your agent CLIs
35810
35751
  publish Ship your own policies as a pack anyone can install
35811
- \u2500\u2500 3 SEE WHAT IT CAUGHT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
35752
+ \u2501\u2501 3 SEE WHAT IT CAUGHT \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
35812
35753
  (no args) Open the policy dashboard on localhost:8020
35813
35754
  audit Scan your agents' history, then open the audit view
35814
35755
  config --status Cloud connection, daemon version, pause state
35815
35756
  harness Extra paths to capture agent sessions from
35816
- \u2500\u2500 4 PUT IT RIGHT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
35757
+ \u2501\u2501 4 PUT IT RIGHT \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
35817
35758
  config --pause Pause enforcement for one session (30m; max 8h)
35818
35759
  flush Deliver everything already spooled, right now
35819
35760
  backfill Re-send history the collector already read past
package/dist/worker.mjs CHANGED
@@ -2559,7 +2559,7 @@ var init_builtin_policies = __esm(() => {
2559
2559
  });
2560
2560
 
2561
2561
  // package.json
2562
- var version = "1.0.2-beta.1";
2562
+ var version = "1.0.2-beta.2";
2563
2563
  var init_package = () => {};
2564
2564
 
2565
2565
  // src/posthog-key.ts
@@ -9268,7 +9268,6 @@ var init_fp_reset = __esm(() => {
9268
9268
  init_fp_home();
9269
9269
  init_fp_config();
9270
9270
  init_daemon_service();
9271
- init_hooks_config();
9272
9271
  });
9273
9272
 
9274
9273
  // src/hooks/handler.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "failproofai",
3
- "version": "1.0.2-beta.1",
3
+ "version": "1.0.2-beta.2",
4
4
  "description": "Observability and enforcement for AI agent harnesses. 39 built-in policies hooked into 12 of them — Claude Code, Codex, Cursor, Hermes, OpenClaw and more — blocking the tool call before it runs. Local dashboard included, no account needed.",
5
5
  "bin": {
6
6
  "failproofai": "./dist/cli.mjs",
@@ -120,15 +120,15 @@
120
120
  "sharp": "0.35.0"
121
121
  },
122
122
  "optionalDependencies": {
123
- "@failproofai/failproofaid-linux-x64": "1.0.2-beta.1",
124
- "@failproofai/failproofaid-linux-arm64": "1.0.2-beta.1",
125
- "@failproofai/failproofaid-darwin-x64": "1.0.2-beta.1",
126
- "@failproofai/failproofaid-darwin-arm64": "1.0.2-beta.1"
123
+ "@failproofai/failproofaid-linux-x64": "1.0.2-beta.2",
124
+ "@failproofai/failproofaid-linux-arm64": "1.0.2-beta.2",
125
+ "@failproofai/failproofaid-darwin-x64": "1.0.2-beta.2",
126
+ "@failproofai/failproofaid-darwin-arm64": "1.0.2-beta.2"
127
127
  },
128
128
  "failproofaidBinaries": {
129
- "linux-x64": "a8c695cfe728e56403f981bd5ea2dc838cb862bd7349354946afead12fe0c36a",
130
- "linux-arm64": "674b596fe496ea51bf98864be7105fe1e34aacf0d588e35e2e3b455839837d94",
131
- "darwin-x64": "c56e5f68a509ec493d6d497ce0d221ab2fb9ff493ec3dd7dca49a41de8621b1e",
132
- "darwin-arm64": "73e80759bfd47c3473167f39b77bb2df3ab8fc1e891a8a3b3cefa9c1d83f6885"
129
+ "linux-x64": "fcfa5ae234e66eb6b57ec28445900c5f5a231f5f3a1fb0aeaca281d81f74c81e",
130
+ "linux-arm64": "a2bb9894d311a86740170128a706a9503fecc15ac5cbbc4587243151175a671c",
131
+ "darwin-x64": "97c1054b6229824ff7a9cbee67f3c1e2608db9e0b38a0dfc1adb21bf772a9666",
132
+ "darwin-arm64": "eb60b5fd3c1727f0d5406961367e2ea9b6c7fbc0b975247e7db664d502863f13"
133
133
  }
134
134
  }