@wardby/cli 0.6.0 → 0.8.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 (740) hide show
  1. package/.env.example +5 -5
  2. package/README.md +6 -1
  3. package/deploy/local/docker-compose.quickstart-coding.yml +19 -0
  4. package/dist/claude-coding-worker/driver.d.ts +33 -3
  5. package/dist/claude-coding-worker/driver.js +151 -21
  6. package/dist/claude-coding-worker/main.js +38 -6
  7. package/dist/claude-coding-worker/sdk.js +29 -2
  8. package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
  9. package/dist/claude-coding-worker/tool-socket.js +111 -0
  10. package/dist/claude-coding-worker/transcript.d.ts +18 -0
  11. package/dist/claude-coding-worker/transcript.js +77 -0
  12. package/dist/claude-plugin/command.d.ts +61 -0
  13. package/dist/claude-plugin/command.js +376 -0
  14. package/dist/cli-help.d.ts +1 -1
  15. package/dist/cli-help.js +3 -1
  16. package/dist/cli.js +71 -13
  17. package/dist/coding/code-host.d.ts +16 -0
  18. package/dist/coding/code-host.js +60 -0
  19. package/dist/coding/continuation-wording.d.ts +35 -0
  20. package/dist/coding/continuation-wording.js +73 -0
  21. package/dist/coding/linked-issue-note.d.ts +23 -0
  22. package/dist/coding/linked-issue-note.js +47 -0
  23. package/dist/coding/mcp-token.d.ts +12 -0
  24. package/dist/coding/mcp-token.js +26 -0
  25. package/dist/coding/merge-wording.d.ts +28 -0
  26. package/dist/coding/merge-wording.js +78 -0
  27. package/dist/coding/pr-description-note.d.ts +9 -0
  28. package/dist/coding/pr-description-note.js +32 -0
  29. package/dist/coding/profile.d.ts +46 -126
  30. package/dist/coding/profile.js +45 -4
  31. package/dist/coding/protected-path-wording.d.ts +8 -0
  32. package/dist/coding/protected-path-wording.js +1 -1
  33. package/dist/coding/protocol.d.ts +264 -346
  34. package/dist/coding/protocol.js +237 -12
  35. package/dist/coding/redact.d.ts +3 -0
  36. package/dist/coding/redact.js +17 -0
  37. package/dist/coding/registry/allowlist.d.ts +12 -0
  38. package/dist/coding/registry/allowlist.js +14 -1
  39. package/dist/coding/registry/audit-mode.d.ts +153 -0
  40. package/dist/coding/registry/audit-mode.js +304 -0
  41. package/dist/coding/registry/lockfile-shared.d.ts +36 -0
  42. package/dist/coding/registry/lockfile-shared.js +128 -0
  43. package/dist/coding/registry/lockfiles.js +1 -1
  44. package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
  45. package/dist/coding/registry/npm-lockfile-formats.js +41 -0
  46. package/dist/coding/registry/npm-lockfile.d.ts +8 -4
  47. package/dist/coding/registry/npm-lockfile.js +4 -6
  48. package/dist/coding/registry/npm.js +78 -8
  49. package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
  50. package/dist/coding/registry/pnpm-lockfile.js +189 -0
  51. package/dist/coding/registry/pypi-plan.d.ts +50 -0
  52. package/dist/coding/registry/pypi-plan.js +406 -0
  53. package/dist/coding/registry/pypi-requirements.d.ts +58 -0
  54. package/dist/coding/registry/pypi-requirements.js +155 -0
  55. package/dist/coding/registry/pypi.d.ts +3 -27
  56. package/dist/coding/registry/pypi.js +40 -154
  57. package/dist/coding/registry/refusal-hints.d.ts +20 -0
  58. package/dist/coding/registry/refusal-hints.js +61 -0
  59. package/dist/coding/registry/refusal-wording.d.ts +11 -0
  60. package/dist/coding/registry/refusal-wording.js +56 -0
  61. package/dist/coding/registry/report.d.ts +70 -8
  62. package/dist/coding/registry/report.js +112 -5
  63. package/dist/coding/registry/types.d.ts +58 -8
  64. package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
  65. package/dist/coding/registry/yarn-lockfile.js +367 -0
  66. package/dist/coding/services/catalog.d.ts +37 -351
  67. package/dist/coding/transcript/claude-code.d.ts +13 -0
  68. package/dist/coding/transcript/claude-code.js +273 -0
  69. package/dist/coding/transcript/download-protocol.d.ts +30 -0
  70. package/dist/coding/transcript/download-protocol.js +18 -0
  71. package/dist/coding/transcript/format.d.ts +20 -0
  72. package/dist/coding/transcript/format.js +32 -0
  73. package/dist/coding/transcript/recorder.d.ts +52 -0
  74. package/dist/coding/transcript/recorder.js +225 -0
  75. package/dist/coding/transcript/resume/checkout.d.ts +31 -0
  76. package/dist/coding/transcript/resume/checkout.js +203 -0
  77. package/dist/coding/transcript/resume/command.d.ts +17 -0
  78. package/dist/coding/transcript/resume/command.js +176 -0
  79. package/dist/coding/transcript/resume/download.d.ts +20 -0
  80. package/dist/coding/transcript/resume/download.js +153 -0
  81. package/dist/coding/transcript/resume/launch.d.ts +38 -0
  82. package/dist/coding/transcript/resume/launch.js +128 -0
  83. package/dist/coding/transcript/resume/session-file.d.ts +13 -0
  84. package/dist/coding/transcript/resume/session-file.js +79 -0
  85. package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
  86. package/dist/coding/transcript/resume/stand-in.js +49 -0
  87. package/dist/coding-worker/artifact.d.ts +8 -3
  88. package/dist/coding-worker/artifact.js +3 -1
  89. package/dist/coding-worker/debug-trace.d.ts +9 -6
  90. package/dist/coding-worker/debug-trace.js +16 -19
  91. package/dist/coding-worker/dependency-cache.d.mts +229 -0
  92. package/dist/coding-worker/dependency-cache.mjs +2123 -0
  93. package/dist/coding-worker/driver.d.ts +4 -3
  94. package/dist/coding-worker/driver.js +124 -39
  95. package/dist/coding-worker/errors.d.ts +1 -0
  96. package/dist/coding-worker/errors.js +32 -0
  97. package/dist/coding-worker/main.js +5 -1
  98. package/dist/coding-worker/mcp-config.d.ts +27 -0
  99. package/dist/coding-worker/mcp-config.js +32 -0
  100. package/dist/coding-worker/sdk.d.ts +36 -0
  101. package/dist/coding-worker/sdk.js +28 -1
  102. package/dist/coding-worker/task-note.d.ts +11 -0
  103. package/dist/coding-worker/task-note.js +13 -0
  104. package/dist/coding-worker/types.d.ts +15 -0
  105. package/dist/config/dependency-cache.d.ts +23 -0
  106. package/dist/config/dependency-cache.js +32 -0
  107. package/dist/config/mcp-call-limit.d.ts +8 -0
  108. package/dist/config/mcp-call-limit.js +18 -0
  109. package/dist/config/mcp-servers.d.ts +8 -0
  110. package/dist/config/mcp-servers.js +12 -0
  111. package/dist/config/providers.d.ts +12 -3
  112. package/dist/config/providers.js +55 -5
  113. package/dist/config/test-simulators.d.ts +92 -0
  114. package/dist/config/test-simulators.js +333 -0
  115. package/dist/config/tool-timeout.d.ts +1 -0
  116. package/dist/config/tool-timeout.js +18 -0
  117. package/dist/core/async-context.d.ts +2 -0
  118. package/dist/core/async-context.js +12 -0
  119. package/dist/core/budget-events.d.ts +108 -0
  120. package/dist/core/budget-events.js +346 -0
  121. package/dist/core/budget-groups.d.ts +50 -1
  122. package/dist/core/budget-groups.js +236 -27
  123. package/dist/core/budget-stopped-head.d.ts +46 -0
  124. package/dist/core/budget-stopped-head.js +81 -0
  125. package/dist/core/budget-topup.d.ts +51 -0
  126. package/dist/core/budget-topup.js +156 -0
  127. package/dist/core/budget-wording.d.ts +16 -2
  128. package/dist/core/budget-wording.js +40 -2
  129. package/dist/core/coding-mcp.d.ts +36 -0
  130. package/dist/core/coding-mcp.js +253 -0
  131. package/dist/core/coding-queue.d.ts +2 -1
  132. package/dist/core/coding-queue.js +7 -0
  133. package/dist/core/coding-repository.d.ts +46 -0
  134. package/dist/core/coding-repository.js +92 -0
  135. package/dist/core/cron.d.ts +19 -1
  136. package/dist/core/cron.js +17 -0
  137. package/dist/core/datastores.js +1 -1
  138. package/dist/core/deferred-coding.d.ts +14 -0
  139. package/dist/core/deferred-coding.js +62 -0
  140. package/dist/core/delegation-child.d.ts +25 -0
  141. package/dist/core/delegation-child.js +37 -0
  142. package/dist/core/delegation-slots.d.ts +27 -0
  143. package/dist/core/delegation-slots.js +44 -0
  144. package/dist/core/dispatch.d.ts +48 -2
  145. package/dist/core/dispatch.js +166 -66
  146. package/dist/core/engine-native.js +1 -1
  147. package/dist/core/error-code.d.ts +38 -0
  148. package/dist/core/error-code.js +169 -0
  149. package/dist/core/grants.d.ts +46 -8
  150. package/dist/core/grants.js +99 -8
  151. package/dist/core/host-events.d.ts +18 -2
  152. package/dist/core/host-events.js +291 -27
  153. package/dist/core/host-status.d.ts +85 -3
  154. package/dist/core/host-status.js +300 -22
  155. package/dist/core/issue-bridge.d.ts +50 -6
  156. package/dist/core/issue-bridge.js +124 -33
  157. package/dist/core/issue-events.d.ts +1 -1
  158. package/dist/core/issue-events.js +4 -10
  159. package/dist/core/issue-status.d.ts +1 -1
  160. package/dist/core/issue-status.js +58 -29
  161. package/dist/core/logger.d.ts +5 -0
  162. package/dist/core/logger.js +14 -1
  163. package/dist/core/lost-run-children.d.ts +6 -0
  164. package/dist/core/lost-run-children.js +32 -0
  165. package/dist/core/mark-ready.d.ts +34 -0
  166. package/dist/core/mark-ready.js +152 -0
  167. package/dist/core/markdown-code.d.ts +8 -0
  168. package/dist/core/markdown-code.js +107 -0
  169. package/dist/core/mcp-client/client.d.ts +47 -0
  170. package/dist/core/mcp-client/client.js +141 -0
  171. package/dist/core/mcp-client/jsonrpc.d.ts +15 -0
  172. package/dist/core/mcp-client/jsonrpc.js +54 -0
  173. package/dist/core/mcp-client/results.d.ts +13 -0
  174. package/dist/core/mcp-client/results.js +42 -0
  175. package/dist/core/mcp-servers.d.ts +90 -0
  176. package/dist/core/mcp-servers.js +230 -0
  177. package/dist/core/mcp-tools.d.ts +108 -0
  178. package/dist/core/mcp-tools.js +287 -0
  179. package/dist/core/memory-tools.js +7 -0
  180. package/dist/core/merge-order-check.d.ts +2 -1
  181. package/dist/core/merge-order-check.js +44 -18
  182. package/dist/core/notification-dispatcher.js +2 -1
  183. package/dist/core/notification-templates.d.ts +1 -7
  184. package/dist/core/notification-templates.js +36 -2
  185. package/dist/core/pull-request-state-sync.js +2 -2
  186. package/dist/core/reconciler.d.ts +4 -3
  187. package/dist/core/reconciler.js +8 -1
  188. package/dist/core/related-pull-requests.d.ts +11 -3
  189. package/dist/core/related-pull-requests.js +49 -20
  190. package/dist/core/reply-parts.d.ts +21 -0
  191. package/dist/core/reply-parts.js +73 -0
  192. package/dist/core/review-fix.d.ts +1 -1
  193. package/dist/core/review-fix.js +4 -3
  194. package/dist/core/review-host-checks.d.ts +1 -1
  195. package/dist/core/review-host-tools.d.ts +3 -0
  196. package/dist/core/review-host-tools.js +102 -14
  197. package/dist/core/review-reads.d.ts +55 -0
  198. package/dist/core/review-reads.js +233 -0
  199. package/dist/core/run-status.d.ts +12 -0
  200. package/dist/core/run-status.js +12 -0
  201. package/dist/core/runner.d.ts +145 -49
  202. package/dist/core/runner.js +719 -216
  203. package/dist/core/schedule-start.d.ts +12 -0
  204. package/dist/core/schedule-start.js +14 -0
  205. package/dist/core/secret-broker-config.d.ts +12 -74
  206. package/dist/core/secret-broker-config.js +1 -1
  207. package/dist/core/secret-guard.d.ts +49 -0
  208. package/dist/core/secret-guard.js +119 -0
  209. package/dist/core/secret-guarded-stores.d.ts +12 -0
  210. package/dist/core/secret-guarded-stores.js +41 -0
  211. package/dist/core/secret-spans.d.ts +50 -0
  212. package/dist/core/secret-spans.js +94 -0
  213. package/dist/core/secrets.d.ts +11 -1
  214. package/dist/core/secrets.js +27 -1
  215. package/dist/core/serializable-retry.d.ts +18 -0
  216. package/dist/core/serializable-retry.js +43 -0
  217. package/dist/core/stop-run.d.ts +46 -0
  218. package/dist/core/stop-run.js +61 -0
  219. package/dist/core/tool-admin.d.ts +5 -1
  220. package/dist/core/tool-admin.js +7 -2
  221. package/dist/core/tool-names.d.ts +13 -0
  222. package/dist/core/tool-names.js +20 -0
  223. package/dist/core/webhooks.d.ts +4 -0
  224. package/dist/core/webhooks.js +68 -49
  225. package/dist/core/workflow-events.d.ts +14 -2
  226. package/dist/core/workflow-events.js +4 -0
  227. package/dist/core/workflow-run-events.d.ts +5 -3
  228. package/dist/core/workflow-run-events.js +45 -9
  229. package/dist/core/zod-json-schema.d.ts +4 -0
  230. package/dist/core/zod-json-schema.js +39 -0
  231. package/dist/core/zod3-window.d.ts +35 -0
  232. package/dist/core/zod3-window.js +124 -0
  233. package/dist/generated/prisma/browser.d.ts +65 -3
  234. package/dist/generated/prisma/client.d.ts +65 -3
  235. package/dist/generated/prisma/commonInputTypes.d.ts +266 -106
  236. package/dist/generated/prisma/enums.d.ts +10 -0
  237. package/dist/generated/prisma/enums.js +8 -0
  238. package/dist/generated/prisma/internal/class.d.ts +110 -0
  239. package/dist/generated/prisma/internal/class.js +4 -4
  240. package/dist/generated/prisma/internal/prismaNamespace.d.ts +957 -9
  241. package/dist/generated/prisma/internal/prismaNamespace.js +166 -2
  242. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +174 -0
  243. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +166 -2
  244. package/dist/generated/prisma/models/Agent.d.ts +377 -8
  245. package/dist/generated/prisma/models/AgentMcpServer.d.ts +1412 -0
  246. package/dist/generated/prisma/models/AgentMcpServer.js +1 -0
  247. package/dist/generated/prisma/models/AgentRepository.d.ts +81 -1
  248. package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
  249. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +228 -7
  250. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
  251. package/dist/generated/prisma/models/CodingProxySession.d.ts +232 -2
  252. package/dist/generated/prisma/models/CodingRun.d.ts +1712 -1
  253. package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
  254. package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
  255. package/dist/generated/prisma/models/HostProvider.d.ts +2176 -0
  256. package/dist/generated/prisma/models/HostProvider.js +1 -0
  257. package/dist/generated/prisma/models/HostProviderCredential.d.ts +1285 -0
  258. package/dist/generated/prisma/models/HostProviderCredential.js +1 -0
  259. package/dist/generated/prisma/models/HostProviderOperation.d.ts +1470 -0
  260. package/dist/generated/prisma/models/HostProviderOperation.js +1 -0
  261. package/dist/generated/prisma/models/HostProviderTrustedAccount.d.ts +1145 -0
  262. package/dist/generated/prisma/models/HostProviderTrustedAccount.js +1 -0
  263. package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
  264. package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
  265. package/dist/generated/prisma/models/McpServer.d.ts +1500 -0
  266. package/dist/generated/prisma/models/McpServer.js +1 -0
  267. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +77 -1
  268. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
  269. package/dist/generated/prisma/models/Principal.d.ts +167 -0
  270. package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
  271. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
  272. package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
  273. package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
  274. package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
  275. package/dist/generated/prisma/models/Run.d.ts +738 -2
  276. package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
  277. package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
  278. package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
  279. package/dist/generated/prisma/models/RunTranscript.js +1 -0
  280. package/dist/generated/prisma/models/Secret.d.ts +387 -0
  281. package/dist/generated/prisma/models/Tool.d.ts +223 -1
  282. package/dist/generated/prisma/models.d.ts +10 -0
  283. package/dist/help/search.js +12 -3
  284. package/dist/help-index.json +2033 -110
  285. package/dist/import/create.js +48 -4
  286. package/dist/import/neutral-schema.d.ts +51 -281
  287. package/dist/import/neutral-schema.js +7 -4
  288. package/dist/knowledge/check.d.ts +1 -1
  289. package/dist/knowledge/cli.d.ts +11 -1
  290. package/dist/knowledge/cli.js +37 -4
  291. package/dist/knowledge/concept.d.ts +3 -19
  292. package/dist/knowledge/location.d.ts +31 -0
  293. package/dist/knowledge/location.js +78 -0
  294. package/dist/mcp/auth/access.d.ts +10 -2
  295. package/dist/mcp/auth/access.js +15 -1
  296. package/dist/mcp/auth/grants-cli.d.ts +6 -4
  297. package/dist/mcp/auth/grants-cli.js +42 -3
  298. package/dist/mcp/auth/ownership.d.ts +7 -7
  299. package/dist/mcp/auth/resource-server.d.ts +3 -1
  300. package/dist/mcp/auth/resource-server.js +17 -2
  301. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  302. package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
  303. package/dist/mcp/context.d.ts +3 -0
  304. package/dist/mcp/host-events/github-ingress.d.ts +2 -0
  305. package/dist/mcp/host-events/github-ingress.js +2 -1
  306. package/dist/mcp/index.d.ts +6 -0
  307. package/dist/mcp/index.js +69 -10
  308. package/dist/mcp/server.d.ts +13 -0
  309. package/dist/mcp/server.js +33 -14
  310. package/dist/mcp/tools/agents.d.ts +4 -0
  311. package/dist/mcp/tools/agents.js +295 -28
  312. package/dist/mcp/tools/datastore.js +17 -8
  313. package/dist/mcp/tools/grants.js +73 -29
  314. package/dist/mcp/tools/host-providers.d.ts +2 -0
  315. package/dist/mcp/tools/host-providers.js +215 -0
  316. package/dist/mcp/tools/mcp-servers.d.ts +26 -0
  317. package/dist/mcp/tools/mcp-servers.js +481 -0
  318. package/dist/mcp/tools/memory.js +11 -1
  319. package/dist/mcp/tools/notification-channels.js +2 -2
  320. package/dist/mcp/tools/packages.d.ts +2 -0
  321. package/dist/mcp/tools/packages.js +195 -0
  322. package/dist/mcp/tools/repositories.js +65 -12
  323. package/dist/mcp/tools/run-access.d.ts +16 -0
  324. package/dist/mcp/tools/run-access.js +25 -0
  325. package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
  326. package/dist/mcp/tools/run-transcript-download.js +129 -0
  327. package/dist/mcp/tools/run-transcript.d.ts +19 -0
  328. package/dist/mcp/tools/run-transcript.js +70 -0
  329. package/dist/mcp/tools/runs.js +209 -27
  330. package/dist/mcp/tools/scheduling.js +3 -1
  331. package/dist/mcp/tools/secret-elicitation-form.js +5 -0
  332. package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
  333. package/dist/mcp/tools/secret-elicitation-server.js +10 -61
  334. package/dist/mcp/tools/secret-elicitation.d.ts +2 -0
  335. package/dist/mcp/tools/secret-elicitation.js +25 -2
  336. package/dist/mcp/tools/secrets.js +40 -6
  337. package/dist/mcp/tools/stop-run.d.ts +2 -0
  338. package/dist/mcp/tools/stop-run.js +82 -0
  339. package/dist/mcp/tools/subagents.js +2 -2
  340. package/dist/mcp/tools/tools.d.ts +7 -5
  341. package/dist/mcp/tools/tools.js +64 -16
  342. package/dist/mcp/tools/trigger.js +28 -6
  343. package/dist/mcp/transport/http-limits.d.ts +2 -0
  344. package/dist/mcp/transport/http-limits.js +6 -2
  345. package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
  346. package/dist/mcp/transport/stdio-link-host.js +67 -0
  347. package/dist/mcp/transport/streamable-http.d.ts +13 -0
  348. package/dist/mcp/transport/streamable-http.js +41 -1
  349. package/dist/mcp/webhooks/ingress.js +10 -0
  350. package/dist/native-worker/docker-launcher.d.ts +38 -2
  351. package/dist/native-worker/docker-launcher.js +65 -5
  352. package/dist/native-worker/gateway-server.d.ts +55 -3
  353. package/dist/native-worker/gateway-server.js +152 -34
  354. package/dist/native-worker/gateway.d.ts +29 -1
  355. package/dist/native-worker/gateway.js +74 -4
  356. package/dist/native-worker/http-server.d.ts +7 -1
  357. package/dist/native-worker/http-server.js +62 -7
  358. package/dist/native-worker/http-transport.js +1 -1
  359. package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
  360. package/dist/native-worker/kubernetes-launcher.js +43 -3
  361. package/dist/native-worker/launch.d.ts +18 -1
  362. package/dist/native-worker/launch.js +6 -1
  363. package/dist/native-worker/ledger.d.ts +24 -4
  364. package/dist/native-worker/ledger.js +62 -8
  365. package/dist/native-worker/loopback.js +3 -8
  366. package/dist/native-worker/main.d.ts +2 -1
  367. package/dist/native-worker/main.js +14 -3
  368. package/dist/native-worker/protocol.d.ts +130 -577
  369. package/dist/native-worker/protocol.js +51 -2
  370. package/dist/native-worker/sandbox-executor.d.ts +17 -2
  371. package/dist/native-worker/sandbox-executor.js +78 -4
  372. package/dist/native-worker/stderr-redaction.d.ts +77 -0
  373. package/dist/native-worker/stderr-redaction.js +237 -0
  374. package/dist/native-worker/stdio.d.ts +1 -1
  375. package/dist/native-worker/stdio.js +6 -5
  376. package/dist/native-worker/warm-pool.d.ts +2 -2
  377. package/dist/native-worker/warm-pool.js +4 -4
  378. package/dist/native-worker/worker.js +28 -2
  379. package/dist/observability/metrics.js +6 -1
  380. package/dist/providers/auth/self-hosted.d.ts +1 -1
  381. package/dist/providers/coding-proxy/capability-hash.d.ts +2 -0
  382. package/dist/providers/coding-proxy/capability-hash.js +5 -0
  383. package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
  384. package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
  385. package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
  386. package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
  387. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
  388. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
  389. package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
  390. package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
  391. package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
  392. package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
  393. package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
  394. package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
  395. package/dist/providers/coding-proxy/hold.d.ts +32 -0
  396. package/dist/providers/coding-proxy/hold.js +86 -0
  397. package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
  398. package/dist/providers/coding-proxy/interrupted.js +104 -0
  399. package/dist/providers/coding-proxy/mcp-route.d.ts +34 -0
  400. package/dist/providers/coding-proxy/mcp-route.js +166 -0
  401. package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -2
  402. package/dist/providers/coding-proxy/memory-ledger.js +99 -8
  403. package/dist/providers/coding-proxy/metering.d.ts +16 -0
  404. package/dist/providers/coding-proxy/metering.js +27 -4
  405. package/dist/providers/coding-proxy/prisma-ledger.d.ts +16 -2
  406. package/dist/providers/coding-proxy/prisma-ledger.js +209 -69
  407. package/dist/providers/coding-proxy/proxy.d.ts +21 -2
  408. package/dist/providers/coding-proxy/proxy.js +300 -48
  409. package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
  410. package/dist/providers/coding-proxy/registry/audit.js +94 -17
  411. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
  412. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
  413. package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
  414. package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
  415. package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
  416. package/dist/providers/coding-proxy/registry/plan.js +201 -48
  417. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
  418. package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
  419. package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
  420. package/dist/providers/coding-proxy/registry/service.js +579 -112
  421. package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
  422. package/dist/providers/coding-proxy/registry/store.js +54 -1
  423. package/dist/providers/coding-proxy/runtime.d.ts +10 -0
  424. package/dist/providers/coding-proxy/runtime.js +109 -16
  425. package/dist/providers/coding-proxy/server.d.ts +9 -1
  426. package/dist/providers/coding-proxy/server.js +55 -1
  427. package/dist/providers/coding-proxy/types.d.ts +78 -1
  428. package/dist/providers/datastore/types.d.ts +5 -0
  429. package/dist/providers/engine/types.d.ts +17 -2
  430. package/dist/providers/engine/types.js +17 -0
  431. package/dist/providers/executor/composition.d.ts +10 -3
  432. package/dist/providers/executor/composition.js +52 -7
  433. package/dist/providers/executor/container.d.ts +394 -9
  434. package/dist/providers/executor/container.js +1210 -96
  435. package/dist/providers/executor/dbos-status.d.ts +31 -0
  436. package/dist/providers/executor/dbos-status.js +64 -0
  437. package/dist/providers/executor/dbos.d.ts +50 -1
  438. package/dist/providers/executor/dbos.js +207 -20
  439. package/dist/providers/executor/deferred.d.ts +12 -24
  440. package/dist/providers/executor/deferred.js +10 -29
  441. package/dist/providers/executor/in-process.d.ts +9 -1
  442. package/dist/providers/executor/in-process.js +14 -4
  443. package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
  444. package/dist/providers/executor/linked-issue-reader.js +30 -0
  445. package/dist/providers/executor/routing.d.ts +2 -0
  446. package/dist/providers/executor/routing.js +4 -0
  447. package/dist/providers/executor/types.d.ts +13 -0
  448. package/dist/providers/host-tools/invoke.d.ts +37 -0
  449. package/dist/providers/host-tools/invoke.js +117 -0
  450. package/dist/providers/host-tools/operations.d.ts +65 -0
  451. package/dist/providers/host-tools/operations.js +149 -0
  452. package/dist/providers/host-tools/registry.d.ts +79 -0
  453. package/dist/providers/host-tools/registry.js +362 -0
  454. package/dist/providers/host-tools/request-guard.d.ts +17 -0
  455. package/dist/providers/host-tools/request-guard.js +99 -0
  456. package/dist/providers/host-tools/self-test.d.ts +64 -0
  457. package/dist/providers/host-tools/self-test.js +142 -0
  458. package/dist/providers/index.d.ts +2 -1
  459. package/dist/providers/issue-tracker/types.d.ts +17 -0
  460. package/dist/providers/issue-tracker/types.js +39 -1
  461. package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
  462. package/dist/providers/jobs/claude-tool-setup.js +5 -2
  463. package/dist/providers/jobs/docker-isolation.d.ts +10 -2
  464. package/dist/providers/jobs/docker-isolation.js +47 -8
  465. package/dist/providers/jobs/docker.d.ts +9 -0
  466. package/dist/providers/jobs/docker.js +60 -11
  467. package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
  468. package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
  469. package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
  470. package/dist/providers/jobs/kubernetes-api.js +10 -0
  471. package/dist/providers/jobs/kubernetes-client.js +10 -1
  472. package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
  473. package/dist/providers/jobs/kubernetes-isolation.js +32 -3
  474. package/dist/providers/jobs/kubernetes.d.ts +11 -1
  475. package/dist/providers/jobs/kubernetes.js +111 -17
  476. package/dist/providers/jobs/types.d.ts +39 -0
  477. package/dist/providers/jobs/types.js +13 -1
  478. package/dist/providers/llm/anthropic.js +5 -1
  479. package/dist/providers/llm/bedrock.d.ts +0 -12
  480. package/dist/providers/llm/bedrock.js +4 -0
  481. package/dist/providers/llm/claude-messages.d.ts +3 -1
  482. package/dist/providers/llm/claude-messages.js +4 -1
  483. package/dist/providers/llm/claude-provider.d.ts +2 -2
  484. package/dist/providers/llm/claude-provider.js +2 -2
  485. package/dist/providers/llm/openai.d.ts +2 -2
  486. package/dist/providers/llm/openai.js +6 -2
  487. package/dist/providers/llm/routing.d.ts +2 -2
  488. package/dist/providers/llm/routing.js +2 -2
  489. package/dist/providers/llm/types.d.ts +12 -2
  490. package/dist/providers/review-host/github-events.d.ts +9 -1
  491. package/dist/providers/review-host/github-events.js +34 -12
  492. package/dist/providers/review-host/github.d.ts +29 -2
  493. package/dist/providers/review-host/github.js +224 -29
  494. package/dist/providers/review-host/local.d.ts +8 -4
  495. package/dist/providers/review-host/local.js +49 -31
  496. package/dist/providers/review-host/patch-pages.d.ts +41 -0
  497. package/dist/providers/review-host/patch-pages.js +176 -0
  498. package/dist/providers/review-host/review-format.d.ts +19 -1
  499. package/dist/providers/review-host/review-format.js +38 -7
  500. package/dist/providers/review-host/types.d.ts +140 -6
  501. package/dist/providers/review-host/types.js +9 -1
  502. package/dist/providers/storage/gcs.d.ts +63 -0
  503. package/dist/providers/storage/gcs.js +69 -0
  504. package/dist/providers/storage/index.d.ts +15 -0
  505. package/dist/providers/storage/index.js +14 -0
  506. package/dist/providers/storage/local.d.ts +24 -0
  507. package/dist/providers/storage/local.js +92 -0
  508. package/dist/providers/storage/meter.d.ts +14 -0
  509. package/dist/providers/storage/meter.js +34 -0
  510. package/dist/providers/storage/s3.d.ts +41 -0
  511. package/dist/providers/storage/s3.js +107 -0
  512. package/dist/providers/storage/types.d.ts +37 -3
  513. package/dist/providers/storage/types.js +21 -4
  514. package/dist/providers/vcs/git.d.ts +39 -4
  515. package/dist/providers/vcs/git.js +339 -26
  516. package/dist/providers/vcs/github-remote.d.ts +26 -3
  517. package/dist/providers/vcs/github-remote.js +124 -14
  518. package/dist/providers/vcs/github.d.ts +183 -44
  519. package/dist/providers/vcs/github.js +455 -56
  520. package/dist/providers/vcs/index.d.ts +1 -1
  521. package/dist/providers/vcs/index.js +9 -2
  522. package/dist/providers/vcs/pr-description.d.ts +127 -0
  523. package/dist/providers/vcs/pr-description.js +270 -0
  524. package/dist/providers/vcs/remote.d.ts +37 -1
  525. package/dist/providers/vcs/remote.js +7 -1
  526. package/dist/providers/vcs/routing.d.ts +16 -8
  527. package/dist/providers/vcs/routing.js +27 -6
  528. package/dist/providers/vcs/types.d.ts +150 -5
  529. package/dist/quickstart/coding-seed.d.ts +14 -3
  530. package/dist/quickstart/coding-seed.js +213 -4
  531. package/dist/quickstart/index.d.ts +5 -0
  532. package/dist/quickstart/index.js +21 -0
  533. package/dist/quickstart/reviewer-prompt.d.ts +1 -1
  534. package/dist/quickstart/reviewer-prompt.js +6 -6
  535. package/dist/quickstart-images.json +1 -1
  536. package/dist/sandbox/eval-core.d.ts +12 -2
  537. package/dist/sandbox/eval-core.js +20 -4
  538. package/dist/sandbox/generated/zod.bundle.js +62 -1
  539. package/dist/sandbox/generated/zod3.bundle.js +5 -0
  540. package/dist/sandbox/host-functions.d.ts +5 -0
  541. package/dist/sandbox/host-functions.js +13 -13
  542. package/dist/sandbox/limits.d.ts +4 -1
  543. package/dist/sandbox/limits.js +4 -1
  544. package/dist/sandbox/run-in-sandbox.d.ts +6 -0
  545. package/dist/sandbox/run-in-sandbox.js +14 -2
  546. package/dist/sandbox/safe-fetch.d.ts +2 -0
  547. package/dist/sandbox/safe-fetch.js +1 -1
  548. package/dist/sandbox/secret-broker.d.ts +1 -0
  549. package/dist/sandbox/secret-broker.js +4 -5
  550. package/dist/sandbox/tool-capabilities.d.ts +10 -30
  551. package/dist/sandbox/tool-timeout.d.ts +32 -0
  552. package/dist/sandbox/tool-timeout.js +52 -0
  553. package/dist/sandbox/user-tool.d.ts +8 -1
  554. package/dist/sandbox/user-tool.js +9 -3
  555. package/dist/sandbox/zod-params.d.ts +37 -5
  556. package/dist/sandbox/zod-params.js +181 -26
  557. package/dist/serve.js +8 -1
  558. package/dist/viewer/api-schema.d.ts +349 -2627
  559. package/dist/viewer/api-schema.js +7 -0
  560. package/dist/viewer/build-schemas.js +6 -2
  561. package/dist/viewer/graph.js +2 -1
  562. package/dist/viewer/openapi.js +2 -4
  563. package/dist/wardby-bin.js +15 -0
  564. package/docs/README.md +11 -1
  565. package/docs/agent-recipes.md +95 -24
  566. package/docs/architecture-runtime.md +1 -1
  567. package/docs/claude-code-plugin.md +164 -0
  568. package/docs/code-review-agents.md +557 -41
  569. package/docs/coding-agent-setup.md +566 -8
  570. package/docs/coding-packages.md +1033 -90
  571. package/docs/coding-services.md +27 -12
  572. package/docs/coding-worker-byo-images.md +24 -2
  573. package/docs/coding-worker-isolation.md +183 -37
  574. package/docs/debugging-agent-runs.md +242 -0
  575. package/docs/getting-started-gke.md +129 -141
  576. package/docs/getting-started-identity-provider.md +53 -38
  577. package/docs/getting-started.md +17 -0
  578. package/docs/host-providers.md +294 -0
  579. package/docs/jira-agents.md +17 -8
  580. package/docs/knowledge/blob-not-found-semantics.md +41 -0
  581. package/docs/knowledge/bounded-file-descriptor.md +52 -0
  582. package/docs/knowledge/delegation-admission-slots.md +52 -0
  583. package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
  584. package/docs/knowledge/import-rename-target.md +52 -0
  585. package/docs/knowledge/index.md +57 -0
  586. package/docs/knowledge/log.md +9 -0
  587. package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
  588. package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
  589. package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
  590. package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
  591. package/docs/knowledge/overview-cli.md +74 -0
  592. package/docs/knowledge/overview-coding-proxy.md +72 -0
  593. package/docs/knowledge/overview-coding.md +72 -0
  594. package/docs/knowledge/overview-config.md +60 -0
  595. package/docs/knowledge/overview-core.md +72 -0
  596. package/docs/knowledge/overview-deploy.md +83 -0
  597. package/docs/knowledge/overview-mcp.md +61 -0
  598. package/docs/knowledge/overview-prisma.md +72 -0
  599. package/docs/knowledge/overview-providers.md +89 -0
  600. package/docs/knowledge/overview-sandbox.md +83 -0
  601. package/docs/knowledge/overview-surfaces.md +83 -0
  602. package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
  603. package/docs/knowledge/proxy-settlement-projections.md +41 -0
  604. package/docs/knowledge/run-pricing-first-writer.md +43 -0
  605. package/docs/knowledge/schedule-claim-transaction.md +41 -0
  606. package/docs/knowledge/secret-entry-replica-contract.md +52 -0
  607. package/docs/knowledge/terminal-run-first-writer.md +41 -0
  608. package/docs/knowledge/transactional-agent-authorization.md +52 -0
  609. package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
  610. package/docs/knowledge/warm-input-publication.md +30 -0
  611. package/docs/knowledge/workspace-staging-failure.md +54 -0
  612. package/docs/knowledge.md +54 -14
  613. package/docs/mcp-servers.md +254 -0
  614. package/docs/native-sandbox.md +143 -31
  615. package/docs/observability.md +4 -0
  616. package/docs/security-deployment.md +139 -29
  617. package/docs/slack-notifications.md +35 -19
  618. package/docs/tool-secrets.md +45 -10
  619. package/docs/viewer-api.md +6 -0
  620. package/docs/viewer-api.openapi.yml +1 -1
  621. package/help/admin-viewer.md +28 -2
  622. package/help/agent-recipes.md +33 -2
  623. package/help/architecture-agent.md +11 -6
  624. package/help/brokered-secrets.md +3 -0
  625. package/help/build-claude-code-image.md +1 -1
  626. package/help/build-worker-image.md +3 -1
  627. package/help/builder-agent.md +19 -6
  628. package/help/claude-code-run-pane.md +40 -0
  629. package/help/code-review-agents.md +177 -6
  630. package/help/coding-packages.md +156 -6
  631. package/help/cost-attribution.md +9 -5
  632. package/help/creating-agents.md +14 -1
  633. package/help/dependency-cache.md +143 -0
  634. package/help/deploy-gke.md +15 -8
  635. package/help/errors/budget-exhausted.md +187 -0
  636. package/help/errors/budget-group-exhausted.md +5 -1
  637. package/help/errors/coding-mcp-pins-unavailable.md +35 -0
  638. package/help/errors/coding-stream-quota-exceeded.md +33 -0
  639. package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
  640. package/help/errors/continuation-closed.md +9 -12
  641. package/help/errors/database-auth-invalid.md +1 -1
  642. package/help/errors/delegation-conflict.md +24 -0
  643. package/help/errors/file-list-truncated.md +45 -0
  644. package/help/errors/full-read-required.md +49 -0
  645. package/help/errors/github-account-not-allowed.md +4 -0
  646. package/help/errors/graph-incomplete.md +43 -0
  647. package/help/errors/graph-limit.md +43 -0
  648. package/help/errors/host-provider-error.md +40 -0
  649. package/help/errors/host-tool-failed.md +36 -0
  650. package/help/errors/mcp-call-limit.md +22 -0
  651. package/help/errors/mcp-call-timeout.md +22 -0
  652. package/help/errors/mcp-server-auth-failed.md +22 -0
  653. package/help/errors/mcp-server-credentials-unavailable.md +45 -0
  654. package/help/errors/mcp-server-error.md +28 -0
  655. package/help/errors/mcp-server-unreachable.md +22 -0
  656. package/help/errors/mcp-servers-off.md +21 -0
  657. package/help/errors/mcp-tool-not-allowed.md +26 -0
  658. package/help/errors/mcp-tool-removed.md +22 -0
  659. package/help/errors/mcp-unavailable.md +25 -0
  660. package/help/errors/merge-conflict.md +49 -0
  661. package/help/errors/native-sandbox-capacity.md +1 -1
  662. package/help/errors/native-sandbox-deadline-exceeded.md +1 -1
  663. package/help/errors/native-sandbox-docker-failed.md +1 -1
  664. package/help/errors/native-sandbox-gateway-error.md +20 -0
  665. package/help/errors/native-sandbox-gateway-unavailable.md +1 -1
  666. package/help/errors/native-sandbox-image-not-pinned.md +1 -1
  667. package/help/errors/native-sandbox-isolation-mismatch.md +1 -1
  668. package/help/errors/native-sandbox-launch-abandoned.md +21 -0
  669. package/help/errors/native-sandbox-network-unenforced.md +1 -1
  670. package/help/errors/native-sandbox-requires-catalog.md +1 -1
  671. package/help/errors/native-sandbox-unavailable.md +1 -1
  672. package/help/errors/native-sandbox-warm-delivery-failed.md +1 -1
  673. package/help/errors/native-sandbox-worker-exited.md +4 -3
  674. package/help/errors/native-sandbox-worker-lost.md +1 -1
  675. package/help/errors/native-sandbox-worker-unready.md +1 -1
  676. package/help/errors/package-not-allowed-pending.md +52 -0
  677. package/help/errors/package-not-allowed.md +51 -0
  678. package/help/errors/package-refusals.md +43 -0
  679. package/help/errors/patch-cursor-malformed.md +31 -0
  680. package/help/errors/repository-not-listed.md +36 -0
  681. package/help/errors/repository-required.md +36 -0
  682. package/help/errors/run-lost.md +39 -0
  683. package/help/errors/run-transcript-download.md +44 -0
  684. package/help/errors/secret-in-value.md +69 -0
  685. package/help/errors/target-merge.md +40 -0
  686. package/help/errors/tool-timeout.md +38 -0
  687. package/help/fix-merge-conflicts.md +73 -0
  688. package/help/github-app-setup.md +132 -0
  689. package/help/github.md +22 -0
  690. package/help/host-providers.md +40 -0
  691. package/help/identity-and-access.md +6 -1
  692. package/help/jira.md +23 -6
  693. package/help/knowledge.md +16 -7
  694. package/help/local-repositories.md +1 -1
  695. package/help/low-power-mode.md +7 -1
  696. package/help/mcp-servers.md +73 -0
  697. package/help/mcp.md +7 -2
  698. package/help/merge-order-check.md +5 -0
  699. package/help/native-capabilities.md +55 -1
  700. package/help/native-sandbox.md +16 -2
  701. package/help/operating-agents.md +21 -0
  702. package/help/package-audit-mode.md +91 -0
  703. package/help/related-pull-requests.md +17 -10
  704. package/help/repo-instructions-and-skills.md +3 -1
  705. package/help/resume-runs-locally.md +134 -0
  706. package/help/review-fix-rounds.md +33 -1
  707. package/help/sharing-agents.md +59 -0
  708. package/help/slack-notifications.md +19 -5
  709. package/help/status-comments.md +31 -0
  710. package/help/stop-run.md +58 -0
  711. package/help/troubleshooting/budgets.md +28 -0
  712. package/help/troubleshooting/coding-workers.md +86 -7
  713. package/help/troubleshooting/debugging-agent-runs.md +29 -0
  714. package/package.json +18 -10
  715. package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
  716. package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
  717. package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
  718. package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
  719. package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
  720. package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
  721. package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
  722. package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
  723. package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
  724. package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
  725. package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
  726. package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
  727. package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
  728. package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
  729. package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
  730. package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
  731. package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
  732. package/prisma/migrations/20261102000000_host_providers/migration.sql +56 -0
  733. package/prisma/migrations/20261104000000_coding_agent_repository_list/migration.sql +5 -0
  734. package/prisma/migrations/20261106000000_tool_timeout/migration.sql +4 -0
  735. package/prisma/migrations/20261107000000_mcp_servers/migration.sql +33 -0
  736. package/prisma/migrations/20261108000000_coding_mcp/migration.sql +5 -0
  737. package/prisma/migrations/20261109000000_task_run_index/migration.sql +3 -0
  738. package/prisma/schema.prisma +468 -109
  739. package/scripts/git-askpass.sh +1 -1
  740. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
