@ultrakit/ultrakit 0.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 (704) hide show
  1. package/README.md +95 -0
  2. package/dist/index.d.ts +6 -0
  3. package/dist/index.js +5991 -0
  4. package/dist/template/.opencode/.env.example +196 -0
  5. package/dist/template/.opencode/.template-manifest.json +718 -0
  6. package/dist/template/.opencode/.version +1 -0
  7. package/dist/template/.opencode/AGENTS.md +573 -0
  8. package/dist/template/.opencode/AGENT_ALIGNMENT.md +564 -0
  9. package/dist/template/.opencode/README.md +79 -0
  10. package/dist/template/.opencode/agent/build.md +447 -0
  11. package/dist/template/.opencode/agent/explore.md +114 -0
  12. package/dist/template/.opencode/agent/general.md +201 -0
  13. package/dist/template/.opencode/agent/painter.md +83 -0
  14. package/dist/template/.opencode/agent/plan.md +469 -0
  15. package/dist/template/.opencode/agent/review.md +235 -0
  16. package/dist/template/.opencode/agent/scout.md +142 -0
  17. package/dist/template/.opencode/agent/vision.md +169 -0
  18. package/dist/template/.opencode/command/compound.md +240 -0
  19. package/dist/template/.opencode/command/create.md +298 -0
  20. package/dist/template/.opencode/command/curate.md +299 -0
  21. package/dist/template/.opencode/command/design.md +130 -0
  22. package/dist/template/.opencode/command/explore.md +170 -0
  23. package/dist/template/.opencode/command/handoff.md +149 -0
  24. package/dist/template/.opencode/command/health.md +356 -0
  25. package/dist/template/.opencode/command/init-context.md +297 -0
  26. package/dist/template/.opencode/command/init-user.md +125 -0
  27. package/dist/template/.opencode/command/init.md +115 -0
  28. package/dist/template/.opencode/command/iterate.md +200 -0
  29. package/dist/template/.opencode/command/lfg.md +173 -0
  30. package/dist/template/.opencode/command/plan.md +436 -0
  31. package/dist/template/.opencode/command/pr.md +166 -0
  32. package/dist/template/.opencode/command/research.md +128 -0
  33. package/dist/template/.opencode/command/resume.md +78 -0
  34. package/dist/template/.opencode/command/review-codebase.md +135 -0
  35. package/dist/template/.opencode/command/ship.md +390 -0
  36. package/dist/template/.opencode/command/status.md +126 -0
  37. package/dist/template/.opencode/command/ui-review.md +111 -0
  38. package/dist/template/.opencode/command/ui-slop-check.md +169 -0
  39. package/dist/template/.opencode/command/verify.md +173 -0
  40. package/dist/template/.opencode/context/README.md +29 -0
  41. package/dist/template/.opencode/context/git-context.md +32 -0
  42. package/dist/template/.opencode/dcp-prompts/defaults/README.md +40 -0
  43. package/dist/template/.opencode/dcp-prompts/defaults/compress-message.md +42 -0
  44. package/dist/template/.opencode/dcp-prompts/defaults/compress-range.md +59 -0
  45. package/dist/template/.opencode/dcp-prompts/defaults/context-limit-nudge.md +15 -0
  46. package/dist/template/.opencode/dcp-prompts/defaults/iteration-nudge.md +3 -0
  47. package/dist/template/.opencode/dcp-prompts/defaults/system.md +31 -0
  48. package/dist/template/.opencode/dcp-prompts/defaults/turn-nudge.md +7 -0
  49. package/dist/template/.opencode/dcp-prompts/overrides/compress-message.md +71 -0
  50. package/dist/template/.opencode/dcp.jsonc +115 -0
  51. package/dist/template/.opencode/memory/README.md +89 -0
  52. package/dist/template/.opencode/memory/_templates/design.md +59 -0
  53. package/dist/template/.opencode/memory/_templates/prd.md +203 -0
  54. package/dist/template/.opencode/memory/_templates/project.md +58 -0
  55. package/dist/template/.opencode/memory/_templates/proposal.md +38 -0
  56. package/dist/template/.opencode/memory/_templates/roadmap.md +93 -0
  57. package/dist/template/.opencode/memory/_templates/state.md +89 -0
  58. package/dist/template/.opencode/memory/_templates/tasks.md +198 -0
  59. package/dist/template/.opencode/memory/_templates/tech-stack.md +85 -0
  60. package/dist/template/.opencode/memory/_templates/user.md +26 -0
  61. package/dist/template/.opencode/memory/project/gotchas.md +67 -0
  62. package/dist/template/.opencode/memory/project/project.md +92 -0
  63. package/dist/template/.opencode/memory/project/roadmap.md +142 -0
  64. package/dist/template/.opencode/memory/project/state.md +84 -0
  65. package/dist/template/.opencode/memory/project/tech-stack.md +53 -0
  66. package/dist/template/.opencode/memory/project/user.md +45 -0
  67. package/dist/template/.opencode/memory/research/benchmark-framework.md +162 -0
  68. package/dist/template/.opencode/memory/research/ccpm-analysis.md +334 -0
  69. package/dist/template/.opencode/memory/research/context-management-analysis.md +685 -0
  70. package/dist/template/.opencode/memory/research/effectiveness-audit.md +213 -0
  71. package/dist/template/.opencode/memory/research/opencode-mcp-bug-report.md +129 -0
  72. package/dist/template/.opencode/memory/research/openspec-analysis.md +226 -0
  73. package/dist/template/.opencode/memory/session-context.md +40 -0
  74. package/dist/template/.opencode/opencode.json +1148 -0
  75. package/dist/template/.opencode/opencodex-fast.jsonc +3 -0
  76. package/dist/template/.opencode/package.json +21 -0
  77. package/dist/template/.opencode/plugin/README.md +81 -0
  78. package/dist/template/.opencode/plugin/copilot-auth.ts +1285 -0
  79. package/dist/template/.opencode/plugin/lib/capture.ts +177 -0
  80. package/dist/template/.opencode/plugin/lib/compact.ts +194 -0
  81. package/dist/template/.opencode/plugin/lib/compile.ts +253 -0
  82. package/dist/template/.opencode/plugin/lib/context.ts +198 -0
  83. package/dist/template/.opencode/plugin/lib/curator.ts +234 -0
  84. package/dist/template/.opencode/plugin/lib/db/graph.ts +253 -0
  85. package/dist/template/.opencode/plugin/lib/db/maintenance.ts +312 -0
  86. package/dist/template/.opencode/plugin/lib/db/observations.ts +304 -0
  87. package/dist/template/.opencode/plugin/lib/db/pipeline.ts +520 -0
  88. package/dist/template/.opencode/plugin/lib/db/schema.ts +687 -0
  89. package/dist/template/.opencode/plugin/lib/db/types.ts +284 -0
  90. package/dist/template/.opencode/plugin/lib/distill.ts +376 -0
  91. package/dist/template/.opencode/plugin/lib/index-generator.ts +170 -0
  92. package/dist/template/.opencode/plugin/lib/inject.ts +126 -0
  93. package/dist/template/.opencode/plugin/lib/lint.ts +359 -0
  94. package/dist/template/.opencode/plugin/lib/memory-admin-tools.ts +277 -0
  95. package/dist/template/.opencode/plugin/lib/memory-db.ts +100 -0
  96. package/dist/template/.opencode/plugin/lib/memory-helpers.ts +141 -0
  97. package/dist/template/.opencode/plugin/lib/memory-hooks.ts +399 -0
  98. package/dist/template/.opencode/plugin/lib/memory-tools.ts +535 -0
  99. package/dist/template/.opencode/plugin/lib/notify.ts +89 -0
  100. package/dist/template/.opencode/plugin/lib/operation-log.ts +110 -0
  101. package/dist/template/.opencode/plugin/lib/validate.ts +243 -0
  102. package/dist/template/.opencode/plugin/memory.ts +90 -0
  103. package/dist/template/.opencode/plugin/package.json +7 -0
  104. package/dist/template/.opencode/plugin/prompt-leverage.ts +191 -0
  105. package/dist/template/.opencode/plugin/rtk.ts +43 -0
  106. package/dist/template/.opencode/plugin/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts +172 -0
  107. package/dist/template/.opencode/plugin/sdk/copilot/chat/get-response-metadata.ts +15 -0
  108. package/dist/template/.opencode/plugin/sdk/copilot/chat/map-openai-compatible-finish-reason.ts +19 -0
  109. package/dist/template/.opencode/plugin/sdk/copilot/chat/openai-compatible-api-types.ts +72 -0
  110. package/dist/template/.opencode/plugin/sdk/copilot/chat/openai-compatible-chat-language-model.ts +835 -0
  111. package/dist/template/.opencode/plugin/sdk/copilot/chat/openai-compatible-chat-options.ts +30 -0
  112. package/dist/template/.opencode/plugin/sdk/copilot/chat/openai-compatible-metadata-extractor.ts +48 -0
  113. package/dist/template/.opencode/plugin/sdk/copilot/chat/openai-compatible-prepare-tools.ts +92 -0
  114. package/dist/template/.opencode/plugin/sdk/copilot/copilot-provider.ts +101 -0
  115. package/dist/template/.opencode/plugin/sdk/copilot/index.ts +5 -0
  116. package/dist/template/.opencode/plugin/sdk/copilot/openai-compatible-error.ts +30 -0
  117. package/dist/template/.opencode/plugin/sdk/copilot/responses/convert-to-openai-responses-input.ts +335 -0
  118. package/dist/template/.opencode/plugin/sdk/copilot/responses/map-openai-responses-finish-reason.ts +22 -0
  119. package/dist/template/.opencode/plugin/sdk/copilot/responses/openai-config.ts +18 -0
  120. package/dist/template/.opencode/plugin/sdk/copilot/responses/openai-error.ts +22 -0
  121. package/dist/template/.opencode/plugin/sdk/copilot/responses/openai-responses-api-types.ts +214 -0
  122. package/dist/template/.opencode/plugin/sdk/copilot/responses/openai-responses-language-model.ts +1770 -0
  123. package/dist/template/.opencode/plugin/sdk/copilot/responses/openai-responses-prepare-tools.ts +173 -0
  124. package/dist/template/.opencode/plugin/sdk/copilot/responses/openai-responses-settings.ts +1 -0
  125. package/dist/template/.opencode/plugin/sdk/copilot/responses/tool/code-interpreter.ts +87 -0
  126. package/dist/template/.opencode/plugin/sdk/copilot/responses/tool/file-search.ts +127 -0
  127. package/dist/template/.opencode/plugin/sdk/copilot/responses/tool/image-generation.ts +114 -0
  128. package/dist/template/.opencode/plugin/sdk/copilot/responses/tool/local-shell.ts +64 -0
  129. package/dist/template/.opencode/plugin/sdk/copilot/responses/tool/web-search-preview.ts +103 -0
  130. package/dist/template/.opencode/plugin/sdk/copilot/responses/tool/web-search.ts +102 -0
  131. package/dist/template/.opencode/plugin/sessions.ts +457 -0
  132. package/dist/template/.opencode/plugin/skill-mcp.ts +618 -0
  133. package/dist/template/.opencode/plugin/tsconfig.json +16 -0
  134. package/dist/template/.opencode/skill/accessibility-audit/SKILL.md +191 -0
  135. package/dist/template/.opencode/skill/agent-evals/SKILL.md +208 -0
  136. package/dist/template/.opencode/skill/agent-teams/SKILL.md +268 -0
  137. package/dist/template/.opencode/skill/anti-ai-slop/SKILL.md +76 -0
  138. package/dist/template/.opencode/skill/api-and-interface-design/SKILL.md +162 -0
  139. package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +122 -0
  140. package/dist/template/.opencode/skill/augment-context-engine/mcp.json +6 -0
  141. package/dist/template/.opencode/skill/beads/SKILL.md +182 -0
  142. package/dist/template/.opencode/skill/beads/references/BEST_PRACTICES.md +27 -0
  143. package/dist/template/.opencode/skill/beads/references/BOUNDARIES.md +219 -0
  144. package/dist/template/.opencode/skill/beads/references/DEPENDENCIES.md +124 -0
  145. package/dist/template/.opencode/skill/beads/references/EXAMPLES.md +45 -0
  146. package/dist/template/.opencode/skill/beads/references/FILE_CLAIMING.md +101 -0
  147. package/dist/template/.opencode/skill/beads/references/GIT_SYNC.md +25 -0
  148. package/dist/template/.opencode/skill/beads/references/HIERARCHY.md +71 -0
  149. package/dist/template/.opencode/skill/beads/references/MULTI_AGENT.md +40 -0
  150. package/dist/template/.opencode/skill/beads/references/RESUMABILITY.md +177 -0
  151. package/dist/template/.opencode/skill/beads/references/SESSION_PROTOCOL.md +61 -0
  152. package/dist/template/.opencode/skill/beads/references/TASK_CREATION.md +38 -0
  153. package/dist/template/.opencode/skill/beads/references/TROUBLESHOOTING.md +38 -0
  154. package/dist/template/.opencode/skill/beads/references/WORKFLOWS.md +226 -0
  155. package/dist/template/.opencode/skill/brainstorming/SKILL.md +114 -0
  156. package/dist/template/.opencode/skill/brand-asset-protocol/SKILL.md +222 -0
  157. package/dist/template/.opencode/skill/chrome-devtools/SKILL.md +76 -0
  158. package/dist/template/.opencode/skill/chrome-devtools/mcp.json +19 -0
  159. package/dist/template/.opencode/skill/ci-cd-and-automation/SKILL.md +202 -0
  160. package/dist/template/.opencode/skill/cloudflare/SKILL.md +253 -0
  161. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/README.md +35 -0
  162. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/api.md +100 -0
  163. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/configuration.md +99 -0
  164. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/gotchas.md +59 -0
  165. package/dist/template/.opencode/skill/cloudflare/references/agents-sdk/patterns.md +89 -0
  166. package/dist/template/.opencode/skill/cloudflare/references/ai-gateway/README.md +695 -0
  167. package/dist/template/.opencode/skill/cloudflare/references/ai-search/README.md +14 -0
  168. package/dist/template/.opencode/skill/cloudflare/references/ai-search/api.md +38 -0
  169. package/dist/template/.opencode/skill/cloudflare/references/ai-search/configuration.md +52 -0
  170. package/dist/template/.opencode/skill/cloudflare/references/ai-search/gotchas.md +41 -0
  171. package/dist/template/.opencode/skill/cloudflare/references/ai-search/patterns.md +45 -0
  172. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/README.md +14 -0
  173. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/api.md +27 -0
  174. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/configuration.md +45 -0
  175. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/gotchas.md +3 -0
  176. package/dist/template/.opencode/skill/cloudflare/references/analytics-engine/patterns.md +36 -0
  177. package/dist/template/.opencode/skill/cloudflare/references/api/README.md +21 -0
  178. package/dist/template/.opencode/skill/cloudflare/references/api/api.md +31 -0
  179. package/dist/template/.opencode/skill/cloudflare/references/api/configuration.md +20 -0
  180. package/dist/template/.opencode/skill/cloudflare/references/api/gotchas.md +28 -0
  181. package/dist/template/.opencode/skill/cloudflare/references/api/patterns.md +47 -0
  182. package/dist/template/.opencode/skill/cloudflare/references/api-shield/README.md +20 -0
  183. package/dist/template/.opencode/skill/cloudflare/references/api-shield/api.md +78 -0
  184. package/dist/template/.opencode/skill/cloudflare/references/api-shield/configuration.md +128 -0
  185. package/dist/template/.opencode/skill/cloudflare/references/api-shield/gotchas.md +51 -0
  186. package/dist/template/.opencode/skill/cloudflare/references/api-shield/patterns.md +145 -0
  187. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/README.md +16 -0
  188. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/api.md +50 -0
  189. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/configuration.md +53 -0
  190. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/gotchas.md +16 -0
  191. package/dist/template/.opencode/skill/cloudflare/references/argo-smart-routing/patterns.md +45 -0
  192. package/dist/template/.opencode/skill/cloudflare/references/bindings/README.md +14 -0
  193. package/dist/template/.opencode/skill/cloudflare/references/bindings/api.md +3 -0
  194. package/dist/template/.opencode/skill/cloudflare/references/bindings/configuration.md +58 -0
  195. package/dist/template/.opencode/skill/cloudflare/references/bindings/gotchas.md +35 -0
  196. package/dist/template/.opencode/skill/cloudflare/references/bindings/patterns.md +37 -0
  197. package/dist/template/.opencode/skill/cloudflare/references/bot-management/README.md +71 -0
  198. package/dist/template/.opencode/skill/cloudflare/references/bot-management/api.md +168 -0
  199. package/dist/template/.opencode/skill/cloudflare/references/bot-management/configuration.md +114 -0
  200. package/dist/template/.opencode/skill/cloudflare/references/bot-management/gotchas.md +99 -0
  201. package/dist/template/.opencode/skill/cloudflare/references/bot-management/patterns.md +125 -0
  202. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/README.md +16 -0
  203. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/api.md +54 -0
  204. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/configuration.md +47 -0
  205. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/gotchas.md +29 -0
  206. package/dist/template/.opencode/skill/cloudflare/references/browser-rendering/patterns.md +29 -0
  207. package/dist/template/.opencode/skill/cloudflare/references/c3/README.md +264 -0
  208. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/README.md +93 -0
  209. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/api.md +176 -0
  210. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/configuration.md +164 -0
  211. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/gotchas.md +203 -0
  212. package/dist/template/.opencode/skill/cloudflare/references/cache-reserve/patterns.md +180 -0
  213. package/dist/template/.opencode/skill/cloudflare/references/containers/README.md +16 -0
  214. package/dist/template/.opencode/skill/cloudflare/references/containers/api.md +43 -0
  215. package/dist/template/.opencode/skill/cloudflare/references/containers/configuration.md +56 -0
  216. package/dist/template/.opencode/skill/cloudflare/references/containers/gotchas.md +21 -0
  217. package/dist/template/.opencode/skill/cloudflare/references/containers/patterns.md +40 -0
  218. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/README.md +85 -0
  219. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/api.md +198 -0
  220. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/configuration.md +151 -0
  221. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/gotchas.md +129 -0
  222. package/dist/template/.opencode/skill/cloudflare/references/cron-triggers/patterns.md +122 -0
  223. package/dist/template/.opencode/skill/cloudflare/references/d1/README.md +92 -0
  224. package/dist/template/.opencode/skill/cloudflare/references/d1/api.md +141 -0
  225. package/dist/template/.opencode/skill/cloudflare/references/d1/configuration.md +127 -0
  226. package/dist/template/.opencode/skill/cloudflare/references/d1/gotchas.md +70 -0
  227. package/dist/template/.opencode/skill/cloudflare/references/d1/patterns.md +144 -0
  228. package/dist/template/.opencode/skill/cloudflare/references/ddos/README.md +34 -0
  229. package/dist/template/.opencode/skill/cloudflare/references/ddos/api.md +136 -0
  230. package/dist/template/.opencode/skill/cloudflare/references/ddos/configuration.md +67 -0
  231. package/dist/template/.opencode/skill/cloudflare/references/ddos/gotchas.md +114 -0
  232. package/dist/template/.opencode/skill/cloudflare/references/ddos/patterns.md +158 -0
  233. package/dist/template/.opencode/skill/cloudflare/references/do-storage/README.md +62 -0
  234. package/dist/template/.opencode/skill/cloudflare/references/do-storage/api.md +89 -0
  235. package/dist/template/.opencode/skill/cloudflare/references/do-storage/configuration.md +116 -0
  236. package/dist/template/.opencode/skill/cloudflare/references/do-storage/gotchas.md +93 -0
  237. package/dist/template/.opencode/skill/cloudflare/references/do-storage/patterns.md +112 -0
  238. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/README.md +125 -0
  239. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/api.md +152 -0
  240. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/configuration.md +148 -0
  241. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/gotchas.md +158 -0
  242. package/dist/template/.opencode/skill/cloudflare/references/durable-objects/patterns.md +255 -0
  243. package/dist/template/.opencode/skill/cloudflare/references/email-routing/README.md +18 -0
  244. package/dist/template/.opencode/skill/cloudflare/references/email-routing/api.md +46 -0
  245. package/dist/template/.opencode/skill/cloudflare/references/email-routing/configuration.md +63 -0
  246. package/dist/template/.opencode/skill/cloudflare/references/email-routing/gotchas.md +16 -0
  247. package/dist/template/.opencode/skill/cloudflare/references/email-routing/patterns.md +46 -0
  248. package/dist/template/.opencode/skill/cloudflare/references/email-workers/README.md +598 -0
  249. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/README.md +62 -0
  250. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/api.md +137 -0
  251. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/configuration.md +133 -0
  252. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/gotchas.md +184 -0
  253. package/dist/template/.opencode/skill/cloudflare/references/hyperdrive/patterns.md +176 -0
  254. package/dist/template/.opencode/skill/cloudflare/references/images/README.md +14 -0
  255. package/dist/template/.opencode/skill/cloudflare/references/images/api.md +3 -0
  256. package/dist/template/.opencode/skill/cloudflare/references/images/configuration.md +45 -0
  257. package/dist/template/.opencode/skill/cloudflare/references/images/gotchas.md +23 -0
  258. package/dist/template/.opencode/skill/cloudflare/references/images/patterns.md +31 -0
  259. package/dist/template/.opencode/skill/cloudflare/references/kv/README.md +60 -0
  260. package/dist/template/.opencode/skill/cloudflare/references/kv/api.md +114 -0
  261. package/dist/template/.opencode/skill/cloudflare/references/kv/configuration.md +92 -0
  262. package/dist/template/.opencode/skill/cloudflare/references/kv/gotchas.md +117 -0
  263. package/dist/template/.opencode/skill/cloudflare/references/kv/patterns.md +139 -0
  264. package/dist/template/.opencode/skill/cloudflare/references/miniflare/README.md +64 -0
  265. package/dist/template/.opencode/skill/cloudflare/references/miniflare/api.md +144 -0
  266. package/dist/template/.opencode/skill/cloudflare/references/miniflare/configuration.md +203 -0
  267. package/dist/template/.opencode/skill/cloudflare/references/miniflare/gotchas.md +187 -0
  268. package/dist/template/.opencode/skill/cloudflare/references/miniflare/patterns.md +211 -0
  269. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/README.md +60 -0
  270. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/api.md +240 -0
  271. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/configuration.md +127 -0
  272. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/gotchas.md +171 -0
  273. package/dist/template/.opencode/skill/cloudflare/references/network-interconnect/patterns.md +171 -0
  274. package/dist/template/.opencode/skill/cloudflare/references/observability/README.md +18 -0
  275. package/dist/template/.opencode/skill/cloudflare/references/observability/api.md +51 -0
  276. package/dist/template/.opencode/skill/cloudflare/references/observability/configuration.md +60 -0
  277. package/dist/template/.opencode/skill/cloudflare/references/observability/gotchas.md +36 -0
  278. package/dist/template/.opencode/skill/cloudflare/references/observability/patterns.md +42 -0
  279. package/dist/template/.opencode/skill/cloudflare/references/pages/README.md +76 -0
  280. package/dist/template/.opencode/skill/cloudflare/references/pages/api.md +200 -0
  281. package/dist/template/.opencode/skill/cloudflare/references/pages/configuration.md +228 -0
  282. package/dist/template/.opencode/skill/cloudflare/references/pages/gotchas.md +161 -0
  283. package/dist/template/.opencode/skill/cloudflare/references/pages/patterns.md +145 -0
  284. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/README.md +57 -0
  285. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/api.md +201 -0
  286. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/configuration.md +159 -0
  287. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/gotchas.md +151 -0
  288. package/dist/template/.opencode/skill/cloudflare/references/pages-functions/patterns.md +190 -0
  289. package/dist/template/.opencode/skill/cloudflare/references/pipelines/README.md +664 -0
  290. package/dist/template/.opencode/skill/cloudflare/references/pulumi/README.md +107 -0
  291. package/dist/template/.opencode/skill/cloudflare/references/pulumi/api.md +194 -0
  292. package/dist/template/.opencode/skill/cloudflare/references/pulumi/configuration.md +216 -0
  293. package/dist/template/.opencode/skill/cloudflare/references/pulumi/gotchas.md +223 -0
  294. package/dist/template/.opencode/skill/cloudflare/references/pulumi/patterns.md +139 -0
  295. package/dist/template/.opencode/skill/cloudflare/references/queues/README.md +69 -0
  296. package/dist/template/.opencode/skill/cloudflare/references/queues/api.md +138 -0
  297. package/dist/template/.opencode/skill/cloudflare/references/queues/configuration.md +125 -0
  298. package/dist/template/.opencode/skill/cloudflare/references/queues/gotchas.md +112 -0
  299. package/dist/template/.opencode/skill/cloudflare/references/queues/patterns.md +155 -0
  300. package/dist/template/.opencode/skill/cloudflare/references/r2/README.md +61 -0
  301. package/dist/template/.opencode/skill/cloudflare/references/r2/api.md +127 -0
  302. package/dist/template/.opencode/skill/cloudflare/references/r2/configuration.md +76 -0
  303. package/dist/template/.opencode/skill/cloudflare/references/r2/gotchas.md +94 -0
  304. package/dist/template/.opencode/skill/cloudflare/references/r2/patterns.md +127 -0
  305. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/README.md +18 -0
  306. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/api.md +29 -0
  307. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/configuration.md +39 -0
  308. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/gotchas.md +20 -0
  309. package/dist/template/.opencode/skill/cloudflare/references/r2-data-catalog/patterns.md +46 -0
  310. package/dist/template/.opencode/skill/cloudflare/references/r2-sql/README.md +512 -0
  311. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/README.md +21 -0
  312. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/api.md +135 -0
  313. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/configuration.md +63 -0
  314. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/gotchas.md +75 -0
  315. package/dist/template/.opencode/skill/cloudflare/references/realtime-sfu/patterns.md +102 -0
  316. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/README.md +81 -0
  317. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/api.md +164 -0
  318. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/configuration.md +147 -0
  319. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/gotchas.md +172 -0
  320. package/dist/template/.opencode/skill/cloudflare/references/realtimekit/patterns.md +155 -0
  321. package/dist/template/.opencode/skill/cloudflare/references/sandbox/README.md +90 -0
  322. package/dist/template/.opencode/skill/cloudflare/references/sandbox/api.md +178 -0
  323. package/dist/template/.opencode/skill/cloudflare/references/sandbox/configuration.md +131 -0
  324. package/dist/template/.opencode/skill/cloudflare/references/sandbox/gotchas.md +156 -0
  325. package/dist/template/.opencode/skill/cloudflare/references/sandbox/patterns.md +203 -0
  326. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/README.md +58 -0
  327. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/api.md +182 -0
  328. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/configuration.md +140 -0
  329. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/gotchas.md +129 -0
  330. package/dist/template/.opencode/skill/cloudflare/references/secrets-store/patterns.md +218 -0
  331. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/README.md +91 -0
  332. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/api.md +139 -0
  333. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/configuration.md +129 -0
  334. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/gotchas.md +87 -0
  335. package/dist/template/.opencode/skill/cloudflare/references/smart-placement/patterns.md +135 -0
  336. package/dist/template/.opencode/skill/cloudflare/references/snippets/README.md +15 -0
  337. package/dist/template/.opencode/skill/cloudflare/references/snippets/api.md +47 -0
  338. package/dist/template/.opencode/skill/cloudflare/references/snippets/configuration.md +33 -0
  339. package/dist/template/.opencode/skill/cloudflare/references/snippets/gotchas.md +21 -0
  340. package/dist/template/.opencode/skill/cloudflare/references/snippets/patterns.md +34 -0
  341. package/dist/template/.opencode/skill/cloudflare/references/spectrum/README.md +16 -0
  342. package/dist/template/.opencode/skill/cloudflare/references/spectrum/api.md +24 -0
  343. package/dist/template/.opencode/skill/cloudflare/references/spectrum/configuration.md +43 -0
  344. package/dist/template/.opencode/skill/cloudflare/references/spectrum/gotchas.md +42 -0
  345. package/dist/template/.opencode/skill/cloudflare/references/spectrum/patterns.md +40 -0
  346. package/dist/template/.opencode/skill/cloudflare/references/static-assets/README.md +14 -0
  347. package/dist/template/.opencode/skill/cloudflare/references/static-assets/api.md +3 -0
  348. package/dist/template/.opencode/skill/cloudflare/references/static-assets/configuration.md +47 -0
  349. package/dist/template/.opencode/skill/cloudflare/references/static-assets/gotchas.md +44 -0
  350. package/dist/template/.opencode/skill/cloudflare/references/static-assets/patterns.md +42 -0
  351. package/dist/template/.opencode/skill/cloudflare/references/stream/README.md +103 -0
  352. package/dist/template/.opencode/skill/cloudflare/references/stream/api.md +204 -0
  353. package/dist/template/.opencode/skill/cloudflare/references/stream/configuration.md +127 -0
  354. package/dist/template/.opencode/skill/cloudflare/references/stream/gotchas.md +131 -0
  355. package/dist/template/.opencode/skill/cloudflare/references/stream/patterns.md +152 -0
  356. package/dist/template/.opencode/skill/cloudflare/references/tail-workers/README.md +640 -0
  357. package/dist/template/.opencode/skill/cloudflare/references/terraform/README.md +76 -0
  358. package/dist/template/.opencode/skill/cloudflare/references/terraform/api.md +159 -0
  359. package/dist/template/.opencode/skill/cloudflare/references/terraform/configuration.md +156 -0
  360. package/dist/template/.opencode/skill/cloudflare/references/terraform/gotchas.md +207 -0
  361. package/dist/template/.opencode/skill/cloudflare/references/terraform/patterns.md +135 -0
  362. package/dist/template/.opencode/skill/cloudflare/references/tunnel/README.md +82 -0
  363. package/dist/template/.opencode/skill/cloudflare/references/tunnel/api.md +105 -0
  364. package/dist/template/.opencode/skill/cloudflare/references/tunnel/configuration.md +113 -0
  365. package/dist/template/.opencode/skill/cloudflare/references/tunnel/gotchas.md +115 -0
  366. package/dist/template/.opencode/skill/cloudflare/references/tunnel/patterns.md +157 -0
  367. package/dist/template/.opencode/skill/cloudflare/references/turn/README.md +699 -0
  368. package/dist/template/.opencode/skill/cloudflare/references/turnstile/README.md +14 -0
  369. package/dist/template/.opencode/skill/cloudflare/references/turnstile/api.md +3 -0
  370. package/dist/template/.opencode/skill/cloudflare/references/turnstile/configuration.md +19 -0
  371. package/dist/template/.opencode/skill/cloudflare/references/turnstile/gotchas.md +27 -0
  372. package/dist/template/.opencode/skill/cloudflare/references/turnstile/patterns.md +41 -0
  373. package/dist/template/.opencode/skill/cloudflare/references/vectorize/README.md +682 -0
  374. package/dist/template/.opencode/skill/cloudflare/references/waf/README.md +14 -0
  375. package/dist/template/.opencode/skill/cloudflare/references/waf/api.md +3 -0
  376. package/dist/template/.opencode/skill/cloudflare/references/waf/configuration.md +44 -0
  377. package/dist/template/.opencode/skill/cloudflare/references/waf/gotchas.md +24 -0
  378. package/dist/template/.opencode/skill/cloudflare/references/waf/patterns.md +29 -0
  379. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/README.md +19 -0
  380. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/api.md +52 -0
  381. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/configuration.md +31 -0
  382. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/gotchas.md +28 -0
  383. package/dist/template/.opencode/skill/cloudflare/references/web-analytics/patterns.md +52 -0
  384. package/dist/template/.opencode/skill/cloudflare/references/workerd/README.md +47 -0
  385. package/dist/template/.opencode/skill/cloudflare/references/workerd/api.md +199 -0
  386. package/dist/template/.opencode/skill/cloudflare/references/workerd/configuration.md +185 -0
  387. package/dist/template/.opencode/skill/cloudflare/references/workerd/gotchas.md +203 -0
  388. package/dist/template/.opencode/skill/cloudflare/references/workerd/patterns.md +216 -0
  389. package/dist/template/.opencode/skill/cloudflare/references/workers/README.md +96 -0
  390. package/dist/template/.opencode/skill/cloudflare/references/workers/api.md +137 -0
  391. package/dist/template/.opencode/skill/cloudflare/references/workers/configuration.md +147 -0
  392. package/dist/template/.opencode/skill/cloudflare/references/workers/gotchas.md +99 -0
  393. package/dist/template/.opencode/skill/cloudflare/references/workers/patterns.md +149 -0
  394. package/dist/template/.opencode/skill/cloudflare/references/workers-ai/README.md +116 -0
  395. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/README.md +48 -0
  396. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/api.md +169 -0
  397. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/configuration.md +136 -0
  398. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/gotchas.md +130 -0
  399. package/dist/template/.opencode/skill/cloudflare/references/workers-for-platforms/patterns.md +170 -0
  400. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/README.md +16 -0
  401. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/api.md +20 -0
  402. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/configuration.md +3 -0
  403. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/gotchas.md +35 -0
  404. package/dist/template/.opencode/skill/cloudflare/references/workers-playground/patterns.md +42 -0
  405. package/dist/template/.opencode/skill/cloudflare/references/workers-vpc/README.md +579 -0
  406. package/dist/template/.opencode/skill/cloudflare/references/workflows/README.md +62 -0
  407. package/dist/template/.opencode/skill/cloudflare/references/workflows/api.md +125 -0
  408. package/dist/template/.opencode/skill/cloudflare/references/workflows/configuration.md +177 -0
  409. package/dist/template/.opencode/skill/cloudflare/references/workflows/gotchas.md +136 -0
  410. package/dist/template/.opencode/skill/cloudflare/references/workflows/patterns.md +132 -0
  411. package/dist/template/.opencode/skill/cloudflare/references/wrangler/README.md +90 -0
  412. package/dist/template/.opencode/skill/cloudflare/references/wrangler/api.md +140 -0
  413. package/dist/template/.opencode/skill/cloudflare/references/wrangler/configuration.md +128 -0
  414. package/dist/template/.opencode/skill/cloudflare/references/wrangler/gotchas.md +93 -0
  415. package/dist/template/.opencode/skill/cloudflare/references/wrangler/patterns.md +150 -0
  416. package/dist/template/.opencode/skill/cloudflare/references/zaraz/README.md +360 -0
  417. package/dist/template/.opencode/skill/code-search-patterns/SKILL.md +253 -0
  418. package/dist/template/.opencode/skill/code-simplification/SKILL.md +211 -0
  419. package/dist/template/.opencode/skill/condition-based-waiting/SKILL.md +135 -0
  420. package/dist/template/.opencode/skill/condition-based-waiting/example.ts +158 -0
  421. package/dist/template/.opencode/skill/context-condensation/SKILL.md +149 -0
  422. package/dist/template/.opencode/skill/context-engineering/SKILL.md +176 -0
  423. package/dist/template/.opencode/skill/context-initialization/SKILL.md +69 -0
  424. package/dist/template/.opencode/skill/context-management/SKILL.md +390 -0
  425. package/dist/template/.opencode/skill/core-data-expert/SKILL.md +93 -0
  426. package/dist/template/.opencode/skill/core-data-expert/references/batch-operations.md +543 -0
  427. package/dist/template/.opencode/skill/core-data-expert/references/cloudkit-integration.md +259 -0
  428. package/dist/template/.opencode/skill/core-data-expert/references/concurrency.md +522 -0
  429. package/dist/template/.opencode/skill/core-data-expert/references/fetch-requests.md +643 -0
  430. package/dist/template/.opencode/skill/core-data-expert/references/glossary.md +233 -0
  431. package/dist/template/.opencode/skill/core-data-expert/references/migration.md +393 -0
  432. package/dist/template/.opencode/skill/core-data-expert/references/model-configuration.md +597 -0
  433. package/dist/template/.opencode/skill/core-data-expert/references/performance.md +300 -0
  434. package/dist/template/.opencode/skill/core-data-expert/references/persistent-history.md +553 -0
  435. package/dist/template/.opencode/skill/core-data-expert/references/project-audit.md +60 -0
  436. package/dist/template/.opencode/skill/core-data-expert/references/saving.md +574 -0
  437. package/dist/template/.opencode/skill/core-data-expert/references/stack-setup.md +625 -0
  438. package/dist/template/.opencode/skill/core-data-expert/references/testing.md +300 -0
  439. package/dist/template/.opencode/skill/core-data-expert/references/threading.md +589 -0
  440. package/dist/template/.opencode/skill/deep-research/SKILL.md +384 -0
  441. package/dist/template/.opencode/skill/defense-in-depth/SKILL.md +176 -0
  442. package/dist/template/.opencode/skill/deprecation-and-migration/SKILL.md +189 -0
  443. package/dist/template/.opencode/skill/design-direction-advisor/SKILL.md +139 -0
  444. package/dist/template/.opencode/skill/design-system-audit/SKILL.md +153 -0
  445. package/dist/template/.opencode/skill/design-taste-frontend/SKILL.md +238 -0
  446. package/dist/template/.opencode/skill/development-lifecycle/SKILL.md +320 -0
  447. package/dist/template/.opencode/skill/dispatching-parallel-agents/SKILL.md +191 -0
  448. package/dist/template/.opencode/skill/documentation-and-adrs/SKILL.md +220 -0
  449. package/dist/template/.opencode/skill/executing-plans/SKILL.md +247 -0
  450. package/dist/template/.opencode/skill/figma/SKILL.md +224 -0
  451. package/dist/template/.opencode/skill/figma-go/SKILL.md +65 -0
  452. package/dist/template/.opencode/skill/finishing-a-development-branch/SKILL.md +357 -0
  453. package/dist/template/.opencode/skill/frontend-design/SKILL.md +235 -0
  454. package/dist/template/.opencode/skill/frontend-design/references/animation/motion-advanced.md +224 -0
  455. package/dist/template/.opencode/skill/frontend-design/references/animation/motion-core.md +181 -0
  456. package/dist/template/.opencode/skill/frontend-design/references/canvas/execution.md +90 -0
  457. package/dist/template/.opencode/skill/frontend-design/references/canvas/philosophy.md +94 -0
  458. package/dist/template/.opencode/skill/frontend-design/references/design/color-system.md +111 -0
  459. package/dist/template/.opencode/skill/frontend-design/references/design/interaction.md +149 -0
  460. package/dist/template/.opencode/skill/frontend-design/references/design/typography-rules.md +106 -0
  461. package/dist/template/.opencode/skill/frontend-design/references/design/ux-writing.md +99 -0
  462. package/dist/template/.opencode/skill/frontend-design/references/shadcn/accessibility.md +132 -0
  463. package/dist/template/.opencode/skill/frontend-design/references/shadcn/core-components.md +153 -0
  464. package/dist/template/.opencode/skill/frontend-design/references/shadcn/form-components.md +158 -0
  465. package/dist/template/.opencode/skill/frontend-design/references/shadcn/setup.md +69 -0
  466. package/dist/template/.opencode/skill/frontend-design/references/shadcn/theming.md +152 -0
  467. package/dist/template/.opencode/skill/frontend-design/references/tailwind/responsive.md +112 -0
  468. package/dist/template/.opencode/skill/frontend-design/references/tailwind/utilities-layout.md +134 -0
  469. package/dist/template/.opencode/skill/frontend-design/references/tailwind/utilities-styling.md +165 -0
  470. package/dist/template/.opencode/skill/frontend-design/references/tailwind/v4-config.md +147 -0
  471. package/dist/template/.opencode/skill/frontend-design/references/tailwind/v4-features.md +128 -0
  472. package/dist/template/.opencode/skill/full-output-enforcement/SKILL.md +62 -0
  473. package/dist/template/.opencode/skill/gemini-large-context/SKILL.md +216 -0
  474. package/dist/template/.opencode/skill/gh-address-comments/SKILL.md +29 -0
  475. package/dist/template/.opencode/skill/gh-address-comments/scripts/fetch_comments.py +237 -0
  476. package/dist/template/.opencode/skill/gh-fix-ci/SKILL.md +38 -0
  477. package/dist/template/.opencode/skill/gh-fix-ci/scripts/inspect_pr_checks.py +509 -0
  478. package/dist/template/.opencode/skill/hi-fi-prototype-html/SKILL.md +253 -0
  479. package/dist/template/.opencode/skill/high-end-visual-design/SKILL.md +111 -0
  480. package/dist/template/.opencode/skill/html-deck-export/SKILL.md +189 -0
  481. package/dist/template/.opencode/skill/incremental-implementation/SKILL.md +191 -0
  482. package/dist/template/.opencode/skill/index-knowledge/SKILL.md +413 -0
  483. package/dist/template/.opencode/skill/industrial-brutalist-ui/SKILL.md +105 -0
  484. package/dist/template/.opencode/skill/jira/SKILL.md +283 -0
  485. package/dist/template/.opencode/skill/jira/mcp.json +6 -0
  486. package/dist/template/.opencode/skill/memory-grounding/SKILL.md +68 -0
  487. package/dist/template/.opencode/skill/memory-system/SKILL.md +148 -0
  488. package/dist/template/.opencode/skill/minimalist-ui/SKILL.md +98 -0
  489. package/dist/template/.opencode/skill/mockup-to-code/SKILL.md +184 -0
  490. package/dist/template/.opencode/skill/opensrc/SKILL.md +284 -0
  491. package/dist/template/.opencode/skill/opensrc/references/architecture.md +176 -0
  492. package/dist/template/.opencode/skill/opensrc/references/cli-usage.md +176 -0
  493. package/dist/template/.opencode/skill/opensrc/references/registry-support.md +137 -0
  494. package/dist/template/.opencode/skill/pdf-extract/SKILL.md +438 -0
  495. package/dist/template/.opencode/skill/performance-optimization/SKILL.md +236 -0
  496. package/dist/template/.opencode/skill/playwright/SKILL.md +381 -0
  497. package/dist/template/.opencode/skill/playwright/mcp.json +16 -0
  498. package/dist/template/.opencode/skill/playwright/references/agent-browser-cli.md +405 -0
  499. package/dist/template/.opencode/skill/playwriter/SKILL.md +158 -0
  500. package/dist/template/.opencode/skill/polar/SKILL.md +102 -0
  501. package/dist/template/.opencode/skill/portless/SKILL.md +109 -0
  502. package/dist/template/.opencode/skill/prd/SKILL.md +146 -0
  503. package/dist/template/.opencode/skill/prd-task/SKILL.md +182 -0
  504. package/dist/template/.opencode/skill/prd-task/references/prd-schema.json +124 -0
  505. package/dist/template/.opencode/skill/prompt-leverage/SKILL.md +90 -0
  506. package/dist/template/.opencode/skill/prompt-leverage/references/framework.md +91 -0
  507. package/dist/template/.opencode/skill/prompt-leverage/scripts/augment_prompt.py +157 -0
  508. package/dist/template/.opencode/skill/react-best-practices/AGENTS.md +2410 -0
  509. package/dist/template/.opencode/skill/react-best-practices/README.md +123 -0
  510. package/dist/template/.opencode/skill/react-best-practices/SKILL.md +133 -0
  511. package/dist/template/.opencode/skill/react-best-practices/metadata.json +15 -0
  512. package/dist/template/.opencode/skill/react-best-practices/rules/_sections.md +46 -0
  513. package/dist/template/.opencode/skill/react-best-practices/rules/_template.md +28 -0
  514. package/dist/template/.opencode/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  515. package/dist/template/.opencode/skill/react-best-practices/rules/advanced-use-latest.md +49 -0
  516. package/dist/template/.opencode/skill/react-best-practices/rules/async-api-routes.md +38 -0
  517. package/dist/template/.opencode/skill/react-best-practices/rules/async-defer-await.md +80 -0
  518. package/dist/template/.opencode/skill/react-best-practices/rules/async-dependencies.md +36 -0
  519. package/dist/template/.opencode/skill/react-best-practices/rules/async-parallel.md +28 -0
  520. package/dist/template/.opencode/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  521. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  522. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-conditional.md +31 -0
  523. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  524. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  525. package/dist/template/.opencode/skill/react-best-practices/rules/bundle-preload.md +50 -0
  526. package/dist/template/.opencode/skill/react-best-practices/rules/client-event-listeners.md +74 -0
  527. package/dist/template/.opencode/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
  528. package/dist/template/.opencode/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  529. package/dist/template/.opencode/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
  530. package/dist/template/.opencode/skill/react-best-practices/rules/js-batch-dom-css.md +82 -0
  531. package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
  532. package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
  533. package/dist/template/.opencode/skill/react-best-practices/rules/js-cache-storage.md +70 -0
  534. package/dist/template/.opencode/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
  535. package/dist/template/.opencode/skill/react-best-practices/rules/js-early-exit.md +50 -0
  536. package/dist/template/.opencode/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
  537. package/dist/template/.opencode/skill/react-best-practices/rules/js-index-maps.md +37 -0
  538. package/dist/template/.opencode/skill/react-best-practices/rules/js-length-check-first.md +49 -0
  539. package/dist/template/.opencode/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
  540. package/dist/template/.opencode/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
  541. package/dist/template/.opencode/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  542. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-activity.md +26 -0
  543. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  544. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
  545. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
  546. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  547. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  548. package/dist/template/.opencode/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
  549. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
  550. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
  551. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
  552. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  553. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  554. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-memo.md +44 -0
  555. package/dist/template/.opencode/skill/react-best-practices/rules/rerender-transitions.md +40 -0
  556. package/dist/template/.opencode/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
  557. package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-lru.md +41 -0
  558. package/dist/template/.opencode/skill/react-best-practices/rules/server-cache-react.md +76 -0
  559. package/dist/template/.opencode/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
  560. package/dist/template/.opencode/skill/react-best-practices/rules/server-serialization.md +38 -0
  561. package/dist/template/.opencode/skill/receiving-code-review/SKILL.md +263 -0
  562. package/dist/template/.opencode/skill/reconcile/SKILL.md +183 -0
  563. package/dist/template/.opencode/skill/redesign-existing-projects/SKILL.md +191 -0
  564. package/dist/template/.opencode/skill/reflection-checkpoints/SKILL.md +183 -0
  565. package/dist/template/.opencode/skill/requesting-code-review/SKILL.md +443 -0
  566. package/dist/template/.opencode/skill/requesting-code-review/references/specialist-profiles.md +108 -0
  567. package/dist/template/.opencode/skill/requesting-code-review/review.md +160 -0
  568. package/dist/template/.opencode/skill/resend/SKILL.md +177 -0
  569. package/dist/template/.opencode/skill/resend/references/react-email.md +287 -0
  570. package/dist/template/.opencode/skill/resend/references/receive-email.md +248 -0
  571. package/dist/template/.opencode/skill/resend/references/send-email.md +318 -0
  572. package/dist/template/.opencode/skill/root-cause-tracing/SKILL.md +192 -0
  573. package/dist/template/.opencode/skill/root-cause-tracing/find-polluter.sh +63 -0
  574. package/dist/template/.opencode/skill/rtk-command-compression/SKILL.md +134 -0
  575. package/dist/template/.opencode/skill/screenshot/SKILL.md +48 -0
  576. package/dist/template/.opencode/skill/screenshot/scripts/ensure_macos_permissions.sh +54 -0
  577. package/dist/template/.opencode/skill/screenshot/scripts/macos_display_info.swift +22 -0
  578. package/dist/template/.opencode/skill/screenshot/scripts/macos_permissions.swift +40 -0
  579. package/dist/template/.opencode/skill/screenshot/scripts/macos_window_info.swift +126 -0
  580. package/dist/template/.opencode/skill/screenshot/scripts/take_screenshot.ps1 +163 -0
  581. package/dist/template/.opencode/skill/screenshot/scripts/take_screenshot.py +585 -0
  582. package/dist/template/.opencode/skill/security-and-hardening/SKILL.md +296 -0
  583. package/dist/template/.opencode/skill/security-threat-model/SKILL.md +36 -0
  584. package/dist/template/.opencode/skill/security-threat-model/references/prompt-template.md +255 -0
  585. package/dist/template/.opencode/skill/security-threat-model/references/security-controls-and-assets.md +32 -0
  586. package/dist/template/.opencode/skill/sharing-skills/SKILL.md +214 -0
  587. package/dist/template/.opencode/skill/skill-creator/SKILL.md +181 -0
  588. package/dist/template/.opencode/skill/skill-installer/SKILL.md +58 -0
  589. package/dist/template/.opencode/skill/skill-installer/scripts/github_utils.py +21 -0
  590. package/dist/template/.opencode/skill/skill-installer/scripts/install-skill-from-github.py +313 -0
  591. package/dist/template/.opencode/skill/skill-installer/scripts/list-skills.py +106 -0
  592. package/dist/template/.opencode/skill/structured-edit/SKILL.md +191 -0
  593. package/dist/template/.opencode/skill/subagent-driven-development/SKILL.md +237 -0
  594. package/dist/template/.opencode/skill/supabase/SKILL.md +130 -0
  595. package/dist/template/.opencode/skill/supabase/mcp.json +27 -0
  596. package/dist/template/.opencode/skill/supabase-postgres-best-practices/AGENTS.md +1490 -0
  597. package/dist/template/.opencode/skill/supabase-postgres-best-practices/SKILL.md +65 -0
  598. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/advanced-full-text-search.md +55 -0
  599. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/advanced-jsonb-indexing.md +49 -0
  600. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/conn-idle-timeout.md +46 -0
  601. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/conn-limits.md +44 -0
  602. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/conn-pooling.md +41 -0
  603. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/conn-prepared-statements.md +46 -0
  604. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/data-batch-inserts.md +54 -0
  605. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/data-n-plus-one.md +53 -0
  606. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/data-pagination.md +50 -0
  607. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/data-upsert.md +50 -0
  608. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/lock-advisory.md +56 -0
  609. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/lock-deadlock-prevention.md +68 -0
  610. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/lock-short-transactions.md +50 -0
  611. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/lock-skip-locked.md +54 -0
  612. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/monitor-explain-analyze.md +45 -0
  613. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/monitor-pg-stat-statements.md +55 -0
  614. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/monitor-vacuum-analyze.md +55 -0
  615. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/query-composite-indexes.md +44 -0
  616. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/query-covering-indexes.md +40 -0
  617. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/query-index-types.md +45 -0
  618. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/query-missing-indexes.md +43 -0
  619. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/query-partial-indexes.md +45 -0
  620. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/schema-data-types.md +46 -0
  621. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/schema-foreign-key-indexes.md +59 -0
  622. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/schema-lowercase-identifiers.md +55 -0
  623. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/schema-partitioning.md +55 -0
  624. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/schema-primary-keys.md +61 -0
  625. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/security-privileges.md +54 -0
  626. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/security-rls-basics.md +50 -0
  627. package/dist/template/.opencode/skill/supabase-postgres-best-practices/rules/security-rls-performance.md +57 -0
  628. package/dist/template/.opencode/skill/swarm-coordination/SKILL.md +244 -0
  629. package/dist/template/.opencode/skill/swarm-coordination/references/architecture.md +39 -0
  630. package/dist/template/.opencode/skill/swarm-coordination/references/delegation-worker-protocol.md +145 -0
  631. package/dist/template/.opencode/skill/swarm-coordination/references/dependency-graph.md +50 -0
  632. package/dist/template/.opencode/skill/swarm-coordination/references/drift-check.md +90 -0
  633. package/dist/template/.opencode/skill/swarm-coordination/references/integration-beads.md +20 -0
  634. package/dist/template/.opencode/skill/swarm-coordination/references/launch-flow.md +186 -0
  635. package/dist/template/.opencode/skill/swarm-coordination/references/reconciler.md +172 -0
  636. package/dist/template/.opencode/skill/swarm-coordination/references/tier-enforcement.md +78 -0
  637. package/dist/template/.opencode/skill/swarm-coordination/references/tmux-integration.md +134 -0
  638. package/dist/template/.opencode/skill/swift-concurrency/SKILL.md +266 -0
  639. package/dist/template/.opencode/skill/swift-concurrency/references/actors.md +640 -0
  640. package/dist/template/.opencode/skill/swift-concurrency/references/async-algorithms.md +822 -0
  641. package/dist/template/.opencode/skill/swift-concurrency/references/async-await-basics.md +249 -0
  642. package/dist/template/.opencode/skill/swift-concurrency/references/async-sequences.md +670 -0
  643. package/dist/template/.opencode/skill/swift-concurrency/references/core-data.md +533 -0
  644. package/dist/template/.opencode/skill/swift-concurrency/references/glossary.md +128 -0
  645. package/dist/template/.opencode/skill/swift-concurrency/references/linting.md +142 -0
  646. package/dist/template/.opencode/skill/swift-concurrency/references/memory-management.md +542 -0
  647. package/dist/template/.opencode/skill/swift-concurrency/references/migration.md +1076 -0
  648. package/dist/template/.opencode/skill/swift-concurrency/references/performance.md +574 -0
  649. package/dist/template/.opencode/skill/swift-concurrency/references/sendable.md +578 -0
  650. package/dist/template/.opencode/skill/swift-concurrency/references/tasks.md +604 -0
  651. package/dist/template/.opencode/skill/swift-concurrency/references/testing.md +565 -0
  652. package/dist/template/.opencode/skill/swift-concurrency/references/threading.md +452 -0
  653. package/dist/template/.opencode/skill/swiftui-expert-skill/SKILL.md +329 -0
  654. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-advanced.md +351 -0
  655. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-basics.md +284 -0
  656. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-transitions.md +326 -0
  657. package/dist/template/.opencode/skill/swiftui-expert-skill/references/image-optimization.md +286 -0
  658. package/dist/template/.opencode/skill/swiftui-expert-skill/references/layout-best-practices.md +312 -0
  659. package/dist/template/.opencode/skill/swiftui-expert-skill/references/liquid-glass.md +377 -0
  660. package/dist/template/.opencode/skill/swiftui-expert-skill/references/list-patterns.md +153 -0
  661. package/dist/template/.opencode/skill/swiftui-expert-skill/references/modern-apis.md +400 -0
  662. package/dist/template/.opencode/skill/swiftui-expert-skill/references/performance-patterns.md +377 -0
  663. package/dist/template/.opencode/skill/swiftui-expert-skill/references/scroll-patterns.md +305 -0
  664. package/dist/template/.opencode/skill/swiftui-expert-skill/references/sheet-navigation-patterns.md +292 -0
  665. package/dist/template/.opencode/skill/swiftui-expert-skill/references/state-management.md +447 -0
  666. package/dist/template/.opencode/skill/swiftui-expert-skill/references/text-formatting.md +285 -0
  667. package/dist/template/.opencode/skill/swiftui-expert-skill/references/view-structure.md +276 -0
  668. package/dist/template/.opencode/skill/systematic-debugging/SKILL.md +402 -0
  669. package/dist/template/.opencode/skill/terse-output-mode/SKILL.md +95 -0
  670. package/dist/template/.opencode/skill/test-driven-development/SKILL.md +403 -0
  671. package/dist/template/.opencode/skill/testing-anti-patterns/SKILL.md +333 -0
  672. package/dist/template/.opencode/skill/think-in-code/SKILL.md +136 -0
  673. package/dist/template/.opencode/skill/using-git-worktrees/SKILL.md +259 -0
  674. package/dist/template/.opencode/skill/ux-quality-gates/SKILL.md +137 -0
  675. package/dist/template/.opencode/skill/v0/SKILL.md +158 -0
  676. package/dist/template/.opencode/skill/v1-run/SKILL.md +175 -0
  677. package/dist/template/.opencode/skill/v1-run/mcp.json +6 -0
  678. package/dist/template/.opencode/skill/vercel-deploy-claimable/SKILL.md +124 -0
  679. package/dist/template/.opencode/skill/vercel-deploy-claimable/scripts/deploy.sh +249 -0
  680. package/dist/template/.opencode/skill/verification-before-completion/SKILL.md +357 -0
  681. package/dist/template/.opencode/skill/verification-before-completion/references/VERIFICATION_PROTOCOL.md +171 -0
  682. package/dist/template/.opencode/skill/verification-gates/SKILL.md +63 -0
  683. package/dist/template/.opencode/skill/visual-analysis/SKILL.md +154 -0
  684. package/dist/template/.opencode/skill/web-design-guidelines/SKILL.md +46 -0
  685. package/dist/template/.opencode/skill/webclaw/SKILL.md +155 -0
  686. package/dist/template/.opencode/skill/workspace-setup/SKILL.md +76 -0
  687. package/dist/template/.opencode/skill/writing-plans/SKILL.md +320 -0
  688. package/dist/template/.opencode/skill/writing-skills/SKILL.md +324 -0
  689. package/dist/template/.opencode/skill/writing-skills/anthropic-best-practices.md +1173 -0
  690. package/dist/template/.opencode/skill/writing-skills/graphviz-conventions.dot +172 -0
  691. package/dist/template/.opencode/skill/writing-skills/persuasion-principles.md +220 -0
  692. package/dist/template/.opencode/skill/writing-skills/references/anti-patterns.md +25 -0
  693. package/dist/template/.opencode/skill/writing-skills/references/claude-search-optimization.md +140 -0
  694. package/dist/template/.opencode/skill/writing-skills/references/discovery-workflow.md +11 -0
  695. package/dist/template/.opencode/skill/writing-skills/references/file-organization.md +32 -0
  696. package/dist/template/.opencode/skill/writing-skills/references/flowcharts-and-examples.md +57 -0
  697. package/dist/template/.opencode/skill/writing-skills/references/rationalization-hardening.md +75 -0
  698. package/dist/template/.opencode/skill/writing-skills/references/testing-methodology.md +397 -0
  699. package/dist/template/.opencode/skill/writing-skills/references/testing-skill-types.md +52 -0
  700. package/dist/template/.opencode/tool/context7.ts +191 -0
  701. package/dist/template/.opencode/tool/grepsearch.ts +143 -0
  702. package/dist/template/.opencode/tsconfig.json +21 -0
  703. package/dist/template/.opencode/tui.json +15 -0
  704. package/package.json +78 -0
