create-windy 0.8.2 → 0.9.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 (574) hide show
  1. package/dist/cli.js +855 -560
  2. package/package.json +1 -1
  3. package/template/.windy-template.json +2 -2
  4. package/template/apps/agent-server/Dockerfile +92 -22
  5. package/template/apps/agent-server/README.md +47 -85
  6. package/template/apps/agent-server/documents/office.py +216 -0
  7. package/template/apps/agent-server/documents/query_report.py +136 -0
  8. package/template/apps/agent-server/documents/smoke.py +177 -0
  9. package/template/apps/agent-server/documents/test_boundaries.py +185 -0
  10. package/template/apps/agent-server/host-contracts.ts +56 -0
  11. package/template/apps/agent-server/install-native.ts +167 -0
  12. package/template/apps/agent-server/main.ts +179 -0
  13. package/template/apps/agent-server/native/EXTENSIONS.md +46 -0
  14. package/template/apps/agent-server/native/admission.ts +73 -0
  15. package/template/apps/agent-server/native/authorization.test.ts +176 -0
  16. package/template/apps/agent-server/native/authorization.ts +118 -0
  17. package/template/apps/agent-server/native/boundary-io.ts +93 -0
  18. package/template/apps/agent-server/native/boundary-product.ts +107 -0
  19. package/template/apps/agent-server/native/boundary-project.test.ts +247 -0
  20. package/template/apps/agent-server/native/boundary-project.ts +188 -0
  21. package/template/apps/agent-server/native/boundary.ts +188 -0
  22. package/template/apps/agent-server/native/compaction-policy.test.ts +175 -0
  23. package/template/apps/agent-server/native/config.ts +95 -0
  24. package/template/apps/agent-server/native/conversation-instructions.ts +9 -0
  25. package/template/apps/agent-server/native/extensions.test.ts +190 -0
  26. package/template/apps/agent-server/native/extensions.ts +31 -0
  27. package/template/apps/agent-server/native/host-profile.test.ts +91 -0
  28. package/template/apps/agent-server/native/host-profile.ts +33 -0
  29. package/template/apps/agent-server/native/host-test-fixture.ts +13 -0
  30. package/template/apps/agent-server/native/http.ts +129 -0
  31. package/template/apps/agent-server/native/lifecycle.test.ts +285 -0
  32. package/template/apps/agent-server/native/lifecycle.ts +136 -0
  33. package/template/apps/agent-server/native/manager.ts +292 -0
  34. package/template/apps/agent-server/native/native.test.ts +207 -0
  35. package/template/apps/agent-server/native/office-preview.test.ts +50 -0
  36. package/template/apps/agent-server/native/office-preview.ts +25 -0
  37. package/template/apps/agent-server/native/parallel-harness.ts +242 -0
  38. package/template/apps/agent-server/native/parallel-mcp-fixture.ts +97 -0
  39. package/template/apps/agent-server/native/parallel.test.ts +256 -0
  40. package/template/apps/agent-server/native/profile-composition.test.ts +147 -0
  41. package/template/apps/agent-server/native/profile.ts +307 -0
  42. package/template/apps/agent-server/native/request.ts +61 -0
  43. package/template/apps/agent-server/native/session-conflict.test.ts +235 -0
  44. package/template/apps/agent-server/native/session-conflict.ts +21 -0
  45. package/template/apps/agent-server/native/shared-skills.test.ts +128 -0
  46. package/template/apps/agent-server/native/shared-skills.ts +240 -0
  47. package/template/apps/agent-server/native/socket-lifecycle.test.ts +48 -0
  48. package/template/apps/agent-server/native/socket.ts +130 -0
  49. package/template/apps/agent-server/native/storage-lifecycle.test.ts +217 -0
  50. package/template/apps/agent-server/native/storage.ts +188 -0
  51. package/template/apps/agent-server/native/stream-authorization.test.ts +89 -0
  52. package/template/apps/agent-server/native/worker.ts +77 -0
  53. package/template/apps/agent-server/native-download.test.ts +119 -0
  54. package/template/apps/agent-server/native-download.ts +145 -0
  55. package/template/apps/agent-server/package.json +63 -0
  56. package/template/apps/agent-server/plugins/access.mjs +126 -0
  57. package/template/apps/agent-server/plugins/branding/README.md +9 -0
  58. package/template/apps/agent-server/plugins/branding/brand.css +85 -0
  59. package/template/apps/agent-server/plugins/branding/client.js +338 -0
  60. package/template/apps/agent-server/plugins/branding/index.mjs +35 -0
  61. package/template/apps/agent-server/plugins/branding/loading.d.mts +2 -0
  62. package/template/apps/agent-server/plugins/branding/loading.mjs +66 -0
  63. package/template/apps/agent-server/plugins/branding/loading.test.ts +89 -0
  64. package/template/apps/agent-server/plugins/branding/package.json +21 -0
  65. package/template/apps/agent-server/plugins/branding.test.ts +294 -0
  66. package/template/apps/agent-server/plugins/compaction.mjs +83 -0
  67. package/template/apps/agent-server/plugins/compaction.test.ts +91 -0
  68. package/template/apps/agent-server/plugins/confine-network.py +57 -0
  69. package/template/apps/agent-server/plugins/default-skills.test.ts +62 -0
  70. package/template/apps/agent-server/plugins/downloads/README.md +28 -0
  71. package/template/apps/agent-server/plugins/downloads/client.js +126 -0
  72. package/template/apps/agent-server/plugins/downloads/downloads.test.ts +222 -0
  73. package/template/apps/agent-server/plugins/downloads/index.d.mts +19 -0
  74. package/template/apps/agent-server/plugins/downloads/index.mjs +180 -0
  75. package/template/apps/agent-server/plugins/downloads/package.json +20 -0
  76. package/template/apps/agent-server/plugins/drop-overlay/README.md +24 -0
  77. package/template/apps/agent-server/plugins/drop-overlay/drop-overlay.test.ts +199 -0
  78. package/template/apps/agent-server/plugins/drop-overlay/index.d.mts +8 -0
  79. package/template/apps/agent-server/plugins/drop-overlay/index.mjs +12 -0
  80. package/template/apps/agent-server/plugins/drop-overlay/style.css +102 -0
  81. package/template/apps/agent-server/plugins/locale/client.js +61 -0
  82. package/template/apps/agent-server/plugins/locale/index.d.mts +9 -0
  83. package/template/apps/agent-server/plugins/locale/index.mjs +16 -0
  84. package/template/apps/agent-server/plugins/locale/locale.test.ts +217 -0
  85. package/template/apps/agent-server/plugins/locale/package.json +19 -0
  86. package/template/apps/agent-server/plugins/parallel.mjs +146 -0
  87. package/template/apps/agent-server/plugins/preset-registry.d.mts +2 -0
  88. package/template/apps/agent-server/plugins/preset-registry.mjs +41 -0
  89. package/template/apps/agent-server/plugins/preset-registry.test.ts +46 -0
  90. package/template/apps/agent-server/plugins/questions.d.mts +25 -0
  91. package/template/apps/agent-server/plugins/questions.mjs +142 -0
  92. package/template/apps/agent-server/plugins/questions.test.ts +105 -0
  93. package/template/apps/agent-server/plugins/settings/README.md +17 -0
  94. package/template/apps/agent-server/plugins/settings/client.js +102 -0
  95. package/template/apps/agent-server/plugins/settings/index.mjs +17 -0
  96. package/template/apps/agent-server/plugins/settings/package.json +19 -0
  97. package/template/apps/agent-server/plugins/settings/settings.test.ts +129 -0
  98. package/template/apps/agent-server/plugins/settings-controller.d.mts +4 -0
  99. package/template/apps/agent-server/plugins/settings-controller.mjs +31 -0
  100. package/template/apps/agent-server/plugins/settings-controller.test.ts +17 -0
  101. package/template/apps/agent-server/plugins/settings-dispatch.test.ts +34 -0
  102. package/template/apps/agent-server/plugins/shared-skills.d.mts +15 -0
  103. package/template/apps/agent-server/plugins/shared-skills.mjs +82 -0
  104. package/template/apps/agent-server/plugins/shared-skills.test.ts +51 -0
  105. package/template/apps/agent-server/plugins/skill-library/README.md +11 -0
  106. package/template/apps/agent-server/plugins/skill-library/archive.test.ts +43 -0
  107. package/template/apps/agent-server/plugins/skill-library/bundle.mjs +234 -0
  108. package/template/apps/agent-server/plugins/skill-library/client-chunks.test.ts +107 -0
  109. package/template/apps/agent-server/plugins/skill-library/client-form-mount.test.ts +139 -0
  110. package/template/apps/agent-server/plugins/skill-library/client-form.test.ts +261 -0
  111. package/template/apps/agent-server/plugins/skill-library/client-ui.test.ts +268 -0
  112. package/template/apps/agent-server/plugins/skill-library/client-use.test.ts +158 -0
  113. package/template/apps/agent-server/plugins/skill-library/client.editor.js +93 -0
  114. package/template/apps/agent-server/plugins/skill-library/client.form.js +316 -0
  115. package/template/apps/agent-server/plugins/skill-library/client.js +348 -0
  116. package/template/apps/agent-server/plugins/skill-library/client.request.js +52 -0
  117. package/template/apps/agent-server/plugins/skill-library/client.transfer.js +48 -0
  118. package/template/apps/agent-server/plugins/skill-library/client.use.js +46 -0
  119. package/template/apps/agent-server/plugins/skill-library/default-roots.test.ts +84 -0
  120. package/template/apps/agent-server/plugins/skill-library/draft.d.mts +17 -0
  121. package/template/apps/agent-server/plugins/skill-library/draft.mjs +152 -0
  122. package/template/apps/agent-server/plugins/skill-library/draft.test.ts +287 -0
  123. package/template/apps/agent-server/plugins/skill-library/index.d.mts +49 -0
  124. package/template/apps/agent-server/plugins/skill-library/index.mjs +226 -0
  125. package/template/apps/agent-server/plugins/skill-library/package.json +24 -0
  126. package/template/apps/agent-server/plugins/skill-library/presentation/README.md +27 -0
  127. package/template/apps/agent-server/plugins/skill-library/presentation/UPSTREAM.md +54 -0
  128. package/template/apps/agent-server/plugins/skill-library/presentation/boot.test.ts +150 -0
  129. package/template/apps/agent-server/plugins/skill-library/presentation/client.js +146 -0
  130. package/template/apps/agent-server/plugins/skill-library/presentation/client.test.ts +195 -0
  131. package/template/apps/agent-server/plugins/skill-library/presentation/index.d.mts +9 -0
  132. package/template/apps/agent-server/plugins/skill-library/presentation/index.mjs +30 -0
  133. package/template/apps/agent-server/plugins/skill-library/presentation/metadata.test.ts +82 -0
  134. package/template/apps/agent-server/plugins/skill-library/presentation/package.json +21 -0
  135. package/template/apps/agent-server/plugins/skill-library/presentation/react-boot.test.ts +162 -0
  136. package/template/apps/agent-server/plugins/skill-library/skills.test.ts +342 -0
  137. package/template/apps/agent-server/plugins/skill-library/storage.mjs +293 -0
  138. package/template/apps/agent-server/plugins/skill-library/style.css +229 -0
  139. package/template/apps/agent-server/plugins/skill-library/test-fixture.ts +77 -0
  140. package/template/apps/agent-server/plugins/skill-library/workflow.d.mts +18 -0
  141. package/template/apps/agent-server/plugins/skill-library/workflow.mjs +189 -0
  142. package/template/apps/agent-server/plugins/skill-library/workflow.test.ts +164 -0
  143. package/template/apps/agent-server/plugins/skills/README.md +5 -0
  144. package/template/apps/agent-server/plugins/skills/windy-data-summary/SKILL.md +14 -0
  145. package/template/apps/agent-server/plugins/skills/windy-extension-guide/SKILL.md +14 -0
  146. package/template/apps/agent-server/plugins/skills/windy-office/SKILL.md +14 -0
  147. package/template/apps/agent-server/plugins/skills/windy-skill-capture/SKILL.md +14 -0
  148. package/template/apps/agent-server/plugins/skills/windy-source-compare/SKILL.md +14 -0
  149. package/template/apps/agent-server/plugins/subprocess.mjs +40 -0
  150. package/template/apps/agent-server/plugins/theme/README.md +18 -0
  151. package/template/apps/agent-server/plugins/theme/client.js +18 -0
  152. package/template/apps/agent-server/plugins/theme/index.d.mts +9 -0
  153. package/template/apps/agent-server/plugins/theme/index.mjs +18 -0
  154. package/template/apps/agent-server/plugins/theme/package.json +19 -0
  155. package/template/apps/agent-server/plugins/theme/source-tokens.ts +82 -0
  156. package/template/apps/agent-server/plugins/theme/sync-tokens.ts +12 -0
  157. package/template/apps/agent-server/plugins/theme/theme.test.ts +193 -0
  158. package/template/apps/agent-server/plugins/theme/tokens.json +166 -0
  159. package/template/apps/agent-server/plugins/tool-catalog/README.md +79 -0
  160. package/template/apps/agent-server/plugins/tool-catalog/categories.mjs +111 -0
  161. package/template/apps/agent-server/plugins/tool-catalog/categories.test.ts +118 -0
  162. package/template/apps/agent-server/plugins/tool-catalog/client-cache.test.ts +264 -0
  163. package/template/apps/agent-server/plugins/tool-catalog/client.js +333 -0
  164. package/template/apps/agent-server/plugins/tool-catalog/client.test.ts +136 -0
  165. package/template/apps/agent-server/plugins/tool-catalog/discovery.d.mts +42 -0
  166. package/template/apps/agent-server/plugins/tool-catalog/discovery.mjs +242 -0
  167. package/template/apps/agent-server/plugins/tool-catalog/discovery.test.ts +229 -0
  168. package/template/apps/agent-server/plugins/tool-catalog/index.d.mts +5 -0
  169. package/template/apps/agent-server/plugins/tool-catalog/index.mjs +91 -0
  170. package/template/apps/agent-server/plugins/tool-catalog/package.json +23 -0
  171. package/template/apps/agent-server/plugins/tool-catalog/presentation.d.mts +21 -0
  172. package/template/apps/agent-server/plugins/tool-catalog/presentation.mjs +153 -0
  173. package/template/apps/agent-server/plugins/tool-catalog/presentation.test.ts +166 -0
  174. package/template/apps/agent-server/plugins/tool-catalog/routes.test.ts +209 -0
  175. package/template/apps/agent-server/plugins/tool-catalog/style.css +155 -0
  176. package/template/apps/agent-server/plugins/tool-catalog/use-tool.test.ts +160 -0
  177. package/template/apps/agent-server/plugins/tool-presentation/README.md +7 -0
  178. package/template/apps/agent-server/plugins/tool-presentation/build-client.ts +29 -0
  179. package/template/apps/agent-server/plugins/tool-presentation/client.js +312 -0
  180. package/template/apps/agent-server/plugins/tool-presentation/client.results.js +9 -0
  181. package/template/apps/agent-server/plugins/tool-presentation/client.test.ts +178 -0
  182. package/template/apps/agent-server/plugins/tool-presentation/index.mjs +10 -0
  183. package/template/apps/agent-server/plugins/tool-presentation/package.json +24 -0
  184. package/template/apps/agent-server/plugins/tool-presentation/result-discovery.mjs +43 -0
  185. package/template/apps/agent-server/plugins/tool-presentation/result-model.d.mts +51 -0
  186. package/template/apps/agent-server/plugins/tool-presentation/result-model.mjs +96 -0
  187. package/template/apps/agent-server/plugins/workspace/README.md +5 -0
  188. package/template/apps/agent-server/plugins/workspace/index.mjs +8 -0
  189. package/template/apps/agent-server/plugins/workspace/package.json +10 -0
  190. package/template/apps/agent-server/plugins/workspace/style.css +124 -0
  191. package/template/apps/agent-server/project/host.ts +13 -0
  192. package/template/apps/agent-server/runtime/artifacts.ts +115 -0
  193. package/template/apps/agent-server/runtime/audit.nodecheck.ts +60 -0
  194. package/template/apps/agent-server/runtime/capacity.ts +61 -0
  195. package/template/apps/agent-server/runtime/client-completion-budget.nodecheck.ts +92 -0
  196. package/template/apps/agent-server/runtime/compatibility.ts +33 -0
  197. package/template/apps/agent-server/runtime/completions.ts +320 -0
  198. package/template/apps/agent-server/runtime/config.ts +246 -0
  199. package/template/apps/agent-server/runtime/context-budget.ts +70 -0
  200. package/template/apps/agent-server/runtime/context-plugin.ts +306 -0
  201. package/template/apps/agent-server/runtime/context.nodecheck.ts +241 -0
  202. package/template/apps/agent-server/runtime/contracts.ts +201 -0
  203. package/template/apps/agent-server/runtime/dsh-engine.ts +196 -0
  204. package/template/apps/agent-server/runtime/evaluation-plugin.ts +115 -0
  205. package/template/apps/agent-server/runtime/evaluation.nodecheck.ts +194 -0
  206. package/template/apps/agent-server/runtime/events.ts +71 -0
  207. package/template/apps/agent-server/runtime/governance.ts +194 -0
  208. package/template/apps/agent-server/runtime/index.ts +339 -0
  209. package/template/apps/agent-server/runtime/internal-output.ts +37 -0
  210. package/template/apps/agent-server/runtime/isolation.nodecheck.ts +287 -0
  211. package/template/apps/agent-server/runtime/model-payload.ts +97 -0
  212. package/template/apps/agent-server/runtime/model-plugin.ts +308 -0
  213. package/template/apps/agent-server/runtime/model-route.ts +34 -0
  214. package/template/apps/agent-server/runtime/model-usage.ts +51 -0
  215. package/template/apps/agent-server/runtime/model-wire.ts +45 -0
  216. package/template/apps/agent-server/runtime/native-authorization.nodecheck.ts +126 -0
  217. package/template/apps/agent-server/runtime/native-completion.nodecheck.ts +81 -0
  218. package/template/apps/agent-server/runtime/output-validation.ts +66 -0
  219. package/template/apps/agent-server/runtime/production-capacity.nodecheck.ts +121 -0
  220. package/template/apps/agent-server/runtime/questions-workflow.nodecheck.ts +249 -0
  221. package/template/apps/agent-server/runtime/report-breakdown.ts +79 -0
  222. package/template/apps/agent-server/runtime/reporting.ts +219 -0
  223. package/template/apps/agent-server/runtime/run-completion.ts +39 -0
  224. package/template/apps/agent-server/runtime/run-request-digest.ts +18 -0
  225. package/template/apps/agent-server/runtime/runtime-test-fixtures.ts +264 -0
  226. package/template/apps/agent-server/runtime/runtime.nodecheck.ts +150 -0
  227. package/template/apps/agent-server/runtime/store-idempotency.nodecheck.ts +74 -0
  228. package/template/apps/agent-server/runtime/store.ts +324 -0
  229. package/template/apps/agent-server/runtime/structured-output-mode.nodecheck.ts +51 -0
  230. package/template/apps/agent-server/runtime/tool-name.ts +6 -0
  231. package/template/apps/agent-server/runtime/tool-plugin.ts +201 -0
  232. package/template/apps/agent-server/runtime/vision-readiness.ts +200 -0
  233. package/template/apps/agent-server/scripts/confinement-check.mjs +103 -0
  234. package/template/apps/agent-server/scripts/coordinator-check.mjs +344 -0
  235. package/template/apps/agent-server/scripts/documents-delivery-check.mjs +309 -0
  236. package/template/apps/agent-server/scripts/office-preview-check.mjs +92 -0
  237. package/template/apps/agent-server/scripts/test-confinement.ts +58 -0
  238. package/template/apps/agent-server/scripts/test-coordinator.ts +36 -0
  239. package/template/apps/agent-server/scripts/test-runtime.ts +46 -0
  240. package/template/apps/agent-server/tsconfig.json +21 -0
  241. package/template/apps/server/Dockerfile +3 -0
  242. package/template/apps/server/package.json +5 -1
  243. package/template/apps/server/scripts/check-dsh-platform-example.ts +251 -0
  244. package/template/apps/server/src/agent/admin-catalog-bootstrap.ts +25 -0
  245. package/template/apps/server/src/agent/agent-session-bootstrap.ts +7 -8
  246. package/template/apps/server/src/agent/agent-session-facade.ts +12 -0
  247. package/template/apps/server/src/agent/agent-session-validation.ts +43 -0
  248. package/template/apps/server/src/agent/dsh-runtime-wire.test.ts +33 -0
  249. package/template/apps/server/src/agent/governance-runtime.ts +41 -0
  250. package/template/apps/server/src/agent/operation-catalog.test.ts +202 -0
  251. package/template/apps/server/src/agent/operation-catalog.ts +135 -0
  252. package/template/apps/server/src/agent/remote-runtime-response.ts +1 -1
  253. package/template/apps/server/src/agent/run-browser-visibility.test.ts +59 -0
  254. package/template/apps/server/src/agent/run-browser-visibility.ts +11 -0
  255. package/template/apps/server/src/agent/run-contracts.ts +1 -0
  256. package/template/apps/server/src/agent/run-definition-support.ts +9 -0
  257. package/template/apps/server/src/agent/run-operation-policy.ts +1 -0
  258. package/template/apps/server/src/agent/run-route-response.ts +35 -0
  259. package/template/apps/server/src/agent/run-routes.ts +46 -43
  260. package/template/apps/server/src/agent/runtime-bootstrap.ts +21 -20
  261. package/template/apps/server/src/agent/runtime-disabled-composition.ts +28 -0
  262. package/template/apps/server/src/agent/runtime-tool-composition.ts +2 -0
  263. package/template/apps/server/src/agent/session-projection-facade.ts +8 -9
  264. package/template/apps/server/src/agent/session-projection-governance.ts +10 -0
  265. package/template/apps/server/src/agent/session-projection-view.ts +19 -16
  266. package/template/apps/server/src/agent/session-recording-reader.contract.test.ts +131 -0
  267. package/template/apps/server/src/agent/session-recording-reader.ts +62 -0
  268. package/template/apps/server/src/agent/tool-catalog-audit.ts +22 -0
  269. package/template/apps/server/src/agent/tool-catalog-availability.ts +21 -0
  270. package/template/apps/server/src/agent/tool-catalog-routes.test.ts +103 -0
  271. package/template/apps/server/src/agent/tool-catalog-routes.ts +62 -0
  272. package/template/apps/server/src/agent/tool-catalog.test.ts +122 -0
  273. package/template/apps/server/src/agent/tool-catalog.ts +44 -0
  274. package/template/apps/server/src/agent/tool-registry.ts +45 -14
  275. package/template/apps/server/src/agent/workbench-bootstrap.ts +39 -0
  276. package/template/apps/server/src/agent/workbench-event-projection.ts +115 -0
  277. package/template/apps/server/src/agent/workbench-facade.contract.test.ts +189 -0
  278. package/template/apps/server/src/agent/workbench-facade.ts +339 -0
  279. package/template/apps/server/src/agent/workbench-recording.contract.test.ts +328 -0
  280. package/template/apps/server/src/agent/workbench-routes.ts +97 -0
  281. package/template/apps/server/src/agent/workbench-run-integration.test.ts +231 -0
  282. package/template/apps/server/src/agent/workbench-run-reader.ts +187 -0
  283. package/template/apps/server/src/agent/workbench-safe-result.ts +61 -0
  284. package/template/apps/server/src/agent/workbench-sse.ts +50 -0
  285. package/template/apps/server/src/agent/workflow-runtime-bootstrap.ts +9 -0
  286. package/template/apps/server/src/agent-skills/access.ts +88 -0
  287. package/template/apps/server/src/agent-skills/bootstrap.ts +49 -0
  288. package/template/apps/server/src/agent-skills/builtin-registration.ts +83 -0
  289. package/template/apps/server/src/agent-skills/builtins.ts +19 -0
  290. package/template/apps/server/src/agent-skills/bundle-zip.ts +163 -0
  291. package/template/apps/server/src/agent-skills/bundle.test.ts +79 -0
  292. package/template/apps/server/src/agent-skills/bundle.ts +133 -0
  293. package/template/apps/server/src/agent-skills/contracts.ts +46 -0
  294. package/template/apps/server/src/agent-skills/drizzle-repository.ts +125 -0
  295. package/template/apps/server/src/agent-skills/input.ts +29 -0
  296. package/template/apps/server/src/agent-skills/postgres.integration.test.ts +348 -0
  297. package/template/apps/server/src/agent-skills/read-routes.test.ts +116 -0
  298. package/template/apps/server/src/agent-skills/reader.ts +108 -0
  299. package/template/apps/server/src/agent-skills/repository.ts +105 -0
  300. package/template/apps/server/src/agent-skills/routes.ts +176 -0
  301. package/template/apps/server/src/agent-skills/service.test.ts +295 -0
  302. package/template/apps/server/src/agent-skills/service.ts +301 -0
  303. package/template/apps/server/src/agent-workflow/preset-registry.test.ts +137 -0
  304. package/template/apps/server/src/agent-workflow/preset-registry.ts +191 -0
  305. package/template/apps/server/src/agent-workflow/preset-routes.test.ts +94 -0
  306. package/template/apps/server/src/agent-workflow/preset-routes.ts +45 -0
  307. package/template/apps/server/src/agent-workflow/query-service.ts +36 -0
  308. package/template/apps/server/src/agent-workflow/recording-projection.contract.test.ts +196 -0
  309. package/template/apps/server/src/agent-workflow/recording-projection.ts +86 -0
  310. package/template/apps/server/src/ai-runtime-report/service.test.ts +10 -7
  311. package/template/apps/server/src/ai-runtime-report/service.ts +1 -1
  312. package/template/apps/server/src/app/agent-workflow-presets.ts +4 -0
  313. package/template/apps/server/src/app/dsh-skill-draft-audit.test.ts +195 -0
  314. package/template/apps/server/src/app/dsh-skill-draft-audit.ts +115 -0
  315. package/template/apps/server/src/app/dsh-workbench-audit.test.ts +71 -0
  316. package/template/apps/server/src/app/dsh-workbench-audit.ts +34 -0
  317. package/template/apps/server/src/app/dsh-workbench-handshake.test.ts +63 -0
  318. package/template/apps/server/src/app/dsh-workbench-handshake.ts +48 -0
  319. package/template/apps/server/src/app/dsh-workbench-http.test.ts +96 -0
  320. package/template/apps/server/src/app/dsh-workbench-lan-origin.test.ts +114 -0
  321. package/template/apps/server/src/app/dsh-workbench-launch.test.ts +70 -0
  322. package/template/apps/server/src/app/dsh-workbench-origin.test.ts +54 -0
  323. package/template/apps/server/src/app/dsh-workbench-proxy.ts +205 -0
  324. package/template/apps/server/src/app/dsh-workbench-session-conflict.test.ts +61 -0
  325. package/template/apps/server/src/app/dsh-workbench-session.ts +59 -0
  326. package/template/apps/server/src/app/dsh-workbench-socket-audit.test.ts +115 -0
  327. package/template/apps/server/src/app/dsh-workbench-socket.test.ts +246 -0
  328. package/template/apps/server/src/app/dsh-workbench-socket.ts +272 -0
  329. package/template/apps/server/src/app/dsh-workbench-test-support.ts +158 -0
  330. package/template/apps/server/src/app/dsh-workbench.test.ts +213 -0
  331. package/template/apps/server/src/app/dsh-workbench.ts +279 -0
  332. package/template/apps/server/src/app/workbench-public-origin.ts +16 -0
  333. package/template/apps/server/src/data-governance/user-plaintext-routes.test.ts +3 -0
  334. package/template/apps/server/src/http-app.ts +31 -0
  335. package/template/apps/server/src/mcp/adapter.ts +1 -0
  336. package/template/apps/server/src/module-composition.test.ts +23 -0
  337. package/template/apps/server/src/module-composition.ts +9 -2
  338. package/template/apps/server/src/observability/bootstrap.ts +12 -0
  339. package/template/apps/server/src/observability/diagnostic-failure-recorder.ts +94 -0
  340. package/template/apps/server/src/observability/diagnostic-http-contract.test.ts +42 -0
  341. package/template/apps/server/src/observability/diagnostic-index.test.ts +89 -0
  342. package/template/apps/server/src/observability/diagnostic-index.ts +88 -0
  343. package/template/apps/server/src/observability/diagnostic-repository.ts +67 -0
  344. package/template/apps/server/src/platform-app-bootstrap.ts +42 -0
  345. package/template/apps/server/src/platform-http-runtime.ts +6 -0
  346. package/template/apps/server/src/runtime-development.test.ts +25 -0
  347. package/template/apps/server/src/runtime-development.ts +6 -44
  348. package/template/apps/server/src/system/diagnostic-routes.test.ts +78 -0
  349. package/template/apps/server/src/system/diagnostic-routes.ts +66 -0
  350. package/template/apps/web/Dockerfile +9 -1
  351. package/template/apps/web/dev/start.ts +21 -10
  352. package/template/apps/web/dsh-workbench-location.ts +21 -0
  353. package/template/apps/web/dsh-workbench-proxy.test.ts +121 -0
  354. package/template/apps/web/dsh-workbench-proxy.ts +194 -0
  355. package/template/apps/web/package.json +3 -1
  356. package/template/apps/web/server.ts +27 -6
  357. package/template/apps/web/src/composables/useLoginFlow.ts +13 -1
  358. package/template/apps/web/src/pages/errors/PlatformErrorPage.vue +6 -0
  359. package/template/apps/web/src/pages/errors/PlatformErrorPage.webtest.ts +14 -1
  360. package/template/apps/web/src/pages/errors/error-page-extension.ts +1 -0
  361. package/template/apps/web/src/pages/system/AgentDebugPage.vue +14 -0
  362. package/template/apps/web/src/pages/system/AgentNativePage.vue +44 -0
  363. package/template/apps/web/src/pages/system/AgentSessionPage.vue +29 -8
  364. package/template/apps/web/src/pages/system/AgentToolsPage.vue +76 -0
  365. package/template/apps/web/src/pages/system/AgentWorkflowPage.vue +20 -7
  366. package/template/apps/web/src/pages/system/DiagnosticLookupPage.vue +56 -0
  367. package/template/apps/web/src/pages/system/DiagnosticLookupPage.webtest.ts +99 -0
  368. package/template/apps/web/src/pages/system/SystemAgentSkillsPage.vue +88 -0
  369. package/template/apps/web/src/pages/system/components/DiagnosticRecordDetails.vue +52 -0
  370. package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillDetailDialog.vue +166 -0
  371. package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillGovernanceActionDialog.vue +51 -0
  372. package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillImportDialog.vue +320 -0
  373. package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillImportDialog.webtest.ts +96 -0
  374. package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillsTable.vue +69 -0
  375. package/template/apps/web/src/pages/system/components/agent-workbench/AgentWorkbench.vue +236 -0
  376. package/template/apps/web/src/pages/system/components/agent-workbench/DraftLeaveDialog.vue +34 -0
  377. package/template/apps/web/src/pages/system/components/agent-workbench/ReplayEventDetail.vue +175 -0
  378. package/template/apps/web/src/pages/system/components/agent-workbench/SessionReplayTimeline.vue +142 -0
  379. package/template/apps/web/src/pages/system/components/agent-workbench/SessionReplayTimeline.webtest.ts +242 -0
  380. package/template/apps/web/src/pages/system/components/agent-workbench/TestRunComposer.vue +97 -0
  381. package/template/apps/web/src/pages/system/components/agent-workbench/ToolCatalogPanel.vue +100 -0
  382. package/template/apps/web/src/pages/system/components/agent-workbench/ToolCatalogPanel.webtest.ts +55 -0
  383. package/template/apps/web/src/pages/system/components/agent-workbench/ToolRuleDetail.vue +81 -0
  384. package/template/apps/web/src/pages/system/components/agent-workbench/WorkbenchSessionList.vue +57 -0
  385. package/template/apps/web/src/pages/system/components/agent-workbench/catalog-presenter.ts +20 -0
  386. package/template/apps/web/src/pages/system/components/agent-workbench/replay-presenter.ts +94 -0
  387. package/template/apps/web/src/pages/system/components/agent-workflow/WorkflowPresetCatalog.vue +82 -0
  388. package/template/apps/web/src/pages/system/components/agent-workflow/WorkflowPresetCatalog.webtest.ts +57 -0
  389. package/template/apps/web/src/pages/system/composables/useAgentSkillsGovernance.ts +105 -0
  390. package/template/apps/web/src/pages/system/composables/useAgentWorkbench.ts +298 -0
  391. package/template/apps/web/src/pages/system/composables/useAgentWorkbench.webtest.ts +164 -0
  392. package/template/apps/web/src/pages/system/composables/useAgentWorkflowPresets.ts +44 -0
  393. package/template/apps/web/src/pages/system/composables/useDiagnosticLookup.ts +64 -0
  394. package/template/apps/web/src/pages/system/composables/useSessionReplay.ts +48 -0
  395. package/template/apps/web/src/router/error-navigation.ts +3 -1
  396. package/template/apps/web/src/router/error-navigation.webtest.ts +14 -2
  397. package/template/apps/web/src/router/index.ts +8 -45
  398. package/template/apps/web/src/router/platform-admin-pages.ts +79 -0
  399. package/template/apps/web/src/router/platform-admin-route-bindings.ts +12 -0
  400. package/template/apps/web/src/services/agent-admin-api.ts +155 -0
  401. package/template/apps/web/src/services/agent-admin-api.webtest.ts +120 -0
  402. package/template/apps/web/src/services/agent-skills-api.ts +55 -0
  403. package/template/apps/web/src/services/agent-workbench-event.ts +60 -0
  404. package/template/apps/web/src/services/agent-workflow-api.ts +12 -0
  405. package/template/apps/web/src/services/diagnostics-api.ts +12 -0
  406. package/template/apps/web/src/services/http.ts +18 -0
  407. package/template/apps/web/src/services/http.webtest.ts +51 -0
  408. package/template/apps/web/vite.config.ts +39 -0
  409. package/template/deploy/dsh/README.md +5 -0
  410. package/template/deploy/dsh/documents/README.md +9 -0
  411. package/template/deploy/dsh/documents/requirements.in +6 -0
  412. package/template/deploy/dsh/documents/requirements.lock +72 -0
  413. package/template/docker-compose.yml +24 -10
  414. package/template/docs/adr/0004-embedded-dsh-runtime.md +9 -0
  415. package/template/docs/architecture/agent-admin-workbench-implementation.md +73 -0
  416. package/template/docs/architecture/agent-admin-workbench-plan.md +41 -0
  417. package/template/docs/architecture/agent-harness.md +6 -0
  418. package/template/docs/architecture/agent-runtime-compatibility.md +2 -0
  419. package/template/docs/architecture/embedded-dsh-integration.md +44 -0
  420. package/template/docs/development/dsh-plugins.md +55 -0
  421. package/template/docs/operations/dsh-agent-migration.md +98 -0
  422. package/template/docs/platform/agent-production-store.md +5 -78
  423. package/template/docs/platform/agent-runtime-observability.md +2 -0
  424. package/template/docs/platform/agent-runtime.md +2 -0
  425. package/template/docs/platform/agent-skills.md +25 -0
  426. package/template/package.json +4 -3
  427. package/template/packages/database/drizzle/0064_dsh_skills_diagnostics.sql +42 -0
  428. package/template/packages/database/drizzle/meta/0064_snapshot.json +15349 -0
  429. package/template/packages/database/drizzle/meta/_journal.json +7 -0
  430. package/template/packages/database/package.json +2 -2
  431. package/template/packages/database/src/schema/agent-skills.ts +65 -0
  432. package/template/packages/database/src/schema/diagnostics.ts +27 -0
  433. package/template/packages/database/src/schema/index.ts +8 -0
  434. package/template/packages/modules/package.json +1 -1
  435. package/template/packages/modules/src/ai-operation-composition.ts +9 -0
  436. package/template/packages/modules/src/ai-operation-visibility.test.ts +33 -0
  437. package/template/packages/modules/src/manifest.ts +2 -0
  438. package/template/packages/modules/src/system-admin-routes.ts +40 -0
  439. package/template/packages/modules/src/system-admin-ui-catalog.ts +24 -11
  440. package/template/packages/modules/src/system-agent-admin-bindings.ts +44 -0
  441. package/template/packages/modules/src/system-agent-admin-menus.ts +46 -0
  442. package/template/packages/modules/src/system-agent-admin-registration.test.ts +52 -0
  443. package/template/packages/modules/src/system-agent-audit-actions.ts +8 -0
  444. package/template/packages/modules/src/system-agent-dsh.ts +119 -0
  445. package/template/packages/modules/src/system-ai-api-bindings.ts +2 -0
  446. package/template/packages/modules/src/system-api-permissions.ts +9 -0
  447. package/template/packages/modules/src/system-audit-actions.ts +36 -0
  448. package/template/packages/modules/src/system-features.ts +24 -0
  449. package/template/packages/modules/src/system-module-audit-selection.ts +25 -0
  450. package/template/packages/modules/src/system-module-catalog.ts +22 -40
  451. package/template/packages/modules/src/system-module-ownership.ts +12 -0
  452. package/template/packages/modules/src/system-modules.ts +16 -3
  453. package/template/packages/modules/src/system-permissions.ts +15 -0
  454. package/template/packages/server-sdk/index.ts +2 -0
  455. package/template/packages/server-sdk/package.json +2 -2
  456. package/template/packages/server-sdk/src/agent-session-provider.ts +19 -0
  457. package/template/packages/shared/index.ts +14 -0
  458. package/template/packages/shared/package.json +1 -1
  459. package/template/packages/shared/src/agent-admin-catalog.ts +73 -0
  460. package/template/packages/shared/src/agent-skills.ts +68 -0
  461. package/template/packages/shared/src/agent-workbench.ts +100 -0
  462. package/template/packages/shared/src/agent-workflow-presets.ts +26 -0
  463. package/template/packages/shared/src/diagnostics.ts +13 -0
  464. package/template/packages/shared/src/rbac.ts +1 -0
  465. package/template/apps/agent-server/install-python-dependencies.sh +0 -92
  466. package/template/apps/agent-server/pyproject.toml +0 -51
  467. package/template/apps/agent-server/src/southwind_agent_server/__init__.py +0 -5
  468. package/template/apps/agent-server/src/southwind_agent_server/app.py +0 -344
  469. package/template/apps/agent-server/src/southwind_agent_server/approval_resolution.py +0 -30
  470. package/template/apps/agent-server/src/southwind_agent_server/artifact_input.py +0 -153
  471. package/template/apps/agent-server/src/southwind_agent_server/asgi.py +0 -8
  472. package/template/apps/agent-server/src/southwind_agent_server/attempt_context.py +0 -199
  473. package/template/apps/agent-server/src/southwind_agent_server/attempt_context_projection.py +0 -203
  474. package/template/apps/agent-server/src/southwind_agent_server/client_completion_contracts.py +0 -61
  475. package/template/apps/agent-server/src/southwind_agent_server/client_completion_governance.py +0 -82
  476. package/template/apps/agent-server/src/southwind_agent_server/client_completion_routes.py +0 -121
  477. package/template/apps/agent-server/src/southwind_agent_server/client_completion_runtime.py +0 -158
  478. package/template/apps/agent-server/src/southwind_agent_server/config.py +0 -267
  479. package/template/apps/agent-server/src/southwind_agent_server/context_message_digest.py +0 -24
  480. package/template/apps/agent-server/src/southwind_agent_server/context_version_contracts.py +0 -71
  481. package/template/apps/agent-server/src/southwind_agent_server/context_version_port.py +0 -307
  482. package/template/apps/agent-server/src/southwind_agent_server/contracts.py +0 -297
  483. package/template/apps/agent-server/src/southwind_agent_server/deterministic.py +0 -63
  484. package/template/apps/agent-server/src/southwind_agent_server/engine.py +0 -134
  485. package/template/apps/agent-server/src/southwind_agent_server/engine_capacity.py +0 -31
  486. package/template/apps/agent-server/src/southwind_agent_server/engine_identity.py +0 -2
  487. package/template/apps/agent-server/src/southwind_agent_server/fingerprint.py +0 -61
  488. package/template/apps/agent-server/src/southwind_agent_server/health_routes.py +0 -93
  489. package/template/apps/agent-server/src/southwind_agent_server/http_helpers.py +0 -62
  490. package/template/apps/agent-server/src/southwind_agent_server/lease.py +0 -15
  491. package/template/apps/agent-server/src/southwind_agent_server/multimodal.py +0 -76
  492. package/template/apps/agent-server/src/southwind_agent_server/openai_engine.py +0 -329
  493. package/template/apps/agent-server/src/southwind_agent_server/openai_engine_validation.py +0 -165
  494. package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +0 -345
  495. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_insert.py +0 -37
  496. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_queries.py +0 -235
  497. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_replay.py +0 -44
  498. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_status.py +0 -83
  499. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_store.py +0 -336
  500. package/template/apps/agent-server/src/southwind_agent_server/postgres_report_summary.py +0 -304
  501. package/template/apps/agent-server/src/southwind_agent_server/postgres_store.py +0 -335
  502. package/template/apps/agent-server/src/southwind_agent_server/postgres_store_backend.py +0 -333
  503. package/template/apps/agent-server/src/southwind_agent_server/provider_audit.py +0 -144
  504. package/template/apps/agent-server/src/southwind_agent_server/provider_governance.py +0 -309
  505. package/template/apps/agent-server/src/southwind_agent_server/provider_output_guidance.py +0 -34
  506. package/template/apps/agent-server/src/southwind_agent_server/readiness_pin.py +0 -37
  507. package/template/apps/agent-server/src/southwind_agent_server/report_lifecycle.py +0 -218
  508. package/template/apps/agent-server/src/southwind_agent_server/report_metrics.py +0 -149
  509. package/template/apps/agent-server/src/southwind_agent_server/report_presenter.py +0 -300
  510. package/template/apps/agent-server/src/southwind_agent_server/report_routes.py +0 -132
  511. package/template/apps/agent-server/src/southwind_agent_server/report_store.py +0 -298
  512. package/template/apps/agent-server/src/southwind_agent_server/report_store_protocol.py +0 -75
  513. package/template/apps/agent-server/src/southwind_agent_server/report_types.py +0 -118
  514. package/template/apps/agent-server/src/southwind_agent_server/run_admission.py +0 -64
  515. package/template/apps/agent-server/src/southwind_agent_server/run_capacity.py +0 -59
  516. package/template/apps/agent-server/src/southwind_agent_server/runtime_budget.py +0 -74
  517. package/template/apps/agent-server/src/southwind_agent_server/runtime_compatibility.py +0 -89
  518. package/template/apps/agent-server/src/southwind_agent_server/runtime_factory.py +0 -105
  519. package/template/apps/agent-server/src/southwind_agent_server/runtime_logging.py +0 -57
  520. package/template/apps/agent-server/src/southwind_agent_server/service.py +0 -325
  521. package/template/apps/agent-server/src/southwind_agent_server/service_control.py +0 -64
  522. package/template/apps/agent-server/src/southwind_agent_server/service_errors.py +0 -4
  523. package/template/apps/agent-server/src/southwind_agent_server/service_execution.py +0 -34
  524. package/template/apps/agent-server/src/southwind_agent_server/service_tasks.py +0 -34
  525. package/template/apps/agent-server/src/southwind_agent_server/signal_events.py +0 -53
  526. package/template/apps/agent-server/src/southwind_agent_server/sqlite_catalog.py +0 -118
  527. package/template/apps/agent-server/src/southwind_agent_server/sqlite_errors.py +0 -2
  528. package/template/apps/agent-server/src/southwind_agent_server/sqlite_schema.py +0 -73
  529. package/template/apps/agent-server/src/southwind_agent_server/sqlite_serialization.py +0 -16
  530. package/template/apps/agent-server/src/southwind_agent_server/sqlite_store.py +0 -350
  531. package/template/apps/agent-server/src/southwind_agent_server/sse.py +0 -41
  532. package/template/apps/agent-server/src/southwind_agent_server/store.py +0 -255
  533. package/template/apps/agent-server/src/southwind_agent_server/store_cipher.py +0 -40
  534. package/template/apps/agent-server/src/southwind_agent_server/structured_logging.py +0 -145
  535. package/template/apps/agent-server/src/southwind_agent_server/telemetry.py +0 -93
  536. package/template/apps/agent-server/src/southwind_agent_server/tool_host.py +0 -152
  537. package/template/apps/agent-server/src/southwind_agent_server/trajectory.py +0 -137
  538. package/template/apps/agent-server/src/southwind_agent_server/unavailable_engine.py +0 -58
  539. package/template/apps/agent-server/src/southwind_agent_server/vision_probe.py +0 -87
  540. package/template/apps/agent-server/src/southwind_agent_server/vision_requirement.py +0 -28
  541. package/template/apps/agent-server/src/southwind_agent_server/vlm_readiness.py +0 -247
  542. package/template/apps/agent-server/tests/__init__.py +0 -1
  543. package/template/apps/agent-server/tests/openai_provider_test_support.py +0 -131
  544. package/template/apps/agent-server/tests/test_api.py +0 -305
  545. package/template/apps/agent-server/tests/test_artifact_input.py +0 -110
  546. package/template/apps/agent-server/tests/test_client_completion.py +0 -230
  547. package/template/apps/agent-server/tests/test_config.py +0 -106
  548. package/template/apps/agent-server/tests/test_fingerprint.py +0 -10
  549. package/template/apps/agent-server/tests/test_multimodal.py +0 -81
  550. package/template/apps/agent-server/tests/test_openai_provider.py +0 -320
  551. package/template/apps/agent-server/tests/test_postgres_report_status.py +0 -59
  552. package/template/apps/agent-server/tests/test_postgres_report_summary.py +0 -298
  553. package/template/apps/agent-server/tests/test_postgres_store.py +0 -135
  554. package/template/apps/agent-server/tests/test_provider_attempt_reporting.py +0 -140
  555. package/template/apps/agent-server/tests/test_provider_governance.py +0 -276
  556. package/template/apps/agent-server/tests/test_report_attempt_lifecycle.py +0 -126
  557. package/template/apps/agent-server/tests/test_report_resilience.py +0 -183
  558. package/template/apps/agent-server/tests/test_report_routes.py +0 -143
  559. package/template/apps/agent-server/tests/test_report_store.py +0 -347
  560. package/template/apps/agent-server/tests/test_report_summary_parity.py +0 -116
  561. package/template/apps/agent-server/tests/test_report_terminal_sync.py +0 -177
  562. package/template/apps/agent-server/tests/test_run_capacity.py +0 -112
  563. package/template/apps/agent-server/tests/test_run_operational_logging.py +0 -114
  564. package/template/apps/agent-server/tests/test_runtime_compatibility.py +0 -119
  565. package/template/apps/agent-server/tests/test_runtime_factory_readiness.py +0 -52
  566. package/template/apps/agent-server/tests/test_sqlite_store.py +0 -182
  567. package/template/apps/agent-server/tests/test_structured_logging.py +0 -142
  568. package/template/apps/agent-server/tests/test_telemetry.py +0 -25
  569. package/template/apps/agent-server/tests/test_tool_approval.py +0 -28
  570. package/template/apps/agent-server/tests/test_tool_structured_output.py +0 -347
  571. package/template/apps/agent-server/tests/test_trajectory.py +0 -91
  572. package/template/apps/agent-server/tests/test_vision_readiness_enforcement.py +0 -72
  573. package/template/apps/agent-server/tests/test_vlm_readiness.py +0 -106
  574. package/template/apps/agent-server/uv.lock +0 -831
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-windy",
3
- "version": "0.8.2",
3
+ "version": "0.9.1",
4
4
  "description": "创建单组织、单租户、私有部署优先的 Windy 企业 Dashboard Starter",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "templateCommit": "7c00e145cc8fef9f4c6ec621e8740e3c01f7cc2d",