@@ -0,0 +1,406 @@
1
+ /**
2
+ * PyPI lockfile verification hooks (`POST /registry/pypi/-/plan`): parsing a
3
+ * `uv.lock` or a pinned requirements file (`pip-compile`, `uv pip compile`,
4
+ * `pip freeze`) into entries, and reading each pinned release's facts from
5
+ * PyPI's JSON API. Nothing here decides anything: the registry core verifies
6
+ * every claim against these registry reads (plan.ts).
7
+ *
8
+ * Approvals are names (`approves: "names"`): a release has many files, and
9
+ * every download keeps the usual per-file checks (wheels only, per-file
10
+ * release age, the index's sha256). No lockfile integrity is compared
11
+ * (`integrity: "registry"`); pip and uv check the hashes a lockfile records
12
+ * themselves.
13
+ *
14
+ * Kept free of imports from pypi.ts, which imports this module.
15
+ */
16
+ import { eq as pepEq, satisfies as pepSatisfies, valid as pepValid } from "@renovatebot/pep440";
17
+ import { parse as parseToml } from "smol-toml";
18
+ import { badRequest, tooLarge } from "./lockfile-shared.js";
19
+ import { followedLines, isPypiProjectName, normalizePypiName, requirementLine, } from "./pypi-requirements.js";
20
+ import { RegistryError, } from "./types.js";
21
+ const JSON_API = "https://pypi.org/pypi/";
22
+ /** The index URLs a registry package in a uv.lock may name (besides the proxy's own). */
23
+ const PUBLIC_INDEXES = ["https://pypi.org/simple", "https://pypi.org/simple/"];
24
+ /** The most dependency lines read from one release. */
25
+ const MAX_REQUIRES_DIST = 2000;
26
+ function unsupported(message) {
27
+ return new RegistryError(400, "wardby_lockfile_unsupported", message);
28
+ }
29
+ /** A registry entry for `name==version`, or an unsupported one when either is not valid. */
30
+ function entryOf(name, version) {
31
+ const path = `${normalizePypiName(name)}@${version}`;
32
+ if (!isPypiProjectName(name) || pepValid(version) === null)
33
+ return {
34
+ path,
35
+ name,
36
+ version,
37
+ integrity: null,
38
+ kind: "unsupported",
39
+ unsupportedReason: "not a valid Python project name and exact version",
40
+ };
41
+ return { path, name: normalizePypiName(name), version, integrity: null, kind: "registry" };
42
+ }
43
+ function unsupportedEntry(name, version, reason) {
44
+ const normalized = isPypiProjectName(name) ? normalizePypiName(name) : name;
45
+ return {
46
+ path: `${normalized}@${version}`,
47
+ name: normalized,
48
+ version,
49
+ integrity: null,
50
+ kind: "unsupported",
51
+ unsupportedReason: reason,
52
+ };
53
+ }
54
+ /** Entries by name, for a lockfile with no per-parent pins (a requirements file). */
55
+ function byName(entries) {
56
+ const names = new Map();
57
+ for (const entry of entries)
58
+ names.set(entry.name, [...(names.get(entry.name) ?? []), entry]);
59
+ return names;
60
+ }
61
+ // --- requirements files ------------------------------------------------------
62
+ /** One logical line of a requirements file: continuations joined, the comment removed. */
63
+ function logicalLines(body) {
64
+ const lines = [];
65
+ let pending = "";
66
+ for (const raw of body.split(/\r?\n/)) {
67
+ const line = raw.trimEnd();
68
+ if (line.endsWith("\\")) {
69
+ pending += `${line.slice(0, -1)} `;
70
+ continue;
71
+ }
72
+ lines.push(pending + line);
73
+ pending = "";
74
+ }
75
+ if (pending)
76
+ lines.push(pending);
77
+ // A comment starts at a `#` at the line's start or after whitespace (pip's rule).
78
+ return lines.map((line) => line.replace(/(^|\s)#.*$/, "").trim()).filter((line) => line !== "");
79
+ }
80
+ /** The requirement part of a line: everything before its first per-requirement option (`--hash=…`). */
81
+ function requirementPart(line) {
82
+ const option = line.search(/\s--?[A-Za-z]/);
83
+ return (option === -1 ? line : line.slice(0, option)).trim();
84
+ }
85
+ const PINNED = /^([A-Za-z0-9][A-Za-z0-9._-]*)\s*(?:\[[^\]]*\])?\s*(.*)$/;
86
+ /**
87
+ * A pinned requirements file: every `name==version` (or `===`) line is an
88
+ * entry; a direct reference (`name @ url`) is an unsupported one. Options
89
+ * (`-r`, `-c`, `--index-url`, …), editable or local projects and unpinned
90
+ * lines are not entries: pip resolves those the usual way. The file records
91
+ * no dependency graph, so a parent's dependency resolves to every entry of
92
+ * that name (marker-split pins).
93
+ */
94
+ export function parseRequirements(body, maxEntries) {
95
+ const entries = [];
96
+ for (const line of logicalLines(body)) {
97
+ if (line.startsWith("-"))
98
+ continue;
99
+ const requirement = requirementPart(line);
100
+ const match = requirement.match(PINNED);
101
+ if (!match)
102
+ continue;
103
+ const name = match[1];
104
+ const spec = match[2].split(";")[0].trim();
105
+ if (spec.startsWith("@")) {
106
+ entries.push(unsupportedEntry(name, "url", "installed from a URL, not the package registry"));
107
+ continue;
108
+ }
109
+ const pin = spec.match(/^===?\s*([^\s,;*]+)$/);
110
+ if (!pin)
111
+ continue;
112
+ entries.push(entryOf(name, pin[1]));
113
+ if (entries.length > maxEntries)
114
+ throw tooLarge(entries.length, maxEntries);
115
+ }
116
+ const unique = [...new Map(entries.map((entry) => [entry.path, entry])).values()];
117
+ const names = byName(unique);
118
+ return {
119
+ entries: unique,
120
+ projects: [],
121
+ integrity: "registry",
122
+ resolve: (_from, key) => names.get(key)?.[0],
123
+ resolveAll: (_from, key) => names.get(key) ?? [],
124
+ };
125
+ }
126
+ /** Every `{ name, version? }` a package's dependency lists name (all groups and extras). */
127
+ function lockDependencies(pkg) {
128
+ const lists = [pkg.dependencies];
129
+ for (const field of ["optional-dependencies", "dev-dependencies"]) {
130
+ const groups = pkg[field];
131
+ if (groups && typeof groups === "object" && !Array.isArray(groups))
132
+ lists.push(...Object.values(groups));
133
+ }
134
+ const out = [];
135
+ for (const list of lists) {
136
+ if (!Array.isArray(list))
137
+ continue;
138
+ for (const item of list) {
139
+ if (typeof item?.name !== "string" || !isPypiProjectName(item.name))
140
+ continue;
141
+ out.push({
142
+ name: normalizePypiName(item.name),
143
+ ...(typeof item.version === "string" ? { version: item.version } : {}),
144
+ });
145
+ }
146
+ }
147
+ return out;
148
+ }
149
+ /**
150
+ * A uv.lock (`version = 1`). A package from PyPI (or the proxy) is an
151
+ * entry; the lock's own projects (editable, virtual and directory sources)
152
+ * are its projects; one from git, a URL, a path or another index is
153
+ * unsupported. A dependency resolves to the version the lock names for it
154
+ * when the lock pins the name at several versions.
155
+ */
156
+ export function parseUvLock(body, maxEntries, proxyRegistryUrl) {
157
+ let doc;
158
+ try {
159
+ doc = parseToml(body);
160
+ }
161
+ catch {
162
+ throw badRequest("the uv.lock is not valid TOML");
163
+ }
164
+ if (doc.version !== 1)
165
+ throw unsupported(`uv.lock version ${String(doc.version)} is not supported (version 1 is)`);
166
+ const packages = Array.isArray(doc.package) ? doc.package : [];
167
+ if (packages.length > maxEntries)
168
+ throw tooLarge(packages.length, maxEntries);
169
+ const indexes = new Set([...PUBLIC_INDEXES, `${proxyRegistryUrl}simple`, `${proxyRegistryUrl}simple/`]);
170
+ const entries = [];
171
+ const projects = [];
172
+ const pins = new Map();
173
+ for (const pkg of packages) {
174
+ if (typeof pkg?.name !== "string")
175
+ throw badRequest("a uv.lock package has no name");
176
+ const name = pkg.name;
177
+ const version = typeof pkg.version === "string" ? pkg.version : "";
178
+ const source = pkg.source && typeof pkg.source === "object" ? pkg.source : {};
179
+ const dependencies = lockDependencies(pkg);
180
+ const path = `${isPypiProjectName(name) ? normalizePypiName(name) : name}@${version}`;
181
+ pins.set(path, new Map(dependencies.map((dependency) => [dependency.name, dependency.version])));
182
+ if ("editable" in source || "virtual" in source || "directory" in source) {
183
+ projects.push({
184
+ path,
185
+ dependencies: dependencies.map((dependency) => ({ key: dependency.name, name: dependency.name, range: "*" })),
186
+ });
187
+ continue;
188
+ }
189
+ if (typeof source.registry !== "string") {
190
+ entries.push(unsupportedEntry(name, version, "installed from git, a URL or a path, not the package registry"));
191
+ continue;
192
+ }
193
+ if (!indexes.has(source.registry)) {
194
+ entries.push(unsupportedEntry(name, version, "locked from another package index"));
195
+ continue;
196
+ }
197
+ entries.push(entryOf(name, version));
198
+ }
199
+ const names = byName(entries);
200
+ const resolve = (from, key) => {
201
+ const candidates = names.get(key);
202
+ if (!candidates || candidates.length <= 1)
203
+ return candidates?.[0];
204
+ const pinned = pins.get(from)?.get(key);
205
+ return pinned === undefined ? candidates[0] : candidates.find((entry) => entry.version === pinned);
206
+ };
207
+ return { entries, projects, integrity: "registry", resolve };
208
+ }
209
+ // --- format detection ----------------------------------------------------------
210
+ /** Which file a plan body is: a uv.lock, a requirements file, or one this registry cannot verify. */
211
+ export function parsePypiLockfile(body, options) {
212
+ const text = body.startsWith("") ? body.slice(1) : body;
213
+ if (/^# This file is automatically @generated by Poetry/m.test(text) || /^content-hash\s*=/m.test(text))
214
+ throw unsupported("Poetry lockfiles are not verified; install from a requirements file or uv.lock instead");
215
+ if (/^lock-version\s*=/m.test(text))
216
+ throw unsupported("pylock.toml files are not verified; install from a requirements file or uv.lock instead");
217
+ if (/^\[\[package\]\]\s*$/m.test(text) || /^version\s*=\s*\d+\s*$/m.test(text))
218
+ return parseUvLock(text, options.maxEntries, options.proxyRegistryUrl);
219
+ return parseRequirements(text, options.maxEntries);
220
+ }
221
+ /** The release's wheels PyPI still serves, each with its upload time and sha256. */
222
+ function wheelsOf(urls) {
223
+ if (!Array.isArray(urls))
224
+ return [];
225
+ return urls.flatMap((file) => {
226
+ if (file?.packagetype !== "bdist_wheel" || file.yanked === true)
227
+ return [];
228
+ if (typeof file.filename !== "string" || !file.filename.endsWith(".whl") || typeof file.url !== "string")
229
+ return [];
230
+ const sha256 = typeof file.digests?.sha256 === "string" ? file.digests.sha256 : "";
231
+ const time = typeof file.upload_time_iso_8601 === "string" ? Date.parse(file.upload_time_iso_8601) : NaN;
232
+ return [{ url: file.url, sha256, uploadedAt: Number.isNaN(time) ? null : new Date(time) }];
233
+ });
234
+ }
235
+ /** The earliest upload among `wheels`, or null when none records one. */
236
+ function earliest(wheels) {
237
+ const times = wheels.flatMap((wheel) => (wheel.uploadedAt ? [wheel.uploadedAt.getTime()] : []));
238
+ return times.length === 0 ? null : new Date(Math.min(...times));
239
+ }
240
+ async function fetchRelease(name, version, upstream, signal) {
241
+ const response = await upstream(`${JSON_API}${encodeURIComponent(name)}/${encodeURIComponent(version)}/json`, {
242
+ accept: "application/json",
243
+ signal,
244
+ });
245
+ if (response.status === 404) {
246
+ await response.body?.cancel().catch(() => undefined);
247
+ return null;
248
+ }
249
+ if (!response.ok)
250
+ throw new RegistryError(502, "wardby_upstream_error", `PyPI returned ${response.status}`);
251
+ const doc = (await response.json());
252
+ if (!doc.info || typeof doc.info !== "object")
253
+ return null;
254
+ const info = doc.info;
255
+ // The release must be exactly the one the lockfile pins.
256
+ if (typeof info.name !== "string" || normalizePypiName(info.name) !== name)
257
+ return null;
258
+ if (typeof info.version !== "string" || !safeEq(info.version, version))
259
+ return null;
260
+ return { info, urls: doc.urls };
261
+ }
262
+ function safeEq(a, b) {
263
+ try {
264
+ return pepEq(a, b);
265
+ }
266
+ catch {
267
+ return a === b;
268
+ }
269
+ }
270
+ /** One release's facts: its dependency lines (with their extras and extra
271
+ * gates), and its earliest wheel's upload time, URL and sha256. A release
272
+ * with no wheel is refused (`wardby_file_not_allowed`): nothing in it may
273
+ * be installed. */
274
+ export async function fetchPypiVersionFact(name, version, upstream, signal) {
275
+ const release = await fetchRelease(name, version, upstream, signal);
276
+ if (!release)
277
+ return null;
278
+ const wheels = wheelsOf(release.urls);
279
+ if (wheels.length === 0)
280
+ throw new RegistryError(403, "wardby_file_not_allowed", `${name} ${version} has no wheel on PyPI (only a source distribution), and only wheels are installed`);
281
+ const publishedAt = earliest(wheels);
282
+ const first = wheels.find((wheel) => wheel.uploadedAt?.getTime() === publishedAt?.getTime()) ?? wheels[0];
283
+ const lines = Array.isArray(release.info.requires_dist) ? release.info.requires_dist.slice(0, MAX_REQUIRES_DIST) : [];
284
+ const dependencies = [];
285
+ for (const value of lines) {
286
+ const line = typeof value === "string" ? requirementLine(value.trim()) : null;
287
+ if (!line || line.range === null)
288
+ continue;
289
+ dependencies.push({
290
+ key: line.name,
291
+ name: line.name,
292
+ range: line.range,
293
+ ...(line.extras.length > 0 ? { extras: line.extras } : {}),
294
+ ...(line.gate !== null ? { when: line.gate } : {}),
295
+ });
296
+ }
297
+ return {
298
+ name,
299
+ version,
300
+ publishedAt,
301
+ integrity: /^[0-9a-f]{64}$/.test(first.sha256)
302
+ ? `sha256-${Buffer.from(first.sha256, "hex").toString("base64")}`
303
+ : "",
304
+ downloadUrl: first.url,
305
+ dependencies,
306
+ };
307
+ }
308
+ /** Publish times for releases whose fact carried none (no wheel recorded an upload time). */
309
+ export async function fetchPypiPublishTimes(name, versions, upstream, options) {
310
+ const times = new Map();
311
+ for (const version of versions) {
312
+ const release = await fetchRelease(name, version, upstream, options.signal);
313
+ const time = release ? earliest(wheelsOf(release.urls)) : null;
314
+ if (time)
315
+ times.set(version, time);
316
+ }
317
+ return times;
318
+ }
319
+ /** Whether a locked version is inside a dependency line's specifier, a
320
+ * pinned pre-release included. */
321
+ export function pypiEdgeSatisfies(version, range) {
322
+ if (range === "*" || range === "")
323
+ return true;
324
+ try {
325
+ return pepSatisfies(version, range, { prereleases: true });
326
+ }
327
+ catch {
328
+ return false;
329
+ }
330
+ }
331
+ /** The dependencies a release installed with `extras` follows, under the
332
+ * same extras policy as the graph walk (pypi-requirements.ts). */
333
+ export function pypiDependenciesOf(fact, extras) {
334
+ const lines = fact.dependencies.map((dependency) => ({
335
+ name: dependency.name,
336
+ extras: [...(dependency.extras ?? [])],
337
+ gate: dependency.when ? [...dependency.when] : null,
338
+ range: dependency.range,
339
+ }));
340
+ const followed = followedLines(fact.name, lines, extras);
341
+ return followed.lines.map((line) => ({
342
+ key: line.name,
343
+ name: line.name,
344
+ range: line.range ?? "*",
345
+ ...(!followed.plain && line.extras.length > 0 ? { extras: line.extras } : {}),
346
+ }));
347
+ }
348
+ export const pypiLockfilePlan = {
349
+ approves: "names",
350
+ parse: parsePypiLockfile,
351
+ fetchVersionFact: fetchPypiVersionFact,
352
+ fetchPublishTimes: fetchPypiPublishTimes,
353
+ edgeSatisfies: pypiEdgeSatisfies,
354
+ dependenciesOf: pypiDependenciesOf,
355
+ };
356
+ // --- uv.lock URLs ----------------------------------------------------------------
357
+ /** PyPI's own path for a file by project and filename, which redirects to the
358
+ * file (a wheel's python tag, or `source` for an sdist). */
359
+ export function publicFileUrl(name, filename) {
360
+ if (!isPypiProjectName(name) || !/^[A-Za-z0-9._+!-]+$/.test(filename))
361
+ return undefined;
362
+ let tag = "source";
363
+ if (filename.endsWith(".whl")) {
364
+ const parts = filename.slice(0, -".whl".length).split("-");
365
+ if (parts.length < 5)
366
+ return undefined;
367
+ tag = parts[parts.length - 3];
368
+ }
369
+ else if (!/\.(?:tar\.gz|zip)$/.test(filename))
370
+ return undefined;
371
+ return `https://files.pythonhosted.org/packages/${tag}/${name[0]}/${name}/${filename}`;
372
+ }
373
+ function escapeRegExp(text) {
374
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
375
+ }
376
+ function decodedOrUndefined(text) {
377
+ try {
378
+ return decodeURIComponent(text);
379
+ }
380
+ catch {
381
+ return undefined;
382
+ }
383
+ }
384
+ /**
385
+ * A uv.lock with the proxy's URLs (which uv records when it locks through
386
+ * the proxy) put back to PyPI's: its index as `https://pypi.org/simple`, each
387
+ * file as PyPI's redirecting path (publicFileUrl). Credentials are never in
388
+ * them (uv records none), but any userinfo before the proxy host is dropped
389
+ * with the URL anyway. Everything else is left exactly as it was.
390
+ */
391
+ export function normalizeUvLock(content, registryUrl) {
392
+ const at = registryUrl.indexOf("://");
393
+ if (at < 0)
394
+ return content;
395
+ const scheme = escapeRegExp(registryUrl.slice(0, at + 3));
396
+ const rest = escapeRegExp(registryUrl.slice(at + 3));
397
+ const base = `${scheme}(?:[^@/"\\s]*@)?${rest}`;
398
+ return content
399
+ .replace(new RegExp(`"${base}simple/?"`, "g"), `"${PUBLIC_INDEXES[0]}"`)
400
+ .replace(new RegExp(`"${base}files/([^/"]+)/([^/"]+)"`, "g"), (match, rawName, rawFile) => {
401
+ const name = decodedOrUndefined(rawName);
402
+ const filename = decodedOrUndefined(rawFile);
403
+ const url = name && filename ? publicFileUrl(name, filename) : undefined;
404
+ return url ? `"${url}"` : match;
405
+ });
406
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * PyPI dependency lines (PEP 508 requirements as wheel METADATA and PyPI's
3
+ * `requires_dist` write them) and the extras policy both the graph walk and
4
+ * lockfile verification follow. Kept free of imports from pypi.ts, which
5
+ * imports this module.
6
+ */
7
+ import type { FileDependency } from "./types.js";
8
+ /** The most extras one allowlist entry or dependency line may name. */
9
+ export declare const MAX_EXTRAS = 32;
10
+ export declare function isPypiProjectName(name: string): boolean;
11
+ export declare function normalizePypiName(name: string): string;
12
+ /** Normalized (PEP 685), sorted, de-duplicated extras from the text inside
13
+ * `[...]`, or null when any is not a valid extra name (PEP 508: the same
14
+ * shape as a project name), the list is empty, or it names too many. */
15
+ export declare function parseExtras(list: string): string[] | null;
16
+ export interface RequirementLine {
17
+ name: string;
18
+ extras: string[];
19
+ /** The extras the line is gated on; null when it is not extra-gated. */
20
+ gate: string[] | null;
21
+ /** The PEP 440 specifier the line asks for (`"*"` for none); null for a
22
+ * direct reference (`name @ url`), which is never a registry edge. */
23
+ range: string | null;
24
+ }
25
+ /** One Requires-Dist value (`uvicorn[standard] (>=0.30) ; extra == "web"`),
26
+ * split only at its first `;` (the marker), which is all wheel METADATA and
27
+ * PyPI's `requires_dist` need: no `name @ url` with a `;` in the URL, no
28
+ * comments or line continuations as in a requirements file. Null when it
29
+ * names no valid project. */
30
+ export declare function requirementLine(value: string): RequirementLine | null;
31
+ /**
32
+ * The lines an install of the package `self` with `extras` follows: every
33
+ * line without an `extra == "…"` marker clause, plus the lines whose marker
34
+ * names one of the install's extras (other marker clauses are ignored, so a
35
+ * requested extra's lines are included on every platform). A line gated on
36
+ * any other extra is skipped. A line naming the package itself
37
+ * (`celery[redis]; extra == "all"`) adds those extras to this install
38
+ * instead, and is not returned. `plain`: the install has no extras, so its
39
+ * dependencies are installed bare.
40
+ */
41
+ export declare function followedLines(self: string | null, lines: readonly RequirementLine[], extras: readonly string[]): {
42
+ lines: RequirementLine[];
43
+ plain: boolean;
44
+ };
45
+ /**
46
+ * The dependencies a wheel's METADATA declares for an install of the package
47
+ * with `extras` (see `followedLines`). Each dependency carries the extras its
48
+ * line asks of it (`uvicorn[standard]`). Names and extras are validated and
49
+ * normalized.
50
+ *
51
+ * Policy, not pip: a plain install (no `extras`) follows no extras at all,
52
+ * neither its own (a self-referencing line) nor its dependencies' — each
53
+ * dependency comes back bare, so extras are followed only along a chain that
54
+ * starts at an allowlist entry naming extras.
55
+ */
56
+ export declare function requiredDists(metadataText: string, extras?: readonly string[]): FileDependency[];
57
+ /** Dependency names a METADATA declares for a plain install (no extras). */
58
+ export declare function requiresDist(metadataText: string): string[];
@@ -0,0 +1,155 @@
1
+ /** The most extras one allowlist entry or dependency line may name. */
2
+ export const MAX_EXTRAS = 32;
3
+ /** A valid PyPI project name (PEP 508): ASCII letters and digits, with
4
+ * `.`, `_` and `-` allowed only between them. */
5
+ const PROJECT_NAME = /^(?:[A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9._-]*[A-Za-z0-9])$/;
6
+ export function isPypiProjectName(name) {
7
+ return PROJECT_NAME.test(name);
8
+ }
9
+ export function normalizePypiName(name) {
10
+ return name.toLowerCase().replace(/[-_.]+/g, "-");
11
+ }
12
+ /** Normalized (PEP 685), sorted, de-duplicated extras from the text inside
13
+ * `[...]`, or null when any is not a valid extra name (PEP 508: the same
14
+ * shape as a project name), the list is empty, or it names too many. */
15
+ export function parseExtras(list) {
16
+ const items = list.split(",").map((item) => item.trim());
17
+ if (items.length > MAX_EXTRAS || items.some((item) => !PROJECT_NAME.test(item)))
18
+ return null;
19
+ return [...new Set(items.map(normalizePypiName))].sort();
20
+ }
21
+ /** The string literals a marker compares `extra` to with `==` or `===`
22
+ * (either operand order), normalized; null when the marker never mentions
23
+ * `extra`. Tokenized, so a quoted value never counts as a clause. Fails
24
+ * closed: when `extra` appears in any shape this does not fully recognise
25
+ * (`extra in "a b"`, `extra.x`, a bare `extra`, an unbalanced quote), the
26
+ * line is gated on no extra at all, so it is never followed. */
27
+ function markerExtras(marker) {
28
+ if (!/\bextra\b/.test(marker))
29
+ return null;
30
+ const tokens = marker.match(/"[^"]*"|'[^']*'|===|==|!=|<=|>=|~=|[A-Za-z_][A-Za-z0-9_.]*|\S/g) ?? [];
31
+ const isLiteral = (token) => token !== undefined && token.length >= 2 && (token[0] === '"' || token[0] === "'");
32
+ const isEquals = (token) => token === "==" || token === "===";
33
+ // A lone quote (unterminated string) means the marker cannot be read.
34
+ if (tokens.some((token) => token === '"' || token === "'"))
35
+ return [];
36
+ const found = [];
37
+ let recognised = 0;
38
+ for (let i = 0; i < tokens.length; i++) {
39
+ if (tokens[i] !== "extra")
40
+ continue;
41
+ let value = null;
42
+ if (isEquals(tokens[i + 1]) && isLiteral(tokens[i + 2]))
43
+ value = tokens[i + 2].slice(1, -1);
44
+ else if (isEquals(tokens[i - 1]) && isLiteral(tokens[i - 2]))
45
+ value = tokens[i - 2].slice(1, -1);
46
+ if (value === null)
47
+ return [];
48
+ recognised++;
49
+ if (PROJECT_NAME.test(value))
50
+ found.push(normalizePypiName(value));
51
+ }
52
+ // `extra` only inside quoted values: not a clause, but not one this reads either.
53
+ return recognised === 0 ? [] : found;
54
+ }
55
+ const REQUIREMENT = /^([A-Za-z0-9][A-Za-z0-9._-]*)\s*(?:\[([^\]]*)\])?/;
56
+ /** One Requires-Dist value (`uvicorn[standard] (>=0.30) ; extra == "web"`),
57
+ * split only at its first `;` (the marker), which is all wheel METADATA and
58
+ * PyPI's `requires_dist` need: no `name @ url` with a `;` in the URL, no
59
+ * comments or line continuations as in a requirements file. Null when it
60
+ * names no valid project. */
61
+ export function requirementLine(value) {
62
+ const match = value.match(REQUIREMENT);
63
+ if (!match || !PROJECT_NAME.test(match[1]))
64
+ return null;
65
+ const semicolon = value.indexOf(";", match[0].length);
66
+ const spec = (semicolon === -1 ? value.slice(match[0].length) : value.slice(match[0].length, semicolon)).trim();
67
+ const bare = spec.startsWith("(") && spec.endsWith(")") ? spec.slice(1, -1).trim() : spec;
68
+ return {
69
+ name: normalizePypiName(match[1]),
70
+ // A malformed extras list still installs the package, just none of its extras.
71
+ extras: match[2] === undefined ? [] : (parseExtras(match[2]) ?? []),
72
+ gate: semicolon === -1 ? null : markerExtras(value.slice(semicolon + 1)),
73
+ range: bare.startsWith("@") ? null : bare === "" ? "*" : bare,
74
+ };
75
+ }
76
+ function requirementLines(metadataText) {
77
+ let self = null;
78
+ const lines = [];
79
+ for (const line of metadataText.split(/\r?\n/)) {
80
+ // The headers end at the first truly empty line; the description
81
+ // follows. A whitespace-only line is a folded header's continuation.
82
+ if (line === "")
83
+ break;
84
+ if (line.startsWith("Name:")) {
85
+ const name = line.slice("Name:".length).trim();
86
+ if (self === null && PROJECT_NAME.test(name))
87
+ self = normalizePypiName(name);
88
+ continue;
89
+ }
90
+ if (!line.startsWith("Requires-Dist:"))
91
+ continue;
92
+ const parsed = requirementLine(line.slice("Requires-Dist:".length).trim());
93
+ if (parsed)
94
+ lines.push(parsed);
95
+ }
96
+ return { self, lines };
97
+ }
98
+ /**
99
+ * The lines an install of the package `self` with `extras` follows: every
100
+ * line without an `extra == "…"` marker clause, plus the lines whose marker
101
+ * names one of the install's extras (other marker clauses are ignored, so a
102
+ * requested extra's lines are included on every platform). A line gated on
103
+ * any other extra is skipped. A line naming the package itself
104
+ * (`celery[redis]; extra == "all"`) adds those extras to this install
105
+ * instead, and is not returned. `plain`: the install has no extras, so its
106
+ * dependencies are installed bare.
107
+ */
108
+ export function followedLines(self, lines, extras) {
109
+ const requested = new Set(extras.map(normalizePypiName));
110
+ const plain = requested.size === 0;
111
+ const included = (line) => line.gate === null || line.gate.some((extra) => requested.has(extra));
112
+ for (let grew = !plain; grew;) {
113
+ grew = false;
114
+ for (const line of lines) {
115
+ if (line.name !== self || !included(line))
116
+ continue;
117
+ for (const extra of line.extras) {
118
+ if (requested.size >= MAX_EXTRAS || requested.has(extra))
119
+ continue;
120
+ requested.add(extra);
121
+ grew = true;
122
+ }
123
+ }
124
+ }
125
+ return { lines: lines.filter((line) => line.name !== self && included(line)), plain };
126
+ }
127
+ /**
128
+ * The dependencies a wheel's METADATA declares for an install of the package
129
+ * with `extras` (see `followedLines`). Each dependency carries the extras its
130
+ * line asks of it (`uvicorn[standard]`). Names and extras are validated and
131
+ * normalized.
132
+ *
133
+ * Policy, not pip: a plain install (no `extras`) follows no extras at all,
134
+ * neither its own (a self-referencing line) nor its dependencies' — each
135
+ * dependency comes back bare, so extras are followed only along a chain that
136
+ * starts at an allowlist entry naming extras.
137
+ */
138
+ export function requiredDists(metadataText, extras = []) {
139
+ const { self, lines } = requirementLines(metadataText);
140
+ const followed = followedLines(self, lines, extras);
141
+ const out = new Map();
142
+ for (const line of followed.lines) {
143
+ const merged = out.get(line.name) ?? new Set();
144
+ if (!followed.plain)
145
+ for (const extra of line.extras)
146
+ if (merged.size < MAX_EXTRAS)
147
+ merged.add(extra);
148
+ out.set(line.name, merged);
149
+ }
150
+ return [...out].map(([name, merged]) => ({ name, extras: [...merged].sort() }));
151
+ }
152
+ /** Dependency names a METADATA declares for a plain install (no extras). */
153
+ export function requiresDist(metadataText) {
154
+ return requiredDists(metadataText).map((dependency) => dependency.name);
155
+ }
@@ -1,28 +1,4 @@
1
- import { type FileDependency, type RegistryAdapter } from "./types.js";
2
- /** The most extras one allowlist entry or dependency line may name. */
3
- export declare const MAX_EXTRAS = 32;
4
- export declare function isPypiProjectName(name: string): boolean;
5
- export declare function normalizePypiName(name: string): string;
6
- /** Normalized (PEP 685), sorted, de-duplicated extras from the text inside
7
- * `[...]`, or null when any is not a valid extra name (PEP 508: the same
8
- * shape as a project name), the list is empty, or it names too many. */
9
- export declare function parseExtras(list: string): string[] | null;
10
- /**
11
- * The dependencies a wheel's METADATA declares for an install of the package
12
- * with `extras`: every line without an `extra == "…"` marker clause, plus the
13
- * lines whose marker names one of `extras` (other marker clauses are ignored,
14
- * so a requested extra's lines are included on every platform). A line gated
15
- * on any other extra is skipped. Each dependency carries the extras its line
16
- * asks of it (`uvicorn[standard]`); a line naming the package itself
17
- * (`celery[redis]; extra == "all"`) adds those extras to this install
18
- * instead. Names and extras are validated and normalized.
19
- *
20
- * Policy, not pip: a plain install (no `extras`) follows no extras at all,
21
- * neither its own (a self-referencing line) nor its dependencies' — each
22
- * dependency comes back bare, so extras are followed only along a chain that
23
- * starts at an allowlist entry naming extras.
24
- */
25
- export declare function requiredDists(metadataText: string, extras?: readonly string[]): FileDependency[];
26
- /** Dependency names a METADATA declares for a plain install (no extras). */
27
- export declare function requiresDist(metadataText: string): string[];
1
+ import { isPypiProjectName, MAX_EXTRAS, normalizePypiName, parseExtras, requiredDists, requiresDist } from "./pypi-requirements.js";
2
+ import { type RegistryAdapter } from "./types.js";
3
+ export { isPypiProjectName, MAX_EXTRAS, normalizePypiName, parseExtras, requiredDists, requiresDist };
28
4
  export declare const pypiAdapter: RegistryAdapter;