@xopcai/xopc 0.0.29 → 0.0.31

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 (632) hide show
  1. package/dist/extensions/telegram/src/adapters/config-surface.js +3 -1
  2. package/dist/extensions/telegram/src/adapters/config-surface.js.map +1 -1
  3. package/dist/extensions/telegram/src/adapters/onboard-cli.js +23 -21
  4. package/dist/extensions/telegram/src/adapters/onboard-cli.js.map +1 -1
  5. package/dist/extensions/telegram/src/adapters/setup-wizard.js +3 -4
  6. package/dist/extensions/telegram/src/adapters/setup-wizard.js.map +1 -1
  7. package/dist/extensions/telegram/src/config-schema.d.ts +0 -1
  8. package/dist/extensions/telegram/src/config-schema.js +17 -4
  9. package/dist/extensions/telegram/src/config-schema.js.map +1 -1
  10. package/dist/extensions/telegram/src/plugin.js +4 -17
  11. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  12. package/dist/extensions/telegram/xopc.extension.json +1 -1
  13. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  14. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  15. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  16. package/dist/gateway/static/root/assets/agents-3u63Fw2Y.js +216 -0
  17. package/dist/gateway/static/root/assets/agents-3u63Fw2Y.js.map +1 -0
  18. package/dist/gateway/static/root/assets/{apps-page-Bmq19MS-.js → apps-page-CWegY6Kp.js} +2 -2
  19. package/dist/gateway/static/root/assets/{apps-page-Bmq19MS-.js.map → apps-page-CWegY6Kp.js.map} +1 -1
  20. package/dist/gateway/static/root/assets/channels-settings-CiyeXcTK.js +9 -0
  21. package/dist/gateway/static/root/assets/channels-settings-CiyeXcTK.js.map +1 -0
  22. package/dist/gateway/static/root/assets/cron-api-_j_79Zf5.js +3 -0
  23. package/dist/gateway/static/root/assets/cron-api-_j_79Zf5.js.map +1 -0
  24. package/dist/gateway/static/root/assets/cron-page-S86YNTtI.js +2 -0
  25. package/dist/gateway/static/root/assets/cron-page-S86YNTtI.js.map +1 -0
  26. package/dist/gateway/static/root/assets/dist-D0jxbvuz.js +2 -0
  27. package/dist/gateway/static/root/assets/{dist--p2HQ2QF.js.map → dist-D0jxbvuz.js.map} +1 -1
  28. package/dist/gateway/static/root/assets/{extension-debug-page-DwHCB_6T.js → extension-debug-page-DB630cW8.js} +2 -2
  29. package/dist/gateway/static/root/assets/{extension-debug-page-DwHCB_6T.js.map → extension-debug-page-DB630cW8.js.map} +1 -1
  30. package/dist/gateway/static/root/assets/{extension-page-BsYwQIex.js → extension-page-CnoPUBul.js} +2 -2
  31. package/dist/gateway/static/root/assets/{extension-page-BsYwQIex.js.map → extension-page-CnoPUBul.js.map} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-settings-page-nsisEgjB.js → extension-settings-page-BsiOkvBe.js} +2 -2
  33. package/dist/gateway/static/root/assets/{extension-settings-page-nsisEgjB.js.map → extension-settings-page-BsiOkvBe.js.map} +1 -1
  34. package/dist/gateway/static/root/assets/{index-CR8zUHGR.js → index-DHLmAIQl.js} +63 -63
  35. package/dist/gateway/static/root/assets/{index-CR8zUHGR.js.map → index-DHLmAIQl.js.map} +1 -1
  36. package/dist/gateway/static/root/assets/index-DoPwy4aU.css +1 -0
  37. package/dist/gateway/static/root/assets/logs-page-Bndhenn2.js +2 -0
  38. package/dist/gateway/static/root/assets/logs-page-Bndhenn2.js.map +1 -0
  39. package/dist/gateway/static/root/assets/sessions-page-Q201-_lP.js +2 -0
  40. package/dist/gateway/static/root/assets/{sessions-page-Be5kIGl_.js.map → sessions-page-Q201-_lP.js.map} +1 -1
  41. package/dist/gateway/static/root/assets/settings-page-Cw75fpc6.js +2 -0
  42. package/dist/gateway/static/root/assets/settings-page-Cw75fpc6.js.map +1 -0
  43. package/dist/gateway/static/root/assets/skills-page-CVwEzD_J.js +3 -0
  44. package/dist/gateway/static/root/assets/skills-page-CVwEzD_J.js.map +1 -0
  45. package/dist/gateway/static/root/index.html +2 -2
  46. package/dist/package.js +1 -1
  47. package/dist/src/agent/agent-manager.d.ts +5 -7
  48. package/dist/src/agent/agent-manager.js +21 -19
  49. package/dist/src/agent/agent-manager.js.map +1 -1
  50. package/dist/src/agent/ipc/inbox.js +4 -2
  51. package/dist/src/agent/ipc/inbox.js.map +1 -1
  52. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  53. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  54. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
  55. package/dist/src/agent/prompt/service-prompt-builder.js +0 -2
  56. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  57. package/dist/src/agent/prompt/system-prompt.d.ts +0 -2
  58. package/dist/src/agent/prompt/system-prompt.js +3 -17
  59. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  60. package/dist/src/agent/service/btw-query.d.ts +16 -0
  61. package/dist/src/agent/service/btw-query.js +88 -0
  62. package/dist/src/agent/service/btw-query.js.map +1 -0
  63. package/dist/src/agent/service/build-direct-message-content.d.ts +30 -0
  64. package/dist/src/agent/service/build-direct-message-content.js +75 -0
  65. package/dist/src/agent/service/build-direct-message-content.js.map +1 -0
  66. package/dist/src/agent/service/parse-outbound-session-key.d.ts +8 -0
  67. package/dist/src/agent/service/parse-outbound-session-key.js +41 -0
  68. package/dist/src/agent/service/parse-outbound-session-key.js.map +1 -0
  69. package/dist/src/agent/service/process-direct-one-shot.d.ts +34 -0
  70. package/dist/src/agent/service/process-direct-one-shot.js +67 -0
  71. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -0
  72. package/dist/src/agent/service/process-direct-streaming.js +12 -1
  73. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  74. package/dist/src/agent/service/reconcile-dreaming-cron.d.ts +6 -0
  75. package/dist/src/agent/service/reconcile-dreaming-cron.js +70 -0
  76. package/dist/src/agent/service/reconcile-dreaming-cron.js.map +1 -0
  77. package/dist/src/agent/service/session-context-report.d.ts +19 -0
  78. package/dist/src/agent/service/session-context-report.js +47 -0
  79. package/dist/src/agent/service/session-context-report.js.map +1 -0
  80. package/dist/src/agent/service/webchat-tts.d.ts +28 -0
  81. package/dist/src/agent/service/webchat-tts.js +73 -0
  82. package/dist/src/agent/service/webchat-tts.js.map +1 -0
  83. package/dist/src/agent/service.d.ts +8 -12
  84. package/dist/src/agent/service.js +74 -379
  85. package/dist/src/agent/service.js.map +1 -1
  86. package/dist/src/agent/skills/config.js +4 -3
  87. package/dist/src/agent/skills/config.js.map +1 -1
  88. package/dist/src/agent/skills/format-skills-prompt.d.ts +0 -2
  89. package/dist/src/agent/skills/format-skills-prompt.js +3 -24
  90. package/dist/src/agent/skills/format-skills-prompt.js.map +1 -1
  91. package/dist/src/agent/skills/hub-lock.js +4 -5
  92. package/dist/src/agent/skills/hub-lock.js.map +1 -1
  93. package/dist/src/agent/skills/index.js +9 -21
  94. package/dist/src/agent/skills/index.js.map +1 -1
  95. package/dist/src/agent/skills/marketplace/adapter.types.d.ts +17 -0
  96. package/dist/src/agent/skills/marketplace/adapter.types.js +1 -0
  97. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.d.ts +2 -0
  98. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +292 -0
  99. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -0
  100. package/dist/src/agent/skills/marketplace/adapters/skillhub/ecosystem-client.d.ts +73 -0
  101. package/dist/src/agent/skills/marketplace/adapters/skillhub/ecosystem-client.js +200 -0
  102. package/dist/src/agent/skills/marketplace/adapters/skillhub/ecosystem-client.js.map +1 -0
  103. package/dist/src/agent/skills/marketplace/adapters/skillhub/registry-client.d.ts +137 -0
  104. package/dist/src/agent/skills/marketplace/adapters/skillhub/registry-client.js +217 -0
  105. package/dist/src/agent/skills/marketplace/adapters/skillhub/registry-client.js.map +1 -0
  106. package/dist/src/agent/skills/marketplace/adapters/skillhub/skillhub-fetch-cache.d.ts +12 -0
  107. package/dist/src/agent/skills/marketplace/adapters/skillhub/skillhub-fetch-cache.js +90 -0
  108. package/dist/src/agent/skills/marketplace/adapters/skillhub/skillhub-fetch-cache.js.map +1 -0
  109. package/dist/src/agent/skills/marketplace/adapters/store/adapter.d.ts +2 -0
  110. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +35 -0
  111. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -0
  112. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +124 -0
  113. package/dist/src/agent/skills/{skills-store-client.js → marketplace/adapters/store/store-api-client.js} +4 -3
  114. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -0
  115. package/dist/src/agent/skills/marketplace/resolve-adapter.d.ts +6 -0
  116. package/dist/src/agent/skills/marketplace/resolve-adapter.js +26 -0
  117. package/dist/src/agent/skills/marketplace/resolve-adapter.js.map +1 -0
  118. package/dist/src/agent/skills/parse-skill-metadata.d.ts +5 -0
  119. package/dist/src/agent/skills/parse-skill-metadata.js +27 -0
  120. package/dist/src/agent/skills/parse-skill-metadata.js.map +1 -0
  121. package/dist/src/agent/skills/skill-markdown-preview-from-raw.d.ts +6 -0
  122. package/dist/src/agent/skills/skill-markdown-preview-from-raw.js +64 -0
  123. package/dist/src/agent/skills/skill-markdown-preview-from-raw.js.map +1 -0
  124. package/dist/src/agent/skills/skill-view-path.d.ts +17 -1
  125. package/dist/src/agent/skills/skill-view-path.js +66 -3
  126. package/dist/src/agent/skills/skill-view-path.js.map +1 -1
  127. package/dist/src/agent/skills/skills-marketplace.d.ts +21 -0
  128. package/dist/src/agent/skills/skills-marketplace.js +18 -0
  129. package/dist/src/agent/skills/skills-marketplace.js.map +1 -0
  130. package/dist/src/agent/skills/test-framework.d.ts +0 -1
  131. package/dist/src/agent/skills/test-framework.js +2 -20
  132. package/dist/src/agent/skills/test-framework.js.map +1 -1
  133. package/dist/src/agent/skills/types.d.ts +12 -6
  134. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  135. package/dist/src/agent/tools/image-generate-tool.js +2 -2
  136. package/dist/src/auth/credentials.js +8 -6
  137. package/dist/src/auth/credentials.js.map +1 -1
  138. package/dist/src/auth/profiles/store.js +5 -3
  139. package/dist/src/auth/profiles/store.js.map +1 -1
  140. package/dist/src/channels/manager.js +1 -1
  141. package/dist/src/channels/outbound/persist-store.js +4 -4
  142. package/dist/src/channels/outbound/persist-store.js.map +1 -1
  143. package/dist/src/cli/commands/config.js +8 -6
  144. package/dist/src/cli/commands/config.js.map +1 -1
  145. package/dist/src/cli/commands/doctor/checks/channel-config.js +3 -4
  146. package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
  147. package/dist/src/cli/commands/init.js +4 -2
  148. package/dist/src/cli/commands/init.js.map +1 -1
  149. package/dist/src/config/loader.js +3 -1
  150. package/dist/src/config/loader.js.map +1 -1
  151. package/dist/src/config/models-json.js +4 -5
  152. package/dist/src/config/models-json.js.map +1 -1
  153. package/dist/src/config/schema.d.ts +12 -4
  154. package/dist/src/config/schema.js +31 -5
  155. package/dist/src/config/schema.js.map +1 -1
  156. package/dist/src/cron/persistence.d.ts +1 -3
  157. package/dist/src/cron/persistence.js +6 -17
  158. package/dist/src/cron/persistence.js.map +1 -1
  159. package/dist/src/cron/validation.js +1 -1
  160. package/dist/src/cron/validation.js.map +1 -1
  161. package/dist/src/extensions/activation-context.js +0 -1
  162. package/dist/src/extensions/activation-context.js.map +1 -1
  163. package/dist/src/extensions/lockfile.js +4 -2
  164. package/dist/src/extensions/lockfile.js.map +1 -1
  165. package/dist/src/gateway/auth.d.ts +0 -9
  166. package/dist/src/gateway/auth.js +1 -12
  167. package/dist/src/gateway/auth.js.map +1 -1
  168. package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -1
  169. package/dist/src/gateway/hono/lib/extension-store.js +4 -4
  170. package/dist/src/gateway/hono/lib/extension-store.js.map +1 -1
  171. package/dist/src/gateway/hono/routes/channels.js +5 -3
  172. package/dist/src/gateway/hono/routes/channels.js.map +1 -1
  173. package/dist/src/gateway/hono/routes/commands-skills.js +28 -3
  174. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  175. package/dist/src/gateway/hono/routes/config.js +23 -2
  176. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  177. package/dist/src/gateway/hono/routes/sessions.js +124 -2
  178. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  179. package/dist/src/gateway/hono/sse.js +9 -2
  180. package/dist/src/gateway/hono/sse.js.map +1 -1
  181. package/dist/src/gateway/index.js +2 -2
  182. package/dist/src/gateway/lock.js +1 -1
  183. package/dist/src/gateway/service/run-gateway-agent.d.ts +37 -0
  184. package/dist/src/gateway/service/run-gateway-agent.js +163 -0
  185. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -0
  186. package/dist/src/gateway/service/save-webchat-user-message.d.ts +9 -0
  187. package/dist/src/gateway/service/save-webchat-user-message.js +34 -0
  188. package/dist/src/gateway/service/save-webchat-user-message.js.map +1 -0
  189. package/dist/src/gateway/service/session-chat-ids.d.ts +9 -0
  190. package/dist/src/gateway/service/session-chat-ids.js +33 -0
  191. package/dist/src/gateway/service/session-chat-ids.js.map +1 -0
  192. package/dist/src/gateway/service/sse-hub.d.ts +10 -0
  193. package/dist/src/gateway/service/sse-hub.js +55 -0
  194. package/dist/src/gateway/service/sse-hub.js.map +1 -0
  195. package/dist/src/gateway/service/types.d.ts +9 -0
  196. package/dist/src/gateway/service/types.js +1 -0
  197. package/dist/src/gateway/service.d.ts +42 -33
  198. package/dist/src/gateway/service.js +92 -246
  199. package/dist/src/gateway/service.js.map +1 -1
  200. package/dist/src/infra/update-lock.js +4 -2
  201. package/dist/src/infra/update-lock.js.map +1 -1
  202. package/dist/src/infra/update-startup.js +5 -14
  203. package/dist/src/infra/update-startup.js.map +1 -1
  204. package/dist/src/infra/write-file-atomic.d.ts +18 -0
  205. package/dist/src/infra/write-file-atomic.js +115 -0
  206. package/dist/src/infra/write-file-atomic.js.map +1 -0
  207. package/dist/src/session/abort-cutoff.d.ts +6 -0
  208. package/dist/src/session/abort-cutoff.js +10 -0
  209. package/dist/src/session/abort-cutoff.js.map +1 -0
  210. package/dist/src/session/compaction-checkpoints.d.ts +8 -0
  211. package/dist/src/session/compaction-checkpoints.js +21 -0
  212. package/dist/src/session/compaction-checkpoints.js.map +1 -0
  213. package/dist/src/session/config-store.js +4 -2
  214. package/dist/src/session/config-store.js.map +1 -1
  215. package/dist/src/session/index.d.ts +8 -1
  216. package/dist/src/session/index.js +7 -1
  217. package/dist/src/session/manager.d.ts +26 -1
  218. package/dist/src/session/manager.js +39 -2
  219. package/dist/src/session/manager.js.map +1 -1
  220. package/dist/src/session/patch-metadata.d.ts +12 -0
  221. package/dist/src/session/patch-metadata.js +23 -0
  222. package/dist/src/session/patch-metadata.js.map +1 -0
  223. package/dist/src/session/search-index.d.ts +2 -0
  224. package/dist/src/session/search-index.js +30 -2
  225. package/dist/src/session/search-index.js.map +1 -1
  226. package/dist/src/session/session-context-for-llm.d.ts +32 -0
  227. package/dist/src/session/session-context-for-llm.js +60 -0
  228. package/dist/src/session/session-context-for-llm.js.map +1 -0
  229. package/dist/src/session/store.d.ts +53 -2
  230. package/dist/src/session/store.js +427 -145
  231. package/dist/src/session/store.js.map +1 -1
  232. package/dist/src/session/strip-webchat-early-save.d.ts +5 -0
  233. package/dist/src/session/strip-webchat-early-save.js +17 -0
  234. package/dist/src/session/strip-webchat-early-save.js.map +1 -0
  235. package/dist/src/session/transcript-format.d.ts +46 -0
  236. package/dist/src/session/transcript-format.js +88 -0
  237. package/dist/src/session/transcript-format.js.map +1 -0
  238. package/dist/src/session/types.d.ts +37 -0
  239. package/dist/src/session/types.js.map +1 -1
  240. package/dist/src/utils/logger/log-store.js +4 -3
  241. package/dist/src/utils/logger/log-store.js.map +1 -1
  242. package/dist/src/voice/tts/merge-config.js +0 -1
  243. package/dist/src/voice/tts/merge-config.js.map +1 -1
  244. package/dist/src/voice/tts/service.js +1 -2
  245. package/dist/src/voice/tts/service.js.map +1 -1
  246. package/package.json +1 -1
  247. package/skills/business/company-values/SKILL-zh.md +80 -0
  248. package/skills/business/company-values/SKILL.md +80 -0
  249. package/skills/business/find-community/SKILL-zh.md +50 -0
  250. package/skills/business/find-community/SKILL.md +50 -0
  251. package/skills/business/first-customers/SKILL-zh.md +76 -0
  252. package/skills/business/first-customers/SKILL.md +76 -0
  253. package/skills/business/grow-sustainably/SKILL-zh.md +92 -0
  254. package/skills/business/grow-sustainably/SKILL.md +92 -0
  255. package/skills/business/marketing-plan/SKILL-zh.md +100 -0
  256. package/skills/business/marketing-plan/SKILL.md +100 -0
  257. package/skills/business/minimalist-review/SKILL-zh.md +82 -0
  258. package/skills/business/minimalist-review/SKILL.md +82 -0
  259. package/skills/business/mvp/SKILL-zh.md +81 -0
  260. package/skills/business/mvp/SKILL.md +81 -0
  261. package/skills/business/pricing/SKILL-zh.md +64 -0
  262. package/skills/business/pricing/SKILL.md +64 -0
  263. package/skills/business/processize/SKILL-zh.md +91 -0
  264. package/skills/business/processize/SKILL.md +91 -0
  265. package/skills/business/validate-idea/SKILL-zh.md +68 -0
  266. package/skills/business/validate-idea/SKILL.md +68 -0
  267. package/skills/{skill-creator → creative/algorithmic-art}/LICENSE.txt +1 -1
  268. package/skills/creative/algorithmic-art/SKILL-zh.md +405 -0
  269. package/skills/creative/algorithmic-art/SKILL.md +405 -0
  270. package/skills/creative/algorithmic-art/templates/generator_template.js +223 -0
  271. package/skills/creative/algorithmic-art/templates/viewer.html +599 -0
  272. package/skills/creative/canvas-design/LICENSE.txt +202 -0
  273. package/skills/creative/canvas-design/SKILL-zh.md +130 -0
  274. package/skills/creative/canvas-design/SKILL.md +130 -0
  275. package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  276. package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  277. package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  278. package/skills/creative/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
  279. package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  280. package/skills/creative/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
  281. package/skills/creative/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  282. package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  283. package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  284. package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  285. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  286. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  287. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  288. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  289. package/skills/creative/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
  290. package/skills/creative/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  291. package/skills/creative/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
  292. package/skills/creative/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  293. package/skills/creative/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  294. package/skills/creative/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
  295. package/skills/creative/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  296. package/skills/creative/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
  297. package/skills/creative/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  298. package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  299. package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  300. package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  301. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  302. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  303. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  304. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  305. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  306. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  307. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  308. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  309. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  310. package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  311. package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  312. package/skills/creative/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
  313. package/skills/creative/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  314. package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  315. package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  316. package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  317. package/skills/creative/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  318. package/skills/creative/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  319. package/skills/creative/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
  320. package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  321. package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  322. package/skills/creative/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  323. package/skills/creative/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  324. package/skills/creative/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  325. package/skills/creative/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  326. package/skills/creative/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  327. package/skills/creative/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  328. package/skills/creative/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
  329. package/skills/creative/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  330. package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  331. package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  332. package/skills/creative/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  333. package/skills/creative/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  334. package/skills/creative/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  335. package/skills/creative/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  336. package/skills/creative/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
  337. package/skills/creative/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
  338. package/skills/creative/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  339. package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  340. package/skills/creative/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
  341. package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  342. package/skills/creative/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
  343. package/skills/creative/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  344. package/skills/creative/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  345. package/skills/creative/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
  346. package/skills/creative/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  347. package/skills/creative/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  348. package/skills/creative/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  349. package/skills/creative/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  350. package/skills/creative/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  351. package/skills/creative/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  352. package/skills/creative/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
  353. package/skills/creative/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  354. package/skills/creative/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  355. package/skills/creative/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  356. package/skills/creative/frontend-design/LICENSE.txt +177 -0
  357. package/skills/creative/frontend-design/SKILL-zh.md +42 -0
  358. package/skills/creative/frontend-design/SKILL.md +42 -0
  359. package/skills/creative/theme-factory/LICENSE.txt +202 -0
  360. package/skills/creative/theme-factory/SKILL-zh.md +59 -0
  361. package/skills/creative/theme-factory/SKILL.md +59 -0
  362. package/skills/creative/theme-factory/theme-showcase.pdf +0 -0
  363. package/skills/creative/theme-factory/themes/arctic-frost.md +19 -0
  364. package/skills/creative/theme-factory/themes/botanical-garden.md +19 -0
  365. package/skills/creative/theme-factory/themes/desert-rose.md +19 -0
  366. package/skills/creative/theme-factory/themes/forest-canopy.md +19 -0
  367. package/skills/creative/theme-factory/themes/golden-hour.md +19 -0
  368. package/skills/creative/theme-factory/themes/midnight-galaxy.md +19 -0
  369. package/skills/creative/theme-factory/themes/modern-minimalist.md +19 -0
  370. package/skills/creative/theme-factory/themes/ocean-depths.md +19 -0
  371. package/skills/creative/theme-factory/themes/sunset-boulevard.md +19 -0
  372. package/skills/creative/theme-factory/themes/tech-innovation.md +19 -0
  373. package/skills/creative/web-artifacts-builder/LICENSE.txt +202 -0
  374. package/skills/creative/web-artifacts-builder/SKILL-zh.md +74 -0
  375. package/skills/creative/web-artifacts-builder/SKILL.md +74 -0
  376. package/skills/creative/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  377. package/skills/creative/web-artifacts-builder/scripts/init-artifact.sh +322 -0
  378. package/skills/creative/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  379. package/skills/documents/doc-coauthoring/SKILL-zh.md +375 -0
  380. package/skills/documents/doc-coauthoring/SKILL.md +375 -0
  381. package/skills/documents/docx/SKILL-zh.md +590 -0
  382. package/skills/{docx → documents/docx}/SKILL.md +11 -11
  383. package/skills/{docx → documents/docx}/scripts/comment.py +2 -2
  384. package/skills/{docx → documents/docx}/scripts/office/helpers/simplify_redlines.py +1 -1
  385. package/skills/{docx → documents/docx}/scripts/office/pack.py +2 -2
  386. package/skills/{xlsx → documents/docx}/scripts/office/validate.py +2 -2
  387. package/skills/{xlsx → documents/docx}/scripts/office/validators/redlining.py +1 -1
  388. package/skills/documents/pdf/SKILL-zh.md +314 -0
  389. package/skills/documents/pptx/SKILL-zh.md +232 -0
  390. package/skills/{pptx → documents/pptx}/editing.md +3 -3
  391. package/skills/{pptx → documents/pptx}/scripts/office/helpers/simplify_redlines.py +1 -1
  392. package/skills/{xlsx → documents/pptx}/scripts/office/pack.py +2 -2
  393. package/skills/{pptx → documents/pptx}/scripts/office/validate.py +2 -2
  394. package/skills/{docx → documents/pptx}/scripts/office/validators/redlining.py +1 -1
  395. package/skills/documents/xlsx/SKILL-zh.md +292 -0
  396. package/skills/{xlsx → documents/xlsx}/scripts/office/helpers/simplify_redlines.py +1 -1
  397. package/skills/{pptx → documents/xlsx}/scripts/office/pack.py +2 -2
  398. package/skills/{docx → documents/xlsx}/scripts/office/validate.py +2 -2
  399. package/skills/{pptx → documents/xlsx}/scripts/office/validators/redlining.py +1 -1
  400. package/skills/meta/skill-creator/LICENSE.txt +202 -0
  401. package/skills/meta/skill-creator/SKILL-zh.md +483 -0
  402. package/skills/{skill-creator → meta/skill-creator}/SKILL.md +0 -1
  403. package/skills/tools/find-skills/SKILL-zh.md +440 -0
  404. package/skills/tools/github/SKILL-zh.md +48 -0
  405. package/skills/tools/internal-comms/LICENSE.txt +202 -0
  406. package/skills/tools/internal-comms/SKILL-zh.md +32 -0
  407. package/skills/tools/internal-comms/SKILL.md +32 -0
  408. package/skills/tools/internal-comms/examples/3p-updates.md +47 -0
  409. package/skills/tools/internal-comms/examples/company-newsletter.md +65 -0
  410. package/skills/tools/internal-comms/examples/faq-answers.md +30 -0
  411. package/skills/tools/internal-comms/examples/general-comms.md +16 -0
  412. package/skills/tools/summarize/SKILL-zh.md +47 -0
  413. package/skills/tools/weather/SKILL-zh.md +46 -0
  414. package/skills/tools/webapp-testing/LICENSE.txt +202 -0
  415. package/skills/tools/webapp-testing/SKILL-zh.md +96 -0
  416. package/skills/tools/webapp-testing/SKILL.md +96 -0
  417. package/skills/tools/webapp-testing/examples/console_logging.py +35 -0
  418. package/skills/tools/webapp-testing/examples/element_discovery.py +40 -0
  419. package/skills/tools/webapp-testing/examples/static_html_automation.py +33 -0
  420. package/skills/tools/webapp-testing/scripts/with_server.py +106 -0
  421. package/dist/gateway/static/root/assets/agents-CkgFSiCY.js +0 -216
  422. package/dist/gateway/static/root/assets/agents-CkgFSiCY.js.map +0 -1
  423. package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js +0 -9
  424. package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js.map +0 -1
  425. package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js +0 -2
  426. package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js.map +0 -1
  427. package/dist/gateway/static/root/assets/cron-utils-N1PqD2DB.js +0 -3
  428. package/dist/gateway/static/root/assets/cron-utils-N1PqD2DB.js.map +0 -1
  429. package/dist/gateway/static/root/assets/dist--p2HQ2QF.js +0 -2
  430. package/dist/gateway/static/root/assets/index-Dnfha4O2.css +0 -1
  431. package/dist/gateway/static/root/assets/logs-page-CQwdV_Xw.js +0 -2
  432. package/dist/gateway/static/root/assets/logs-page-CQwdV_Xw.js.map +0 -1
  433. package/dist/gateway/static/root/assets/sessions-page-Be5kIGl_.js +0 -2
  434. package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js +0 -2
  435. package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js.map +0 -1
  436. package/dist/gateway/static/root/assets/skills-page-Clg8deH0.js +0 -3
  437. package/dist/gateway/static/root/assets/skills-page-Clg8deH0.js.map +0 -1
  438. package/dist/src/agent/skills/skills-store-client.d.ts +0 -66
  439. package/dist/src/agent/skills/skills-store-client.js.map +0 -1
  440. package/dist/src/stt/index.d.ts +0 -1
  441. package/dist/src/stt/index.js +0 -8
  442. /package/skills/{docx → documents/docx}/LICENSE.txt +0 -0
  443. /package/skills/{docx → documents/docx}/scripts/__init__.py +0 -0
  444. /package/skills/{docx → documents/docx}/scripts/accept_changes.py +0 -0
  445. /package/skills/{docx → documents/docx}/scripts/office/helpers/__init__.py +0 -0
  446. /package/skills/{docx → documents/docx}/scripts/office/helpers/merge_runs.py +0 -0
  447. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -0
  448. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -0
  449. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -0
  450. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -0
  451. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -0
  452. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -0
  453. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -0
  454. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -0
  455. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -0
  456. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -0
  457. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -0
  458. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -0
  459. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -0
  460. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -0
  461. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -0
  462. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -0
  463. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -0
  464. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -0
  465. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -0
  466. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -0
  467. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -0
  468. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -0
  469. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -0
  470. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -0
  471. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -0
  472. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -0
  473. /package/skills/{docx → documents/docx}/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -0
  474. /package/skills/{docx → documents/docx}/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -0
  475. /package/skills/{docx → documents/docx}/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -0
  476. /package/skills/{docx → documents/docx}/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -0
  477. /package/skills/{docx → documents/docx}/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -0
  478. /package/skills/{docx → documents/docx}/scripts/office/schemas/mce/mc.xsd +0 -0
  479. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-2010.xsd +0 -0
  480. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-2012.xsd +0 -0
  481. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-2018.xsd +0 -0
  482. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -0
  483. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -0
  484. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -0
  485. /package/skills/{docx → documents/docx}/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -0
  486. /package/skills/{docx → documents/docx}/scripts/office/soffice.py +0 -0
  487. /package/skills/{docx → documents/docx}/scripts/office/unpack.py +0 -0
  488. /package/skills/{docx → documents/docx}/scripts/office/validators/__init__.py +0 -0
  489. /package/skills/{docx → documents/docx}/scripts/office/validators/base.py +0 -0
  490. /package/skills/{docx → documents/docx}/scripts/office/validators/docx.py +0 -0
  491. /package/skills/{docx → documents/docx}/scripts/office/validators/pptx.py +0 -0
  492. /package/skills/{docx → documents/docx}/scripts/templates/comments.xml +0 -0
  493. /package/skills/{docx → documents/docx}/scripts/templates/commentsExtended.xml +0 -0
  494. /package/skills/{docx → documents/docx}/scripts/templates/commentsExtensible.xml +0 -0
  495. /package/skills/{docx → documents/docx}/scripts/templates/commentsIds.xml +0 -0
  496. /package/skills/{docx → documents/docx}/scripts/templates/people.xml +0 -0
  497. /package/skills/{pdf → documents/pdf}/LICENSE.txt +0 -0
  498. /package/skills/{pdf → documents/pdf}/SKILL.md +0 -0
  499. /package/skills/{pdf → documents/pdf}/forms.md +0 -0
  500. /package/skills/{pdf → documents/pdf}/reference.md +0 -0
  501. /package/skills/{pdf → documents/pdf}/scripts/check_bounding_boxes.py +0 -0
  502. /package/skills/{pdf → documents/pdf}/scripts/check_fillable_fields.py +0 -0
  503. /package/skills/{pdf → documents/pdf}/scripts/convert_pdf_to_images.py +0 -0
  504. /package/skills/{pdf → documents/pdf}/scripts/create_validation_image.py +0 -0
  505. /package/skills/{pdf → documents/pdf}/scripts/extract_form_field_info.py +0 -0
  506. /package/skills/{pdf → documents/pdf}/scripts/extract_form_structure.py +0 -0
  507. /package/skills/{pdf → documents/pdf}/scripts/fill_fillable_fields.py +0 -0
  508. /package/skills/{pdf → documents/pdf}/scripts/fill_pdf_form_with_annotations.py +0 -0
  509. /package/skills/{pptx → documents/pptx}/LICENSE.txt +0 -0
  510. /package/skills/{pptx → documents/pptx}/SKILL.md +0 -0
  511. /package/skills/{pptx → documents/pptx}/pptxgenjs.md +0 -0
  512. /package/skills/{pptx → documents/pptx}/scripts/__init__.py +0 -0
  513. /package/skills/{pptx → documents/pptx}/scripts/add_slide.py +0 -0
  514. /package/skills/{pptx → documents/pptx}/scripts/clean.py +0 -0
  515. /package/skills/{pptx → documents/pptx}/scripts/office/helpers/__init__.py +0 -0
  516. /package/skills/{pptx → documents/pptx}/scripts/office/helpers/merge_runs.py +0 -0
  517. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -0
  518. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -0
  519. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -0
  520. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -0
  521. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -0
  522. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -0
  523. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -0
  524. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -0
  525. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -0
  526. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -0
  527. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -0
  528. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -0
  529. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -0
  530. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -0
  531. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -0
  532. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -0
  533. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -0
  534. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -0
  535. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -0
  536. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -0
  537. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -0
  538. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -0
  539. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -0
  540. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -0
  541. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -0
  542. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -0
  543. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -0
  544. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -0
  545. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -0
  546. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -0
  547. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -0
  548. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/mce/mc.xsd +0 -0
  549. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-2010.xsd +0 -0
  550. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-2012.xsd +0 -0
  551. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-2018.xsd +0 -0
  552. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -0
  553. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -0
  554. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -0
  555. /package/skills/{pptx → documents/pptx}/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -0
  556. /package/skills/{pptx → documents/pptx}/scripts/office/soffice.py +0 -0
  557. /package/skills/{pptx → documents/pptx}/scripts/office/unpack.py +0 -0
  558. /package/skills/{pptx → documents/pptx}/scripts/office/validators/__init__.py +0 -0
  559. /package/skills/{pptx → documents/pptx}/scripts/office/validators/base.py +0 -0
  560. /package/skills/{pptx → documents/pptx}/scripts/office/validators/docx.py +0 -0
  561. /package/skills/{pptx → documents/pptx}/scripts/office/validators/pptx.py +0 -0
  562. /package/skills/{pptx → documents/pptx}/scripts/thumbnail.py +0 -0
  563. /package/skills/{xlsx → documents/xlsx}/LICENSE.txt +0 -0
  564. /package/skills/{xlsx → documents/xlsx}/SKILL.md +0 -0
  565. /package/skills/{skill-creator/scripts → documents/xlsx/scripts/office/helpers}/__init__.py +0 -0
  566. /package/skills/{xlsx → documents/xlsx}/scripts/office/helpers/merge_runs.py +0 -0
  567. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -0
  568. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -0
  569. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -0
  570. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -0
  571. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -0
  572. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -0
  573. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -0
  574. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -0
  575. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -0
  576. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -0
  577. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -0
  578. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -0
  579. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -0
  580. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -0
  581. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -0
  582. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -0
  583. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -0
  584. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -0
  585. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -0
  586. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -0
  587. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -0
  588. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -0
  589. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -0
  590. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -0
  591. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -0
  592. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -0
  593. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -0
  594. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -0
  595. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -0
  596. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -0
  597. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -0
  598. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/mce/mc.xsd +0 -0
  599. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-2010.xsd +0 -0
  600. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-2012.xsd +0 -0
  601. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-2018.xsd +0 -0
  602. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-cex-2018.xsd +0 -0
  603. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-cid-2016.xsd +0 -0
  604. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -0
  605. /package/skills/{xlsx → documents/xlsx}/scripts/office/schemas/microsoft/wml-symex-2015.xsd +0 -0
  606. /package/skills/{xlsx → documents/xlsx}/scripts/office/soffice.py +0 -0
  607. /package/skills/{xlsx → documents/xlsx}/scripts/office/unpack.py +0 -0
  608. /package/skills/{xlsx → documents/xlsx}/scripts/office/validators/__init__.py +0 -0
  609. /package/skills/{xlsx → documents/xlsx}/scripts/office/validators/base.py +0 -0
  610. /package/skills/{xlsx → documents/xlsx}/scripts/office/validators/docx.py +0 -0
  611. /package/skills/{xlsx → documents/xlsx}/scripts/office/validators/pptx.py +0 -0
  612. /package/skills/{xlsx → documents/xlsx}/scripts/recalc.py +0 -0
  613. /package/skills/{skill-creator → meta/skill-creator}/agents/analyzer.md +0 -0
  614. /package/skills/{skill-creator → meta/skill-creator}/agents/comparator.md +0 -0
  615. /package/skills/{skill-creator → meta/skill-creator}/agents/grader.md +0 -0
  616. /package/skills/{skill-creator → meta/skill-creator}/assets/eval_review.html +0 -0
  617. /package/skills/{skill-creator → meta/skill-creator}/eval-viewer/generate_review.py +0 -0
  618. /package/skills/{skill-creator → meta/skill-creator}/eval-viewer/viewer.html +0 -0
  619. /package/skills/{skill-creator → meta/skill-creator}/references/schemas.md +0 -0
  620. /package/skills/{xlsx/scripts/office/helpers → meta/skill-creator/scripts}/__init__.py +0 -0
  621. /package/skills/{skill-creator → meta/skill-creator}/scripts/aggregate_benchmark.py +0 -0
  622. /package/skills/{skill-creator → meta/skill-creator}/scripts/generate_report.py +0 -0
  623. /package/skills/{skill-creator → meta/skill-creator}/scripts/improve_description.py +0 -0
  624. /package/skills/{skill-creator → meta/skill-creator}/scripts/package_skill.py +0 -0
  625. /package/skills/{skill-creator → meta/skill-creator}/scripts/quick_validate.py +0 -0
  626. /package/skills/{skill-creator → meta/skill-creator}/scripts/run_eval.py +0 -0
  627. /package/skills/{skill-creator → meta/skill-creator}/scripts/run_loop.py +0 -0
  628. /package/skills/{skill-creator → meta/skill-creator}/scripts/utils.py +0 -0
  629. /package/skills/{find-skills → tools/find-skills}/SKILL.md +0 -0
  630. /package/skills/{github → tools/github}/SKILL.md +0 -0
  631. /package/skills/{summarize → tools/summarize}/SKILL.md +0 -0
  632. /package/skills/{weather → tools/weather}/SKILL.md +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"lockfile.js","names":[],"sources":["../../../src/extensions/lockfile.ts"],"sourcesContent":["import { readFile, writeFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { createHash } from 'crypto';\nimport { createLogger } from '../utils/logger.js';\nimport { resolveExtensionsLockPath, resolveExtensionsDir } from '../config/paths.js';\n\nconst log = createLogger('ExtensionLockfile');\n\n// ============================================\n// Types\n// ============================================\n\nexport type ExtensionSource = 'npm' | 'local' | 'git';\n\nexport interface ExtensionLockEntry {\n /** Extension ID */\n name: string;\n /** Installed version */\n version: string;\n /** Resolved URL or path */\n resolved: string;\n /** Integrity hash (for verification) */\n integrity?: string;\n /** Installation timestamp */\n installedAt: string;\n /** Source type */\n source: ExtensionSource;\n /** Local path (for local extensions) */\n localPath?: string;\n /** Git reference (for git extensions) */\n gitRef?: string;\n /** Dependencies */\n dependencies?: Record<string, string>;\n}\n\nexport interface ExtensionsLockfile {\n version: number;\n lockfileVersion: number;\n /** Installed extensions */\n extensions: Record<string, ExtensionLockEntry>;\n /** Last updated timestamp */\n lastUpdated?: string;\n}\n\n// ============================================\n// Extension Lockfile Manager\n// ============================================\n\nexport class ExtensionLockfileManager {\n private readonly lockfilePath: string;\n\n constructor(lockfilePath?: string) {\n this.lockfilePath = lockfilePath || resolveExtensionsLockPath();\n }\n\n /**\n * Load the lockfile\n */\n async load(): Promise<ExtensionsLockfile> {\n if (!existsSync(this.lockfilePath)) {\n return { version: 1, lockfileVersion: 1, extensions: {} };\n }\n\n try {\n const content = await readFile(this.lockfilePath, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n lockfileVersion: data.lockfileVersion || 1,\n extensions: data.extensions || {},\n lastUpdated: data.lastUpdated,\n };\n } catch (error) {\n log.warn({ error }, 'Failed to load lockfile, starting fresh');\n return { version: 1, lockfileVersion: 1, extensions: {} };\n }\n }\n\n /**\n * Save the lockfile\n */\n async save(data: ExtensionsLockfile): Promise<void> {\n data.lastUpdated = new Date().toISOString();\n\n await mkdir(dirname(this.lockfilePath), { recursive: true });\n await writeFile(\n this.lockfilePath,\n JSON.stringify(data, null, 2),\n 'utf-8'\n );\n\n log.debug('Lockfile saved');\n }\n\n /**\n * Add or update an extension entry\n */\n async upsert(\n extensionId: string,\n entry: Omit<ExtensionLockEntry, 'installedAt'>\n ): Promise<void> {\n const data = await this.load();\n\n data.extensions[extensionId] = {\n ...entry,\n installedAt: new Date().toISOString(),\n };\n\n await this.save(data);\n log.info({ extensionId, version: entry.version }, 'Extension locked');\n }\n\n /**\n * Remove an extension entry\n */\n async remove(extensionId: string): Promise<void> {\n const data = await this.load();\n\n if (data.extensions[extensionId]) {\n delete data.extensions[extensionId];\n await this.save(data);\n log.info({ extensionId }, 'Extension removed from lockfile');\n }\n }\n\n /**\n * Get a specific extension entry\n */\n async get(extensionId: string): Promise<ExtensionLockEntry | null> {\n const data = await this.load();\n return data.extensions[extensionId] || null;\n }\n\n /**\n * Check if an extension is locked\n */\n async has(extensionId: string): Promise<boolean> {\n const data = await this.load();\n return extensionId in data.extensions;\n }\n\n /**\n * List all locked extensions\n */\n async list(): Promise<ExtensionLockEntry[]> {\n const data = await this.load();\n return Object.values(data.extensions);\n }\n\n /**\n * Verify extension integrity\n */\n async verify(extensionId: string): Promise<{ valid: boolean; reason?: string }> {\n const entry = await this.get(extensionId);\n\n if (!entry) {\n return { valid: false, reason: 'Extension not in lockfile' };\n }\n\n const extDir = join(resolveExtensionsDir(), extensionId);\n\n if (!existsSync(extDir)) {\n return { valid: false, reason: 'Extension directory not found' };\n }\n\n // TODO: Verify integrity hash if available\n // This would require reading and hashing the extension files\n\n return { valid: true };\n }\n\n /**\n * Verify all locked extensions\n */\n async verifyAll(): Promise<\n Array<{ extensionId: string; valid: boolean; reason?: string }>\n > {\n const data = await this.load();\n const results: Array<{ extensionId: string; valid: boolean; reason?: string }> = [];\n\n for (const extensionId of Object.keys(data.extensions)) {\n results.push({\n extensionId,\n ...(await this.verify(extensionId)),\n });\n }\n\n return results;\n }\n\n /**\n * Freeze current state (save with validation)\n */\n async freeze(): Promise<ExtensionsLockfile> {\n const data = await this.load();\n\n // Validate all extensions exist\n for (const [extensionId] of Object.entries(data.extensions)) {\n const extDir = join(resolveExtensionsDir(), extensionId);\n\n if (!existsSync(extDir)) {\n log.warn({ extensionId }, 'Extension in lockfile but not installed');\n }\n }\n\n data.lastUpdated = new Date().toISOString();\n await this.save(data);\n\n log.info('Lockfile frozen');\n return data;\n }\n\n /**\n * Generate integrity hash for a file\n */\n static async generateIntegrity(filePath: string): Promise<string> {\n const { readFile } = await import('fs/promises');\n const content = await readFile(filePath);\n return 'sha512-' + createHash('sha512').update(content).digest('base64');\n }\n}\n\n// ============================================\n// Global Instance\n// ============================================\n\nlet globalManager: ExtensionLockfileManager | undefined;\n\nexport function getExtensionLockfileManager(\n lockfilePath?: string\n): ExtensionLockfileManager {\n if (!globalManager) {\n globalManager = new ExtensionLockfileManager(lockfilePath);\n }\n return globalManager;\n}\n\nexport function resetExtensionLockfileManager(): void {\n globalManager = undefined;\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\nexport async function loadExtensionLockfile(\n lockfilePath?: string\n): Promise<ExtensionsLockfile> {\n const manager = getExtensionLockfileManager(lockfilePath);\n return manager.load();\n}\n\nexport async function saveExtensionLockfile(\n data: ExtensionsLockfile,\n lockfilePath?: string\n): Promise<void> {\n const manager = getExtensionLockfileManager(lockfilePath);\n return manager.save(data);\n}\n"],"mappings":";;;;;;;;aAIkD;YACmC;AAErF,MAAM,MAAM,aAAa,oBAAoB;AA0C7C,IAAa,2BAAb,MAAsC;CACpC;CAEA,YAAY,cAAuB;AACjC,OAAK,eAAe,gBAAgB,2BAA2B;;;;;CAMjE,MAAM,OAAoC;AACxC,MAAI,CAAC,WAAW,KAAK,aAAa,CAChC,QAAO;GAAE,SAAS;GAAG,iBAAiB;GAAG,YAAY,EAAE;GAAE;AAG3D,MAAI;GACF,MAAM,UAAU,MAAM,SAAS,KAAK,cAAc,QAAQ;GAC1D,MAAM,OAAO,KAAK,MAAM,QAAQ;AAChC,UAAO;IACL,SAAS,KAAK,WAAW;IACzB,iBAAiB,KAAK,mBAAmB;IACzC,YAAY,KAAK,cAAc,EAAE;IACjC,aAAa,KAAK;IACnB;WACM,OAAO;AACd,OAAI,KAAK,EAAE,OAAO,EAAE,0CAA0C;AAC9D,UAAO;IAAE,SAAS;IAAG,iBAAiB;IAAG,YAAY,EAAE;IAAE;;;;;;CAO7D,MAAM,KAAK,MAAyC;AAClD,OAAK,+BAAc,IAAI,MAAM,EAAC,aAAa;AAE3C,QAAM,MAAM,QAAQ,KAAK,aAAa,EAAE,EAAE,WAAW,MAAM,CAAC;AAC5D,QAAM,UACJ,KAAK,cACL,KAAK,UAAU,MAAM,MAAM,EAAE,EAC7B,QACD;AAED,MAAI,MAAM,iBAAiB;;;;;CAM7B,MAAM,OACJ,aACA,OACe;EACf,MAAM,OAAO,MAAM,KAAK,MAAM;AAE9B,OAAK,WAAW,eAAe;GAC7B,GAAG;GACH,8BAAa,IAAI,MAAM,EAAC,aAAa;GACtC;AAED,QAAM,KAAK,KAAK,KAAK;AACrB,MAAI,KAAK;GAAE;GAAa,SAAS,MAAM;GAAS,EAAE,mBAAmB;;;;;CAMvE,MAAM,OAAO,aAAoC;EAC/C,MAAM,OAAO,MAAM,KAAK,MAAM;AAE9B,MAAI,KAAK,WAAW,cAAc;AAChC,UAAO,KAAK,WAAW;AACvB,SAAM,KAAK,KAAK,KAAK;AACrB,OAAI,KAAK,EAAE,aAAa,EAAE,kCAAkC;;;;;;CAOhE,MAAM,IAAI,aAAyD;AAEjE,UAAO,MADY,KAAK,MAAM,EAClB,WAAW,gBAAgB;;;;;CAMzC,MAAM,IAAI,aAAuC;AAE/C,SAAO,gBAAe,MADH,KAAK,MAAM,EACH;;;;;CAM7B,MAAM,OAAsC;EAC1C,MAAM,OAAO,MAAM,KAAK,MAAM;AAC9B,SAAO,OAAO,OAAO,KAAK,WAAW;;;;;CAMvC,MAAM,OAAO,aAAmE;AAG9E,MAAI,CAAC,MAFe,KAAK,IAAI,YAAY,CAGvC,QAAO;GAAE,OAAO;GAAO,QAAQ;GAA6B;AAK9D,MAAI,CAAC,WAFU,KAAK,sBAAsB,EAAE,YAEtB,CAAC,CACrB,QAAO;GAAE,OAAO;GAAO,QAAQ;GAAiC;AAMlE,SAAO,EAAE,OAAO,MAAM;;;;;CAMxB,MAAM,YAEJ;EACA,MAAM,OAAO,MAAM,KAAK,MAAM;EAC9B,MAAM,UAA2E,EAAE;AAEnF,OAAK,MAAM,eAAe,OAAO,KAAK,KAAK,WAAW,CACpD,SAAQ,KAAK;GACX;GACA,GAAI,MAAM,KAAK,OAAO,YAAY;GACnC,CAAC;AAGJ,SAAO;;;;;CAMT,MAAM,SAAsC;EAC1C,MAAM,OAAO,MAAM,KAAK,MAAM;AAG9B,OAAK,MAAM,CAAC,gBAAgB,OAAO,QAAQ,KAAK,WAAW,CAGzD,KAAI,CAAC,WAFU,KAAK,sBAAsB,EAAE,YAEtB,CAAC,CACrB,KAAI,KAAK,EAAE,aAAa,EAAE,0CAA0C;AAIxE,OAAK,+BAAc,IAAI,MAAM,EAAC,aAAa;AAC3C,QAAM,KAAK,KAAK,KAAK;AAErB,MAAI,KAAK,kBAAkB;AAC3B,SAAO;;;;;CAMT,aAAa,kBAAkB,UAAmC;EAChE,MAAM,EAAE,aAAa,MAAM,OAAO;EAClC,MAAM,UAAU,MAAM,SAAS,SAAS;AACxC,SAAO,YAAY,WAAW,SAAS,CAAC,OAAO,QAAQ,CAAC,OAAO,SAAS;;;AAQ5E,IAAI;AAEJ,SAAgB,4BACd,cAC0B;AAC1B,KAAI,CAAC,cACH,iBAAgB,IAAI,yBAAyB,aAAa;AAE5D,QAAO;;AAGT,SAAgB,gCAAsC;AACpD,iBAAgB,KAAA;;AAOlB,eAAsB,sBACpB,cAC6B;AAE7B,QADgB,4BAA4B,aAC9B,CAAC,MAAM;;AAGvB,eAAsB,sBACpB,MACA,cACe;AAEf,QADgB,4BAA4B,aAC9B,CAAC,KAAK,KAAK"}
