@xopcai/xopc 0.0.174 → 0.0.176

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 (242) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{activity-store-CyEDJeIt.js → activity-store-DsFM1upC.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DF7Bol6I.js → agent-avatar-dicebear-DvdMLOga.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-BVjlpbeZ.js +2 -0
  6. package/dist/gateway/static/root/assets/{api-DYunqroX.js → api-BdPLCCBm.js} +1 -1
  7. package/dist/gateway/static/root/assets/{api-DwyUxpgY.js → api-Bop4IQRW.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-B4xJyvDu.js → app-management-settings-panel-DMLDOHul.js} +1 -1
  9. package/dist/gateway/static/root/assets/appearance-settings-DbI9foFR.js +1 -0
  10. package/dist/gateway/static/root/assets/apps-page-njqxLWYD.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-DWhBmmjD.js → archive-plugin-Dfdxuwvb.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-BOpZfa_I.js → attachment-load-Dn3RlnYD.js} +2 -2
  13. package/dist/gateway/static/root/assets/{attachment-preview-renderer-DonnL2dL.js → attachment-preview-renderer-Cmo-5BP5.js} +2 -2
  14. package/dist/gateway/static/root/assets/{attachment-process-heavy-RnGYy9bC.js → attachment-process-heavy-B2_kr5EA.js} +3 -3
  15. package/dist/gateway/static/root/assets/{automation-suggestion-card-Byu3I7Rs.js → automation-suggestion-card-Bc0Y7A9u.js} +1 -1
  16. package/dist/gateway/static/root/assets/automations-page-D-eweHZJ.js +6 -0
  17. package/dist/gateway/static/root/assets/{binary-plugins-6AG1qatz.js → binary-plugins-0XtB-xC0.js} +2 -2
  18. package/dist/gateway/static/root/assets/{block-editor-CJhrn98_.js → block-editor-C4fXWbEE.js} +6 -6
  19. package/dist/gateway/static/root/assets/browser-settings-page-lC86-drr.js +8 -0
  20. package/dist/gateway/static/root/assets/{browser-workflow-inputs-CBVb4mt9.js → browser-workflow-inputs-CZmzNymN.js} +1 -1
  21. package/dist/gateway/static/root/assets/{browser-workflows-page-Cq4XUKbu.js → browser-workflows-page-CBYM9HqG.js} +2 -2
  22. package/dist/gateway/static/root/assets/capabilities-settings-panel-6tYNfHqJ.js +7 -0
  23. package/dist/gateway/static/root/assets/{capability-presets-api-hbW4NAKO.js → capability-presets-api-BiJxmmhW.js} +1 -1
  24. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Co-ymbd9.js +1 -0
  25. package/dist/gateway/static/root/assets/{channel-recipient-api-CzMjHb17.js → channel-recipient-api-BKTUZDp-.js} +1 -1
  26. package/dist/gateway/static/root/assets/channels-settings-D46eVjaQ.js +1 -0
  27. package/dist/gateway/static/root/assets/channels-status-swr-BMRAO4zZ.js +1 -0
  28. package/dist/gateway/static/root/assets/{connector-logo-B9Au6gMZ.js → connector-logo-Pr4RIKjj.js} +1 -1
  29. package/dist/gateway/static/root/assets/connectors-page-Dw1eYbRi.js +2 -0
  30. package/dist/gateway/static/root/assets/desktop-pet-B8cZuQUt.js +1 -0
  31. package/dist/gateway/static/root/assets/{desktop-pet-settings-CNff5TFb.js → desktop-pet-settings-CEQacUDF.js} +1 -1
  32. package/dist/gateway/static/root/assets/{directory-picker-path-field-Bf956uo-.js → directory-picker-path-field-DWnxdZtc.js} +1 -1
  33. package/dist/gateway/static/root/assets/{dreaming-settings-CHM8FE1g.js → dreaming-settings-D2e2w2Ho.js} +3 -3
  34. package/dist/gateway/static/root/assets/{extension-debug-page-ZqM_0eUs.js → extension-debug-page-BLjTGbv3.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-page-D4hvXOMM.js → extension-page-D2_UC6hy.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-settings-page-GsqxaJjA.js → extension-settings-page-BsH6o_PX.js} +1 -1
  37. package/dist/gateway/static/root/assets/{focus-detail-page-CE6uwrl1.js → focus-detail-page-BBXUtxRB.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-config-api-B4THmgnS.js → gateway-config-api-C-DkC6UJ.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-settings-CPv-MxGE.js → gateway-settings-DEOGiimF.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-startup-retry-MP3K71pP.js → gateway-startup-retry-BlSLh1TF.js} +1 -1
  41. package/dist/gateway/static/root/assets/goal-create-dialog-CSFcRE_N.js +1 -0
  42. package/dist/gateway/static/root/assets/goal-detail-page-VjRArfAJ.js +4 -0
  43. package/dist/gateway/static/root/assets/{goals-config-api-DCcDuIjG.js → goals-config-api-CcdS9qek.js} +1 -1
  44. package/dist/gateway/static/root/assets/goals-page-BAcErdch.js +2 -0
  45. package/dist/gateway/static/root/assets/{goals-settings-o9QMXvNq.js → goals-settings-BY7crl0z.js} +1 -1
  46. package/dist/gateway/static/root/assets/{heartbeat-settings-DixwpXnH.js → heartbeat-settings-DtTkS0gs.js} +1 -1
  47. package/dist/gateway/static/root/assets/{image-generation-api-BOGH9FGi.js → image-generation-api-WGgkbwDZ.js} +1 -1
  48. package/dist/gateway/static/root/assets/index-2UImfRDC.js +212 -0
  49. package/dist/gateway/static/root/assets/index-CS9sVShT.css +1 -0
  50. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-D4o4ZPF6.js → keyboard-shortcuts-settings-C5lpWQ3f.js} +1 -1
  51. package/dist/gateway/static/root/assets/local-app-workbench-page-Cl0fcPL4.js +2 -0
  52. package/dist/gateway/static/root/assets/{local-apps-page-GzMmpO7G.js → local-apps-page-b05wWvXG.js} +1 -1
  53. package/dist/gateway/static/root/assets/{locale-store-CAuhEGCn.js → locale-store-sToMfHX_.js} +1 -1
  54. package/dist/gateway/static/root/assets/logs-page-cDE1jLJv.js +7 -0
  55. package/dist/gateway/static/root/assets/{markdown-split-CIX8D1pv.js → markdown-split-0gPVst5y.js} +1 -1
  56. package/dist/gateway/static/root/assets/{media-plugins-Bp3eIA45.js → media-plugins-Rxyq_KTm.js} +1 -1
  57. package/dist/gateway/static/root/assets/messages-CarlxqXV.js +3 -0
  58. package/dist/gateway/static/root/assets/{notes-page-RVFiYAoO.js → notes-page-DRhNDl_Q.js} +1 -1
  59. package/dist/gateway/static/root/assets/notes-workbench-BKNBk0Uf.js +4 -0
  60. package/dist/gateway/static/root/assets/{page-tabs-BGAYH3Ef.js → page-tabs-cOEOQqHh.js} +1 -1
  61. package/dist/gateway/static/root/assets/pdf-D4PI9qAw.js +54 -0
  62. package/dist/gateway/static/root/assets/pdf.worker.min-CHFwMXne.mjs +29 -0
  63. package/dist/gateway/static/root/assets/{preview-open-alternatives-BM6pDkHp.js → preview-open-alternatives-BopOLFvu.js} +1 -1
  64. package/dist/gateway/static/root/assets/{product-open-page-BiMetEmn.js → product-open-page-DWVPmmOq.js} +1 -1
  65. package/dist/gateway/static/root/assets/project-detail-page-BhjEXNQW.js +1 -0
  66. package/dist/gateway/static/root/assets/projects-page-B80e69PH.js +1 -0
  67. package/dist/gateway/static/root/assets/remote-access-hub-CwdVob6H.js +1 -0
  68. package/dist/gateway/static/root/assets/{save-bar-controls-BdjV8MK5.js → save-bar-controls-BfZmKe1t.js} +1 -1
  69. package/dist/gateway/static/root/assets/{schedule-field-ChlqXU46.js → schedule-field-Cpi4jCRV.js} +1 -1
  70. package/dist/gateway/static/root/assets/{schema-form-DDKf5ZSH.js → schema-form-OXFkcZQe.js} +1 -1
  71. package/dist/gateway/static/root/assets/sessions-page-BGt3Asj6.js +1 -0
  72. package/dist/gateway/static/root/assets/settings-advanced-gate-BnTdM9Nn.js +1 -0
  73. package/dist/gateway/static/root/assets/{settings-form-section-CPG0KGVs.js → settings-form-section-BwqkZCHJ.js} +1 -1
  74. package/dist/gateway/static/root/assets/{settings-loading-skeleton-DRSDHucM.js → settings-loading-skeleton-BbqH_S3Y.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-CeB7_xD0.js → settings-page-BoxC-JSa.js} +1 -1
  76. package/dist/gateway/static/root/assets/{settings-page-layout-BENrkwd0.js → settings-page-layout-Ddu2iGaW.js} +1 -1
  77. package/dist/gateway/static/root/assets/setup-status-panel-z1Lwv0js.js +1 -0
  78. package/dist/gateway/static/root/assets/{share-preview-page-DIzczJkG.js → share-preview-page-CVazOFjy.js} +2 -2
  79. package/dist/gateway/static/root/assets/shares-settings-C4lXuyQj.js +1 -0
  80. package/dist/gateway/static/root/assets/skill-reload-api-DSuIDkeI.js +1 -0
  81. package/dist/gateway/static/root/assets/skills-page-xgZczqVe.js +2 -0
  82. package/dist/gateway/static/root/assets/skills-page.utils-DgyB1tSo.js +1 -0
  83. package/dist/gateway/static/root/assets/{system-settings-panel-Dp4d5Q1B.js → system-settings-panel-BoLSQL65.js} +1 -1
  84. package/dist/gateway/static/root/assets/{theme-store-CbGc1laW.js → theme-store-CBNcGOfj.js} +1 -1
  85. package/dist/gateway/static/root/assets/time-picker-gochWrny.js +1 -0
  86. package/dist/gateway/static/root/assets/{typed-models-lib-DwPk3OPL.js → typed-models-lib-DvRnr7YB.js} +1 -1
  87. package/dist/gateway/static/root/assets/{use-channel-catalog-CXrEu2dw.js → use-channel-catalog-CA9BFVB7.js} +1 -1
  88. package/dist/gateway/static/root/assets/user-context-page-CEfIy4WZ.js +1 -0
  89. package/dist/gateway/static/root/assets/{voice-api-key-field-DFoA79LB.js → voice-api-key-field-v8tgylEZ.js} +1 -1
  90. package/dist/gateway/static/root/assets/work-discovery-page-B-3MClaf.js +1 -0
  91. package/dist/gateway/static/root/assets/work-item-detail-page-CEsFEdax.js +1 -0
  92. package/dist/gateway/static/root/assets/work-page-CT9AHnq6.js +3 -0
  93. package/dist/gateway/static/root/assets/workflow-run-setup-panel-CC3cJn5k.js +3 -0
  94. package/dist/gateway/static/root/assets/workflows-page-C-1-_Zp1.js +11 -0
  95. package/dist/gateway/static/root/index.html +7 -7
  96. package/dist/package.js +1 -1
  97. package/dist/src/agent/agent-manager.js +8 -8
  98. package/dist/src/agent/context/execution-scope.d.ts +26 -0
  99. package/dist/src/agent/context/execution-scope.js +84 -0
  100. package/dist/src/agent/context/project-context.d.ts +3 -1
  101. package/dist/src/agent/context/project-context.js +26 -8
  102. package/dist/src/agent/embedded/model-runtime.d.ts +1 -2
  103. package/dist/src/agent/embedded/model-runtime.js +17 -29
  104. package/dist/src/agent/embedded/session-runner.js +2 -3
  105. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  106. package/dist/src/agent/prompt/service-prompt-builder.js +1 -0
  107. package/dist/src/agent/prompt/system-prompt.js +1 -1
  108. package/dist/src/agent/service/process-direct-streaming.js +7 -4
  109. package/dist/src/agent/service.js +1 -1
  110. package/dist/src/agent/session/session-config-service.d.ts +4 -1
  111. package/dist/src/agent/session/session-config-service.js +5 -3
  112. package/dist/src/agent/session/session-inspector.d.ts +6 -0
  113. package/dist/src/agent/session/session-inspector.js +9 -2
  114. package/dist/src/agent/skills/hub-pull.js +1 -1
  115. package/dist/src/agent/skills/index.d.ts +2 -0
  116. package/dist/src/agent/skills/index.js +14 -5
  117. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +1 -1
  118. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  119. package/dist/src/agent/skills/test-framework.js +1 -1
  120. package/dist/src/agent/workflow/subagent-runner.js +2 -0
  121. package/dist/src/agent/workflow/types.d.ts +1 -0
  122. package/dist/src/auth/model-credential-store.d.ts +17 -0
  123. package/dist/src/auth/model-credential-store.js +110 -0
  124. package/dist/src/auth/oauth/github-copilot.js +2 -2
  125. package/dist/src/auth/oauth/openai-codex.js +98 -7
  126. package/dist/src/auth/oauth/types.d.ts +4 -1
  127. package/dist/src/auth/oauth/xopc-cloud.js +124 -6
  128. package/dist/src/automations/domain/defaults.d.ts +1 -0
  129. package/dist/src/automations/domain/defaults.js +4 -0
  130. package/dist/src/automations/domain/index.d.ts +1 -0
  131. package/dist/src/automations/domain/index.js +2 -1
  132. package/dist/src/automations/index.js +2 -1
  133. package/dist/src/automations/service/action-executor.js +2 -2
  134. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  135. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  136. package/dist/src/cli/commands/skills.js +1 -1
  137. package/dist/src/cli/commands/update.js +1 -1
  138. package/dist/src/config/agent-profile.js +1 -1
  139. package/dist/src/config/index.js +2 -2
  140. package/dist/src/config/schema.d.ts +21 -0
  141. package/dist/src/config/schema.js +12 -2
  142. package/dist/src/gateway/agents-admin.js +1 -1
  143. package/dist/src/gateway/heartbeat/service.js +1 -1
  144. package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -0
  145. package/dist/src/gateway/hono/lib/config-payload.js +1 -0
  146. package/dist/src/gateway/hono/oauth-async.d.ts +5 -0
  147. package/dist/src/gateway/hono/oauth-async.js +20 -8
  148. package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +1 -1
  149. package/dist/src/gateway/hono/routes/config-patch/gateway.js +9 -0
  150. package/dist/src/gateway/hono/routes/goals.js +13 -0
  151. package/dist/src/gateway/hono/routes/home.d.ts +16 -3
  152. package/dist/src/gateway/hono/routes/home.js +98 -25
  153. package/dist/src/gateway/hono/routes/index.js +2 -0
  154. package/dist/src/gateway/hono/routes/local-apps.js +1 -1
  155. package/dist/src/gateway/hono/routes/project-skills.d.ts +3 -0
  156. package/dist/src/gateway/hono/routes/project-skills.js +119 -0
  157. package/dist/src/gateway/hono/routes/update.js +2 -2
  158. package/dist/src/gateway/index.js +1 -1
  159. package/dist/src/gateway/run-loop.js +1 -1
  160. package/dist/src/gateway/service/sessions-api.d.ts +2 -1
  161. package/dist/src/gateway/service.js +5 -5
  162. package/dist/src/heartbeat/index.js +1 -1
  163. package/dist/src/infra/gateway-processes.js +1 -1
  164. package/dist/src/infra/update-restart.js +1 -1
  165. package/dist/src/infra/update-runner.js +2 -2
  166. package/dist/src/infra/update-startup.js +1 -1
  167. package/dist/src/mcp/channel-bridge.js +1 -1
  168. package/dist/src/projects/index.d.ts +1 -0
  169. package/dist/src/projects/index.js +2 -1
  170. package/dist/src/projects/project-skill-service.d.ts +67 -0
  171. package/dist/src/projects/project-skill-service.js +131 -0
  172. package/dist/src/providers/index.js +4 -2
  173. package/dist/src/providers/provider-auth-service.d.ts +22 -0
  174. package/dist/src/providers/provider-auth-service.js +66 -0
  175. package/dist/src/providers/register-runtime-providers.d.ts +6 -0
  176. package/dist/src/providers/register-runtime-providers.js +55 -0
  177. package/dist/src/providers/xopc-cloud-account-service.d.ts +2 -2
  178. package/dist/src/providers/xopc-cloud-account-service.js +6 -5
  179. package/dist/src/providers/xopc-cloud-config.d.ts +3 -0
  180. package/dist/src/providers/xopc-cloud-config.js +13 -0
  181. package/dist/src/providers/xopc-cloud-model-source.d.ts +2 -2
  182. package/dist/src/providers/xopc-cloud-model-source.js +6 -5
  183. package/dist/src/session/index.d.ts +1 -1
  184. package/dist/src/session/index.js +2 -2
  185. package/dist/src/session/thinking-resolve.d.ts +8 -0
  186. package/dist/src/session/thinking-resolve.js +6 -3
  187. package/dist/src/storage/sqlite/home-attention-repository.d.ts +3 -0
  188. package/dist/src/storage/sqlite/home-attention-repository.js +21 -0
  189. package/dist/src/storage/sqlite/index.d.ts +1 -0
  190. package/dist/src/storage/sqlite/index.js +2 -1
  191. package/dist/src/storage/sqlite/migrations/067_home_attention_acknowledgements.sql +9 -0
  192. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  193. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  194. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  195. package/dist/src/storage/sqlite/schema.js +1 -1
  196. package/dist/src/storage/sqlite/schema.sql +10 -0
  197. package/dist/src/tui/tui-startup-resources.js +1 -1
  198. package/dist/src/tui/tui.js +2 -2
  199. package/dist/src/tui/xopc-tui-keybindings.d.ts +44 -4
  200. package/dist/src/workflows/engine/workflow-engine.d.ts +1 -0
  201. package/dist/src/workflows/engine/workflow-engine.js +2 -0
  202. package/dist/src/workflows/service/workflow-run-service.js +11 -5
  203. package/dist/src/workflows/service/workflow-session-bridge.js +2 -1
  204. package/package.json +5 -5
  205. package/dist/gateway/static/root/assets/agents-BVxEFPQ5.js +0 -2
  206. package/dist/gateway/static/root/assets/appearance-settings-B2PQxRiu.js +0 -1
  207. package/dist/gateway/static/root/assets/apps-page-BtIgd82S.js +0 -1
  208. package/dist/gateway/static/root/assets/automations-page-CG_SCH5b.js +0 -6
  209. package/dist/gateway/static/root/assets/browser-settings-page-CfLqPWZC.js +0 -8
  210. package/dist/gateway/static/root/assets/capabilities-settings-panel-DCJmm6cR.js +0 -7
  211. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CnkAYvWI.js +0 -1
  212. package/dist/gateway/static/root/assets/channels-settings-DtqqFpDn.js +0 -1
  213. package/dist/gateway/static/root/assets/channels-status-swr-C-5yHbc0.js +0 -1
  214. package/dist/gateway/static/root/assets/connectors-page-CaHfs8YF.js +0 -2
  215. package/dist/gateway/static/root/assets/desktop-pet-CvFMKYdb.js +0 -1
  216. package/dist/gateway/static/root/assets/goal-create-dialog-DAeb82xP.js +0 -1
  217. package/dist/gateway/static/root/assets/goal-detail-page-CwLSp01r.js +0 -4
  218. package/dist/gateway/static/root/assets/goals-page-DvJQ6_4M.js +0 -2
  219. package/dist/gateway/static/root/assets/index-CfXiRNN5.css +0 -1
  220. package/dist/gateway/static/root/assets/index-eyttVNS_.js +0 -212
  221. package/dist/gateway/static/root/assets/local-app-workbench-page-CPcfqn_A.js +0 -2
  222. package/dist/gateway/static/root/assets/logs-page-DXABWCZp.js +0 -7
  223. package/dist/gateway/static/root/assets/messages-BiBdO1-O.js +0 -3
  224. package/dist/gateway/static/root/assets/notes-workbench-DgJzZRX3.js +0 -4
  225. package/dist/gateway/static/root/assets/pdf-epILhEOn.js +0 -54
  226. package/dist/gateway/static/root/assets/pdf.worker.min-iDqQPrd3.mjs +0 -31
  227. package/dist/gateway/static/root/assets/project-detail-page-DF7F70Vg.js +0 -1
  228. package/dist/gateway/static/root/assets/projects-page-Cw3jyi5s.js +0 -1
  229. package/dist/gateway/static/root/assets/remote-access-hub-ChAJsaNY.js +0 -1
  230. package/dist/gateway/static/root/assets/sessions-page-BxZIxt7z.js +0 -1
  231. package/dist/gateway/static/root/assets/settings-advanced-gate-DcDLS0xV.js +0 -1
  232. package/dist/gateway/static/root/assets/setup-status-panel-4Xa9NA7v.js +0 -1
  233. package/dist/gateway/static/root/assets/shares-settings-BpN0o5Cf.js +0 -1
  234. package/dist/gateway/static/root/assets/skill-reload-api-DvF2UAaL.js +0 -1
  235. package/dist/gateway/static/root/assets/skills-page-CGKXpNfy.js +0 -2
  236. package/dist/gateway/static/root/assets/time-picker-BhgCeDuO.js +0 -1
  237. package/dist/gateway/static/root/assets/user-context-page-Dy_fKAK_.js +0 -1
  238. package/dist/gateway/static/root/assets/work-discovery-page-BWkjb1NK.js +0 -1
  239. package/dist/gateway/static/root/assets/work-item-detail-page-DLBNFse5.js +0 -1
  240. package/dist/gateway/static/root/assets/work-page-Bn5RXMIE.js +0 -1
  241. package/dist/gateway/static/root/assets/workflow-run-setup-panel-BuniGPO0.js +0 -3
  242. package/dist/gateway/static/root/assets/workflows-page-_vFhRrAl.js +0 -11
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveSkillsDir } from "../../config/paths.js";
2
2
  import { parseFrontmatter } from "../../markdown/frontmatter.js";
