@pencil-agent/nano-pencil 1.11.32 → 1.11.34

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 (394) hide show
  1. package/dist/cli.js +0 -0
  2. package/dist/core/config/settings-manager.d.ts +8 -0
  3. package/dist/core/config/settings-manager.js +16 -0
  4. package/dist/core/index.d.ts +1 -0
  5. package/dist/core/index.js +2 -0
  6. package/dist/core/model/switcher.d.ts +2 -1
  7. package/dist/core/model/switcher.js +30 -7
  8. package/dist/core/model-registry.d.ts +14 -0
  9. package/dist/core/model-registry.js +64 -1
  10. package/dist/core/runtime/agent-session.d.ts +8 -0
  11. package/dist/core/runtime/agent-session.js +47 -8
  12. package/dist/modes/interactive/components/custom-editor.d.ts +4 -2
  13. package/dist/modes/interactive/components/custom-editor.js +33 -7
  14. package/dist/modes/interactive/components/index.d.ts +1 -0
  15. package/dist/modes/interactive/components/index.js +1 -0
  16. package/dist/modes/interactive/components/model-selector.d.ts +3 -1
  17. package/dist/modes/interactive/components/model-selector.js +58 -26
  18. package/dist/modes/interactive/interactive-mode.d.ts +47 -1
  19. package/dist/modes/interactive/interactive-mode.js +653 -46
  20. package/dist/nanopencil-defaults.d.ts +8 -2
  21. package/dist/nanopencil-defaults.js +61 -2
  22. package/dist/node_modules/zod/LICENSE +21 -0
  23. package/dist/node_modules/zod/README.md +208 -0
  24. package/dist/node_modules/zod/index.js +4 -0
  25. package/dist/node_modules/zod/locales/index.d.ts +1 -0
  26. package/dist/node_modules/zod/locales/index.js +1 -0
  27. package/dist/node_modules/zod/locales/package.json +6 -0
  28. package/dist/node_modules/zod/mini/index.d.ts +3 -0
  29. package/dist/node_modules/zod/mini/index.js +3 -0
  30. package/dist/node_modules/zod/mini/package.json +6 -0
  31. package/dist/node_modules/zod/package.json +135 -0
  32. package/dist/node_modules/zod/v3/ZodError.d.ts +164 -0
  33. package/dist/node_modules/zod/v3/ZodError.js +133 -0
  34. package/dist/node_modules/zod/v3/errors.d.ts +5 -0
  35. package/dist/node_modules/zod/v3/errors.js +9 -0
  36. package/dist/node_modules/zod/v3/external.d.ts +6 -0
  37. package/dist/node_modules/zod/v3/external.js +6 -0
  38. package/dist/node_modules/zod/v3/helpers/enumUtil.d.ts +8 -0
  39. package/dist/node_modules/zod/v3/helpers/enumUtil.js +1 -0
  40. package/dist/node_modules/zod/v3/helpers/errorUtil.d.ts +9 -0
  41. package/dist/node_modules/zod/v3/helpers/errorUtil.js +6 -0
  42. package/dist/node_modules/zod/v3/helpers/parseUtil.d.ts +78 -0
  43. package/dist/node_modules/zod/v3/helpers/parseUtil.js +109 -0
  44. package/dist/node_modules/zod/v3/helpers/partialUtil.d.ts +8 -0
  45. package/dist/node_modules/zod/v3/helpers/partialUtil.js +1 -0
  46. package/dist/node_modules/zod/v3/helpers/typeAliases.d.ts +2 -0
  47. package/dist/node_modules/zod/v3/helpers/typeAliases.js +1 -0
  48. package/dist/node_modules/zod/v3/helpers/util.d.ts +85 -0
  49. package/dist/node_modules/zod/v3/helpers/util.js +133 -0
  50. package/dist/node_modules/zod/v3/index.d.ts +4 -0
  51. package/dist/node_modules/zod/v3/index.js +4 -0
  52. package/dist/node_modules/zod/v3/locales/en.d.ts +3 -0
  53. package/dist/node_modules/zod/v3/locales/en.js +109 -0
  54. package/dist/node_modules/zod/v3/package.json +6 -0
  55. package/dist/node_modules/zod/v3/standard-schema.d.ts +102 -0
  56. package/dist/node_modules/zod/v3/standard-schema.js +1 -0
  57. package/dist/node_modules/zod/v3/types.d.ts +1034 -0
  58. package/dist/node_modules/zod/v3/types.js +3695 -0
  59. package/dist/node_modules/zod/v4/classic/checks.d.ts +1 -0
  60. package/dist/node_modules/zod/v4/classic/checks.js +1 -0
  61. package/dist/node_modules/zod/v4/classic/coerce.d.ts +17 -0
  62. package/dist/node_modules/zod/v4/classic/coerce.js +17 -0
  63. package/dist/node_modules/zod/v4/classic/compat.d.ts +50 -0
  64. package/dist/node_modules/zod/v4/classic/compat.js +31 -0
  65. package/dist/node_modules/zod/v4/classic/errors.d.ts +30 -0
  66. package/dist/node_modules/zod/v4/classic/errors.js +48 -0
  67. package/dist/node_modules/zod/v4/classic/external.d.ts +15 -0
  68. package/dist/node_modules/zod/v4/classic/external.js +20 -0
  69. package/dist/node_modules/zod/v4/classic/from-json-schema.d.ts +12 -0
  70. package/dist/node_modules/zod/v4/classic/from-json-schema.js +584 -0
  71. package/dist/node_modules/zod/v4/classic/index.d.ts +4 -0
  72. package/dist/node_modules/zod/v4/classic/index.js +4 -0
  73. package/dist/node_modules/zod/v4/classic/iso.d.ts +22 -0
  74. package/dist/node_modules/zod/v4/classic/iso.js +30 -0
  75. package/dist/node_modules/zod/v4/classic/package.json +6 -0
  76. package/dist/node_modules/zod/v4/classic/parse.d.ts +31 -0
  77. package/dist/node_modules/zod/v4/classic/parse.js +15 -0
  78. package/dist/node_modules/zod/v4/classic/schemas.d.ts +739 -0
  79. package/dist/node_modules/zod/v4/classic/schemas.js +1157 -0
  80. package/dist/node_modules/zod/v4/core/api.d.ts +304 -0
  81. package/dist/node_modules/zod/v4/core/api.js +1082 -0
  82. package/dist/node_modules/zod/v4/core/checks.d.ts +278 -0
  83. package/dist/node_modules/zod/v4/core/checks.js +575 -0
  84. package/dist/node_modules/zod/v4/core/core.d.ts +70 -0
  85. package/dist/node_modules/zod/v4/core/core.js +76 -0
  86. package/dist/node_modules/zod/v4/core/doc.d.ts +14 -0
  87. package/dist/node_modules/zod/v4/core/doc.js +35 -0
  88. package/dist/node_modules/zod/v4/core/errors.d.ts +220 -0
  89. package/dist/node_modules/zod/v4/core/errors.js +182 -0
  90. package/dist/node_modules/zod/v4/core/index.d.ts +16 -0
  91. package/dist/node_modules/zod/v4/core/index.js +16 -0
  92. package/dist/node_modules/zod/v4/core/json-schema-generator.d.ts +65 -0
  93. package/dist/node_modules/zod/v4/core/json-schema-generator.js +95 -0
  94. package/dist/node_modules/zod/v4/core/json-schema-processors.d.ts +49 -0
  95. package/dist/node_modules/zod/v4/core/json-schema-processors.js +605 -0
  96. package/dist/node_modules/zod/v4/core/json-schema.d.ts +88 -0
  97. package/dist/node_modules/zod/v4/core/json-schema.js +1 -0
  98. package/dist/node_modules/zod/v4/core/package.json +6 -0
  99. package/dist/node_modules/zod/v4/core/parse.d.ts +49 -0
  100. package/dist/node_modules/zod/v4/core/parse.js +93 -0
  101. package/dist/node_modules/zod/v4/core/regexes.d.ts +79 -0
  102. package/dist/node_modules/zod/v4/core/regexes.js +133 -0
  103. package/dist/node_modules/zod/v4/core/registries.d.ts +35 -0
  104. package/dist/node_modules/zod/v4/core/registries.js +51 -0
  105. package/dist/node_modules/zod/v4/core/schemas.d.ts +1146 -0
  106. package/dist/node_modules/zod/v4/core/schemas.js +2093 -0
  107. package/dist/node_modules/zod/v4/core/standard-schema.d.ts +126 -0
  108. package/dist/node_modules/zod/v4/core/standard-schema.js +1 -0
  109. package/dist/node_modules/zod/v4/core/to-json-schema.d.ts +114 -0
  110. package/dist/node_modules/zod/v4/core/to-json-schema.js +437 -0
  111. package/dist/node_modules/zod/v4/core/util.d.ts +199 -0
  112. package/dist/node_modules/zod/v4/core/util.js +651 -0
  113. package/dist/node_modules/zod/v4/core/versions.d.ts +5 -0
  114. package/dist/node_modules/zod/v4/core/versions.js +5 -0
  115. package/dist/node_modules/zod/v4/index.d.ts +3 -0
  116. package/dist/node_modules/zod/v4/index.js +3 -0
  117. package/dist/node_modules/zod/v4/locales/ar.d.ts +4 -0
  118. package/dist/node_modules/zod/v4/locales/ar.js +106 -0
  119. package/dist/node_modules/zod/v4/locales/az.d.ts +4 -0
  120. package/dist/node_modules/zod/v4/locales/az.js +105 -0
  121. package/dist/node_modules/zod/v4/locales/be.d.ts +4 -0
  122. package/dist/node_modules/zod/v4/locales/be.js +156 -0
  123. package/dist/node_modules/zod/v4/locales/bg.d.ts +4 -0
  124. package/dist/node_modules/zod/v4/locales/bg.js +120 -0
  125. package/dist/node_modules/zod/v4/locales/ca.d.ts +4 -0
  126. package/dist/node_modules/zod/v4/locales/ca.js +107 -0
  127. package/dist/node_modules/zod/v4/locales/cs.d.ts +4 -0
  128. package/dist/node_modules/zod/v4/locales/cs.js +111 -0
  129. package/dist/node_modules/zod/v4/locales/da.d.ts +4 -0
  130. package/dist/node_modules/zod/v4/locales/da.js +115 -0
  131. package/dist/node_modules/zod/v4/locales/de.d.ts +4 -0
  132. package/dist/node_modules/zod/v4/locales/de.js +108 -0
  133. package/dist/node_modules/zod/v4/locales/en.d.ts +4 -0
  134. package/dist/node_modules/zod/v4/locales/en.js +109 -0
  135. package/dist/node_modules/zod/v4/locales/eo.d.ts +4 -0
  136. package/dist/node_modules/zod/v4/locales/eo.js +109 -0
  137. package/dist/node_modules/zod/v4/locales/es.d.ts +4 -0
  138. package/dist/node_modules/zod/v4/locales/es.js +132 -0
  139. package/dist/node_modules/zod/v4/locales/fa.d.ts +4 -0
  140. package/dist/node_modules/zod/v4/locales/fa.js +114 -0
  141. package/dist/node_modules/zod/v4/locales/fi.d.ts +4 -0
  142. package/dist/node_modules/zod/v4/locales/fi.js +112 -0
  143. package/dist/node_modules/zod/v4/locales/fr-CA.d.ts +4 -0
  144. package/dist/node_modules/zod/v4/locales/fr-CA.js +107 -0
  145. package/dist/node_modules/zod/v4/locales/fr.d.ts +4 -0
  146. package/dist/node_modules/zod/v4/locales/fr.js +108 -0
  147. package/dist/node_modules/zod/v4/locales/he.d.ts +4 -0
  148. package/dist/node_modules/zod/v4/locales/he.js +214 -0
  149. package/dist/node_modules/zod/v4/locales/hu.d.ts +4 -0
  150. package/dist/node_modules/zod/v4/locales/hu.js +108 -0
  151. package/dist/node_modules/zod/v4/locales/hy.d.ts +4 -0
  152. package/dist/node_modules/zod/v4/locales/hy.js +147 -0
  153. package/dist/node_modules/zod/v4/locales/id.d.ts +4 -0
  154. package/dist/node_modules/zod/v4/locales/id.js +106 -0
  155. package/dist/node_modules/zod/v4/locales/index.d.ts +49 -0
  156. package/dist/node_modules/zod/v4/locales/index.js +49 -0
  157. package/dist/node_modules/zod/v4/locales/is.d.ts +4 -0
  158. package/dist/node_modules/zod/v4/locales/is.js +109 -0
  159. package/dist/node_modules/zod/v4/locales/it.d.ts +4 -0
  160. package/dist/node_modules/zod/v4/locales/it.js +108 -0
  161. package/dist/node_modules/zod/v4/locales/ja.d.ts +4 -0
  162. package/dist/node_modules/zod/v4/locales/ja.js +107 -0
  163. package/dist/node_modules/zod/v4/locales/ka.d.ts +4 -0
  164. package/dist/node_modules/zod/v4/locales/ka.js +112 -0
  165. package/dist/node_modules/zod/v4/locales/kh.d.ts +5 -0
  166. package/dist/node_modules/zod/v4/locales/kh.js +5 -0
  167. package/dist/node_modules/zod/v4/locales/km.d.ts +4 -0
  168. package/dist/node_modules/zod/v4/locales/km.js +110 -0
  169. package/dist/node_modules/zod/v4/locales/ko.d.ts +4 -0
  170. package/dist/node_modules/zod/v4/locales/ko.js +111 -0
  171. package/dist/node_modules/zod/v4/locales/lt.d.ts +4 -0
  172. package/dist/node_modules/zod/v4/locales/lt.js +203 -0
  173. package/dist/node_modules/zod/v4/locales/mk.d.ts +4 -0
  174. package/dist/node_modules/zod/v4/locales/mk.js +109 -0
  175. package/dist/node_modules/zod/v4/locales/ms.d.ts +4 -0
  176. package/dist/node_modules/zod/v4/locales/ms.js +107 -0
  177. package/dist/node_modules/zod/v4/locales/nl.d.ts +4 -0
  178. package/dist/node_modules/zod/v4/locales/nl.js +110 -0
  179. package/dist/node_modules/zod/v4/locales/no.d.ts +4 -0
  180. package/dist/node_modules/zod/v4/locales/no.js +108 -0
  181. package/dist/node_modules/zod/v4/locales/ota.d.ts +4 -0
  182. package/dist/node_modules/zod/v4/locales/ota.js +109 -0
  183. package/dist/node_modules/zod/v4/locales/package.json +6 -0
  184. package/dist/node_modules/zod/v4/locales/pl.d.ts +4 -0
  185. package/dist/node_modules/zod/v4/locales/pl.js +109 -0
  186. package/dist/node_modules/zod/v4/locales/ps.d.ts +4 -0
  187. package/dist/node_modules/zod/v4/locales/ps.js +114 -0
  188. package/dist/node_modules/zod/v4/locales/pt.d.ts +4 -0
  189. package/dist/node_modules/zod/v4/locales/pt.js +108 -0
  190. package/dist/node_modules/zod/v4/locales/ru.d.ts +4 -0
  191. package/dist/node_modules/zod/v4/locales/ru.js +156 -0
  192. package/dist/node_modules/zod/v4/locales/sl.d.ts +4 -0
  193. package/dist/node_modules/zod/v4/locales/sl.js +109 -0
  194. package/dist/node_modules/zod/v4/locales/sv.d.ts +4 -0
  195. package/dist/node_modules/zod/v4/locales/sv.js +110 -0
  196. package/dist/node_modules/zod/v4/locales/ta.d.ts +4 -0
  197. package/dist/node_modules/zod/v4/locales/ta.js +110 -0
  198. package/dist/node_modules/zod/v4/locales/th.d.ts +4 -0
  199. package/dist/node_modules/zod/v4/locales/th.js +110 -0
  200. package/dist/node_modules/zod/v4/locales/tr.d.ts +4 -0
  201. package/dist/node_modules/zod/v4/locales/tr.js +105 -0
  202. package/dist/node_modules/zod/v4/locales/ua.d.ts +5 -0
  203. package/dist/node_modules/zod/v4/locales/ua.js +5 -0
  204. package/dist/node_modules/zod/v4/locales/uk.d.ts +4 -0
  205. package/dist/node_modules/zod/v4/locales/uk.js +108 -0
  206. package/dist/node_modules/zod/v4/locales/ur.d.ts +4 -0
  207. package/dist/node_modules/zod/v4/locales/ur.js +110 -0
  208. package/dist/node_modules/zod/v4/locales/uz.d.ts +4 -0
  209. package/dist/node_modules/zod/v4/locales/uz.js +109 -0
  210. package/dist/node_modules/zod/v4/locales/vi.d.ts +4 -0
  211. package/dist/node_modules/zod/v4/locales/vi.js +108 -0
  212. package/dist/node_modules/zod/v4/locales/yo.d.ts +4 -0
  213. package/dist/node_modules/zod/v4/locales/yo.js +107 -0
  214. package/dist/node_modules/zod/v4/locales/zh-CN.d.ts +4 -0
  215. package/dist/node_modules/zod/v4/locales/zh-CN.js +109 -0
  216. package/dist/node_modules/zod/v4/locales/zh-TW.d.ts +4 -0
  217. package/dist/node_modules/zod/v4/locales/zh-TW.js +107 -0
  218. package/dist/node_modules/zod/v4/mini/checks.d.ts +1 -0
  219. package/dist/node_modules/zod/v4/mini/checks.js +1 -0
  220. package/dist/node_modules/zod/v4/mini/coerce.d.ts +7 -0
  221. package/dist/node_modules/zod/v4/mini/coerce.js +22 -0
  222. package/dist/node_modules/zod/v4/mini/external.d.ts +12 -0
  223. package/dist/node_modules/zod/v4/mini/external.js +14 -0
  224. package/dist/node_modules/zod/v4/mini/index.d.ts +3 -0
  225. package/dist/node_modules/zod/v4/mini/index.js +3 -0
  226. package/dist/node_modules/zod/v4/mini/iso.d.ts +22 -0
  227. package/dist/node_modules/zod/v4/mini/iso.js +34 -0
  228. package/dist/node_modules/zod/v4/mini/package.json +6 -0
  229. package/dist/node_modules/zod/v4/mini/parse.d.ts +1 -0
  230. package/dist/node_modules/zod/v4/mini/parse.js +1 -0
  231. package/dist/node_modules/zod/v4/mini/schemas.d.ts +427 -0
  232. package/dist/node_modules/zod/v4/mini/schemas.js +925 -0
  233. package/dist/node_modules/zod/v4/package.json +6 -0
  234. package/dist/node_modules/zod/v4-mini/index.d.ts +3 -0
  235. package/dist/node_modules/zod/v4-mini/index.js +3 -0
  236. package/dist/node_modules/zod/v4-mini/package.json +6 -0
  237. package/docs/debug-logging.md +148 -0
  238. package/node_modules/@pencil-agent/ai/dist/config-path.d.ts +2 -0
  239. package/node_modules/@pencil-agent/ai/dist/config-path.d.ts.map +1 -0
  240. package/node_modules/@pencil-agent/ai/dist/config-path.js +16 -0
  241. package/node_modules/@pencil-agent/ai/dist/config-path.js.map +1 -0
  242. package/node_modules/@pencil-agent/ai/dist/debug-logger.d.ts +95 -0
  243. package/node_modules/@pencil-agent/ai/dist/debug-logger.d.ts.map +1 -0
  244. package/node_modules/@pencil-agent/ai/dist/debug-logger.js +218 -0
  245. package/node_modules/@pencil-agent/ai/dist/debug-logger.js.map +1 -0
  246. package/node_modules/@pencil-agent/ai/dist/providers/openai-completions.d.ts.map +1 -1
  247. package/node_modules/@pencil-agent/ai/dist/providers/openai-completions.js +152 -14
  248. package/node_modules/@pencil-agent/ai/dist/providers/openai-completions.js.map +1 -1
  249. package/package.json +5 -3
  250. package/dist/packages/agent-core/src/agent-loop.d.ts +0 -27
  251. package/dist/packages/agent-core/src/agent-loop.js +0 -314
  252. package/dist/packages/agent-core/src/agent.d.ts +0 -163
  253. package/dist/packages/agent-core/src/agent.js +0 -416
  254. package/dist/packages/agent-core/src/index.d.ts +0 -11
  255. package/dist/packages/agent-core/src/index.js +0 -15
  256. package/dist/packages/agent-core/src/proxy.d.ts +0 -91
  257. package/dist/packages/agent-core/src/proxy.js +0 -274
  258. package/dist/packages/agent-core/src/types.d.ts +0 -184
  259. package/dist/packages/agent-core/src/types.js +0 -8
  260. package/dist/packages/ai/src/api-registry.d.ts +0 -26
  261. package/dist/packages/ai/src/api-registry.js +0 -50
  262. package/dist/packages/ai/src/env-api-keys.d.ts +0 -9
  263. package/dist/packages/ai/src/env-api-keys.js +0 -106
  264. package/dist/packages/ai/src/index.d.ts +0 -28
  265. package/dist/packages/ai/src/index.js +0 -21
  266. package/dist/packages/ai/src/models.d.ts +0 -30
  267. package/dist/packages/ai/src/models.generated.d.ts +0 -14525
  268. package/dist/packages/ai/src/models.generated.js +0 -14307
  269. package/dist/packages/ai/src/models.js +0 -61
  270. package/dist/packages/ai/src/providers/amazon-bedrock.d.ts +0 -21
  271. package/dist/packages/ai/src/providers/amazon-bedrock.js +0 -603
  272. package/dist/packages/ai/src/providers/anthropic.d.ts +0 -39
  273. package/dist/packages/ai/src/providers/anthropic.js +0 -735
  274. package/dist/packages/ai/src/providers/azure-openai-responses.d.ts +0 -21
  275. package/dist/packages/ai/src/providers/azure-openai-responses.js +0 -190
  276. package/dist/packages/ai/src/providers/github-copilot-headers.d.ts +0 -14
  277. package/dist/packages/ai/src/providers/github-copilot-headers.js +0 -35
  278. package/dist/packages/ai/src/providers/google-gemini-cli.d.ts +0 -80
  279. package/dist/packages/ai/src/providers/google-gemini-cli.js +0 -750
  280. package/dist/packages/ai/src/providers/google-shared.d.ts +0 -71
  281. package/dist/packages/ai/src/providers/google-shared.js +0 -312
  282. package/dist/packages/ai/src/providers/google-vertex.d.ts +0 -21
  283. package/dist/packages/ai/src/providers/google-vertex.js +0 -377
  284. package/dist/packages/ai/src/providers/google.d.ts +0 -19
  285. package/dist/packages/ai/src/providers/google.js +0 -358
  286. package/dist/packages/ai/src/providers/openai-codex-responses.d.ts +0 -9
  287. package/dist/packages/ai/src/providers/openai-codex-responses.js +0 -705
  288. package/dist/packages/ai/src/providers/openai-completions.d.ts +0 -21
  289. package/dist/packages/ai/src/providers/openai-completions.js +0 -733
  290. package/dist/packages/ai/src/providers/openai-responses-shared.d.ts +0 -23
  291. package/dist/packages/ai/src/providers/openai-responses-shared.js +0 -433
  292. package/dist/packages/ai/src/providers/openai-responses.d.ts +0 -19
  293. package/dist/packages/ai/src/providers/openai-responses.js +0 -204
  294. package/dist/packages/ai/src/providers/register-builtins.d.ts +0 -9
  295. package/dist/packages/ai/src/providers/register-builtins.js +0 -69
  296. package/dist/packages/ai/src/providers/simple-options.d.ts +0 -14
  297. package/dist/packages/ai/src/providers/simple-options.js +0 -41
  298. package/dist/packages/ai/src/providers/transform-messages.d.ts +0 -14
  299. package/dist/packages/ai/src/providers/transform-messages.js +0 -161
  300. package/dist/packages/ai/src/stream.d.ts +0 -15
  301. package/dist/packages/ai/src/stream.js +0 -34
  302. package/dist/packages/ai/src/types.d.ts +0 -287
  303. package/dist/packages/ai/src/types.js +0 -8
  304. package/dist/packages/ai/src/utils/event-stream.d.ts +0 -27
  305. package/dist/packages/ai/src/utils/event-stream.js +0 -87
  306. package/dist/packages/ai/src/utils/http-proxy.d.ts +0 -14
  307. package/dist/packages/ai/src/utils/http-proxy.js +0 -21
  308. package/dist/packages/ai/src/utils/json-parse.d.ts +0 -15
  309. package/dist/packages/ai/src/utils/json-parse.js +0 -35
  310. package/dist/packages/ai/src/utils/oauth/anthropic.d.ts +0 -23
  311. package/dist/packages/ai/src/utils/oauth/anthropic.js +0 -110
  312. package/dist/packages/ai/src/utils/oauth/github-copilot.d.ts +0 -36
  313. package/dist/packages/ai/src/utils/oauth/github-copilot.js +0 -287
  314. package/dist/packages/ai/src/utils/oauth/google-antigravity.d.ts +0 -32
  315. package/dist/packages/ai/src/utils/oauth/google-antigravity.js +0 -379
  316. package/dist/packages/ai/src/utils/oauth/google-gemini-cli.d.ts +0 -32
  317. package/dist/packages/ai/src/utils/oauth/google-gemini-cli.js +0 -484
  318. package/dist/packages/ai/src/utils/oauth/index.d.ts +0 -68
  319. package/dist/packages/ai/src/utils/oauth/index.js +0 -139
  320. package/dist/packages/ai/src/utils/oauth/openai-codex.d.ts +0 -40
  321. package/dist/packages/ai/src/utils/oauth/openai-codex.js +0 -386
  322. package/dist/packages/ai/src/utils/oauth/pkce.d.ts +0 -19
  323. package/dist/packages/ai/src/utils/oauth/pkce.js +0 -37
  324. package/dist/packages/ai/src/utils/oauth/types.d.ts +0 -53
  325. package/dist/packages/ai/src/utils/oauth/types.js +0 -8
  326. package/dist/packages/ai/src/utils/overflow.d.ts +0 -58
  327. package/dist/packages/ai/src/utils/overflow.js +0 -121
  328. package/dist/packages/ai/src/utils/sanitize-unicode.d.ts +0 -28
  329. package/dist/packages/ai/src/utils/sanitize-unicode.js +0 -32
  330. package/dist/packages/ai/src/utils/typebox-helpers.d.ts +0 -23
  331. package/dist/packages/ai/src/utils/typebox-helpers.js +0 -27
  332. package/dist/packages/ai/src/utils/validation.d.ts +0 -24
  333. package/dist/packages/ai/src/utils/validation.js +0 -78
  334. package/dist/packages/tui/src/autocomplete.d.ts +0 -56
  335. package/dist/packages/tui/src/autocomplete.js +0 -602
  336. package/dist/packages/tui/src/components/box.d.ts +0 -28
  337. package/dist/packages/tui/src/components/box.js +0 -110
  338. package/dist/packages/tui/src/components/cancellable-loader.d.ts +0 -28
  339. package/dist/packages/tui/src/components/cancellable-loader.js +0 -41
  340. package/dist/packages/tui/src/components/editor.d.ts +0 -211
  341. package/dist/packages/tui/src/components/editor.js +0 -1692
  342. package/dist/packages/tui/src/components/image.d.ts +0 -34
  343. package/dist/packages/tui/src/components/image.js +0 -75
  344. package/dist/packages/tui/src/components/input.d.ts +0 -43
  345. package/dist/packages/tui/src/components/input.js +0 -439
  346. package/dist/packages/tui/src/components/loader.d.ts +0 -27
  347. package/dist/packages/tui/src/components/loader.js +0 -55
  348. package/dist/packages/tui/src/components/markdown.d.ts +0 -101
  349. package/dist/packages/tui/src/components/markdown.js +0 -635
  350. package/dist/packages/tui/src/components/select-list.d.ts +0 -38
  351. package/dist/packages/tui/src/components/select-list.js +0 -158
  352. package/dist/packages/tui/src/components/settings-list.d.ts +0 -56
  353. package/dist/packages/tui/src/components/settings-list.js +0 -191
  354. package/dist/packages/tui/src/components/spacer.d.ts +0 -18
  355. package/dist/packages/tui/src/components/spacer.js +0 -29
  356. package/dist/packages/tui/src/components/text.d.ts +0 -25
  357. package/dist/packages/tui/src/components/text.js +0 -95
  358. package/dist/packages/tui/src/components/truncated-text.d.ts +0 -19
  359. package/dist/packages/tui/src/components/truncated-text.js +0 -57
  360. package/dist/packages/tui/src/editor-component.d.ts +0 -45
  361. package/dist/packages/tui/src/editor-component.js +0 -8
  362. package/dist/packages/tui/src/fuzzy.d.ts +0 -22
  363. package/dist/packages/tui/src/fuzzy.js +0 -113
  364. package/dist/packages/tui/src/index.d.ts +0 -29
  365. package/dist/packages/tui/src/index.js +0 -38
  366. package/dist/packages/tui/src/keybindings.d.ts +0 -45
  367. package/dist/packages/tui/src/keybindings.js +0 -120
  368. package/dist/packages/tui/src/keys.d.ts +0 -166
  369. package/dist/packages/tui/src/keys.js +0 -965
  370. package/dist/packages/tui/src/kill-ring.d.ts +0 -34
  371. package/dist/packages/tui/src/kill-ring.js +0 -50
  372. package/dist/packages/tui/src/stdin-buffer.d.ts +0 -54
  373. package/dist/packages/tui/src/stdin-buffer.js +0 -323
  374. package/dist/packages/tui/src/terminal-image.d.ts +0 -74
  375. package/dist/packages/tui/src/terminal-image.js +0 -288
  376. package/dist/packages/tui/src/terminal.d.ts +0 -84
  377. package/dist/packages/tui/src/terminal.js +0 -255
  378. package/dist/packages/tui/src/tui.d.ts +0 -216
  379. package/dist/packages/tui/src/tui.js +0 -961
  380. package/dist/packages/tui/src/undo-stack.d.ts +0 -23
  381. package/dist/packages/tui/src/undo-stack.js +0 -31
  382. package/dist/packages/tui/src/utils.d.ts +0 -84
  383. package/dist/packages/tui/src/utils.js +0 -812
  384. package/node_modules/ast-types/.DS_Store +0 -0
  385. package/node_modules/fast-uri/.DS_Store +0 -0
  386. package/node_modules/json-schema-traverse/.DS_Store +0 -0
  387. package/node_modules/koffi/.DS_Store +0 -0
  388. package/node_modules/netmask/.DS_Store +0 -0
  389. package/node_modules/openai/.DS_Store +0 -0
  390. package/node_modules/smart-buffer/.DS_Store +0 -0
  391. package/node_modules/socks/.DS_Store +0 -0
  392. package/node_modules/strnum/.DS_Store +0 -0
  393. package/node_modules/undici/.DS_Store +0 -0
  394. package/node_modules/zod-to-json-schema/.DS_Store +0 -0
