@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,224 @@
|
|
|
1
|
+
# SPDX-License-Identifier: FSL-1.1-Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Open Computer Use Contributors
|
|
3
|
+
"""Tests for MCP tools — output truncation, command semantics, uniqueness check.
|
|
4
|
+
|
|
5
|
+
Uses mock Docker to test tool logic without real containers.
|
|
6
|
+
|
|
7
|
+
Run: cd computer-use-server && python -m pytest ../tests/orchestrator/test_mcp_tools.py -v
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
import unittest
|
|
13
|
+
from unittest.mock import patch, MagicMock, AsyncMock
|
|
14
|
+
|
|
15
|
+
# Add computer-use-server to path for imports
|
|
16
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'computer-use-server'))
|
|
17
|
+
|
|
18
|
+
from context_vars import current_chat_id
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _mock_exec_result(output="", exit_code=0, success=True):
|
|
22
|
+
"""Create a mock execute_bash result."""
|
|
23
|
+
return {"output": output, "exit_code": exit_code, "success": success}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _mock_container():
|
|
27
|
+
"""Create a mock Docker container."""
|
|
28
|
+
c = MagicMock()
|
|
29
|
+
c.id = "mock-container-id"
|
|
30
|
+
c.name = "owui-chat-test"
|
|
31
|
+
c.status = "running"
|
|
32
|
+
return c
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class TestBashToolOutputTruncation(unittest.IsolatedAsyncioTestCase):
|
|
36
|
+
"""Tests for bash_tool output truncation (Claude Code best practice: maxResultSizeChars=30K)."""
|
|
37
|
+
|
|
38
|
+
@patch("mcp_tools._ensure_gitlab_token", new_callable=AsyncMock)
|
|
39
|
+
@patch("mcp_tools._get_or_create_container", return_value=_mock_container())
|
|
40
|
+
async def test_large_output_is_truncated(self, mock_container, mock_token):
|
|
41
|
+
"""Output >30K chars should be truncated with head+tail and a message."""
|
|
42
|
+
from mcp_tools import bash_tool
|
|
43
|
+
current_chat_id.set("test-chat")
|
|
44
|
+
ctx = MagicMock()
|
|
45
|
+
ctx.report_progress = AsyncMock()
|
|
46
|
+
|
|
47
|
+
big_output = "x" * 60_000 # 60K chars
|
|
48
|
+
with patch("mcp_tools.execute_bash_streaming",
|
|
49
|
+
return_value={"output": big_output, "exit_code": 0, "success": True}):
|
|
50
|
+
result = await bash_tool("cat big_file", "read big file", ctx)
|
|
51
|
+
|
|
52
|
+
self.assertIn("truncated", result.lower())
|
|
53
|
+
self.assertLessEqual(len(result), 32_000) # 30K + truncation message
|
|
54
|
+
|
|
55
|
+
@patch("mcp_tools._ensure_gitlab_token", new_callable=AsyncMock)
|
|
56
|
+
@patch("mcp_tools._get_or_create_container", return_value=_mock_container())
|
|
57
|
+
async def test_short_output_not_truncated(self, mock_container, mock_token):
|
|
58
|
+
"""Output <30K chars should be returned as-is."""
|
|
59
|
+
from mcp_tools import bash_tool
|
|
60
|
+
current_chat_id.set("test-chat")
|
|
61
|
+
ctx = MagicMock()
|
|
62
|
+
ctx.report_progress = AsyncMock()
|
|
63
|
+
|
|
64
|
+
short_output = "hello world\n" * 100 # ~1.2K chars
|
|
65
|
+
with patch("mcp_tools.execute_bash_streaming",
|
|
66
|
+
return_value={"output": short_output, "exit_code": 0, "success": True}):
|
|
67
|
+
result = await bash_tool("echo hello", "test", ctx)
|
|
68
|
+
|
|
69
|
+
self.assertEqual(result, short_output)
|
|
70
|
+
self.assertNotIn("truncated", result.lower())
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class TestBashToolCommandSemantics(unittest.IsolatedAsyncioTestCase):
|
|
74
|
+
"""Tests for command semantics (grep/find/diff exit code 1 != error)."""
|
|
75
|
+
|
|
76
|
+
@patch("mcp_tools._ensure_gitlab_token", new_callable=AsyncMock)
|
|
77
|
+
@patch("mcp_tools._get_or_create_container", return_value=_mock_container())
|
|
78
|
+
async def test_grep_exit1_returns_no_matches(self, mock_container, mock_token):
|
|
79
|
+
"""grep exit code 1 should return 'No matches found', not an error."""
|
|
80
|
+
from mcp_tools import bash_tool
|
|
81
|
+
current_chat_id.set("test-chat")
|
|
82
|
+
ctx = MagicMock()
|
|
83
|
+
ctx.report_progress = AsyncMock()
|
|
84
|
+
|
|
85
|
+
with patch("mcp_tools.execute_bash_streaming",
|
|
86
|
+
return_value={"output": "", "exit_code": 1, "success": False}):
|
|
87
|
+
result = await bash_tool("grep -r TODO /repo", "search", ctx)
|
|
88
|
+
|
|
89
|
+
self.assertIn("No matches found", result)
|
|
90
|
+
self.assertNotIn("Exit code", result)
|
|
91
|
+
|
|
92
|
+
@patch("mcp_tools._ensure_gitlab_token", new_callable=AsyncMock)
|
|
93
|
+
@patch("mcp_tools._get_or_create_container", return_value=_mock_container())
|
|
94
|
+
async def test_grep_exit2_is_error(self, mock_container, mock_token):
|
|
95
|
+
"""grep exit code 2+ should be reported as error."""
|
|
96
|
+
from mcp_tools import bash_tool
|
|
97
|
+
current_chat_id.set("test-chat")
|
|
98
|
+
ctx = MagicMock()
|
|
99
|
+
ctx.report_progress = AsyncMock()
|
|
100
|
+
|
|
101
|
+
with patch("mcp_tools.execute_bash_streaming",
|
|
102
|
+
return_value={"output": "grep: invalid option", "exit_code": 2, "success": False}):
|
|
103
|
+
result = await bash_tool("grep --bad-flag /repo", "search", ctx)
|
|
104
|
+
|
|
105
|
+
self.assertIn("grep: invalid option", result)
|
|
106
|
+
|
|
107
|
+
@patch("mcp_tools._ensure_gitlab_token", new_callable=AsyncMock)
|
|
108
|
+
@patch("mcp_tools._get_or_create_container", return_value=_mock_container())
|
|
109
|
+
async def test_diff_exit1_returns_files_differ(self, mock_container, mock_token):
|
|
110
|
+
"""diff exit code 1 should return 'Files differ', not an error."""
|
|
111
|
+
from mcp_tools import bash_tool
|
|
112
|
+
current_chat_id.set("test-chat")
|
|
113
|
+
ctx = MagicMock()
|
|
114
|
+
ctx.report_progress = AsyncMock()
|
|
115
|
+
|
|
116
|
+
with patch("mcp_tools.execute_bash_streaming",
|
|
117
|
+
return_value={"output": "", "exit_code": 1, "success": False}):
|
|
118
|
+
result = await bash_tool("diff a.txt b.txt", "compare", ctx)
|
|
119
|
+
|
|
120
|
+
self.assertIn("Files differ", result)
|
|
121
|
+
self.assertNotIn("Exit code", result)
|
|
122
|
+
|
|
123
|
+
@patch("mcp_tools._ensure_gitlab_token", new_callable=AsyncMock)
|
|
124
|
+
@patch("mcp_tools._get_or_create_container", return_value=_mock_container())
|
|
125
|
+
async def test_regular_command_exit1_is_error(self, mock_container, mock_token):
|
|
126
|
+
"""Non-semantic commands: exit code 1 remains an error."""
|
|
127
|
+
from mcp_tools import bash_tool
|
|
128
|
+
current_chat_id.set("test-chat")
|
|
129
|
+
ctx = MagicMock()
|
|
130
|
+
ctx.report_progress = AsyncMock()
|
|
131
|
+
|
|
132
|
+
with patch("mcp_tools.execute_bash_streaming",
|
|
133
|
+
return_value={"output": "", "exit_code": 1, "success": False}):
|
|
134
|
+
result = await bash_tool("python3 script.py", "run script", ctx)
|
|
135
|
+
|
|
136
|
+
self.assertIn("Exit code: 1", result)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class TestViewTruncation(unittest.IsolatedAsyncioTestCase):
|
|
140
|
+
"""Tests for view output truncation at 30K (increased from 16K)."""
|
|
141
|
+
|
|
142
|
+
@patch("mcp_tools._ensure_gitlab_token", new_callable=AsyncMock)
|
|
143
|
+
@patch("mcp_tools._get_or_create_container", return_value=_mock_container())
|
|
144
|
+
async def test_view_truncation_at_30k(self, mock_container, mock_token):
|
|
145
|
+
"""Output >30K should be truncated with head+tail."""
|
|
146
|
+
from mcp_tools import view
|
|
147
|
+
current_chat_id.set("test-chat")
|
|
148
|
+
|
|
149
|
+
big_output = "line\n" * 10_000 # ~50K chars
|
|
150
|
+
with patch("mcp_tools._execute_bash",
|
|
151
|
+
return_value={"output": big_output, "exit_code": 0}):
|
|
152
|
+
result = await view("read big file", "/tmp/big.log")
|
|
153
|
+
|
|
154
|
+
self.assertIn("truncated", result.lower())
|
|
155
|
+
self.assertLessEqual(len(result), 32_000)
|
|
156
|
+
|
|
157
|
+
@patch("mcp_tools._ensure_gitlab_token", new_callable=AsyncMock)
|
|
158
|
+
@patch("mcp_tools._get_or_create_container", return_value=_mock_container())
|
|
159
|
+
async def test_view_no_truncation_under_30k(self, mock_container, mock_token):
|
|
160
|
+
"""Output of 20K (between old 16K and new 30K) should NOT be truncated."""
|
|
161
|
+
from mcp_tools import view
|
|
162
|
+
current_chat_id.set("test-chat")
|
|
163
|
+
|
|
164
|
+
# 20K chars -- above old 16K threshold but below new 30K
|
|
165
|
+
normal_output = "x" * 20_000
|
|
166
|
+
with patch("mcp_tools._execute_bash",
|
|
167
|
+
return_value={"output": normal_output, "exit_code": 0}):
|
|
168
|
+
result = await view("read file", "/tmp/file.py")
|
|
169
|
+
|
|
170
|
+
self.assertEqual(result, normal_output)
|
|
171
|
+
self.assertNotIn("truncated", result.lower())
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class TestStrReplaceUniqueness(unittest.IsolatedAsyncioTestCase):
|
|
175
|
+
"""Tests for str_replace uniqueness check."""
|
|
176
|
+
|
|
177
|
+
@patch("mcp_tools._ensure_gitlab_token", new_callable=AsyncMock)
|
|
178
|
+
@patch("mcp_tools._get_or_create_container", return_value=_mock_container())
|
|
179
|
+
async def test_multiple_matches_returns_error(self, mock_container, mock_token):
|
|
180
|
+
"""str_replace should error when old_str appears multiple times."""
|
|
181
|
+
from mcp_tools import str_replace
|
|
182
|
+
current_chat_id.set("test-chat")
|
|
183
|
+
|
|
184
|
+
# The Python script inside container should detect multiple occurrences
|
|
185
|
+
error_output = "Error: Found 3 occurrences of old_str in /tmp/test.py. Add more context to make it unique."
|
|
186
|
+
with patch("mcp_tools._execute_python_with_stdin",
|
|
187
|
+
return_value={"output": error_output, "exit_code": 1, "success": False}):
|
|
188
|
+
result = await str_replace("fix", "print('hello')", "/tmp/test.py", "print('world')")
|
|
189
|
+
|
|
190
|
+
self.assertIn("occurrences", result.lower())
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class TestHelperFunctions(unittest.TestCase):
|
|
194
|
+
"""Tests for helper functions: _get_first_command, _apply_command_semantics, _truncate_output."""
|
|
195
|
+
|
|
196
|
+
def test_get_first_command_simple(self):
|
|
197
|
+
from mcp_tools import _get_first_command
|
|
198
|
+
self.assertEqual(_get_first_command("grep -r TODO ."), "grep")
|
|
199
|
+
|
|
200
|
+
def test_get_first_command_with_path(self):
|
|
201
|
+
from mcp_tools import _get_first_command
|
|
202
|
+
self.assertEqual(_get_first_command("/usr/bin/grep pattern"), "grep")
|
|
203
|
+
|
|
204
|
+
def test_get_first_command_with_env_vars(self):
|
|
205
|
+
from mcp_tools import _get_first_command
|
|
206
|
+
self.assertEqual(_get_first_command("FOO=bar python3 script.py"), "python3")
|
|
207
|
+
|
|
208
|
+
def test_get_first_command_with_sudo(self):
|
|
209
|
+
from mcp_tools import _get_first_command
|
|
210
|
+
self.assertEqual(_get_first_command("sudo grep pattern"), "grep")
|
|
211
|
+
|
|
212
|
+
def test_truncate_output_short(self):
|
|
213
|
+
from mcp_tools import _truncate_output
|
|
214
|
+
self.assertEqual(_truncate_output("hello", 100), "hello")
|
|
215
|
+
|
|
216
|
+
def test_truncate_output_long(self):
|
|
217
|
+
from mcp_tools import _truncate_output
|
|
218
|
+
result = _truncate_output("x" * 100, 50)
|
|
219
|
+
self.assertIn("truncated", result.lower())
|
|
220
|
+
self.assertLessEqual(len(result), 200) # 50 + message overhead
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
if __name__ == "__main__":
|
|
224
|
+
unittest.main()
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# SPDX-License-Identifier: FSL-1.1-Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Open Computer Use Contributors
|
|
3
|
+
"""Pitfall 1 regression guard — per-CLI auth allowlist isolation.
|
|
4
|
+
|
|
5
|
+
When SUBAGENT_CLI selects a runtime, only that runtime's passthrough tuple
|
|
6
|
+
crosses the orchestrator->sandbox boundary. Other runtimes' auth env vars
|
|
7
|
+
must NOT leak into the container's `Env`, even if the operator has them
|
|
8
|
+
set on the host (common in mixed-deployment environments).
|
|
9
|
+
|
|
10
|
+
Also verifies the OPENCODE_CONFIG pin (Plan 06-01 Edit 1c) — when
|
|
11
|
+
SUBAGENT_CLI=opencode, extra_env["OPENCODE_CONFIG"] must equal
|
|
12
|
+
"/tmp/opencode.json" so docker exec'd subprocesses inherit it and OpenCode
|
|
13
|
+
never falls back to ~/.local/share/opencode/auth.json (Pitfall 7 reopen).
|
|
14
|
+
|
|
15
|
+
Mirrors tests/orchestrator/test_docker_manager.py pattern: monkeypatch.setenv
|
|
16
|
+
+ importlib.reload(docker_manager) + mocked docker client + capture
|
|
17
|
+
`containers.create(environment=...)` kwargs (the actual sandbox container is
|
|
18
|
+
created via `client.containers.create(**config)` — `containers.run` is only
|
|
19
|
+
used for the ephemeral directory-setup shim).
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import importlib
|
|
25
|
+
import os
|
|
26
|
+
import sys
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from unittest.mock import MagicMock, patch
|
|
29
|
+
|
|
30
|
+
import pytest
|
|
31
|
+
|
|
32
|
+
# Make `computer-use-server` importable (project layout puts it as a sibling
|
|
33
|
+
# directory, not a Python package on sys.path by default).
|
|
34
|
+
_REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
35
|
+
_SERVER_DIR = _REPO_ROOT / "computer-use-server"
|
|
36
|
+
if str(_SERVER_DIR) not in sys.path:
|
|
37
|
+
sys.path.insert(0, str(_SERVER_DIR))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _build_mock_docker_client():
|
|
41
|
+
"""Mock docker client wired for the _create_container call path.
|
|
42
|
+
|
|
43
|
+
Mirrors tests/orchestrator/test_docker_manager.py::_build_mock_docker_client
|
|
44
|
+
so the SUT's exception-tolerant fallbacks (network attach, save_container_meta,
|
|
45
|
+
README write, MCP resource sync, defensive scrub) are all silently satisfied.
|
|
46
|
+
|
|
47
|
+
The actual sandbox is created via `client.containers.create(**config)` — that
|
|
48
|
+
is the call we inspect for the `environment` kwarg. `containers.run` is the
|
|
49
|
+
ephemeral mkdir shim and irrelevant to the assertion target.
|
|
50
|
+
"""
|
|
51
|
+
client = MagicMock()
|
|
52
|
+
client.containers.run.return_value = None
|
|
53
|
+
fake_container = MagicMock()
|
|
54
|
+
# Defensive scrub call (Plan 06-01 D4) — return a (exit_code, output) tuple
|
|
55
|
+
# so any unpacking in the SUT does not raise.
|
|
56
|
+
fake_container.exec_run = MagicMock(return_value=(0, b""))
|
|
57
|
+
client.containers.create.return_value = fake_container
|
|
58
|
+
client.networks.list.return_value = []
|
|
59
|
+
client.volumes.list.return_value = []
|
|
60
|
+
client.images.get.return_value = MagicMock()
|
|
61
|
+
return client, fake_container
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _clear_phase6_auth_env():
|
|
65
|
+
"""Pop every Phase-6 auth env var so the parametrize starts from a clean slate.
|
|
66
|
+
|
|
67
|
+
Without this, a stale OPENAI_API_KEY from a sibling test (or the developer's
|
|
68
|
+
shell) would survive `monkeypatch.setenv` only for the keys we explicitly
|
|
69
|
+
set, but the module-level tuples are built at import time from os.getenv —
|
|
70
|
+
`importlib.reload` re-runs them, so the pre-reload os.environ state IS the
|
|
71
|
+
test fixture. Be explicit.
|
|
72
|
+
"""
|
|
73
|
+
for key in (
|
|
74
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
75
|
+
"ANTHROPIC_BASE_URL",
|
|
76
|
+
"ANTHROPIC_API_KEY",
|
|
77
|
+
"OPENAI_API_KEY",
|
|
78
|
+
"OPENAI_BASE_URL",
|
|
79
|
+
"OPENROUTER_API_KEY",
|
|
80
|
+
"CODEX_MODEL",
|
|
81
|
+
"OPENCODE_MODEL",
|
|
82
|
+
"AZURE_OPENAI_API_KEY",
|
|
83
|
+
"AZURE_OPENAI_ENDPOINT",
|
|
84
|
+
"AZURE_OPENAI_API_VERSION",
|
|
85
|
+
"CODEX_CONFIG_EXTRA",
|
|
86
|
+
"OPENCODE_CONFIG_EXTRA",
|
|
87
|
+
"SUBAGENT_CLI",
|
|
88
|
+
):
|
|
89
|
+
os.environ.pop(key, None)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@pytest.mark.parametrize(
|
|
93
|
+
"cli,expected_keys,forbidden_keys,expected_opencode_config",
|
|
94
|
+
[
|
|
95
|
+
(
|
|
96
|
+
"claude",
|
|
97
|
+
{"ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_BASE_URL"},
|
|
98
|
+
{"OPENAI_API_KEY", "OPENROUTER_API_KEY", "OPENAI_BASE_URL", "OPENCODE_CONFIG", "OPENCODE_CONFIG_EXTRA", "CODEX_CONFIG_EXTRA"},
|
|
99
|
+
None, # OPENCODE_CONFIG must NOT be set for non-opencode runtimes
|
|
100
|
+
),
|
|
101
|
+
(
|
|
102
|
+
"codex",
|
|
103
|
+
{"OPENAI_API_KEY", "OPENAI_BASE_URL", "CODEX_CONFIG_EXTRA"},
|
|
104
|
+
{"ANTHROPIC_AUTH_TOKEN", "OPENROUTER_API_KEY", "OPENCODE_CONFIG", "OPENCODE_CONFIG_EXTRA"},
|
|
105
|
+
None,
|
|
106
|
+
),
|
|
107
|
+
(
|
|
108
|
+
"opencode",
|
|
109
|
+
{"OPENROUTER_API_KEY", "OPENAI_API_KEY", "OPENCODE_CONFIG_EXTRA"},
|
|
110
|
+
{"ANTHROPIC_AUTH_TOKEN", "CODEX_CONFIG_EXTRA"},
|
|
111
|
+
"/tmp/opencode.json", # Plan 06-01 Edit 1c — ROADMAP success #2
|
|
112
|
+
),
|
|
113
|
+
],
|
|
114
|
+
)
|
|
115
|
+
def test_passthrough_isolation(
|
|
116
|
+
cli, expected_keys, forbidden_keys, expected_opencode_config
|
|
117
|
+
):
|
|
118
|
+
"""With all three host auth env vars set, only the active CLI's allowlist
|
|
119
|
+
crosses into extra_env. Closes Pitfall 1 (auth bleed across CLIs).
|
|
120
|
+
|
|
121
|
+
For opencode, additionally verifies OPENCODE_CONFIG=/tmp/opencode.json is
|
|
122
|
+
pinned in the container Env so docker exec subprocesses inherit it
|
|
123
|
+
(Pitfall 7 — entrypoint export alone is insufficient)."""
|
|
124
|
+
overrides = {
|
|
125
|
+
"SUBAGENT_CLI": cli,
|
|
126
|
+
# Set ALL three families of auth env vars on the "host" (test process).
|
|
127
|
+
"ANTHROPIC_AUTH_TOKEN": "sk-ant-stub",
|
|
128
|
+
"ANTHROPIC_BASE_URL": "https://api.anthropic.example",
|
|
129
|
+
"ANTHROPIC_API_KEY": "sk-ant-api-stub",
|
|
130
|
+
"OPENAI_API_KEY": "sk-oai-stub",
|
|
131
|
+
"OPENAI_BASE_URL": "https://gateway.example",
|
|
132
|
+
"OPENROUTER_API_KEY": "sk-or-stub",
|
|
133
|
+
"OPENCODE_CONFIG_EXTRA": '{"stub":"opencode"}',
|
|
134
|
+
"CODEX_CONFIG_EXTRA": "[stub-codex]",
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
with patch.dict(os.environ, {}, clear=False):
|
|
138
|
+
_clear_phase6_auth_env()
|
|
139
|
+
for k, v in overrides.items():
|
|
140
|
+
os.environ[k] = v
|
|
141
|
+
|
|
142
|
+
# Re-import docker_manager so module-level os.getenv() reads (which build
|
|
143
|
+
# _PASSTHROUGH_BY_CLI and SUBAGENT_CLI) pick up the new env.
|
|
144
|
+
import docker_manager
|
|
145
|
+
importlib.reload(docker_manager)
|
|
146
|
+
|
|
147
|
+
client, fake_container = _build_mock_docker_client()
|
|
148
|
+
with patch("docker_manager.get_docker_client", return_value=client):
|
|
149
|
+
docker_manager._create_container("test-chat", "owui-chat-test")
|
|
150
|
+
|
|
151
|
+
# Capture the environment dict from containers.create kwargs (not .run —
|
|
152
|
+
# `.run` is the ephemeral mkdir shim; the actual sandbox uses .create).
|
|
153
|
+
assert client.containers.create.call_count == 1, (
|
|
154
|
+
"expected exactly one containers.create() invocation"
|
|
155
|
+
)
|
|
156
|
+
env_dict = client.containers.create.call_args.kwargs["environment"]
|
|
157
|
+
|
|
158
|
+
# Active allowlist landed.
|
|
159
|
+
for key in expected_keys:
|
|
160
|
+
assert key in env_dict, (
|
|
161
|
+
f"{cli}: expected {key} in extra_env, got keys={sorted(env_dict)}"
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Other CLIs' allowlists did NOT bleed.
|
|
165
|
+
for key in forbidden_keys:
|
|
166
|
+
assert key not in env_dict, (
|
|
167
|
+
f"{cli}: {key} leaked into extra_env (Pitfall 1 — auth bleed). "
|
|
168
|
+
f"Active allowlist must be _PASSTHROUGH_BY_CLI[{cli!r}] only."
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# SUBAGENT_CLI itself always lands (Phase 4 invariant — Phase 7 .bashrc
|
|
172
|
+
# autostart needs it).
|
|
173
|
+
assert env_dict.get("SUBAGENT_CLI") == cli
|
|
174
|
+
|
|
175
|
+
# OPENCODE_CONFIG pin contract (Plan 06-01 Edit 1c — ROADMAP success #2).
|
|
176
|
+
# For opencode: must equal "/tmp/opencode.json" so docker exec subprocesses
|
|
177
|
+
# inherit it. For other runtimes: must be ABSENT (no spurious env).
|
|
178
|
+
if expected_opencode_config is None:
|
|
179
|
+
assert "OPENCODE_CONFIG" not in env_dict, (
|
|
180
|
+
f"{cli}: OPENCODE_CONFIG should not be set for non-opencode "
|
|
181
|
+
f"runtime, got {env_dict.get('OPENCODE_CONFIG')!r}"
|
|
182
|
+
)
|
|
183
|
+
else:
|
|
184
|
+
assert env_dict.get("OPENCODE_CONFIG") == expected_opencode_config, (
|
|
185
|
+
f"{cli}: expected OPENCODE_CONFIG={expected_opencode_config!r} "
|
|
186
|
+
f"(so `docker exec opencode ...` inherits the config path and "
|
|
187
|
+
f"never falls back to ~/.local/share/opencode/auth.json — "
|
|
188
|
+
f"Pitfall 7), got {env_dict.get('OPENCODE_CONFIG')!r}"
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Defensive scrub of OpenCode auth.json was attempted (Plan 06-01 D4).
|
|
192
|
+
assert fake_container.exec_run.call_count >= 1, (
|
|
193
|
+
"expected the auth.json scrub exec_run call"
|
|
194
|
+
)
|
|
195
|
+
scrub_call_args = [
|
|
196
|
+
call.args[0] for call in fake_container.exec_run.call_args_list
|
|
197
|
+
]
|
|
198
|
+
assert any(
|
|
199
|
+
"rm -f /home/assistant/.local/share/opencode/auth.json" in arg
|
|
200
|
+
for arg in scrub_call_args
|
|
201
|
+
), f"defensive scrub call not found in exec_run history: {scrub_call_args}"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# SPDX-License-Identifier: FSL-1.1-Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Open Computer Use Contributors
|
|
3
|
+
"""
|
|
4
|
+
Tier 2 — /home/assistant/README.md is written on container creation.
|
|
5
|
+
|
|
6
|
+
We mock `docker` SDK interactions and just pin that
|
|
7
|
+
`_write_file_to_container` is called with the workdir + rendered prompt.
|
|
8
|
+
Exercising real Docker in unit tests is out of scope; E2E smoke is in the
|
|
9
|
+
verification script.
|
|
10
|
+
"""
|
|
11
|
+
import sys
|
|
12
|
+
import unittest
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from unittest.mock import MagicMock, patch
|
|
15
|
+
|
|
16
|
+
ROOT = Path(__file__).resolve().parent.parent.parent
|
|
17
|
+
sys.path.insert(0, str(ROOT / "computer-use-server"))
|
|
18
|
+
|
|
19
|
+
import docker_manager as dm # noqa: E402
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ReadmeWriterContract(unittest.TestCase):
|
|
23
|
+
def test_write_file_builds_valid_tar(self):
|
|
24
|
+
"""_write_file_to_container must put_archive a tar with exactly one
|
|
25
|
+
entry named after the filename, with the supplied body."""
|
|
26
|
+
container = MagicMock()
|
|
27
|
+
captured = {}
|
|
28
|
+
|
|
29
|
+
def _capture(path, tar_bytes):
|
|
30
|
+
captured["path"] = path
|
|
31
|
+
captured["tar"] = tar_bytes
|
|
32
|
+
# Real put_archive returns True on success; the helper now
|
|
33
|
+
# raises on False.
|
|
34
|
+
return True
|
|
35
|
+
|
|
36
|
+
container.put_archive.side_effect = _capture
|
|
37
|
+
|
|
38
|
+
dm._write_file_to_container(container, "/home/assistant", "README.md", "HELLO WORLD\n")
|
|
39
|
+
|
|
40
|
+
self.assertEqual(captured["path"], "/home/assistant")
|
|
41
|
+
# Decode the tar and assert its contents
|
|
42
|
+
import io, tarfile
|
|
43
|
+
tf = tarfile.open(fileobj=io.BytesIO(captured["tar"]), mode="r")
|
|
44
|
+
names = tf.getnames()
|
|
45
|
+
self.assertEqual(names, ["README.md"])
|
|
46
|
+
body = tf.extractfile("README.md").read().decode("utf-8")
|
|
47
|
+
self.assertEqual(body, "HELLO WORLD\n")
|
|
48
|
+
|
|
49
|
+
def test_readme_gets_rendered_prompt(self):
|
|
50
|
+
"""When render_system_prompt_sync is available, the docker_manager
|
|
51
|
+
writes its output verbatim."""
|
|
52
|
+
container = MagicMock()
|
|
53
|
+
captured = {}
|
|
54
|
+
|
|
55
|
+
def _capture(container_arg, path, filename, text):
|
|
56
|
+
captured["path"] = path
|
|
57
|
+
captured["filename"] = filename
|
|
58
|
+
captured["text"] = text
|
|
59
|
+
|
|
60
|
+
with patch.object(dm, "_write_file_to_container", side_effect=_capture), \
|
|
61
|
+
patch.object(dm, "render_system_prompt_sync",
|
|
62
|
+
return_value="# rendered prompt for chat-test\n"):
|
|
63
|
+
# Call the exact snippet the hook runs. Re-implement the try-block
|
|
64
|
+
# shape here rather than invoking the private _create_container
|
|
65
|
+
# (which would require full Docker env).
|
|
66
|
+
_, workdir = dm._get_container_user_and_workdir()
|
|
67
|
+
readme_text = dm.render_system_prompt_sync("chat-test", None)
|
|
68
|
+
dm._write_file_to_container(container, workdir, "README.md", readme_text)
|
|
69
|
+
|
|
70
|
+
self.assertEqual(captured["filename"], "README.md")
|
|
71
|
+
self.assertIn("chat-test", captured["text"])
|
|
72
|
+
self.assertIn(captured["path"], ("/home/assistant", "/root"))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
unittest.main()
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# SPDX-License-Identifier: FSL-1.1-Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Open Computer Use Contributors
|
|
3
|
+
"""
|
|
4
|
+
render_system_prompt is called on every MCP request (via MCPContextMiddleware
|
|
5
|
+
pre-render for Tier 4). It MUST NOT hit skill_manager's HTTP provider every
|
|
6
|
+
time. Pin the 60s (chat_id, user_email) cache behavior.
|
|
7
|
+
"""
|
|
8
|
+
import asyncio
|
|
9
|
+
import sys
|
|
10
|
+
import time
|
|
11
|
+
import unittest
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from unittest.mock import patch
|
|
14
|
+
|
|
15
|
+
ROOT = Path(__file__).resolve().parent.parent.parent
|
|
16
|
+
sys.path.insert(0, str(ROOT / "computer-use-server"))
|
|
17
|
+
|
|
18
|
+
import system_prompt # noqa: E402
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class RenderCacheContract(unittest.TestCase):
|
|
22
|
+
def setUp(self):
|
|
23
|
+
system_prompt.invalidate_render_cache()
|
|
24
|
+
|
|
25
|
+
def test_same_key_hits_cache(self):
|
|
26
|
+
calls = []
|
|
27
|
+
|
|
28
|
+
async def _fake_uncached(chat_id, user_email):
|
|
29
|
+
calls.append((chat_id, user_email))
|
|
30
|
+
return f"rendered:{chat_id}:{user_email}"
|
|
31
|
+
|
|
32
|
+
with patch.object(system_prompt, "_render_uncached", side_effect=_fake_uncached):
|
|
33
|
+
t1 = asyncio.run(system_prompt.render_system_prompt("c1", "u@x"))
|
|
34
|
+
t2 = asyncio.run(system_prompt.render_system_prompt("c1", "u@x"))
|
|
35
|
+
|
|
36
|
+
self.assertEqual(t1, t2)
|
|
37
|
+
self.assertEqual(len(calls), 1, "second call should hit cache")
|
|
38
|
+
|
|
39
|
+
def test_different_key_misses_cache(self):
|
|
40
|
+
async def _fake_uncached(chat_id, user_email):
|
|
41
|
+
return f"rendered:{chat_id}:{user_email}"
|
|
42
|
+
|
|
43
|
+
with patch.object(system_prompt, "_render_uncached", side_effect=_fake_uncached) as m:
|
|
44
|
+
asyncio.run(system_prompt.render_system_prompt("c1", "u@x"))
|
|
45
|
+
asyncio.run(system_prompt.render_system_prompt("c2", "u@x"))
|
|
46
|
+
asyncio.run(system_prompt.render_system_prompt("c1", None))
|
|
47
|
+
self.assertEqual(m.call_count, 3)
|
|
48
|
+
|
|
49
|
+
def test_invalidate_drops_entry(self):
|
|
50
|
+
calls = []
|
|
51
|
+
|
|
52
|
+
async def _fake_uncached(chat_id, user_email):
|
|
53
|
+
calls.append(1)
|
|
54
|
+
return "x"
|
|
55
|
+
|
|
56
|
+
with patch.object(system_prompt, "_render_uncached", side_effect=_fake_uncached):
|
|
57
|
+
asyncio.run(system_prompt.render_system_prompt("c1", None))
|
|
58
|
+
system_prompt.invalidate_render_cache("c1")
|
|
59
|
+
asyncio.run(system_prompt.render_system_prompt("c1", None))
|
|
60
|
+
|
|
61
|
+
self.assertEqual(len(calls), 2, "invalidate_render_cache('c1') must drop the cached entry")
|
|
62
|
+
|
|
63
|
+
def test_ttl_expires(self):
|
|
64
|
+
calls = []
|
|
65
|
+
|
|
66
|
+
async def _fake_uncached(chat_id, user_email):
|
|
67
|
+
calls.append(1)
|
|
68
|
+
return "y"
|
|
69
|
+
|
|
70
|
+
real_ttl = system_prompt._RENDER_TTL_SECONDS
|
|
71
|
+
try:
|
|
72
|
+
system_prompt._RENDER_TTL_SECONDS = 0.01 # 10ms for the test
|
|
73
|
+
with patch.object(system_prompt, "_render_uncached", side_effect=_fake_uncached):
|
|
74
|
+
asyncio.run(system_prompt.render_system_prompt("c1", None))
|
|
75
|
+
time.sleep(0.05)
|
|
76
|
+
asyncio.run(system_prompt.render_system_prompt("c1", None))
|
|
77
|
+
finally:
|
|
78
|
+
system_prompt._RENDER_TTL_SECONDS = real_ttl
|
|
79
|
+
|
|
80
|
+
self.assertEqual(len(calls), 2, "entry must be re-rendered after TTL")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
if __name__ == "__main__":
|
|
84
|
+
unittest.main()
|