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.
- package/dist/cli.js +855 -560
- package/package.json +1 -1
- package/template/.windy-template.json +2 -2
- package/template/apps/agent-server/Dockerfile +92 -22
- package/template/apps/agent-server/README.md +47 -85
- package/template/apps/agent-server/documents/office.py +216 -0
- package/template/apps/agent-server/documents/query_report.py +136 -0
- package/template/apps/agent-server/documents/smoke.py +177 -0
- package/template/apps/agent-server/documents/test_boundaries.py +185 -0
- package/template/apps/agent-server/host-contracts.ts +56 -0
- package/template/apps/agent-server/install-native.ts +167 -0
- package/template/apps/agent-server/main.ts +179 -0
- package/template/apps/agent-server/native/EXTENSIONS.md +46 -0
- package/template/apps/agent-server/native/admission.ts +73 -0
- package/template/apps/agent-server/native/authorization.test.ts +176 -0
- package/template/apps/agent-server/native/authorization.ts +118 -0
- package/template/apps/agent-server/native/boundary-io.ts +93 -0
- package/template/apps/agent-server/native/boundary-product.ts +107 -0
- package/template/apps/agent-server/native/boundary-project.test.ts +247 -0
- package/template/apps/agent-server/native/boundary-project.ts +188 -0
- package/template/apps/agent-server/native/boundary.ts +188 -0
- package/template/apps/agent-server/native/compaction-policy.test.ts +175 -0
- package/template/apps/agent-server/native/config.ts +95 -0
- package/template/apps/agent-server/native/conversation-instructions.ts +9 -0
- package/template/apps/agent-server/native/extensions.test.ts +190 -0
- package/template/apps/agent-server/native/extensions.ts +31 -0
- package/template/apps/agent-server/native/host-profile.test.ts +91 -0
- package/template/apps/agent-server/native/host-profile.ts +33 -0
- package/template/apps/agent-server/native/host-test-fixture.ts +13 -0
- package/template/apps/agent-server/native/http.ts +129 -0
- package/template/apps/agent-server/native/lifecycle.test.ts +285 -0
- package/template/apps/agent-server/native/lifecycle.ts +136 -0
- package/template/apps/agent-server/native/manager.ts +292 -0
- package/template/apps/agent-server/native/native.test.ts +207 -0
- package/template/apps/agent-server/native/office-preview.test.ts +50 -0
- package/template/apps/agent-server/native/office-preview.ts +25 -0
- package/template/apps/agent-server/native/parallel-harness.ts +242 -0
- package/template/apps/agent-server/native/parallel-mcp-fixture.ts +97 -0
- package/template/apps/agent-server/native/parallel.test.ts +256 -0
- package/template/apps/agent-server/native/profile-composition.test.ts +147 -0
- package/template/apps/agent-server/native/profile.ts +307 -0
- package/template/apps/agent-server/native/request.ts +61 -0
- package/template/apps/agent-server/native/session-conflict.test.ts +235 -0
- package/template/apps/agent-server/native/session-conflict.ts +21 -0
- package/template/apps/agent-server/native/shared-skills.test.ts +128 -0
- package/template/apps/agent-server/native/shared-skills.ts +240 -0
- package/template/apps/agent-server/native/socket-lifecycle.test.ts +48 -0
- package/template/apps/agent-server/native/socket.ts +130 -0
- package/template/apps/agent-server/native/storage-lifecycle.test.ts +217 -0
- package/template/apps/agent-server/native/storage.ts +188 -0
- package/template/apps/agent-server/native/stream-authorization.test.ts +89 -0
- package/template/apps/agent-server/native/worker.ts +77 -0
- package/template/apps/agent-server/native-download.test.ts +119 -0
- package/template/apps/agent-server/native-download.ts +145 -0
- package/template/apps/agent-server/package.json +63 -0
- package/template/apps/agent-server/plugins/access.mjs +126 -0
- package/template/apps/agent-server/plugins/branding/README.md +9 -0
- package/template/apps/agent-server/plugins/branding/brand.css +85 -0
- package/template/apps/agent-server/plugins/branding/client.js +338 -0
- package/template/apps/agent-server/plugins/branding/index.mjs +35 -0
- package/template/apps/agent-server/plugins/branding/loading.d.mts +2 -0
- package/template/apps/agent-server/plugins/branding/loading.mjs +66 -0
- package/template/apps/agent-server/plugins/branding/loading.test.ts +89 -0
- package/template/apps/agent-server/plugins/branding/package.json +21 -0
- package/template/apps/agent-server/plugins/branding.test.ts +294 -0
- package/template/apps/agent-server/plugins/compaction.mjs +83 -0
- package/template/apps/agent-server/plugins/compaction.test.ts +91 -0
- package/template/apps/agent-server/plugins/confine-network.py +57 -0
- package/template/apps/agent-server/plugins/default-skills.test.ts +62 -0
- package/template/apps/agent-server/plugins/downloads/README.md +28 -0
- package/template/apps/agent-server/plugins/downloads/client.js +126 -0
- package/template/apps/agent-server/plugins/downloads/downloads.test.ts +222 -0
- package/template/apps/agent-server/plugins/downloads/index.d.mts +19 -0
- package/template/apps/agent-server/plugins/downloads/index.mjs +180 -0
- package/template/apps/agent-server/plugins/downloads/package.json +20 -0
- package/template/apps/agent-server/plugins/drop-overlay/README.md +24 -0
- package/template/apps/agent-server/plugins/drop-overlay/drop-overlay.test.ts +199 -0
- package/template/apps/agent-server/plugins/drop-overlay/index.d.mts +8 -0
- package/template/apps/agent-server/plugins/drop-overlay/index.mjs +12 -0
- package/template/apps/agent-server/plugins/drop-overlay/style.css +102 -0
- package/template/apps/agent-server/plugins/locale/client.js +61 -0
- package/template/apps/agent-server/plugins/locale/index.d.mts +9 -0
- package/template/apps/agent-server/plugins/locale/index.mjs +16 -0
- package/template/apps/agent-server/plugins/locale/locale.test.ts +217 -0
- package/template/apps/agent-server/plugins/locale/package.json +19 -0
- package/template/apps/agent-server/plugins/parallel.mjs +146 -0
- package/template/apps/agent-server/plugins/preset-registry.d.mts +2 -0
- package/template/apps/agent-server/plugins/preset-registry.mjs +41 -0
- package/template/apps/agent-server/plugins/preset-registry.test.ts +46 -0
- package/template/apps/agent-server/plugins/questions.d.mts +25 -0
- package/template/apps/agent-server/plugins/questions.mjs +142 -0
- package/template/apps/agent-server/plugins/questions.test.ts +105 -0
- package/template/apps/agent-server/plugins/settings/README.md +17 -0
- package/template/apps/agent-server/plugins/settings/client.js +102 -0
- package/template/apps/agent-server/plugins/settings/index.mjs +17 -0
- package/template/apps/agent-server/plugins/settings/package.json +19 -0
- package/template/apps/agent-server/plugins/settings/settings.test.ts +129 -0
- package/template/apps/agent-server/plugins/settings-controller.d.mts +4 -0
- package/template/apps/agent-server/plugins/settings-controller.mjs +31 -0
- package/template/apps/agent-server/plugins/settings-controller.test.ts +17 -0
- package/template/apps/agent-server/plugins/settings-dispatch.test.ts +34 -0
- package/template/apps/agent-server/plugins/shared-skills.d.mts +15 -0
- package/template/apps/agent-server/plugins/shared-skills.mjs +82 -0
- package/template/apps/agent-server/plugins/shared-skills.test.ts +51 -0
- package/template/apps/agent-server/plugins/skill-library/README.md +11 -0
- package/template/apps/agent-server/plugins/skill-library/archive.test.ts +43 -0
- package/template/apps/agent-server/plugins/skill-library/bundle.mjs +234 -0
- package/template/apps/agent-server/plugins/skill-library/client-chunks.test.ts +107 -0
- package/template/apps/agent-server/plugins/skill-library/client-form-mount.test.ts +139 -0
- package/template/apps/agent-server/plugins/skill-library/client-form.test.ts +261 -0
- package/template/apps/agent-server/plugins/skill-library/client-ui.test.ts +268 -0
- package/template/apps/agent-server/plugins/skill-library/client-use.test.ts +158 -0
- package/template/apps/agent-server/plugins/skill-library/client.editor.js +93 -0
- package/template/apps/agent-server/plugins/skill-library/client.form.js +316 -0
- package/template/apps/agent-server/plugins/skill-library/client.js +348 -0
- package/template/apps/agent-server/plugins/skill-library/client.request.js +52 -0
- package/template/apps/agent-server/plugins/skill-library/client.transfer.js +48 -0
- package/template/apps/agent-server/plugins/skill-library/client.use.js +46 -0
- package/template/apps/agent-server/plugins/skill-library/default-roots.test.ts +84 -0
- package/template/apps/agent-server/plugins/skill-library/draft.d.mts +17 -0
- package/template/apps/agent-server/plugins/skill-library/draft.mjs +152 -0
- package/template/apps/agent-server/plugins/skill-library/draft.test.ts +287 -0
- package/template/apps/agent-server/plugins/skill-library/index.d.mts +49 -0
- package/template/apps/agent-server/plugins/skill-library/index.mjs +226 -0
- package/template/apps/agent-server/plugins/skill-library/package.json +24 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/README.md +27 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/UPSTREAM.md +54 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/boot.test.ts +150 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/client.js +146 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/client.test.ts +195 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/index.d.mts +9 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/index.mjs +30 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/metadata.test.ts +82 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/package.json +21 -0
- package/template/apps/agent-server/plugins/skill-library/presentation/react-boot.test.ts +162 -0
- package/template/apps/agent-server/plugins/skill-library/skills.test.ts +342 -0
- package/template/apps/agent-server/plugins/skill-library/storage.mjs +293 -0
- package/template/apps/agent-server/plugins/skill-library/style.css +229 -0
- package/template/apps/agent-server/plugins/skill-library/test-fixture.ts +77 -0
- package/template/apps/agent-server/plugins/skill-library/workflow.d.mts +18 -0
- package/template/apps/agent-server/plugins/skill-library/workflow.mjs +189 -0
- package/template/apps/agent-server/plugins/skill-library/workflow.test.ts +164 -0
- package/template/apps/agent-server/plugins/skills/README.md +5 -0
- package/template/apps/agent-server/plugins/skills/windy-data-summary/SKILL.md +14 -0
- package/template/apps/agent-server/plugins/skills/windy-extension-guide/SKILL.md +14 -0
- package/template/apps/agent-server/plugins/skills/windy-office/SKILL.md +14 -0
- package/template/apps/agent-server/plugins/skills/windy-skill-capture/SKILL.md +14 -0
- package/template/apps/agent-server/plugins/skills/windy-source-compare/SKILL.md +14 -0
- package/template/apps/agent-server/plugins/subprocess.mjs +40 -0
- package/template/apps/agent-server/plugins/theme/README.md +18 -0
- package/template/apps/agent-server/plugins/theme/client.js +18 -0
- package/template/apps/agent-server/plugins/theme/index.d.mts +9 -0
- package/template/apps/agent-server/plugins/theme/index.mjs +18 -0
- package/template/apps/agent-server/plugins/theme/package.json +19 -0
- package/template/apps/agent-server/plugins/theme/source-tokens.ts +82 -0
- package/template/apps/agent-server/plugins/theme/sync-tokens.ts +12 -0
- package/template/apps/agent-server/plugins/theme/theme.test.ts +193 -0
- package/template/apps/agent-server/plugins/theme/tokens.json +166 -0
- package/template/apps/agent-server/plugins/tool-catalog/README.md +79 -0
- package/template/apps/agent-server/plugins/tool-catalog/categories.mjs +111 -0
- package/template/apps/agent-server/plugins/tool-catalog/categories.test.ts +118 -0
- package/template/apps/agent-server/plugins/tool-catalog/client-cache.test.ts +264 -0
- package/template/apps/agent-server/plugins/tool-catalog/client.js +333 -0
- package/template/apps/agent-server/plugins/tool-catalog/client.test.ts +136 -0
- package/template/apps/agent-server/plugins/tool-catalog/discovery.d.mts +42 -0
- package/template/apps/agent-server/plugins/tool-catalog/discovery.mjs +242 -0
- package/template/apps/agent-server/plugins/tool-catalog/discovery.test.ts +229 -0
- package/template/apps/agent-server/plugins/tool-catalog/index.d.mts +5 -0
- package/template/apps/agent-server/plugins/tool-catalog/index.mjs +91 -0
- package/template/apps/agent-server/plugins/tool-catalog/package.json +23 -0
- package/template/apps/agent-server/plugins/tool-catalog/presentation.d.mts +21 -0
- package/template/apps/agent-server/plugins/tool-catalog/presentation.mjs +153 -0
- package/template/apps/agent-server/plugins/tool-catalog/presentation.test.ts +166 -0
- package/template/apps/agent-server/plugins/tool-catalog/routes.test.ts +209 -0
- package/template/apps/agent-server/plugins/tool-catalog/style.css +155 -0
- package/template/apps/agent-server/plugins/tool-catalog/use-tool.test.ts +160 -0
- package/template/apps/agent-server/plugins/tool-presentation/README.md +7 -0
- package/template/apps/agent-server/plugins/tool-presentation/build-client.ts +29 -0
- package/template/apps/agent-server/plugins/tool-presentation/client.js +312 -0
- package/template/apps/agent-server/plugins/tool-presentation/client.results.js +9 -0
- package/template/apps/agent-server/plugins/tool-presentation/client.test.ts +178 -0
- package/template/apps/agent-server/plugins/tool-presentation/index.mjs +10 -0
- package/template/apps/agent-server/plugins/tool-presentation/package.json +24 -0
- package/template/apps/agent-server/plugins/tool-presentation/result-discovery.mjs +43 -0
- package/template/apps/agent-server/plugins/tool-presentation/result-model.d.mts +51 -0
- package/template/apps/agent-server/plugins/tool-presentation/result-model.mjs +96 -0
- package/template/apps/agent-server/plugins/workspace/README.md +5 -0
- package/template/apps/agent-server/plugins/workspace/index.mjs +8 -0
- package/template/apps/agent-server/plugins/workspace/package.json +10 -0
- package/template/apps/agent-server/plugins/workspace/style.css +124 -0
- package/template/apps/agent-server/project/host.ts +13 -0
- package/template/apps/agent-server/runtime/artifacts.ts +115 -0
- package/template/apps/agent-server/runtime/audit.nodecheck.ts +60 -0
- package/template/apps/agent-server/runtime/capacity.ts +61 -0
- package/template/apps/agent-server/runtime/client-completion-budget.nodecheck.ts +92 -0
- package/template/apps/agent-server/runtime/compatibility.ts +33 -0
- package/template/apps/agent-server/runtime/completions.ts +320 -0
- package/template/apps/agent-server/runtime/config.ts +246 -0
- package/template/apps/agent-server/runtime/context-budget.ts +70 -0
- package/template/apps/agent-server/runtime/context-plugin.ts +306 -0
- package/template/apps/agent-server/runtime/context.nodecheck.ts +241 -0
- package/template/apps/agent-server/runtime/contracts.ts +201 -0
- package/template/apps/agent-server/runtime/dsh-engine.ts +196 -0
- package/template/apps/agent-server/runtime/evaluation-plugin.ts +115 -0
- package/template/apps/agent-server/runtime/evaluation.nodecheck.ts +194 -0
- package/template/apps/agent-server/runtime/events.ts +71 -0
- package/template/apps/agent-server/runtime/governance.ts +194 -0
- package/template/apps/agent-server/runtime/index.ts +339 -0
- package/template/apps/agent-server/runtime/internal-output.ts +37 -0
- package/template/apps/agent-server/runtime/isolation.nodecheck.ts +287 -0
- package/template/apps/agent-server/runtime/model-payload.ts +97 -0
- package/template/apps/agent-server/runtime/model-plugin.ts +308 -0
- package/template/apps/agent-server/runtime/model-route.ts +34 -0
- package/template/apps/agent-server/runtime/model-usage.ts +51 -0
- package/template/apps/agent-server/runtime/model-wire.ts +45 -0
- package/template/apps/agent-server/runtime/native-authorization.nodecheck.ts +126 -0
- package/template/apps/agent-server/runtime/native-completion.nodecheck.ts +81 -0
- package/template/apps/agent-server/runtime/output-validation.ts +66 -0
- package/template/apps/agent-server/runtime/production-capacity.nodecheck.ts +121 -0
- package/template/apps/agent-server/runtime/questions-workflow.nodecheck.ts +249 -0
- package/template/apps/agent-server/runtime/report-breakdown.ts +79 -0
- package/template/apps/agent-server/runtime/reporting.ts +219 -0
- package/template/apps/agent-server/runtime/run-completion.ts +39 -0
- package/template/apps/agent-server/runtime/run-request-digest.ts +18 -0
- package/template/apps/agent-server/runtime/runtime-test-fixtures.ts +264 -0
- package/template/apps/agent-server/runtime/runtime.nodecheck.ts +150 -0
- package/template/apps/agent-server/runtime/store-idempotency.nodecheck.ts +74 -0
- package/template/apps/agent-server/runtime/store.ts +324 -0
- package/template/apps/agent-server/runtime/structured-output-mode.nodecheck.ts +51 -0
- package/template/apps/agent-server/runtime/tool-name.ts +6 -0
- package/template/apps/agent-server/runtime/tool-plugin.ts +201 -0
- package/template/apps/agent-server/runtime/vision-readiness.ts +200 -0
- package/template/apps/agent-server/scripts/confinement-check.mjs +103 -0
- package/template/apps/agent-server/scripts/coordinator-check.mjs +344 -0
- package/template/apps/agent-server/scripts/documents-delivery-check.mjs +309 -0
- package/template/apps/agent-server/scripts/office-preview-check.mjs +92 -0
- package/template/apps/agent-server/scripts/test-confinement.ts +58 -0
- package/template/apps/agent-server/scripts/test-coordinator.ts +36 -0
- package/template/apps/agent-server/scripts/test-runtime.ts +46 -0
- package/template/apps/agent-server/tsconfig.json +21 -0
- package/template/apps/server/Dockerfile +3 -0
- package/template/apps/server/package.json +5 -1
- package/template/apps/server/scripts/check-dsh-platform-example.ts +251 -0
- package/template/apps/server/src/agent/admin-catalog-bootstrap.ts +25 -0
- package/template/apps/server/src/agent/agent-session-bootstrap.ts +7 -8
- package/template/apps/server/src/agent/agent-session-facade.ts +12 -0
- package/template/apps/server/src/agent/agent-session-validation.ts +43 -0
- package/template/apps/server/src/agent/dsh-runtime-wire.test.ts +33 -0
- package/template/apps/server/src/agent/governance-runtime.ts +41 -0
- package/template/apps/server/src/agent/operation-catalog.test.ts +202 -0
- package/template/apps/server/src/agent/operation-catalog.ts +135 -0
- package/template/apps/server/src/agent/remote-runtime-response.ts +1 -1
- package/template/apps/server/src/agent/run-browser-visibility.test.ts +59 -0
- package/template/apps/server/src/agent/run-browser-visibility.ts +11 -0
- package/template/apps/server/src/agent/run-contracts.ts +1 -0
- package/template/apps/server/src/agent/run-definition-support.ts +9 -0
- package/template/apps/server/src/agent/run-operation-policy.ts +1 -0
- package/template/apps/server/src/agent/run-route-response.ts +35 -0
- package/template/apps/server/src/agent/run-routes.ts +46 -43
- package/template/apps/server/src/agent/runtime-bootstrap.ts +21 -20
- package/template/apps/server/src/agent/runtime-disabled-composition.ts +28 -0
- package/template/apps/server/src/agent/runtime-tool-composition.ts +2 -0
- package/template/apps/server/src/agent/session-projection-facade.ts +8 -9
- package/template/apps/server/src/agent/session-projection-governance.ts +10 -0
- package/template/apps/server/src/agent/session-projection-view.ts +19 -16
- package/template/apps/server/src/agent/session-recording-reader.contract.test.ts +131 -0
- package/template/apps/server/src/agent/session-recording-reader.ts +62 -0
- package/template/apps/server/src/agent/tool-catalog-audit.ts +22 -0
- package/template/apps/server/src/agent/tool-catalog-availability.ts +21 -0
- package/template/apps/server/src/agent/tool-catalog-routes.test.ts +103 -0
- package/template/apps/server/src/agent/tool-catalog-routes.ts +62 -0
- package/template/apps/server/src/agent/tool-catalog.test.ts +122 -0
- package/template/apps/server/src/agent/tool-catalog.ts +44 -0
- package/template/apps/server/src/agent/tool-registry.ts +45 -14
- package/template/apps/server/src/agent/workbench-bootstrap.ts +39 -0
- package/template/apps/server/src/agent/workbench-event-projection.ts +115 -0
- package/template/apps/server/src/agent/workbench-facade.contract.test.ts +189 -0
- package/template/apps/server/src/agent/workbench-facade.ts +339 -0
- package/template/apps/server/src/agent/workbench-recording.contract.test.ts +328 -0
- package/template/apps/server/src/agent/workbench-routes.ts +97 -0
- package/template/apps/server/src/agent/workbench-run-integration.test.ts +231 -0
- package/template/apps/server/src/agent/workbench-run-reader.ts +187 -0
- package/template/apps/server/src/agent/workbench-safe-result.ts +61 -0
- package/template/apps/server/src/agent/workbench-sse.ts +50 -0
- package/template/apps/server/src/agent/workflow-runtime-bootstrap.ts +9 -0
- package/template/apps/server/src/agent-skills/access.ts +88 -0
- package/template/apps/server/src/agent-skills/bootstrap.ts +49 -0
- package/template/apps/server/src/agent-skills/builtin-registration.ts +83 -0
- package/template/apps/server/src/agent-skills/builtins.ts +19 -0
- package/template/apps/server/src/agent-skills/bundle-zip.ts +163 -0
- package/template/apps/server/src/agent-skills/bundle.test.ts +79 -0
- package/template/apps/server/src/agent-skills/bundle.ts +133 -0
- package/template/apps/server/src/agent-skills/contracts.ts +46 -0
- package/template/apps/server/src/agent-skills/drizzle-repository.ts +125 -0
- package/template/apps/server/src/agent-skills/input.ts +29 -0
- package/template/apps/server/src/agent-skills/postgres.integration.test.ts +348 -0
- package/template/apps/server/src/agent-skills/read-routes.test.ts +116 -0
- package/template/apps/server/src/agent-skills/reader.ts +108 -0
- package/template/apps/server/src/agent-skills/repository.ts +105 -0
- package/template/apps/server/src/agent-skills/routes.ts +176 -0
- package/template/apps/server/src/agent-skills/service.test.ts +295 -0
- package/template/apps/server/src/agent-skills/service.ts +301 -0
- package/template/apps/server/src/agent-workflow/preset-registry.test.ts +137 -0
- package/template/apps/server/src/agent-workflow/preset-registry.ts +191 -0
- package/template/apps/server/src/agent-workflow/preset-routes.test.ts +94 -0
- package/template/apps/server/src/agent-workflow/preset-routes.ts +45 -0
- package/template/apps/server/src/agent-workflow/query-service.ts +36 -0
- package/template/apps/server/src/agent-workflow/recording-projection.contract.test.ts +196 -0
- package/template/apps/server/src/agent-workflow/recording-projection.ts +86 -0
- package/template/apps/server/src/ai-runtime-report/service.test.ts +10 -7
- package/template/apps/server/src/ai-runtime-report/service.ts +1 -1
- package/template/apps/server/src/app/agent-workflow-presets.ts +4 -0
- package/template/apps/server/src/app/dsh-skill-draft-audit.test.ts +195 -0
- package/template/apps/server/src/app/dsh-skill-draft-audit.ts +115 -0
- package/template/apps/server/src/app/dsh-workbench-audit.test.ts +71 -0
- package/template/apps/server/src/app/dsh-workbench-audit.ts +34 -0
- package/template/apps/server/src/app/dsh-workbench-handshake.test.ts +63 -0
- package/template/apps/server/src/app/dsh-workbench-handshake.ts +48 -0
- package/template/apps/server/src/app/dsh-workbench-http.test.ts +96 -0
- package/template/apps/server/src/app/dsh-workbench-lan-origin.test.ts +114 -0
- package/template/apps/server/src/app/dsh-workbench-launch.test.ts +70 -0
- package/template/apps/server/src/app/dsh-workbench-origin.test.ts +54 -0
- package/template/apps/server/src/app/dsh-workbench-proxy.ts +205 -0
- package/template/apps/server/src/app/dsh-workbench-session-conflict.test.ts +61 -0
- package/template/apps/server/src/app/dsh-workbench-session.ts +59 -0
- package/template/apps/server/src/app/dsh-workbench-socket-audit.test.ts +115 -0
- package/template/apps/server/src/app/dsh-workbench-socket.test.ts +246 -0
- package/template/apps/server/src/app/dsh-workbench-socket.ts +272 -0
- package/template/apps/server/src/app/dsh-workbench-test-support.ts +158 -0
- package/template/apps/server/src/app/dsh-workbench.test.ts +213 -0
- package/template/apps/server/src/app/dsh-workbench.ts +279 -0
- package/template/apps/server/src/app/workbench-public-origin.ts +16 -0
- package/template/apps/server/src/data-governance/user-plaintext-routes.test.ts +3 -0
- package/template/apps/server/src/http-app.ts +31 -0
- package/template/apps/server/src/mcp/adapter.ts +1 -0
- package/template/apps/server/src/module-composition.test.ts +23 -0
- package/template/apps/server/src/module-composition.ts +9 -2
- package/template/apps/server/src/observability/bootstrap.ts +12 -0
- package/template/apps/server/src/observability/diagnostic-failure-recorder.ts +94 -0
- package/template/apps/server/src/observability/diagnostic-http-contract.test.ts +42 -0
- package/template/apps/server/src/observability/diagnostic-index.test.ts +89 -0
- package/template/apps/server/src/observability/diagnostic-index.ts +88 -0
- package/template/apps/server/src/observability/diagnostic-repository.ts +67 -0
- package/template/apps/server/src/platform-app-bootstrap.ts +42 -0
- package/template/apps/server/src/platform-http-runtime.ts +6 -0
- package/template/apps/server/src/runtime-development.test.ts +25 -0
- package/template/apps/server/src/runtime-development.ts +6 -44
- package/template/apps/server/src/system/diagnostic-routes.test.ts +78 -0
- package/template/apps/server/src/system/diagnostic-routes.ts +66 -0
- package/template/apps/web/Dockerfile +9 -1
- package/template/apps/web/dev/start.ts +21 -10
- package/template/apps/web/dsh-workbench-location.ts +21 -0
- package/template/apps/web/dsh-workbench-proxy.test.ts +121 -0
- package/template/apps/web/dsh-workbench-proxy.ts +194 -0
- package/template/apps/web/package.json +3 -1
- package/template/apps/web/server.ts +27 -6
- package/template/apps/web/src/composables/useLoginFlow.ts +13 -1
- package/template/apps/web/src/pages/errors/PlatformErrorPage.vue +6 -0
- package/template/apps/web/src/pages/errors/PlatformErrorPage.webtest.ts +14 -1
- package/template/apps/web/src/pages/errors/error-page-extension.ts +1 -0
- package/template/apps/web/src/pages/system/AgentDebugPage.vue +14 -0
- package/template/apps/web/src/pages/system/AgentNativePage.vue +44 -0
- package/template/apps/web/src/pages/system/AgentSessionPage.vue +29 -8
- package/template/apps/web/src/pages/system/AgentToolsPage.vue +76 -0
- package/template/apps/web/src/pages/system/AgentWorkflowPage.vue +20 -7
- package/template/apps/web/src/pages/system/DiagnosticLookupPage.vue +56 -0
- package/template/apps/web/src/pages/system/DiagnosticLookupPage.webtest.ts +99 -0
- package/template/apps/web/src/pages/system/SystemAgentSkillsPage.vue +88 -0
- package/template/apps/web/src/pages/system/components/DiagnosticRecordDetails.vue +52 -0
- package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillDetailDialog.vue +166 -0
- package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillGovernanceActionDialog.vue +51 -0
- package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillImportDialog.vue +320 -0
- package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillImportDialog.webtest.ts +96 -0
- package/template/apps/web/src/pages/system/components/agent-skills/AgentSkillsTable.vue +69 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/AgentWorkbench.vue +236 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/DraftLeaveDialog.vue +34 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/ReplayEventDetail.vue +175 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/SessionReplayTimeline.vue +142 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/SessionReplayTimeline.webtest.ts +242 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/TestRunComposer.vue +97 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/ToolCatalogPanel.vue +100 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/ToolCatalogPanel.webtest.ts +55 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/ToolRuleDetail.vue +81 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/WorkbenchSessionList.vue +57 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/catalog-presenter.ts +20 -0
- package/template/apps/web/src/pages/system/components/agent-workbench/replay-presenter.ts +94 -0
- package/template/apps/web/src/pages/system/components/agent-workflow/WorkflowPresetCatalog.vue +82 -0
- package/template/apps/web/src/pages/system/components/agent-workflow/WorkflowPresetCatalog.webtest.ts +57 -0
- package/template/apps/web/src/pages/system/composables/useAgentSkillsGovernance.ts +105 -0
- package/template/apps/web/src/pages/system/composables/useAgentWorkbench.ts +298 -0
- package/template/apps/web/src/pages/system/composables/useAgentWorkbench.webtest.ts +164 -0
- package/template/apps/web/src/pages/system/composables/useAgentWorkflowPresets.ts +44 -0
- package/template/apps/web/src/pages/system/composables/useDiagnosticLookup.ts +64 -0
- package/template/apps/web/src/pages/system/composables/useSessionReplay.ts +48 -0
- package/template/apps/web/src/router/error-navigation.ts +3 -1
- package/template/apps/web/src/router/error-navigation.webtest.ts +14 -2
- package/template/apps/web/src/router/index.ts +8 -45
- package/template/apps/web/src/router/platform-admin-pages.ts +79 -0
- package/template/apps/web/src/router/platform-admin-route-bindings.ts +12 -0
- package/template/apps/web/src/services/agent-admin-api.ts +155 -0
- package/template/apps/web/src/services/agent-admin-api.webtest.ts +120 -0
- package/template/apps/web/src/services/agent-skills-api.ts +55 -0
- package/template/apps/web/src/services/agent-workbench-event.ts +60 -0
- package/template/apps/web/src/services/agent-workflow-api.ts +12 -0
- package/template/apps/web/src/services/diagnostics-api.ts +12 -0
- package/template/apps/web/src/services/http.ts +18 -0
- package/template/apps/web/src/services/http.webtest.ts +51 -0
- package/template/apps/web/vite.config.ts +39 -0
- package/template/deploy/dsh/README.md +5 -0
- package/template/deploy/dsh/documents/README.md +9 -0
- package/template/deploy/dsh/documents/requirements.in +6 -0
- package/template/deploy/dsh/documents/requirements.lock +72 -0
- package/template/docker-compose.yml +24 -10
- package/template/docs/adr/0004-embedded-dsh-runtime.md +9 -0
- package/template/docs/architecture/agent-admin-workbench-implementation.md +73 -0
- package/template/docs/architecture/agent-admin-workbench-plan.md +41 -0
- package/template/docs/architecture/agent-harness.md +6 -0
- package/template/docs/architecture/agent-runtime-compatibility.md +2 -0
- package/template/docs/architecture/embedded-dsh-integration.md +44 -0
- package/template/docs/development/dsh-plugins.md +55 -0
- package/template/docs/operations/dsh-agent-migration.md +98 -0
- package/template/docs/platform/agent-production-store.md +5 -78
- package/template/docs/platform/agent-runtime-observability.md +2 -0
- package/template/docs/platform/agent-runtime.md +2 -0
- package/template/docs/platform/agent-skills.md +25 -0
- package/template/package.json +4 -3
- package/template/packages/database/drizzle/0064_dsh_skills_diagnostics.sql +42 -0
- package/template/packages/database/drizzle/meta/0064_snapshot.json +15349 -0
- package/template/packages/database/drizzle/meta/_journal.json +7 -0
- package/template/packages/database/package.json +2 -2
- package/template/packages/database/src/schema/agent-skills.ts +65 -0
- package/template/packages/database/src/schema/diagnostics.ts +27 -0
- package/template/packages/database/src/schema/index.ts +8 -0
- package/template/packages/modules/package.json +1 -1
- package/template/packages/modules/src/ai-operation-composition.ts +9 -0
- package/template/packages/modules/src/ai-operation-visibility.test.ts +33 -0
- package/template/packages/modules/src/manifest.ts +2 -0
- package/template/packages/modules/src/system-admin-routes.ts +40 -0
- package/template/packages/modules/src/system-admin-ui-catalog.ts +24 -11
- package/template/packages/modules/src/system-agent-admin-bindings.ts +44 -0
- package/template/packages/modules/src/system-agent-admin-menus.ts +46 -0
- package/template/packages/modules/src/system-agent-admin-registration.test.ts +52 -0
- package/template/packages/modules/src/system-agent-audit-actions.ts +8 -0
- package/template/packages/modules/src/system-agent-dsh.ts +119 -0
- package/template/packages/modules/src/system-ai-api-bindings.ts +2 -0
- package/template/packages/modules/src/system-api-permissions.ts +9 -0
- package/template/packages/modules/src/system-audit-actions.ts +36 -0
- package/template/packages/modules/src/system-features.ts +24 -0
- package/template/packages/modules/src/system-module-audit-selection.ts +25 -0
- package/template/packages/modules/src/system-module-catalog.ts +22 -40
- package/template/packages/modules/src/system-module-ownership.ts +12 -0
- package/template/packages/modules/src/system-modules.ts +16 -3
- package/template/packages/modules/src/system-permissions.ts +15 -0
- package/template/packages/server-sdk/index.ts +2 -0
- package/template/packages/server-sdk/package.json +2 -2
- package/template/packages/server-sdk/src/agent-session-provider.ts +19 -0
- package/template/packages/shared/index.ts +14 -0
- package/template/packages/shared/package.json +1 -1
- package/template/packages/shared/src/agent-admin-catalog.ts +73 -0
- package/template/packages/shared/src/agent-skills.ts +68 -0
- package/template/packages/shared/src/agent-workbench.ts +100 -0
- package/template/packages/shared/src/agent-workflow-presets.ts +26 -0
- package/template/packages/shared/src/diagnostics.ts +13 -0
- package/template/packages/shared/src/rbac.ts +1 -0
- package/template/apps/agent-server/install-python-dependencies.sh +0 -92
- package/template/apps/agent-server/pyproject.toml +0 -51
- package/template/apps/agent-server/src/southwind_agent_server/__init__.py +0 -5
- package/template/apps/agent-server/src/southwind_agent_server/app.py +0 -344
- package/template/apps/agent-server/src/southwind_agent_server/approval_resolution.py +0 -30
- package/template/apps/agent-server/src/southwind_agent_server/artifact_input.py +0 -153
- package/template/apps/agent-server/src/southwind_agent_server/asgi.py +0 -8
- package/template/apps/agent-server/src/southwind_agent_server/attempt_context.py +0 -199
- package/template/apps/agent-server/src/southwind_agent_server/attempt_context_projection.py +0 -203
- package/template/apps/agent-server/src/southwind_agent_server/client_completion_contracts.py +0 -61
- package/template/apps/agent-server/src/southwind_agent_server/client_completion_governance.py +0 -82
- package/template/apps/agent-server/src/southwind_agent_server/client_completion_routes.py +0 -121
- package/template/apps/agent-server/src/southwind_agent_server/client_completion_runtime.py +0 -158
- package/template/apps/agent-server/src/southwind_agent_server/config.py +0 -267
- package/template/apps/agent-server/src/southwind_agent_server/context_message_digest.py +0 -24
- package/template/apps/agent-server/src/southwind_agent_server/context_version_contracts.py +0 -71
- package/template/apps/agent-server/src/southwind_agent_server/context_version_port.py +0 -307
- package/template/apps/agent-server/src/southwind_agent_server/contracts.py +0 -297
- package/template/apps/agent-server/src/southwind_agent_server/deterministic.py +0 -63
- package/template/apps/agent-server/src/southwind_agent_server/engine.py +0 -134
- package/template/apps/agent-server/src/southwind_agent_server/engine_capacity.py +0 -31
- package/template/apps/agent-server/src/southwind_agent_server/engine_identity.py +0 -2
- package/template/apps/agent-server/src/southwind_agent_server/fingerprint.py +0 -61
- package/template/apps/agent-server/src/southwind_agent_server/health_routes.py +0 -93
- package/template/apps/agent-server/src/southwind_agent_server/http_helpers.py +0 -62
- package/template/apps/agent-server/src/southwind_agent_server/lease.py +0 -15
- package/template/apps/agent-server/src/southwind_agent_server/multimodal.py +0 -76
- package/template/apps/agent-server/src/southwind_agent_server/openai_engine.py +0 -329
- package/template/apps/agent-server/src/southwind_agent_server/openai_engine_validation.py +0 -165
- package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +0 -345
- package/template/apps/agent-server/src/southwind_agent_server/postgres_report_insert.py +0 -37
- package/template/apps/agent-server/src/southwind_agent_server/postgres_report_queries.py +0 -235
- package/template/apps/agent-server/src/southwind_agent_server/postgres_report_replay.py +0 -44
- package/template/apps/agent-server/src/southwind_agent_server/postgres_report_status.py +0 -83
- package/template/apps/agent-server/src/southwind_agent_server/postgres_report_store.py +0 -336
- package/template/apps/agent-server/src/southwind_agent_server/postgres_report_summary.py +0 -304
- package/template/apps/agent-server/src/southwind_agent_server/postgres_store.py +0 -335
- package/template/apps/agent-server/src/southwind_agent_server/postgres_store_backend.py +0 -333
- package/template/apps/agent-server/src/southwind_agent_server/provider_audit.py +0 -144
- package/template/apps/agent-server/src/southwind_agent_server/provider_governance.py +0 -309
- package/template/apps/agent-server/src/southwind_agent_server/provider_output_guidance.py +0 -34
- package/template/apps/agent-server/src/southwind_agent_server/readiness_pin.py +0 -37
- package/template/apps/agent-server/src/southwind_agent_server/report_lifecycle.py +0 -218
- package/template/apps/agent-server/src/southwind_agent_server/report_metrics.py +0 -149
- package/template/apps/agent-server/src/southwind_agent_server/report_presenter.py +0 -300
- package/template/apps/agent-server/src/southwind_agent_server/report_routes.py +0 -132
- package/template/apps/agent-server/src/southwind_agent_server/report_store.py +0 -298
- package/template/apps/agent-server/src/southwind_agent_server/report_store_protocol.py +0 -75
- package/template/apps/agent-server/src/southwind_agent_server/report_types.py +0 -118
- package/template/apps/agent-server/src/southwind_agent_server/run_admission.py +0 -64
- package/template/apps/agent-server/src/southwind_agent_server/run_capacity.py +0 -59
- package/template/apps/agent-server/src/southwind_agent_server/runtime_budget.py +0 -74
- package/template/apps/agent-server/src/southwind_agent_server/runtime_compatibility.py +0 -89
- package/template/apps/agent-server/src/southwind_agent_server/runtime_factory.py +0 -105
- package/template/apps/agent-server/src/southwind_agent_server/runtime_logging.py +0 -57
- package/template/apps/agent-server/src/southwind_agent_server/service.py +0 -325
- package/template/apps/agent-server/src/southwind_agent_server/service_control.py +0 -64
- package/template/apps/agent-server/src/southwind_agent_server/service_errors.py +0 -4
- package/template/apps/agent-server/src/southwind_agent_server/service_execution.py +0 -34
- package/template/apps/agent-server/src/southwind_agent_server/service_tasks.py +0 -34
- package/template/apps/agent-server/src/southwind_agent_server/signal_events.py +0 -53
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_catalog.py +0 -118
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_errors.py +0 -2
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_schema.py +0 -73
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_serialization.py +0 -16
- package/template/apps/agent-server/src/southwind_agent_server/sqlite_store.py +0 -350
- package/template/apps/agent-server/src/southwind_agent_server/sse.py +0 -41
- package/template/apps/agent-server/src/southwind_agent_server/store.py +0 -255
- package/template/apps/agent-server/src/southwind_agent_server/store_cipher.py +0 -40
- package/template/apps/agent-server/src/southwind_agent_server/structured_logging.py +0 -145
- package/template/apps/agent-server/src/southwind_agent_server/telemetry.py +0 -93
- package/template/apps/agent-server/src/southwind_agent_server/tool_host.py +0 -152
- package/template/apps/agent-server/src/southwind_agent_server/trajectory.py +0 -137
- package/template/apps/agent-server/src/southwind_agent_server/unavailable_engine.py +0 -58
- package/template/apps/agent-server/src/southwind_agent_server/vision_probe.py +0 -87
- package/template/apps/agent-server/src/southwind_agent_server/vision_requirement.py +0 -28
- package/template/apps/agent-server/src/southwind_agent_server/vlm_readiness.py +0 -247
- package/template/apps/agent-server/tests/__init__.py +0 -1
- package/template/apps/agent-server/tests/openai_provider_test_support.py +0 -131
- package/template/apps/agent-server/tests/test_api.py +0 -305
- package/template/apps/agent-server/tests/test_artifact_input.py +0 -110
- package/template/apps/agent-server/tests/test_client_completion.py +0 -230
- package/template/apps/agent-server/tests/test_config.py +0 -106
- package/template/apps/agent-server/tests/test_fingerprint.py +0 -10
- package/template/apps/agent-server/tests/test_multimodal.py +0 -81
- package/template/apps/agent-server/tests/test_openai_provider.py +0 -320
- package/template/apps/agent-server/tests/test_postgres_report_status.py +0 -59
- package/template/apps/agent-server/tests/test_postgres_report_summary.py +0 -298
- package/template/apps/agent-server/tests/test_postgres_store.py +0 -135
- package/template/apps/agent-server/tests/test_provider_attempt_reporting.py +0 -140
- package/template/apps/agent-server/tests/test_provider_governance.py +0 -276
- package/template/apps/agent-server/tests/test_report_attempt_lifecycle.py +0 -126
- package/template/apps/agent-server/tests/test_report_resilience.py +0 -183
- package/template/apps/agent-server/tests/test_report_routes.py +0 -143
- package/template/apps/agent-server/tests/test_report_store.py +0 -347
- package/template/apps/agent-server/tests/test_report_summary_parity.py +0 -116
- package/template/apps/agent-server/tests/test_report_terminal_sync.py +0 -177
- package/template/apps/agent-server/tests/test_run_capacity.py +0 -112
- package/template/apps/agent-server/tests/test_run_operational_logging.py +0 -114
- package/template/apps/agent-server/tests/test_runtime_compatibility.py +0 -119
- package/template/apps/agent-server/tests/test_runtime_factory_readiness.py +0 -52
- package/template/apps/agent-server/tests/test_sqlite_store.py +0 -182
- package/template/apps/agent-server/tests/test_structured_logging.py +0 -142
- package/template/apps/agent-server/tests/test_telemetry.py +0 -25
- package/template/apps/agent-server/tests/test_tool_approval.py +0 -28
- package/template/apps/agent-server/tests/test_tool_structured_output.py +0 -347
- package/template/apps/agent-server/tests/test_trajectory.py +0 -91
- package/template/apps/agent-server/tests/test_vision_readiness_enforcement.py +0 -72
- package/template/apps/agent-server/tests/test_vlm_readiness.py +0 -106
- package/template/apps/agent-server/uv.lock +0 -831
package/package.json
CHANGED
|
@@ -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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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))
|