package/dist/cli.js CHANGED
File without changes
@@ -97,6 +97,10 @@ export interface Settings {
97
97
  lockStaleMinutes?: number;
98
98
  };
99
99
  };
100
+ /** Auto-update setting: 'always' = auto-update on startup, 'prompt' = ask user (default), 'never' = never check */
101
+ autoUpdate?: "always" | "prompt" | "never";
102
+ /** Last skipped version for update prompts */
103
+ skippedVersion?: string;
100
104
  }
101
105
  export type SettingsScope = "global" | "project";
102
106
  export interface SettingsStorage {
@@ -251,5 +255,9 @@ export declare class SettingsManager {
251
255
  getAutocompleteMaxVisible(): number;
252
256
  setAutocompleteMaxVisible(maxVisible: number): void;
253
257
  getCodeBlockIndent(): string;
258
+ getAutoUpdate(): "always" | "prompt" | "never";
259
+ setAutoUpdate(mode: "always" | "prompt" | "never"): void;
260
+ getSkippedVersion(): string | undefined;
261
+ setSkippedVersion(version: string | undefined): void;
254
262
  }
255
263
  //# sourceMappingURL=settings-manager.d.ts.map
@@ -689,5 +689,21 @@ export class SettingsManager {
689
689
  getCodeBlockIndent() {
690
690
  return this.settings.markdown?.codeBlockIndent ?? " ";
691
691
  }
692
+ getAutoUpdate() {
693
+ return this.settings.autoUpdate ?? "prompt";
694
+ }
695
+ setAutoUpdate(mode) {
696
+ this.globalSettings.autoUpdate = mode;
697
+ this.markModified("autoUpdate");
698
+ this.save();
699
+ }
700
+ getSkippedVersion() {
701
+ return this.settings.skippedVersion;
702
+ }
703
+ setSkippedVersion(version) {
704
+ this.globalSettings.skippedVersion = version;
705
+ this.markModified("skippedVersion");
706
+ this.save();
707
+ }
692
708
  }
693
709
  //# sourceMappingURL=settings-manager.js.map
@@ -10,6 +10,7 @@ export type { CompactionResult } from "./session/compaction/index.js";
10
10
  export { createEventBus, type EventBus, type EventBusController, } from "./runtime/event-bus.js";
11
11
  export { type AgentEndEvent, type AgentStartEvent, type AgentToolResult, type AgentToolUpdateCallback, type BeforeAgentStartEvent, type ContextEvent, discoverAndLoadExtensions, type ExecOptions, type ExecResult, type Extension, type ExtensionAPI, type ExtensionCommandContext, type ExtensionContext, type ExtensionError, type ExtensionEvent, type ExtensionFactory, type ExtensionFlag, type ExtensionHandler, ExtensionRunner, type ExtensionShortcut, type ExtensionUIContext, type LoadExtensionsResult, type MessageRenderer, type RegisteredCommand, type SessionBeforeCompactEvent, type SessionBeforeForkEvent, type SessionBeforeSwitchEvent, type SessionBeforeTreeEvent, type SessionCompactEvent, type SessionForkEvent, type SessionShutdownEvent, type SessionStartEvent, type SessionSwitchEvent, type SessionTreeEvent, type ToolCallEvent, type ToolDefinition, type ToolRenderResultOptions, type ToolResultEvent, type TurnEndEvent, type TurnStartEvent, wrapToolsWithExtensions, } from "./extensions/index.js";
12
12
  export { MCPManager } from "./mcp-manager.js";
13
+ export { getDebugLogger, createDebugLogger, debug, type DebugLogLevel, } from "../packages/ai/dist/debug-logger.js";
13
14
  export type { MCPServerConfig, MCPTool, MCPToolResult, } from "./mcp/mcp-client.js";
14
15
  export { loadMCPConfig, saveMCPConfig, addMCPServer, removeMCPServer, getMCPServer, listMCPServers, listEnabledMCPServers, } from "./mcp/mcp-config.js";
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -11,5 +11,7 @@ export { createEventBus, } from "./runtime/event-bus.js";
11
11
  export { discoverAndLoadExtensions, ExtensionRunner, wrapToolsWithExtensions, } from "./extensions/index.js";
12
12
  // MCP (Model Context Protocol) support
13
13
  export { MCPManager } from "./mcp-manager.js";
14
+ // Debug logging (re-exported from ai package)
15
+ export { getDebugLogger, createDebugLogger, debug, } from "../packages/ai/dist/debug-logger.js";
14
16
  export { loadMCPConfig, saveMCPConfig, addMCPServer, removeMCPServer, getMCPServer, listMCPServers, listEnabledMCPServers, } from "./mcp/mcp-config.js";
15
17
  //# sourceMappingURL=index.js.map
@@ -40,7 +40,7 @@ export declare class ModelSwitcher {
40
40
  */
41
41
  hasApiKey(model: Model<any>): Promise<boolean>;
42
42
  /**
43
- * Get models with API keys
43
+ * Get models with API keys (async, validates OAuth tokens)
44
44
  */
45
45
  getModelsWithApiKey(): Promise<Model<any>[]>;
46
46
  /**
@@ -60,6 +60,7 @@ export declare class ModelSwitcher {
60
60
  private cycleScopedModel;
61
61
  /**
62
62
  * Cycle through all available models
63
+ * Skips models with expired OAuth tokens.
63
64
  */
64
65
  private cycleAvailableModel;
65
66
  /**
@@ -20,13 +20,14 @@ export class ModelSwitcher {
20
20
  return !!apiKey;
21
21
  }
22
22
  /**
23
- * Get models with API keys
23
+ * Get models with API keys (async, validates OAuth tokens)
24
24
  */
25
25
  async getModelsWithApiKey() {
26
26
  const available = this.options.getAvailableModels();
27
27
  const result = [];
28
28
  for (const model of available) {
29
- if (await this.hasApiKey(model)) {
29
+ const apiKey = await this.options.getApiKey(model);
30
+ if (apiKey) {
30
31
  result.push(model);
31
32
  }
32
33
  }
@@ -89,9 +90,10 @@ export class ModelSwitcher {
89
90
  }
90
91
  /**
91
92
  * Cycle through all available models
93
+ * Skips models with expired OAuth tokens.
92
94
  */
93
95
  async cycleAvailableModel(direction) {
94
- const available = await this.getModelsWithApiKey();
96
+ const available = this.options.getAvailableModels();
95
97
  if (available.length <= 1)
96
98
  return undefined;
97
99
  const currentModel = this.getModel();
@@ -99,11 +101,32 @@ export class ModelSwitcher {
99
101
  if (currentIndex === -1)
100
102
  currentIndex = 0;
101
103
  const len = available.length;
102
- const nextIndex = direction === "forward"
103
- ? (currentIndex + 1) % len
104
- : (currentIndex - 1 + len) % len;
105
- const next = available[nextIndex];
104
+ // Find next model with valid API key, skipping expired OAuth tokens
105
+ let nextIndex = currentIndex;
106
+ let attempts = 0;
107
+ let next;
106
108
  const previousModel = currentModel;
109
+ while (attempts < len - 1) {
110
+ attempts++;
111
+ nextIndex =
112
+ direction === "forward"
113
+ ? (nextIndex + 1) % len
114
+ : (nextIndex - 1 + len) % len;
115
+ const candidate = available[nextIndex];
116
+ if (!candidate)
117
+ continue;
118
+ // Use async getApiKey to validate OAuth tokens
119
+ const apiKey = await this.options.getApiKey(candidate);
120
+ if (apiKey) {
121
+ next = candidate;
122
+ break;
123
+ }
124
+ // No valid key - skip this model and continue cycling
125
+ }
126
+ if (!next) {
127
+ // No models have valid API keys
128
+ return undefined;
129
+ }
107
130
  // Set the new model
108
131
  this.options.setModelOnAgent(next);
109
132
  return {
@@ -58,6 +58,11 @@ export declare class ModelRegistry {
58
58
  * This is a fast check that doesn't refresh OAuth tokens.
59
59
  */
60
60
  getAvailable(): Model<Api>[];
61
+ /**
62
+ * Get models with valid API keys (async, validates OAuth tokens).
63
+ * This checks and refreshes OAuth tokens, filtering out expired ones.
64
+ */
65
+ getAvailableAsync(): Promise<Model<Api>[]>;
61
66
  /**
62
67
  * Find a model by provider and ID.
63
68
  */
@@ -83,6 +88,15 @@ export declare class ModelRegistry {
83
88
  */
84
89
  registerProvider(providerName: string, config: ProviderConfigInput): void;
85
90
  private applyProviderConfig;
91
+ private static readonly OPENROUTER_JSON_BASE;
92
+ private static readonly OPENROUTER_JSON_API;
93
+ /**
94
+ * Append an OpenRouter model to models.json by id (same string as on openrouter.ai, e.g. x-ai/grok-4.20).
95
+ * API key is not written; use /login openrouter or OPENROUTER_API_KEY.
96
+ */
97
+ appendOpenRouterModel(modelId: string, options?: {
98
+ name?: string;
99
+ }): void;
86
100
  }
87
101
  /**
88
102
  * Input type for registerProvider API.
@@ -7,7 +7,7 @@
7
7
  import { getModels, getProviders, registerApiProvider, registerOAuthProvider, } from "@pencil-agent/ai";
8
8
  import { Type } from "@sinclair/typebox";
9
9
  import AjvModule from "ajv";
10
- import { existsSync, readFileSync } from "fs";
10
+ import { existsSync, readFileSync, writeFileSync } from "fs";
11
11
  import { join } from "path";
12
12
  import { getAgentDir } from "../config.js";
13
13
  import { clearConfigValueCache, resolveConfigValue, resolveHeaders } from "./config/resolve-config-value.js";
@@ -411,6 +411,20 @@ export class ModelRegistry {
411
411
  getAvailable() {
412
412
  return this.models.filter((m) => this.authStorage.hasAuth(m.provider));
413
413
  }
414
+ /**
415
+ * Get models with valid API keys (async, validates OAuth tokens).
416
+ * This checks and refreshes OAuth tokens, filtering out expired ones.
417
+ */
418
+ async getAvailableAsync() {
419
+ const result = [];
420
+ for (const model of this.models) {
421
+ const apiKey = await this.authStorage.getApiKey(model.provider);
422
+ if (apiKey) {
423
+ result.push(model);
424
+ }
425
+ }
426
+ return result;
427
+ }
414
428
  /**
415
429
  * Find a model by provider and ID.
416
430
  */
@@ -536,5 +550,54 @@ export class ModelRegistry {
536
550
  });
537
551
  }
538
552
  }
553
+ static OPENROUTER_JSON_BASE = "https://openrouter.ai/api/v1";
554
+ static OPENROUTER_JSON_API = "openai-completions";
555
+ /**
556
+ * Append an OpenRouter model to models.json by id (same string as on openrouter.ai, e.g. x-ai/grok-4.20).
557
+ * API key is not written; use /login openrouter or OPENROUTER_API_KEY.
558
+ */
559
+ appendOpenRouterModel(modelId, options) {
560
+ const providerKey = "openrouter";
561
+ const trimmed = modelId.trim();
562
+ if (!trimmed) {
563
+ throw new Error("OpenRouter model id cannot be empty");
564
+ }
565
+ const modelsPath = this.modelsJsonPath;
566
+ if (!modelsPath) {
567
+ throw new Error("models.json path is not configured");
568
+ }
569
+ let data;
570
+ if (existsSync(modelsPath)) {
571
+ const raw = readFileSync(modelsPath, "utf-8");
572
+ data = JSON.parse(raw);
573
+ }
574
+ else {
575
+ data = { providers: {} };
576
+ }
577
+ if (!data.providers || typeof data.providers !== "object") {
578
+ data.providers = {};
579
+ }
580
+ const existing = data.providers[providerKey] ?? {};
581
+ const prevModels = Array.isArray(existing.models) ? [...existing.models] : [];
582
+ if (prevModels.some((m) => m && typeof m === "object" && m.id === trimmed)) {
583
+ throw new Error(`OpenRouter model "${trimmed}" already exists in models.json`);
584
+ }
585
+ const displayName = options?.name?.trim() || trimmed;
586
+ prevModels.push({
587
+ id: trimmed,
588
+ name: displayName,
589
+ input: ["text"],
590
+ contextWindow: 256000,
591
+ maxTokens: 8192,
592
+ });
593
+ data.providers[providerKey] = {
594
+ ...existing,
595
+ baseUrl: existing.baseUrl ?? ModelRegistry.OPENROUTER_JSON_BASE,
596
+ api: existing.api ?? ModelRegistry.OPENROUTER_JSON_API,
597
+ models: prevModels,
598
+ };
599
+ writeFileSync(modelsPath, JSON.stringify(data, null, 2), "utf-8");
600
+ this.refresh();
601
+ }
539
602
  }
540
603
  //# sourceMappingURL=model-registry.js.map
@@ -1,5 +1,13 @@
1
1
  import type { Agent, AgentEvent, AgentMessage, AgentState, AgentTool, ThinkingLevel } from "@pencil-agent/agent-core";
2
2
  import type { ImageContent, Model, TextContent } from "@pencil-agent/ai";
3
+ /**
4
+ * Custom error for model cycling with additional context.
5
+ */
6
+ export declare class CycleModelError extends Error {
7
+ readonly provider?: string | undefined;
8
+ readonly code?: "oauth_expired" | "no_valid_key" | "api_error" | undefined;
9
+ constructor(message: string, provider?: string | undefined, code?: "oauth_expired" | "no_valid_key" | "api_error" | undefined);
10
+ }
3
11
  import { type BashResult } from "../bash-executor.js";
4
12
  import { type CompactionResult } from "../session/compaction/index.js";
5
13
  import { CompactionCoordinator } from "../session/compaction/compaction-coordinator.js";
@@ -19,6 +19,19 @@ import { getDocsPath } from "../../config.js";
19
19
  import { theme } from "../../modes/interactive/theme/theme.js";
20
20
  import { stripFrontmatter } from "../../utils/frontmatter.js";
21
21
  import { sleep } from "../utils/sleep.js";
22
+ /**
23
+ * Custom error for model cycling with additional context.
24
+ */
25
+ export class CycleModelError extends Error {
26
+ provider;
27
+ code;
28
+ constructor(message, provider, code) {
29
+ super(message);
30
+ this.provider = provider;
31
+ this.code = code;
32
+ this.name = "CycleModelError";
33
+ }
34
+ }
22
35
  import { executeBash as executeBashCommand, executeBashWithOperations, } from "../bash-executor.js";
23
36
  import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, generateBranchSummary, prepareCompaction, shouldCompact, } from "../session/compaction/index.js";
24
37
  import { CompactionCoordinator } from "../session/compaction/compaction-coordinator.js";
@@ -1190,7 +1203,8 @@ export class AgentSession {
1190
1203
  };
1191
1204
  }
1192
1205
  async _cycleAvailableModel(direction) {
1193
- const availableModels = await this._modelRegistry.getAvailable();
1206
+ // Use getAvailableAsync to pre-filter models with invalid OAuth tokens
1207
+ const availableModels = await this._modelRegistry.getAvailableAsync();
1194
1208
  if (availableModels.length <= 1)
1195
1209
  return undefined;
1196
1210
  const currentModel = this.model;
@@ -1198,13 +1212,38 @@ export class AgentSession {
1198
1212
  if (currentIndex === -1)
1199
1213
  currentIndex = 0;
1200
1214
  const len = availableModels.length;
1201
- const nextIndex = direction === "forward"
1202
- ? (currentIndex + 1) % len
1203
- : (currentIndex - 1 + len) % len;
1204
- const nextModel = availableModels[nextIndex];
1205
- const apiKey = await this._modelRegistry.getApiKey(nextModel);
1206
- if (!apiKey) {
1207
- throw new Error(`No API key for ${nextModel.provider}/${nextModel.id}`);
1215
+ // Find next model with valid API key, skipping expired OAuth tokens
1216
+ // Start from nextIndex and loop through all models
1217
+ const startIndex = currentIndex;
1218
+ let nextIndex = currentIndex;
1219
+ let attempts = 0;
1220
+ let nextModel;
1221
+ let apiKey;
1222
+ while (attempts < len - 1) {
1223
+ attempts++;
1224
+ nextIndex =
1225
+ direction === "forward"
1226
+ ? (nextIndex + 1) % len
1227
+ : (nextIndex - 1 + len) % len;
1228
+ const candidate = availableModels[nextIndex];
1229
+ if (!candidate)
1230
+ continue;
1231
+ // Use async getApiKey to validate OAuth tokens
1232
+ apiKey = await this._modelRegistry.getApiKey(candidate);
1233
+ if (apiKey) {
1234
+ nextModel = candidate;
1235
+ break;
1236
+ }
1237
+ // No valid key - skip this model and continue cycling
1238
+ }
1239
+ if (!nextModel || !apiKey) {
1240
+ // No models have valid API keys (all OAuth tokens expired or no keys)
1241
+ const provider = currentModel?.provider;
1242
+ const cred = provider ? this._modelRegistry.authStorage.get(provider) : undefined;
1243
+ if (cred?.type === "oauth") {
1244
+ throw new CycleModelError(`All available models have expired OAuth tokens. Use /login ${provider} to re-authenticate.`, provider, "oauth_expired");
1245
+ }
1246
+ throw new CycleModelError(`No models with valid API keys available`, provider, "no_valid_key");
1208
1247
  }
1209
1248
  this.agent.setModel(nextModel);
1210
1249
  this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
@@ -1,6 +1,6 @@
1
1
  /**
2
- * [UPSTREAM]: Depends on @pencil-agent/tui
3
- * [SURFACE]: CustomEditor
2
+ * [UPSTREAM]:
3
+ * [SURFACE]:
4
4
  * [LOCUS]: modes/interactive/components/custom-editor.ts -
5
5
  * [COVENANT]: Change → update this header
6
6
  */
@@ -17,6 +17,8 @@ export declare class CustomEditor extends Editor {
17
17
  onPasteImage?: () => void;
18
18
  /** Handler for extension-registered shortcuts. Returns true if handled. */
19
19
  onExtensionShortcut?: (data: string) => boolean;
20
+ /** Handler for attachment navigation (arrow keys, delete). Returns true if handled. */
21
+ onAttachmentKey?: (data: string) => boolean;
20
22
  constructor(tui: TUI, theme: EditorTheme, keybindings: KeybindingsManager, options?: EditorOptions);
21
23
  /**
22
24
  * Register a handler for an app action.
@@ -1,10 +1,10 @@
1
1
  /**
2
- * [UPSTREAM]: Depends on @pencil-agent/tui
3
- * [SURFACE]: CustomEditor
2
+ * [UPSTREAM]:
3
+ * [SURFACE]:
4
4
  * [LOCUS]: modes/interactive/components/custom-editor.ts -
5
5
  * [COVENANT]: Change → update this header
6
6
  */
7
- import { Editor } from "@pencil-agent/tui";
7
+ import { Editor, getEditorKeybindings, matchesKey } from "@pencil-agent/tui";
8
8
  /**
9
9
  * Custom editor that handles app-level keybindings for coding-agent.
10
10
  */
@@ -17,6 +17,8 @@ export class CustomEditor extends Editor {
17
17
  onPasteImage;
18
18
  /** Handler for extension-registered shortcuts. Returns true if handled. */
19
19
  onExtensionShortcut;
20
+ /** Handler for attachment navigation (arrow keys, delete). Returns true if handled. */
21
+ onAttachmentKey;
20
22
  constructor(tui, theme, keybindings, options) {
21
23
  super(tui, theme, options);
22
24
  this.keybindings = keybindings;
@@ -32,10 +34,19 @@ export class CustomEditor extends Editor {
32
34
  if (this.onExtensionShortcut?.(data)) {
33
35
  return;
34
36
  }
35
- // Check for paste image keybinding
36
- if (this.keybindings.matches(data, "pasteImage")) {
37
- this.onPasteImage?.();
38
- return;
37
+ // Detect image paste via empty bracketed paste — the terminal sends an
38
+ // empty bracket sequence when the clipboard contains an image (since
39
+ // raw image bytes can't be pasted as text). This is the ONLY trigger
40
+ // for clipboard image reading; we intentionally do NOT intercept the
41
+ // raw Ctrl+V key code because Windows keeps stale image data in the
42
+ // clipboard even after the user copies text, which would cause the
43
+ // wrong content to be pasted.
44
+ if (this.onPasteImage && data.includes("\x1b[200~") && data.includes("\x1b[201~")) {
45
+ const content = data.replace("\x1b[200~", "").replace("\x1b[201~", "").trim();
46
+ if (content.length === 0) {
47
+ this.onPasteImage();
48
+ return;
49
+ }
39
50
  }
40
51
  // Check app keybindings first
41
52
  // Escape/interrupt - only if autocomplete is NOT active
@@ -69,6 +80,21 @@ export class CustomEditor extends Editor {
69
80
  return;
70
81
  }
71
82
  }
83
+ // Forward navigation/delete keys to the attachment handler. The handler
84
+ // only consumes them when appropriate (e.g. Delete only when an
85
+ // attachment is selected), otherwise returns false so the editor
86
+ // processes the key normally.
87
+ if (this.onAttachmentKey) {
88
+ const kb = getEditorKeybindings();
89
+ if (kb.matches(data, "cursorUp") ||
90
+ kb.matches(data, "cursorDown") ||
91
+ matchesKey(data, "delete") ||
92
+ matchesKey(data, "backspace")) {
93
+ if (this.onAttachmentKey(data)) {
94
+ return;
95
+ }
96
+ }
97
+ }
72
98
  // Pass to parent for editor handling
73
99
  super.handleInput(data);
74
100
  }
@@ -5,6 +5,7 @@
5
5
  * [COVENANT]: Change components → update this header
6
6
  */
7
7
  export { ArminComponent } from "./armin.js";
8
+ export { AttachmentsBarComponent } from "./attachments-bar.js";
8
9
  export { AssistantMessageComponent } from "./assistant-message.js";
9
10
  export { promptForApiKey } from "./apikey-input.js";
10
11
  export { BashExecutionComponent } from "./bash-execution.js";
@@ -6,6 +6,7 @@
6
6
  */
7
7
  // UI Components for extensions
8
8
  export { ArminComponent } from "./armin.js";
9
+ export { AttachmentsBarComponent } from "./attachments-bar.js";
9
10
  export { AssistantMessageComponent } from "./assistant-message.js";
10
11
  export { promptForApiKey } from "./apikey-input.js";
11
12
  export { BashExecutionComponent } from "./bash-execution.js";
@@ -35,9 +35,11 @@ export declare class ModelSelectorComponent extends Container implements Focusab
35
35
  private scopeText?;
36
36
  private scopeHintText?;
37
37
  private filterByProvider?;
38
+ /** When set, Ctrl+N runs this (parent closes selector and prompts for OpenRouter model id). */
39
+ private onAddOpenRouterModel?;
38
40
  get focused(): boolean;
39
41
  set focused(value: boolean);
40
- constructor(tui: TUI, currentModel: Model<any> | undefined, settingsManager: SettingsManager, modelRegistry: ModelRegistry, scopedModels: ReadonlyArray<ScopedModelItem>, ensureProviderConfigured: EnsureProviderConfigured | undefined, onSelect: (model: Model<any>) => void, onCancel: () => void, initialSearchInput?: string, filterByProvider?: string);
42
+ constructor(tui: TUI, currentModel: Model<any> | undefined, settingsManager: SettingsManager, modelRegistry: ModelRegistry, scopedModels: ReadonlyArray<ScopedModelItem>, ensureProviderConfigured: EnsureProviderConfigured | undefined, onSelect: (model: Model<any>) => void, onCancel: () => void, initialSearchInput?: string, filterByProvider?: string, onAddOpenRouterModel?: () => void);
41
43
  private loadModels;
42
44
  private sortModels;
43
45
  private getScopeText;
@@ -5,7 +5,7 @@
5
5
  * [COVENANT]: Change → update this header
6
6
  */
7
7
  import { modelsAreEqual } from "@pencil-agent/ai";
8
- import { Container, fuzzyFilter, getEditorKeybindings, Input, Spacer, Text, } from "@pencil-agent/tui";
8
+ import { Container, fuzzyFilter, getEditorKeybindings, Input, matchesKey, Spacer, Text, } from "@pencil-agent/tui";
9
9
  import { theme } from "../theme/theme.js";
10
10
  import { promptForApiKey } from "./apikey-input.js";
11
11
  import { DynamicBorder } from "./dynamic-border.js";
@@ -32,6 +32,8 @@ export class ModelSelectorComponent extends Container {
32
32
  scopeText;
33
33
  scopeHintText;
34
34
  filterByProvider;
35
+ /** When set, Ctrl+N runs this (parent closes selector and prompts for OpenRouter model id). */
36
+ onAddOpenRouterModel;
35
37
  get focused() {
36
38
  return this._focused;
37
39
  }
@@ -39,7 +41,7 @@ export class ModelSelectorComponent extends Container {
39
41
  this._focused = value;
40
42
  this.searchInput.focused = value;
41
43
  }
42
- constructor(tui, currentModel, settingsManager, modelRegistry, scopedModels, ensureProviderConfigured, onSelect, onCancel, initialSearchInput, filterByProvider) {
44
+ constructor(tui, currentModel, settingsManager, modelRegistry, scopedModels, ensureProviderConfigured, onSelect, onCancel, initialSearchInput, filterByProvider, onAddOpenRouterModel) {
43
45
  super();
44
46
  this.tui = tui;
45
47
  this.currentModel = currentModel;
@@ -48,6 +50,7 @@ export class ModelSelectorComponent extends Container {
48
50
  this.scopedModels = scopedModels;
49
51
  this.ensureProviderConfigured = ensureProviderConfigured;
50
52
  this.filterByProvider = filterByProvider;
53
+ this.onAddOpenRouterModel = onAddOpenRouterModel;
51
54
  this.scope = scopedModels.length > 0 && !filterByProvider ? "scoped" : "all";
52
55
  this.onSelectCallback = onSelect;
53
56
  this.onCancelCallback = onCancel;
@@ -73,6 +76,10 @@ export class ModelSelectorComponent extends Container {
73
76
  }
74
77
  };
75
78
  this.addChild(this.searchInput);
79
+ if (this.onAddOpenRouterModel) {
80
+ this.addChild(new Spacer(1));
81
+ this.addChild(new Text(theme.fg("muted", "Ctrl+N: add OpenRouter model by id (same as openrouter.ai)"), 0, 0));
82
+ }
76
83
  this.addChild(new Spacer(1));
77
84
  this.listContainer = new Container();
78
85
  this.addChild(this.listContainer);
@@ -255,38 +262,63 @@ export class ModelSelectorComponent extends Container {
255
262
  else if (kb.matches(keyData, "selectCancel")) {
256
263
  this.onCancelCallback();
257
264
  }
265
+ else if (this.onAddOpenRouterModel && matchesKey(keyData, "ctrl+n")) {
266
+ this.onAddOpenRouterModel();
267
+ }
258
268
  else {
259
269
  this.searchInput.handleInput(keyData);
260
270
  this.filterModels(this.searchInput.getValue());
261
271
  }
262
272
  }
263
273
  async handleSelect(model) {
264
- if (this.ensureProviderConfigured) {
265
- const ready = await this.ensureProviderConfigured(model);
266
- if (!ready)
267
- return;
268
- this.modelRegistry.refresh();
274
+ try {
275
+ if (this.ensureProviderConfigured) {
276
+ const ready = await this.ensureProviderConfigured(model);
277
+ if (!ready) {
278
+ this.onCancelCallback();
279
+ return;
280
+ }
281
+ this.modelRegistry.refresh();
282
+ }
283
+ // Use async getApiKey to validate OAuth tokens (hasAuth is sync and doesn't refresh)
284
+ const apiKey = await this.modelRegistry.authStorage.getApiKey(model.provider);
285
+ if (!apiKey) {
286
+ // Check if this is an OAuth provider with expired/invalid token
287
+ const cred = this.modelRegistry.authStorage.get(model.provider);
288
+ if (cred?.type === "oauth") {
289
+ // OAuth token expired or refresh failed - prompt user to re-login
290
+ // Note: onSelectCallback will handle showing error and suggesting /login
291
+ this.onSelectCallback(model);
292
+ return;
293
+ }
294
+ // Non-OAuth provider without key - prompt for API key input
295
+ const providerHints = {
296
+ "dashscope-coding": "DashScope API key (sk-sp-...)",
297
+ "qianfan-coding": "Qianfan API key",
298
+ "ark-coding": "Ark API key",
299
+ openrouter: "OpenRouter API key",
300
+ };
301
+ const prompt = providerHints[model.provider] ?? `${model.provider} API key`;
302
+ const key = await promptForApiKey({ prompt: `Enter ${prompt}` });
303
+ if (!key) {
304
+ this.onCancelCallback();
305
+ return;
306
+ }
307
+ this.modelRegistry.authStorage.set(model.provider, {
308
+ type: "api_key",
309
+ key,
310
+ });
311
+ this.modelRegistry.refresh();
312
+ }
313
+ const refreshedModel = this.modelRegistry.find(model.provider, model.id) ?? model;
314
+ this.settingsManager.setDefaultModelAndProvider(refreshedModel.provider, refreshedModel.id);
315
+ this.onSelectCallback(refreshedModel);
269
316
  }
270
- if (!this.modelRegistry.authStorage.hasAuth(model.provider)) {
271
- const providerHints = {
272
- "dashscope-coding": "DashScope API key (sk-sp-...)",
273
- "qianfan-coding": "Qianfan API key",
274
- "ark-coding": "Ark API key",
275
- openrouter: "OpenRouter API key",
276
- };
277
- const prompt = providerHints[model.provider] ?? `${model.provider} API key`;
278
- const key = await promptForApiKey({ prompt: `Enter ${prompt}` });
279
- if (!key)
280
- return;
281
- this.modelRegistry.authStorage.set(model.provider, {
282
- type: "api_key",
283
- key,
284
- });
285
- this.modelRegistry.refresh();
317
+ catch (error) {
318
+ // Ensure selector is closed on any error
319
+ this.onCancelCallback();
320
+ throw error;
286
321
  }
287
- const refreshedModel = this.modelRegistry.find(model.provider, model.id) ?? model;
288
- this.settingsManager.setDefaultModelAndProvider(refreshedModel.provider, refreshedModel.id);
289
- this.onSelectCallback(refreshedModel);
290
322
  }
291
323
  getSearchInput() {
292
324
  return this.searchInput;