@mseep/open-computer-use 1.0.0
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/.coderabbit.yaml +25 -0
- package/.dockerignore +95 -0
- package/.env.example +137 -0
- package/.githooks/pre-commit +68 -0
- package/.github/CODEOWNERS +125 -0
- package/.github/ISSUE_TEMPLATE/adr-proposal.md +41 -0
- package/.github/ISSUE_TEMPLATE/bug-report.md +49 -0
- package/.github/ISSUE_TEMPLATE/component-proposal.md +38 -0
- package/.github/ISSUE_TEMPLATE/config.yml +15 -0
- package/.github/ISSUE_TEMPLATE/dependency-proposal.md +59 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
- package/.github/ISSUE_TEMPLATE/nfr-proposal.md +44 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- package/.github/codeql/codeql-config.yml +11 -0
- package/.github/codeql/extensions/security-models/python-sanitizers.model.yml +17 -0
- package/.github/codeql/extensions/security-models/qlpack.yml +7 -0
- package/.github/dependabot.yml +23 -0
- package/.github/security-exceptions.yml +23 -0
- package/.github/workflows/build.yml +420 -0
- package/.github/workflows/codeql.yml +33 -0
- package/.github/workflows/contracts-lint.yml +90 -0
- package/.github/workflows/docs-lint.yml +151 -0
- package/.github/workflows/helm.yml +131 -0
- package/.github/workflows/identity-lint.yml +30 -0
- package/.github/workflows/release-chart.yml +177 -0
- package/.github/workflows/release.yml +95 -0
- package/.github/workflows/security.yml +332 -0
- package/.github/workflows/stale.yml +31 -0
- package/.github/workflows/supply-chain.yml +242 -0
- package/.gitleaks.toml +53 -0
- package/.markdownlint.yaml +51 -0
- package/.semgrepignore +85 -0
- package/.vale/styles/Architecture/ap13-data-class-substrate.yml +12 -0
- package/.vale/styles/Architecture/banned-phrases.yml +23 -0
- package/.vale/styles/Architecture/banned-vocab.yml +23 -0
- package/.vale/styles/Architecture/marketing-tone.yml +19 -0
- package/.vale.ini +18 -0
- package/CHANGELOG.md +411 -0
- package/CLAUDE.md +218 -0
- package/CONTRIBUTING.md +82 -0
- package/Dockerfile +676 -0
- package/LICENSE +98 -0
- package/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +21 -0
- package/NOTICE +36 -0
- package/README.md +516 -0
- package/SECURITY.md +45 -0
- package/THIRD-PARTY-LICENSES.md +14 -0
- package/apt-packages.txt +108 -0
- package/computer-use-server/.dockerignore +13 -0
- package/computer-use-server/Dockerfile +44 -0
- package/computer-use-server/README.md +84 -0
- package/computer-use-server/app.py +1544 -0
- package/computer-use-server/bin/list-subagent-models +449 -0
- package/computer-use-server/cli-defaults/README.md +31 -0
- package/computer-use-server/cli-defaults/codex.json +7 -0
- package/computer-use-server/cli-defaults/opencode.json +18 -0
- package/computer-use-server/cli_adapters/__init__.py +46 -0
- package/computer-use-server/cli_adapters/claude.py +163 -0
- package/computer-use-server/cli_adapters/codex.py +163 -0
- package/computer-use-server/cli_adapters/opencode.py +169 -0
- package/computer-use-server/cli_adapters/result.py +34 -0
- package/computer-use-server/cli_runtime.py +316 -0
- package/computer-use-server/context_vars.py +24 -0
- package/computer-use-server/docker_manager.py +1100 -0
- package/computer-use-server/docs_html.py +12 -0
- package/computer-use-server/mcp_resources.py +170 -0
- package/computer-use-server/mcp_tools.py +1430 -0
- package/computer-use-server/requirements.txt +17 -0
- package/computer-use-server/security.py +50 -0
- package/computer-use-server/skill_manager.py +664 -0
- package/computer-use-server/static/browser-viewer.js +445 -0
- package/computer-use-server/static/chart.umd.js +14 -0
- package/computer-use-server/static/docs.html +203 -0
- package/computer-use-server/static/github-dark.min.css +10 -0
- package/computer-use-server/static/github.min.css +10 -0
- package/computer-use-server/static/highlight.min.js +1213 -0
- package/computer-use-server/static/highlightjs-line-numbers.min.js +1 -0
- package/computer-use-server/static/icons.js +74 -0
- package/computer-use-server/static/jszip.min.js +13 -0
- package/computer-use-server/static/katex/auto-render.min.js +1 -0
- package/computer-use-server/static/katex/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-Bold.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-Italic.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Math-Italic.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Script-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/computer-use-server/static/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/computer-use-server/static/katex/katex.min.css +1 -0
- package/computer-use-server/static/katex/katex.min.js +1 -0
- package/computer-use-server/static/locale.js +242 -0
- package/computer-use-server/static/mammoth.browser.min.js +21 -0
- package/computer-use-server/static/marked.min.js +6 -0
- package/computer-use-server/static/mermaid.min.js +2811 -0
- package/computer-use-server/static/pdf.min.js +22 -0
- package/computer-use-server/static/pdf.worker.min.js +22 -0
- package/computer-use-server/static/pptxviewjs.min.js +1 -0
- package/computer-use-server/static/preact-htm.min.js +1 -0
- package/computer-use-server/static/preview.css +1030 -0
- package/computer-use-server/static/preview.js +1522 -0
- package/computer-use-server/static/xlsx.full.min.js +22 -0
- package/computer-use-server/static/xterm-addon-fit.min.js +2 -0
- package/computer-use-server/static/xterm-addon-web-links.min.js +2 -0
- package/computer-use-server/static/xterm.css +218 -0
- package/computer-use-server/static/xterm.min.js +2 -0
- package/computer-use-server/system_prompt.py +761 -0
- package/computer-use-server/uploads.py +82 -0
- package/contracts/README.md +53 -0
- package/contracts/audit/audit-fanin.asyncapi.yaml +407 -0
- package/contracts/exec/exec-channel.schema.json +240 -0
- package/contracts/mcp/2025-06-18/ocu-constraints.schema.json +178 -0
- package/contracts/storage/file-artifact-api.schema.json +390 -0
- package/contracts/storage/file-ops.schema.json +217 -0
- package/contracts/storage/mount-config.schema.json +197 -0
- package/cron/Dockerfile +15 -0
- package/cron/cleanup-quick.sh +21 -0
- package/cron/cleanup.sh +127 -0
- package/data/outputs/.gitkeep +0 -0
- package/data/uploads/.gitkeep +0 -0
- package/docker-compose.test.yml +54 -0
- package/docker-compose.webui.yml +77 -0
- package/docker-compose.yml +96 -0
- package/docs/CLOUD.md +29 -0
- package/docs/COMPARISON.md +128 -0
- package/docs/DOCKER.md +469 -0
- package/docs/DYNAMIC-SKILLS.md +77 -0
- package/docs/FEATURES.md +100 -0
- package/docs/INSTALL.md +111 -0
- package/docs/KNOWN-BUGS.md +86 -0
- package/docs/MCP.md +320 -0
- package/docs/SCREENSHOTS.md +39 -0
- package/docs/SKILLS-USER-GUIDE.md +86 -0
- package/docs/SKILLS.md +483 -0
- package/docs/TERMINAL-TAB.md +56 -0
- package/docs/architecture/02-trust-boundaries.md +224 -0
- package/docs/architecture/03-c4-context.md +61 -0
- package/docs/architecture/04-bounded-contexts.md +119 -0
- package/docs/architecture/05-c4-container.md +88 -0
- package/docs/architecture/06-threat-model.md +172 -0
- package/docs/architecture/08-contracts.md +105 -0
- package/docs/architecture/MANIFESTO.md +38 -0
- package/docs/architecture/PROCESS.md +64 -0
- package/docs/architecture/README.md +37 -0
- package/docs/architecture/adr/0000-template.md +65 -0
- package/docs/architecture/adr/0001-layer-0-gate-legacy-exclusion.md +75 -0
- package/docs/architecture/adr/0002-session-view-descriptor.md +57 -0
- package/docs/architecture/adr/0003-sandbox-runtime-tier-ladder.md +63 -0
- package/docs/architecture/adr/0004-operator-authentication-substrate.md +63 -0
- package/docs/architecture/adr/0005-egress-credential-delivery-envoy-sds.md +62 -0
- package/docs/architecture/adr/0006-egress-forward-proxy-substrate.md +65 -0
- package/docs/architecture/adr/0007-egress-auth-mechanism.md +72 -0
- package/docs/architecture/adr/0008-session-egress-attribution.md +59 -0
- package/docs/architecture/adr/0009-audit-pipeline-pluggable-by-contract.md +76 -0
- package/docs/architecture/adr/0010-storage-backend-pluggable-adapter.md +60 -0
- package/docs/architecture/adr/0011-storage-egress-lane.md +67 -0
- package/docs/architecture/adr/0012-implementation-language.md +67 -0
- package/docs/architecture/adr/0020-sandbox-image-provisioning.md +82 -0
- package/docs/architecture/adr/README.md +53 -0
- package/docs/architecture/compliance/.gitkeep +0 -0
- package/docs/architecture/components/00-overview.md +42 -0
- package/docs/architecture/components/0000-template.md +50 -0
- package/docs/architecture/components/01-mcp-gateway.md +80 -0
- package/docs/architecture/components/02-control-operator-api.md +80 -0
- package/docs/architecture/components/04-storage-broker.md +104 -0
- package/docs/architecture/components/05-session-sandbox.md +93 -0
- package/docs/architecture/components/06-egress-trust-edge.md +95 -0
- package/docs/architecture/components/07-audit-pipeline.md +110 -0
- package/docs/architecture/diagrams/.gitkeep +0 -0
- package/docs/architecture/diagrams/02-trust-boundaries.mmd +111 -0
- package/docs/architecture/diagrams/06-threat-model.mmd +41 -0
- package/docs/architecture/diagrams/08-contracts.mmd +47 -0
- package/docs/architecture/diagrams/c4-container.mmd +59 -0
- package/docs/architecture/diagrams/c4-context.mmd +46 -0
- package/docs/architecture/glossary.md +172 -0
- package/docs/architecture/manifesto/.gitkeep +0 -0
- package/docs/architecture/manifesto/01-audience-and-buyer.md +57 -0
- package/docs/architecture/manifesto/02-nfrs.md +325 -0
- package/docs/architecture/manifesto/03-non-negotiables.md +35 -0
- package/docs/architecture/manifesto/04-non-goals.md +23 -0
- package/docs/architecture/manifesto/05-licensing-posture.md +61 -0
- package/docs/architecture/manifesto/06-starter-mode-policy.md +49 -0
- package/docs/architecture/manifesto/07-governance.md +60 -0
- package/docs/architecture/primitives-backlog.md +51 -0
- package/docs/architecture.svg +117 -0
- package/docs/claude-code-gateway.md +173 -0
- package/docs/cli-config-templates.md +240 -0
- package/docs/data-flow.svg +72 -0
- package/docs/demo-landing-page.gif +0 -0
- package/docs/demo-qwen-trending.gif +0 -0
- package/docs/dynamic-skills.svg +77 -0
- package/docs/file-flow.svg +126 -0
- package/docs/future-architecture/README.md +152 -0
- package/docs/future-architecture/adr/0001-control-plane-language-go.md +80 -0
- package/docs/future-architecture/adr/0002-guest-agent-language-go.md +84 -0
- package/docs/future-architecture/adr/0003-docker-poc-first-then-k8s.md +37 -0
- package/docs/future-architecture/adr/0004-pluggable-runtime-via-runtimeclass.md +34 -0
- package/docs/future-architecture/adr/0005-mcp-as-control-plane-gateway.md +34 -0
- package/docs/future-architecture/adr/0006-no-agpl-no-bsl-dependencies.md +41 -0
- package/docs/future-architecture/adr/0007-superseded-by-future-architecture.md +37 -0
- package/docs/future-architecture/adr/0008-internal-grpc-external-rest-mcp.md +106 -0
- package/docs/future-architecture/adr/0009-external-protocol-dialects.md +94 -0
- package/docs/future-architecture/adr/0010-lambda-as-inspiration-not-runtime.md +86 -0
- package/docs/future-architecture/adr/0011-kata-as-first-class-dind-runtime.md +84 -0
- package/docs/future-architecture/antipatterns.md +552 -0
- package/docs/future-architecture/architecture/01-layers.md +109 -0
- package/docs/future-architecture/architecture/02-layer4-control-plane.md +122 -0
- package/docs/future-architecture/architecture/03-layer3-providers.md +174 -0
- package/docs/future-architecture/architecture/04-layer2-runtimes.md +114 -0
- package/docs/future-architecture/architecture/04b-credential-broker.md +153 -0
- package/docs/future-architecture/architecture/05-layer1-guest-agent.md +138 -0
- package/docs/future-architecture/architecture/06-storage.md +134 -0
- package/docs/future-architecture/architecture/07-security.md +194 -0
- package/docs/future-architecture/architecture/08-networking.md +149 -0
- package/docs/future-architecture/architecture/09-templates.md +122 -0
- package/docs/future-architecture/architecture/10-observability.md +121 -0
- package/docs/future-architecture/design-notes.md +72 -0
- package/docs/future-architecture/gaps.md +281 -0
- package/docs/future-architecture/phase-template.md +123 -0
- package/docs/future-architecture/references.md +225 -0
- package/docs/future-architecture/research/01-kata-containers.md +100 -0
- package/docs/future-architecture/research/02-e2b-infra.md +133 -0
- package/docs/future-architecture/research/03-coder.md +115 -0
- package/docs/future-architecture/research/04-cloud-hypervisor.md +99 -0
- package/docs/future-architecture/research/05-firecracker.md +114 -0
- package/docs/future-architecture/research/06-agent-sandbox.md +142 -0
- package/docs/future-architecture/research/07-chromedp.md +78 -0
- package/docs/future-architecture/research/08-microsandbox.md +78 -0
- package/docs/future-architecture/research/09-agentbox.md +135 -0
- package/docs/future-architecture/research/10-sysbox.md +100 -0
- package/docs/future-architecture/research/11-firecracker-containerd.md +93 -0
- package/docs/future-architecture/research/12-docker-socket-proxy.md +59 -0
- package/docs/future-architecture/research/14-e2b-desktop-and-surf.md +107 -0
- package/docs/future-architecture/research/18-open-webui-terminals-observed.md +135 -0
- package/docs/future-architecture/research/bank-buyer.md +96 -0
- package/docs/future-architecture/research/enthusiast-audience.md +106 -0
- package/docs/future-architecture/research/proof-uipath-anthropic-2026-05.md +76 -0
- package/docs/future-architecture/research/widemoat-thesis-advisor.md +124 -0
- package/docs/future-architecture/roadmap.md +438 -0
- package/docs/kata-runtime.md +267 -0
- package/docs/kubernetes.md +86 -0
- package/docs/logo.png +0 -0
- package/docs/multi-cli.md +161 -0
- package/docs/openwebui-filter.md +134 -0
- package/docs/roadmap/implementation-roadmap.md +104 -0
- package/docs/sandbox-contents.svg +229 -0
- package/docs/screenshots/01-create-document.png +0 -0
- package/docs/screenshots/02-file-preview.png +0 -0
- package/docs/screenshots/03-browser-viewer.png +0 -0
- package/docs/screenshots/04-sub-agent-terminal.png +0 -0
- package/docs/screenshots/05-chat-overview.png +0 -0
- package/docs/screenshots/06-sub-agent-dashboard.png +0 -0
- package/docs/screenshots/07-frontend-design-skill.png +0 -0
- package/docs/screenshots/08-pptx-skill.png +0 -0
- package/docs/screenshots/09-skill-creator.png +0 -0
- package/docs/screenshots/10-data-chart.png +0 -0
- package/docs/shared-browser.svg +102 -0
- package/docs/system-prompt.md +113 -0
- package/docs/terminal-flow.svg +69 -0
- package/examples/helm/README.md +20 -0
- package/examples/helm/standalone/values.yaml +49 -0
- package/examples/helm/with-open-webui/README.md +99 -0
- package/examples/helm/with-open-webui/values-computer-use.yaml +32 -0
- package/examples/helm/with-open-webui/values-open-webui.yaml +67 -0
- package/fonts/NotoEmoji-Regular.ttf +0 -0
- package/helm/computer-use-server/.helmignore +17 -0
- package/helm/computer-use-server/Chart.yaml +32 -0
- package/helm/computer-use-server/README.md +211 -0
- package/helm/computer-use-server/templates/NOTES.txt +66 -0
- package/helm/computer-use-server/templates/_helpers.tpl +115 -0
- package/helm/computer-use-server/templates/configmap-dind-init.yaml +82 -0
- package/helm/computer-use-server/templates/configmap.yaml +18 -0
- package/helm/computer-use-server/templates/deployment.yaml +248 -0
- package/helm/computer-use-server/templates/ingress.yaml +38 -0
- package/helm/computer-use-server/templates/networkpolicy.yaml +50 -0
- package/helm/computer-use-server/templates/pdb.yaml +16 -0
- package/helm/computer-use-server/templates/pvc-data.yaml +20 -0
- package/helm/computer-use-server/templates/pvc-skills-cache.yaml +20 -0
- package/helm/computer-use-server/templates/pvc-user-data.yaml +20 -0
- package/helm/computer-use-server/templates/pvc-var-lib-docker.yaml +27 -0
- package/helm/computer-use-server/templates/secret.yaml +23 -0
- package/helm/computer-use-server/templates/service.yaml +22 -0
- package/helm/computer-use-server/templates/serviceaccount.yaml +15 -0
- package/helm/computer-use-server/templates/tests/test-health.yaml +23 -0
- package/helm/computer-use-server/values.schema.json +183 -0
- package/helm/computer-use-server/values.yaml +297 -0
- package/lychee.toml +36 -0
- package/openwebui/Dockerfile +52 -0
- package/openwebui/README.md +38 -0
- package/openwebui/functions/README.md +48 -0
- package/openwebui/functions/computer_link_filter.py +487 -0
- package/openwebui/init.sh +305 -0
- package/openwebui/patches/README.md +44 -0
- package/openwebui/patches/fix_artifacts_auto_show.py +441 -0
- package/openwebui/patches/fix_attached_files_position.py +87 -0
- package/openwebui/patches/fix_large_tool_args.py +156 -0
- package/openwebui/patches/fix_large_tool_results.py +289 -0
- package/openwebui/patches/fix_preview_url_detection.py +230 -0
- package/openwebui/patches/fix_skip_embedding_chat_files.py +229 -0
- package/openwebui/patches/fix_skip_rag_files_native_fc.py +100 -0
- package/openwebui/patches/fix_tool_loop_errors.py +510 -0
- package/package.json +39 -0
- package/requirements.txt +112 -0
- package/scripts/check-config.sh +141 -0
- package/scripts/docs-lint/ai-slop-detector.sh +202 -0
- package/scripts/docs-lint/architecture-tree-whitelist.sh +131 -0
- package/scripts/docs-lint/ascii-diagram-detector.sh +58 -0
- package/scripts/docs-lint/front-matter-validator.sh +97 -0
- package/scripts/docs-lint/gitignored-ref-detector.sh +122 -0
- package/scripts/docs-lint/identity-email-detector.sh +48 -0
- package/scripts/docs-lint/test-linters.sh +354 -0
- package/scripts/docs-lint/wc-budget.sh +61 -0
- package/scripts/githooks/pre-push +75 -0
- package/server.json +13 -0
- package/settings-wrapper/Dockerfile +9 -0
- package/settings-wrapper/README.md +119 -0
- package/settings-wrapper/app.py +113 -0
- package/settings-wrapper/requirements.txt +2 -0
- package/settings-wrapper/skills.json +25 -0
- package/skills/README.md +46 -0
- package/skills/examples/algorithmic-art/SKILL.md +405 -0
- package/skills/examples/algorithmic-art/templates/generator_template.js +223 -0
- package/skills/examples/algorithmic-art/templates/viewer.html +601 -0
- package/skills/examples/artifacts-builder/SKILL.md +74 -0
- package/skills/examples/artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/skills/examples/artifacts-builder/scripts/init-artifact.sh +322 -0
- package/skills/examples/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/skills/examples/canvas-design/LICENSE.txt +202 -0
- package/skills/examples/canvas-design/SKILL.md +130 -0
- package/skills/examples/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/skills/examples/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/skills/examples/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/skills/examples/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/skills/examples/copy-editing/SKILL.md +447 -0
- package/skills/examples/copy-editing/evals/evals.json +89 -0
- package/skills/examples/copy-editing/references/plain-english-alternatives.md +394 -0
- package/skills/examples/internal-comms/LICENSE.txt +202 -0
- package/skills/examples/internal-comms/SKILL.md +32 -0
- package/skills/examples/internal-comms/examples/3p-updates.md +47 -0
- package/skills/examples/internal-comms/examples/company-newsletter.md +65 -0
- package/skills/examples/internal-comms/examples/faq-answers.md +30 -0
- package/skills/examples/internal-comms/examples/general-comms.md +16 -0
- package/skills/examples/mcp-builder/SKILL.md +328 -0
- package/skills/examples/mcp-builder/reference/evaluation.md +602 -0
- package/skills/examples/mcp-builder/reference/mcp_best_practices.md +915 -0
- package/skills/examples/mcp-builder/reference/node_mcp_server.md +916 -0
- package/skills/examples/mcp-builder/reference/python_mcp_server.md +752 -0
- package/skills/examples/mcp-builder/scripts/connections.py +151 -0
- package/skills/examples/mcp-builder/scripts/evaluation.py +373 -0
- package/skills/examples/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/skills/examples/mcp-builder/scripts/requirements.txt +2 -0
- package/skills/examples/product-marketing-context/SKILL.md +241 -0
- package/skills/examples/product-marketing-context/evals/evals.json +85 -0
- package/skills/examples/single-cell-rna-qc/SKILL.md +175 -0
- package/skills/examples/single-cell-rna-qc/references/scverse_qc_guidelines.md +186 -0
- package/skills/examples/single-cell-rna-qc/scripts/qc_analysis.py +232 -0
- package/skills/examples/single-cell-rna-qc/scripts/qc_core.py +233 -0
- package/skills/examples/single-cell-rna-qc/scripts/qc_plotting.py +235 -0
- package/skills/examples/skill-creator/SKILL.md +355 -0
- package/skills/examples/skill-creator/references/output-patterns.md +82 -0
- package/skills/examples/skill-creator/references/workflows.md +28 -0
- package/skills/examples/skill-creator/scripts/init_skill.py +303 -0
- package/skills/examples/skill-creator/scripts/package_skill.py +110 -0
- package/skills/examples/skill-creator/scripts/quick_validate.py +95 -0
- package/skills/examples/slack-gif-creator/SKILL.md +254 -0
- package/skills/examples/slack-gif-creator/core/easing.py +234 -0
- package/skills/examples/slack-gif-creator/core/frame_composer.py +176 -0
- package/skills/examples/slack-gif-creator/core/gif_builder.py +269 -0
- package/skills/examples/slack-gif-creator/core/validators.py +136 -0
- package/skills/examples/slack-gif-creator/requirements.txt +4 -0
- package/skills/examples/social-content/SKILL.md +278 -0
- package/skills/examples/social-content/evals/evals.json +92 -0
- package/skills/examples/social-content/references/platforms.md +170 -0
- package/skills/examples/social-content/references/post-templates.md +177 -0
- package/skills/examples/social-content/references/reverse-engineering.md +195 -0
- package/skills/examples/theme-factory/SKILL.md +59 -0
- package/skills/examples/theme-factory/theme-showcase.pdf +0 -0
- package/skills/examples/theme-factory/themes/arctic-frost.md +19 -0
- package/skills/examples/theme-factory/themes/botanical-garden.md +19 -0
- package/skills/examples/theme-factory/themes/desert-rose.md +19 -0
- package/skills/examples/theme-factory/themes/forest-canopy.md +19 -0
- package/skills/examples/theme-factory/themes/golden-hour.md +19 -0
- package/skills/examples/theme-factory/themes/midnight-galaxy.md +19 -0
- package/skills/examples/theme-factory/themes/modern-minimalist.md +19 -0
- package/skills/examples/theme-factory/themes/ocean-depths.md +19 -0
- package/skills/examples/theme-factory/themes/sunset-boulevard.md +19 -0
- package/skills/examples/theme-factory/themes/tech-innovation.md +19 -0
- package/skills/examples/web-artifacts-builder/LICENSE.txt +202 -0
- package/skills/examples/web-artifacts-builder/SKILL.md +74 -0
- package/skills/examples/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/skills/examples/web-artifacts-builder/scripts/init-artifact.sh +322 -0
- package/skills/examples/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/skills/examples/writing-skills/SKILL.md +655 -0
- package/skills/examples/writing-skills/anthropic-best-practices.md +1150 -0
- package/skills/examples/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/skills/examples/writing-skills/graphviz-conventions.dot +172 -0
- package/skills/examples/writing-skills/persuasion-principles.md +187 -0
- package/skills/examples/writing-skills/render-graphs.js +168 -0
- package/skills/examples/writing-skills/testing-skills-with-subagents.md +384 -0
- package/skills/public/describe-image/SKILL.md +105 -0
- package/skills/public/describe-image/scripts/describe.py +389 -0
- package/skills/public/doc-coauthoring/SKILL.md +375 -0
- package/skills/public/docx/LICENSE.txt +30 -0
- package/skills/public/docx/SKILL.md +199 -0
- package/skills/public/docx/docx-js.md +350 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/public/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/public/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/public/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/public/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/public/docx/ooxml/schemas/mce/mc.xsd +75 -0
- package/skills/public/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/public/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/public/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/public/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/public/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/public/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/public/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/public/docx/ooxml/scripts/pack.py +159 -0
- package/skills/public/docx/ooxml/scripts/unpack.py +29 -0
- package/skills/public/docx/ooxml/scripts/validate.py +69 -0
- package/skills/public/docx/ooxml/scripts/validation/__init__.py +15 -0
- package/skills/public/docx/ooxml/scripts/validation/base.py +951 -0
- package/skills/public/docx/ooxml/scripts/validation/docx.py +274 -0
- package/skills/public/docx/ooxml/scripts/validation/pptx.py +315 -0
- package/skills/public/docx/ooxml/scripts/validation/redlining.py +279 -0
- package/skills/public/docx/ooxml.md +632 -0
- package/skills/public/docx/scripts/__init__.py +1 -0
- package/skills/public/docx/scripts/document.py +1292 -0
- package/skills/public/docx/scripts/templates/comments.xml +3 -0
- package/skills/public/docx/scripts/templates/commentsExtended.xml +3 -0
- package/skills/public/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/skills/public/docx/scripts/templates/commentsIds.xml +3 -0
- package/skills/public/docx/scripts/templates/people.xml +3 -0
- package/skills/public/docx/scripts/utilities.py +374 -0
- package/skills/public/file-reading/LICENSE.txt +30 -0
- package/skills/public/file-reading/SKILL.md +350 -0
- package/skills/public/frontend-design/LICENSE.txt +177 -0
- package/skills/public/frontend-design/SKILL.md +42 -0
- package/skills/public/gitlab-explorer/SKILL.md +174 -0
- package/skills/public/gitlab-explorer/references/git-commands.md +323 -0
- package/skills/public/gitlab-explorer/references/glab-commands.md +282 -0
- package/skills/public/gitlab-explorer/scripts/check_gitlab_auth.sh +109 -0
- package/skills/public/pdf/FORMS.md +205 -0
- package/skills/public/pdf/REFERENCE.md +612 -0
- package/skills/public/pdf/SKILL.md +364 -0
- package/skills/public/pdf/scripts/check_bounding_boxes.py +70 -0
- package/skills/public/pdf/scripts/check_bounding_boxes_test.py +226 -0
- package/skills/public/pdf/scripts/check_fillable_fields.py +12 -0
- package/skills/public/pdf/scripts/convert_pdf_to_images.py +35 -0
- package/skills/public/pdf/scripts/create_validation_image.py +41 -0
- package/skills/public/pdf/scripts/extract_form_field_info.py +152 -0
- package/skills/public/pdf/scripts/fill_fillable_fields.py +114 -0
- package/skills/public/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/skills/public/pdf-reading/LICENSE.txt +30 -0
- package/skills/public/pdf-reading/REFERENCE.md +196 -0
- package/skills/public/pdf-reading/SKILL.md +305 -0
- package/skills/public/playwright-cli/SKILL.md +278 -0
- package/skills/public/playwright-cli/references/request-mocking.md +87 -0
- package/skills/public/playwright-cli/references/running-code.md +232 -0
- package/skills/public/playwright-cli/references/session-management.md +169 -0
- package/skills/public/playwright-cli/references/storage-state.md +275 -0
- package/skills/public/playwright-cli/references/test-generation.md +88 -0
- package/skills/public/playwright-cli/references/tracing.md +139 -0
- package/skills/public/playwright-cli/references/video-recording.md +43 -0
- package/skills/public/pptx/LICENSE.txt +30 -0
- package/skills/public/pptx/SKILL.md +484 -0
- package/skills/public/pptx/css.md +335 -0
- package/skills/public/pptx/html2pptx.md +893 -0
- package/skills/public/pptx/html2pptx.tgz +0 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/public/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/public/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/public/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/public/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/public/pptx/ooxml/schemas/mce/mc.xsd +75 -0
- package/skills/public/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/public/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/public/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/public/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/public/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/public/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/public/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/public/pptx/ooxml/scripts/pack.py +159 -0
- package/skills/public/pptx/ooxml/scripts/unpack.py +29 -0
- package/skills/public/pptx/ooxml/scripts/validate.py +69 -0
- package/skills/public/pptx/ooxml/scripts/validation/__init__.py +15 -0
- package/skills/public/pptx/ooxml/scripts/validation/base.py +951 -0
- package/skills/public/pptx/ooxml/scripts/validation/docx.py +274 -0
- package/skills/public/pptx/ooxml/scripts/validation/pptx.py +315 -0
- package/skills/public/pptx/ooxml/scripts/validation/redlining.py +279 -0
- package/skills/public/pptx/ooxml.md +427 -0
- package/skills/public/pptx/scripts/inventory.py +1020 -0
- package/skills/public/pptx/scripts/rearrange.py +231 -0
- package/skills/public/pptx/scripts/replace.py +385 -0
- package/skills/public/pptx/scripts/thumbnail.py +450 -0
- package/skills/public/skill-creator/SKILL.md +356 -0
- package/skills/public/skill-creator/references/output-patterns.md +82 -0
- package/skills/public/skill-creator/references/workflows.md +28 -0
- package/skills/public/skill-creator/scripts/init_skill.py +303 -0
- package/skills/public/skill-creator/scripts/package_skill.py +110 -0
- package/skills/public/skill-creator/scripts/quick_validate.py +95 -0
- package/skills/public/sub-agent/SKILL.md +186 -0
- package/skills/public/sub-agent/references/security-review.md +153 -0
- package/skills/public/sub-agent/references/usage.md +207 -0
- package/skills/public/sub-agent/scripts/list_subagent_models.sh +22 -0
- package/skills/public/test-driven-development/SKILL.md +371 -0
- package/skills/public/test-driven-development/testing-anti-patterns.md +299 -0
- package/skills/public/webapp-testing/LICENSE.txt +202 -0
- package/skills/public/webapp-testing/SKILL.md +96 -0
- package/skills/public/webapp-testing/examples/console_logging.py +35 -0
- package/skills/public/webapp-testing/examples/element_discovery.py +40 -0
- package/skills/public/webapp-testing/examples/static_html_automation.py +33 -0
- package/skills/public/webapp-testing/scripts/with_server.py +106 -0
- package/skills/public/xlsx/LICENSE.txt +30 -0
- package/skills/public/xlsx/SKILL.md +316 -0
- package/skills/public/xlsx/preview_data.py +93 -0
- package/skills/public/xlsx/recalc.py +178 -0
- package/tests/README.md +42 -0
- package/tests/fixtures/cli/claude_v0.9.2.0_argv.json +46 -0
- package/tests/fixtures/cli/claude_v0.9.2.0_stdout.json +32 -0
- package/tests/fixtures/cli/codex_run.jsonl +4 -0
- package/tests/fixtures/cli/opencode_run.jsonl +6 -0
- package/tests/integration/README.md +56 -0
- package/tests/integration/conftest.py +280 -0
- package/tests/integration/pytest.ini +13 -0
- package/tests/integration/test_mcp_auth.py +85 -0
- package/tests/integration/test_mcp_tools.py +101 -0
- package/tests/integration/test_workspace_lifecycle.py +125 -0
- package/tests/orchestrator/mock_llm_server.py +343 -0
- package/tests/orchestrator/test_cli_adapters.py +566 -0
- package/tests/orchestrator/test_cli_adapters_live.py +527 -0
- package/tests/orchestrator/test_cli_runtime.py +451 -0
- package/tests/orchestrator/test_docker_manager.py +302 -0
- package/tests/orchestrator/test_dynamic_instructions.py +69 -0
- package/tests/orchestrator/test_mcp_resources.py +140 -0
- package/tests/orchestrator/test_mcp_tools.py +224 -0
- package/tests/orchestrator/test_passthrough_isolation.py +201 -0
- package/tests/orchestrator/test_readme_in_container.py +76 -0
- package/tests/orchestrator/test_render_cache.py +84 -0
- package/tests/orchestrator/test_runtime_cli_endpoint.py +108 -0
- package/tests/orchestrator/test_single_user_mode.py +212 -0
- package/tests/orchestrator/test_startup_warnings.py +123 -0
- package/tests/orchestrator/test_sub_agent_dispatch.py +327 -0
- package/tests/orchestrator/test_subagent_claude_compat.py +367 -0
- package/tests/orchestrator/test_system_prompt_endpoint.py +191 -0
- package/tests/orchestrator/test_tool_descriptions.py +52 -0
- package/tests/orchestrator/test_view_image.py +201 -0
- package/tests/patches/conftest.py +30 -0
- package/tests/patches/fixtures/__init__.py +10 -0
- package/tests/patches/fixtures/middleware_v0.9.1.py +5057 -0
- package/tests/patches/fixtures/middleware_v0.9.2.py +5120 -0
- package/tests/patches/fixtures/retrieval_v0.9.1.py +2684 -0
- package/tests/patches/fixtures/retrieval_v0.9.2.py +2700 -0
- package/tests/patches/test_fix_attached_files_position.py +118 -0
- package/tests/patches/test_fix_large_tool_args.py +130 -0
- package/tests/patches/test_fix_large_tool_results.py +531 -0
- package/tests/patches/test_fix_skip_embedding_chat_files.py +160 -0
- package/tests/patches/test_fix_skip_rag_files_native_fc.py +120 -0
- package/tests/patches/test_fix_tool_loop_errors.py +128 -0
- package/tests/security/test_path_traversal_app.py +132 -0
- package/tests/security/test_path_traversal_docker.py +36 -0
- package/tests/security/test_path_traversal_settings.py +87 -0
- package/tests/security/test_safe_path_util.py +166 -0
- package/tests/security/test_xss_preview.py +46 -0
- package/tests/test-default-model-resolution.py +136 -0
- package/tests/test-docker-image.sh +358 -0
- package/tests/test-list-subagent-models.sh +421 -0
- package/tests/test-mcp-endpoint-live.sh +92 -0
- package/tests/test-mcp-native-surface.sh +213 -0
- package/tests/test-no-cyrillic.sh +135 -0
- package/tests/test-opencode-error-mapping.py +130 -0
- package/tests/test-pr88-skills.sh +305 -0
- package/tests/test-project-structure.sh +202 -0
- package/tests/test-single-user-mode.sh +269 -0
- package/tests/test-skill-no-hardcoded-models.sh +65 -0
- package/tests/test-subagent-cli-surface.py +137 -0
- package/tests/test-subagent-runtime.sh +109 -0
- package/tests/test_codex_toml_converter.py +204 -0
- package/tests/test_default_resolver_no_legacy_global.py +159 -0
- package/tests/test_filter.py +648 -0
- package/tests/test_init_sh_unchanged.sh +49 -0
- package/tests/test_opencode_alias_map_drop.py +144 -0
- package/tests/test_requirements.py +91 -0
- package/tests/test_subagent_docstring.py +193 -0
- package/tests/test_tools.py +34 -0
- package/vendor/extract-text/README.md +46 -0
- package/vendor/extract-text/extract-text +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"metadata": {
|
|
3
|
+
"captured_from": "v0.9.2.0",
|
|
4
|
+
"source": "computer-use-server/mcp_tools.py:_format_sub_agent_result lines 819-845 input shape",
|
|
5
|
+
"captured_at": "2026-04-26",
|
|
6
|
+
"purpose": "Phase 5 TEST-03 — ClaudeAdapter.parse_result roundtrip; mirrors the shape claude CLI emits as the LAST line of --output-format json. The byte-compat invariant is enforced jointly with claude_v0.9.2.0_argv.json (the argv side) and the parse_result test in test_cli_adapters.py (the parse side)."
|
|
7
|
+
},
|
|
8
|
+
"happy_path": {
|
|
9
|
+
"stdout": "{\"type\": \"system\", \"subtype\": \"init\"}\n{\"type\": \"assistant\", \"message\": {\"role\": \"assistant\"}}\n{\"type\": \"result\", \"result\": \"Task done. Files written.\", \"total_cost_usd\": 0.1234, \"num_turns\": 7, \"is_error\": false, \"session_id\": \"abc-123-uuid\"}",
|
|
10
|
+
"stderr": "",
|
|
11
|
+
"returncode": 0,
|
|
12
|
+
"expected": {
|
|
13
|
+
"text": "Task done. Files written.",
|
|
14
|
+
"cost_usd": 0.1234,
|
|
15
|
+
"turns": 7,
|
|
16
|
+
"is_error": false,
|
|
17
|
+
"session_id": "abc-123-uuid"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"zero_cost_path": {
|
|
21
|
+
"stdout": "{\"type\": \"result\", \"result\": \"x\", \"total_cost_usd\": 0.0, \"num_turns\": 0, \"is_error\": false, \"session_id\": \"\"}",
|
|
22
|
+
"stderr": "",
|
|
23
|
+
"returncode": 0,
|
|
24
|
+
"expected": {
|
|
25
|
+
"text": "x",
|
|
26
|
+
"cost_usd": null,
|
|
27
|
+
"turns": null,
|
|
28
|
+
"is_error": false,
|
|
29
|
+
"session_id": null
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{"type": "turn.started", "turn_id": "t-1"}
|
|
2
|
+
{"type": "item.started", "item": {"type": "message", "id": "m-1"}}
|
|
3
|
+
{"type": "item.completed", "item": {"type": "message", "id": "m-1", "content": [{"type": "text", "text": "Hello from codex. The answer is 42."}]}}
|
|
4
|
+
{"type": "turn.completed", "turn_id": "t-1", "usage": {"input_tokens": 1234, "output_tokens": 56}}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{"type": "session-started", "session_id": "ignored-by-parser"}
|
|
2
|
+
{"type": "step-start", "step": 1}
|
|
3
|
+
{"type": "step-finish", "step": 1, "cost": 0.0042, "usage": {"input_tokens": 800, "output_tokens": 30}}
|
|
4
|
+
{"type": "step-start", "step": 2}
|
|
5
|
+
{"type": "step-finish", "step": 2, "cost": 0.0011}
|
|
6
|
+
{"type": "assistant-message-completed", "text": "Hello from opencode. Answer: forty-two."}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Integration tests
|
|
2
|
+
|
|
3
|
+
End-to-end tests against a real `computer-use-server` container that spawns real workspace containers via the host Docker socket. Mirrors the prod Compose/Helm setup 1-to-1 — no mocks at the HTTP boundary, no mocks at the Docker boundary.
|
|
4
|
+
|
|
5
|
+
## What's covered
|
|
6
|
+
|
|
7
|
+
| Concern | Test file | Why it matters |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `MCP_API_KEY` auth (valid / missing / wrong) | `test_mcp_auth.py` | Refactoring out the `verify_mcp_auth` dependency would silently make `/mcp` public. Unit tests can't catch this — the dependency is wired at app construction. |
|
|
10
|
+
| `tools/list` matches expected name set | `test_mcp_tools.py` | A typo (`bash_tool` → `bash_too1`) ships green today; this pins the surface. |
|
|
11
|
+
| `tools/call bash_tool` end-to-end echo | `test_mcp_tools.py` | Catches workspace image misconfig, Docker socket missing, response wrapping regressions, sub-agent dispatch breakage. |
|
|
12
|
+
| `/health` is unauthenticated and returns `healthy` | `test_mcp_tools.py` | k8s probes break if either changes. |
|
|
13
|
+
| Workspace container has the prod labels (managed-by, chat-id, tool) | `test_workspace_lifecycle.py` | Drift in any of these labels breaks the cleanup cron's filter in prod. |
|
|
14
|
+
| `/mnt/user-data/{uploads,outputs}` bind mounts | `test_workspace_lifecycle.py` | Compose USER_DATA_BASE_PATH must round-trip into the spawned container. |
|
|
15
|
+
|
|
16
|
+
## How to run
|
|
17
|
+
|
|
18
|
+
### From a clean checkout (test harness owns the stack)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# One-shot: build images, bring stack up, run tests, tear down.
|
|
22
|
+
pytest tests/integration/ -v
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
First run rebuilds the orchestrator image (~3 min) and may pull the workspace image. Subsequent runs reuse the local cache.
|
|
26
|
+
|
|
27
|
+
### Against an already-running stack (CI matrix, dev iteration)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
docker compose -f docker-compose.test.yml up -d --build
|
|
31
|
+
export OCU_TEST_BASE_URL=http://localhost:18081
|
|
32
|
+
export OCU_TEST_MCP_API_KEY=test-token-do-not-use-in-prod
|
|
33
|
+
pytest tests/integration/ -v
|
|
34
|
+
# … iterate on a single test …
|
|
35
|
+
pytest tests/integration/test_mcp_auth.py::test_invalid_token_returns_401 -v
|
|
36
|
+
# tear down explicitly
|
|
37
|
+
docker compose -f docker-compose.test.yml down -v --remove-orphans
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Cleanup
|
|
41
|
+
|
|
42
|
+
Every integration test uses a `chat_id` that starts with the `itest-` prefix (see the `chat_id` fixture). The orchestrator names spawned workspace containers `owui-chat-<chat_id>`, so the session finalizer reaps orphans by container-name filter (`owui-chat-itest-*`) plus the prod label `managed-by=mcp-computer-use-orchestrator`. This deliberately avoids a production-side env knob just for cleanup — production code does not know tests exist.
|
|
43
|
+
|
|
44
|
+
Worst-case manual cleanup, scoped to integration-test containers only:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
docker ps -a --filter 'name=owui-chat-itest-' \
|
|
48
|
+
--filter 'label=managed-by=mcp-computer-use-orchestrator' -q \
|
|
49
|
+
| xargs -r docker rm -f
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Do **not** filter only by `managed-by=mcp-computer-use-orchestrator` — that would also remove the developer's actively-running prod workspace containers on the same machine.
|
|
53
|
+
|
|
54
|
+
## CI
|
|
55
|
+
|
|
56
|
+
`.github/workflows/build.yml` runs this suite on every push to `main` and every PR. The job builds the workspace + server images locally (no GHCR pull), brings up the compose stack, runs pytest, and always tears down regardless of result.
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# SPDX-License-Identifier: FSL-1.1-Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Open Computer Use Contributors
|
|
3
|
+
"""
|
|
4
|
+
Integration test fixtures.
|
|
5
|
+
|
|
6
|
+
These tests run against a *real* computer-use-server container started via
|
|
7
|
+
docker-compose.test.yml. The orchestrator binds the host Docker socket and
|
|
8
|
+
spawns real workspace containers, exactly like prod.
|
|
9
|
+
|
|
10
|
+
Two ways to drive the stack:
|
|
11
|
+
|
|
12
|
+
1. Test harness owns lifecycle (default):
|
|
13
|
+
pytest brings the stack up at session start and tears it down at the end.
|
|
14
|
+
`make integration-test` or plain `pytest tests/integration/` from a clean
|
|
15
|
+
checkout. Slow on first run (image build), fast afterwards (cache reuse).
|
|
16
|
+
|
|
17
|
+
2. CI / external stack:
|
|
18
|
+
export OCU_TEST_BASE_URL=http://localhost:18081
|
|
19
|
+
export OCU_TEST_MCP_API_KEY=test-token-do-not-use-in-prod
|
|
20
|
+
Stack is assumed to be already up; pytest only runs assertions and
|
|
21
|
+
cleanup. Keeps build/test concerns separate in the CI matrix.
|
|
22
|
+
|
|
23
|
+
In both modes the session finalizer reaps every workspace container whose
|
|
24
|
+
name starts with `owui-chat-itest-` (the prefix every chat_id fixture uses)
|
|
25
|
+
so a failing test does not leave orphans on the host between runs. No
|
|
26
|
+
production-side env knob is needed — the prefix alone uniquely identifies
|
|
27
|
+
test containers.
|
|
28
|
+
"""
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
import os
|
|
32
|
+
import subprocess
|
|
33
|
+
import time
|
|
34
|
+
import uuid
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
from typing import Iterator
|
|
37
|
+
|
|
38
|
+
import httpx
|
|
39
|
+
import pytest
|
|
40
|
+
|
|
41
|
+
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
42
|
+
COMPOSE_FILE = REPO_ROOT / "docker-compose.test.yml"
|
|
43
|
+
|
|
44
|
+
# Constant matches docker-compose.test.yml — keep these in sync.
|
|
45
|
+
DEFAULT_API_KEY = "test-token-do-not-use-in-prod"
|
|
46
|
+
DEFAULT_BASE_URL = "http://localhost:18081"
|
|
47
|
+
HEALTH_TIMEOUT_S = 60
|
|
48
|
+
HEALTH_POLL_INTERVAL_S = 1.0
|
|
49
|
+
COMPOSE_TIMEOUT_S = int(os.environ.get("OCU_TEST_COMPOSE_TIMEOUT_S", "900"))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _have_docker() -> bool:
|
|
53
|
+
try:
|
|
54
|
+
return subprocess.run(
|
|
55
|
+
["docker", "version"], capture_output=True, timeout=5
|
|
56
|
+
).returncode == 0
|
|
57
|
+
except (FileNotFoundError, subprocess.TimeoutExpired):
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _wait_for_health(url: str, timeout: float) -> None:
|
|
62
|
+
deadline = time.monotonic() + timeout
|
|
63
|
+
last_err: Exception | None = None
|
|
64
|
+
while time.monotonic() < deadline:
|
|
65
|
+
try:
|
|
66
|
+
r = httpx.get(f"{url}/health", timeout=2.0)
|
|
67
|
+
if r.status_code == 200 and r.json().get("status") == "healthy":
|
|
68
|
+
return
|
|
69
|
+
except Exception as e:
|
|
70
|
+
last_err = e
|
|
71
|
+
time.sleep(HEALTH_POLL_INTERVAL_S)
|
|
72
|
+
raise RuntimeError(
|
|
73
|
+
f"orchestrator at {url}/health never became healthy in {timeout}s "
|
|
74
|
+
f"(last error: {last_err})"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _compose(cmd: list[str], env: dict | None = None) -> subprocess.CompletedProcess:
|
|
79
|
+
full = ["docker", "compose", "-f", str(COMPOSE_FILE), *cmd]
|
|
80
|
+
try:
|
|
81
|
+
return subprocess.run(
|
|
82
|
+
full,
|
|
83
|
+
capture_output=True,
|
|
84
|
+
text=True,
|
|
85
|
+
timeout=COMPOSE_TIMEOUT_S,
|
|
86
|
+
env={**os.environ, **(env or {})},
|
|
87
|
+
)
|
|
88
|
+
except subprocess.TimeoutExpired as exc:
|
|
89
|
+
return subprocess.CompletedProcess(
|
|
90
|
+
args=full,
|
|
91
|
+
returncode=124,
|
|
92
|
+
stdout=(exc.stdout or ""),
|
|
93
|
+
stderr=f"docker compose timed out after {COMPOSE_TIMEOUT_S}s",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# Every integration test uses a chat_id that starts with this prefix (see the
|
|
98
|
+
# `chat_id` fixture). The orchestrator's container naming convention is
|
|
99
|
+
# `owui-chat-<chat_id>`, so prefixing the chat_id lets us reap orphans by
|
|
100
|
+
# container-name filter — no production-side code change needed.
|
|
101
|
+
TEST_CHAT_ID_PREFIX = "itest-"
|
|
102
|
+
TEST_CONTAINER_NAME_PREFIX = f"owui-chat-{TEST_CHAT_ID_PREFIX}"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _reap_test_workspace_containers() -> int:
|
|
106
|
+
"""Force-remove workspace containers spawned by this test session.
|
|
107
|
+
|
|
108
|
+
Identified by container-name prefix (`owui-chat-itest-`), which only ever
|
|
109
|
+
appears when tests run — no prod chat-id starts with `itest-`. This avoids
|
|
110
|
+
a production-side env knob just for test cleanup.
|
|
111
|
+
|
|
112
|
+
Belt-and-braces: tests usually end their own chat sessions, but a crashed
|
|
113
|
+
test or a SIGINT mid-suite would otherwise leak containers on the runner.
|
|
114
|
+
Returns count of containers actually removed.
|
|
115
|
+
"""
|
|
116
|
+
import sys
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
listing = subprocess.run(
|
|
120
|
+
["docker", "ps", "-aq",
|
|
121
|
+
"--filter", f"name={TEST_CONTAINER_NAME_PREFIX}",
|
|
122
|
+
"--filter", "label=managed-by=mcp-computer-use-orchestrator"],
|
|
123
|
+
capture_output=True, text=True, timeout=30,
|
|
124
|
+
)
|
|
125
|
+
except subprocess.TimeoutExpired:
|
|
126
|
+
print("[conftest] WARN: docker ps timed out during reap", file=sys.stderr)
|
|
127
|
+
return 0
|
|
128
|
+
ids = [i for i in listing.stdout.strip().splitlines() if i]
|
|
129
|
+
if not ids:
|
|
130
|
+
return 0
|
|
131
|
+
try:
|
|
132
|
+
rm = subprocess.run(
|
|
133
|
+
["docker", "rm", "-f", *ids],
|
|
134
|
+
capture_output=True, text=True, timeout=60,
|
|
135
|
+
)
|
|
136
|
+
except subprocess.TimeoutExpired:
|
|
137
|
+
print("[conftest] WARN: docker rm -f timed out during reap", file=sys.stderr)
|
|
138
|
+
return 0
|
|
139
|
+
if rm.returncode != 0:
|
|
140
|
+
# Don't raise — finalizer must not mask the underlying test failure.
|
|
141
|
+
print(
|
|
142
|
+
f"[conftest] WARN: docker rm -f failed (rc={rm.returncode}): "
|
|
143
|
+
f"{rm.stderr.strip()[:300]}",
|
|
144
|
+
file=sys.stderr,
|
|
145
|
+
)
|
|
146
|
+
try:
|
|
147
|
+
recheck = subprocess.run(
|
|
148
|
+
["docker", "ps", "-aq",
|
|
149
|
+
"--filter", f"name={TEST_CONTAINER_NAME_PREFIX}",
|
|
150
|
+
"--filter", "label=managed-by=mcp-computer-use-orchestrator"],
|
|
151
|
+
capture_output=True, text=True, timeout=30,
|
|
152
|
+
)
|
|
153
|
+
except subprocess.TimeoutExpired:
|
|
154
|
+
print("[conftest] WARN: docker ps recheck timed out", file=sys.stderr)
|
|
155
|
+
return 0
|
|
156
|
+
remaining = len([i for i in recheck.stdout.strip().splitlines() if i])
|
|
157
|
+
return len(ids) - remaining
|
|
158
|
+
return len(ids)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@pytest.fixture(scope="session")
|
|
162
|
+
def orchestrator() -> Iterator[dict]:
|
|
163
|
+
"""Yield {url, api_key} after ensuring the stack is healthy.
|
|
164
|
+
|
|
165
|
+
Skips the entire suite if Docker is unavailable — these tests are real
|
|
166
|
+
integration, not unit tests, and pretending otherwise hides regressions.
|
|
167
|
+
"""
|
|
168
|
+
if not _have_docker():
|
|
169
|
+
pytest.skip("Docker daemon not reachable; integration tests require Docker")
|
|
170
|
+
|
|
171
|
+
external = os.environ.get("OCU_TEST_BASE_URL")
|
|
172
|
+
api_key = os.environ.get("OCU_TEST_MCP_API_KEY", DEFAULT_API_KEY)
|
|
173
|
+
|
|
174
|
+
if external:
|
|
175
|
+
# CI / dev opted to manage the stack themselves. Just wait + yield.
|
|
176
|
+
_wait_for_health(external, HEALTH_TIMEOUT_S)
|
|
177
|
+
try:
|
|
178
|
+
yield {"url": external, "api_key": api_key}
|
|
179
|
+
finally:
|
|
180
|
+
reaped = _reap_test_workspace_containers()
|
|
181
|
+
if reaped:
|
|
182
|
+
print(f"[conftest] reaped {reaped} orphan workspace containers")
|
|
183
|
+
return
|
|
184
|
+
|
|
185
|
+
# Owned-stack mode. Build + up + wait. Always teardown.
|
|
186
|
+
up = _compose(["up", "-d", "--build"])
|
|
187
|
+
if up.returncode != 0:
|
|
188
|
+
pytest.fail(f"docker compose up failed:\nSTDOUT:\n{up.stdout}\nSTDERR:\n{up.stderr}")
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
_wait_for_health(DEFAULT_BASE_URL, HEALTH_TIMEOUT_S)
|
|
192
|
+
yield {"url": DEFAULT_BASE_URL, "api_key": api_key}
|
|
193
|
+
finally:
|
|
194
|
+
import sys
|
|
195
|
+
reaped = _reap_test_workspace_containers()
|
|
196
|
+
if reaped:
|
|
197
|
+
print(f"[conftest] reaped {reaped} orphan workspace containers")
|
|
198
|
+
down = _compose(["down", "-v", "--remove-orphans"])
|
|
199
|
+
if down.returncode != 0:
|
|
200
|
+
# Don't raise — we're in a finalizer and an exception here would
|
|
201
|
+
# mask the actual test failure. But do surface the daemon error so
|
|
202
|
+
# leftover networks/volumes on the runner are diagnosable.
|
|
203
|
+
print(
|
|
204
|
+
f"[conftest] WARN: docker compose down failed (rc={down.returncode}): "
|
|
205
|
+
f"{down.stderr.strip()[:300]}",
|
|
206
|
+
file=sys.stderr,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
@pytest.fixture()
|
|
211
|
+
def client(orchestrator) -> Iterator[httpx.Client]:
|
|
212
|
+
"""HTTP client preconfigured with auth + sensible timeout for tool calls."""
|
|
213
|
+
headers = {
|
|
214
|
+
"Authorization": f"Bearer {orchestrator['api_key']}",
|
|
215
|
+
"Content-Type": "application/json",
|
|
216
|
+
"Accept": "application/json, text/event-stream",
|
|
217
|
+
}
|
|
218
|
+
with httpx.Client(base_url=orchestrator["url"], headers=headers, timeout=120.0) as c:
|
|
219
|
+
yield c
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@pytest.fixture()
|
|
223
|
+
def chat_id() -> str:
|
|
224
|
+
"""A fresh chat-id per test — each gets its own workspace container.
|
|
225
|
+
|
|
226
|
+
The `itest-` prefix is load-bearing: the session finalizer uses it (via
|
|
227
|
+
`owui-chat-itest-*` container-name match) to find and reap orphans
|
|
228
|
+
without touching prod containers a developer may have running locally.
|
|
229
|
+
"""
|
|
230
|
+
return f"{TEST_CHAT_ID_PREFIX}{uuid.uuid4().hex[:12]}"
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def mcp_request(method: str, params: dict | None = None, req_id: int = 1) -> dict:
|
|
234
|
+
"""Build a JSON-RPC 2.0 request envelope matching the MCP spec."""
|
|
235
|
+
payload: dict = {"jsonrpc": "2.0", "id": req_id, "method": method}
|
|
236
|
+
if params is not None:
|
|
237
|
+
payload["params"] = params
|
|
238
|
+
return payload
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def parse_mcp_response(resp: httpx.Response) -> dict:
|
|
242
|
+
"""Return the decoded JSON-RPC envelope from either an SSE or JSON body.
|
|
243
|
+
|
|
244
|
+
FastMCP's streamable_http_app picks the response format based on the
|
|
245
|
+
request's Accept header — we send both, and the server tends to reply
|
|
246
|
+
with text/event-stream. The single data: line carries the actual envelope.
|
|
247
|
+
"""
|
|
248
|
+
import json
|
|
249
|
+
|
|
250
|
+
ctype = resp.headers.get("content-type", "")
|
|
251
|
+
body = resp.text
|
|
252
|
+
# Detect SSE only by Content-Type or by an `event:`/`data:` line at the
|
|
253
|
+
# *start* of a line. The original substring-anywhere check was too loose:
|
|
254
|
+
# a perfectly valid JSON-RPC payload like {"result":{"data":"x"}} contains
|
|
255
|
+
# the literal `"data:` and would be misrouted to the SSE branch.
|
|
256
|
+
is_sse = (
|
|
257
|
+
"text/event-stream" in ctype
|
|
258
|
+
or body.lstrip().startswith("event:")
|
|
259
|
+
or any(line.startswith("data:") for line in body.splitlines())
|
|
260
|
+
)
|
|
261
|
+
if is_sse and "text/event-stream" in ctype:
|
|
262
|
+
# Trust Content-Type when present — only then walk SSE frames.
|
|
263
|
+
for line in body.splitlines():
|
|
264
|
+
if line.startswith("data:"):
|
|
265
|
+
return json.loads(line[len("data:"):].strip())
|
|
266
|
+
raise AssertionError(f"SSE body had no data: line. Raw:\n{body[:500]}")
|
|
267
|
+
return json.loads(body)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def call_mcp(client: httpx.Client, chat_id: str, method: str,
|
|
271
|
+
params: dict | None = None, req_id: int = 1) -> dict:
|
|
272
|
+
"""POST /mcp with the X-Chat-Id header the orchestrator requires."""
|
|
273
|
+
resp = client.post(
|
|
274
|
+
"/mcp",
|
|
275
|
+
json=mcp_request(method, params, req_id),
|
|
276
|
+
headers={"X-Chat-Id": chat_id},
|
|
277
|
+
)
|
|
278
|
+
return {"status": resp.status_code, "headers": dict(resp.headers),
|
|
279
|
+
"envelope": parse_mcp_response(resp) if resp.status_code == 200 else None,
|
|
280
|
+
"body": resp.text}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
# Copyright (c) 2025 Open Computer Use Contributors
|
|
3
|
+
#
|
|
4
|
+
# Integration-only pytest config. The unit suite under tests/orchestrator/
|
|
5
|
+
# uses default discovery; this file scopes timeouts and markers to the
|
|
6
|
+
# integration directory only so a stray @pytest.mark.timeout(180) on a
|
|
7
|
+
# unit test wouldn't accidentally inherit our slow-test budget.
|
|
8
|
+
[pytest]
|
|
9
|
+
testpaths = .
|
|
10
|
+
addopts = -v --tb=short --strict-markers
|
|
11
|
+
markers =
|
|
12
|
+
integration: real Docker + real HTTP; runs against docker-compose.test.yml
|
|
13
|
+
timeout = 60
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# SPDX-License-Identifier: FSL-1.1-Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Open Computer Use Contributors
|
|
3
|
+
"""
|
|
4
|
+
Auth contract: POST /mcp requires Bearer MCP_API_KEY when configured.
|
|
5
|
+
|
|
6
|
+
Regression target: a refactor that drops the verify_mcp_auth dependency would
|
|
7
|
+
make /mcp open to the world. Unit tests don't catch this because the dependency
|
|
8
|
+
is wired at app construction time. This suite hits the real container.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import httpx
|
|
13
|
+
import pytest
|
|
14
|
+
|
|
15
|
+
from conftest import mcp_request
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _init_payload() -> dict:
|
|
19
|
+
return mcp_request(
|
|
20
|
+
"initialize",
|
|
21
|
+
{
|
|
22
|
+
"protocolVersion": "2025-03-26",
|
|
23
|
+
"capabilities": {},
|
|
24
|
+
"clientInfo": {"name": "integration-test", "version": "0.0.0"},
|
|
25
|
+
},
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.mark.integration
|
|
30
|
+
def test_valid_token_returns_200(orchestrator, chat_id):
|
|
31
|
+
"""Sanity: the well-known good token from compose env is accepted."""
|
|
32
|
+
with httpx.Client(base_url=orchestrator["url"], timeout=10.0) as c:
|
|
33
|
+
r = c.post(
|
|
34
|
+
"/mcp",
|
|
35
|
+
json=_init_payload(),
|
|
36
|
+
headers={
|
|
37
|
+
"Authorization": f"Bearer {orchestrator['api_key']}",
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
"Accept": "application/json, text/event-stream",
|
|
40
|
+
"X-Chat-Id": chat_id,
|
|
41
|
+
},
|
|
42
|
+
)
|
|
43
|
+
assert r.status_code == 200, f"expected 200, got {r.status_code}: {r.text[:300]}"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.mark.integration
|
|
47
|
+
def test_missing_authorization_returns_401(orchestrator, chat_id):
|
|
48
|
+
"""No Authorization header → 401 with WWW-Authenticate: Bearer."""
|
|
49
|
+
with httpx.Client(base_url=orchestrator["url"], timeout=10.0) as c:
|
|
50
|
+
r = c.post(
|
|
51
|
+
"/mcp",
|
|
52
|
+
json=_init_payload(),
|
|
53
|
+
headers={
|
|
54
|
+
"Content-Type": "application/json",
|
|
55
|
+
"Accept": "application/json, text/event-stream",
|
|
56
|
+
"X-Chat-Id": chat_id,
|
|
57
|
+
},
|
|
58
|
+
)
|
|
59
|
+
# FastAPI/HTTPBearer returns 403 by default when auto_error=True and the
|
|
60
|
+
# header is missing; the codepath in app.py overrides to 401 explicitly.
|
|
61
|
+
# Either status proves auth is enforced; pin to 401 because that's what
|
|
62
|
+
# the code documents.
|
|
63
|
+
assert r.status_code == 401, (
|
|
64
|
+
f"expected 401 for missing auth header, got {r.status_code}: {r.text[:300]}"
|
|
65
|
+
)
|
|
66
|
+
assert "bearer" in r.headers.get("www-authenticate", "").lower()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@pytest.mark.integration
|
|
70
|
+
def test_invalid_token_returns_401(orchestrator, chat_id):
|
|
71
|
+
"""Wrong token → 401, never 200."""
|
|
72
|
+
with httpx.Client(base_url=orchestrator["url"], timeout=10.0) as c:
|
|
73
|
+
r = c.post(
|
|
74
|
+
"/mcp",
|
|
75
|
+
json=_init_payload(),
|
|
76
|
+
headers={
|
|
77
|
+
"Authorization": "Bearer obviously-wrong-token",
|
|
78
|
+
"Content-Type": "application/json",
|
|
79
|
+
"Accept": "application/json, text/event-stream",
|
|
80
|
+
"X-Chat-Id": chat_id,
|
|
81
|
+
},
|
|
82
|
+
)
|
|
83
|
+
assert r.status_code == 401, (
|
|
84
|
+
f"expected 401 for bad token, got {r.status_code}: {r.text[:300]}"
|
|
85
|
+
)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# SPDX-License-Identifier: FSL-1.1-Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Open Computer Use Contributors
|
|
3
|
+
"""
|
|
4
|
+
MCP protocol: tools/list shape + tools/call bash_tool end-to-end.
|
|
5
|
+
|
|
6
|
+
Regression target: a typo in @mcp.tool() registration (bash_tool → bash_too1)
|
|
7
|
+
or a refactor that breaks the streamable_http_app's response wrapping. Both
|
|
8
|
+
land in prod silently today.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import pytest
|
|
13
|
+
|
|
14
|
+
from conftest import call_mcp
|
|
15
|
+
|
|
16
|
+
# Snapshot of tools registered in mcp_tools.py. Update intentionally when the
|
|
17
|
+
# tool surface changes; a drift here means somebody renamed/added/removed a tool
|
|
18
|
+
# and the team should agree before shipping.
|
|
19
|
+
EXPECTED_TOOL_NAMES = {"bash_tool", "str_replace", "create_file", "view", "sub_agent"}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _initialize(client, chat_id) -> None:
|
|
23
|
+
"""MCP requires initialize before any other method."""
|
|
24
|
+
r = call_mcp(client, chat_id, "initialize", {
|
|
25
|
+
"protocolVersion": "2025-03-26",
|
|
26
|
+
"capabilities": {},
|
|
27
|
+
"clientInfo": {"name": "integration-test", "version": "0.0.0"},
|
|
28
|
+
})
|
|
29
|
+
assert r["status"] == 200, f"initialize failed: {r['body'][:300]}"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.mark.integration
|
|
33
|
+
def test_tools_list_matches_expected_set(client, chat_id):
|
|
34
|
+
_initialize(client, chat_id)
|
|
35
|
+
r = call_mcp(client, chat_id, "tools/list", req_id=2)
|
|
36
|
+
assert r["status"] == 200, f"tools/list HTTP {r['status']}"
|
|
37
|
+
|
|
38
|
+
env = r["envelope"]
|
|
39
|
+
assert env["jsonrpc"] == "2.0"
|
|
40
|
+
assert env["id"] == 2
|
|
41
|
+
assert "result" in env, f"missing result: {env}"
|
|
42
|
+
tools = env["result"]["tools"]
|
|
43
|
+
names = {t["name"] for t in tools}
|
|
44
|
+
|
|
45
|
+
assert names == EXPECTED_TOOL_NAMES, (
|
|
46
|
+
f"tool set drifted.\n expected: {sorted(EXPECTED_TOOL_NAMES)}\n got: {sorted(names)}"
|
|
47
|
+
)
|
|
48
|
+
# Each tool must declare a non-empty inputSchema. A registration that
|
|
49
|
+
# forgets the schema is technically valid for FastMCP but breaks clients.
|
|
50
|
+
for t in tools:
|
|
51
|
+
assert isinstance(t.get("inputSchema"), dict) and t["inputSchema"], (
|
|
52
|
+
f"tool {t['name']!r} has empty inputSchema"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@pytest.mark.integration
|
|
57
|
+
@pytest.mark.timeout(180) # first call cold-starts a workspace container
|
|
58
|
+
def test_bash_tool_echo_roundtrip(client, chat_id):
|
|
59
|
+
"""The smallest possible real tool call. Catches:
|
|
60
|
+
- workspace image missing / unpullable
|
|
61
|
+
- Docker socket misconfigured
|
|
62
|
+
- container spawn racing /health
|
|
63
|
+
- response wrapping (content[0].text) regressions
|
|
64
|
+
"""
|
|
65
|
+
_initialize(client, chat_id)
|
|
66
|
+
|
|
67
|
+
r = call_mcp(client, chat_id, "tools/call", {
|
|
68
|
+
"name": "bash_tool",
|
|
69
|
+
"arguments": {
|
|
70
|
+
"command": "echo hello-from-integration",
|
|
71
|
+
"description": "integration smoke: echo",
|
|
72
|
+
},
|
|
73
|
+
}, req_id=2)
|
|
74
|
+
assert r["status"] == 200, f"tools/call HTTP {r['status']}: {r['body'][:400]}"
|
|
75
|
+
|
|
76
|
+
env = r["envelope"]
|
|
77
|
+
assert env["jsonrpc"] == "2.0"
|
|
78
|
+
assert "result" in env, f"got JSON-RPC error instead of result: {env}"
|
|
79
|
+
result = env["result"]
|
|
80
|
+
|
|
81
|
+
# MCP tool-level error path: result.isError=True is a successful protocol
|
|
82
|
+
# response carrying a domain-level failure. Treat as fail for this smoke.
|
|
83
|
+
assert not result.get("isError"), f"bash_tool reported isError=True: {result}"
|
|
84
|
+
|
|
85
|
+
content = result.get("content", [])
|
|
86
|
+
assert content and content[0]["type"] == "text", (
|
|
87
|
+
f"expected text content[], got: {content}"
|
|
88
|
+
)
|
|
89
|
+
text_blob = "".join(part["text"] for part in content if part.get("type") == "text")
|
|
90
|
+
assert "hello-from-integration" in text_blob, (
|
|
91
|
+
f"expected echo output in tool result, got:\n{text_blob[:500]}"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@pytest.mark.integration
|
|
96
|
+
def test_health_unauthenticated(orchestrator):
|
|
97
|
+
"""/health stays open — used by k8s probes and uptime monitors."""
|
|
98
|
+
import httpx
|
|
99
|
+
r = httpx.get(f"{orchestrator['url']}/health", timeout=5.0)
|
|
100
|
+
assert r.status_code == 200
|
|
101
|
+
assert r.json() == {"status": "healthy"}
|