blun-king-cli 9.1.587 → 9.1.589

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 (436) hide show
  1. package/CHANGELOG.md +11 -185
  2. package/LIESMICH.txt +51 -13
  3. package/README.md +44 -47
  4. package/agent-spine-plugin/.codex-plugin/plugin.json +16 -4
  5. package/agent-spine-plugin/CHANGELOG.md +37 -5
  6. package/agent-spine-plugin/README.md +3 -3
  7. package/agent-spine-plugin/blun.plugin.json +45 -10
  8. package/agent-spine-plugin/docs/artifact-evaluation.md +93 -0
  9. package/agent-spine-plugin/docs/host-integration.md +42 -27
  10. package/agent-spine-plugin/docs/preflight-recall.md +4 -2
  11. package/agent-spine-plugin/docs/session-timeline.md +97 -236
  12. package/agent-spine-plugin/docs/world-model.md +25 -0
  13. package/agent-spine-plugin/hooks/codex.json +1 -1
  14. package/agent-spine-plugin/hooks/hooks.json +1 -1
  15. package/agent-spine-plugin/package.json +1 -3
  16. package/agent-spine-plugin/scripts/check-hosts.js +3 -3
  17. package/agent-spine-plugin/scripts/release-check.js +10 -5
  18. package/agent-spine-plugin/scripts/run-checks.js +4 -1
  19. package/agent-spine-plugin/scripts/run-tests-hermetic.js +32 -6
  20. package/agent-spine-plugin/src/cli-learning.js +15 -0
  21. package/agent-spine-plugin/src/cli.js +2 -0
  22. package/agent-spine-plugin/src/hook.js +32 -32
  23. package/agent-spine-plugin/src/lib/action-lesson-recall.js +73 -8
  24. package/agent-spine-plugin/src/lib/briefing.js +146 -36
  25. package/agent-spine-plugin/src/lib/channel-continuity.js +19 -0
  26. package/agent-spine-plugin/src/lib/delivery-agent-usage.js +14 -7
  27. package/agent-spine-plugin/src/lib/gateway-group-response.js +128 -0
  28. package/agent-spine-plugin/src/lib/gateway-runs.js +24 -15
  29. package/agent-spine-plugin/src/lib/hook-briefing-use.js +13 -3
  30. package/agent-spine-plugin/src/lib/hook-context.js +16 -3
  31. package/agent-spine-plugin/src/lib/hook-output.js +129 -5
  32. package/agent-spine-plugin/src/lib/hook-timeline.js +5 -3
  33. package/agent-spine-plugin/src/lib/indexed-memory.js +2 -2
  34. package/agent-spine-plugin/src/lib/learning-artifact-evaluator.js +114 -0
  35. package/agent-spine-plugin/src/lib/learning-context.js +11 -4
  36. package/agent-spine-plugin/src/lib/learning-measurements.js +2 -2
  37. package/agent-spine-plugin/src/lib/mcp-runtime.js +89 -3
  38. package/agent-spine-plugin/src/lib/mcp-source-context.js +12 -2
  39. package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +91 -8
  40. package/agent-spine-plugin/src/lib/mcp-world-tools.js +2 -2
  41. package/agent-spine-plugin/src/lib/owned-file-lock.js +20 -1
  42. package/agent-spine-plugin/src/lib/persona-runtime.js +2 -2
  43. package/agent-spine-plugin/src/lib/preflight-delivery-id.js +27 -0
  44. package/agent-spine-plugin/src/lib/preflight.js +4 -4
  45. package/agent-spine-plugin/src/lib/session-timeline-codex.js +15 -0
  46. package/agent-spine-plugin/src/lib/session-timeline-contract.js +12 -4
  47. package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +36 -7
  48. package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +13 -10
  49. package/agent-spine-plugin/src/lib/session-timeline-invocation.js +1 -1
  50. package/agent-spine-plugin/src/lib/session-timeline-king.js +14 -0
  51. package/agent-spine-plugin/src/lib/session-timeline-prior.js +18 -12
  52. package/agent-spine-plugin/src/lib/session-timeline-provider.js +5 -0
  53. package/agent-spine-plugin/src/lib/session-timeline-query.js +2 -0
  54. package/agent-spine-plugin/src/lib/session-timeline-results.js +35 -10
  55. package/agent-spine-plugin/src/lib/session-timeline-source-open.js +30 -0
  56. package/agent-spine-plugin/src/lib/session-timeline.js +122 -75
  57. package/agent-spine-plugin/src/lib/source-roots.js +3 -2
  58. package/agent-spine-plugin/src/lib/task-knowledge-context.js +22 -1
  59. package/agent-spine-plugin/src/lib/timeline-continuation-update.js +100 -0
  60. package/agent-spine-plugin/src/lib/timeline-tool-guard.js +30 -7
  61. package/agent-spine-plugin/src/lib/timeline-user-feedback.js +217 -0
  62. package/agent-spine-plugin/src/lib/timeline-world-capture.js +233 -0
  63. package/agent-spine-plugin/src/lib/world-knowledge.js +59 -2
  64. package/agent-spine-plugin/src/lib/world-model.js +64 -9
  65. package/agent-spine-plugin/src/worker.js +13 -1
  66. package/bin/blun.js +43 -28
  67. package/bin/core-bootstrap.js +5 -4
  68. package/bin/king.js +43 -28
  69. package/bin/launcher-mode.js +1 -10
  70. package/bin/launcher-runtime.js +128 -295
  71. package/bin/managed-node.js +0 -0
  72. package/bin/managed-plugin-selection.cjs +0 -1
  73. package/bin/native-module-repair.js +0 -0
  74. package/bin/node-runtime.js +0 -0
  75. package/bin/node-version.js +0 -0
  76. package/bin/plugin-bootstrap.js +56 -120
  77. package/bin/private-paths.js +11 -34
  78. package/bin/standard-tools-bootstrap.js +34 -114
  79. package/bin/turn-thinking-policy.cjs +3 -11
  80. package/bin/update-copy.js +200 -0
  81. package/bin/update-lease.js +0 -0
  82. package/bin/update-notice.js +155 -274
  83. package/bin/verify-agent-behavior.cjs +122 -0
  84. package/bin/verify-agent-components.cjs +104 -0
  85. package/bin/verify-bundled-agent-sources.cjs +57 -0
  86. package/blun.mjs +143076 -135288
  87. package/bundled-agent-sources.json +701 -0
  88. package/package.json +12 -15
  89. package/standard-skills/translate-native/README.md +1293 -0
  90. package/standard-skills/translate-native/SKILL.md +172 -22
  91. package/standard-skills/translate-native/VERSION +1 -1
  92. package/standard-skills/translate-native/agents/openai.yaml +18 -0
  93. package/standard-skills/translate-native/assets/icon.svg +8 -0
  94. package/standard-skills/translate-native/docs/BLUN_CODE_INTEGRATION.md +76 -0
  95. package/standard-skills/translate-native/docs/PREMORTEM.md +489 -0
  96. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +2035 -0
  97. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1302 -0
  98. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +136 -0
  99. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HEALTH_HTTP.md +130 -0
  100. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +175 -0
  101. package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +86 -0
  102. package/standard-skills/translate-native/integrations/AGENT_RULES.md +32 -0
  103. package/standard-skills/translate-native/integrations/adapters/blun-code-language-guard.js +514 -0
  104. package/standard-skills/translate-native/integrations/adapters/node-language-guard.js +230 -0
  105. package/standard-skills/translate-native/integrations/audit_log.py +327 -0
  106. package/standard-skills/translate-native/integrations/claude_language_hook.js +1536 -0
  107. package/standard-skills/translate-native/integrations/commercial_localization_profile.py +42 -0
  108. package/standard-skills/translate-native/integrations/delivery-policy.example.json +28 -0
  109. package/standard-skills/translate-native/integrations/enforced_delivery.py +543 -0
  110. package/standard-skills/translate-native/integrations/guard_service.py +435 -0
  111. package/standard-skills/translate-native/integrations/language_gateway.py +67 -0
  112. package/standard-skills/translate-native/integrations/mcp_auth_headers.py +198 -0
  113. package/standard-skills/translate-native/integrations/mcp_http_gateway.py +429 -0
  114. package/standard-skills/translate-native/integrations/non_language_html_entities.js +1485 -0
  115. package/standard-skills/translate-native/integrations/pre_output_guard.py +65 -0
  116. package/standard-skills/translate-native/integrations/task_router.py +101 -0
  117. package/standard-skills/translate-native/integrations/website_localization.py +401 -0
  118. package/standard-skills/translate-native/integrations/website_localization_api.py +581 -0
  119. package/standard-skills/translate-native/integrations/website_localization_benchmark.py +1885 -0
  120. package/standard-skills/translate-native/integrations/website_localization_benchmark_campaign.py +1772 -0
  121. package/standard-skills/translate-native/integrations/website_localization_benchmark_candidate.py +506 -0
  122. package/standard-skills/translate-native/integrations/website_localization_benchmark_http.py +400 -0
  123. package/standard-skills/translate-native/integrations/website_localization_benchmark_review_store.py +781 -0
  124. package/standard-skills/translate-native/integrations/website_localization_benchmark_reviewer_http.py +500 -0
  125. package/standard-skills/translate-native/integrations/website_localization_benchmark_runtime.py +1107 -0
  126. package/standard-skills/translate-native/integrations/website_localization_benchmark_suite.py +463 -0
  127. package/standard-skills/translate-native/integrations/website_localization_cms.py +2835 -0
  128. package/standard-skills/translate-native/integrations/website_localization_cms_client.py +875 -0
  129. package/standard-skills/translate-native/integrations/website_localization_cms_dispatch.py +805 -0
  130. package/standard-skills/translate-native/integrations/website_localization_cms_http.py +588 -0
  131. package/standard-skills/translate-native/integrations/website_localization_cms_lifecycle_monitor.py +991 -0
  132. package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +1441 -0
  133. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +414 -0
  134. package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +1073 -0
  135. package/standard-skills/translate-native/integrations/website_localization_cms_removal_dispatch.py +865 -0
  136. package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +583 -0
  137. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +964 -0
  138. package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +665 -0
  139. package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +1153 -0
  140. package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +675 -0
  141. package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +1125 -0
  142. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification.py +674 -0
  143. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +444 -0
  144. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +1469 -0
  145. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +1142 -0
  146. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +634 -0
  147. package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +804 -0
  148. package/standard-skills/translate-native/integrations/website_localization_deepl_baseline.py +922 -0
  149. package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +482 -0
  150. package/standard-skills/translate-native/integrations/website_localization_health.py +1541 -0
  151. package/standard-skills/translate-native/integrations/website_localization_health_http.py +372 -0
  152. package/standard-skills/translate-native/integrations/website_localization_http_provider.py +297 -0
  153. package/standard-skills/translate-native/integrations/website_localization_native_reference_http.py +479 -0
  154. package/standard-skills/translate-native/integrations/website_localization_native_reference_intake.py +363 -0
  155. package/standard-skills/translate-native/integrations/website_localization_native_reference_queue.py +1449 -0
  156. package/standard-skills/translate-native/integrations/website_localization_native_reference_store.py +420 -0
  157. package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +235 -0
  158. package/standard-skills/translate-native/integrations/website_localization_queue.py +671 -0
  159. package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +516 -0
  160. package/standard-skills/translate-native/integrations/website_localization_release.py +928 -0
  161. package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +1008 -0
  162. package/standard-skills/translate-native/integrations/website_localization_runner.py +276 -0
  163. package/standard-skills/translate-native/integrations/website_localization_runtime.py +862 -0
  164. package/standard-skills/translate-native/integrations/website_localization_service.py +350 -0
  165. package/standard-skills/translate-native/integrations/website_localization_supervisor.py +511 -0
  166. package/standard-skills/translate-native/integrations/website_localization_worker.py +663 -0
  167. package/standard-skills/translate-native/provenance.json +3 -4
  168. package/standard-skills/translate-native/references/commercial-localization.md +177 -0
  169. package/standard-skills/translate-native/scripts/blun_language_guard.py +7 -1
  170. package/standard-skills/translate-native/scripts/check_commercial_review.py +80 -0
  171. package/standard-skills/translate-native/scripts/commercial_localization_profile.py +333 -0
  172. package/standard-tools/language-guard/LICENSE +21 -0
  173. package/standard-tools/language-guard/VERSION +1 -0
  174. package/standard-tools/language-guard/blun_language_guard.py +7 -1
  175. package/standard-tools/language-guard/check_commercial_review.py +80 -0
  176. package/standard-tools/language-guard/commercial_localization_profile.py +333 -0
  177. package/standard-tools/language-guard/language_gateway.py +62 -0
  178. package/standard-tools/language-guard/pre_output_guard.py +64 -0
  179. package/standard-tools/language-guard/provenance.json +4 -11
  180. package/standard-tools/manifest.json +34 -11
  181. package/telegram-plugin/commands/access.md +2 -10
  182. package/telegram-plugin/dist/bridge.mjs +64041 -687
  183. package/telegram-plugin/dist/mcp-server.mjs +72810 -9027
  184. package/telegram-plugin/dist/noise.mjs +28 -63511
  185. package/agent-spine-plugin/CONTRIBUTING.md +0 -52
  186. package/agent-spine-plugin/SECURITY.md +0 -47
  187. package/agent-spine-plugin/docs/assignment-continuation.md +0 -48
  188. package/agent-spine-plugin/docs/releasing.md +0 -85
  189. package/agent-spine-plugin/docs/structured-completion.md +0 -67
  190. package/bin/abort-listener-policy.cjs +0 -43
  191. package/bin/active-steer-priority-policy.cjs +0 -24
  192. package/bin/agent-api-http-adapter.mjs +0 -446
  193. package/bin/agent-api-private-http-server.mjs +0 -288
  194. package/bin/agent-api-runtime.mjs +0 -252
  195. package/bin/agent-api-service-environment.mjs +0 -236
  196. package/bin/agent-api-service-host.mjs +0 -209
  197. package/bin/agent-api-service-process.mjs +0 -171
  198. package/bin/agent-api-session-registry.mjs +0 -428
  199. package/bin/agent-api-tool-broker.cjs +0 -248
  200. package/bin/agent-api-turn-controller.mjs +0 -461
  201. package/bin/agent-api-usage-journal.cjs +0 -259
  202. package/bin/agent-resume-snapshot.cjs +0 -241
  203. package/bin/agentspine-king-goal-inbox.mjs +0 -111
  204. package/bin/agentspine-king-goal-intake.mjs +0 -106
  205. package/bin/approval-rejection-stop.cjs +0 -15
  206. package/bin/assistant-message-offload-policy.cjs +0 -284
  207. package/bin/baseline-skill-performance-policy.cjs +0 -39
  208. package/bin/bash-search-scope-policy.cjs +0 -49
  209. package/bin/codebase-search-runtime.cjs +0 -23
  210. package/bin/cognitive-action-checkpoint.cjs +0 -1104
  211. package/bin/cognitive-attention-delivery.cjs +0 -76
  212. package/bin/cognitive-attention-policy.cjs +0 -143
  213. package/bin/cognitive-attention-runtime.cjs +0 -91
  214. package/bin/cognitive-context-projection.cjs +0 -73
  215. package/bin/cognitive-cross-portal-acceptance.cjs +0 -443
  216. package/bin/cognitive-effective-view.cjs +0 -77
  217. package/bin/cognitive-focus-projection.cjs +0 -206
  218. package/bin/cognitive-focus-scope.cjs +0 -37
  219. package/bin/cognitive-goal-autostart-policy.cjs +0 -72
  220. package/bin/cognitive-goal-time-trigger-controller.cjs +0 -146
  221. package/bin/cognitive-memory-adapter.cjs +0 -282
  222. package/bin/cognitive-memory-command.cjs +0 -293
  223. package/bin/cognitive-memory-provider.cjs +0 -92
  224. package/bin/cognitive-salience-policy.cjs +0 -159
  225. package/bin/cognitive-state-store.cjs +0 -508
  226. package/bin/cognitive-turn-lifecycle.cjs +0 -624
  227. package/bin/cognitive-work-focus.cjs +0 -180
  228. package/bin/compaction-history-archive.cjs +0 -166
  229. package/bin/compaction-history-startup.cjs +0 -50
  230. package/bin/compaction-model-policy.cjs +0 -31
  231. package/bin/compaction-stage-policy.cjs +0 -21
  232. package/bin/compaction-transaction-policy.cjs +0 -122
  233. package/bin/config-write-dedup-policy.cjs +0 -27
  234. package/bin/context-budget-ledger.cjs +0 -31
  235. package/bin/context-doctor-policy.cjs +0 -70
  236. package/bin/context-insight-policy.cjs +0 -36
  237. package/bin/context-performance-policy.cjs +0 -19
  238. package/bin/context-pressure-policy.cjs +0 -20
  239. package/bin/cron-run-output.cjs +0 -45
  240. package/bin/cron-run-store.cjs +0 -145
  241. package/bin/curiosity-scout-policy.cjs +0 -49
  242. package/bin/default-model-output-budget-policy.cjs +0 -28
  243. package/bin/durable-task-resume-policy.cjs +0 -130
  244. package/bin/durable-task-resume-runtime.cjs +0 -117
  245. package/bin/durable-task-resume-store.cjs +0 -88
  246. package/bin/editable-tool-approval-policy.cjs +0 -540
  247. package/bin/editable-tool-approval-runtime.cjs +0 -99
  248. package/bin/effective-system-prompt-cache-policy.cjs +0 -33
  249. package/bin/error-memory-performance-policy.cjs +0 -113
  250. package/bin/file-observation-policy.cjs +0 -133
  251. package/bin/foreground-output-capture-policy.cjs +0 -41
  252. package/bin/generated-source-health.cjs +0 -142
  253. package/bin/glob-pattern-policy.cjs +0 -13
  254. package/bin/goal-completion-evidence-policy.cjs +0 -120
  255. package/bin/grep-output-limit-policy.cjs +0 -39
  256. package/bin/historical-media-projection-policy.cjs +0 -48
  257. package/bin/history-offload-pressure-policy.cjs +0 -33
  258. package/bin/html-to-research-markdown.cjs +0 -147
  259. package/bin/identity-context-policy.cjs +0 -764
  260. package/bin/identity-journal-policy.cjs +0 -107
  261. package/bin/input-draft-persistence.cjs +0 -77
  262. package/bin/king-tui-function-contract.json +0 -33
  263. package/bin/launcher-restart-policy.cjs +0 -150
  264. package/bin/live-response-repetition-guard.cjs +0 -196
  265. package/bin/llm-config-log-dedup-policy.cjs +0 -76
  266. package/bin/loop-event-record-policy.cjs +0 -174
  267. package/bin/managed-context-startup-policy.cjs +0 -27
  268. package/bin/media-activity-layout-policy.cjs +0 -34
  269. package/bin/media-auto-retrieval-policy.cjs +0 -90
  270. package/bin/media-result-policy.cjs +0 -59
  271. package/bin/micro-compaction-policy.cjs +0 -145
  272. package/bin/mistake-relevance-policy.cjs +0 -319
  273. package/bin/model-retry-progress-policy.cjs +0 -46
  274. package/bin/native-large-file-io.cjs +0 -42
  275. package/bin/native-runtime-cache.cjs +0 -76
  276. package/bin/natural-presence-policy.cjs +0 -28
  277. package/bin/noninteractive-shell-env-policy.cjs +0 -19
  278. package/bin/observer-hooks.cjs +0 -14
  279. package/bin/outbound-claim-provenance.cjs +0 -150
  280. package/bin/oversized-context-offload-policy.cjs +0 -86
  281. package/bin/pending-media-policy.cjs +0 -182
  282. package/bin/pending-token-estimate-policy.cjs +0 -41
  283. package/bin/personal-memory-consent-policy.cjs +0 -72
  284. package/bin/personal-memory-performance-policy.cjs +0 -12
  285. package/bin/personality-choice-policy.cjs +0 -101
  286. package/bin/personality-memory-adapter.cjs +0 -379
  287. package/bin/personality-mode.cjs +0 -46
  288. package/bin/personality-setup-policy.cjs +0 -197
  289. package/bin/proactive-compaction-policy.cjs +0 -25
  290. package/bin/profile-identity-resolution.cjs +0 -136
  291. package/bin/profile-runtime.cjs +0 -318
  292. package/bin/profile-tool-exclusion-policy.cjs +0 -37
  293. package/bin/programmatic-context-isolation.cjs +0 -25
  294. package/bin/programmatic-tool-runtime.mjs +0 -627
  295. package/bin/provider-idle-timeout-policy.cjs +0 -14
  296. package/bin/provider-model-refresh-deadline.cjs +0 -53
  297. package/bin/provider-model-refresh-policy.cjs +0 -107
  298. package/bin/rate-limit-recovery-policy.cjs +0 -47
  299. package/bin/read-batch-policy.cjs +0 -32
  300. package/bin/read-continuation-policy.cjs +0 -59
  301. package/bin/recurring-cron-history-policy.cjs +0 -124
  302. package/bin/relationship-continuity-policy.cjs +0 -143
  303. package/bin/relationship-curiosity-policy.cjs +0 -107
  304. package/bin/relationship-learning-policy.cjs +0 -168
  305. package/bin/release-artifact-freeze-policy.cjs +0 -30
  306. package/bin/reload-plugin-bootstrap.cjs +0 -18
  307. package/bin/reload-queue-policy.cjs +0 -38
  308. package/bin/repeated-assistant-response-policy.cjs +0 -232
  309. package/bin/repeated-injection-projection.cjs +0 -107
  310. package/bin/repeated-user-message-projection.cjs +0 -8
  311. package/bin/research-page-result.cjs +0 -74
  312. package/bin/retry-checkpoint-policy.cjs +0 -13
  313. package/bin/runtime-exit-ledger.cjs +0 -144
  314. package/bin/scoped-cron-run-policy.cjs +0 -358
  315. package/bin/session-checkpoint-policy.cjs +0 -25
  316. package/bin/session-compaction-policy.cjs +0 -84
  317. package/bin/session-replay-policy.cjs +0 -20
  318. package/bin/session-replay-window-policy.cjs +0 -40
  319. package/bin/session-resume-checkpoint.cjs +0 -254
  320. package/bin/session-scrollback-archive.cjs +0 -229
  321. package/bin/skill-activation-performance-policy.cjs +0 -69
  322. package/bin/skill-listing-performance-policy.cjs +0 -92
  323. package/bin/soul-organization-policy.cjs +0 -78
  324. package/bin/soul-preservation-policy.cjs +0 -20
  325. package/bin/startup-preferences.cjs +0 -131
  326. package/bin/streaming-flush-performance-policy.cjs +0 -28
  327. package/bin/structured-agent-swarm-output.cjs +0 -325
  328. package/bin/structured-subagent-output.cjs +0 -252
  329. package/bin/subagent-context-fork-policy.cjs +0 -155
  330. package/bin/subagent-max-tokens-handoff-policy.cjs +0 -69
  331. package/bin/subagent-parent-responsiveness.cjs +0 -19
  332. package/bin/subagent-skill-policy.cjs +0 -206
  333. package/bin/subagent-timeout-policy.cjs +0 -182
  334. package/bin/subagent-tool-policy.cjs +0 -60
  335. package/bin/subagent-usage-rollup-policy.cjs +0 -29
  336. package/bin/system-prompt-context-policy.cjs +0 -124
  337. package/bin/system-prompt-token-cache-policy.cjs +0 -60
  338. package/bin/telegram-addressed-focus.cjs +0 -55
  339. package/bin/telegram-addressed-priority.cjs +0 -12
  340. package/bin/telegram-approval-relay.cjs +0 -290
  341. package/bin/telegram-bot-priority.cjs +0 -17
  342. package/bin/telegram-console-status-policy.cjs +0 -174
  343. package/bin/telegram-context-projection-policy.cjs +0 -141
  344. package/bin/telegram-delivery-lifecycle.cjs +0 -125
  345. package/bin/telegram-direct-focus-policy.cjs +0 -273
  346. package/bin/telegram-mcp-compatibility.cjs +0 -49
  347. package/bin/telegram-media-delivery-policy.cjs +0 -42
  348. package/bin/telegram-private-conversation-policy.cjs +0 -185
  349. package/bin/telegram-queue-handoff-policy.cjs +0 -73
  350. package/bin/telegram-remote-status-policy.cjs +0 -120
  351. package/bin/telegram-session-queue-runtime.mjs +0 -306
  352. package/bin/telegram-text-chunk-policy.cjs +0 -63
  353. package/bin/telegram-truncated-reply-policy.cjs +0 -37
  354. package/bin/telegram-urgent-policy.cjs +0 -45
  355. package/bin/telemetry-spool-policy.cjs +0 -57
  356. package/bin/thinking-activity-status-policy.cjs +0 -132
  357. package/bin/thinking-only-guard.cjs +0 -80
  358. package/bin/todo-list-turn-policy.cjs +0 -131
  359. package/bin/tool-call-loop-policy.cjs +0 -51
  360. package/bin/tool-file-persistence.cjs +0 -141
  361. package/bin/tool-result-offload-policy.cjs +0 -359
  362. package/bin/tool-result-offload-telemetry.cjs +0 -12
  363. package/bin/tool-schema-token-cache-policy.cjs +0 -41
  364. package/bin/tool-stream-preview-policy.cjs +0 -9
  365. package/bin/tui-functional-contract.cjs +0 -55
  366. package/bin/turn-tool-performance-policy.cjs +0 -486
  367. package/bin/usage-cache-efficiency-policy.cjs +0 -26
  368. package/bin/user-home-path-policy.cjs +0 -13
  369. package/bin/user-message-offload-policy.cjs +0 -103
  370. package/bin/user-prompt-hook-origin-policy.cjs +0 -34
  371. package/bin/user-tool-record-policy.cjs +0 -7
  372. package/bin/validated-learning-insight-policy.cjs +0 -58
  373. package/bin/validated-learning-outcome-trace.cjs +0 -107
  374. package/bin/validated-learning-performance-policy.cjs +0 -53
  375. package/bin/validated-learning-signal.cjs +0 -463
  376. package/bin/windows-bash-dialect-policy.cjs +0 -25
  377. package/bin/windows-node-crash-dump.cjs +0 -110
  378. package/bin/write-continuation-policy.cjs +0 -69
  379. package/codebase-index/README.md +0 -82
  380. package/codebase-index/codebase_index.py +0 -470
  381. package/standard-skills/agent-browser/SKILL.md +0 -19
  382. package/standard-skills/agent-browser/references/runtime.md +0 -8
  383. package/standard-skills/blun-session-inspector/SKILL.md +0 -41
  384. package/standard-skills/blun-session-inspector/scripts/inspect-session.cjs +0 -437
  385. package/standard-skills/design-taste-frontend/SKILL.md +0 -1206
  386. package/standard-skills/full-output-enforcement/SKILL.md +0 -49
  387. package/standard-skills/high-end-visual-design/SKILL.md +0 -98
  388. package/standard-skills/image-to-code/SKILL.md +0 -1228
  389. package/standard-skills/industrial-brutalist-ui/SKILL.md +0 -92
  390. package/standard-skills/minimalist-ui/SKILL.md +0 -85
  391. package/standard-skills/motion-design-taste/SKILL.md +0 -74
  392. package/standard-skills/playwright-testing/SKILL.md +0 -19
  393. package/standard-skills/playwright-testing/references/runtime.md +0 -7
  394. package/standard-skills/premortem/SKILL.md +0 -148
  395. package/standard-skills/redesign-existing-projects/SKILL.md +0 -178
  396. package/standard-skills/research-evidence/SKILL.md +0 -39
  397. package/standard-skills/research-evidence/references/evidence-format.md +0 -104
  398. package/standard-skills/research-evidence/scripts/evidence-collection.cjs +0 -260
  399. package/standard-skills/research-evidence/scripts/score-report.cjs +0 -130
  400. package/standard-skills/screenshot-lesen/SKILL.md +0 -52
  401. package/standard-skills/stitch-design-taste/DESIGN.md +0 -121
  402. package/standard-skills/stitch-design-taste/SKILL.md +0 -184
  403. package/standard-skills/telegram-channel/SKILL.md +0 -18
  404. package/standard-skills/telegram-channel/references/runtime.md +0 -7
  405. package/standard-skills/venture-flywheel/SKILL.md +0 -32
  406. package/standard-skills/venture-flywheel/identity/project-identity.cjs +0 -146
  407. package/standard-skills/venture-flywheel/policy/capability-engine.cjs +0 -114
  408. package/standard-skills/venture-flywheel/policy/repository-trust.cjs +0 -229
  409. package/standard-skills/venture-flywheel/references/BEISPIELE-phase0.md +0 -146
  410. package/standard-skills/venture-flywheel/references/CAPABILITY-MAP.md +0 -34
  411. package/standard-skills/venture-flywheel/references/SPEC-phase0-identity-trust.md +0 -77
  412. package/standard-skills/venture-flywheel/references/SPEC-phase0-state-events.md +0 -93
  413. package/standard-skills/venture-flywheel/schemas/capability-decision.schema.json +0 -13
  414. package/standard-skills/venture-flywheel/schemas/execution-event.schema.json +0 -44
  415. package/standard-skills/venture-flywheel/schemas/project-identity.schema.json +0 -32
  416. package/standard-skills/venture-flywheel/schemas/repository-trust.schema.json +0 -57
  417. package/standard-skills/venture-flywheel/schemas/run-transition.schema.json +0 -59
  418. package/standard-skills/venture-flywheel/state/execution-event.cjs +0 -191
  419. package/standard-skills/venture-flywheel/state/task-state-machine.cjs +0 -190
  420. package/standard-skills/web-lesen/SKILL.md +0 -73
  421. package/standard-skills/web-lesen/scripts/crawl_public.py +0 -379
  422. package/standard-skills/windows-mcp/SKILL.md +0 -19
  423. package/standard-skills/windows-mcp/references/runtime.md +0 -9
  424. package/telegram-plugin/DELIVERY.md +0 -36
  425. package/telegram-plugin/bin/telegram-approval-relay.cjs +0 -290
  426. package/telegram-plugin/bin/telegram-console-status-policy.cjs +0 -175
  427. package/telegram-plugin/bin/telegram-delivery-lifecycle.cjs +0 -125
  428. package/telegram-plugin/bin/telegram-direct-reply-policy.cjs +0 -48
  429. package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +0 -122
  430. package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +0 -186
  431. package/telegram-plugin/bin/telegram-remote-status-policy.cjs +0 -121
  432. package/telegram-plugin/bin/telegram-reply-parts.cjs +0 -149
  433. package/telegram-plugin/bin/telegram-text-chunk-policy.cjs +0 -63
  434. package/telegram-plugin/bin/telegram-typing-keepalive.cjs +0 -89
  435. package/telegram-plugin/compat/mcp-server-fa511cd1.mjs +0 -73825
  436. /package/{bin → scripts}/fix-node-pty-perms.js +0 -0
