failproofai 1.0.9-beta.2 → 1.0.10-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) 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 +4 -4
  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 +6 -6
  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/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
  18. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  21. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  30. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  32. package/.next/standalone/.next/server/app/index.html +1 -1
  33. package/.next/standalone/.next/server/app/index.rsc +14 -14
  34. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
  35. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  36. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  37. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  38. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  41. package/.next/standalone/.next/server/app/policies/page.js +1 -1
  42. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  45. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  48. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  49. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  52. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  55. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  58. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  59. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  60. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  61. package/.next/standalone/.next/server/chunks/src_hooks_1eem5a7._.js +1 -1
  62. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +2 -2
  63. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +2 -2
  64. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1ox4w55._.js → [root-of-the-server]__0a2-9ht._.js} +2 -2
  65. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +2 -2
  66. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +2 -2
  67. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +2 -2
  68. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15578wp._.js +2 -2
  69. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m_svbe._.js +2 -2
  70. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +2 -2
  71. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +2 -2
  72. package/.next/standalone/.next/server/chunks/ssr/_042cgl1._.js +1 -1
  73. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  74. package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +1 -1
  75. package/.next/standalone/.next/server/chunks/ssr/{_0n6zrjv._.js → _0krq5f0._.js} +3 -3
  76. package/.next/standalone/.next/server/chunks/ssr/_1gb0ifp._.js +2 -2
  77. package/.next/standalone/.next/server/chunks/ssr/{_1pa3k5k._.js → _1n-mym7._.js} +1 -1
  78. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  79. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
  80. package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  82. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  83. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +1 -1
  85. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  86. package/.next/standalone/.next/server/pages/404.html +1 -1
  87. package/.next/standalone/.next/server/pages/500.html +1 -1
  88. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  89. package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
  90. package/.next/standalone/.next/static/chunks/0s4cko_weh6pi.js +1 -0
  91. package/.next/standalone/.next/static/chunks/0yclxmfppc_8e.js +1 -0
  92. package/.next/standalone/.next/static/chunks/{30z-240_lrczt.js → 1-k37ijadiv9h.js} +1 -1
  93. package/.next/standalone/.next/static/chunks/{28cmd5molgwa3.js → 18reoqya39rov.js} +1 -1
  94. package/.next/standalone/.next/static/chunks/{2b59i-n9l-4of.js → 2cvvec76j9bwq.js} +1 -1
  95. package/.next/standalone/.next/static/chunks/2o9-3ff26v4yd.js +1 -0
  96. package/.next/standalone/.next/static/chunks/3q8vesnwk_r0i.js +1 -0
  97. package/.next/standalone/.next/static/chunks/3tj1zi4xv-bll.js +1 -0
  98. package/.next/standalone/.next/static/chunks/3vk6jdkxvb7yk.js +6 -0
  99. package/.next/standalone/.next/static/chunks/{1srecm9k-z_i1.js → 3z7mx6me_j7d3.js} +1 -1
  100. package/.next/standalone/.next/static/chunks/{2hg_bp8z_vm2g.js → 3ztf2h_fv6_t9.js} +1 -1
  101. package/.next/standalone/fp-cloud-cli/fp_cli/app.py +4 -0
  102. package/.next/standalone/fp-cloud-cli/fp_cli/auth.py +29 -4
  103. package/.next/standalone/fp-cloud-cli/fp_cli/client.py +57 -14
  104. package/.next/standalone/fp-cloud-cli/fp_cli/errors.py +17 -3
  105. package/.next/standalone/fp-cloud-cli/tests/test_request_id.py +111 -0
  106. package/.next/standalone/fp-cloud-cli/uv.lock +3 -3
  107. package/.next/standalone/hermes-plugin/README.md +83 -10
  108. package/.next/standalone/hermes-plugin/__init__.py +762 -28
  109. package/.next/standalone/hermes-plugin/client.py +4 -2
  110. package/.next/standalone/hermes-plugin/ledger.py +9 -3
  111. package/.next/standalone/hermes-plugin/plugin.yaml +2 -2
  112. package/.next/standalone/package.json +10 -10
  113. package/.next/standalone/sdk/python/failproofai_sdk/evaluator/__init__.py +8 -1
  114. package/.next/standalone/sdk/python/failproofai_sdk/evaluator/client.py +82 -7
  115. package/.next/standalone/sdk/python/failproofai_sdk/evaluator/runtime.py +23 -4
  116. package/.next/standalone/sdk/python/tests/test_evaluator_request_id.py +197 -0
  117. package/.next/standalone/sdk/python/uv.lock +9 -9
  118. package/.next/standalone/sdk/typescript/CHANGELOG.md +39 -0
  119. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +3 -3
  120. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +1 -1
  121. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +16 -113
  122. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +3 -1
  123. package/.next/standalone/server.js +1 -1
  124. package/dist/cli.mjs +235 -117
  125. package/dist/worker.mjs +5 -2
  126. package/hermes-plugin/README.md +83 -10
  127. package/hermes-plugin/__init__.py +762 -28
  128. package/hermes-plugin/client.py +4 -2
  129. package/hermes-plugin/ledger.py +9 -3
  130. package/hermes-plugin/plugin.yaml +2 -2
  131. package/package.json +10 -10
  132. package/src/hooks/daemon-service.ts +14 -1
  133. package/src/hooks/integrations.ts +108 -26
  134. package/src/hooks/safe-config-write.ts +80 -7
  135. package/src/hooks/types.ts +7 -0
  136. package/.next/standalone/.next/static/chunks/0h--izcpk__m9.js +0 -1
  137. package/.next/standalone/.next/static/chunks/2k5vhij_w1g82.js +0 -1
  138. package/.next/standalone/.next/static/chunks/2o1fy-waqn1he.js +0 -6
  139. package/.next/standalone/.next/static/chunks/38gpf5tb_rd0m.js +0 -1
  140. package/.next/standalone/.next/static/chunks/3nyf50dub1vuk.js +0 -1
  141. package/.next/standalone/.next/static/chunks/42-l25bbfo0ec.js +0 -1
  142. /package/.next/standalone/.next/static/{D1BjwOkHNPetPo47DhV4_ → OJTzlkhxVSWnwhlF2Q7m3}/_buildManifest.js +0 -0
  143. /package/.next/standalone/.next/static/{D1BjwOkHNPetPo47DhV4_ → OJTzlkhxVSWnwhlF2Q7m3}/_clientMiddlewareManifest.js +0 -0
  144. /package/.next/standalone/.next/static/{D1BjwOkHNPetPo47DhV4_ → OJTzlkhxVSWnwhlF2Q7m3}/_ssgManifest.js +0 -0
