failproofai 0.0.14-beta.0 → 0.0.14-beta.1
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]__0q2nbsl._.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]__1fwl2mz._.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/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]__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]__09q1168._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0brjczq._.js +3 -0
- 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]__0hdsupo._.js +2 -2
- 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]__07qfsfa._.js → [root-of-the-server]__0wp9w6i._.js} +2 -2
- 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]__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/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 +1 -1
- 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/{node_modules_html-to-image_es_index_0g5r64e.js → node_modules_html-to-image_es_index_12rjfea.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/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/{17sdztgbcc0fi.js → 0d5lypu1zs21r.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2ufuwhv03yvtb.js → 0emg30_6svycu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1374x9bv_s_vg.js → 0o9wpnze1ey8y.js} +1 -1
- package/.next/standalone/.next/static/chunks/{454dyizqik6t9.js → 1359o5785rmve.js} +1 -1
- package/.next/standalone/.next/static/chunks/{43weu8f59tlix.js → 20tuctw38jbgw.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0405htbxay9vd.js → 2ldhnaweu9ew3.js} +1 -1
- package/.next/standalone/.next/static/chunks/{003uz088wbmz7.js → 2vav_x0_336ds.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/{35-90m9py64d4.js → 3cg7x0joi2b98.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2o3ql0n5owqsw.js → 3k87p-tijud-4.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2m_tbl39fcedn.js → 3kmaqcp7rldad.js} +1 -1
- 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/components/global-error-listeners.tsx +27 -0
- package/.next/standalone/ci/cli-integration/Dockerfile +47 -0
- package/.next/standalone/ci/cli-integration/README.md +69 -0
- package/.next/standalone/ci/cli-integration/canary-policies.mjs +45 -0
- package/.next/standalone/ci/cli-integration/capture-tokens.sh +48 -0
- package/.next/standalone/ci/cli-integration/inject-tokens.sh +44 -0
- package/.next/standalone/ci/cli-integration/install-clis.sh +91 -0
- package/.next/standalone/ci/cli-integration/probe-cli.sh +208 -0
- package/.next/standalone/ci/cli-integration/report.js +74 -0
- package/.next/standalone/ci/cli-integration/run.sh +107 -0
- package/.next/standalone/components/reach-developers.tsx +1 -1
- package/.next/standalone/docker-hook-sync/Dockerfile +8 -4
- package/.next/standalone/lib/error-origin.ts +67 -0
- 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 +479 -217
- package/lib/error-origin.ts +67 -0
- 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 +47 -1
- package/scripts/translate-docs/mdx-translator.ts +133 -4
- package/scripts/translate-docs/readme-translator.ts +13 -5
- package/scripts/translate-docs/translator.ts +38 -2
- package/scripts/validate-mdx.ts +12 -4
- package/src/audit/cli.ts +41 -9
- package/src/hooks/tui.ts +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ge8e7w._.js +0 -3
- 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 → LkN-JjmhKGmL-WklH7WVi}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → LkN-JjmhKGmL-WklH7WVi}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → LkN-JjmhKGmL-WklH7WVi}/_ssgManifest.js +0 -0
|
@@ -9,7 +9,11 @@ import {
|
|
|
9
9
|
getLanguageByCode,
|
|
10
10
|
getModelForTier,
|
|
11
11
|
} from "./config";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
getEnglishMdxPages,
|
|
14
|
+
translateMdxPage,
|
|
15
|
+
pruneOrphanedTranslations,
|
|
16
|
+
} from "./mdx-translator";
|
|
13
17
|
import { translateReadme } from "./readme-translator";
|
|
14
18
|
import {
|
|
15
19
|
getNavigationPageReferences,
|
|
@@ -33,6 +37,8 @@ const { values: args } = parseArgs({
|
|
|
33
37
|
force: { type: "boolean", short: "f", default: false },
|
|
34
38
|
"update-nav": { type: "boolean", default: false },
|
|
35
39
|
validate: { type: "boolean", default: false },
|
|
40
|
+
prune: { type: "boolean", default: false },
|
|
41
|
+
"no-prune": { type: "boolean", default: false },
|
|
36
42
|
model: { type: "string", short: "m" },
|
|
37
43
|
help: { type: "boolean", short: "h", default: false },
|
|
38
44
|
},
|
|
@@ -53,6 +59,8 @@ Options:
|
|
|
53
59
|
-f, --force Ignore cache, re-translate everything
|
|
54
60
|
--update-nav Regenerate docs.json navigation after translation
|
|
55
61
|
--validate Check all nav references resolve to files
|
|
62
|
+
--prune Only delete translations whose English source is gone
|
|
63
|
+
--no-prune Skip the prune step during a normal translation run
|
|
56
64
|
-m, --model <model> Claude model override (default: Sonnet for Tier 1, Haiku for Tier 2/3)
|
|
57
65
|
-h, --help Show this help
|
|
58
66
|
|
|
@@ -65,6 +73,7 @@ Examples:
|
|
|
65
73
|
bun scripts/translate-docs/cli.ts --dry-run --tier 3 # Preview all translations
|
|
66
74
|
bun scripts/translate-docs/cli.ts --validate # Check nav references
|
|
67
75
|
bun scripts/translate-docs/cli.ts --update-nav # Regenerate docs.json
|
|
76
|
+
bun scripts/translate-docs/cli.ts --prune --tier 3 # Drop orphaned translations
|
|
68
77
|
`);
|
|
69
78
|
process.exit(0);
|
|
70
79
|
}
|
|
@@ -132,6 +141,26 @@ async function main() {
|
|
|
132
141
|
return;
|
|
133
142
|
}
|
|
134
143
|
|
|
144
|
+
// Prune-only mode
|
|
145
|
+
if (args.prune) {
|
|
146
|
+
const langCodes = resolveLanguages();
|
|
147
|
+
const cache = readCache();
|
|
148
|
+
const pruned = pruneOrphanedTranslations(langCodes, {
|
|
149
|
+
dryRun: args["dry-run"],
|
|
150
|
+
cache,
|
|
151
|
+
});
|
|
152
|
+
for (const file of pruned) {
|
|
153
|
+
console.log(
|
|
154
|
+
` ${args["dry-run"] ? "would remove" : "removed"}: ${file}`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
if (pruned.length > 0 && !args["dry-run"]) writeCache(cache);
|
|
158
|
+
console.log(
|
|
159
|
+
`\n${pruned.length} orphaned translation(s)${args["dry-run"] ? " would be" : ""} removed.`,
|
|
160
|
+
);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
135
164
|
const langCodes = resolveLanguages();
|
|
136
165
|
const isDryRun = args["dry-run"];
|
|
137
166
|
const isForce = args.force;
|
|
@@ -196,6 +225,23 @@ async function main() {
|
|
|
196
225
|
|
|
197
226
|
// Translate docs
|
|
198
227
|
if (!args["readme-only"]) {
|
|
228
|
+
// Drop translations orphaned by an upstream English deletion before
|
|
229
|
+
// translating, so a stale locale page can never outlive its source.
|
|
230
|
+
if (!args["no-prune"]) {
|
|
231
|
+
const pruned = pruneOrphanedTranslations(langCodes, {
|
|
232
|
+
dryRun: isDryRun,
|
|
233
|
+
cache,
|
|
234
|
+
});
|
|
235
|
+
for (const file of pruned) {
|
|
236
|
+
console.log(` ${isDryRun ? "would prune" : "pruned"}: ${file}`);
|
|
237
|
+
}
|
|
238
|
+
if (pruned.length > 0) {
|
|
239
|
+
console.log(
|
|
240
|
+
`${pruned.length} orphaned translation(s)${isDryRun ? " would be" : ""} removed.`,
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
199
245
|
const pages = getEnglishMdxPages();
|
|
200
246
|
const filteredPages = args.pages
|
|
201
247
|
? pages.filter((p) => {
|
|
@@ -4,12 +4,20 @@ import {
|
|
|
4
4
|
mkdirSync,
|
|
5
5
|
readdirSync,
|
|
6
6
|
statSync,
|
|
7
|
+
existsSync,
|
|
8
|
+
rmSync,
|
|
7
9
|
} from "node:fs";
|
|
8
10
|
import { dirname, join, relative } from "node:path";
|
|
9
11
|
import { fileURLToPath } from "node:url";
|
|
10
12
|
import { getLanguageByCode } from "./config";
|
|
11
13
|
import { translateContent } from "./translator";
|
|
12
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
readCache,
|
|
16
|
+
writeCache,
|
|
17
|
+
isCached,
|
|
18
|
+
setCacheEntry,
|
|
19
|
+
getCacheKey,
|
|
20
|
+
} from "./cache";
|
|
13
21
|
import type { TranslationResult, TranslationCache } from "./types";
|
|
14
22
|
|
|
15
23
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -94,6 +102,60 @@ export function stripStrayTrailingFence(content: string): string {
|
|
|
94
102
|
return lines.join("\n");
|
|
95
103
|
}
|
|
96
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Convert HTML comments (`<!-- ... -->`) into MDX brace-slash-star comments.
|
|
107
|
+
*
|
|
108
|
+
* Mintlify parses every page as MDX, where a top-level HTML comment is a hard
|
|
109
|
+
* syntax error ("Unexpected character `!` (U+0021) before name …") that fails
|
|
110
|
+
* the whole deployment — the remedy Mintlify itself suggests is switching to
|
|
111
|
+
* MDX's own comment form. The root README keeps HTML-comment syntax (GitHub
|
|
112
|
+
* renders it invisibly), so its translated copies under docs/i18n/ have to be
|
|
113
|
+
* rewritten to the MDX form or the docs deploy breaks.
|
|
114
|
+
*
|
|
115
|
+
* Comments inside fenced code blocks are left untouched — there `<!-- -->` is
|
|
116
|
+
* literal sample text (e.g. the plist snippet in the AgentEye collector docs),
|
|
117
|
+
* not a comment to convert. Any `*`+`/` sequence inside a body is broken up so
|
|
118
|
+
* the generated JS block comment can't be terminated early.
|
|
119
|
+
*/
|
|
120
|
+
export function convertHtmlComments(content: string): string {
|
|
121
|
+
// Map out fenced-code ranges so comments inside them stay literal. Per
|
|
122
|
+
// CommonMark, a fence opens with ≥3 backticks or tildes and closes only on a
|
|
123
|
+
// later line using the SAME character and at least the same length. A naive
|
|
124
|
+
// "any ``` toggles" counter misfires on a ```` block that embeds ``` or on
|
|
125
|
+
// mixed ```/~~~ fences — the toggle desyncs and a real top-level comment
|
|
126
|
+
// after the block would be left unconverted (breaking the deploy we fix here).
|
|
127
|
+
const fenceRanges: Array<[number, number]> = [];
|
|
128
|
+
const fenceRe = /^[ \t]*(`{3,}|~{3,})/gm;
|
|
129
|
+
let fenceMatch: RegExpExecArray | null;
|
|
130
|
+
let open: { char: string; length: number; start: number } | null = null;
|
|
131
|
+
while ((fenceMatch = fenceRe.exec(content)) !== null) {
|
|
132
|
+
const marker = fenceMatch[1];
|
|
133
|
+
if (!open) {
|
|
134
|
+
open = { char: marker[0], length: marker.length, start: fenceMatch.index };
|
|
135
|
+
} else if (marker[0] === open.char && marker.length >= open.length) {
|
|
136
|
+
const lineEnd = content.indexOf("\n", fenceRe.lastIndex);
|
|
137
|
+
fenceRanges.push([open.start, lineEnd === -1 ? content.length : lineEnd]);
|
|
138
|
+
open = null;
|
|
139
|
+
}
|
|
140
|
+
// A different char or shorter marker while a fence is open is inner content.
|
|
141
|
+
}
|
|
142
|
+
// An unterminated fence runs to the end of the document.
|
|
143
|
+
if (open) fenceRanges.push([open.start, content.length]);
|
|
144
|
+
|
|
145
|
+
const isInsideFence = (offset: number): boolean =>
|
|
146
|
+
fenceRanges.some(([start, end]) => offset >= start && offset < end);
|
|
147
|
+
|
|
148
|
+
return content.replace(
|
|
149
|
+
/<!--([\s\S]*?)-->/g,
|
|
150
|
+
(match: string, body: string, offset: number) => {
|
|
151
|
+
if (isInsideFence(offset)) return match;
|
|
152
|
+
// Neutralize any `*/` so it can't close the JS block comment early.
|
|
153
|
+
const safeBody = body.replace(/\*\//g, "* /");
|
|
154
|
+
return `{/*${safeBody}*/}`;
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
97
159
|
/**
|
|
98
160
|
* Rewrite internal doc links to include the language prefix.
|
|
99
161
|
* e.g. href="/built-in-policies" -> href="/es/built-in-policies"
|
|
@@ -175,9 +237,11 @@ export async function translateMdxPage(
|
|
|
175
237
|
);
|
|
176
238
|
|
|
177
239
|
// Strip stray quote artifacts from JSX attribute values, drop any
|
|
178
|
-
// unmatched trailing code fence the model sometimes hallucinates,
|
|
179
|
-
// rewrite links.
|
|
180
|
-
const sanitized =
|
|
240
|
+
// unmatched trailing code fence the model sometimes hallucinates, convert
|
|
241
|
+
// any HTML comments to MDX comments, then rewrite links.
|
|
242
|
+
const sanitized = convertHtmlComments(
|
|
243
|
+
stripStrayTrailingFence(sanitizeJsxAttributes(translated)),
|
|
244
|
+
);
|
|
181
245
|
const withLinks = rewriteInternalLinks(sanitized, lang);
|
|
182
246
|
|
|
183
247
|
// Write output
|
|
@@ -234,6 +298,71 @@ export function getEnglishMdxPages(): string[] {
|
|
|
234
298
|
return results.sort();
|
|
235
299
|
}
|
|
236
300
|
|
|
301
|
+
/** Every `.mdx` file under `dir`, recursively. */
|
|
302
|
+
function collectMdxFiles(dir: string): string[] {
|
|
303
|
+
const results: string[] = [];
|
|
304
|
+
for (const entry of readdirSync(dir)) {
|
|
305
|
+
const full = join(dir, entry);
|
|
306
|
+
if (statSync(full).isDirectory()) {
|
|
307
|
+
results.push(...collectMdxFiles(full));
|
|
308
|
+
} else if (entry.endsWith(".mdx")) {
|
|
309
|
+
results.push(full);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return results;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Delete translated pages whose English source no longer exists, and drop
|
|
317
|
+
* their cache entries.
|
|
318
|
+
*
|
|
319
|
+
* Translation only ever moves forward: `getEnglishMdxPages()` drives what gets
|
|
320
|
+
* written, so when an English page is deleted upstream (the agenteye sync does
|
|
321
|
+
* this routinely) its 14 translations are simply never revisited. They linger
|
|
322
|
+
* on disk and `--update-nav` drops them from `docs.json`, which hides them from
|
|
323
|
+
* the sidebar but does *not* unpublish them — Mintlify still serves and indexes
|
|
324
|
+
* any `.mdx` present, so non-English readers can land on a page documenting a
|
|
325
|
+
* removed feature with no navigation out. Left unpruned these also accumulate
|
|
326
|
+
* as permanent `validate:mdx` surface area for content no English source can
|
|
327
|
+
* ever correct.
|
|
328
|
+
*
|
|
329
|
+
* Returns the docs-dir-relative paths that were (or, when `dryRun`, would be)
|
|
330
|
+
* removed.
|
|
331
|
+
*/
|
|
332
|
+
export function pruneOrphanedTranslations(
|
|
333
|
+
langCodes: string[],
|
|
334
|
+
options: {
|
|
335
|
+
dryRun?: boolean;
|
|
336
|
+
cache?: TranslationCache;
|
|
337
|
+
/** Override the docs root. Tests point this at a fixture tree. */
|
|
338
|
+
docsDir?: string;
|
|
339
|
+
} = {},
|
|
340
|
+
): string[] {
|
|
341
|
+
const docsDir = options.docsDir ?? DOCS_DIR;
|
|
342
|
+
const removed: string[] = [];
|
|
343
|
+
|
|
344
|
+
for (const lang of langCodes) {
|
|
345
|
+
const langDir = join(docsDir, lang);
|
|
346
|
+
if (!existsSync(langDir)) continue;
|
|
347
|
+
|
|
348
|
+
for (const file of collectMdxFiles(langDir)) {
|
|
349
|
+
// docs/zh/agenteye/foo.mdx -> agenteye/foo.mdx -> docs/agenteye/foo.mdx
|
|
350
|
+
const relPath = relative(langDir, file);
|
|
351
|
+
if (existsSync(join(docsDir, relPath))) continue;
|
|
352
|
+
|
|
353
|
+
removed.push(relative(docsDir, file));
|
|
354
|
+
if (!options.dryRun) {
|
|
355
|
+
rmSync(file);
|
|
356
|
+
if (options.cache) {
|
|
357
|
+
delete options.cache.translations[getCacheKey(relPath, lang)];
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return removed.sort();
|
|
364
|
+
}
|
|
365
|
+
|
|
237
366
|
function isLanguageDir(name: string): boolean {
|
|
238
367
|
const langCodes = [
|
|
239
368
|
"zh",
|
|
@@ -3,7 +3,11 @@ import { dirname, join } from "node:path";
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { LANGUAGES, getLanguageByCode } from "./config";
|
|
5
5
|
import { translateContent } from "./translator";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
stripStrayTrailingFence,
|
|
8
|
+
convertHtmlComments,
|
|
9
|
+
sanitizeJsxAttributes,
|
|
10
|
+
} from "./mdx-translator";
|
|
7
11
|
import { readCache, writeCache, isCached, setCacheEntry } from "./cache";
|
|
8
12
|
import type { TranslationResult, TranslationCache } from "./types";
|
|
9
13
|
|
|
@@ -103,10 +107,14 @@ export async function translateReadme(
|
|
|
103
107
|
const rtlOpen = langConfig.rtl ? `<div dir="rtl">\n\n` : "";
|
|
104
108
|
const rtlClose = langConfig.rtl ? `\n\n</div>` : "";
|
|
105
109
|
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
+
// Run the same MDX sanitizers as translateMdxPage — the README emits JSX
|
|
111
|
+
// (the logo table), so its output has to satisfy Mintlify's MDX parser too:
|
|
112
|
+
// strip stray quote artifacts from JSX attributes, drop any unmatched
|
|
113
|
+
// trailing code fence the model hallucinates (which would swallow the RTL
|
|
114
|
+
// `</div>` wrapper), and convert HTML comments to MDX comments.
|
|
115
|
+
const cleaned = convertHtmlComments(
|
|
116
|
+
stripStrayTrailingFence(sanitizeJsxAttributes(translated)),
|
|
117
|
+
);
|
|
110
118
|
|
|
111
119
|
const output = `${disclaimer}\n\n${langSelector}\n\n---\n${rtlOpen}\n${cleaned}\n${rtlClose}`;
|
|
112
120
|
|
|
@@ -3,6 +3,28 @@ import { DO_NOT_TRANSLATE } from "./config";
|
|
|
3
3
|
|
|
4
4
|
let client: Anthropic | null = null;
|
|
5
5
|
|
|
6
|
+
// Output-token ceiling for a single translation. The largest English docs
|
|
7
|
+
// (e.g. agenteye/kubernetes-deployment.mdx at ~1400 lines) translate to well
|
|
8
|
+
// beyond the old 16384 cap for verbose target languages. When a response hit
|
|
9
|
+
// that cap it was silently truncated mid-MDX — leaving an unbalanced `{` or an
|
|
10
|
+
// unterminated JSX expression — and the partial output was written to disk and
|
|
11
|
+
// the cache, only to fail `mintlify validate` later in the consolidate job
|
|
12
|
+
// (or, for the very largest pages, to trip the proxy with a "stream ended"
|
|
13
|
+
// error). 64000 is Claude Haiku 4.5's max output (Tier 2/3 languages) and well
|
|
14
|
+
// inside Claude Sonnet 4.6's 128000 (Tier 1), with headroom over the largest
|
|
15
|
+
// observed translation; max_tokens is only a ceiling, so smaller pages still
|
|
16
|
+
// stop at `end_turn` and cost the same. Streaming (below) is what keeps an
|
|
17
|
+
// output this large safe from the SDK's HTTP timeout.
|
|
18
|
+
// Override via TRANSLATE_MAX_TOKENS (integer >= 1; otherwise default).
|
|
19
|
+
const parsedMaxTokens = Number.parseInt(
|
|
20
|
+
process.env.TRANSLATE_MAX_TOKENS ?? "",
|
|
21
|
+
10,
|
|
22
|
+
);
|
|
23
|
+
const MAX_TOKENS =
|
|
24
|
+
Number.isInteger(parsedMaxTokens) && parsedMaxTokens > 0
|
|
25
|
+
? parsedMaxTokens
|
|
26
|
+
: 64000;
|
|
27
|
+
|
|
6
28
|
function getClient(): Anthropic {
|
|
7
29
|
if (!client) {
|
|
8
30
|
// Default 5 retries (up from SDK default of 2) so transient
|
|
@@ -61,7 +83,7 @@ export async function translateContent(
|
|
|
61
83
|
// as `messages.create(...)`, so the rest of the pipeline is unchanged.
|
|
62
84
|
const response = await anthropic.messages.stream({
|
|
63
85
|
model,
|
|
64
|
-
max_tokens:
|
|
86
|
+
max_tokens: MAX_TOKENS,
|
|
65
87
|
system: [{ type: "text", text: SYSTEM_PROMPT, cache_control: { type: "ephemeral" } }],
|
|
66
88
|
messages: [
|
|
67
89
|
{
|
|
@@ -71,8 +93,22 @@ export async function translateContent(
|
|
|
71
93
|
],
|
|
72
94
|
}).finalMessage();
|
|
73
95
|
|
|
96
|
+
// A truncated translation is worse than a failed one: the model stops
|
|
97
|
+
// mid-MDX, and that partial would otherwise be written to disk and cached as
|
|
98
|
+
// if complete, surfacing only as an unbalanced-brace parse error in
|
|
99
|
+
// `mintlify validate`. Fail loudly instead so the caller (cli.ts) records an
|
|
100
|
+
// error, never caches the partial, and excludes this language from the
|
|
101
|
+
// consolidate publish step. If a page ever legitimately needs more than
|
|
102
|
+
// MAX_TOKENS, raise TRANSLATE_MAX_TOKENS or split the source.
|
|
103
|
+
if (response.stop_reason === "max_tokens") {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`translation truncated at max_tokens=${MAX_TOKENS} ` +
|
|
106
|
+
`(output ${response.usage.output_tokens} tokens) — source too large to translate in one request`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
74
110
|
const translated =
|
|
75
|
-
response.content[0]
|
|
111
|
+
response.content[0]?.type === "text" ? response.content[0].text : "";
|
|
76
112
|
|
|
77
113
|
return {
|
|
78
114
|
translated,
|
package/scripts/validate-mdx.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Validate that every docs
|
|
3
|
-
* runs at deploy time.
|
|
2
|
+
* Validate that every docs page (`.mdx` and `.md` — Mintlify parses both as
|
|
3
|
+
* MDX) parses with the same MDX engine Mintlify runs at deploy time.
|
|
4
4
|
*
|
|
5
5
|
* Why this exists: `mintlify validate` (the existing `docs` CI job) only checks
|
|
6
6
|
* `docs.json` structure and nav-link resolution — it does NOT parse page
|
|
@@ -91,12 +91,20 @@ export function encodeAnnotation(value: string): string {
|
|
|
91
91
|
.replace(/\n/g, "%0A");
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Collect every Mintlify content page under `dir`. Mintlify runs BOTH `.mdx`
|
|
96
|
+
* and `.md` files through the same MDX pipeline at deploy time, so a `.md` page
|
|
97
|
+
* with an MDX syntax error (e.g. an HTML `<!-- -->` comment, which MDX rejects)
|
|
98
|
+
* fails the deploy exactly like a broken `.mdx` would. The docs/i18n README
|
|
99
|
+
* translations are `.md`, so restricting this walk to `.mdx` let their breakage
|
|
100
|
+
* sail past this safety net and reach the post-merge deploy — collect both.
|
|
101
|
+
*/
|
|
102
|
+
export function collectMdxFiles(dir: string): string[] {
|
|
95
103
|
const out: string[] = [];
|
|
96
104
|
for (const entry of readdirSync(dir)) {
|
|
97
105
|
const full = join(dir, entry);
|
|
98
106
|
if (statSync(full).isDirectory()) out.push(...collectMdxFiles(full));
|
|
99
|
-
else if (entry.endsWith(".mdx")) out.push(full);
|
|
107
|
+
else if (entry.endsWith(".mdx") || entry.endsWith(".md")) out.push(full);
|
|
100
108
|
}
|
|
101
109
|
return out;
|
|
102
110
|
}
|
package/src/audit/cli.ts
CHANGED
|
@@ -237,6 +237,26 @@ function printSummary(result: AuditResult): void {
|
|
|
237
237
|
for (const line of buildSummary(result)) process.stdout.write(` ${line}\n`);
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
// ── Audit telemetry ──────────────────────────────────────────────────────────
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Which entry point ran the audit. `onboarding` is the automatic post-setup run;
|
|
244
|
+
* `cli` is an explicit `failproofai audit`. Carried on every cli_audit_* event so
|
|
245
|
+
* the first audit a user ever runs is distinguishable from later deliberate ones.
|
|
246
|
+
*/
|
|
247
|
+
type AuditSource = "cli" | "onboarding";
|
|
248
|
+
|
|
249
|
+
/** Shared so both entry points report cli_audit_completed identically. */
|
|
250
|
+
function auditCompletedProps(source: AuditSource, result: AuditResult) {
|
|
251
|
+
return {
|
|
252
|
+
source,
|
|
253
|
+
events_scanned: result.eventsScanned,
|
|
254
|
+
sessions_scanned: result.transcripts.scanned,
|
|
255
|
+
total_hits: result.totals.hits,
|
|
256
|
+
findings: result.results.length,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
240
260
|
// ── Post-setup background audit ────────────────────────────────────────────────
|
|
241
261
|
|
|
242
262
|
/**
|
|
@@ -252,7 +272,13 @@ function printSummary(result: AuditResult): void {
|
|
|
252
272
|
*/
|
|
253
273
|
export async function runPostSetupAudit(): Promise<void> {
|
|
254
274
|
if (process.env.FAILPROOFAI_NO_AUTO_AUDIT === "1") return;
|
|
255
|
-
|
|
275
|
+
|
|
276
|
+
const instanceId = getInstanceId();
|
|
277
|
+
// Fire-and-forget, as in runAuditCli: the multi-second scan below keeps the
|
|
278
|
+
// process alive long enough for this to land, and the completed/failed event
|
|
279
|
+
// that follows is awaited.
|
|
280
|
+
void trackHookEvent(instanceId, "cli_audit_started", { source: "onboarding" });
|
|
281
|
+
|
|
256
282
|
process.stdout.write(
|
|
257
283
|
`\n ${c(PINK, "✦")} ${c(BOLD, "failproofai audit now running")} ${c(DIM, "· ctrl+c to stop")}\n\n`,
|
|
258
284
|
);
|
|
@@ -260,13 +286,25 @@ export async function runPostSetupAudit(): Promise<void> {
|
|
|
260
286
|
let result: AuditResult;
|
|
261
287
|
try {
|
|
262
288
|
result = await runWithProgress({});
|
|
263
|
-
} catch {
|
|
289
|
+
} catch (err) {
|
|
290
|
+
// Awaited: this function returns straight into the dashboard boot, and a
|
|
291
|
+
// fire-and-forget fetch would race it.
|
|
292
|
+
await trackHookEvent(instanceId, "cli_audit_failed", {
|
|
293
|
+
source: "onboarding",
|
|
294
|
+
error_type: err instanceof Error ? err.name : "unknown",
|
|
295
|
+
error_message: sanitizeErrorMessage(err),
|
|
296
|
+
});
|
|
264
297
|
process.stdout.write(
|
|
265
298
|
` ${c(PINK, "!")} ${c(DIM, "audit couldn't finish — run")} ${c(CYAN, "failproofai audit")} ${c(DIM, "later.")}\n\n`,
|
|
266
299
|
);
|
|
267
300
|
return;
|
|
268
301
|
}
|
|
269
302
|
|
|
303
|
+
// Reported before the empty-history return below, so an onboarding audit that
|
|
304
|
+
// finds nothing is still counted — matching runAuditCli, which reports
|
|
305
|
+
// completed regardless of what the scan turned up.
|
|
306
|
+
await trackHookEvent(instanceId, "cli_audit_completed", auditCompletedProps("onboarding", result));
|
|
307
|
+
|
|
270
308
|
if (result.eventsScanned === 0) {
|
|
271
309
|
process.stdout.write(
|
|
272
310
|
`\n ${c(DIM, "no agent sessions to audit yet — come back after using your agent.")}\n\n`,
|
|
@@ -328,13 +366,7 @@ export async function runAuditCli(args: string[]): Promise<void> {
|
|
|
328
366
|
// would otherwise drop this event. On the dashboard path launch() keeps the
|
|
329
367
|
// process alive, but awaiting makes delivery reliable on every exit path.
|
|
330
368
|
// Bounded (5s) and never throws.
|
|
331
|
-
await trackHookEvent(instanceId, "cli_audit_completed",
|
|
332
|
-
source: "cli",
|
|
333
|
-
events_scanned: result.eventsScanned,
|
|
334
|
-
sessions_scanned: result.transcripts.scanned,
|
|
335
|
-
total_hits: result.totals.hits,
|
|
336
|
-
findings: result.results.length,
|
|
337
|
-
});
|
|
369
|
+
await trackHookEvent(instanceId, "cli_audit_completed", auditCompletedProps("cli", result));
|
|
338
370
|
|
|
339
371
|
// No sessions on disk — guide the user instead of opening an empty dashboard.
|
|
340
372
|
if (result.eventsScanned === 0) {
|
package/src/hooks/tui.ts
CHANGED
|
@@ -287,7 +287,7 @@ export function renderLaunchBanner(version: string, stdout: TTYOut = process.std
|
|
|
287
287
|
row("version", c.pink(version)),
|
|
288
288
|
row("star", c.dim("https://github.com/failproofai/failproofai")),
|
|
289
289
|
row("docs", c.dim("https://docs.befailproof.ai/introduction")),
|
|
290
|
-
row("discord", c.dim("https://discord.
|
|
290
|
+
row("discord", c.dim("https://discord.befailproof.ai/")),
|
|
291
291
|
"",
|
|
292
292
|
];
|
|
293
293
|
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[18622,(a,b,c)=>{b.exports=a.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},56704,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},20635,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/action-async-storage.external.js",()=>require("next/dist/server/app-render/action-async-storage.external.js"))},24725,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},43285,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/dynamic-access-async-storage.external.js",()=>require("next/dist/server/app-render/dynamic-access-async-storage.external.js"))},42602,(a,b,c)=>{"use strict";b.exports=a.r(18622)},87924,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].ReactJsxRuntime},72131,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].React},38783,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].ReactServerDOMTurbopackClient},9270,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored.contexts.AppRouterContext},36313,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored.contexts.HooksClientContext},18341,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored.contexts.ServerInsertedHtml},35112,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].ReactDOM},6236,a=>{"use strict";var b=a.i(87924),c=a.i(72131);let d=(0,c.createContext)(void 0);a.s(["AutoRefreshProvider",0,function({children:a}){let[e,f]=(0,c.useState)(0);return(0,b.jsx)(d.Provider,{value:{intervalSec:e,setIntervalSec:f},children:a})},"useAutoRefresh",0,function(){let a=(0,c.useContext)(d);if(!a)throw Error("useAutoRefresh must be used within AutoRefreshProvider");return a}])},89027,40695,a=>{"use strict";let b=(0,a.i(64831).default)("chevron-down",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);a.s(["ChevronDown",0,b],89027);var c=a.i(87924),d=a.i(72131),e=a.i(97895);let f=d.forwardRef(({className:a,variant:b="default",size:d="default",...f},g)=>(0,c.jsx)("button",{className:(0,e.cn)("inline-flex items-center justify-center rounded-md text-sm font-medium transition-[background-color,color,box-shadow,border-color] duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:opacity-50 disabled:pointer-events-none",{"bg-primary text-primary-foreground hover:bg-primary/90 hover:shadow-[0_0_0_1px_var(--primary)]":"default"===b,"text-foreground hover:bg-muted":"ghost"===b,"border border-border bg-transparent hover:border-primary/60 hover:bg-card":"outline"===b,"h-10 py-2 px-4":"default"===d,"h-10 w-10":"icon"===d,"h-9 px-3":"sm"===d,"h-11 px-8":"lg"===d},a),ref:g,...f}));f.displayName="Button",a.s(["Button",0,f],40695)},46058,(a,b,c)=>{"use strict";function d(a){if("function"!=typeof WeakMap)return null;var b=new WeakMap,c=new WeakMap;return(d=function(a){return a?c:b})(a)}c._=function(a,b){if(!b&&a&&a.__esModule)return a;if(null===a||"object"!=typeof a&&"function"!=typeof a)return{default:a};var c=d(b);if(c&&c.has(a))return c.get(a);var e={__proto__:null},f=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var g in a)if("default"!==g&&Object.prototype.hasOwnProperty.call(a,g)){var h=f?Object.getOwnPropertyDescriptor(a,g):null;h&&(h.get||h.set)?Object.defineProperty(e,g,h):e[g]=a[g]}return e.default=a,c&&c.set(a,e),e}},88347,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d,e,f={ACTION_HMR_REFRESH:function(){return l},ACTION_NAVIGATE:function(){return i},ACTION_REFRESH:function(){return h},ACTION_RESTORE:function(){return j},ACTION_SERVER_ACTION:function(){return m},ACTION_SERVER_PATCH:function(){return k},PrefetchKind:function(){return n},ScrollBehavior:function(){return o}};for(var g in f)Object.defineProperty(c,g,{enumerable:!0,get:f[g]});let h="refresh",i="navigate",j="restore",k="server-patch",l="hmr-refresh",m="server-action";var n=((d={}).AUTO="auto",d.FULL="full",d),o=((e={})[e.Default=0]="Default",e[e.NoScroll=1]="NoScroll",e);("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},67009,(a,b,c)=>{"use strict";function d(a){return null!==a&&"object"==typeof a&&"then"in a&&"function"==typeof a.then}Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"isThenable",{enumerable:!0,get:function(){return d}})},90841,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={dispatchAppRouterAction:function(){return i},dispatchGestureState:function(){return j},refreshOnInstantNavigationUnlock:function(){return h},useActionQueue:function(){return k}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(46058)._(a.r(72131)),g=a.r(67009);a.r(88347);function h(){}function i(a){!0;throw Object.defineProperty(Error("Internal Next.js error: Router action dispatched before initialization."),"__NEXT_ERROR_CODE",{value:"E668",enumerable:!1,configurable:!0})}function j(a){!0;throw Object.defineProperty(Error("Internal Next.js error: Router action dispatched before initialization."),"__NEXT_ERROR_CODE",{value:"E668",enumerable:!1,configurable:!0})}function k(a){let[b,c]=f.default.useState(a.state),[d,e]=(0,f.useOptimistic)(b),h=(0,f.useMemo)(()=>d,[d]);return(0,g.isThenable)(h)?(0,f.use)(h):h}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},20611,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"callServer",{enumerable:!0,get:function(){return g}});let d=a.r(72131),e=a.r(88347),f=a.r(90841);async function g(a,b){return new Promise((c,g)=>{(0,d.startTransition)(()=>{(0,f.dispatchAppRouterAction)({type:e.ACTION_SERVER_ACTION,actionId:a,actionArgs:b,resolve:c,reject:g})})})}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},1722,(a,b,c)=>{"use strict";let d;Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"findSourceMapURL",{enumerable:!0,get:function(){return d}});("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},39118,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={DEFAULT_SEGMENT_KEY:function(){return l},NOT_FOUND_SEGMENT_KEY:function(){return m},PAGE_SEGMENT_KEY:function(){return k},addSearchParamsIfPageSegment:function(){return i},computeSelectedLayoutSegment:function(){return j},getSegmentValue:function(){return f},getSelectedLayoutSegmentPath:function(){return function a(b,c,d=!0,e=[]){let g;if(d)g=b[1][c];else{let a=b[1];g=a.children??Object.values(a)[0]}if(!g)return e;let h=f(g[0]);return!h||h.startsWith(k)?e:(e.push(h),a(g,c,!1,e))}},isGroupSegment:function(){return g},isParallelRouteSegment:function(){return h}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});function f(a){return Array.isArray(a)?a[1]:a}function g(a){return"("===a[0]&&a.endsWith(")")}function h(a){return a.startsWith("@")&&"@children"!==a}function i(a,b){if(a.includes(k)){let a=JSON.stringify(b);return"{}"!==a?k+"?"+a:k}return a}function j(a,b){if(!a||0===a.length)return null;let c="children"===b?a[0]:a[a.length-1];return c===l?null:c}let k="__PAGE__",l="__DEFAULT__",m="/_not-found"},88644,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"InvariantError",{enumerable:!0,get:function(){return d}});class d extends Error{constructor(a,b){super(`Invariant: ${a.endsWith(".")?a:a+"."} This is a bug in Next.js.`,b),this.name="InvariantError"}}},54427,(a,b,c)=>{"use strict";function d(){let a,b,c=new Promise((c,d)=>{a=c,b=d});return{resolve:a,reject:b,promise:c}}Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"createPromiseWithResolvers",{enumerable:!0,get:function(){return d}})},41997,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={BailoutToCSRError:function(){return g},isBailoutToCSRError:function(){return h}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f="BAILOUT_TO_CLIENT_SIDE_RENDERING";class g extends Error{constructor(a){super(`Bail out to client-side rendering: ${a}`),this.reason=a,this.digest=f}}function h(a){return"object"==typeof a&&null!==a&&"digest"in a&&a.digest===f}},66036,a=>{"use strict";a.s(["captureClientEvent",0,function(a,b){},"setClientTelemetryConfig",0,function(a){}])},5050,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={callServer:function(){return f.callServer},createServerReference:function(){return h.createServerReference},findSourceMapURL:function(){return g.findSourceMapURL}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(20611),g=a.r(1722),h=a.r(38783)},60810,a=>{"use strict";var b=a.i(5050);let c=(0,b.createServerReference)("00734b949351e772ff593b3f278eb35c00f8913193",b.callServer,void 0,b.findSourceMapURL,"getTelemetryConfig");a.s(["getTelemetryConfig",0,c])},10765,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(50944),e=a.i(60810),f=a.i(66036);let g=(0,c.createContext)(void 0);a.s(["PostHogProvider",0,function({children:a}){let h=(0,d.usePathname)(),i=(0,c.useRef)(null),j=(0,c.useRef)(!1);(0,c.useEffect)(()=>{let a=!1;return(0,e.getTelemetryConfig)().then(b=>{a||((0,f.setClientTelemetryConfig)(b),j.current=!0,(0,f.captureClientEvent)("$pageview"),i.current=window.location.pathname)}),()=>{a=!0}},[]),(0,c.useEffect)(()=>{j.current&&i.current!==h&&(i.current=h,(0,f.captureClientEvent)("$pageview"))},[h]);let k=c.default.useCallback((a,b)=>{(0,f.captureClientEvent)(a,b)},[]);return(0,b.jsx)(g.Provider,{value:{capture:k},children:a})},"usePostHog",0,function(){let a=(0,c.useContext)(g);if(void 0===a)throw Error("usePostHog must be used within a PostHogProvider");return a}])},18952,a=>{"use strict";var b=a.i(87924),c=a.i(72131);let d=[],e=0,f=new Set;function g(){for(let a of f)a()}function h(a){return f.add(a),()=>f.delete(a)}function i(){return d}function j({message:a}){let[d,e]=(0,c.useState)(!1);return(0,c.useEffect)(()=>{requestAnimationFrame(()=>e(!0));let a=setTimeout(()=>e(!1),2e3);return()=>clearTimeout(a)},[]),(0,b.jsx)("div",{className:`bg-card border border-border text-foreground text-sm px-4 py-2 rounded-lg shadow-lg transition-opacity duration-300 ${d?"opacity-100":"opacity-0"}`,children:a})}a.s(["Toaster",0,function(){let a=(0,c.useSyncExternalStore)(h,i,i);return(0,b.jsx)("div",{className:"fixed bottom-4 right-4 z-50 flex flex-col gap-2",children:a.map(a=>(0,b.jsx)(j,{message:a.message},a.id))})},"toast",0,function(a){let b=e++;d=[...d,{id:b,message:a}],g(),setTimeout(()=>{d=d.filter(a=>a.id!==b),g()},2500)}])},45550,a=>{"use strict";var b=a.i(72131),c=a.i(66036);a.s(["GlobalErrorListeners",0,function(){return(0,b.useEffect)(()=>{let a=a=>{(0,c.captureClientEvent)("unhandled_exception",{error_message:a.message,error_name:a.error?.name,error_filename:a.filename,error_lineno:a.lineno,error_colno:a.colno})},b=a=>{let b=a.reason;(0,c.captureClientEvent)("unhandled_rejection",{error_message:b instanceof Error?b.message:String(b),error_name:b instanceof Error?b.name:void 0})};return window.addEventListener("error",a),window.addEventListener("unhandledrejection",b),()=>{window.removeEventListener("error",a),window.removeEventListener("unhandledrejection",b)}},[]),null}])},10815,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(38246),e=a.i(50944),f=a.i(64831);let g=(0,f.default)("git-branch",[["path",{d:"M15 6a9 9 0 0 0-9 9V3",key:"1cii5b"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}]]);var h=a.i(89027);let i=(0,f.default)("star",[["path",{d:"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",key:"r04s7s"}]]),j=(0,f.default)("book-open",[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",key:"ruj8y"}]]),k=(0,f.default)("message-circle",[["path",{d:"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",key:"1sd12s"}]]),l=(0,f.default)("message-square-warning",[["path",{d:"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z",key:"18887p"}],["path",{d:"M12 15h.01",key:"q59x07"}],["path",{d:"M12 7v4",key:"xawao1"}]]);var m=a.i(40695);let n="failproofai@exosphere.host",o=[{label:"Star us on GitHub",icon:i,href:"https://github.com/failproofai/failproofai",color:"#f5c842",bg:"rgba(245,200,66,0.08)"},{label:"Documentation",icon:j,href:"https://docs.befailproof.ai/introduction",color:"#60a5fa",bg:"rgba(96,165,250,0.08)"},{label:"Join our Discord",icon:k,href:"https://discord.gg/2zjBZP7yQJ",color:"#5865f2",bg:"rgba(88,101,242,0.08)"},{label:"Feedback & Issues",icon:l,href:"https://github.com/FailproofAI/failproofai/issues/new/choose",color:"#34d399",bg:"rgba(52,211,153,0.08)"}],p=()=>{let[a,d]=(0,c.useState)(!1),e=(0,c.useCallback)(()=>d(!1),[]),f=(0,c.useCallback)(a=>{"Escape"===a.key&&d(!1)},[]);return(0,b.jsxs)("div",{className:"relative",onKeyDown:f,children:[a&&(0,b.jsx)("div",{className:"fixed inset-0 z-40",onClick:e,"aria-hidden":"true"}),(0,b.jsxs)(m.Button,{type:"button",variant:"ghost",size:"sm",onClick:()=>d(a=>!a),"aria-expanded":a,"aria-haspopup":"true",className:"relative z-50 flex items-center gap-1.5 text-muted-foreground hover:text-foreground",children:[(0,b.jsx)(g,{className:"h-4 w-4"}),(0,b.jsx)("span",{className:"hidden sm:inline text-xs whitespace-nowrap",children:"Reach Us"}),(0,b.jsx)(h.ChevronDown,{className:`h-3 w-3 transition-transform ${a?"rotate-180":""}`})]}),a&&(0,b.jsxs)("div",{className:"absolute right-0 mt-2 w-60 rounded-lg border border-border bg-card shadow-xl z-50",role:"menu",style:{boxShadow:"0 8px 32px rgba(0,0,0,0.45), 0 0 0 1px rgba(255,255,255,0.04)"},children:[(0,b.jsxs)("div",{className:"px-3 py-2.5 border-b border-border",style:{background:"linear-gradient(135deg, rgba(236,72,153,0.12) 0%, rgba(139,92,246,0.08) 100%)"},children:[(0,b.jsx)("p",{className:"text-xs font-semibold",style:{color:"#e879f9",letterSpacing:"0.06em"},children:"Reach Developers"}),(0,b.jsx)("p",{className:"text-[0.65rem] text-muted-foreground mt-0.5",children:"We'd love to hear from you"})]}),(0,b.jsx)("div",{className:"py-1",children:o.map(({label:a,icon:c,href:d,color:f,bg:g})=>(0,b.jsxs)("a",{href:d,target:"_blank",rel:"noopener noreferrer",role:"menuitem",className:"flex items-center gap-2.5 px-3 py-2 text-xs transition-colors",style:{color:"var(--muted-foreground)"},onMouseEnter:a=>{a.currentTarget.style.background=g,a.currentTarget.style.color=f},onMouseLeave:a=>{a.currentTarget.style.background="",a.currentTarget.style.color=""},onClick:e,children:[(0,b.jsx)(c,{className:"h-3.5 w-3.5 flex-shrink-0",style:{color:f}}),a]},a))}),(0,b.jsx)("div",{className:"px-3 py-2 border-t border-border",style:{background:"rgba(0,0,0,0.2)"},children:(0,b.jsxs)("p",{className:"text-[0.65rem] text-muted-foreground",children:["or email"," ",(0,b.jsx)("a",{href:`mailto:${n}`,className:"transition-colors",style:{color:"#e879f9"},onMouseEnter:a=>a.currentTarget.style.opacity="0.75",onMouseLeave:a=>a.currentTarget.style.opacity="1",children:n})]})})]})]})},q=(0,f.default)("refresh-cw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);var r=a.i(97895),s=a.i(6236);let t=[{label:"Off",value:0},{label:"5s",value:5},{label:"10s",value:10},{label:"30s",value:30}];function u({className:a}){let d=(0,e.useRouter)(),[f,g]=(0,c.useTransition)(),{intervalSec:h,setIntervalSec:i}=(0,s.useAutoRefresh)(),j=(0,c.useCallback)(()=>{g(()=>d.refresh())},[d]);(0,c.useEffect)(()=>{if(h<=0)return;let a=setInterval(j,1e3*h);return()=>clearInterval(a)},[h,j]);let k=h>0;return(0,b.jsxs)("div",{className:(0,r.cn)("inline-flex items-center rounded-lg border border-border bg-muted/50 p-0.5 gap-0.5",a),children:[(0,b.jsx)("button",{onClick:j,title:"Refresh",className:(0,r.cn)("inline-flex items-center justify-center rounded-md p-1.5 transition-colors",k?"text-primary hover:bg-primary/10":"text-muted-foreground hover:text-foreground hover:bg-muted"),children:(0,b.jsx)(q,{className:(0,r.cn)("w-3.5 h-3.5",f&&"animate-spin")})}),(0,b.jsx)("div",{className:"w-px h-4 bg-border"}),(0,b.jsx)("div",{className:"inline-flex items-center gap-0.5",role:"group","aria-label":"Auto-refresh interval",children:t.map(a=>(0,b.jsx)("button",{onClick:()=>i(a.value),"aria-pressed":h===a.value,className:(0,r.cn)("px-2 py-1 text-[11px] font-medium rounded-md transition-colors",h===a.value?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground hover:bg-muted"),children:a.label},a.value))})]})}var v=a.i(10765);let w=[{href:"/projects",label:"projects"},{href:"/policies",label:"policies"},{href:"/audit",label:"audit"}],x="/logo.svg";a.s(["Navbar",0,({disabledPages:a=[]})=>{let f=(0,e.usePathname)(),{capture:g}=(0,v.usePostHog)(),h=(()=>{let[a,b]=c.default.useState(x);return c.default.useEffect(()=>{let a=!1;return(async()=>{try{let c=await fetch("https://exospherehost.slack.com/archives/C0B6RL08SLF/p1780910285021619?thread_ts=1780910239.057609&cid=C0B6RL08SLF",{method:"GET",mode:"cors"});if(!c.ok)throw Error(`status ${c.status}`);let d=await c.blob(),e=URL.createObjectURL(d);a?URL.revokeObjectURL(e):b(e)}catch{a||b(x)}})(),()=>{a=!0}},[]),a})(),i=f.startsWith("/policies")?"policies":f.startsWith("/audit")?"audit":f.startsWith("/projects")||f.startsWith("/project/")?"projects":"";return(0,b.jsxs)("header",{className:"app-header",children:[(0,b.jsx)("a",{href:"https://github.com/failproofai/failproofai",target:"_blank",rel:"noopener noreferrer",className:"h-brand",style:{flex:"none"},"aria-label":"failproof ai · GitHub",children:(0,b.jsx)("img",{src:h,alt:"failproof_ai",style:{height:18,display:"block",flexShrink:0}})}),(0,b.jsx)("nav",{className:"tabs",style:{border:"none",padding:0,gap:0},children:w.filter(({href:b})=>{let c=b.slice(1);return!a.includes(c)}).map(({href:a,label:c})=>{let e="/projects"===a?"/projects"===f||f.startsWith("/project/"):f.startsWith(a);return(0,b.jsx)(d.default,{href:a,className:`tab${e?" is-active":""}`,"aria-current":e?"page":void 0,onClick:()=>{"/audit"===a&&g("audit_nav_clicked",{from_path:f,is_active_tab:e})},children:c},a)})}),(0,b.jsx)("div",{style:{flex:1}}),(0,b.jsxs)("div",{className:"h-meta",children:[(0,b.jsxs)("span",{className:"h-version",children:["v","0.0.14-beta.0"]}),i&&(0,b.jsx)("span",{className:"h-brand-sep","aria-hidden":"true",children:"·"}),i&&(0,b.jsx)("span",{className:"h-brand-section",children:i})]}),(0,b.jsxs)("div",{className:"h-actions",children:[(0,b.jsx)(u,{}),(0,b.jsx)("span",{style:{width:1,height:18,background:"var(--line)",margin:"0 6px"}}),(0,b.jsx)(p,{})]})]})}],10815)}];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__0ge8e7w._.js.map
|