failproofai 1.0.0-beta.11 → 1.0.0-beta.13
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 +3 -3
- 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 +2 -3
- 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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +2 -3
- 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 +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 +2 -2
- 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 +3 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -3
- 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/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +2 -3
- 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 +10 -10
- package/.next/standalone/.next/server/app/policies/page.js +2 -3
- 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 +3 -4
- 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 +3 -4
- 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 +3 -4
- 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 +4 -4
- package/.next/standalone/.next/server/app/settings/page.js +2 -3
- 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]__1a7i2q4._.js → [root-of-the-server]__00ni9za._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08y94xv._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ed01_d._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1_ps0jw._.js → [root-of-the-server]__0effm9m._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0lk_935._.js → [root-of-the-server]__0ix8gm7._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0ky_n0r._.js → [root-of-the-server]__0ji11a-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0v2fpxe._.js → [root-of-the-server]__0ojwjxl._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vb5fl2._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ibjy5x._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1uyc-z4._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__20d06rh._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +1 -3
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +1 -3
- 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]__1rdruw4._.js → [root-of-the-server]__0_1tiya._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__20ie7me._.js → [root-of-the-server]__0eeipso._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0spkm68._.js +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1tyf0tc._.js → [root-of-the-server]__17itmx-._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1gwr8l-._.js → [root-of-the-server]__1dx-a-c._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mmefsr._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1yw368c._.js → [root-of-the-server]__1n2vcv4._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1a2hcb_._.js → [root-of-the-server]__1tlvv9a._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1fahg9e._.js → _0vo2qyt._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0uz7o9y._.js → _0xej-0e._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_04mekdy._.js → _10399ge._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0se484m._.js → _149k9oy._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0n4bc3i._.js → _166jvu8._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0r-dsre._.js → _1_hwp06._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1w8sola._.js → _1mnhi_r._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1w_6p9g._.js → _1ror7k9._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1gmzkwj._.js → _1sdgprl._.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/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 +15 -15
- package/.next/standalone/.next/static/chunks/{0-m1vctj2jny6.js → 01s3vpzky_qew.js} +1 -1
- package/.next/standalone/.next/static/chunks/0km-jn9o5xyqs.css +2 -0
- package/.next/standalone/.next/static/chunks/{0on899o88y54u.js → 0zbcd_n8ku2ov.js} +1 -1
- package/.next/standalone/.next/static/chunks/{04y6igmx5olt6.js → 1erji0ratofla.js} +1 -1
- package/.next/standalone/.next/static/chunks/{06abmgw7cvecc.js → 23hnlzqx44vbe.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1a9qlmo5s678i.js → 2cwsiyhc7d2cw.js} +1 -1
- package/.next/standalone/.next/static/chunks/{37nu_nos28w1x.js → 2y42ebzynyxdv.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0ug1y_6-uwu5t.js → 315lncj7dsp9c.js} +1 -1
- package/.next/standalone/.next/static/chunks/31_px0dfgdg9j.js +6 -0
- package/.next/standalone/.next/static/chunks/{43ylh_2r15k-w.js → 3l4-fu3xt75j8.js} +1 -1
- package/.next/standalone/.next/static/chunks/3poscoxn69x9g.js +1 -0
- package/.next/standalone/app/policies/hooks-client.tsx +4 -4
- package/.next/standalone/ino.ujh3/.failproofai/VERSION +4 -0
- package/.next/standalone/ino.ujh3/.failproofai/state/last-version +1 -0
- package/.next/standalone/ino.ujh3/.failproofai/state/telemetry-id +1 -0
- package/.next/standalone/package.json +10 -10
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai-worker.mjs +1 -1
- package/bin/failproofai.mjs +186 -5
- package/dist/cli.mjs +1130 -1352
- package/dist/worker.mjs +171 -1010
- package/package.json +10 -10
- package/src/hooks/backfill-cli.ts +1 -1
- package/src/hooks/cloud-connection.ts +4 -4
- package/src/hooks/cloud-enrollment-cli.ts +1 -1
- package/src/hooks/cloud-enrollment.ts +3 -3
- package/src/hooks/cloud-managed-policies.ts +60 -22
- package/src/hooks/configure-wizard.ts +124 -53
- package/src/hooks/custom-hooks-loader.ts +57 -8
- package/src/hooks/daemon-service.ts +66 -11
- package/src/hooks/flush-cli.ts +180 -0
- package/src/hooks/fp-config.ts +242 -118
- package/src/hooks/fp-home.ts +138 -22
- package/src/hooks/fp-reset.ts +357 -43
- package/src/hooks/handler.ts +11 -11
- package/src/hooks/harness-cli.ts +309 -0
- package/src/hooks/hook-activity-store.ts +5 -5
- package/src/hooks/manager.ts +35 -0
- package/src/hooks/onboarding-attempt.ts +22 -6
- package/src/hooks/tui.ts +64 -7
- package/src/hooks/uninstall-cli.ts +1 -1
- package/src/hooks/worker-server.ts +69 -12
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1iny24d._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tyedjt._.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +0 -5
- package/.next/standalone/.next/static/chunks/0p_y4ndalc68e.js +0 -6
- package/.next/standalone/.next/static/chunks/13vrxdsdihqd_.css +0 -2
- package/.next/standalone/.next/static/chunks/19lrnqxn7ni7i.js +0 -1
- /package/.next/standalone/.next/static/{BZDo0aAHzDwh5ntxgIgpc → ziAsXfNE0cH_S7LHK-Py3}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{BZDo0aAHzDwh5ntxgIgpc → ziAsXfNE0cH_S7LHK-Py3}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{BZDo0aAHzDwh5ntxgIgpc → ziAsXfNE0cH_S7LHK-Py3}/_ssgManifest.js +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -19,7 +19,7 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
19
19
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
20
20
|
|
|
21
21
|
// package.json
|
|
22
|
-
var version2 = "1.0.0-beta.
|
|
22
|
+
var version2 = "1.0.0-beta.13", package_default;
|
|
23
23
|
var init_package = __esm(() => {
|
|
24
24
|
package_default = {
|
|
25
25
|
name: "failproofai",
|
|
@@ -124,12 +124,12 @@ var init_package = __esm(() => {
|
|
|
124
124
|
"html-to-image": "^1.11.13",
|
|
125
125
|
html2canvas: "^1.4.1",
|
|
126
126
|
"posthog-node": "^5.47.7",
|
|
127
|
-
"smol-toml": "^1.7.1",
|
|
128
127
|
"sql.js": "^1.14.1",
|
|
129
128
|
yaml: "^2.9.0"
|
|
130
129
|
},
|
|
131
130
|
overrides: {
|
|
132
131
|
postcss: "8.5.23",
|
|
132
|
+
nanoid: "3.3.17",
|
|
133
133
|
"eslint-plugin-react-hooks": "7.0.1",
|
|
134
134
|
vite: "8.0.16",
|
|
135
135
|
undici: "7.29.0",
|
|
@@ -137,16 +137,16 @@ var init_package = __esm(() => {
|
|
|
137
137
|
sharp: "0.35.0"
|
|
138
138
|
},
|
|
139
139
|
optionalDependencies: {
|
|
140
|
-
"@failproofai/failproofaid-linux-x64": "1.0.0-beta.
|
|
141
|
-
"@failproofai/failproofaid-linux-arm64": "1.0.0-beta.
|
|
142
|
-
"@failproofai/failproofaid-darwin-x64": "1.0.0-beta.
|
|
143
|
-
"@failproofai/failproofaid-darwin-arm64": "1.0.0-beta.
|
|
140
|
+
"@failproofai/failproofaid-linux-x64": "1.0.0-beta.13",
|
|
141
|
+
"@failproofai/failproofaid-linux-arm64": "1.0.0-beta.13",
|
|
142
|
+
"@failproofai/failproofaid-darwin-x64": "1.0.0-beta.13",
|
|
143
|
+
"@failproofai/failproofaid-darwin-arm64": "1.0.0-beta.13"
|
|
144
144
|
},
|
|
145
145
|
failproofaidBinaries: {
|
|
146
|
-
"linux-x64": "
|
|
147
|
-
"linux-arm64": "
|
|
148
|
-
"darwin-x64": "
|
|
149
|
-
"darwin-arm64": "
|
|
146
|
+
"linux-x64": "b96dd035433adbf1290ad8b4ed32fc8134d4dfc03057b8f6a210c041ac7d8d93",
|
|
147
|
+
"linux-arm64": "0e11c7349de7d10488a6ea8f80714260e3dbedabcd06b0ab530119970b16404d",
|
|
148
|
+
"darwin-x64": "7d2943d6126430d9282ca106918be8aa2e0133c4c7189493996b14cbbb361d06",
|
|
149
|
+
"darwin-arm64": "dd6c646611ee81d7db88254917232bd5b0cfac514657bd2ce1062c7bb24cf960"
|
|
150
150
|
}
|
|
151
151
|
};
|
|
152
152
|
});
|
|
@@ -154,971 +154,6 @@ var init_package = __esm(() => {
|
|
|
154
154
|
// src/posthog-key.ts
|
|
155
155
|
var POSTHOG_API_KEY = "phc_Ac1Ww1GqKc0z1SyrRWbmatEeQdlOQIsDEEdP8l8JRgX", POSTHOG_PRODUCT = "failproofai-oss";
|
|
156
156
|
|
|
157
|
-
// node_modules/smol-toml/dist/date.js
|
|
158
|
-
var DATE_TIME_RE, TomlDate;
|
|
159
|
-
var init_date = __esm(() => {
|
|
160
|
-
/*!
|
|
161
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
162
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
163
|
-
*
|
|
164
|
-
* Redistribution and use in source and binary forms, with or without
|
|
165
|
-
* modification, are permitted provided that the following conditions are met:
|
|
166
|
-
*
|
|
167
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
168
|
-
* list of conditions and the following disclaimer.
|
|
169
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
170
|
-
* this list of conditions and the following disclaimer in the
|
|
171
|
-
* documentation and/or other materials provided with the distribution.
|
|
172
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
173
|
-
* may be used to endorse or promote products derived from this software without
|
|
174
|
-
* specific prior written permission.
|
|
175
|
-
*
|
|
176
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
177
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
178
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
179
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
180
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
181
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
182
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
183
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
184
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
185
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
186
|
-
*/
|
|
187
|
-
DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
188
|
-
TomlDate = class TomlDate extends Date {
|
|
189
|
-
#hasDate = false;
|
|
190
|
-
#hasTime = false;
|
|
191
|
-
#offset = null;
|
|
192
|
-
constructor(date) {
|
|
193
|
-
let hasDate = true;
|
|
194
|
-
let hasTime = true;
|
|
195
|
-
let offset = "Z";
|
|
196
|
-
if (typeof date === "string") {
|
|
197
|
-
let match = date.match(DATE_TIME_RE);
|
|
198
|
-
if (match) {
|
|
199
|
-
if (!match[1]) {
|
|
200
|
-
hasDate = false;
|
|
201
|
-
date = `0000-01-01T${date}`;
|
|
202
|
-
}
|
|
203
|
-
hasTime = !!match[2];
|
|
204
|
-
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
205
|
-
if (match[2] && +match[2] > 23) {
|
|
206
|
-
date = "";
|
|
207
|
-
} else {
|
|
208
|
-
offset = match[3] || null;
|
|
209
|
-
date = date.toUpperCase();
|
|
210
|
-
if (!offset && hasTime)
|
|
211
|
-
date += "Z";
|
|
212
|
-
}
|
|
213
|
-
} else {
|
|
214
|
-
date = "";
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
super(date);
|
|
218
|
-
if (!isNaN(this.getTime())) {
|
|
219
|
-
this.#hasDate = hasDate;
|
|
220
|
-
this.#hasTime = hasTime;
|
|
221
|
-
this.#offset = offset;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
isDateTime() {
|
|
225
|
-
return this.#hasDate && this.#hasTime;
|
|
226
|
-
}
|
|
227
|
-
isLocal() {
|
|
228
|
-
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
229
|
-
}
|
|
230
|
-
isDate() {
|
|
231
|
-
return this.#hasDate && !this.#hasTime;
|
|
232
|
-
}
|
|
233
|
-
isTime() {
|
|
234
|
-
return this.#hasTime && !this.#hasDate;
|
|
235
|
-
}
|
|
236
|
-
isValid() {
|
|
237
|
-
return this.#hasDate || this.#hasTime;
|
|
238
|
-
}
|
|
239
|
-
toISOString() {
|
|
240
|
-
let iso = super.toISOString();
|
|
241
|
-
if (this.isDate())
|
|
242
|
-
return iso.slice(0, 10);
|
|
243
|
-
if (this.isTime())
|
|
244
|
-
return iso.slice(11, 23);
|
|
245
|
-
if (this.#offset === null)
|
|
246
|
-
return iso.slice(0, -1);
|
|
247
|
-
if (this.#offset === "Z")
|
|
248
|
-
return iso;
|
|
249
|
-
let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
|
|
250
|
-
offset = this.#offset[0] === "-" ? offset : -offset;
|
|
251
|
-
let offsetDate = new Date(this.getTime() - offset * 60000);
|
|
252
|
-
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
253
|
-
}
|
|
254
|
-
static wrapAsOffsetDateTime(jsDate, offset = "Z") {
|
|
255
|
-
let date = new TomlDate(jsDate);
|
|
256
|
-
date.#offset = offset;
|
|
257
|
-
return date;
|
|
258
|
-
}
|
|
259
|
-
static wrapAsLocalDateTime(jsDate) {
|
|
260
|
-
let date = new TomlDate(jsDate);
|
|
261
|
-
date.#offset = null;
|
|
262
|
-
return date;
|
|
263
|
-
}
|
|
264
|
-
static wrapAsLocalDate(jsDate) {
|
|
265
|
-
let date = new TomlDate(jsDate);
|
|
266
|
-
date.#hasTime = false;
|
|
267
|
-
date.#offset = null;
|
|
268
|
-
return date;
|
|
269
|
-
}
|
|
270
|
-
static wrapAsLocalTime(jsDate) {
|
|
271
|
-
let date = new TomlDate(jsDate);
|
|
272
|
-
date.#hasDate = false;
|
|
273
|
-
date.#offset = null;
|
|
274
|
-
return date;
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// node_modules/smol-toml/dist/error.js
|
|
280
|
-
function getLineColFromPtr(string, ptr) {
|
|
281
|
-
let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
|
|
282
|
-
return [lines.length, lines.pop().length + 1];
|
|
283
|
-
}
|
|
284
|
-
function makeCodeBlock(string, line, column) {
|
|
285
|
-
let lines = string.split(/\r\n|\n|\r/g);
|
|
286
|
-
let codeblock = "";
|
|
287
|
-
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
288
|
-
for (let i = line - 1;i <= line + 1; i++) {
|
|
289
|
-
let l = lines[i - 1];
|
|
290
|
-
if (!l)
|
|
291
|
-
continue;
|
|
292
|
-
codeblock += i.toString().padEnd(numberLen, " ");
|
|
293
|
-
codeblock += ": ";
|
|
294
|
-
codeblock += l;
|
|
295
|
-
codeblock += `
|
|
296
|
-
`;
|
|
297
|
-
if (i === line) {
|
|
298
|
-
codeblock += " ".repeat(numberLen + column + 2);
|
|
299
|
-
codeblock += `^
|
|
300
|
-
`;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return codeblock;
|
|
304
|
-
}
|
|
305
|
-
var TomlError;
|
|
306
|
-
var init_error = __esm(() => {
|
|
307
|
-
/*!
|
|
308
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
309
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
310
|
-
*
|
|
311
|
-
* Redistribution and use in source and binary forms, with or without
|
|
312
|
-
* modification, are permitted provided that the following conditions are met:
|
|
313
|
-
*
|
|
314
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
315
|
-
* list of conditions and the following disclaimer.
|
|
316
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
317
|
-
* this list of conditions and the following disclaimer in the
|
|
318
|
-
* documentation and/or other materials provided with the distribution.
|
|
319
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
320
|
-
* may be used to endorse or promote products derived from this software without
|
|
321
|
-
* specific prior written permission.
|
|
322
|
-
*
|
|
323
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
324
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
325
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
326
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
327
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
328
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
329
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
330
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
331
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
332
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
333
|
-
*/
|
|
334
|
-
TomlError = class TomlError extends Error {
|
|
335
|
-
line;
|
|
336
|
-
column;
|
|
337
|
-
codeblock;
|
|
338
|
-
constructor(message, options) {
|
|
339
|
-
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
|
340
|
-
const codeblock = makeCodeBlock(options.toml, line, column);
|
|
341
|
-
super(`Invalid TOML document: ${message}
|
|
342
|
-
|
|
343
|
-
${codeblock}`, options);
|
|
344
|
-
this.line = line;
|
|
345
|
-
this.column = column;
|
|
346
|
-
this.codeblock = codeblock;
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
// node_modules/smol-toml/dist/primitive.js
|
|
352
|
-
function parseString(str, ptr) {
|
|
353
|
-
let c = str[ptr++];
|
|
354
|
-
let first = c;
|
|
355
|
-
let isLiteral = c === "'";
|
|
356
|
-
let isMultiline = c === str[ptr] && c === str[ptr + 1];
|
|
357
|
-
if (isMultiline) {
|
|
358
|
-
if (str[ptr += 2] === `
|
|
359
|
-
`)
|
|
360
|
-
ptr++;
|
|
361
|
-
else if (str[ptr] === "\r" && str[ptr + 1] === `
|
|
362
|
-
`)
|
|
363
|
-
ptr += 2;
|
|
364
|
-
}
|
|
365
|
-
let parsed = "";
|
|
366
|
-
let sliceStart = ptr;
|
|
367
|
-
let state = 0;
|
|
368
|
-
for (let i = ptr;i < str.length; i++) {
|
|
369
|
-
c = str[i];
|
|
370
|
-
if (isMultiline && (c === `
|
|
371
|
-
` || c === "\r" && str[i + 1] === `
|
|
372
|
-
`)) {
|
|
373
|
-
state = state && 3;
|
|
374
|
-
} else if (c < " " && c !== "\t" || c === "") {
|
|
375
|
-
throw new TomlError("control characters are not allowed in strings", {
|
|
376
|
-
toml: str,
|
|
377
|
-
ptr: i
|
|
378
|
-
});
|
|
379
|
-
} else if ((!state || state === 3) && c === first && (!isMultiline || str[i + 1] === first && str[i + 2] === first)) {
|
|
380
|
-
if (isMultiline) {
|
|
381
|
-
if (str[i + 3] === first)
|
|
382
|
-
i++;
|
|
383
|
-
if (str[i + 3] === first)
|
|
384
|
-
i++;
|
|
385
|
-
}
|
|
386
|
-
return [
|
|
387
|
-
state ? parsed : parsed + str.slice(sliceStart, i),
|
|
388
|
-
i + (isMultiline ? 3 : 1)
|
|
389
|
-
];
|
|
390
|
-
} else if (!state) {
|
|
391
|
-
if (!isLiteral && c === "\\") {
|
|
392
|
-
parsed += str.slice(sliceStart, sliceStart = i);
|
|
393
|
-
state = 1;
|
|
394
|
-
}
|
|
395
|
-
} else if (state === 1) {
|
|
396
|
-
if (c === "x" || c === "u" || c === "U") {
|
|
397
|
-
let value = 0;
|
|
398
|
-
let len = c === "x" ? 2 : c === "u" ? 4 : 8;
|
|
399
|
-
for (let j = 0;j < len; j++, i++) {
|
|
400
|
-
let hex = str.charCodeAt(i + 1);
|
|
401
|
-
let digit = hex >= 48 && hex <= 57 ? hex - 48 : hex >= 65 && hex <= 70 ? hex - 65 + 10 : hex >= 97 && hex <= 102 ? hex - 97 + 10 : -1;
|
|
402
|
-
if (digit < 0)
|
|
403
|
-
throw new TomlError("invalid non-hex character in unicode escape", { toml: str, ptr: i + 1 });
|
|
404
|
-
value = value << 4 | digit;
|
|
405
|
-
}
|
|
406
|
-
if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) {
|
|
407
|
-
throw new TomlError("invalid unicode escape", { toml: str, ptr: i });
|
|
408
|
-
}
|
|
409
|
-
parsed += String.fromCodePoint(value);
|
|
410
|
-
sliceStart = i + 1;
|
|
411
|
-
state = 0;
|
|
412
|
-
} else if (c === " " || c === "\t") {
|
|
413
|
-
state = 2;
|
|
414
|
-
} else {
|
|
415
|
-
if (c === "b")
|
|
416
|
-
parsed += "\b";
|
|
417
|
-
else if (c === "t")
|
|
418
|
-
parsed += "\t";
|
|
419
|
-
else if (c === "n")
|
|
420
|
-
parsed += `
|
|
421
|
-
`;
|
|
422
|
-
else if (c === "f")
|
|
423
|
-
parsed += "\f";
|
|
424
|
-
else if (c === "r")
|
|
425
|
-
parsed += "\r";
|
|
426
|
-
else if (c === "e")
|
|
427
|
-
parsed += "\x1B";
|
|
428
|
-
else if (c === '"')
|
|
429
|
-
parsed += '"';
|
|
430
|
-
else if (c === "\\")
|
|
431
|
-
parsed += "\\";
|
|
432
|
-
else
|
|
433
|
-
throw new TomlError("unrecognized escape sequence", { toml: str, ptr: i });
|
|
434
|
-
sliceStart = i + 1;
|
|
435
|
-
state = 0;
|
|
436
|
-
}
|
|
437
|
-
} else if (c !== " " && c !== "\t") {
|
|
438
|
-
if (state === 2) {
|
|
439
|
-
throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
|
|
440
|
-
toml: str,
|
|
441
|
-
ptr: sliceStart
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
state = !isLiteral && c === "\\" ? 1 : 0;
|
|
445
|
-
sliceStart = i;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
throw new TomlError("unfinished string", { toml: str, ptr });
|
|
449
|
-
}
|
|
450
|
-
function parseValue(value, toml, ptr, integersAsBigInt) {
|
|
451
|
-
if (value === "true")
|
|
452
|
-
return true;
|
|
453
|
-
if (value === "false")
|
|
454
|
-
return false;
|
|
455
|
-
if (value === "-inf")
|
|
456
|
-
return -Infinity;
|
|
457
|
-
if (value === "inf" || value === "+inf")
|
|
458
|
-
return Infinity;
|
|
459
|
-
if (value === "nan" || value === "+nan" || value === "-nan")
|
|
460
|
-
return NaN;
|
|
461
|
-
if (value === "-0")
|
|
462
|
-
return integersAsBigInt ? 0n : 0;
|
|
463
|
-
let isInt = INT_REGEX.test(value);
|
|
464
|
-
if (isInt || FLOAT_REGEX.test(value)) {
|
|
465
|
-
if (LEADING_ZERO.test(value)) {
|
|
466
|
-
throw new TomlError("leading zeroes are not allowed", {
|
|
467
|
-
toml,
|
|
468
|
-
ptr
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
value = value.replace(/_/g, "");
|
|
472
|
-
let numeric = +value;
|
|
473
|
-
if (isNaN(numeric)) {
|
|
474
|
-
throw new TomlError("invalid number", {
|
|
475
|
-
toml,
|
|
476
|
-
ptr
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
if (isInt) {
|
|
480
|
-
if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
|
|
481
|
-
throw new TomlError("integer value cannot be represented losslessly", {
|
|
482
|
-
toml,
|
|
483
|
-
ptr
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
if (isInt || integersAsBigInt === true)
|
|
487
|
-
numeric = BigInt(value);
|
|
488
|
-
}
|
|
489
|
-
return numeric;
|
|
490
|
-
}
|
|
491
|
-
const date = new TomlDate(value);
|
|
492
|
-
if (!date.isValid()) {
|
|
493
|
-
throw new TomlError("invalid value", {
|
|
494
|
-
toml,
|
|
495
|
-
ptr
|
|
496
|
-
});
|
|
497
|
-
}
|
|
498
|
-
return date;
|
|
499
|
-
}
|
|
500
|
-
var INT_REGEX, FLOAT_REGEX, LEADING_ZERO;
|
|
501
|
-
var init_primitive = __esm(() => {
|
|
502
|
-
init_date();
|
|
503
|
-
init_error();
|
|
504
|
-
/*!
|
|
505
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
506
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
507
|
-
*
|
|
508
|
-
* Redistribution and use in source and binary forms, with or without
|
|
509
|
-
* modification, are permitted provided that the following conditions are met:
|
|
510
|
-
*
|
|
511
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
512
|
-
* list of conditions and the following disclaimer.
|
|
513
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
514
|
-
* this list of conditions and the following disclaimer in the
|
|
515
|
-
* documentation and/or other materials provided with the distribution.
|
|
516
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
517
|
-
* may be used to endorse or promote products derived from this software without
|
|
518
|
-
* specific prior written permission.
|
|
519
|
-
*
|
|
520
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
521
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
522
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
523
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
524
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
525
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
526
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
527
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
528
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
529
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
530
|
-
*/
|
|
531
|
-
INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
|
|
532
|
-
FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
|
|
533
|
-
LEADING_ZERO = /^[+-]?0[0-9_]/;
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
// node_modules/smol-toml/dist/util.js
|
|
537
|
-
function indexOfNewline(str, start = 0, end = str.length) {
|
|
538
|
-
let idx = str.indexOf(`
|
|
539
|
-
`, start);
|
|
540
|
-
if (str[idx - 1] === "\r")
|
|
541
|
-
idx--;
|
|
542
|
-
return idx <= end ? idx : -1;
|
|
543
|
-
}
|
|
544
|
-
function skipComment(str, ptr) {
|
|
545
|
-
for (let i = ptr;i < str.length; i++) {
|
|
546
|
-
let c = str[i];
|
|
547
|
-
if (c === `
|
|
548
|
-
`)
|
|
549
|
-
return i;
|
|
550
|
-
if (c === "\r" && str[i + 1] === `
|
|
551
|
-
`)
|
|
552
|
-
return i + 1;
|
|
553
|
-
if (c < " " && c !== "\t" || c === "") {
|
|
554
|
-
throw new TomlError("control characters are not allowed in comments", {
|
|
555
|
-
toml: str,
|
|
556
|
-
ptr
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
return str.length;
|
|
561
|
-
}
|
|
562
|
-
function skipVoid(str, ptr, banNewLines, banComments) {
|
|
563
|
-
let c;
|
|
564
|
-
while (true) {
|
|
565
|
-
while ((c = str[ptr]) === " " || c === "\t" || !banNewLines && (c === `
|
|
566
|
-
` || c === "\r" && str[ptr + 1] === `
|
|
567
|
-
`))
|
|
568
|
-
ptr++;
|
|
569
|
-
if (banComments || c !== "#")
|
|
570
|
-
break;
|
|
571
|
-
ptr = skipComment(str, ptr);
|
|
572
|
-
}
|
|
573
|
-
return ptr;
|
|
574
|
-
}
|
|
575
|
-
function skipUntil(str, ptr, sep, end, banNewLines = false) {
|
|
576
|
-
if (!end) {
|
|
577
|
-
ptr = indexOfNewline(str, ptr);
|
|
578
|
-
return ptr < 0 ? str.length : ptr;
|
|
579
|
-
}
|
|
580
|
-
for (let i = ptr;i < str.length; i++) {
|
|
581
|
-
let c = str[i];
|
|
582
|
-
if (c === "#") {
|
|
583
|
-
i = indexOfNewline(str, i);
|
|
584
|
-
if (i < 0)
|
|
585
|
-
break;
|
|
586
|
-
} else if (c === sep) {
|
|
587
|
-
return i + 1;
|
|
588
|
-
} else if (c === end || banNewLines && (c === `
|
|
589
|
-
` || c === "\r" && str[i + 1] === `
|
|
590
|
-
`)) {
|
|
591
|
-
return i;
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
throw new TomlError("cannot find end of structure", {
|
|
595
|
-
toml: str,
|
|
596
|
-
ptr
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
var init_util = __esm(() => {
|
|
600
|
-
init_error();
|
|
601
|
-
/*!
|
|
602
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
603
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
604
|
-
*
|
|
605
|
-
* Redistribution and use in source and binary forms, with or without
|
|
606
|
-
* modification, are permitted provided that the following conditions are met:
|
|
607
|
-
*
|
|
608
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
609
|
-
* list of conditions and the following disclaimer.
|
|
610
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
611
|
-
* this list of conditions and the following disclaimer in the
|
|
612
|
-
* documentation and/or other materials provided with the distribution.
|
|
613
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
614
|
-
* may be used to endorse or promote products derived from this software without
|
|
615
|
-
* specific prior written permission.
|
|
616
|
-
*
|
|
617
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
618
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
619
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
620
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
621
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
622
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
623
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
624
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
625
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
626
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
627
|
-
*/
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
// node_modules/smol-toml/dist/extract.js
|
|
631
|
-
function sliceAndTrimEndOf(str, startPtr, endPtr) {
|
|
632
|
-
let value = str.slice(startPtr, endPtr);
|
|
633
|
-
let commentIdx = value.indexOf("#");
|
|
634
|
-
if (commentIdx > -1) {
|
|
635
|
-
skipComment(str, commentIdx);
|
|
636
|
-
value = value.slice(0, commentIdx);
|
|
637
|
-
}
|
|
638
|
-
return [value.trimEnd(), commentIdx];
|
|
639
|
-
}
|
|
640
|
-
function extractValue(str, ptr, end, depth, integersAsBigInt) {
|
|
641
|
-
if (depth === 0) {
|
|
642
|
-
throw new TomlError("document contains excessively nested structures. aborting.", {
|
|
643
|
-
toml: str,
|
|
644
|
-
ptr
|
|
645
|
-
});
|
|
646
|
-
}
|
|
647
|
-
let c = str[ptr];
|
|
648
|
-
if (c === "[" || c === "{") {
|
|
649
|
-
let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt);
|
|
650
|
-
if (end) {
|
|
651
|
-
endPtr2 = skipVoid(str, endPtr2);
|
|
652
|
-
if (str[endPtr2] === ",")
|
|
653
|
-
endPtr2++;
|
|
654
|
-
else if (str[endPtr2] !== end) {
|
|
655
|
-
throw new TomlError("expected comma or end of structure", {
|
|
656
|
-
toml: str,
|
|
657
|
-
ptr: endPtr2
|
|
658
|
-
});
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
return [value, endPtr2];
|
|
662
|
-
}
|
|
663
|
-
if (c === '"' || c === "'") {
|
|
664
|
-
let [parsed, endPtr2] = parseString(str, ptr);
|
|
665
|
-
if (end) {
|
|
666
|
-
endPtr2 = skipVoid(str, endPtr2);
|
|
667
|
-
if (str[endPtr2] && str[endPtr2] !== "," && str[endPtr2] !== end && str[endPtr2] !== `
|
|
668
|
-
` && str[endPtr2] !== "\r") {
|
|
669
|
-
throw new TomlError("unexpected character encountered", {
|
|
670
|
-
toml: str,
|
|
671
|
-
ptr: endPtr2
|
|
672
|
-
});
|
|
673
|
-
}
|
|
674
|
-
if (str[endPtr2] === ",")
|
|
675
|
-
endPtr2++;
|
|
676
|
-
}
|
|
677
|
-
return [parsed, endPtr2];
|
|
678
|
-
}
|
|
679
|
-
let endPtr = skipUntil(str, ptr, ",", end);
|
|
680
|
-
let slice = sliceAndTrimEndOf(str, ptr, endPtr - (str[endPtr - 1] === "," ? 1 : 0));
|
|
681
|
-
if (!slice[0]) {
|
|
682
|
-
throw new TomlError("incomplete key-value declaration: no value specified", {
|
|
683
|
-
toml: str,
|
|
684
|
-
ptr
|
|
685
|
-
});
|
|
686
|
-
}
|
|
687
|
-
if (end && slice[1] > -1) {
|
|
688
|
-
endPtr = skipVoid(str, ptr + slice[1]);
|
|
689
|
-
if (str[endPtr] === ",")
|
|
690
|
-
endPtr++;
|
|
691
|
-
}
|
|
692
|
-
return [
|
|
693
|
-
parseValue(slice[0], str, ptr, integersAsBigInt),
|
|
694
|
-
endPtr
|
|
695
|
-
];
|
|
696
|
-
}
|
|
697
|
-
var init_extract = __esm(() => {
|
|
698
|
-
init_primitive();
|
|
699
|
-
init_struct();
|
|
700
|
-
init_util();
|
|
701
|
-
init_error();
|
|
702
|
-
/*!
|
|
703
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
704
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
705
|
-
*
|
|
706
|
-
* Redistribution and use in source and binary forms, with or without
|
|
707
|
-
* modification, are permitted provided that the following conditions are met:
|
|
708
|
-
*
|
|
709
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
710
|
-
* list of conditions and the following disclaimer.
|
|
711
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
712
|
-
* this list of conditions and the following disclaimer in the
|
|
713
|
-
* documentation and/or other materials provided with the distribution.
|
|
714
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
715
|
-
* may be used to endorse or promote products derived from this software without
|
|
716
|
-
* specific prior written permission.
|
|
717
|
-
*
|
|
718
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
719
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
720
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
721
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
722
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
723
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
724
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
725
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
726
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
727
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
728
|
-
*/
|
|
729
|
-
});
|
|
730
|
-
|
|
731
|
-
// node_modules/smol-toml/dist/struct.js
|
|
732
|
-
function parseKey(str, ptr, end = "=") {
|
|
733
|
-
let dot = ptr - 1;
|
|
734
|
-
let parsed = [];
|
|
735
|
-
let endPtr = str.indexOf(end, ptr);
|
|
736
|
-
if (endPtr < 0) {
|
|
737
|
-
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
738
|
-
toml: str,
|
|
739
|
-
ptr
|
|
740
|
-
});
|
|
741
|
-
}
|
|
742
|
-
do {
|
|
743
|
-
let c = str[ptr = ++dot];
|
|
744
|
-
if (c !== " " && c !== "\t") {
|
|
745
|
-
if (c === '"' || c === "'") {
|
|
746
|
-
if (c === str[ptr + 1] && c === str[ptr + 2]) {
|
|
747
|
-
throw new TomlError("multiline strings are not allowed in keys", {
|
|
748
|
-
toml: str,
|
|
749
|
-
ptr
|
|
750
|
-
});
|
|
751
|
-
}
|
|
752
|
-
let [part, eos] = parseString(str, ptr);
|
|
753
|
-
dot = str.indexOf(".", eos);
|
|
754
|
-
let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
755
|
-
let newLine = indexOfNewline(strEnd);
|
|
756
|
-
if (newLine > -1) {
|
|
757
|
-
throw new TomlError("newlines are not allowed in keys", {
|
|
758
|
-
toml: str,
|
|
759
|
-
ptr: ptr + dot + newLine
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
|
-
if (strEnd.trimStart()) {
|
|
763
|
-
throw new TomlError("found extra tokens after the string part", {
|
|
764
|
-
toml: str,
|
|
765
|
-
ptr: eos
|
|
766
|
-
});
|
|
767
|
-
}
|
|
768
|
-
if (endPtr < eos) {
|
|
769
|
-
endPtr = str.indexOf(end, eos);
|
|
770
|
-
if (endPtr < 0) {
|
|
771
|
-
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
772
|
-
toml: str,
|
|
773
|
-
ptr
|
|
774
|
-
});
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
parsed.push(part);
|
|
778
|
-
} else {
|
|
779
|
-
dot = str.indexOf(".", ptr);
|
|
780
|
-
let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
781
|
-
if (!KEY_PART_RE.test(part)) {
|
|
782
|
-
throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", {
|
|
783
|
-
toml: str,
|
|
784
|
-
ptr
|
|
785
|
-
});
|
|
786
|
-
}
|
|
787
|
-
parsed.push(part.trimEnd());
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
} while (dot + 1 && dot < endPtr);
|
|
791
|
-
return [parsed, skipVoid(str, endPtr + 1, true, true)];
|
|
792
|
-
}
|
|
793
|
-
function parseInlineTable(str, ptr, depth, integersAsBigInt) {
|
|
794
|
-
let res = {};
|
|
795
|
-
let seen = new Set;
|
|
796
|
-
let c;
|
|
797
|
-
ptr++;
|
|
798
|
-
while ((c = str[ptr++]) !== "}" && c) {
|
|
799
|
-
if (c === ",") {
|
|
800
|
-
throw new TomlError("expected value, found comma", {
|
|
801
|
-
toml: str,
|
|
802
|
-
ptr: ptr - 1
|
|
803
|
-
});
|
|
804
|
-
} else if (c === "#")
|
|
805
|
-
ptr = skipComment(str, ptr);
|
|
806
|
-
else if (c !== " " && c !== "\t" && c !== `
|
|
807
|
-
` && c !== "\r") {
|
|
808
|
-
let k;
|
|
809
|
-
let t = res;
|
|
810
|
-
let hasOwn = false;
|
|
811
|
-
let [key, keyEndPtr] = parseKey(str, ptr - 1);
|
|
812
|
-
for (let i = 0;i < key.length; i++) {
|
|
813
|
-
if (i)
|
|
814
|
-
t = hasOwn ? t[k] : t[k] = {};
|
|
815
|
-
k = key[i];
|
|
816
|
-
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
|
|
817
|
-
throw new TomlError("trying to redefine an already defined value", {
|
|
818
|
-
toml: str,
|
|
819
|
-
ptr
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
if (!hasOwn && k === "__proto__") {
|
|
823
|
-
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
if (hasOwn) {
|
|
827
|
-
throw new TomlError("trying to redefine an already defined value", {
|
|
828
|
-
toml: str,
|
|
829
|
-
ptr
|
|
830
|
-
});
|
|
831
|
-
}
|
|
832
|
-
let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1, integersAsBigInt);
|
|
833
|
-
seen.add(value);
|
|
834
|
-
t[k] = value;
|
|
835
|
-
ptr = valueEndPtr;
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
if (!c) {
|
|
839
|
-
throw new TomlError("unfinished table encountered", {
|
|
840
|
-
toml: str,
|
|
841
|
-
ptr
|
|
842
|
-
});
|
|
843
|
-
}
|
|
844
|
-
return [res, ptr];
|
|
845
|
-
}
|
|
846
|
-
function parseArray(str, ptr, depth, integersAsBigInt) {
|
|
847
|
-
let res = [];
|
|
848
|
-
let c;
|
|
849
|
-
ptr++;
|
|
850
|
-
while ((c = str[ptr++]) !== "]" && c) {
|
|
851
|
-
if (c === ",") {
|
|
852
|
-
throw new TomlError("expected value, found comma", {
|
|
853
|
-
toml: str,
|
|
854
|
-
ptr: ptr - 1
|
|
855
|
-
});
|
|
856
|
-
} else if (c === "#")
|
|
857
|
-
ptr = skipComment(str, ptr);
|
|
858
|
-
else if (c !== " " && c !== "\t" && c !== `
|
|
859
|
-
` && c !== "\r") {
|
|
860
|
-
let e = extractValue(str, ptr - 1, "]", depth - 1, integersAsBigInt);
|
|
861
|
-
res.push(e[0]);
|
|
862
|
-
ptr = e[1];
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
if (!c) {
|
|
866
|
-
throw new TomlError("unfinished array encountered", {
|
|
867
|
-
toml: str,
|
|
868
|
-
ptr
|
|
869
|
-
});
|
|
870
|
-
}
|
|
871
|
-
return [res, ptr];
|
|
872
|
-
}
|
|
873
|
-
var KEY_PART_RE;
|
|
874
|
-
var init_struct = __esm(() => {
|
|
875
|
-
init_primitive();
|
|
876
|
-
init_extract();
|
|
877
|
-
init_util();
|
|
878
|
-
init_error();
|
|
879
|
-
/*!
|
|
880
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
881
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
882
|
-
*
|
|
883
|
-
* Redistribution and use in source and binary forms, with or without
|
|
884
|
-
* modification, are permitted provided that the following conditions are met:
|
|
885
|
-
*
|
|
886
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
887
|
-
* list of conditions and the following disclaimer.
|
|
888
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
889
|
-
* this list of conditions and the following disclaimer in the
|
|
890
|
-
* documentation and/or other materials provided with the distribution.
|
|
891
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
892
|
-
* may be used to endorse or promote products derived from this software without
|
|
893
|
-
* specific prior written permission.
|
|
894
|
-
*
|
|
895
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
896
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
897
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
898
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
899
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
900
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
901
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
902
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
903
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
904
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
905
|
-
*/
|
|
906
|
-
KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
|
|
907
|
-
});
|
|
908
|
-
|
|
909
|
-
// node_modules/smol-toml/dist/parse.js
|
|
910
|
-
function peekTable(key, table, meta, type) {
|
|
911
|
-
let t = table;
|
|
912
|
-
let m = meta;
|
|
913
|
-
let k;
|
|
914
|
-
let hasOwn = false;
|
|
915
|
-
let state;
|
|
916
|
-
for (let i = 0;i < key.length; i++) {
|
|
917
|
-
if (i) {
|
|
918
|
-
t = hasOwn ? t[k] : t[k] = {};
|
|
919
|
-
m = (state = m[k]).c;
|
|
920
|
-
if (type === 0 && (state.t === 1 || state.t === 2)) {
|
|
921
|
-
return null;
|
|
922
|
-
}
|
|
923
|
-
if (state.t === 2) {
|
|
924
|
-
let l = t.length - 1;
|
|
925
|
-
t = t[l];
|
|
926
|
-
m = m[l].c;
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
k = key[i];
|
|
930
|
-
if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) {
|
|
931
|
-
return null;
|
|
932
|
-
}
|
|
933
|
-
if (!hasOwn) {
|
|
934
|
-
if (k === "__proto__") {
|
|
935
|
-
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
936
|
-
Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
|
|
937
|
-
}
|
|
938
|
-
m[k] = {
|
|
939
|
-
t: i < key.length - 1 && type === 2 ? 3 : type,
|
|
940
|
-
d: false,
|
|
941
|
-
i: 0,
|
|
942
|
-
c: {}
|
|
943
|
-
};
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
state = m[k];
|
|
947
|
-
if (state.t !== type && !(type === 1 && state.t === 3)) {
|
|
948
|
-
return null;
|
|
949
|
-
}
|
|
950
|
-
if (type === 2) {
|
|
951
|
-
if (!state.d) {
|
|
952
|
-
state.d = true;
|
|
953
|
-
t[k] = [];
|
|
954
|
-
}
|
|
955
|
-
t[k].push(t = {});
|
|
956
|
-
state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} };
|
|
957
|
-
}
|
|
958
|
-
if (state.d) {
|
|
959
|
-
return null;
|
|
960
|
-
}
|
|
961
|
-
state.d = true;
|
|
962
|
-
if (type === 1) {
|
|
963
|
-
t = hasOwn ? t[k] : t[k] = {};
|
|
964
|
-
} else if (type === 0 && hasOwn) {
|
|
965
|
-
return null;
|
|
966
|
-
}
|
|
967
|
-
return [k, t, state.c];
|
|
968
|
-
}
|
|
969
|
-
function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
|
|
970
|
-
let res = {};
|
|
971
|
-
let meta = {};
|
|
972
|
-
let tbl = res;
|
|
973
|
-
let m = meta;
|
|
974
|
-
for (let ptr = skipVoid(toml, 0);ptr < toml.length; ) {
|
|
975
|
-
if (toml[ptr] === "[") {
|
|
976
|
-
let isTableArray = toml[++ptr] === "[";
|
|
977
|
-
let k = parseKey(toml, ptr += +isTableArray, "]");
|
|
978
|
-
if (isTableArray) {
|
|
979
|
-
if (toml[k[1] - 1] !== "]") {
|
|
980
|
-
throw new TomlError("expected end of table declaration", {
|
|
981
|
-
toml,
|
|
982
|
-
ptr: k[1] - 1
|
|
983
|
-
});
|
|
984
|
-
}
|
|
985
|
-
k[1]++;
|
|
986
|
-
}
|
|
987
|
-
let p = peekTable(k[0], res, meta, isTableArray ? 2 : 1);
|
|
988
|
-
if (!p) {
|
|
989
|
-
throw new TomlError("trying to redefine an already defined table or value", {
|
|
990
|
-
toml,
|
|
991
|
-
ptr
|
|
992
|
-
});
|
|
993
|
-
}
|
|
994
|
-
m = p[2];
|
|
995
|
-
tbl = p[1];
|
|
996
|
-
ptr = k[1];
|
|
997
|
-
} else {
|
|
998
|
-
let k = parseKey(toml, ptr);
|
|
999
|
-
let p = peekTable(k[0], tbl, m, 0);
|
|
1000
|
-
if (!p) {
|
|
1001
|
-
throw new TomlError("trying to redefine an already defined table or value", {
|
|
1002
|
-
toml,
|
|
1003
|
-
ptr
|
|
1004
|
-
});
|
|
1005
|
-
}
|
|
1006
|
-
let v = extractValue(toml, k[1], undefined, maxDepth, integersAsBigInt);
|
|
1007
|
-
p[1][p[0]] = v[0];
|
|
1008
|
-
ptr = v[1];
|
|
1009
|
-
}
|
|
1010
|
-
ptr = skipVoid(toml, ptr, true);
|
|
1011
|
-
if (toml[ptr] && toml[ptr] !== `
|
|
1012
|
-
` && toml[ptr] !== "\r") {
|
|
1013
|
-
throw new TomlError("each key-value declaration must be followed by an end-of-line", {
|
|
1014
|
-
toml,
|
|
1015
|
-
ptr
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
ptr = skipVoid(toml, ptr);
|
|
1019
|
-
}
|
|
1020
|
-
return res;
|
|
1021
|
-
}
|
|
1022
|
-
var init_parse = __esm(() => {
|
|
1023
|
-
init_struct();
|
|
1024
|
-
init_extract();
|
|
1025
|
-
init_util();
|
|
1026
|
-
init_error();
|
|
1027
|
-
/*!
|
|
1028
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
1029
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
1030
|
-
*
|
|
1031
|
-
* Redistribution and use in source and binary forms, with or without
|
|
1032
|
-
* modification, are permitted provided that the following conditions are met:
|
|
1033
|
-
*
|
|
1034
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
1035
|
-
* list of conditions and the following disclaimer.
|
|
1036
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
1037
|
-
* this list of conditions and the following disclaimer in the
|
|
1038
|
-
* documentation and/or other materials provided with the distribution.
|
|
1039
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
1040
|
-
* may be used to endorse or promote products derived from this software without
|
|
1041
|
-
* specific prior written permission.
|
|
1042
|
-
*
|
|
1043
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
1044
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
1045
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
1046
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
1047
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
1048
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
1049
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
1050
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
1051
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1052
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1053
|
-
*/
|
|
1054
|
-
});
|
|
1055
|
-
|
|
1056
|
-
// node_modules/smol-toml/dist/stringify.js
|
|
1057
|
-
var init_stringify = __esm(() => {
|
|
1058
|
-
/*!
|
|
1059
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
1060
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
1061
|
-
*
|
|
1062
|
-
* Redistribution and use in source and binary forms, with or without
|
|
1063
|
-
* modification, are permitted provided that the following conditions are met:
|
|
1064
|
-
*
|
|
1065
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
1066
|
-
* list of conditions and the following disclaimer.
|
|
1067
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
1068
|
-
* this list of conditions and the following disclaimer in the
|
|
1069
|
-
* documentation and/or other materials provided with the distribution.
|
|
1070
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
1071
|
-
* may be used to endorse or promote products derived from this software without
|
|
1072
|
-
* specific prior written permission.
|
|
1073
|
-
*
|
|
1074
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
1075
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
1076
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
1077
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
1078
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
1079
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
1080
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
1081
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
1082
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1083
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1084
|
-
*/
|
|
1085
|
-
});
|
|
1086
|
-
|
|
1087
|
-
// node_modules/smol-toml/dist/index.js
|
|
1088
|
-
var init_dist = __esm(() => {
|
|
1089
|
-
init_parse();
|
|
1090
|
-
init_stringify();
|
|
1091
|
-
init_date();
|
|
1092
|
-
init_error();
|
|
1093
|
-
/*!
|
|
1094
|
-
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
1095
|
-
* SPDX-License-Identifier: BSD-3-Clause
|
|
1096
|
-
*
|
|
1097
|
-
* Redistribution and use in source and binary forms, with or without
|
|
1098
|
-
* modification, are permitted provided that the following conditions are met:
|
|
1099
|
-
*
|
|
1100
|
-
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
1101
|
-
* list of conditions and the following disclaimer.
|
|
1102
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
1103
|
-
* this list of conditions and the following disclaimer in the
|
|
1104
|
-
* documentation and/or other materials provided with the distribution.
|
|
1105
|
-
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
1106
|
-
* may be used to endorse or promote products derived from this software without
|
|
1107
|
-
* specific prior written permission.
|
|
1108
|
-
*
|
|
1109
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
1110
|
-
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
1111
|
-
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
1112
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
1113
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
1114
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
1115
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
1116
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
1117
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
1118
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
1119
|
-
*/
|
|
1120
|
-
});
|
|
1121
|
-
|
|
1122
157
|
// src/hooks/fp-home.ts
|
|
1123
158
|
import { homedir } from "node:os";
|
|
1124
159
|
import { resolve } from "node:path";
|
|
@@ -1143,7 +178,10 @@ function resettablePaths() {
|
|
|
1143
178
|
legacy.collectorHealth(),
|
|
1144
179
|
legacy.onboardingLock(),
|
|
1145
180
|
legacy.cloudManagedPolicies(),
|
|
1146
|
-
|
|
181
|
+
legacy.configToml(),
|
|
182
|
+
legacy.credentialsToml(),
|
|
183
|
+
legacy.localPoliciesDir(),
|
|
184
|
+
globalPolicyConfigFile(),
|
|
1147
185
|
cloudPoliciesDir(),
|
|
1148
186
|
at("state"),
|
|
1149
187
|
configFile(),
|
|
@@ -1153,10 +191,15 @@ function resettablePaths() {
|
|
|
1153
191
|
logsDir()
|
|
1154
192
|
];
|
|
1155
193
|
}
|
|
1156
|
-
var LAYOUT_VERSION =
|
|
194
|
+
var LAYOUT_VERSION = 3, at = (...parts) => resolve(failproofaiHome(), ...parts), atHome = (home, ...parts) => home ? resolve(failproofaiHome(home), ...parts) : at(...parts), versionFile = (home) => atHome(home, "VERSION"), configFile = (home) => atHome(home, "config.json"), credentialsFile = (home) => atHome(home, "credentials.json"), binDir = (home) => atHome(home, "bin"), policiesDir = (home) => atHome(home, "policies"), customPoliciesDir, globalPolicyConfigFile = (home) => atHome(home, "policies-config.json"), cloudPoliciesDir = (home) => resolve(policiesDir(home), "cloud-policies"), customAgentsDir = (home) => atHome(home, "custom-agents"), auditDir = (home) => atHome(home, "audit"), auditDashboardFile = (home) => resolve(auditDir(home), "dashboard.json"), auditCacheDir = (home) => resolve(auditDir(home), "cache"), hookActivityDir = (home) => atHome(home, "hook-activity"), runDir = (home) => atHome(home, "run"), daemonSocket = () => process.env.FAILPROOFAI_DAEMON_SOCKET || resolve(runDir(), "failproofaid.sock"), auditLockFile = (home) => resolve(runDir(home), "audit.lock"), stateDir = (home) => atHome(home, "state"), shimsDir = (home) => resolve(stateDir(home), "shims"), spoolDir = (home) => resolve(stateDir(home), "spool"), sessionPauseDir = () => resolve(stateDir(), "sessions"), telemetryIdFile = (home) => resolve(stateDir(home), "telemetry-id"), launcherMarker = (home) => resolve(stateDir(home), "launcher-configured"), onboardingAttemptFile = (home) => resolve(stateDir(home), "onboarding-attempt.json"), lastVersionFile = (home) => resolve(stateDir(home), "last-version"), onboardingLockFile = (home) => resolve(stateDir(home), "onboarding.lock"), codexSessionPathsFile = (home) => resolve(stateDir(home), "codex-session-paths.json"), logsDir = (home) => atHome(home, "logs"), legacy;
|
|
1157
195
|
var init_fp_home = __esm(() => {
|
|
196
|
+
customPoliciesDir = policiesDir;
|
|
1158
197
|
legacy = {
|
|
1159
198
|
policyConfig: () => at("policies-config.json"),
|
|
199
|
+
configToml: () => at("config.toml"),
|
|
200
|
+
credentialsToml: () => at("credentials.toml"),
|
|
201
|
+
localPoliciesDir: () => at("policies", "local-policies"),
|
|
202
|
+
customPoliciesDir: () => at("policies", "custom-policies"),
|
|
1160
203
|
policyConfigLocal: () => at("policies-config.local.json"),
|
|
1161
204
|
cloudCredentials: () => at("cloud.json"),
|
|
1162
205
|
ingestCredentials: () => at("ingest.json"),
|
|
@@ -1186,6 +229,11 @@ function detectLayout() {
|
|
|
1186
229
|
return { kind: "current", version: raw };
|
|
1187
230
|
return raw.layout > LAYOUT_VERSION ? { kind: "future", found: raw.layout } : { kind: "stale", found: raw.layout };
|
|
1188
231
|
}
|
|
232
|
+
if (existsSync(configFile())) {
|
|
233
|
+
return { kind: "current", version: { layout: LAYOUT_VERSION, cli: "" }, inferred: true };
|
|
234
|
+
}
|
|
235
|
+
if (existsSync(legacy.configToml()))
|
|
236
|
+
return { kind: "stale", found: LAYOUT_VERSION - 1 };
|
|
1189
237
|
const layoutOneMarkers = [
|
|
1190
238
|
legacy.policyConfig(),
|
|
1191
239
|
legacy.cacheDir(),
|
|
@@ -1197,9 +245,22 @@ function detectLayout() {
|
|
|
1197
245
|
];
|
|
1198
246
|
return layoutOneMarkers.some((p) => existsSync(p)) ? { kind: "stale", found: 1 } : { kind: "absent" };
|
|
1199
247
|
}
|
|
248
|
+
function readLegacyTomlVersion(text) {
|
|
249
|
+
const layout = Number(/^\s*layout\s*=\s*(\d+)\s*$/m.exec(text)?.[1]);
|
|
250
|
+
if (!Number.isFinite(layout))
|
|
251
|
+
return null;
|
|
252
|
+
const str = (key) => new RegExp(`^\\s*${key}\\s*=\\s*"([^"]*)"`, "m").exec(text)?.[1];
|
|
253
|
+
return { layout, cli: str("cli") ?? "", daemon: str("daemon") };
|
|
254
|
+
}
|
|
1200
255
|
function readVersionFile() {
|
|
256
|
+
let text;
|
|
257
|
+
try {
|
|
258
|
+
text = readFileSync(versionFile(), "utf8");
|
|
259
|
+
} catch {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
1201
262
|
try {
|
|
1202
|
-
const parsed = parse(
|
|
263
|
+
const parsed = JSON.parse(text);
|
|
1203
264
|
const layout = Number(parsed.layout);
|
|
1204
265
|
if (!Number.isFinite(layout))
|
|
1205
266
|
return null;
|
|
@@ -1209,7 +270,7 @@ function readVersionFile() {
|
|
|
1209
270
|
daemon: typeof parsed.daemon === "string" ? parsed.daemon : undefined
|
|
1210
271
|
};
|
|
1211
272
|
} catch {
|
|
1212
|
-
return
|
|
273
|
+
return readLegacyTomlVersion(text);
|
|
1213
274
|
}
|
|
1214
275
|
}
|
|
1215
276
|
function writeVersionFile(v = {}) {
|
|
@@ -1219,16 +280,7 @@ function writeVersionFile(v = {}) {
|
|
|
1219
280
|
cli: v.cli ?? version2,
|
|
1220
281
|
daemon: v.clearDaemon ? undefined : v.daemon ?? existing?.daemon
|
|
1221
282
|
};
|
|
1222
|
-
|
|
1223
|
-
"# Written by failproofai. `layout` is what tells a newer CLI whether this",
|
|
1224
|
-
"# directory can be read as-is; do not edit it by hand.",
|
|
1225
|
-
`layout = ${next.layout}`,
|
|
1226
|
-
`cli = ${JSON.stringify(next.cli)}`
|
|
1227
|
-
];
|
|
1228
|
-
if (next.daemon)
|
|
1229
|
-
lines.push(`daemon = ${JSON.stringify(next.daemon)}`);
|
|
1230
|
-
writeFileAt(versionFile(), lines.join(`
|
|
1231
|
-
`) + `
|
|
283
|
+
writeFileAt(versionFile(), `${JSON.stringify({ layout: next.layout, cli: next.cli, ...next.daemon ? { daemon: next.daemon } : {} }, null, 2)}
|
|
1232
284
|
`);
|
|
1233
285
|
}
|
|
1234
286
|
function readIntervalDays(raw) {
|
|
@@ -1239,9 +291,25 @@ function readIntervalDays(raw) {
|
|
|
1239
291
|
return DEFAULT_AUDIT_INTERVAL_DAYS;
|
|
1240
292
|
return Math.min(days, MAX_AUDIT_INTERVAL_DAYS);
|
|
1241
293
|
}
|
|
294
|
+
function readSources(raw) {
|
|
295
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
296
|
+
return;
|
|
297
|
+
const out = {};
|
|
298
|
+
for (const [name, table] of Object.entries(raw)) {
|
|
299
|
+
if (!table || typeof table !== "object" || Array.isArray(table))
|
|
300
|
+
continue;
|
|
301
|
+
const entries = table.extra_paths;
|
|
302
|
+
if (!Array.isArray(entries))
|
|
303
|
+
continue;
|
|
304
|
+
const paths = entries.filter((e) => typeof e === "string" && e.trim() !== "");
|
|
305
|
+
if (paths.length > 0)
|
|
306
|
+
out[name] = { extraPaths: paths };
|
|
307
|
+
}
|
|
308
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
309
|
+
}
|
|
1242
310
|
function readConfig() {
|
|
1243
311
|
try {
|
|
1244
|
-
const parsed = parse(readFileSync(configFile(), "utf8"));
|
|
312
|
+
const parsed = JSON.parse(readFileSync(configFile(), "utf8"));
|
|
1245
313
|
const mode = parsed.mode?.kind;
|
|
1246
314
|
const daemon = parsed.daemon ?? {};
|
|
1247
315
|
const collector = parsed.collector ?? {};
|
|
@@ -1256,7 +324,8 @@ function readConfig() {
|
|
|
1256
324
|
hooksVerbosity: collector.hooks_verbosity === "all" || collector.hooks_verbosity === "off" ? collector.hooks_verbosity : "decisions",
|
|
1257
325
|
redact: collector.redact === "off" ? "off" : "minimal",
|
|
1258
326
|
environment: typeof collector.environment === "string" ? collector.environment : "local",
|
|
1259
|
-
machineId: typeof collector.machine_id === "string" ? collector.machine_id : undefined
|
|
327
|
+
machineId: typeof collector.machine_id === "string" ? collector.machine_id : undefined,
|
|
328
|
+
sources: readSources(collector.sources)
|
|
1260
329
|
},
|
|
1261
330
|
telemetry: { enabled: telemetry.enabled !== false },
|
|
1262
331
|
audit: { auto: audit.auto === true, intervalDays: readIntervalDays(audit.interval_days) }
|
|
@@ -1267,31 +336,24 @@ function readConfig() {
|
|
|
1267
336
|
}
|
|
1268
337
|
function writeConfig(config) {
|
|
1269
338
|
const c = config.collector;
|
|
1270
|
-
const
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
lines.push(`machine_id = ${JSON.stringify(c.machineId)}`);
|
|
1289
|
-
if (!config.telemetry.enabled) {
|
|
1290
|
-
lines.push("", "[telemetry]", "enabled = false");
|
|
1291
|
-
}
|
|
1292
|
-
lines.push("", "[audit]", "# Scan this machine's agent history on a schedule and refresh the audit", "# dashboard. OFF by default: the scan reads the CONTENTS of every session", "# transcript on disk, so it waits to be asked. It runs as a separate", "# short-lived process — never on the hook path.", `auto = ${config.audit.auto}`, `interval_days = ${config.audit.intervalDays}`);
|
|
1293
|
-
writeFileAt(configFile(), lines.join(`
|
|
1294
|
-
`) + `
|
|
339
|
+
const out = {
|
|
340
|
+
mode: { kind: config.mode },
|
|
341
|
+
daemon: { configured: config.daemon.configured },
|
|
342
|
+
collector: {
|
|
343
|
+
sessions: c.sessions,
|
|
344
|
+
hooks: c.hooks,
|
|
345
|
+
hooks_verbosity: c.hooksVerbosity,
|
|
346
|
+
redact: c.redact,
|
|
347
|
+
environment: c.environment,
|
|
348
|
+
...c.machineId ? { machine_id: c.machineId } : {},
|
|
349
|
+
...Object.entries(c.sources ?? {}).some(([, s]) => s.extraPaths?.length) ? {
|
|
350
|
+
sources: Object.fromEntries(Object.entries(c.sources ?? {}).filter(([, s]) => s.extraPaths?.length).map(([name, s]) => [name, { extra_paths: s.extraPaths }]))
|
|
351
|
+
} : {}
|
|
352
|
+
},
|
|
353
|
+
...config.telemetry.enabled ? {} : { telemetry: { enabled: false } },
|
|
354
|
+
audit: { auto: config.audit.auto, interval_days: config.audit.intervalDays }
|
|
355
|
+
};
|
|
356
|
+
writeFileAt(configFile(), `${JSON.stringify(out, null, 2)}
|
|
1295
357
|
`);
|
|
1296
358
|
}
|
|
1297
359
|
function updateConfig(patch) {
|
|
@@ -1308,7 +370,7 @@ function updateConfig(patch) {
|
|
|
1308
370
|
}
|
|
1309
371
|
function readCredentials() {
|
|
1310
372
|
try {
|
|
1311
|
-
const parsed = parse(readFileSync(credentialsFile(), "utf8"));
|
|
373
|
+
const parsed = JSON.parse(readFileSync(credentialsFile(), "utf8"));
|
|
1312
374
|
const cloud = parsed.cloud;
|
|
1313
375
|
const ingest = parsed.ingest;
|
|
1314
376
|
const auth = parsed.auth;
|
|
@@ -1341,34 +403,32 @@ function readCredentials() {
|
|
|
1341
403
|
}
|
|
1342
404
|
}
|
|
1343
405
|
function writeCredentials(creds) {
|
|
1344
|
-
const
|
|
1345
|
-
"# failproofai credentials — owner-only (0600). Do not commit."
|
|
1346
|
-
];
|
|
406
|
+
const out = {};
|
|
1347
407
|
if (creds.cloud) {
|
|
1348
|
-
|
|
408
|
+
out.cloud = {
|
|
409
|
+
url: creds.cloud.url,
|
|
410
|
+
machine_id: creds.cloud.machineId,
|
|
411
|
+
...creds.cloud.machineLabel ? { machine_label: creds.cloud.machineLabel } : {},
|
|
412
|
+
token: creds.cloud.token
|
|
413
|
+
};
|
|
1349
414
|
}
|
|
1350
415
|
if (creds.ingest) {
|
|
1351
|
-
|
|
416
|
+
out.ingest = { url: creds.ingest.url, key: creds.ingest.key };
|
|
1352
417
|
}
|
|
1353
418
|
if (creds.org && (creds.org.id || creds.org.slug || creds.org.name)) {
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
if (creds.org.name)
|
|
1360
|
-
lines.push(`name = ${JSON.stringify(creds.org.name)}`);
|
|
419
|
+
out.org = {
|
|
420
|
+
...creds.org.id ? { id: creds.org.id } : {},
|
|
421
|
+
...creds.org.slug ? { slug: creds.org.slug } : {},
|
|
422
|
+
...creds.org.name ? { name: creds.org.name } : {}
|
|
423
|
+
};
|
|
1361
424
|
}
|
|
1362
425
|
if (creds.auth && (creds.auth.sessionToken || creds.auth.email)) {
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
lines.push(`expires_at = ${creds.auth.expiresAt}`);
|
|
1370
|
-
if (creds.auth.email)
|
|
1371
|
-
lines.push(`email = ${JSON.stringify(creds.auth.email)}`);
|
|
426
|
+
out.auth = {
|
|
427
|
+
...creds.auth.baseUrl ? { base_url: creds.auth.baseUrl } : {},
|
|
428
|
+
...creds.auth.sessionToken ? { session_token: creds.auth.sessionToken } : {},
|
|
429
|
+
...creds.auth.expiresAt ? { expires_at: creds.auth.expiresAt } : {},
|
|
430
|
+
...creds.auth.email ? { email: creds.auth.email } : {}
|
|
431
|
+
};
|
|
1372
432
|
}
|
|
1373
433
|
const home = failproofaiHome();
|
|
1374
434
|
mkdirSync(home, { recursive: true });
|
|
@@ -1376,8 +436,7 @@ function writeCredentials(creds) {
|
|
|
1376
436
|
if (statSync(home).mode & 63)
|
|
1377
437
|
chmodSync(home, 448);
|
|
1378
438
|
} catch {}
|
|
1379
|
-
writeFileSync(credentialsFile(),
|
|
1380
|
-
`) + `
|
|
439
|
+
writeFileSync(credentialsFile(), `${JSON.stringify(out, null, 2)}
|
|
1381
440
|
`, { mode: 384 });
|
|
1382
441
|
try {
|
|
1383
442
|
chmodSync(credentialsFile(), 384);
|
|
@@ -1389,7 +448,6 @@ function writeFileAt(path, contents) {
|
|
|
1389
448
|
}
|
|
1390
449
|
var DEFAULT_AUDIT_INTERVAL_DAYS = 7, MIN_AUDIT_INTERVAL_DAYS = 1, MAX_AUDIT_INTERVAL_DAYS = 90, DEFAULT_CONFIG;
|
|
1391
450
|
var init_fp_config = __esm(() => {
|
|
1392
|
-
init_dist();
|
|
1393
451
|
init_package();
|
|
1394
452
|
init_fp_home();
|
|
1395
453
|
DEFAULT_CONFIG = {
|
|
@@ -5631,7 +4689,19 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
|
|
|
5631
4689
|
const projectRoot = findProjectConfigDir(opts?.sessionCwd ?? process.cwd());
|
|
5632
4690
|
const conventionEnabled = opts?.customPoliciesEnabled !== false;
|
|
5633
4691
|
const loadedPaths = new Set;
|
|
5634
|
-
const cloudManagedByPath = new Map
|
|
4692
|
+
const cloudManagedByPath = new Map;
|
|
4693
|
+
for (const policy of opts?.cloudManagedPolicies ?? []) {
|
|
4694
|
+
const key = resolve5(policy.path);
|
|
4695
|
+
const existing = cloudManagedByPath.get(key);
|
|
4696
|
+
if (!existing) {
|
|
4697
|
+
cloudManagedByPath.set(key, policy);
|
|
4698
|
+
continue;
|
|
4699
|
+
}
|
|
4700
|
+
hookLogWarn(`cloud-managed policies ${existing.id} and ${policy.id} have identical source, so they share ` + `one artifact and load as one policy; enforcing it if either asks to enforce`);
|
|
4701
|
+
if (existing.effect !== "enforce" && policy.effect === "enforce") {
|
|
4702
|
+
cloudManagedByPath.set(key, policy);
|
|
4703
|
+
}
|
|
4704
|
+
}
|
|
5635
4705
|
for (const customPoliciesPath of typeof customPoliciesPaths === "string" ? [customPoliciesPaths] : customPoliciesPaths ?? []) {
|
|
5636
4706
|
const absPath = resolve5(projectRoot, customPoliciesPath);
|
|
5637
4707
|
if (existsSync5(absPath)) {
|
|
@@ -5646,7 +4716,7 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
|
|
|
5646
4716
|
const tagged = hook;
|
|
5647
4717
|
if (cloudManaged) {
|
|
5648
4718
|
tagged.__cloudManaged = cloudManaged;
|
|
5649
|
-
tagged.__policyId = `cloud:${cloudManaged.id}@${cloudManaged.
|
|
4719
|
+
tagged.__policyId = `cloud:${cloudManaged.id}@${cloudManaged.version}:${hook.name}`;
|
|
5650
4720
|
} else {
|
|
5651
4721
|
tagged.__policyId = customPolicyId(absPath, hook.name);
|
|
5652
4722
|
}
|
|
@@ -5658,23 +4728,24 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
|
|
|
5658
4728
|
}
|
|
5659
4729
|
const hooksBeforeConvention = getCustomHooks().length;
|
|
5660
4730
|
const projectDir = resolve5(projectRoot, ".failproofai", "policies");
|
|
4731
|
+
const projectScope = projectDir === customPoliciesDir() ? "user" : "project";
|
|
5661
4732
|
if (conventionEnabled) {
|
|
5662
4733
|
sweepStaleTmpArtifacts(projectDir);
|
|
5663
|
-
warnSkippedPolicyFiles(projectDir,
|
|
4734
|
+
warnSkippedPolicyFiles(projectDir, projectScope);
|
|
5664
4735
|
}
|
|
5665
4736
|
sweepStaleTmpArtifacts(shimsDir());
|
|
5666
4737
|
const projectFiles = conventionEnabled ? discoverPolicyFiles(projectDir).filter((f) => !loadedPaths.has(f)) : [];
|
|
5667
4738
|
for (const file of projectFiles) {
|
|
5668
4739
|
loadedPaths.add(file);
|
|
5669
4740
|
const hooksBefore = getCustomHooks().length;
|
|
5670
|
-
await loadSingleFile(file, { conventionScope:
|
|
4741
|
+
await loadSingleFile(file, { conventionScope: projectScope });
|
|
5671
4742
|
const newHooks = getCustomHooks().slice(hooksBefore);
|
|
5672
4743
|
for (const hook of newHooks) {
|
|
5673
|
-
hook.__policyId = conventionPolicyId(
|
|
4744
|
+
hook.__policyId = conventionPolicyId(projectScope, basename(file), hook.name);
|
|
5674
4745
|
}
|
|
5675
4746
|
if (newHooks.length > 0) {
|
|
5676
4747
|
conventionSources.push({
|
|
5677
|
-
scope:
|
|
4748
|
+
scope: projectScope,
|
|
5678
4749
|
file: basename(file),
|
|
5679
4750
|
hookNames: newHooks.map((h) => h.name)
|
|
5680
4751
|
});
|
|
@@ -10517,16 +9588,21 @@ function cloudManagedPolicyRoot() {
|
|
|
10517
9588
|
function parseManifest(value) {
|
|
10518
9589
|
if (!value || typeof value !== "object")
|
|
10519
9590
|
throw new Error("active manifest is not an object");
|
|
10520
|
-
const
|
|
10521
|
-
if (
|
|
10522
|
-
throw new Error(`unsupported active manifest schema ${String(
|
|
9591
|
+
const raw = value;
|
|
9592
|
+
if (!ACCEPTED_ACTIVE_SCHEMA_VERSIONS.includes(raw.schemaVersion)) {
|
|
9593
|
+
throw new Error(`unsupported active manifest schema ${String(raw.schemaVersion)} ` + `(supported: ${ACCEPTED_ACTIVE_SCHEMA_VERSIONS.join(", ")})`);
|
|
10523
9594
|
}
|
|
10524
|
-
|
|
10525
|
-
|
|
9595
|
+
const deployment = raw.deployment ?? raw.generation;
|
|
9596
|
+
if (!Number.isSafeInteger(deployment) || (deployment ?? -1) < 0) {
|
|
9597
|
+
throw new Error("active manifest deployment is invalid");
|
|
10526
9598
|
}
|
|
10527
|
-
if (!Array.isArray(
|
|
9599
|
+
if (!Array.isArray(raw.policies))
|
|
10528
9600
|
throw new Error("active manifest policies is not an array");
|
|
10529
|
-
|
|
9601
|
+
const policies = raw.policies.map((p) => {
|
|
9602
|
+
const entry = p;
|
|
9603
|
+
return { ...entry, version: entry.version ?? entry.revision };
|
|
9604
|
+
});
|
|
9605
|
+
return { schemaVersion: raw.schemaVersion, deployment, policies };
|
|
10530
9606
|
}
|
|
10531
9607
|
function resolveManagedPath(root, candidate) {
|
|
10532
9608
|
if (!candidate || isAbsolute2(candidate))
|
|
@@ -10572,8 +9648,8 @@ function readActiveCloudManagedPolicies() {
|
|
|
10572
9648
|
if (!POLICY_ID_RE.test(policy.id) || policy.id === "." || policy.id === "..") {
|
|
10573
9649
|
throw new Error(`unsafe cloud-managed policy id ${JSON.stringify(policy.id)}`);
|
|
10574
9650
|
}
|
|
10575
|
-
if (!Number.isSafeInteger(policy.
|
|
10576
|
-
throw new Error(`invalid
|
|
9651
|
+
if (!Number.isSafeInteger(policy.version) || policy.version < 0) {
|
|
9652
|
+
throw new Error(`invalid version for cloud-managed policy ${policy.id}`);
|
|
10577
9653
|
}
|
|
10578
9654
|
if (!SHA256_RE.test(policy.sha256)) {
|
|
10579
9655
|
throw new Error(`invalid SHA-256 for cloud-managed policy ${policy.id}`);
|
|
@@ -10592,17 +9668,18 @@ function readActiveCloudManagedPolicies() {
|
|
|
10592
9668
|
}
|
|
10593
9669
|
return {
|
|
10594
9670
|
id: policy.id,
|
|
10595
|
-
|
|
9671
|
+
version: policy.version,
|
|
10596
9672
|
effect: policy.effect ?? "enforce",
|
|
10597
9673
|
sha256: policy.sha256,
|
|
10598
9674
|
path: path3,
|
|
10599
|
-
|
|
9675
|
+
deployment: manifest.deployment
|
|
10600
9676
|
};
|
|
10601
9677
|
});
|
|
10602
9678
|
}
|
|
10603
|
-
var
|
|
9679
|
+
var ACCEPTED_ACTIVE_SCHEMA_VERSIONS, SHA256_RE, POLICY_ID_RE;
|
|
10604
9680
|
var init_cloud_managed_policies = __esm(() => {
|
|
10605
9681
|
init_fp_home();
|
|
9682
|
+
ACCEPTED_ACTIVE_SCHEMA_VERSIONS = [1, 2];
|
|
10606
9683
|
SHA256_RE = /^[a-f0-9]{64}$/;
|
|
10607
9684
|
POLICY_ID_RE = /^[A-Za-z0-9._-]{1,128}$/;
|
|
10608
9685
|
});
|
|
@@ -11512,20 +10589,40 @@ async function probeDaemon() {
|
|
|
11512
10589
|
return { ok: false, reason: "unreachable" };
|
|
11513
10590
|
}
|
|
11514
10591
|
}
|
|
10592
|
+
async function daemonAcceptsConnectionsQuietly() {
|
|
10593
|
+
try {
|
|
10594
|
+
const { daemonAcceptsConnections: daemonAcceptsConnections3 } = await Promise.resolve().then(() => (init_daemon_client2(), exports_daemon_client2));
|
|
10595
|
+
return await daemonAcceptsConnections3();
|
|
10596
|
+
} catch {
|
|
10597
|
+
return false;
|
|
10598
|
+
}
|
|
10599
|
+
}
|
|
11515
10600
|
async function probeDaemonEndToEnd() {
|
|
11516
10601
|
return (await probeDaemon()).ok;
|
|
11517
10602
|
}
|
|
11518
|
-
async function waitForDaemonRunning() {
|
|
11519
|
-
const
|
|
10603
|
+
async function waitForDaemonRunning(deps = {}) {
|
|
10604
|
+
const status = deps.status ?? daemonServiceStatus;
|
|
10605
|
+
const accepts = deps.accepts ?? daemonAcceptsConnectionsQuietly;
|
|
10606
|
+
const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
10607
|
+
const now = deps.now ?? Date.now;
|
|
10608
|
+
const deadline = now() + SERVICE_START_TIMEOUT_MS;
|
|
11520
10609
|
for (;; ) {
|
|
11521
|
-
if (
|
|
10610
|
+
if (status() === "running")
|
|
11522
10611
|
break;
|
|
11523
|
-
if (
|
|
10612
|
+
if (now() >= deadline)
|
|
11524
10613
|
return false;
|
|
11525
|
-
await
|
|
10614
|
+
await sleep(SERVICE_START_POLL_MS);
|
|
10615
|
+
}
|
|
10616
|
+
const settleUntil = now() + SERVICE_SETTLE_MS;
|
|
10617
|
+
for (;; ) {
|
|
10618
|
+
if (status() !== "running")
|
|
10619
|
+
return false;
|
|
10620
|
+
if (await accepts())
|
|
10621
|
+
return true;
|
|
10622
|
+
if (now() >= settleUntil)
|
|
10623
|
+
return true;
|
|
10624
|
+
await sleep(SERVICE_START_POLL_MS);
|
|
11526
10625
|
}
|
|
11527
|
-
await new Promise((r) => setTimeout(r, SERVICE_SETTLE_MS));
|
|
11528
|
-
return daemonServiceStatus() === "running";
|
|
11529
10626
|
}
|
|
11530
10627
|
function readInstalledServiceDefinition() {
|
|
11531
10628
|
if (!isDaemonSupportedPlatform())
|
|
@@ -11756,6 +10853,18 @@ var init_daemon_service = __esm(() => {
|
|
|
11756
10853
|
});
|
|
11757
10854
|
|
|
11758
10855
|
// src/hooks/fp-reset.ts
|
|
10856
|
+
import {
|
|
10857
|
+
copyFileSync,
|
|
10858
|
+
existsSync as existsSync18,
|
|
10859
|
+
mkdirSync as mkdirSync10,
|
|
10860
|
+
readFileSync as readFileSync15,
|
|
10861
|
+
readdirSync as readdirSync13,
|
|
10862
|
+
renameSync as renameSync5,
|
|
10863
|
+
rmSync as rmSync6,
|
|
10864
|
+
rmdirSync,
|
|
10865
|
+
statSync as statSync15,
|
|
10866
|
+
writeFileSync as writeFileSync8
|
|
10867
|
+
} from "node:fs";
|
|
11759
10868
|
function layoutWarningForHook() {
|
|
11760
10869
|
const state = detectLayout();
|
|
11761
10870
|
if (state.kind === "current" || state.kind === "absent")
|
|
@@ -11763,6 +10872,8 @@ function layoutWarningForHook() {
|
|
|
11763
10872
|
if (state.kind === "future") {
|
|
11764
10873
|
return `[failproofai] this directory was written by a newer version ` + `(layout ${state.found} vs ${LAYOUT_VERSION}) — policies are NOT being enforced. ` + `Upgrade failproofai.`;
|
|
11765
10874
|
}
|
|
10875
|
+
if (existsSync18(globalPolicyConfigFile()))
|
|
10876
|
+
return null;
|
|
11766
10877
|
return `[failproofai] setup predates this version — global policies are NOT being enforced. ` + `Run \`failproofai config\` to re-create it.`;
|
|
11767
10878
|
}
|
|
11768
10879
|
var init_fp_reset = __esm(() => {
|
|
@@ -11875,7 +10986,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
11875
10986
|
let conventionHookNames = new Set;
|
|
11876
10987
|
let activePause = null;
|
|
11877
10988
|
const policyAttribution = new Map;
|
|
11878
|
-
let
|
|
10989
|
+
let cloudDeployment;
|
|
11879
10990
|
const observedResults = [];
|
|
11880
10991
|
if (opts?.forceDecision) {
|
|
11881
10992
|
config = { enabledPolicies: [] };
|
|
@@ -11898,7 +11009,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
11898
11009
|
cli
|
|
11899
11010
|
});
|
|
11900
11011
|
}
|
|
11901
|
-
|
|
11012
|
+
cloudDeployment = cloudManagedPolicies[0]?.deployment;
|
|
11902
11013
|
const configuredCustomPaths = config.customPoliciesPaths ?? config.customPoliciesPath;
|
|
11903
11014
|
const allExplicitPaths = cloudManagedPolicies.length === 0 ? configuredCustomPaths : [
|
|
11904
11015
|
...typeof configuredCustomPaths === "string" ? [configuredCustomPaths] : configuredCustomPaths ?? [],
|
|
@@ -11923,7 +11034,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
11923
11034
|
const hookName = hook.name;
|
|
11924
11035
|
const conventionScope = hook.__conventionScope;
|
|
11925
11036
|
const isConvention = !!conventionScope;
|
|
11926
|
-
const prefix = cloudManaged ? `cloud/${cloudManaged.id}@${cloudManaged.
|
|
11037
|
+
const prefix = cloudManaged ? `cloud/${cloudManaged.id}@${cloudManaged.version}` : isConvention ? `.failproofai-${conventionScope}` : "custom";
|
|
11927
11038
|
const observeOnly = cloudManaged?.effect === "observe";
|
|
11928
11039
|
const fn = async (ctx) => {
|
|
11929
11040
|
if (observeOnly) {
|
|
@@ -11931,7 +11042,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
11931
11042
|
if (shadow.decision !== "allow") {
|
|
11932
11043
|
observedResults.push({
|
|
11933
11044
|
policyId: cloudManaged.id,
|
|
11934
|
-
|
|
11045
|
+
version: cloudManaged.version,
|
|
11935
11046
|
decision: shadow.decision,
|
|
11936
11047
|
reason: shadow.reason ?? null
|
|
11937
11048
|
});
|
|
@@ -11962,7 +11073,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
11962
11073
|
const registeredName = `${prefix}/${hookName}`;
|
|
11963
11074
|
policyAttribution.set(registeredName, {
|
|
11964
11075
|
source: cloudManaged ? "cloud" : isConvention ? "convention" : "custom",
|
|
11965
|
-
...cloudManaged ? { cloudPolicyId: cloudManaged.id,
|
|
11076
|
+
...cloudManaged ? { cloudPolicyId: cloudManaged.id, cloudVersion: cloudManaged.version } : {}
|
|
11966
11077
|
});
|
|
11967
11078
|
registerPolicy(registeredName, hook.description ?? "", fn, hook.match ?? {}, -1);
|
|
11968
11079
|
}
|
|
@@ -12011,10 +11122,10 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
|
|
|
12011
11122
|
return {
|
|
12012
11123
|
policySource: attribution?.source ?? "builtin",
|
|
12013
11124
|
...attribution?.cloudPolicyId ? { cloudPolicyId: attribution.cloudPolicyId } : {},
|
|
12014
|
-
...attribution?.
|
|
11125
|
+
...attribution?.cloudVersion !== undefined ? { cloudVersion: attribution.cloudVersion } : {}
|
|
12015
11126
|
};
|
|
12016
11127
|
})() : {},
|
|
12017
|
-
...
|
|
11128
|
+
...cloudDeployment !== undefined ? { cloudDeployment } : {},
|
|
12018
11129
|
...observedResults.length > 0 ? { observed: observedResults } : {},
|
|
12019
11130
|
...activePause ? { pausedBy: activePause.setBy, pauseExpiresAt: activePause.expiresAt } : {}
|
|
12020
11131
|
};
|
|
@@ -12104,65 +11215,98 @@ var init_handler = __esm(() => {
|
|
|
12104
11215
|
// src/hooks/fp-reset.ts
|
|
12105
11216
|
var exports_fp_reset = {};
|
|
12106
11217
|
__export(exports_fp_reset, {
|
|
11218
|
+
writeCarriedPolicyConfig: () => writeCarriedPolicyConfig,
|
|
12107
11219
|
resetHome: () => resetHome,
|
|
11220
|
+
readCarriedTelemetryOptOut: () => readCarriedTelemetryOptOut,
|
|
11221
|
+
readCarriedPolicyConfig: () => readCarriedPolicyConfig,
|
|
12108
11222
|
migrateHookActivity: () => migrateHookActivity,
|
|
12109
11223
|
migrateConventionPolicies: () => migrateConventionPolicies,
|
|
12110
11224
|
layoutWarningForHook: () => layoutWarningForHook2,
|
|
11225
|
+
layoutBlockerForScheduledRun: () => layoutBlockerForScheduledRun,
|
|
12111
11226
|
checkLayoutForCli: () => checkLayoutForCli
|
|
12112
11227
|
});
|
|
12113
|
-
import {
|
|
12114
|
-
|
|
11228
|
+
import {
|
|
11229
|
+
copyFileSync as copyFileSync2,
|
|
11230
|
+
existsSync as existsSync19,
|
|
11231
|
+
mkdirSync as mkdirSync11,
|
|
11232
|
+
readFileSync as readFileSync16,
|
|
11233
|
+
readdirSync as readdirSync14,
|
|
11234
|
+
renameSync as renameSync6,
|
|
11235
|
+
rmSync as rmSync7,
|
|
11236
|
+
rmdirSync as rmdirSync2,
|
|
11237
|
+
statSync as statSync16,
|
|
11238
|
+
writeFileSync as writeFileSync9
|
|
11239
|
+
} from "node:fs";
|
|
11240
|
+
import { dirname as dirname9, resolve as resolve15 } from "node:path";
|
|
12115
11241
|
function migrateConventionPolicies() {
|
|
12116
|
-
const from =
|
|
12117
|
-
if (!
|
|
11242
|
+
const from = legacy.customPoliciesDir();
|
|
11243
|
+
if (!existsSync19(from))
|
|
12118
11244
|
return [];
|
|
12119
11245
|
const moved = [];
|
|
12120
|
-
|
|
12121
|
-
|
|
11246
|
+
const mergeInto = (dir, dest, prefix) => {
|
|
11247
|
+
let entries;
|
|
11248
|
+
try {
|
|
11249
|
+
entries = readdirSync14(dir, { withFileTypes: true });
|
|
11250
|
+
} catch {
|
|
11251
|
+
return;
|
|
11252
|
+
}
|
|
12122
11253
|
if (entries.length === 0)
|
|
12123
|
-
return
|
|
12124
|
-
|
|
12125
|
-
|
|
11254
|
+
return;
|
|
11255
|
+
try {
|
|
11256
|
+
mkdirSync11(dest, { recursive: true });
|
|
11257
|
+
} catch {
|
|
11258
|
+
return;
|
|
11259
|
+
}
|
|
12126
11260
|
for (const entry of entries) {
|
|
12127
|
-
const
|
|
12128
|
-
|
|
11261
|
+
const source = resolve15(dir, entry.name);
|
|
11262
|
+
const target = resolve15(dest, entry.name);
|
|
11263
|
+
const name = `${prefix}${entry.name}`;
|
|
11264
|
+
if (!existsSync19(target)) {
|
|
11265
|
+
try {
|
|
11266
|
+
renameSync6(source, target);
|
|
11267
|
+
moved.push(name);
|
|
11268
|
+
} catch {}
|
|
12129
11269
|
continue;
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
}
|
|
11270
|
+
}
|
|
11271
|
+
if (entry.isDirectory() && statSync16(target).isDirectory()) {
|
|
11272
|
+
mergeInto(source, target, `${name}/`);
|
|
11273
|
+
}
|
|
12134
11274
|
}
|
|
11275
|
+
};
|
|
11276
|
+
mergeInto(from, policiesDir(), "");
|
|
11277
|
+
try {
|
|
11278
|
+
rmdirSync2(from);
|
|
12135
11279
|
} catch {}
|
|
12136
11280
|
return moved.sort((a, b) => a.localeCompare(b));
|
|
12137
11281
|
}
|
|
12138
11282
|
function migrateHookActivity() {
|
|
12139
11283
|
const from = legacy.hookActivityDir();
|
|
12140
|
-
if (!
|
|
11284
|
+
if (!existsSync19(from))
|
|
12141
11285
|
return [];
|
|
12142
11286
|
const moved = [];
|
|
12143
11287
|
try {
|
|
12144
|
-
const entries =
|
|
11288
|
+
const entries = readdirSync14(from, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl"));
|
|
12145
11289
|
if (entries.length === 0)
|
|
12146
11290
|
return [];
|
|
12147
11291
|
const to = hookActivityDir();
|
|
12148
|
-
|
|
11292
|
+
mkdirSync11(to, { recursive: true });
|
|
12149
11293
|
const stamp2 = Date.now();
|
|
12150
11294
|
let seq = 0;
|
|
12151
11295
|
for (const entry of entries) {
|
|
12152
11296
|
const source = resolve15(from, entry.name);
|
|
12153
11297
|
let name = entry.name === "current.jsonl" ? `page-${stamp2}-${seq++}.jsonl` : entry.name;
|
|
12154
11298
|
let target = resolve15(to, name);
|
|
12155
|
-
while (
|
|
11299
|
+
while (existsSync19(target)) {
|
|
12156
11300
|
name = `page-${stamp2}-${seq++}.jsonl`;
|
|
12157
11301
|
target = resolve15(to, name);
|
|
12158
11302
|
}
|
|
12159
11303
|
try {
|
|
12160
|
-
|
|
11304
|
+
renameSync6(source, target);
|
|
12161
11305
|
moved.push(name);
|
|
12162
11306
|
} catch (err) {
|
|
12163
11307
|
if (err?.code === "EXDEV") {
|
|
12164
11308
|
try {
|
|
12165
|
-
|
|
11309
|
+
copyFileSync2(source, target);
|
|
12166
11310
|
moved.push(name);
|
|
12167
11311
|
} catch {}
|
|
12168
11312
|
}
|
|
@@ -12171,20 +11315,85 @@ function migrateHookActivity() {
|
|
|
12171
11315
|
} catch {}
|
|
12172
11316
|
return moved.sort((a, b) => a.localeCompare(b));
|
|
12173
11317
|
}
|
|
11318
|
+
function readCarriedPolicyConfig() {
|
|
11319
|
+
const to = globalPolicyConfigFile();
|
|
11320
|
+
const layoutTwo = resolve15(legacy.localPoliciesDir(), "policies-config.json");
|
|
11321
|
+
const from = existsSync19(layoutTwo) ? layoutTwo : legacy.policyConfig();
|
|
11322
|
+
if (!existsSync19(from))
|
|
11323
|
+
return null;
|
|
11324
|
+
let parsed;
|
|
11325
|
+
try {
|
|
11326
|
+
parsed = JSON.parse(readFileSync16(from, "utf8"));
|
|
11327
|
+
} catch {
|
|
11328
|
+
return null;
|
|
11329
|
+
}
|
|
11330
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
11331
|
+
return null;
|
|
11332
|
+
const carried = {};
|
|
11333
|
+
let found = false;
|
|
11334
|
+
for (const key of CARRIED_POLICY_CONFIG_KEYS) {
|
|
11335
|
+
if (parsed[key] !== undefined) {
|
|
11336
|
+
carried[key] = parsed[key];
|
|
11337
|
+
found = true;
|
|
11338
|
+
}
|
|
11339
|
+
}
|
|
11340
|
+
if (!found)
|
|
11341
|
+
return null;
|
|
11342
|
+
if (carried.enabledPolicies === undefined)
|
|
11343
|
+
carried.enabledPolicies = [];
|
|
11344
|
+
return carried;
|
|
11345
|
+
}
|
|
11346
|
+
function writeCarriedPolicyConfig(carried) {
|
|
11347
|
+
if (!carried)
|
|
11348
|
+
return [];
|
|
11349
|
+
const to = globalPolicyConfigFile();
|
|
11350
|
+
try {
|
|
11351
|
+
mkdirSync11(dirname9(to), { recursive: true });
|
|
11352
|
+
writeFileSync9(to, JSON.stringify(carried, null, 2) + `
|
|
11353
|
+
`, "utf8");
|
|
11354
|
+
} catch {
|
|
11355
|
+
return [];
|
|
11356
|
+
}
|
|
11357
|
+
return Object.keys(carried).sort((a, b) => a.localeCompare(b));
|
|
11358
|
+
}
|
|
11359
|
+
function readCarriedTelemetryOptOut() {
|
|
11360
|
+
const from = legacy.configToml();
|
|
11361
|
+
if (!existsSync19(from))
|
|
11362
|
+
return false;
|
|
11363
|
+
try {
|
|
11364
|
+
const text = readFileSync16(from, "utf8");
|
|
11365
|
+
const start = text.search(/^\s*\[telemetry\]\s*$/m);
|
|
11366
|
+
if (start === -1)
|
|
11367
|
+
return false;
|
|
11368
|
+
const body = text.slice(start).replace(/^\s*\[telemetry\]\s*$/m, "");
|
|
11369
|
+
const nextTable = body.search(/^\s*\[/m);
|
|
11370
|
+
const section = nextTable === -1 ? body : body.slice(0, nextTable);
|
|
11371
|
+
return /^\s*enabled\s*=\s*false\s*$/m.test(section);
|
|
11372
|
+
} catch {
|
|
11373
|
+
return false;
|
|
11374
|
+
}
|
|
11375
|
+
}
|
|
12174
11376
|
function resetHome(from) {
|
|
12175
11377
|
const migrated = migrateConventionPolicies();
|
|
12176
11378
|
const activity = migrateHookActivity();
|
|
11379
|
+
const pendingPolicyConfig = readCarriedPolicyConfig();
|
|
11380
|
+
const telemetryOptOut = readCarriedTelemetryOptOut();
|
|
12177
11381
|
const removed = [];
|
|
12178
11382
|
for (const path3 of resettablePaths()) {
|
|
12179
|
-
if (
|
|
11383
|
+
if (from === LAYOUT_VERSION && path3 === globalPolicyConfigFile())
|
|
11384
|
+
continue;
|
|
11385
|
+
if (!existsSync19(path3))
|
|
12180
11386
|
continue;
|
|
12181
11387
|
try {
|
|
12182
|
-
|
|
11388
|
+
rmSync7(path3, { recursive: true, force: true });
|
|
12183
11389
|
removed.push(path3);
|
|
12184
11390
|
} catch {}
|
|
12185
11391
|
}
|
|
11392
|
+
const policyConfig = writeCarriedPolicyConfig(pendingPolicyConfig);
|
|
11393
|
+
if (telemetryOptOut)
|
|
11394
|
+
updateConfig({ telemetry: { enabled: false } });
|
|
12186
11395
|
writeVersionFile();
|
|
12187
|
-
return { removed, migrated, activity, from };
|
|
11396
|
+
return { removed, migrated, activity, policyConfig, from };
|
|
12188
11397
|
}
|
|
12189
11398
|
async function checkLayoutForCli() {
|
|
12190
11399
|
const state = detectLayout();
|
|
@@ -12227,7 +11436,7 @@ async function checkLayoutForCli() {
|
|
|
12227
11436
|
]
|
|
12228
11437
|
};
|
|
12229
11438
|
}
|
|
12230
|
-
if (state.kind === "absent")
|
|
11439
|
+
if (state.kind === "absent" || state.kind === "current" && state.inferred)
|
|
12231
11440
|
writeVersionFile();
|
|
12232
11441
|
return {
|
|
12233
11442
|
state,
|
|
@@ -12296,6 +11505,15 @@ function staleDaemonHint() {
|
|
|
12296
11505
|
return [];
|
|
12297
11506
|
}
|
|
12298
11507
|
}
|
|
11508
|
+
function layoutBlockerForScheduledRun() {
|
|
11509
|
+
const state = detectLayout();
|
|
11510
|
+
if (state.kind === "current" || state.kind === "absent")
|
|
11511
|
+
return null;
|
|
11512
|
+
if (state.kind === "future") {
|
|
11513
|
+
return `[failproofai] this directory was written by a newer version ` + `(layout ${state.found} vs ${LAYOUT_VERSION}) — refusing to run unattended. ` + `Upgrade failproofai.`;
|
|
11514
|
+
}
|
|
11515
|
+
return `[failproofai] setup predates this version (layout ${state.found} vs ${LAYOUT_VERSION}) — ` + `refusing to run unattended, because completing it would reset this home. ` + `Run \`failproofai config\`.`;
|
|
11516
|
+
}
|
|
12299
11517
|
function layoutWarningForHook2() {
|
|
12300
11518
|
const state = detectLayout();
|
|
12301
11519
|
if (state.kind === "current" || state.kind === "absent")
|
|
@@ -12303,20 +11521,31 @@ function layoutWarningForHook2() {
|
|
|
12303
11521
|
if (state.kind === "future") {
|
|
12304
11522
|
return `[failproofai] this directory was written by a newer version ` + `(layout ${state.found} vs ${LAYOUT_VERSION}) — policies are NOT being enforced. ` + `Upgrade failproofai.`;
|
|
12305
11523
|
}
|
|
11524
|
+
if (existsSync19(globalPolicyConfigFile()))
|
|
11525
|
+
return null;
|
|
12306
11526
|
return `[failproofai] setup predates this version — global policies are NOT being enforced. ` + `Run \`failproofai config\` to re-create it.`;
|
|
12307
11527
|
}
|
|
12308
|
-
var
|
|
11528
|
+
var CARRIED_POLICY_CONFIG_KEYS;
|
|
12309
11529
|
var init_fp_reset2 = __esm(() => {
|
|
12310
11530
|
init_fp_home();
|
|
12311
11531
|
init_fp_config();
|
|
12312
11532
|
init_daemon_service();
|
|
12313
|
-
|
|
11533
|
+
CARRIED_POLICY_CONFIG_KEYS = [
|
|
11534
|
+
"enabledPolicies",
|
|
11535
|
+
"customPoliciesPaths",
|
|
11536
|
+
"customPoliciesPath",
|
|
11537
|
+
"disabledCustomPolicies",
|
|
11538
|
+
"conventionPolicies",
|
|
11539
|
+
"disabledConventionPolicies",
|
|
11540
|
+
"policyParams",
|
|
11541
|
+
"llm"
|
|
11542
|
+
];
|
|
12314
11543
|
});
|
|
12315
11544
|
|
|
12316
11545
|
// scripts/install-telemetry.mjs
|
|
12317
11546
|
import { createHmac, randomUUID as randomUUID2 } from "node:crypto";
|
|
12318
11547
|
import { execSync as execSync4 } from "node:child_process";
|
|
12319
|
-
import { readFileSync as
|
|
11548
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync10, mkdirSync as mkdirSync12 } from "node:fs";
|
|
12320
11549
|
import { homedir as homedir20, platform, arch, hostname, cpus } from "node:os";
|
|
12321
11550
|
import { join as join27 } from "node:path";
|
|
12322
11551
|
function hashToId3(raw) {
|
|
@@ -12326,7 +11555,7 @@ function getInstanceId3() {
|
|
|
12326
11555
|
const idDir = join27(homedir20(), ".failproofai");
|
|
12327
11556
|
const idFile = join27(idDir, "instance-id");
|
|
12328
11557
|
try {
|
|
12329
|
-
const existing =
|
|
11558
|
+
const existing = readFileSync17(idFile, "utf-8").trim();
|
|
12330
11559
|
if (existing)
|
|
12331
11560
|
return existing;
|
|
12332
11561
|
} catch {}
|
|
@@ -12335,7 +11564,7 @@ function getInstanceId3() {
|
|
|
12335
11564
|
if (p === "linux") {
|
|
12336
11565
|
for (const machineIdPath of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
12337
11566
|
try {
|
|
12338
|
-
const id2 =
|
|
11567
|
+
const id2 = readFileSync17(machineIdPath, "utf-8").trim();
|
|
12339
11568
|
if (id2)
|
|
12340
11569
|
return hashToId3(id2);
|
|
12341
11570
|
} catch {}
|
|
@@ -12367,8 +11596,8 @@ function getInstanceId3() {
|
|
|
12367
11596
|
} catch {}
|
|
12368
11597
|
const id = randomUUID2();
|
|
12369
11598
|
try {
|
|
12370
|
-
|
|
12371
|
-
|
|
11599
|
+
mkdirSync12(idDir, { recursive: true });
|
|
11600
|
+
writeFileSync10(idFile, id, "utf-8");
|
|
12372
11601
|
} catch {}
|
|
12373
11602
|
return id;
|
|
12374
11603
|
}
|
|
@@ -12406,8 +11635,8 @@ __export(exports_install_check, {
|
|
|
12406
11635
|
compareSemver: () => compareSemver,
|
|
12407
11636
|
checkHooks: () => checkHooks
|
|
12408
11637
|
});
|
|
12409
|
-
import { existsSync as
|
|
12410
|
-
import { dirname as
|
|
11638
|
+
import { existsSync as existsSync20, readFileSync as readFileSync18, writeFileSync as writeFileSync11, mkdirSync as mkdirSync13 } from "node:fs";
|
|
11639
|
+
import { dirname as dirname10, resolve as resolve16 } from "node:path";
|
|
12411
11640
|
import { platform as platform2, arch as arch2, release, homedir as homedir21, hostname as hostname2 } from "node:os";
|
|
12412
11641
|
import { createHmac as createHmac2 } from "node:crypto";
|
|
12413
11642
|
function hashToId4(raw) {
|
|
@@ -12417,14 +11646,14 @@ function lastVersionPath() {
|
|
|
12417
11646
|
return lastVersionFile();
|
|
12418
11647
|
}
|
|
12419
11648
|
function compareSemver(a, b) {
|
|
12420
|
-
const
|
|
11649
|
+
const parse = (v) => {
|
|
12421
11650
|
const m = /^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/.exec(v);
|
|
12422
11651
|
if (!m)
|
|
12423
11652
|
return null;
|
|
12424
11653
|
return { nums: [Number(m[1]), Number(m[2]), Number(m[3])], pre: m[4] ?? null };
|
|
12425
11654
|
};
|
|
12426
|
-
const pa =
|
|
12427
|
-
const pb =
|
|
11655
|
+
const pa = parse(a);
|
|
11656
|
+
const pb = parse(b);
|
|
12428
11657
|
if (!pa || !pb)
|
|
12429
11658
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
12430
11659
|
for (let i = 0;i < 3; i++) {
|
|
@@ -12462,12 +11691,12 @@ function compareSemver(a, b) {
|
|
|
12462
11691
|
}
|
|
12463
11692
|
function checkHooks() {
|
|
12464
11693
|
const hooksConfigPath = globalPolicyConfigFile();
|
|
12465
|
-
if (!
|
|
11694
|
+
if (!existsSync20(hooksConfigPath)) {
|
|
12466
11695
|
return { configured: false, registered: false, policyCount: 0 };
|
|
12467
11696
|
}
|
|
12468
11697
|
let config;
|
|
12469
11698
|
try {
|
|
12470
|
-
config = JSON.parse(
|
|
11699
|
+
config = JSON.parse(readFileSync18(hooksConfigPath, "utf8"));
|
|
12471
11700
|
} catch {
|
|
12472
11701
|
return { configured: false, registered: false, policyCount: 0 };
|
|
12473
11702
|
}
|
|
@@ -12476,11 +11705,11 @@ function checkHooks() {
|
|
|
12476
11705
|
}
|
|
12477
11706
|
const policyCount = config.enabledPolicies.length;
|
|
12478
11707
|
const settingsPath = resolve16(homedir21(), ".claude", "settings.json");
|
|
12479
|
-
if (!
|
|
11708
|
+
if (!existsSync20(settingsPath))
|
|
12480
11709
|
return { configured: true, registered: false, policyCount };
|
|
12481
11710
|
let settings;
|
|
12482
11711
|
try {
|
|
12483
|
-
settings = JSON.parse(
|
|
11712
|
+
settings = JSON.parse(readFileSync18(settingsPath, "utf8"));
|
|
12484
11713
|
} catch {
|
|
12485
11714
|
return { configured: true, registered: false, policyCount };
|
|
12486
11715
|
}
|
|
@@ -12504,8 +11733,8 @@ async function maybeReportInstall(version3) {
|
|
|
12504
11733
|
const versionFile2 = lastVersionPath();
|
|
12505
11734
|
let previousVersion = null;
|
|
12506
11735
|
try {
|
|
12507
|
-
if (
|
|
12508
|
-
previousVersion =
|
|
11736
|
+
if (existsSync20(versionFile2)) {
|
|
11737
|
+
previousVersion = readFileSync18(versionFile2, "utf8").trim() || null;
|
|
12509
11738
|
}
|
|
12510
11739
|
} catch {}
|
|
12511
11740
|
if (previousVersion === version3)
|
|
@@ -12541,8 +11770,8 @@ async function maybeReportInstall(version3) {
|
|
|
12541
11770
|
enabled_policy_count: hooks.policyCount
|
|
12542
11771
|
}, { version: version3, timeoutMs: REPORT_TIMEOUT_MS, enabled: telemetryEnabled }));
|
|
12543
11772
|
try {
|
|
12544
|
-
|
|
12545
|
-
|
|
11773
|
+
mkdirSync13(dirname10(versionFile2), { recursive: true });
|
|
11774
|
+
writeFileSync11(versionFile2, version3, "utf8");
|
|
12546
11775
|
} catch {}
|
|
12547
11776
|
await Promise.all(events.map((p) => p.catch(() => {})));
|
|
12548
11777
|
} catch {}
|
|
@@ -12805,10 +12034,11 @@ function runPrompt(p) {
|
|
|
12805
12034
|
return lines;
|
|
12806
12035
|
};
|
|
12807
12036
|
const collapse = (result) => {
|
|
12037
|
+
const summary = result === BACK ? "back" : p.summaryFor(result);
|
|
12808
12038
|
repaint(stdout, region, [
|
|
12809
12039
|
c.dim(BAR),
|
|
12810
12040
|
`${c.dim(STEP_DONE)} ${p.message}`,
|
|
12811
|
-
`${c.dim(BAR)} ${c.dim(
|
|
12041
|
+
`${c.dim(BAR)} ${c.dim(summary)}`
|
|
12812
12042
|
]);
|
|
12813
12043
|
};
|
|
12814
12044
|
return new Promise((resolve17) => {
|
|
@@ -12834,6 +12064,8 @@ function runPrompt(p) {
|
|
|
12834
12064
|
return;
|
|
12835
12065
|
if (key.ctrl && (key.name === "c" || key.name === "d") || key.name === "escape") {
|
|
12836
12066
|
finish(null);
|
|
12067
|
+
} else if (key.name === "left" && p.allowBack) {
|
|
12068
|
+
finish(BACK);
|
|
12837
12069
|
} else if (key.name === "up") {
|
|
12838
12070
|
cursor = cursor > 0 ? cursor - 1 : choices.length - 1;
|
|
12839
12071
|
repaint(stdout, region, build());
|
|
@@ -12877,7 +12109,8 @@ function selectOne(opts) {
|
|
|
12877
12109
|
const hint = choice.hint ? ` ${c.dim(ellipsize(choice.hint, budget))}` : "";
|
|
12878
12110
|
return `${dot} ${label}${hint}`;
|
|
12879
12111
|
},
|
|
12880
|
-
|
|
12112
|
+
allowBack: opts.allowBack,
|
|
12113
|
+
footer: opts.allowBack ? "↑/↓ navigate · enter to select · ← back · esc to cancel" : "↑/↓ navigate · enter to select · esc to cancel",
|
|
12881
12114
|
onKey: (key, cursor) => key.name === "return" ? { done: choices[cursor].value } : undefined,
|
|
12882
12115
|
summaryFor: (value) => value === null ? "cancelled" : choices.find((ch) => ch.value === value)?.label ?? String(value)
|
|
12883
12116
|
});
|
|
@@ -12911,7 +12144,8 @@ function multiSelect(opts) {
|
|
|
12911
12144
|
return `${caret} ${box} ${label}${hint}`;
|
|
12912
12145
|
},
|
|
12913
12146
|
warnLine: () => warn ? c.warn(`Select at least ${minSelected}.`) : null,
|
|
12914
|
-
|
|
12147
|
+
allowBack: opts.allowBack,
|
|
12148
|
+
footer: opts.hint ?? (opts.allowBack ? "↑/↓ move · space select · ctrl+a all · ← back · enter confirm" : "↑/↓ move · space select · ctrl+a all · enter confirm"),
|
|
12915
12149
|
onKey: (key, cursor) => {
|
|
12916
12150
|
if (key.name === "space") {
|
|
12917
12151
|
if (choices[cursor]?.locked)
|
|
@@ -12973,11 +12207,13 @@ function promptText(opts) {
|
|
|
12973
12207
|
return new Promise((resolve17) => {
|
|
12974
12208
|
let value = "";
|
|
12975
12209
|
const draw = (error) => {
|
|
12210
|
+
const cols = stdout.columns || 80;
|
|
12976
12211
|
const shown = opts.mask ? "•".repeat(value.length) : value;
|
|
12977
12212
|
const hint = opts.hint ? ` ${c.dim(opts.hint)}` : "";
|
|
12213
|
+
const line = truncate(`${c.bold(opts.message)} ${shown}${hint}`, cols - 1);
|
|
12978
12214
|
const err = error ? `
|
|
12979
|
-
${c.warn(error)}` : "";
|
|
12980
|
-
stdout.write(`\r\x1B[2K${
|
|
12215
|
+
${truncate(c.warn(error), cols - 3)}` : "";
|
|
12216
|
+
stdout.write(`\r\x1B[2K${line}${err}`);
|
|
12981
12217
|
if (err)
|
|
12982
12218
|
stdout.write("\x1B[1A");
|
|
12983
12219
|
};
|
|
@@ -13024,7 +12260,7 @@ function promptText(opts) {
|
|
|
13024
12260
|
stdin.on("keypress", onKey);
|
|
13025
12261
|
});
|
|
13026
12262
|
}
|
|
13027
|
-
var ESC = "\x1B", BAR = "│", BAR_END = "└", STEP_ACTIVE = "◆", STEP_DONE = "◇", RADIO_ON = "●", RADIO_OFF = "○", CHECK_ON = "◼", CHECK_OFF = "◻", CARET = "❯", FLOWER = "❋", HUES, ANSI_RESET, ANSI_BOLD, ANSI_DIM, LOGO_MIN_COLS = 22, TAGLINE = "end-to-end failure layer for ai agents", LOGO_GRID, LOGO_TEAL, LOGO_PINK, WINDOW = 8;
|
|
12263
|
+
var ESC = "\x1B", BAR = "│", BAR_END = "└", STEP_ACTIVE = "◆", STEP_DONE = "◇", RADIO_ON = "●", RADIO_OFF = "○", CHECK_ON = "◼", CHECK_OFF = "◻", CARET = "❯", FLOWER = "❋", HUES, ANSI_RESET, ANSI_BOLD, ANSI_DIM, LOGO_MIN_COLS = 22, TAGLINE = "end-to-end failure layer for ai agents", LOGO_GRID, LOGO_TEAL, LOGO_PINK, WINDOW = 8, BACK;
|
|
13028
12264
|
var init_tui = __esm(() => {
|
|
13029
12265
|
HUES = {
|
|
13030
12266
|
guide: { rgb: [102, 209, 181], basic: "36" },
|
|
@@ -13060,6 +12296,7 @@ var init_tui = __esm(() => {
|
|
|
13060
12296
|
];
|
|
13061
12297
|
LOGO_TEAL = HUES.guide.rgb;
|
|
13062
12298
|
LOGO_PINK = HUES.logoPink.rgb;
|
|
12299
|
+
BACK = Symbol("failproofai.back");
|
|
13063
12300
|
});
|
|
13064
12301
|
|
|
13065
12302
|
// src/hooks/collector-config.ts
|
|
@@ -14556,7 +13793,7 @@ var require_stringify = __commonJS((exports) => {
|
|
|
14556
13793
|
props.push(doc.directives.tagString(tag));
|
|
14557
13794
|
return props.join(" ");
|
|
14558
13795
|
}
|
|
14559
|
-
function
|
|
13796
|
+
function stringify(item, ctx, onComment, onChompKeep) {
|
|
14560
13797
|
if (identity.isPair(item))
|
|
14561
13798
|
return item.toString(ctx, onComment, onChompKeep);
|
|
14562
13799
|
if (identity.isAlias(item)) {
|
|
@@ -14585,14 +13822,14 @@ var require_stringify = __commonJS((exports) => {
|
|
|
14585
13822
|
${ctx.indent}${str2}`;
|
|
14586
13823
|
}
|
|
14587
13824
|
exports.createStringifyContext = createStringifyContext;
|
|
14588
|
-
exports.stringify =
|
|
13825
|
+
exports.stringify = stringify;
|
|
14589
13826
|
});
|
|
14590
13827
|
|
|
14591
13828
|
// node_modules/yaml/dist/stringify/stringifyPair.js
|
|
14592
13829
|
var require_stringifyPair = __commonJS((exports) => {
|
|
14593
13830
|
var identity = require_identity();
|
|
14594
13831
|
var Scalar = require_Scalar();
|
|
14595
|
-
var
|
|
13832
|
+
var stringify = require_stringify();
|
|
14596
13833
|
var stringifyComment = require_stringifyComment();
|
|
14597
13834
|
function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
|
|
14598
13835
|
const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
|
|
@@ -14614,7 +13851,7 @@ var require_stringifyPair = __commonJS((exports) => {
|
|
|
14614
13851
|
});
|
|
14615
13852
|
let keyCommentDone = false;
|
|
14616
13853
|
let chompKeep = false;
|
|
14617
|
-
let str2 =
|
|
13854
|
+
let str2 = stringify.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
|
|
14618
13855
|
if (!explicitKey && !ctx.inFlow && str2.length > 1024) {
|
|
14619
13856
|
if (simpleKeys)
|
|
14620
13857
|
throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
|
|
@@ -14666,7 +13903,7 @@ ${indent}:`;
|
|
|
14666
13903
|
ctx.indent = ctx.indent.substring(2);
|
|
14667
13904
|
}
|
|
14668
13905
|
let valueCommentDone = false;
|
|
14669
|
-
const valueStr =
|
|
13906
|
+
const valueStr = stringify.stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true);
|
|
14670
13907
|
let ws = " ";
|
|
14671
13908
|
if (keyComment || vsb || vcb) {
|
|
14672
13909
|
ws = vsb ? `
|
|
@@ -14804,7 +14041,7 @@ var require_merge = __commonJS((exports) => {
|
|
|
14804
14041
|
var require_addPairToJSMap = __commonJS((exports) => {
|
|
14805
14042
|
var log = require_log();
|
|
14806
14043
|
var merge = require_merge();
|
|
14807
|
-
var
|
|
14044
|
+
var stringify = require_stringify();
|
|
14808
14045
|
var identity = require_identity();
|
|
14809
14046
|
var toJS = require_toJS();
|
|
14810
14047
|
function addPairToJSMap(ctx, map, { key, value }) {
|
|
@@ -14840,7 +14077,7 @@ var require_addPairToJSMap = __commonJS((exports) => {
|
|
|
14840
14077
|
if (typeof jsKey !== "object")
|
|
14841
14078
|
return String(jsKey);
|
|
14842
14079
|
if (identity.isNode(key) && ctx?.doc) {
|
|
14843
|
-
const strCtx =
|
|
14080
|
+
const strCtx = stringify.createStringifyContext(ctx.doc, {});
|
|
14844
14081
|
strCtx.anchors = new Set;
|
|
14845
14082
|
for (const node of ctx.anchors.keys())
|
|
14846
14083
|
strCtx.anchors.add(node.anchor);
|
|
@@ -14902,12 +14139,12 @@ var require_Pair = __commonJS((exports) => {
|
|
|
14902
14139
|
// node_modules/yaml/dist/stringify/stringifyCollection.js
|
|
14903
14140
|
var require_stringifyCollection = __commonJS((exports) => {
|
|
14904
14141
|
var identity = require_identity();
|
|
14905
|
-
var
|
|
14142
|
+
var stringify = require_stringify();
|
|
14906
14143
|
var stringifyComment = require_stringifyComment();
|
|
14907
14144
|
function stringifyCollection(collection, ctx, options) {
|
|
14908
14145
|
const flow = ctx.inFlow ?? collection.flow;
|
|
14909
|
-
const
|
|
14910
|
-
return
|
|
14146
|
+
const stringify2 = flow ? stringifyFlowCollection : stringifyBlockCollection;
|
|
14147
|
+
return stringify2(collection, ctx, options);
|
|
14911
14148
|
}
|
|
14912
14149
|
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
|
|
14913
14150
|
const { indent, options: { commentString } } = ctx;
|
|
@@ -14932,7 +14169,7 @@ var require_stringifyCollection = __commonJS((exports) => {
|
|
|
14932
14169
|
}
|
|
14933
14170
|
}
|
|
14934
14171
|
chompKeep = false;
|
|
14935
|
-
let str3 =
|
|
14172
|
+
let str3 = stringify.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
|
|
14936
14173
|
if (comment2)
|
|
14937
14174
|
str3 += stringifyComment.lineComment(str3, itemIndent, commentString(comment2));
|
|
14938
14175
|
if (chompKeep && comment2)
|
|
@@ -15001,7 +14238,7 @@ ${indent}${line}` : `
|
|
|
15001
14238
|
}
|
|
15002
14239
|
if (comment)
|
|
15003
14240
|
reqNewline = true;
|
|
15004
|
-
let str2 =
|
|
14241
|
+
let str2 = stringify.stringify(item, itemCtx, () => comment = null);
|
|
15005
14242
|
reqNewline || (reqNewline = lines.length > linesAtValue || str2.includes(`
|
|
15006
14243
|
`));
|
|
15007
14244
|
if (i < items.length - 1) {
|
|
@@ -16242,7 +15479,7 @@ var require_Schema = __commonJS((exports) => {
|
|
|
16242
15479
|
// node_modules/yaml/dist/stringify/stringifyDocument.js
|
|
16243
15480
|
var require_stringifyDocument = __commonJS((exports) => {
|
|
16244
15481
|
var identity = require_identity();
|
|
16245
|
-
var
|
|
15482
|
+
var stringify = require_stringify();
|
|
16246
15483
|
var stringifyComment = require_stringifyComment();
|
|
16247
15484
|
function stringifyDocument(doc, options) {
|
|
16248
15485
|
const lines = [];
|
|
@@ -16257,7 +15494,7 @@ var require_stringifyDocument = __commonJS((exports) => {
|
|
|
16257
15494
|
}
|
|
16258
15495
|
if (hasDirectives)
|
|
16259
15496
|
lines.push("---");
|
|
16260
|
-
const ctx =
|
|
15497
|
+
const ctx = stringify.createStringifyContext(doc, options);
|
|
16261
15498
|
const { commentString } = ctx.options;
|
|
16262
15499
|
if (doc.commentBefore) {
|
|
16263
15500
|
if (lines.length !== 1)
|
|
@@ -16279,7 +15516,7 @@ var require_stringifyDocument = __commonJS((exports) => {
|
|
|
16279
15516
|
contentComment = doc.contents.comment;
|
|
16280
15517
|
}
|
|
16281
15518
|
const onChompKeep = contentComment ? undefined : () => chompKeep = true;
|
|
16282
|
-
let body =
|
|
15519
|
+
let body = stringify.stringify(doc.contents, ctx, () => contentComment = null, onChompKeep);
|
|
16283
15520
|
if (contentComment)
|
|
16284
15521
|
body += stringifyComment.lineComment(body, "", commentString(contentComment));
|
|
16285
15522
|
if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") {
|
|
@@ -16287,7 +15524,7 @@ var require_stringifyDocument = __commonJS((exports) => {
|
|
|
16287
15524
|
} else
|
|
16288
15525
|
lines.push(body);
|
|
16289
15526
|
} else {
|
|
16290
|
-
lines.push(
|
|
15527
|
+
lines.push(stringify.stringify(doc.contents, ctx));
|
|
16291
15528
|
}
|
|
16292
15529
|
if (doc.directives?.docEnd) {
|
|
16293
15530
|
if (doc.comment) {
|
|
@@ -18306,7 +17543,7 @@ var require_cst_scalar = __commonJS((exports) => {
|
|
|
18306
17543
|
|
|
18307
17544
|
// node_modules/yaml/dist/parse/cst-stringify.js
|
|
18308
17545
|
var require_cst_stringify = __commonJS((exports) => {
|
|
18309
|
-
var
|
|
17546
|
+
var stringify = (cst) => ("type" in cst) ? stringifyToken(cst) : stringifyItem(cst);
|
|
18310
17547
|
function stringifyToken(token) {
|
|
18311
17548
|
switch (token.type) {
|
|
18312
17549
|
case "block-scalar": {
|
|
@@ -18359,7 +17596,7 @@ var require_cst_stringify = __commonJS((exports) => {
|
|
|
18359
17596
|
res += stringifyToken(value);
|
|
18360
17597
|
return res;
|
|
18361
17598
|
}
|
|
18362
|
-
exports.stringify =
|
|
17599
|
+
exports.stringify = stringify;
|
|
18363
17600
|
});
|
|
18364
17601
|
|
|
18365
17602
|
// node_modules/yaml/dist/parse/cst-visit.js
|
|
@@ -20050,7 +19287,7 @@ var require_public_api = __commonJS((exports) => {
|
|
|
20050
19287
|
}
|
|
20051
19288
|
return doc;
|
|
20052
19289
|
}
|
|
20053
|
-
function
|
|
19290
|
+
function parse(src, reviver, options) {
|
|
20054
19291
|
let _reviver = undefined;
|
|
20055
19292
|
if (typeof reviver === "function") {
|
|
20056
19293
|
_reviver = reviver;
|
|
@@ -20069,7 +19306,7 @@ var require_public_api = __commonJS((exports) => {
|
|
|
20069
19306
|
}
|
|
20070
19307
|
return doc.toJS(Object.assign({ reviver: _reviver }, options));
|
|
20071
19308
|
}
|
|
20072
|
-
function
|
|
19309
|
+
function stringify(value, replacer, options) {
|
|
20073
19310
|
let _replacer = null;
|
|
20074
19311
|
if (typeof replacer === "function" || Array.isArray(replacer)) {
|
|
20075
19312
|
_replacer = replacer;
|
|
@@ -20091,15 +19328,15 @@ var require_public_api = __commonJS((exports) => {
|
|
|
20091
19328
|
return value.toString(options);
|
|
20092
19329
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
20093
19330
|
}
|
|
20094
|
-
exports.parse =
|
|
19331
|
+
exports.parse = parse;
|
|
20095
19332
|
exports.parseAllDocuments = parseAllDocuments;
|
|
20096
19333
|
exports.parseDocument = parseDocument;
|
|
20097
|
-
exports.stringify =
|
|
19334
|
+
exports.stringify = stringify;
|
|
20098
19335
|
});
|
|
20099
19336
|
|
|
20100
19337
|
// node_modules/yaml/dist/index.js
|
|
20101
19338
|
var composer, Document, Schema, errors, Alias, identity, Pair, Scalar, YAMLMap, YAMLSeq, cst, lexer, lineCounter, parser, publicApi, visit, $Composer, $Document, $Schema, $YAMLError, $YAMLParseError, $YAMLWarning, $Alias, $isAlias, $isCollection, $isDocument, $isMap, $isNode, $isPair, $isScalar, $isSeq, $Pair, $Scalar, $YAMLMap, $YAMLSeq, $Lexer, $LineCounter, $Parser, $parse, $parseAllDocuments, $parseDocument, $stringify, $visit, $visitAsync;
|
|
20102
|
-
var
|
|
19339
|
+
var init_dist = __esm(() => {
|
|
20103
19340
|
composer = require_composer();
|
|
20104
19341
|
Document = require_Document();
|
|
20105
19342
|
Schema = require_Schema();
|
|
@@ -20148,31 +19385,31 @@ var init_dist2 = __esm(() => {
|
|
|
20148
19385
|
|
|
20149
19386
|
// src/hooks/integrations.ts
|
|
20150
19387
|
import { execSync as execSync5 } from "node:child_process";
|
|
20151
|
-
import { readFileSync as
|
|
20152
|
-
import { resolve as resolve17, dirname as
|
|
19388
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync12, existsSync as existsSync21, mkdirSync as mkdirSync14, unlinkSync as unlinkSync3 } from "node:fs";
|
|
19389
|
+
import { resolve as resolve17, dirname as dirname11 } from "node:path";
|
|
20153
19390
|
import { fileURLToPath } from "node:url";
|
|
20154
19391
|
import { homedir as homedir22 } from "node:os";
|
|
20155
19392
|
function readJsonFile(path3) {
|
|
20156
|
-
if (!
|
|
19393
|
+
if (!existsSync21(path3))
|
|
20157
19394
|
return {};
|
|
20158
|
-
const raw =
|
|
19395
|
+
const raw = readFileSync19(path3, "utf8");
|
|
20159
19396
|
return JSON.parse(raw);
|
|
20160
19397
|
}
|
|
20161
19398
|
function writeJsonFile(path3, data) {
|
|
20162
|
-
|
|
20163
|
-
|
|
19399
|
+
mkdirSync14(dirname11(path3), { recursive: true });
|
|
19400
|
+
writeFileSync12(path3, JSON.stringify(data, null, 2) + `
|
|
20164
19401
|
`, "utf8");
|
|
20165
19402
|
}
|
|
20166
19403
|
function readYamlDoc(path3) {
|
|
20167
19404
|
try {
|
|
20168
|
-
return
|
|
19405
|
+
return existsSync21(path3) ? $parseDocument(readFileSync19(path3, "utf8")) : $parseDocument("");
|
|
20169
19406
|
} catch {
|
|
20170
19407
|
return $parseDocument("");
|
|
20171
19408
|
}
|
|
20172
19409
|
}
|
|
20173
19410
|
function writeYamlDoc(path3, doc) {
|
|
20174
|
-
|
|
20175
|
-
|
|
19411
|
+
mkdirSync14(dirname11(path3), { recursive: true });
|
|
19412
|
+
writeFileSync12(path3, doc.toString(), "utf8");
|
|
20176
19413
|
}
|
|
20177
19414
|
function isMarkedHook(hook) {
|
|
20178
19415
|
if (!hook || typeof hook !== "object")
|
|
@@ -20215,7 +19452,7 @@ function isMarkedCopilotHook(hook) {
|
|
|
20215
19452
|
return false;
|
|
20216
19453
|
}
|
|
20217
19454
|
function opencodePluginFilePath(settingsPath) {
|
|
20218
|
-
return resolve17(
|
|
19455
|
+
return resolve17(dirname11(settingsPath), "plugins", "failproofai.mjs");
|
|
20219
19456
|
}
|
|
20220
19457
|
function buildOpenCodePluginShim(binaryPath, scope) {
|
|
20221
19458
|
const useNpx = scope === "project";
|
|
@@ -20451,7 +19688,7 @@ function makePiProjectRelativeEntry(extPath) {
|
|
|
20451
19688
|
return extResolved;
|
|
20452
19689
|
}
|
|
20453
19690
|
function hermesConfigHasHooks(settingsPath) {
|
|
20454
|
-
if (!
|
|
19691
|
+
if (!existsSync21(settingsPath))
|
|
20455
19692
|
return false;
|
|
20456
19693
|
try {
|
|
20457
19694
|
const doc = readYamlDoc(settingsPath);
|
|
@@ -20467,7 +19704,7 @@ function hermesConfigHasHooks(settingsPath) {
|
|
|
20467
19704
|
return false;
|
|
20468
19705
|
}
|
|
20469
19706
|
function unhookedHermesProfiles() {
|
|
20470
|
-
return listHermesProfiles().filter((p) =>
|
|
19707
|
+
return listHermesProfiles().filter((p) => existsSync21(p.home)).filter((p) => !hermesConfigHasHooks(resolve17(p.home, "config.yaml"))).map((p) => p.name);
|
|
20471
19708
|
}
|
|
20472
19709
|
function getOpenClawPluginPath() {
|
|
20473
19710
|
const fromEnv = process.env.FAILPROOFAI_PACKAGE_ROOT;
|
|
@@ -20501,7 +19738,7 @@ function detectInstalledClis() {
|
|
|
20501
19738
|
}
|
|
20502
19739
|
var claudeCode, codex, copilot, cursor, OPENCODE_PLUGIN_REL_PATH = "./plugins/failproofai.mjs", opencode, pi, hermes, OPENCLAW_PLUGIN_ID = "failproofai", openclaw, factory, devin, ANTIGRAVITY_HOOK_NAME = "failproofai", ANTIGRAVITY_TOOL_EVENTS, antigravity, goose, INTEGRATIONS;
|
|
20503
19740
|
var init_integrations = __esm(() => {
|
|
20504
|
-
|
|
19741
|
+
init_dist();
|
|
20505
19742
|
init_hermes_profiles();
|
|
20506
19743
|
init_types();
|
|
20507
19744
|
claudeCode = {
|
|
@@ -20613,7 +19850,7 @@ var init_integrations = __esm(() => {
|
|
|
20613
19850
|
},
|
|
20614
19851
|
hooksInstalledInSettings(scope, cwd) {
|
|
20615
19852
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
20616
|
-
if (!
|
|
19853
|
+
if (!existsSync21(settingsPath))
|
|
20617
19854
|
return false;
|
|
20618
19855
|
try {
|
|
20619
19856
|
const settings = this.readSettings(settingsPath);
|
|
@@ -20729,7 +19966,7 @@ var init_integrations = __esm(() => {
|
|
|
20729
19966
|
},
|
|
20730
19967
|
hooksInstalledInSettings(scope, cwd) {
|
|
20731
19968
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
20732
|
-
if (!
|
|
19969
|
+
if (!existsSync21(settingsPath))
|
|
20733
19970
|
return false;
|
|
20734
19971
|
try {
|
|
20735
19972
|
const settings = this.readSettings(settingsPath);
|
|
@@ -20843,7 +20080,7 @@ var init_integrations = __esm(() => {
|
|
|
20843
20080
|
},
|
|
20844
20081
|
hooksInstalledInSettings(scope, cwd) {
|
|
20845
20082
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
20846
|
-
if (!
|
|
20083
|
+
if (!existsSync21(settingsPath))
|
|
20847
20084
|
return false;
|
|
20848
20085
|
try {
|
|
20849
20086
|
const settings = this.readSettings(settingsPath);
|
|
@@ -20946,7 +20183,7 @@ var init_integrations = __esm(() => {
|
|
|
20946
20183
|
},
|
|
20947
20184
|
hooksInstalledInSettings(scope, cwd) {
|
|
20948
20185
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
20949
|
-
if (!
|
|
20186
|
+
if (!existsSync21(settingsPath))
|
|
20950
20187
|
return false;
|
|
20951
20188
|
try {
|
|
20952
20189
|
const settings = this.readSettings(settingsPath);
|
|
@@ -21006,8 +20243,8 @@ var init_integrations = __esm(() => {
|
|
|
21006
20243
|
const effectiveScope = scope ?? "project";
|
|
21007
20244
|
const settingsPath = effectiveScope === "user" ? resolve17(homedir22(), ".config", "opencode", "opencode.json") : resolve17(process.cwd(), ".opencode", "opencode.json");
|
|
21008
20245
|
const pluginPath = opencodePluginFilePath(settingsPath);
|
|
21009
|
-
|
|
21010
|
-
|
|
20246
|
+
mkdirSync14(dirname11(pluginPath), { recursive: true });
|
|
20247
|
+
writeFileSync12(pluginPath, buildOpenCodePluginShim(binaryPath, effectiveScope), "utf8");
|
|
21011
20248
|
if (!Array.isArray(s.plugin))
|
|
21012
20249
|
s.plugin = [];
|
|
21013
20250
|
const desired = effectiveScope === "user" ? `file://${pluginPath}` : OPENCODE_PLUGIN_REL_PATH;
|
|
@@ -21030,9 +20267,9 @@ var init_integrations = __esm(() => {
|
|
|
21030
20267
|
}
|
|
21031
20268
|
this.writeSettings(settingsPath, settings);
|
|
21032
20269
|
const pluginPath = opencodePluginFilePath(settingsPath);
|
|
21033
|
-
if (
|
|
20270
|
+
if (existsSync21(pluginPath)) {
|
|
21034
20271
|
try {
|
|
21035
|
-
const content =
|
|
20272
|
+
const content = readFileSync19(pluginPath, "utf8");
|
|
21036
20273
|
if (content.includes(FAILPROOFAI_HOOK_MARKER)) {
|
|
21037
20274
|
unlinkSync3(pluginPath);
|
|
21038
20275
|
if (removed === 0)
|
|
@@ -21044,7 +20281,7 @@ var init_integrations = __esm(() => {
|
|
|
21044
20281
|
},
|
|
21045
20282
|
hooksInstalledInSettings(scope, cwd) {
|
|
21046
20283
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
21047
|
-
if (!
|
|
20284
|
+
if (!existsSync21(settingsPath))
|
|
21048
20285
|
return false;
|
|
21049
20286
|
try {
|
|
21050
20287
|
const settings = this.readSettings(settingsPath);
|
|
@@ -21054,9 +20291,9 @@ var init_integrations = __esm(() => {
|
|
|
21054
20291
|
if (!hasEntry)
|
|
21055
20292
|
return false;
|
|
21056
20293
|
const pluginPath = opencodePluginFilePath(settingsPath);
|
|
21057
|
-
if (!
|
|
20294
|
+
if (!existsSync21(pluginPath))
|
|
21058
20295
|
return false;
|
|
21059
|
-
const content =
|
|
20296
|
+
const content = readFileSync19(pluginPath, "utf8");
|
|
21060
20297
|
return content.includes(FAILPROOFAI_HOOK_MARKER);
|
|
21061
20298
|
} catch {
|
|
21062
20299
|
return false;
|
|
@@ -21121,7 +20358,7 @@ var init_integrations = __esm(() => {
|
|
|
21121
20358
|
}
|
|
21122
20359
|
},
|
|
21123
20360
|
removeHooksFromFile(settingsPath) {
|
|
21124
|
-
if (!
|
|
20361
|
+
if (!existsSync21(settingsPath))
|
|
21125
20362
|
return 0;
|
|
21126
20363
|
const settings = this.readSettings(settingsPath);
|
|
21127
20364
|
if (!Array.isArray(settings.packages))
|
|
@@ -21136,7 +20373,7 @@ var init_integrations = __esm(() => {
|
|
|
21136
20373
|
},
|
|
21137
20374
|
hooksInstalledInSettings(scope, cwd) {
|
|
21138
20375
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
21139
|
-
if (!
|
|
20376
|
+
if (!existsSync21(settingsPath))
|
|
21140
20377
|
return false;
|
|
21141
20378
|
try {
|
|
21142
20379
|
const settings = this.readSettings(settingsPath);
|
|
@@ -21195,7 +20432,7 @@ var init_integrations = __esm(() => {
|
|
|
21195
20432
|
doc.set("hooks_auto_accept", true);
|
|
21196
20433
|
},
|
|
21197
20434
|
removeHooksFromFile(settingsPath) {
|
|
21198
|
-
if (!
|
|
20435
|
+
if (!existsSync21(settingsPath))
|
|
21199
20436
|
return 0;
|
|
21200
20437
|
const doc = readYamlDoc(settingsPath);
|
|
21201
20438
|
const js = doc.toJS() ?? {};
|
|
@@ -21285,7 +20522,7 @@ var init_integrations = __esm(() => {
|
|
|
21285
20522
|
hooks.allowConversationAccess = true;
|
|
21286
20523
|
},
|
|
21287
20524
|
removeHooksFromFile(settingsPath) {
|
|
21288
|
-
if (!
|
|
20525
|
+
if (!existsSync21(settingsPath))
|
|
21289
20526
|
return 0;
|
|
21290
20527
|
const settings = this.readSettings(settingsPath);
|
|
21291
20528
|
const plugins = settings.plugins;
|
|
@@ -21314,7 +20551,7 @@ var init_integrations = __esm(() => {
|
|
|
21314
20551
|
},
|
|
21315
20552
|
hooksInstalledInSettings(scope, cwd) {
|
|
21316
20553
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
21317
|
-
if (!
|
|
20554
|
+
if (!existsSync21(settingsPath))
|
|
21318
20555
|
return false;
|
|
21319
20556
|
try {
|
|
21320
20557
|
const settings = this.readSettings(settingsPath);
|
|
@@ -21411,7 +20648,7 @@ var init_integrations = __esm(() => {
|
|
|
21411
20648
|
},
|
|
21412
20649
|
hooksInstalledInSettings(scope, cwd) {
|
|
21413
20650
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
21414
|
-
if (!
|
|
20651
|
+
if (!existsSync21(settingsPath))
|
|
21415
20652
|
return false;
|
|
21416
20653
|
try {
|
|
21417
20654
|
const settings = this.readSettings(settingsPath);
|
|
@@ -21517,7 +20754,7 @@ var init_integrations = __esm(() => {
|
|
|
21517
20754
|
},
|
|
21518
20755
|
hooksInstalledInSettings(scope, cwd) {
|
|
21519
20756
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
21520
|
-
if (!
|
|
20757
|
+
if (!existsSync21(settingsPath))
|
|
21521
20758
|
return false;
|
|
21522
20759
|
try {
|
|
21523
20760
|
const settings = this.readSettings(settingsPath);
|
|
@@ -21656,7 +20893,7 @@ var init_integrations = __esm(() => {
|
|
|
21656
20893
|
},
|
|
21657
20894
|
hooksInstalledInSettings(scope, cwd) {
|
|
21658
20895
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
21659
|
-
if (!
|
|
20896
|
+
if (!existsSync21(settingsPath))
|
|
21660
20897
|
return false;
|
|
21661
20898
|
try {
|
|
21662
20899
|
const settings = this.readSettings(settingsPath);
|
|
@@ -21762,7 +20999,7 @@ var init_integrations = __esm(() => {
|
|
|
21762
20999
|
},
|
|
21763
21000
|
hooksInstalledInSettings(scope, cwd) {
|
|
21764
21001
|
const settingsPath = this.getSettingsPath(scope, cwd);
|
|
21765
|
-
if (!
|
|
21002
|
+
if (!existsSync21(settingsPath))
|
|
21766
21003
|
return false;
|
|
21767
21004
|
try {
|
|
21768
21005
|
const settings = this.readSettings(settingsPath);
|
|
@@ -22041,7 +21278,7 @@ var init_cli_error = __esm(() => {
|
|
|
22041
21278
|
|
|
22042
21279
|
// src/hooks/manager.ts
|
|
22043
21280
|
import { execSync as execSync6 } from "node:child_process";
|
|
22044
|
-
import { existsSync as
|
|
21281
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
22045
21282
|
import { resolve as resolve18, basename as basename4 } from "node:path";
|
|
22046
21283
|
import { platform as platform3, arch as arch3, release as release2, hostname as hostname3 } from "node:os";
|
|
22047
21284
|
function getSettingsPath(scope, cwd) {
|
|
@@ -22152,7 +21389,7 @@ async function installHooksImpl(policyNames, scope = "user", cwd, includeBeta =
|
|
|
22152
21389
|
} else if (customPoliciesPath && (typeof customPoliciesPath === "string" || customPoliciesPath.length > 0)) {
|
|
22153
21390
|
const incoming = (typeof customPoliciesPath === "string" ? [customPoliciesPath] : customPoliciesPath).map((path3) => resolve18(path3));
|
|
22154
21391
|
const carried = (previousConfig.customPoliciesPaths ?? (previousConfig.customPoliciesPath ? [previousConfig.customPoliciesPath] : [])).map((path3) => resolve18(path3)).filter((path3) => {
|
|
22155
|
-
if (
|
|
21392
|
+
if (existsSync22(path3))
|
|
22156
21393
|
return true;
|
|
22157
21394
|
console.log(`Dropping custom policies path (file no longer exists): ${path3}`);
|
|
22158
21395
|
return false;
|
|
@@ -22344,7 +21581,7 @@ async function removeHooks(policyNames, scope = "user", cwd, opts) {
|
|
|
22344
21581
|
const scopesToRemove = scope === "all" ? [...integration.scopes] : integration.scopes.includes(scope) ? [scope] : [];
|
|
22345
21582
|
for (const s of scopesToRemove) {
|
|
22346
21583
|
const settingsPaths = settingsPathsFor(integration, s, cwd);
|
|
22347
|
-
const existing = settingsPaths.filter((p) =>
|
|
21584
|
+
const existing = settingsPaths.filter((p) => existsSync22(p));
|
|
22348
21585
|
if (existing.length === 0) {
|
|
22349
21586
|
if (scope !== "all" && selectedClis.length === 1) {
|
|
22350
21587
|
console.log("No settings file found. Nothing to remove.");
|
|
@@ -22424,6 +21661,7 @@ var init_manager = __esm(() => {
|
|
|
22424
21661
|
init_cli_error();
|
|
22425
21662
|
init_hook_logger();
|
|
22426
21663
|
init_fp_home();
|
|
21664
|
+
init_cloud_managed_policies();
|
|
22427
21665
|
VALID_POLICY_NAMES = new Set(BUILTIN_POLICIES.map((p) => p.name));
|
|
22428
21666
|
});
|
|
22429
21667
|
|
|
@@ -22488,7 +21726,7 @@ var DEFAULT_FETCH_TIMEOUT_MS = 15000;
|
|
|
22488
21726
|
|
|
22489
21727
|
// src/hooks/cloud-enrollment.ts
|
|
22490
21728
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
22491
|
-
import { existsSync as
|
|
21729
|
+
import { existsSync as existsSync23, readFileSync as readFileSync20, rmSync as rmSync8 } from "node:fs";
|
|
22492
21730
|
import { hostname as hostname4 } from "node:os";
|
|
22493
21731
|
function cloudCredentialPath() {
|
|
22494
21732
|
return process.env.FAILPROOFAI_CLOUD_CREDENTIALS ?? credentialsFile();
|
|
@@ -22527,10 +21765,10 @@ function readCloudCredentials() {
|
|
|
22527
21765
|
if (!usingJsonOverride())
|
|
22528
21766
|
return readCredentials().cloud ?? null;
|
|
22529
21767
|
const path3 = cloudCredentialPath();
|
|
22530
|
-
if (!
|
|
21768
|
+
if (!existsSync23(path3))
|
|
22531
21769
|
return null;
|
|
22532
21770
|
try {
|
|
22533
|
-
const raw = JSON.parse(
|
|
21771
|
+
const raw = JSON.parse(readFileSync20(path3, "utf8"));
|
|
22534
21772
|
if (raw.schemaVersion !== SCHEMA_VERSION2)
|
|
22535
21773
|
return null;
|
|
22536
21774
|
if (typeof raw.url !== "string" || typeof raw.machineId !== "string" || typeof raw.token !== "string") {
|
|
@@ -22566,10 +21804,10 @@ function resolveMachineLabel(explicit) {
|
|
|
22566
21804
|
function clearCloudCredentials() {
|
|
22567
21805
|
if (usingJsonOverride()) {
|
|
22568
21806
|
const path3 = cloudCredentialPath();
|
|
22569
|
-
if (!
|
|
21807
|
+
if (!existsSync23(path3))
|
|
22570
21808
|
return false;
|
|
22571
21809
|
try {
|
|
22572
|
-
|
|
21810
|
+
rmSync8(path3);
|
|
22573
21811
|
return true;
|
|
22574
21812
|
} catch {
|
|
22575
21813
|
return false;
|
|
@@ -22610,7 +21848,7 @@ async function verifyCloudCredentials(creds) {
|
|
|
22610
21848
|
return {
|
|
22611
21849
|
ok: true,
|
|
22612
21850
|
policyCount: Array.isArray(body.policies) ? body.policies.length : 0,
|
|
22613
|
-
|
|
21851
|
+
deployment: typeof body.deployment === "number" ? body.deployment : 0
|
|
22614
21852
|
};
|
|
22615
21853
|
} catch {
|
|
22616
21854
|
return {
|
|
@@ -22735,7 +21973,7 @@ async function connectToCloud(input) {
|
|
|
22735
21973
|
canIngest ? verifyIngest({ url: ingestUrl, key: input.token }) : Promise.resolve({ ok: false, reason: missing(PERMISSION_EVENTS) })
|
|
22736
21974
|
]);
|
|
22737
21975
|
const outcome = {
|
|
22738
|
-
policy: policyResult.ok ? { ok: true, policyCount: policyResult.policyCount,
|
|
21976
|
+
policy: policyResult.ok ? { ok: true, policyCount: policyResult.policyCount, deployment: policyResult.deployment } : { ok: false, reason: policyResult.reason },
|
|
22739
21977
|
ingest: ingestResult.ok ? { ok: true } : { ok: false, reason: ingestResult.reason },
|
|
22740
21978
|
anyConfigured: false,
|
|
22741
21979
|
org: known ? { id: known.orgId, slug: known.orgSlug, name: known.orgName } : undefined
|
|
@@ -22773,14 +22011,14 @@ function describeOutcome(outcome, machineId, url) {
|
|
|
22773
22011
|
if (outcome.policy.ok && outcome.ingest.ok) {
|
|
22774
22012
|
lines.push(`Connected to ${url} as ${machineId}${into}.`);
|
|
22775
22013
|
const n = outcome.policy.policyCount ?? 0;
|
|
22776
|
-
lines.push(` Policy ${n} polic${n === 1 ? "y" : "ies"} assigned (
|
|
22014
|
+
lines.push(` Policy ${n} polic${n === 1 ? "y" : "ies"} assigned (deployment ${outcome.policy.deployment ?? 0}).`);
|
|
22777
22015
|
lines.push(` Dashboard hook activity will be sent to ${ingestUrlFor(url)}.`);
|
|
22778
22016
|
return lines;
|
|
22779
22017
|
}
|
|
22780
22018
|
if (outcome.policy.ok && !outcome.ingest.ok) {
|
|
22781
22019
|
const n = outcome.policy.policyCount ?? 0;
|
|
22782
22020
|
lines.push(`Connected to ${url} as ${machineId}${into}, for policy only.`);
|
|
22783
|
-
lines.push(` Policy ${n} polic${n === 1 ? "y" : "ies"} assigned (
|
|
22021
|
+
lines.push(` Policy ${n} polic${n === 1 ? "y" : "ies"} assigned (deployment ${outcome.policy.deployment ?? 0}).`);
|
|
22784
22022
|
lines.push(` Dashboard NOT configured: ${outcome.ingest.reason}`);
|
|
22785
22023
|
lines.push("");
|
|
22786
22024
|
lines.push(" Enforcement works. Nothing will appear in the dashboard until this");
|
|
@@ -22817,8 +22055,8 @@ var init_cloud_connection = __esm(() => {
|
|
|
22817
22055
|
});
|
|
22818
22056
|
|
|
22819
22057
|
// src/hooks/setup-state.ts
|
|
22820
|
-
import { existsSync as
|
|
22821
|
-
import { dirname as
|
|
22058
|
+
import { existsSync as existsSync24, realpathSync as realpathSync2, statSync as statSync17 } from "node:fs";
|
|
22059
|
+
import { dirname as dirname12, resolve as resolve19 } from "node:path";
|
|
22822
22060
|
import { homedir as homedir25 } from "node:os";
|
|
22823
22061
|
function globalConfigPath(home = homedir25()) {
|
|
22824
22062
|
return globalPolicyConfigFile(home);
|
|
@@ -22831,7 +22069,7 @@ function legacyMarkerPath(home) {
|
|
|
22831
22069
|
}
|
|
22832
22070
|
function isDir(path3) {
|
|
22833
22071
|
try {
|
|
22834
|
-
return
|
|
22072
|
+
return statSync17(path3).isDirectory();
|
|
22835
22073
|
} catch {
|
|
22836
22074
|
return false;
|
|
22837
22075
|
}
|
|
@@ -22842,7 +22080,7 @@ function findProjectRoot(start, home = homedir25()) {
|
|
|
22842
22080
|
while (dir !== resolvedHome) {
|
|
22843
22081
|
if (isDir(resolve19(dir, ".failproofai")))
|
|
22844
22082
|
return dir;
|
|
22845
|
-
const parent =
|
|
22083
|
+
const parent = dirname12(dir);
|
|
22846
22084
|
if (parent === dir)
|
|
22847
22085
|
break;
|
|
22848
22086
|
dir = parent;
|
|
@@ -22874,10 +22112,10 @@ function detectSetupState(cwd = process.cwd(), home = homedir25()) {
|
|
|
22874
22112
|
cwd: resolvedCwd,
|
|
22875
22113
|
home: resolvedHome,
|
|
22876
22114
|
projectRoot,
|
|
22877
|
-
hasGlobalConfig:
|
|
22878
|
-
hasProjectConfig: projectRoot !== resolvedHome &&
|
|
22115
|
+
hasGlobalConfig: existsSync24(globalConfigPath(resolvedHome)),
|
|
22116
|
+
hasProjectConfig: projectRoot !== resolvedHome && existsSync24(projectConfigPath(projectRoot)),
|
|
22879
22117
|
hasGlobalHooks: hasGlobalHooksInstalled(),
|
|
22880
|
-
hasLegacyMarker:
|
|
22118
|
+
hasLegacyMarker: existsSync24(legacyMarkerPath(resolvedHome)),
|
|
22881
22119
|
inHomeDir: resolvedCwd === resolvedHome
|
|
22882
22120
|
};
|
|
22883
22121
|
}
|
|
@@ -22925,14 +22163,14 @@ var init_setup_state = __esm(() => {
|
|
|
22925
22163
|
});
|
|
22926
22164
|
|
|
22927
22165
|
// src/hooks/onboarding-attempt.ts
|
|
22928
|
-
import { existsSync as
|
|
22929
|
-
import { dirname as
|
|
22166
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync21, rmSync as rmSync9, writeFileSync as writeFileSync13 } from "node:fs";
|
|
22167
|
+
import { dirname as dirname13 } from "node:path";
|
|
22930
22168
|
function readOnboardingAttempt() {
|
|
22931
22169
|
const path3 = onboardingAttemptFile();
|
|
22932
|
-
if (!
|
|
22170
|
+
if (!existsSync25(path3))
|
|
22933
22171
|
return null;
|
|
22934
22172
|
try {
|
|
22935
|
-
const raw = JSON.parse(
|
|
22173
|
+
const raw = JSON.parse(readFileSync21(path3, "utf8"));
|
|
22936
22174
|
if (raw.schemaVersion !== SCHEMA_VERSION3)
|
|
22937
22175
|
return null;
|
|
22938
22176
|
if (typeof raw.reason !== "string" || typeof raw.cliVersion !== "string")
|
|
@@ -22951,7 +22189,7 @@ function readOnboardingAttempt() {
|
|
|
22951
22189
|
function recordOnboardingAttempt(reason, cliVersion, daemonStatus, now = Date.now()) {
|
|
22952
22190
|
try {
|
|
22953
22191
|
const path3 = onboardingAttemptFile();
|
|
22954
|
-
|
|
22192
|
+
mkdirSync15(dirname13(path3), { recursive: true });
|
|
22955
22193
|
const record = {
|
|
22956
22194
|
schemaVersion: SCHEMA_VERSION3,
|
|
22957
22195
|
reason,
|
|
@@ -22959,12 +22197,12 @@ function recordOnboardingAttempt(reason, cliVersion, daemonStatus, now = Date.no
|
|
|
22959
22197
|
daemonStatus,
|
|
22960
22198
|
at: now
|
|
22961
22199
|
};
|
|
22962
|
-
|
|
22200
|
+
writeFileSync13(path3, JSON.stringify(record, null, 2), "utf8");
|
|
22963
22201
|
} catch {}
|
|
22964
22202
|
}
|
|
22965
22203
|
function clearOnboardingAttempt() {
|
|
22966
22204
|
try {
|
|
22967
|
-
|
|
22205
|
+
rmSync9(onboardingAttemptFile(), { force: true });
|
|
22968
22206
|
} catch {}
|
|
22969
22207
|
}
|
|
22970
22208
|
function blockerCleared(attempt, probe) {
|
|
@@ -22975,6 +22213,8 @@ function blockerCleared(attempt, probe) {
|
|
|
22975
22213
|
return probe.daemonStatus() !== attempt.daemonStatus || probe.canElevate();
|
|
22976
22214
|
case "cancelled":
|
|
22977
22215
|
return probe.cliVersion !== attempt.cliVersion;
|
|
22216
|
+
case "unsupported_platform":
|
|
22217
|
+
return probe.cliVersion !== attempt.cliVersion;
|
|
22978
22218
|
case "not_a_tty":
|
|
22979
22219
|
case "running_as_sudo":
|
|
22980
22220
|
return true;
|
|
@@ -22987,14 +22227,16 @@ function attemptHintLines(attempt) {
|
|
|
22987
22227
|
needs_root: "it needs root to install the failproofaid service",
|
|
22988
22228
|
daemon_failed: "the failproofaid service could not be started",
|
|
22989
22229
|
cancelled: "it was cancelled",
|
|
22230
|
+
unsupported_platform: "failproofaid does not run on this platform",
|
|
22990
22231
|
not_a_tty: "there was no terminal to ask in",
|
|
22991
22232
|
running_as_sudo: "it was run under sudo"
|
|
22992
22233
|
};
|
|
22993
22234
|
const detail = why[attempt.reason] ?? "it did not finish";
|
|
22235
|
+
const action = attempt.reason === "unsupported_platform" ? "Check for a failproofai update — this platform may be supported by a newer release." : "Run `failproofai config` when you are ready.";
|
|
22994
22236
|
return [
|
|
22995
22237
|
``,
|
|
22996
22238
|
`[failproofai] Setup is not finished — ${detail}.`,
|
|
22997
|
-
`
|
|
22239
|
+
` ${action}`,
|
|
22998
22240
|
``
|
|
22999
22241
|
];
|
|
23000
22242
|
}
|
|
@@ -23004,7 +22246,7 @@ var init_onboarding_attempt = __esm(() => {
|
|
|
23004
22246
|
});
|
|
23005
22247
|
|
|
23006
22248
|
// src/hooks/onboarding-lock.ts
|
|
23007
|
-
import { mkdirSync as
|
|
22249
|
+
import { mkdirSync as mkdirSync16, readFileSync as readFileSync22, rmSync as rmSync10, writeFileSync as writeFileSync14 } from "node:fs";
|
|
23008
22250
|
import { homedir as homedir26 } from "node:os";
|
|
23009
22251
|
function onboardingLockPath(home = homedir26()) {
|
|
23010
22252
|
return onboardingLockFile(home);
|
|
@@ -23021,7 +22263,7 @@ function processAlive(pid) {
|
|
|
23021
22263
|
}
|
|
23022
22264
|
function readLock(path3) {
|
|
23023
22265
|
try {
|
|
23024
|
-
const parsed = JSON.parse(
|
|
22266
|
+
const parsed = JSON.parse(readFileSync22(path3, "utf8"));
|
|
23025
22267
|
if (typeof parsed.pid !== "number")
|
|
23026
22268
|
return null;
|
|
23027
22269
|
return { pid: parsed.pid, startedAt: Number(parsed.startedAt) || 0 };
|
|
@@ -23035,9 +22277,9 @@ function acquireOnboardingLock(home = homedir26()) {
|
|
|
23035
22277
|
const held = readLock(path3);
|
|
23036
22278
|
if (held && held.pid !== process.pid && processAlive(held.pid))
|
|
23037
22279
|
return null;
|
|
23038
|
-
|
|
22280
|
+
mkdirSync16(stateDir(home), { recursive: true });
|
|
23039
22281
|
const body = { pid: process.pid, startedAt: Date.now() };
|
|
23040
|
-
|
|
22282
|
+
writeFileSync14(path3, JSON.stringify(body), "utf8");
|
|
23041
22283
|
let released = false;
|
|
23042
22284
|
return {
|
|
23043
22285
|
release() {
|
|
@@ -23047,7 +22289,7 @@ function acquireOnboardingLock(home = homedir26()) {
|
|
|
23047
22289
|
try {
|
|
23048
22290
|
const current = readLock(path3);
|
|
23049
22291
|
if (!current || current.pid === process.pid)
|
|
23050
|
-
|
|
22292
|
+
rmSync10(path3, { force: true });
|
|
23051
22293
|
} catch {}
|
|
23052
22294
|
}
|
|
23053
22295
|
};
|
|
@@ -23060,7 +22302,7 @@ var init_onboarding_lock = __esm(() => {
|
|
|
23060
22302
|
});
|
|
23061
22303
|
|
|
23062
22304
|
// lib/claude-sessions.ts
|
|
23063
|
-
import { readdirSync as
|
|
22305
|
+
import { readdirSync as readdirSync15, statSync as statSync18, existsSync as existsSync27 } from "node:fs";
|
|
23064
22306
|
import { join as join28, basename as basename5 } from "node:path";
|
|
23065
22307
|
function getClaudeProjectsRoot() {
|
|
23066
22308
|
return getClaudeProjectsPath();
|
|
@@ -23069,7 +22311,7 @@ function listClaudeProjects() {
|
|
|
23069
22311
|
const root = getClaudeProjectsRoot();
|
|
23070
22312
|
let entries;
|
|
23071
22313
|
try {
|
|
23072
|
-
entries =
|
|
22314
|
+
entries = readdirSync15(root, { withFileTypes: true });
|
|
23073
22315
|
} catch {
|
|
23074
22316
|
return [];
|
|
23075
22317
|
}
|
|
@@ -23083,7 +22325,7 @@ function listClaudeTranscripts(project) {
|
|
|
23083
22325
|
const out = [];
|
|
23084
22326
|
let entries;
|
|
23085
22327
|
try {
|
|
23086
|
-
entries =
|
|
22328
|
+
entries = readdirSync15(project.path, { withFileTypes: true });
|
|
23087
22329
|
} catch {
|
|
23088
22330
|
return out;
|
|
23089
22331
|
}
|
|
@@ -23094,7 +22336,7 @@ function listClaudeTranscripts(project) {
|
|
|
23094
22336
|
continue;
|
|
23095
22337
|
const transcriptPath = join28(project.path, entry.name);
|
|
23096
22338
|
try {
|
|
23097
|
-
const s =
|
|
22339
|
+
const s = statSync18(transcriptPath);
|
|
23098
22340
|
out.push({
|
|
23099
22341
|
projectName: project.name,
|
|
23100
22342
|
cwd: project.cwd,
|
|
@@ -23107,11 +22349,11 @@ function listClaudeTranscripts(project) {
|
|
|
23107
22349
|
} catch {}
|
|
23108
22350
|
} else if (entry.isDirectory() && UUID_RE2.test(entry.name)) {
|
|
23109
22351
|
const subDir = join28(project.path, entry.name, "subagents");
|
|
23110
|
-
if (!
|
|
22352
|
+
if (!existsSync27(subDir))
|
|
23111
22353
|
continue;
|
|
23112
22354
|
let subEntries;
|
|
23113
22355
|
try {
|
|
23114
|
-
subEntries =
|
|
22356
|
+
subEntries = readdirSync15(subDir, { withFileTypes: true });
|
|
23115
22357
|
} catch {
|
|
23116
22358
|
continue;
|
|
23117
22359
|
}
|
|
@@ -23121,7 +22363,7 @@ function listClaudeTranscripts(project) {
|
|
|
23121
22363
|
const agentId = sub.name.slice(0, -".jsonl".length);
|
|
23122
22364
|
const transcriptPath = join28(subDir, sub.name);
|
|
23123
22365
|
try {
|
|
23124
|
-
const s =
|
|
22366
|
+
const s = statSync18(transcriptPath);
|
|
23125
22367
|
out.push({
|
|
23126
22368
|
projectName: project.name,
|
|
23127
22369
|
cwd: project.cwd,
|
|
@@ -23265,7 +22507,7 @@ var init_claude = __esm(() => {
|
|
|
23265
22507
|
});
|
|
23266
22508
|
|
|
23267
22509
|
// src/audit/cli-adapters/codex.ts
|
|
23268
|
-
import { statSync as
|
|
22510
|
+
import { statSync as statSync19 } from "node:fs";
|
|
23269
22511
|
async function listCodexTranscriptMetadata(opts = {}) {
|
|
23270
22512
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
23271
22513
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -23282,7 +22524,7 @@ async function listCodexTranscriptMetadata(opts = {}) {
|
|
|
23282
22524
|
continue;
|
|
23283
22525
|
let sizeBytes = 0;
|
|
23284
22526
|
try {
|
|
23285
|
-
sizeBytes =
|
|
22527
|
+
sizeBytes = statSync19(s.path).size;
|
|
23286
22528
|
} catch {}
|
|
23287
22529
|
if (!s.sessionId)
|
|
23288
22530
|
continue;
|
|
@@ -23316,7 +22558,7 @@ var init_codex = __esm(() => {
|
|
|
23316
22558
|
});
|
|
23317
22559
|
|
|
23318
22560
|
// src/audit/cli-adapters/copilot.ts
|
|
23319
|
-
import { statSync as
|
|
22561
|
+
import { statSync as statSync20 } from "node:fs";
|
|
23320
22562
|
async function listCopilotTranscriptMetadata(opts = {}) {
|
|
23321
22563
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
23322
22564
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -23333,7 +22575,7 @@ async function listCopilotTranscriptMetadata(opts = {}) {
|
|
|
23333
22575
|
continue;
|
|
23334
22576
|
let sizeBytes = 0;
|
|
23335
22577
|
try {
|
|
23336
|
-
sizeBytes =
|
|
22578
|
+
sizeBytes = statSync20(s.path).size;
|
|
23337
22579
|
} catch {}
|
|
23338
22580
|
if (!s.sessionId)
|
|
23339
22581
|
continue;
|
|
@@ -23367,7 +22609,7 @@ var init_copilot = __esm(() => {
|
|
|
23367
22609
|
});
|
|
23368
22610
|
|
|
23369
22611
|
// src/audit/cli-adapters/cursor.ts
|
|
23370
|
-
import { statSync as
|
|
22612
|
+
import { statSync as statSync21 } from "node:fs";
|
|
23371
22613
|
async function listCursorTranscriptMetadata(opts = {}) {
|
|
23372
22614
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
23373
22615
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -23384,7 +22626,7 @@ async function listCursorTranscriptMetadata(opts = {}) {
|
|
|
23384
22626
|
continue;
|
|
23385
22627
|
let sizeBytes = 0;
|
|
23386
22628
|
try {
|
|
23387
|
-
sizeBytes =
|
|
22629
|
+
sizeBytes = statSync21(s.path).size;
|
|
23388
22630
|
} catch {}
|
|
23389
22631
|
if (!s.sessionId)
|
|
23390
22632
|
continue;
|
|
@@ -23630,7 +22872,7 @@ var init_opencode = __esm(() => {
|
|
|
23630
22872
|
});
|
|
23631
22873
|
|
|
23632
22874
|
// src/audit/cli-adapters/pi.ts
|
|
23633
|
-
import { statSync as
|
|
22875
|
+
import { statSync as statSync22 } from "node:fs";
|
|
23634
22876
|
async function listPiTranscriptMetadata(opts = {}) {
|
|
23635
22877
|
const projectFilter = opts.projects ? new Set(opts.projects) : null;
|
|
23636
22878
|
const sinceMs = opts.sinceMs ?? 0;
|
|
@@ -23647,7 +22889,7 @@ async function listPiTranscriptMetadata(opts = {}) {
|
|
|
23647
22889
|
continue;
|
|
23648
22890
|
let sizeBytes = 0;
|
|
23649
22891
|
try {
|
|
23650
|
-
sizeBytes =
|
|
22892
|
+
sizeBytes = statSync22(s.path).size;
|
|
23651
22893
|
} catch {}
|
|
23652
22894
|
if (!s.sessionId)
|
|
23653
22895
|
continue;
|
|
@@ -24382,7 +23624,7 @@ var init_features = __esm(() => {
|
|
|
24382
23624
|
|
|
24383
23625
|
// src/audit/cache.ts
|
|
24384
23626
|
import { createHash as createHash6 } from "node:crypto";
|
|
24385
|
-
import { existsSync as
|
|
23627
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync23, writeFileSync as writeFileSync15, chmodSync as chmodSync4 } from "node:fs";
|
|
24386
23628
|
import { join as join29 } from "node:path";
|
|
24387
23629
|
function getEngineVersion() {
|
|
24388
23630
|
if (cachedEngineVersion)
|
|
@@ -24409,10 +23651,10 @@ function readCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes) {
|
|
|
24409
23651
|
if (sizeBytes === 0)
|
|
24410
23652
|
return null;
|
|
24411
23653
|
const cachePath = getCachePathFor(transcriptPath);
|
|
24412
|
-
if (!
|
|
23654
|
+
if (!existsSync28(cachePath))
|
|
24413
23655
|
return null;
|
|
24414
23656
|
try {
|
|
24415
|
-
const raw =
|
|
23657
|
+
const raw = readFileSync23(cachePath, "utf-8");
|
|
24416
23658
|
const entry = JSON.parse(raw);
|
|
24417
23659
|
if (entry.schemaVersion !== CACHE_SCHEMA_VERSION)
|
|
24418
23660
|
return null;
|
|
@@ -24436,7 +23678,7 @@ function writeCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes, result)
|
|
|
24436
23678
|
return;
|
|
24437
23679
|
const cachePath = getCachePathFor(transcriptPath);
|
|
24438
23680
|
try {
|
|
24439
|
-
|
|
23681
|
+
mkdirSync17(auditCacheDir(), { recursive: true });
|
|
24440
23682
|
const entry = {
|
|
24441
23683
|
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
24442
23684
|
cachedAt: Date.now(),
|
|
@@ -24446,7 +23688,7 @@ function writeCachedTranscriptResult(transcriptPath, mtimeMs, sizeBytes, result)
|
|
|
24446
23688
|
detectorVersion: getDetectorVersion(),
|
|
24447
23689
|
result
|
|
24448
23690
|
};
|
|
24449
|
-
|
|
23691
|
+
writeFileSync15(cachePath, JSON.stringify(entry), { encoding: "utf-8", mode: 384 });
|
|
24450
23692
|
try {
|
|
24451
23693
|
chmodSync4(cachePath, 384);
|
|
24452
23694
|
} catch {}
|
|
@@ -24812,11 +24054,11 @@ var init_audit = __esm(() => {
|
|
|
24812
24054
|
import {
|
|
24813
24055
|
closeSync,
|
|
24814
24056
|
linkSync,
|
|
24815
|
-
mkdirSync as
|
|
24057
|
+
mkdirSync as mkdirSync18,
|
|
24816
24058
|
openSync,
|
|
24817
|
-
readFileSync as
|
|
24059
|
+
readFileSync as readFileSync24,
|
|
24818
24060
|
unlinkSync as unlinkSync4,
|
|
24819
|
-
writeFileSync as
|
|
24061
|
+
writeFileSync as writeFileSync16,
|
|
24820
24062
|
writeSync
|
|
24821
24063
|
} from "node:fs";
|
|
24822
24064
|
function acquireAuditLock(source, now = Date.now()) {
|
|
@@ -24875,7 +24117,7 @@ function handleFor(path3, info) {
|
|
|
24875
24117
|
}
|
|
24876
24118
|
function readLock2(path3) {
|
|
24877
24119
|
try {
|
|
24878
|
-
const parsed = JSON.parse(
|
|
24120
|
+
const parsed = JSON.parse(readFileSync24(path3, "utf8"));
|
|
24879
24121
|
if (typeof parsed?.pid !== "number" || typeof parsed?.startedAt !== "number")
|
|
24880
24122
|
return null;
|
|
24881
24123
|
return {
|
|
@@ -24891,7 +24133,7 @@ function writeLockExclusive(path3, info) {
|
|
|
24891
24133
|
const body = JSON.stringify(info);
|
|
24892
24134
|
const staging = `${path3}.${process.pid}.tmp`;
|
|
24893
24135
|
try {
|
|
24894
|
-
|
|
24136
|
+
writeFileSync16(staging, body, { mode: 384 });
|
|
24895
24137
|
} catch {
|
|
24896
24138
|
return false;
|
|
24897
24139
|
}
|
|
@@ -24925,8 +24167,8 @@ function createThenWrite(path3, body) {
|
|
|
24925
24167
|
}
|
|
24926
24168
|
}
|
|
24927
24169
|
function ensureRunDir() {
|
|
24928
|
-
|
|
24929
|
-
|
|
24170
|
+
mkdirSync18(failproofaiHome(), { recursive: true });
|
|
24171
|
+
mkdirSync18(runDir(), { recursive: true, mode: 448 });
|
|
24930
24172
|
}
|
|
24931
24173
|
var AUDIT_LOCK_MAX_AGE_MS;
|
|
24932
24174
|
var init_audit_lock = __esm(() => {
|
|
@@ -25090,26 +24332,26 @@ function parseScriptArgs(argv) {
|
|
|
25090
24332
|
var init_parse_script_args = () => {};
|
|
25091
24333
|
|
|
25092
24334
|
// scripts/install-diagnosis.mjs
|
|
25093
|
-
import { existsSync as
|
|
25094
|
-
import { dirname as
|
|
24335
|
+
import { existsSync as existsSync29, readFileSync as readFileSync25, realpathSync as realpathSync3 } from "node:fs";
|
|
24336
|
+
import { dirname as dirname14, resolve as resolve21 } from "node:path";
|
|
25095
24337
|
import { homedir as homedir27, platform as platform4 } from "node:os";
|
|
25096
24338
|
import { spawnSync } from "node:child_process";
|
|
25097
24339
|
function findPackageRoot(start) {
|
|
25098
24340
|
try {
|
|
25099
24341
|
let dir = realpathSync3(start);
|
|
25100
|
-
if (
|
|
25101
|
-
dir =
|
|
24342
|
+
if (existsSync29(dir) && !existsSync29(resolve21(dir, "package.json"))) {
|
|
24343
|
+
dir = dirname14(dir);
|
|
25102
24344
|
}
|
|
25103
24345
|
while (true) {
|
|
25104
24346
|
const pkgPath = resolve21(dir, "package.json");
|
|
25105
|
-
if (
|
|
24347
|
+
if (existsSync29(pkgPath)) {
|
|
25106
24348
|
try {
|
|
25107
|
-
const pkg = JSON.parse(
|
|
24349
|
+
const pkg = JSON.parse(readFileSync25(pkgPath, "utf8"));
|
|
25108
24350
|
if (pkg.name === PKG_NAME)
|
|
25109
24351
|
return dir;
|
|
25110
24352
|
} catch {}
|
|
25111
24353
|
}
|
|
25112
|
-
const parent =
|
|
24354
|
+
const parent = dirname14(dir);
|
|
25113
24355
|
if (parent === dir)
|
|
25114
24356
|
return null;
|
|
25115
24357
|
dir = parent;
|
|
@@ -25122,7 +24364,7 @@ function readPackageVersion(packageRoot) {
|
|
|
25122
24364
|
if (!packageRoot)
|
|
25123
24365
|
return null;
|
|
25124
24366
|
try {
|
|
25125
|
-
const pkg = JSON.parse(
|
|
24367
|
+
const pkg = JSON.parse(readFileSync25(resolve21(packageRoot, "package.json"), "utf8"));
|
|
25126
24368
|
return typeof pkg.version === "string" ? pkg.version : null;
|
|
25127
24369
|
} catch {
|
|
25128
24370
|
return null;
|
|
@@ -25149,7 +24391,7 @@ function locateNpmGlobal() {
|
|
|
25149
24391
|
if (!root)
|
|
25150
24392
|
return null;
|
|
25151
24393
|
const candidate = resolve21(root, PKG_NAME);
|
|
25152
|
-
return
|
|
24394
|
+
return existsSync29(resolve21(candidate, "package.json")) ? candidate : null;
|
|
25153
24395
|
} catch {
|
|
25154
24396
|
return null;
|
|
25155
24397
|
}
|
|
@@ -25157,7 +24399,7 @@ function locateNpmGlobal() {
|
|
|
25157
24399
|
function locateBunGlobal() {
|
|
25158
24400
|
try {
|
|
25159
24401
|
const candidate = resolve21(homedir27(), ".bun", "install", "global", "node_modules", PKG_NAME);
|
|
25160
|
-
return
|
|
24402
|
+
return existsSync29(resolve21(candidate, "package.json")) ? candidate : null;
|
|
25161
24403
|
} catch {
|
|
25162
24404
|
return null;
|
|
25163
24405
|
}
|
|
@@ -25264,8 +24506,8 @@ __export(exports_launch, {
|
|
|
25264
24506
|
launch: () => launch
|
|
25265
24507
|
});
|
|
25266
24508
|
import { spawn as spawn2 } from "child_process";
|
|
25267
|
-
import { realpathSync as realpathSync4, existsSync as
|
|
25268
|
-
import { resolve as resolve22, dirname as
|
|
24509
|
+
import { realpathSync as realpathSync4, existsSync as existsSync30 } from "node:fs";
|
|
24510
|
+
import { resolve as resolve22, dirname as dirname15 } from "node:path";
|
|
25269
24511
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
25270
24512
|
import { createInterface } from "node:readline";
|
|
25271
24513
|
function launch(mode) {
|
|
@@ -25289,9 +24531,9 @@ function launch(mode) {
|
|
|
25289
24531
|
process.env.PORT = port;
|
|
25290
24532
|
process.env.HOSTNAME = bindHost;
|
|
25291
24533
|
cmd = "node";
|
|
25292
|
-
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve22(
|
|
24534
|
+
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve22(dirname15(realpathSync4(fileURLToPath2(import.meta.url))), "..");
|
|
25293
24535
|
const serverJsPath = resolve22(packageRoot, ".next/standalone/server.js");
|
|
25294
|
-
if (!
|
|
24536
|
+
if (!existsSync30(serverJsPath)) {
|
|
25295
24537
|
let shadowMessage = null;
|
|
25296
24538
|
try {
|
|
25297
24539
|
const diag = diagnoseShadow({ selfPackageRoot: packageRoot, selfVersion: version2 });
|
|
@@ -25734,11 +24976,12 @@ __export(exports_configure_wizard, {
|
|
|
25734
24976
|
clisSupportingScope: () => clisSupportingScope,
|
|
25735
24977
|
classifyDaemonInstallFailure: () => classifyDaemonInstallFailure,
|
|
25736
24978
|
buildPresetChoices: () => buildPresetChoices,
|
|
24979
|
+
buildCompletionSummary: () => buildCompletionSummary,
|
|
25737
24980
|
buildAgentChoices: () => buildAgentChoices
|
|
25738
24981
|
});
|
|
25739
|
-
import { existsSync as
|
|
24982
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync19, writeFileSync as writeFileSync17, readFileSync as readFileSync26 } from "node:fs";
|
|
25740
24983
|
import { homedir as homedir28 } from "node:os";
|
|
25741
|
-
import { dirname as
|
|
24984
|
+
import { dirname as dirname16, resolve as resolve23, sep as sep5 } from "node:path";
|
|
25742
24985
|
async function emit(event, props) {
|
|
25743
24986
|
try {
|
|
25744
24987
|
await trackHookEvent2(getInstanceId2(), event, props);
|
|
@@ -25845,8 +25088,8 @@ function setCustomPoliciesEnabled(scope, cwd, enabled) {
|
|
|
25845
25088
|
const path3 = getConfigPathForScope(scope, cwd);
|
|
25846
25089
|
let config = {};
|
|
25847
25090
|
try {
|
|
25848
|
-
if (
|
|
25849
|
-
config = JSON.parse(
|
|
25091
|
+
if (existsSync31(path3))
|
|
25092
|
+
config = JSON.parse(readFileSync26(path3, "utf8"));
|
|
25850
25093
|
} catch {
|
|
25851
25094
|
return;
|
|
25852
25095
|
}
|
|
@@ -25855,7 +25098,7 @@ function setCustomPoliciesEnabled(scope, cwd, enabled) {
|
|
|
25855
25098
|
else
|
|
25856
25099
|
config.customPoliciesEnabled = false;
|
|
25857
25100
|
try {
|
|
25858
|
-
|
|
25101
|
+
writeFileSync17(path3, JSON.stringify(config, null, 2) + `
|
|
25859
25102
|
`, "utf8");
|
|
25860
25103
|
} catch {}
|
|
25861
25104
|
}
|
|
@@ -25902,14 +25145,28 @@ function describeCustomPolicies(cwd) {
|
|
|
25902
25145
|
}
|
|
25903
25146
|
return { active, warnings, fileCount, scopes };
|
|
25904
25147
|
}
|
|
25148
|
+
function buildCompletionSummary(policiesCount, harnessesCount, customEnabled, daemonInstalled, connected) {
|
|
25149
|
+
const extras = [];
|
|
25150
|
+
if (customEnabled === true)
|
|
25151
|
+
extras.push("custom");
|
|
25152
|
+
else if (customEnabled === false)
|
|
25153
|
+
extras.push("custom off");
|
|
25154
|
+
if (daemonInstalled)
|
|
25155
|
+
extras.push("daemon");
|
|
25156
|
+
if (connected)
|
|
25157
|
+
extras.push("reporting");
|
|
25158
|
+
const extrasNote = extras.length > 0 ? ` · ${extras.join(", ")}` : "";
|
|
25159
|
+
const harnesses = `${harnessesCount} harness${harnessesCount === 1 ? "" : "es"}`;
|
|
25160
|
+
return `Setup complete — ${policiesCount} policies · ${harnesses}${extrasNote}`;
|
|
25161
|
+
}
|
|
25905
25162
|
function reviewLines(state) {
|
|
25906
25163
|
const { target, clis, policies, cwd, customEnabled, installDaemon, connect } = state;
|
|
25907
25164
|
const scopes = scopesFor(target);
|
|
25908
25165
|
const where = target === "both" ? `Global, plus this project (${homeify2(cwd)})` : target === "project" ? `This project (${homeify2(cwd)})` : "Everywhere (global)";
|
|
25909
25166
|
const lines = [];
|
|
25910
|
-
const
|
|
25167
|
+
const harnessNames = clis.map((c2) => getIntegration(c2).displayName);
|
|
25911
25168
|
lines.push(` Where : ${where}`);
|
|
25912
|
-
lines.push(`
|
|
25169
|
+
lines.push(` Harnesses : ${harnessNames.length ? summarize(harnessNames, "harnesses") : "(none)"}`);
|
|
25913
25170
|
lines.push(policies.length === 0 ? " Policies : none enabled (add later: failproofai policies --install)" : ` Policies : ${policies.length} enabled`);
|
|
25914
25171
|
if (installDaemon && isDaemonSupportedPlatform()) {
|
|
25915
25172
|
lines.push(` Daemon : failproofaid, installed as a system service running as you`);
|
|
@@ -25955,12 +25212,12 @@ function firstRunMarkerPath() {
|
|
|
25955
25212
|
return launcherMarker();
|
|
25956
25213
|
}
|
|
25957
25214
|
function hasSeenLauncher() {
|
|
25958
|
-
return
|
|
25215
|
+
return existsSync31(firstRunMarkerPath());
|
|
25959
25216
|
}
|
|
25960
25217
|
function markLauncherSeen() {
|
|
25961
25218
|
try {
|
|
25962
|
-
|
|
25963
|
-
|
|
25219
|
+
mkdirSync19(dirname16(firstRunMarkerPath()), { recursive: true });
|
|
25220
|
+
writeFileSync17(firstRunMarkerPath(), "1", "utf8");
|
|
25964
25221
|
} catch {}
|
|
25965
25222
|
}
|
|
25966
25223
|
function retryProbe() {
|
|
@@ -26053,7 +25310,20 @@ on its own.
|
|
|
26053
25310
|
return { applied: false };
|
|
26054
25311
|
}
|
|
26055
25312
|
emit("configure_started", {});
|
|
26056
|
-
|
|
25313
|
+
if (!isDaemonSupportedPlatform()) {
|
|
25314
|
+
stdout.write(`failproofai requires failproofaid, its background policy daemon, which runs on
|
|
25315
|
+
` + `Linux and macOS only — not ${process.platform}. Setup cannot continue here: an
|
|
25316
|
+
installation with no daemon behind it would read as configured while enforcing
|
|
25317
|
+
nothing, which is worse than not being set up at all.
|
|
25318
|
+
|
|
25319
|
+
Nothing was changed. This platform will be supported once failproofaid gains a
|
|
25320
|
+
${process.platform} service target.
|
|
25321
|
+
|
|
25322
|
+
`);
|
|
25323
|
+
emit("configure_aborted", { reason: "unsupported_platform" });
|
|
25324
|
+
return { applied: false, abort: "unsupported_platform" };
|
|
25325
|
+
}
|
|
25326
|
+
intro("let's set up failproofai", stdout);
|
|
26057
25327
|
const cancel = () => {
|
|
26058
25328
|
outro("Cancelled — nothing was changed.", { ok: false }, stdout);
|
|
26059
25329
|
return { applied: false, abort: "cancelled" };
|
|
@@ -26141,37 +25411,48 @@ refreshed. Re-run \`failproofai config\` once you can use sudo.
|
|
|
26141
25411
|
const customEnabledBefore = readHooksConfig().customPoliciesEnabled !== false;
|
|
26142
25412
|
const presetChoices = buildPresetChoices(cwd, customEnabledBefore);
|
|
26143
25413
|
const hasCustomFiles = describeCustomPolicies(cwd).fileCount > 0;
|
|
26144
|
-
|
|
26145
|
-
|
|
26146
|
-
|
|
26147
|
-
|
|
26148
|
-
|
|
26149
|
-
|
|
26150
|
-
|
|
26151
|
-
|
|
26152
|
-
|
|
26153
|
-
|
|
26154
|
-
|
|
26155
|
-
|
|
26156
|
-
|
|
26157
|
-
|
|
26158
|
-
|
|
26159
|
-
|
|
26160
|
-
|
|
26161
|
-
|
|
26162
|
-
|
|
26163
|
-
|
|
26164
|
-
|
|
26165
|
-
|
|
26166
|
-
|
|
26167
|
-
|
|
26168
|
-
|
|
26169
|
-
|
|
26170
|
-
|
|
26171
|
-
|
|
26172
|
-
|
|
26173
|
-
|
|
26174
|
-
|
|
25414
|
+
let presets = null;
|
|
25415
|
+
let clisSel = null;
|
|
25416
|
+
while (clisSel === null) {
|
|
25417
|
+
const priorPresets = presets;
|
|
25418
|
+
presets = await multiSelect({
|
|
25419
|
+
message: "What should we guard against?",
|
|
25420
|
+
choices: priorPresets ? presetChoices.map((c2) => ({ ...c2, checked: priorPresets.includes(c2.value) })) : presetChoices,
|
|
25421
|
+
summaryNoun: "bundles",
|
|
25422
|
+
hint: "space toggles · combine presets · ↵ confirm · none is fine",
|
|
25423
|
+
stdin,
|
|
25424
|
+
stdout
|
|
25425
|
+
});
|
|
25426
|
+
if (presets === null)
|
|
25427
|
+
return cancel();
|
|
25428
|
+
const priorClis = clisSel;
|
|
25429
|
+
const picked = await multiSelect({
|
|
25430
|
+
message: "Which harnesses should it protect?",
|
|
25431
|
+
choices: [
|
|
25432
|
+
{
|
|
25433
|
+
label: "Everything available",
|
|
25434
|
+
value: ALL_CLIS,
|
|
25435
|
+
hint: `protect all ${clisSupportingScope(primaryScope).length} CLIs configurable here`,
|
|
25436
|
+
summaryExclude: true
|
|
25437
|
+
},
|
|
25438
|
+
...buildAgentChoices(primaryScope, cwd)
|
|
25439
|
+
].map((c2) => priorClis ? { ...c2, checked: priorClis.includes(c2.value) } : c2),
|
|
25440
|
+
minSelected: 1,
|
|
25441
|
+
summaryNoun: "harnesses",
|
|
25442
|
+
hint: "detected CLIs are pre-selected · space toggles · ctrl+a all · ← back · ↵ confirm",
|
|
25443
|
+
allowBack: true,
|
|
25444
|
+
stdin,
|
|
25445
|
+
stdout
|
|
25446
|
+
});
|
|
25447
|
+
if (picked === null)
|
|
25448
|
+
return cancel();
|
|
25449
|
+
if (picked === BACK)
|
|
25450
|
+
continue;
|
|
25451
|
+
clisSel = picked;
|
|
25452
|
+
}
|
|
25453
|
+
const chosenPresets = presets ?? [];
|
|
25454
|
+
const policies = resolvePresetSelection(chosenPresets);
|
|
25455
|
+
const customEnabled = hasCustomFiles ? chosenPresets.includes(CUSTOM) : undefined;
|
|
26175
25456
|
const supported = new Set(scopes.flatMap((s) => clisSupportingScope(s)));
|
|
26176
25457
|
const clis = (clisSel.includes(ALL_CLIS) ? [...INTEGRATION_TYPES] : clisSel.filter((v) => v !== ALL_CLIS)).filter((id) => supported.has(id));
|
|
26177
25458
|
let connect = null;
|
|
@@ -26184,15 +25465,15 @@ refreshed. Re-run \`failproofai config\` once you can use sudo.
|
|
|
26184
25465
|
" dashboard. Staying local sends nothing, anywhere, ever."
|
|
26185
25466
|
],
|
|
26186
25467
|
choices: [
|
|
26187
|
-
{
|
|
26188
|
-
label: "Not now — stay local",
|
|
26189
|
-
value: "local",
|
|
26190
|
-
hint: "policies still enforce · connect later with failproofai config --connect"
|
|
26191
|
-
},
|
|
26192
25468
|
{
|
|
26193
25469
|
label: "Paste an API key",
|
|
26194
25470
|
value: "key",
|
|
26195
25471
|
hint: "reports decisions and transcripts to your dashboard"
|
|
25472
|
+
},
|
|
25473
|
+
{
|
|
25474
|
+
label: "Not now — stay local",
|
|
25475
|
+
value: "local",
|
|
25476
|
+
hint: "policies still enforce · connect later with failproofai config --connect"
|
|
26196
25477
|
}
|
|
26197
25478
|
],
|
|
26198
25479
|
stdin,
|
|
@@ -26406,7 +25687,7 @@ Hooks keep enforcing; scheduled audits stay off until it is.
|
|
|
26406
25687
|
cli: clis,
|
|
26407
25688
|
cli_count: clis.length,
|
|
26408
25689
|
policy_count: policies.length,
|
|
26409
|
-
source:
|
|
25690
|
+
source: chosenPresets.join("+"),
|
|
26410
25691
|
connected: connect !== null
|
|
26411
25692
|
});
|
|
26412
25693
|
for (const scope of scopes) {
|
|
@@ -26445,11 +25726,7 @@ Hooks keep enforcing; scheduled audits stay off until it is.
|
|
|
26445
25726
|
await applied;
|
|
26446
25727
|
markLauncherSeen();
|
|
26447
25728
|
clearOnboardingAttempt();
|
|
26448
|
-
|
|
26449
|
-
const daemonNote = daemonInstalled ? " · daemon on" : "";
|
|
26450
|
-
const cloudNote = connected ? " · reporting on" : "";
|
|
26451
|
-
const assistants = `${clis.length} assistant${clis.length === 1 ? "" : "s"}`;
|
|
26452
|
-
outro(`Setup complete — ${policies.length} policies${customNote} · ${assistants}${daemonNote}${cloudNote}`, { ok: true }, stdout);
|
|
25729
|
+
outro(buildCompletionSummary(policies.length, clis.length, customEnabled, daemonInstalled, connected), { ok: true }, stdout);
|
|
26453
25730
|
return {
|
|
26454
25731
|
applied: true,
|
|
26455
25732
|
target,
|
|
@@ -26484,6 +25761,121 @@ var init_configure_wizard = __esm(() => {
|
|
|
26484
25761
|
init_onboarding_lock();
|
|
26485
25762
|
});
|
|
26486
25763
|
|
|
25764
|
+
// src/hooks/flush-cli.ts
|
|
25765
|
+
var exports_flush_cli = {};
|
|
25766
|
+
__export(exports_flush_cli, {
|
|
25767
|
+
runFlushCommand: () => runFlushCommand,
|
|
25768
|
+
pendingBatches: () => pendingBatches,
|
|
25769
|
+
flushRequestPath: () => flushRequestPath,
|
|
25770
|
+
DEFAULT_FLUSH_TIMEOUT_SECS: () => DEFAULT_FLUSH_TIMEOUT_SECS
|
|
25771
|
+
});
|
|
25772
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync20, writeFileSync as writeFileSync18, readdirSync as readdirSync16 } from "node:fs";
|
|
25773
|
+
import { dirname as dirname17, join as join30 } from "node:path";
|
|
25774
|
+
function flushRequestPath(home) {
|
|
25775
|
+
return join30(failproofaiHome(home), "state", "flush-request.json");
|
|
25776
|
+
}
|
|
25777
|
+
function spoolDirs(home) {
|
|
25778
|
+
const root = spoolDir(home);
|
|
25779
|
+
if (!existsSync32(root))
|
|
25780
|
+
return [];
|
|
25781
|
+
try {
|
|
25782
|
+
return readdirSync16(root, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name !== "failed").map((e) => join30(root, e.name));
|
|
25783
|
+
} catch {
|
|
25784
|
+
return [];
|
|
25785
|
+
}
|
|
25786
|
+
}
|
|
25787
|
+
function pendingBatches(home) {
|
|
25788
|
+
let n = 0;
|
|
25789
|
+
for (const dir of spoolDirs(home)) {
|
|
25790
|
+
try {
|
|
25791
|
+
n += readdirSync16(dir).filter((f) => f.endsWith(".jsonl")).length;
|
|
25792
|
+
} catch {}
|
|
25793
|
+
}
|
|
25794
|
+
return n;
|
|
25795
|
+
}
|
|
25796
|
+
async function runFlushCommand(opts = {}) {
|
|
25797
|
+
const { home, wait = false } = opts;
|
|
25798
|
+
const timeoutSecs = opts.timeoutSecs ?? DEFAULT_FLUSH_TIMEOUT_SECS;
|
|
25799
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
25800
|
+
const lines = [];
|
|
25801
|
+
const cfg = readConfig();
|
|
25802
|
+
if (!cfg.collector?.hooks && !cfg.collector?.sessions) {
|
|
25803
|
+
return {
|
|
25804
|
+
exitCode: 1,
|
|
25805
|
+
pending: 0,
|
|
25806
|
+
lines: [
|
|
25807
|
+
"Collection is off, so nothing is spooled to flush.",
|
|
25808
|
+
"Turn it on with `failproofai config`."
|
|
25809
|
+
]
|
|
25810
|
+
};
|
|
25811
|
+
}
|
|
25812
|
+
if (!readIngestCredential()) {
|
|
25813
|
+
return {
|
|
25814
|
+
exitCode: 1,
|
|
25815
|
+
pending: 0,
|
|
25816
|
+
lines: [
|
|
25817
|
+
"This machine is not connected, so there is nowhere to flush to.",
|
|
25818
|
+
"Connect it with `failproofai config`."
|
|
25819
|
+
]
|
|
25820
|
+
};
|
|
25821
|
+
}
|
|
25822
|
+
if (!isDaemonSupportedPlatform()) {
|
|
25823
|
+
return {
|
|
25824
|
+
exitCode: 1,
|
|
25825
|
+
pending: pendingBatches(home),
|
|
25826
|
+
lines: [
|
|
25827
|
+
`failproofaid does not run on ${process.platform}, and it is what delivers batches.`,
|
|
25828
|
+
"Nothing would pick this request up, so nothing was written."
|
|
25829
|
+
]
|
|
25830
|
+
};
|
|
25831
|
+
}
|
|
25832
|
+
const status = daemonServiceStatus();
|
|
25833
|
+
if (status !== "running") {
|
|
25834
|
+
return {
|
|
25835
|
+
exitCode: 1,
|
|
25836
|
+
pending: pendingBatches(home),
|
|
25837
|
+
lines: [
|
|
25838
|
+
`failproofaid is ${status}, and it is what delivers batches.`,
|
|
25839
|
+
"Start it with `failproofai config`."
|
|
25840
|
+
]
|
|
25841
|
+
};
|
|
25842
|
+
}
|
|
25843
|
+
const before = pendingBatches(home);
|
|
25844
|
+
if (before === 0) {
|
|
25845
|
+
return { exitCode: 0, pending: 0, lines: ["Nothing spooled — everything already delivered."] };
|
|
25846
|
+
}
|
|
25847
|
+
const path3 = flushRequestPath(home);
|
|
25848
|
+
mkdirSync20(dirname17(path3), { recursive: true });
|
|
25849
|
+
writeFileSync18(path3, `${JSON.stringify({ requestedAtMs: Date.now() }, null, 2)}
|
|
25850
|
+
`, {
|
|
25851
|
+
mode: 384
|
|
25852
|
+
});
|
|
25853
|
+
lines.push(`${before} batch${before === 1 ? "" : "es"} spooled. Requested delivery.`);
|
|
25854
|
+
if (!wait) {
|
|
25855
|
+
lines.push("The daemon picks this up within a few seconds.");
|
|
25856
|
+
return { exitCode: 0, pending: before, lines };
|
|
25857
|
+
}
|
|
25858
|
+
const deadline = Date.now() + timeoutSecs * 1000;
|
|
25859
|
+
let pending3 = before;
|
|
25860
|
+
while (Date.now() < deadline) {
|
|
25861
|
+
await sleep(1000);
|
|
25862
|
+
pending3 = pendingBatches(home);
|
|
25863
|
+
if (pending3 === 0) {
|
|
25864
|
+
lines.push("Spool drained.");
|
|
25865
|
+
return { exitCode: 0, pending: 0, lines };
|
|
25866
|
+
}
|
|
25867
|
+
}
|
|
25868
|
+
lines.push(`Still ${pending3} batch${pending3 === 1 ? "" : "es"} spooled after ${timeoutSecs}s.`, "Delivery continues in the background; re-run with a longer --timeout to keep watching.");
|
|
25869
|
+
return { exitCode: 1, pending: pending3, lines };
|
|
25870
|
+
}
|
|
25871
|
+
var DEFAULT_FLUSH_TIMEOUT_SECS = 60;
|
|
25872
|
+
var init_flush_cli = __esm(() => {
|
|
25873
|
+
init_fp_home();
|
|
25874
|
+
init_fp_config();
|
|
25875
|
+
init_collector_config();
|
|
25876
|
+
init_daemon_service();
|
|
25877
|
+
});
|
|
25878
|
+
|
|
26487
25879
|
// src/hooks/backfill-cli.ts
|
|
26488
25880
|
var exports_backfill_cli = {};
|
|
26489
25881
|
__export(exports_backfill_cli, {
|
|
@@ -26491,16 +25883,16 @@ __export(exports_backfill_cli, {
|
|
|
26491
25883
|
backfillRequestPath: () => backfillRequestPath,
|
|
26492
25884
|
DEFAULT_BACKFILL_DAYS: () => DEFAULT_BACKFILL_DAYS
|
|
26493
25885
|
});
|
|
26494
|
-
import { existsSync as
|
|
26495
|
-
import { dirname as
|
|
25886
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync21, writeFileSync as writeFileSync19, readdirSync as readdirSync17, statSync as statSync23 } from "node:fs";
|
|
25887
|
+
import { dirname as dirname18, join as join31 } from "node:path";
|
|
26496
25888
|
function backfillRequestPath(home) {
|
|
26497
|
-
return
|
|
25889
|
+
return join31(failproofaiHome(home), "state", "backfill-request.json");
|
|
26498
25890
|
}
|
|
26499
25891
|
function surveySessions(sinceMs, homeDir) {
|
|
26500
25892
|
const out = [];
|
|
26501
25893
|
for (const { cli, dir } of SESSION_DIRS) {
|
|
26502
|
-
const root =
|
|
26503
|
-
if (!
|
|
25894
|
+
const root = join31(homeDir, dir);
|
|
25895
|
+
if (!existsSync33(root))
|
|
26504
25896
|
continue;
|
|
26505
25897
|
let files = 0;
|
|
26506
25898
|
let newest = 0;
|
|
@@ -26509,18 +25901,18 @@ function surveySessions(sinceMs, homeDir) {
|
|
|
26509
25901
|
return;
|
|
26510
25902
|
let entries;
|
|
26511
25903
|
try {
|
|
26512
|
-
entries =
|
|
25904
|
+
entries = readdirSync17(d, { withFileTypes: true });
|
|
26513
25905
|
} catch {
|
|
26514
25906
|
return;
|
|
26515
25907
|
}
|
|
26516
25908
|
for (const e of entries) {
|
|
26517
|
-
const p =
|
|
25909
|
+
const p = join31(d, e.name);
|
|
26518
25910
|
if (e.isDirectory()) {
|
|
26519
25911
|
walk(p, depth + 1);
|
|
26520
25912
|
continue;
|
|
26521
25913
|
}
|
|
26522
25914
|
try {
|
|
26523
|
-
const st =
|
|
25915
|
+
const st = statSync23(p);
|
|
26524
25916
|
if (st.mtimeMs >= sinceMs) {
|
|
26525
25917
|
files += 1;
|
|
26526
25918
|
newest = Math.max(newest, st.mtimeMs);
|
|
@@ -26538,7 +25930,7 @@ function runBackfillCommand(opts = {}) {
|
|
|
26538
25930
|
const now = opts.now ?? Date.now();
|
|
26539
25931
|
const sinceMs = opts.sinceMs ?? now - DEFAULT_BACKFILL_DAYS * 24 * 60 * 60 * 1000;
|
|
26540
25932
|
const home = failproofaiHome();
|
|
26541
|
-
if (!
|
|
25933
|
+
if (!existsSync33(home)) {
|
|
26542
25934
|
return {
|
|
26543
25935
|
exitCode: 1,
|
|
26544
25936
|
lines: [`No failproofai home at ${home}. Run \`failproofai config\` first.`]
|
|
@@ -26566,11 +25958,11 @@ function runBackfillCommand(opts = {}) {
|
|
|
26566
25958
|
exitCode: 1,
|
|
26567
25959
|
lines: [
|
|
26568
25960
|
"Collection is switched off, so a backfill would re-read history and send",
|
|
26569
|
-
|
|
25961
|
+
'none of it. Enable it in ~/.failproofai/config.json under "collector".'
|
|
26570
25962
|
]
|
|
26571
25963
|
};
|
|
26572
25964
|
}
|
|
26573
|
-
const found = surveySessions(sinceMs,
|
|
25965
|
+
const found = surveySessions(sinceMs, dirname18(home));
|
|
26574
25966
|
const totalFiles = found.reduce((n, f) => n + f.files, 0);
|
|
26575
25967
|
const sinceLabel = new Date(sinceMs).toISOString().slice(0, 10);
|
|
26576
25968
|
const lines = [
|
|
@@ -26593,8 +25985,8 @@ function runBackfillCommand(opts = {}) {
|
|
|
26593
25985
|
}
|
|
26594
25986
|
try {
|
|
26595
25987
|
const path3 = backfillRequestPath();
|
|
26596
|
-
|
|
26597
|
-
|
|
25988
|
+
mkdirSync21(dirname18(path3), { recursive: true });
|
|
25989
|
+
writeFileSync19(path3, `${JSON.stringify({ sinceMs, requestedAtMs: now }, null, 2)}
|
|
26598
25990
|
`, {
|
|
26599
25991
|
mode: 384
|
|
26600
25992
|
});
|
|
@@ -26635,13 +26027,210 @@ var init_backfill_cli = __esm(() => {
|
|
|
26635
26027
|
];
|
|
26636
26028
|
});
|
|
26637
26029
|
|
|
26030
|
+
// src/hooks/harness-cli.ts
|
|
26031
|
+
var exports_harness_cli = {};
|
|
26032
|
+
__export(exports_harness_cli, {
|
|
26033
|
+
runHarnessCommand: () => runHarnessCommand,
|
|
26034
|
+
removePath: () => removePath,
|
|
26035
|
+
listPaths: () => listPaths,
|
|
26036
|
+
addPath: () => addPath,
|
|
26037
|
+
HARNESS_KEYS: () => HARNESS_KEYS
|
|
26038
|
+
});
|
|
26039
|
+
function unknownHarness(name) {
|
|
26040
|
+
return fail([
|
|
26041
|
+
`Unknown harness: ${name}`,
|
|
26042
|
+
"",
|
|
26043
|
+
`Known harnesses: ${HARNESS_KEYS.join(", ")}`
|
|
26044
|
+
]);
|
|
26045
|
+
}
|
|
26046
|
+
function pathOf(entry) {
|
|
26047
|
+
const eq = entry.indexOf("=");
|
|
26048
|
+
if (eq <= 0)
|
|
26049
|
+
return entry.trim();
|
|
26050
|
+
const label = entry.slice(0, eq).trim();
|
|
26051
|
+
return label === "" ? entry.trim() : entry.slice(eq + 1).trim();
|
|
26052
|
+
}
|
|
26053
|
+
function labelOf(entry) {
|
|
26054
|
+
const eq = entry.indexOf("=");
|
|
26055
|
+
if (eq <= 0)
|
|
26056
|
+
return null;
|
|
26057
|
+
const label = entry.slice(0, eq).trim();
|
|
26058
|
+
return label === "" ? null : label;
|
|
26059
|
+
}
|
|
26060
|
+
function currentPaths(harness) {
|
|
26061
|
+
return readConfig().collector.sources?.[harness]?.extraPaths ?? [];
|
|
26062
|
+
}
|
|
26063
|
+
function writePaths(harness, paths) {
|
|
26064
|
+
const cfg = readConfig();
|
|
26065
|
+
const sources = { ...cfg.collector.sources ?? {} };
|
|
26066
|
+
if (paths.length > 0)
|
|
26067
|
+
sources[harness] = { extraPaths: paths };
|
|
26068
|
+
else
|
|
26069
|
+
delete sources[harness];
|
|
26070
|
+
updateConfig({
|
|
26071
|
+
collector: {
|
|
26072
|
+
...cfg.collector,
|
|
26073
|
+
sources: Object.keys(sources).length > 0 ? sources : undefined
|
|
26074
|
+
}
|
|
26075
|
+
});
|
|
26076
|
+
}
|
|
26077
|
+
function addPath(harness, entry) {
|
|
26078
|
+
if (!HARNESS_KEYS.includes(harness))
|
|
26079
|
+
return unknownHarness(harness);
|
|
26080
|
+
const trimmed = entry.trim();
|
|
26081
|
+
if (trimmed === "")
|
|
26082
|
+
return fail(["A path is required."]);
|
|
26083
|
+
if (pathOf(trimmed) === "") {
|
|
26084
|
+
return fail([`Could not read a path out of ${JSON.stringify(entry)}.`, "", "Use `<path>` or `<label>=<path>`."]);
|
|
26085
|
+
}
|
|
26086
|
+
const existing = currentPaths(harness);
|
|
26087
|
+
if (existing.includes(trimmed)) {
|
|
26088
|
+
return ok([`${harness}: ${trimmed} is already configured.`]);
|
|
26089
|
+
}
|
|
26090
|
+
const samePath = existing.find((e) => pathOf(e) === pathOf(trimmed));
|
|
26091
|
+
if (samePath) {
|
|
26092
|
+
return fail([
|
|
26093
|
+
`${harness} already captures ${pathOf(trimmed)} as ${JSON.stringify(samePath)}.`,
|
|
26094
|
+
"",
|
|
26095
|
+
"Remove it first if you meant to relabel it:",
|
|
26096
|
+
` failproofai harness remove-path ${harness} ${pathOf(trimmed)}`
|
|
26097
|
+
]);
|
|
26098
|
+
}
|
|
26099
|
+
const wanted = labelOf(trimmed);
|
|
26100
|
+
if (wanted) {
|
|
26101
|
+
const sameLabel = existing.find((e) => labelOf(e) === wanted);
|
|
26102
|
+
if (sameLabel) {
|
|
26103
|
+
return fail([
|
|
26104
|
+
`${harness} already uses the label ${JSON.stringify(wanted)} for ${pathOf(sameLabel)}.`,
|
|
26105
|
+
"",
|
|
26106
|
+
"Labels namespace agent ids, so two paths cannot share one."
|
|
26107
|
+
]);
|
|
26108
|
+
}
|
|
26109
|
+
}
|
|
26110
|
+
writePaths(harness, [...existing, trimmed]);
|
|
26111
|
+
return ok([
|
|
26112
|
+
`${harness}: now also capturing ${pathOf(trimmed)}`,
|
|
26113
|
+
wanted ? ` agent ids will be namespaced ${wanted}-*` : " a label will be derived from the folder name; `failproofai harness list` shows it",
|
|
26114
|
+
` written to ${configFile()}`,
|
|
26115
|
+
...TAKES_EFFECT_HINT
|
|
26116
|
+
]);
|
|
26117
|
+
}
|
|
26118
|
+
function removePath(harness, target) {
|
|
26119
|
+
if (!HARNESS_KEYS.includes(harness))
|
|
26120
|
+
return unknownHarness(harness);
|
|
26121
|
+
const existing = currentPaths(harness);
|
|
26122
|
+
const t = target.trim();
|
|
26123
|
+
const kept = existing.filter((e) => e !== t && pathOf(e) !== t && labelOf(e) !== t);
|
|
26124
|
+
if (kept.length === existing.length) {
|
|
26125
|
+
return fail([
|
|
26126
|
+
`${harness} has no extra path matching ${JSON.stringify(t)}.`,
|
|
26127
|
+
"",
|
|
26128
|
+
existing.length > 0 ? `Configured: ${existing.join(", ")}` : `${harness} has no extra paths configured.`
|
|
26129
|
+
]);
|
|
26130
|
+
}
|
|
26131
|
+
writePaths(harness, kept);
|
|
26132
|
+
return ok([
|
|
26133
|
+
`${harness}: no longer capturing ${t}`,
|
|
26134
|
+
"",
|
|
26135
|
+
"Already-collected sessions from that path are NOT removed — they are on the",
|
|
26136
|
+
"server. This only stops new ones.",
|
|
26137
|
+
...TAKES_EFFECT_HINT
|
|
26138
|
+
]);
|
|
26139
|
+
}
|
|
26140
|
+
function listPaths(harness) {
|
|
26141
|
+
if (harness && !HARNESS_KEYS.includes(harness))
|
|
26142
|
+
return unknownHarness(harness);
|
|
26143
|
+
const sources = readConfig().collector.sources ?? {};
|
|
26144
|
+
const names = harness ? [harness] : HARNESS_KEYS.filter((k) => sources[k]?.extraPaths?.length);
|
|
26145
|
+
const unknown = Object.keys(sources).filter((k) => !HARNESS_KEYS.includes(k));
|
|
26146
|
+
if (names.length === 0 && unknown.length === 0) {
|
|
26147
|
+
return ok([
|
|
26148
|
+
"No extra capture paths configured.",
|
|
26149
|
+
"",
|
|
26150
|
+
"Every harness is watching only its default location. Add one with:",
|
|
26151
|
+
" failproofai harness add-path <harness> [<label>=]<path>",
|
|
26152
|
+
"",
|
|
26153
|
+
`Harnesses: ${HARNESS_KEYS.join(", ")}`
|
|
26154
|
+
]);
|
|
26155
|
+
}
|
|
26156
|
+
const lines = [];
|
|
26157
|
+
for (const name of names) {
|
|
26158
|
+
const entries = sources[name]?.extraPaths ?? [];
|
|
26159
|
+
if (entries.length === 0) {
|
|
26160
|
+
if (harness)
|
|
26161
|
+
lines.push(`${name}: no extra paths configured (default location only)`);
|
|
26162
|
+
continue;
|
|
26163
|
+
}
|
|
26164
|
+
lines.push(`${name}:`);
|
|
26165
|
+
for (const e of entries) {
|
|
26166
|
+
const label = labelOf(e);
|
|
26167
|
+
lines.push(label ? ` ${pathOf(e)} → agent ids ${label}-*` : ` ${pathOf(e)} → label derived from the folder name`);
|
|
26168
|
+
}
|
|
26169
|
+
}
|
|
26170
|
+
if (unknown.length > 0) {
|
|
26171
|
+
if (lines.length === 0)
|
|
26172
|
+
lines.push("No extra capture paths configured for any known harness.");
|
|
26173
|
+
lines.push("", `⚠ config.json configures ${unknown.length} unknown harness(es): ${unknown.join(", ")}`, " Nothing is captured from them.", ` Known: ${HARNESS_KEYS.join(", ")}`);
|
|
26174
|
+
}
|
|
26175
|
+
return ok(lines);
|
|
26176
|
+
}
|
|
26177
|
+
function runHarnessCommand(argv) {
|
|
26178
|
+
const [sub, ...rest] = argv;
|
|
26179
|
+
switch (sub) {
|
|
26180
|
+
case "add-path":
|
|
26181
|
+
if (rest.length < 2) {
|
|
26182
|
+
return fail(["Usage: failproofai harness add-path <harness> [<label>=]<path>"]);
|
|
26183
|
+
}
|
|
26184
|
+
return addPath(rest[0], rest.slice(1).join(" "));
|
|
26185
|
+
case "remove-path":
|
|
26186
|
+
if (rest.length < 2) {
|
|
26187
|
+
return fail(["Usage: failproofai harness remove-path <harness> <path|label>"]);
|
|
26188
|
+
}
|
|
26189
|
+
return removePath(rest[0], rest.slice(1).join(" "));
|
|
26190
|
+
case "list":
|
|
26191
|
+
return listPaths(rest[0]);
|
|
26192
|
+
default:
|
|
26193
|
+
return fail([
|
|
26194
|
+
sub ? `Unknown subcommand: ${sub}` : "A subcommand is required.",
|
|
26195
|
+
"",
|
|
26196
|
+
"Usage:",
|
|
26197
|
+
" failproofai harness list [<harness>]",
|
|
26198
|
+
" failproofai harness add-path <harness> [<label>=]<path>",
|
|
26199
|
+
" failproofai harness remove-path <harness> <path|label>"
|
|
26200
|
+
]);
|
|
26201
|
+
}
|
|
26202
|
+
}
|
|
26203
|
+
var HARNESS_KEYS, ok = (lines) => ({ lines, exitCode: 0 }), fail = (lines) => ({ lines, exitCode: 1 }), TAKES_EFFECT_HINT;
|
|
26204
|
+
var init_harness_cli = __esm(() => {
|
|
26205
|
+
init_fp_config();
|
|
26206
|
+
init_fp_home();
|
|
26207
|
+
HARNESS_KEYS = [
|
|
26208
|
+
"claude",
|
|
26209
|
+
"codex",
|
|
26210
|
+
"copilot",
|
|
26211
|
+
"openclaw",
|
|
26212
|
+
"pi",
|
|
26213
|
+
"factory",
|
|
26214
|
+
"antigravity",
|
|
26215
|
+
"cursor",
|
|
26216
|
+
"goose",
|
|
26217
|
+
"opencode",
|
|
26218
|
+
"devin",
|
|
26219
|
+
"hermes"
|
|
26220
|
+
];
|
|
26221
|
+
TAKES_EFFECT_HINT = [
|
|
26222
|
+
"",
|
|
26223
|
+
"The daemon picks this up on its own within a few seconds — no restart, no sudo."
|
|
26224
|
+
];
|
|
26225
|
+
});
|
|
26226
|
+
|
|
26638
26227
|
// src/hooks/uninstall-cli.ts
|
|
26639
26228
|
var exports_uninstall_cli = {};
|
|
26640
26229
|
__export(exports_uninstall_cli, {
|
|
26641
26230
|
serviceStateLabel: () => serviceStateLabel,
|
|
26642
26231
|
runUninstallCommand: () => runUninstallCommand
|
|
26643
26232
|
});
|
|
26644
|
-
import { existsSync as
|
|
26233
|
+
import { existsSync as existsSync34, rmSync as rmSync11 } from "node:fs";
|
|
26645
26234
|
function survey(cwd) {
|
|
26646
26235
|
const clis = [];
|
|
26647
26236
|
for (const id of listInstallableIds()) {
|
|
@@ -26662,9 +26251,9 @@ function survey(cwd) {
|
|
|
26662
26251
|
return {
|
|
26663
26252
|
clis,
|
|
26664
26253
|
servicePath,
|
|
26665
|
-
serviceInstalled: !!servicePath &&
|
|
26254
|
+
serviceInstalled: !!servicePath && existsSync34(servicePath),
|
|
26666
26255
|
daemonConfigured,
|
|
26667
|
-
homeExists:
|
|
26256
|
+
homeExists: existsSync34(failproofaiHome())
|
|
26668
26257
|
};
|
|
26669
26258
|
}
|
|
26670
26259
|
async function runUninstallCommand(opts = {}) {
|
|
@@ -26731,7 +26320,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
26731
26320
|
purged: false,
|
|
26732
26321
|
lines: [
|
|
26733
26322
|
...lines,
|
|
26734
|
-
`✗ could not update ${failproofaiHome()}/config.
|
|
26323
|
+
`✗ could not update ${failproofaiHome()}/config.json: ${err instanceof Error ? err.message : String(err)}`,
|
|
26735
26324
|
``,
|
|
26736
26325
|
`Stopped before touching the service. Removing it while this machine still`,
|
|
26737
26326
|
`requires it would deny every tool call. Fix the file's permissions and re-run.`
|
|
@@ -26754,7 +26343,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
26754
26343
|
if (found.serviceInstalled) {
|
|
26755
26344
|
try {
|
|
26756
26345
|
await uninstallDaemonService();
|
|
26757
|
-
if (found.servicePath &&
|
|
26346
|
+
if (found.servicePath && existsSync34(found.servicePath)) {
|
|
26758
26347
|
failures.push(`the service at ${found.servicePath} is still there (most often: no sudo). ` + `Remove it with the commands below.`);
|
|
26759
26348
|
} else {
|
|
26760
26349
|
lines.push(`✓ stopped and removed the daemon service`);
|
|
@@ -26765,7 +26354,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
26765
26354
|
}
|
|
26766
26355
|
if (opts.purge && found.homeExists) {
|
|
26767
26356
|
try {
|
|
26768
|
-
|
|
26357
|
+
rmSync11(failproofaiHome(), { recursive: true, force: true });
|
|
26769
26358
|
purged = true;
|
|
26770
26359
|
lines.push(`✓ deleted ${failproofaiHome()}`);
|
|
26771
26360
|
} catch (err) {
|
|
@@ -26776,7 +26365,7 @@ async function runUninstallCommand(opts = {}) {
|
|
|
26776
26365
|
lines.push(``, `Not everything could be removed:`);
|
|
26777
26366
|
for (const f of failures)
|
|
26778
26367
|
lines.push(` ✗ ${f}`);
|
|
26779
|
-
if (found.servicePath &&
|
|
26368
|
+
if (found.servicePath && existsSync34(found.servicePath)) {
|
|
26780
26369
|
lines.push(``, `To remove the service by hand:`, ...manualServiceRemoval(found.servicePath), ``, `(\`${daemonStatusCommand()}\` shows its current state.)`);
|
|
26781
26370
|
}
|
|
26782
26371
|
return { exitCode: 1, lines, planLines, purged };
|
|
@@ -26836,6 +26425,7 @@ __export(exports_tui, {
|
|
|
26836
26425
|
CHECK_OFF: () => CHECK_OFF2,
|
|
26837
26426
|
CARET: () => CARET2,
|
|
26838
26427
|
BAR: () => BAR2,
|
|
26428
|
+
BACK: () => BACK2,
|
|
26839
26429
|
ANSI_RESET: () => ANSI_RESET2,
|
|
26840
26430
|
ANSI_DIM: () => ANSI_DIM2,
|
|
26841
26431
|
ANSI_BOLD: () => ANSI_BOLD2
|
|
@@ -26979,14 +26569,14 @@ function renderLaunchBanner2(version3, stdout = process.stdout) {
|
|
|
26979
26569
|
}
|
|
26980
26570
|
function outro2(message, opts = {}, stdout = process.stdout) {
|
|
26981
26571
|
const c2 = paint2(colorsEnabled2(stdout));
|
|
26982
|
-
const
|
|
26572
|
+
const ok2 = opts.ok !== false;
|
|
26983
26573
|
if (!stdout.isTTY) {
|
|
26984
26574
|
stdout.write(message + `
|
|
26985
26575
|
`);
|
|
26986
26576
|
return;
|
|
26987
26577
|
}
|
|
26988
|
-
const end =
|
|
26989
|
-
const text =
|
|
26578
|
+
const end = ok2 ? c2.pink(BAR_END2) : c2.dim(BAR_END2);
|
|
26579
|
+
const text = ok2 ? c2.pink(message) : c2.dim(message);
|
|
26990
26580
|
writeLines2(stdout, [c2.dim(BAR2), `${end} ${text}`]);
|
|
26991
26581
|
}
|
|
26992
26582
|
function repaint2(out, region, lines) {
|
|
@@ -27062,10 +26652,11 @@ function runPrompt2(p) {
|
|
|
27062
26652
|
return lines;
|
|
27063
26653
|
};
|
|
27064
26654
|
const collapse = (result) => {
|
|
26655
|
+
const summary = result === BACK2 ? "back" : p.summaryFor(result);
|
|
27065
26656
|
repaint2(stdout, region, [
|
|
27066
26657
|
c2.dim(BAR2),
|
|
27067
26658
|
`${c2.dim(STEP_DONE2)} ${p.message}`,
|
|
27068
|
-
`${c2.dim(BAR2)} ${c2.dim(
|
|
26659
|
+
`${c2.dim(BAR2)} ${c2.dim(summary)}`
|
|
27069
26660
|
]);
|
|
27070
26661
|
};
|
|
27071
26662
|
return new Promise((resolve24) => {
|
|
@@ -27091,6 +26682,8 @@ function runPrompt2(p) {
|
|
|
27091
26682
|
return;
|
|
27092
26683
|
if (key.ctrl && (key.name === "c" || key.name === "d") || key.name === "escape") {
|
|
27093
26684
|
finish(null);
|
|
26685
|
+
} else if (key.name === "left" && p.allowBack) {
|
|
26686
|
+
finish(BACK2);
|
|
27094
26687
|
} else if (key.name === "up") {
|
|
27095
26688
|
cursor2 = cursor2 > 0 ? cursor2 - 1 : choices.length - 1;
|
|
27096
26689
|
repaint2(stdout, region, build());
|
|
@@ -27134,7 +26727,8 @@ function selectOne2(opts) {
|
|
|
27134
26727
|
const hint = choice.hint ? ` ${c2.dim(ellipsize2(choice.hint, budget))}` : "";
|
|
27135
26728
|
return `${dot} ${label}${hint}`;
|
|
27136
26729
|
},
|
|
27137
|
-
|
|
26730
|
+
allowBack: opts.allowBack,
|
|
26731
|
+
footer: opts.allowBack ? "↑/↓ navigate · enter to select · ← back · esc to cancel" : "↑/↓ navigate · enter to select · esc to cancel",
|
|
27138
26732
|
onKey: (key, cursor2) => key.name === "return" ? { done: choices[cursor2].value } : undefined,
|
|
27139
26733
|
summaryFor: (value) => value === null ? "cancelled" : choices.find((ch) => ch.value === value)?.label ?? String(value)
|
|
27140
26734
|
});
|
|
@@ -27168,7 +26762,8 @@ function multiSelect2(opts) {
|
|
|
27168
26762
|
return `${caret} ${box} ${label}${hint}`;
|
|
27169
26763
|
},
|
|
27170
26764
|
warnLine: () => warn ? c2.warn(`Select at least ${minSelected}.`) : null,
|
|
27171
|
-
|
|
26765
|
+
allowBack: opts.allowBack,
|
|
26766
|
+
footer: opts.hint ?? (opts.allowBack ? "↑/↓ move · space select · ctrl+a all · ← back · enter confirm" : "↑/↓ move · space select · ctrl+a all · enter confirm"),
|
|
27172
26767
|
onKey: (key, cursor2) => {
|
|
27173
26768
|
if (key.name === "space") {
|
|
27174
26769
|
if (choices[cursor2]?.locked)
|
|
@@ -27230,11 +26825,13 @@ function promptText2(opts) {
|
|
|
27230
26825
|
return new Promise((resolve24) => {
|
|
27231
26826
|
let value = "";
|
|
27232
26827
|
const draw = (error) => {
|
|
26828
|
+
const cols = stdout.columns || 80;
|
|
27233
26829
|
const shown = opts.mask ? "•".repeat(value.length) : value;
|
|
27234
26830
|
const hint = opts.hint ? ` ${c2.dim(opts.hint)}` : "";
|
|
26831
|
+
const line = truncate2(`${c2.bold(opts.message)} ${shown}${hint}`, cols - 1);
|
|
27235
26832
|
const err = error ? `
|
|
27236
|
-
${c2.warn(error)}` : "";
|
|
27237
|
-
stdout.write(`\r\x1B[2K${
|
|
26833
|
+
${truncate2(c2.warn(error), cols - 3)}` : "";
|
|
26834
|
+
stdout.write(`\r\x1B[2K${line}${err}`);
|
|
27238
26835
|
if (err)
|
|
27239
26836
|
stdout.write("\x1B[1A");
|
|
27240
26837
|
};
|
|
@@ -27281,7 +26878,7 @@ function promptText2(opts) {
|
|
|
27281
26878
|
stdin.on("keypress", onKey);
|
|
27282
26879
|
});
|
|
27283
26880
|
}
|
|
27284
|
-
var ESC2 = "\x1B", BAR2 = "│", BAR_END2 = "└", STEP_ACTIVE2 = "◆", STEP_DONE2 = "◇", RADIO_ON2 = "●", RADIO_OFF2 = "○", CHECK_ON2 = "◼", CHECK_OFF2 = "◻", CARET2 = "❯", FLOWER2 = "❋", HUES2, ANSI_RESET2, ANSI_BOLD2, ANSI_DIM2, LOGO_MIN_COLS2 = 22, TAGLINE2 = "end-to-end failure layer for ai agents", LOGO_GRID2, LOGO_TEAL2, LOGO_PINK2, WINDOW3 = 8;
|
|
26881
|
+
var ESC2 = "\x1B", BAR2 = "│", BAR_END2 = "└", STEP_ACTIVE2 = "◆", STEP_DONE2 = "◇", RADIO_ON2 = "●", RADIO_OFF2 = "○", CHECK_ON2 = "◼", CHECK_OFF2 = "◻", CARET2 = "❯", FLOWER2 = "❋", HUES2, ANSI_RESET2, ANSI_BOLD2, ANSI_DIM2, LOGO_MIN_COLS2 = 22, TAGLINE2 = "end-to-end failure layer for ai agents", LOGO_GRID2, LOGO_TEAL2, LOGO_PINK2, WINDOW3 = 8, BACK2;
|
|
27285
26882
|
var init_tui2 = __esm(() => {
|
|
27286
26883
|
HUES2 = {
|
|
27287
26884
|
guide: { rgb: [102, 209, 181], basic: "36" },
|
|
@@ -27317,6 +26914,7 @@ var init_tui2 = __esm(() => {
|
|
|
27317
26914
|
];
|
|
27318
26915
|
LOGO_TEAL2 = HUES2.guide.rgb;
|
|
27319
26916
|
LOGO_PINK2 = HUES2.logoPink.rgb;
|
|
26917
|
+
BACK2 = Symbol("failproofai.back");
|
|
27320
26918
|
});
|
|
27321
26919
|
|
|
27322
26920
|
// src/hooks/manager.ts
|
|
@@ -27329,7 +26927,7 @@ __export(exports_manager, {
|
|
|
27329
26927
|
getSettingsPath: () => getSettingsPath2
|
|
27330
26928
|
});
|
|
27331
26929
|
import { execSync as execSync7 } from "node:child_process";
|
|
27332
|
-
import { existsSync as
|
|
26930
|
+
import { existsSync as existsSync35 } from "node:fs";
|
|
27333
26931
|
import { resolve as resolve24, basename as basename6 } from "node:path";
|
|
27334
26932
|
import { platform as platform5, arch as arch4, release as release3, hostname as hostname5 } from "node:os";
|
|
27335
26933
|
function getSettingsPath2(scope, cwd) {
|
|
@@ -27440,7 +27038,7 @@ async function installHooksImpl2(policyNames, scope = "user", cwd, includeBeta =
|
|
|
27440
27038
|
} else if (customPoliciesPath && (typeof customPoliciesPath === "string" || customPoliciesPath.length > 0)) {
|
|
27441
27039
|
const incoming = (typeof customPoliciesPath === "string" ? [customPoliciesPath] : customPoliciesPath).map((path3) => resolve24(path3));
|
|
27442
27040
|
const carried = (previousConfig.customPoliciesPaths ?? (previousConfig.customPoliciesPath ? [previousConfig.customPoliciesPath] : [])).map((path3) => resolve24(path3)).filter((path3) => {
|
|
27443
|
-
if (
|
|
27041
|
+
if (existsSync35(path3))
|
|
27444
27042
|
return true;
|
|
27445
27043
|
console.log(`Dropping custom policies path (file no longer exists): ${path3}`);
|
|
27446
27044
|
return false;
|
|
@@ -27632,7 +27230,7 @@ async function removeHooks2(policyNames, scope = "user", cwd, opts) {
|
|
|
27632
27230
|
const scopesToRemove = scope === "all" ? [...integration.scopes] : integration.scopes.includes(scope) ? [scope] : [];
|
|
27633
27231
|
for (const s of scopesToRemove) {
|
|
27634
27232
|
const settingsPaths = settingsPathsFor(integration, s, cwd);
|
|
27635
|
-
const existing = settingsPaths.filter((p) =>
|
|
27233
|
+
const existing = settingsPaths.filter((p) => existsSync35(p));
|
|
27636
27234
|
if (existing.length === 0) {
|
|
27637
27235
|
if (scope !== "all" && selectedClis.length === 1) {
|
|
27638
27236
|
console.log("No settings file found. Nothing to remove.");
|
|
@@ -27833,7 +27431,7 @@ Failproof AI Hook Policies
|
|
|
27833
27431
|
for (const path3 of explicitPaths) {
|
|
27834
27432
|
const absPath = resolve24(findProjectConfigDir(cwd ?? process.cwd()), path3);
|
|
27835
27433
|
console.log(` ${absPath}`);
|
|
27836
|
-
if (!
|
|
27434
|
+
if (!existsSync35(absPath)) {
|
|
27837
27435
|
console.log(` \x1B[31m✗ File not found: ${absPath}\x1B[0m`);
|
|
27838
27436
|
continue;
|
|
27839
27437
|
}
|
|
@@ -27901,6 +27499,21 @@ Failproof AI Hook Policies
|
|
|
27901
27499
|
}
|
|
27902
27500
|
console.log();
|
|
27903
27501
|
}
|
|
27502
|
+
try {
|
|
27503
|
+
const cloud = readActiveCloudManagedPolicies();
|
|
27504
|
+
if (cloud.length > 0) {
|
|
27505
|
+
const gen = cloud[0].deployment;
|
|
27506
|
+
console.log(`
|
|
27507
|
+
── Cloud-managed — deployment ${gen} ─────────`);
|
|
27508
|
+
const colWidth = Math.max(nameColWidth, ...cloud.map((c2) => c2.id.length + 2));
|
|
27509
|
+
for (const artifact of cloud) {
|
|
27510
|
+
const status = artifact.effect === "observe" ? "\x1B[33m◐ OBS\x1B[0m" : "\x1B[32m✓ ON\x1B[0m";
|
|
27511
|
+
console.log(` ${status} ${artifact.id.padEnd(colWidth)}v${artifact.version}`);
|
|
27512
|
+
}
|
|
27513
|
+
console.log("\n Managed from the dashboard — not switchable with `failproofai policies`.");
|
|
27514
|
+
console.log();
|
|
27515
|
+
}
|
|
27516
|
+
} catch {}
|
|
27904
27517
|
try {
|
|
27905
27518
|
syncConventionPolicies(discovered.user, "user");
|
|
27906
27519
|
} catch (err) {
|
|
@@ -27920,6 +27533,7 @@ var init_manager2 = __esm(() => {
|
|
|
27920
27533
|
init_cli_error();
|
|
27921
27534
|
init_hook_logger();
|
|
27922
27535
|
init_fp_home();
|
|
27536
|
+
init_cloud_managed_policies();
|
|
27923
27537
|
VALID_POLICY_NAMES2 = new Set(BUILTIN_POLICIES.map((p) => p.name));
|
|
27924
27538
|
});
|
|
27925
27539
|
|
|
@@ -28968,8 +28582,8 @@ __export(exports_launch2, {
|
|
|
28968
28582
|
launch: () => launch2
|
|
28969
28583
|
});
|
|
28970
28584
|
import { spawn as spawn3 } from "child_process";
|
|
28971
|
-
import { realpathSync as realpathSync5, existsSync as
|
|
28972
|
-
import { resolve as resolve25, dirname as
|
|
28585
|
+
import { realpathSync as realpathSync5, existsSync as existsSync36 } from "node:fs";
|
|
28586
|
+
import { resolve as resolve25, dirname as dirname19 } from "node:path";
|
|
28973
28587
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
28974
28588
|
import { createInterface as createInterface2 } from "node:readline";
|
|
28975
28589
|
function launch2(mode) {
|
|
@@ -28993,9 +28607,9 @@ function launch2(mode) {
|
|
|
28993
28607
|
process.env.PORT = port;
|
|
28994
28608
|
process.env.HOSTNAME = bindHost;
|
|
28995
28609
|
cmd = "node";
|
|
28996
|
-
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve25(
|
|
28610
|
+
const packageRoot = process.env.FAILPROOFAI_PACKAGE_ROOT ?? resolve25(dirname19(realpathSync5(fileURLToPath3(import.meta.url))), "..");
|
|
28997
28611
|
const serverJsPath = resolve25(packageRoot, ".next/standalone/server.js");
|
|
28998
|
-
if (!
|
|
28612
|
+
if (!existsSync36(serverJsPath)) {
|
|
28999
28613
|
let shadowMessage = null;
|
|
29000
28614
|
try {
|
|
29001
28615
|
const diag = diagnoseShadow({ selfPackageRoot: packageRoot, selfVersion: version2 });
|
|
@@ -29092,17 +28706,17 @@ var init_cli_error2 = __esm(() => {
|
|
|
29092
28706
|
|
|
29093
28707
|
// bin/failproofai.mjs
|
|
29094
28708
|
import { realpathSync as realpathSync6 } from "fs";
|
|
29095
|
-
import { dirname as
|
|
28709
|
+
import { dirname as dirname20, resolve as resolve26 } from "path";
|
|
29096
28710
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
29097
28711
|
// package.json
|
|
29098
|
-
var version = "1.0.0-beta.
|
|
28712
|
+
var version = "1.0.0-beta.13";
|
|
29099
28713
|
|
|
29100
28714
|
// bin/failproofai.mjs
|
|
29101
28715
|
if (!process.env.FAILPROOFAI_PACKAGE_ROOT) {
|
|
29102
|
-
process.env.FAILPROOFAI_PACKAGE_ROOT = resolve26(
|
|
28716
|
+
process.env.FAILPROOFAI_PACKAGE_ROOT = resolve26(dirname20(realpathSync6(fileURLToPath4(import.meta.url))), "..");
|
|
29103
28717
|
}
|
|
29104
28718
|
if (!process.env.FAILPROOFAI_DIST_PATH) {
|
|
29105
|
-
process.env.FAILPROOFAI_DIST_PATH = resolve26(
|
|
28719
|
+
process.env.FAILPROOFAI_DIST_PATH = resolve26(dirname20(realpathSync6(fileURLToPath4(import.meta.url))), "..", "dist");
|
|
29106
28720
|
}
|
|
29107
28721
|
var args = process.argv.slice(2);
|
|
29108
28722
|
if (args[0] === "p")
|
|
@@ -29226,7 +28840,7 @@ if (hookIdx >= 0) {
|
|
|
29226
28840
|
}
|
|
29227
28841
|
}
|
|
29228
28842
|
async function runCli() {
|
|
29229
|
-
const SUBCOMMANDS = ["policies", "policy", "audit", "config", "uninstall", "backfill"];
|
|
28843
|
+
const SUBCOMMANDS = ["policies", "policy", "audit", "config", "uninstall", "backfill", "flush", "harness"];
|
|
29230
28844
|
if ((args.includes("--help") || args.includes("-h")) && !SUBCOMMANDS.includes(args[0])) {
|
|
29231
28845
|
const extraArgs = args.filter((a) => a !== "--help" && a !== "-h");
|
|
29232
28846
|
if (extraArgs.length > 0) {
|
|
@@ -29242,6 +28856,13 @@ USAGE
|
|
|
29242
28856
|
COMMANDS
|
|
29243
28857
|
(no args) Launch the policy dashboard
|
|
29244
28858
|
config Interactive setup \u2014 pick scope, agents & policies
|
|
28859
|
+
--connect <url> --token <key> Connect to Failproof Cloud non-interactively
|
|
28860
|
+
--machine-id <id> Stable id for this machine
|
|
28861
|
+
--machine-label <name> Human-readable name in the dashboard
|
|
28862
|
+
--no-transcripts Report decisions only, never transcripts
|
|
28863
|
+
--disconnect Stop pulling policy and sending activity
|
|
28864
|
+
--status Show connection, daemon and pause state
|
|
28865
|
+
--pause / --resume Pause or resume enforcement
|
|
29245
28866
|
|
|
29246
28867
|
policy add <name> Enable a single policy (see \`policy --help\`)
|
|
29247
28868
|
policy remove <name> Disable a single policy
|
|
@@ -29268,10 +28889,30 @@ COMMANDS
|
|
|
29268
28889
|
|
|
29269
28890
|
policies --help, -h Show this help for the policies command
|
|
29270
28891
|
|
|
28892
|
+
harness list Show extra capture paths per agent CLI
|
|
28893
|
+
harness add-path <h> <path> Also capture sessions from <path> for harness
|
|
28894
|
+
<h>. Accepts \`<label>=<path>\`; the label
|
|
28895
|
+
namespaces agent ids so two copies of one
|
|
28896
|
+
project stay distinct.
|
|
28897
|
+
harness remove-path <h> <p> Stop capturing that path
|
|
28898
|
+
harness --help, -h Show this help for the harness command
|
|
28899
|
+
|
|
29271
28900
|
audit Audit your agent's behavior, then open the
|
|
29272
28901
|
dashboard at http://localhost:8020/audit
|
|
29273
28902
|
audit --help, -h Show this help for the audit command
|
|
29274
28903
|
|
|
28904
|
+
backfill Re-send history the collector already read past
|
|
28905
|
+
\u2014 after clearing the dashboard, re-enrolling a
|
|
28906
|
+
machine, or connecting later than the work
|
|
28907
|
+
--since <when> How far back: 30d, 6m, or YYYY-MM-DD
|
|
28908
|
+
(default: 30 days)
|
|
28909
|
+
--dry-run Report what would be re-read, change nothing
|
|
28910
|
+
|
|
28911
|
+
flush Deliver everything already spooled, now,
|
|
28912
|
+
instead of waiting for the next sweep
|
|
28913
|
+
--wait Block until the spool drains (or --timeout)
|
|
28914
|
+
--timeout <secs> How long to wait with --wait (default: 60)
|
|
28915
|
+
|
|
29275
28916
|
uninstall Remove failproofai from this machine: hook
|
|
29276
28917
|
entries from every agent CLI, and the daemon
|
|
29277
28918
|
service. Run this BEFORE \`npm rm -g failproofai\`
|
|
@@ -29311,6 +28952,10 @@ EXAMPLES
|
|
|
29311
28952
|
failproofai policies --uninstall --cli opencode
|
|
29312
28953
|
failproofai policies --uninstall --cli pi
|
|
29313
28954
|
failproofai policies --uninstall --custom
|
|
28955
|
+
failproofai backfill --since 6m
|
|
28956
|
+
failproofai backfill --dry-run
|
|
28957
|
+
failproofai flush --wait
|
|
28958
|
+
failproofai config --status
|
|
29314
28959
|
|
|
29315
28960
|
LINKS
|
|
29316
28961
|
\u2B50 Star us: https://github.com/failproofai/failproofai
|
|
@@ -29332,8 +28977,8 @@ Run \`failproofai --help\` for usage.`);
|
|
|
29332
28977
|
{
|
|
29333
28978
|
const isHelpOrVersion = args.includes("--help") || args.includes("-h") || args.includes("--version") || args.includes("-v");
|
|
29334
28979
|
if (args[0] === "audit" && args.includes("--scheduled")) {
|
|
29335
|
-
const {
|
|
29336
|
-
const warning =
|
|
28980
|
+
const { layoutBlockerForScheduledRun: layoutBlockerForScheduledRun2 } = await Promise.resolve().then(() => (init_fp_reset2(), exports_fp_reset));
|
|
28981
|
+
const warning = layoutBlockerForScheduledRun2();
|
|
29337
28982
|
if (warning) {
|
|
29338
28983
|
console.error(warning);
|
|
29339
28984
|
process.exit(1);
|
|
@@ -29359,6 +29004,68 @@ Run \`failproofai --help\` for usage.`);
|
|
|
29359
29004
|
await maybeFirstRunConfigure2({}, { postSetupAudit: args[0] !== "audit", force: layoutWasReset });
|
|
29360
29005
|
} catch {}
|
|
29361
29006
|
}
|
|
29007
|
+
if (args[0] === "flush") {
|
|
29008
|
+
const subArgs = args.slice(1);
|
|
29009
|
+
if (subArgs.includes("--help") || subArgs.includes("-h")) {
|
|
29010
|
+
console.log(`
|
|
29011
|
+
failproofai flush \u2014 deliver what is already spooled, now
|
|
29012
|
+
|
|
29013
|
+
USAGE
|
|
29014
|
+
failproofai flush [--wait] [--timeout <secs>]
|
|
29015
|
+
|
|
29016
|
+
WHY
|
|
29017
|
+
The collector is unhurried on purpose: a batch is swept once it is older than
|
|
29018
|
+
two minutes, at most 64 per pass, on a 60-second cadence. That pacing keeps a
|
|
29019
|
+
backlog from stampeding the server, and it is exactly wrong when you are
|
|
29020
|
+
standing at a dashboard waiting to see your own events \u2014 "not delivered yet"
|
|
29021
|
+
and "not working" look identical from there.
|
|
29022
|
+
|
|
29023
|
+
This asks the daemon to make a pass right now, with no minimum age and no
|
|
29024
|
+
per-pass cap. It re-sends nothing: only batches already spooled and not yet
|
|
29025
|
+
delivered. For history the collector has already read past, use \`backfill\`.
|
|
29026
|
+
|
|
29027
|
+
OPTIONS
|
|
29028
|
+
--wait Block until the spool drains, or --timeout elapses.
|
|
29029
|
+
--timeout <secs> How long --wait waits. Default: 60.
|
|
29030
|
+
`);
|
|
29031
|
+
process.exit(0);
|
|
29032
|
+
}
|
|
29033
|
+
const KNOWN = new Set(["--wait", "--timeout"]);
|
|
29034
|
+
const unknown = subArgs.find((a, i) => a.startsWith("-") && !KNOWN.has(a) && subArgs[i - 1] !== "--timeout");
|
|
29035
|
+
if (unknown) {
|
|
29036
|
+
throw new CliError3(`Unexpected argument: ${unknown}
|
|
29037
|
+
Run \`failproofai flush --help\` for usage.`);
|
|
29038
|
+
}
|
|
29039
|
+
let timeoutSecs;
|
|
29040
|
+
const tIdx = subArgs.indexOf("--timeout");
|
|
29041
|
+
if (tIdx >= 0) {
|
|
29042
|
+
const raw = subArgs[tIdx + 1];
|
|
29043
|
+
if (!raw || raw.startsWith("-"))
|
|
29044
|
+
throw new CliError3("Missing value after --timeout.");
|
|
29045
|
+
const n = Number(raw);
|
|
29046
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
29047
|
+
throw new CliError3(`Could not read --timeout ${raw}. Give a number of seconds.`);
|
|
29048
|
+
}
|
|
29049
|
+
timeoutSecs = n;
|
|
29050
|
+
}
|
|
29051
|
+
lastSubcommand = "flush";
|
|
29052
|
+
const { runFlushCommand: runFlushCommand2 } = await Promise.resolve().then(() => (init_flush_cli(), exports_flush_cli));
|
|
29053
|
+
const result = await runFlushCommand2({ wait: subArgs.includes("--wait"), timeoutSecs });
|
|
29054
|
+
for (const line of result.lines) {
|
|
29055
|
+
if (result.exitCode === 0)
|
|
29056
|
+
console.log(line);
|
|
29057
|
+
else
|
|
29058
|
+
console.error(line);
|
|
29059
|
+
}
|
|
29060
|
+
await track("cli_flush", {
|
|
29061
|
+
ok: result.exitCode === 0,
|
|
29062
|
+
waited: subArgs.includes("--wait"),
|
|
29063
|
+
pending: result.pending
|
|
29064
|
+
});
|
|
29065
|
+
lastSubcommand = null;
|
|
29066
|
+
await exitAfterFlush(result.exitCode);
|
|
29067
|
+
return;
|
|
29068
|
+
}
|
|
29362
29069
|
if (args[0] === "backfill") {
|
|
29363
29070
|
const subArgs = args.slice(1);
|
|
29364
29071
|
if (subArgs.includes("--help") || subArgs.includes("-h")) {
|
|
@@ -29426,6 +29133,71 @@ Run \`failproofai backfill --help\` for usage.`);
|
|
|
29426
29133
|
await exitAfterFlush(result.exitCode);
|
|
29427
29134
|
return;
|
|
29428
29135
|
}
|
|
29136
|
+
if (args[0] === "harness") {
|
|
29137
|
+
const subArgs = args.slice(1);
|
|
29138
|
+
if (subArgs.length === 0 || subArgs.includes("--help") || subArgs.includes("-h")) {
|
|
29139
|
+
console.log(`
|
|
29140
|
+
failproofai harness \u2014 capture sessions from more than one location per agent CLI
|
|
29141
|
+
|
|
29142
|
+
USAGE
|
|
29143
|
+
failproofai harness list [<harness>]
|
|
29144
|
+
failproofai harness add-path <harness> [<label>=]<path>
|
|
29145
|
+
failproofai harness remove-path <harness> <path|label>
|
|
29146
|
+
|
|
29147
|
+
WHY
|
|
29148
|
+
Each agent CLI is watched wherever its own installer put it \u2014 ~/.claude/projects,
|
|
29149
|
+
~/.hermes/state.db, and so on. That misses every other arrangement: a second
|
|
29150
|
+
profile, a mounted team share, a container's home beside the host's, an agent
|
|
29151
|
+
an operator moved. Those hold real sessions and nothing collects them.
|
|
29152
|
+
|
|
29153
|
+
THE LABEL
|
|
29154
|
+
An entry is \`<path>\` or \`<label>=<path>\`. The label namespaces agent ids as
|
|
29155
|
+
<label>-<agentId>, and it matters: two locations holding the same project
|
|
29156
|
+
derive the SAME id (it comes from the cwd inside the transcript, identical in
|
|
29157
|
+
both copies), so without a label they merge into one agent whose sessions
|
|
29158
|
+
interleave from two machines' worth of history. Omit it and one is derived
|
|
29159
|
+
from the folder name.
|
|
29160
|
+
|
|
29161
|
+
HARNESSES
|
|
29162
|
+
claude, codex, copilot, openclaw, pi, factory, antigravity, cursor,
|
|
29163
|
+
goose, opencode, devin, hermes
|
|
29164
|
+
|
|
29165
|
+
\`claude\` covers subagent transcripts too \u2014 they live under the same root.
|
|
29166
|
+
|
|
29167
|
+
NOTES
|
|
29168
|
+
\u2022 Session collection must be on for any of this to be read; extra paths follow
|
|
29169
|
+
[collector] in ~/.failproofai/config.toml like the default ones do.
|
|
29170
|
+
\u2022 A path overlapping one already captured is REFUSED by the daemon at startup
|
|
29171
|
+
rather than collected twice under two ids. It says so in the journal.
|
|
29172
|
+
\u2022 Takes effect within seconds \u2014 the daemon re-reads config.toml on an interval
|
|
29173
|
+
and cycles its collector. No restart, no sudo.
|
|
29174
|
+
|
|
29175
|
+
EXAMPLES
|
|
29176
|
+
failproofai harness add-path claude work=/srv/team/.claude/projects
|
|
29177
|
+
failproofai harness add-path hermes prod=/srv/hermes-prod/state.db
|
|
29178
|
+
failproofai harness add-path codex /mnt/other-home/.codex/sessions
|
|
29179
|
+
failproofai harness list
|
|
29180
|
+
failproofai harness remove-path claude work
|
|
29181
|
+
`.trimStart());
|
|
29182
|
+
process.exit(0);
|
|
29183
|
+
}
|
|
29184
|
+
lastSubcommand = "harness";
|
|
29185
|
+
const { runHarnessCommand: runHarnessCommand2 } = await Promise.resolve().then(() => (init_harness_cli(), exports_harness_cli));
|
|
29186
|
+
const result = runHarnessCommand2(subArgs);
|
|
29187
|
+
for (const line of result.lines) {
|
|
29188
|
+
if (result.exitCode === 0)
|
|
29189
|
+
console.log(line);
|
|
29190
|
+
else
|
|
29191
|
+
console.error(line);
|
|
29192
|
+
}
|
|
29193
|
+
await track("cli_harness", {
|
|
29194
|
+
ok: result.exitCode === 0,
|
|
29195
|
+
sub: ["list", "add-path", "remove-path"].includes(subArgs[0]) ? subArgs[0] : "unknown"
|
|
29196
|
+
});
|
|
29197
|
+
lastSubcommand = null;
|
|
29198
|
+
await exitAfterFlush(result.exitCode);
|
|
29199
|
+
return;
|
|
29200
|
+
}
|
|
29429
29201
|
if (args[0] === "uninstall") {
|
|
29430
29202
|
const subArgs = args.slice(1);
|
|
29431
29203
|
if (subArgs.includes("--help") || subArgs.includes("-h")) {
|
|
@@ -29836,7 +29608,7 @@ USAGE
|
|
|
29836
29608
|
WHAT IT DOES
|
|
29837
29609
|
Walks you through 4 quick steps and writes everything for you:
|
|
29838
29610
|
1. Where \u2014 global (all projects) or just this project
|
|
29839
|
-
2.
|
|
29611
|
+
2. Harnesses \u2014 which agent CLIs to protect (Claude, Codex, ...)
|
|
29840
29612
|
3. Policies \u2014 presets (combine any), Everything, or a custom pick
|
|
29841
29613
|
4. Review \u2014 confirms the exact files it will change, then applies
|
|
29842
29614
|
|
|
@@ -29845,7 +29617,13 @@ FAILPROOF CLOUD
|
|
|
29845
29617
|
Connect this machine to Failproof Cloud
|
|
29846
29618
|
[--no-transcripts] decisions only, no transcripts
|
|
29847
29619
|
failproofai config --disconnect Stop pulling policy and sending activity
|
|
29848
|
-
failproofai config --status Show connection and pause state
|
|
29620
|
+
failproofai config --status Show connection, daemon and pause state
|
|
29621
|
+
failproofai config --pause [--session <id>]
|
|
29622
|
+
Pause enforcement, time-boxed
|
|
29623
|
+
failproofai config --resume [--all]
|
|
29624
|
+
Resume enforcement
|
|
29625
|
+
|
|
29626
|
+
--machine-label <name> Human-readable name in the dashboard
|
|
29849
29627
|
|
|
29850
29628
|
One connection, two capabilities: this machine PULLS centrally-managed
|
|
29851
29629
|
policies and SENDS what its hooks decided, so the dashboard shows the fleet
|