4
- "generatorVersion": "0.8.2",
3
+ "templateCommit": "65f35a9b300c836eafca56da477238edb0ee1cde",
4
+ "generatorVersion": "0.9.1",
5
5
  "modules": [
6
6
  {
7
7
  "name": "system",
@@ -1,27 +1,97 @@
1
1
  # syntax=docker/dockerfile:1
2
+ # One application-owned Agent Server image; DSH is an npm workspace dependency.
3
+ FROM oven/bun:1.3.14-slim@sha256:d56a2534ffd262e92c12fd3249d3924d296d97086da773f821d7d0477435ea04 AS bun
4
+ FROM node:24.7.0-bookworm-slim@sha256:0104d9447ea3ddf7373643be7f9915fc7b7c896e41d0d33229338e457217cd78 AS node
5
+ FROM bun AS dependencies
6
+ WORKDIR /app
7
+ COPY package.json bun.lock ./
2
8
 
3
- FROM python:3.12-slim AS runtime
4
- WORKDIR /app/apps/agent-server
5
-
6
- ARG WINDY_PYPI_INDEX_URL=http://mirrors.cloud.tencent.com/pypi/simple
7
- ARG WINDY_PYPI_TOTAL_TIMEOUT_SECONDS=180
9
+ # windy-copy:deps begin
10
+ COPY apps/agent-server/package.json apps/agent-server/package.json
11
+ COPY apps/license/package.json apps/license/package.json
12
+ COPY apps/server/package.json apps/server/package.json
13
+ COPY apps/signing-service/package.json apps/signing-service/package.json
14
+ COPY apps/web/package.json apps/web/package.json
15
+ COPY apps/windy-gateway/package.json apps/windy-gateway/package.json
16
+ COPY packages/ai-client/package.json packages/ai-client/package.json
17
+ COPY packages/config/package.json packages/config/package.json
18
+ COPY packages/create-windy/package.json packages/create-windy/package.json
19
+ COPY packages/crud-generator/package.json packages/crud-generator/package.json
20
+ COPY packages/database/package.json packages/database/package.json
21
+ COPY packages/delivery/package.json packages/delivery/package.json
22
+ COPY packages/example-work-order/package.json packages/example-work-order/package.json
23
+ COPY packages/jobs/package.json packages/jobs/package.json
24
+ COPY packages/license-sdk/package.json packages/license-sdk/package.json
25
+ COPY packages/model-gateway/package.json packages/model-gateway/package.json
26
+ COPY packages/modules/package.json packages/modules/package.json
27
+ COPY packages/server-sdk/package.json packages/server-sdk/package.json
28
+ COPY packages/shared/package.json packages/shared/package.json
29
+ COPY packages/storage/package.json packages/storage/package.json
30
+ # windy-copy:deps end
31
+ # Other platforms and unused audio engines are excluded. Install the fixed
32
+ # Debian prerequisites and Office WASM engine against this workspace lock.
33
+ RUN --mount=type=cache,id=windy-agent-bun-1.3.14,target=/root/.bun/install/cache,sharing=shared \
34
+ bun install --frozen-lockfile --filter @southwind-ai/agent-server --production --ignore-scripts --omit=optional --linker=hoisted
35
+ COPY apps/agent-server/install-native.ts apps/agent-server/native-download.ts /opt/
36
+ ARG WINDY_AGENT_NATIVE_REGISTRY=https://registry.npmjs.org
37
+ RUN --mount=type=cache,id=windy-agent-native-v1,target=/root/.cache/windy-agent-native,sharing=locked \
38
+ DSH_NATIVE_CACHE_DIR=/root/.cache/windy-agent-native DSH_NATIVE_REGISTRY=$WINDY_AGENT_NATIVE_REGISTRY bun /opt/install-native.ts
39
+ # Keep the complete upstream engine package, including sources/, licenses/ and
40
+ # prebuilds.json. Office conversion never downloads an engine at runtime.
41
+ FROM dependencies AS build
42
+ COPY packages packages
43
+ COPY apps/agent-server apps/agent-server
44
+ RUN bun run --cwd apps/agent-server build
8
45
 
9
- COPY apps/agent-server/install-python-dependencies.sh /usr/local/bin/windy-agent-python-install
10
- RUN chmod 0755 /usr/local/bin/windy-agent-python-install \
11
- && windy-agent-python-install install-uv \
12
- && useradd --create-home --uid 10001 windy
13
- COPY apps/agent-server/pyproject.toml apps/agent-server/uv.lock ./
14
- RUN windy-agent-python-install lock
15
- RUN windy-agent-python-install sync --frozen --no-dev --no-install-project
16
- COPY apps/agent-server/src ./src
17
- RUN windy-agent-python-install sync --frozen --no-dev
46
+ FROM scratch AS fonts
47
+ ADD --checksum=sha256:4a2515eb6db3978b897fef9709ed0d2b1f4c6c4df4d83d6c4ef65f71f1b1f502 \
48
+ https://deb.debian.org/debian/pool/main/f/fonts-noto-cjk/fonts-noto-cjk_20220127+repack1-1_all.deb /fonts.deb
49
+ FROM python:3.12.12-slim-bookworm@sha256:593bd06efe90efa80dc4eee3948be7c0fde4134606dd40d8dd8dbcade98e669c AS document-wheels
50
+ ARG WINDY_PYPI_INDEX_URL=https://pypi.org/simple
51
+ ARG WINDY_PYPI_TOTAL_TIMEOUT_SECONDS=600
52
+ COPY deploy/dsh/documents/requirements.lock /requirements.lock
53
+ RUN --mount=type=cache,target=/root/.cache/pip \
54
+ test "$WINDY_PYPI_TOTAL_TIMEOUT_SECONDS" -ge 1 && test "$WINDY_PYPI_TOTAL_TIMEOUT_SECONDS" -le 600 && \
55
+ timeout --kill-after=5s "$WINDY_PYPI_TOTAL_TIMEOUT_SECONDS" pip download \
56
+ --index-url "$WINDY_PYPI_INDEX_URL" --timeout 30 --retries 2 \
57
+ --require-hashes --only-binary=:all: -r /requirements.lock --dest /wheels
18
58
 
19
- ENV PATH="/app/apps/agent-server/.venv/bin:${PATH}"
20
- ENV PYTHONUNBUFFERED=1
59
+ FROM python:3.12.12-slim-bookworm@sha256:593bd06efe90efa80dc4eee3948be7c0fde4134606dd40d8dd8dbcade98e669c AS runtime
60
+ WORKDIR /app/apps/agent-server
61
+ ARG WINDY_DEBIAN_MIRROR=http://deb.debian.org/debian
62
+ ARG WINDY_DEBIAN_SECURITY_MIRROR=http://deb.debian.org/debian-security
63
+ RUN --mount=type=cache,id=windy-agent-apt,target=/var/cache/apt,sharing=locked \
64
+ set -eu; \
65
+ echo "$WINDY_DEBIAN_MIRROR" | grep -Eq '^https?://[A-Za-z0-9./:_-]+$'; \
66
+ echo "$WINDY_DEBIAN_SECURITY_MIRROR" | grep -Eq '^https?://[A-Za-z0-9./:_-]+$'; \
67
+ sed -i -e "s|^URIs: http://deb.debian.org/debian$|URIs: $WINDY_DEBIAN_MIRROR|" \
68
+ -e "s|^URIs: http://deb.debian.org/debian-security$|URIs: $WINDY_DEBIAN_SECURITY_MIRROR|" \
69
+ /etc/apt/sources.list.d/debian.sources; \
70
+ timeout --kill-after=5s 300s apt-get update -o APT::Update::Error-Mode=any \
71
+ -o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 -o Acquire::Retries=2; \
72
+ timeout --kill-after=5s 600s apt-get install --no-install-recommends --yes libseccomp2 util-linux git ca-certificates; \
73
+ rm -rf /var/lib/apt/lists/*
74
+ RUN --mount=type=bind,from=fonts,source=/,target=/font-source \
75
+ echo '4a2515eb6db3978b897fef9709ed0d2b1f4c6c4df4d83d6c4ef65f71f1b1f502 /font-source/fonts.deb' | sha256sum -c - && \
76
+ dpkg -i /font-source/fonts.deb
77
+ COPY --from=node /usr/local/bin/node /usr/local/bin/node
78
+ COPY --from=dependencies /app/node_modules /app/node_modules
79
+ COPY --from=build /app/apps/agent-server/dist ./dist
80
+ COPY apps/agent-server/package.json ./package.json
81
+ COPY apps/agent-server/plugins ./plugins
82
+ COPY --chown=0:0 apps/agent-server/project ./project
83
+ RUN chmod -R a+rX,a-w ./project
84
+ RUN chmod 0444 ./plugins/subprocess.mjs ./plugins/confine-network.py
85
+ COPY deploy/dsh/documents/requirements.lock /opt/windy-documents/requirements.lock
86
+ COPY apps/agent-server/documents /opt/windy-documents
87
+ RUN --mount=type=bind,from=document-wheels,source=/wheels,target=/wheels python -m venv /opt/venv && \
88
+ /opt/venv/bin/pip install --no-index --find-links=/wheels --require-hashes --only-binary=:all: -r /opt/windy-documents/requirements.lock && \
89
+ mkdir -p /app/data/agent/dsh && chmod 0711 /app/data/agent /app/data/agent/dsh
90
+ ENV NODE_ENV=production PATH=/opt/venv/bin:/usr/local/bin:/usr/bin:/bin \
91
+ PYTHONDONTWRITEBYTECODE=1 PYTHONUTF8=1 PIP_NO_INDEX=1 \
92
+ AGENT_RUNTIME_DATABASE_PATH=/app/data/agent/embedded-dsh.sqlite AGENT_DSH_HOME=/app/data/agent/dsh
21
93
  EXPOSE 8080
22
- RUN mkdir -p /app/data/agent \
23
- && chown -R windy:windy /app/data
24
- USER windy
25
- HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=4 \
26
- CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health/ready', timeout=3)"]
27
- CMD ["uvicorn", "southwind_agent_server.asgi:app", "--host", "0.0.0.0", "--port", "8080"]
94
+ # Coordinator changes UID/GID for isolated workers; workers never run as root.
95
+ HEALTHCHECK --interval=15s --timeout=5s --start-period=15s --retries=4 \
96
+ CMD ["node", "-e", "fetch('http://127.0.0.1:8080/health/ready',{signal:AbortSignal.timeout(3000)}).then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
97
+ CMD ["node", "dist/main.js"]
@@ -1,90 +1,52 @@
1
- # Windy Agent Server
2
-
3
- Python 3.12 Agent 运行时。HTTP 层只公开 Windy canonical Agent 契约;真实业务 Run 由
4
- `OpenAiCompatibleEngineAdapter` 直接执行,模型调用复用受治理的 OpenAI-compatible
5
- `/chat/completions` Provider。Engine、Provider 和 Tool 私有类型不会越过
6
- `AgentEngineAdapter`。
7
-
8
- ```bash
9
- uv sync --frozen
10
- uv run pytest
11
- uv run ruff check .
12
- uv run ruff format --check .
13
- uv run mypy
14
- ```
1
+ # Agent Server:内置 DSH
2
+
3
+ 官方 npm DSH 固定 `0.2.1-rc.2`、Cordis `4.0.5`,随 Bun workspace 安装,Node 24.7+ 执行。Python 仅用于镜像内固定文档工具。
15
4
 
16
- HTTP 接口:
17
-
18
- - `GET /api/agent/runtime/compatibility`(内部认证、V1 协议 Offer)
19
- - `POST /api/agent/runs`
20
- - `GET /api/agent/runs/:runId/events`
21
- - `GET /api/agent/runs/:runId/result`
22
- - `POST /api/agent/runs/:runId/cancel`
23
-
24
- Run 创建使用 `Idempotency-Key`。事件以 SSE 传输,支持 `Last-Event-ID` 和 `after`
25
- 断线重放,并周期发送 comment heartbeat。Provider 或 Engine 异常只映射为 canonical
26
- 安全错误,不把原始异常正文暴露给调用方。
27
-
28
- 兼容 Offer 返回 Engine identity、支持的协议版本、传输能力、callback auth profile 及三层摘要。
29
- 新 Windy Server 会在 Run 请求头固定所选版本和 Offer digest;新 Agent Server 仍接受完全不带 pin
30
- 的旧调用方,但拒绝半套或不匹配 pin。它只用于同一受控部署,不能把内部 token 发给外部业务系统。
31
- 跨系统限制见 [Remote Agent Runtime 兼容契约](../../docs/architecture/agent-runtime-compatibility.md)。
32
-
33
- 配置以下仅服务端可见的环境变量后启用 Direct Engine:
34
-
35
- ```bash
36
- export AGENT_SERVER_INTERNAL_TOKEN='<random-token>'
37
- export QWEN_API_URL='https://dashscope-intl.aliyuncs.com/compatible-mode/v1'
38
- export QWEN_API_KEY='<server-secret>'
39
- export QWEN_MODEL='qwen-plus'
40
- export AI_PROVIDER_HTTPS_HOST_ALLOWLIST='dashscope-intl.aliyuncs.com'
41
- export AI_PROVIDER_CAPABILITIES='text-generation'
42
- export AI_PROVIDER_INPUT_MODALITIES='text'
43
- export AGENT_RUN_STORE_PATH='.data/agent-runs.sqlite3'
44
- export AI_PROVIDER_AUDIT_STORE_PATH='.data/provider-audit.sqlite3'
45
- export AI_PROVIDER_AUDIT_RETENTION_DAYS='90'
46
- uv run uvicorn southwind_agent_server.asgi:app
5
+ ```sh
6
+ bun install --frozen-lockfile
7
+ bun run --cwd apps/agent-server build
8
+ bun run --cwd apps/agent-server start
47
9
  ```
48
10
 
49
- 公网 URL 必须使用 HTTPS 且 Host 精确命中 allowlist;本机、容器服务名和内网地址允许
50
- HTTP。Provider 请求有连接与总超时、响应大小限制、错误脱敏和出网审计。缺少 URL、
51
- Key 或 Model 时使用 `UnavailableEngineAdapter` 稳定返回 unavailable,不调用模型。
52
-
53
- Direct Engine 保留文本、结构化输出、Citation、Vision Artifact、受治理 Tool、多轮 Tool、
54
- 审批等待/恢复、取消、Usage 和 Provider Attempt。Tool 只接受 Operation 允许的 Key,执行时
55
- 回调 Windy Tool Host 并携带当前 Run 的 opaque Execution Grant。Service 在每次模型轮次
56
- 和 Tool 前后重新检查取消,避免取消后继续产生副作用或发布成功终态。
57
-
58
- VLM Operation readiness 比 Endpoint 可达性更严格。必须固定 Deployment 事实并声明图片
59
- offer;否则 `/health/vlm-ready` 返回 V1 `unavailable` snapshot,视觉 Operation 保持关闭:
60
-
61
- ```bash
62
- export AI_PROVIDER_CAPABILITIES='text-generation,vision'
63
- export AI_PROVIDER_INPUT_MODALITIES='text,image'
64
- export AI_PROVIDER_DEPLOYMENT_IDENTITY='windy-deployment-v1_<uuid-v4>'
65
- export AI_PROVIDER_RELEASE_DIGEST='sha256:<64-lowercase-hex>'
66
- export AI_PROVIDER_READINESS_TTL_SECONDS='60'
67
- export AI_PROVIDER_MAX_CONCURRENT_RUNS='1'
68
- export AI_PROVIDER_MAX_QUEUE_DEPTH='0'
11
+ 产品登录后的同源 `/agent` 使用上游原生工作台。Windy Server 负责 Feature、License、RBAC、当前登录与业务工具授权;协调器保管 Provider 和内部凭据,用户 worker 仅持有可撤销的边界 token。Run、SSE、幂等、取消、Client Agent Session、Context、Artifact、审计和结果加密维持原公开协议。
12
+
13
+ Linux 协调器按账号创建独立 UID、0700 HOME 与 workspace。默认最多两个 worker;每用户 heap 768 MiB、进程 128、文件描述符 512、单文件 128 MiB、HOME 软配额 512 MiB。子进程使用 Landlock 和 seccomp,能力缺失拒绝执行。全局模型容量至少预留一个槽位给 canonical/Client 调用,原生排队与父子任务共享预算;这些保护上限不代表硬件容量承诺。
14
+
15
+ `AGENT_DSH_USER_EXTENSIONS` 默认开启;设为 `0` 关闭个人管理入口与个人技能发现,但不会卸载既有插件。用户安装的插件是其授权的可信代码,可访问本人的 HOME、会话和网络。撤销应先停用或卸载,再关闭入口。
16
+
17
+ ## 项目接入
18
+
19
+ `project/host.ts` 是项目自有组合入口,使用 `DshHostConfiguration` 提供助手名称、业务说明、只读技能目录与额外公开 DSH 插件。Windy 不包含案件、笔录、产品 Copilot 历史或领域预设。项目插件只能调用受治理 Host 接口,不能通过工作区元数据授予权限。
20
+
21
+ 项目插件与技能资源放在 `project/` 下,例如 `project/plugins/business.mjs` 和 `project/skills/review/`;在 `host.ts` 中填写相对 Agent Server 的路径。整个目录随生产镜像交付,属于 root、对 Worker 只读,升级保留项目自有内容。该目录不承载 Provider 凭据或其它 Secret。
22
+
23
+ 品牌客户端读取当前平台 `/api/platform/branding` 的 `softwareName`、`logoUrl`、`description`,默认 Windy。中文、主题和 UI 使用公开 locale、theme、slots 与插件生命周期。
24
+
25
+ 共享技能通过官方 `ctx.skills.registerProvider` 接入;每次发现与读取都向产品 Server 重做当前授权。协调器将已授权的版本及附件物化为 HOME 外的 root-owned、用户组只读目录,版本变化后撤下旧目录。个人 `.dsh/skills` 仍由原生技能管理负责。
26
+
27
+ ## 存储与交付
28
+
29
+ canonical 数据库使用 `AGENT_RUNTIME_DATABASE_PATH`(默认 `/app/data/agent/embedded-dsh.sqlite`),用户数据使用 `AGENT_DSH_HOME`(默认 `/app/data/agent/dsh`)。当前仅支持单 Agent Server 副本。
30
+
31
+ 旧 Python Agent 专用数据库不读取、不迁移;切换前备份后使用新路径。业务 PostgreSQL、文件、AH-1 Session、Memory 和 Workflow 的治理义务继续保留。旧记录无法取得运行详情时明确标记缺失。Provider 原有配置继续使用;已退役 Python 的 OTEL exporter 和 connect-only timeout 不再声称受支持。
32
+
33
+ Office 预览复用官方 office-to-pdf/PDF.js,Linux `libreoffice-kit-wasm@0.1.5` 及许可源码随镜像离线交付。每用户转换并发 1、后台 0、输入 16 MiB、输出 20 MiB、缓存 32 MiB/2 项、超时 60 秒。WASM RSS 不受 V8 heap 完整限制。
34
+
35
+ ## 聚焦验证入口
36
+
37
+ ```sh
38
+ bun run --cwd apps/agent-server typecheck
39
+ bun run --cwd apps/agent-server test
40
+ bun test apps/agent-server/native apps/agent-server/plugins
41
+ bun run --cwd apps/agent-server test:coordinator
42
+ bun run --cwd apps/agent-server test:confinement
69
43
  ```
70
44
 
71
- Readiness 使用固定一像素合成图片调用已配置的 `/chat/completions` 并要求有界结构化结果。
72
- 它不读取客户截图,也不把用户 Artifact、URL、Run ID、Prompt 或 Provider 输出放进 health
73
- payload。
74
-
75
- 未设置 `AGENT_RUN_STORE_PATH` 时的 `InMemoryRunStore` 仅用于 deterministic 测试。
76
- 配置路径后使用有界 SQLite Store,可在单副本重启后保留 Run/Event/Result 和 cursor;
77
- 多副本部署必须使用共享 Store。Run 固定保存稳定 Engine ID
78
- `windy.direct.openai-compatible.v1`;历史 `google.adk.v2` Run 只读兼容,不回填,也不能由
79
- Direct Engine 从中断点继续。
80
-
81
- 每次实际 Provider HTTP 调用前,Runtime 对 Manifest 允许的输入 JSON Pointer 与 outbound
82
- envelope 执行 DLP,并将 deployment、operation、run、attempt、分类集合、序列化字节数和
83
- allow/redact/reject 决策写入 append-only 审计。审计不保存 Prompt、请求正文或 Secret;
84
- 审计写入失败时禁止出网。
85
-
86
- 开发与运维统一使用 Windy 主站 `/admin/system/ai-runtime`。详情中的脱敏 Trajectory 展示
87
- Run、输入模态、Tool Key、审批、Usage、Artifact 数量、取消/失败和终态,不展示输入输出正文、
88
- Tool 参数、chain-of-thought 或 Provider 原始响应。业务历史会话通过
89
- `registerAgentSessionProviders()` 投影到受当前登录身份、Feature、RBAC 和对象范围保护的
90
- 主站接口;不再存在独立调试站点、专用调试身份或第二种 Token。
45
+ Node 契约使用真实 DSH Loop 与合成 Provider。Linux 镜像、真实认证模型、文档质量及现场负载分别验收;不得互相替代。镜像验证可用 `WINDY_AGENT_TEST_IMAGE` 指定已构建镜像。
46
+
47
+ ### 本机 JSON 输出兼容模式
48
+
49
+ 默认 `QWEN_STRUCTURED_OUTPUT_MODE=json_schema` 保持提供方严格结构输出。
50
+ 只有运行器无法编译合法业务 Schema 时,可在该部署显式设置 `json_object`。
51
+ 此模式仅改变无工具请求的 `response_format`:完整授权 Schema 仍进入系统提示,输出仍经过原有 JSON Schema 与业务校验;缺字段、类型错误和无效引用不会被补齐或放行。
52
+ 该配置不改变 Manifest、Host Guard、输出 Schema 授权或其它部署的默认值。
@@ -0,0 +1,216 @@
1
+ """Bounded, local document helpers; no model calls, network, or business writes."""
2
+
3
+ from datetime import date, datetime
4
+ from decimal import Decimal, InvalidOperation
5
+ from hashlib import sha256
6
+ from io import BytesIO
7
+ from pathlib import Path
8
+ from zipfile import ZipFile
9
+
10
+ from docx import Document
11
+ from docx.oxml.ns import qn
12
+ from docx.shared import Pt
13
+ from docx.table import Table
14
+ from openpyxl import Workbook, load_workbook
15
+ from openpyxl.comments import Comment
16
+ from pypdf import PdfReader
17
+
18
+ MAX_INPUT_BYTES = 16 * 1024 * 1024
19
+ # Upstream /api/file uses attachments.imageLimits.maxImageBytes (20 MiB by default).
20
+ MAX_OUTPUT_BYTES = 20 * 1024 * 1024
21
+ MAX_ROWS = 10_000
22
+
23
+
24
+ def digest(path: Path) -> str:
25
+ return sha256(path.read_bytes()).hexdigest()
26
+
27
+
28
+ def check_input(path: Path, zipped: bool = False) -> None:
29
+ if not path.is_file() or not 0 < path.stat().st_size <= MAX_INPUT_BYTES:
30
+ raise ValueError("input must be a nonempty file of at most 16 MiB")
31
+ if zipped:
32
+ with ZipFile(path) as archive:
33
+ entries = archive.infolist()
34
+ if len(entries) > 2048 or sum(e.file_size for e in entries) > 64 * 1024 * 1024:
35
+ raise ValueError("Office ZIP exceeds entry/expanded-size budget")
36
+ if any(e.file_size > MAX_INPUT_BYTES for e in entries):
37
+ raise ValueError("Office ZIP member exceeds 16 MiB")
38
+
39
+
40
+ def save_new(document, output: Path) -> None:
41
+ """Exclusive creation preserves originals and previously generated revisions."""
42
+ content = BytesIO()
43
+ document.save(content)
44
+ data = content.getvalue()
45
+ if not 0 < len(data) <= MAX_OUTPUT_BYTES:
46
+ raise ValueError("output exceeds the 20 MiB native download budget")
47
+ with output.open("xb") as handle:
48
+ handle.write(data)
49
+
50
+
51
+ def new_document(title: str):
52
+ document = Document()
53
+ normal = document.styles["Normal"]
54
+ normal.font.name = "Noto Sans CJK SC"
55
+ normal.font.size = Pt(11)
56
+ normal.element.rPr.rFonts.set(qn("w:eastAsia"), "Noto Sans CJK SC")
57
+ document.core_properties.title = title
58
+ document.core_properties.author = ""
59
+ document.core_properties.last_modified_by = ""
60
+ document.add_heading(title, 0)
61
+ return document
62
+
63
+
64
+ def read_text(source: Path) -> str:
65
+ suffix = source.suffix.lower()
66
+ check_input(source, zipped=suffix == ".docx")
67
+ if suffix == ".docx":
68
+ document = Document(source)
69
+ lines = []
70
+ for block in document.iter_inner_content():
71
+ if isinstance(block, Table):
72
+ lines.extend(" | ".join(cell.text for cell in row.cells) for row in block.rows)
73
+ else:
74
+ lines.append(block.text)
75
+ text = "\n".join(lines)
76
+ elif suffix == ".pdf":
77
+ reader = PdfReader(source, strict=True)
78
+ if reader.is_encrypted or len(reader.pages) > 100:
79
+ raise ValueError("encrypted PDFs or PDFs over 100 pages are unsupported")
80
+ pages = [page.extract_text() or "" for page in reader.pages]
81
+ if any(not page.strip() for page in pages):
82
+ raise ValueError("PDF has a page without extractable text; OCR or page review is required")
83
+ text = "\n".join(pages)
84
+ else:
85
+ raise ValueError("only .docx and text-based .pdf are supported")
86
+ if not text.strip() or len(text) > 1_000_000:
87
+ raise ValueError("missing extractable text or extracted text exceeds budget")
88
+ return text
89
+
90
+
91
+ def write_revision(source: Path, output: Path, text: str, title: str) -> None:
92
+ """Write a new editable text draft, without promising source layout fidelity."""
93
+ if output.suffix.lower() != ".docx":
94
+ raise ValueError("revision output must use .docx")
95
+ read_text(source)
96
+ if not text.strip() or len(text) > 1_000_000:
97
+ raise ValueError("revision text is empty or exceeds budget")
98
+ before = digest(source)
99
+ document = new_document(title)
100
+ document.core_properties.subject = f"Source SHA256: {before}"
101
+ for paragraph in text.splitlines():
102
+ document.add_paragraph(paragraph)
103
+ save_new(document, output)
104
+ if digest(source) != before:
105
+ raise RuntimeError("source changed during revision")
106
+
107
+
108
+ def money(value) -> Decimal:
109
+ if isinstance(value, bool) or not isinstance(value, (str, int, float, Decimal)):
110
+ raise ValueError("amount must be a finite decimal value")
111
+ try:
112
+ amount = Decimal(str(value))
113
+ except InvalidOperation as error:
114
+ raise ValueError("invalid decimal amount") from error
115
+ if not amount.is_finite() or abs(amount) >= Decimal("1e12"):
116
+ raise ValueError("amount is non-finite or outside budget")
117
+ if amount != amount.quantize(Decimal("0.01")):
118
+ raise ValueError("amount must have at most two decimal places")
119
+ return amount
120
+
121
+
122
+ def summarize_excel(source: Path, output: Path, *, unit: str) -> Decimal:
123
+ """Known four-column sample contract; formulas/macros are deliberately rejected."""
124
+ if not isinstance(unit, str) or not unit.strip() or len(unit) > 32:
125
+ raise ValueError("an explicit amount unit is required; no automatic conversion")
126
+ if source.suffix.lower() != ".xlsx" or output.suffix.lower() != ".xlsx":
127
+ raise ValueError("only .xlsx is supported")
128
+ check_input(source, zipped=True)
129
+ before = digest(source)
130
+ workbook = load_workbook(source, read_only=True, data_only=False)
131
+ try:
132
+ if len(workbook.worksheets) != 1:
133
+ raise ValueError("sample summarizer requires exactly one worksheet")
134
+ sheet = workbook.active
135
+ if sheet.max_row is not None and sheet.max_row > MAX_ROWS + 1:
136
+ raise ValueError("worksheet exceeds row budget")
137
+ # XLSX dimension metadata can understate the data and silently truncate read_only iteration.
138
+ sheet.reset_dimensions()
139
+ rows = sheet.iter_rows()
140
+ header = next(rows, ())
141
+ if [cell.value for cell in header] != ["编号", "名称", "日期", "金额"]:
142
+ raise ValueError("expected columns: 编号, 名称, 日期, 金额")
143
+ result = Workbook()
144
+ target = result.active
145
+ target.title = "整理结果"
146
+ target.append(["编号", "名称", "日期", "金额"])
147
+ total = Decimal("0.00")
148
+ last_row = 1
149
+ for last_row, row in enumerate(rows, start=2):
150
+ if last_row > MAX_ROWS + 1 or len(row) != 4:
151
+ raise ValueError("actual worksheet data exceeds row/column contract")
152
+ if any(cell.data_type in ("f", "e") for cell in row):
153
+ raise ValueError("formula or error cells require a separately verified calculation")
154
+ identifier, label, when, value = (cell.value for cell in row)
155
+ if not isinstance(identifier, str) or not identifier.isdigit():
156
+ raise ValueError("identifiers must be text so leading zeros remain exact")
157
+ if not isinstance(label, str) or not isinstance(when, (date, datetime)):
158
+ raise ValueError("name/date column types do not match contract")
159
+ amount = money(value)
160
+ total += amount
161
+ target.append([identifier, label, when, format(amount, ".2f")])
162
+ # append() infers formulas from '=' even when the source cell was literal text.
163
+ for column in (1, 2, 4):
164
+ target.cell(target.max_row, column).data_type = "s"
165
+ target.cell(target.max_row, 1).number_format = "@"
166
+ target.cell(target.max_row, 3).number_format = "yyyy-mm-dd"
167
+ target.append(["汇总", "", None, format(total, ".2f")])
168
+ # Currency stays decimal text: no binary-float coercion or cached formula claim.
169
+ target.column_dimensions["A"].width = 16
170
+ target.column_dimensions["B"].width = 24
171
+ target.column_dimensions["C"].width = 16
172
+ target.column_dimensions["D"].width = 20
173
+ source_range = f"{sheet.title}!A1:D{last_row}"
174
+ target["D1"].comment = Comment(f"金额单位:{unit};未转换单位。来源:{source_range}。", "DSH")
175
+ provenance = result.create_sheet("来源说明")
176
+ for label, value in (("来源文件", source.name), ("来源 SHA256", before),
177
+ ("来源范围", source_range), ("筛选条件", "全部输入数据行,无过滤"),
178
+ ("金额单位", unit), ("单位转换", "未转换"),
179
+ ("数据行数", str(last_row - 1)), ("Decimal 合计", format(total, ".2f"))):
180
+ provenance.append([label, value])
181
+ provenance.cell(provenance.max_row, 2).data_type = "s"
182
+ provenance.column_dimensions["A"].width = 18
183
+ provenance.column_dimensions["B"].width = 72
184
+ save_new(result, output)
185
+ finally:
186
+ workbook.close()
187
+ if digest(source) != before:
188
+ raise RuntimeError("source changed during summary")
189
+ return total
190
+
191
+
192
+ if __name__ == "__main__":
193
+ import argparse
194
+
195
+ parser = argparse.ArgumentParser(description=__doc__)
196
+ subparsers = parser.add_subparsers(dest="command", required=True)
197
+ read_parser = subparsers.add_parser("read")
198
+ read_parser.add_argument("source", type=Path)
199
+ revise_parser = subparsers.add_parser("revise")
200
+ revise_parser.add_argument("source", type=Path)
201
+ revise_parser.add_argument("output", type=Path)
202
+ revise_parser.add_argument("--text", type=Path, required=True)
203
+ revise_parser.add_argument("--title", default="文档修订稿")
204
+ excel_parser = subparsers.add_parser("summarize-excel")
205
+ excel_parser.add_argument("source", type=Path)
206
+ excel_parser.add_argument("output", type=Path)
207
+ excel_parser.add_argument("--unit", required=True, help="source amount unit, e.g. 元; no conversion")
208
+ arguments = parser.parse_args()
209
+ if arguments.command == "read":
210
+ print(read_text(arguments.source))
211
+ elif arguments.command == "revise":
212
+ check_input(arguments.text)
213
+ write_revision(arguments.source, arguments.output,
214
+ arguments.text.read_text(encoding="utf-8"), arguments.title)
215
+ else:
216
+ print(format(summarize_excel(arguments.source, arguments.output, unit=arguments.unit), ".2f"))
@@ -0,0 +1,136 @@
1
+ """Build a source-attributed DOCX from a complete, normalized MCP query export.
2
+
3
+ This checks a local export's declared coverage, not its authenticity or authorization.
4
+ The MCP caller must fetch/re-authorize every page and normalize the actual tool response.
5
+ """
6
+
7
+ import argparse
8
+ import json
9
+ from datetime import datetime
10
+ from decimal import Decimal
11
+ from hashlib import sha256
12
+ from pathlib import Path
13
+
14
+ from office import MAX_ROWS, check_input, money, new_document, save_new
15
+
16
+
17
+ def required_text(value, field: str, limit: int = 2048) -> str:
18
+ if not isinstance(value, str) or not value.strip() or len(value) > limit:
19
+ raise ValueError(f"invalid {field}")
20
+ return value
21
+
22
+
23
+ def validate_snapshot(snapshot: dict) -> tuple[dict, list[dict], Decimal]:
24
+ if (not isinstance(snapshot, dict) or type(snapshot.get("schemaVersion")) is not int
25
+ or snapshot["schemaVersion"] != 1):
26
+ raise ValueError("unsupported snapshot schema")
27
+ if snapshot.get("complete") is not True or snapshot.get("errors") != []:
28
+ raise ValueError("incomplete or partially failed query export")
29
+ if snapshot.get("partial", False) is not False or snapshot.get("truncated", False) is not False:
30
+ raise ValueError("query export declares partial or truncated coverage")
31
+ source = snapshot.get("source")
32
+ if not isinstance(source, dict) or source.get("kind") not in (
33
+ "synthetic-fixture", "mcp-query-export"
34
+ ):
35
+ raise ValueError("missing explicit source kind")
36
+ for key in ("tool", "queryId", "scope", "query", "capturedAt"):
37
+ required_text(source.get(key), f"source.{key}")
38
+ required_text(source.get("unit"), "source.unit", limit=32)
39
+ if "metric" in source:
40
+ required_text(source["metric"], "source.metric", limit=64)
41
+ captured_at = datetime.fromisoformat(source["capturedAt"].replace("Z", "+00:00"))
42
+ if captured_at.tzinfo is None:
43
+ raise ValueError("capturedAt must include timezone")
44
+ total = snapshot.get("total")
45
+ if type(total) is not int or not 0 <= total <= MAX_ROWS:
46
+ raise ValueError("missing total or total exceeds row budget")
47
+ pages = snapshot.get("pages")
48
+ if not isinstance(pages, list) or not 1 <= len(pages) <= 100:
49
+ raise ValueError("missing pages or page budget exceeded")
50
+ records, identifiers, visited = [], set(), set()
51
+ expected_cursor, amount = None, Decimal("0.00")
52
+ for index, page in enumerate(pages):
53
+ if not isinstance(page, dict) or page.get("status") != "success":
54
+ raise ValueError("query page failed")
55
+ if page.get("truncated") is not False or page.get("partial", False) is not False:
56
+ raise ValueError("truncated or partial query page")
57
+ if page.get("errors", []) != []:
58
+ raise ValueError("query page contains errors")
59
+ if "cursor" not in page or "nextCursor" not in page:
60
+ raise ValueError("pagination cursors must be explicit")
61
+ cursor, following = page["cursor"], page["nextCursor"]
62
+ if cursor != expected_cursor:
63
+ raise ValueError("missing or out-of-order query page")
64
+ if following is not None:
65
+ required_text(following, "nextCursor")
66
+ if following in visited:
67
+ raise ValueError("repeated pagination cursor")
68
+ visited.add(following)
69
+ if (index == len(pages) - 1) != (following is None):
70
+ raise ValueError("pagination must terminate exactly on the final page")
71
+ expected_cursor = following
72
+ items = page.get("records")
73
+ if not isinstance(items, list) or len(records) + len(items) > MAX_ROWS:
74
+ raise ValueError("invalid records or row budget exceeded")
75
+ for item in items:
76
+ if not isinstance(item, dict):
77
+ raise ValueError("invalid record")
78
+ identifier = required_text(item.get("id"), "record.id")
79
+ required_text(item.get("label"), "record.label")
80
+ required_text(item.get("sourceRef"), "record.sourceRef")
81
+ if "unit" in item and item["unit"] != source["unit"]:
82
+ raise ValueError("mixed record units require explicit normalization before reporting")
83
+ if identifier in identifiers:
84
+ raise ValueError("duplicate record across query pages")
85
+ identifiers.add(identifier)
86
+ # Exporters must preserve decimal strings, rather than JSON floating point.
87
+ required_text(item.get("amount"), "record.amount", limit=32)
88
+ amount += money(item["amount"])
89
+ records.append(item)
90
+ if len(records) != total:
91
+ raise ValueError("record count differs from declared total")
92
+ return source, records, amount
93
+
94
+
95
+ def generate_report(source_path: Path, output: Path) -> dict:
96
+ if output.suffix.lower() != ".docx":
97
+ raise ValueError("report output must use .docx")
98
+ check_input(source_path)
99
+ payload = source_path.read_bytes()
100
+ source_digest = sha256(payload).hexdigest()
101
+ snapshot = json.loads(payload)
102
+ source, records, total = validate_snapshot(snapshot)
103
+ metric = source.get("metric", "金额")
104
+ document = new_document("查询数据汇总报告")
105
+ if source["kind"] == "synthetic-fixture":
106
+ document.add_paragraph("脱敏合成样例,仅用于文件和来源覆盖检查。")
107
+ document.add_paragraph(f"导出时声明的查询范围:{source['scope']}")
108
+ document.add_paragraph(f"查询条件:{source['query']}")
109
+ document.add_paragraph(f"在该范围内完成 {len(snapshot['pages'])} 页,共 {len(records)} 条记录。")
110
+ document.add_paragraph(f"{metric}合计:{format(total, '.2f')} {source['unit']}(Decimal 计算)。")
111
+ table = document.add_table(rows=1, cols=4)
112
+ table.style = "Light Shading Accent 1"
113
+ for cell, label in zip(table.rows[0].cells, ("记录 ID", "名称", f"{metric}({source['unit']})", "来源定位")):
114
+ cell.text = label
115
+ for record in records:
116
+ values = (record["id"], record["label"], format(money(record["amount"]), ".2f"),
117
+ record["sourceRef"])
118
+ for cell, value in zip(table.add_row().cells, values):
119
+ cell.text = value
120
+ document.add_heading("来源与覆盖边界", level=1)
121
+ for label, value in (("MCP 工具", source["tool"]), ("查询关联", source["queryId"]),
122
+ ("导出时间", source["capturedAt"]), ("快照 SHA256", source_digest)):
123
+ document.add_paragraph(f"{label}:{value}")
124
+ document.add_paragraph("来源定位用于回查;访问来源仍按当前身份和数据范围重新授权。")
125
+ document.add_paragraph("报告反映该导出时点和筛选范围,不代表其他范围或实时数据库全量。")
126
+ save_new(document, output)
127
+ return {"records": len(records), "total": format(total, ".2f"), "unit": source["unit"], "metric": metric,
128
+ "sourceSha256": source_digest, "sourceKind": source["kind"]}
129
+
130
+
131
+ if __name__ == "__main__":
132
+ parser = argparse.ArgumentParser(description=__doc__)
133
+ parser.add_argument("snapshot", type=Path)
134
+ parser.add_argument("output", type=Path)
135
+ arguments = parser.parse_args()
136
+ print(json.dumps(generate_report(arguments.snapshot, arguments.output), ensure_ascii=False))