failproofai 1.0.9-beta.1 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.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 +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.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 +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- 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/audit/status/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/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/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 +14 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +1 -1
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3yc._.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]__04usis8._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15578wp._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__03m2iw6._.js → [root-of-the-server]__1ec94jt._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m_svbe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_042cgl1._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_11ilmst._.js → _0xq-p5o._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1jatlmf._.js → _1g7s7di._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1gb0ifp._.js +3 -3
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.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/app_settings_02tf1h4._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- 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 +23 -23
- package/.next/standalone/.next/static/chunks/{1uec0n0lcx5h1.js → 03madt33xbsx2.js} +1 -1
- package/.next/standalone/.next/static/chunks/0w8_n30wmnorq.js +1 -0
- package/.next/standalone/.next/static/chunks/{3vp54x0dyrrm6.js → 0zlixskj11-yh.js} +1 -1
- package/.next/standalone/.next/static/chunks/{21qlo00jis4w-.js → 1-n1o5wh4wfy6.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2n00c3zqyloy9.js → 1t6tmwe_1myeo.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3tv107_for_n7.js → 28z6u4u7hdrnd.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1r74hmr1wm_sd.js → 2dj6xq9mueqb6.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1-d48e9k-7e1a.js → 2lczelmvvc2yg.js} +1 -1
- package/.next/standalone/.next/static/chunks/{08ckontevw-0w.js → 3fbsuyflx-2qi.js} +1 -1
- package/.next/standalone/.next/static/chunks/{21-pqc3-l9ak2.js → 3jffngwvgxm5q.js} +1 -1
- package/.next/standalone/package.json +9 -9
- package/.next/standalone/sdk/typescript/CHANGELOG.md +39 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +3 -3
- package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +1 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +16 -113
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +3 -1
- package/.next/standalone/server.js +1 -1
- package/dist/cli.mjs +254 -124
- package/dist/worker.mjs +1 -1
- package/package.json +9 -9
- package/src/hooks/daemon-service.ts +14 -1
- package/src/hooks/integrations.ts +133 -31
- package/src/hooks/safe-config-write.ts +80 -7
- package/.next/standalone/.next/static/chunks/0pefjgvu4x-sx.js +0 -1
- /package/.next/standalone/.next/static/{ozuWoyIwOTqeUUjKqOKiH → Q2PyL8ZdGGdvVnn-3FrL2}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{ozuWoyIwOTqeUUjKqOKiH → Q2PyL8ZdGGdvVnn-3FrL2}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{ozuWoyIwOTqeUUjKqOKiH → Q2PyL8ZdGGdvVnn-3FrL2}/_ssgManifest.js +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "failproofai",
|
|
3
|
-
"version": "1.0.9
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Observability and enforcement for AI agent harnesses. 40 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",
|
|
@@ -122,15 +122,15 @@
|
|
|
122
122
|
"browserslist": "4.28.8"
|
|
123
123
|
},
|
|
124
124
|
"optionalDependencies": {
|
|
125
|
-
"@failproofai/failproofaid-linux-x64": "1.0.9
|
|
126
|
-
"@failproofai/failproofaid-linux-arm64": "1.0.9
|
|
127
|
-
"@failproofai/failproofaid-darwin-x64": "1.0.9
|
|
128
|
-
"@failproofai/failproofaid-darwin-arm64": "1.0.9
|
|
125
|
+
"@failproofai/failproofaid-linux-x64": "1.0.9",
|
|
126
|
+
"@failproofai/failproofaid-linux-arm64": "1.0.9",
|
|
127
|
+
"@failproofai/failproofaid-darwin-x64": "1.0.9",
|
|
128
|
+
"@failproofai/failproofaid-darwin-arm64": "1.0.9"
|
|
129
129
|
},
|
|
130
130
|
"failproofaidBinaries": {
|
|
131
|
-
"linux-x64": "
|
|
132
|
-
"linux-arm64": "
|
|
133
|
-
"darwin-x64": "
|
|
134
|
-
"darwin-arm64": "
|
|
131
|
+
"linux-x64": "c406199fbd5682ee84eb3bdd679fe48d1f78a26e97710f05bcfe42771e33ca4a",
|
|
132
|
+
"linux-arm64": "8ec339035013aaf069bd882660b89eefde137a5fb3c66bed9c65bfbfa1afaa19",
|
|
133
|
+
"darwin-x64": "fdf77e2432131ff6081769555c0a87d709d3380c78bc33de92743694dd20a83b",
|
|
134
|
+
"darwin-arm64": "a85e7e2af98fbcc09b6dfdd7fba8289d309757eab6482770ca64d3eeb81407d5"
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -1556,10 +1556,23 @@ export async function refreshDaemonToCliVersion(
|
|
|
1556
1556
|
const prime = deps.prime ?? primeElevation;
|
|
1557
1557
|
const interactive =
|
|
1558
1558
|
deps.interactive ?? (() => Boolean(process.stdin.isTTY && process.stdout.isTTY));
|
|
1559
|
-
|
|
1559
|
+
const current = status();
|
|
1560
|
+
if (current === "not-installed") {
|
|
1560
1561
|
return { ok: true, lines: ["No failproofaid service on this machine; nothing to update."] };
|
|
1561
1562
|
}
|
|
1562
1563
|
|
|
1564
|
+
// Already this version: nothing to install, so nothing to ask root for. The
|
|
1565
|
+
// reinstall below is idempotent, but it needs sudo, so without this every
|
|
1566
|
+
// `update` after the daemon was brought current either prompted for a password
|
|
1567
|
+
// for no reason or — with no TTY to prompt on (a fleet box, CI) — failed with
|
|
1568
|
+
// "root privileges are required" and exited 1 on a machine that was fine.
|
|
1569
|
+
// `VERSION.daemon` is written only after an install succeeds, and the binary
|
|
1570
|
+
// it names must still be on disk.
|
|
1571
|
+
const recorded = readVersionFile()?.daemon;
|
|
1572
|
+
if (current === "running" && recorded === version && existsSync(installedBinaryPath(version))) {
|
|
1573
|
+
return { ok: true, lines: [`failproofaid ${version} is already installed and running; nothing to update.`] };
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1563
1576
|
// `installDaemonService()`, not a binary fetch plus a restart.
|
|
1564
1577
|
//
|
|
1565
1578
|
// The first version of this did the latter, and it did not work: it called
|
|
@@ -1178,7 +1178,7 @@ export const opencode: Integration = {
|
|
|
1178
1178
|
// (a) Write the shim file. mkdirSync is recursive so the plugins/ dir
|
|
1179
1179
|
// is created on first install.
|
|
1180
1180
|
mkdirSync(dirname(pluginPath), { recursive: true });
|
|
1181
|
-
writeConfigFileAtomic(pluginPath, buildOpenCodePluginShim(binaryPath, effectiveScope));
|
|
1181
|
+
writeConfigFileAtomic(pluginPath, buildOpenCodePluginShim(binaryPath, effectiveScope), { symlinks: "replace" });
|
|
1182
1182
|
|
|
1183
1183
|
// (b) Merge our entry into the plugin array idempotently. Replace any
|
|
1184
1184
|
// existing failproofai-marked entry; otherwise append.
|
|
@@ -1518,17 +1518,61 @@ function hasAllHermesPluginFiles(dir: string): boolean {
|
|
|
1518
1518
|
}
|
|
1519
1519
|
|
|
1520
1520
|
/**
|
|
1521
|
-
*
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1524
|
-
*
|
|
1521
|
+
* The record FailproofAI keeps beside a link it created:
|
|
1522
|
+
* `<profile>/plugins/.failproofai-link`, holding the link's target. It lives
|
|
1523
|
+
* OUTSIDE the linked directory on purpose — anything inside the target is
|
|
1524
|
+
* content whoever owns that directory controls. Hermes' plugin scan skips it
|
|
1525
|
+
* (a file, not a directory).
|
|
1525
1526
|
*/
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1527
|
+
const HERMES_LINK_RECORD = ".failproofai-link";
|
|
1528
|
+
|
|
1529
|
+
function hermesLinkRecordPath(pluginPath: string): string {
|
|
1530
|
+
return resolve(dirname(pluginPath), HERMES_LINK_RECORD);
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
function readHermesLinkRecord(pluginPath: string): string | null {
|
|
1534
|
+
try {
|
|
1535
|
+
const recorded = readFileSync(hermesLinkRecordPath(pluginPath), "utf8").trim();
|
|
1536
|
+
return recorded === "" ? null : resolve(recorded);
|
|
1537
|
+
} catch {
|
|
1538
|
+
return null;
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
function writeHermesLinkRecord(pluginPath: string, target: string): void {
|
|
1543
|
+
writeConfigFileAtomic(hermesLinkRecordPath(pluginPath), resolve(target) + "\n", { backup: false, symlinks: "replace" });
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
function removeHermesLinkRecord(pluginPath: string): void {
|
|
1547
|
+
rmSync(hermesLinkRecordPath(pluginPath), { force: true });
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
/**
|
|
1551
|
+
* Whether a link at `pluginPath` pointing at `target` is FailproofAI's.
|
|
1552
|
+
*
|
|
1553
|
+
* A directory name and a manifest `name:` are things any plugin can copy, so
|
|
1554
|
+
* neither proves anything. Ownership is one of two verifiable facts:
|
|
1555
|
+
*
|
|
1556
|
+
* 1. our record: the link target equals what `.failproofai-link` says we
|
|
1557
|
+
* linked (every link this build creates is recorded), or
|
|
1558
|
+
* 2. provenance, for links created before the record existed (the 1.0.9
|
|
1559
|
+
* betas): the target IS this package's `hermes-plugin/`, or it is
|
|
1560
|
+
* `…/node_modules/failproofai/hermes-plugin` inside a directory whose
|
|
1561
|
+
* `package.json` names the package `failproofai`.
|
|
1562
|
+
*
|
|
1563
|
+
* Anything else — including a same-named, same-manifest plugin somewhere
|
|
1564
|
+
* else, or a dangling link with no record — is foreign and never touched.
|
|
1565
|
+
*/
|
|
1566
|
+
function isOwnedHermesPluginLink(pluginPath: string, target: string): boolean {
|
|
1567
|
+
const recorded = readHermesLinkRecord(pluginPath);
|
|
1568
|
+
if (recorded && resolve(target) === recorded) return true;
|
|
1569
|
+
if (samePath(target, getHermesPluginSourcePath())) return true;
|
|
1570
|
+
const pkgRoot = dirname(resolve(target));
|
|
1571
|
+
if (basename(resolve(target)) !== HERMES_PLUGIN_SOURCE_DIR) return false;
|
|
1572
|
+
if (basename(pkgRoot) !== "failproofai" || basename(dirname(pkgRoot)) !== "node_modules") return false;
|
|
1529
1573
|
try {
|
|
1530
|
-
const
|
|
1531
|
-
return
|
|
1574
|
+
const pkg = JSON.parse(readFileSync(resolve(pkgRoot, "package.json"), "utf8")) as { name?: unknown };
|
|
1575
|
+
return pkg.name === "failproofai";
|
|
1532
1576
|
} catch {
|
|
1533
1577
|
return false;
|
|
1534
1578
|
}
|
|
@@ -1578,7 +1622,7 @@ function hermesPluginState(settingsPath: string): HermesPluginState {
|
|
|
1578
1622
|
} catch {
|
|
1579
1623
|
return { kind: "foreign" };
|
|
1580
1624
|
}
|
|
1581
|
-
if (!
|
|
1625
|
+
if (!isOwnedHermesPluginLink(pluginPath, target)) return { kind: "foreign" };
|
|
1582
1626
|
return {
|
|
1583
1627
|
kind: "link",
|
|
1584
1628
|
target,
|
|
@@ -1636,7 +1680,18 @@ export function installHermesPlugin(
|
|
|
1636
1680
|
`Move it aside or install FailproofAI under a different Hermes profile.`,
|
|
1637
1681
|
);
|
|
1638
1682
|
}
|
|
1639
|
-
if (existing.kind === "link" && existing.current)
|
|
1683
|
+
if (existing.kind === "link" && existing.current) {
|
|
1684
|
+
// A link from a 1.0.9 beta was proven ours by provenance; record it now so
|
|
1685
|
+
// ownership no longer depends on where npm keeps the package.
|
|
1686
|
+
if (readHermesLinkRecord(destination) !== resolve(existing.target)) {
|
|
1687
|
+
try {
|
|
1688
|
+
writeHermesLinkRecord(destination, existing.target);
|
|
1689
|
+
} catch {
|
|
1690
|
+
// Provenance still proves it on the next run; not worth failing over.
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
return "unchanged";
|
|
1694
|
+
}
|
|
1640
1695
|
|
|
1641
1696
|
mkdirSync(dirname(destination), { recursive: true });
|
|
1642
1697
|
const suffix = `${process.pid}-${Date.now()}`;
|
|
@@ -1673,6 +1728,7 @@ export function installHermesPlugin(
|
|
|
1673
1728
|
if (linked && (existing.kind === "absent" || existing.kind === "link")) {
|
|
1674
1729
|
try {
|
|
1675
1730
|
renameSync(temporary, destination);
|
|
1731
|
+
writeHermesLinkRecord(destination, source);
|
|
1676
1732
|
return "linked";
|
|
1677
1733
|
} catch (err) {
|
|
1678
1734
|
// Windows cannot always rename a junction over another junction; the
|
|
@@ -1695,6 +1751,8 @@ export function installHermesPlugin(
|
|
|
1695
1751
|
renameSync(temporary, destination);
|
|
1696
1752
|
// fs.rm never follows a symlink, so a backed-up link removes only itself.
|
|
1697
1753
|
if (movedExisting) rmSync(backup, { recursive: true, force: true });
|
|
1754
|
+
if (linked) writeHermesLinkRecord(destination, source);
|
|
1755
|
+
else removeHermesLinkRecord(destination);
|
|
1698
1756
|
} catch (err) {
|
|
1699
1757
|
rmSync(temporary, { recursive: true, force: true });
|
|
1700
1758
|
if (movedExisting && !pathPresent(destination) && pathPresent(backup)) {
|
|
@@ -1711,6 +1769,7 @@ function removeManagedHermesPlugin(settingsPath: string): boolean {
|
|
|
1711
1769
|
if (state.kind === "link") {
|
|
1712
1770
|
// Only the link goes; the package directory it points at is npm's.
|
|
1713
1771
|
unlinkSync(pluginPath);
|
|
1772
|
+
removeHermesLinkRecord(pluginPath);
|
|
1714
1773
|
return true;
|
|
1715
1774
|
}
|
|
1716
1775
|
// The marker is the ownership boundary. Remove even an incomplete managed
|
|
@@ -1748,28 +1807,44 @@ function removeLegacyHermesHooks(doc: Document): number {
|
|
|
1748
1807
|
}
|
|
1749
1808
|
|
|
1750
1809
|
function hermesConfigState(settingsPath: string): {
|
|
1810
|
+
/** Hermes will load it: listed in `plugins.enabled` AND not in `plugins.disabled`. */
|
|
1751
1811
|
pluginEnabled: boolean;
|
|
1812
|
+
/** Listed in `plugins.enabled`, whatever `plugins.disabled` says. */
|
|
1813
|
+
pluginListed: boolean;
|
|
1814
|
+
/** Listed in `plugins.disabled`, which Hermes checks first and which wins. */
|
|
1815
|
+
pluginDisabled: boolean;
|
|
1752
1816
|
legacyShellHookPresent: boolean;
|
|
1753
1817
|
unreadable?: boolean;
|
|
1754
1818
|
} {
|
|
1755
1819
|
if (!existsSync(settingsPath)) {
|
|
1756
|
-
return { pluginEnabled: false, legacyShellHookPresent: false };
|
|
1820
|
+
return { pluginEnabled: false, pluginListed: false, pluginDisabled: false, legacyShellHookPresent: false };
|
|
1757
1821
|
}
|
|
1758
1822
|
const doc = inspectYamlDoc(settingsPath);
|
|
1759
|
-
if (!doc)
|
|
1823
|
+
if (!doc) {
|
|
1824
|
+
return { pluginEnabled: false, pluginListed: false, pluginDisabled: false, legacyShellHookPresent: false, unreadable: true };
|
|
1825
|
+
}
|
|
1760
1826
|
const js = (doc.toJS() ?? {}) as {
|
|
1761
1827
|
hooks?: Record<string, HermesHookEntry[]>;
|
|
1762
1828
|
plugins?: HermesPluginsConfig;
|
|
1763
1829
|
};
|
|
1764
1830
|
const enabled = js.plugins?.enabled;
|
|
1831
|
+
const disabled = js.plugins?.disabled;
|
|
1765
1832
|
const legacyShellHookPresent =
|
|
1766
1833
|
!!js.hooks &&
|
|
1767
1834
|
typeof js.hooks === "object" &&
|
|
1768
1835
|
Object.values(js.hooks).some(
|
|
1769
1836
|
(entries) => Array.isArray(entries) && entries.some((entry) => isMarkedHook(entry)),
|
|
1770
1837
|
);
|
|
1838
|
+
// Hermes gates `plugins.disabled` before `plugins.enabled`
|
|
1839
|
+
// (hermes_cli/plugins_discovery.py `gate_manifest`), so a plugin in both
|
|
1840
|
+
// lists never loads. Treating that as enabled reported a switched-off plugin
|
|
1841
|
+
// healthy and let `update` skip it as "already current".
|
|
1842
|
+
const pluginListed = Array.isArray(enabled) && enabled.includes(HERMES_PLUGIN_ID);
|
|
1843
|
+
const pluginDisabled = Array.isArray(disabled) && disabled.includes(HERMES_PLUGIN_ID);
|
|
1771
1844
|
return {
|
|
1772
|
-
pluginEnabled:
|
|
1845
|
+
pluginEnabled: pluginListed && !pluginDisabled,
|
|
1846
|
+
pluginListed,
|
|
1847
|
+
pluginDisabled,
|
|
1773
1848
|
legacyShellHookPresent,
|
|
1774
1849
|
};
|
|
1775
1850
|
}
|
|
@@ -1835,6 +1910,9 @@ export async function migrateHermesProfiles(opts: {
|
|
|
1835
1910
|
const results: HermesProfileMigration[] = [];
|
|
1836
1911
|
let daemonOk: boolean | undefined;
|
|
1837
1912
|
for (const profile of listHermesProfiles()) {
|
|
1913
|
+
// One profile's surprise (a file removed mid-run, a permission change) is
|
|
1914
|
+
// that profile's failed line — never the end of the report for the rest.
|
|
1915
|
+
try {
|
|
1838
1916
|
if (!existsSync(profile.home)) continue;
|
|
1839
1917
|
const settingsPath = resolve(profile.home, "config.yaml");
|
|
1840
1918
|
const pluginPath = hermesPluginPathForSettings(settingsPath);
|
|
@@ -1867,11 +1945,20 @@ export async function migrateHermesProfiles(opts: {
|
|
|
1867
1945
|
continue;
|
|
1868
1946
|
}
|
|
1869
1947
|
|
|
1870
|
-
if (!legacy && !ours && !config.
|
|
1948
|
+
if (!legacy && !ours && !config.pluginListed && !config.pluginDisabled) {
|
|
1871
1949
|
results.push({ ...base, status: "untouched", detail: "no failproofai integration", legacyShellHooksRemain: false });
|
|
1872
1950
|
continue;
|
|
1873
1951
|
}
|
|
1874
1952
|
if (plugin.kind === "link" && plugin.current && plugin.complete && config.pluginEnabled && !legacy) {
|
|
1953
|
+
// A link a 1.0.9 beta created was proven ours by provenance; record it
|
|
1954
|
+
// so ownership stops depending on where npm keeps the package.
|
|
1955
|
+
if (readHermesLinkRecord(pluginPath) !== resolve(plugin.target)) {
|
|
1956
|
+
try {
|
|
1957
|
+
writeHermesLinkRecord(pluginPath, plugin.target);
|
|
1958
|
+
} catch {
|
|
1959
|
+
// Provenance still proves it on the next run.
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1875
1962
|
results.push({ ...base, status: "current", detail: "already linked", legacyShellHooksRemain: false });
|
|
1876
1963
|
continue;
|
|
1877
1964
|
}
|
|
@@ -1886,19 +1973,6 @@ export async function migrateHermesProfiles(opts: {
|
|
|
1886
1973
|
});
|
|
1887
1974
|
continue;
|
|
1888
1975
|
}
|
|
1889
|
-
if (existsSync(settingsPath)) {
|
|
1890
|
-
const errors = parseDocument(readFileSync(settingsPath, "utf8")).errors;
|
|
1891
|
-
if (errors.length > 0) {
|
|
1892
|
-
results.push({
|
|
1893
|
-
...base,
|
|
1894
|
-
status: "failed",
|
|
1895
|
-
detail: `${settingsPath} does not parse as YAML; left untouched`,
|
|
1896
|
-
legacyShellHooksRemain: legacy,
|
|
1897
|
-
});
|
|
1898
|
-
continue;
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
|
|
1902
1976
|
if (daemonOk === undefined) daemonOk = await opts.daemonSupportsPolicyEvaluation();
|
|
1903
1977
|
if (!daemonOk) {
|
|
1904
1978
|
results.push({
|
|
@@ -1919,6 +1993,7 @@ export async function migrateHermesProfiles(opts: {
|
|
|
1919
1993
|
const doc = readYamlDoc(settingsPath);
|
|
1920
1994
|
enableHermesPluginInDoc(doc);
|
|
1921
1995
|
writeYamlDoc(settingsPath, doc);
|
|
1996
|
+
const reenabledOnly = !legacy && plugin.kind === "link" && plugin.current && mode === "unchanged";
|
|
1922
1997
|
const from = legacy
|
|
1923
1998
|
? "shell hooks"
|
|
1924
1999
|
: plugin.kind === "copy"
|
|
@@ -1927,7 +2002,12 @@ export async function migrateHermesProfiles(opts: {
|
|
|
1927
2002
|
? "old plugin link"
|
|
1928
2003
|
: "enabled but missing plugin";
|
|
1929
2004
|
const to = mode === "copied" ? "plugin copy (symlink not possible here)" : "linked plugin";
|
|
1930
|
-
|
|
2005
|
+
const detail = reenabledOnly
|
|
2006
|
+
? config.pluginDisabled
|
|
2007
|
+
? "plugin re-enabled (was listed in plugins.disabled)"
|
|
2008
|
+
: "plugin enabled in config.yaml"
|
|
2009
|
+
: `${from} → ${to}`;
|
|
2010
|
+
results.push({ ...base, status: "migrated", detail, legacyShellHooksRemain: false });
|
|
1931
2011
|
} catch (err) {
|
|
1932
2012
|
results.push({
|
|
1933
2013
|
...base,
|
|
@@ -1936,6 +2016,15 @@ export async function migrateHermesProfiles(opts: {
|
|
|
1936
2016
|
legacyShellHooksRemain: hermesConfigState(settingsPath).legacyShellHookPresent,
|
|
1937
2017
|
});
|
|
1938
2018
|
}
|
|
2019
|
+
} catch (err) {
|
|
2020
|
+
results.push({
|
|
2021
|
+
name: profile.name,
|
|
2022
|
+
home: profile.home,
|
|
2023
|
+
status: "failed",
|
|
2024
|
+
detail: `could not inspect this profile (${err instanceof Error ? err.message : String(err)}); left untouched`,
|
|
2025
|
+
legacyShellHooksRemain: false,
|
|
2026
|
+
});
|
|
2027
|
+
}
|
|
1939
2028
|
}
|
|
1940
2029
|
return results;
|
|
1941
2030
|
}
|
|
@@ -1948,6 +2037,8 @@ export interface HermesProfileHealth {
|
|
|
1948
2037
|
/** How the plugin is installed: a link into the package, a copy, or neither. */
|
|
1949
2038
|
pluginMode: "link" | "copy" | null;
|
|
1950
2039
|
pluginEnabled: boolean;
|
|
2040
|
+
/** failproofai is listed in `plugins.disabled`, so Hermes will not load it. */
|
|
2041
|
+
pluginDisabled: boolean;
|
|
1951
2042
|
legacyShellHookPresent: boolean;
|
|
1952
2043
|
/**
|
|
1953
2044
|
* Still enforced only by legacy config.yaml shell hooks. Hermes cron jobs run
|
|
@@ -1956,6 +2047,8 @@ export interface HermesProfileHealth {
|
|
|
1956
2047
|
cronUnchecked: boolean;
|
|
1957
2048
|
/** config.yaml exists but does not parse; failproofai will not touch it. */
|
|
1958
2049
|
configUnreadable: boolean;
|
|
2050
|
+
/** Another plugin (not provably FailproofAI's) occupies plugins/failproofai. */
|
|
2051
|
+
pluginForeign: boolean;
|
|
1959
2052
|
healthy: boolean;
|
|
1960
2053
|
}
|
|
1961
2054
|
|
|
@@ -1974,9 +2067,11 @@ export function hermesProfileHealth(): HermesProfileHealth[] {
|
|
|
1974
2067
|
pluginInstalled,
|
|
1975
2068
|
pluginMode: plugin.kind === "link" || plugin.kind === "copy" ? plugin.kind : null,
|
|
1976
2069
|
pluginEnabled: config.pluginEnabled,
|
|
2070
|
+
pluginDisabled: config.pluginDisabled,
|
|
1977
2071
|
legacyShellHookPresent: config.legacyShellHookPresent,
|
|
1978
2072
|
cronUnchecked: config.legacyShellHookPresent && !pluginWorks,
|
|
1979
2073
|
configUnreadable: config.unreadable === true,
|
|
2074
|
+
pluginForeign: plugin.kind === "foreign",
|
|
1980
2075
|
healthy: pluginWorks && !config.legacyShellHookPresent && config.unreadable !== true,
|
|
1981
2076
|
};
|
|
1982
2077
|
});
|
|
@@ -1988,6 +2083,12 @@ export function hermesProfileStatusRows(): Array<[string, string]> {
|
|
|
1988
2083
|
.filter((profile) => existsSync(profile.home))
|
|
1989
2084
|
.map((profile) => {
|
|
1990
2085
|
const label = "hermes/" + profile.name;
|
|
2086
|
+
if (profile.pluginForeign) {
|
|
2087
|
+
return [
|
|
2088
|
+
label,
|
|
2089
|
+
`UNHEALTHY — another plugin occupies ${resolve(profile.home, "plugins", "failproofai")}; failproofai will not replace it. Move it aside, then run update`,
|
|
2090
|
+
];
|
|
2091
|
+
}
|
|
1991
2092
|
if (profile.configUnreadable) {
|
|
1992
2093
|
return [label, `UNHEALTHY — ${profile.settingsPath} does not parse; failproofai leaves it untouched until it is fixed`];
|
|
1993
2094
|
}
|
|
@@ -2001,7 +2102,8 @@ export function hermesProfileStatusRows(): Array<[string, string]> {
|
|
|
2001
2102
|
}
|
|
2002
2103
|
const problems: string[] = [];
|
|
2003
2104
|
if (!profile.pluginInstalled) problems.push("plugin files missing or incomplete");
|
|
2004
|
-
if (
|
|
2105
|
+
if (profile.pluginDisabled) problems.push("plugin disabled (listed in plugins.disabled)");
|
|
2106
|
+
else if (!profile.pluginEnabled) problems.push("plugin not enabled");
|
|
2005
2107
|
if (profile.legacyShellHookPresent) problems.push("legacy shell hook also present");
|
|
2006
2108
|
if (problems.length > 0) return [label, "UNHEALTHY — " + problems.join("; ")];
|
|
2007
2109
|
return [
|
|
@@ -29,12 +29,14 @@
|
|
|
29
29
|
import {
|
|
30
30
|
chmodSync,
|
|
31
31
|
closeSync,
|
|
32
|
+
constants as fsConstants,
|
|
32
33
|
copyFileSync,
|
|
33
34
|
existsSync,
|
|
34
35
|
fsyncSync,
|
|
35
36
|
lstatSync,
|
|
36
37
|
mkdirSync,
|
|
37
38
|
openSync,
|
|
39
|
+
readlinkSync,
|
|
38
40
|
realpathSync,
|
|
39
41
|
renameSync,
|
|
40
42
|
rmSync,
|
|
@@ -52,26 +54,97 @@ export function configBackupPath(path: string): string {
|
|
|
52
54
|
/** Hooks for tests to simulate an interruption at the one step that matters. */
|
|
53
55
|
export interface AtomicWriteDeps {
|
|
54
56
|
rename?: (from: string, to: string) => void;
|
|
57
|
+
/** Keep `<name>.failproofai-backup` of the previous version (default true). */
|
|
58
|
+
backup?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* What to do when the path is a symlink. `follow` (default) writes through to
|
|
61
|
+
* the target — right for a user's config, which is read and parsed before it
|
|
62
|
+
* is written and may live in a dotfiles checkout. `replace` swaps the link
|
|
63
|
+
* itself for the new file and never touches what it pointed at — right for a
|
|
64
|
+
* file failproofai generates and fully owns (a plugin shim, an ownership
|
|
65
|
+
* record), which is written without being read, so a planted link must not
|
|
66
|
+
* steer the write into another file.
|
|
67
|
+
*/
|
|
68
|
+
symlinks?: "follow" | "replace";
|
|
55
69
|
}
|
|
56
70
|
|
|
57
|
-
/** A
|
|
71
|
+
/** A config that is a symlink to nothing: writing would either replace the link or create a file somewhere unknown. */
|
|
72
|
+
export class DanglingConfigSymlinkError extends Error {
|
|
73
|
+
constructor(readonly path: string, readonly target: string) {
|
|
74
|
+
super(
|
|
75
|
+
`Refusing to write ${path}: it is a symlink to ${target}, which does not exist. ` +
|
|
76
|
+
`Fix or remove the link, then retry — failproofai will not replace it with a regular file.`,
|
|
77
|
+
);
|
|
78
|
+
this.name = "DanglingConfigSymlinkError";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* A symlinked config is written through to what it points at, so a dotfiles
|
|
84
|
+
* checkout keeps its link. A link whose target does not exist is refused: the
|
|
85
|
+
* rename would replace the link with a regular file (silently detaching the
|
|
86
|
+
* dotfiles), and creating the target instead would write wherever the link
|
|
87
|
+
* says — a path a cloned repository can choose for a project-scoped config.
|
|
88
|
+
*/
|
|
58
89
|
function resolveWriteTarget(path: string): string {
|
|
90
|
+
let isLink = false;
|
|
91
|
+
try {
|
|
92
|
+
isLink = lstatSync(path).isSymbolicLink();
|
|
93
|
+
} catch {
|
|
94
|
+
return path; // absent: a new file at the path as given
|
|
95
|
+
}
|
|
96
|
+
if (!isLink) return path;
|
|
97
|
+
try {
|
|
98
|
+
return realpathSync(path);
|
|
99
|
+
} catch {
|
|
100
|
+
let target = "(unreadable link)";
|
|
101
|
+
try {
|
|
102
|
+
target = readlinkSync(path);
|
|
103
|
+
} catch {
|
|
104
|
+
// keep the placeholder
|
|
105
|
+
}
|
|
106
|
+
throw new DanglingConfigSymlinkError(path, target);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function isSymlink(path: string): boolean {
|
|
59
111
|
try {
|
|
60
|
-
|
|
112
|
+
return lstatSync(path).isSymbolicLink();
|
|
61
113
|
} catch {
|
|
62
|
-
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Keep the previous version beside the file without ever following a link that
|
|
120
|
+
* sits where the backup goes. `copyFileSync` onto `<name>.failproofai-backup`
|
|
121
|
+
* would write THROUGH a symlink planted there — for a project-scoped config
|
|
122
|
+
* inside a cloned repository, into any file the user can write. So the copy
|
|
123
|
+
* goes to a fresh, exclusively created temp file and is renamed over the backup
|
|
124
|
+
* path: a rename replaces a symlink, it does not follow one.
|
|
125
|
+
*/
|
|
126
|
+
function writeBackup(target: string, dir: string): void {
|
|
127
|
+
const backup = `${target}.failproofai-backup`;
|
|
128
|
+
const temporary = join(dir, `.${basename(target)}.failproofai-backup-${process.pid}-${randomBytes(4).toString("hex")}.tmp`);
|
|
129
|
+
try {
|
|
130
|
+
copyFileSync(target, temporary, fsConstants.COPYFILE_EXCL);
|
|
131
|
+
renameSync(temporary, backup);
|
|
132
|
+
} catch (err) {
|
|
133
|
+
rmSync(temporary, { force: true });
|
|
134
|
+
throw err;
|
|
63
135
|
}
|
|
64
|
-
return path;
|
|
65
136
|
}
|
|
66
137
|
|
|
67
138
|
export function writeConfigFileAtomic(path: string, content: string, deps: AtomicWriteDeps = {}): void {
|
|
68
|
-
const
|
|
139
|
+
const replacingLink = deps.symlinks === "replace" && isSymlink(path);
|
|
140
|
+
const target = deps.symlinks === "replace" ? path : resolveWriteTarget(path);
|
|
69
141
|
const dir = dirname(target);
|
|
70
142
|
mkdirSync(dir, { recursive: true });
|
|
71
143
|
|
|
72
144
|
let mode: number | undefined;
|
|
73
145
|
try {
|
|
74
|
-
|
|
146
|
+
// A link being replaced lends nothing: its target's mode is someone else's.
|
|
147
|
+
mode = replacingLink ? undefined : statSync(target).mode & 0o777;
|
|
75
148
|
} catch {
|
|
76
149
|
mode = undefined; // a new file: the process umask decides, as writeFileSync would
|
|
77
150
|
}
|
|
@@ -89,7 +162,7 @@ export function writeConfigFileAtomic(path: string, content: string, deps: Atomi
|
|
|
89
162
|
// `open` applies the umask; the live file's own bits are what should survive.
|
|
90
163
|
if (mode !== undefined) chmodSync(temporary, mode);
|
|
91
164
|
|
|
92
|
-
if (existsSync(target))
|
|
165
|
+
if (deps.backup !== false && !replacingLink && existsSync(target)) writeBackup(target, dir);
|
|
93
166
|
|
|
94
167
|
(deps.rename ?? renameSync)(temporary, target);
|
|
95
168
|
} catch (err) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,70915,e=>{"use strict";var t=e.i(95187);let r=(0,t.createServerReference)("00a9163b93014ab406fd89a6249f844ab47fada4df",t.callServer,void 0,t.findSourceMapURL,"getTelemetryConfig");e.s(["getTelemetryConfig",0,r])},97917,e=>{"use strict";var t=e.i(71645),r=e.i(9969);let n=/\b[\w-]+-extension:\/\//i;function o(e){return"app"===function({stack:e,filename:t,appOrigin:r}){let o=[t,e].filter(Boolean).join("\n");return o.trim()?n.test(o)?"extension":r&&o.includes(r)?"app":"unknown":"unknown"}(e)}e.s(["GlobalErrorListeners",0,function(){return(0,t.useEffect)(()=>{let e=e=>{o({stack:e.error?.stack,filename:e.filename,appOrigin:window.location.origin})&&(0,r.captureClientEvent)("unhandled_exception",{error_message:e.message,error_name:e.error?.name,error_filename:e.filename,error_lineno:e.lineno,error_colno:e.colno})},t=e=>{let t=e.reason;o({stack:t instanceof Error?t.stack:void 0,appOrigin:window.location.origin})&&(0,r.captureClientEvent)("unhandled_rejection",{error_message:t instanceof Error?t.message:String(t),error_name:t instanceof Error?t.name:void 0})};return window.addEventListener("error",e),window.addEventListener("unhandledrejection",t),()=>{window.removeEventListener("error",e),window.removeEventListener("unhandledrejection",t)}},[]),null}],97917)},55574,e=>{"use strict";var t=e.i(43476),r=e.i(71645);let n=[],o=0,a=new Set;function i(){for(let e of a)e()}function s(e){return a.add(e),()=>a.delete(e)}function l(){return n}function u({message:e}){let[n,o]=(0,r.useState)(!1);return(0,r.useEffect)(()=>{requestAnimationFrame(()=>o(!0));let e=setTimeout(()=>o(!1),2e3);return()=>clearTimeout(e)},[]),(0,t.jsx)("div",{className:`bg-card border border-border text-foreground text-sm px-4 py-2 rounded-lg shadow-lg transition-opacity duration-300 ${n?"opacity-100":"opacity-0"}`,children:e})}e.s(["Toaster",0,function(){let e=(0,r.useSyncExternalStore)(s,l,l);return(0,t.jsx)("div",{className:"fixed bottom-4 right-4 z-50 flex flex-col gap-2",children:e.map(e=>(0,t.jsx)(u,{message:e.message},e.id))})},"toast",0,function(e){let t=o++;n=[...n,{id:t,message:e}],i(),setTimeout(()=>{n=n.filter(e=>e.id!==t),i()},2500)}])},63780,e=>{"use strict";var t=e.i(43476),r=e.i(22016),n=e.i(18566),o=e.i(66794),a=e.i(71645),i=e.i(56420);let s={name:"git-branch",size:24,node:[["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"}]]};s.node;let l=(0,i.default)(s);var u=e.i(16327);let c={name:"star",size:24,node:[["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"}]]};c.node;let d=(0,i.default)(c),f={name:"book-open",size:24,node:[["path",{d:"M12 5v16",key:"1f6ucr"}],["path",{d:"M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z",key:"1fyvmf"}]]};f.node;let h=(0,i.default)(f),p={name:"message-circle",size:24,node:[["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"}]]};p.node;let m=(0,i.default)(p),g={name:"messages-square",size:24,node:[["path",{d:"M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z",key:"1n2ejm"}],["path",{d:"M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1",key:"1qfcsi"}]]};g.node;let b=(0,i.default)(g),v={name:"message-square-warning",size:24,node:[["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"}]]};v.node;let y=(0,i.default)(v);var x=e.i(67881);let w="failproofai@exosphere.host",j=[{label:"Star us on GitHub",icon:d,href:"https://github.com/failproofai/failproofai",color:"#f5c842",bg:"rgba(245,200,66,0.08)"},{label:"Documentation",icon:h,href:"https://docs.befailproof.ai/introduction",color:"#60a5fa",bg:"rgba(96,165,250,0.08)"},{label:"Join our Discord",icon:m,href:"https://discord.befailproof.ai/",color:"#5865f2",bg:"rgba(88,101,242,0.08)"},{label:"Join r/failproofai",icon:b,href:"https://www.reddit.com/r/failproofai/",color:"#ff4500",bg:"rgba(255,69,0,0.08)"},{label:"Feedback & Issues",icon:y,href:"https://github.com/FailproofAI/failproofai/issues/new/choose",color:"#34d399",bg:"rgba(52,211,153,0.08)"}],k=()=>{let[e,r]=(0,a.useState)(!1),n=(0,a.useCallback)(()=>r(!1),[]),o=(0,a.useCallback)(e=>{"Escape"===e.key&&r(!1)},[]);return(0,t.jsxs)("div",{className:"relative",onKeyDown:o,children:[e&&(0,t.jsx)("div",{className:"fixed inset-0 z-40",onClick:n,"aria-hidden":"true"}),(0,t.jsxs)(x.Button,{type:"button",variant:"ghost",size:"sm",onClick:()=>r(e=>!e),"aria-expanded":e,"aria-haspopup":"true",className:"relative z-50 flex items-center gap-1.5 text-muted-foreground hover:text-foreground",children:[(0,t.jsx)(l,{className:"h-4 w-4"}),(0,t.jsx)("span",{className:"hidden sm:inline text-xs whitespace-nowrap",children:"Reach Us"}),(0,t.jsx)(u.ChevronDown,{className:`h-3 w-3 transition-transform ${e?"rotate-180":""}`})]}),e&&(0,t.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,t.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,t.jsx)("p",{className:"text-xs font-semibold",style:{color:"#e879f9",letterSpacing:"0.06em"},children:"Reach Developers"}),(0,t.jsx)("p",{className:"text-[0.65rem] text-muted-foreground mt-0.5",children:"We'd love to hear from you"})]}),(0,t.jsx)("div",{className:"py-1",children:j.map(({label:e,icon:r,href:o,color:a,bg:i})=>(0,t.jsxs)("a",{href:o,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:e=>{e.currentTarget.style.background=i,e.currentTarget.style.color=a},onMouseLeave:e=>{e.currentTarget.style.background="",e.currentTarget.style.color=""},onClick:n,children:[(0,t.jsx)(r,{className:"h-3.5 w-3.5 flex-shrink-0",style:{color:a}}),e]},e))}),(0,t.jsx)("div",{className:"px-3 py-2 border-t border-border",style:{background:"rgba(0,0,0,0.2)"},children:(0,t.jsxs)("p",{className:"text-[0.65rem] text-muted-foreground",children:["or email"," ",(0,t.jsx)("a",{href:`mailto:${w}`,className:"transition-colors",style:{color:"#e879f9"},onMouseEnter:e=>e.currentTarget.style.opacity="0.75",onMouseLeave:e=>e.currentTarget.style.opacity="1",children:w})]})})]})]})},N={name:"refresh-cw",size:24,node:[["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"}]]};N.node;let S=(0,i.default)(N);var C=e.i(47163),E=e.i(85881);let _=[{label:"Off",value:0},{label:"5s",value:5},{label:"10s",value:10},{label:"30s",value:30}];function P({className:e}){let r=(0,n.useRouter)(),[o,i]=(0,a.useTransition)(),{intervalSec:s,setIntervalSec:l}=(0,E.useAutoRefresh)(),u=(0,a.useCallback)(()=>{i(()=>r.refresh())},[r]);(0,a.useEffect)(()=>{if(s<=0)return;let e=setInterval(u,1e3*s);return()=>clearInterval(e)},[s,u]);let c=s>0;return(0,t.jsxs)("div",{className:(0,C.cn)("inline-flex items-center rounded-lg border border-border bg-muted/50 p-0.5 gap-0.5",e),children:[(0,t.jsx)("button",{onClick:u,title:"Refresh",className:(0,C.cn)("inline-flex items-center justify-center rounded-md p-1.5 transition-colors",c?"text-primary hover:bg-primary/10":"text-muted-foreground hover:text-foreground hover:bg-muted"),children:(0,t.jsx)(S,{className:(0,C.cn)("w-3.5 h-3.5",o&&"animate-spin")})}),(0,t.jsx)("div",{className:"w-px h-4 bg-border"}),(0,t.jsx)("div",{className:"inline-flex items-center gap-0.5",role:"group","aria-label":"Auto-refresh interval",children:_.map(e=>(0,t.jsx)("button",{onClick:()=>l(e.value),"aria-pressed":s===e.value,className:(0,C.cn)("px-2 py-1 text-[11px] font-medium rounded-md transition-colors",s===e.value?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground hover:bg-muted"),children:e.label},e.value))})]})}var T=e.i(12344);let R=[{href:"/projects",label:"projects"},{href:"/policies",label:"policies"},{href:"/audit",label:"audit"}];e.s(["Navbar",0,({disabledPages:e=[]})=>{let a=(0,n.usePathname)(),{capture:i}=(0,T.usePostHog)(),s=a.startsWith("/policies")?"policies":a.startsWith("/audit")?"audit":a.startsWith("/settings")?"settings":a.startsWith("/projects")||a.startsWith("/project/")?"projects":"";return(0,t.jsxs)("header",{className:"app-header",children:[(0,t.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,t.jsx)("img",{src:"/logo.svg",alt:"failproof_ai",style:{height:18,display:"block",flexShrink:0}})}),(0,t.jsx)("nav",{className:"tabs",style:{border:"none",padding:0,gap:0},children:R.filter(({href:t})=>{let r=t.slice(1);return!e.includes(r)}).map(({href:e,label:n})=>{let o="/projects"===e?"/projects"===a||a.startsWith("/project/"):a.startsWith(e);return(0,t.jsx)(r.default,{href:e,className:`tab${o?" is-active":""}`,"aria-current":o?"page":void 0,onClick:()=>{"/audit"===e&&i("audit_nav_clicked",{from_path:a,is_active_tab:o})},children:n},e)})}),(0,t.jsx)("div",{style:{flex:1}}),(0,t.jsxs)("div",{className:"h-meta",children:[(0,t.jsxs)("span",{className:"h-version",children:["v","1.0.9-beta.1"]}),s&&(0,t.jsx)("span",{className:"h-brand-sep","aria-hidden":"true",children:"·"}),s&&(0,t.jsx)("span",{className:"h-brand-section",children:s})]}),(0,t.jsxs)("div",{className:"h-actions",children:[(0,t.jsx)(P,{}),(0,t.jsx)("span",{style:{width:1,height:18,background:"var(--line)",margin:"0 6px"}}),!e.includes("settings")&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(r.default,{href:"/settings",className:`h-icon-btn${a.startsWith("/settings")?" is-active":""}`,"aria-label":"settings","aria-current":a.startsWith("/settings")?"page":void 0,title:"settings",children:(0,t.jsx)(o.Settings,{className:"w-3.5 h-3.5",strokeWidth:1.75,"aria-hidden":"true"})}),(0,t.jsx)("span",{style:{width:1,height:18,background:"var(--line)",margin:"0 6px"}})]}),(0,t.jsx)(k,{})]})]})}],63780)},67881,e=>{"use strict";var t=e.i(43476),r=e.i(71645),n=e.i(47163);let o=r.forwardRef(({className:e,variant:r="default",size:o="default",...a},i)=>(0,t.jsx)("button",{className:(0,n.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"===r,"text-foreground hover:bg-muted":"ghost"===r,"border border-border bg-transparent hover:border-primary/60 hover:bg-card":"outline"===r,"h-10 py-2 px-4":"default"===o,"h-10 w-10":"icon"===o,"h-9 px-3":"sm"===o,"h-11 px-8":"lg"===o},e),ref:i,...a}));o.displayName="Button",e.s(["Button",0,o])},85881,e=>{"use strict";var t=e.i(43476),r=e.i(71645);let n=(0,r.createContext)(void 0);e.s(["AutoRefreshProvider",0,function({children:e}){let[o,a]=(0,r.useState)(0);return(0,t.jsx)(n.Provider,{value:{intervalSec:o,setIntervalSec:a},children:e})},"useAutoRefresh",0,function(){let e=(0,r.useContext)(n);if(!e)throw Error("useAutoRefresh must be used within AutoRefreshProvider");return e}])},12344,e=>{"use strict";var t=e.i(43476),r=e.i(71645),n=e.i(18566),o=e.i(70915),a=e.i(9969);let i=(0,r.createContext)(void 0);e.s(["PostHogProvider",0,function({children:e}){let s=(0,n.usePathname)(),l=(0,r.useRef)(null),u=(0,r.useRef)(!1);(0,r.useEffect)(()=>{let e=!1;return(0,o.getTelemetryConfig)().then(t=>{e||((0,a.setClientTelemetryConfig)(t),u.current=!0,(0,a.captureClientEvent)("$pageview"),l.current=window.location.pathname)}),()=>{e=!0}},[]),(0,r.useEffect)(()=>{u.current&&l.current!==s&&(l.current=s,(0,a.captureClientEvent)("$pageview"))},[s]);let c=r.default.useCallback((e,t)=>{(0,a.captureClientEvent)(e,t)},[]);return(0,t.jsx)(i.Provider,{value:{capture:c},children:e})},"usePostHog",0,function(){let e=(0,r.useContext)(i);if(void 0===e)throw Error("usePostHog must be used within a PostHogProvider");return e}])},9969,e=>{"use strict";let t=null;e.s(["captureClientEvent",0,function(e,r){if(!t||!t.enabled)return;let n=JSON.stringify({api_key:t.apiKey,event:e,distinct_id:t.distinctId,properties:{...r,$lib:"failproofai-web",failproofai_version:t.version,product:"failproofai-oss",$current_url:window.location.href,$pathname:window.location.pathname}});fetch(t.host.replace(/\/+$/,"")+"/capture/",{method:"POST",headers:{"Content-Type":"application/json"},body:n,keepalive:!0,signal:AbortSignal.timeout(5e3)}).catch(()=>{})},"setClientTelemetryConfig",0,function(e){t=e}],9969)},5014,e=>{"use strict";var t=e.i(71645);let r=(...e)=>e.filter((e,t,r)=>!!e&&""!==e.trim()&&r.indexOf(e)===t).join(" ").trim(),n={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"},o=(0,t.createContext)({}),a=(0,t.forwardRef)(({color:e,size:a,width:i,height:s,strokeWidth:l,absoluteStrokeWidth:u,nonScalingStroke:c,className:d="",children:f,iconNode:h=[],icon:p={node:h,aliases:[],size:24},...m},g)=>{let{size:b=24,strokeWidth:v=2,absoluteStrokeWidth:y=!1,nonScalingStroke:x=!1,color:w="currentColor",className:j=""}=(0,t.useContext)(o)??{},k=!!f||(e=>{for(let t in e)if(t.startsWith("aria-")||"role"===t||"title"===t)return!0;return!1})(m),[N,S,C=[]]=function(e,t={}){return function(e,t={}){let o=t.attributeNames??{},a=e=>o[e]??e,i=e.size??e.width??n.width,s=e.size??e.height??n.height,l=e.aliases?.filter(e=>"string"==typeof e&&""!==e.trim()).map(e=>`lucide-${e}`)??[],u=[...e.name?[`lucide-${e.name}`]:[],...l],c=t.className?.split(" ").filter(Boolean)??[],d=!1===t.includeDefaultClasses?r(...c):r("lucide",...u,...c),f=t.absoluteStrokeWidth?Number(t.strokeWidth??n["stroke-width"])*Number(e.size??e.width??n.width)/Number(t.size??t.width??n.width):t.strokeWidth??n["stroke-width"];return["svg",{...Object.entries(n).reduce((e,[t,r])=>(e[a(t)]=r,e),{}),..."color"in t&&t.color&&{[a("stroke")]:t.color},..."size"in t&&null!=t.size&&{[a("width")]:t.size,[a("height")]:t.size},..."width"in t&&null!=t.width&&{[a("width")]:t.width},..."height"in t&&null!=t.height&&{[a("height")]:t.height},[a("stroke-width")]:f,...d&&{[a("class")]:d},[a("viewBox")]:`0 0 ${i} ${s}`,...!1===t.hasA11yProp?{[a("aria-hidden")]:"true"}:{},..."attributes"in t&&t.attributes},e.node.map(e=>{let[r,n,o]=e,i=t.nonScalingStroke?{[a("vector-effect")]:"non-scaling-stroke",...n}:n;return o?[r,i,o]:[r,i]})]}(e,{...t,attributeNames:{...t.attributeNames,class:"className","stroke-width":"strokeWidth","stroke-linecap":"strokeLinecap","stroke-linejoin":"strokeLinejoin","vector-effect":"vectorEffect"}})}(p,{color:e??w,width:i??a??b,height:s??a??b,strokeWidth:l??v,absoluteStrokeWidth:u??y,nonScalingStroke:c??x,className:r(j,d),hasA11yProp:k,attributes:m});return(0,t.createElement)(N,{ref:g,...S},[...C.map(([e,r])=>(0,t.createElement)(e,r)),...Array.isArray(f)?f:[f]])});e.s(["default",0,a],5014)},56420,e=>{"use strict";var t=e.i(71645),r=e.i(5014);e.s(["default",0,function(e,n=[],o=[]){let a,i="string"==typeof e?function(e,t,r=[]){if(null==t)throw Error("[lucide]: iconNode is required when icon name is used");return{name:e?.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),size:24,node:t,...r.length>0?{aliases:r}:{}}}(e,n,o):e,s=(0,t.forwardRef)(({className:e,...n},o)=>(0,t.createElement)(r.default,{ref:o,icon:i,className:e,...n}));return i.name&&(s.displayName=(a=(e=>{let t="",r=!1;for(let n of e){if("-"===n||"_"===n||n<=" "){r=t.length>0;continue}0===t.length?t+=n.toLowerCase():t+=r?n.toUpperCase():n,r=!1}return t})(i.name)).charAt(0).toUpperCase()+a.slice(1)),s}],56420)},16327,e=>{"use strict";var t=e.i(56420);let r={name:"chevron-down",size:24,node:[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]};r.node;let n=(0,t.default)(r);e.s(["ChevronDown",0,n],16327)},66794,e=>{"use strict";var t=e.i(56420);let r={name:"settings",size:24,node:[["path",{d:"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915",key:"1i5ecw"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]};r.node;let n=(0,t.default)(r);e.s(["Settings",0,n],66794)},95187,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={callServer:function(){return a.callServer},createServerReference:function(){return s.createServerReference},findSourceMapURL:function(){return i.findSourceMapURL}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let a=e.r(32120),i=e.r(92245),s=e.r(35326)},22016,(e,t,r)=>{"use strict";e.i(47167),Object.defineProperty(r,"__esModule",{value:!0});var n={default:function(){return b},useLinkStatus:function(){return y}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let a=e.r(90809),i=e.r(43476),s=a._(e.r(71645)),l=e.r(95057),u=e.r(8372),c=e.r(18581),d=e.r(18967),f=e.r(5550),h=e.r(88540),p=e.r(91949),m=e.r(73668),g=e.r(9396);function b(t){var r;let n,o,a,[b,y]=(0,s.useOptimistic)(p.IDLE_LINK_STATUS),x=(0,s.useRef)(null),{href:w,as:j,children:k,prefetch:N=null,passHref:S,replace:C,shallow:E,scroll:_,onClick:P,onMouseEnter:T,onTouchStart:R,legacyBehavior:O=!1,onNavigate:A,transitionTypes:M,ref:L,unstable_dynamicOnHover:z,...$}=t;n=k,O&&("string"==typeof n||"number"==typeof n)&&(n=(0,i.jsx)("a",{children:n}));let U=s.default.useContext(u.AppRouterContext),I=!1!==N,W=!1===N?"none":!0===N?"full":"auto",B="none"!==W?"auto"===W?g.FetchStrategy.PPR:g.FetchStrategy.Full:g.FetchStrategy.PPR,D="string"==typeof(r=j||w)?r:(0,l.formatUrl)(r);if(O){if(n?.$$typeof===Symbol.for("react.lazy"))throw Object.defineProperty(Error("`<Link legacyBehavior>` received a direct child that is either a Server Component, or JSX that was loaded with React.lazy(). This is not supported. Either remove legacyBehavior, or make the direct child a Client Component that renders the Link's `<a>` tag."),"__NEXT_ERROR_CODE",{value:"E863",enumerable:!1,configurable:!0});o=s.default.Children.only(n)}let F=O?o&&"object"==typeof o&&o.ref:L,H,q=s.default.useCallback(e=>(null!==U&&(x.current=(0,p.mountLinkInstance)(e,D,U,B,I,y,H)),()=>{x.current&&((0,p.unmountLinkForCurrentNavigation)(x.current),x.current=null),(0,p.unmountPrefetchableInstance)(e)}),[I,D,U,B,y,H]),K={ref:(0,c.useMergedRef)(q,F),onClick(t){O||"function"!=typeof P||P(t),O&&o.props&&"function"==typeof o.props.onClick&&o.props.onClick(t),!U||t.defaultPrevented||function(t,r,n,o,a,i,l,u="none"){if("u">typeof window){let c,{nodeName:d}=t.currentTarget;if("A"===d.toUpperCase()&&((c=t.currentTarget.getAttribute("target"))&&"_self"!==c||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||t.nativeEvent&&2===t.nativeEvent.which)||t.currentTarget.hasAttribute("download"))return;if(!(0,m.isLocalURL)(r)){o&&(t.preventDefault(),location.replace(r));return}if(t.preventDefault(),i){let e=!1;if(i({preventDefault:()=>{e=!0}}),e)return}let{dispatchNavigateAction:f}=e.r(99781);s.default.startTransition(()=>{f(r,o?"replace":"push",!1===a?h.ScrollBehavior.NoScroll:h.ScrollBehavior.Default,n.current,l,u)})}}(t,D,x,C,_,A,M,W)},onMouseEnter(e){O||"function"!=typeof T||T(e),O&&o.props&&"function"==typeof o.props.onMouseEnter&&o.props.onMouseEnter(e),U&&I&&(0,p.onNavigationIntent)(e.currentTarget,!0===z)},onTouchStart:function(e){O||"function"!=typeof R||R(e),O&&o.props&&"function"==typeof o.props.onTouchStart&&o.props.onTouchStart(e),U&&I&&(0,p.onNavigationIntent)(e.currentTarget,!0===z)}};return(0,d.isAbsoluteUrl)(D)?K.href=D:O&&!S&&("a"!==o.type||"href"in o.props)||(K.href=(0,f.addBasePath)(D)),a=O?s.default.cloneElement(o,K):(0,i.jsx)("a",{...$,...K,children:n}),(0,i.jsx)(v.Provider,{value:b,children:a})}let v=(0,s.createContext)(p.IDLE_LINK_STATUS),y=()=>(0,s.useContext)(v);("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},18581,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"useMergedRef",{enumerable:!0,get:function(){return o}});let n=e.r(71645);function o(e,t){let r=(0,n.useRef)(null),o=(0,n.useRef)(null);return(0,n.useCallback)(n=>{if(null===n){let e=r.current;e&&(r.current=null,e());let t=o.current;t&&(o.current=null,t())}else e&&(r.current=a(e,n)),t&&(o.current=a(t,n))},[e,t])}function a(e,t){if("function"!=typeof e)return e.current=t,()=>{e.current=null};{let r=e(t);return"function"==typeof r?r:()=>e(null)}}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},18967,(e,t,r)=>{"use strict";e.i(47167),Object.defineProperty(r,"__esModule",{value:!0});var n={DecodeError:function(){return b},MiddlewareNotFoundError:function(){return w},MissingStaticPage:function(){return x},NormalizeError:function(){return v},PageNotFoundError:function(){return y},SP:function(){return m},ST:function(){return g},WEB_VITALS:function(){return a},execOnce:function(){return i},getDisplayName:function(){return d},getLocationOrigin:function(){return u},getURL:function(){return c},isAbsoluteUrl:function(){return l},isResSent:function(){return f},loadGetInitialProps:function(){return p},normalizeRepeatedSlashes:function(){return h},stringifyError:function(){return j}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let a=["CLS","FCP","FID","INP","LCP","TTFB"];function i(e){let t,r=!1;return(...n)=>(r||(r=!0,t=e(...n)),t)}let s=/^[a-zA-Z][a-zA-Z\d+\-.]*?:/,l=e=>{let t=e.charCodeAt(0);return!!(t>=65&&t<=90||t>=97&&t<=122)&&s.test(e)};function u(){let{protocol:e,hostname:t,port:r}=window.location;return`${e}//${t}${r?":"+r:""}`}function c(){let{href:e}=window.location,t=u();return e.substring(t.length)}function d(e){return"string"==typeof e?e:e.displayName||e.name||"Unknown"}function f(e){return e.finished||e.headersSent}function h(e){let t=e.split("?");return t[0].replace(/\\/g,"/").replace(/\/\/+/g,"/")+(t[1]?`?${t.slice(1).join("?")}`:"")}async function p(e,t){let r=t.res||t.ctx&&t.ctx.res;if(!e.getInitialProps)return t.ctx&&t.Component?{pageProps:await p(t.Component,t.ctx)}:{};let n=await e.getInitialProps(t);if(r&&f(r))return n;if(!n)throw Object.defineProperty(Error(`"${d(e)}.getInitialProps()" should resolve to an object. But found "${n}" instead.`),"__NEXT_ERROR_CODE",{value:"E1025",enumerable:!1,configurable:!0});return n}let m="u">typeof performance,g=m&&["mark","measure","getEntriesByName"].every(e=>"function"==typeof performance[e]);class b extends Error{}class v extends Error{}class y extends Error{constructor(e){super(),this.code="ENOENT",this.name="PageNotFoundError",this.message=`Cannot find module for page: ${e}`}}class x extends Error{constructor(e,t){super(),this.message=`Failed to load static file for page: ${e} ${t}`}}class w extends Error{constructor(){super(),this.code="ENOENT",this.message="Cannot find the middleware module"}}function j(e){return JSON.stringify({message:e.message,stack:e.stack})}},73668,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"isLocalURL",{enumerable:!0,get:function(){return a}});let n=e.r(18967),o=e.r(52817);function a(e){if(!(0,n.isAbsoluteUrl)(e))return!0;try{let t=(0,n.getLocationOrigin)(),r=new URL(e,t);return r.origin===t&&(0,o.hasBasePath)(r.pathname)}catch(e){return!1}}},98183,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={assign:function(){return l},searchParamsToUrlQuery:function(){return a},urlQueryToSearchParams:function(){return s}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});function a(e){let t={};for(let[r,n]of e.entries()){let e=t[r];void 0===e?t[r]=n:Array.isArray(e)?e.push(n):t[r]=[e,n]}return t}function i(e){return"string"==typeof e?e:("number"!=typeof e||isNaN(e))&&"boolean"!=typeof e?"":String(e)}function s(e){let t=new URLSearchParams;for(let[r,n]of Object.entries(e))if(Array.isArray(n))for(let e of n)t.append(r,i(e));else t.set(r,i(n));return t}function l(e,...t){for(let r of t){for(let t of r.keys())e.delete(t);for(let[t,n]of r.entries())e.append(t,n)}return e}},95057,(e,t,r)=>{"use strict";e.i(47167),Object.defineProperty(r,"__esModule",{value:!0});var n={formatUrl:function(){return s},formatWithValidation:function(){return u},urlObjectKeys:function(){return l}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let a=e.r(90809)._(e.r(98183)),i=/https?|ftp|gopher|file/;function s(e){let{auth:t,hostname:r}=e,n=e.protocol||"",o=e.pathname||"",s=e.hash||"",l=e.query||"",u=!1;t=t?encodeURIComponent(t).replace(/%3A/i,":")+"@":"",e.host?u=t+e.host:r&&(u=t+(~r.indexOf(":")?`[${r}]`:r),e.port&&(u+=":"+e.port)),l&&"object"==typeof l&&(l=String(a.urlQueryToSearchParams(l)));let c=e.search||l&&`?${l}`||"";return n&&!n.endsWith(":")&&(n+=":"),e.slashes||(!n||i.test(n))&&!1!==u?(u="//"+(u||""),o&&"/"!==o[0]&&(o="/"+o)):u||(u=""),s&&"#"!==s[0]&&(s="#"+s),c&&"?"!==c[0]&&(c="?"+c),o=o.replace(/[?#]/g,encodeURIComponent),c=c.replace("#","%23"),`${n}${u}${o}${c}${s}`}let l=["auth","hash","host","hostname","href","path","pathname","port","protocol","query","search","slashes"];function u(e){return s(e)}},18566,(e,t,r)=>{t.exports=e.r(76562)}]);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|