iosm-cli 0.1.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 (729) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/LICENSE +21 -0
  3. package/README.md +650 -0
  4. package/dist/cli/args.d.ts +54 -0
  5. package/dist/cli/args.d.ts.map +1 -0
  6. package/dist/cli/args.js +331 -0
  7. package/dist/cli/args.js.map +1 -0
  8. package/dist/cli/config-selector.d.ts +14 -0
  9. package/dist/cli/config-selector.d.ts.map +1 -0
  10. package/dist/cli/config-selector.js +31 -0
  11. package/dist/cli/config-selector.js.map +1 -0
  12. package/dist/cli/file-processor.d.ts +15 -0
  13. package/dist/cli/file-processor.d.ts.map +1 -0
  14. package/dist/cli/file-processor.js +79 -0
  15. package/dist/cli/file-processor.js.map +1 -0
  16. package/dist/cli/list-models.d.ts +9 -0
  17. package/dist/cli/list-models.d.ts.map +1 -0
  18. package/dist/cli/list-models.js +92 -0
  19. package/dist/cli/list-models.js.map +1 -0
  20. package/dist/cli/session-picker.d.ts +9 -0
  21. package/dist/cli/session-picker.d.ts.map +1 -0
  22. package/dist/cli/session-picker.js +34 -0
  23. package/dist/cli/session-picker.js.map +1 -0
  24. package/dist/cli.d.ts +3 -0
  25. package/dist/cli.d.ts.map +1 -0
  26. package/dist/cli.js +15 -0
  27. package/dist/cli.js.map +1 -0
  28. package/dist/config.d.ts +88 -0
  29. package/dist/config.d.ts.map +1 -0
  30. package/dist/config.js +262 -0
  31. package/dist/config.js.map +1 -0
  32. package/dist/core/agent-profiles.d.ts +29 -0
  33. package/dist/core/agent-profiles.d.ts.map +1 -0
  34. package/dist/core/agent-profiles.js +86 -0
  35. package/dist/core/agent-profiles.js.map +1 -0
  36. package/dist/core/agent-session.d.ts +688 -0
  37. package/dist/core/agent-session.d.ts.map +1 -0
  38. package/dist/core/agent-session.js +3112 -0
  39. package/dist/core/agent-session.js.map +1 -0
  40. package/dist/core/agent-teams.d.ts +41 -0
  41. package/dist/core/agent-teams.d.ts.map +1 -0
  42. package/dist/core/agent-teams.js +90 -0
  43. package/dist/core/agent-teams.js.map +1 -0
  44. package/dist/core/ask-user-tool.d.ts +22 -0
  45. package/dist/core/ask-user-tool.d.ts.map +1 -0
  46. package/dist/core/ask-user-tool.js +115 -0
  47. package/dist/core/ask-user-tool.js.map +1 -0
  48. package/dist/core/auth-storage.d.ts +133 -0
  49. package/dist/core/auth-storage.d.ts.map +1 -0
  50. package/dist/core/auth-storage.js +391 -0
  51. package/dist/core/auth-storage.js.map +1 -0
  52. package/dist/core/bash-executor.d.ts +49 -0
  53. package/dist/core/bash-executor.d.ts.map +1 -0
  54. package/dist/core/bash-executor.js +213 -0
  55. package/dist/core/bash-executor.js.map +1 -0
  56. package/dist/core/compaction/branch-summarization.d.ts +86 -0
  57. package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
  58. package/dist/core/compaction/branch-summarization.js +242 -0
  59. package/dist/core/compaction/branch-summarization.js.map +1 -0
  60. package/dist/core/compaction/compaction.d.ts +121 -0
  61. package/dist/core/compaction/compaction.d.ts.map +1 -0
  62. package/dist/core/compaction/compaction.js +610 -0
  63. package/dist/core/compaction/compaction.js.map +1 -0
  64. package/dist/core/compaction/index.d.ts +7 -0
  65. package/dist/core/compaction/index.d.ts.map +1 -0
  66. package/dist/core/compaction/index.js +7 -0
  67. package/dist/core/compaction/index.js.map +1 -0
  68. package/dist/core/compaction/utils.d.ts +35 -0
  69. package/dist/core/compaction/utils.d.ts.map +1 -0
  70. package/dist/core/compaction/utils.js +138 -0
  71. package/dist/core/compaction/utils.js.map +1 -0
  72. package/dist/core/defaults.d.ts +3 -0
  73. package/dist/core/defaults.d.ts.map +1 -0
  74. package/dist/core/defaults.js +2 -0
  75. package/dist/core/defaults.js.map +1 -0
  76. package/dist/core/diagnostics.d.ts +15 -0
  77. package/dist/core/diagnostics.d.ts.map +1 -0
  78. package/dist/core/diagnostics.js +2 -0
  79. package/dist/core/diagnostics.js.map +1 -0
  80. package/dist/core/event-bus.d.ts +9 -0
  81. package/dist/core/event-bus.d.ts.map +1 -0
  82. package/dist/core/event-bus.js +25 -0
  83. package/dist/core/event-bus.js.map +1 -0
  84. package/dist/core/exec.d.ts +29 -0
  85. package/dist/core/exec.d.ts.map +1 -0
  86. package/dist/core/exec.js +71 -0
  87. package/dist/core/exec.js.map +1 -0
  88. package/dist/core/export-html/ansi-to-html.d.ts +22 -0
  89. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  90. package/dist/core/export-html/ansi-to-html.js +249 -0
  91. package/dist/core/export-html/ansi-to-html.js.map +1 -0
  92. package/dist/core/export-html/index.d.ts +34 -0
  93. package/dist/core/export-html/index.d.ts.map +1 -0
  94. package/dist/core/export-html/index.js +222 -0
  95. package/dist/core/export-html/index.js.map +1 -0
  96. package/dist/core/export-html/template.css +971 -0
  97. package/dist/core/export-html/template.html +54 -0
  98. package/dist/core/export-html/template.js +1590 -0
  99. package/dist/core/export-html/tool-renderer.d.ts +35 -0
  100. package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  101. package/dist/core/export-html/tool-renderer.js +63 -0
  102. package/dist/core/export-html/tool-renderer.js.map +1 -0
  103. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  104. package/dist/core/export-html/vendor/marked.min.js +6 -0
  105. package/dist/core/extensions/index.d.ts +11 -0
  106. package/dist/core/extensions/index.d.ts.map +1 -0
  107. package/dist/core/extensions/index.js +9 -0
  108. package/dist/core/extensions/index.js.map +1 -0
  109. package/dist/core/extensions/loader.d.ts +25 -0
  110. package/dist/core/extensions/loader.d.ts.map +1 -0
  111. package/dist/core/extensions/loader.js +447 -0
  112. package/dist/core/extensions/loader.js.map +1 -0
  113. package/dist/core/extensions/runner.d.ts +146 -0
  114. package/dist/core/extensions/runner.d.ts.map +1 -0
  115. package/dist/core/extensions/runner.js +652 -0
  116. package/dist/core/extensions/runner.js.map +1 -0
  117. package/dist/core/extensions/types.d.ts +1074 -0
  118. package/dist/core/extensions/types.d.ts.map +1 -0
  119. package/dist/core/extensions/types.js +35 -0
  120. package/dist/core/extensions/types.js.map +1 -0
  121. package/dist/core/extensions/wrapper.d.ts +27 -0
  122. package/dist/core/extensions/wrapper.d.ts.map +1 -0
  123. package/dist/core/extensions/wrapper.js +102 -0
  124. package/dist/core/extensions/wrapper.js.map +1 -0
  125. package/dist/core/footer-data-provider.d.ts +32 -0
  126. package/dist/core/footer-data-provider.d.ts.map +1 -0
  127. package/dist/core/footer-data-provider.js +134 -0
  128. package/dist/core/footer-data-provider.js.map +1 -0
  129. package/dist/core/hooks.d.ts +53 -0
  130. package/dist/core/hooks.d.ts.map +1 -0
  131. package/dist/core/hooks.js +332 -0
  132. package/dist/core/hooks.js.map +1 -0
  133. package/dist/core/index.d.ts +9 -0
  134. package/dist/core/index.d.ts.map +1 -0
  135. package/dist/core/index.js +9 -0
  136. package/dist/core/index.js.map +1 -0
  137. package/dist/core/keybindings.d.ts +55 -0
  138. package/dist/core/keybindings.d.ts.map +1 -0
  139. package/dist/core/keybindings.js +157 -0
  140. package/dist/core/keybindings.js.map +1 -0
  141. package/dist/core/mcp/cli.d.ts +27 -0
  142. package/dist/core/mcp/cli.d.ts.map +1 -0
  143. package/dist/core/mcp/cli.js +275 -0
  144. package/dist/core/mcp/cli.js.map +1 -0
  145. package/dist/core/mcp/config.d.ts +11 -0
  146. package/dist/core/mcp/config.d.ts.map +1 -0
  147. package/dist/core/mcp/config.js +310 -0
  148. package/dist/core/mcp/config.js.map +1 -0
  149. package/dist/core/mcp/index.d.ts +5 -0
  150. package/dist/core/mcp/index.d.ts.map +1 -0
  151. package/dist/core/mcp/index.js +4 -0
  152. package/dist/core/mcp/index.js.map +1 -0
  153. package/dist/core/mcp/runtime.d.ts +42 -0
  154. package/dist/core/mcp/runtime.d.ts.map +1 -0
  155. package/dist/core/mcp/runtime.js +387 -0
  156. package/dist/core/mcp/runtime.js.map +1 -0
  157. package/dist/core/mcp/types.d.ts +76 -0
  158. package/dist/core/mcp/types.d.ts.map +1 -0
  159. package/dist/core/mcp/types.js +2 -0
  160. package/dist/core/mcp/types.js.map +1 -0
  161. package/dist/core/memory.d.ts +27 -0
  162. package/dist/core/memory.d.ts.map +1 -0
  163. package/dist/core/memory.js +203 -0
  164. package/dist/core/memory.js.map +1 -0
  165. package/dist/core/messages.d.ts +84 -0
  166. package/dist/core/messages.d.ts.map +1 -0
  167. package/dist/core/messages.js +141 -0
  168. package/dist/core/messages.js.map +1 -0
  169. package/dist/core/model-registry.d.ts +115 -0
  170. package/dist/core/model-registry.d.ts.map +1 -0
  171. package/dist/core/model-registry.js +549 -0
  172. package/dist/core/model-registry.js.map +1 -0
  173. package/dist/core/model-resolver.d.ts +104 -0
  174. package/dist/core/model-resolver.d.ts.map +1 -0
  175. package/dist/core/model-resolver.js +448 -0
  176. package/dist/core/model-resolver.js.map +1 -0
  177. package/dist/core/package-manager.d.ts +156 -0
  178. package/dist/core/package-manager.d.ts.map +1 -0
  179. package/dist/core/package-manager.js +1465 -0
  180. package/dist/core/package-manager.js.map +1 -0
  181. package/dist/core/parallel-task-agent.d.ts +19 -0
  182. package/dist/core/parallel-task-agent.d.ts.map +1 -0
  183. package/dist/core/parallel-task-agent.js +482 -0
  184. package/dist/core/parallel-task-agent.js.map +1 -0
  185. package/dist/core/prompt-templates.d.ts +50 -0
  186. package/dist/core/prompt-templates.d.ts.map +1 -0
  187. package/dist/core/prompt-templates.js +251 -0
  188. package/dist/core/prompt-templates.js.map +1 -0
  189. package/dist/core/qwen-cli-provider.d.ts +10 -0
  190. package/dist/core/qwen-cli-provider.d.ts.map +1 -0
  191. package/dist/core/qwen-cli-provider.js +271 -0
  192. package/dist/core/qwen-cli-provider.js.map +1 -0
  193. package/dist/core/resolve-config-value.d.ts +17 -0
  194. package/dist/core/resolve-config-value.d.ts.map +1 -0
  195. package/dist/core/resolve-config-value.js +60 -0
  196. package/dist/core/resolve-config-value.js.map +1 -0
  197. package/dist/core/resource-loader.d.ts +195 -0
  198. package/dist/core/resource-loader.d.ts.map +1 -0
  199. package/dist/core/resource-loader.js +820 -0
  200. package/dist/core/resource-loader.js.map +1 -0
  201. package/dist/core/sdk.d.ts +106 -0
  202. package/dist/core/sdk.d.ts.map +1 -0
  203. package/dist/core/sdk.js +460 -0
  204. package/dist/core/sdk.js.map +1 -0
  205. package/dist/core/session-manager.d.ts +323 -0
  206. package/dist/core/session-manager.d.ts.map +1 -0
  207. package/dist/core/session-manager.js +1094 -0
  208. package/dist/core/session-manager.js.map +1 -0
  209. package/dist/core/settings-manager.d.ts +243 -0
  210. package/dist/core/settings-manager.d.ts.map +1 -0
  211. package/dist/core/settings-manager.js +691 -0
  212. package/dist/core/settings-manager.js.map +1 -0
  213. package/dist/core/skills.d.ts +58 -0
  214. package/dist/core/skills.d.ts.map +1 -0
  215. package/dist/core/skills.js +364 -0
  216. package/dist/core/skills.js.map +1 -0
  217. package/dist/core/slash-commands.d.ts +15 -0
  218. package/dist/core/slash-commands.d.ts.map +1 -0
  219. package/dist/core/slash-commands.js +64 -0
  220. package/dist/core/slash-commands.js.map +1 -0
  221. package/dist/core/subagent-runs.d.ts +16 -0
  222. package/dist/core/subagent-runs.d.ts.map +1 -0
  223. package/dist/core/subagent-runs.js +70 -0
  224. package/dist/core/subagent-runs.js.map +1 -0
  225. package/dist/core/subagents.d.ts +45 -0
  226. package/dist/core/subagents.d.ts.map +1 -0
  227. package/dist/core/subagents.js +467 -0
  228. package/dist/core/subagents.js.map +1 -0
  229. package/dist/core/system-prompt.d.ts +28 -0
  230. package/dist/core/system-prompt.d.ts.map +1 -0
  231. package/dist/core/system-prompt.js +196 -0
  232. package/dist/core/system-prompt.js.map +1 -0
  233. package/dist/core/task-plan.d.ts +32 -0
  234. package/dist/core/task-plan.d.ts.map +1 -0
  235. package/dist/core/task-plan.js +155 -0
  236. package/dist/core/task-plan.js.map +1 -0
  237. package/dist/core/timings.d.ts +7 -0
  238. package/dist/core/timings.d.ts.map +1 -0
  239. package/dist/core/timings.js +26 -0
  240. package/dist/core/timings.js.map +1 -0
  241. package/dist/core/tools/bash.d.ts +58 -0
  242. package/dist/core/tools/bash.d.ts.map +1 -0
  243. package/dist/core/tools/bash.js +275 -0
  244. package/dist/core/tools/bash.js.map +1 -0
  245. package/dist/core/tools/edit-diff.d.ts +63 -0
  246. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  247. package/dist/core/tools/edit-diff.js +243 -0
  248. package/dist/core/tools/edit-diff.js.map +1 -0
  249. package/dist/core/tools/edit.d.ts +42 -0
  250. package/dist/core/tools/edit.d.ts.map +1 -0
  251. package/dist/core/tools/edit.js +158 -0
  252. package/dist/core/tools/edit.js.map +1 -0
  253. package/dist/core/tools/find.d.ts +39 -0
  254. package/dist/core/tools/find.d.ts.map +1 -0
  255. package/dist/core/tools/find.js +219 -0
  256. package/dist/core/tools/find.js.map +1 -0
  257. package/dist/core/tools/grep.d.ts +45 -0
  258. package/dist/core/tools/grep.d.ts.map +1 -0
  259. package/dist/core/tools/grep.js +254 -0
  260. package/dist/core/tools/grep.js.map +1 -0
  261. package/dist/core/tools/ignore-filter.d.ts +5 -0
  262. package/dist/core/tools/ignore-filter.d.ts.map +1 -0
  263. package/dist/core/tools/ignore-filter.js +97 -0
  264. package/dist/core/tools/ignore-filter.js.map +1 -0
  265. package/dist/core/tools/index.d.ts +97 -0
  266. package/dist/core/tools/index.d.ts.map +1 -0
  267. package/dist/core/tools/index.js +78 -0
  268. package/dist/core/tools/index.js.map +1 -0
  269. package/dist/core/tools/ls.d.ts +46 -0
  270. package/dist/core/tools/ls.d.ts.map +1 -0
  271. package/dist/core/tools/ls.js +136 -0
  272. package/dist/core/tools/ls.js.map +1 -0
  273. package/dist/core/tools/path-utils.d.ts +8 -0
  274. package/dist/core/tools/path-utils.d.ts.map +1 -0
  275. package/dist/core/tools/path-utils.js +81 -0
  276. package/dist/core/tools/path-utils.js.map +1 -0
  277. package/dist/core/tools/permissions.d.ts +8 -0
  278. package/dist/core/tools/permissions.d.ts.map +1 -0
  279. package/dist/core/tools/permissions.js +2 -0
  280. package/dist/core/tools/permissions.js.map +1 -0
  281. package/dist/core/tools/read.d.ts +39 -0
  282. package/dist/core/tools/read.d.ts.map +1 -0
  283. package/dist/core/tools/read.js +166 -0
  284. package/dist/core/tools/read.js.map +1 -0
  285. package/dist/core/tools/task.d.ts +109 -0
  286. package/dist/core/tools/task.d.ts.map +1 -0
  287. package/dist/core/tools/task.js +1065 -0
  288. package/dist/core/tools/task.js.map +1 -0
  289. package/dist/core/tools/todo.d.ts +42 -0
  290. package/dist/core/tools/todo.d.ts.map +1 -0
  291. package/dist/core/tools/todo.js +159 -0
  292. package/dist/core/tools/todo.js.map +1 -0
  293. package/dist/core/tools/truncate.d.ts +70 -0
  294. package/dist/core/tools/truncate.d.ts.map +1 -0
  295. package/dist/core/tools/truncate.js +205 -0
  296. package/dist/core/tools/truncate.js.map +1 -0
  297. package/dist/core/tools/write.d.ts +32 -0
  298. package/dist/core/tools/write.d.ts.map +1 -0
  299. package/dist/core/tools/write.js +90 -0
  300. package/dist/core/tools/write.js.map +1 -0
  301. package/dist/index.d.ts +30 -0
  302. package/dist/index.d.ts.map +1 -0
  303. package/dist/index.js +45 -0
  304. package/dist/index.js.map +1 -0
  305. package/dist/iosm/agent-verification.d.ts +16 -0
  306. package/dist/iosm/agent-verification.d.ts.map +1 -0
  307. package/dist/iosm/agent-verification.js +138 -0
  308. package/dist/iosm/agent-verification.js.map +1 -0
  309. package/dist/iosm/automation.d.ts +40 -0
  310. package/dist/iosm/automation.d.ts.map +1 -0
  311. package/dist/iosm/automation.js +76 -0
  312. package/dist/iosm/automation.js.map +1 -0
  313. package/dist/iosm/config.d.ts +151 -0
  314. package/dist/iosm/config.d.ts.map +1 -0
  315. package/dist/iosm/config.js +323 -0
  316. package/dist/iosm/config.js.map +1 -0
  317. package/dist/iosm/context-loader.d.ts +12 -0
  318. package/dist/iosm/context-loader.d.ts.map +1 -0
  319. package/dist/iosm/context-loader.js +50 -0
  320. package/dist/iosm/context-loader.js.map +1 -0
  321. package/dist/iosm/cycle.d.ts +51 -0
  322. package/dist/iosm/cycle.d.ts.map +1 -0
  323. package/dist/iosm/cycle.js +861 -0
  324. package/dist/iosm/cycle.js.map +1 -0
  325. package/dist/iosm/guide.d.ts +31 -0
  326. package/dist/iosm/guide.d.ts.map +1 -0
  327. package/dist/iosm/guide.js +101 -0
  328. package/dist/iosm/guide.js.map +1 -0
  329. package/dist/iosm/index.d.ts +12 -0
  330. package/dist/iosm/index.d.ts.map +1 -0
  331. package/dist/iosm/index.js +11 -0
  332. package/dist/iosm/index.js.map +1 -0
  333. package/dist/iosm/init.d.ts +58 -0
  334. package/dist/iosm/init.d.ts.map +1 -0
  335. package/dist/iosm/init.js +1221 -0
  336. package/dist/iosm/init.js.map +1 -0
  337. package/dist/iosm/metrics.d.ts +23 -0
  338. package/dist/iosm/metrics.d.ts.map +1 -0
  339. package/dist/iosm/metrics.js +336 -0
  340. package/dist/iosm/metrics.js.map +1 -0
  341. package/dist/iosm/paths.d.ts +24 -0
  342. package/dist/iosm/paths.d.ts.map +1 -0
  343. package/dist/iosm/paths.js +77 -0
  344. package/dist/iosm/paths.js.map +1 -0
  345. package/dist/iosm/runtime-context.d.ts +20 -0
  346. package/dist/iosm/runtime-context.d.ts.map +1 -0
  347. package/dist/iosm/runtime-context.js +170 -0
  348. package/dist/iosm/runtime-context.js.map +1 -0
  349. package/dist/iosm/types.d.ts +151 -0
  350. package/dist/iosm/types.d.ts.map +1 -0
  351. package/dist/iosm/types.js +3 -0
  352. package/dist/iosm/types.js.map +1 -0
  353. package/dist/main.d.ts +8 -0
  354. package/dist/main.d.ts.map +1 -0
  355. package/dist/main.js +1478 -0
  356. package/dist/main.js.map +1 -0
  357. package/dist/migrations.d.ts +33 -0
  358. package/dist/migrations.d.ts.map +1 -0
  359. package/dist/migrations.js +261 -0
  360. package/dist/migrations.js.map +1 -0
  361. package/dist/modes/index.d.ts +9 -0
  362. package/dist/modes/index.d.ts.map +1 -0
  363. package/dist/modes/index.js +8 -0
  364. package/dist/modes/index.js.map +1 -0
  365. package/dist/modes/interactive/components/armin.d.ts +34 -0
  366. package/dist/modes/interactive/components/armin.d.ts.map +1 -0
  367. package/dist/modes/interactive/components/armin.js +329 -0
  368. package/dist/modes/interactive/components/armin.js.map +1 -0
  369. package/dist/modes/interactive/components/ascii-logo.d.ts +11 -0
  370. package/dist/modes/interactive/components/ascii-logo.d.ts.map +1 -0
  371. package/dist/modes/interactive/components/ascii-logo.js +25 -0
  372. package/dist/modes/interactive/components/ascii-logo.js.map +1 -0
  373. package/dist/modes/interactive/components/assistant-message.d.ts +16 -0
  374. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
  375. package/dist/modes/interactive/components/assistant-message.js +92 -0
  376. package/dist/modes/interactive/components/assistant-message.js.map +1 -0
  377. package/dist/modes/interactive/components/bash-execution.d.ts +36 -0
  378. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
  379. package/dist/modes/interactive/components/bash-execution.js +170 -0
  380. package/dist/modes/interactive/components/bash-execution.js.map +1 -0
  381. package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  382. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
  383. package/dist/modes/interactive/components/bordered-loader.js +48 -0
  384. package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
  385. package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  386. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
  387. package/dist/modes/interactive/components/branch-summary-message.js +42 -0
  388. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
  389. package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  390. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
  391. package/dist/modes/interactive/components/compaction-summary-message.js +43 -0
  392. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
  393. package/dist/modes/interactive/components/config-selector.d.ts +71 -0
  394. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
  395. package/dist/modes/interactive/components/config-selector.js +470 -0
  396. package/dist/modes/interactive/components/config-selector.js.map +1 -0
  397. package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  398. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
  399. package/dist/modes/interactive/components/countdown-timer.js +28 -0
  400. package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
  401. package/dist/modes/interactive/components/custom-editor.d.ts +21 -0
  402. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
  403. package/dist/modes/interactive/components/custom-editor.js +63 -0
  404. package/dist/modes/interactive/components/custom-editor.js.map +1 -0
  405. package/dist/modes/interactive/components/custom-message.d.ts +20 -0
  406. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
  407. package/dist/modes/interactive/components/custom-message.js +74 -0
  408. package/dist/modes/interactive/components/custom-message.js.map +1 -0
  409. package/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  410. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
  411. package/dist/modes/interactive/components/daxnuts.js +138 -0
  412. package/dist/modes/interactive/components/daxnuts.js.map +1 -0
  413. package/dist/modes/interactive/components/decrypt-loader.d.ts +25 -0
  414. package/dist/modes/interactive/components/decrypt-loader.d.ts.map +1 -0
  415. package/dist/modes/interactive/components/decrypt-loader.js +102 -0
  416. package/dist/modes/interactive/components/decrypt-loader.js.map +1 -0
  417. package/dist/modes/interactive/components/diff.d.ts +12 -0
  418. package/dist/modes/interactive/components/diff.d.ts.map +1 -0
  419. package/dist/modes/interactive/components/diff.js +133 -0
  420. package/dist/modes/interactive/components/diff.js.map +1 -0
  421. package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  422. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
  423. package/dist/modes/interactive/components/dynamic-border.js +20 -0
  424. package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
  425. package/dist/modes/interactive/components/extension-editor.d.ts +20 -0
  426. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
  427. package/dist/modes/interactive/components/extension-editor.js +105 -0
  428. package/dist/modes/interactive/components/extension-editor.js.map +1 -0
  429. package/dist/modes/interactive/components/extension-input.d.ts +23 -0
  430. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
  431. package/dist/modes/interactive/components/extension-input.js +55 -0
  432. package/dist/modes/interactive/components/extension-input.js.map +1 -0
  433. package/dist/modes/interactive/components/extension-selector.d.ts +24 -0
  434. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
  435. package/dist/modes/interactive/components/extension-selector.js +71 -0
  436. package/dist/modes/interactive/components/extension-selector.js.map +1 -0
  437. package/dist/modes/interactive/components/footer.d.ts +39 -0
  438. package/dist/modes/interactive/components/footer.d.ts.map +1 -0
  439. package/dist/modes/interactive/components/footer.js +285 -0
  440. package/dist/modes/interactive/components/footer.js.map +1 -0
  441. package/dist/modes/interactive/components/index.d.ts +33 -0
  442. package/dist/modes/interactive/components/index.d.ts.map +1 -0
  443. package/dist/modes/interactive/components/index.js +34 -0
  444. package/dist/modes/interactive/components/index.js.map +1 -0
  445. package/dist/modes/interactive/components/keybinding-hints.d.ts +50 -0
  446. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
  447. package/dist/modes/interactive/components/keybinding-hints.js +85 -0
  448. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
  449. package/dist/modes/interactive/components/login-dialog.d.ts +42 -0
  450. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
  451. package/dist/modes/interactive/components/login-dialog.js +139 -0
  452. package/dist/modes/interactive/components/login-dialog.js.map +1 -0
  453. package/dist/modes/interactive/components/mcp-selector.d.ts +31 -0
  454. package/dist/modes/interactive/components/mcp-selector.d.ts.map +1 -0
  455. package/dist/modes/interactive/components/mcp-selector.js +171 -0
  456. package/dist/modes/interactive/components/mcp-selector.js.map +1 -0
  457. package/dist/modes/interactive/components/model-selector.d.ts +51 -0
  458. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
  459. package/dist/modes/interactive/components/model-selector.js +292 -0
  460. package/dist/modes/interactive/components/model-selector.js.map +1 -0
  461. package/dist/modes/interactive/components/oauth-selector.d.ts +19 -0
  462. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
  463. package/dist/modes/interactive/components/oauth-selector.js +134 -0
  464. package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
  465. package/dist/modes/interactive/components/scoped-models-selector.d.ts +49 -0
  466. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
  467. package/dist/modes/interactive/components/scoped-models-selector.js +271 -0
  468. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
  469. package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  470. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
  471. package/dist/modes/interactive/components/session-selector-search.js +155 -0
  472. package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
  473. package/dist/modes/interactive/components/session-selector.d.ts +95 -0
  474. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
  475. package/dist/modes/interactive/components/session-selector.js +839 -0
  476. package/dist/modes/interactive/components/session-selector.js.map +1 -0
  477. package/dist/modes/interactive/components/settings-selector.d.ts +60 -0
  478. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
  479. package/dist/modes/interactive/components/settings-selector.js +311 -0
  480. package/dist/modes/interactive/components/settings-selector.js.map +1 -0
  481. package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  482. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
  483. package/dist/modes/interactive/components/show-images-selector.js +34 -0
  484. package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
  485. package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  486. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
  487. package/dist/modes/interactive/components/skill-invocation-message.js +45 -0
  488. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
  489. package/dist/modes/interactive/components/subagent-message.d.ts +91 -0
  490. package/dist/modes/interactive/components/subagent-message.d.ts.map +1 -0
  491. package/dist/modes/interactive/components/subagent-message.js +306 -0
  492. package/dist/modes/interactive/components/subagent-message.js.map +1 -0
  493. package/dist/modes/interactive/components/task-plan-message.d.ts +12 -0
  494. package/dist/modes/interactive/components/task-plan-message.d.ts.map +1 -0
  495. package/dist/modes/interactive/components/task-plan-message.js +61 -0
  496. package/dist/modes/interactive/components/task-plan-message.js.map +1 -0
  497. package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  498. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
  499. package/dist/modes/interactive/components/theme-selector.js +44 -0
  500. package/dist/modes/interactive/components/theme-selector.js.map +1 -0
  501. package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  502. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
  503. package/dist/modes/interactive/components/thinking-selector.js +46 -0
  504. package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
  505. package/dist/modes/interactive/components/tool-execution.d.ts +78 -0
  506. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
  507. package/dist/modes/interactive/components/tool-execution.js +880 -0
  508. package/dist/modes/interactive/components/tool-execution.js.map +1 -0
  509. package/dist/modes/interactive/components/tree-selector.d.ts +70 -0
  510. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
  511. package/dist/modes/interactive/components/tree-selector.js +921 -0
  512. package/dist/modes/interactive/components/tree-selector.js.map +1 -0
  513. package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  514. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
  515. package/dist/modes/interactive/components/user-message-selector.js +110 -0
  516. package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
  517. package/dist/modes/interactive/components/user-message.d.ts +9 -0
  518. package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
  519. package/dist/modes/interactive/components/user-message.js +27 -0
  520. package/dist/modes/interactive/components/user-message.js.map +1 -0
  521. package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  522. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
  523. package/dist/modes/interactive/components/visual-truncate.js +33 -0
  524. package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
  525. package/dist/modes/interactive/interactive-mode.d.ts +453 -0
  526. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
  527. package/dist/modes/interactive/interactive-mode.js +8669 -0
  528. package/dist/modes/interactive/interactive-mode.js.map +1 -0
  529. package/dist/modes/interactive/theme/dark.json +85 -0
  530. package/dist/modes/interactive/theme/light.json +84 -0
  531. package/dist/modes/interactive/theme/theme-schema.json +335 -0
  532. package/dist/modes/interactive/theme/theme.d.ts +78 -0
  533. package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
  534. package/dist/modes/interactive/theme/theme.js +944 -0
  535. package/dist/modes/interactive/theme/theme.js.map +1 -0
  536. package/dist/modes/print-mode.d.ts +28 -0
  537. package/dist/modes/print-mode.d.ts.map +1 -0
  538. package/dist/modes/print-mode.js +101 -0
  539. package/dist/modes/print-mode.js.map +1 -0
  540. package/dist/modes/rpc/rpc-client.d.ts +217 -0
  541. package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
  542. package/dist/modes/rpc/rpc-client.js +404 -0
  543. package/dist/modes/rpc/rpc-client.js.map +1 -0
  544. package/dist/modes/rpc/rpc-mode.d.ts +20 -0
  545. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
  546. package/dist/modes/rpc/rpc-mode.js +580 -0
  547. package/dist/modes/rpc/rpc-mode.js.map +1 -0
  548. package/dist/modes/rpc/rpc-types.d.ts +409 -0
  549. package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
  550. package/dist/modes/rpc/rpc-types.js +8 -0
  551. package/dist/modes/rpc/rpc-types.js.map +1 -0
  552. package/dist/utils/changelog.d.ts +21 -0
  553. package/dist/utils/changelog.d.ts.map +1 -0
  554. package/dist/utils/changelog.js +87 -0
  555. package/dist/utils/changelog.js.map +1 -0
  556. package/dist/utils/clipboard-image.d.ts +11 -0
  557. package/dist/utils/clipboard-image.d.ts.map +1 -0
  558. package/dist/utils/clipboard-image.js +162 -0
  559. package/dist/utils/clipboard-image.js.map +1 -0
  560. package/dist/utils/clipboard-native.d.ts +7 -0
  561. package/dist/utils/clipboard-native.d.ts.map +1 -0
  562. package/dist/utils/clipboard-native.js +14 -0
  563. package/dist/utils/clipboard-native.js.map +1 -0
  564. package/dist/utils/clipboard.d.ts +2 -0
  565. package/dist/utils/clipboard.d.ts.map +1 -0
  566. package/dist/utils/clipboard.js +67 -0
  567. package/dist/utils/clipboard.js.map +1 -0
  568. package/dist/utils/frontmatter.d.ts +8 -0
  569. package/dist/utils/frontmatter.d.ts.map +1 -0
  570. package/dist/utils/frontmatter.js +26 -0
  571. package/dist/utils/frontmatter.js.map +1 -0
  572. package/dist/utils/git.d.ts +26 -0
  573. package/dist/utils/git.d.ts.map +1 -0
  574. package/dist/utils/git.js +163 -0
  575. package/dist/utils/git.js.map +1 -0
  576. package/dist/utils/image-convert.d.ts +9 -0
  577. package/dist/utils/image-convert.d.ts.map +1 -0
  578. package/dist/utils/image-convert.js +35 -0
  579. package/dist/utils/image-convert.js.map +1 -0
  580. package/dist/utils/image-resize.d.ts +36 -0
  581. package/dist/utils/image-resize.d.ts.map +1 -0
  582. package/dist/utils/image-resize.js +181 -0
  583. package/dist/utils/image-resize.js.map +1 -0
  584. package/dist/utils/mime.d.ts +2 -0
  585. package/dist/utils/mime.d.ts.map +1 -0
  586. package/dist/utils/mime.js +26 -0
  587. package/dist/utils/mime.js.map +1 -0
  588. package/dist/utils/photon.d.ts +21 -0
  589. package/dist/utils/photon.d.ts.map +1 -0
  590. package/dist/utils/photon.js +121 -0
  591. package/dist/utils/photon.js.map +1 -0
  592. package/dist/utils/shell.d.ts +26 -0
  593. package/dist/utils/shell.d.ts.map +1 -0
  594. package/dist/utils/shell.js +186 -0
  595. package/dist/utils/shell.js.map +1 -0
  596. package/dist/utils/sleep.d.ts +5 -0
  597. package/dist/utils/sleep.d.ts.map +1 -0
  598. package/dist/utils/sleep.js +17 -0
  599. package/dist/utils/sleep.js.map +1 -0
  600. package/dist/utils/tools-manager.d.ts +3 -0
  601. package/dist/utils/tools-manager.d.ts.map +1 -0
  602. package/dist/utils/tools-manager.js +251 -0
  603. package/dist/utils/tools-manager.js.map +1 -0
  604. package/docs/README.md +32 -0
  605. package/docs/cli-reference.md +342 -0
  606. package/docs/configuration.md +301 -0
  607. package/docs/development-and-testing.md +295 -0
  608. package/docs/extensions-packages-themes.md +415 -0
  609. package/docs/getting-started.md +246 -0
  610. package/docs/interactive-mode.md +272 -0
  611. package/docs/iosm-init-and-cycles.md +355 -0
  612. package/docs/orchestration-and-subagents.md +273 -0
  613. package/docs/rpc-json-sdk.md +353 -0
  614. package/docs/sessions-traces-export.md +260 -0
  615. package/examples/README.md +120 -0
  616. package/examples/extensions/README.md +306 -0
  617. package/examples/extensions/antigravity-image-gen.ts +415 -0
  618. package/examples/extensions/auto-commit-on-exit.ts +49 -0
  619. package/examples/extensions/bash-spawn-hook.ts +30 -0
  620. package/examples/extensions/bookmark.ts +50 -0
  621. package/examples/extensions/built-in-tool-renderer.ts +246 -0
  622. package/examples/extensions/claude-rules.ts +86 -0
  623. package/examples/extensions/commands.ts +72 -0
  624. package/examples/extensions/confirm-destructive.ts +59 -0
  625. package/examples/extensions/custom-compaction.ts +114 -0
  626. package/examples/extensions/custom-footer.ts +64 -0
  627. package/examples/extensions/custom-header.ts +73 -0
  628. package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
  629. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  630. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  631. package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
  632. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  633. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  634. package/examples/extensions/custom-provider-qwen-cli/index.ts +345 -0
  635. package/examples/extensions/custom-provider-qwen-cli/package.json +16 -0
  636. package/examples/extensions/dirty-repo-guard.ts +56 -0
  637. package/examples/extensions/doom-overlay/README.md +46 -0
  638. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
  639. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  640. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  641. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  642. package/examples/extensions/doom-overlay/doom-component.ts +132 -0
  643. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  644. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  645. package/examples/extensions/doom-overlay/index.ts +74 -0
  646. package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
  647. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  648. package/examples/extensions/dynamic-resources/dynamic.json +79 -0
  649. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  650. package/examples/extensions/dynamic-resources/index.ts +15 -0
  651. package/examples/extensions/dynamic-tools.ts +74 -0
  652. package/examples/extensions/event-bus.ts +43 -0
  653. package/examples/extensions/file-trigger.ts +41 -0
  654. package/examples/extensions/git-checkpoint.ts +53 -0
  655. package/examples/extensions/handoff.ts +150 -0
  656. package/examples/extensions/hello.ts +25 -0
  657. package/examples/extensions/inline-bash.ts +94 -0
  658. package/examples/extensions/input-transform.ts +43 -0
  659. package/examples/extensions/interactive-shell.ts +196 -0
  660. package/examples/extensions/mac-system-theme.ts +47 -0
  661. package/examples/extensions/message-renderer.ts +59 -0
  662. package/examples/extensions/minimal-mode.ts +426 -0
  663. package/examples/extensions/modal-editor.ts +85 -0
  664. package/examples/extensions/model-status.ts +31 -0
  665. package/examples/extensions/notify.ts +55 -0
  666. package/examples/extensions/overlay-qa-tests.ts +881 -0
  667. package/examples/extensions/overlay-test.ts +150 -0
  668. package/examples/extensions/permission-gate.ts +34 -0
  669. package/examples/extensions/pirate.ts +47 -0
  670. package/examples/extensions/plan-mode/README.md +65 -0
  671. package/examples/extensions/plan-mode/index.ts +340 -0
  672. package/examples/extensions/plan-mode/utils.ts +168 -0
  673. package/examples/extensions/preset.ts +398 -0
  674. package/examples/extensions/protected-paths.ts +30 -0
  675. package/examples/extensions/qna.ts +119 -0
  676. package/examples/extensions/question.ts +264 -0
  677. package/examples/extensions/questionnaire.ts +427 -0
  678. package/examples/extensions/rainbow-editor.ts +88 -0
  679. package/examples/extensions/reload-runtime.ts +37 -0
  680. package/examples/extensions/rpc-demo.ts +124 -0
  681. package/examples/extensions/sandbox/index.ts +318 -0
  682. package/examples/extensions/sandbox/package-lock.json +92 -0
  683. package/examples/extensions/sandbox/package.json +19 -0
  684. package/examples/extensions/send-user-message.ts +97 -0
  685. package/examples/extensions/session-name.ts +27 -0
  686. package/examples/extensions/shutdown-command.ts +63 -0
  687. package/examples/extensions/snake.ts +343 -0
  688. package/examples/extensions/space-invaders.ts +560 -0
  689. package/examples/extensions/ssh.ts +220 -0
  690. package/examples/extensions/status-line.ts +40 -0
  691. package/examples/extensions/subagent/README.md +172 -0
  692. package/examples/extensions/subagent/agents/planner.md +37 -0
  693. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  694. package/examples/extensions/subagent/agents/scout.md +50 -0
  695. package/examples/extensions/subagent/agents/worker.md +24 -0
  696. package/examples/extensions/subagent/agents.ts +126 -0
  697. package/examples/extensions/subagent/index.ts +964 -0
  698. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  699. package/examples/extensions/subagent/prompts/implement.md +10 -0
  700. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  701. package/examples/extensions/summarize.ts +195 -0
  702. package/examples/extensions/system-prompt-header.ts +17 -0
  703. package/examples/extensions/timed-confirm.ts +70 -0
  704. package/examples/extensions/titlebar-spinner.ts +58 -0
  705. package/examples/extensions/todo.ts +299 -0
  706. package/examples/extensions/tool-override.ts +143 -0
  707. package/examples/extensions/tools.ts +146 -0
  708. package/examples/extensions/trigger-compact.ts +40 -0
  709. package/examples/extensions/truncated-tool.ts +192 -0
  710. package/examples/extensions/widget-placement.ts +17 -0
  711. package/examples/extensions/with-deps/index.ts +36 -0
  712. package/examples/extensions/with-deps/package-lock.json +31 -0
  713. package/examples/extensions/with-deps/package.json +22 -0
  714. package/examples/rpc-extension-ui.ts +632 -0
  715. package/examples/sdk/01-minimal.ts +22 -0
  716. package/examples/sdk/02-custom-model.ts +49 -0
  717. package/examples/sdk/03-custom-prompt.ts +55 -0
  718. package/examples/sdk/04-skills.ts +46 -0
  719. package/examples/sdk/05-tools.ts +56 -0
  720. package/examples/sdk/06-extensions.ts +88 -0
  721. package/examples/sdk/07-context-files.ts +40 -0
  722. package/examples/sdk/08-prompt-templates.ts +47 -0
  723. package/examples/sdk/09-api-keys-and-oauth.ts +48 -0
  724. package/examples/sdk/10-settings.ts +51 -0
  725. package/examples/sdk/11-sessions.ts +48 -0
  726. package/examples/sdk/12-full-control.ts +82 -0
  727. package/examples/sdk/README.md +337 -0
  728. package/examples/tsconfig.json +3 -0
  729. package/package.json +107 -0