@@ -7,6 +7,11 @@ translates structured verdicts into Hermes-native hook behavior.
7
7
  Validated contract: Hermes 0.21.3 at
8
8
  `4d55ca91656ac5f83e1506679b7f81e0238e5e16`. The plugin uses only documented
9
9
  manifest v2 fields, `PluginContext` methods/state, and keyword hook payloads.
10
+ Hermes 0.20.0 is also supported: its `PluginContext` has no `get_config` or
11
+ `state` (both arrived in 0.20.1), so the plugin reads the same
12
+ `plugins.entries.failproofai` settings through Hermes' config loader and keeps
13
+ its ledger in the directory `state.data_dir` would name, which a later Hermes
14
+ upgrade reuses.
10
15
 
11
16
  ## Installation
12
17
 
@@ -40,6 +45,14 @@ Legacy FailproofAI shell hooks are removed during migration. Operator-owned
40
45
  hooks and unrelated plugin settings are preserved. No dashboard deployment or
41
46
  backtest is part of installation.
42
47
 
48
+ ## Supported Hermes versions
49
+
50
+ Hermes 0.20.0 and later. Tested on 0.20.0 (v2026.8.3), 0.20.1 (v2026.8.13),
51
+ 0.20.6 (v2026.8.27), 0.21.0 (v2026.8.31), 0.21.3 (v2026.9.14), 0.21.5
52
+ (v2026.9.24, the latest release) and upstream main (2026-10-05).
53
+ Hermes 0.20.0 has no `ctx.get_config` or `ctx.state`; the plugin detects that and
54
+ reads the same settings and state directory another way.
55
+
43
56
  ## Runtime path
44
57
 
45
58
  ```text
@@ -49,6 +62,8 @@ Hermes pre_tool_call
49
62
  -> warm TypeScript policy worker
50
63
  -> structured allow | deny | instruct verdict
51
64
  -> Hermes-native return value
65
+ Hermes tool_execution middleware (wraps the real call)
66
+ -> instruct reminder placed at the start of the call's own result
52
67
  ```
53
68
 
54
69
  There is no cloud request and no new CLI process in the tool-call path.
@@ -57,16 +72,67 @@ There is no cloud request and no new CLI process in the tool-call path.
57
72
 
58
73
  - `allow`: return no directive; Hermes runs the tool.
59
74
  - `deny`: always return `{"action":"block","message":"..."}`.