3
3
  import { fuzzyFindText, normalizeForFuzzyMatch, normalizeToLF, restoreLineEndings } from "../tools/edit-diff.js";
4
- import { formatScanSummary, scanSkillDirectory } from "./scanner.js";
5
4
  import { resolveWorkspaceSkillsDir } from "./workspace-skills-dir.js";
5
+ import { formatScanSummary, scanSkillDirectory } from "./scanner.js";
6
6
  import { join, resolve, sep } from "path";
7
7
  import { existsSync, realpathSync } from "fs";
8
8
  import { mkdir, writeFile } from "fs/promises";
@@ -2,8 +2,8 @@ import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { parseFrontmatter } from "../../markdown/frontmatter.js";
4
4
  import { hasBinary } from "./installer.js";
5
- import { scanSkillDirectory } from "./scanner.js";
6
5
  import { parseSkillMetadata } from "./parse-skill-metadata.js";
6
+ import { scanSkillDirectory } from "./scanner.js";
7
7
  import { basename, join, relative } from "path";
8
8
  import { existsSync, readFileSync, readdirSync } from "fs";
9
9
  //#region src/agent/skills/test-framework.ts
@@ -114,6 +114,7 @@ var DelegateSubagentRunner = class {
114
114
  sessionType: "workflow-subagent",
115
115
  hiddenFromSessionList: true,
116
116
  parentSessionKey: metadata.parentSessionKey,
117
+ projectId: metadata.projectId,
117
118
  workflowRunId: metadata.workflowRunId,
118
119
  workflowDefinitionId: metadata.workflowDefinitionId,
119
120
  workflowAgentId: metadata.workflowAgentId,
@@ -132,6 +133,7 @@ var DelegateSubagentRunner = class {
132
133
  sessionType: "workflow-subagent",
133
134
  hiddenFromSessionList: true,
134
135
  parentSessionKey: metadata.parentSessionKey,
136
+ projectId: metadata.projectId,
135
137
  workflowRunId: metadata.workflowRunId,
136
138
  workflowDefinitionId: metadata.workflowDefinitionId,
137
139
  workflowAgentId: metadata.workflowAgentId,
@@ -134,6 +134,7 @@ export interface SubagentRunOptions<T = unknown> {
134
134
  sessionKey?: string;
135
135
  sessionMetadata?: {
136
136
  parentSessionKey?: string;
137
+ projectId?: string;
137
138
  workflowRunId: string;
138
139
  workflowDefinitionId: string;
139
140
  workflowAgentId: string;
@@ -0,0 +1,17 @@
1
+ import { type AuthOperationOptions, type Credential, type CredentialInfo, type CredentialStore } from '@earendil-works/pi-ai';
2
+ import { CredentialResolver } from './credentials.js';
3
+ type OAuthCredentialRepository = Pick<CredentialResolver, 'deleteOAuthToken' | 'listOAuthTokens' | 'loadOAuthTokenRecord' | 'saveOAuthToken'>;
4
+ /**
5
+ * ModelRuntime credential store backed by xopc OAuth persistence.
6
+ * API keys remain process-local because their canonical sources are xopc config and environment.
7
+ */
8
+ export declare class XopcModelCredentialStore implements CredentialStore {
9
+ private readonly repository;
10
+ private readonly runtimeApiKeys;
11
+ constructor(repository?: OAuthCredentialRepository);
12
+ read(providerId: string, options?: AuthOperationOptions): Promise<Credential | undefined>;
13
+ list(options?: AuthOperationOptions): Promise<readonly CredentialInfo[]>;
14
+ modify(providerId: string, update: (current: Credential | undefined) => Promise<Credential | undefined>, options?: AuthOperationOptions): Promise<Credential | undefined>;
15
+ delete(providerId: string, options?: AuthOperationOptions): Promise<void>;
16
+ }
17
+ export {};
@@ -0,0 +1,110 @@
1
+ import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
+ import { CredentialResolver, init_credentials } from "./credentials.js";
3
+ //#region src/auth/model-credential-store.ts
4
+ function normalizeProviderId(providerId) {
5
+ return providerId.toLowerCase();
6
+ }
7
+ function toRuntimeCredential(token) {
8
+ const { type: _type, provider: _provider, expiresAt, createdAt: _createdAt, updatedAt: _updatedAt, ...credential } = token;
9
+ return {
10
+ ...credential,
11
+ type: "oauth",
12
+ access: token.access,
13
+ refresh: token.refresh ?? "",
14
+ expires: expiresAt ?? Number.MAX_SAFE_INTEGER
15
+ };
16
+ }
17
+ function toPersistedToken(credential, current) {
18
+ const { type: _type, expires, ...token } = credential;
19
+ let previous = {};
20
+ if (current) {
21
+ const { type: _previousType, expires: _previousExpires, ...previousFields } = toRuntimeCredential(current);
22
+ previous = previousFields;
23
+ }
24
+ return {
25
+ ...previous,
26
+ ...token,
27
+ access: credential.access,
28
+ refresh: credential.refresh || void 0,
29
+ expiresAt: expires,
30
+ createdAt: current?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
31
+ };
32
+ }
33
+ async function serializeProviderModification(providerId, operation) {
34
+ const previous = providerModificationTails.get(providerId) ?? Promise.resolve();
35
+ let release;
36
+ const gate = new Promise((resolve) => {
37
+ release = resolve;
38
+ });
39
+ const tail = previous.catch(() => void 0).then(() => gate);
40
+ providerModificationTails.set(providerId, tail);
41
+ await previous.catch(() => void 0);
42
+ try {
43
+ return await operation();
44
+ } finally {
45
+ release();
46
+ if (providerModificationTails.get(providerId) === tail) providerModificationTails.delete(providerId);
47
+ }
48
+ }
49
+ var providerModificationTails, XopcModelCredentialStore;
50
+ var init_model_credential_store = __esmMin((() => {
51
+ init_credentials();
52
+ providerModificationTails = /* @__PURE__ */ new Map();
53
+ XopcModelCredentialStore = class {
54
+ runtimeApiKeys = /* @__PURE__ */ new Map();
55
+ constructor(repository = new CredentialResolver()) {
56
+ this.repository = repository;
57
+ }
58
+ async read(providerId, options) {
59
+ options?.signal?.throwIfAborted();
60
+ const normalizedProvider = normalizeProviderId(providerId);
61
+ const runtimeApiKey = this.runtimeApiKeys.get(normalizedProvider);
62
+ if (runtimeApiKey) return runtimeApiKey;
63
+ const token = await this.repository.loadOAuthTokenRecord(normalizedProvider);
64
+ options?.signal?.throwIfAborted();
65
+ return token ? toRuntimeCredential(token) : void 0;
66
+ }
67
+ async list(options) {
68
+ options?.signal?.throwIfAborted();
69
+ const oauthTokens = await this.repository.listOAuthTokens();
70
+ options?.signal?.throwIfAborted();
71
+ const credentials = /* @__PURE__ */ new Map();
72
+ for (const token of oauthTokens) credentials.set(normalizeProviderId(token.provider), {
73
+ providerId: normalizeProviderId(token.provider),
74
+ type: "oauth"
75
+ });
76
+ for (const providerId of this.runtimeApiKeys.keys()) credentials.set(providerId, {
77
+ providerId,
78
+ type: "api_key"
79
+ });
80
+ return [...credentials.values()];
81
+ }
82
+ async modify(providerId, update, options) {
83
+ const normalizedProvider = normalizeProviderId(providerId);
84
+ return serializeProviderModification(normalizedProvider, async () => {
85
+ options?.signal?.throwIfAborted();
86
+ const persisted = await this.repository.loadOAuthTokenRecord(normalizedProvider);
87
+ const current = this.runtimeApiKeys.get(normalizedProvider) ?? (persisted ? toRuntimeCredential(persisted) : void 0);
88
+ const updated = await update(current);
89
+ options?.signal?.throwIfAborted();
90
+ if (!updated) return current;
91
+ if (updated.type === "oauth") {
92
+ await this.repository.saveOAuthToken(normalizedProvider, toPersistedToken(updated, persisted));
93
+ this.runtimeApiKeys.delete(normalizedProvider);
94
+ } else this.runtimeApiKeys.set(normalizedProvider, updated);
95
+ return updated;
96
+ });
97
+ }
98
+ async delete(providerId, options) {
99
+ const normalizedProvider = normalizeProviderId(providerId);
100
+ await serializeProviderModification(normalizedProvider, async () => {
101
+ options?.signal?.throwIfAborted();
102
+ await this.repository.deleteOAuthToken(normalizedProvider);
103
+ this.runtimeApiKeys.delete(normalizedProvider);
104
+ });
105
+ }
106
+ };
107
+ }));
108
+ //#endregion
109
+ init_model_credential_store();
110
+ export { XopcModelCredentialStore, init_model_credential_store };
@@ -18,7 +18,7 @@ function fromPiCredential({ type: _type, ...credentials }) {
18
18
  }
19
19
  function toAuthInteraction(callbacks) {
20
20
  return {
21
- signal: callbacks.signal,
21
+ signal: callbacks.signal ?? new AbortController().signal,
22
22
  async prompt(prompt) {
23
23
  if (prompt.type === "select") return await callbacks.onSelect({
24
24
  message: prompt.message,
@@ -57,7 +57,7 @@ var init_github_copilot = __esmMin((() => {
57
57
  return fromPiCredential(await getCopilotOAuth().login(toAuthInteraction(callbacks)));
58
58
  },
59
59
  async refreshToken(credentials) {
60
- return fromPiCredential(await getCopilotOAuth().refresh(toPiCredential(credentials)));
60
+ return fromPiCredential(await getCopilotOAuth().refresh(toPiCredential(credentials), new AbortController().signal));
61
61
  },
62
62
  getApiKey(credentials) {
63
63
  return credentials.access;
@@ -2,12 +2,17 @@ import { __esmMin } from "../../../_virtual/_rolldown/runtime.js";
2
2
  import { generatePKCE, init_pkce } from "./pkce.js";
3
3
  import { randomBytes } from "node:crypto";
4
4
  import http from "node:http";
5
+ import { setTimeout as setTimeout$1 } from "node:timers/promises";
5
6
  //#region src/auth/oauth/openai-codex.ts
6
7
  /**
7
8
  * OpenAI Codex (ChatGPT) OAuth.
8
9
  *
9
10
  * Owns callback validation, manual prompt handling, and success/error pages.
10
11
  */
12
+ function requestSignal(signal) {
13
+ const timeout = AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS);
14
+ return signal ? AbortSignal.any([signal, timeout]) : timeout;
15
+ }
11
16
  function xopcOAuthHtml(params) {
12
17
  const color = params.tone === "success" ? "#2563eb" : "#dc2626";
13
18
  const escapedTitle = escapeHtml(params.title);
@@ -199,7 +204,7 @@ async function postTokenForm(body, signal) {
199
204
  Accept: "application/json"
200
205
  },
201
206
  body,
202
- signal: signal ?? AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS)
207
+ signal: requestSignal(signal)
203
208
  });
204
209
  const contentType = response.headers.get("content-type") ?? "";
205
210
  const text = await response.text();
@@ -207,15 +212,82 @@ async function postTokenForm(body, signal) {
207
212
  if (!contentType.toLowerCase().includes("application/json")) throw new Error(`OpenAI Codex token response was not JSON: ${contentType || "missing content-type"}`);
208
213
  return JSON.parse(text);
209
214
  }
210
- async function exchangeAuthorizationCode(code, verifier, signal) {
215
+ async function exchangeAuthorizationCode(code, verifier, signal, redirectUri = REDIRECT_URI) {
211
216
  return normalizeTokenResponse(await postTokenForm(new URLSearchParams({
212
217
  grant_type: "authorization_code",
213
218
  client_id: CLIENT_ID,
214
219
  code,
215
220
  code_verifier: verifier,
216
- redirect_uri: REDIRECT_URI
221
+ redirect_uri: redirectUri
217
222
  }), signal));
218
223
  }
224
+ async function requestDeviceCode(signal) {
225
+ const response = await fetch(DEVICE_USER_CODE_URL, {
226
+ method: "POST",
227
+ headers: {
228
+ "Content-Type": "application/json",
229
+ Accept: "application/json"
230
+ },
231
+ body: JSON.stringify({ client_id: CLIENT_ID }),
232
+ signal: requestSignal(signal)
233
+ });
234
+ const body = await response.json().catch(() => ({}));
235
+ if (!response.ok) {
236
+ if (response.status === 404) throw new Error("OpenAI Codex device code login is not enabled. Enable it in ChatGPT security or workspace settings, or use browser login.");
237
+ throw new Error(body.error_description ?? body.error ?? `OpenAI Codex device code request failed (${response.status})`);
238
+ }
239
+ if (!body.device_auth_id || !body.user_code) throw new Error("OpenAI Codex device code response is incomplete");
240
+ const intervalSeconds = Number(body.interval);
241
+ return {
242
+ deviceAuthId: body.device_auth_id,
243
+ userCode: body.user_code,
244
+ intervalMs: Math.max(1, Number.isFinite(intervalSeconds) ? intervalSeconds : 5) * 1e3
245
+ };
246
+ }
247
+ async function pollDeviceAuthorization(params) {
248
+ const expiresAt = Date.now() + DEVICE_AUTH_TIMEOUT_MS;
249
+ while (Date.now() < expiresAt) {
250
+ if (params.signal?.aborted) throw params.signal.reason instanceof Error ? params.signal.reason : /* @__PURE__ */ new Error("OpenAI Codex login cancelled");
251
+ const response = await fetch(DEVICE_TOKEN_URL, {
252
+ method: "POST",
253
+ headers: {
254
+ "Content-Type": "application/json",
255
+ Accept: "application/json"
256
+ },
257
+ body: JSON.stringify({
258
+ device_auth_id: params.deviceAuthId,
259
+ user_code: params.userCode
260
+ }),
261
+ signal: requestSignal(params.signal)
262
+ });
263
+ const body = await response.json().catch(() => ({}));
264
+ if (response.ok) {
265
+ if (!body.authorization_code || !body.code_verifier) throw new Error("OpenAI Codex device authorization response is incomplete");
266
+ return {
267
+ code: body.authorization_code,
268
+ verifier: body.code_verifier
269
+ };
270
+ }
271
+ if (response.status !== 403 && response.status !== 404) throw new Error(body.error_description ?? body.error ?? `OpenAI Codex device authorization failed (${response.status})`);
272
+ const remainingMs = expiresAt - Date.now();
273
+ await setTimeout$1(Math.min(params.intervalMs, remainingMs), void 0, params.signal ? { signal: params.signal } : void 0);
274
+ }
275
+ throw new Error("OpenAI Codex device authorization timed out");
276
+ }
277
+ async function loginOpenAICodexWithDeviceCode(callbacks) {
278
+ const device = await requestDeviceCode(callbacks.signal);
279
+ callbacks.onDeviceCode({
280
+ userCode: device.userCode,
281
+ verificationUri: DEVICE_VERIFICATION_URL,
282
+ intervalSeconds: device.intervalMs / 1e3,
283
+ expiresInSeconds: DEVICE_AUTH_TIMEOUT_MS / 1e3
284
+ });
285
+ const authorization = await pollDeviceAuthorization({
286
+ ...device,
287
+ signal: callbacks.signal
288
+ });
289
+ return exchangeAuthorizationCode(authorization.code, authorization.verifier, callbacks.signal, DEVICE_REDIRECT_URI);
290
+ }
219
291
  async function refreshAccessToken(refreshToken) {
220
292
  return normalizeTokenResponse(await postTokenForm(new URLSearchParams({
221
293
  grant_type: "refresh_token",
@@ -258,7 +330,7 @@ function getAccountId(accessToken) {
258
330
  return null;
259
331
  }
260
332
  }
261
- async function loginOpenAICodex(callbacks) {
333
+ async function loginOpenAICodexWithBrowser(callbacks) {
262
334
  const { verifier, state, url } = await createAuthorizationFlow();
263
335
  const server = await startLocalOAuthServer(state);
264
336
  try {
@@ -288,25 +360,44 @@ async function loginOpenAICodex(callbacks) {
288
360
  server.close();
289
361
  }
290
362
  }
363
+ async function loginOpenAICodex(callbacks) {
364
+ return await callbacks.onSelect({
365
+ message: "Choose how to authorize OpenAI Codex",
366
+ options: [{
367
+ id: "browser",
368
+ label: "Browser (recommended for this device)"
369
+ }, {
370
+ id: "device_code",
371
+ label: "Device code (remote or headless)"
372
+ }]
373
+ }) === "device_code" ? loginOpenAICodexWithDeviceCode(callbacks) : loginOpenAICodexWithBrowser(callbacks);
374
+ }
291
375
  async function refreshOpenAICodexToken(refreshToken) {
292
376
  return refreshAccessToken(refreshToken);
293
377
  }
294
- var CLIENT_ID, AUTHORIZE_URL, TOKEN_URL, CALLBACK_PORT, CALLBACK_PATH, REDIRECT_URI, SCOPE, MANUAL_PROMPT_DELAY_MS, TOKEN_REQUEST_TIMEOUT_MS, openaiCodexOAuthProvider;
378
+ var CLIENT_ID, AUTH_BASE_URL, AUTHORIZE_URL, TOKEN_URL, DEVICE_USER_CODE_URL, DEVICE_TOKEN_URL, DEVICE_VERIFICATION_URL, DEVICE_REDIRECT_URI, CALLBACK_PORT, CALLBACK_PATH, REDIRECT_URI, SCOPE, MANUAL_PROMPT_DELAY_MS, TOKEN_REQUEST_TIMEOUT_MS, DEVICE_AUTH_TIMEOUT_MS, openaiCodexOAuthProvider;
295
379
  var init_openai_codex = __esmMin((() => {
296
380
  init_pkce();
297
381
  CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
298
- AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize";
299
- TOKEN_URL = "https://auth.openai.com/oauth/token";
382
+ AUTH_BASE_URL = "https://auth.openai.com";
383
+ AUTHORIZE_URL = `${AUTH_BASE_URL}/oauth/authorize`;
384
+ TOKEN_URL = `${AUTH_BASE_URL}/oauth/token`;
385
+ DEVICE_USER_CODE_URL = `${AUTH_BASE_URL}/api/accounts/deviceauth/usercode`;
386
+ DEVICE_TOKEN_URL = `${AUTH_BASE_URL}/api/accounts/deviceauth/token`;
387
+ DEVICE_VERIFICATION_URL = `${AUTH_BASE_URL}/codex/device`;
388
+ DEVICE_REDIRECT_URI = `${AUTH_BASE_URL}/deviceauth/callback`;
300
389
  CALLBACK_PORT = 1455;
301
390
  CALLBACK_PATH = "/auth/callback";
302
391
  REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
303
392
  SCOPE = "openid profile email offline_access";
304
393
  MANUAL_PROMPT_DELAY_MS = 15e3;
305
394
  TOKEN_REQUEST_TIMEOUT_MS = 3e4;
395
+ DEVICE_AUTH_TIMEOUT_MS = 15 * 6e4;
306
396
  openaiCodexOAuthProvider = {
307
397
  id: "openai-codex",
308
398
  name: "OpenAI Codex",
309
399
  usesCallbackServer: true,
400
+ loginMethods: ["browser", "device_code"],
310
401
  async login(callbacks) {
311
402
  return loginOpenAICodex(callbacks);
312
403
  },
@@ -10,6 +10,7 @@ export type OAuthCredentials = {
10
10
  [key: string]: unknown;
11
11
  };
12
12
  export type OAuthProviderId = string;
13
+ export type OAuthLoginMethod = 'browser' | 'device_code';
13
14
  export type OAuthPrompt = {
14
15
  message: string;
15
16
  placeholder?: string;
@@ -49,8 +50,10 @@ export interface OAuthProviderInterface {
49
50
  login(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;
50
51
  /** Whether login uses a local callback server and supports manual code input. */
51
52
  usesCallbackServer?: boolean;
53
+ /** Login methods exposed by providers that support more than one OAuth flow. */
54
+ loginMethods?: readonly OAuthLoginMethod[];
52
55
  /** Refresh expired credentials, return updated credentials to persist */
53
- refreshToken(credentials: OAuthCredentials): Promise<OAuthCredentials>;
56
+ refreshToken(credentials: OAuthCredentials, signal?: AbortSignal): Promise<OAuthCredentials>;
54
57
  /** Convert credentials to API key string for the provider */
55
58
  getApiKey(credentials: OAuthCredentials): string;
56
59
  }
@@ -1,6 +1,9 @@
1
1
  import { __esmMin } from "../../../_virtual/_rolldown/runtime.js";
2
+ import { generatePKCE, init_pkce } from "./pkce.js";
2
3
  import { hostname } from "node:os";
3
- import { setTimeout } from "node:timers/promises";
4
+ import { randomBytes } from "node:crypto";
5
+ import http from "node:http";
6
+ import { setTimeout as setTimeout$1 } from "node:timers/promises";
4
7
  //#region src/auth/oauth/xopc-cloud.ts
5
8
  function consoleUrl() {
6
9
  return (process.env.XOPC_CONSOLE_URL ?? DEFAULT_CONSOLE_URL).replace(/\/+$/, "");
@@ -29,7 +32,106 @@ async function tokenRequest(body, signal) {
29
32
  signal: signal ?? AbortSignal.timeout(3e4)
30
33
  });
31
34
  }
32
- async function login(callbacks) {
35
+ function callbackHtml(title, message) {
36
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${title}</title></head><body><main><h1>${title}</h1><p>${message}</p><p>You can close this window and return to XOPC.</p></main></body></html>`;
37
+ }
38
+ async function loginWithBrowser(callbacks) {
39
+ if (callbacks.signal?.aborted) throw callbacks.signal.reason instanceof Error ? callbacks.signal.reason : /* @__PURE__ */ new Error("XOPC OAuth login cancelled");
40
+ const { verifier, challenge } = await generatePKCE();
41
+ const state = randomBytes(24).toString("base64url");
42
+ let settle;
43
+ const callback = new Promise((resolve) => {
44
+ settle = resolve;
45
+ });
46
+ const server = http.createServer((request, response) => {
47
+ response.setHeader("content-type", "text/html; charset=utf-8");
48
+ try {
49
+ const url = new URL(request.url ?? "", "http://127.0.0.1");
50
+ if (url.pathname !== CALLBACK_PATH) {
51
+ response.statusCode = 404;
52
+ response.end(callbackHtml("Authorization callback not found", "This is not a valid XOPC OAuth callback URL."));
53
+ return;
54
+ }
55
+ const returnedState = url.searchParams.get("state");
56
+ const oauthError = url.searchParams.get("error");
57
+ const code = url.searchParams.get("code");
58
+ if (returnedState !== state) {
59
+ const error = /* @__PURE__ */ new Error("XOPC OAuth state mismatch");
60
+ response.statusCode = 400;
61
+ response.end(callbackHtml("Authorization failed", error.message));
62
+ settle?.({ error });
63
+ return;
64
+ }
65
+ if (oauthError || !code) {
66
+ const error = /* @__PURE__ */ new Error(oauthError === "access_denied" ? "XOPC OAuth authorization was denied" : "XOPC OAuth callback did not include an authorization code");
67
+ response.statusCode = 400;
68
+ response.end(callbackHtml("Authorization failed", error.message));
69
+ settle?.({ error });
70
+ return;
71
+ }
72
+ response.statusCode = 200;
73
+ response.end(callbackHtml("Authorization complete", "XOPC received the authorization callback successfully."));
74
+ settle?.({ code });
75
+ } catch {
76
+ const error = /* @__PURE__ */ new Error("XOPC OAuth callback could not be processed");
77
+ response.statusCode = 500;
78
+ response.end(callbackHtml("Authorization failed", error.message));
79
+ settle?.({ error });
80
+ }
81
+ });
82
+ const redirectUri = await new Promise((resolve, reject) => {
83
+ server.once("error", reject);
84
+ server.listen(0, "127.0.0.1", () => {
85
+ server.removeListener("error", reject);
86
+ const address = server.address();
87
+ if (!address || typeof address === "string") {
88
+ reject(/* @__PURE__ */ new Error("XOPC OAuth callback server did not expose a TCP port"));
89
+ return;
90
+ }
91
+ resolve(`http://127.0.0.1:${address.port}${CALLBACK_PATH}`);
92
+ });
93
+ });
94
+ const authorizationUrl = new URL(`${consoleUrl()}/oauth/authorize`);
95
+ authorizationUrl.search = new URLSearchParams({
96
+ response_type: "code",
97
+ client_id: CLIENT_ID,
98
+ redirect_uri: redirectUri,
99
+ scope: DEFAULT_SCOPE,
100
+ code_challenge: challenge,
101
+ code_challenge_method: "S256",
102
+ state,
103
+ device_name: hostname() || "XOPC client",
104
+ client_type: "cli"
105
+ }).toString();
106
+ const timeout = setTimeout(() => settle?.({ error: /* @__PURE__ */ new Error("XOPC OAuth authorization timed out") }), AUTHORIZATION_TIMEOUT_MS);
107
+ timeout.unref?.();
108
+ const abort = () => settle?.({ error: callbacks.signal?.reason instanceof Error ? callbacks.signal.reason : /* @__PURE__ */ new Error("XOPC OAuth login cancelled") });
109
+ callbacks.signal?.addEventListener("abort", abort, { once: true });
110
+ try {
111
+ callbacks.onAuth({
112
+ url: authorizationUrl.toString(),
113
+ instructions: "Complete authorization in your browser. XOPC will finish automatically after the local callback."
114
+ });
115
+ const result = await callback;
116
+ if (result.error) throw result.error;
117
+ if (!result.code) throw new Error("XOPC OAuth callback did not include an authorization code");
118
+ const token = await tokenRequest(new URLSearchParams({
119
+ grant_type: "authorization_code",
120
+ client_id: CLIENT_ID,
121
+ code: result.code,
122
+ code_verifier: verifier,
123
+ redirect_uri: redirectUri
124
+ }), callbacks.signal);
125
+ const body = await readJson(token);
126
+ if (!token.ok) throw new Error(body.error_description ?? body.error ?? "XOPC OAuth token exchange failed");
127
+ return credentials(body);
128
+ } finally {
129
+ clearTimeout(timeout);
130
+ callbacks.signal?.removeEventListener("abort", abort);
131
+ server.close();
132
+ }
133
+ }
134
+ async function loginWithDeviceCode(callbacks) {
33
135
  const response = await fetch(`${consoleUrl()}/oauth/device_authorization`, {
34
136
  method: "POST",
35
137
  headers: {
@@ -60,7 +162,7 @@ async function login(callbacks) {
60
162
  });
61
163
  while (Date.now() < expiresAt) {
62
164
  if (callbacks.signal?.aborted) throw callbacks.signal.reason ?? /* @__PURE__ */ new Error("OAuth login cancelled");
63
- await setTimeout(intervalMs, void 0, callbacks.signal ? { signal: callbacks.signal } : void 0);
165
+ await setTimeout$1(intervalMs, void 0, callbacks.signal ? { signal: callbacks.signal } : void 0);
64
166
  const token = await tokenRequest(new URLSearchParams({
65
167
  grant_type: "urn:ietf:params:oauth:grant-type:device_code",
66
168
  client_id: CLIENT_ID,
@@ -73,24 +175,40 @@ async function login(callbacks) {
73
175
  }
74
176
  throw new Error("XOPC OAuth authorization expired");
75
177
  }
76
- async function refreshToken(current) {
178
+ async function login(callbacks) {
179
+ return await callbacks.onSelect({
180
+ message: "Choose how to authorize XOPC Model Service",
181
+ options: [{
182
+ id: "browser",
183
+ label: "Browser (recommended for this device)"
184
+ }, {
185
+ id: "device_code",
186
+ label: "Device code (remote or headless)"
187
+ }]
188
+ }) === "device_code" ? loginWithDeviceCode(callbacks) : loginWithBrowser(callbacks);
189
+ }
190
+ async function refreshToken(current, signal) {
77
191
  const response = await tokenRequest(new URLSearchParams({
78
192
  grant_type: "refresh_token",
79
193
  client_id: CLIENT_ID,
80
194
  refresh_token: current.refresh
81
- }));
195
+ }), signal);
82
196
  const body = await readJson(response);
83
197
  if (!response.ok) throw new Error(body.error_description ?? body.error ?? "XOPC OAuth refresh failed");
84
198
  return credentials(body);
85
199
  }
86
- var CLIENT_ID, DEFAULT_CONSOLE_URL, DEFAULT_SCOPE, xopcCloudOAuthProvider;
200
+ var CLIENT_ID, DEFAULT_CONSOLE_URL, DEFAULT_SCOPE, CALLBACK_PATH, AUTHORIZATION_TIMEOUT_MS, xopcCloudOAuthProvider;
87
201
  var init_xopc_cloud = __esmMin((() => {
202
+ init_pkce();
88
203
  CLIENT_ID = "xopc-native";
89
204
  DEFAULT_CONSOLE_URL = "https://console.xopc.ai";
90
205
  DEFAULT_SCOPE = "models:read models:invoke account:usage offline_access";
206
+ CALLBACK_PATH = "/oauth/callback";
207
+ AUTHORIZATION_TIMEOUT_MS = 5 * 6e4;
91
208
  xopcCloudOAuthProvider = {
92
209
  id: "xopc-cloud",
93
210
  name: "XOPC Model Service",
211
+ loginMethods: ["browser", "device_code"],
94
212
  login,
95
213
  refreshToken,
96
214
  getApiKey: (value) => value.access
@@ -0,0 +1 @@
1
+ export declare const DEFAULT_AUTOMATION_TIMEOUT_SECONDS = 300;
@@ -0,0 +1,4 @@
1
+ //#region src/automations/domain/defaults.ts
2
+ const DEFAULT_AUTOMATION_TIMEOUT_SECONDS = 300;
3
+ //#endregion
4
+ export { DEFAULT_AUTOMATION_TIMEOUT_SECONDS };
@@ -1,3 +1,4 @@
1
+ export * from './defaults.js';
1
2
  export * from './schedule.js';
2
3
  export * from './types.js';
3
4
  export * from './validation.js';
@@ -1,3 +1,4 @@
1
+ import { DEFAULT_AUTOMATION_TIMEOUT_SECONDS } from "./defaults.js";
1
2
  import { computeNextAutomationRunAtMs, computeNextScheduleRunAtMs, timerDelayUntil } from "./schedule.js";
2
3
  import { AutomationActionSchema, AutomationAfterRunSchema, AutomationReliabilitySchema, AutomationSafetyPolicySchema, AutomationScheduleSchema, AutomationSchema, AutomationStateSchema, AutomationTriggerSchema, CreateAutomationSchema, UpdateAutomationSchema } from "./validation.js";
3
- export { AutomationActionSchema, AutomationAfterRunSchema, AutomationReliabilitySchema, AutomationSafetyPolicySchema, AutomationScheduleSchema, AutomationSchema, AutomationStateSchema, AutomationTriggerSchema, CreateAutomationSchema, UpdateAutomationSchema, computeNextAutomationRunAtMs, computeNextScheduleRunAtMs, timerDelayUntil };
4
+ export { AutomationActionSchema, AutomationAfterRunSchema, AutomationReliabilitySchema, AutomationSafetyPolicySchema, AutomationScheduleSchema, AutomationSchema, AutomationStateSchema, AutomationTriggerSchema, CreateAutomationSchema, DEFAULT_AUTOMATION_TIMEOUT_SECONDS, UpdateAutomationSchema, computeNextAutomationRunAtMs, computeNextScheduleRunAtMs, timerDelayUntil };
@@ -1,8 +1,9 @@
1
1
  import { onAutomationProductEvent, publishAutomationProductEvent } from "./product-events.js";
2
+ import { DEFAULT_AUTOMATION_TIMEOUT_SECONDS } from "./domain/defaults.js";
2
3
  import { computeNextAutomationRunAtMs, computeNextScheduleRunAtMs, timerDelayUntil } from "./domain/schedule.js";
3
4
  import { AutomationActionSchema, AutomationAfterRunSchema, AutomationReliabilitySchema, AutomationSafetyPolicySchema, AutomationScheduleSchema, AutomationSchema, AutomationStateSchema, AutomationTriggerSchema, CreateAutomationSchema, UpdateAutomationSchema } from "./domain/validation.js";
4
5
  import "./domain/index.js";
5
6
  import { AutomationActionExecutor } from "./service/action-executor.js";
6
7
  import { AutomationAlreadyRunningError, AutomationService } from "./service/automation-service.js";
7
8
  import "./service/index.js";
8
- export { AutomationActionExecutor, AutomationActionSchema, AutomationAfterRunSchema, AutomationAlreadyRunningError, AutomationReliabilitySchema, AutomationSafetyPolicySchema, AutomationScheduleSchema, AutomationSchema, AutomationService, AutomationStateSchema, AutomationTriggerSchema, CreateAutomationSchema, UpdateAutomationSchema, computeNextAutomationRunAtMs, computeNextScheduleRunAtMs, onAutomationProductEvent, publishAutomationProductEvent, timerDelayUntil };
9
+ export { AutomationActionExecutor, AutomationActionSchema, AutomationAfterRunSchema, AutomationAlreadyRunningError, AutomationReliabilitySchema, AutomationSafetyPolicySchema, AutomationScheduleSchema, AutomationSchema, AutomationService, AutomationStateSchema, AutomationTriggerSchema, CreateAutomationSchema, DEFAULT_AUTOMATION_TIMEOUT_SECONDS, UpdateAutomationSchema, computeNextAutomationRunAtMs, computeNextScheduleRunAtMs, onAutomationProductEvent, publishAutomationProductEvent, timerDelayUntil };
@@ -2,13 +2,13 @@ import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { init_agent_scope, normalizeAgentId } from "../../agent/agent-scope.js";
4
4
  import { buildSessionKey, init_session_key } from "../../routing/session-key.js";
5
+ import "../domain/defaults.js";
5
6
  import crypto from "node:crypto";
6
7
  //#region src/automations/service/action-executor.ts
7
8
  init_agent_scope();
8
9
  init_session_key();
9
10
  init_logger();
10
11
  const log = createLogger("Automation:ActionExecutor");
11
- const DEFAULT_TIMEOUT_MS = 18e4;
12
12
  function withTimeout(promise, timeoutMs, signal) {
13
13
  return new Promise((resolve, reject) => {
14
14
  if (signal.aborted) {
@@ -41,7 +41,7 @@ var AutomationActionExecutor = class {
41
41
  };
42
42
  }
43
43
  async execute(automation, run, signal) {
44
- const timeoutMs = (automation.action.timeoutSeconds ?? automation.reliability?.timeoutSeconds ?? 0) > 0 ? (automation.action.timeoutSeconds ?? automation.reliability?.timeoutSeconds) * 1e3 : DEFAULT_TIMEOUT_MS;
44
+ const timeoutMs = (automation.action.timeoutSeconds ?? automation.reliability?.timeoutSeconds ?? 0) > 0 ? (automation.action.timeoutSeconds ?? automation.reliability?.timeoutSeconds) * 1e3 : 300 * 1e3;
45
45
  return withTimeout(this.executeWithoutTimeout(automation, run, signal), timeoutMs, signal).catch((err) => {
46
46
  const message = err instanceof Error ? err.message : String(err);
47
47
  return {
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
52
52
  id: "database-schema",
53
53
  label: "Database schema",
54
54
  status: "pass",
55
- message: `SQLite schema v${status.dbVersion} (current release v66).`,
55
+ message: `SQLite schema v${status.dbVersion} (current release v67).`,
56
56
  hints: []
57
57
  };
58
58
  }
@@ -3,8 +3,8 @@ import { loadConfig } from "../../../config/loader.js";
3
3
  import "../../../config/index.js";
4
4
  import { isRestartEnabled } from "../../../config/commands.flags.js";
5
5
  import { resolveGatewayService } from "../../../daemon/service.js";
6
- import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "../../../infra/restart.js";
7
6
  import { findVerifiedGatewayListenerPidsOnPortSync, formatGatewayPidList, signalVerifiedGatewayPidSync } from "../../../infra/gateway-processes.js";
7
+ import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "../../../infra/restart.js";
8
8
  import { runServiceRestart, runServiceStop } from "./lifecycle-core.js";
9
9
  import { DEFAULT_RESTART_HEALTH_ATTEMPTS, renderGatewayPortHealthDiagnostics, waitForGatewayHealthyListener } from "./restart-health.js";
10
10
  import { parsePortFromArgs, renderGatewayServiceStartHints, resolveGatewayPortFromConfig } from "./shared.js";
@@ -3,8 +3,8 @@ import { init_paths, resolveBundledSkillsDir, resolveSkillsLockPath } from "../.
3
3
  import { findInstallSpec, getDefaultInstallerPreferences, hasBinary, installSkill } from "../../agent/skills/installer.js";
4
4
  import { createSkillConfigManager, isSkillEnabled } from "../../agent/skills/config.js";
5
5
  import { formatScanSummary, scanSkillDirectory } from "../../agent/skills/scanner.js";
6
- import { loadSkillsLock } from "../../agent/skills/hub-lock.js";
7
6
  import { createSkillLoader } from "../../agent/skills/index.js";
7
+ import { loadSkillsLock } from "../../agent/skills/hub-lock.js";
8
8
  import { pullSkillFromSource, updateSkillFromLock } from "../../agent/skills/hub-pull.js";
9
9
  import { register } from "../registry.js";
10
10
  import { createSkillsTestCommand } from "./skills-test.js";