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
@@ -0,0 +1,342 @@
1
+ import { expect, test } from "bun:test";
2
+ import {
3
+ mkdir,
4
+ rm,
5
+ writeFile,
6
+ readFile,
7
+ symlink,
8
+ link,
9
+ } from "node:fs/promises";
10
+ import { join } from "node:path";
11
+ import { createServer } from "node:http";
12
+ import { readFileSync } from "node:fs";
13
+ import { runInNewContext } from "node:vm";
14
+ import { zipSync, strToU8, unzipSync } from "fflate";
15
+ import { apply, type SkillContext } from "./index.mjs";
16
+
17
+ import { cleanups, markdown, fixture } from "./test-fixture.js";
18
+
19
+ test("Host skill lifecycle, attachments, conflict, read-only defaults, export and explicit share", async () => {
20
+ const f = await fixture();
21
+ expect(
22
+ (await (await f.call({ action: "list" })).json()).items[0],
23
+ ).toMatchObject({ name: "default-skill", readOnly: true });
24
+ expect((await f.call({ action: "create", raw: markdown() })).status).toBe(
25
+ 200,
26
+ );
27
+ const item = await (
28
+ await f.call({ action: "read", name: "my-skill", source: "personal" })
29
+ ).json();
30
+ expect(item.raw).toBe(markdown());
31
+ expect((await f.call({ action: "create", raw: markdown() })).status).toBe(
32
+ 409,
33
+ );
34
+ expect(
35
+ (await f.call({ action: "create", raw: markdown("default-skill") })).status,
36
+ ).toBe(409);
37
+ expect(
38
+ (
39
+ await f.call({
40
+ action: "save",
41
+ name: "default-skill",
42
+ source: "defaults",
43
+ raw: markdown("default-skill"),
44
+ })
45
+ ).status,
46
+ ).toBe(403);
47
+ expect(
48
+ (
49
+ await f.call({
50
+ action: "save",
51
+ name: "my-skill",
52
+ source: "personal",
53
+ raw: markdown(),
54
+ version: "stale",
55
+ })
56
+ ).status,
57
+ ).toBe(409);
58
+ expect(
59
+ (
60
+ await f.call({
61
+ action: "save",
62
+ name: "my-skill",
63
+ source: "personal",
64
+ raw: markdown() + "\n补充步骤",
65
+ version: item.version,
66
+ })
67
+ ).status,
68
+ ).toBe(200);
69
+ const bundle = zipSync({
70
+ "shared/SKILL.md": strToU8(markdown("shared")),
71
+ "shared/scripts/clean.py": strToU8("print('synthetic')"),
72
+ "shared/references/template.md": strToU8("模板"),
73
+ "shared/assets/data.csv": strToU8("value\n1"),
74
+ "shared/__proto__": strToU8("ordinary attachment"),
75
+ });
76
+ expect(
77
+ (
78
+ await f.call({
79
+ action: "import",
80
+ archive: Buffer.from(bundle).toString("base64"),
81
+ })
82
+ ).status,
83
+ ).toBe(200);
84
+ const exported = await f.call({
85
+ action: "export",
86
+ name: "shared",
87
+ source: "personal",
88
+ });
89
+ expect(exported.headers.get("content-disposition")).toContain("shared.zip");
90
+ const bytes = new Uint8Array(await exported.arrayBuffer());
91
+ expect(Object.keys(unzipSync(bytes)).sort()).toEqual([
92
+ "shared/SKILL.md",
93
+ "shared/__proto__",
94
+ "shared/assets/data.csv",
95
+ "shared/references/template.md",
96
+ "shared/scripts/clean.py",
97
+ ]);
98
+ const recipient = await fixture();
99
+ expect(
100
+ (
101
+ await recipient.call({
102
+ action: "read",
103
+ name: "shared",
104
+ source: "personal",
105
+ })
106
+ ).status,
107
+ ).toBe(404);
108
+ expect(
109
+ (
110
+ await recipient.call({
111
+ action: "import",
112
+ archive: Buffer.from(bytes).toString("base64"),
113
+ })
114
+ ).status,
115
+ ).toBe(200);
116
+ const personal = await (
117
+ await f.call({ action: "read", name: "my-skill", source: "personal" })
118
+ ).json();
119
+ expect(
120
+ (
121
+ await f.call({
122
+ action: "delete",
123
+ name: "my-skill",
124
+ source: "personal",
125
+ version: personal.version,
126
+ })
127
+ ).status,
128
+ ).toBe(400);
129
+ expect(
130
+ (
131
+ await f.call({
132
+ action: "delete",
133
+ name: "my-skill",
134
+ source: "personal",
135
+ version: personal.version,
136
+ confirmed: true,
137
+ })
138
+ ).status,
139
+ ).toBe(200);
140
+ expect(
141
+ (await f.call({ action: "read", name: "my-skill", source: "personal" }))
142
+ .status,
143
+ ).toBe(404);
144
+ });
145
+ test("reject missing auth, foreign workspace, arbitrary path, symlinks and hardlinks", async () => {
146
+ const f = await fixture();
147
+ expect(
148
+ (
149
+ await f.call(
150
+ { action: "list" },
151
+ { cookie: "native=other", origin: "http://localhost" },
152
+ )
153
+ ).status,
154
+ ).toBe(403);
155
+ expect(
156
+ (
157
+ await f.call(
158
+ { action: "list" },
159
+ { cookie: "native=owner", origin: "https://foreign.invalid" },
160
+ )
161
+ ).status,
162
+ ).toBe(403);
163
+ expect(
164
+ (await f.call({ action: "list", workspaceId: "other-workspace" })).status,
165
+ ).toBe(403);
166
+ expect(
167
+ (await f.call({ action: "list", workspaceId: "missing" })).status,
168
+ ).toBe(404);
169
+ expect((await f.call({ action: "list", path: f.other })).status).toBe(400);
170
+ await mkdir(join(f.root, ".dsh"));
171
+ await symlink(f.other, join(f.root, ".dsh", "skills"));
172
+ expect((await f.call({ action: "create", raw: markdown() })).status).toBe(
173
+ 400,
174
+ );
175
+ await rm(join(f.root, ".dsh", "skills"));
176
+ await f.call({ action: "create", raw: markdown() });
177
+ const skillPath = join(f.root, ".dsh", "skills", "my-skill", "SKILL.md");
178
+ const original = await readFile(skillPath);
179
+ await writeFile(join(f.other, "private.md"), markdown());
180
+ await rm(skillPath);
181
+ await symlink(join(f.other, "private.md"), skillPath);
182
+ expect(
183
+ (await f.call({ action: "read", name: "my-skill", source: "personal" }))
184
+ .status,
185
+ ).toBe(400);
186
+ await rm(skillPath);
187
+ await writeFile(skillPath, original);
188
+ await link(skillPath, join(f.other, "linked.md"));
189
+ expect(
190
+ (await f.call({ action: "export", name: "my-skill", source: "personal" }))
191
+ .status,
192
+ ).toBe(413);
193
+ });
194
+ test("ZIP traversal, duplicate case, symlink, zipbomb, invalid YAML are refused before publication", async () => {
195
+ const f = await fixture();
196
+ const archives = [
197
+ zipSync({ "../SKILL.md": strToU8(markdown()) }),
198
+ zipSync({
199
+ "SKILL.md": strToU8(markdown()),
200
+ "skill.md": strToU8("duplicate"),
201
+ }),
202
+ zipSync({
203
+ "SKILL.md": strToU8(markdown()),
204
+ ".env": strToU8("PRIVATE_SYNTHETIC"),
205
+ }),
206
+ zipSync({
207
+ "first/SKILL.md": strToU8(markdown()),
208
+ "second/SKILL.md": strToU8(markdown()),
209
+ }),
210
+ zipSync({
211
+ "SKILL.md": strToU8(markdown()),
212
+ "scripts/too-big": new Uint8Array(5 * 1024 * 1024),
213
+ }),
214
+ ];
215
+ const symbolic = zipSync({
216
+ "SKILL.md": strToU8(markdown()),
217
+ "assets/link": strToU8("target"),
218
+ });
219
+ const view = new DataView(symbolic.buffer);
220
+ let found = 0;
221
+ for (let offset = 0; offset < symbolic.length - 46; offset++)
222
+ if (view.getUint32(offset, true) === 0x02014b50 && ++found === 2) {
223
+ view.setUint32(offset + 38, 0xa1ff0000, true);
224
+ break;
225
+ }
226
+ archives.push(symbolic);
227
+ for (const archive of archives)
228
+ expect(
229
+ (
230
+ await f.call({
231
+ action: "import",
232
+ archive: Buffer.from(archive).toString("base64"),
233
+ })
234
+ ).status,
235
+ ).toBeGreaterThanOrEqual(400);
236
+ expect(
237
+ (
238
+ await f.call({
239
+ action: "create",
240
+ raw: "---\nname: Bad_Name\ndescription: bad\n---\ntext",
241
+ })
242
+ ).status,
243
+ ).toBe(400);
244
+ expect(
245
+ (
246
+ await f.call({
247
+ action: "create",
248
+ raw: "---\nname: valid\nname: dup\ndescription: bad\n---\ntext",
249
+ })
250
+ ).status,
251
+ ).toBe(400);
252
+ expect((await (await f.call({ action: "list" })).json()).items).toHaveLength(
253
+ 1,
254
+ );
255
+ });
256
+ test("actual Node Host route enforces body bound and runs serial mutations", async () => {
257
+ const f = await fixture();
258
+ let handler:
259
+ | Parameters<SkillContext["webServer"]["register"]>[0]["handler"]
260
+ | undefined;
261
+ f.ctx.webServer.register = (route) => {
262
+ handler = route.handler;
263
+ return () => {};
264
+ };
265
+ apply(f.ctx, f.config);
266
+ const server = createServer((request, response) => {
267
+ void handler!(request, response);
268
+ });
269
+ await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
270
+ cleanups.push(
271
+ () => new Promise<void>((resolve) => server.close(() => resolve())),
272
+ );
273
+ const address = server.address();
274
+ if (!address || typeof address === "string") throw new Error("address");
275
+ const url = `http://127.0.0.1:${address.port}/windy/skills`,
276
+ headers = {
277
+ cookie: "native=owner",
278
+ origin: "http://localhost",
279
+ "content-type": "application/json",
280
+ };
281
+ const results = await Promise.all(
282
+ [1, 2].map(() =>
283
+ fetch(url, {
284
+ method: "POST",
285
+ headers,
286
+ body: JSON.stringify({
287
+ action: "create",
288
+ workspaceId: "owner-workspace",
289
+ raw: markdown(),
290
+ }),
291
+ }),
292
+ ),
293
+ );
294
+ expect(results.map((result) => result.status).sort()).toEqual([200, 409]);
295
+ expect(
296
+ (
297
+ await fetch(url, {
298
+ method: "POST",
299
+ headers,
300
+ body: "x".repeat(6 * 1024 * 1024 + 1),
301
+ })
302
+ ).status,
303
+ ).toBe(413);
304
+ });
305
+ test("client registers native main and sidebar seats using public workspace hook", () => {
306
+ const source = readFileSync(new URL("./client.js", import.meta.url), "utf8");
307
+ let plugin: { apply(ctx: unknown): void } | undefined;
308
+ runInNewContext(source, {
309
+ window: {
310
+ __ModuleLoader__: {
311
+ load({
312
+ factory,
313
+ }: {
314
+ factory(require: (name: string) => unknown): unknown;
315
+ }) {
316
+ plugin = factory((name) =>
317
+ name === "react"
318
+ ? { createElement() {}, lazy() {} }
319
+ : { Button() {} },
320
+ ) as typeof plugin;
321
+ },
322
+ },
323
+ },
324
+ });
325
+ const entries: unknown[] = [];
326
+ plugin!.apply({
327
+ slots: {
328
+ inject(_name: string, callback: () => unknown) {
329
+ callback();
330
+ },
331
+ register(options: unknown) {
332
+ entries.push(options);
333
+ },
334
+ },
335
+ });
336
+ expect(entries).toContainEqual({ name: "main", key: "windy-skills" });
337
+ expect(entries).toContainEqual(
338
+ expect.objectContaining({ name: "sidebar.panellist", id: "windy-skills" }),
339
+ );
340
+ expect(source).toContain("useWorkspaces((state) => state.items)");
341
+ expect(source).not.toContain("iframe");
342
+ });
@@ -0,0 +1,293 @@
1
+ import { constants } from "node:fs";
2
+ import {
3
+ open,
4
+ mkdir,
5
+ readdir,
6
+ lstat,
7
+ realpath,
8
+ rename,
9
+ rm,
10
+ } from "node:fs/promises";
11
+ import { join, relative, resolve } from "node:path";
12
+ import { randomUUID, createHash } from "node:crypto";
13
+ import { LIMITS, fail, skillName, skillDocument } from "./bundle.mjs";
14
+
15
+ const dirFlags =
16
+ constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW;
17
+ export function contained(parent, child) {
18
+ const diff = relative(parent, child);
19
+ return (
20
+ !diff ||
21
+ (!diff.startsWith("..") && !diff.startsWith("/") && !diff.includes(":"))
22
+ );
23
+ }
24
+ function anchored(handle, path) {
25
+ return process.platform === "linux" ? `/proc/self/fd/${handle.fd}` : path;
26
+ }
27
+ async function directory(path) {
28
+ const handle = await open(path, dirFlags);
29
+ return { handle, path: anchored(handle, path) };
30
+ }
31
+ async function descend(parent, name, create = false) {
32
+ const path = join(parent.path, name);
33
+ if (create)
34
+ await mkdir(path, { mode: 0o700 }).catch((error) => {
35
+ if (error.code !== "EEXIST") throw error;
36
+ });
37
+ return directory(path);
38
+ }
39
+ export async function skillRoots(ctx, config, workspaceId, run) {
40
+ if (typeof workspaceId !== "string" || workspaceId.length > 128)
41
+ fail("请选择工作区。");
42
+ const workspace = ctx.workspaceRegistry.get(workspaceId);
43
+ if (!workspace) fail("工作区不可用。", 404);
44
+ const rootPath = await realpath(ctx.sandboxPolicy.workspaceRoot),
45
+ cwd = await realpath(workspace.path);
46
+ if (!contained(rootPath, cwd) || cwd !== resolve(workspace.path))
47
+ fail("工作区不属于当前用户。", 403);
48
+ const handles = [];
49
+ try {
50
+ let root = await directory(rootPath);
51
+ handles.push(root.handle);
52
+ const components = relative(rootPath, cwd).split("/").filter(Boolean);
53
+ for (const component of components) {
54
+ root = await descend(root, component);
55
+ handles.push(root.handle);
56
+ }
57
+ const dsh = await descend(root, ".dsh", true);
58
+ handles.push(dsh.handle);
59
+ const personal = await descend(dsh, "skills", true);
60
+ handles.push(personal.handle);
61
+ const extras = config.extraDefaultSkillDirs ?? [];
62
+ if (!Array.isArray(extras) || extras.length > 15)
63
+ fail("默认技能目录配置无效。");
64
+ const paths = [config.defaultSkillDir, ...extras];
65
+ if (
66
+ paths.some(
67
+ (path) => typeof path !== "string" || !path || path.length > 4096,
68
+ )
69
+ )
70
+ fail("默认技能目录配置无效。");
71
+ const directories = [];
72
+ for (const path of new Set(paths.map((path) => resolve(path)))) {
73
+ const root = await directory(path);
74
+ directories.push(root);
75
+ handles.push(root.handle);
76
+ }
77
+ const defaults = { directories };
78
+ return await run({ personal, defaults });
79
+ } finally {
80
+ await Promise.all(handles.map((handle) => handle.close()));
81
+ }
82
+ }
83
+ export async function readFileSafe(parent, name, limit = LIMITS.file) {
84
+ const handle = await open(
85
+ join(parent.path, name),
86
+ constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,
87
+ );
88
+ try {
89
+ const before = await handle.stat();
90
+ if (!before.isFile() || before.nlink !== 1 || before.size > limit)
91
+ fail("技能文件不是普通文件或体积过大。", 413);
92
+ const bytes = new Uint8Array(before.size + 1);
93
+ const { bytesRead } = await handle.read(bytes, 0, bytes.length, 0),
94
+ after = await handle.stat();
95
+ if (
96
+ bytesRead !== before.size ||
97
+ before.mtimeMs !== after.mtimeMs ||
98
+ before.ino !== after.ino
99
+ )
100
+ fail("文件已变化,请刷新后重试。", 409);
101
+ return bytes.slice(0, bytesRead);
102
+ } finally {
103
+ await handle.close();
104
+ }
105
+ }
106
+ export async function readSkill(root, name, includeFiles = false) {
107
+ skillName(name);
108
+ if (root.directories) {
109
+ const matches = [];
110
+ for (const candidate of root.directories)
111
+ if (await exists(candidate, name)) matches.push(candidate);
112
+ if (!matches.length) fail("默认技能不存在。", 404);
113
+ if (matches.length !== 1) fail("多个默认技能同名,请检查项目配置。", 409);
114
+ return readSkill(matches[0], name, includeFiles);
115
+ }
116
+ const dir = await descend(root, name);
117
+ try {
118
+ const bytes = await readFileSafe(dir, "SKILL.md", LIMITS.markdown),
119
+ raw = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
120
+ const meta = skillDocument(raw);
121
+ if (meta.name !== name) fail("技能目录和 name 不一致。");
122
+ const version = createHash("sha256").update(bytes).digest("hex");
123
+ return {
124
+ ...meta,
125
+ raw,
126
+ version,
127
+ ...(includeFiles ? { files: await collect(dir) } : {}),
128
+ };
129
+ } finally {
130
+ await dir.handle.close();
131
+ }
132
+ }
133
+ async function collect(
134
+ root,
135
+ prefix = "",
136
+ state = { files: Object.create(null), total: 0, count: 0 },
137
+ ) {
138
+ for (const entry of await readdir(root.path, { withFileTypes: true })) {
139
+ const name = entry.name,
140
+ key = prefix + name;
141
+ if (name.startsWith(".") || ++state.count > LIMITS.entries)
142
+ fail("技能包含隐藏文件或过多文件。", 413);
143
+ if (entry.isDirectory()) {
144
+ const child = await descend(root, name);
145
+ try {
146
+ await collect(child, `${key}/`, state);
147
+ } finally {
148
+ await child.handle.close();
149
+ }
150
+ } else {
151
+ if (!entry.isFile()) fail("技能不能包含符号链接或特殊文件。");
152
+ const bytes = await readFileSafe(root, name);
153
+ if ((state.total += bytes.length) > LIMITS.total)
154
+ fail("技能展开体积过大。", 413);
155
+ state.files[key] = bytes;
156
+ }
157
+ }
158
+ return state.files;
159
+ }
160
+ export async function listSkills(roots) {
161
+ const result = [];
162
+ for (const [source, root] of Object.entries(roots)) {
163
+ const directories = root.directories ?? [root];
164
+ const entries = [];
165
+ for (const directory of directories)
166
+ entries.push(
167
+ ...(await readdir(directory.path, { withFileTypes: true })).slice(
168
+ 0,
169
+ 128,
170
+ ),
171
+ );
172
+ const seen = new Set();
173
+ for (const entry of entries) {
174
+ if (!entry.isDirectory() || !/^[a-z0-9-]{1,64}$/.test(entry.name))
175
+ continue;
176
+ if (seen.has(entry.name)) continue;
177
+ seen.add(entry.name);
178
+ try {
179
+ const item = await readSkill(root, entry.name);
180
+ result.push({
181
+ name: item.name,
182
+ description: item.description,
183
+ displayName: item.displayName ?? item.name,
184
+ source,
185
+ readOnly: source === "defaults",
186
+ userInvocable: item.userInvocable,
187
+ });
188
+ } catch {
189
+ /* A broken skill cannot expose another path or stop the catalog. */
190
+ }
191
+ }
192
+ }
193
+ return result.sort((a, b) => a.name.localeCompare(b.name));
194
+ }
195
+ export async function installSkill(roots, bundle) {
196
+ if (
197
+ (await exists(roots.defaults, bundle.name)) ||
198
+ (await exists(roots.personal, bundle.name))
199
+ )
200
+ fail("同名技能已存在,请修改 name 后导入。", 409);
201
+ const finalPath = join(roots.personal.path, bundle.name);
202
+ try {
203
+ await mkdir(finalPath, { mode: 0o700 });
204
+ } catch (error) {
205
+ if (error.code === "EEXIST") fail("同名技能已存在。", 409);
206
+ throw error;
207
+ }
208
+ let completed = false;
209
+ try {
210
+ // SKILL.md is published last, so the native provider never observes a partial bundle.
211
+ const entries = Object.entries(bundle.files).sort(
212
+ ([a], [b]) => (a === "SKILL.md") - (b === "SKILL.md"),
213
+ );
214
+ for (const [name, bytes] of entries) {
215
+ const parts = name.split("/"),
216
+ handles = [];
217
+ let target = await directory(finalPath);
218
+ handles.push(target.handle);
219
+ try {
220
+ for (const part of parts.slice(0, -1)) {
221
+ target = await descend(target, part, true);
222
+ handles.push(target.handle);
223
+ }
224
+ const file = await open(
225
+ join(target.path, parts.at(-1)),
226
+ constants.O_WRONLY |
227
+ constants.O_CREAT |
228
+ constants.O_EXCL |
229
+ constants.O_NOFOLLOW,
230
+ 0o600,
231
+ );
232
+ try {
233
+ await file.writeFile(bytes);
234
+ } finally {
235
+ await file.close();
236
+ }
237
+ } finally {
238
+ await Promise.all(handles.map((handle) => handle.close()));
239
+ }
240
+ }
241
+ completed = true;
242
+ } finally {
243
+ if (!completed) await rm(finalPath, { recursive: true, force: true });
244
+ }
245
+ }
246
+
247
+ export async function updateSkill(root, name, raw, version) {
248
+ const current = await readSkill(root, name);
249
+ if (current.version !== version || skillDocument(raw).name !== name)
250
+ fail("技能已变化或 name 不一致,请刷新后另存。", 409);
251
+ const dir = await descend(root, name),
252
+ temp = `.edit-${randomUUID()}`;
253
+ try {
254
+ const file = await open(
255
+ join(dir.path, temp),
256
+ constants.O_WRONLY |
257
+ constants.O_CREAT |
258
+ constants.O_EXCL |
259
+ constants.O_NOFOLLOW,
260
+ 0o600,
261
+ );
262
+ try {
263
+ await file.writeFile(raw, "utf8");
264
+ } finally {
265
+ await file.close();
266
+ }
267
+ if ((await readSkill(root, name)).version !== version)
268
+ fail("技能已变化,请刷新。", 409);
269
+ await rename(join(dir.path, temp), join(dir.path, "SKILL.md"));
270
+ } finally {
271
+ await rm(join(dir.path, temp), { force: true });
272
+ await dir.handle.close();
273
+ }
274
+ }
275
+ export async function deleteSkill(root, name, version) {
276
+ const current = await readSkill(root, name);
277
+ if (current.version !== version) fail("技能已变化,请刷新。", 409);
278
+ await rm(join(root.path, name), { recursive: true });
279
+ }
280
+ async function exists(root, name) {
281
+ if (root.directories) {
282
+ for (const directory of root.directories)
283
+ if (await exists(directory, name)) return true;
284
+ return false;
285
+ }
286
+ return lstat(join(root.path, name)).then(
287
+ () => true,
288
+ (error) => {
289
+ if (error.code === "ENOENT") return false;
290
+ throw error;
291
+ },
292
+ );
293
+ }