60
- - `instruct`: persist delivery state, block the first attempt with a
61
- model-visible `FAILPROOF INSTRUCTION`, keep the same API request blocked, then
62
- allow a later API iteration for the same instruction scope.
63
-
64
- The default instruction scope is profile + session + task + turn + policy
65
- fingerprint + canonical tool. The persistent SQLite ledger lives below Hermes'
66
- profile-scoped plugin data directory. Two distinct instruction interruptions
67
- are allowed per turn by default; after that, advisory instructions fail open so
68
- they cannot create an infinite retry loop. A real deny is never bypassed by the
69
- ledger.
75
+ - `instruct`: the call runs, and the reminder is placed at the **start** of its
76
+ result, so it survives the 1,500-character preview Hermes keeps of a large
77
+ result:
78
+ - a JSON object result gets `"failproof_policy_reminder"` as its first key
79
+ (the rest is unchanged, so `json.loads` consumers such as `execute_code`
80
+ scripts keep working). A field of that name the tool returned itself is
81
+ moved to `"tool_failproof_policy_reminder"`, never merged into the
82
+ reminder;
83
+ - other text gets a leading `[FailproofAI policy reminder (<policies>)] ...`
84
+ line (an `Error...` result keeps that prefix and gets the line at its end);
85
+ - a list of content blocks or a multimodal envelope gets a leading text block,
86
+ leaving image blocks intact.
87
+
88
+ Tool calls made by an `execute_code` script hand their reminder to the outer
89
+ `execute_code` result, which is the one the model reads, and the script gets
90
+ its own result untouched, so nothing it prints, writes or sends carries the
91
+ reminder. (With no open outer call to carry it, the inner result keeps it.)
92
+ A result Hermes reports as blocked (`{"error": ...}` only) is never
93
+ annotated. This uses Hermes' `tool_execution` middleware
94
+ (`ctx.register_middleware`, present unchanged in 0.20.0, 0.21.x and main).
95
+
96
+ A policy's reminder (same policy and reason) is attached once per Hermes
97
+ session + turn; a later turn gets it again. When the full reminder would take
98
+ the result past 7,500 characters it is shortened to the policy names and the
99
+ first 160 characters of the reason, so it never pushes a result over Hermes'
100
+ 8,000-character persistence threshold and never fills the 1,500-character
101
+ preview of a result already past it.
102
+
103
+ `instruct` therefore no longer stops the action first on Hermes: use `deny`
104
+ when an action must not happen at all.
105
+
106
+ Where Hermes offers no `tool_execution` middleware, `instruct` falls back to
107
+ holding the call once: persist delivery state, return model-visible
108
+ `FailproofAI policy guidance (...)` ("apply it, then continue; repeating the
109
+ same call is allowed"), keep the same API request held, then allow a later API
110
+ iteration. That fallback's scope is profile + session + task + turn + policy
111
+ fingerprint — not the tool, so moving the same work to another tool (for
112
+ example `execute_code`) is not held again.
113
+ The persistent SQLite ledger lives below Hermes' profile-scoped plugin data
114
+ directory. Two distinct instruction interruptions are allowed per turn by
115
+ default; after that, advisory instructions fail open so they cannot create an
116
+ infinite retry loop. A real deny is never bypassed by the ledger.
117
+
118
+ Every model turn also receives a short protocol note (`pre_llm_call`): a
119
+ `failproof_policy_reminder` is an operator rule added by FailproofAI (not tool
120
+ data) about a call that ran normally and is never to be quoted, repeated or
121
+ mentioned in replies, messages or files, a FailproofAI block means that action
122
+ must not run by any route, and `FailproofAI policy guidance` held a call only once.
123
+
124
+ No hook raises: `pre_tool_call` blocks on any internal error (Hermes 0.20.0 and
125
+ 0.21.x would treat a raised exception as allow), observer hooks log and return,
126
+ and the middleware falls back to the plain result. One evaluation, connect
127
+ included, is capped at 25 seconds (`evaluation_timeout_ms`, default 12000):
128
+ Hermes 0.21.x abandons a `pre_tool_call` after 30 seconds and then blocks every
129
+ call for 60. Observer hooks wait at most 2 seconds, so against a hung daemon a
130
+ blocked call costs the evaluation deadline plus 2 seconds, not twice the
131
+ deadline.
132
+
133
+ Tool names are canonicalized in the daemon: Hermes 0.21's `process_manage`,
134
+ `cronjob_manage` and `todo_list` match policies written for 0.20's `process`,
135
+ `cronjob` and `todo`.
70
136
 
71
137
  ## Configuration
72
138
 
@@ -137,6 +203,13 @@ hermes plugins doctor ~/.hermes/plugins/failproofai --ci
137
203
  hermes logs --level WARNING
138
204
  ```
139
205
 
206
+ Each `register()` writes `heartbeat.json` beside `instructions.db` in the
207
+ profile's plugin data directory (`plugin-data/agent-plugin-failproofai-5296f299/`):
208
+ pid, Hermes version, `HERMES_HOME`, profile, the plugin's real path and version,
209
+ the hooks and middleware Hermes accepted, `register_ok` and a timestamp. It is
210
+ the proof of what a running Hermes process actually loaded, which
211
+ `hermes plugins list` (config only) cannot show; Hermes' log gets one INFO line.
212
+
140
213
  Use a temporary `HERMES_HOME` for development and compatibility tests. Remove
141
214
  the integration with:
142
215