@@ -0,0 +1,372 @@
1
+ #!/usr/bin/env python3
2
+ """Authenticated, content-free HTTP reader for localization service health.
3
+
4
+ The host supplies authentication and the already-composed read-only health
5
+ callback. This adapter performs no repair, retry, signing, model, or CMS work.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import json
12
+ import math
13
+ import re
14
+ from dataclasses import dataclass
15
+ from typing import Any, Callable, Mapping
16
+
17
+
18
+ HEALTH_PATH = "/v2/localization/health"
19
+ AUTH_REQUEST_SCHEMA = "blun.localization-health-http-auth-request.v1"
20
+ PRINCIPAL_SCHEMA = "blun.localization-health-reader-principal.v1"
21
+ RESPONSE_SCHEMA = "blun.website-localization-health-http.v1"
22
+ ERROR_SCHEMA = "blun.website-localization-health-http-error.v1"
23
+ HEALTH_SCHEMA = "blun.website-localization-health.v1"
24
+ TOKEN = re.compile(r"^[A-Za-z0-9_.:-]{1,256}$")
25
+ ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
26
+ HEADER_NAME = re.compile(r"^[!#$%&'*+.^_`|~0-9A-Za-z-]{1,128}$")
27
+ MAX_HEADERS = 64
28
+ MAX_HEADER_VALUE = 4096
29
+ MAX_RESPONSE_BYTES = 4_000_000
30
+ HEALTH_STATUSES = {"healthy", "degraded", "blocked"}
31
+ PROVIDER_STATUSES = {"healthy", "blocked"}
32
+ WEBSITE_STATUSES = {
33
+ "processing", "localization_failed", "awaiting_approval", "ready",
34
+ "publishing", "publication_failed", "published", "cancelled",
35
+ "deleting", "deletion_failed", "deleted",
36
+ }
37
+
38
+
39
+ class HealthHTTPFailed(RuntimeError):
40
+ """Stable content-free failure returned by the HTTP boundary."""
41
+
42
+ def __init__(self, code: str, *, status: int, retryable: bool = False):
43
+ if not isinstance(code, str) or ERROR_CODE.fullmatch(code) is None:
44
+ raise ValueError("health HTTP error code is invalid")
45
+ if status not in {400, 401, 403, 404, 503}:
46
+ raise ValueError("health HTTP status is invalid")
47
+ if not isinstance(retryable, bool):
48
+ raise ValueError("health HTTP retryability is invalid")
49
+ super().__init__(code)
50
+ self.code = code
51
+ self.status = status
52
+ self.retryable = retryable
53
+
54
+
55
+ @dataclass(frozen=True)
56
+ class HealthReaderPrincipal:
57
+ reader_id: str
58
+ credential_id: str
59
+ credential_version: str
60
+ scope: str
61
+
62
+
63
+ def _canonical_json(value: Any) -> bytes:
64
+ try:
65
+ encoded = json.dumps(
66
+ value,
67
+ ensure_ascii=False,
68
+ allow_nan=False,
69
+ sort_keys=True,
70
+ separators=(",", ":"),
71
+ ).encode("utf-8")
72
+ except (TypeError, ValueError, RecursionError):
73
+ raise HealthHTTPFailed(
74
+ "health.http.response_invalid", status=503, retryable=True,
75
+ ) from None
76
+ if not encoded or len(encoded) > MAX_RESPONSE_BYTES:
77
+ raise HealthHTTPFailed(
78
+ "health.http.response_invalid", status=503, retryable=True,
79
+ )
80
+ return encoded
81
+
82
+
83
+ def _token(value: Any) -> str:
84
+ if not isinstance(value, str) or TOKEN.fullmatch(value) is None:
85
+ raise ValueError
86
+ return value
87
+
88
+
89
+ def _reason(value: Any) -> str:
90
+ if not isinstance(value, str) or ERROR_CODE.fullmatch(value) is None:
91
+ raise ValueError
92
+ return value
93
+
94
+
95
+ def _timestamp(value: Any) -> float:
96
+ if isinstance(value, bool) or not isinstance(value, (int, float)):
97
+ raise ValueError
98
+ result = float(value)
99
+ if not math.isfinite(result) or result < 0:
100
+ raise ValueError
101
+ return result
102
+
103
+
104
+ def _count(value: Any) -> int:
105
+ if isinstance(value, bool) or not isinstance(value, int) or value < 0:
106
+ raise ValueError
107
+ return value
108
+
109
+
110
+ def _exact_mapping(value: Any, fields: set[str]) -> dict[str, Any]:
111
+ if not isinstance(value, dict) or set(value) != fields:
112
+ raise ValueError
113
+ return value
114
+
115
+
116
+ def _counts(value: Any) -> dict[str, int]:
117
+ if not isinstance(value, dict) or len(value) > 64:
118
+ raise ValueError
119
+ return {_token(key): _count(item) for key, item in value.items()}
120
+
121
+
122
+ def _reasons(value: Any) -> list[str]:
123
+ if not isinstance(value, list) or len(value) > 128:
124
+ raise ValueError
125
+ result = [_reason(item) for item in value]
126
+ if result != sorted(set(result)):
127
+ raise ValueError
128
+ return result
129
+
130
+
131
+ def _principal(value: Any) -> HealthReaderPrincipal:
132
+ try:
133
+ value = _exact_mapping(value, {
134
+ "schema", "reader_id", "credential_id", "credential_version",
135
+ "scope",
136
+ })
137
+ if value["schema"] != PRINCIPAL_SCHEMA or value["scope"] != "service-health":
138
+ raise ValueError
139
+ return HealthReaderPrincipal(
140
+ _token(value["reader_id"]),
141
+ _token(value["credential_id"]),
142
+ _token(value["credential_version"]),
143
+ value["scope"],
144
+ )
145
+ except (KeyError, ValueError, TypeError):
146
+ raise HealthHTTPFailed(
147
+ "health.http.authentication_failed", status=401,
148
+ ) from None
149
+
150
+
151
+ def _report_payload(report: Any, *, expected_checked_at: float) -> dict[str, Any]:
152
+ try:
153
+ payload = report.as_payload()
154
+ payload = _exact_mapping(payload, {
155
+ "schema", "checked_at", "status", "components", "providers",
156
+ "website_versions",
157
+ })
158
+ if payload["schema"] != HEALTH_SCHEMA or payload["status"] not in HEALTH_STATUSES:
159
+ raise ValueError
160
+ if _timestamp(payload["checked_at"]) != expected_checked_at:
161
+ raise ValueError
162
+
163
+ components = payload["components"]
164
+ if not isinstance(components, list) or not components or len(components) > 16:
165
+ raise ValueError
166
+ component_names = []
167
+ for component in components:
168
+ component = _exact_mapping(
169
+ component, {"component", "status", "reasons", "counts"},
170
+ )
171
+ component_names.append(_token(component["component"]))
172
+ if component["status"] not in HEALTH_STATUSES:
173
+ raise ValueError
174
+ _reasons(component["reasons"])
175
+ _counts(component["counts"])
176
+ if len(component_names) != len(set(component_names)):
177
+ raise ValueError
178
+ expected_status = (
179
+ "blocked" if any(
180
+ item["status"] == "blocked" for item in components
181
+ ) else "degraded" if any(
182
+ item["status"] == "degraded" for item in components
183
+ ) else "healthy"
184
+ )
185
+ if payload["status"] != expected_status:
186
+ raise ValueError
187
+
188
+ providers = payload["providers"]
189
+ if not isinstance(providers, list) or len(providers) > 1024:
190
+ raise ValueError
191
+ for provider in providers:
192
+ provider = _exact_mapping(provider, {
193
+ "provider_id", "model_id", "model_version", "status", "reason",
194
+ })
195
+ _token(provider["provider_id"])
196
+ _token(provider["model_id"])
197
+ _token(provider["model_version"])
198
+ if provider["status"] not in PROVIDER_STATUSES:
199
+ raise ValueError
200
+ if provider["reason"] is not None:
201
+ _reason(provider["reason"])
202
+
203
+ versions = payload["website_versions"]
204
+ if not isinstance(versions, list) or len(versions) > 100_000:
205
+ raise ValueError
206
+ version_ids = []
207
+ for version in versions:
208
+ version = _exact_mapping(version, {
209
+ "event_id", "site_id", "website_version", "plan_id", "status",
210
+ "required_locales", "approved_locales", "queue_counts",
211
+ "blocked_locales",
212
+ })
213
+ version_ids.append(_token(version["event_id"]))
214
+ for name in ("site_id", "website_version", "plan_id"):
215
+ _token(version[name])
216
+ if version["status"] not in WEBSITE_STATUSES:
217
+ raise ValueError
218
+ required = _count(version["required_locales"])
219
+ approved = _count(version["approved_locales"])
220
+ if approved > required:
221
+ raise ValueError
222
+ _counts(version["queue_counts"])
223
+ blocked = version["blocked_locales"]
224
+ if not isinstance(blocked, list) or len(blocked) > required:
225
+ raise ValueError
226
+ observed = []
227
+ for item in blocked:
228
+ if not isinstance(item, list) or len(item) != 2:
229
+ raise ValueError
230
+ observed.append((_token(item[0]), _reason(item[1])))
231
+ if observed != sorted(set(observed)):
232
+ raise ValueError
233
+ if len(version_ids) != len(set(version_ids)):
234
+ raise ValueError
235
+
236
+ _canonical_json(payload)
237
+ return payload
238
+ except HealthHTTPFailed:
239
+ raise
240
+ except Exception:
241
+ raise HealthHTTPFailed(
242
+ "health.http.response_invalid", status=503, retryable=True,
243
+ ) from None
244
+
245
+
246
+ class WebsiteLocalizationHealthHTTPApplication:
247
+ """Strict authenticated WSGI reader for one composed health monitor."""
248
+
249
+ def __init__(
250
+ self,
251
+ health_provider: Callable[..., Any],
252
+ authenticator: Callable[[dict[str, Any]], Any],
253
+ *,
254
+ clock: Callable[[], float],
255
+ ):
256
+ if not callable(health_provider):
257
+ raise ValueError("health provider must be callable")
258
+ if not callable(authenticator):
259
+ raise ValueError("health authenticator must be callable")
260
+ if not callable(clock):
261
+ raise ValueError("health clock must be callable")
262
+ self.health_provider = health_provider
263
+ self.authenticator = authenticator
264
+ self.clock = clock
265
+
266
+ @staticmethod
267
+ def _headers(environ: Mapping[str, Any]) -> tuple[tuple[str, str], ...]:
268
+ headers = []
269
+ for key, value in environ.items():
270
+ if key.startswith("HTTP_"):
271
+ name = key[5:].replace("_", "-").lower()
272
+ elif key in {"CONTENT_TYPE", "CONTENT_LENGTH"}:
273
+ name = key.replace("_", "-").lower()
274
+ else:
275
+ continue
276
+ if (
277
+ HEADER_NAME.fullmatch(name) is None
278
+ or not isinstance(value, str)
279
+ or len(value) > MAX_HEADER_VALUE
280
+ or "\r" in value
281
+ or "\n" in value
282
+ ):
283
+ raise HealthHTTPFailed("health.http.headers_invalid", status=400)
284
+ headers.append((name, value))
285
+ headers.sort()
286
+ if len(headers) > MAX_HEADERS or len({name for name, _ in headers}) != len(headers):
287
+ raise HealthHTTPFailed("health.http.headers_invalid", status=400)
288
+ return tuple(headers)
289
+
290
+ @staticmethod
291
+ def _empty_body(environ: Mapping[str, Any]) -> bytes:
292
+ if environ.get("HTTP_TRANSFER_ENCODING") not in {None, ""}:
293
+ raise HealthHTTPFailed("health.http.transfer_encoding", status=400)
294
+ if environ.get("CONTENT_LENGTH") not in {None, "", "0"}:
295
+ raise HealthHTTPFailed("health.http.body_not_allowed", status=400)
296
+ return b""
297
+
298
+ def _authenticate(self, headers: tuple[tuple[str, str], ...], body: bytes) -> None:
299
+ request = {
300
+ "schema": AUTH_REQUEST_SCHEMA,
301
+ "method": "GET",
302
+ "path": HEALTH_PATH,
303
+ "headers": [list(item) for item in headers],
304
+ "body_sha256": hashlib.sha256(body).hexdigest(),
305
+ }
306
+ try:
307
+ _principal(self.authenticator(request))
308
+ except HealthHTTPFailed:
309
+ raise
310
+ except Exception:
311
+ raise HealthHTTPFailed(
312
+ "health.http.authentication_unavailable",
313
+ status=503,
314
+ retryable=True,
315
+ ) from None
316
+
317
+ @staticmethod
318
+ def _send(start_response, status: int, payload: Mapping[str, Any]):
319
+ body = _canonical_json(dict(payload))
320
+ phrases = {
321
+ 200: "OK", 400: "Bad Request", 401: "Unauthorized",
322
+ 403: "Forbidden", 404: "Not Found", 503: "Service Unavailable",
323
+ }
324
+ start_response(f"{status} {phrases[status]}", [
325
+ ("Content-Type", "application/json; charset=utf-8"),
326
+ ("Content-Length", str(len(body))),
327
+ ("Cache-Control", "no-store"),
328
+ ("X-Content-Type-Options", "nosniff"),
329
+ ("Referrer-Policy", "no-referrer"),
330
+ ])
331
+ return [body]
332
+
333
+ def __call__(self, environ: Mapping[str, Any], start_response: Callable[..., Any]):
334
+ try:
335
+ if not isinstance(environ, Mapping):
336
+ raise HealthHTTPFailed("health.http.environment_invalid", status=400)
337
+ if environ.get("wsgi.url_scheme") != "https":
338
+ raise HealthHTTPFailed("health.http.https_required", status=400)
339
+ if environ.get("QUERY_STRING") not in {None, ""}:
340
+ raise HealthHTTPFailed("health.http.query_invalid", status=400)
341
+ if environ.get("REQUEST_METHOD") != "GET" or environ.get("PATH_INFO") != HEALTH_PATH:
342
+ raise HealthHTTPFailed("health.http.route_not_found", status=404)
343
+ body = self._empty_body(environ)
344
+ self._authenticate(self._headers(environ), body)
345
+ try:
346
+ now = _timestamp(self.clock())
347
+ report = _report_payload(
348
+ self.health_provider(now=now), expected_checked_at=now,
349
+ )
350
+ except HealthHTTPFailed:
351
+ raise
352
+ except Exception:
353
+ raise HealthHTTPFailed(
354
+ "health.http.monitor_unavailable", status=503, retryable=True,
355
+ ) from None
356
+ status = 503 if report["status"] == "blocked" else 200
357
+ return self._send(start_response, status, {
358
+ "schema": RESPONSE_SCHEMA,
359
+ "report": report,
360
+ })
361
+ except HealthHTTPFailed as error:
362
+ return self._send(start_response, error.status, {
363
+ "schema": ERROR_SCHEMA,
364
+ "error_code": error.code,
365
+ "retryable": error.retryable,
366
+ })
367
+ except Exception:
368
+ return self._send(start_response, 503, {
369
+ "schema": ERROR_SCHEMA,
370
+ "error_code": "health.http.internal",
371
+ "retryable": True,
372
+ })
@@ -0,0 +1,297 @@
1
+ #!/usr/bin/env python3
2
+ """Provider-neutral, request-bound HTTP adapter for localization LLM calls."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import json
7
+ import re
8
+ import socket
9
+ import urllib.error
10
+ import urllib.parse
11
+ import urllib.request
12
+ from dataclasses import dataclass
13
+ from hashlib import sha256
14
+ from typing import Any, Callable, Mapping, Protocol
15
+
16
+
17
+ REQUEST_SCHEMA = "blun.localization-provider-request.v1"
18
+ RESPONSE_SCHEMA = "blun.localization-provider-response.v1"
19
+ MAX_BODY_BYTES = 4_000_000
20
+ MAX_ENDPOINT_LENGTH = 2048
21
+ MAX_HEADER_VALUE_LENGTH = 4096
22
+ HEADER_NAME = re.compile(r"^[!#$%&'*+.^_`|~0-9A-Za-z-]{1,128}$")
23
+ ERROR_CODE = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
24
+ REQUEST_ID = re.compile(r"^blun-l10n-call-[a-f0-9]{64}$")
25
+ WORKER_REQUEST_SCHEMA = "blun.website-localization-worker.v4"
26
+ WORKER_REQUEST_FIELDS = {
27
+ "schema", "request_id", "phase", "provider_id", "model_id",
28
+ "model_version", "system_instruction", "input",
29
+ }
30
+ WORKER_PHASES = {"transcreation", "target_native", "source_fidelity"}
31
+ RESERVED_HEADERS = {
32
+ "accept", "connection", "content-length", "content-type", "host",
33
+ "idempotency-key", "transfer-encoding", "x-localization-request-id",
34
+ "x-localization-request-sha256",
35
+ }
36
+
37
+
38
+ class HTTPProviderFailed(RuntimeError):
39
+ """Content-free failure consumed by the generic localization worker."""
40
+
41
+ localization_provider_failure = True
42
+
43
+ def __init__(self, code: str, *, retryable: bool):
44
+ if not isinstance(code, str) or ERROR_CODE.fullmatch(code) is None:
45
+ raise ValueError("provider error code is invalid")
46
+ if not isinstance(retryable, bool):
47
+ raise ValueError("provider retryability must be boolean")
48
+ super().__init__(code)
49
+ self.code = code
50
+ self.retryable = retryable
51
+
52
+
53
+ @dataclass(frozen=True)
54
+ class HTTPResult:
55
+ status: int
56
+ headers: tuple[tuple[str, str], ...]
57
+ body: bytes
58
+
59
+
60
+ class HTTPTransport(Protocol):
61
+ def post(self, url: str, headers: Mapping[str, str], body: bytes, *, timeout: float) -> HTTPResult: ...
62
+
63
+
64
+ class _NoRedirect(urllib.request.HTTPRedirectHandler):
65
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
66
+ return None
67
+
68
+
69
+ class URLTransport:
70
+ """One-attempt stdlib HTTPS transport with redirects disabled."""
71
+
72
+ def __init__(self):
73
+ self._opener = urllib.request.build_opener(_NoRedirect)
74
+
75
+ def post(self, url: str, headers: Mapping[str, str], body: bytes, *, timeout: float) -> HTTPResult:
76
+ request = urllib.request.Request(url, data=body, headers=dict(headers), method="POST")
77
+ try:
78
+ response = self._opener.open(request, timeout=timeout)
79
+ except urllib.error.HTTPError as error:
80
+ headers = tuple(error.headers.items()) if error.headers is not None else ()
81
+ return HTTPResult(int(error.code), headers, b"")
82
+ except (urllib.error.URLError, TimeoutError, socket.timeout, OSError):
83
+ raise HTTPProviderFailed("network", retryable=True) from None
84
+ try:
85
+ raw = response.read(MAX_BODY_BYTES + 1)
86
+ return HTTPResult(int(response.status), tuple(response.headers.items()), raw)
87
+ except (TimeoutError, socket.timeout, OSError):
88
+ raise HTTPProviderFailed("network", retryable=True) from None
89
+ finally:
90
+ response.close()
91
+
92
+
93
+ def _canonical_json(value: Any) -> bytes:
94
+ try:
95
+ text = json.dumps(value, ensure_ascii=False, allow_nan=False, sort_keys=True, separators=(",", ":"))
96
+ except (TypeError, ValueError):
97
+ raise HTTPProviderFailed("request_invalid", retryable=False) from None
98
+ raw = text.encode("utf-8")
99
+ if not raw or len(raw) > MAX_BODY_BYTES:
100
+ raise HTTPProviderFailed("request_too_large", retryable=False)
101
+ return raw
102
+
103
+
104
+ def _pairs(items):
105
+ result = {}
106
+ for key, value in items:
107
+ if key in result:
108
+ raise ValueError("duplicate key")
109
+ result[key] = value
110
+ return result
111
+
112
+
113
+ def _constant(value):
114
+ raise ValueError("nonfinite number")
115
+
116
+
117
+ def _endpoint(value: Any, allow_loopback_http: bool) -> str:
118
+ if (
119
+ not isinstance(value, str) or value != value.strip() or len(value) > MAX_ENDPOINT_LENGTH
120
+ or any(ord(char) <= 32 or ord(char) == 127 for char in value)
121
+ ):
122
+ raise ValueError("endpoint is invalid")
123
+ try:
124
+ parsed = urllib.parse.urlsplit(value)
125
+ hostname = parsed.hostname
126
+ port = parsed.port
127
+ except ValueError:
128
+ raise ValueError("endpoint is invalid") from None
129
+ if parsed.username is not None or parsed.password is not None or parsed.query or parsed.fragment:
130
+ raise ValueError("endpoint is invalid")
131
+ if not hostname or not parsed.path.startswith("/") or parsed.path.startswith("//"):
132
+ raise ValueError("endpoint is invalid")
133
+ if parsed.scheme == "https":
134
+ pass
135
+ elif parsed.scheme == "http" and allow_loopback_http and hostname.lower() in {"localhost", "127.0.0.1", "::1"}:
136
+ pass
137
+ else:
138
+ raise ValueError("endpoint must use HTTPS")
139
+ if port is not None and not 1 <= port <= 65535:
140
+ raise ValueError("endpoint is invalid")
141
+ return value
142
+
143
+
144
+ def _auth_headers(provider: Callable[[], Mapping[str, str]]) -> dict[str, str]:
145
+ try:
146
+ supplied = provider()
147
+ except Exception:
148
+ raise HTTPProviderFailed("authentication", retryable=False) from None
149
+ if not isinstance(supplied, Mapping):
150
+ raise HTTPProviderFailed("authentication", retryable=False)
151
+ result = {}
152
+ normalized_names = set()
153
+ for name, value in supplied.items():
154
+ normalized = name.lower() if isinstance(name, str) else ""
155
+ if (
156
+ not isinstance(name, str) or HEADER_NAME.fullmatch(name) is None
157
+ or normalized in RESERVED_HEADERS or normalized in normalized_names
158
+ ):
159
+ raise HTTPProviderFailed("authentication", retryable=False)
160
+ if (
161
+ not isinstance(value, str) or not value or len(value) > MAX_HEADER_VALUE_LENGTH
162
+ or "\r" in value or "\n" in value or any(ord(char) < 32 for char in value)
163
+ or any(ord(char) == 127 for char in value)
164
+ ):
165
+ raise HTTPProviderFailed("authentication", retryable=False)
166
+ normalized_names.add(normalized)
167
+ result[name] = value
168
+ if not result:
169
+ raise HTTPProviderFailed("authentication", retryable=False)
170
+ return result
171
+
172
+
173
+ def _headers(value: Any) -> dict[str, str]:
174
+ if not isinstance(value, tuple):
175
+ raise HTTPProviderFailed("transport_invalid", retryable=True)
176
+ result = {}
177
+ for item in value:
178
+ if not isinstance(item, tuple) or len(item) != 2 or not all(isinstance(part, str) for part in item):
179
+ raise HTTPProviderFailed("transport_invalid", retryable=True)
180
+ name, content = item[0].lower(), item[1].strip()
181
+ if name in result:
182
+ raise HTTPProviderFailed("response_headers", retryable=True)
183
+ result[name] = content
184
+ return result
185
+
186
+
187
+ class HTTPProviderAdapter:
188
+ """One HTTP attempt for one deterministic worker phase."""
189
+
190
+ def __init__(
191
+ self,
192
+ endpoint: str,
193
+ authentication_headers: Callable[[], Mapping[str, str]],
194
+ *,
195
+ transport: HTTPTransport | None = None,
196
+ timeout: float = 60.0,
197
+ allow_loopback_http: bool = False,
198
+ ):
199
+ if not isinstance(allow_loopback_http, bool):
200
+ raise TypeError("allow_loopback_http must be boolean")
201
+ self.endpoint = _endpoint(endpoint, allow_loopback_http)
202
+ if not callable(authentication_headers):
203
+ raise TypeError("authentication_headers must be callable")
204
+ if isinstance(timeout, bool) or not isinstance(timeout, (int, float)) or not 0 < timeout <= 300:
205
+ raise ValueError("timeout is outside the supported range")
206
+ self.authentication_headers = authentication_headers
207
+ self.transport = URLTransport() if transport is None else transport
208
+ if not callable(getattr(self.transport, "post", None)):
209
+ raise TypeError("transport must provide post")
210
+ self.timeout = float(timeout)
211
+
212
+ def invoke(self, request: Any) -> Mapping[str, Any]:
213
+ try:
214
+ payload_method = getattr(request, "as_payload", None)
215
+ request_id = getattr(request, "request_id", None)
216
+ except Exception:
217
+ raise HTTPProviderFailed("request_invalid", retryable=False) from None
218
+ if not callable(payload_method) or not isinstance(request_id, str) or not request_id:
219
+ raise HTTPProviderFailed("request_invalid", retryable=False)
220
+ try:
221
+ payload = payload_method()
222
+ except Exception:
223
+ raise HTTPProviderFailed("request_invalid", retryable=False) from None
224
+ if (
225
+ REQUEST_ID.fullmatch(request_id) is None
226
+ or not isinstance(payload, dict)
227
+ or set(payload) != WORKER_REQUEST_FIELDS
228
+ or payload.get("schema") != WORKER_REQUEST_SCHEMA
229
+ or payload.get("request_id") != request_id
230
+ or payload.get("phase") not in WORKER_PHASES
231
+ or not isinstance(payload.get("input"), dict)
232
+ or any(not isinstance(payload.get(field), str) or not payload[field] for field in (
233
+ "provider_id", "model_id", "model_version", "system_instruction",
234
+ ))
235
+ ):
236
+ raise HTTPProviderFailed("request_invalid", retryable=False)
237
+ request_bytes = _canonical_json(payload)
238
+ request_hash = sha256(request_bytes).hexdigest()
239
+ envelope = {
240
+ "schema": REQUEST_SCHEMA,
241
+ "request_id": request_id,
242
+ "request_sha256": request_hash,
243
+ "request": payload,
244
+ }
245
+ body = _canonical_json(envelope)
246
+ headers = _auth_headers(self.authentication_headers)
247
+ headers.update({
248
+ "Accept": "application/json",
249
+ "Content-Type": "application/json; charset=utf-8",
250
+ "Idempotency-Key": request_id,
251
+ "X-Localization-Request-Id": request_id,
252
+ "X-Localization-Request-Sha256": request_hash,
253
+ })
254
+ try:
255
+ result = self.transport.post(self.endpoint, headers, body, timeout=self.timeout)
256
+ except HTTPProviderFailed:
257
+ raise
258
+ except Exception:
259
+ raise HTTPProviderFailed("network", retryable=True) from None
260
+ if (
261
+ not isinstance(result, HTTPResult) or isinstance(result.status, bool)
262
+ or not isinstance(result.status, int) or not 100 <= result.status <= 599
263
+ ):
264
+ raise HTTPProviderFailed("transport_invalid", retryable=True)
265
+ if result.status != 200:
266
+ if 300 <= result.status <= 399:
267
+ raise HTTPProviderFailed("redirect", retryable=False)
268
+ retryable = result.status in {408, 425, 429} or 500 <= result.status <= 599
269
+ raise HTTPProviderFailed("http_status", retryable=retryable)
270
+ response_headers = _headers(result.headers)
271
+ content_type = response_headers.get("content-type", "").lower().replace(" ", "")
272
+ if content_type not in {"application/json", "application/json;charset=utf-8"}:
273
+ raise HTTPProviderFailed("response_content_type", retryable=True)
274
+ if not isinstance(result.body, bytes) or not result.body or len(result.body) > MAX_BODY_BYTES:
275
+ raise HTTPProviderFailed("response_size", retryable=True)
276
+ declared = response_headers.get("content-length")
277
+ if declared is not None and (not declared.isascii() or not declared.isdecimal() or int(declared) != len(result.body)):
278
+ raise HTTPProviderFailed("response_size", retryable=True)
279
+ try:
280
+ text = result.body.decode("utf-8")
281
+ if text.startswith("\ufeff"):
282
+ raise ValueError("BOM rejected")
283
+ envelope = json.loads(text, object_pairs_hook=_pairs, parse_constant=_constant)
284
+ except (UnicodeDecodeError, json.JSONDecodeError, ValueError, RecursionError):
285
+ raise HTTPProviderFailed("response_json", retryable=True) from None
286
+ if not isinstance(envelope, dict) or set(envelope) != {
287
+ "schema", "request_id", "request_sha256", "response",
288
+ }:
289
+ raise HTTPProviderFailed("response_binding", retryable=False)
290
+ if (
291
+ envelope["schema"] != RESPONSE_SCHEMA
292
+ or envelope["request_id"] != request_id
293
+ or envelope["request_sha256"] != request_hash
294
+ or not isinstance(envelope["response"], dict)
295
+ ):
296
+ raise HTTPProviderFailed("response_binding", retryable=False)
297
+ return envelope["response"]