@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,664 @@
|
|
|
1
|
+
# SPDX-License-Identifier: FSL-1.1-Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Open Computer Use Contributors
|
|
3
|
+
"""
|
|
4
|
+
Skill Manager for docker-ai.
|
|
5
|
+
|
|
6
|
+
Fetches user-enabled skills from mcp-settings-wrapper, caches ZIP files,
|
|
7
|
+
generates <available_skills> XML for system prompt, and builds Docker mounts.
|
|
8
|
+
"""
|
|
9
|
+
import asyncio
|
|
10
|
+
import hashlib
|
|
11
|
+
import io
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
import os
|
|
15
|
+
import shutil
|
|
16
|
+
import tempfile
|
|
17
|
+
import time
|
|
18
|
+
import zipfile
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Optional
|
|
22
|
+
|
|
23
|
+
import aiohttp
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
# Configuration
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
MCP_TOKENS_URL = os.getenv("MCP_TOKENS_URL", "")
|
|
32
|
+
MCP_TOKENS_API_KEY = os.getenv("MCP_TOKENS_API_KEY", "")
|
|
33
|
+
SKILLS_CACHE_DIR = Path(os.getenv("SKILLS_CACHE_DIR", "/data/skills-cache"))
|
|
34
|
+
# Host path for Docker volume mounts (computer-use-orchestrator sees /data/skills-cache,
|
|
35
|
+
# but Docker daemon needs the real host path for mounting into user containers)
|
|
36
|
+
SKILLS_CACHE_HOST_PATH = Path(os.getenv("SKILLS_CACHE_HOST_PATH", "/tmp/skills-cache"))
|
|
37
|
+
MANIFEST_PATH = SKILLS_CACHE_DIR / ".manifest.json"
|
|
38
|
+
USER_CONFIGS_DIR = SKILLS_CACHE_DIR / "_user_configs"
|
|
39
|
+
|
|
40
|
+
# Cache TTLs
|
|
41
|
+
MEMORY_CACHE_TTL = 60 # seconds — in-memory cache for user skill lists
|
|
42
|
+
API_TIMEOUT = 5 # seconds — HTTP timeout for API calls
|
|
43
|
+
ZIP_DOWNLOAD_TIMEOUT = 30 # seconds — HTTP timeout for ZIP download
|
|
44
|
+
MAX_ZIP_SIZE = 50 * 1024 * 1024 # 50 MB — max ZIP download size
|
|
45
|
+
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
# Data model
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class SkillInfo:
|
|
52
|
+
name: str
|
|
53
|
+
description: str
|
|
54
|
+
category: str # "public", "example", "user"
|
|
55
|
+
skill_path: Optional[str] = None # e.g. "public/pdf" for native
|
|
56
|
+
zip_sha256: Optional[str] = None # for user-uploaded skills
|
|
57
|
+
host_path: Optional[str] = None # resolved host path for Docker mount
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def location(self) -> str:
|
|
61
|
+
"""Path inside the container."""
|
|
62
|
+
if self.category == "user":
|
|
63
|
+
return f"/mnt/skills/user/{self.name}/SKILL.md"
|
|
64
|
+
elif self.skill_path:
|
|
65
|
+
return f"/mnt/skills/{self.skill_path}/SKILL.md"
|
|
66
|
+
else:
|
|
67
|
+
return f"/mnt/skills/public/{self.name}/SKILL.md"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
# English descriptions for native skills (for system prompt)
|
|
72
|
+
# Taken from the current hardcoded system_prompt.py block.
|
|
73
|
+
# ---------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
NATIVE_PROMPT_DESCRIPTIONS: dict[str, str] = {
|
|
76
|
+
"docx": (
|
|
77
|
+
"Comprehensive document creation, editing, and analysis with support for "
|
|
78
|
+
"tracked changes, comments, formatting preservation, and text extraction. "
|
|
79
|
+
"When You needs to work with professional documents (.docx files) for: "
|
|
80
|
+
"(1) Creating new documents, (2) Modifying or editing content, "
|
|
81
|
+
"(3) Working with tracked changes, (4) Adding comments, or any other document tasks"
|
|
82
|
+
),
|
|
83
|
+
"pdf": (
|
|
84
|
+
"Comprehensive PDF manipulation toolkit for extracting text and tables, "
|
|
85
|
+
"creating new PDFs, merging/splitting documents, and handling forms. "
|
|
86
|
+
"When You needs to fill in a PDF form or programmatically process, generate, "
|
|
87
|
+
"or analyze PDF documents at scale."
|
|
88
|
+
),
|
|
89
|
+
"pptx": (
|
|
90
|
+
"Presentation creation, editing, and analysis. When You needs to work with "
|
|
91
|
+
"presentations (.pptx files) for: (1) Creating new presentations, "
|
|
92
|
+
"(2) Modifying or editing content, (3) Working with layouts, "
|
|
93
|
+
"(4) Adding comments or speaker notes, or any other presentation tasks"
|
|
94
|
+
),
|
|
95
|
+
"xlsx": (
|
|
96
|
+
"Comprehensive spreadsheet creation, editing, and analysis with support for "
|
|
97
|
+
"formulas, formatting, data analysis, and visualization. When You needs to "
|
|
98
|
+
"work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: "
|
|
99
|
+
"(1) Creating new spreadsheets with formulas and formatting, "
|
|
100
|
+
"(2) Reading or analyzing data, (3) Modify existing spreadsheets while "
|
|
101
|
+
"preserving formulas, (4) Data analysis and visualization in spreadsheets, "
|
|
102
|
+
"or (5) Recalculating formulas"
|
|
103
|
+
),
|
|
104
|
+
"skill-creator": (
|
|
105
|
+
"Guide for creating effective skills. This skill should be used when users "
|
|
106
|
+
"want to create a new skill (or update an existing skill) that extends You's "
|
|
107
|
+
"capabilities with specialized knowledge, workflows, or tool integrations."
|
|
108
|
+
),
|
|
109
|
+
"gitlab-explorer": (
|
|
110
|
+
"Explore GitLab repositories using glab CLI and git commands. Use when user "
|
|
111
|
+
"asks to: clone repositories, search projects or code in GitLab, view merge "
|
|
112
|
+
"requests, explore project structure, check CI/CD pipelines, work with "
|
|
113
|
+
"issues, or analyze git history. IMPORTANT: Always run authentication check "
|
|
114
|
+
"script first before any GitLab operation."
|
|
115
|
+
),
|
|
116
|
+
"sub-agent": (
|
|
117
|
+
"COSTLY: Spawns a separate Claude CLI session (high API usage). "
|
|
118
|
+
"Use ONLY for complex CODE tasks requiring 10+ iterative tool calls: "
|
|
119
|
+
"multi-file refactoring with test loops, code review with fixes across "
|
|
120
|
+
"many files, iterative test-fix cycles. "
|
|
121
|
+
"Do NOT use for: presentations, research, documentation, simple edits, Git ops."
|
|
122
|
+
),
|
|
123
|
+
"describe-image": (
|
|
124
|
+
"Describe images (charts, diagrams, tables, screenshots) using Vision AI. "
|
|
125
|
+
"Use as fallback when you cannot read an image file directly."
|
|
126
|
+
),
|
|
127
|
+
"playwright-cli": (
|
|
128
|
+
"Automates browser interactions for web testing, form filling, screenshots, "
|
|
129
|
+
"and data extraction. Use when the user needs to navigate websites, interact "
|
|
130
|
+
"with web pages, fill forms, take screenshots, test web applications, "
|
|
131
|
+
"or extract information from web pages."
|
|
132
|
+
),
|
|
133
|
+
# Example skills
|
|
134
|
+
"algorithmic-art": (
|
|
135
|
+
"Create algorithmic art with p5.js using generative randomness and "
|
|
136
|
+
"interactive parameter tuning. Generative art, flow fields, particle systems."
|
|
137
|
+
),
|
|
138
|
+
"artifacts-builder": (
|
|
139
|
+
"Toolkit for building complex multi-component HTML artifacts using modern "
|
|
140
|
+
"frontend technologies (React, Tailwind CSS, shadcn/ui)."
|
|
141
|
+
),
|
|
142
|
+
"brand-guidelines": (
|
|
143
|
+
"Apply official brand colors and typography to artifacts. Use when brand "
|
|
144
|
+
"colors, style guidelines, visual design, or corporate standards are needed."
|
|
145
|
+
),
|
|
146
|
+
"canvas-design": (
|
|
147
|
+
"Create beautiful visual works in .png and .pdf formats using design "
|
|
148
|
+
"philosophy. For posters, illustrations, design, and other static visuals."
|
|
149
|
+
),
|
|
150
|
+
"internal-comms": (
|
|
151
|
+
"Resources for writing internal communications: status reports, leadership "
|
|
152
|
+
"updates, newsletters, FAQs, incident reports, project updates."
|
|
153
|
+
),
|
|
154
|
+
"mcp-builder": (
|
|
155
|
+
"Guide for building MCP servers (Model Context Protocol) that let LLMs "
|
|
156
|
+
"interact with external services. Python (FastMCP) or Node/TypeScript (MCP SDK)."
|
|
157
|
+
),
|
|
158
|
+
"single-cell-rna-qc": (
|
|
159
|
+
"Quality control for single-cell RNA-seq data (.h5ad or .h5 files) "
|
|
160
|
+
"following scverse best practices with MAD filtering and result visualization."
|
|
161
|
+
),
|
|
162
|
+
"slack-gif-creator": (
|
|
163
|
+
"Tools for creating animated GIFs optimized for Slack. "
|
|
164
|
+
"Size constraints, validation, and animation concepts."
|
|
165
|
+
),
|
|
166
|
+
"theme-factory": (
|
|
167
|
+
"Toolkit for styling artifacts. 10 ready-made themes with colors and "
|
|
168
|
+
"fonts for slides, documents, reports, HTML landing pages. "
|
|
169
|
+
"Can generate new themes on the fly."
|
|
170
|
+
),
|
|
171
|
+
"frontend-design": (
|
|
172
|
+
"Create distinctive, production-grade frontend interfaces with high design quality. "
|
|
173
|
+
"Use when building web components, pages, dashboards, React components, HTML/CSS layouts, "
|
|
174
|
+
"or styling/beautifying any web UI. Avoids generic AI aesthetics."
|
|
175
|
+
),
|
|
176
|
+
"doc-coauthoring": (
|
|
177
|
+
"Structured 3-stage workflow for co-authoring documents: context gathering, "
|
|
178
|
+
"section-by-section refinement with brainstorming, and reader testing via sub-agent. "
|
|
179
|
+
"Use for specs, PRDs, RFCs, proposals, technical documentation."
|
|
180
|
+
),
|
|
181
|
+
"webapp-testing": (
|
|
182
|
+
"Toolkit for testing local web applications using Playwright. "
|
|
183
|
+
"Verify frontend functionality, debug UI, capture screenshots, view browser logs. "
|
|
184
|
+
"Includes helper scripts for server lifecycle management."
|
|
185
|
+
),
|
|
186
|
+
"test-driven-development": (
|
|
187
|
+
"TDD workflow: write test first, watch it fail, write minimal code to pass. "
|
|
188
|
+
"Use for any feature or bugfix. Enforces discipline — no production code "
|
|
189
|
+
"without a failing test first."
|
|
190
|
+
),
|
|
191
|
+
"writing-skills": (
|
|
192
|
+
"TDD-based methodology for writing Claude Code skills. "
|
|
193
|
+
"Test with sub-agents, find gaps, refine. Meta-skill for skill creation."
|
|
194
|
+
),
|
|
195
|
+
"copy-editing": (
|
|
196
|
+
"Seven-sweep copy editing framework: clarity, flow, power, proof, voice, "
|
|
197
|
+
"conversion, consistency. Systematic improvement of marketing and business copy."
|
|
198
|
+
),
|
|
199
|
+
"social-content": (
|
|
200
|
+
"Social media content creation for LinkedIn, Twitter/X, Instagram. "
|
|
201
|
+
"Content calendars, repurposing, engagement optimization."
|
|
202
|
+
),
|
|
203
|
+
"product-marketing-context": (
|
|
204
|
+
"Create product marketing context document: positioning, ICP, messaging, "
|
|
205
|
+
"brand voice. Foundation for other marketing skills."
|
|
206
|
+
),
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
# Default public skills (fallback when API is unavailable)
|
|
210
|
+
DEFAULT_PUBLIC_SKILLS = [
|
|
211
|
+
"docx", "pdf", "pptx", "xlsx",
|
|
212
|
+
"skill-creator", "gitlab-explorer",
|
|
213
|
+
"sub-agent", "describe-image", "playwright-cli",
|
|
214
|
+
"frontend-design", "doc-coauthoring", "webapp-testing",
|
|
215
|
+
"test-driven-development",
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
# ---------------------------------------------------------------------------
|
|
219
|
+
# In-memory cache
|
|
220
|
+
# ---------------------------------------------------------------------------
|
|
221
|
+
|
|
222
|
+
_memory_cache: dict[str, tuple[float, list[SkillInfo]]] = {}
|
|
223
|
+
_email_locks: dict[str, asyncio.Lock] = {}
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _get_lock(email: str) -> asyncio.Lock:
|
|
227
|
+
"""Get or create an asyncio.Lock for the given email."""
|
|
228
|
+
if email not in _email_locks:
|
|
229
|
+
_email_locks[email] = asyncio.Lock()
|
|
230
|
+
return _email_locks[email]
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# ---------------------------------------------------------------------------
|
|
234
|
+
# Disk cache helpers
|
|
235
|
+
# ---------------------------------------------------------------------------
|
|
236
|
+
|
|
237
|
+
def _read_manifest() -> dict:
|
|
238
|
+
"""Read skills cache manifest from disk."""
|
|
239
|
+
try:
|
|
240
|
+
if MANIFEST_PATH.exists():
|
|
241
|
+
return json.loads(MANIFEST_PATH.read_text())
|
|
242
|
+
except Exception as e:
|
|
243
|
+
logger.warning(f"[SKILLS] Failed to read manifest: {e}")
|
|
244
|
+
return {}
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _write_manifest(manifest: dict) -> None:
|
|
248
|
+
"""Write skills cache manifest to disk."""
|
|
249
|
+
try:
|
|
250
|
+
SKILLS_CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
|
251
|
+
MANIFEST_PATH.write_text(json.dumps(manifest, indent=2))
|
|
252
|
+
except Exception as e:
|
|
253
|
+
logger.warning(f"[SKILLS] Failed to write manifest: {e}")
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _save_user_config_cache(email: str, data: dict) -> None:
|
|
257
|
+
"""Save user config response to disk for fallback."""
|
|
258
|
+
try:
|
|
259
|
+
USER_CONFIGS_DIR.mkdir(parents=True, exist_ok=True)
|
|
260
|
+
email_hash = hashlib.md5(email.encode()).hexdigest()
|
|
261
|
+
path = USER_CONFIGS_DIR / f"{email_hash}.json"
|
|
262
|
+
path.write_text(json.dumps(data))
|
|
263
|
+
except Exception as e:
|
|
264
|
+
logger.warning(f"[SKILLS] Failed to save user config cache: {e}")
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _load_user_config_cache(email: str) -> Optional[dict]:
|
|
268
|
+
"""Load user config from disk cache."""
|
|
269
|
+
try:
|
|
270
|
+
email_hash = hashlib.md5(email.encode()).hexdigest()
|
|
271
|
+
path = USER_CONFIGS_DIR / f"{email_hash}.json"
|
|
272
|
+
if path.exists():
|
|
273
|
+
return json.loads(path.read_text())
|
|
274
|
+
except Exception as e:
|
|
275
|
+
logger.warning(f"[SKILLS] Failed to load user config cache: {e}")
|
|
276
|
+
return None
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# ---------------------------------------------------------------------------
|
|
280
|
+
# API client
|
|
281
|
+
# ---------------------------------------------------------------------------
|
|
282
|
+
|
|
283
|
+
async def _fetch_user_config(email: str) -> Optional[dict]:
|
|
284
|
+
"""
|
|
285
|
+
Fetch user's enabled skills from mcp-settings-wrapper.
|
|
286
|
+
|
|
287
|
+
GET /api/internal/user-config/{email}
|
|
288
|
+
Returns: {"email": "...", "enabled_skills": [...]}
|
|
289
|
+
"""
|
|
290
|
+
if not MCP_TOKENS_API_KEY:
|
|
291
|
+
logger.warning("[SKILLS] MCP_TOKENS_API_KEY not configured")
|
|
292
|
+
return None
|
|
293
|
+
|
|
294
|
+
url = f"{MCP_TOKENS_URL}/api/internal/user-config/{email}"
|
|
295
|
+
headers = {"X-Internal-Api-Key": MCP_TOKENS_API_KEY}
|
|
296
|
+
|
|
297
|
+
try:
|
|
298
|
+
async with aiohttp.ClientSession() as session:
|
|
299
|
+
async with session.get(
|
|
300
|
+
url, headers=headers,
|
|
301
|
+
timeout=aiohttp.ClientTimeout(total=API_TIMEOUT)
|
|
302
|
+
) as resp:
|
|
303
|
+
if resp.status == 200:
|
|
304
|
+
data = await resp.json()
|
|
305
|
+
_save_user_config_cache(email, data)
|
|
306
|
+
return data
|
|
307
|
+
else:
|
|
308
|
+
logger.warning(f"[SKILLS] API returned {resp.status} for {email}")
|
|
309
|
+
except asyncio.TimeoutError:
|
|
310
|
+
logger.warning(f"[SKILLS] Timeout fetching config for {email}")
|
|
311
|
+
except Exception as e:
|
|
312
|
+
logger.warning(f"[SKILLS] Error fetching config: {e}")
|
|
313
|
+
|
|
314
|
+
return None
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
async def _download_skill_zip(name: str) -> Optional[bytes]:
|
|
318
|
+
"""
|
|
319
|
+
Download skill ZIP from mcp-settings-wrapper.
|
|
320
|
+
|
|
321
|
+
GET /api/internal/skills/{name}/download
|
|
322
|
+
Returns ZIP bytes or None.
|
|
323
|
+
"""
|
|
324
|
+
if not MCP_TOKENS_API_KEY:
|
|
325
|
+
return None
|
|
326
|
+
|
|
327
|
+
url = f"{MCP_TOKENS_URL}/api/internal/skills/{name}/download"
|
|
328
|
+
headers = {"X-Internal-Api-Key": MCP_TOKENS_API_KEY}
|
|
329
|
+
|
|
330
|
+
try:
|
|
331
|
+
async with aiohttp.ClientSession() as session:
|
|
332
|
+
async with session.get(
|
|
333
|
+
url, headers=headers,
|
|
334
|
+
timeout=aiohttp.ClientTimeout(total=ZIP_DOWNLOAD_TIMEOUT)
|
|
335
|
+
) as resp:
|
|
336
|
+
if resp.status != 200:
|
|
337
|
+
logger.warning(f"[SKILLS] Download {name}: HTTP {resp.status}")
|
|
338
|
+
return None
|
|
339
|
+
|
|
340
|
+
content_type = resp.headers.get("Content-Type", "")
|
|
341
|
+
if "application/json" in content_type:
|
|
342
|
+
# Native skill — already on filesystem
|
|
343
|
+
return None
|
|
344
|
+
|
|
345
|
+
# Read ZIP with size limit
|
|
346
|
+
data = bytearray()
|
|
347
|
+
async for chunk in resp.content.iter_chunked(8192):
|
|
348
|
+
data.extend(chunk)
|
|
349
|
+
if len(data) > MAX_ZIP_SIZE:
|
|
350
|
+
logger.warning(f"[SKILLS] ZIP too large for {name}, aborting")
|
|
351
|
+
return None
|
|
352
|
+
|
|
353
|
+
return bytes(data)
|
|
354
|
+
except asyncio.TimeoutError:
|
|
355
|
+
logger.warning(f"[SKILLS] Timeout downloading ZIP for {name}")
|
|
356
|
+
except Exception as e:
|
|
357
|
+
logger.warning(f"[SKILLS] Error downloading ZIP {name}: {e}")
|
|
358
|
+
|
|
359
|
+
return None
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
# ---------------------------------------------------------------------------
|
|
363
|
+
# ZIP cache management
|
|
364
|
+
# ---------------------------------------------------------------------------
|
|
365
|
+
|
|
366
|
+
async def ensure_skill_cached(skill: SkillInfo) -> Optional[str]:
|
|
367
|
+
"""
|
|
368
|
+
Ensure a user-uploaded skill is cached on disk.
|
|
369
|
+
|
|
370
|
+
For native skills (public/example), returns None — they're in the Docker image.
|
|
371
|
+
For user skills, downloads and extracts ZIP if needed.
|
|
372
|
+
|
|
373
|
+
Returns the host cache path or None.
|
|
374
|
+
"""
|
|
375
|
+
if skill.category != "user":
|
|
376
|
+
return None
|
|
377
|
+
|
|
378
|
+
cache_dir = SKILLS_CACHE_DIR / skill.name
|
|
379
|
+
manifest = _read_manifest()
|
|
380
|
+
|
|
381
|
+
# Check if already cached with matching SHA256
|
|
382
|
+
cached = manifest.get(skill.name, {})
|
|
383
|
+
if (
|
|
384
|
+
cached.get("sha256") == skill.zip_sha256
|
|
385
|
+
and cache_dir.exists()
|
|
386
|
+
and (cache_dir / "SKILL.md").exists()
|
|
387
|
+
):
|
|
388
|
+
skill.host_path = str(cache_dir)
|
|
389
|
+
return str(cache_dir)
|
|
390
|
+
|
|
391
|
+
# Download ZIP
|
|
392
|
+
logger.info(f"[SKILLS] Downloading ZIP for {skill.name} (sha256={skill.zip_sha256})")
|
|
393
|
+
zip_data = await _download_skill_zip(skill.name)
|
|
394
|
+
if not zip_data:
|
|
395
|
+
# If we have old cache, use it
|
|
396
|
+
if cache_dir.exists() and (cache_dir / "SKILL.md").exists():
|
|
397
|
+
logger.info(f"[SKILLS] Using stale cache for {skill.name}")
|
|
398
|
+
skill.host_path = str(cache_dir)
|
|
399
|
+
return str(cache_dir)
|
|
400
|
+
return None
|
|
401
|
+
|
|
402
|
+
# Extract atomically: unzip to temp dir, then rename
|
|
403
|
+
try:
|
|
404
|
+
SKILLS_CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
|
405
|
+
tmp_dir = tempfile.mkdtemp(dir=SKILLS_CACHE_DIR, prefix=f".{skill.name}-")
|
|
406
|
+
|
|
407
|
+
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
|
408
|
+
# Detect if ZIP has a top-level directory wrapper
|
|
409
|
+
names = zf.namelist()
|
|
410
|
+
prefix = ""
|
|
411
|
+
if names and all(n.startswith(names[0].split("/")[0] + "/") for n in names if n):
|
|
412
|
+
prefix = names[0].split("/")[0] + "/"
|
|
413
|
+
|
|
414
|
+
for member in zf.infolist():
|
|
415
|
+
if member.is_dir():
|
|
416
|
+
continue
|
|
417
|
+
# Strip prefix if present
|
|
418
|
+
rel_path = member.filename
|
|
419
|
+
if prefix and rel_path.startswith(prefix):
|
|
420
|
+
rel_path = rel_path[len(prefix):]
|
|
421
|
+
if not rel_path:
|
|
422
|
+
continue
|
|
423
|
+
|
|
424
|
+
target = os.path.join(tmp_dir, rel_path)
|
|
425
|
+
os.makedirs(os.path.dirname(target), exist_ok=True)
|
|
426
|
+
with open(target, "wb") as f:
|
|
427
|
+
f.write(zf.read(member.filename))
|
|
428
|
+
|
|
429
|
+
# Make files world-readable (container user is non-root)
|
|
430
|
+
os.chmod(tmp_dir, 0o755)
|
|
431
|
+
for root, dirs, files in os.walk(tmp_dir):
|
|
432
|
+
for d in dirs:
|
|
433
|
+
os.chmod(os.path.join(root, d), 0o755)
|
|
434
|
+
for f in files:
|
|
435
|
+
os.chmod(os.path.join(root, f), 0o644)
|
|
436
|
+
|
|
437
|
+
# Replace contents in-place (preserve directory inode for bind mounts)
|
|
438
|
+
if cache_dir.exists():
|
|
439
|
+
for item in os.listdir(str(cache_dir)):
|
|
440
|
+
item_path = os.path.join(str(cache_dir), item)
|
|
441
|
+
if os.path.isdir(item_path):
|
|
442
|
+
shutil.rmtree(item_path)
|
|
443
|
+
else:
|
|
444
|
+
os.remove(item_path)
|
|
445
|
+
for item in os.listdir(tmp_dir):
|
|
446
|
+
shutil.move(os.path.join(tmp_dir, item), os.path.join(str(cache_dir), item))
|
|
447
|
+
shutil.rmtree(tmp_dir, ignore_errors=True)
|
|
448
|
+
else:
|
|
449
|
+
os.rename(tmp_dir, str(cache_dir))
|
|
450
|
+
|
|
451
|
+
# Update manifest
|
|
452
|
+
manifest[skill.name] = {
|
|
453
|
+
"sha256": skill.zip_sha256,
|
|
454
|
+
"cached_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
455
|
+
}
|
|
456
|
+
_write_manifest(manifest)
|
|
457
|
+
|
|
458
|
+
skill.host_path = str(cache_dir)
|
|
459
|
+
logger.info(f"[SKILLS] Cached {skill.name} at {cache_dir}")
|
|
460
|
+
return str(cache_dir)
|
|
461
|
+
|
|
462
|
+
except Exception as e:
|
|
463
|
+
logger.error(f"[SKILLS] Error extracting ZIP for {skill.name}: {e}")
|
|
464
|
+
# Cleanup temp dir
|
|
465
|
+
if 'tmp_dir' in locals() and os.path.exists(tmp_dir):
|
|
466
|
+
shutil.rmtree(tmp_dir, ignore_errors=True)
|
|
467
|
+
return None
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
# ---------------------------------------------------------------------------
|
|
471
|
+
# Main entry points
|
|
472
|
+
# ---------------------------------------------------------------------------
|
|
473
|
+
|
|
474
|
+
def _build_default_skills() -> list[SkillInfo]:
|
|
475
|
+
"""Build default public skills list (fallback)."""
|
|
476
|
+
return [
|
|
477
|
+
SkillInfo(
|
|
478
|
+
name=name,
|
|
479
|
+
description=NATIVE_PROMPT_DESCRIPTIONS.get(name, ""),
|
|
480
|
+
category="public",
|
|
481
|
+
skill_path=f"public/{name}",
|
|
482
|
+
)
|
|
483
|
+
for name in DEFAULT_PUBLIC_SKILLS
|
|
484
|
+
]
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def _parse_api_skills(enabled_skills: list[dict]) -> list[SkillInfo]:
|
|
488
|
+
"""Parse API response into SkillInfo list, ensuring default public skills are always present."""
|
|
489
|
+
result = []
|
|
490
|
+
seen_names = set()
|
|
491
|
+
for s in enabled_skills:
|
|
492
|
+
result.append(SkillInfo(
|
|
493
|
+
name=s["name"],
|
|
494
|
+
description=s.get("description", ""),
|
|
495
|
+
category=s.get("category", "user"),
|
|
496
|
+
skill_path=s.get("skill_path"),
|
|
497
|
+
zip_sha256=s.get("zip_sha256"),
|
|
498
|
+
))
|
|
499
|
+
seen_names.add(s["name"])
|
|
500
|
+
|
|
501
|
+
# Ensure default public skills are always included
|
|
502
|
+
for name in DEFAULT_PUBLIC_SKILLS:
|
|
503
|
+
if name not in seen_names:
|
|
504
|
+
result.append(SkillInfo(
|
|
505
|
+
name=name,
|
|
506
|
+
description=NATIVE_PROMPT_DESCRIPTIONS.get(name, ""),
|
|
507
|
+
category="public",
|
|
508
|
+
skill_path=f"public/{name}",
|
|
509
|
+
))
|
|
510
|
+
|
|
511
|
+
return result
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
async def get_user_skills(email: Optional[str]) -> list[SkillInfo]:
|
|
515
|
+
"""
|
|
516
|
+
Get enabled skills for a user.
|
|
517
|
+
|
|
518
|
+
3-level fallback: in-memory cache → disk cache → hardcoded defaults.
|
|
519
|
+
"""
|
|
520
|
+
if not email:
|
|
521
|
+
return _build_default_skills()
|
|
522
|
+
|
|
523
|
+
# 1. In-memory cache
|
|
524
|
+
now = time.time()
|
|
525
|
+
cached = _memory_cache.get(email)
|
|
526
|
+
if cached and (now - cached[0]) < MEMORY_CACHE_TTL:
|
|
527
|
+
return cached[1]
|
|
528
|
+
|
|
529
|
+
# Serialize per-email to avoid duplicate API calls
|
|
530
|
+
lock = _get_lock(email)
|
|
531
|
+
async with lock:
|
|
532
|
+
# Double-check after acquiring lock
|
|
533
|
+
cached = _memory_cache.get(email)
|
|
534
|
+
if cached and (now - cached[0]) < MEMORY_CACHE_TTL:
|
|
535
|
+
return cached[1]
|
|
536
|
+
|
|
537
|
+
# 2. API call
|
|
538
|
+
data = await _fetch_user_config(email)
|
|
539
|
+
if data and "enabled_skills" in data:
|
|
540
|
+
skills = _parse_api_skills(data["enabled_skills"])
|
|
541
|
+
_memory_cache[email] = (time.time(), skills)
|
|
542
|
+
return skills
|
|
543
|
+
|
|
544
|
+
# 3. Disk cache fallback
|
|
545
|
+
disk_data = _load_user_config_cache(email)
|
|
546
|
+
if disk_data and "enabled_skills" in disk_data:
|
|
547
|
+
logger.info(f"[SKILLS] Using disk cache for {email}")
|
|
548
|
+
skills = _parse_api_skills(disk_data["enabled_skills"])
|
|
549
|
+
_memory_cache[email] = (time.time(), skills)
|
|
550
|
+
return skills
|
|
551
|
+
|
|
552
|
+
# 4. Hardcoded defaults
|
|
553
|
+
logger.warning(f"[SKILLS] Using default skills for {email}")
|
|
554
|
+
skills = _build_default_skills()
|
|
555
|
+
_memory_cache[email] = (time.time(), skills)
|
|
556
|
+
return skills
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
def get_user_skills_sync(email: Optional[str]) -> list[SkillInfo]:
|
|
560
|
+
"""
|
|
561
|
+
Synchronous version — reads only from cache, no API calls.
|
|
562
|
+
|
|
563
|
+
Used by _create_container() which runs in asyncio.to_thread.
|
|
564
|
+
"""
|
|
565
|
+
if not email:
|
|
566
|
+
return _build_default_skills()
|
|
567
|
+
|
|
568
|
+
# In-memory cache
|
|
569
|
+
cached = _memory_cache.get(email)
|
|
570
|
+
if cached:
|
|
571
|
+
return cached[1]
|
|
572
|
+
|
|
573
|
+
# Disk cache
|
|
574
|
+
disk_data = _load_user_config_cache(email)
|
|
575
|
+
if disk_data and "enabled_skills" in disk_data:
|
|
576
|
+
return _parse_api_skills(disk_data["enabled_skills"])
|
|
577
|
+
|
|
578
|
+
return _build_default_skills()
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
# ---------------------------------------------------------------------------
|
|
582
|
+
# XML generation for system prompt
|
|
583
|
+
# ---------------------------------------------------------------------------
|
|
584
|
+
|
|
585
|
+
MAX_DESCRIPTION_LEN = 300
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
def _get_skill_description(skill: SkillInfo) -> str:
|
|
589
|
+
"""Get English description for system prompt (native skills use hardcoded)."""
|
|
590
|
+
desc = NATIVE_PROMPT_DESCRIPTIONS.get(skill.name)
|
|
591
|
+
if desc:
|
|
592
|
+
return desc
|
|
593
|
+
# User-uploaded: use description from API, truncate if needed
|
|
594
|
+
desc = skill.description
|
|
595
|
+
if len(desc) > MAX_DESCRIPTION_LEN:
|
|
596
|
+
desc = desc[:MAX_DESCRIPTION_LEN - 3] + "..."
|
|
597
|
+
return desc
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
def build_available_skills_xml(skills: list[SkillInfo]) -> str:
|
|
601
|
+
"""
|
|
602
|
+
Generate <available_skills> XML block for system prompt.
|
|
603
|
+
|
|
604
|
+
Format matches the existing hardcoded block in system_prompt.py.
|
|
605
|
+
"""
|
|
606
|
+
lines = ["<available_skills>"]
|
|
607
|
+
for skill in skills:
|
|
608
|
+
desc = _get_skill_description(skill)
|
|
609
|
+
lines.append("<skill>")
|
|
610
|
+
lines.append(f"<name>\n{skill.name}\n</name>")
|
|
611
|
+
lines.append(f"<description>\n{desc}\n</description>")
|
|
612
|
+
lines.append(f"<location>\n{skill.location}\n</location>")
|
|
613
|
+
lines.append("</skill>")
|
|
614
|
+
lines.append("")
|
|
615
|
+
lines.append("</available_skills>")
|
|
616
|
+
return "\n".join(lines)
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
def build_sub_agent_skills_text(skills: list[SkillInfo]) -> str:
|
|
620
|
+
"""
|
|
621
|
+
Build skills list text for sub-agent system prompt.
|
|
622
|
+
|
|
623
|
+
Format: "- skill-name: location - Short description"
|
|
624
|
+
"""
|
|
625
|
+
lines = []
|
|
626
|
+
for skill in skills:
|
|
627
|
+
desc = _get_skill_description(skill)
|
|
628
|
+
# Truncate for sub-agent (shorter)
|
|
629
|
+
if len(desc) > 120:
|
|
630
|
+
desc = desc[:117] + "..."
|
|
631
|
+
lines.append(f"- {skill.name}: {skill.location} - {desc}")
|
|
632
|
+
return "\n".join(lines)
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
# ---------------------------------------------------------------------------
|
|
636
|
+
# Docker mounts for user skills
|
|
637
|
+
# ---------------------------------------------------------------------------
|
|
638
|
+
|
|
639
|
+
def get_skill_mounts(skills: list[SkillInfo]) -> dict:
|
|
640
|
+
"""
|
|
641
|
+
Build Docker volume mounts for user-uploaded skills.
|
|
642
|
+
|
|
643
|
+
Uses SKILLS_CACHE_HOST_PATH (not SKILLS_CACHE_DIR) because Docker daemon
|
|
644
|
+
runs on the host and needs host paths, while computer-use-orchestrator sees /data/skills-cache.
|
|
645
|
+
|
|
646
|
+
Returns dict compatible with docker-py volumes parameter:
|
|
647
|
+
{host_path: {"bind": container_path, "mode": "ro"}}
|
|
648
|
+
"""
|
|
649
|
+
mounts = {}
|
|
650
|
+
for skill in skills:
|
|
651
|
+
if skill.category != "user":
|
|
652
|
+
continue
|
|
653
|
+
|
|
654
|
+
# Verify the skill is actually cached (check via container path)
|
|
655
|
+
cache_dir = SKILLS_CACHE_DIR / skill.name
|
|
656
|
+
if not (cache_dir.exists() and (cache_dir / "SKILL.md").exists()):
|
|
657
|
+
continue
|
|
658
|
+
|
|
659
|
+
# Use HOST path for Docker volume source
|
|
660
|
+
host_path = str(SKILLS_CACHE_HOST_PATH / skill.name)
|
|
661
|
+
container_path = f"/mnt/skills/user/{skill.name}"
|
|
662
|
+
mounts[host_path] = {"bind": container_path, "mode": "ro"}
|
|
663
|
+
|
|
664
|
+
return mounts
|