@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.
Files changed (769) hide show
  1. package/.coderabbit.yaml +25 -0
  2. package/.dockerignore +95 -0
  3. package/.env.example +137 -0
  4. package/.githooks/pre-commit +68 -0
  5. package/.github/CODEOWNERS +125 -0
  6. package/.github/ISSUE_TEMPLATE/adr-proposal.md +41 -0
  7. package/.github/ISSUE_TEMPLATE/bug-report.md +49 -0
  8. package/.github/ISSUE_TEMPLATE/component-proposal.md +38 -0
  9. package/.github/ISSUE_TEMPLATE/config.yml +15 -0
  10. package/.github/ISSUE_TEMPLATE/dependency-proposal.md +59 -0
  11. package/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
  12. package/.github/ISSUE_TEMPLATE/nfr-proposal.md +44 -0
  13. package/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  14. package/.github/codeql/codeql-config.yml +11 -0
  15. package/.github/codeql/extensions/security-models/python-sanitizers.model.yml +17 -0
  16. package/.github/codeql/extensions/security-models/qlpack.yml +7 -0
  17. package/.github/dependabot.yml +23 -0
  18. package/.github/security-exceptions.yml +23 -0
  19. package/.github/workflows/build.yml +420 -0
  20. package/.github/workflows/codeql.yml +33 -0
  21. package/.github/workflows/contracts-lint.yml +90 -0
  22. package/.github/workflows/docs-lint.yml +151 -0
  23. package/.github/workflows/helm.yml +131 -0
  24. package/.github/workflows/identity-lint.yml +30 -0
  25. package/.github/workflows/release-chart.yml +177 -0
  26. package/.github/workflows/release.yml +95 -0
  27. package/.github/workflows/security.yml +332 -0
  28. package/.github/workflows/stale.yml +31 -0
  29. package/.github/workflows/supply-chain.yml +242 -0
  30. package/.gitleaks.toml +53 -0
  31. package/.markdownlint.yaml +51 -0
  32. package/.semgrepignore +85 -0
  33. package/.vale/styles/Architecture/ap13-data-class-substrate.yml +12 -0
  34. package/.vale/styles/Architecture/banned-phrases.yml +23 -0
  35. package/.vale/styles/Architecture/banned-vocab.yml +23 -0
  36. package/.vale/styles/Architecture/marketing-tone.yml +19 -0
  37. package/.vale.ini +18 -0
  38. package/CHANGELOG.md +411 -0
  39. package/CLAUDE.md +218 -0
  40. package/CONTRIBUTING.md +82 -0
  41. package/Dockerfile +676 -0
  42. package/LICENSE +98 -0
  43. package/LICENSE-APACHE +202 -0
  44. package/LICENSE-MIT +21 -0
  45. package/NOTICE +36 -0
  46. package/README.md +516 -0
  47. package/SECURITY.md +45 -0
  48. package/THIRD-PARTY-LICENSES.md +14 -0
  49. package/apt-packages.txt +108 -0
  50. package/computer-use-server/.dockerignore +13 -0
  51. package/computer-use-server/Dockerfile +44 -0
  52. package/computer-use-server/README.md +84 -0
  53. package/computer-use-server/app.py +1544 -0
  54. package/computer-use-server/bin/list-subagent-models +449 -0
  55. package/computer-use-server/cli-defaults/README.md +31 -0
  56. package/computer-use-server/cli-defaults/codex.json +7 -0
  57. package/computer-use-server/cli-defaults/opencode.json +18 -0
  58. package/computer-use-server/cli_adapters/__init__.py +46 -0
  59. package/computer-use-server/cli_adapters/claude.py +163 -0
  60. package/computer-use-server/cli_adapters/codex.py +163 -0
  61. package/computer-use-server/cli_adapters/opencode.py +169 -0
  62. package/computer-use-server/cli_adapters/result.py +34 -0
  63. package/computer-use-server/cli_runtime.py +316 -0
  64. package/computer-use-server/context_vars.py +24 -0
  65. package/computer-use-server/docker_manager.py +1100 -0
  66. package/computer-use-server/docs_html.py +12 -0
  67. package/computer-use-server/mcp_resources.py +170 -0
  68. package/computer-use-server/mcp_tools.py +1430 -0
  69. package/computer-use-server/requirements.txt +17 -0
  70. package/computer-use-server/security.py +50 -0
  71. package/computer-use-server/skill_manager.py +664 -0
  72. package/computer-use-server/static/browser-viewer.js +445 -0
  73. package/computer-use-server/static/chart.umd.js +14 -0
  74. package/computer-use-server/static/docs.html +203 -0
  75. package/computer-use-server/static/github-dark.min.css +10 -0
  76. package/computer-use-server/static/github.min.css +10 -0
  77. package/computer-use-server/static/highlight.min.js +1213 -0
  78. package/computer-use-server/static/highlightjs-line-numbers.min.js +1 -0
  79. package/computer-use-server/static/icons.js +74 -0
  80. package/computer-use-server/static/jszip.min.js +13 -0
  81. package/computer-use-server/static/katex/auto-render.min.js +1 -0
  82. package/computer-use-server/static/katex/fonts/KaTeX_AMS-Regular.ttf +0 -0
  83. package/computer-use-server/static/katex/fonts/KaTeX_AMS-Regular.woff +0 -0
  84. package/computer-use-server/static/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  85. package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  86. package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  87. package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  88. package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  89. package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  90. package/computer-use-server/static/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  91. package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  92. package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  93. package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  94. package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  95. package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  96. package/computer-use-server/static/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  97. package/computer-use-server/static/katex/fonts/KaTeX_Main-Bold.ttf +0 -0
  98. package/computer-use-server/static/katex/fonts/KaTeX_Main-Bold.woff +0 -0
  99. package/computer-use-server/static/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  100. package/computer-use-server/static/katex/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  101. package/computer-use-server/static/katex/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  102. package/computer-use-server/static/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  103. package/computer-use-server/static/katex/fonts/KaTeX_Main-Italic.ttf +0 -0
  104. package/computer-use-server/static/katex/fonts/KaTeX_Main-Italic.woff +0 -0
  105. package/computer-use-server/static/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  106. package/computer-use-server/static/katex/fonts/KaTeX_Main-Regular.ttf +0 -0
  107. package/computer-use-server/static/katex/fonts/KaTeX_Main-Regular.woff +0 -0
  108. package/computer-use-server/static/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  109. package/computer-use-server/static/katex/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  110. package/computer-use-server/static/katex/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  111. package/computer-use-server/static/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  112. package/computer-use-server/static/katex/fonts/KaTeX_Math-Italic.ttf +0 -0
  113. package/computer-use-server/static/katex/fonts/KaTeX_Math-Italic.woff +0 -0
  114. package/computer-use-server/static/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  115. package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  116. package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  117. package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  118. package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  119. package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  120. package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  121. package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  122. package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  123. package/computer-use-server/static/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  124. package/computer-use-server/static/katex/fonts/KaTeX_Script-Regular.ttf +0 -0
  125. package/computer-use-server/static/katex/fonts/KaTeX_Script-Regular.woff +0 -0
  126. package/computer-use-server/static/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  127. package/computer-use-server/static/katex/fonts/KaTeX_Size1-Regular.ttf +0 -0
  128. package/computer-use-server/static/katex/fonts/KaTeX_Size1-Regular.woff +0 -0
  129. package/computer-use-server/static/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  130. package/computer-use-server/static/katex/fonts/KaTeX_Size2-Regular.ttf +0 -0
  131. package/computer-use-server/static/katex/fonts/KaTeX_Size2-Regular.woff +0 -0
  132. package/computer-use-server/static/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  133. package/computer-use-server/static/katex/fonts/KaTeX_Size3-Regular.ttf +0 -0
  134. package/computer-use-server/static/katex/fonts/KaTeX_Size3-Regular.woff +0 -0
  135. package/computer-use-server/static/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  136. package/computer-use-server/static/katex/fonts/KaTeX_Size4-Regular.ttf +0 -0
  137. package/computer-use-server/static/katex/fonts/KaTeX_Size4-Regular.woff +0 -0
  138. package/computer-use-server/static/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  139. package/computer-use-server/static/katex/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  140. package/computer-use-server/static/katex/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  141. package/computer-use-server/static/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  142. package/computer-use-server/static/katex/katex.min.css +1 -0
  143. package/computer-use-server/static/katex/katex.min.js +1 -0
  144. package/computer-use-server/static/locale.js +242 -0
  145. package/computer-use-server/static/mammoth.browser.min.js +21 -0
  146. package/computer-use-server/static/marked.min.js +6 -0
  147. package/computer-use-server/static/mermaid.min.js +2811 -0
  148. package/computer-use-server/static/pdf.min.js +22 -0
  149. package/computer-use-server/static/pdf.worker.min.js +22 -0
  150. package/computer-use-server/static/pptxviewjs.min.js +1 -0
  151. package/computer-use-server/static/preact-htm.min.js +1 -0
  152. package/computer-use-server/static/preview.css +1030 -0
  153. package/computer-use-server/static/preview.js +1522 -0
  154. package/computer-use-server/static/xlsx.full.min.js +22 -0
  155. package/computer-use-server/static/xterm-addon-fit.min.js +2 -0
  156. package/computer-use-server/static/xterm-addon-web-links.min.js +2 -0
  157. package/computer-use-server/static/xterm.css +218 -0
  158. package/computer-use-server/static/xterm.min.js +2 -0
  159. package/computer-use-server/system_prompt.py +761 -0
  160. package/computer-use-server/uploads.py +82 -0
  161. package/contracts/README.md +53 -0
  162. package/contracts/audit/audit-fanin.asyncapi.yaml +407 -0
  163. package/contracts/exec/exec-channel.schema.json +240 -0
  164. package/contracts/mcp/2025-06-18/ocu-constraints.schema.json +178 -0
  165. package/contracts/storage/file-artifact-api.schema.json +390 -0
  166. package/contracts/storage/file-ops.schema.json +217 -0
  167. package/contracts/storage/mount-config.schema.json +197 -0
  168. package/cron/Dockerfile +15 -0
  169. package/cron/cleanup-quick.sh +21 -0
  170. package/cron/cleanup.sh +127 -0
  171. package/data/outputs/.gitkeep +0 -0
  172. package/data/uploads/.gitkeep +0 -0
  173. package/docker-compose.test.yml +54 -0
  174. package/docker-compose.webui.yml +77 -0
  175. package/docker-compose.yml +96 -0
  176. package/docs/CLOUD.md +29 -0
  177. package/docs/COMPARISON.md +128 -0
  178. package/docs/DOCKER.md +469 -0
  179. package/docs/DYNAMIC-SKILLS.md +77 -0
  180. package/docs/FEATURES.md +100 -0
  181. package/docs/INSTALL.md +111 -0
  182. package/docs/KNOWN-BUGS.md +86 -0
  183. package/docs/MCP.md +320 -0
  184. package/docs/SCREENSHOTS.md +39 -0
  185. package/docs/SKILLS-USER-GUIDE.md +86 -0
  186. package/docs/SKILLS.md +483 -0
  187. package/docs/TERMINAL-TAB.md +56 -0
  188. package/docs/architecture/02-trust-boundaries.md +224 -0
  189. package/docs/architecture/03-c4-context.md +61 -0
  190. package/docs/architecture/04-bounded-contexts.md +119 -0
  191. package/docs/architecture/05-c4-container.md +88 -0
  192. package/docs/architecture/06-threat-model.md +172 -0
  193. package/docs/architecture/08-contracts.md +105 -0
  194. package/docs/architecture/MANIFESTO.md +38 -0
  195. package/docs/architecture/PROCESS.md +64 -0
  196. package/docs/architecture/README.md +37 -0
  197. package/docs/architecture/adr/0000-template.md +65 -0
  198. package/docs/architecture/adr/0001-layer-0-gate-legacy-exclusion.md +75 -0
  199. package/docs/architecture/adr/0002-session-view-descriptor.md +57 -0
  200. package/docs/architecture/adr/0003-sandbox-runtime-tier-ladder.md +63 -0
  201. package/docs/architecture/adr/0004-operator-authentication-substrate.md +63 -0
  202. package/docs/architecture/adr/0005-egress-credential-delivery-envoy-sds.md +62 -0
  203. package/docs/architecture/adr/0006-egress-forward-proxy-substrate.md +65 -0
  204. package/docs/architecture/adr/0007-egress-auth-mechanism.md +72 -0
  205. package/docs/architecture/adr/0008-session-egress-attribution.md +59 -0
  206. package/docs/architecture/adr/0009-audit-pipeline-pluggable-by-contract.md +76 -0
  207. package/docs/architecture/adr/0010-storage-backend-pluggable-adapter.md +60 -0
  208. package/docs/architecture/adr/0011-storage-egress-lane.md +67 -0
  209. package/docs/architecture/adr/0012-implementation-language.md +67 -0
  210. package/docs/architecture/adr/0020-sandbox-image-provisioning.md +82 -0
  211. package/docs/architecture/adr/README.md +53 -0
  212. package/docs/architecture/compliance/.gitkeep +0 -0
  213. package/docs/architecture/components/00-overview.md +42 -0
  214. package/docs/architecture/components/0000-template.md +50 -0
  215. package/docs/architecture/components/01-mcp-gateway.md +80 -0
  216. package/docs/architecture/components/02-control-operator-api.md +80 -0
  217. package/docs/architecture/components/04-storage-broker.md +104 -0
  218. package/docs/architecture/components/05-session-sandbox.md +93 -0
  219. package/docs/architecture/components/06-egress-trust-edge.md +95 -0
  220. package/docs/architecture/components/07-audit-pipeline.md +110 -0
  221. package/docs/architecture/diagrams/.gitkeep +0 -0
  222. package/docs/architecture/diagrams/02-trust-boundaries.mmd +111 -0
  223. package/docs/architecture/diagrams/06-threat-model.mmd +41 -0
  224. package/docs/architecture/diagrams/08-contracts.mmd +47 -0
  225. package/docs/architecture/diagrams/c4-container.mmd +59 -0
  226. package/docs/architecture/diagrams/c4-context.mmd +46 -0
  227. package/docs/architecture/glossary.md +172 -0
  228. package/docs/architecture/manifesto/.gitkeep +0 -0
  229. package/docs/architecture/manifesto/01-audience-and-buyer.md +57 -0
  230. package/docs/architecture/manifesto/02-nfrs.md +325 -0
  231. package/docs/architecture/manifesto/03-non-negotiables.md +35 -0
  232. package/docs/architecture/manifesto/04-non-goals.md +23 -0
  233. package/docs/architecture/manifesto/05-licensing-posture.md +61 -0
  234. package/docs/architecture/manifesto/06-starter-mode-policy.md +49 -0
  235. package/docs/architecture/manifesto/07-governance.md +60 -0
  236. package/docs/architecture/primitives-backlog.md +51 -0
  237. package/docs/architecture.svg +117 -0
  238. package/docs/claude-code-gateway.md +173 -0
  239. package/docs/cli-config-templates.md +240 -0
  240. package/docs/data-flow.svg +72 -0
  241. package/docs/demo-landing-page.gif +0 -0
  242. package/docs/demo-qwen-trending.gif +0 -0
  243. package/docs/dynamic-skills.svg +77 -0
  244. package/docs/file-flow.svg +126 -0
  245. package/docs/future-architecture/README.md +152 -0
  246. package/docs/future-architecture/adr/0001-control-plane-language-go.md +80 -0
  247. package/docs/future-architecture/adr/0002-guest-agent-language-go.md +84 -0
  248. package/docs/future-architecture/adr/0003-docker-poc-first-then-k8s.md +37 -0
  249. package/docs/future-architecture/adr/0004-pluggable-runtime-via-runtimeclass.md +34 -0
  250. package/docs/future-architecture/adr/0005-mcp-as-control-plane-gateway.md +34 -0
  251. package/docs/future-architecture/adr/0006-no-agpl-no-bsl-dependencies.md +41 -0
  252. package/docs/future-architecture/adr/0007-superseded-by-future-architecture.md +37 -0
  253. package/docs/future-architecture/adr/0008-internal-grpc-external-rest-mcp.md +106 -0
  254. package/docs/future-architecture/adr/0009-external-protocol-dialects.md +94 -0
  255. package/docs/future-architecture/adr/0010-lambda-as-inspiration-not-runtime.md +86 -0
  256. package/docs/future-architecture/adr/0011-kata-as-first-class-dind-runtime.md +84 -0
  257. package/docs/future-architecture/antipatterns.md +552 -0
  258. package/docs/future-architecture/architecture/01-layers.md +109 -0
  259. package/docs/future-architecture/architecture/02-layer4-control-plane.md +122 -0
  260. package/docs/future-architecture/architecture/03-layer3-providers.md +174 -0
  261. package/docs/future-architecture/architecture/04-layer2-runtimes.md +114 -0
  262. package/docs/future-architecture/architecture/04b-credential-broker.md +153 -0
  263. package/docs/future-architecture/architecture/05-layer1-guest-agent.md +138 -0
  264. package/docs/future-architecture/architecture/06-storage.md +134 -0
  265. package/docs/future-architecture/architecture/07-security.md +194 -0
  266. package/docs/future-architecture/architecture/08-networking.md +149 -0
  267. package/docs/future-architecture/architecture/09-templates.md +122 -0
  268. package/docs/future-architecture/architecture/10-observability.md +121 -0
  269. package/docs/future-architecture/design-notes.md +72 -0
  270. package/docs/future-architecture/gaps.md +281 -0
  271. package/docs/future-architecture/phase-template.md +123 -0
  272. package/docs/future-architecture/references.md +225 -0
  273. package/docs/future-architecture/research/01-kata-containers.md +100 -0
  274. package/docs/future-architecture/research/02-e2b-infra.md +133 -0
  275. package/docs/future-architecture/research/03-coder.md +115 -0
  276. package/docs/future-architecture/research/04-cloud-hypervisor.md +99 -0
  277. package/docs/future-architecture/research/05-firecracker.md +114 -0
  278. package/docs/future-architecture/research/06-agent-sandbox.md +142 -0
  279. package/docs/future-architecture/research/07-chromedp.md +78 -0
  280. package/docs/future-architecture/research/08-microsandbox.md +78 -0
  281. package/docs/future-architecture/research/09-agentbox.md +135 -0
  282. package/docs/future-architecture/research/10-sysbox.md +100 -0
  283. package/docs/future-architecture/research/11-firecracker-containerd.md +93 -0
  284. package/docs/future-architecture/research/12-docker-socket-proxy.md +59 -0
  285. package/docs/future-architecture/research/14-e2b-desktop-and-surf.md +107 -0
  286. package/docs/future-architecture/research/18-open-webui-terminals-observed.md +135 -0
  287. package/docs/future-architecture/research/bank-buyer.md +96 -0
  288. package/docs/future-architecture/research/enthusiast-audience.md +106 -0
  289. package/docs/future-architecture/research/proof-uipath-anthropic-2026-05.md +76 -0
  290. package/docs/future-architecture/research/widemoat-thesis-advisor.md +124 -0
  291. package/docs/future-architecture/roadmap.md +438 -0
  292. package/docs/kata-runtime.md +267 -0
  293. package/docs/kubernetes.md +86 -0
  294. package/docs/logo.png +0 -0
  295. package/docs/multi-cli.md +161 -0
  296. package/docs/openwebui-filter.md +134 -0
  297. package/docs/roadmap/implementation-roadmap.md +104 -0
  298. package/docs/sandbox-contents.svg +229 -0
  299. package/docs/screenshots/01-create-document.png +0 -0
  300. package/docs/screenshots/02-file-preview.png +0 -0
  301. package/docs/screenshots/03-browser-viewer.png +0 -0
  302. package/docs/screenshots/04-sub-agent-terminal.png +0 -0
  303. package/docs/screenshots/05-chat-overview.png +0 -0
  304. package/docs/screenshots/06-sub-agent-dashboard.png +0 -0
  305. package/docs/screenshots/07-frontend-design-skill.png +0 -0
  306. package/docs/screenshots/08-pptx-skill.png +0 -0
  307. package/docs/screenshots/09-skill-creator.png +0 -0
  308. package/docs/screenshots/10-data-chart.png +0 -0
  309. package/docs/shared-browser.svg +102 -0
  310. package/docs/system-prompt.md +113 -0
  311. package/docs/terminal-flow.svg +69 -0
  312. package/examples/helm/README.md +20 -0
  313. package/examples/helm/standalone/values.yaml +49 -0
  314. package/examples/helm/with-open-webui/README.md +99 -0
  315. package/examples/helm/with-open-webui/values-computer-use.yaml +32 -0
  316. package/examples/helm/with-open-webui/values-open-webui.yaml +67 -0
  317. package/fonts/NotoEmoji-Regular.ttf +0 -0
  318. package/helm/computer-use-server/.helmignore +17 -0
  319. package/helm/computer-use-server/Chart.yaml +32 -0
  320. package/helm/computer-use-server/README.md +211 -0
  321. package/helm/computer-use-server/templates/NOTES.txt +66 -0
  322. package/helm/computer-use-server/templates/_helpers.tpl +115 -0
  323. package/helm/computer-use-server/templates/configmap-dind-init.yaml +82 -0
  324. package/helm/computer-use-server/templates/configmap.yaml +18 -0
  325. package/helm/computer-use-server/templates/deployment.yaml +248 -0
  326. package/helm/computer-use-server/templates/ingress.yaml +38 -0
  327. package/helm/computer-use-server/templates/networkpolicy.yaml +50 -0
  328. package/helm/computer-use-server/templates/pdb.yaml +16 -0
  329. package/helm/computer-use-server/templates/pvc-data.yaml +20 -0
  330. package/helm/computer-use-server/templates/pvc-skills-cache.yaml +20 -0
  331. package/helm/computer-use-server/templates/pvc-user-data.yaml +20 -0
  332. package/helm/computer-use-server/templates/pvc-var-lib-docker.yaml +27 -0
  333. package/helm/computer-use-server/templates/secret.yaml +23 -0
  334. package/helm/computer-use-server/templates/service.yaml +22 -0
  335. package/helm/computer-use-server/templates/serviceaccount.yaml +15 -0
  336. package/helm/computer-use-server/templates/tests/test-health.yaml +23 -0
  337. package/helm/computer-use-server/values.schema.json +183 -0
  338. package/helm/computer-use-server/values.yaml +297 -0
  339. package/lychee.toml +36 -0
  340. package/openwebui/Dockerfile +52 -0
  341. package/openwebui/README.md +38 -0
  342. package/openwebui/functions/README.md +48 -0
  343. package/openwebui/functions/computer_link_filter.py +487 -0
  344. package/openwebui/init.sh +305 -0
  345. package/openwebui/patches/README.md +44 -0
  346. package/openwebui/patches/fix_artifacts_auto_show.py +441 -0
  347. package/openwebui/patches/fix_attached_files_position.py +87 -0
  348. package/openwebui/patches/fix_large_tool_args.py +156 -0
  349. package/openwebui/patches/fix_large_tool_results.py +289 -0
  350. package/openwebui/patches/fix_preview_url_detection.py +230 -0
  351. package/openwebui/patches/fix_skip_embedding_chat_files.py +229 -0
  352. package/openwebui/patches/fix_skip_rag_files_native_fc.py +100 -0
  353. package/openwebui/patches/fix_tool_loop_errors.py +510 -0
  354. package/package.json +39 -0
  355. package/requirements.txt +112 -0
  356. package/scripts/check-config.sh +141 -0
  357. package/scripts/docs-lint/ai-slop-detector.sh +202 -0
  358. package/scripts/docs-lint/architecture-tree-whitelist.sh +131 -0
  359. package/scripts/docs-lint/ascii-diagram-detector.sh +58 -0
  360. package/scripts/docs-lint/front-matter-validator.sh +97 -0
  361. package/scripts/docs-lint/gitignored-ref-detector.sh +122 -0
  362. package/scripts/docs-lint/identity-email-detector.sh +48 -0
  363. package/scripts/docs-lint/test-linters.sh +354 -0
  364. package/scripts/docs-lint/wc-budget.sh +61 -0
  365. package/scripts/githooks/pre-push +75 -0
  366. package/server.json +13 -0
  367. package/settings-wrapper/Dockerfile +9 -0
  368. package/settings-wrapper/README.md +119 -0
  369. package/settings-wrapper/app.py +113 -0
  370. package/settings-wrapper/requirements.txt +2 -0
  371. package/settings-wrapper/skills.json +25 -0
  372. package/skills/README.md +46 -0
  373. package/skills/examples/algorithmic-art/SKILL.md +405 -0
  374. package/skills/examples/algorithmic-art/templates/generator_template.js +223 -0
  375. package/skills/examples/algorithmic-art/templates/viewer.html +601 -0
  376. package/skills/examples/artifacts-builder/SKILL.md +74 -0
  377. package/skills/examples/artifacts-builder/scripts/bundle-artifact.sh +54 -0
  378. package/skills/examples/artifacts-builder/scripts/init-artifact.sh +322 -0
  379. package/skills/examples/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  380. package/skills/examples/canvas-design/LICENSE.txt +202 -0
  381. package/skills/examples/canvas-design/SKILL.md +130 -0
  382. package/skills/examples/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  383. package/skills/examples/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  384. package/skills/examples/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  385. package/skills/examples/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
  386. package/skills/examples/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  387. package/skills/examples/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
  388. package/skills/examples/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  389. package/skills/examples/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  390. package/skills/examples/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  391. package/skills/examples/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  392. package/skills/examples/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  393. package/skills/examples/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  394. package/skills/examples/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  395. package/skills/examples/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  396. package/skills/examples/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
  397. package/skills/examples/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  398. package/skills/examples/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
  399. package/skills/examples/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  400. package/skills/examples/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  401. package/skills/examples/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
  402. package/skills/examples/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  403. package/skills/examples/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
  404. package/skills/examples/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  405. package/skills/examples/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  406. package/skills/examples/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  407. package/skills/examples/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  408. package/skills/examples/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  409. package/skills/examples/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  410. package/skills/examples/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  411. package/skills/examples/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  412. package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  413. package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  414. package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  415. package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  416. package/skills/examples/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  417. package/skills/examples/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  418. package/skills/examples/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  419. package/skills/examples/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
  420. package/skills/examples/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  421. package/skills/examples/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  422. package/skills/examples/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  423. package/skills/examples/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  424. package/skills/examples/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  425. package/skills/examples/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  426. package/skills/examples/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
  427. package/skills/examples/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  428. package/skills/examples/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  429. package/skills/examples/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  430. package/skills/examples/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  431. package/skills/examples/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  432. package/skills/examples/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  433. package/skills/examples/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  434. package/skills/examples/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  435. package/skills/examples/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
  436. package/skills/examples/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  437. package/skills/examples/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  438. package/skills/examples/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  439. package/skills/examples/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  440. package/skills/examples/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  441. package/skills/examples/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  442. package/skills/examples/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  443. package/skills/examples/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
  444. package/skills/examples/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
  445. package/skills/examples/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  446. package/skills/examples/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  447. package/skills/examples/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
  448. package/skills/examples/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  449. package/skills/examples/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
  450. package/skills/examples/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  451. package/skills/examples/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  452. package/skills/examples/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
  453. package/skills/examples/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  454. package/skills/examples/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  455. package/skills/examples/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  456. package/skills/examples/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  457. package/skills/examples/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  458. package/skills/examples/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  459. package/skills/examples/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
  460. package/skills/examples/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  461. package/skills/examples/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  462. package/skills/examples/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  463. package/skills/examples/copy-editing/SKILL.md +447 -0
  464. package/skills/examples/copy-editing/evals/evals.json +89 -0
  465. package/skills/examples/copy-editing/references/plain-english-alternatives.md +394 -0
  466. package/skills/examples/internal-comms/LICENSE.txt +202 -0
  467. package/skills/examples/internal-comms/SKILL.md +32 -0
  468. package/skills/examples/internal-comms/examples/3p-updates.md +47 -0
  469. package/skills/examples/internal-comms/examples/company-newsletter.md +65 -0
  470. package/skills/examples/internal-comms/examples/faq-answers.md +30 -0
  471. package/skills/examples/internal-comms/examples/general-comms.md +16 -0
  472. package/skills/examples/mcp-builder/SKILL.md +328 -0
  473. package/skills/examples/mcp-builder/reference/evaluation.md +602 -0
  474. package/skills/examples/mcp-builder/reference/mcp_best_practices.md +915 -0
  475. package/skills/examples/mcp-builder/reference/node_mcp_server.md +916 -0
  476. package/skills/examples/mcp-builder/reference/python_mcp_server.md +752 -0
  477. package/skills/examples/mcp-builder/scripts/connections.py +151 -0
  478. package/skills/examples/mcp-builder/scripts/evaluation.py +373 -0
  479. package/skills/examples/mcp-builder/scripts/example_evaluation.xml +22 -0
  480. package/skills/examples/mcp-builder/scripts/requirements.txt +2 -0
  481. package/skills/examples/product-marketing-context/SKILL.md +241 -0
  482. package/skills/examples/product-marketing-context/evals/evals.json +85 -0
  483. package/skills/examples/single-cell-rna-qc/SKILL.md +175 -0
  484. package/skills/examples/single-cell-rna-qc/references/scverse_qc_guidelines.md +186 -0
  485. package/skills/examples/single-cell-rna-qc/scripts/qc_analysis.py +232 -0
  486. package/skills/examples/single-cell-rna-qc/scripts/qc_core.py +233 -0
  487. package/skills/examples/single-cell-rna-qc/scripts/qc_plotting.py +235 -0
  488. package/skills/examples/skill-creator/SKILL.md +355 -0
  489. package/skills/examples/skill-creator/references/output-patterns.md +82 -0
  490. package/skills/examples/skill-creator/references/workflows.md +28 -0
  491. package/skills/examples/skill-creator/scripts/init_skill.py +303 -0
  492. package/skills/examples/skill-creator/scripts/package_skill.py +110 -0
  493. package/skills/examples/skill-creator/scripts/quick_validate.py +95 -0
  494. package/skills/examples/slack-gif-creator/SKILL.md +254 -0
  495. package/skills/examples/slack-gif-creator/core/easing.py +234 -0
  496. package/skills/examples/slack-gif-creator/core/frame_composer.py +176 -0
  497. package/skills/examples/slack-gif-creator/core/gif_builder.py +269 -0
  498. package/skills/examples/slack-gif-creator/core/validators.py +136 -0
  499. package/skills/examples/slack-gif-creator/requirements.txt +4 -0
  500. package/skills/examples/social-content/SKILL.md +278 -0
  501. package/skills/examples/social-content/evals/evals.json +92 -0
  502. package/skills/examples/social-content/references/platforms.md +170 -0
  503. package/skills/examples/social-content/references/post-templates.md +177 -0
  504. package/skills/examples/social-content/references/reverse-engineering.md +195 -0
  505. package/skills/examples/theme-factory/SKILL.md +59 -0
  506. package/skills/examples/theme-factory/theme-showcase.pdf +0 -0
  507. package/skills/examples/theme-factory/themes/arctic-frost.md +19 -0
  508. package/skills/examples/theme-factory/themes/botanical-garden.md +19 -0
  509. package/skills/examples/theme-factory/themes/desert-rose.md +19 -0
  510. package/skills/examples/theme-factory/themes/forest-canopy.md +19 -0
  511. package/skills/examples/theme-factory/themes/golden-hour.md +19 -0
  512. package/skills/examples/theme-factory/themes/midnight-galaxy.md +19 -0
  513. package/skills/examples/theme-factory/themes/modern-minimalist.md +19 -0
  514. package/skills/examples/theme-factory/themes/ocean-depths.md +19 -0
  515. package/skills/examples/theme-factory/themes/sunset-boulevard.md +19 -0
  516. package/skills/examples/theme-factory/themes/tech-innovation.md +19 -0
  517. package/skills/examples/web-artifacts-builder/LICENSE.txt +202 -0
  518. package/skills/examples/web-artifacts-builder/SKILL.md +74 -0
  519. package/skills/examples/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  520. package/skills/examples/web-artifacts-builder/scripts/init-artifact.sh +322 -0
  521. package/skills/examples/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  522. package/skills/examples/writing-skills/SKILL.md +655 -0
  523. package/skills/examples/writing-skills/anthropic-best-practices.md +1150 -0
  524. package/skills/examples/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  525. package/skills/examples/writing-skills/graphviz-conventions.dot +172 -0
  526. package/skills/examples/writing-skills/persuasion-principles.md +187 -0
  527. package/skills/examples/writing-skills/render-graphs.js +168 -0
  528. package/skills/examples/writing-skills/testing-skills-with-subagents.md +384 -0
  529. package/skills/public/describe-image/SKILL.md +105 -0
  530. package/skills/public/describe-image/scripts/describe.py +389 -0
  531. package/skills/public/doc-coauthoring/SKILL.md +375 -0
  532. package/skills/public/docx/LICENSE.txt +30 -0
  533. package/skills/public/docx/SKILL.md +199 -0
  534. package/skills/public/docx/docx-js.md +350 -0
  535. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  536. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  537. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  538. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  539. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  540. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  541. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  542. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  543. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  544. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  545. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  546. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  547. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  548. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  549. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  550. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  551. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  552. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  553. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  554. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  555. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  556. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  557. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  558. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  559. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  560. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  561. package/skills/public/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  562. package/skills/public/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  563. package/skills/public/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  564. package/skills/public/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  565. package/skills/public/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  566. package/skills/public/docx/ooxml/schemas/mce/mc.xsd +75 -0
  567. package/skills/public/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  568. package/skills/public/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  569. package/skills/public/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  570. package/skills/public/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  571. package/skills/public/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  572. package/skills/public/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  573. package/skills/public/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  574. package/skills/public/docx/ooxml/scripts/pack.py +159 -0
  575. package/skills/public/docx/ooxml/scripts/unpack.py +29 -0
  576. package/skills/public/docx/ooxml/scripts/validate.py +69 -0
  577. package/skills/public/docx/ooxml/scripts/validation/__init__.py +15 -0
  578. package/skills/public/docx/ooxml/scripts/validation/base.py +951 -0
  579. package/skills/public/docx/ooxml/scripts/validation/docx.py +274 -0
  580. package/skills/public/docx/ooxml/scripts/validation/pptx.py +315 -0
  581. package/skills/public/docx/ooxml/scripts/validation/redlining.py +279 -0
  582. package/skills/public/docx/ooxml.md +632 -0
  583. package/skills/public/docx/scripts/__init__.py +1 -0
  584. package/skills/public/docx/scripts/document.py +1292 -0
  585. package/skills/public/docx/scripts/templates/comments.xml +3 -0
  586. package/skills/public/docx/scripts/templates/commentsExtended.xml +3 -0
  587. package/skills/public/docx/scripts/templates/commentsExtensible.xml +3 -0
  588. package/skills/public/docx/scripts/templates/commentsIds.xml +3 -0
  589. package/skills/public/docx/scripts/templates/people.xml +3 -0
  590. package/skills/public/docx/scripts/utilities.py +374 -0
  591. package/skills/public/file-reading/LICENSE.txt +30 -0
  592. package/skills/public/file-reading/SKILL.md +350 -0
  593. package/skills/public/frontend-design/LICENSE.txt +177 -0
  594. package/skills/public/frontend-design/SKILL.md +42 -0
  595. package/skills/public/gitlab-explorer/SKILL.md +174 -0
  596. package/skills/public/gitlab-explorer/references/git-commands.md +323 -0
  597. package/skills/public/gitlab-explorer/references/glab-commands.md +282 -0
  598. package/skills/public/gitlab-explorer/scripts/check_gitlab_auth.sh +109 -0
  599. package/skills/public/pdf/FORMS.md +205 -0
  600. package/skills/public/pdf/REFERENCE.md +612 -0
  601. package/skills/public/pdf/SKILL.md +364 -0
  602. package/skills/public/pdf/scripts/check_bounding_boxes.py +70 -0
  603. package/skills/public/pdf/scripts/check_bounding_boxes_test.py +226 -0
  604. package/skills/public/pdf/scripts/check_fillable_fields.py +12 -0
  605. package/skills/public/pdf/scripts/convert_pdf_to_images.py +35 -0
  606. package/skills/public/pdf/scripts/create_validation_image.py +41 -0
  607. package/skills/public/pdf/scripts/extract_form_field_info.py +152 -0
  608. package/skills/public/pdf/scripts/fill_fillable_fields.py +114 -0
  609. package/skills/public/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  610. package/skills/public/pdf-reading/LICENSE.txt +30 -0
  611. package/skills/public/pdf-reading/REFERENCE.md +196 -0
  612. package/skills/public/pdf-reading/SKILL.md +305 -0
  613. package/skills/public/playwright-cli/SKILL.md +278 -0
  614. package/skills/public/playwright-cli/references/request-mocking.md +87 -0
  615. package/skills/public/playwright-cli/references/running-code.md +232 -0
  616. package/skills/public/playwright-cli/references/session-management.md +169 -0
  617. package/skills/public/playwright-cli/references/storage-state.md +275 -0
  618. package/skills/public/playwright-cli/references/test-generation.md +88 -0
  619. package/skills/public/playwright-cli/references/tracing.md +139 -0
  620. package/skills/public/playwright-cli/references/video-recording.md +43 -0
  621. package/skills/public/pptx/LICENSE.txt +30 -0
  622. package/skills/public/pptx/SKILL.md +484 -0
  623. package/skills/public/pptx/css.md +335 -0
  624. package/skills/public/pptx/html2pptx.md +893 -0
  625. package/skills/public/pptx/html2pptx.tgz +0 -0
  626. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  627. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  628. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  629. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  630. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  631. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  632. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  633. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  634. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  635. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  636. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  637. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  638. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  639. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  640. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  641. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  642. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  643. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  644. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  645. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  646. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  647. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  648. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  649. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  650. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  651. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  652. package/skills/public/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  653. package/skills/public/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  654. package/skills/public/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  655. package/skills/public/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  656. package/skills/public/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  657. package/skills/public/pptx/ooxml/schemas/mce/mc.xsd +75 -0
  658. package/skills/public/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  659. package/skills/public/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  660. package/skills/public/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  661. package/skills/public/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  662. package/skills/public/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  663. package/skills/public/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  664. package/skills/public/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  665. package/skills/public/pptx/ooxml/scripts/pack.py +159 -0
  666. package/skills/public/pptx/ooxml/scripts/unpack.py +29 -0
  667. package/skills/public/pptx/ooxml/scripts/validate.py +69 -0
  668. package/skills/public/pptx/ooxml/scripts/validation/__init__.py +15 -0
  669. package/skills/public/pptx/ooxml/scripts/validation/base.py +951 -0
  670. package/skills/public/pptx/ooxml/scripts/validation/docx.py +274 -0
  671. package/skills/public/pptx/ooxml/scripts/validation/pptx.py +315 -0
  672. package/skills/public/pptx/ooxml/scripts/validation/redlining.py +279 -0
  673. package/skills/public/pptx/ooxml.md +427 -0
  674. package/skills/public/pptx/scripts/inventory.py +1020 -0
  675. package/skills/public/pptx/scripts/rearrange.py +231 -0
  676. package/skills/public/pptx/scripts/replace.py +385 -0
  677. package/skills/public/pptx/scripts/thumbnail.py +450 -0
  678. package/skills/public/skill-creator/SKILL.md +356 -0
  679. package/skills/public/skill-creator/references/output-patterns.md +82 -0
  680. package/skills/public/skill-creator/references/workflows.md +28 -0
  681. package/skills/public/skill-creator/scripts/init_skill.py +303 -0
  682. package/skills/public/skill-creator/scripts/package_skill.py +110 -0
  683. package/skills/public/skill-creator/scripts/quick_validate.py +95 -0
  684. package/skills/public/sub-agent/SKILL.md +186 -0
  685. package/skills/public/sub-agent/references/security-review.md +153 -0
  686. package/skills/public/sub-agent/references/usage.md +207 -0
  687. package/skills/public/sub-agent/scripts/list_subagent_models.sh +22 -0
  688. package/skills/public/test-driven-development/SKILL.md +371 -0
  689. package/skills/public/test-driven-development/testing-anti-patterns.md +299 -0
  690. package/skills/public/webapp-testing/LICENSE.txt +202 -0
  691. package/skills/public/webapp-testing/SKILL.md +96 -0
  692. package/skills/public/webapp-testing/examples/console_logging.py +35 -0
  693. package/skills/public/webapp-testing/examples/element_discovery.py +40 -0
  694. package/skills/public/webapp-testing/examples/static_html_automation.py +33 -0
  695. package/skills/public/webapp-testing/scripts/with_server.py +106 -0
  696. package/skills/public/xlsx/LICENSE.txt +30 -0
  697. package/skills/public/xlsx/SKILL.md +316 -0
  698. package/skills/public/xlsx/preview_data.py +93 -0
  699. package/skills/public/xlsx/recalc.py +178 -0
  700. package/tests/README.md +42 -0
  701. package/tests/fixtures/cli/claude_v0.9.2.0_argv.json +46 -0
  702. package/tests/fixtures/cli/claude_v0.9.2.0_stdout.json +32 -0
  703. package/tests/fixtures/cli/codex_run.jsonl +4 -0
  704. package/tests/fixtures/cli/opencode_run.jsonl +6 -0
  705. package/tests/integration/README.md +56 -0
  706. package/tests/integration/conftest.py +280 -0
  707. package/tests/integration/pytest.ini +13 -0
  708. package/tests/integration/test_mcp_auth.py +85 -0
  709. package/tests/integration/test_mcp_tools.py +101 -0
  710. package/tests/integration/test_workspace_lifecycle.py +125 -0
  711. package/tests/orchestrator/mock_llm_server.py +343 -0
  712. package/tests/orchestrator/test_cli_adapters.py +566 -0
  713. package/tests/orchestrator/test_cli_adapters_live.py +527 -0
  714. package/tests/orchestrator/test_cli_runtime.py +451 -0
  715. package/tests/orchestrator/test_docker_manager.py +302 -0
  716. package/tests/orchestrator/test_dynamic_instructions.py +69 -0
  717. package/tests/orchestrator/test_mcp_resources.py +140 -0
  718. package/tests/orchestrator/test_mcp_tools.py +224 -0
  719. package/tests/orchestrator/test_passthrough_isolation.py +201 -0
  720. package/tests/orchestrator/test_readme_in_container.py +76 -0
  721. package/tests/orchestrator/test_render_cache.py +84 -0
  722. package/tests/orchestrator/test_runtime_cli_endpoint.py +108 -0
  723. package/tests/orchestrator/test_single_user_mode.py +212 -0
  724. package/tests/orchestrator/test_startup_warnings.py +123 -0
  725. package/tests/orchestrator/test_sub_agent_dispatch.py +327 -0
  726. package/tests/orchestrator/test_subagent_claude_compat.py +367 -0
  727. package/tests/orchestrator/test_system_prompt_endpoint.py +191 -0
  728. package/tests/orchestrator/test_tool_descriptions.py +52 -0
  729. package/tests/orchestrator/test_view_image.py +201 -0
  730. package/tests/patches/conftest.py +30 -0
  731. package/tests/patches/fixtures/__init__.py +10 -0
  732. package/tests/patches/fixtures/middleware_v0.9.1.py +5057 -0
  733. package/tests/patches/fixtures/middleware_v0.9.2.py +5120 -0
  734. package/tests/patches/fixtures/retrieval_v0.9.1.py +2684 -0
  735. package/tests/patches/fixtures/retrieval_v0.9.2.py +2700 -0
  736. package/tests/patches/test_fix_attached_files_position.py +118 -0
  737. package/tests/patches/test_fix_large_tool_args.py +130 -0
  738. package/tests/patches/test_fix_large_tool_results.py +531 -0
  739. package/tests/patches/test_fix_skip_embedding_chat_files.py +160 -0
  740. package/tests/patches/test_fix_skip_rag_files_native_fc.py +120 -0
  741. package/tests/patches/test_fix_tool_loop_errors.py +128 -0
  742. package/tests/security/test_path_traversal_app.py +132 -0
  743. package/tests/security/test_path_traversal_docker.py +36 -0
  744. package/tests/security/test_path_traversal_settings.py +87 -0
  745. package/tests/security/test_safe_path_util.py +166 -0
  746. package/tests/security/test_xss_preview.py +46 -0
  747. package/tests/test-default-model-resolution.py +136 -0
  748. package/tests/test-docker-image.sh +358 -0
  749. package/tests/test-list-subagent-models.sh +421 -0
  750. package/tests/test-mcp-endpoint-live.sh +92 -0
  751. package/tests/test-mcp-native-surface.sh +213 -0
  752. package/tests/test-no-cyrillic.sh +135 -0
  753. package/tests/test-opencode-error-mapping.py +130 -0
  754. package/tests/test-pr88-skills.sh +305 -0
  755. package/tests/test-project-structure.sh +202 -0
  756. package/tests/test-single-user-mode.sh +269 -0
  757. package/tests/test-skill-no-hardcoded-models.sh +65 -0
  758. package/tests/test-subagent-cli-surface.py +137 -0
  759. package/tests/test-subagent-runtime.sh +109 -0
  760. package/tests/test_codex_toml_converter.py +204 -0
  761. package/tests/test_default_resolver_no_legacy_global.py +159 -0
  762. package/tests/test_filter.py +648 -0
  763. package/tests/test_init_sh_unchanged.sh +49 -0
  764. package/tests/test_opencode_alias_map_drop.py +144 -0
  765. package/tests/test_requirements.py +91 -0
  766. package/tests/test_subagent_docstring.py +193 -0
  767. package/tests/test_tools.py +34 -0
  768. package/vendor/extract-text/README.md +46 -0
  769. package/vendor/extract-text/extract-text +0 -0