1
+ {"version":3,"file":"lockfile.js","names":[],"sources":["../../../src/extensions/lockfile.ts"],"sourcesContent":["import { readFile, mkdir } from 'fs/promises';\nimport { writeTextAtomic } from '../infra/write-file-atomic.js';\nimport { existsSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { createHash } from 'crypto';\nimport { createLogger } from '../utils/logger.js';\nimport { resolveExtensionsLockPath, resolveExtensionsDir } from '../config/paths.js';\n\nconst log = createLogger('ExtensionLockfile');\n\n// ============================================\n// Types\n// ============================================\n\nexport type ExtensionSource = 'npm' | 'local' | 'git';\n\nexport interface ExtensionLockEntry {\n /** Extension ID */\n name: string;\n /** Installed version */\n version: string;\n /** Resolved URL or path */\n resolved: string;\n /** Integrity hash (for verification) */\n integrity?: string;\n /** Installation timestamp */\n installedAt: string;\n /** Source type */\n source: ExtensionSource;\n /** Local path (for local extensions) */\n localPath?: string;\n /** Git reference (for git extensions) */\n gitRef?: string;\n /** Dependencies */\n dependencies?: Record<string, string>;\n}\n\nexport interface ExtensionsLockfile {\n version: number;\n lockfileVersion: number;\n /** Installed extensions */\n extensions: Record<string, ExtensionLockEntry>;\n /** Last updated timestamp */\n lastUpdated?: string;\n}\n\n// ============================================\n// Extension Lockfile Manager\n// ============================================\n\nexport class ExtensionLockfileManager {\n private readonly lockfilePath: string;\n\n constructor(lockfilePath?: string) {\n this.lockfilePath = lockfilePath || resolveExtensionsLockPath();\n }\n\n /**\n * Load the lockfile\n */\n async load(): Promise<ExtensionsLockfile> {\n if (!existsSync(this.lockfilePath)) {\n return { version: 1, lockfileVersion: 1, extensions: {} };\n }\n\n try {\n const content = await readFile(this.lockfilePath, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n lockfileVersion: data.lockfileVersion || 1,\n extensions: data.extensions || {},\n lastUpdated: data.lastUpdated,\n };\n } catch (error) {\n log.warn({ error }, 'Failed to load lockfile, starting fresh');\n return { version: 1, lockfileVersion: 1, extensions: {} };\n }\n }\n\n /**\n * Save the lockfile\n */\n async save(data: ExtensionsLockfile): Promise<void> {\n data.lastUpdated = new Date().toISOString();\n\n await mkdir(dirname(this.lockfilePath), { recursive: true });\n await writeTextAtomic(this.lockfilePath, JSON.stringify(data, null, 2));\n\n log.debug('Lockfile saved');\n }\n\n /**\n * Add or update an extension entry\n */\n async upsert(\n extensionId: string,\n entry: Omit<ExtensionLockEntry, 'installedAt'>\n ): Promise<void> {\n const data = await this.load();\n\n data.extensions[extensionId] = {\n ...entry,\n installedAt: new Date().toISOString(),\n };\n\n await this.save(data);\n log.info({ extensionId, version: entry.version }, 'Extension locked');\n }\n\n /**\n * Remove an extension entry\n */\n async remove(extensionId: string): Promise<void> {\n const data = await this.load();\n\n if (data.extensions[extensionId]) {\n delete data.extensions[extensionId];\n await this.save(data);\n log.info({ extensionId }, 'Extension removed from lockfile');\n }\n }\n\n /**\n * Get a specific extension entry\n */\n async get(extensionId: string): Promise<ExtensionLockEntry | null> {\n const data = await this.load();\n return data.extensions[extensionId] || null;\n }\n\n /**\n * Check if an extension is locked\n */\n async has(extensionId: string): Promise<boolean> {\n const data = await this.load();\n return extensionId in data.extensions;\n }\n\n /**\n * List all locked extensions\n */\n async list(): Promise<ExtensionLockEntry[]> {\n const data = await this.load();\n return Object.values(data.extensions);\n }\n\n /**\n * Verify extension integrity\n */\n async verify(extensionId: string): Promise<{ valid: boolean; reason?: string }> {\n const entry = await this.get(extensionId);\n\n if (!entry) {\n return { valid: false, reason: 'Extension not in lockfile' };\n }\n\n const extDir = join(resolveExtensionsDir(), extensionId);\n\n if (!existsSync(extDir)) {\n return { valid: false, reason: 'Extension directory not found' };\n }\n\n // TODO: Verify integrity hash if available\n // This would require reading and hashing the extension files\n\n return { valid: true };\n }\n\n /**\n * Verify all locked extensions\n */\n async verifyAll(): Promise<\n Array<{ extensionId: string; valid: boolean; reason?: string }>\n > {\n const data = await this.load();\n const results: Array<{ extensionId: string; valid: boolean; reason?: string }> = [];\n\n for (const extensionId of Object.keys(data.extensions)) {\n results.push({\n extensionId,\n ...(await this.verify(extensionId)),\n });\n }\n\n return results;\n }\n\n /**\n * Freeze current state (save with validation)\n */\n async freeze(): Promise<ExtensionsLockfile> {\n const data = await this.load();\n\n // Validate all extensions exist\n for (const [extensionId] of Object.entries(data.extensions)) {\n const extDir = join(resolveExtensionsDir(), extensionId);\n\n if (!existsSync(extDir)) {\n log.warn({ extensionId }, 'Extension in lockfile but not installed');\n }\n }\n\n data.lastUpdated = new Date().toISOString();\n await this.save(data);\n\n log.info('Lockfile frozen');\n return data;\n }\n\n /**\n * Generate integrity hash for a file\n */\n static async generateIntegrity(filePath: string): Promise<string> {\n const { readFile } = await import('fs/promises');\n const content = await readFile(filePath);\n return 'sha512-' + createHash('sha512').update(content).digest('base64');\n }\n}\n\n// ============================================\n// Global Instance\n// ============================================\n\nlet globalManager: ExtensionLockfileManager | undefined;\n\nexport function getExtensionLockfileManager(\n lockfilePath?: string\n): ExtensionLockfileManager {\n if (!globalManager) {\n globalManager = new ExtensionLockfileManager(lockfilePath);\n }\n return globalManager;\n}\n\nexport function resetExtensionLockfileManager(): void {\n globalManager = undefined;\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\nexport async function loadExtensionLockfile(\n lockfilePath?: string\n): Promise<ExtensionsLockfile> {\n const manager = getExtensionLockfileManager(lockfilePath);\n return manager.load();\n}\n\nexport async function saveExtensionLockfile(\n data: ExtensionsLockfile,\n lockfilePath?: string\n): Promise<void> {\n const manager = getExtensionLockfileManager(lockfilePath);\n return manager.save(data);\n}\n"],"mappings":"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"}
@@ -24,15 +24,6 @@ export declare function resolveGatewayAuth(params: {
24
24
  * Assert that gateway auth is properly configured.
25
25
  */
26
26
  export declare function assertGatewayAuthConfigured(auth: ResolvedGatewayAuth): void;
27
- /**
28
- * Constant-time string comparison to prevent timing attacks.
29
- *
30
- * Uses `crypto.timingSafeEqual` with padding so both buffers always have
31
- * the same byte length. The actual length is checked separately.
32
- *
33
- * @deprecated Use `safeEqualSecret` from `./security/secret-equal.js` directly.
34
- */
35
- export declare function safeCompare(a: string, b: string): boolean;
36
27
  /**
37
28
  * Validate a credential against configured auth using constant-time comparison.
38
29
  *
@@ -40,17 +40,6 @@ function assertGatewayAuthConfigured(auth) {
40
40
  if (auth.mode === "password" && !auth.password) throw new Error("Gateway auth mode is password, but no password was configured. Set gateway.auth.password in config or XOPC_GATEWAY_PASSWORD environment variable.");
41
41
  }
42
42
  /**
43
- * Constant-time string comparison to prevent timing attacks.
44
- *
45
- * Uses `crypto.timingSafeEqual` with padding so both buffers always have
46
- * the same byte length. The actual length is checked separately.
47
- *
48
- * @deprecated Use `safeEqualSecret` from `./security/secret-equal.js` directly.
49
- */
50
- function safeCompare(a, b) {
51
- return safeEqualSecret(a, b);
52
- }
53
- /**
54
43
  * Validate a credential against configured auth using constant-time comparison.
55
44
  *
56
45
  * Works for both token and password modes — the caller extracts the credential
@@ -81,6 +70,6 @@ function extractToken(headers) {
81
70
  if (apiKey) return Array.isArray(apiKey) ? apiKey[0] : apiKey;
82
71
  }
83
72
  //#endregion
84
- export { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, safeCompare, validateToken };
73
+ export { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken };
85
74
 
86
75
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","names":[],"sources":["../../../src/gateway/auth.ts"],"sourcesContent":["import crypto from 'crypto';\nimport type { GatewayAuthConfig } from '../config/schema.js';\nimport { safeEqualSecret } from './security/secret-equal.js';\n\n/**\n * Resolved gateway authentication configuration.\n *\n * Supports three modes:\n * - `none`: no authentication (local dev only)\n * - `token`: Bearer token authentication (default)\n * - `password`: password-based authentication (for simpler setups)\n */\nexport interface ResolvedGatewayAuth {\n mode: 'none' | 'token' | 'password';\n token?: string;\n password?: string;\n}\n\n/**\n * Resolve gateway authentication configuration.\n * Priority: env vars > config > defaults\n */\nexport function resolveGatewayAuth(params: {\n authConfig?: GatewayAuthConfig | null;\n env?: NodeJS.ProcessEnv;\n}): ResolvedGatewayAuth {\n const env = params.env ?? process.env;\n const config: GatewayAuthConfig = params.authConfig ?? { mode: 'token' };\n\n // Environment variables take precedence\n const envMode = env.XOPC_GATEWAY_AUTH_MODE;\n const envToken = env.XOPC_GATEWAY_TOKEN;\n const envPassword = env.XOPC_GATEWAY_PASSWORD;\n\n // Resolve mode\n let mode: ResolvedGatewayAuth['mode'] = 'token';\n if (envMode === 'none' || envMode === 'token' || envMode === 'password') {\n mode = envMode;\n } else if (config.mode === 'none' || config.mode === 'password') {\n mode = config.mode;\n }\n\n // Ambiguity detection: reject conflicting credential types\n const hasToken = Boolean(envToken || config.token);\n const hasPassword = Boolean(envPassword || config.password);\n if (hasToken && hasPassword) {\n throw new Error(\n 'Invalid config: both gateway.auth.token and gateway.auth.password are set. ' +\n 'Choose one authentication mode: \"token\" (Bearer header) or \"password\".',\n );\n }\n\n // Resolve token\n let token: string | undefined;\n if (mode === 'token') {\n if (envToken) {\n token = envToken;\n } else if (config.token) {\n token = config.token;\n } else {\n // Auto-generate token if not provided\n token = crypto.randomBytes(24).toString('hex');\n }\n }\n\n // Resolve password\n let password: string | undefined;\n if (mode === 'password') {\n if (envPassword) {\n password = envPassword;\n } else if (config.password) {\n password = config.password;\n }\n }\n\n return { mode, token, password };\n}\n\n/**\n * Assert that gateway auth is properly configured.\n */\nexport function assertGatewayAuthConfigured(auth: ResolvedGatewayAuth): void {\n if (auth.mode === 'token' && !auth.token) {\n throw new Error(\n 'Gateway auth mode is token, but no token was configured. ' +\n 'Set gateway.auth.token in config or XOPC_GATEWAY_TOKEN environment variable.',\n );\n }\n if (auth.mode === 'password' && !auth.password) {\n throw new Error(\n 'Gateway auth mode is password, but no password was configured. ' +\n 'Set gateway.auth.password in config or XOPC_GATEWAY_PASSWORD environment variable.',\n );\n }\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n *\n * Uses `crypto.timingSafeEqual` with padding so both buffers always have\n * the same byte length. The actual length is checked separately.\n *\n * @deprecated Use `safeEqualSecret` from `./security/secret-equal.js` directly.\n */\nexport function safeCompare(a: string, b: string): boolean {\n return safeEqualSecret(a, b);\n}\n\n/**\n * Validate a credential against configured auth using constant-time comparison.\n *\n * Works for both token and password modes — the caller extracts the credential\n * from the appropriate transport (header, query param, etc.).\n */\nexport function validateToken(auth: ResolvedGatewayAuth, providedCredential?: string | null): boolean {\n if (auth.mode === 'none') {\n return true;\n }\n\n if (!providedCredential) {\n return false;\n }\n\n if (auth.mode === 'password') {\n if (!auth.password) return false;\n return safeEqualSecret(auth.password, providedCredential);\n }\n\n // Default: token mode\n if (!auth.token) return false;\n return safeEqualSecret(auth.token, providedCredential);\n}\n\n/**\n * Extract token from request headers.\n * Supports: Authorization: Bearer <token>, X-Api-Key: <token>\n */\nexport function extractToken(headers?: Record<string, string | string[] | undefined>): string | undefined {\n if (!headers) return undefined;\n\n // Authorization: Bearer <token>\n const authHeader = headers.authorization;\n if (authHeader) {\n const value = Array.isArray(authHeader) ? authHeader[0] : authHeader;\n if (value?.startsWith('Bearer ')) {\n return value.slice(7);\n }\n }\n\n // X-Api-Key: <token>\n const apiKey = headers['x-api-key'];\n if (apiKey) {\n return Array.isArray(apiKey) ? apiKey[0] : apiKey;\n }\n\n return undefined;\n}\n"],"mappings":";;;;;;;AAsBA,SAAgB,mBAAmB,QAGX;CACtB,MAAM,MAAM,OAAO,OAAO,QAAQ;CAClC,MAAM,SAA4B,OAAO,cAAc,EAAE,MAAM,SAAS;CAGxE,MAAM,UAAU,IAAI;CACpB,MAAM,WAAW,IAAI;CACrB,MAAM,cAAc,IAAI;CAGxB,IAAI,OAAoC;AACxC,KAAI,YAAY,UAAU,YAAY,WAAW,YAAY,WAC3D,QAAO;UACE,OAAO,SAAS,UAAU,OAAO,SAAS,WACnD,QAAO,OAAO;CAIhB,MAAM,WAAW,QAAQ,YAAY,OAAO,MAAM;CAClD,MAAM,cAAc,QAAQ,eAAe,OAAO,SAAS;AAC3D,KAAI,YAAY,YACd,OAAM,IAAI,MACR,wJAED;CAIH,IAAI;AACJ,KAAI,SAAS,QACX,KAAI,SACF,SAAQ;UACC,OAAO,MAChB,SAAQ,OAAO;KAGf,SAAQ,OAAO,YAAY,GAAG,CAAC,SAAS,MAAM;CAKlD,IAAI;AACJ,KAAI,SAAS;MACP,YACF,YAAW;WACF,OAAO,SAChB,YAAW,OAAO;;AAItB,QAAO;EAAE;EAAM;EAAO;EAAU;;;;;AAMlC,SAAgB,4BAA4B,MAAiC;AAC3E,KAAI,KAAK,SAAS,WAAW,CAAC,KAAK,MACjC,OAAM,IAAI,MACR,wIAED;AAEH,KAAI,KAAK,SAAS,cAAc,CAAC,KAAK,SACpC,OAAM,IAAI,MACR,oJAED;;;;;;;;;;AAYL,SAAgB,YAAY,GAAW,GAAoB;AACzD,QAAO,gBAAgB,GAAG,EAAE;;;;;;;;AAS9B,SAAgB,cAAc,MAA2B,oBAA6C;AACpG,KAAI,KAAK,SAAS,OAChB,QAAO;AAGT,KAAI,CAAC,mBACH,QAAO;AAGT,KAAI,KAAK,SAAS,YAAY;AAC5B,MAAI,CAAC,KAAK,SAAU,QAAO;AAC3B,SAAO,gBAAgB,KAAK,UAAU,mBAAmB;;AAI3D,KAAI,CAAC,KAAK,MAAO,QAAO;AACxB,QAAO,gBAAgB,KAAK,OAAO,mBAAmB;;;;;;AAOxD,SAAgB,aAAa,SAA6E;AACxG,KAAI,CAAC,QAAS,QAAO,KAAA;CAGrB,MAAM,aAAa,QAAQ;AAC3B,KAAI,YAAY;EACd,MAAM,QAAQ,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;AAC1D,MAAI,OAAO,WAAW,UAAU,CAC9B,QAAO,MAAM,MAAM,EAAE;;CAKzB,MAAM,SAAS,QAAQ;AACvB,KAAI,OACF,QAAO,MAAM,QAAQ,OAAO,GAAG,OAAO,KAAK"}
1
+ {"version":3,"file":"auth.js","names":[],"sources":["../../../src/gateway/auth.ts"],"sourcesContent":["import crypto from 'crypto';\nimport type { GatewayAuthConfig } from '../config/schema.js';\nimport { safeEqualSecret } from './security/secret-equal.js';\n\n/**\n * Resolved gateway authentication configuration.\n *\n * Supports three modes:\n * - `none`: no authentication (local dev only)\n * - `token`: Bearer token authentication (default)\n * - `password`: password-based authentication (for simpler setups)\n */\nexport interface ResolvedGatewayAuth {\n mode: 'none' | 'token' | 'password';\n token?: string;\n password?: string;\n}\n\n/**\n * Resolve gateway authentication configuration.\n * Priority: env vars > config > defaults\n */\nexport function resolveGatewayAuth(params: {\n authConfig?: GatewayAuthConfig | null;\n env?: NodeJS.ProcessEnv;\n}): ResolvedGatewayAuth {\n const env = params.env ?? process.env;\n const config: GatewayAuthConfig = params.authConfig ?? { mode: 'token' };\n\n // Environment variables take precedence\n const envMode = env.XOPC_GATEWAY_AUTH_MODE;\n const envToken = env.XOPC_GATEWAY_TOKEN;\n const envPassword = env.XOPC_GATEWAY_PASSWORD;\n\n // Resolve mode\n let mode: ResolvedGatewayAuth['mode'] = 'token';\n if (envMode === 'none' || envMode === 'token' || envMode === 'password') {\n mode = envMode;\n } else if (config.mode === 'none' || config.mode === 'password') {\n mode = config.mode;\n }\n\n // Ambiguity detection: reject conflicting credential types\n const hasToken = Boolean(envToken || config.token);\n const hasPassword = Boolean(envPassword || config.password);\n if (hasToken && hasPassword) {\n throw new Error(\n 'Invalid config: both gateway.auth.token and gateway.auth.password are set. ' +\n 'Choose one authentication mode: \"token\" (Bearer header) or \"password\".',\n );\n }\n\n // Resolve token\n let token: string | undefined;\n if (mode === 'token') {\n if (envToken) {\n token = envToken;\n } else if (config.token) {\n token = config.token;\n } else {\n // Auto-generate token if not provided\n token = crypto.randomBytes(24).toString('hex');\n }\n }\n\n // Resolve password\n let password: string | undefined;\n if (mode === 'password') {\n if (envPassword) {\n password = envPassword;\n } else if (config.password) {\n password = config.password;\n }\n }\n\n return { mode, token, password };\n}\n\n/**\n * Assert that gateway auth is properly configured.\n */\nexport function assertGatewayAuthConfigured(auth: ResolvedGatewayAuth): void {\n if (auth.mode === 'token' && !auth.token) {\n throw new Error(\n 'Gateway auth mode is token, but no token was configured. ' +\n 'Set gateway.auth.token in config or XOPC_GATEWAY_TOKEN environment variable.',\n );\n }\n if (auth.mode === 'password' && !auth.password) {\n throw new Error(\n 'Gateway auth mode is password, but no password was configured. ' +\n 'Set gateway.auth.password in config or XOPC_GATEWAY_PASSWORD environment variable.',\n );\n }\n}\n\n/**\n * Validate a credential against configured auth using constant-time comparison.\n *\n * Works for both token and password modes — the caller extracts the credential\n * from the appropriate transport (header, query param, etc.).\n */\nexport function validateToken(auth: ResolvedGatewayAuth, providedCredential?: string | null): boolean {\n if (auth.mode === 'none') {\n return true;\n }\n\n if (!providedCredential) {\n return false;\n }\n\n if (auth.mode === 'password') {\n if (!auth.password) return false;\n return safeEqualSecret(auth.password, providedCredential);\n }\n\n // Default: token mode\n if (!auth.token) return false;\n return safeEqualSecret(auth.token, providedCredential);\n}\n\n/**\n * Extract token from request headers.\n * Supports: Authorization: Bearer <token>, X-Api-Key: <token>\n */\nexport function extractToken(headers?: Record<string, string | string[] | undefined>): string | undefined {\n if (!headers) return undefined;\n\n // Authorization: Bearer <token>\n const authHeader = headers.authorization;\n if (authHeader) {\n const value = Array.isArray(authHeader) ? authHeader[0] : authHeader;\n if (value?.startsWith('Bearer ')) {\n return value.slice(7);\n }\n }\n\n // X-Api-Key: <token>\n const apiKey = headers['x-api-key'];\n if (apiKey) {\n return Array.isArray(apiKey) ? apiKey[0] : apiKey;\n }\n\n return undefined;\n}\n"],"mappings":";;;;;;;AAsBA,SAAgB,mBAAmB,QAGX;CACtB,MAAM,MAAM,OAAO,OAAO,QAAQ;CAClC,MAAM,SAA4B,OAAO,cAAc,EAAE,MAAM,SAAS;CAGxE,MAAM,UAAU,IAAI;CACpB,MAAM,WAAW,IAAI;CACrB,MAAM,cAAc,IAAI;CAGxB,IAAI,OAAoC;AACxC,KAAI,YAAY,UAAU,YAAY,WAAW,YAAY,WAC3D,QAAO;UACE,OAAO,SAAS,UAAU,OAAO,SAAS,WACnD,QAAO,OAAO;CAIhB,MAAM,WAAW,QAAQ,YAAY,OAAO,MAAM;CAClD,MAAM,cAAc,QAAQ,eAAe,OAAO,SAAS;AAC3D,KAAI,YAAY,YACd,OAAM,IAAI,MACR,wJAED;CAIH,IAAI;AACJ,KAAI,SAAS,QACX,KAAI,SACF,SAAQ;UACC,OAAO,MAChB,SAAQ,OAAO;KAGf,SAAQ,OAAO,YAAY,GAAG,CAAC,SAAS,MAAM;CAKlD,IAAI;AACJ,KAAI,SAAS;MACP,YACF,YAAW;WACF,OAAO,SAChB,YAAW,OAAO;;AAItB,QAAO;EAAE;EAAM;EAAO;EAAU;;;;;AAMlC,SAAgB,4BAA4B,MAAiC;AAC3E,KAAI,KAAK,SAAS,WAAW,CAAC,KAAK,MACjC,OAAM,IAAI,MACR,wIAED;AAEH,KAAI,KAAK,SAAS,cAAc,CAAC,KAAK,SACpC,OAAM,IAAI,MACR,oJAED;;;;;;;;AAUL,SAAgB,cAAc,MAA2B,oBAA6C;AACpG,KAAI,KAAK,SAAS,OAChB,QAAO;AAGT,KAAI,CAAC,mBACH,QAAO;AAGT,KAAI,KAAK,SAAS,YAAY;AAC5B,MAAI,CAAC,KAAK,SAAU,QAAO;AAC3B,SAAO,gBAAgB,KAAK,UAAU,mBAAmB;;AAI3D,KAAI,CAAC,KAAK,MAAO,QAAO;AACxB,QAAO,gBAAgB,KAAK,OAAO,mBAAmB;;;;;;AAOxD,SAAgB,aAAa,SAA6E;AACxG,KAAI,CAAC,QAAS,QAAO,KAAA;CAGrB,MAAM,aAAa,QAAQ;AAC3B,KAAI,YAAY;EACd,MAAM,QAAQ,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;AAC1D,MAAI,OAAO,WAAW,UAAU,CAC9B,QAAO,MAAM,MAAM,EAAE;;CAKzB,MAAM,SAAS,QAAQ;AACvB,KAAI,OACF,QAAO,MAAM,QAAQ,OAAO,GAAG,OAAO,KAAK"}
@@ -167,9 +167,9 @@ export declare function buildSafeWebConfigPayload(service: GatewayService): Prom
167
167
  tts: {
168
168
  enabled: boolean;
169
169
  provider: "openai" | "alibaba" | "edge" | "minimax";
170
+ trigger: "off" | "always" | "inbound" | "tagged";
170
171
  maxTextLength: number;
171
172
  timeoutMs: number;
172
- trigger?: "off" | "always" | "inbound" | "tagged";
173
173
  fallback?: {
174
174
  enabled: boolean;
175
175
  order: ("openai" | "alibaba" | "edge" | "minimax")[];
@@ -1,7 +1,9 @@
1
+ import { init_write_file_atomic, writeTextAtomic } from "../../../infra/write-file-atomic.js";
1
2
  import { join } from "node:path";
2
3
  import { homedir } from "node:os";
3
- import { mkdir, readFile, writeFile } from "node:fs/promises";
4
+ import { readFile } from "node:fs/promises";
4
5
  //#region src/gateway/hono/lib/extension-store.ts
6
+ init_write_file_atomic();
5
7
  /** Extension UI: write-through JSON KV per namespace under ~/.xopc/extensions/{namespace}/storage.json */
6
8
  const extensionStoreCache = /* @__PURE__ */ new Map();
7
9
  function getExtensionStorePath(namespace) {
@@ -24,9 +26,7 @@ async function loadExtensionStore(namespace) {
24
26
  }
25
27
  }
26
28
  async function saveExtensionStore(namespace, data) {
27
- const filePath = getExtensionStorePath(namespace);
28
- await mkdir(join(filePath, ".."), { recursive: true });
29
- await writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
29
+ await writeTextAtomic(getExtensionStorePath(namespace), JSON.stringify(data, null, 2));
30
30
  extensionStoreCache.set(namespace, data);
31
31
  }
32
32
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"extension-store.js","names":[],"sources":["../../../../../src/gateway/hono/lib/extension-store.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n/** Extension UI: write-through JSON KV per namespace under ~/.xopc/extensions/{namespace}/storage.json */\nconst extensionStoreCache = new Map<string, Record<string, unknown>>();\n\nfunction getExtensionStorePath(namespace: string): string {\n const safeNamespace = namespace.replace(/[^a-zA-Z0-9_-]/g, '_');\n return join(homedir(), '.xopc', 'extensions', safeNamespace, 'storage.json');\n}\n\nexport async function loadExtensionStore(namespace: string): Promise<Record<string, unknown>> {\n const cached = extensionStoreCache.get(namespace);\n if (cached) return cached;\n\n const filePath = getExtensionStorePath(namespace);\n try {\n const raw = await readFile(filePath, 'utf-8');\n const data = JSON.parse(raw) as Record<string, unknown>;\n extensionStoreCache.set(namespace, data);\n return data;\n } catch {\n const empty: Record<string, unknown> = {};\n extensionStoreCache.set(namespace, empty);\n return empty;\n }\n}\n\nexport async function saveExtensionStore(namespace: string, data: Record<string, unknown>): Promise<void> {\n const filePath = getExtensionStorePath(namespace);\n await mkdir(join(filePath, '..'), { recursive: true });\n await writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');\n extensionStoreCache.set(namespace, data);\n}\n"],"mappings":";;;;;AAKA,MAAM,sCAAsB,IAAI,KAAsC;AAEtE,SAAS,sBAAsB,WAA2B;CACxD,MAAM,gBAAgB,UAAU,QAAQ,mBAAmB,IAAI;AAC/D,QAAO,KAAK,SAAS,EAAE,SAAS,cAAc,eAAe,eAAe;;AAG9E,eAAsB,mBAAmB,WAAqD;CAC5F,MAAM,SAAS,oBAAoB,IAAI,UAAU;AACjD,KAAI,OAAQ,QAAO;CAEnB,MAAM,WAAW,sBAAsB,UAAU;AACjD,KAAI;EACF,MAAM,MAAM,MAAM,SAAS,UAAU,QAAQ;EAC7C,MAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,sBAAoB,IAAI,WAAW,KAAK;AACxC,SAAO;SACD;EACN,MAAM,QAAiC,EAAE;AACzC,sBAAoB,IAAI,WAAW,MAAM;AACzC,SAAO;;;AAIX,eAAsB,mBAAmB,WAAmB,MAA8C;CACxG,MAAM,WAAW,sBAAsB,UAAU;AACjD,OAAM,MAAM,KAAK,UAAU,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACtD,OAAM,UAAU,UAAU,KAAK,UAAU,MAAM,MAAM,EAAE,EAAE,QAAQ;AACjE,qBAAoB,IAAI,WAAW,KAAK"}
1
+ {"version":3,"file":"extension-store.js","names":[],"sources":["../../../../../src/gateway/hono/lib/extension-store.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { writeTextAtomic } from '../../../infra/write-file-atomic.js';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n/** Extension UI: write-through JSON KV per namespace under ~/.xopc/extensions/{namespace}/storage.json */\nconst extensionStoreCache = new Map<string, Record<string, unknown>>();\n\nfunction getExtensionStorePath(namespace: string): string {\n const safeNamespace = namespace.replace(/[^a-zA-Z0-9_-]/g, '_');\n return join(homedir(), '.xopc', 'extensions', safeNamespace, 'storage.json');\n}\n\nexport async function loadExtensionStore(namespace: string): Promise<Record<string, unknown>> {\n const cached = extensionStoreCache.get(namespace);\n if (cached) return cached;\n\n const filePath = getExtensionStorePath(namespace);\n try {\n const raw = await readFile(filePath, 'utf-8');\n const data = JSON.parse(raw) as Record<string, unknown>;\n extensionStoreCache.set(namespace, data);\n return data;\n } catch {\n const empty: Record<string, unknown> = {};\n extensionStoreCache.set(namespace, empty);\n return empty;\n }\n}\n\nexport async function saveExtensionStore(namespace: string, data: Record<string, unknown>): Promise<void> {\n const filePath = getExtensionStorePath(namespace);\n await writeTextAtomic(filePath, JSON.stringify(data, null, 2));\n extensionStoreCache.set(namespace, data);\n}\n"],"mappings":";;;;;wBACsE;;AAKtE,MAAM,sCAAsB,IAAI,KAAsC;AAEtE,SAAS,sBAAsB,WAA2B;CACxD,MAAM,gBAAgB,UAAU,QAAQ,mBAAmB,IAAI;AAC/D,QAAO,KAAK,SAAS,EAAE,SAAS,cAAc,eAAe,eAAe;;AAG9E,eAAsB,mBAAmB,WAAqD;CAC5F,MAAM,SAAS,oBAAoB,IAAI,UAAU;AACjD,KAAI,OAAQ,QAAO;CAEnB,MAAM,WAAW,sBAAsB,UAAU;AACjD,KAAI;EACF,MAAM,MAAM,MAAM,SAAS,UAAU,QAAQ;EAC7C,MAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,sBAAoB,IAAI,WAAW,KAAK;AACxC,SAAO;SACD;EACN,MAAM,QAAiC,EAAE;AACzC,sBAAoB,IAAI,WAAW,MAAM;AACzC,SAAO;;;AAIX,eAAsB,mBAAmB,WAAmB,MAA8C;AAExG,OAAM,gBADW,sBAAsB,UACT,EAAE,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC9D,qBAAoB,IAAI,WAAW,KAAK"}
@@ -1,4 +1,7 @@
1
+ import { init_write_file_atomic, writeTextAtomic } from "../../../infra/write-file-atomic.js";
2
+ import { readFileSync } from "node:fs";
1
3
  //#region src/gateway/hono/routes/channels.ts
4
+ init_write_file_atomic();
2
5
  const feishuSetupSessions = /* @__PURE__ */ new Map();
3
6
  async function startFeishuSetupPolling(sessionKey, service) {
4
7
  const session = feishuSetupSessions.get(sessionKey);
@@ -15,9 +18,8 @@ async function startFeishuSetupPolling(sessionKey, service) {
15
18
  session.phase = "done";
16
19
  session.result = outcome.result;
17
20
  try {
18
- const fs = await import("node:fs");
19
21
  const configPath = service.getHealth().configPath;
20
- const raw = fs.readFileSync(configPath, "utf8");
22
+ const raw = readFileSync(configPath, "utf8");
21
23
  const config = JSON.parse(raw);
22
24
  const existingFeishu = config.channels?.feishu ?? {};
23
25
  config.channels = {
@@ -31,7 +33,7 @@ async function startFeishuSetupPolling(sessionKey, service) {
31
33
  connectionMode: existingFeishu.connectionMode || "websocket"
32
34
  }
33
35
  };
34
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
36
+ await writeTextAtomic(configPath, `${JSON.stringify(config, null, 2)}\n`);
35
37
  await service.afterFeishuCredentialsPersisted();
36
38
  } catch {}
37
39
  } else {
@@ -1 +1 @@
1
- {"version":3,"file":"channels.js","names":[],"sources":["../../../../../src/gateway/hono/routes/channels.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport type { GatewayService } from '../../service.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\ntype FeishuSetupDomain = 'feishu' | 'lark';\n\ninterface FeishuSetupSession {\n deviceCode: string;\n domain: FeishuSetupDomain;\n intervalSec: number;\n expireInSec: number;\n createdAt: number;\n phase: 'idle' | 'polling' | 'scanned' | 'done' | 'error';\n result?: {\n appId: string;\n appSecret: string;\n domain: FeishuSetupDomain;\n openId?: string;\n };\n error?: string;\n}\n\nconst feishuSetupSessions = new Map<string, FeishuSetupSession>();\n\nasync function startFeishuSetupPolling(sessionKey: string, service: GatewayService): Promise<void> {\n const session = feishuSetupSessions.get(sessionKey);\n if (!session) return;\n\n const { pollAppRegistration } = await import(\n '../../../../extensions/feishu/src/auth/app-registration.js'\n );\n\n session.phase = 'polling';\n\n const outcome = await pollAppRegistration({\n deviceCode: session.deviceCode,\n intervalSec: session.intervalSec,\n expireInSec: session.expireInSec,\n initialDomain: session.domain,\n });\n\n if (outcome.status === 'success') {\n session.phase = 'done';\n session.result = outcome.result;\n try {\n const fs = await import('node:fs');\n const configPath = service.getHealth().configPath;\n const raw = fs.readFileSync(configPath, 'utf8');\n const config = JSON.parse(raw) as {\n channels?: Record<string, unknown>;\n };\n const existingFeishu = (config.channels?.feishu ?? {}) as Record<string, unknown>;\n\n config.channels = {\n ...config.channels,\n feishu: {\n ...existingFeishu,\n enabled: true,\n appId: outcome.result.appId,\n appSecret: outcome.result.appSecret,\n domain: outcome.result.domain,\n connectionMode: (existingFeishu.connectionMode as string) || 'websocket',\n },\n };\n\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf8');\n await service.afterFeishuCredentialsPersisted();\n } catch {\n // Config write / reload failure is non-blocking; session still carries credentials for debugging.\n }\n } else {\n session.phase = 'error';\n session.error =\n outcome.status === 'access_denied'\n ? 'User denied authorization.'\n : outcome.status === 'expired'\n ? 'Session expired.'\n : outcome.status === 'timeout'\n ? 'Scan timed out.'\n : 'message' in outcome\n ? outcome.message\n : 'Unknown error.';\n }\n\n setTimeout(() => feishuSetupSessions.delete(sessionKey), 30_000);\n}\n\nexport function registerChannelRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.get('/api/channels/status', (c) => {\n const channels = service.getChannelsStatus();\n return c.json({ ok: true, payload: { channels } });\n });\n\n authenticated.post('/api/channels/weixin/login/start', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const account =\n body && typeof body === 'object' && typeof (body as { account?: unknown }).account === 'string'\n ? (body as { account: string }).account.trim() || undefined\n : undefined;\n const rawTimeout =\n body && typeof body === 'object' ? (body as { timeoutMs?: unknown }).timeoutMs : undefined;\n const timeoutMs =\n typeof rawTimeout === 'number' && Number.isFinite(rawTimeout) ? Math.max(60_000, rawTimeout) : undefined;\n\n const { startWeixinGatewayQrLogin } = await import('../../../channels/weixin/index.js');\n const result = await startWeixinGatewayQrLogin({\n configPath: service.getHealth().configPath,\n account,\n timeoutMs,\n onPersisted: async (r) => {\n if (r.ok) {\n await service.afterWeixinCredentialsPersisted();\n }\n },\n });\n\n if (result.ok === false) {\n return c.json(\n { ok: false, error: { code: 'WEIXIN_LOGIN_FAILED', message: result.message } },\n 400,\n );\n }\n return c.json({\n ok: true,\n payload: { sessionKey: result.sessionKey, qrcodeUrl: result.qrcodeUrl },\n });\n });\n\n authenticated.get('/api/channels/weixin/login/:sessionKey', async (c) => {\n const sessionKey = c.req.param('sessionKey')?.trim() ?? '';\n if (!sessionKey) {\n return c.json({ ok: false, error: { code: 'BAD_REQUEST', message: 'Missing sessionKey' } }, 400);\n }\n const { getWeixinGatewayQrLoginStatus } = await import('../../../channels/weixin/index.js');\n const status = getWeixinGatewayQrLoginStatus(sessionKey);\n return c.json({ ok: true, payload: { status } });\n });\n\n authenticated.post('/api/channels/feishu/setup/start', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const rawDomain =\n body && typeof body === 'object' && typeof (body as { domain?: unknown }).domain === 'string'\n ? (body as { domain: string }).domain.trim().toLowerCase()\n : '';\n const domain: FeishuSetupDomain = rawDomain === 'lark' ? 'lark' : 'feishu';\n\n const { initAppRegistration, beginAppRegistration } = await import(\n '../../../../extensions/feishu/src/auth/app-registration.js'\n );\n\n const supported = await initAppRegistration(domain);\n if (!supported) {\n return c.json(\n {\n ok: false,\n error: { code: 'FEISHU_SCAN_NOT_SUPPORTED', message: 'Scan-to-create is not available.' },\n },\n 400,\n );\n }\n\n const begin = await beginAppRegistration(domain);\n\n const sessionKey = `feishu-setup-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\n feishuSetupSessions.set(sessionKey, {\n deviceCode: begin.deviceCode,\n domain,\n intervalSec: begin.intervalSec,\n expireInSec: begin.expireInSec,\n createdAt: Date.now(),\n phase: 'idle',\n });\n\n void startFeishuSetupPolling(sessionKey, service);\n\n return c.json({\n ok: true,\n payload: { sessionKey, qrUrl: begin.qrUrl },\n });\n });\n\n authenticated.get('/api/channels/feishu/setup/:sessionKey', async (c) => {\n const sessionKey = c.req.param('sessionKey')?.trim() ?? '';\n if (!sessionKey) {\n return c.json({ ok: false, error: { code: 'BAD_REQUEST', message: 'Missing sessionKey' } }, 400);\n }\n\n const session = feishuSetupSessions.get(sessionKey);\n if (!session) {\n return c.json({\n ok: true,\n payload: {\n status: { phase: 'unknown' as const, message: 'Session not found or expired.' },\n },\n });\n }\n\n if (session.phase === 'done' && session.result) {\n return c.json({\n ok: true,\n payload: {\n status: {\n phase: 'done' as const,\n ok: true,\n appId: session.result.appId,\n domain: session.result.domain,\n openId: session.result.openId,\n },\n },\n });\n }\n\n if (session.phase === 'error') {\n return c.json({\n ok: true,\n payload: {\n status: {\n phase: 'done' as const,\n ok: false,\n message: session.error ?? 'Setup failed.',\n },\n },\n });\n }\n\n return c.json({\n ok: true,\n payload: {\n status: { phase: 'polling' as const },\n },\n });\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"channels.js","names":[],"sources":["../../../../../src/gateway/hono/routes/channels.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\n\nimport type { Hono } from 'hono';\n\nimport { writeTextAtomic } from '../../../infra/write-file-atomic.js';\nimport type { GatewayService } from '../../service.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\ntype FeishuSetupDomain = 'feishu' | 'lark';\n\ninterface FeishuSetupSession {\n deviceCode: string;\n domain: FeishuSetupDomain;\n intervalSec: number;\n expireInSec: number;\n createdAt: number;\n phase: 'idle' | 'polling' | 'scanned' | 'done' | 'error';\n result?: {\n appId: string;\n appSecret: string;\n domain: FeishuSetupDomain;\n openId?: string;\n };\n error?: string;\n}\n\nconst feishuSetupSessions = new Map<string, FeishuSetupSession>();\n\nasync function startFeishuSetupPolling(sessionKey: string, service: GatewayService): Promise<void> {\n const session = feishuSetupSessions.get(sessionKey);\n if (!session) return;\n\n const { pollAppRegistration } = await import(\n '../../../../extensions/feishu/src/auth/app-registration.js'\n );\n\n session.phase = 'polling';\n\n const outcome = await pollAppRegistration({\n deviceCode: session.deviceCode,\n intervalSec: session.intervalSec,\n expireInSec: session.expireInSec,\n initialDomain: session.domain,\n });\n\n if (outcome.status === 'success') {\n session.phase = 'done';\n session.result = outcome.result;\n try {\n const configPath = service.getHealth().configPath;\n const raw = readFileSync(configPath, 'utf8');\n const config = JSON.parse(raw) as {\n channels?: Record<string, unknown>;\n };\n const existingFeishu = (config.channels?.feishu ?? {}) as Record<string, unknown>;\n\n config.channels = {\n ...config.channels,\n feishu: {\n ...existingFeishu,\n enabled: true,\n appId: outcome.result.appId,\n appSecret: outcome.result.appSecret,\n domain: outcome.result.domain,\n connectionMode: (existingFeishu.connectionMode as string) || 'websocket',\n },\n };\n\n await writeTextAtomic(configPath, `${JSON.stringify(config, null, 2)}\\n`);\n await service.afterFeishuCredentialsPersisted();\n } catch {\n // Config write / reload failure is non-blocking; session still carries credentials for debugging.\n }\n } else {\n session.phase = 'error';\n session.error =\n outcome.status === 'access_denied'\n ? 'User denied authorization.'\n : outcome.status === 'expired'\n ? 'Session expired.'\n : outcome.status === 'timeout'\n ? 'Scan timed out.'\n : 'message' in outcome\n ? outcome.message\n : 'Unknown error.';\n }\n\n setTimeout(() => feishuSetupSessions.delete(sessionKey), 30_000);\n}\n\nexport function registerChannelRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.get('/api/channels/status', (c) => {\n const channels = service.getChannelsStatus();\n return c.json({ ok: true, payload: { channels } });\n });\n\n authenticated.post('/api/channels/weixin/login/start', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const account =\n body && typeof body === 'object' && typeof (body as { account?: unknown }).account === 'string'\n ? (body as { account: string }).account.trim() || undefined\n : undefined;\n const rawTimeout =\n body && typeof body === 'object' ? (body as { timeoutMs?: unknown }).timeoutMs : undefined;\n const timeoutMs =\n typeof rawTimeout === 'number' && Number.isFinite(rawTimeout) ? Math.max(60_000, rawTimeout) : undefined;\n\n const { startWeixinGatewayQrLogin } = await import('../../../channels/weixin/index.js');\n const result = await startWeixinGatewayQrLogin({\n configPath: service.getHealth().configPath,\n account,\n timeoutMs,\n onPersisted: async (r) => {\n if (r.ok) {\n await service.afterWeixinCredentialsPersisted();\n }\n },\n });\n\n if (result.ok === false) {\n return c.json(\n { ok: false, error: { code: 'WEIXIN_LOGIN_FAILED', message: result.message } },\n 400,\n );\n }\n return c.json({\n ok: true,\n payload: { sessionKey: result.sessionKey, qrcodeUrl: result.qrcodeUrl },\n });\n });\n\n authenticated.get('/api/channels/weixin/login/:sessionKey', async (c) => {\n const sessionKey = c.req.param('sessionKey')?.trim() ?? '';\n if (!sessionKey) {\n return c.json({ ok: false, error: { code: 'BAD_REQUEST', message: 'Missing sessionKey' } }, 400);\n }\n const { getWeixinGatewayQrLoginStatus } = await import('../../../channels/weixin/index.js');\n const status = getWeixinGatewayQrLoginStatus(sessionKey);\n return c.json({ ok: true, payload: { status } });\n });\n\n authenticated.post('/api/channels/feishu/setup/start', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const rawDomain =\n body && typeof body === 'object' && typeof (body as { domain?: unknown }).domain === 'string'\n ? (body as { domain: string }).domain.trim().toLowerCase()\n : '';\n const domain: FeishuSetupDomain = rawDomain === 'lark' ? 'lark' : 'feishu';\n\n const { initAppRegistration, beginAppRegistration } = await import(\n '../../../../extensions/feishu/src/auth/app-registration.js'\n );\n\n const supported = await initAppRegistration(domain);\n if (!supported) {\n return c.json(\n {\n ok: false,\n error: { code: 'FEISHU_SCAN_NOT_SUPPORTED', message: 'Scan-to-create is not available.' },\n },\n 400,\n );\n }\n\n const begin = await beginAppRegistration(domain);\n\n const sessionKey = `feishu-setup-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\n feishuSetupSessions.set(sessionKey, {\n deviceCode: begin.deviceCode,\n domain,\n intervalSec: begin.intervalSec,\n expireInSec: begin.expireInSec,\n createdAt: Date.now(),\n phase: 'idle',\n });\n\n void startFeishuSetupPolling(sessionKey, service);\n\n return c.json({\n ok: true,\n payload: { sessionKey, qrUrl: begin.qrUrl },\n });\n });\n\n authenticated.get('/api/channels/feishu/setup/:sessionKey', async (c) => {\n const sessionKey = c.req.param('sessionKey')?.trim() ?? '';\n if (!sessionKey) {\n return c.json({ ok: false, error: { code: 'BAD_REQUEST', message: 'Missing sessionKey' } }, 400);\n }\n\n const session = feishuSetupSessions.get(sessionKey);\n if (!session) {\n return c.json({\n ok: true,\n payload: {\n status: { phase: 'unknown' as const, message: 'Session not found or expired.' },\n },\n });\n }\n\n if (session.phase === 'done' && session.result) {\n return c.json({\n ok: true,\n payload: {\n status: {\n phase: 'done' as const,\n ok: true,\n appId: session.result.appId,\n domain: session.result.domain,\n openId: session.result.openId,\n },\n },\n });\n }\n\n if (session.phase === 'error') {\n return c.json({\n ok: true,\n payload: {\n status: {\n phase: 'done' as const,\n ok: false,\n message: session.error ?? 'Setup failed.',\n },\n },\n });\n }\n\n return c.json({\n ok: true,\n payload: {\n status: { phase: 'polling' as const },\n },\n });\n });\n}\n"],"mappings":";;;wBAIsE;AAsBtE,MAAM,sCAAsB,IAAI,KAAiC;AAEjE,eAAe,wBAAwB,YAAoB,SAAwC;CACjG,MAAM,UAAU,oBAAoB,IAAI,WAAW;AACnD,KAAI,CAAC,QAAS;CAEd,MAAM,EAAE,wBAAwB,MAAM,OACpC;AAGF,SAAQ,QAAQ;CAEhB,MAAM,UAAU,MAAM,oBAAoB;EACxC,YAAY,QAAQ;EACpB,aAAa,QAAQ;EACrB,aAAa,QAAQ;EACrB,eAAe,QAAQ;EACxB,CAAC;AAEF,KAAI,QAAQ,WAAW,WAAW;AAChC,UAAQ,QAAQ;AAChB,UAAQ,SAAS,QAAQ;AACzB,MAAI;GACF,MAAM,aAAa,QAAQ,WAAW,CAAC;GACvC,MAAM,MAAM,aAAa,YAAY,OAAO;GAC5C,MAAM,SAAS,KAAK,MAAM,IAAI;GAG9B,MAAM,iBAAkB,OAAO,UAAU,UAAU,EAAE;AAErD,UAAO,WAAW;IAChB,GAAG,OAAO;IACV,QAAQ;KACN,GAAG;KACH,SAAS;KACT,OAAO,QAAQ,OAAO;KACtB,WAAW,QAAQ,OAAO;KAC1B,QAAQ,QAAQ,OAAO;KACvB,gBAAiB,eAAe,kBAA6B;KAC9D;IACF;AAED,SAAM,gBAAgB,YAAY,GAAG,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC,IAAI;AACzE,SAAM,QAAQ,iCAAiC;UACzC;QAGH;AACL,UAAQ,QAAQ;AAChB,UAAQ,QACN,QAAQ,WAAW,kBACf,+BACA,QAAQ,WAAW,YACjB,qBACA,QAAQ,WAAW,YACjB,oBACA,aAAa,UACX,QAAQ,UACR;;AAGd,kBAAiB,oBAAoB,OAAO,WAAW,EAAE,IAAO;;AAGlE,SAAgB,sBAAsB,eAAqB,MAAoC;CAC7F,MAAM,EAAE,SAAS,8BAA8B;AAE/C,eAAc,IAAI,yBAAyB,MAAM;EAC/C,MAAM,WAAW,QAAQ,mBAAmB;AAC5C,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM,SAAS,EAAE,UAAU;GAAE,CAAC;GAClD;AAEF,eAAc,KAAK,oCAAoC,2BAA2B,OAAO,MAAM;EAC7F,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EACjD,MAAM,UACJ,QAAQ,OAAO,SAAS,YAAY,OAAQ,KAA+B,YAAY,WAClF,KAA6B,QAAQ,MAAM,IAAI,KAAA,IAChD,KAAA;EACN,MAAM,aACJ,QAAQ,OAAO,SAAS,WAAY,KAAiC,YAAY,KAAA;EACnF,MAAM,YACJ,OAAO,eAAe,YAAY,OAAO,SAAS,WAAW,GAAG,KAAK,IAAI,KAAQ,WAAW,GAAG,KAAA;EAEjG,MAAM,EAAE,8BAA8B,MAAM,OAAO;EACnD,MAAM,SAAS,MAAM,0BAA0B;GAC7C,YAAY,QAAQ,WAAW,CAAC;GAChC;GACA;GACA,aAAa,OAAO,MAAM;AACxB,QAAI,EAAE,GACJ,OAAM,QAAQ,iCAAiC;;GAGpD,CAAC;AAEF,MAAI,OAAO,OAAO,MAChB,QAAO,EAAE,KACP;GAAE,IAAI;GAAO,OAAO;IAAE,MAAM;IAAuB,SAAS,OAAO;IAAS;GAAE,EAC9E,IACD;AAEH,SAAO,EAAE,KAAK;GACZ,IAAI;GACJ,SAAS;IAAE,YAAY,OAAO;IAAY,WAAW,OAAO;IAAW;GACxE,CAAC;GACF;AAEF,eAAc,IAAI,0CAA0C,OAAO,MAAM;EACvE,MAAM,aAAa,EAAE,IAAI,MAAM,aAAa,EAAE,MAAM,IAAI;AACxD,MAAI,CAAC,WACH,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;IAAE,MAAM;IAAe,SAAS;IAAsB;GAAE,EAAE,IAAI;EAElG,MAAM,EAAE,kCAAkC,MAAM,OAAO;EACvD,MAAM,SAAS,8BAA8B,WAAW;AACxD,SAAO,EAAE,KAAK;GAAE,IAAI;GAAM,SAAS,EAAE,QAAQ;GAAE,CAAC;GAChD;AAEF,eAAc,KAAK,oCAAoC,2BAA2B,OAAO,MAAM;EAC7F,MAAM,OAAO,MAAM,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;EAKjD,MAAM,UAHJ,QAAQ,OAAO,SAAS,YAAY,OAAQ,KAA8B,WAAW,WAChF,KAA4B,OAAO,MAAM,CAAC,aAAa,GACxD,QAC0C,SAAS,SAAS;EAElE,MAAM,EAAE,qBAAqB,yBAAyB,MAAM,OAC1D;AAIF,MAAI,CAAC,MADmB,oBAAoB,OAAO,CAEjD,QAAO,EAAE,KACP;GACE,IAAI;GACJ,OAAO;IAAE,MAAM;IAA6B,SAAS;IAAoC;GAC1F,EACD,IACD;EAGH,MAAM,QAAQ,MAAM,qBAAqB,OAAO;EAEhD,MAAM,aAAa,gBAAgB,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE;AAEvF,sBAAoB,IAAI,YAAY;GAClC,YAAY,MAAM;GAClB;GACA,aAAa,MAAM;GACnB,aAAa,MAAM;GACnB,WAAW,KAAK,KAAK;GACrB,OAAO;GACR,CAAC;AAEG,0BAAwB,YAAY,QAAQ;AAEjD,SAAO,EAAE,KAAK;GACZ,IAAI;GACJ,SAAS;IAAE;IAAY,OAAO,MAAM;IAAO;GAC5C,CAAC;GACF;AAEF,eAAc,IAAI,0CAA0C,OAAO,MAAM;EACvE,MAAM,aAAa,EAAE,IAAI,MAAM,aAAa,EAAE,MAAM,IAAI;AACxD,MAAI,CAAC,WACH,QAAO,EAAE,KAAK;GAAE,IAAI;GAAO,OAAO;IAAE,MAAM;IAAe,SAAS;IAAsB;GAAE,EAAE,IAAI;EAGlG,MAAM,UAAU,oBAAoB,IAAI,WAAW;AACnD,MAAI,CAAC,QACH,QAAO,EAAE,KAAK;GACZ,IAAI;GACJ,SAAS,EACP,QAAQ;IAAE,OAAO;IAAoB,SAAS;IAAiC,EAChF;GACF,CAAC;AAGJ,MAAI,QAAQ,UAAU,UAAU,QAAQ,OACtC,QAAO,EAAE,KAAK;GACZ,IAAI;GACJ,SAAS,EACP,QAAQ;IACN,OAAO;IACP,IAAI;IACJ,OAAO,QAAQ,OAAO;IACtB,QAAQ,QAAQ,OAAO;IACvB,QAAQ,QAAQ,OAAO;IACxB,EACF;GACF,CAAC;AAGJ,MAAI,QAAQ,UAAU,QACpB,QAAO,EAAE,KAAK;GACZ,IAAI;GACJ,SAAS,EACP,QAAQ;IACN,OAAO;IACP,IAAI;IACJ,SAAS,QAAQ,SAAS;IAC3B,EACF;GACF,CAAC;AAGJ,SAAO,EAAE,KAAK;GACZ,IAAI;GACJ,SAAS,EACP,QAAQ,EAAE,OAAO,WAAoB,EACtC;GACF,CAAC;GACF"}
@@ -30,7 +30,8 @@ function registerCommandsSkillsRoutes(authenticated, deps) {
30
30
  });
31
31
  });
32
32
  authenticated.get("/api/skills", (c) => {
33
- const payload = service.getSkillsApi();
33
+ const lang = c.req.query("lang")?.trim() || void 0;
34
+ const payload = service.getSkillsApi(lang);
34
35
  return c.json({
35
36
  ok: true,
36
37
  payload
@@ -51,7 +52,8 @@ function registerCommandsSkillsRoutes(authenticated, deps) {
51
52
  error: "Invalid skill name"
52
53
  }, 400);
53
54
  }
54
- const data = service.getSkillMarkdownSource(skillName);
55
+ const lang = c.req.query("lang")?.trim() || void 0;
56
+ const data = service.getSkillMarkdownSource(skillName, lang);
55
57
  if (!data) return c.json({
56
58
  ok: false,
57
59
  error: "Skill not found"
@@ -99,12 +101,14 @@ function registerCommandsSkillsRoutes(authenticated, deps) {
99
101
  const page = pageRaw != null && pageRaw !== "" ? Math.max(1, Number(pageRaw) || 1) : void 0;
100
102
  const pageSize = pageSizeRaw != null && pageSizeRaw !== "" ? Math.min(50, Math.max(1, Number(pageSizeRaw) || 20)) : void 0;
101
103
  const sort = sortRaw === "newest" || sortRaw === "downloads" ? sortRaw : void 0;
104
+ const category = c.req.query("category")?.trim() ?? "";
102
105
  try {
103
106
  const payload = await service.fetchSkillsMarketplaceCatalog({
104
107
  q: q || void 0,
105
108
  page,
106
109
  pageSize,
107
- sort
110
+ sort,
111
+ category: category || void 0
108
112
  });
109
113
  return c.json({
110
114
  ok: true,
@@ -117,6 +121,27 @@ function registerCommandsSkillsRoutes(authenticated, deps) {
117
121
  }, 502);
118
122
  }
119
123
  });
124
+ authenticated.get("/api/skills/marketplace/provider", (c) => {
125
+ const info = service.getSkillsMarketplaceProvider();
126
+ return c.json({
127
+ ok: true,
128
+ payload: info
129
+ });
130
+ });
131
+ authenticated.get("/api/skills/marketplace/categories", async (c) => {
132
+ try {
133
+ const payload = await service.fetchSkillsMarketplaceCategories();
134
+ return c.json({
135
+ ok: true,
136
+ payload
137
+ });
138
+ } catch (err) {
139
+ return c.json({
140
+ ok: false,
141
+ error: err instanceof Error ? err.message : "Marketplace categories failed"
142
+ }, 502);
143
+ }
144
+ });
120
145
  authenticated.get("/api/skills/marketplace/packages/:pkgName", async (c) => {
121
146
  const raw = c.req.param("pkgName");
122
147
  if (!raw) return c.json({
@@ -1 +1 @@
1
- {"version":3,"file":"commands-skills.js","names":[],"sources":["../../../../../src/gateway/hono/routes/commands-skills.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { commandRegistry } from '../../../chat-commands/index.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nexport function registerCommandsSkillsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // ========== Chat slash commands (CommandRegistry) ==========\n\n authenticated.get('/api/commands', (c) => {\n const all = commandRegistry.list();\n const commands = all\n .filter((cmd) => cmd.scope.includes('global') || cmd.scope.includes('private'))\n .map((cmd) => ({\n id: cmd.id,\n name: cmd.name,\n aliases: cmd.aliases ?? [],\n description: cmd.description,\n category: cmd.category,\n scope: cmd.scope,\n acceptsArgs: cmd.acceptsArgs ?? false,\n examples: cmd.examples ?? [],\n }));\n const extensionCommands = all\n .filter((cmd) => cmd.category === 'extension')\n .map((cmd) => ({\n id: cmd.id,\n name: cmd.name,\n description: cmd.description,\n extensionId: cmd.id.startsWith('ext.') ? cmd.id.split('.')[1] : undefined,\n }));\n return c.json({ ok: true, payload: { commands, extensionCommands } });\n });\n\n // ========== Skills (managed global skills under ~/.xopc/skills) ==========\n\n authenticated.get('/api/skills', (c) => {\n const payload = service.getSkillsApi();\n return c.json({ ok: true, payload });\n });\n\n authenticated.get('/api/skills/:skillName/content', (c) => {\n const raw = c.req.param('skillName');\n if (!raw) {\n return c.json({ ok: false, error: 'Missing skill name' }, 400);\n }\n let skillName: string;\n try {\n skillName = decodeURIComponent(raw);\n } catch {\n return c.json({ ok: false, error: 'Invalid skill name' }, 400);\n }\n const data = service.getSkillMarkdownSource(skillName);\n if (!data) {\n return c.json({ ok: false, error: 'Skill not found' }, 404);\n }\n return c.json({ ok: true, payload: data });\n });\n\n authenticated.post('/api/skills/reload', (c) => {\n service.reloadSkillsFromDisk();\n return c.json({ ok: true });\n });\n\n authenticated.patch('/api/skills/enabled', async (c) => {\n let body: { skillName?: unknown; enabled?: unknown };\n try {\n body = (await c.req.json()) as { skillName?: unknown; enabled?: unknown };\n } catch {\n return c.json({ ok: false, error: 'Invalid JSON' }, 400);\n }\n const skillName = typeof body.skillName === 'string' ? body.skillName.trim() : '';\n const enabled = body.enabled;\n if (!skillName || typeof enabled !== 'boolean') {\n return c.json({ ok: false, error: 'Expected { skillName: string, enabled: boolean }' }, 400);\n }\n try {\n service.patchSkillEnabled(skillName, enabled);\n return c.json({ ok: true });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Update failed' },\n 400,\n );\n }\n });\n\n authenticated.get('/api/skills/marketplace', async (c) => {\n const q = c.req.query('q')?.trim() ?? '';\n const pageRaw = c.req.query('page');\n const pageSizeRaw = c.req.query('pageSize');\n const sortRaw = c.req.query('sort');\n const page = pageRaw != null && pageRaw !== '' ? Math.max(1, Number(pageRaw) || 1) : undefined;\n const pageSize =\n pageSizeRaw != null && pageSizeRaw !== ''\n ? Math.min(50, Math.max(1, Number(pageSizeRaw) || 20))\n : undefined;\n const sort =\n sortRaw === 'newest' || sortRaw === 'downloads' ? sortRaw : undefined;\n try {\n const payload = await service.fetchSkillsMarketplaceCatalog({\n q: q || undefined,\n page,\n pageSize,\n sort,\n });\n return c.json({ ok: true, payload });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Marketplace request failed' },\n 502,\n );\n }\n });\n\n authenticated.get('/api/skills/marketplace/packages/:pkgName', async (c) => {\n const raw = c.req.param('pkgName');\n if (!raw) {\n return c.json({ ok: false, error: 'Missing package name' }, 400);\n }\n let pkgName: string;\n try {\n pkgName = decodeURIComponent(raw);\n } catch {\n return c.json({ ok: false, error: 'Invalid package name' }, 400);\n }\n try {\n const payload = await service.fetchSkillsMarketplacePackageDetail(pkgName);\n return c.json({ ok: true, payload });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Marketplace request failed' },\n 502,\n );\n }\n });\n\n authenticated.post('/api/skills/marketplace/install', async (c) => {\n let body: { name?: unknown; version?: unknown; overwrite?: unknown };\n try {\n body = (await c.req.json()) as typeof body;\n } catch {\n return c.json({ ok: false, error: 'Invalid JSON' }, 400);\n }\n const name = typeof body.name === 'string' ? body.name.trim() : '';\n const version = typeof body.version === 'string' ? body.version.trim() : undefined;\n const overwrite =\n body.overwrite === true ||\n body.overwrite === 'true' ||\n body.overwrite === '1';\n if (!name) {\n return c.json({ ok: false, error: 'Expected { name: string, version?: string, overwrite?: boolean }' }, 400);\n }\n try {\n const payload = await service.installSkillFromMarketplace({ name, version, overwrite });\n return c.json({ ok: true, payload });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Install failed' },\n 400,\n );\n }\n });\n\n authenticated.post('/api/skills/upload', async (c) => {\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ ok: false, error: 'Invalid multipart body' }, 400);\n }\n const file = body['file'];\n if (!file || typeof file !== 'object') {\n return c.json({ ok: false, error: 'Missing file field' }, 400);\n }\n let buf: Buffer;\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n } else {\n return c.json({ ok: false, error: 'Invalid file upload' }, 400);\n }\n const skillIdRaw = body['skillId'];\n const overwriteRaw = body['overwrite'];\n const skillId = typeof skillIdRaw === 'string' && skillIdRaw.trim() ? skillIdRaw.trim() : undefined;\n const overwrite =\n overwriteRaw === 'true' ||\n overwriteRaw === true ||\n overwriteRaw === '1';\n\n try {\n const result = service.installManagedSkillZip(buf, { skillId, overwrite });\n return c.json({ ok: true, payload: result });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Install failed' },\n 400,\n );\n }\n });\n\n authenticated.delete('/api/skills/:id', (c) => {\n const id = c.req.param('id');\n if (!id) {\n return c.json({ ok: false, error: 'Missing id' }, 400);\n }\n try {\n service.deleteManagedSkill(id);\n return c.json({ ok: true });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Delete failed' },\n 400,\n );\n }\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"commands-skills.js","names":[],"sources":["../../../../../src/gateway/hono/routes/commands-skills.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { commandRegistry } from '../../../chat-commands/index.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nexport function registerCommandsSkillsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // ========== Chat slash commands (CommandRegistry) ==========\n\n authenticated.get('/api/commands', (c) => {\n const all = commandRegistry.list();\n const commands = all\n .filter((cmd) => cmd.scope.includes('global') || cmd.scope.includes('private'))\n .map((cmd) => ({\n id: cmd.id,\n name: cmd.name,\n aliases: cmd.aliases ?? [],\n description: cmd.description,\n category: cmd.category,\n scope: cmd.scope,\n acceptsArgs: cmd.acceptsArgs ?? false,\n examples: cmd.examples ?? [],\n }));\n const extensionCommands = all\n .filter((cmd) => cmd.category === 'extension')\n .map((cmd) => ({\n id: cmd.id,\n name: cmd.name,\n description: cmd.description,\n extensionId: cmd.id.startsWith('ext.') ? cmd.id.split('.')[1] : undefined,\n }));\n return c.json({ ok: true, payload: { commands, extensionCommands } });\n });\n\n // ========== Skills (managed global skills under ~/.xopc/skills) ==========\n\n authenticated.get('/api/skills', (c) => {\n const lang = c.req.query('lang')?.trim() || undefined;\n const payload = service.getSkillsApi(lang);\n return c.json({ ok: true, payload });\n });\n\n authenticated.get('/api/skills/:skillName/content', (c) => {\n const raw = c.req.param('skillName');\n if (!raw) {\n return c.json({ ok: false, error: 'Missing skill name' }, 400);\n }\n let skillName: string;\n try {\n skillName = decodeURIComponent(raw);\n } catch {\n return c.json({ ok: false, error: 'Invalid skill name' }, 400);\n }\n const lang = c.req.query('lang')?.trim() || undefined;\n const data = service.getSkillMarkdownSource(skillName, lang);\n if (!data) {\n return c.json({ ok: false, error: 'Skill not found' }, 404);\n }\n return c.json({ ok: true, payload: data });\n });\n\n authenticated.post('/api/skills/reload', (c) => {\n service.reloadSkillsFromDisk();\n return c.json({ ok: true });\n });\n\n authenticated.patch('/api/skills/enabled', async (c) => {\n let body: { skillName?: unknown; enabled?: unknown };\n try {\n body = (await c.req.json()) as { skillName?: unknown; enabled?: unknown };\n } catch {\n return c.json({ ok: false, error: 'Invalid JSON' }, 400);\n }\n const skillName = typeof body.skillName === 'string' ? body.skillName.trim() : '';\n const enabled = body.enabled;\n if (!skillName || typeof enabled !== 'boolean') {\n return c.json({ ok: false, error: 'Expected { skillName: string, enabled: boolean }' }, 400);\n }\n try {\n service.patchSkillEnabled(skillName, enabled);\n return c.json({ ok: true });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Update failed' },\n 400,\n );\n }\n });\n\n authenticated.get('/api/skills/marketplace', async (c) => {\n const q = c.req.query('q')?.trim() ?? '';\n const pageRaw = c.req.query('page');\n const pageSizeRaw = c.req.query('pageSize');\n const sortRaw = c.req.query('sort');\n const page = pageRaw != null && pageRaw !== '' ? Math.max(1, Number(pageRaw) || 1) : undefined;\n const pageSize =\n pageSizeRaw != null && pageSizeRaw !== ''\n ? Math.min(50, Math.max(1, Number(pageSizeRaw) || 20))\n : undefined;\n const sort =\n sortRaw === 'newest' || sortRaw === 'downloads' ? sortRaw : undefined;\n const category = c.req.query('category')?.trim() ?? '';\n try {\n const payload = await service.fetchSkillsMarketplaceCatalog({\n q: q || undefined,\n page,\n pageSize,\n sort,\n category: category || undefined,\n });\n return c.json({ ok: true, payload });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Marketplace request failed' },\n 502,\n );\n }\n });\n\n authenticated.get('/api/skills/marketplace/provider', (c) => {\n const info = service.getSkillsMarketplaceProvider();\n return c.json({ ok: true, payload: info });\n });\n\n authenticated.get('/api/skills/marketplace/categories', async (c) => {\n try {\n const payload = await service.fetchSkillsMarketplaceCategories();\n return c.json({ ok: true, payload });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Marketplace categories failed' },\n 502,\n );\n }\n });\n\n authenticated.get('/api/skills/marketplace/packages/:pkgName', async (c) => {\n const raw = c.req.param('pkgName');\n if (!raw) {\n return c.json({ ok: false, error: 'Missing package name' }, 400);\n }\n let pkgName: string;\n try {\n pkgName = decodeURIComponent(raw);\n } catch {\n return c.json({ ok: false, error: 'Invalid package name' }, 400);\n }\n try {\n const payload = await service.fetchSkillsMarketplacePackageDetail(pkgName);\n return c.json({ ok: true, payload });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Marketplace request failed' },\n 502,\n );\n }\n });\n\n authenticated.post('/api/skills/marketplace/install', async (c) => {\n let body: { name?: unknown; version?: unknown; overwrite?: unknown };\n try {\n body = (await c.req.json()) as typeof body;\n } catch {\n return c.json({ ok: false, error: 'Invalid JSON' }, 400);\n }\n const name = typeof body.name === 'string' ? body.name.trim() : '';\n const version = typeof body.version === 'string' ? body.version.trim() : undefined;\n const overwrite =\n body.overwrite === true ||\n body.overwrite === 'true' ||\n body.overwrite === '1';\n if (!name) {\n return c.json({ ok: false, error: 'Expected { name: string, version?: string, overwrite?: boolean }' }, 400);\n }\n try {\n const payload = await service.installSkillFromMarketplace({ name, version, overwrite });\n return c.json({ ok: true, payload });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Install failed' },\n 400,\n );\n }\n });\n\n authenticated.post('/api/skills/upload', async (c) => {\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ ok: false, error: 'Invalid multipart body' }, 400);\n }\n const file = body['file'];\n if (!file || typeof file !== 'object') {\n return c.json({ ok: false, error: 'Missing file field' }, 400);\n }\n let buf: Buffer;\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n } else {\n return c.json({ ok: false, error: 'Invalid file upload' }, 400);\n }\n const skillIdRaw = body['skillId'];\n const overwriteRaw = body['overwrite'];\n const skillId = typeof skillIdRaw === 'string' && skillIdRaw.trim() ? skillIdRaw.trim() : undefined;\n const overwrite =\n overwriteRaw === 'true' ||\n overwriteRaw === true ||\n overwriteRaw === '1';\n\n try {\n const result = service.installManagedSkillZip(buf, { skillId, overwrite });\n return c.json({ ok: true, payload: result });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Install failed' },\n 400,\n );\n }\n });\n\n authenticated.delete('/api/skills/:id', (c) => {\n const id = c.req.param('id');\n if (!id) {\n return c.json({ ok: false, error: 'Missing id' }, 400);\n }\n try {\n service.deleteManagedSkill(id);\n return c.json({ ok: true });\n } catch (err) {\n return c.json(\n { ok: false, error: err instanceof Error ? err.message : 'Delete failed' },\n 400,\n );\n }\n });\n}\n"],"mappings":"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"}
@@ -364,10 +364,21 @@ function registerConfigRoutes(authenticated, deps) {
364
364
  const bodyTg = tgRaw;
365
365
  if (!config.channels) config.channels = { telegram: {
366
366
  enabled: false,
367
- botToken: "",
368
367
  allowFrom: [],
369
368
  groupAllowFrom: [],
370
369
  debug: false,
370
+ accounts: { default: {
371
+ accountId: "default",
372
+ enabled: true,
373
+ botToken: "",
374
+ allowFrom: [],
375
+ dmPolicy: "pairing",
376
+ groupPolicy: "open",
377
+ replyToMode: "off",
378
+ historyLimit: 50,
379
+ textChunkLimit: 4e3,
380
+ streamMode: "partial"
381
+ } },
371
382
  dmPolicy: "pairing",
372
383
  groupPolicy: "open",
373
384
  replyToMode: "off",
@@ -377,7 +388,17 @@ function registerConfigRoutes(authenticated, deps) {
377
388
  if (!config.channels.telegram) config.channels.telegram = {};
378
389
  const tg = config.channels.telegram;
379
390
  if (bodyTg.enabled !== void 0) tg.enabled = bodyTg.enabled;
380
- if (bodyTg.botToken !== void 0) tg.botToken = bodyTg.botToken;
391
+ if (bodyTg.botToken !== void 0) {
392
+ const accRaw = tg.accounts;
393
+ const acc = accRaw && typeof accRaw === "object" && !Array.isArray(accRaw) ? { ...accRaw } : {};
394
+ const defRaw = acc.default;
395
+ acc.default = {
396
+ ...defRaw && typeof defRaw === "object" && !Array.isArray(defRaw) ? { ...defRaw } : {},
397
+ accountId: "default",
398
+ botToken: bodyTg.botToken
399
+ };
400
+ tg.accounts = acc;
401
+ }
381
402
  if (bodyTg.allowFrom !== void 0) tg.allowFrom = bodyTg.allowFrom;
382
403
  if (bodyTg.apiRoot !== void 0) tg.apiRoot = bodyTg.apiRoot;
383
404
  if (bodyTg.debug !== void 0) tg.debug = bodyTg.debug;