@@ -0,0 +1,1285 @@
1
+ /**
2
+ * GitHub Copilot Auth Plugin
3
+ * Simplified auth provider without token expiration checks
4
+ *
5
+ * Claude Reasoning Support:
6
+ * This plugin adds `thinking_budget` to the request body for Claude models.
7
+ * The Copilot API accepts this parameter and returns reasoning in the response.
8
+ *
9
+ * NOTE: Response parsing for reasoning_text/reasoning_opaque is handled by
10
+ * the custom SDK at .opencode/plugin/sdk/copilot/ which properly converts
11
+ * these fields to AI SDK's reasoning content parts.
12
+ */
13
+
14
+ import path from "node:path";
15
+ import { pathToFileURL } from "node:url";
16
+ import type { Plugin } from "@opencode-ai/plugin";
17
+
18
+ const CLIENT_ID = "Ov23li8tweQw6odWQebz";
19
+
20
+ // Logger function that will be set by the plugin
21
+ let log: (
22
+ level: "debug" | "info" | "warn" | "error",
23
+ message: string,
24
+ extra?: Record<string, any>,
25
+ ) => void = () => {};
26
+
27
+ /**
28
+ * Set the logger function from the plugin context
29
+ */
30
+ function setLogger(client: any) {
31
+ log = (level, message, extra) => {
32
+ client.app
33
+ .log({
34
+ service: "copilot-auth",
35
+ level,
36
+ message,
37
+ extra,
38
+ })
39
+ .catch(() => {}); // Fire and forget, don't block on logging
40
+ };
41
+ }
42
+
43
+ // Add a small safety buffer when polling to avoid hitting the server
44
+ // slightly too early due to clock skew / timer drift.
45
+ const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000; // 3 seconds
46
+
47
+ const HEADERS = {
48
+ "User-Agent": "opencode/1.3.17",
49
+ };
50
+
51
+ const RESPONSES_API_ALTERNATE_INPUT_TYPES = [
52
+ "file_search_call",
53
+ "computer_call",
54
+ "computer_call_output",
55
+ "web_search_call",
56
+ "function_call",
57
+ "function_call_output",
58
+ "image_generation_call",
59
+ "code_interpreter_call",
60
+ "local_shell_call",
61
+ "local_shell_call_output",
62
+ "mcp_list_tools",
63
+ "mcp_approval_request",
64
+ "mcp_approval_response",
65
+ "mcp_call",
66
+ "reasoning",
67
+ ];
68
+
69
+ // Expected ID prefixes per Responses API item type.
70
+ // The OpenAI Responses API validates that item IDs start with specific prefixes.
71
+ // GitHub Copilot's backend (especially GPT models) returns non-standard prefixes
72
+ // (e.g., "h_" instead of "fc_") or no prefix at all that the API then rejects on replay.
73
+ const RESPONSES_API_EXPECTED_PREFIXES: Record<string, string> = {
74
+ function_call: "fc_",
75
+ local_shell_call: "fc_",
76
+ // function_call_output.call_id prefix is validated directly in sanitizeResponseInputIds
77
+ };
78
+
79
+ // Role-based items (role: "assistant", "user", etc.) are internally typed as "message"
80
+ // by the OpenAI Responses API and their IDs must start with "msg_".
81
+ const RESPONSES_API_ROLE_PREFIX = "msg_";
82
+
83
+ function normalizeDomain(url: string): string {
84
+ return url.replace(/^https?:\/\//, "").replace(/\/$/, "");
85
+ }
86
+
87
+ const DEFAULT_COPILOT_API_BASE = "https://api.githubcopilot.com";
88
+
89
+ function toCopilotMessagesBase(url: string | undefined): string {
90
+ const base = (url?.trim() || DEFAULT_COPILOT_API_BASE)
91
+ .replace(/\/+$/, "")
92
+ .replace(/\/v1$/, "");
93
+ return `${base}/v1`;
94
+ }
95
+
96
+ function isClaudeCopilotModel(modelId: string, model: any): boolean {
97
+ return [modelId, model?.id, model?.api?.id]
98
+ .filter((value): value is string => typeof value === "string")
99
+ .some((value) => value.toLowerCase().includes("claude"));
100
+ }
101
+
102
+ function getUrls(domain: string) {
103
+ return {
104
+ DEVICE_CODE_URL: `https://${domain}/login/device/code`,
105
+ ACCESS_TOKEN_URL: `https://${domain}/login/oauth/access_token`,
106
+ };
107
+ }
108
+
109
+ const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
110
+
111
+ function getRequestUrl(input: RequestInfo | URL): string {
112
+ if (typeof input === "string") return input;
113
+ if (input instanceof URL) return input.toString();
114
+ if (typeof Request !== "undefined" && input instanceof Request) {
115
+ return input.url;
116
+ }
117
+ return input.toString();
118
+ }
119
+
120
+ function extractClaudeThinkingBudget(body: any): number | undefined {
121
+ const candidates = [body?.thinking_budget, body?.thinking?.budget_tokens];
122
+
123
+ for (const candidate of candidates) {
124
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
125
+ const normalized = Math.trunc(candidate);
126
+ if (normalized > 0) return normalized;
127
+ }
128
+ }
129
+
130
+ return undefined;
131
+ }
132
+
133
+ function getErrorMessage(error: unknown): string {
134
+ if (error instanceof Error) return error.message;
135
+ if (typeof error === "string") return error;
136
+ try {
137
+ return JSON.stringify(error);
138
+ } catch {
139
+ return String(error);
140
+ }
141
+ }
142
+
143
+ function isTransientUpstreamTimeoutError(error: unknown): boolean {
144
+ const message = getErrorMessage(error).toLowerCase();
145
+ return (
146
+ message.includes("upstream idle timeout") ||
147
+ message.includes("mid_stream") ||
148
+ message.includes("sse read timed out") ||
149
+ message.includes("socket connection was closed unexpectedly") ||
150
+ message.includes("connection reset") ||
151
+ message.includes("econnreset") ||
152
+ message.includes("etimedout")
153
+ );
154
+ }
155
+
156
+ // Rate limit handling configuration
157
+ const RATE_LIMIT_CONFIG = {
158
+ maxDelayMs: 60000, // Cap at 60 seconds
159
+ defaultCooldownMs: 60000, // Default cooldown when Retry-After header is missing
160
+ };
161
+
162
+ // Local request shaping to smooth bursts before they hit Copilot limits
163
+ const REQUEST_SHAPING_CONFIG = {
164
+ tokensPerSecond: 1,
165
+ burstCapacity: 2,
166
+ maxQueueDelayMs: 15000,
167
+ };
168
+
169
+ // Per-model rate limit state (in-memory, resets on restart)
170
+ interface RateLimitEntry {
171
+ rateLimitedUntil: number; // Unix timestamp (ms)
172
+ }
173
+ const rateLimitState = new Map<string, RateLimitEntry>();
174
+ const familyCircuitBreakerState = new Map<string, number>();
175
+
176
+ interface TokenBucketState {
177
+ tokens: number;
178
+ lastRefillAt: number;
179
+ }
180
+ const modelTokenBuckets = new Map<string, TokenBucketState>();
181
+ const modelQueueTail = new Map<string, Promise<void>>();
182
+
183
+ // Model fallback chains: same-family alternatives when a model is rate-limited
184
+ const MODEL_FALLBACK_CHAINS: Record<string, string[]> = {
185
+ // Claude family
186
+ "claude-opus-4.6": [
187
+ "claude-opus-4.5",
188
+ "claude-sonnet-4.6",
189
+ "claude-sonnet-4.5",
190
+ ],
191
+ "claude-opus-4.5": [
192
+ "claude-opus-4.6",
193
+ "claude-sonnet-4.5",
194
+ "claude-sonnet-4.6",
195
+ ],
196
+ "claude-sonnet-4.6": [
197
+ "claude-sonnet-4.5",
198
+ "claude-opus-4.6",
199
+ "claude-opus-4.5",
200
+ ],
201
+ "claude-sonnet-4.5": [
202
+ "claude-sonnet-4.6",
203
+ "claude-opus-4.5",
204
+ "claude-opus-4.6",
205
+ ],
206
+ };
207
+
208
+ /**
209
+ * Parse the Retry-After header from a 429 response.
210
+ * Returns cooldown in milliseconds, or null if header is missing/unparseable.
211
+ */
212
+ function parseRetryAfter(response: Response): number | null {
213
+ const header = response.headers.get("retry-after");
214
+ if (!header) return null;
215
+ // Try as seconds first (most common)
216
+ const seconds = parseInt(header, 10);
217
+ if (!isNaN(seconds) && seconds > 0) return seconds * 1000;
218
+ // Try as HTTP date
219
+ const date = Date.parse(header);
220
+ if (!isNaN(date)) return Math.max(0, date - Date.now());
221
+ return null;
222
+ }
223
+
224
+ function clampCooldownMs(
225
+ value: number | null | undefined,
226
+ fallbackMs = 0,
227
+ ): number {
228
+ return Math.min(
229
+ Math.max(value ?? fallbackMs, 0),
230
+ RATE_LIMIT_CONFIG.maxDelayMs,
231
+ );
232
+ }
233
+
234
+ function getRateLimitRemainingMs(model: string): number | null {
235
+ const entry = rateLimitState.get(model);
236
+ if (!entry) return null;
237
+ const remaining = entry.rateLimitedUntil - Date.now();
238
+ if (remaining <= 0) {
239
+ rateLimitState.delete(model);
240
+ return null;
241
+ }
242
+ return remaining;
243
+ }
244
+
245
+ function getModelFamily(model: string): string[] {
246
+ const family = new Set<string>([
247
+ model,
248
+ ...(MODEL_FALLBACK_CHAINS[model] || []),
249
+ ]);
250
+ return [...family];
251
+ }
252
+
253
+ function getFamilyCircuitKey(model: string): string {
254
+ return getModelFamily(model).sort().join("|");
255
+ }
256
+
257
+ function getFamilyCircuitRemainingMs(model: string): number {
258
+ const key = getFamilyCircuitKey(model);
259
+ const until = familyCircuitBreakerState.get(key);
260
+ if (!until) return 0;
261
+ const remaining = until - Date.now();
262
+ if (remaining <= 0) {
263
+ familyCircuitBreakerState.delete(key);
264
+ return 0;
265
+ }
266
+ return remaining;
267
+ }
268
+
269
+ function openFamilyCircuitBreaker(model: string, cooldownMs: number): void {
270
+ const key = getFamilyCircuitKey(model);
271
+ familyCircuitBreakerState.set(key, Date.now() + clampCooldownMs(cooldownMs));
272
+ }
273
+
274
+ function getFamilyMaxCooldownRemainingMs(model: string): number {
275
+ let maxRemaining = 0;
276
+ for (const candidate of getModelFamily(model)) {
277
+ const remaining = getRateLimitRemainingMs(candidate) ?? 0;
278
+ if (remaining > maxRemaining) maxRemaining = remaining;
279
+ }
280
+ return maxRemaining;
281
+ }
282
+
283
+ function formatRetryAfter(seconds: number): string {
284
+ if (seconds < 60) return `${seconds}s`;
285
+ const mins = Math.floor(seconds / 60);
286
+ const secs = seconds % 60;
287
+ return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;
288
+ }
289
+
290
+ async function shapeRequestForModel(model: string): Promise<void> {
291
+ if (!model) return;
292
+
293
+ const previousTail = modelQueueTail.get(model) ?? Promise.resolve();
294
+ let releaseQueue: (() => void) | undefined;
295
+ const currentGate = new Promise<void>((resolve) => {
296
+ releaseQueue = resolve;
297
+ });
298
+ const currentTail = previousTail.then(() => currentGate);
299
+ modelQueueTail.set(model, currentTail);
300
+
301
+ let queueTimeout: ReturnType<typeof setTimeout> | undefined;
302
+ try {
303
+ await Promise.race([
304
+ previousTail,
305
+ new Promise<void>((_, reject) => {
306
+ queueTimeout = setTimeout(() => {
307
+ reject(
308
+ new Error(
309
+ `[Copilot] Local request queue saturated for ${model}. Retry in ${formatRetryAfter(Math.ceil(REQUEST_SHAPING_CONFIG.maxQueueDelayMs / 1000))}.`,
310
+ ),
311
+ );
312
+ }, REQUEST_SHAPING_CONFIG.maxQueueDelayMs);
313
+ }),
314
+ ]);
315
+
316
+ const now = Date.now();
317
+ const bucket = modelTokenBuckets.get(model) ?? {
318
+ tokens: REQUEST_SHAPING_CONFIG.burstCapacity,
319
+ lastRefillAt: now,
320
+ };
321
+
322
+ const elapsedMs = Math.max(0, now - bucket.lastRefillAt);
323
+ const refillTokens =
324
+ (elapsedMs / 1000) * REQUEST_SHAPING_CONFIG.tokensPerSecond;
325
+ bucket.tokens = Math.min(
326
+ REQUEST_SHAPING_CONFIG.burstCapacity,
327
+ bucket.tokens + refillTokens,
328
+ );
329
+ bucket.lastRefillAt = now;
330
+
331
+ if (bucket.tokens < 1) {
332
+ const deficit = 1 - bucket.tokens;
333
+ const waitMs = Math.ceil(
334
+ (deficit / REQUEST_SHAPING_CONFIG.tokensPerSecond) * 1000,
335
+ );
336
+ if (waitMs > REQUEST_SHAPING_CONFIG.maxQueueDelayMs) {
337
+ throw new Error(
338
+ `[Copilot] Local request queue saturated for ${model}. Retry in ${formatRetryAfter(Math.ceil(waitMs / 1000))}.`,
339
+ );
340
+ }
341
+ log("info", `Local request shaping wait for ${model}`, {
342
+ wait_ms: waitMs,
343
+ });
344
+ await sleep(waitMs);
345
+ bucket.tokens = 0;
346
+ bucket.lastRefillAt = Date.now();
347
+ } else {
348
+ bucket.tokens -= 1;
349
+ }
350
+
351
+ modelTokenBuckets.set(model, bucket);
352
+ } finally {
353
+ if (queueTimeout) clearTimeout(queueTimeout);
354
+ releaseQueue?.();
355
+ if (modelQueueTail.get(model) === currentTail) {
356
+ modelQueueTail.delete(model);
357
+ }
358
+ }
359
+ }
360
+
361
+ function markModelRateLimited(model: string, cooldownMs: number): void {
362
+ const boundedCooldownMs = clampCooldownMs(cooldownMs);
363
+ rateLimitState.set(model, {
364
+ rateLimitedUntil: Date.now() + boundedCooldownMs,
365
+ });
366
+ log(
367
+ "info",
368
+ `Marked ${model} as rate-limited for ${Math.round(boundedCooldownMs / 1000)}s`,
369
+ );
370
+ }
371
+
372
+ // Maximum length for item IDs in the OpenAI Responses API
373
+ const MAX_RESPONSE_API_ID_LENGTH = 64;
374
+ // OpenAI Responses API only allows: letters, numbers, underscores, dashes
375
+ const INVALID_ID_CHARS = /[^a-zA-Z0-9_-]/g;
376
+
377
+ /** Check if an ID contains characters not allowed by the Responses API */
378
+ function hasInvalidIdChars(id: string): boolean {
379
+ // Use a non-global regex for .test() to avoid lastIndex state bug
380
+ return /[^a-zA-Z0-9_-]/.test(id);
381
+ }
382
+
383
+ /**
384
+ * Sanitize an ID for the Responses API.
385
+ * Handles three issues from GitHub Copilot:
386
+ * 1. Invalid characters — Copilot IDs contain +, |, /, = (base64-like encoding)
387
+ * 2. Wrong prefix — GPT models return "h_" instead of "fc_" for function_call items
388
+ * 3. Excessive length — Copilot returns 400+ char IDs (max is 64)
389
+ *
390
+ * Approach matches anomalyco/opencode: replace invalid chars with "_", preserve prefix,
391
+ * truncate to 64 chars, strip trailing underscores.
392
+ *
393
+ * @param id - The original ID to sanitize
394
+ * @param forcedPrefix - If provided, use this prefix instead of the detected one.
395
+ * See: https://github.com/vercel/ai/issues/5171
396
+ */
397
+ function sanitizeResponseId(id: string, forcedPrefix?: string): string {
398
+ if (!id) return id;
399
+
400
+ // Detect the original prefix (e.g., "fc_", "msg_", "call_", "resp_", "h_")
401
+ const prefixMatch = id.match(/^([a-z]+_)/);
402
+ const detectedPrefix = prefixMatch ? prefixMatch[1] : "";
403
+ const prefix = forcedPrefix ?? detectedPrefix;
404
+
405
+ // Strip the original prefix to get the core ID
406
+ const rawCore = id.slice(detectedPrefix.length);
407
+ // Replace invalid characters with underscores (same as anomalyco/opencode)
408
+ const cleanCore = rawCore.replace(INVALID_ID_CHARS, "_").replace(/_+$/g, "");
409
+
410
+ // Check if any sanitization is actually needed
411
+ const needsSanitization =
412
+ forcedPrefix ||
413
+ hasInvalidIdChars(rawCore) ||
414
+ id.length > MAX_RESPONSE_API_ID_LENGTH;
415
+
416
+ if (!needsSanitization) return id;
417
+
418
+ // If result fits within length and core is non-empty, use cleaned core directly
419
+ if (
420
+ cleanCore.length > 0 &&
421
+ prefix.length + cleanCore.length <= MAX_RESPONSE_API_ID_LENGTH
422
+ ) {
423
+ return `${prefix}${cleanCore}`;
424
+ }
425
+
426
+ // Hash the full original ID for deterministic uniqueness when truncating
427
+ let hash = 0;
428
+ for (let i = 0; i < id.length; i++) {
429
+ hash = ((hash << 5) - hash + id.charCodeAt(i)) | 0;
430
+ }
431
+ const hashStr = Math.abs(hash).toString(36);
432
+ const maxMiddleLen =
433
+ MAX_RESPONSE_API_ID_LENGTH - prefix.length - hashStr.length - 1;
434
+ const middle = cleanCore.slice(0, Math.max(0, maxMiddleLen));
435
+ // Format: prefix + middle + "_" + hash (ensure total <= 64)
436
+ const result = `${prefix}${middle}_${hashStr}`.slice(
437
+ 0,
438
+ MAX_RESPONSE_API_ID_LENGTH,
439
+ );
440
+ // Strip trailing underscores from truncation
441
+ return result.replace(/_+$/, "");
442
+ }
443
+
444
+ /**
445
+ * Check if an ID has the expected prefix for its item type.
446
+ * Handles both type-based items (function_call → "fc_") and
447
+ * role-based items (assistant/user/developer/system → "msg_").
448
+ * Returns the expected prefix if the ID is wrong, or null if it's fine.
449
+ */
450
+ function getExpectedPrefix(item: any): string | null {
451
+ if (!item || typeof item !== "object") return null;
452
+ if (typeof item.id !== "string") return null;
453
+
454
+ // Type-based items: function_call, local_shell_call, etc.
455
+ if (item.type) {
456
+ const expected = RESPONSES_API_EXPECTED_PREFIXES[item.type];
457
+ if (expected && !item.id.startsWith(expected)) {
458
+ return expected;
459
+ }
460
+ }
461
+
462
+ // Role-based items: assistant, user, developer, system → "msg_" prefix
463
+ if (item.role && !item.id.startsWith(RESPONSES_API_ROLE_PREFIX)) {
464
+ return RESPONSES_API_ROLE_PREFIX;
465
+ }
466
+
467
+ return null;
468
+ }
469
+
470
+ /** Check if a string ID needs sanitization (invalid chars or too long) */
471
+ function idNeedsSanitization(id: string): boolean {
472
+ return id.length > MAX_RESPONSE_API_ID_LENGTH || hasInvalidIdChars(id);
473
+ }
474
+
475
+ /**
476
+ * Sanitize all IDs in a Responses API input array.
477
+ *
478
+ * Handles THREE classes of invalid IDs:
479
+ * 1. Invalid characters — Copilot IDs contain +, |, /, = (only [a-zA-Z0-9_-] allowed)
480
+ * 2. Wrong prefix — Copilot GPT models return IDs like "h_xxx" instead of "fc_xxx"
481
+ * 3. Excessive length — Copilot returns 400+ char IDs that exceed the 64-char limit.
482
+ *
483
+ * Uses a two-pass approach:
484
+ * - Pass 1: Build an ID remap for all invalid IDs
485
+ * - Pass 2: Apply the remap to both `id` and `call_id` fields consistently,
486
+ * so function_call_output.call_id stays in sync with function_call.id
487
+ */
488
+ function sanitizeResponseInputIds(input: any[]): any[] {
489
+ // Pass 1: Build ID remapping
490
+ const idRemap = new Map<string, string>();
491
+
492
+ for (const item of input) {
493
+ if (!item || typeof item !== "object") continue;
494
+
495
+ // Check for wrong prefix (e.g., function_call with "h_" instead of "fc_")
496
+ const expectedPrefix = getExpectedPrefix(item);
497
+ if (
498
+ expectedPrefix &&
499
+ typeof item.id === "string" &&
500
+ !idRemap.has(item.id)
501
+ ) {
502
+ const newId = sanitizeResponseId(item.id, expectedPrefix);
503
+ if (newId !== item.id) {
504
+ idRemap.set(item.id, newId);
505
+ }
506
+ }
507
+
508
+ // Check for invalid chars or excessive length on id
509
+ if (
510
+ typeof item.id === "string" &&
511
+ idNeedsSanitization(item.id) &&
512
+ !idRemap.has(item.id)
513
+ ) {
514
+ idRemap.set(item.id, sanitizeResponseId(item.id));
515
+ }
516
+
517
+ // Check for wrong prefix on call_id (defensive: handles truncated conversations
518
+ // where function_call_output appears without its corresponding function_call)
519
+ if (
520
+ item.type === "function_call_output" &&
521
+ typeof item.call_id === "string" &&
522
+ !item.call_id.startsWith("fc_") &&
523
+ !idRemap.has(item.call_id)
524
+ ) {
525
+ const newCallId = sanitizeResponseId(item.call_id, "fc_");
526
+ if (newCallId !== item.call_id) {
527
+ idRemap.set(item.call_id, newCallId);
528
+ }
529
+ }
530
+
531
+ // Check for invalid chars or excessive length on call_id
532
+ if (
533
+ typeof item.call_id === "string" &&
534
+ idNeedsSanitization(item.call_id) &&
535
+ !idRemap.has(item.call_id)
536
+ ) {
537
+ idRemap.set(item.call_id, sanitizeResponseId(item.call_id));
538
+ }
539
+ }
540
+
541
+ // No changes needed
542
+ if (idRemap.size === 0) return input;
543
+
544
+ // Pass 2: Apply remapping to both id and call_id fields
545
+ return input.map((item: any) => {
546
+ if (!item || typeof item !== "object") return item;
547
+ const sanitized = { ...item };
548
+ if (typeof sanitized.id === "string" && idRemap.has(sanitized.id)) {
549
+ sanitized.id = idRemap.get(sanitized.id);
550
+ }
551
+ if (
552
+ typeof sanitized.call_id === "string" &&
553
+ idRemap.has(sanitized.call_id)
554
+ ) {
555
+ sanitized.call_id = idRemap.get(sanitized.call_id);
556
+ }
557
+ return sanitized;
558
+ });
559
+ }
560
+
561
+ export const CopilotAuthPlugin: Plugin = async ({ client: sdk, directory }) => {
562
+ // Initialize logger with the SDK client
563
+ setLogger(sdk);
564
+
565
+ const localCopilotSdk = pathToFileURL(
566
+ path.join(directory, ".opencode", "plugin", "sdk", "copilot", "index.ts"),
567
+ ).toString();
568
+
569
+ return {
570
+ auth: {
571
+ provider: "github-copilot",
572
+ loader: async (getAuth, provider) => {
573
+ const info = await getAuth();
574
+ if (!info || info.type !== "oauth") return {};
575
+
576
+ // Enterprise URL support for baseURL
577
+ const enterpriseUrl = (info as any).enterpriseUrl;
578
+ const baseURL = enterpriseUrl
579
+ ? `https://copilot-api.${normalizeDomain(enterpriseUrl)}`
580
+ : undefined;
581
+
582
+ if (provider && provider.models) {
583
+ for (const [modelId, model] of Object.entries(provider.models)) {
584
+ model.cost = {
585
+ input: 0,
586
+ output: 0,
587
+ cache: {
588
+ read: 0,
589
+ write: 0,
590
+ },
591
+ };
592
+
593
+ // OpenCode 1.14.33 routes Copilot Claude models through the
594
+ // Anthropic Messages API when Copilot /models reports /v1/messages.
595
+ // Keep that route: the local OpenAI-compatible SDK calls
596
+ // /chat/completions, which returns 404 for current Claude models.
597
+ if (isClaudeCopilotModel(modelId, model)) {
598
+ model.api.npm = "@ai-sdk/anthropic";
599
+ model.api.url = toCopilotMessagesBase(baseURL ?? model.api.url);
600
+ continue;
601
+ }
602
+
603
+ // Route OpenAI-compatible Copilot models through the bundled
604
+ // @ai-sdk/github-copilot SDK. This SDK is shipped with OpenCode and
605
+ // supports both /chat/completions (gpt-4*, older) and /v1/responses
606
+ // (gpt-5.x reasoning models), so projects without local @ai-sdk/*
607
+ // dependencies can initialize the provider without ProviderInitError.
608
+ model.api.npm = "@ai-sdk/github-copilot";
609
+ }
610
+ }
611
+
612
+ return {
613
+ baseURL,
614
+ apiKey: "",
615
+ async fetch(input, init) {
616
+ const info = await getAuth();
617
+ if (info.type !== "oauth") return fetch(input, init);
618
+
619
+ let isAgentCall = false;
620
+ let isVisionRequest = false;
621
+ let modifiedBody: any;
622
+ let isClaudeModel = false;
623
+
624
+ try {
625
+ const body =
626
+ typeof init?.body === "string"
627
+ ? JSON.parse(init.body)
628
+ : init?.body;
629
+
630
+ const url = getRequestUrl(input);
631
+
632
+ // Check if this is a Claude model request
633
+ const modelId = body?.model || "";
634
+ isClaudeModel = modelId.toLowerCase().includes("claude");
635
+
636
+ // Completions API
637
+ if (body?.messages && url.includes("completions")) {
638
+ // Keep local logic: detect if any message is assistant/tool
639
+ isAgentCall = body.messages.some((msg: any) =>
640
+ ["tool", "assistant"].includes(msg.role),
641
+ );
642
+ isVisionRequest = body.messages.some(
643
+ (msg: any) =>
644
+ Array.isArray(msg.content) &&
645
+ msg.content.some((part: any) => part.type === "image_url"),
646
+ );
647
+
648
+ // For Claude models, add thinking_budget to enable reasoning
649
+ // The Copilot API accepts this parameter and returns reasoning_text/reasoning_opaque
650
+ if (isClaudeModel) {
651
+ const thinkingBudget = extractClaudeThinkingBudget(body);
652
+ const isThinkingEnabled = thinkingBudget != null;
653
+
654
+ const cleanedMessages = body.messages.map(
655
+ (msg: any, idx: number) => {
656
+ if (msg.role !== "assistant") return msg;
657
+
658
+ // If thinking is disabled, strip all reasoning metadata to prevent
659
+ // stale reasoning context from continuing across turns.
660
+ if (!isThinkingEnabled) {
661
+ const {
662
+ reasoning_text: _reasoningText,
663
+ reasoning_opaque: _reasoningOpaque,
664
+ ...baseMsg
665
+ } = msg;
666
+ if (!Array.isArray(baseMsg.content)) return baseMsg;
667
+
668
+ const cleanedContent = baseMsg.content.filter(
669
+ (part: any) => part.type !== "thinking",
670
+ );
671
+
672
+ return {
673
+ ...baseMsg,
674
+ content:
675
+ cleanedContent.length > 0 ? cleanedContent : null,
676
+ };
677
+ }
678
+
679
+ // Log message structure for debugging
680
+ log("debug", `Processing assistant message ${idx}`, {
681
+ has_reasoning_text: !!msg.reasoning_text,
682
+ has_reasoning_opaque: !!msg.reasoning_opaque,
683
+ content_type: typeof msg.content,
684
+ content_is_array: Array.isArray(msg.content),
685
+ });
686
+
687
+ // If message has reasoning_text but no/invalid reasoning_opaque, remove reasoning
688
+ if (msg.reasoning_text && !msg.reasoning_opaque) {
689
+ log(
690
+ "warn",
691
+ `Removing reasoning_text without reasoning_opaque from message ${idx}`,
692
+ );
693
+ const { reasoning_text: _unused, ...cleanedMsg } = msg;
694
+ return cleanedMsg;
695
+ }
696
+
697
+ // If content is an array, strip ALL thinking blocks.
698
+ if (Array.isArray(msg.content)) {
699
+ const hasThinkingBlock = msg.content.some(
700
+ (part: any) => part.type === "thinking",
701
+ );
702
+ if (hasThinkingBlock) {
703
+ log(
704
+ "debug",
705
+ `Stripping all thinking blocks from message ${idx}`,
706
+ );
707
+ const cleanedContent = msg.content.filter(
708
+ (part: any) => part.type !== "thinking",
709
+ );
710
+ return {
711
+ ...msg,
712
+ content:
713
+ cleanedContent.length > 0 ? cleanedContent : null,
714
+ };
715
+ }
716
+ }
717
+
718
+ return msg;
719
+ },
720
+ );
721
+
722
+ const nextBody: Record<string, any> = {
723
+ ...(modifiedBody || body),
724
+ messages: cleanedMessages,
725
+ };
726
+
727
+ if (isThinkingEnabled) {
728
+ nextBody.thinking_budget = thinkingBudget;
729
+ log("info", `Adding thinking_budget for Claude model`, {
730
+ model: modelId,
731
+ thinking_budget: thinkingBudget,
732
+ });
733
+ } else {
734
+ delete nextBody.thinking_budget;
735
+ log(
736
+ "info",
737
+ `Claude thinking disabled for this request (no thinking budget set)`,
738
+ { model: modelId },
739
+ );
740
+ }
741
+
742
+ // Copilot OpenAI-compatible endpoint expects `thinking_budget`.
743
+ // Remove Anthropic-style `thinking` object to avoid mixed payloads.
744
+ delete nextBody.thinking;
745
+
746
+ modifiedBody = nextBody;
747
+ }
748
+
749
+ // For GPT models (o1, gpt-5, etc.), add reasoning parameter
750
+ const isGptModel =
751
+ modelId.toLowerCase().includes("gpt") ||
752
+ modelId.toLowerCase().includes("o1") ||
753
+ modelId.toLowerCase().includes("o3") ||
754
+ modelId.toLowerCase().includes("o4");
755
+
756
+ if (isGptModel && !isClaudeModel) {
757
+ // Get reasoning effort from body options or default to "medium"
758
+ const reasoningEffort =
759
+ body.reasoning?.effort ||
760
+ body.reasoningEffort ||
761
+ body.reasoning_effort ||
762
+ "medium";
763
+
764
+ modifiedBody = {
765
+ ...(modifiedBody || body),
766
+ reasoning: {
767
+ effort: reasoningEffort,
768
+ },
769
+ };
770
+
771
+ // Also pass through other reasoning options if present
772
+ if (body.reasoningSummary || body.reasoning?.summary) {
773
+ modifiedBody.reasoning.summary =
774
+ body.reasoningSummary || body.reasoning?.summary;
775
+ }
776
+
777
+ log("info", `Adding reasoning for GPT model`, {
778
+ model: modelId,
779
+ reasoning_effort: reasoningEffort,
780
+ });
781
+ }
782
+ }
783
+
784
+ // Responses API
785
+ if (body?.input) {
786
+ // Log raw IDs before sanitization for debugging
787
+ const rawIds = body.input
788
+ .filter((item: any) => item && typeof item === "object")
789
+ .flatMap((item: any) => [
790
+ item.id ? `id=${item.id}` : null,
791
+ item.call_id ? `call_id=${item.call_id}` : null,
792
+ ])
793
+ .filter(Boolean);
794
+ if (rawIds.length > 0) {
795
+ log(
796
+ "debug",
797
+ "[ID-SANITIZE] Raw input IDs before sanitization",
798
+ {
799
+ ids: rawIds,
800
+ count: rawIds.length,
801
+ },
802
+ );
803
+ }
804
+
805
+ // Sanitize IDs from Copilot backend:
806
+ // 1. Wrong prefix — GPT models return "h_xxx" instead of "fc_xxx"
807
+ // 2. Excessive length — Copilot returns 400+ char IDs (max is 64)
808
+ const sanitizedInput = sanitizeResponseInputIds(body.input);
809
+ const refDiffers = sanitizedInput !== body.input;
810
+ const jsonDiffers =
811
+ refDiffers &&
812
+ JSON.stringify(sanitizedInput) !== JSON.stringify(body.input);
813
+ const inputWasSanitized = refDiffers && jsonDiffers;
814
+
815
+ log("debug", "[ID-SANITIZE] Sanitization result", {
816
+ was_sanitized: inputWasSanitized,
817
+ ref_differs: refDiffers,
818
+ json_differs: jsonDiffers,
819
+ });
820
+
821
+ if (inputWasSanitized) {
822
+ const fixes = body.input
823
+ .map((item: any, i: number) => ({
824
+ item,
825
+ i,
826
+ si: sanitizedInput[i],
827
+ }))
828
+ .filter(
829
+ ({ item, si }: any) =>
830
+ item &&
831
+ si &&
832
+ (item.id !== si.id || item.call_id !== si.call_id),
833
+ );
834
+ log(
835
+ "info",
836
+ "[ID-SANITIZE] Fixed IDs in Responses API input",
837
+ {
838
+ items_fixed: fixes.length,
839
+ fixes: fixes.map(({ item, si }: any) => ({
840
+ type: item.type,
841
+ old_id: item.id,
842
+ new_id: si?.id,
843
+ old_call_id: item.call_id,
844
+ new_call_id: si?.call_id,
845
+ })),
846
+ },
847
+ );
848
+ modifiedBody = {
849
+ ...(modifiedBody || body),
850
+ input: sanitizedInput,
851
+ };
852
+ } else {
853
+ log(
854
+ "debug",
855
+ "[ID-SANITIZE] No sanitization needed — all IDs valid",
856
+ );
857
+ }
858
+
859
+ isAgentCall = (sanitizedInput || body.input).some(
860
+ (item: any) =>
861
+ item?.role === "assistant" ||
862
+ (item?.type &&
863
+ RESPONSES_API_ALTERNATE_INPUT_TYPES.includes(item.type)),
864
+ );
865
+
866
+ isVisionRequest = body.input.some(
867
+ (item: any) =>
868
+ Array.isArray(item?.content) &&
869
+ item.content.some(
870
+ (part: any) => part.type === "input_image",
871
+ ),
872
+ );
873
+ }
874
+
875
+ // Messages API (Anthropic style)
876
+ if (body?.messages && !url.includes("completions")) {
877
+ isAgentCall = body.messages.some((msg: any) =>
878
+ ["tool", "assistant"].includes(msg.role),
879
+ );
880
+ isVisionRequest = body.messages.some(
881
+ (item: any) =>
882
+ Array.isArray(item?.content) &&
883
+ item.content.some(
884
+ (part: any) =>
885
+ part?.type === "image" ||
886
+ (part?.type === "tool_result" &&
887
+ Array.isArray(part?.content) &&
888
+ part.content.some(
889
+ (nested: any) => nested?.type === "image",
890
+ )),
891
+ ),
892
+ );
893
+ }
894
+
895
+ // Sanitize tool definitions: strip non-standard fields like
896
+ // "custom" (wrapping eager_input_streaming) injected by
897
+ // runtime layers. These cause "Extra inputs are not permitted"
898
+ // on the Copilot API.
899
+ const toolSource = modifiedBody || body;
900
+ if (Array.isArray(toolSource?.tools)) {
901
+ let toolsChanged = false;
902
+ const sanitizedTools = toolSource.tools.map((tool: any) => {
903
+ if (!tool || typeof tool !== "object") return tool;
904
+
905
+ let result = tool;
906
+
907
+ // Strip top-level non-standard fields from tool object
908
+ if ("custom" in result || "eager_input_streaming" in result) {
909
+ toolsChanged = true;
910
+ const {
911
+ custom: _custom,
912
+ eager_input_streaming: _eis,
913
+ ...clean
914
+ } = result;
915
+ result = clean;
916
+ }
917
+
918
+ // Also check nested function object (Chat Completions format)
919
+ if (
920
+ result.function &&
921
+ typeof result.function === "object" &&
922
+ ("custom" in result.function ||
923
+ "eager_input_streaming" in result.function)
924
+ ) {
925
+ toolsChanged = true;
926
+ const {
927
+ custom: _c,
928
+ eager_input_streaming: _e,
929
+ ...cleanFn
930
+ } = result.function;
931
+ result = { ...result, function: cleanFn };
932
+ }
933
+
934
+ return result;
935
+ });
936
+
937
+ if (toolsChanged) {
938
+ modifiedBody = {
939
+ ...(modifiedBody || body),
940
+ tools: sanitizedTools,
941
+ };
942
+ log(
943
+ "debug",
944
+ "Stripped non-standard fields (custom/eager_input_streaming) from tool definitions",
945
+ );
946
+ }
947
+ }
948
+ } catch {}
949
+
950
+ const headers: Record<string, string> = {
951
+ "x-initiator": isAgentCall ? "agent" : "user",
952
+ ...(init?.headers as Record<string, string>),
953
+ ...HEADERS,
954
+ Authorization: `Bearer ${info.refresh}`,
955
+ "Openai-Intent": "conversation-edits",
956
+ };
957
+
958
+ if (isVisionRequest) {
959
+ headers["Copilot-Vision-Request"] = "true";
960
+ }
961
+
962
+ // Official only deletes lowercase "authorization"
963
+ delete headers["x-api-key"];
964
+ delete headers["authorization"];
965
+
966
+ // Prepare the final init object with potentially modified body
967
+ const finalInit = {
968
+ ...init,
969
+ headers,
970
+ ...(modifiedBody ? { body: JSON.stringify(modifiedBody) } : {}),
971
+ };
972
+
973
+ // Extract model from request body for rate limit tracking
974
+ let currentModel = "";
975
+ try {
976
+ const bodyObj =
977
+ typeof finalInit.body === "string"
978
+ ? JSON.parse(finalInit.body)
979
+ : finalInit.body;
980
+ currentModel = bodyObj?.model || "";
981
+ } catch {}
982
+
983
+ // Pre-flight: fail fast if current model family is cooling down
984
+ const activeFinalInit: RequestInit = finalInit;
985
+ if (currentModel) {
986
+ const familyCooldownMs = Math.max(
987
+ getFamilyCircuitRemainingMs(currentModel),
988
+ getFamilyMaxCooldownRemainingMs(currentModel),
989
+ );
990
+ if (familyCooldownMs > 0) {
991
+ throw new Error(
992
+ `[Copilot] Rate limited: all fallback models cooling down. Retry in ${formatRetryAfter(Math.ceil(familyCooldownMs / 1000))}.`,
993
+ );
994
+ }
995
+ }
996
+
997
+ const maxFetchAttempts = 2;
998
+
999
+ for (let attempt = 1; attempt <= maxFetchAttempts; attempt++) {
1000
+ try {
1001
+ if (currentModel) {
1002
+ await shapeRequestForModel(currentModel);
1003
+ }
1004
+ const response = await fetch(input, activeFinalInit);
1005
+
1006
+ if (response.status === 429) {
1007
+ try {
1008
+ await response.body?.cancel();
1009
+ } catch {}
1010
+
1011
+ const retryAfterMs = parseRetryAfter(response);
1012
+ const cooldownMs = clampCooldownMs(
1013
+ retryAfterMs,
1014
+ RATE_LIMIT_CONFIG.defaultCooldownMs,
1015
+ );
1016
+
1017
+ if (currentModel) {
1018
+ markModelRateLimited(currentModel, cooldownMs);
1019
+ openFamilyCircuitBreaker(currentModel, cooldownMs);
1020
+ }
1021
+
1022
+ throw new Error(
1023
+ `[Copilot] Rate limited: ${currentModel || "model"} cooling down. Retry in ${formatRetryAfter(Math.ceil(cooldownMs / 1000))}.`,
1024
+ );
1025
+ }
1026
+
1027
+ // Response transformation is handled by the custom SDK at
1028
+ // .opencode/plugin/sdk/copilot/
1029
+ return response;
1030
+ } catch (error) {
1031
+ const errorMessage = getErrorMessage(error);
1032
+ if (
1033
+ errorMessage.includes("Rate limited") ||
1034
+ errorMessage.includes("Local request queue saturated")
1035
+ ) {
1036
+ throw error instanceof Error
1037
+ ? error
1038
+ : new Error(errorMessage);
1039
+ }
1040
+
1041
+ if (
1042
+ attempt < maxFetchAttempts &&
1043
+ isTransientUpstreamTimeoutError(error)
1044
+ ) {
1045
+ const retryDelayMs = 750 * attempt;
1046
+ log(
1047
+ "warn",
1048
+ `Transient upstream timeout from Copilot, retrying request`,
1049
+ {
1050
+ model: currentModel || undefined,
1051
+ attempt,
1052
+ retry_delay_ms: retryDelayMs,
1053
+ error: errorMessage,
1054
+ },
1055
+ );
1056
+ await sleep(retryDelayMs);
1057
+ continue;
1058
+ }
1059
+
1060
+ if (isTransientUpstreamTimeoutError(error)) {
1061
+ throw new Error(
1062
+ `[Copilot] Upstream idle timeout while streaming ${currentModel || "request"}. Retry with a lower thinking budget or switch to a lower-latency Claude variant.`,
1063
+ );
1064
+ }
1065
+
1066
+ throw error;
1067
+ }
1068
+ }
1069
+
1070
+ throw new Error(
1071
+ `[Copilot] Failed request after ${maxFetchAttempts} attempts.`,
1072
+ );
1073
+ },
1074
+ };
1075
+ },
1076
+ methods: [
1077
+ {
1078
+ type: "oauth",
1079
+ label: "Login with GitHub Copilot",
1080
+ prompts: [
1081
+ {
1082
+ type: "select",
1083
+ key: "deploymentType",
1084
+ message: "Select GitHub deployment type",
1085
+ options: [
1086
+ {
1087
+ label: "GitHub.com",
1088
+ value: "github.com",
1089
+ hint: "Public",
1090
+ },
1091
+ {
1092
+ label: "GitHub Enterprise",
1093
+ value: "enterprise",
1094
+ hint: "Data residency or self-hosted",
1095
+ },
1096
+ ],
1097
+ },
1098
+ {
1099
+ type: "text",
1100
+ key: "enterpriseUrl",
1101
+ message: "Enter your GitHub Enterprise URL or domain",
1102
+ placeholder: "company.ghe.com or https://company.ghe.com",
1103
+ condition: (inputs: any) =>
1104
+ inputs.deploymentType === "enterprise",
1105
+ validate: (value: string) => {
1106
+ if (!value) return "URL or domain is required";
1107
+ try {
1108
+ const url = value.includes("://")
1109
+ ? new URL(value)
1110
+ : new URL(`https://${value}`);
1111
+ if (!url.hostname)
1112
+ return "Please enter a valid URL or domain";
1113
+ return undefined;
1114
+ } catch {
1115
+ return "Please enter a valid URL (e.g., company.ghe.com or https://company.ghe.com)";
1116
+ }
1117
+ },
1118
+ },
1119
+ ],
1120
+ async authorize(inputs: any = {}) {
1121
+ const deploymentType = inputs.deploymentType || "github.com";
1122
+
1123
+ let domain = "github.com";
1124
+ let actualProvider = "github-copilot";
1125
+
1126
+ if (deploymentType === "enterprise") {
1127
+ const enterpriseUrl = inputs.enterpriseUrl;
1128
+ domain = normalizeDomain(enterpriseUrl);
1129
+ actualProvider = "github-copilot-enterprise";
1130
+ }
1131
+
1132
+ const urls = getUrls(domain);
1133
+
1134
+ const deviceResponse = await fetch(urls.DEVICE_CODE_URL, {
1135
+ method: "POST",
1136
+ headers: {
1137
+ Accept: "application/json",
1138
+ "Content-Type": "application/json",
1139
+ "User-Agent": "opencode/1.3.17",
1140
+ },
1141
+ body: JSON.stringify({
1142
+ client_id: CLIENT_ID,
1143
+ scope: "read:user",
1144
+ }),
1145
+ });
1146
+
1147
+ if (!deviceResponse.ok) {
1148
+ throw new Error("Failed to initiate device authorization");
1149
+ }
1150
+
1151
+ const deviceData = await deviceResponse.json();
1152
+
1153
+ return {
1154
+ url: deviceData.verification_uri,
1155
+ instructions: `Enter code: ${deviceData.user_code}`,
1156
+ method: "auto",
1157
+ callback: async () => {
1158
+ while (true) {
1159
+ const response = await fetch(urls.ACCESS_TOKEN_URL, {
1160
+ method: "POST",
1161
+ headers: {
1162
+ Accept: "application/json",
1163
+ "Content-Type": "application/json",
1164
+ "User-Agent": "opencode/1.3.17",
1165
+ },
1166
+ body: JSON.stringify({
1167
+ client_id: CLIENT_ID,
1168
+ device_code: deviceData.device_code,
1169
+ grant_type:
1170
+ "urn:ietf:params:oauth:grant-type:device_code",
1171
+ }),
1172
+ });
1173
+
1174
+ if (!response.ok) return { type: "failed" };
1175
+
1176
+ const data = await response.json();
1177
+
1178
+ if (data.access_token) {
1179
+ const result: {
1180
+ type: "success";
1181
+ refresh: string;
1182
+ access: string;
1183
+ expires: number;
1184
+ provider?: string;
1185
+ enterpriseUrl?: string;
1186
+ } = {
1187
+ type: "success",
1188
+ refresh: data.access_token,
1189
+ access: data.access_token,
1190
+ expires: 0,
1191
+ };
1192
+
1193
+ if (actualProvider === "github-copilot-enterprise") {
1194
+ result.provider = "github-copilot-enterprise";
1195
+ result.enterpriseUrl = domain;
1196
+ }
1197
+
1198
+ return result;
1199
+ }
1200
+
1201
+ if (data.error === "authorization_pending") {
1202
+ await sleep(
1203
+ deviceData.interval * 1000 +
1204
+ OAUTH_POLLING_SAFETY_MARGIN_MS,
1205
+ );
1206
+ continue;
1207
+ }
1208
+
1209
+ if (data.error === "slow_down") {
1210
+ // Based on the RFC spec, we must add 5 seconds to our current polling interval.
1211
+ let newInterval = (deviceData.interval + 5) * 1000;
1212
+
1213
+ if (
1214
+ data.interval &&
1215
+ typeof data.interval === "number" &&
1216
+ data.interval > 0
1217
+ ) {
1218
+ newInterval = data.interval * 1000;
1219
+ }
1220
+
1221
+ await sleep(newInterval + OAUTH_POLLING_SAFETY_MARGIN_MS);
1222
+ continue;
1223
+ }
1224
+
1225
+ if (data.error) return { type: "failed" };
1226
+
1227
+ await sleep(
1228
+ deviceData.interval * 1000 + OAUTH_POLLING_SAFETY_MARGIN_MS,
1229
+ );
1230
+ }
1231
+ },
1232
+ };
1233
+ },
1234
+ },
1235
+ ],
1236
+ },
1237
+ // Hook to add custom headers for Claude reasoning support
1238
+ "chat.headers": async (input: any, output: any) => {
1239
+ // Only apply to GitHub Copilot provider
1240
+ if (!input.model?.providerID?.includes("github-copilot")) return;
1241
+
1242
+ // Add Anthropic beta header for interleaved thinking (extended reasoning)
1243
+ // This is required for Claude models to return thinking blocks
1244
+ if (input.model?.api?.npm === "@ai-sdk/anthropic") {
1245
+ output.headers["anthropic-beta"] = "interleaved-thinking-2025-05-14";
1246
+ }
1247
+
1248
+ // When using the local Copilot SDK, let the SDK/message pipeline decide
1249
+ // initiator semantics. Overriding x-initiator here can break Responses routing.
1250
+ if (input.model?.api?.npm === localCopilotSdk) return;
1251
+
1252
+ // Mark subagent sessions as agent-initiated (matching standard Copilot tools)
1253
+ try {
1254
+ const session = await sdk.session
1255
+ .get({
1256
+ path: {
1257
+ id: input.sessionID,
1258
+ },
1259
+ throwOnError: true,
1260
+ })
1261
+ .catch(() => undefined);
1262
+ if (session?.data?.parentID) {
1263
+ output.headers["x-initiator"] = "agent";
1264
+ }
1265
+ } catch {
1266
+ // Ignore errors from session lookup
1267
+ }
1268
+ },
1269
+ // Hook to strip maxOutputTokens for GPT models (matches upstream Copilot CLI behavior)
1270
+ "chat.params": async (input: any, output: any) => {
1271
+ if (!input.model?.providerID?.includes("github-copilot")) return;
1272
+
1273
+ // Copilot rejects eager tool streaming on Anthropic Messages routing.
1274
+ if (input.model?.api?.npm === "@ai-sdk/anthropic") {
1275
+ output.options ??= {};
1276
+ output.options.toolStreaming = false;
1277
+ }
1278
+
1279
+ // GPT models don't support maxOutputTokens through the Copilot proxy
1280
+ if (input.model?.api?.id?.includes("gpt")) {
1281
+ output.maxOutputTokens = undefined;
1282
+ }
1283
+ },
1284
+ };
1285
+ };