@@ -0,0 +1,327 @@
1
+ # SPDX-License-Identifier: FSL-1.1-Apache-2.0
2
+ # Copyright (c) 2025 Open Computer Use Contributors
3
+ """TEST-04: end-to-end dispatch suite for mcp_tools.sub_agent.
4
+
5
+ Mocks the subprocess boundary (cli_runtime.dispatch is replaced with an
6
+ AsyncMock that returns a synthetic SubAgentResult) and asserts:
7
+
8
+ 1. The MCP tool signature is byte-identical to the v0.9.2.0 contract:
9
+ sub_agent(task, description, ctx, model='', max_turns=0,
10
+ working_directory='/home/assistant', resume_session_id='').
11
+ 2. dispatch routes to the correct adapter for each SUBAGENT_CLI value
12
+ ({claude, codex, opencode}) — verified by inspecting cli_runtime.resolve_cli()
13
+ under the active env at dispatch time.
14
+ 3. Cost-guardrail caveat (Phase 7 success criterion 5; PITFALLS.md Pitfall 4):
15
+ when SubAgentResult.cost_usd is None (codex always; opencode when usage
16
+ is missing), the rendered MCP result string contains the literal
17
+ "unavailable" and contains NO "$0.0" / "$0.00" substring.
18
+ When cost_usd is a float, the rendered string contains "$X.XXXX".
19
+
20
+ The cost rendering branch was inlined into mcp_tools.sub_agent by Phase 5
21
+ plan 05-05 (verified at mcp_tools.py:1092-1095). This suite is the
22
+ regression guard that prevents future drift.
23
+
24
+ Mirrors the env-scrub + module-reload pattern from
25
+ tests/orchestrator/test_subagent_claude_compat.py so local-dev shells
26
+ with model-override env vars exported do not break the assertions.
27
+ """
28
+
29
+ import asyncio
30
+ import importlib
31
+ import inspect
32
+ import os
33
+ import sys
34
+ from unittest.mock import AsyncMock, MagicMock
35
+
36
+ import pytest
37
+
38
+ _SERVER_DIR = os.path.join(
39
+ os.path.dirname(__file__), "..", "..", "computer-use-server"
40
+ )
41
+ sys.path.insert(0, _SERVER_DIR)
42
+
43
+
44
+ # ---------------------------------------------------------------------------
45
+ # Env scrub — mirror test_subagent_claude_compat.py so local dev does not
46
+ # poison the model-resolution assertions.
47
+ # ---------------------------------------------------------------------------
48
+ _DEV_ENV_VARS_TO_SCRUB = (
49
+ "ANTHROPIC_DEFAULT_SONNET_MODEL",
50
+ "ANTHROPIC_DEFAULT_OPUS_MODEL",
51
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL",
52
+ "CLAUDE_SUB_AGENT_DEFAULT_MODEL",
53
+ "CODEX_SUB_AGENT_DEFAULT_MODEL",
54
+ "OPENCODE_SUB_AGENT_DEFAULT_MODEL",
55
+ "CODEX_MODEL",
56
+ "OPENCODE_MODEL",
57
+ "OPENCODE_MODEL_ALIASES",
58
+ )
59
+
60
+
61
+ def _scrub_dev_env(monkeypatch):
62
+ for var in _DEV_ENV_VARS_TO_SCRUB:
63
+ monkeypatch.delenv(var, raising=False)
64
+
65
+
66
+ def _make_result(*, cost_usd, text="OK", is_error=False, turns=1, returncode=0):
67
+ """Build a synthetic SubAgentResult.
68
+
69
+ Matches cli_adapters/result.py SubAgentResult fields exactly
70
+ (frozen dataclass: text, cost_usd, turns, is_error, session_id,
71
+ raw_events, returncode).
72
+ """
73
+ from cli_adapters.result import SubAgentResult
74
+ return SubAgentResult(
75
+ text=text,
76
+ cost_usd=cost_usd,
77
+ turns=turns,
78
+ is_error=is_error,
79
+ session_id="test-session",
80
+ raw_events=[],
81
+ returncode=returncode,
82
+ )
83
+
84
+
85
+ def _make_ctx():
86
+ """Minimal FastMCP Context double — only the methods sub_agent calls."""
87
+ ctx = MagicMock()
88
+ ctx.report_progress = AsyncMock()
89
+ ctx.info = MagicMock()
90
+ ctx.warning = MagicMock()
91
+ ctx.error = MagicMock()
92
+ return ctx
93
+
94
+
95
+ def _reload_runtime():
96
+ """Reload cli_runtime + mcp_tools so module-level env reads settle.
97
+
98
+ Order matters: docker_manager validates SUBAGENT_CLI at import time,
99
+ cli_runtime imports from docker_manager, mcp_tools imports from
100
+ cli_runtime.
101
+ """
102
+ for mod_name in ("docker_manager", "cli_runtime", "mcp_tools"):
103
+ if mod_name in sys.modules:
104
+ importlib.reload(sys.modules[mod_name])
105
+ else:
106
+ importlib.import_module(mod_name)
107
+
108
+
109
+ def _unwrap_tool(tool_obj):
110
+ """Return the original async function behind FastMCP @mcp.tool() wrapping."""
111
+ return getattr(tool_obj, "fn", None) or getattr(tool_obj, "__wrapped__", None) or tool_obj
112
+
113
+
114
+ def _install_common_stubs(monkeypatch, mcp_tools, fake_dispatch):
115
+ """Stub the side-effect-heavy collaborators so sub_agent can run on host.
116
+
117
+ - cli_dispatch: replaced with the per-test fake (the boundary under test)
118
+ - _get_or_create_container: opaque MagicMock (dispatch never touches it
119
+ because we stub cli_dispatch wholesale)
120
+ - _ensure_gitlab_token: no-op AsyncMock
121
+ - _execute_bash: returns an empty result so the marker-file write +
122
+ _stream_session_logs body bail immediately
123
+ - _validate_chat_id: returns a deterministic ('test', None) tuple so we
124
+ do not depend on contextvar state
125
+ - skill_manager: no real skills lookup
126
+ """
127
+ monkeypatch.setattr(mcp_tools, "cli_dispatch", fake_dispatch)
128
+ monkeypatch.setattr(
129
+ mcp_tools, "_get_or_create_container", lambda *a, **kw: MagicMock()
130
+ )
131
+ monkeypatch.setattr(
132
+ mcp_tools, "_ensure_gitlab_token", AsyncMock(return_value=None)
133
+ )
134
+ monkeypatch.setattr(
135
+ mcp_tools, "_execute_bash", lambda *a, **kw: {"output": "", "exit_code": 0}
136
+ )
137
+ monkeypatch.setattr(
138
+ mcp_tools, "_validate_chat_id", lambda: ("test", None)
139
+ )
140
+ monkeypatch.setattr(
141
+ mcp_tools.skill_manager, "get_user_skills_sync", lambda *a, **kw: []
142
+ )
143
+ monkeypatch.setattr(
144
+ mcp_tools.skill_manager, "build_sub_agent_skills_text", lambda *a, **kw: ""
145
+ )
146
+
147
+
148
+ # ===========================================================================
149
+ # Test 1 — MCP signature regression guard.
150
+ # ===========================================================================
151
+
152
+ def test_signature_is_byte_identical(monkeypatch):
153
+ """v0.9.2.0 contract: sub_agent(task, description, ctx, model='',
154
+ max_turns=0, working_directory='/home/assistant', resume_session_id='').
155
+
156
+ Any drift breaks every existing skill caller.
157
+ """
158
+ _scrub_dev_env(monkeypatch)
159
+ monkeypatch.setenv("SUBAGENT_CLI", "claude")
160
+ _reload_runtime()
161
+ import mcp_tools
162
+
163
+ fn = _unwrap_tool(mcp_tools.sub_agent)
164
+ sig = inspect.signature(fn)
165
+ params = list(sig.parameters.items())
166
+ names = [n for n, _ in params]
167
+
168
+ assert names == [
169
+ "task", "description", "ctx",
170
+ "model", "max_turns", "working_directory", "resume_session_id",
171
+ ], f"sub_agent parameters drifted from v0.9.2.0 contract: {names}"
172
+
173
+ defaults = {n: p.default for n, p in params if p.default is not inspect.Parameter.empty}
174
+ assert defaults["model"] == ""
175
+ assert defaults["max_turns"] == 0
176
+ assert defaults["working_directory"] == "/home/assistant"
177
+ assert defaults["resume_session_id"] == ""
178
+
179
+
180
+ # ===========================================================================
181
+ # Test 2 — dispatch routes to the correct adapter per SUBAGENT_CLI value.
182
+ # ===========================================================================
183
+
184
+ @pytest.mark.parametrize("cli_value,expected_cli_str", [
185
+ ("claude", "claude"),
186
+ ("codex", "codex"),
187
+ ("opencode", "opencode"),
188
+ ])
189
+ def test_dispatch_routes_to_correct_adapter(
190
+ monkeypatch, cli_value, expected_cli_str,
191
+ ):
192
+ """resolve_cli() inside the dispatch boundary must reflect SUBAGENT_CLI."""
193
+ _scrub_dev_env(monkeypatch)
194
+ monkeypatch.setenv("SUBAGENT_CLI", cli_value)
195
+ # Phase 2: opencode/codex no longer have hardcoded defaults — set the
196
+ # per-CLI default env so resolve_subagent_model("", ...) doesn't raise
197
+ # before fake_dispatch is reached. The actual id is irrelevant; the test
198
+ # only checks that dispatch was invoked with the right CLI.
199
+ if cli_value == "opencode":
200
+ monkeypatch.setenv("OPENCODE_SUB_AGENT_DEFAULT_MODEL", "anthropic/claude-sonnet-4-6")
201
+ elif cli_value == "codex":
202
+ monkeypatch.setenv("CODEX_SUB_AGENT_DEFAULT_MODEL", "gpt-5-codex")
203
+ _reload_runtime()
204
+ import cli_runtime
205
+ import mcp_tools
206
+
207
+ captured = {}
208
+
209
+ async def fake_dispatch(**kwargs):
210
+ captured.update(kwargs)
211
+ captured["_cli_seen"] = cli_runtime.resolve_cli()
212
+ # Codex never has cost; claude does; opencode optional.
213
+ cost = 0.0042 if cli_value == "claude" else None
214
+ return (
215
+ _make_result(cost_usd=cost, text="hello world"),
216
+ f"resolved-{cli_value}-model",
217
+ "sonnet",
218
+ )
219
+
220
+ _install_common_stubs(monkeypatch, mcp_tools, fake_dispatch)
221
+
222
+ fn = _unwrap_tool(mcp_tools.sub_agent)
223
+ # claude is the only CLI where 'sonnet' is a valid model alias for the
224
+ # default model resolution path that runs inside sub_agent BEFORE
225
+ # dispatch. For codex/opencode we pass an empty model so the per-CLI
226
+ # default kicks in inside resolve_subagent_model (called by the real
227
+ # dispatch — but we replace dispatch wholesale, so the model value is
228
+ # captured verbatim). Either way the model arg flows through to
229
+ # captured kwargs and we only assert the routing.
230
+ result = asyncio.run(fn(
231
+ task="hello", description="d", ctx=_make_ctx(),
232
+ ))
233
+
234
+ seen_cli = captured.get("_cli_seen")
235
+ assert seen_cli is not None, "fake_dispatch was not invoked"
236
+ assert seen_cli.value == expected_cli_str, (
237
+ f"resolve_cli() returned {seen_cli!r}; expected {expected_cli_str!r}"
238
+ )
239
+ # Sanity: dispatch was awaited once (captured kwargs are present).
240
+ assert "task" in captured
241
+ assert "system_prompt" in captured
242
+ # Result string carries the completion banner + the synthetic text.
243
+ assert "Sub-Agent Completed" in result, (
244
+ f"missing completion banner; first 300 chars: {result[:300]}"
245
+ )
246
+ assert "hello world" in result
247
+
248
+
249
+ # ===========================================================================
250
+ # Test 3 — cost rendering: cost_usd=None must render "unavailable".
251
+ # ===========================================================================
252
+
253
+ @pytest.mark.parametrize("cli_value", ["codex", "opencode"])
254
+ def test_cost_rendering_unavailable_for_none(monkeypatch, cli_value):
255
+ """Pitfall 4 + Phase 7 success criterion 5.
256
+
257
+ cost_usd=None (codex always; opencode when usage is missing) must
258
+ render as the literal "unavailable" — NEVER as "$0.00" / "$0.0000",
259
+ which would mislead the operator into thinking the run was free.
260
+ """
261
+ _scrub_dev_env(monkeypatch)
262
+ monkeypatch.setenv("SUBAGENT_CLI", cli_value)
263
+ # Phase 2: per-CLI default env required for opencode/codex.
264
+ if cli_value == "opencode":
265
+ monkeypatch.setenv("OPENCODE_SUB_AGENT_DEFAULT_MODEL", "anthropic/claude-sonnet-4-6")
266
+ elif cli_value == "codex":
267
+ monkeypatch.setenv("CODEX_SUB_AGENT_DEFAULT_MODEL", "gpt-5-codex")
268
+ _reload_runtime()
269
+ import mcp_tools
270
+
271
+ async def fake_dispatch(**kwargs):
272
+ return (
273
+ _make_result(cost_usd=None, text="ok"),
274
+ "model-id",
275
+ "model-display",
276
+ )
277
+
278
+ _install_common_stubs(monkeypatch, mcp_tools, fake_dispatch)
279
+
280
+ fn = _unwrap_tool(mcp_tools.sub_agent)
281
+ result = asyncio.run(fn(
282
+ task="t", description="d", ctx=_make_ctx(),
283
+ ))
284
+
285
+ assert "unavailable" in result, (
286
+ f"expected literal 'unavailable' in result for cost_usd=None; "
287
+ f"first 400 chars: {result[:400]}"
288
+ )
289
+ # Negative assertions: never let a None cost render as a dollar amount.
290
+ assert "$0.0" not in result, (
291
+ f"cost_usd=None must NOT render as $0.0X; first 400 chars: {result[:400]}"
292
+ )
293
+ assert "$0.00" not in result
294
+ assert "$0.0000" not in result
295
+
296
+
297
+ def test_cost_rendering_dollar_for_float(monkeypatch):
298
+ """Positive case: a float cost renders as $X.XXXX (4-decimal USD)."""
299
+ _scrub_dev_env(monkeypatch)
300
+ monkeypatch.setenv("SUBAGENT_CLI", "claude")
301
+ _reload_runtime()
302
+ import mcp_tools
303
+
304
+ async def fake_dispatch(**kwargs):
305
+ return (
306
+ _make_result(cost_usd=0.0042, text="ok"),
307
+ "claude-sonnet-4-6",
308
+ "sonnet",
309
+ )
310
+
311
+ _install_common_stubs(monkeypatch, mcp_tools, fake_dispatch)
312
+
313
+ fn = _unwrap_tool(mcp_tools.sub_agent)
314
+ result = asyncio.run(fn(
315
+ task="t", description="d", ctx=_make_ctx(),
316
+ ))
317
+
318
+ assert "$0.0042" in result, (
319
+ f"expected '$0.0042' for cost_usd=0.0042; first 400 chars: {result[:400]}"
320
+ )
321
+ assert "unavailable" not in result, (
322
+ "float cost must NOT render as 'unavailable'"
323
+ )
324
+
325
+
326
+ if __name__ == "__main__":
327
+ sys.exit(pytest.main([__file__, "-v"]))
@@ -0,0 +1,367 @@
1
+ # SPDX-License-Identifier: FSL-1.1-Apache-2.0
2
+ # Copyright (c) 2025 Open Computer Use Contributors
3
+ """ADAPT-02 byte-compat: ClaudeAdapter.build_argv must produce argv
4
+ byte-identical to the v0.9.2.0 production claude_command (argv layer).
5
+
6
+ The lifted code in cli_adapters/claude.py is DORMANT in Phase 4 (production
7
+ path stays in mcp_tools.sub_agent through Phase 6). This snapshot test is
8
+ the forcing function that prevents drift between the two copies, so when
9
+ Phase 7 flips dispatch through cli_runtime, the change is provably zero
10
+ regression for SUBAGENT_CLI=claude.
11
+
12
+ The shell-execution wrapper (`cd <wd> && <headers_env> ...`) lives in
13
+ mcp_tools.sub_agent and is NOT part of build_argv's contract — only the
14
+ argv list itself is asserted byte-identical.
15
+ """
16
+
17
+ import json
18
+ import os
19
+ import sys
20
+
21
+ import pytest
22
+
23
+ _SERVER_DIR = os.path.join(
24
+ os.path.dirname(__file__), "..", "..", "computer-use-server"
25
+ )
26
+ sys.path.insert(0, _SERVER_DIR)
27
+
28
+ _FIXTURE_PATH = os.path.join(
29
+ os.path.dirname(__file__), "..", "fixtures", "cli", "claude_v0.9.2.0_argv.json"
30
+ )
31
+
32
+
33
+ @pytest.fixture(scope="module")
34
+ def fixture():
35
+ with open(_FIXTURE_PATH) as f:
36
+ return json.load(f)
37
+
38
+
39
+ def test_new_session_argv_byte_compat(fixture):
40
+ """NEW SESSION branch (resume_session_id == ""): 15-element argv with
41
+ --model + --append-system-prompt before the common flags."""
42
+ from cli_adapters.claude import ClaudeAdapter
43
+ adapter = ClaudeAdapter()
44
+ case = fixture["new_session"]
45
+ actual = adapter.build_argv(**case["inputs"])
46
+ assert actual == case["expected_argv"], (
47
+ f"build_argv NEW SESSION drifted from v0.9.2.0 baseline.\n"
48
+ f" expected: {case['expected_argv']}\n"
49
+ f" actual: {actual}\n"
50
+ )
51
+ assert len(actual) == 15, f"expected 15-element argv, got {len(actual)}"
52
+
53
+
54
+ def test_resume_argv_byte_compat(fixture):
55
+ """RESUME branch (resume_session_id non-empty): 13-element argv with
56
+ --resume <session_id> in place of --model + --append-system-prompt."""
57
+ from cli_adapters.claude import ClaudeAdapter
58
+ adapter = ClaudeAdapter()
59
+ case = fixture["resume"]
60
+ actual = adapter.build_argv(**case["inputs"])
61
+ assert actual == case["expected_argv"], (
62
+ f"build_argv RESUME drifted from v0.9.2.0 baseline.\n"
63
+ f" expected: {case['expected_argv']}\n"
64
+ f" actual: {actual}\n"
65
+ )
66
+ assert len(actual) == 13, f"expected 13-element argv, got {len(actual)}"
67
+
68
+
69
+ def test_disallowed_tools_value_is_unquoted(fixture):
70
+ """The original mcp_tools.py:957 emits `--disallowedTools 'AskUserQuestion,ExitPlanMode'`
71
+ inside a SHELL command string — the single quotes are shell quoting, not part
72
+ of the argv value. In argv form the value is the literal string
73
+ `AskUserQuestion,ExitPlanMode` with no quotes (RESEARCH.md line 215, plan
74
+ 04-02 SUMMARY line 97)."""
75
+ for case_key in ("new_session", "resume"):
76
+ argv = fixture[case_key]["expected_argv"]
77
+ idx = argv.index("--disallowedTools")
78
+ assert argv[idx + 1] == "AskUserQuestion,ExitPlanMode", (
79
+ f"{case_key}: --disallowedTools value must be unquoted, got {argv[idx + 1]!r}"
80
+ )
81
+
82
+
83
+ def test_parse_result_minimal_roundtrip():
84
+ """parse_result consumes Claude's --output-format json line and populates
85
+ SubAgentResult correctly. Smoke test (the format hasn't changed and won't
86
+ change in Phase 4) plus the Pitfall 4 zero-cost-becomes-None invariant."""
87
+ from cli_adapters.claude import ClaudeAdapter
88
+ adapter = ClaudeAdapter()
89
+ line = json.dumps({
90
+ "type": "result",
91
+ "result": "task complete",
92
+ "total_cost_usd": 0.123,
93
+ "num_turns": 5,
94
+ "is_error": False,
95
+ "session_id": "sess-xyz",
96
+ })
97
+ res = adapter.parse_result(stdout=line, stderr="", returncode=0)
98
+ assert res.text == "task complete"
99
+ assert res.cost_usd == 0.123
100
+ assert res.turns == 5
101
+ assert res.is_error is False
102
+ assert res.session_id == "sess-xyz"
103
+
104
+ # Pitfall 4: cost_usd -> None when 0.0 (render "unavailable", not "$0.00").
105
+ zero_cost_line = json.dumps({
106
+ "type": "result", "result": "x", "total_cost_usd": 0.0,
107
+ "num_turns": 0, "is_error": False, "session_id": "",
108
+ })
109
+ res2 = adapter.parse_result(stdout=zero_cost_line, stderr="", returncode=0)
110
+ assert res2.cost_usd is None
111
+ assert res2.turns is None
112
+ assert res2.session_id is None
113
+
114
+
115
+ # === Phase 5 / plan 05-06: end-to-end dispatch byte-compat ===
116
+ # Plan 05-05 flipped mcp_tools.sub_agent from inline claude_command to
117
+ # cli_runtime.dispatch -> ClaudeAdapter -> _execute_bash_capture. These
118
+ # tests assert the assembled shell command and the parsed SubAgentResult
119
+ # are byte-identical to what v0.9.2.0 would have produced for the same
120
+ # inputs.
121
+
122
+ import asyncio
123
+ import shlex as _shlex_mod
124
+ from types import SimpleNamespace
125
+ from unittest.mock import patch
126
+
127
+ # WARNING 2 fix: scrub model-override env vars so local-dev shells (where
128
+ # a developer might have e.g. ANTHROPIC_DEFAULT_SONNET_MODEL=my-deployment
129
+ # exported) don't break the byte-compat assertions. CI is clean; local
130
+ # dev gets the same guarantees.
131
+ _DEV_ENV_VARS_TO_SCRUB = (
132
+ "ANTHROPIC_DEFAULT_SONNET_MODEL",
133
+ "ANTHROPIC_DEFAULT_OPUS_MODEL",
134
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL",
135
+ "CLAUDE_SUB_AGENT_DEFAULT_MODEL",
136
+ "CODEX_SUB_AGENT_DEFAULT_MODEL",
137
+ "OPENCODE_SUB_AGENT_DEFAULT_MODEL",
138
+ "CODEX_MODEL",
139
+ "OPENCODE_MODEL",
140
+ "OPENCODE_MODEL_ALIASES",
141
+ )
142
+
143
+
144
+ def _scrub_dev_env(monkeypatch):
145
+ for var in _DEV_ENV_VARS_TO_SCRUB:
146
+ monkeypatch.delenv(var, raising=False)
147
+
148
+
149
+ def test_claude_dispatch_byte_compat(fixture, monkeypatch):
150
+ """SUBAGENT_CLI=claude (default): cli_runtime.dispatch builds the same
151
+ shell command as v0.9.2.0's mcp_tools.sub_agent inline claude_command,
152
+ and parse_result returns the same SubAgentResult.
153
+
154
+ We mock _execute_bash_capture to capture the shell command without
155
+ needing a Docker container, then return a known stdout that the
156
+ ClaudeAdapter.parse_result is expected to digest into a known
157
+ SubAgentResult.
158
+ """
159
+ _scrub_dev_env(monkeypatch)
160
+
161
+ # Drop modules so cli_runtime re-imports cleanly under the test env.
162
+ for mod in ("cli_runtime", "docker_manager"):
163
+ sys.modules.pop(mod, None)
164
+
165
+ # Import the freshly-loaded dispatch + Cli.
166
+ from cli_runtime import dispatch as cli_dispatch, Cli
167
+ # Sanity: default SUBAGENT_CLI resolves to claude.
168
+ from cli_runtime import resolve_cli
169
+ assert resolve_cli() == Cli.CLAUDE
170
+
171
+ # Inputs mirror the v0.9.2.0 NEW SESSION fixture. mcp_tools.sub_agent
172
+ # passes these via cli_dispatch(...).
173
+ case = fixture["new_session"]
174
+ inputs = case["inputs"]
175
+ expected_argv = case["expected_argv"]
176
+
177
+ # The captured shell command we expect dispatch to construct:
178
+ # cd <wd> && [headers_env]<shlex.quote(argv) joined>
179
+ working_directory = "/home/assistant"
180
+ headers_env = "" # No user_email path -> no ANTHROPIC_CUSTOM_HEADERS.
181
+ expected_quoted = " ".join(_shlex_mod.quote(a) for a in expected_argv)
182
+ expected_shell_cmd = (
183
+ f"cd {_shlex_mod.quote(working_directory)} && "
184
+ f"{headers_env}{expected_quoted}"
185
+ )
186
+
187
+ # Stub stdout fed to ClaudeAdapter.parse_result.
188
+ with open(_FIXTURE_PATH.replace("argv.json", "stdout.json")) as f:
189
+ stdout_fixture = json.load(f)
190
+ happy = stdout_fixture["happy_path"]
191
+
192
+ captured_cmd = {}
193
+
194
+ def _fake_capture(container, command, timeout=None):
195
+ captured_cmd["cmd"] = command
196
+ captured_cmd["timeout"] = timeout
197
+ return SimpleNamespace(
198
+ stdout=happy["stdout"],
199
+ stderr=happy["stderr"],
200
+ returncode=happy["returncode"],
201
+ )
202
+
203
+ with patch("cli_runtime._execute_bash_capture", side_effect=_fake_capture):
204
+ sub_result, model_id, model_display = asyncio.run(
205
+ cli_dispatch(
206
+ container=object(), # opaque - _fake_capture ignores it
207
+ task=inputs["task"],
208
+ system_prompt=inputs["system_prompt"],
209
+ model="sonnet", # alias resolves to inputs["model"] via resolve_subagent_model
210
+ max_turns=inputs["max_turns"],
211
+ timeout_s=inputs["timeout_s"],
212
+ working_directory=working_directory,
213
+ resume_session_id="",
214
+ plan_file="",
215
+ headers_env=headers_env,
216
+ )
217
+ )
218
+
219
+ # === Assert 1: shell command is byte-identical to v0.9.2.0 ===
220
+ assert captured_cmd["cmd"] == expected_shell_cmd, (
221
+ "Dispatch produced a shell command different from v0.9.2.0:\n"
222
+ f" expected: {expected_shell_cmd}\n"
223
+ f" actual: {captured_cmd['cmd']}\n"
224
+ )
225
+ # Timeout passed through to the executor.
226
+ assert captured_cmd["timeout"] == inputs["timeout_s"]
227
+
228
+ # === Assert 2: parsed SubAgentResult matches the parse-side fixture ===
229
+ exp = happy["expected"]
230
+ assert sub_result.text == exp["text"]
231
+ assert sub_result.cost_usd == exp["cost_usd"]
232
+ assert sub_result.turns == exp["turns"]
233
+ assert sub_result.session_id == exp["session_id"]
234
+ assert sub_result.is_error is exp["is_error"]
235
+
236
+ # === Assert 3: model resolution preserved v0.9.2.0 alias semantics ===
237
+ # "sonnet" -> "claude-sonnet-4-6" (default), display "sonnet".
238
+ assert model_id == "claude-sonnet-4-6"
239
+ assert model_display == "sonnet"
240
+
241
+
242
+ def test_claude_dispatch_resume_byte_compat(fixture, monkeypatch):
243
+ """RESUME branch byte-compat: same as above but with resume_session_id set.
244
+ Verifies the resume argv (no --model, no --append-system-prompt) is
245
+ assembled identically to v0.9.2.0."""
246
+ _scrub_dev_env(monkeypatch)
247
+
248
+ for mod in ("cli_runtime", "docker_manager"):
249
+ sys.modules.pop(mod, None)
250
+
251
+ from cli_runtime import dispatch as cli_dispatch
252
+ case = fixture["resume"]
253
+ inputs = case["inputs"]
254
+ expected_argv = case["expected_argv"]
255
+
256
+ working_directory = "/home/assistant"
257
+ headers_env = ""
258
+ expected_quoted = " ".join(_shlex_mod.quote(a) for a in expected_argv)
259
+ expected_shell_cmd = (
260
+ f"cd {_shlex_mod.quote(working_directory)} && "
261
+ f"{headers_env}{expected_quoted}"
262
+ )
263
+
264
+ captured_cmd = {}
265
+
266
+ def _fake_capture(container, command, timeout=None):
267
+ captured_cmd["cmd"] = command
268
+ return SimpleNamespace(
269
+ stdout='{"type": "result", "result": "resumed ok", '
270
+ '"total_cost_usd": 0.05, "num_turns": 3, '
271
+ '"is_error": false, "session_id": "abc-123-session"}',
272
+ stderr="",
273
+ returncode=0,
274
+ )
275
+
276
+ with patch("cli_runtime._execute_bash_capture", side_effect=_fake_capture):
277
+ sub_result, _, _ = asyncio.run(
278
+ cli_dispatch(
279
+ container=object(),
280
+ task=inputs["task"],
281
+ system_prompt=inputs["system_prompt"],
282
+ model="sonnet",
283
+ max_turns=inputs["max_turns"],
284
+ timeout_s=inputs["timeout_s"],
285
+ working_directory=working_directory,
286
+ resume_session_id=inputs["resume_session_id"],
287
+ plan_file="",
288
+ headers_env=headers_env,
289
+ )
290
+ )
291
+
292
+ assert captured_cmd["cmd"] == expected_shell_cmd, (
293
+ f"Resume dispatch shell command drifted from v0.9.2.0:\n"
294
+ f" expected: {expected_shell_cmd}\n"
295
+ f" actual: {captured_cmd['cmd']}\n"
296
+ )
297
+ assert sub_result.text == "resumed ok"
298
+ assert sub_result.session_id == "abc-123-session"
299
+
300
+
301
+ def test_claude_dispatch_with_headers_env_byte_compat(fixture, monkeypatch):
302
+ """Headers env (ANTHROPIC_CUSTOM_HEADERS path): when mcp_tools passes a
303
+ non-empty headers_env (because user_email is set), dispatch concatenates
304
+ it BEFORE the argv - exactly the v0.9.2.0 shape."""
305
+ _scrub_dev_env(monkeypatch)
306
+
307
+ for mod in ("cli_runtime", "docker_manager"):
308
+ sys.modules.pop(mod, None)
309
+ from cli_runtime import dispatch as cli_dispatch
310
+
311
+ case = fixture["new_session"]
312
+ inputs = case["inputs"]
313
+ expected_argv = case["expected_argv"]
314
+
315
+ working_directory = "/home/assistant"
316
+ # Mirrors mcp_tools.sub_agent's headers_env construction (already shlex.quote'd).
317
+ headers_env = (
318
+ f"ANTHROPIC_CUSTOM_HEADERS="
319
+ f"{_shlex_mod.quote('x-openwebui-user-email: alice@example.com')} "
320
+ )
321
+ expected_quoted = " ".join(_shlex_mod.quote(a) for a in expected_argv)
322
+ expected_shell_cmd = (
323
+ f"cd {_shlex_mod.quote(working_directory)} && "
324
+ f"{headers_env}{expected_quoted}"
325
+ )
326
+
327
+ captured_cmd = {}
328
+
329
+ def _fake_capture(container, command, timeout=None):
330
+ captured_cmd["cmd"] = command
331
+ return SimpleNamespace(
332
+ stdout='{"type": "result", "result": "ok", "total_cost_usd": 0.1, '
333
+ '"num_turns": 1, "is_error": false, "session_id": "s1"}',
334
+ stderr="",
335
+ returncode=0,
336
+ )
337
+
338
+ with patch("cli_runtime._execute_bash_capture", side_effect=_fake_capture):
339
+ asyncio.run(
340
+ cli_dispatch(
341
+ container=object(),
342
+ task=inputs["task"],
343
+ system_prompt=inputs["system_prompt"],
344
+ model="sonnet",
345
+ max_turns=inputs["max_turns"],
346
+ timeout_s=inputs["timeout_s"],
347
+ working_directory=working_directory,
348
+ resume_session_id="",
349
+ plan_file="",
350
+ headers_env=headers_env,
351
+ )
352
+ )
353
+
354
+ assert captured_cmd["cmd"] == expected_shell_cmd, (
355
+ f"Dispatch with headers_env drifted from v0.9.2.0 contract:\n"
356
+ f" expected: {expected_shell_cmd}\n"
357
+ f" actual: {captured_cmd['cmd']}\n"
358
+ )
359
+ # The ANTHROPIC_CUSTOM_HEADERS prefix appears verbatim (with the shell
360
+ # quoting that mcp_tools.sub_agent applied) - preserves GATEWAY-07
361
+ # contract from v0.8.12.9.
362
+ assert "ANTHROPIC_CUSTOM_HEADERS=" in captured_cmd["cmd"]
363
+ assert "x-openwebui-user-email: alice@example.com" in captured_cmd["cmd"]
364
+
365
+
366
+ if __name__ == "__main__":
367
+ sys.exit(pytest.main([__file__, "-v"]))