@@ -0,0 +1,251 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync } from "fs";
2
+ import { homedir } from "os";
3
+ import { basename, isAbsolute, join, resolve, sep } from "path";
4
+ import { CONFIG_DIR_NAME, getPromptsDir } from "../config.js";
5
+ import { parseFrontmatter } from "../utils/frontmatter.js";
6
+ /**
7
+ * Parse command arguments respecting quoted strings (bash-style)
8
+ * Returns array of arguments
9
+ */
10
+ export function parseCommandArgs(argsString) {
11
+ const args = [];
12
+ let current = "";
13
+ let inQuote = null;
14
+ for (let i = 0; i < argsString.length; i++) {
15
+ const char = argsString[i];
16
+ if (inQuote) {
17
+ if (char === inQuote) {
18
+ inQuote = null;
19
+ }
20
+ else {
21
+ current += char;
22
+ }
23
+ }
24
+ else if (char === '"' || char === "'") {
25
+ inQuote = char;
26
+ }
27
+ else if (char === " " || char === "\t") {
28
+ if (current) {
29
+ args.push(current);
30
+ current = "";
31
+ }
32
+ }
33
+ else {
34
+ current += char;
35
+ }
36
+ }
37
+ if (current) {
38
+ args.push(current);
39
+ }
40
+ return args;
41
+ }
42
+ /**
43
+ * Substitute argument placeholders in template content
44
+ * Supports:
45
+ * - $1, $2, ... for positional args
46
+ * - $@ and $ARGUMENTS for all args
47
+ * - ${@:N} for args from Nth onwards (bash-style slicing)
48
+ * - ${@:N:L} for L args starting from Nth
49
+ *
50
+ * Note: Replacement happens on the template string only. Argument values
51
+ * containing patterns like $1, $@, or $ARGUMENTS are NOT recursively substituted.
52
+ */
53
+ export function substituteArgs(content, args) {
54
+ let result = content;
55
+ // Replace $1, $2, etc. with positional args FIRST (before wildcards)
56
+ // This prevents wildcard replacement values containing $<digit> patterns from being re-substituted
57
+ result = result.replace(/\$(\d+)/g, (_, num) => {
58
+ const index = parseInt(num, 10) - 1;
59
+ return args[index] ?? "";
60
+ });
61
+ // Replace ${@:start} or ${@:start:length} with sliced args (bash-style)
62
+ // Process BEFORE simple $@ to avoid conflicts
63
+ result = result.replace(/\$\{@:(\d+)(?::(\d+))?\}/g, (_, startStr, lengthStr) => {
64
+ let start = parseInt(startStr, 10) - 1; // Convert to 0-indexed (user provides 1-indexed)
65
+ // Treat 0 as 1 (bash convention: args start at 1)
66
+ if (start < 0)
67
+ start = 0;
68
+ if (lengthStr) {
69
+ const length = parseInt(lengthStr, 10);
70
+ return args.slice(start, start + length).join(" ");
71
+ }
72
+ return args.slice(start).join(" ");
73
+ });
74
+ // Pre-compute all args joined (optimization)
75
+ const allArgs = args.join(" ");
76
+ // Replace $ARGUMENTS with all args joined (new syntax, aligns with Claude, Codex, OpenCode)
77
+ result = result.replace(/\$ARGUMENTS/g, allArgs);
78
+ // Replace $@ with all args joined (existing syntax)
79
+ result = result.replace(/\$@/g, allArgs);
80
+ return result;
81
+ }
82
+ function loadTemplateFromFile(filePath, source, sourceLabel) {
83
+ try {
84
+ const rawContent = readFileSync(filePath, "utf-8");
85
+ const { frontmatter, body } = parseFrontmatter(rawContent);
86
+ const name = basename(filePath).replace(/\.md$/, "");
87
+ // Get description from frontmatter or first non-empty line
88
+ let description = frontmatter.description || "";
89
+ if (!description) {
90
+ const firstLine = body.split("\n").find((line) => line.trim());
91
+ if (firstLine) {
92
+ // Truncate if too long
93
+ description = firstLine.slice(0, 60);
94
+ if (firstLine.length > 60)
95
+ description += "...";
96
+ }
97
+ }
98
+ // Append source to description
99
+ description = description ? `${description} ${sourceLabel}` : sourceLabel;
100
+ return {
101
+ name,
102
+ description,
103
+ content: body,
104
+ source,
105
+ filePath,
106
+ };
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ /**
113
+ * Scan a directory for .md files (non-recursive) and load them as prompt templates.
114
+ */
115
+ function loadTemplatesFromDir(dir, source, sourceLabel) {
116
+ const templates = [];
117
+ if (!existsSync(dir)) {
118
+ return templates;
119
+ }
120
+ try {
121
+ const entries = readdirSync(dir, { withFileTypes: true });
122
+ for (const entry of entries) {
123
+ const fullPath = join(dir, entry.name);
124
+ // For symlinks, check if they point to a file
125
+ let isFile = entry.isFile();
126
+ if (entry.isSymbolicLink()) {
127
+ try {
128
+ const stats = statSync(fullPath);
129
+ isFile = stats.isFile();
130
+ }
131
+ catch {
132
+ // Broken symlink, skip it
133
+ continue;
134
+ }
135
+ }
136
+ if (isFile && entry.name.endsWith(".md")) {
137
+ const template = loadTemplateFromFile(fullPath, source, sourceLabel);
138
+ if (template) {
139
+ templates.push(template);
140
+ }
141
+ }
142
+ }
143
+ }
144
+ catch {
145
+ return templates;
146
+ }
147
+ return templates;
148
+ }
149
+ function normalizePath(input) {
150
+ const trimmed = input.trim();
151
+ if (trimmed === "~")
152
+ return homedir();
153
+ if (trimmed.startsWith("~/"))
154
+ return join(homedir(), trimmed.slice(2));
155
+ if (trimmed.startsWith("~"))
156
+ return join(homedir(), trimmed.slice(1));
157
+ return trimmed;
158
+ }
159
+ function resolvePromptPath(p, cwd) {
160
+ const normalized = normalizePath(p);
161
+ return isAbsolute(normalized) ? normalized : resolve(cwd, normalized);
162
+ }
163
+ function buildPathSourceLabel(p) {
164
+ const base = basename(p).replace(/\.md$/, "") || "path";
165
+ return `(path:${base})`;
166
+ }
167
+ /**
168
+ * Load all prompt templates from:
169
+ * 1. Global: agentDir/prompts/
170
+ * 2. Project: cwd/{CONFIG_DIR_NAME}/prompts/
171
+ * 3. Explicit prompt paths
172
+ */
173
+ export function loadPromptTemplates(options = {}) {
174
+ const resolvedCwd = options.cwd ?? process.cwd();
175
+ const resolvedAgentDir = options.agentDir ?? getPromptsDir();
176
+ const promptPaths = options.promptPaths ?? [];
177
+ const includeDefaults = options.includeDefaults ?? true;
178
+ const templates = [];
179
+ if (includeDefaults) {
180
+ // 1. Load global templates from agentDir/prompts/
181
+ // Note: if agentDir is provided, it should be the agent dir, not the prompts dir
182
+ const globalPromptsDir = options.agentDir ? join(options.agentDir, "prompts") : resolvedAgentDir;
183
+ templates.push(...loadTemplatesFromDir(globalPromptsDir, "user", "(user)"));
184
+ // 2. Load project templates from cwd/{CONFIG_DIR_NAME}/prompts/
185
+ const projectPromptsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, "prompts");
186
+ templates.push(...loadTemplatesFromDir(projectPromptsDir, "project", "(project)"));
187
+ }
188
+ const userPromptsDir = options.agentDir ? join(options.agentDir, "prompts") : resolvedAgentDir;
189
+ const projectPromptsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, "prompts");
190
+ const isUnderPath = (target, root) => {
191
+ const normalizedRoot = resolve(root);
192
+ if (target === normalizedRoot) {
193
+ return true;
194
+ }
195
+ const prefix = normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`;
196
+ return target.startsWith(prefix);
197
+ };
198
+ const getSourceInfo = (resolvedPath) => {
199
+ if (!includeDefaults) {
200
+ if (isUnderPath(resolvedPath, userPromptsDir)) {
201
+ return { source: "user", label: "(user)" };
202
+ }
203
+ if (isUnderPath(resolvedPath, projectPromptsDir)) {
204
+ return { source: "project", label: "(project)" };
205
+ }
206
+ }
207
+ return { source: "path", label: buildPathSourceLabel(resolvedPath) };
208
+ };
209
+ // 3. Load explicit prompt paths
210
+ for (const rawPath of promptPaths) {
211
+ const resolvedPath = resolvePromptPath(rawPath, resolvedCwd);
212
+ if (!existsSync(resolvedPath)) {
213
+ continue;
214
+ }
215
+ try {
216
+ const stats = statSync(resolvedPath);
217
+ const { source, label } = getSourceInfo(resolvedPath);
218
+ if (stats.isDirectory()) {
219
+ templates.push(...loadTemplatesFromDir(resolvedPath, source, label));
220
+ }
221
+ else if (stats.isFile() && resolvedPath.endsWith(".md")) {
222
+ const template = loadTemplateFromFile(resolvedPath, source, label);
223
+ if (template) {
224
+ templates.push(template);
225
+ }
226
+ }
227
+ }
228
+ catch {
229
+ // Ignore read failures
230
+ }
231
+ }
232
+ return templates;
233
+ }
234
+ /**
235
+ * Expand a prompt template if it matches a template name.
236
+ * Returns the expanded content or the original text if not a template.
237
+ */
238
+ export function expandPromptTemplate(text, templates) {
239
+ if (!text.startsWith("/"))
240
+ return text;
241
+ const spaceIndex = text.indexOf(" ");
242
+ const templateName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);
243
+ const argsString = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1);
244
+ const template = templates.find((t) => t.name === templateName);
245
+ if (template) {
246
+ const args = parseCommandArgs(argsString);
247
+ return substituteArgs(template.content, args);
248
+ }
249
+ return text;
250
+ }
251
+ //# sourceMappingURL=prompt-templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-templates.js","sourceRoot":"","sources":["../../src/core/prompt-templates.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync, readFileSync, statSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { basename, isAbsolute, join, resolve, sep } from \"path\";\nimport { CONFIG_DIR_NAME, getPromptsDir } from \"../config.js\";\nimport { parseFrontmatter } from \"../utils/frontmatter.js\";\n\n/**\n * Represents a prompt template loaded from a markdown file\n */\nexport interface PromptTemplate {\n\tname: string;\n\tdescription: string;\n\tcontent: string;\n\tsource: string; // \"user\", \"project\", or \"path\"\n\tfilePath: string; // Absolute path to the template file\n}\n\n/**\n * Parse command arguments respecting quoted strings (bash-style)\n * Returns array of arguments\n */\nexport function parseCommandArgs(argsString: string): string[] {\n\tconst args: string[] = [];\n\tlet current = \"\";\n\tlet inQuote: string | null = null;\n\n\tfor (let i = 0; i < argsString.length; i++) {\n\t\tconst char = argsString[i];\n\n\t\tif (inQuote) {\n\t\t\tif (char === inQuote) {\n\t\t\t\tinQuote = null;\n\t\t\t} else {\n\t\t\t\tcurrent += char;\n\t\t\t}\n\t\t} else if (char === '\"' || char === \"'\") {\n\t\t\tinQuote = char;\n\t\t} else if (char === \" \" || char === \"\\t\") {\n\t\t\tif (current) {\n\t\t\t\targs.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t} else {\n\t\t\tcurrent += char;\n\t\t}\n\t}\n\n\tif (current) {\n\t\targs.push(current);\n\t}\n\n\treturn args;\n}\n\n/**\n * Substitute argument placeholders in template content\n * Supports:\n * - $1, $2, ... for positional args\n * - $@ and $ARGUMENTS for all args\n * - ${@:N} for args from Nth onwards (bash-style slicing)\n * - ${@:N:L} for L args starting from Nth\n *\n * Note: Replacement happens on the template string only. Argument values\n * containing patterns like $1, $@, or $ARGUMENTS are NOT recursively substituted.\n */\nexport function substituteArgs(content: string, args: string[]): string {\n\tlet result = content;\n\n\t// Replace $1, $2, etc. with positional args FIRST (before wildcards)\n\t// This prevents wildcard replacement values containing $<digit> patterns from being re-substituted\n\tresult = result.replace(/\\$(\\d+)/g, (_, num) => {\n\t\tconst index = parseInt(num, 10) - 1;\n\t\treturn args[index] ?? \"\";\n\t});\n\n\t// Replace ${@:start} or ${@:start:length} with sliced args (bash-style)\n\t// Process BEFORE simple $@ to avoid conflicts\n\tresult = result.replace(/\\$\\{@:(\\d+)(?::(\\d+))?\\}/g, (_, startStr, lengthStr) => {\n\t\tlet start = parseInt(startStr, 10) - 1; // Convert to 0-indexed (user provides 1-indexed)\n\t\t// Treat 0 as 1 (bash convention: args start at 1)\n\t\tif (start < 0) start = 0;\n\n\t\tif (lengthStr) {\n\t\t\tconst length = parseInt(lengthStr, 10);\n\t\t\treturn args.slice(start, start + length).join(\" \");\n\t\t}\n\t\treturn args.slice(start).join(\" \");\n\t});\n\n\t// Pre-compute all args joined (optimization)\n\tconst allArgs = args.join(\" \");\n\n\t// Replace $ARGUMENTS with all args joined (new syntax, aligns with Claude, Codex, OpenCode)\n\tresult = result.replace(/\\$ARGUMENTS/g, allArgs);\n\n\t// Replace $@ with all args joined (existing syntax)\n\tresult = result.replace(/\\$@/g, allArgs);\n\n\treturn result;\n}\n\nfunction loadTemplateFromFile(filePath: string, source: string, sourceLabel: string): PromptTemplate | null {\n\ttry {\n\t\tconst rawContent = readFileSync(filePath, \"utf-8\");\n\t\tconst { frontmatter, body } = parseFrontmatter<Record<string, string>>(rawContent);\n\n\t\tconst name = basename(filePath).replace(/\\.md$/, \"\");\n\n\t\t// Get description from frontmatter or first non-empty line\n\t\tlet description = frontmatter.description || \"\";\n\t\tif (!description) {\n\t\t\tconst firstLine = body.split(\"\\n\").find((line) => line.trim());\n\t\t\tif (firstLine) {\n\t\t\t\t// Truncate if too long\n\t\t\t\tdescription = firstLine.slice(0, 60);\n\t\t\t\tif (firstLine.length > 60) description += \"...\";\n\t\t\t}\n\t\t}\n\n\t\t// Append source to description\n\t\tdescription = description ? `${description} ${sourceLabel}` : sourceLabel;\n\n\t\treturn {\n\t\t\tname,\n\t\t\tdescription,\n\t\t\tcontent: body,\n\t\t\tsource,\n\t\t\tfilePath,\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Scan a directory for .md files (non-recursive) and load them as prompt templates.\n */\nfunction loadTemplatesFromDir(dir: string, source: string, sourceLabel: string): PromptTemplate[] {\n\tconst templates: PromptTemplate[] = [];\n\n\tif (!existsSync(dir)) {\n\t\treturn templates;\n\t}\n\n\ttry {\n\t\tconst entries = readdirSync(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\t// For symlinks, check if they point to a file\n\t\t\tlet isFile = entry.isFile();\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tconst stats = statSync(fullPath);\n\t\t\t\t\tisFile = stats.isFile();\n\t\t\t\t} catch {\n\t\t\t\t\t// Broken symlink, skip it\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isFile && entry.name.endsWith(\".md\")) {\n\t\t\t\tconst template = loadTemplateFromFile(fullPath, source, sourceLabel);\n\t\t\t\tif (template) {\n\t\t\t\t\ttemplates.push(template);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\treturn templates;\n\t}\n\n\treturn templates;\n}\n\nexport interface LoadPromptTemplatesOptions {\n\t/** Working directory for project-local templates. Default: process.cwd() */\n\tcwd?: string;\n\t/** Agent config directory for global templates. Default: from getPromptsDir() */\n\tagentDir?: string;\n\t/** Explicit prompt template paths (files or directories) */\n\tpromptPaths?: string[];\n\t/** Include default prompt directories. Default: true */\n\tincludeDefaults?: boolean;\n}\n\nfunction normalizePath(input: string): string {\n\tconst trimmed = input.trim();\n\tif (trimmed === \"~\") return homedir();\n\tif (trimmed.startsWith(\"~/\")) return join(homedir(), trimmed.slice(2));\n\tif (trimmed.startsWith(\"~\")) return join(homedir(), trimmed.slice(1));\n\treturn trimmed;\n}\n\nfunction resolvePromptPath(p: string, cwd: string): string {\n\tconst normalized = normalizePath(p);\n\treturn isAbsolute(normalized) ? normalized : resolve(cwd, normalized);\n}\n\nfunction buildPathSourceLabel(p: string): string {\n\tconst base = basename(p).replace(/\\.md$/, \"\") || \"path\";\n\treturn `(path:${base})`;\n}\n\n/**\n * Load all prompt templates from:\n * 1. Global: agentDir/prompts/\n * 2. Project: cwd/{CONFIG_DIR_NAME}/prompts/\n * 3. Explicit prompt paths\n */\nexport function loadPromptTemplates(options: LoadPromptTemplatesOptions = {}): PromptTemplate[] {\n\tconst resolvedCwd = options.cwd ?? process.cwd();\n\tconst resolvedAgentDir = options.agentDir ?? getPromptsDir();\n\tconst promptPaths = options.promptPaths ?? [];\n\tconst includeDefaults = options.includeDefaults ?? true;\n\n\tconst templates: PromptTemplate[] = [];\n\n\tif (includeDefaults) {\n\t\t// 1. Load global templates from agentDir/prompts/\n\t\t// Note: if agentDir is provided, it should be the agent dir, not the prompts dir\n\t\tconst globalPromptsDir = options.agentDir ? join(options.agentDir, \"prompts\") : resolvedAgentDir;\n\t\ttemplates.push(...loadTemplatesFromDir(globalPromptsDir, \"user\", \"(user)\"));\n\n\t\t// 2. Load project templates from cwd/{CONFIG_DIR_NAME}/prompts/\n\t\tconst projectPromptsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, \"prompts\");\n\t\ttemplates.push(...loadTemplatesFromDir(projectPromptsDir, \"project\", \"(project)\"));\n\t}\n\n\tconst userPromptsDir = options.agentDir ? join(options.agentDir, \"prompts\") : resolvedAgentDir;\n\tconst projectPromptsDir = resolve(resolvedCwd, CONFIG_DIR_NAME, \"prompts\");\n\n\tconst isUnderPath = (target: string, root: string): boolean => {\n\t\tconst normalizedRoot = resolve(root);\n\t\tif (target === normalizedRoot) {\n\t\t\treturn true;\n\t\t}\n\t\tconst prefix = normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`;\n\t\treturn target.startsWith(prefix);\n\t};\n\n\tconst getSourceInfo = (resolvedPath: string): { source: string; label: string } => {\n\t\tif (!includeDefaults) {\n\t\t\tif (isUnderPath(resolvedPath, userPromptsDir)) {\n\t\t\t\treturn { source: \"user\", label: \"(user)\" };\n\t\t\t}\n\t\t\tif (isUnderPath(resolvedPath, projectPromptsDir)) {\n\t\t\t\treturn { source: \"project\", label: \"(project)\" };\n\t\t\t}\n\t\t}\n\t\treturn { source: \"path\", label: buildPathSourceLabel(resolvedPath) };\n\t};\n\n\t// 3. Load explicit prompt paths\n\tfor (const rawPath of promptPaths) {\n\t\tconst resolvedPath = resolvePromptPath(rawPath, resolvedCwd);\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stats = statSync(resolvedPath);\n\t\t\tconst { source, label } = getSourceInfo(resolvedPath);\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\ttemplates.push(...loadTemplatesFromDir(resolvedPath, source, label));\n\t\t\t} else if (stats.isFile() && resolvedPath.endsWith(\".md\")) {\n\t\t\t\tconst template = loadTemplateFromFile(resolvedPath, source, label);\n\t\t\t\tif (template) {\n\t\t\t\t\ttemplates.push(template);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read failures\n\t\t}\n\t}\n\n\treturn templates;\n}\n\n/**\n * Expand a prompt template if it matches a template name.\n * Returns the expanded content or the original text if not a template.\n */\nexport function expandPromptTemplate(text: string, templates: PromptTemplate[]): string {\n\tif (!text.startsWith(\"/\")) return text;\n\n\tconst spaceIndex = text.indexOf(\" \");\n\tconst templateName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex);\n\tconst argsString = spaceIndex === -1 ? \"\" : text.slice(spaceIndex + 1);\n\n\tconst template = templates.find((t) => t.name === templateName);\n\tif (template) {\n\t\tconst args = parseCommandArgs(argsString);\n\t\treturn substituteArgs(template.content, args);\n\t}\n\n\treturn text;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Built-in Qwen CLI provider integration.
3
+ *
4
+ * Implements OAuth device authorization (PKCE) against chat.qwen.ai
5
+ * and exposes OpenAI-compatible Qwen coding models in the model registry.
6
+ */
7
+ import type { ProviderConfigInput } from "./model-registry.js";
8
+ export declare const QWEN_CLI_PROVIDER_ID = "qwen-cli";
9
+ export declare function createQwenCliProviderConfig(): ProviderConfigInput;
10
+ //# sourceMappingURL=qwen-cli-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qwen-cli-provider.d.ts","sourceRoot":"","sources":["../../src/core/qwen-cli-provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAiT/C,wBAAgB,2BAA2B,IAAI,mBAAmB,CA6CjE"}
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Built-in Qwen CLI provider integration.
3
+ *
4
+ * Implements OAuth device authorization (PKCE) against chat.qwen.ai
5
+ * and exposes OpenAI-compatible Qwen coding models in the model registry.
6
+ */
7
+ import { createHash, randomBytes, randomUUID } from "node:crypto";
8
+ export const QWEN_CLI_PROVIDER_ID = "qwen-cli";
9
+ const QWEN_DEVICE_CODE_ENDPOINT = "https://chat.qwen.ai/api/v1/oauth2/device/code";
10
+ const QWEN_TOKEN_ENDPOINT = "https://chat.qwen.ai/api/v1/oauth2/token";
11
+ const QWEN_CLIENT_ID = "f0304373b74a44d2b584a3fb70ca9e56";
12
+ const QWEN_SCOPE = "openid profile email model.completion";
13
+ const QWEN_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
14
+ const QWEN_DEFAULT_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1";
15
+ const QWEN_DEFAULT_POLL_INTERVAL_MS = 2000;
16
+ function objectToUrlEncoded(data) {
17
+ return Object.entries(data)
18
+ .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
19
+ .join("&");
20
+ }
21
+ function generatePKCEPair() {
22
+ const verifier = randomBytes(32).toString("base64url");
23
+ const challenge = createHash("sha256").update(verifier).digest("base64url");
24
+ return { verifier, challenge };
25
+ }
26
+ function isAbortError(error) {
27
+ if (!(error instanceof Error))
28
+ return false;
29
+ return error.name === "AbortError" || error.message === "Login cancelled";
30
+ }
31
+ function throwIfAborted(signal) {
32
+ if (signal?.aborted) {
33
+ throw new Error("Login cancelled");
34
+ }
35
+ }
36
+ async function abortableSleep(ms, signal) {
37
+ return new Promise((resolve, reject) => {
38
+ if (signal?.aborted) {
39
+ reject(new Error("Login cancelled"));
40
+ return;
41
+ }
42
+ const timeout = setTimeout(() => {
43
+ cleanup();
44
+ resolve();
45
+ }, ms);
46
+ const onAbort = () => {
47
+ clearTimeout(timeout);
48
+ cleanup();
49
+ reject(new Error("Login cancelled"));
50
+ };
51
+ const cleanup = () => {
52
+ signal?.removeEventListener("abort", onAbort);
53
+ };
54
+ signal?.addEventListener("abort", onAbort, { once: true });
55
+ });
56
+ }
57
+ function parseJsonResponse(text) {
58
+ if (!text)
59
+ return undefined;
60
+ try {
61
+ return JSON.parse(text);
62
+ }
63
+ catch {
64
+ return undefined;
65
+ }
66
+ }
67
+ function errorDetails(error, description) {
68
+ if (error && description)
69
+ return `${error}: ${description}`;
70
+ if (error)
71
+ return error;
72
+ return description || "unknown error";
73
+ }
74
+ async function startDeviceFlow(signal) {
75
+ throwIfAborted(signal);
76
+ const { verifier, challenge } = generatePKCEPair();
77
+ const response = await fetch(QWEN_DEVICE_CODE_ENDPOINT, {
78
+ method: "POST",
79
+ headers: {
80
+ "Content-Type": "application/x-www-form-urlencoded",
81
+ Accept: "application/json",
82
+ "x-request-id": randomUUID(),
83
+ },
84
+ body: objectToUrlEncoded({
85
+ client_id: QWEN_CLIENT_ID,
86
+ scope: QWEN_SCOPE,
87
+ code_challenge: challenge,
88
+ code_challenge_method: "S256",
89
+ }),
90
+ signal,
91
+ });
92
+ const responseText = await response.text();
93
+ const data = parseJsonResponse(responseText);
94
+ if (!response.ok) {
95
+ throw new Error(`Qwen device authorization failed (${response.status} ${response.statusText}): ${errorDetails(data?.error, data?.error_description || responseText)}`);
96
+ }
97
+ if (!data?.device_code || !data.user_code || !data.verification_uri || !data.expires_in) {
98
+ throw new Error("Qwen device authorization failed: invalid response from server");
99
+ }
100
+ return { deviceCode: data, verifier };
101
+ }
102
+ async function pollForToken(deviceCode, verifier, intervalSeconds, expiresIn, signal) {
103
+ let intervalMs = typeof intervalSeconds === "number" && Number.isFinite(intervalSeconds) && intervalSeconds > 0
104
+ ? Math.max(1000, Math.floor(intervalSeconds * 1000))
105
+ : QWEN_DEFAULT_POLL_INTERVAL_MS;
106
+ const deadline = Date.now() + expiresIn * 1000;
107
+ while (Date.now() < deadline) {
108
+ throwIfAborted(signal);
109
+ let response;
110
+ try {
111
+ response = await fetch(QWEN_TOKEN_ENDPOINT, {
112
+ method: "POST",
113
+ headers: {
114
+ "Content-Type": "application/x-www-form-urlencoded",
115
+ Accept: "application/json",
116
+ },
117
+ body: objectToUrlEncoded({
118
+ grant_type: QWEN_GRANT_TYPE,
119
+ client_id: QWEN_CLIENT_ID,
120
+ device_code: deviceCode,
121
+ code_verifier: verifier,
122
+ }),
123
+ signal,
124
+ });
125
+ }
126
+ catch (error) {
127
+ if (isAbortError(error)) {
128
+ throw new Error("Login cancelled");
129
+ }
130
+ throw error;
131
+ }
132
+ const responseText = await response.text();
133
+ const data = parseJsonResponse(responseText);
134
+ const error = data?.error;
135
+ const description = data?.error_description;
136
+ if (response.ok && data?.access_token) {
137
+ return data;
138
+ }
139
+ // OAuth RFC 8628 polling states
140
+ if (error === "authorization_pending") {
141
+ await abortableSleep(intervalMs, signal);
142
+ continue;
143
+ }
144
+ if (error === "slow_down" || response.status === 429) {
145
+ intervalMs = Math.min(intervalMs + 5000, 10000);
146
+ await abortableSleep(intervalMs, signal);
147
+ continue;
148
+ }
149
+ if (error === "access_denied") {
150
+ throw new Error("Qwen authorization denied by user");
151
+ }
152
+ if (error === "expired_token") {
153
+ throw new Error("Qwen device code expired. Please run /login again");
154
+ }
155
+ if (!response.ok) {
156
+ throw new Error(`Qwen token request failed (${response.status} ${response.statusText}): ${errorDetails(error, description || responseText)}`);
157
+ }
158
+ throw new Error(`Qwen token request failed: ${errorDetails(error, description || responseText)}`);
159
+ }
160
+ throw new Error("Qwen authentication timed out. Please run /login again");
161
+ }
162
+ async function loginQwen(callbacks) {
163
+ callbacks.onProgress?.("Requesting Qwen device authorization...");
164
+ const { deviceCode, verifier } = await startDeviceFlow(callbacks.signal);
165
+ const authUrl = deviceCode.verification_uri_complete || deviceCode.verification_uri;
166
+ const instructions = deviceCode.verification_uri_complete
167
+ ? "Open this URL and approve access in your browser"
168
+ : `Open this URL and enter code: ${deviceCode.user_code}`;
169
+ callbacks.onAuth({ url: authUrl, instructions });
170
+ callbacks.onProgress?.("Waiting for Qwen authorization...");
171
+ const token = await pollForToken(deviceCode.device_code, verifier, deviceCode.interval, deviceCode.expires_in, callbacks.signal);
172
+ if (!token.access_token || !token.expires_in) {
173
+ throw new Error("Qwen login failed: missing access token in server response");
174
+ }
175
+ return {
176
+ refresh: token.refresh_token || "",
177
+ access: token.access_token,
178
+ expires: Date.now() + token.expires_in * 1000 - 5 * 60 * 1000,
179
+ enterpriseUrl: token.resource_url,
180
+ };
181
+ }
182
+ async function refreshQwenToken(credentials) {
183
+ if (!credentials.refresh) {
184
+ throw new Error("Qwen credentials missing refresh token. Please run /login again");
185
+ }
186
+ const response = await fetch(QWEN_TOKEN_ENDPOINT, {
187
+ method: "POST",
188
+ headers: {
189
+ "Content-Type": "application/x-www-form-urlencoded",
190
+ Accept: "application/json",
191
+ },
192
+ body: objectToUrlEncoded({
193
+ grant_type: "refresh_token",
194
+ refresh_token: credentials.refresh,
195
+ client_id: QWEN_CLIENT_ID,
196
+ }),
197
+ });
198
+ const responseText = await response.text();
199
+ const data = parseJsonResponse(responseText);
200
+ if (!response.ok) {
201
+ throw new Error(`Qwen token refresh failed (${response.status} ${response.statusText}): ${errorDetails(data?.error, data?.error_description || responseText)}`);
202
+ }
203
+ if (!data?.access_token || !data.expires_in) {
204
+ throw new Error("Qwen token refresh failed: missing access token in response");
205
+ }
206
+ return {
207
+ ...credentials,
208
+ refresh: data.refresh_token || credentials.refresh,
209
+ access: data.access_token,
210
+ expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,
211
+ enterpriseUrl: data.resource_url ?? credentials.enterpriseUrl,
212
+ };
213
+ }
214
+ function getQwenBaseUrl(resourceUrl) {
215
+ if (typeof resourceUrl !== "string" || !resourceUrl.trim()) {
216
+ return QWEN_DEFAULT_BASE_URL;
217
+ }
218
+ const normalizedInput = resourceUrl.trim().startsWith("http") ? resourceUrl.trim() : `https://${resourceUrl.trim()}`;
219
+ let normalizedUrl = normalizedInput.replace(/\/+$/, "");
220
+ if (!normalizedUrl.endsWith("/v1")) {
221
+ normalizedUrl += "/v1";
222
+ }
223
+ return normalizedUrl;
224
+ }
225
+ export function createQwenCliProviderConfig() {
226
+ return {
227
+ baseUrl: QWEN_DEFAULT_BASE_URL,
228
+ api: "openai-completions",
229
+ models: [
230
+ {
231
+ id: "qwen3-coder-plus",
232
+ name: "Qwen3 Coder Plus",
233
+ reasoning: false,
234
+ input: ["text"],
235
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
236
+ contextWindow: 1000000,
237
+ maxTokens: 65536,
238
+ },
239
+ {
240
+ id: "qwen3-coder-flash",
241
+ name: "Qwen3 Coder Flash",
242
+ reasoning: false,
243
+ input: ["text"],
244
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
245
+ contextWindow: 1000000,
246
+ maxTokens: 65536,
247
+ },
248
+ {
249
+ id: "qwen3-vl-plus",
250
+ name: "Qwen3 VL Plus",
251
+ reasoning: true,
252
+ input: ["text", "image"],
253
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
254
+ contextWindow: 262144,
255
+ maxTokens: 32768,
256
+ compat: { supportsDeveloperRole: false, thinkingFormat: "qwen" },
257
+ },
258
+ ],
259
+ oauth: {
260
+ name: "Qwen CLI (Free OAuth)",
261
+ login: loginQwen,
262
+ refreshToken: refreshQwenToken,
263
+ getApiKey: (credentials) => String(credentials.access || ""),
264
+ modifyModels: (models, credentials) => {
265
+ const baseUrl = getQwenBaseUrl(credentials.enterpriseUrl);
266
+ return models.map((model) => (model.provider === QWEN_CLI_PROVIDER_ID ? { ...model, baseUrl } : model));
267
+ },
268
+ },
269
+ };
270
+ }
271
+ //# sourceMappingURL=qwen-cli-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qwen-cli-provider.js","sourceRoot":"","sources":["../../src/core/qwen-cli-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Built-in Qwen CLI provider integration.\n *\n * Implements OAuth device authorization (PKCE) against chat.qwen.ai\n * and exposes OpenAI-compatible Qwen coding models in the model registry.\n */\n\nimport { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport type { OAuthCredentials, OAuthLoginCallbacks } from \"@mariozechner/pi-ai\";\nimport type { ProviderConfigInput } from \"./model-registry.js\";\n\nexport const QWEN_CLI_PROVIDER_ID = \"qwen-cli\";\n\nconst QWEN_DEVICE_CODE_ENDPOINT = \"https://chat.qwen.ai/api/v1/oauth2/device/code\";\nconst QWEN_TOKEN_ENDPOINT = \"https://chat.qwen.ai/api/v1/oauth2/token\";\nconst QWEN_CLIENT_ID = \"f0304373b74a44d2b584a3fb70ca9e56\";\nconst QWEN_SCOPE = \"openid profile email model.completion\";\nconst QWEN_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\nconst QWEN_DEFAULT_BASE_URL = \"https://dashscope.aliyuncs.com/compatible-mode/v1\";\nconst QWEN_DEFAULT_POLL_INTERVAL_MS = 2000;\n\ntype DeviceCodeResponse = {\n\tdevice_code: string;\n\tuser_code: string;\n\tverification_uri: string;\n\tverification_uri_complete?: string;\n\texpires_in: number;\n\tinterval?: number;\n\terror?: string;\n\terror_description?: string;\n};\n\ntype TokenResponse = {\n\taccess_token?: string;\n\trefresh_token?: string;\n\ttoken_type?: string;\n\texpires_in?: number;\n\tresource_url?: string;\n\terror?: string;\n\terror_description?: string;\n};\n\nfunction objectToUrlEncoded(data: Record<string, string>): string {\n\treturn Object.entries(data)\n\t\t.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n\t\t.join(\"&\");\n}\n\nfunction generatePKCEPair(): { verifier: string; challenge: string } {\n\tconst verifier = randomBytes(32).toString(\"base64url\");\n\tconst challenge = createHash(\"sha256\").update(verifier).digest(\"base64url\");\n\treturn { verifier, challenge };\n}\n\nfunction isAbortError(error: unknown): boolean {\n\tif (!(error instanceof Error)) return false;\n\treturn error.name === \"AbortError\" || error.message === \"Login cancelled\";\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n\tif (signal?.aborted) {\n\t\tthrow new Error(\"Login cancelled\");\n\t}\n}\n\nasync function abortableSleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(new Error(\"Login cancelled\"));\n\t\t\treturn;\n\t\t}\n\n\t\tconst timeout = setTimeout(() => {\n\t\t\tcleanup();\n\t\t\tresolve();\n\t\t}, ms);\n\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tcleanup();\n\t\t\treject(new Error(\"Login cancelled\"));\n\t\t};\n\n\t\tconst cleanup = () => {\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t};\n\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\nfunction parseJsonResponse<T>(text: string): T | undefined {\n\tif (!text) return undefined;\n\ttry {\n\t\treturn JSON.parse(text) as T;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction errorDetails(error?: string, description?: string): string {\n\tif (error && description) return `${error}: ${description}`;\n\tif (error) return error;\n\treturn description || \"unknown error\";\n}\n\nasync function startDeviceFlow(signal?: AbortSignal): Promise<{ deviceCode: DeviceCodeResponse; verifier: string }> {\n\tthrowIfAborted(signal);\n\tconst { verifier, challenge } = generatePKCEPair();\n\n\tconst response = await fetch(QWEN_DEVICE_CODE_ENDPOINT, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\tAccept: \"application/json\",\n\t\t\t\"x-request-id\": randomUUID(),\n\t\t},\n\t\tbody: objectToUrlEncoded({\n\t\t\tclient_id: QWEN_CLIENT_ID,\n\t\t\tscope: QWEN_SCOPE,\n\t\t\tcode_challenge: challenge,\n\t\t\tcode_challenge_method: \"S256\",\n\t\t}),\n\t\tsignal,\n\t});\n\n\tconst responseText = await response.text();\n\tconst data = parseJsonResponse<DeviceCodeResponse>(responseText);\n\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`Qwen device authorization failed (${response.status} ${response.statusText}): ${errorDetails(\n\t\t\t\tdata?.error,\n\t\t\t\tdata?.error_description || responseText,\n\t\t\t)}`,\n\t\t);\n\t}\n\n\tif (!data?.device_code || !data.user_code || !data.verification_uri || !data.expires_in) {\n\t\tthrow new Error(\"Qwen device authorization failed: invalid response from server\");\n\t}\n\n\treturn { deviceCode: data, verifier };\n}\n\nasync function pollForToken(\n\tdeviceCode: string,\n\tverifier: string,\n\tintervalSeconds: number | undefined,\n\texpiresIn: number,\n\tsignal?: AbortSignal,\n): Promise<TokenResponse> {\n\tlet intervalMs =\n\t\ttypeof intervalSeconds === \"number\" && Number.isFinite(intervalSeconds) && intervalSeconds > 0\n\t\t\t? Math.max(1000, Math.floor(intervalSeconds * 1000))\n\t\t\t: QWEN_DEFAULT_POLL_INTERVAL_MS;\n\tconst deadline = Date.now() + expiresIn * 1000;\n\n\twhile (Date.now() < deadline) {\n\t\tthrowIfAborted(signal);\n\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetch(QWEN_TOKEN_ENDPOINT, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: objectToUrlEncoded({\n\t\t\t\t\tgrant_type: QWEN_GRANT_TYPE,\n\t\t\t\t\tclient_id: QWEN_CLIENT_ID,\n\t\t\t\t\tdevice_code: deviceCode,\n\t\t\t\t\tcode_verifier: verifier,\n\t\t\t\t}),\n\t\t\t\tsignal,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (isAbortError(error)) {\n\t\t\t\tthrow new Error(\"Login cancelled\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\tconst responseText = await response.text();\n\t\tconst data = parseJsonResponse<TokenResponse>(responseText);\n\t\tconst error = data?.error;\n\t\tconst description = data?.error_description;\n\n\t\tif (response.ok && data?.access_token) {\n\t\t\treturn data;\n\t\t}\n\n\t\t// OAuth RFC 8628 polling states\n\t\tif (error === \"authorization_pending\") {\n\t\t\tawait abortableSleep(intervalMs, signal);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (error === \"slow_down\" || response.status === 429) {\n\t\t\tintervalMs = Math.min(intervalMs + 5000, 10000);\n\t\t\tawait abortableSleep(intervalMs, signal);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (error === \"access_denied\") {\n\t\t\tthrow new Error(\"Qwen authorization denied by user\");\n\t\t}\n\n\t\tif (error === \"expired_token\") {\n\t\t\tthrow new Error(\"Qwen device code expired. Please run /login again\");\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Qwen token request failed (${response.status} ${response.statusText}): ${errorDetails(\n\t\t\t\t\terror,\n\t\t\t\t\tdescription || responseText,\n\t\t\t\t)}`,\n\t\t\t);\n\t\t}\n\n\t\tthrow new Error(`Qwen token request failed: ${errorDetails(error, description || responseText)}`);\n\t}\n\n\tthrow new Error(\"Qwen authentication timed out. Please run /login again\");\n}\n\nasync function loginQwen(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n\tcallbacks.onProgress?.(\"Requesting Qwen device authorization...\");\n\n\tconst { deviceCode, verifier } = await startDeviceFlow(callbacks.signal);\n\tconst authUrl = deviceCode.verification_uri_complete || deviceCode.verification_uri;\n\tconst instructions = deviceCode.verification_uri_complete\n\t\t? \"Open this URL and approve access in your browser\"\n\t\t: `Open this URL and enter code: ${deviceCode.user_code}`;\n\n\tcallbacks.onAuth({ url: authUrl, instructions });\n\tcallbacks.onProgress?.(\"Waiting for Qwen authorization...\");\n\n\tconst token = await pollForToken(\n\t\tdeviceCode.device_code,\n\t\tverifier,\n\t\tdeviceCode.interval,\n\t\tdeviceCode.expires_in,\n\t\tcallbacks.signal,\n\t);\n\n\tif (!token.access_token || !token.expires_in) {\n\t\tthrow new Error(\"Qwen login failed: missing access token in server response\");\n\t}\n\n\treturn {\n\t\trefresh: token.refresh_token || \"\",\n\t\taccess: token.access_token,\n\t\texpires: Date.now() + token.expires_in * 1000 - 5 * 60 * 1000,\n\t\tenterpriseUrl: token.resource_url,\n\t};\n}\n\nasync function refreshQwenToken(credentials: OAuthCredentials): Promise<OAuthCredentials> {\n\tif (!credentials.refresh) {\n\t\tthrow new Error(\"Qwen credentials missing refresh token. Please run /login again\");\n\t}\n\n\tconst response = await fetch(QWEN_TOKEN_ENDPOINT, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t\tbody: objectToUrlEncoded({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\trefresh_token: credentials.refresh,\n\t\t\tclient_id: QWEN_CLIENT_ID,\n\t\t}),\n\t});\n\n\tconst responseText = await response.text();\n\tconst data = parseJsonResponse<TokenResponse>(responseText);\n\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`Qwen token refresh failed (${response.status} ${response.statusText}): ${errorDetails(\n\t\t\t\tdata?.error,\n\t\t\t\tdata?.error_description || responseText,\n\t\t\t)}`,\n\t\t);\n\t}\n\n\tif (!data?.access_token || !data.expires_in) {\n\t\tthrow new Error(\"Qwen token refresh failed: missing access token in response\");\n\t}\n\n\treturn {\n\t\t...credentials,\n\t\trefresh: data.refresh_token || credentials.refresh,\n\t\taccess: data.access_token,\n\t\texpires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,\n\t\tenterpriseUrl: data.resource_url ?? credentials.enterpriseUrl,\n\t};\n}\n\nfunction getQwenBaseUrl(resourceUrl: unknown): string {\n\tif (typeof resourceUrl !== \"string\" || !resourceUrl.trim()) {\n\t\treturn QWEN_DEFAULT_BASE_URL;\n\t}\n\n\tconst normalizedInput = resourceUrl.trim().startsWith(\"http\") ? resourceUrl.trim() : `https://${resourceUrl.trim()}`;\n\tlet normalizedUrl = normalizedInput.replace(/\\/+$/, \"\");\n\tif (!normalizedUrl.endsWith(\"/v1\")) {\n\t\tnormalizedUrl += \"/v1\";\n\t}\n\treturn normalizedUrl;\n}\n\nexport function createQwenCliProviderConfig(): ProviderConfigInput {\n\treturn {\n\t\tbaseUrl: QWEN_DEFAULT_BASE_URL,\n\t\tapi: \"openai-completions\",\n\t\tmodels: [\n\t\t\t{\n\t\t\t\tid: \"qwen3-coder-plus\",\n\t\t\t\tname: \"Qwen3 Coder Plus\",\n\t\t\t\treasoning: false,\n\t\t\t\tinput: [\"text\"],\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\t\t\tcontextWindow: 1000000,\n\t\t\t\tmaxTokens: 65536,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"qwen3-coder-flash\",\n\t\t\t\tname: \"Qwen3 Coder Flash\",\n\t\t\t\treasoning: false,\n\t\t\t\tinput: [\"text\"],\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\t\t\tcontextWindow: 1000000,\n\t\t\t\tmaxTokens: 65536,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"qwen3-vl-plus\",\n\t\t\t\tname: \"Qwen3 VL Plus\",\n\t\t\t\treasoning: true,\n\t\t\t\tinput: [\"text\", \"image\"],\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\t\t\tcontextWindow: 262144,\n\t\t\t\tmaxTokens: 32768,\n\t\t\t\tcompat: { supportsDeveloperRole: false, thinkingFormat: \"qwen\" },\n\t\t\t},\n\t\t],\n\t\toauth: {\n\t\t\tname: \"Qwen CLI (Free OAuth)\",\n\t\t\tlogin: loginQwen,\n\t\t\trefreshToken: refreshQwenToken,\n\t\t\tgetApiKey: (credentials) => String(credentials.access || \"\"),\n\t\t\tmodifyModels: (models, credentials) => {\n\t\t\t\tconst baseUrl = getQwenBaseUrl(credentials.enterpriseUrl);\n\t\t\t\treturn models.map((model) => (model.provider === QWEN_CLI_PROVIDER_ID ? { ...model, baseUrl } : model));\n\t\t\t},\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Resolve configuration values that may be shell commands, environment variables, or literals.
3
+ * Used by auth-storage.ts and model-registry.ts.
4
+ */
5
+ /**
6
+ * Resolve a config value (API key, header value, etc.) to an actual value.
7
+ * - If starts with "!", executes the rest as a shell command and uses stdout (cached)
8
+ * - Otherwise checks environment variable first, then treats as literal (not cached)
9
+ */
10
+ export declare function resolveConfigValue(config: string): string | undefined;
11
+ /**
12
+ * Resolve all header values using the same resolution logic as API keys.
13
+ */
14
+ export declare function resolveHeaders(headers: Record<string, string> | undefined): Record<string, string> | undefined;
15
+ /** Clear the config value command cache. Exported for testing. */
16
+ export declare function clearConfigValueCache(): void;
17
+ //# sourceMappingURL=resolve-config-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-config-value.d.ts","sourceRoot":"","sources":["../../src/core/resolve-config-value.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMrE;AAyBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAU9G;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}