failproofai 0.0.6-beta.2 → 0.0.6-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  10. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  11. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  12. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  13. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  14. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  16. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  19. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  20. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  21. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  22. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  24. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  25. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  26. package/.next/standalone/.next/server/app/index.html +1 -1
  27. package/.next/standalone/.next/server/app/index.rsc +15 -15
  28. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  29. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  30. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  31. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  32. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  33. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  34. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  36. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
  37. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  40. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  42. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  43. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  44. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  47. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g72weg._.js +1 -1
  50. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
  51. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__092s1ta._.js +2 -2
  52. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__05akje6._.js → [root-of-the-server]__096k.db._.js} +2 -2
  53. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09icjsf._.js +2 -2
  54. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g.lg8b._.js +2 -2
  55. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h..k-e._.js +2 -2
  56. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0i5kvry._.js → [root-of-the-server]__0kyh86x._.js} +2 -2
  57. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0okos0k._.js +2 -2
  58. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0w6l33k._.js +2 -2
  59. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11pa2ra._.js +2 -2
  60. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12t-wym._.js +2 -2
  61. package/.next/standalone/.next/server/chunks/ssr/_10lm7or._.js +2 -2
  62. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
  63. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +1 -1
  64. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  65. package/.next/standalone/.next/server/pages/404.html +2 -2
  66. package/.next/standalone/.next/server/pages/500.html +1 -1
  67. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  68. package/.next/standalone/.next/server/server-reference-manifest.json +9 -9
  69. package/.next/standalone/.next/static/chunks/{1052sguyd-.ka.js → 0-dm_9a6nsc2l.js} +1 -1
  70. package/.next/standalone/.next/static/chunks/{05j1px0r8yzh6.js → 01pmw1-asbek~.js} +2 -2
  71. package/.next/standalone/.next/static/chunks/{14cl9poem30dq.js → 051m32nx~n5yr.js} +1 -1
  72. package/.next/standalone/.next/static/chunks/{0badv41uxa56..js → 0a-yctdwn368y.js} +1 -1
  73. package/.next/standalone/.next/static/chunks/{0xpl.oscrakvx.js → 0l-mu4okl-cj1.js} +1 -1
  74. package/.next/standalone/.next/static/chunks/{00j0rr7rh8ef8.js → 0mazj-p-~2kc6.js} +1 -1
  75. package/.next/standalone/.next/static/chunks/0qakntsrpc~1j.js +6 -0
  76. package/.next/standalone/.next/static/chunks/{0npb~873.wvg3.js → 156zca6aewyr-.js} +1 -1
  77. package/.next/standalone/CHANGELOG.md +7 -0
  78. package/.next/standalone/bin/failproofai.mjs +91 -4
  79. package/.next/standalone/dist/cli.mjs +1155 -54
  80. package/.next/standalone/docs/ar/built-in-policies.mdx +118 -118
  81. package/.next/standalone/docs/built-in-policies.mdx +2 -2
  82. package/.next/standalone/docs/de/built-in-policies.mdx +48 -48
  83. package/.next/standalone/docs/es/built-in-policies.mdx +82 -82
  84. package/.next/standalone/docs/fr/built-in-policies.mdx +72 -72
  85. package/.next/standalone/docs/he/built-in-policies.mdx +129 -128
  86. package/.next/standalone/docs/hi/built-in-policies.mdx +178 -182
  87. package/.next/standalone/docs/it/built-in-policies.mdx +64 -64
  88. package/.next/standalone/docs/ja/built-in-policies.mdx +128 -128
  89. package/.next/standalone/docs/ko/built-in-policies.mdx +111 -111
  90. package/.next/standalone/docs/pt-br/built-in-policies.mdx +65 -65
  91. package/.next/standalone/docs/ru/built-in-policies.mdx +72 -72
  92. package/.next/standalone/docs/tr/built-in-policies.mdx +99 -99
  93. package/.next/standalone/docs/vi/built-in-policies.mdx +69 -72
  94. package/.next/standalone/docs/zh/built-in-policies.mdx +76 -78
  95. package/.next/standalone/package.json +1 -1
  96. package/.next/standalone/server.js +1 -1
  97. package/.next/standalone/src/auth/login.ts +104 -0
  98. package/.next/standalone/src/auth/logout.ts +50 -0
  99. package/.next/standalone/src/auth/token-store.ts +64 -0
  100. package/.next/standalone/src/hooks/builtin-policies.ts +22 -20
  101. package/.next/standalone/src/hooks/handler.ts +35 -15
  102. package/.next/standalone/src/relay/daemon.ts +362 -0
  103. package/.next/standalone/src/relay/pid.ts +76 -0
  104. package/.next/standalone/src/relay/queue.ts +225 -0
  105. package/bin/failproofai.mjs +91 -4
  106. package/dist/cli.mjs +1155 -54
  107. package/package.json +1 -1
  108. package/src/auth/login.ts +104 -0
  109. package/src/auth/logout.ts +50 -0
  110. package/src/auth/token-store.ts +64 -0
  111. package/src/hooks/builtin-policies.ts +22 -20
  112. package/src/hooks/handler.ts +35 -15
  113. package/src/relay/daemon.ts +362 -0
  114. package/src/relay/pid.ts +76 -0
  115. package/src/relay/queue.ts +225 -0
  116. package/.next/standalone/.next/static/chunks/0ijk_kek9_wyx.js +0 -6
  117. /package/.next/standalone/.next/static/{A9pNTZdoYJTVyPAYwQMx5 → r-wX0MuAfCjbhJm3phQc8}/_buildManifest.js +0 -0
  118. /package/.next/standalone/.next/static/{A9pNTZdoYJTVyPAYwQMx5 → r-wX0MuAfCjbhJm3phQc8}/_clientMiddlewareManifest.js +0 -0
  119. /package/.next/standalone/.next/static/{A9pNTZdoYJTVyPAYwQMx5 → r-wX0MuAfCjbhJm3phQc8}/_ssgManifest.js +0 -0
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  title: 内置策略
3
- description: "涵盖常见 Agent 故障模式的 30 条内置策略"
3
+ description: "30 条内置策略,可捕获常见的 Agent 故障模式"
4
4
  icon: shield
5
5
  ---
6
6
 
7
- failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。每条策略针对特定的钩子事件类型和工具名称触发。九条策略接受参数,让你无需编写代码即可调整其行为。四条工作流策略在 Claude 停止前强制执行 提交推送 → PR → CI 的流水线。
7
+ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。每条策略会在特定的 Hook 事件类型和工具名称上触发。其中九条策略支持参数配置,让你无需编写代码即可调整其行为。四条工作流策略在 Claude 停止前强制执行 commitpush → PR → CI 流水线。
8
8
 
9
9
  ---
10
10
 
@@ -12,8 +12,8 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
12
12
 
13
13
  策略按类别分组:
14
14
 
15
- | 类别 | 策略 | 钩子类型 |
16
- |----------|----------|-----------|
15
+ | 类别 | 策略 | Hook 类型 |
16
+ |------|------|-----------|
17
17
  | [危险命令](#dangerous-commands) | block-sudo, block-rm-rf, block-curl-pipe-sh, block-failproofai-commands | PreToolUse |
18
18
  | [密钥(清理器)](#secrets-sanitizers) | sanitize-jwt, sanitize-api-keys, sanitize-connection-strings, sanitize-private-key-content, sanitize-bearer-tokens | PostToolUse |
19
19
  | [环境](#environment) | block-env-files, protect-env-vars | PreToolUse |
@@ -26,13 +26,13 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
26
26
 
27
27
  - **`block-`** — 阻止 Agent 继续执行。
28
28
  - **`warn-`** — 为 Agent 提供额外上下文,使其能够自我纠正。
29
- - **`sanitize-`** — 在 Agent 看到工具输出之前清除其中的敏感数据。
30
- - **`require-`** — 在条件满足之前阻止 Stop 事件触发。
29
+ - **`sanitize-`** — 在 Agent 看到工具输出之前,从中清除敏感数据。
30
+ - **`require-`** — 在条件满足之前阻断 Stop 事件。
31
31
 
32
32
  ---
33
33
 
34
34
  <Tip>
35
- 每条策略在 `policyParams` 中都支持可选的 `hint` 字段。该提示会附加到 Claude 所看到的 deny 或 instruct 消息中,提供可操作的指导,而无需修改策略代码。适用于内置策略、自定义策略和约定策略。详见 [配置 → hint](/zh/configuration#hint-cross-cutting)。
35
+ 每条策略都支持在 `policyParams` 中设置可选的 `hint` 字段。该提示会追加到 Claude 看到的 deny 或 instruct 消息中,提供可操作的指导,无需修改策略代码。适用于内置策略、自定义策略和约定策略。详见 [配置 → hint](/zh/configuration#hint-cross-cutting)。
36
36
  </Tip>
37
37
 
38
38
  ---
@@ -44,15 +44,15 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
44
44
  ### `block-sudo`
45
45
 
46
46
  **事件:** PreToolUse (Bash)
47
- **默认行为:** 拒绝任何包含 `sudo` 的命令。
47
+ **默认行为:** 拒绝所有包含 `sudo` 关键字的命令。
48
48
 
49
- 阻止包含 `sudo` 关键字的调用。模式匹配基于解析后的命令词元(token),而非原始字符串,以防止通过 shell 运算符注入绕过检测。
49
+ 拦截包含 `sudo` 关键字的调用。模式匹配基于解析后的命令 token,而非原始字符串,以防止通过 Shell 操作符注入来绕过检测。
50
50
 
51
51
  **参数:**
52
52
 
53
- | 参数 | 类型 | 默认值 | 描述 |
54
- |-------|------|---------|-------------|
55
- | `allowPatterns` | `string[]` | `[]` | 允许执行的精确命令前缀。每个条目与解析后的 argv 词元进行匹配。 |
53
+ | 参数 | 类型 | 默认值 | 说明 |
54
+ |------|------|--------|------|
55
+ | `allowPatterns` | `string[]` | `[]` | 允许通过的精确命令前缀。每个条目与解析后的 argv token 进行匹配。 |
56
56
 
57
57
  **示例:**
58
58
 
@@ -66,10 +66,10 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
66
66
  }
67
67
  ```
68
68
 
69
- 使用此配置,`sudo systemctl status nginx` 会被允许,但 `sudo rm /etc/hosts` 会被拒绝。
69
+ 使用此配置,`sudo systemctl status nginx` 将被允许,而 `sudo rm /etc/hosts` 将被拒绝。
70
70
 
71
71
  <Note>
72
- 模式匹配基于解析后的词元,而非原始命令字符串。这可以防止通过追加 shell 运算符绕过(例如 `sudo systemctl status x; rm -rf /` 不会匹配 `sudo systemctl status *`)。
72
+ 模式匹配基于解析后的 token,而非原始命令字符串。这可以防止通过附加 Shell 操作符来绕过检测(例如,`sudo systemctl status x; rm -rf /` 不会匹配 `sudo systemctl status *`)。
73
73
  </Note>
74
74
 
75
75
  ---
@@ -81,9 +81,9 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
81
81
 
82
82
  **参数:**
83
83
 
84
- | 参数 | 类型 | 默认值 | 描述 |
85
- |-------|------|---------|-------------|
86
- | `allowPaths` | `string[]` | `[]` | 允许递归删除的安全路径(例如 `/tmp`)。 |
84
+ | 参数 | 类型 | 默认值 | 说明 |
85
+ |------|------|--------|------|
86
+ | `allowPaths` | `string[]` | `[]` | 允许递归删除的安全路径(如 `/tmp`)。 |
87
87
 
88
88
  **示例:**
89
89
 
@@ -111,20 +111,20 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
111
111
  ### `block-failproofai-commands`
112
112
 
113
113
  **事件:** PreToolUse (Bash)
114
- **默认行为:** 拒绝可能卸载或禁用 failproofai 自身的命令(例如 `npm uninstall failproofai`、`failproofai policies --uninstall`)。
114
+ **默认行为:** 拒绝可能卸载或禁用 failproofai 自身的命令(如 `npm uninstall failproofai`、`failproofai policies --uninstall`)。
115
115
 
116
116
  无参数。
117
117
 
118
118
  ---
119
119
 
120
- ## 密钥(清理器) {#secrets-sanitizers}
120
+ ## 密钥(清理器){#secrets-sanitizers}
121
121
 
122
- 防止 Agent 将凭据泄露到其上下文或输出中。清理器策略在 **PostToolUse** 事件上触发。当 Claude 运行 Bash 命令、读取文件或调用任何工具时,这些策略会在输出返回给 Claude 之前对其进行检查。如果检测到密钥模式,策略会返回 deny 决策,阻止输出被传回。
122
+ 防止 Agent 将凭证泄露到其上下文或输出中。清理器策略在 **PostToolUse** 事件上触发。当 Claude 运行 Bash 命令、读取文件或调用任何工具时,这些策略会在输出返回给 Claude 之前对其进行检查。若检测到密钥模式,策略将返回 deny 决策,阻止输出被传回。
123
123
 
124
124
  ### `sanitize-jwt`
125
125
 
126
126
  **事件:** PostToolUse(所有工具)
127
- **默认行为:** 脱敏 JWT 令牌(三段由 `.` 分隔的 base64url 片段)。
127
+ **默认行为:** 脱敏 JWT token(三段由 `.` 分隔的 base64url 字符串)。
128
128
 
129
129
  无参数。
130
130
 
@@ -133,13 +133,13 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
133
133
  ### `sanitize-api-keys`
134
134
 
135
135
  **事件:** PostToolUse(所有工具)
136
- **默认行为:** 脱敏常见 API 密钥格式:Anthropic(`sk-ant-`)、OpenAI(`sk-`)、GitHub PAT(`ghp_`)、AWS 访问密钥(`AKIA`)、Stripe 密钥(`sk_live_`、`sk_test_`)以及 Google API 密钥(`AIza`)。
136
+ **默认行为:** 脱敏常见 API Key 格式:Anthropic(`sk-ant-`)、OpenAI(`sk-`)、GitHub PAT(`ghp_`)、AWS Access Key(`AKIA`)、Stripe Key(`sk_live_`、`sk_test_`)以及 Google API Key(`AIza`)。
137
137
 
138
138
  **参数:**
139
139
 
140
- | 参数 | 类型 | 默认值 | 描述 |
141
- |-------|------|---------|-------------|
142
- | `additionalPatterns` | `{ regex: string; label: string }[]` | `[]` | 需要视为密钥的额外正则表达式模式。 |
140
+ | 参数 | 类型 | 默认值 | 说明 |
141
+ |------|------|--------|------|
142
+ | `additionalPatterns` | `{ regex: string; label: string }[]` | `[]` | 额外需要视为密钥的正则表达式模式。 |
143
143
 
144
144
  **示例:**
145
145
 
@@ -161,7 +161,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
161
161
  ### `sanitize-connection-strings`
162
162
 
163
163
  **事件:** PostToolUse(所有工具)
164
- **默认行为:** 脱敏包含嵌入式凭据的数据库连接字符串(例如 `postgresql://user:password@host/db`)。
164
+ **默认行为:** 脱敏包含内嵌凭证的数据库连接字符串(如 `postgresql://user:password@host/db`)。
165
165
 
166
166
  无参数。
167
167
 
@@ -179,7 +179,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
179
179
  ### `sanitize-bearer-tokens`
180
180
 
181
181
  **事件:** PostToolUse(所有工具)
182
- **默认行为:** 脱敏 `Authorization: Bearer <token>` 请求头中长度不少于 20 个字符的令牌。
182
+ **默认行为:** 脱敏 `Authorization: Bearer <token>` 请求头中长度大于等于 20 个字符的 token。
183
183
 
184
184
  无参数。
185
185
 
@@ -187,14 +187,14 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
187
187
 
188
188
  ## 环境 {#environment}
189
189
 
190
- 防止 Agent 读取或暴露敏感的环境配置。
190
+ 保护敏感的环境配置,防止 Agent 读取或暴露这些信息。
191
191
 
192
192
  ### `block-env-files`
193
193
 
194
194
  **事件:** PreToolUse (Bash, Read)
195
- **默认行为:** 拒绝通过 `cat .env`、以 `.env` 为文件路径的 `Read` 工具调用等方式读取 `.env` 文件。
195
+ **默认行为:** 拒绝通过 `cat .env`、文件路径为 `.env` `Read` 工具调用等方式读取 `.env` 文件。
196
196
 
197
- 不会阻止 `.envrc` 或其他与环境相关的文件,仅阻止名称恰好为 `.env` 的文件。
197
+ 不拦截 `.envrc` 或其他相关环境文件,仅拦截名称严格为 `.env` 的文件。
198
198
 
199
199
  无参数。
200
200
 
@@ -211,7 +211,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
211
211
 
212
212
  ## 文件访问 {#file-access}
213
213
 
214
- Agent 保持在项目边界内工作,远离敏感文件。
214
+ Agent 限制在项目目录内,并使其远离敏感文件。
215
215
 
216
216
  ### `block-read-outside-cwd`
217
217
 
@@ -220,8 +220,8 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
220
220
 
221
221
  **参数:**
222
222
 
223
- | 参数 | 类型 | 默认值 | 描述 |
224
- |-------|------|---------|-------------|
223
+ | 参数 | 类型 | 默认值 | 说明 |
224
+ |------|------|--------|------|
225
225
  | `allowPaths` | `string[]` | `[]` | 即使在当前工作目录之外也允许访问的绝对路径前缀。 |
226
226
 
227
227
  **示例:**
@@ -241,13 +241,13 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
241
241
  ### `block-secrets-write`
242
242
 
243
243
  **事件:** PreToolUse (Write, Edit)
244
- **默认行为:** 拒绝写入常用于私钥和证书的文件:`id_rsa`、`id_ed25519`、`*.key`、`*.pem`、`*.p12`、`*.pfx`。
244
+ **默认行为:** 拒绝写入常用于存储私钥和证书的文件:`id_rsa`、`id_ed25519`、`*.key`、`*.pem`、`*.p12`、`*.pfx`。
245
245
 
246
246
  **参数:**
247
247
 
248
- | 参数 | 类型 | 默认值 | 描述 |
249
- |-------|------|---------|-------------|
250
- | `additionalPatterns` | `string[]` | `[]` | 需要阻止的额外文件名模式(glob 风格)。 |
248
+ | 参数 | 类型 | 默认值 | 说明 |
249
+ |------|------|--------|------|
250
+ | `additionalPatterns` | `string[]` | `[]` | 额外需要拦截的文件名模式(glob 风格)。 |
251
251
 
252
252
  **示例:**
253
253
 
@@ -265,7 +265,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
265
265
 
266
266
  ## Git {#git}
267
267
 
268
- 防止意外推送、强制推送以及难以撤销的分支误操作。
268
+ 防止意外推送、强制推送以及难以撤销的分支操作失误。
269
269
 
270
270
  ### `block-push-master`
271
271
 
@@ -274,8 +274,8 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
274
274
 
275
275
  **参数:**
276
276
 
277
- | 参数 | 类型 | 默认值 | 描述 |
278
- |-------|------|---------|-------------|
277
+ | 参数 | 类型 | 默认值 | 说明 |
278
+ |------|------|--------|------|
279
279
  | `protectedBranches` | `string[]` | `["main", "master"]` | 不允许直接推送的分支名称。 |
280
280
 
281
281
  **示例:**
@@ -291,7 +291,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
291
291
  ```
292
292
 
293
293
  <Tip>
294
- 若要允许推送到所有分支(即在不从 `enabledPolicies` 中移除该策略的情况下将其禁用),请将 `protectedBranches` 设置为 `[]`。
294
+ 若要允许推送到所有分支(即在不将其从 `enabledPolicies` 中移除的情况下有效禁用此策略),可将 `protectedBranches` 设为 `[]`。
295
295
  </Tip>
296
296
 
297
297
  ---
@@ -303,8 +303,8 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
303
303
 
304
304
  **参数:**
305
305
 
306
- | 参数 | 类型 | 默认值 | 描述 |
307
- |-------|------|---------|-------------|
306
+ | 参数 | 类型 | 默认值 | 说明 |
307
+ |------|------|--------|------|
308
308
  | `protectedBranches` | `string[]` | `["main", "master"]` | 不允许直接切换的分支名称。 |
309
309
 
310
310
  ---
@@ -314,7 +314,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
314
314
  **事件:** PreToolUse (Bash)
315
315
  **默认行为:** 拒绝 `git push --force` 和 `git push -f`。
316
316
 
317
- 无策略专属参数。使用通用 [`hint`](/zh/configuration#hint-cross-cutting) 来建议替代方案:
317
+ 无策略特定参数。可使用通用 [`hint`](/zh/configuration#hint-cross-cutting) 建议替代方案:
318
318
 
319
319
  ```json
320
320
  {
@@ -331,7 +331,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
331
331
  ### `warn-git-amend`
332
332
 
333
333
  **事件:** PreToolUse (Bash)
334
- **默认行为:** 当运行 `git commit --amend` 时,指示 Claude 谨慎操作。不会阻止该命令执行。
334
+ **默认行为:** 在运行 `git commit --amend` 时指示 Claude 谨慎操作。不阻止该命令执行。
335
335
 
336
336
  无参数。
337
337
 
@@ -340,7 +340,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
340
340
  ### `warn-git-stash-drop`
341
341
 
342
342
  **事件:** PreToolUse (Bash)
343
- **默认行为:** 在运行 `git stash drop` 之前,指示 Claude 进行确认。不会阻止该命令执行。
343
+ **默认行为:** 在运行 `git stash drop` 前指示 Claude 进行确认。不阻止该命令执行。
344
344
 
345
345
  无参数。
346
346
 
@@ -349,7 +349,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
349
349
  ### `warn-all-files-staged`
350
350
 
351
351
  **事件:** PreToolUse (Bash)
352
- **默认行为:** 当运行 `git add -A` 或 `git add .` 时,指示 Claude 审查所暂存的内容。不会阻止该命令执行。
352
+ **默认行为:** 在运行 `git add -A` 或 `git add .` 时指示 Claude 检查其所暂存的内容。不阻止该命令执行。
353
353
 
354
354
  无参数。
355
355
 
@@ -357,7 +357,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
357
357
 
358
358
  ## 数据库 {#database}
359
359
 
360
- 在破坏性 SQL 操作执行之前将其拦截。
360
+ 在破坏性 SQL 操作对数据库执行之前将其拦截。
361
361
 
362
362
  ### `warn-destructive-sql`
363
363
 
@@ -379,7 +379,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
379
379
 
380
380
  ## 警告 {#warnings}
381
381
 
382
- 在执行可能存在风险但非破坏性的操作之前,为 Agent 提供额外上下文。
382
+ 在执行潜在有风险但非破坏性的操作前,为 Agent 提供额外上下文。
383
383
 
384
384
  ### `warn-large-file-write`
385
385
 
@@ -388,8 +388,8 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
388
388
 
389
389
  **参数:**
390
390
 
391
- | 参数 | 类型 | 默认值 | 描述 |
392
- |-------|------|---------|-------------|
391
+ | 参数 | 类型 | 默认值 | 说明 |
392
+ |------|------|--------|------|
393
393
  | `thresholdKb` | `number` | `1024` | 触发警告的文件大小阈值(单位:KB)。 |
394
394
 
395
395
  **示例:**
@@ -405,7 +405,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
405
405
  ```
406
406
 
407
407
  <Note>
408
- 钩子处理器对 stdin 的有效负载强制限制为 1 MB。若要使用较小内容测试此策略,请将 `thresholdKb` 设置为远低于 1024 的值。
408
+ Hook 处理器对 stdin 负载强制执行 1 MB 的大小限制。若要使用较小内容测试此策略,请将 `thresholdKb` 设为远低于 1024 的值。
409
409
  </Note>
410
410
 
411
411
  ---
@@ -422,7 +422,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
422
422
  ### `warn-background-process`
423
423
 
424
424
  **事件:** PreToolUse (Bash)
425
- **默认行为:** 当通过 `nohup`、`&`、`disown` 或 `screen` 启动后台进程时,指示 Claude 保持谨慎。
425
+ **默认行为:** 在通过 `nohup`、`&`、`disown` 或 `screen` 启动后台进程时,指示 Claude 谨慎操作。
426
426
 
427
427
  无参数。
428
428
 
@@ -431,7 +431,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
431
431
  ### `warn-global-package-install`
432
432
 
433
433
  **事件:** PreToolUse (Bash)
434
- **默认行为:** 在运行 `npm install -g`、`yarn global add` 或不在虚拟环境中执行 `pip install` 之前,指示 Claude 进行确认。
434
+ **默认行为:** 在运行 `npm install -g`、`yarn global add` 或未在虚拟环境中执行的 `pip install` 之前,指示 Claude 进行确认。
435
435
 
436
436
  无参数。
437
437
 
@@ -439,23 +439,23 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
439
439
 
440
440
  ## 包管理器 {#package-managers}
441
441
 
442
- 强制规定 Agent 可以使用的包管理器。
442
+ 限制 Agent 只能使用指定的包管理器。
443
443
 
444
444
  ### `prefer-package-manager`
445
445
 
446
446
  **事件:** PreToolUse (Bash)
447
- **默认行为:** 默认禁用。启用后,会阻止所有不在 `allowed` 列表中的包管理器命令,并告知 Claude 使用允许的包管理器重写该命令。
447
+ **默认行为:** 默认禁用。启用后,将拦截不在 `allowed` 列表中的任何包管理器命令,并告知 Claude 使用允许的包管理器重写该命令。
448
448
 
449
449
  可检测的包管理器:pip, pip3, python -m pip, npm, npx, yarn, pnpm, pnpx, bun, bunx, uv, poetry, pipenv, conda, cargo。
450
450
 
451
- | 参数 | 类型 | 默认值 | 描述 |
452
- |-----------|------|---------|-------------|
453
- | `allowed` | string[] | `[]` | 允许使用的包管理器名称。检测到的管理器若不在此列表中则会被阻止。为空时,该策略不生效。 |
454
- | `blocked` | string[] | `[]` | 在内置列表之外额外需要阻止的管理器名称(例如 `['pdm', 'pipx']`)。 |
451
+ | 参数 | 类型 | 默认值 | 说明 |
452
+ |------|------|--------|------|
453
+ | `allowed` | string[] | `[]` | 允许使用的包管理器名称。检测到的管理器若不在此列表中将被拦截。列表为空时,策略不生效。 |
454
+ | `blocked` | string[] | `[]` | 除内置列表之外需要额外拦截的包管理器名称(如 `['pdm', 'pipx']`)。 |
455
455
 
456
- 内置阻止列表涵盖:pip, pip3, npm, npx, yarn, pnpm, pnpx, bun, bunx, uv, poetry, pipenv, conda, cargo。使用 `blocked` 追加不在此列表中的管理器。
456
+ 内置拦截列表包含:pip, pip3, npm, npx, yarn, pnpm, pnpx, bun, bunx, uv, poetry, pipenv, conda, cargo。使用 `blocked` 可追加不在此列表中的包管理器。
457
457
 
458
- **配置示例:**
458
+ **示例配置:**
459
459
 
460
460
  ```json
461
461
  {
@@ -469,18 +469,18 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
469
469
  }
470
470
  ```
471
471
 
472
- 使用此配置,`pip install flask` 和 `pdm install flask` 都会被拒绝,并告知 Claude 改用 `uv` 或 `bun`。`uv pip install flask` 等命令会被允许,因为 `uv` 在允许列表中且优先被检查。
472
+ 使用此配置,`pip install flask` 和 `pdm install flask` 均会被拒绝,并告知 Claude 改用 `uv` 或 `bun`。而 `uv pip install flask` 则会被允许,因为 `uv` 在允许列表中且优先检查。
473
473
 
474
474
  ---
475
475
 
476
476
  ## AI 行为
477
477
 
478
- 检测 Agent 卡住或行为异常的情况。
478
+ 检测 Agent 陷入循环或行为异常的情况。
479
479
 
480
480
  ### `warn-repeated-tool-calls`
481
481
 
482
482
  **事件:** PreToolUse(所有工具)
483
- **默认行为:** 当同一工具以完全相同的参数被调用 3 次及以上时,指示 Claude 重新考虑——这通常是 Agent 陷入循环的常见信号。
483
+ **默认行为:** 当同一工具以相同参数被调用 3 次或以上时,指示 Claude 重新考虑——这通常是 Agent 陷入循环的信号。
484
484
 
485
485
  无参数。
486
486
 
@@ -488,14 +488,14 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
488
488
 
489
489
  ## 工作流 {#workflow}
490
490
 
491
- 强制执行规范的会话结束工作流。这些策略在 **Stop** 事件上触发,在每个条件满足之前拒绝 Claude 停止。它们遵循自然的依赖链:提交推送 → PR → CI。如果某条策略返回 deny,则链中后续策略会被跳过(deny 短路)。
491
+ 强制执行有纪律的会话结束工作流。这些策略在 **Stop** 事件上触发,在每个条件满足之前拒绝 Claude 停止。它们遵循自然的依赖链:commitpush → PR → CI。若某条策略拒绝,则链中后续策略将被跳过(deny 短路)。
492
492
 
493
- 所有工作流策略都是**失败开放**的:如果所需工具不可用(例如未安装 `gh`、没有 git 远程仓库),策略会放行并附带一条说明性消息,解释为何跳过该检查。
493
+ 所有工作流策略均为**失败开放(fail-open)**模式:如果所需工具不可用(如 `gh` 未安装、无 git 远程仓库),策略将放行并附带说明性消息,解释跳过检查的原因。
494
494
 
495
495
  ### `require-commit-before-stop`
496
496
 
497
497
  **事件:** Stop
498
- **默认行为:** 当存在未提交的更改(已修改、已暂存或未追踪的文件)时,拒绝停止。工作目录干净时返回说明性消息。
498
+ **默认行为:** 当存在未提交的更改(已修改、已暂存或未跟踪的文件)时,拒绝停止。当工作目录干净时,返回说明性消息。
499
499
 
500
500
  无参数。
501
501
 
@@ -504,12 +504,12 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
504
504
  ### `require-push-before-stop`
505
505
 
506
506
  **事件:** Stop
507
- **默认行为:** 当存在未推送的提交,或当前分支没有远程追踪分支时,拒绝停止。如需创建追踪分支,建议使用 `git push -u`。若未配置远程仓库,则失败开放。
507
+ **默认行为:** 当存在未推送的 commit,或当前分支没有远程追踪分支时,拒绝停止。若需要,建议使用 `git push -u` 创建追踪分支。如果未配置远程仓库,则失败开放。
508
508
 
509
509
  **参数:**
510
510
 
511
- | 参数 | 类型 | 默认值 | 描述 |
512
- |-------|------|---------|-------------|
511
+ | 参数 | 类型 | 默认值 | 说明 |
512
+ |------|------|--------|------|
513
513
  | `remote` | `string` | `"origin"` | 推送目标的远程仓库名称。 |
514
514
 
515
515
  **示例:**
@@ -534,8 +534,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
534
534
  无参数。
535
535
 
536
536
  <Note>
537
- 此策略需要安装并完成身份验证的 [GitHub CLI](https://cli.github.com/)(`gh`)。
538
- 运行 `gh auth login` 时,请使用具有 `repo` 权限(用于读取 Pull Request)的个人访问令牌。若 `gh` 未安装或未通过身份验证,该策略会失败开放并向 Claude 报告原因。
537
+ 此策略需要安装并已完成身份验证的 [GitHub CLI](https://cli.github.com/)(`gh`)。请使用具有 `repo` 作用域(用于读取 Pull Request)的个人访问 token 运行 `gh auth login`。如果 `gh` 未安装或未完成身份验证,策略将失败开放并向 Claude 报告原因。
539
538
  </Note>
540
539
 
541
540
  ---
@@ -543,13 +542,12 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
543
542
  ### `require-ci-green-before-stop`
544
543
 
545
544
  **事件:** Stop
546
- **默认行为:** 当当前分支的 CI 检查失败或仍在运行时,拒绝停止。同时检查 GitHub Actions 工作流运行和第三方机器人检查(例如 CodeRabbit、SonarCloud、Codecov)。将 `skipped` 结论视为成功。所有检查通过时返回说明性消息。
545
+ **默认行为:** 当当前分支上的 CI 检查失败或仍在运行时,拒绝停止。同时检查 GitHub Actions 工作流运行状态和第三方 Bot 检查(如 CodeRabbit、SonarCloud、Codecov)。将 `skipped` 和 `cancelled` 结论视为成功。所有检查通过时,返回说明性消息。
547
546
 
548
547
  无参数。
549
548
 
550
549
  <Note>
551
- 此策略需要安装并完成身份验证的 [GitHub CLI](https://cli.github.com/)(`gh`)。
552
- 运行 `gh auth login` 时,请使用具有 `repo` 权限(用于读取 Actions 工作流运行和 Checks API)的个人访问令牌。若 `gh` 未安装或未通过身份验证,该策略会失败开放并向 Claude 报告原因。
550
+ 此策略需要安装并已完成身份验证的 [GitHub CLI](https://cli.github.com/)(`gh`)。请使用具有 `repo` 作用域(用于读取 Actions 工作流运行状态和 Checks API)的个人访问 token 运行 `gh auth login`。如果 `gh` 未安装或未完成身份验证,策略将失败开放并向 Claude 报告原因。
553
551
  </Note>
554
552
 
555
553
  ---
@@ -558,7 +556,7 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
558
556
 
559
557
  ## 禁用单条策略
560
558
 
561
- 从配置文件的 `enabledPolicies` 中移除特定策略,或在控制台的"策略"标签页中将其关闭。
559
+ 从配置文件的 `enabledPolicies` 中移除特定策略,或在控制台的策略标签页中将其关闭。
562
560
 
563
561
  ```json
564
562
  {
@@ -569,4 +567,4 @@ failproofai 内置了 30 条策略,用于捕获常见的 Agent 故障模式。
569
567
  }
570
568
  ```
571
569
 
572
- 未列在 `enabledPolicies` 中的策略不会运行,即使在 `policyParams` 中存在对应的条目也不例外。
570
+ 未在 `enabledPolicies` 中列出的策略不会运行,即使 `policyParams` 中存在对应的条目也不例外。
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "failproofai",
3
- "version": "0.0.6-beta.2",
3
+ "version": "0.0.6-beta.3",
4
4
  "description": "The easiest way to manage policies that keep your AI agents reliable, on-task, and running autonomously — for Claude Code & the Agents SDK",
5
5
  "bin": {
6
6
  "failproofai": "./dist/cli.mjs"
@@ -9,7 +9,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
9
9
  const hostname = process.env.HOSTNAME || '0.0.0.0'
10
10
 
11
11
  let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
12
- const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"0.0.6-beta.2"},"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/failproofai/failproofai","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":false,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"partialFallbacks":false,"dynamicOnHover":false,"varyParams":false,"prefetchInlining":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/failproofai/failproofai"},"distDirRoot":".next"}
12
+ const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"0.0.6-beta.3"},"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/failproofai/failproofai","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":false,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"partialFallbacks":false,"dynamicOnHover":false,"varyParams":false,"prefetchInlining":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/failproofai/failproofai"},"distDirRoot":".next"}
13
13
 
14
14
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
15
15
 
@@ -0,0 +1,104 @@
1
+ import { spawn } from "node:child_process";
2
+ import { platform } from "node:os";
3
+ import { writeTokens, type AuthTokens } from "./token-store";
4
+
5
+ const DEFAULT_SERVER_URL = process.env.FAILPROOFAI_SERVER_URL ?? "https://api.befailproof.ai";
6
+ const HTTP_TIMEOUT_MS = 10_000;
7
+
8
+ interface DeviceCodeResponse {
9
+ device_code: string;
10
+ user_code: string;
11
+ verification_url: string;
12
+ expires_in: number;
13
+ interval: number;
14
+ }
15
+
16
+ interface TokenResponse {
17
+ access_token: string;
18
+ refresh_token: string;
19
+ expires_in: number;
20
+ user: { id: string; email: string; name?: string };
21
+ }
22
+
23
+ function openBrowser(url: string): void {
24
+ const os = platform();
25
+ try {
26
+ if (os === "darwin") {
27
+ spawn("open", [url], { detached: true, stdio: "ignore" }).unref();
28
+ } else if (os === "win32") {
29
+ // On cmd's `start`, the first quoted token is treated as a window
30
+ // title. Pass an empty title so URLs containing "&" or spaces are
31
+ // interpreted as the target, not the title.
32
+ spawn("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
33
+ } else {
34
+ spawn("xdg-open", [url], { detached: true, stdio: "ignore" }).unref();
35
+ }
36
+ } catch {
37
+ // Fallback: the URL is already printed above.
38
+ }
39
+ }
40
+
41
+ async function postJson<T>(url: string, body: unknown, timeoutMs = HTTP_TIMEOUT_MS): Promise<T> {
42
+ const resp = await fetch(url, {
43
+ method: "POST",
44
+ headers: { "Content-Type": "application/json" },
45
+ body: JSON.stringify(body),
46
+ signal: AbortSignal.timeout(timeoutMs),
47
+ });
48
+ if (!resp.ok) {
49
+ throw new Error(`${url} → ${resp.status} ${resp.statusText}`);
50
+ }
51
+ return (await resp.json()) as T;
52
+ }
53
+
54
+ export async function login(): Promise<void> {
55
+ const serverUrl = DEFAULT_SERVER_URL;
56
+
57
+ console.log("Requesting device code...");
58
+ const dc = await postJson<DeviceCodeResponse>(`${serverUrl}/api/v1/auth/device-code`, {});
59
+
60
+ console.log(`\n Open this URL in your browser (will be opened automatically):`);
61
+ console.log(` ${dc.verification_url}\n`);
62
+ console.log(` Your code: ${dc.user_code}\n`);
63
+
64
+ openBrowser(dc.verification_url);
65
+
66
+ const deadline = Date.now() + dc.expires_in * 1000;
67
+ const intervalMs = dc.interval * 1000;
68
+
69
+ while (Date.now() < deadline) {
70
+ await new Promise((r) => setTimeout(r, intervalMs));
71
+ try {
72
+ const result = await postJson<TokenResponse | { status: string }>(
73
+ `${serverUrl}/api/v1/auth/device-token`,
74
+ { device_code: dc.device_code },
75
+ );
76
+ if ("access_token" in result) {
77
+ const tokens: AuthTokens = {
78
+ access_token: result.access_token,
79
+ refresh_token: result.refresh_token,
80
+ expires_at: Math.floor(Date.now() / 1000) + result.expires_in,
81
+ user_email: result.user.email,
82
+ user_id: result.user.id,
83
+ server_url: serverUrl,
84
+ };
85
+ writeTokens(tokens);
86
+ console.log(`Logged in as ${result.user.email}`);
87
+
88
+ // Auto-start relay daemon
89
+ try {
90
+ const { ensureRelayRunning } = await import("../relay/daemon");
91
+ ensureRelayRunning();
92
+ console.log("Relay daemon started.");
93
+ } catch (e) {
94
+ console.warn("Failed to auto-start relay daemon:", e);
95
+ }
96
+ return;
97
+ }
98
+ } catch {
99
+ // Pending or transient error — keep polling
100
+ }
101
+ }
102
+
103
+ throw new Error("Login timed out. Run `failproofai login` again.");
104
+ }