@xopcai/xopc 0.0.211 → 0.0.213

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 (212) 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-BzjFoSr0.js → activity-store-Xw-pOm9A.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DTfjhfVE.js → agent-avatar-dicebear-Ca1bciiK.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-DD3TqNrC.js +68 -0
  6. package/dist/gateway/static/root/assets/{api-D269PnU9.js → api-CZK-lRew.js} +1 -1
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-BFpfQDWc.js → app-management-settings-panel-BLFIG09j.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-DLxFdqhY.js → appearance-settings-BsTWUq1i.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-cJkDKn72.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-DPlH4dnc.js → archive-plugin-B9LsFfEx.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-xqfLLd0I.js → attachment-load-CsWiFfmN.js} +1 -1
  12. package/dist/gateway/static/root/assets/automations-page-CbjU2e75.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-workspace-C4xyo0c4.js +6 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-C0tuoPXk.js → binary-plugins-DbqhT_JB.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-Deyphj1o.js → block-editor-BGpHwxZ5.js} +47 -47
  16. package/dist/gateway/static/root/assets/browser-settings-page-CrhpQl-e.js +8 -0
  17. package/dist/gateway/static/root/assets/{browser-workflow-inputs-CYEbXyRF.js → browser-workflow-inputs-BXlon_hL.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-workflows-page-Bf0tPbGi.js → browser-workflows-page-B3BBDM_r.js} +2 -2
  19. package/dist/gateway/static/root/assets/capabilities-settings-panel-B9MoPW9u.js +7 -0
  20. package/dist/gateway/static/root/assets/{capability-presets-api-DPkFA_-R.js → capability-presets-api-BqvMm6UW.js} +1 -1
  21. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BmwldV9R.js +3 -0
  22. package/dist/gateway/static/root/assets/{channel-recipient-api-DqKaAcnZ.js → channel-recipient-api-9uca5kDa.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-settings-CwLqWcy_.js +1 -0
  24. package/dist/gateway/static/root/assets/channels-status-swr-DeBw3du9.js +1 -0
  25. package/dist/gateway/static/root/assets/{chat-terminal-dock-CTDRZa7e.js → chat-terminal-dock-DJjYT3WX.js} +2 -2
  26. package/dist/gateway/static/root/assets/{chunk-KS7C4IRE-BMhrPKJC.js → chunk-KS7C4IRE-BaASWQor.js} +1 -1
  27. package/dist/gateway/static/root/assets/{connectors-api-Buu8fif8.js → connectors-api-XCLfuDrN.js} +1 -1
  28. package/dist/gateway/static/root/assets/connectors-page-CVkGtcMS.js +2 -0
  29. package/dist/gateway/static/root/assets/{cron-expression-DTLR82NB.js → cron-expression-DzQN7zBR.js} +1 -1
  30. package/dist/gateway/static/root/assets/{date-picker-DyNogHQH.js → date-picker-B-r5O5qd.js} +1 -1
  31. package/dist/gateway/static/root/assets/{dependency-picker-BpnCuo7B.js → dependency-picker-Ch2XBU2s.js} +1 -1
  32. package/dist/gateway/static/root/assets/{desktop-pet-CDKI4gVB.js → desktop-pet-BdjX8jde.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-settings-DjT5C2a3.js → desktop-pet-settings-CzjjgMMn.js} +1 -1
  34. package/dist/gateway/static/root/assets/directory-picker-path-field-BCTgGTk4.js +1 -0
  35. package/dist/gateway/static/root/assets/{extension-debug-page-DWf2z7q5.js → extension-debug-page-6OGgOucD.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-page-Dorx0kf9.js → extension-page-Cf6MUfCF.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-settings-page-B1wU9ZOB.js → extension-settings-page-pSY_ZvQZ.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-config-api-B1lG4dNr.js → gateway-config-api-CFJMng9v.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-config-swr-BIxuwPQi.js → gateway-config-swr-DpiY6aub.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-settings-DqIOqJjM.js → gateway-settings-aQYxNePf.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-startup-retry-BpZgd4U-.js → gateway-startup-retry-BZ_6ChP4.js} +1 -1
  42. package/dist/gateway/static/root/assets/{heartbeat-settings-DG4Kmgkc.js → heartbeat-settings-CI33q9i1.js} +1 -1
  43. package/dist/gateway/static/root/assets/home-page-CAIaWs6r.js +1 -0
  44. package/dist/gateway/static/root/assets/{image-generation-api-PkhYohDa.js → image-generation-api-DPndEWOU.js} +1 -1
  45. package/dist/gateway/static/root/assets/index-BhstAl5i.js +108 -0
  46. package/dist/gateway/static/root/assets/index-DQzjgIkQ.css +2 -0
  47. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-6OQT3gQF.js → keyboard-shortcuts-settings-CbLJRGXR.js} +1 -1
  48. package/dist/gateway/static/root/assets/local-app-workbench-page-BqFnCaKT.js +2 -0
  49. package/dist/gateway/static/root/assets/{local-apps-page-DfruRAmE.js → local-apps-page-Crf6c3SK.js} +1 -1
  50. package/dist/gateway/static/root/assets/{locale-store-C5MK9WcP.js → locale-store-BYSRjM6g.js} +1 -1
  51. package/dist/gateway/static/root/assets/logs-page-BpfLQWex.js +2 -0
  52. package/dist/gateway/static/root/assets/{management-settings-L1VYkywO.js → management-settings-mxyYWKgM.js} +1 -1
  53. package/dist/gateway/static/root/assets/{markdown-split-oqgHbqt-.js → markdown-split-kZaPrUTM.js} +1 -1
  54. package/dist/gateway/static/root/assets/{markdown-view-V4rcPPH0.js → markdown-view-DlsczsQ1.js} +1 -1
  55. package/dist/gateway/static/root/assets/{media-plugins-Bb6gSX2o.js → media-plugins-Dk67jaG6.js} +1 -1
  56. package/dist/gateway/static/root/assets/messages-DyM8OOVG.js +3 -0
  57. package/dist/gateway/static/root/assets/notes-api-DaeeQw8A.js +1 -0
  58. package/dist/gateway/static/root/assets/{notes-page-B1rOXjpT.js → notes-page-CQDzw8fX.js} +1 -1
  59. package/dist/gateway/static/root/assets/notes-workbench-BYiROmRJ.js +4 -0
  60. package/dist/gateway/static/root/assets/{page-tabs-CBuCKeyy.js → page-tabs-C4UkhX2U.js} +1 -1
  61. package/dist/gateway/static/root/assets/{preview-open-alternatives-BQ0tLfPO.js → preview-open-alternatives-nzcjh6y0.js} +1 -1
  62. package/dist/gateway/static/root/assets/{product-open-page-DPeFn7Hu.js → product-open-page-3FvW5cHm.js} +1 -1
  63. package/dist/gateway/static/root/assets/project-detail-page-p45i1sMj.js +1 -0
  64. package/dist/gateway/static/root/assets/projects-page-Y9yXB4DX.js +1 -0
  65. package/dist/gateway/static/root/assets/registry-api-Bu6OGEY2.js +2 -0
  66. package/dist/gateway/static/root/assets/remote-access-hub-CNsGY0VS.js +1 -0
  67. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BCfQNzjG.js → runtime-tools-settings-panel-CVqPSfUb.js} +2 -2
  68. package/dist/gateway/static/root/assets/{schema-form-Bo7YbHYN.js → schema-form-Dz6eZpqv.js} +1 -1
  69. package/dist/gateway/static/root/assets/sessions-page-BAtpgb1t.js +1 -0
  70. package/dist/gateway/static/root/assets/settings-advanced-gate-pgBQ21Oe.js +1 -0
  71. package/dist/gateway/static/root/assets/{settings-form-section-B9dnKr3M.js → settings-form-section-BaWFAZv4.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-loading-skeleton-CYDV2JtY.js → settings-loading-skeleton-BWmdZfNg.js} +1 -1
  73. package/dist/gateway/static/root/assets/{settings-page-DbrIYfS9.js → settings-page-Btcb-Dc8.js} +1 -1
  74. package/dist/gateway/static/root/assets/setup-status-panel-BNllZUFP.js +1 -0
  75. package/dist/gateway/static/root/assets/{share-preview-page-olgr7LLN.js → share-preview-page-CGzY3S0N.js} +1 -1
  76. package/dist/gateway/static/root/assets/shares-settings-CncwbTHY.js +1 -0
  77. package/dist/gateway/static/root/assets/skill-reload-api-CcW2dhSW.js +1 -0
  78. package/dist/gateway/static/root/assets/{skills-page-PE16CNw5.js → skills-page-Bi2IWpU0.js} +1 -1
  79. package/dist/gateway/static/root/assets/{skills-page.utils-nXmBcBxt.js → skills-page.utils-BancvwN2.js} +1 -1
  80. package/dist/gateway/static/root/assets/{system-settings-panel-C3qPwAdY.js → system-settings-panel-CihjIzWx.js} +1 -1
  81. package/dist/gateway/static/root/assets/task-detail-page-SSNFtY-d.js +1 -0
  82. package/dist/gateway/static/root/assets/{theme-store-KR5Otp5w.js → theme-store-D1_t_31B.js} +1 -1
  83. package/dist/gateway/static/root/assets/{typed-models-lib-lMZodtDF.js → typed-models-lib-C2LhiQq5.js} +1 -1
  84. package/dist/gateway/static/root/assets/{use-autosave-CKpatP3S.js → use-autosave-tf_8rxAK.js} +1 -1
  85. package/dist/gateway/static/root/assets/user-context-page-BnPTFEar.js +1 -0
  86. package/dist/gateway/static/root/assets/{voice-api-key-field-CDcv0Wbh.js → voice-api-key-field-DN-y7Zfe.js} +1 -1
  87. package/dist/gateway/static/root/assets/work-discovery-overlay-bqqH4aZ9.js +1 -0
  88. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BAHYNlQt.js → workflow-run-setup-panel-2H33iXOB.js} +2 -2
  89. package/dist/gateway/static/root/assets/workflows-page-BnfxRf1q.js +5 -0
  90. package/dist/gateway/static/root/index.html +12 -10
  91. package/dist/package.js +1 -1
  92. package/dist/src/auth/oauth/xopc-cloud.js +1 -1
  93. package/dist/src/cli/commands/connectors.js +1 -1
  94. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  95. package/dist/src/cli/commands/tunnel.js +3 -3
  96. package/dist/src/config/agent-profile.js +1 -1
  97. package/dist/src/connectors/composio-managed-client.d.ts +60 -0
  98. package/dist/src/connectors/composio-managed-client.js +135 -0
  99. package/dist/src/connectors/composio-managed-events.d.ts +41 -0
  100. package/dist/src/connectors/composio-managed-events.js +105 -0
  101. package/dist/src/connectors/composio-sessions.d.ts +2 -1
  102. package/dist/src/connectors/composio-sessions.js +13 -7
  103. package/dist/src/connectors/composio.js +2 -1
  104. package/dist/src/connectors/connected-source-ingestion.js +67 -25
  105. package/dist/src/connectors/health.js +1 -1
  106. package/dist/src/connectors/learning-recipes.js +2 -0
  107. package/dist/src/connectors/runtime-adapter-registry.js +2 -2
  108. package/dist/src/discussions/sealer.js +2 -2
  109. package/dist/src/discussions/service.js +6 -2
  110. package/dist/src/discussions/transcript.d.ts +2 -0
  111. package/dist/src/discussions/transcript.js +16 -3
  112. package/dist/src/extensions/install.d.ts +10 -0
  113. package/dist/src/extensions/install.js +111 -14
  114. package/dist/src/extensions/loader.js +22 -18
  115. package/dist/src/gateway/agents-admin.js +1 -1
  116. package/dist/src/gateway/heartbeat/service.js +1 -1
  117. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  118. package/dist/src/gateway/hono/middleware/auth.js +2 -2
  119. package/dist/src/gateway/hono/middleware/logger.js +1 -1
  120. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +1 -1
  121. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  122. package/dist/src/gateway/hono/routes/connectors.js +11 -4
  123. package/dist/src/gateway/hono/routes/exposure.js +1 -1
  124. package/dist/src/gateway/hono/routes/home.d.ts +1 -1
  125. package/dist/src/gateway/hono/routes/home.js +2 -2
  126. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  127. package/dist/src/gateway/hono/routes/shares.js +1 -1
  128. package/dist/src/gateway/hono/routes/tunnel.js +3 -3
  129. package/dist/src/gateway/hono/routes/workflows.js +69 -0
  130. package/dist/src/gateway/index.js +2 -2
  131. package/dist/src/gateway/runtime-config.js +2 -2
  132. package/dist/src/gateway/security/audit.js +2 -2
  133. package/dist/src/gateway/service/config-coordinator.js +1 -1
  134. package/dist/src/gateway/service.d.ts +1 -0
  135. package/dist/src/gateway/service.js +25 -10
  136. package/dist/src/heartbeat/index.js +1 -1
  137. package/dist/src/notes/note-attachment-sync.js +1 -1
  138. package/dist/src/notes/service.d.ts +1 -0
  139. package/dist/src/notes/service.js +2 -1
  140. package/dist/src/notes/types.d.ts +2 -0
  141. package/dist/src/providers/model-catalog-persistence.d.ts +1 -1
  142. package/dist/src/providers/model-catalog-store.d.ts +2 -60
  143. package/dist/src/providers/model-catalog-types.d.ts +60 -0
  144. package/dist/src/providers/model-catalog-types.js +1 -0
  145. package/dist/src/providers/provider-disconnect-core.d.ts +11 -0
  146. package/dist/src/providers/provider-disconnect-core.js +35 -0
  147. package/dist/src/providers/provider-disconnect.d.ts +2 -10
  148. package/dist/src/providers/provider-disconnect.js +4 -26
  149. package/dist/src/providers/xopc-cloud-catalog-coordinator.js +2 -2
  150. package/dist/src/storage/sqlite/migrations/124_workflow_context_snapshots.sql +15 -0
  151. package/dist/src/storage/sqlite/migrations/125_project_workflow_presets.sql +12 -0
  152. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  153. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  154. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  155. package/dist/src/storage/sqlite/schema.js +1 -1
  156. package/dist/src/tasks/home-query-service.d.ts +12 -127
  157. package/dist/src/tasks/home-query-service.js +73 -271
  158. package/dist/src/tasks/index.js +2 -2
  159. package/dist/src/tui/tui-startup-resources.js +1 -1
  160. package/dist/src/tui/xopc-tui-keybindings.d.ts +2 -2
  161. package/dist/src/tunnel/index.js +2 -2
  162. package/dist/src/voice/audio/normalize.d.ts +1 -0
  163. package/dist/src/voice/audio/normalize.js +24 -4
  164. package/dist/src/voice/local/wav.d.ts +3 -0
  165. package/dist/src/voice/local/wav.js +10 -4
  166. package/dist/src/work-discovery/service.js +6 -8
  167. package/dist/src/work-discovery/types.d.ts +2 -0
  168. package/dist/src/workflows/context/workflow-context-snapshot-repository.d.ts +21 -0
  169. package/dist/src/workflows/context/workflow-context-snapshot-repository.js +40 -0
  170. package/dist/src/workflows/context/workflow-context.d.ts +18 -0
  171. package/dist/src/workflows/context/workflow-context.js +159 -0
  172. package/dist/src/workflows/domain/run.d.ts +10 -1
  173. package/dist/src/workflows/engine/workflow-engine.d.ts +1 -0
  174. package/dist/src/workflows/engine/workflow-engine.js +2 -0
  175. package/dist/src/workflows/project-presets/project-workflow-preset-repository.d.ts +20 -0
  176. package/dist/src/workflows/project-presets/project-workflow-preset-repository.js +38 -0
  177. package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
  178. package/dist/src/workflows/service/workflow-run-service.js +107 -22
  179. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -0
  180. package/dist/src/workflows/service/workflow-writeback-service.d.ts +9 -0
  181. package/dist/src/workflows/service/workflow-writeback-service.js +106 -0
  182. package/package.json +6 -6
  183. package/dist/gateway/static/root/assets/agents-CjhgfuVJ.js +0 -68
  184. package/dist/gateway/static/root/assets/apps-page-CjmlGB5V.js +0 -1
  185. package/dist/gateway/static/root/assets/automations-page-4m6Ey6wG.js +0 -6
  186. package/dist/gateway/static/root/assets/browser-settings-page-CAGCYx8U.js +0 -8
  187. package/dist/gateway/static/root/assets/capabilities-settings-panel-CKfLsxTI.js +0 -7
  188. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CpipKNqX.js +0 -3
  189. package/dist/gateway/static/root/assets/channels-settings-Bvq-O4pt.js +0 -1
  190. package/dist/gateway/static/root/assets/channels-status-swr-CrMld2l7.js +0 -1
  191. package/dist/gateway/static/root/assets/connectors-page-CSQRzaVn.js +0 -2
  192. package/dist/gateway/static/root/assets/directory-picker-path-field-DlJY90TM.js +0 -1
  193. package/dist/gateway/static/root/assets/home-page-BhqItS_s.js +0 -1
  194. package/dist/gateway/static/root/assets/index-DLhvsU9B.css +0 -2
  195. package/dist/gateway/static/root/assets/index-_cuTcWjB.js +0 -107
  196. package/dist/gateway/static/root/assets/local-app-workbench-page-DWjTmzxw.js +0 -2
  197. package/dist/gateway/static/root/assets/logs-page-BA5efZ8B.js +0 -2
  198. package/dist/gateway/static/root/assets/messages-ctG2e-ix.js +0 -3
  199. package/dist/gateway/static/root/assets/notes-workbench-CkHXVmKP.js +0 -4
  200. package/dist/gateway/static/root/assets/project-detail-page-DCqet9-L.js +0 -1
  201. package/dist/gateway/static/root/assets/projects-page-D0t_AjzG.js +0 -1
  202. package/dist/gateway/static/root/assets/remote-access-hub-BUWPoBvw.js +0 -1
  203. package/dist/gateway/static/root/assets/sessions-page-vLhrrM3m.js +0 -1
  204. package/dist/gateway/static/root/assets/settings-advanced-gate-OP1y0Y8M.js +0 -1
  205. package/dist/gateway/static/root/assets/setup-status-panel-Cxc-Ejl5.js +0 -1
  206. package/dist/gateway/static/root/assets/shares-settings-ZOqC6-aA.js +0 -1
  207. package/dist/gateway/static/root/assets/skill-reload-api-DwvC3Iuf.js +0 -1
  208. package/dist/gateway/static/root/assets/task-detail-page-DCRB-5q-.js +0 -1
  209. package/dist/gateway/static/root/assets/user-context-page-CoiedRuA.js +0 -1
  210. package/dist/gateway/static/root/assets/work-discovery-overlay-CGdT22un.js +0 -1
  211. package/dist/gateway/static/root/assets/work-discovery-page-BwaU1RqI.js +0 -1
  212. package/dist/gateway/static/root/assets/workflows-page-DHYmh9G7.js +0 -5
@@ -7,8 +7,9 @@ import { checkEngineCompatibility } from "./engine-check.js";
7
7
  import { collectExtensionPackageDependencyIssues } from "./package-contract.js";
8
8
  import { dirname, isAbsolute, join, resolve, sep } from "path";
9
9
  import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
10
- import { execSync } from "child_process";
10
+ import { execFileSync } from "node:child_process";
11
11
  import AdmZip from "adm-zip";
12
+ import semver from "semver";
12
13
  import { tmpdir } from "os";
13
14
  //#region src/extensions/install.ts
14
15
  /**
@@ -21,6 +22,58 @@ init_package_version();
21
22
  init_logger();
22
23
  const log = createLogger("ExtensionInstall");
23
24
  const NPM_INSTALL_ENV = process.env.XOPC_EXTENSION_NPM_INSTALL?.trim().toLowerCase();
25
+ const NPM_INSTALL_SCRIPTS_ENV = process.env.XOPC_EXTENSION_NPM_INSTALL_SCRIPTS?.trim().toLowerCase();
26
+ const ALLOW_NPM_INSTALL_SCRIPTS = [
27
+ "1",
28
+ "true",
29
+ "allow"
30
+ ].includes(NPM_INSTALL_SCRIPTS_ENV ?? "");
31
+ const NPM_PACKAGE_PART_RE = /^(?![._])[a-z0-9][a-z0-9._~-]*$/;
32
+ /** Accept registry package names with an optional exact semver; reject URLs, paths, tags, and ranges. */
33
+ function validateNpmPackageSpec(packageSpec) {
34
+ if (!packageSpec || packageSpec !== packageSpec.trim() || /\s/.test(packageSpec)) return {
35
+ ok: false,
36
+ error: "npm package spec must not be empty or contain whitespace"
37
+ };
38
+ let packageName = packageSpec;
39
+ let version;
40
+ if (packageSpec.startsWith("@")) {
41
+ const slashIndex = packageSpec.indexOf("/");
42
+ const versionSeparator = packageSpec.lastIndexOf("@");
43
+ if (slashIndex <= 1) return {
44
+ ok: false,
45
+ error: "Invalid scoped npm package name"
46
+ };
47
+ if (versionSeparator > slashIndex) {
48
+ packageName = packageSpec.slice(0, versionSeparator);
49
+ version = packageSpec.slice(versionSeparator + 1);
50
+ }
51
+ } else {
52
+ const versionSeparator = packageSpec.lastIndexOf("@");
53
+ if (versionSeparator > 0) {
54
+ packageName = packageSpec.slice(0, versionSeparator);
55
+ version = packageSpec.slice(versionSeparator + 1);
56
+ }
57
+ }
58
+ if (packageName.length > 214) return {
59
+ ok: false,
60
+ error: "npm package name exceeds 214 characters"
61
+ };
62
+ const parts = packageName.startsWith("@") ? packageName.slice(1).split("/") : [packageName];
63
+ if (parts.length !== (packageName.startsWith("@") ? 2 : 1) || parts.some((part) => !NPM_PACKAGE_PART_RE.test(part))) return {
64
+ ok: false,
65
+ error: "Only npm registry package names are allowed (for example pkg or @scope/pkg)"
66
+ };
67
+ if (version !== void 0 && !semver.valid(version)) return {
68
+ ok: false,
69
+ error: "npm package versions must be exact semver values; tags and ranges are not allowed"
70
+ };
71
+ return {
72
+ ok: true,
73
+ packageName,
74
+ ...version ? { version } : {}
75
+ };
76
+ }
24
77
  function extractExecSyncOutput(error) {
25
78
  if (!error || typeof error !== "object") return "";
26
79
  const o = error;
@@ -41,8 +94,9 @@ function truncateOutput(text, max = 4500) {
41
94
  }
42
95
  /**
43
96
  * Install production `node_modules` for an unpacked extension (package.json dependencies).
44
- * Uses pnpm when `pnpm-lock.yaml` is present, otherwise npm. Set `XOPC_EXTENSION_NPM_INSTALL=skip`
45
- * to skip (extensions must ship runnable code or you install deps manually).
97
+ * Uses pnpm when `pnpm-lock.yaml` is present, otherwise npm. Lifecycle scripts are disabled by
98
+ * default; set `XOPC_EXTENSION_NPM_INSTALL_SCRIPTS=allow` only for a reviewed extension that needs
99
+ * them. Set `XOPC_EXTENSION_NPM_INSTALL=skip` to skip dependency installation entirely.
46
100
  */
47
101
  function installExtensionProdDependencies(extensionDir) {
48
102
  if (NPM_INSTALL_ENV === "skip" || NPM_INSTALL_ENV === "0" || NPM_INSTALL_ENV === "false") {
@@ -65,9 +119,9 @@ function installExtensionProdDependencies(extensionDir) {
65
119
  env: process.env,
66
120
  ...process.platform === "win32" ? { shell: process.env.ComSpec && process.env.ComSpec.trim() || "cmd.exe" } : {}
67
121
  };
68
- const run = (label, command) => {
122
+ const run = (label, executable, args) => {
69
123
  try {
70
- execSync(command, execOpts);
124
+ execFileSync(executable, args, execOpts);
71
125
  return { ok: true };
72
126
  } catch (err) {
73
127
  const out = truncateOutput(extractExecSyncOutput(err));
@@ -77,17 +131,38 @@ function installExtensionProdDependencies(extensionDir) {
77
131
  };
78
132
  }
79
133
  };
80
- if (existsSync(join(extensionDir, "pnpm-lock.yaml"))) {
81
- const pnpm = run("pnpm", "pnpm install --prod --no-frozen-lockfile");
134
+ const usePnpm = existsSync(join(extensionDir, "pnpm-lock.yaml"));
135
+ const scriptArgs = ALLOW_NPM_INSTALL_SCRIPTS ? [] : ["--ignore-scripts"];
136
+ const npmExecutable = process.platform === "win32" ? "npm.cmd" : "npm";
137
+ const pnpmExecutable = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
138
+ if (usePnpm) {
139
+ const pnpm = run("pnpm", pnpmExecutable, [
140
+ "install",
141
+ "--prod",
142
+ "--no-frozen-lockfile",
143
+ ...scriptArgs
144
+ ]);
82
145
  if (pnpm.ok) return pnpm;
83
- const npmFallback = run("npm", "npm install --omit=dev --no-audit --no-fund");
146
+ const npmFallback = run("npm", npmExecutable, [
147
+ "install",
148
+ "--omit=dev",
149
+ "--no-audit",
150
+ "--no-fund",
151
+ ...scriptArgs
152
+ ]);
84
153
  if (npmFallback.ok) {
85
154
  log.warn({ extensionDir }, "pnpm failed; extension dependencies installed with npm instead");
86
155
  return { ok: true };
87
156
  }
88
157
  return npmFallback;
89
158
  }
90
- return run("npm", "npm install --omit=dev --no-audit --no-fund");
159
+ return run("npm", npmExecutable, [
160
+ "install",
161
+ "--omit=dev",
162
+ "--no-audit",
163
+ "--no-fund",
164
+ ...scriptArgs
165
+ ]);
91
166
  }
92
167
  function isSafeZipPath(name) {
93
168
  if (!name) return false;
@@ -261,11 +336,20 @@ function resolveExtensionsDir(workspaceDir, global = false) {
261
336
  * Install extension from npm package
262
337
  */
263
338
  async function installFromNpm(packageSpec, extensionsDir, timeoutMs = 12e4) {
264
- const tmpDir = join(tmpdir(), `xopc-install-${Date.now()}`);
339
+ const validation = validateNpmPackageSpec(packageSpec);
340
+ if (validation.ok === false) return {
341
+ ok: false,
342
+ error: `Invalid npm package spec: ${validation.error}`
343
+ };
344
+ const tmpDir = mkdtempSync(join(tmpdir(), "xopc-install-"));
265
345
  try {
266
346
  console.log(`📦 Downloading ${packageSpec} from npm...`);
267
- mkdirSync(tmpDir, { recursive: true });
268
- const packedFile = execSync(`npm pack ${packageSpec} --pack-destination ${tmpDir}`, {
347
+ const packedFile = execFileSync(process.platform === "win32" ? "npm.cmd" : "npm", [
348
+ "pack",
349
+ packageSpec,
350
+ "--pack-destination",
351
+ tmpDir
352
+ ], {
269
353
  timeout: timeoutMs,
270
354
  encoding: "utf-8",
271
355
  stdio: "pipe"
@@ -274,9 +358,22 @@ async function installFromNpm(packageSpec, extensionsDir, timeoutMs = 12e4) {
274
358
  ok: false,
275
359
  error: "Failed to download package from npm"
276
360
  };
361
+ if (packedFile !== packedFile.split(/[\\/]/).pop() || !packedFile.endsWith(".tgz")) return {
362
+ ok: false,
363
+ error: "npm returned an invalid archive filename"
364
+ };
277
365
  const archivePath = join(tmpDir, packedFile);
366
+ if (!existsSync(archivePath)) return {
367
+ ok: false,
368
+ error: "npm package archive was not created"
369
+ };
278
370
  console.log(`📂 Extracting ${packedFile}...`);
279
- execSync(`tar -xzf ${archivePath} -C ${tmpDir}`, {
371
+ execFileSync("tar", [
372
+ "-xzf",
373
+ archivePath,
374
+ "-C",
375
+ tmpDir
376
+ ], {
280
377
  timeout: 3e4,
281
378
  stdio: "pipe"
282
379
  });
@@ -532,4 +629,4 @@ function readManifest(extensionDir) {
532
629
  }
533
630
  }
534
631
  //#endregion
535
- export { installExtensionFromStoreZip, installFromLocal, installFromNpm, listAllExtensions, peekExtensionIdFromStoreZip, peekExtensionManifestFromStoreZip, peekExtensionPackageJsonFromStoreZip, removeExtension, resolveExtensionsDir };
632
+ export { installExtensionFromStoreZip, installFromLocal, installFromNpm, listAllExtensions, peekExtensionIdFromStoreZip, peekExtensionManifestFromStoreZip, peekExtensionPackageJsonFromStoreZip, removeExtension, resolveExtensionsDir, validateNpmPackageSpec };
@@ -290,13 +290,6 @@ var ExtensionLoader = class {
290
290
  }
291
291
  async loadExtension(config) {
292
292
  try {
293
- const cacheKey = this.cache.buildKey(this.options, [config.id]);
294
- const cached = this.cache.get(cacheKey);
295
- if (cached) {
296
- log.debug({ extensionId: config.id }, "Extension loaded from cache");
297
- return cached;
298
- }
299
- if (this.extensionInstances.has(config.id)) return this.extensionInstances.get(config.id);
300
293
  let extensionPath;
301
294
  if (isAbsolute(config.path)) extensionPath = config.path;
302
295
  else extensionPath = resolveExtensionPath(config.path, this.options) || resolveExtensionPath(config.id, this.options);
@@ -314,19 +307,30 @@ var ExtensionLoader = class {
314
307
  }, "Resolved extension path");
315
308
  const source = config.source || "bundled";
316
309
  const safetyResult = checkExtensionPathSafety(extensionPath, extensionPath, source);
317
- if (!safetyResult.safe) {
310
+ if (this.securityConfig.checkPermissions && !safetyResult.safe) {
318
311
  logSecurityIssue(config.id, safetyResult);
319
- if (this.securityConfig.checkPermissions && source !== "bundled") {
320
- if (!isExtensionAllowed(config.id, this.securityConfig)) {
321
- this.diagnostics.error(config.id, `Extension not allowed: ${safetyResult.detail}`);
322
- log.error({
323
- extensionId: config.id,
324
- reason: safetyResult.reason
325
- }, "Extension blocked by security policy");
326
- return null;
327
- }
328
- }
312
+ this.diagnostics.error(config.id, `Unsafe extension path: ${safetyResult.detail}`);
313
+ log.error({
314
+ extensionId: config.id,
315
+ reason: safetyResult.reason
316
+ }, "Extension blocked because its path is unsafe");
317
+ return null;
329
318
  }
319
+ if (source !== "bundled" && !isExtensionAllowed(config.id, this.securityConfig)) {
320
+ this.diagnostics.error(config.id, "Extension is not present in extensions.security.allow");
321
+ log.error({
322
+ extensionId: config.id,
323
+ source
324
+ }, "Extension blocked because it is not trusted by security policy");
325
+ return null;
326
+ }
327
+ const cacheKey = this.cache.buildKey(this.options, [config.id]);
328
+ const cached = this.cache.get(cacheKey);
329
+ if (cached) {
330
+ log.debug({ extensionId: config.id }, "Extension loaded from cache");
331
+ return cached;
332
+ }
333
+ if (this.extensionInstances.has(config.id)) return this.extensionInstances.get(config.id);
330
334
  provenanceTracker.track(config.id, source);
331
335
  const manifest = this.loadManifest(extensionPath);
332
336
  if (!manifest) {
@@ -1,5 +1,5 @@
1
- import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
2
1
  import { resolveCapabilityPresetLayer, resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
2
+ import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
3
3
  import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
4
4
  import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
5
5
  import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES, REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET } from "../agent/context/workspace.js";
@@ -1,9 +1,9 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { shouldSilence, stripHeartbeatToken } from "../../heartbeat/tokens.js";
4
+ import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
4
5
  import { isWithinActiveHours } from "../../heartbeat/active-hours.js";
5
6
  import { isHeartbeatContentEmpty } from "../../heartbeat/content-check.js";
6
- import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
7
7
  import { createHeartbeatWake } from "../../heartbeat/wake.js";
8
8
  import { resolveHeartbeatMdPath } from "../workspace-heartbeat-path.js";
9
9
  import { readFile } from "fs/promises";
@@ -8,10 +8,10 @@ import { getProviderRegistry, init_plugin_registry } from "../../../providers/pl
8
8
  import { getAllProviders, init_providers, isProviderConfigured } from "../../../providers/index.js";
9
9
  import { normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
10
10
  import { resolveShareConfig } from "../../../share/share-config.js";
11
- import { maskTunnelSecretForWeb } from "../../../tunnel/env.js";
12
11
  import { resolveSessionConfigForWeb, resolveUpdateConfigForWeb } from "../../../config/web-patch.js";
13
12
  import { GENERIC_MASKED_SECRET, maskSecretLength } from "./mask-secret-length.js";
14
13
  import { safeToolsWebForGet } from "../../config-tools-web.js";
14
+ import { maskTunnelSecretForWeb } from "../../../tunnel/env.js";
15
15
  import { buildSafeProvidersConfigForWeb } from "./safe-providers-config.js";
16
16
  import { maskSttConfigForWeb, maskTtsConfigForWeb } from "./safe-voice-config.js";
17
17
  //#region src/gateway/hono/lib/config-payload.ts
@@ -1,13 +1,13 @@
1
1
  import { logAuthEvent } from "../../../utils/logger/audit.js";
2
2
  import { createLogger } from "../../../utils/logger/index.js";
3
3
  import { init_logger } from "../../../utils/logger.js";
4
+ import { safeEqualSecret } from "../../security/secret-equal.js";
5
+ import { resolveClientIpFromRequest } from "../../client-ip.js";
4
6
  import { authPolicyConfig, buckets, resolveAuthRateLimit } from "../../rate-limit/buckets.js";
5
7
  import { getClientIpFromHeaders } from "../../security/loopback.js";
6
8
  import { resolveAuthTracking } from "../../rate-limit/auth-policy.js";
7
9
  import { isAuthRateLimitGloballyDisabled } from "../../rate-limit/env-flags.js";
8
10
  import "../../rate-limit/index.js";
9
- import { safeEqualSecret } from "../../security/secret-equal.js";
10
- import { resolveClientIpFromRequest } from "../../client-ip.js";
11
11
  import { authorizeTrustedProxy } from "../../trusted-proxy.js";
12
12
  import { createMiddleware } from "hono/factory";
13
13
  import { getConnInfo } from "@hono/node-server/conninfo";
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../../../utils/logger/index.js";
2
2
  import { init_logger } from "../../../utils/logger.js";
3
- import { getClientIpFromHeaders } from "../../security/loopback.js";
4
3
  import { resolveClientIpFromRequest } from "../../client-ip.js";
4
+ import { getClientIpFromHeaders } from "../../security/loopback.js";
5
5
  import { createMiddleware } from "hono/factory";
6
6
  import { getConnInfo } from "@hono/node-server/conninfo";
7
7
  //#region src/gateway/hono/middleware/logger.ts
@@ -1,9 +1,9 @@
1
1
  import { createLogger } from "../../../utils/logger/index.js";
2
2
  import { init_logger } from "../../../utils/logger.js";
3
+ import { resolveClientIpFromRequest } from "../../client-ip.js";
3
4
  import { buckets } from "../../rate-limit/buckets.js";
4
5
  import { getClientIpFromHeaders } from "../../security/loopback.js";
5
6
  import "../../rate-limit/index.js";
6
- import { resolveClientIpFromRequest } from "../../client-ip.js";
7
7
  import { createMiddleware } from "hono/factory";
8
8
  import { getConnInfo } from "@hono/node-server/conninfo";
9
9
  //#region src/gateway/hono/middleware/strict-rate-limit.ts
@@ -3,11 +3,11 @@ import { BindingsConfigSchema, BrowserConfigSchema, McpConfigSchema, VoiceConfig
3
3
  import { CredentialResolver, init_credentials } from "../../../../auth/credentials.js";
4
4
  import { canonicalizeConfiguredMcpServer } from "../../../../config/mcp-config-normalize.js";
5
5
  import { setTuiDefaultAgentConfig } from "../../../../commands/agents.config.js";
6
- import { mergeTunnelConfigPatch } from "../../../../tunnel/tunnel-config.js";
7
6
  import { mergeGatewaySkillsMarketplacePatch, mergeSessionConfigPatch, mergeUpdateConfigPatch } from "../../../../config/web-patch.js";
8
7
  import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../../../auth.js";
9
8
  import { isMaskedSecretPatchValue } from "../../lib/mask-secret-length.js";
10
9
  import { applyToolsWebPatch } from "../../../config-tools-web.js";
10
+ import { mergeTunnelConfigPatch } from "../../../../tunnel/tunnel-config.js";
11
11
  import { assertGatewayRuntimeConfig } from "../../../runtime-config.js";
12
12
  import { mergeSttConfigPatch, mergeTtsConfigPatch } from "../../lib/safe-voice-config.js";
13
13
  import { PATCH_OK, patchError } from "./result.js";
@@ -14,14 +14,15 @@ import { getConnectorDefinition, listConnectorCatalog } from "../../../connector
14
14
  import { listUnderstandingSourceGrants, revokeUnderstandingSourceGrant } from "../../../user-context/sources/repository.js";
15
15
  import { recordConnectorHealthUsage } from "../../../connectors/usage.js";
16
16
  import { getConnectorInstance, listConnectorInstances } from "../../../connectors/instances.js";
17
+ import { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig } from "../../../connectors/install.js";
17
18
  import { startConnectorAuthorization } from "../../../connectors/auth-provider-registry.js";
18
19
  import { composioLogoResponse } from "../../../connectors/composio-logo.js";
20
+ import { inspectManagedComposioStatus } from "../../../connectors/composio-managed-client.js";
19
21
  import { appendComposioTriggerEvent, listComposioTriggerEvents } from "../../../connectors/composio-triggers.js";
20
22
  import { buildConnectedPeopleGraph } from "../../../knowledge/people-graph.js";
21
23
  import "../../../knowledge/index.js";
22
24
  import { ingestLocalFolderSource } from "../../../connectors/connected-source-ingestion.js";
23
25
  import { previewConnectorDefinition, testConnectorInstance } from "../../../connectors/health.js";
24
- import { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig } from "../../../connectors/install.js";
25
26
  import { setConnectorEnabled } from "../../../connectors/lifecycle.js";
26
27
  import { projectComposioConnectionStatus } from "../../../connectors/runtime-status.js";
27
28
  //#region src/gateway/hono/routes/connectors.ts
@@ -592,10 +593,13 @@ function registerConnectorRoutes(authenticated, deps) {
592
593
  }
593
594
  });
594
595
  authenticated.get("/api/connectors/composio/setup-status", async (c) => {
595
- const configured = Boolean(await resolveComposioApiKey());
596
+ const status = Boolean(await resolveComposioApiKey()) ? {
597
+ configured: true,
598
+ mode: "byok"
599
+ } : await inspectManagedComposioStatus();
596
600
  return c.json({
597
601
  ok: true,
598
- payload: { configured }
602
+ payload: status
599
603
  });
600
604
  });
601
605
  authenticated.post("/api/connectors/composio/setup", strictRateLimitMiddleware, async (c) => {
@@ -605,7 +609,10 @@ function registerConnectorRoutes(authenticated, deps) {
605
609
  await configureComposioApiKey(apiKey);
606
610
  return c.json({
607
611
  ok: true,
608
- payload: { configured: true }
612
+ payload: {
613
+ configured: true,
614
+ mode: "byok"
615
+ }
609
616
  });
610
617
  } catch (error) {
611
618
  return c.json({
@@ -1,6 +1,6 @@
1
- import { consumeTunnelMutationLimit } from "../../../tunnel/tunnel-rate-limit.js";
2
1
  import { extractToken } from "../../auth.js";
3
2
  import { getExposureManager } from "../../../remote-access/exposure-manager.js";
3
+ import { consumeTunnelMutationLimit } from "../../../tunnel/tunnel-rate-limit.js";
4
4
  //#region src/gateway/hono/routes/exposure.ts
5
5
  function requireGatewayToken(c) {
6
6
  return extractToken({ authorization: c.req.header("authorization") ?? void 0 }) ?? null;
@@ -1,5 +1,5 @@
1
1
  import type { Hono } from 'hono';
2
2
  import type { AuthenticatedRouteDeps } from './deps.js';
3
- export { buildHomeBriefing, buildHomeFocusItems } from '../../../tasks/home-query-service.js';
3
+ export { buildHomeWorkbench, decisionFromTask } from '../../../tasks/home-query-service.js';
4
4
  /** Register the unified work-home read model and its decision actions. */
5
5
  export declare function registerHomeRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void;
@@ -2,7 +2,7 @@ import { acknowledgeHomeAttention } from "../../../storage/sqlite/home-attention
2
2
  import { decideConnectorApproval } from "../../../storage/sqlite/connector-repository.js";
3
3
  import "../../../storage/sqlite/index.js";
4
4
  import { listGatewayAgents } from "../../agents-admin.js";
5
- import { HomeQueryService, buildHomeBriefing, buildHomeFocusItems } from "../../../tasks/home-query-service.js";
5
+ import { HomeQueryService, buildHomeWorkbench, decisionFromTask } from "../../../tasks/home-query-service.js";
6
6
  //#region src/gateway/hono/routes/home.ts
7
7
  /** Register the unified work-home read model and its decision actions. */
8
8
  function registerHomeRoutes(authenticated, deps) {
@@ -90,4 +90,4 @@ function registerHomeRoutes(authenticated, deps) {
90
90
  });
91
91
  }
92
92
  //#endregion
93
- export { buildHomeBriefing, buildHomeFocusItems, registerHomeRoutes };
93
+ export { buildHomeWorkbench, decisionFromTask, registerHomeRoutes };
@@ -1,7 +1,7 @@
1
1
  import { canonicalizeConfiguredMcpServer, normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
2
2
  import { loadMergedBundleMcpConfig } from "../../../agent/mcp/bundle-mcp-config.js";
3
- import { getWorkspacePath } from "../../../config/workspace-path-helpers.js";
4
3
  import { isManagedConnectorServer } from "../../../connectors/materialize.js";
4
+ import { getWorkspacePath } from "../../../config/workspace-path-helpers.js";
5
5
  import { listBundleMcpServerCapabilitiesForGateway, listBundleMcpServerToolsForGateway } from "../../../agent/mcp/bundle-mcp-gateway.js";
6
6
  //#region src/gateway/hono/routes/mcp.ts
7
7
  function registerMcpRoutes(authenticated, deps) {
@@ -8,8 +8,8 @@ import { resolveShareUrl, resolveSiteShareUrl } from "../../../share/share-url.j
8
8
  import { resolveReverseProxyPublicUrl } from "../../public-url.js";
9
9
  import { audienceDefaults, cleanupStagedSite, decideShareKind, forgetStagedSite, makeDescription, makeTitle, probeShareTarget, rememberStagedSite, stageSingleHtmlAsSite } from "../../../share/share-auto.js";
10
10
  import { deleteThumbnail, placeholderSvg, readThumbnail, scheduleThumbnail, thumbnailContentType, thumbnailExists } from "../../../share/share-thumbnail.js";
11
- import { getClientIpFromHeaders } from "../../security/loopback.js";
12
11
  import { extractToken } from "../../auth.js";
12
+ import { getClientIpFromHeaders } from "../../security/loopback.js";
13
13
  import { renderFolderLandingPage, renderShareExpiredPage, renderShareLandingPage } from "../../../share/share-landing.js";
14
14
  import { consumeSharePublicLimit } from "../../../share/share-rate-limit.js";
15
15
  import { createZipStream, planDirectoryFiles } from "../../../share/share-zip.js";
@@ -2,18 +2,18 @@ import { init_public_url, validatePublicUrl } from "../../../config/public-url.j
2
2
  import { resolveGatewayEffectiveHost } from "../../../config/gateway-bind.js";
3
3
  import { loadTunnelState } from "../../../tunnel/tunnel-state.js";
4
4
  import { resolveReverseProxyPublicUrl } from "../../public-url.js";
5
+ import { extractToken } from "../../auth.js";
5
6
  import { TUNNEL_CONSENT_REQUIRED_CODE, TunnelConsentError, assertTunnelMayStart, getTunnelConsentState } from "../../../tunnel/consent.js";
6
7
  import { getTunnelRegistrationSecretMeta, readTunnelRegistrationSecretFromConfigOnly, resolveTunnelBrokerUrl } from "../../../tunnel/env.js";
7
- import { applyTunnelConsentToConfig, setTunnelEnabledInConfig } from "../../../tunnel/tunnel-config.js";
8
8
  import { createPairingSecret, exchangePairingSecretOnce, getCachedPairingExchange } from "../../../tunnel/pairing.js";
9
9
  import { logTunnelAudit } from "../../../tunnel/tunnel-audit.js";
10
10
  import { getTunnelService, hashGatewayToken } from "../../../tunnel/tunnel-service.js";
11
11
  import { configureTunnelFromGatewayConfig } from "../../../tunnel/gateway-lifecycle.js";
12
+ import { applyTunnelConsentToConfig, setTunnelEnabledInConfig } from "../../../tunnel/tunnel-config.js";
12
13
  import { getClientIpFromHeaders } from "../../security/loopback.js";
14
+ import { applyLanPairingGatewayPatch } from "../../../tunnel/enable-lan-pairing.js";
13
15
  import { consumeTunnelMutationLimit } from "../../../tunnel/tunnel-rate-limit.js";
14
16
  import "../../../tunnel/index.js";
15
- import { extractToken } from "../../auth.js";
16
- import { applyLanPairingGatewayPatch } from "../../../tunnel/enable-lan-pairing.js";
17
17
  import { buildMobileConnectUrlOrder, resolveMobilePairLanUrl, validateMobilePairBaseUrl } from "../../../tunnel/pair-url.js";
18
18
  import { buildMobilePairContext } from "../../../tunnel/pair-context.js";
19
19
  import { consumePairingExchangeFailLimit } from "../../../tunnel/pairing-rate-limit.js";
@@ -10,10 +10,39 @@ import { WorkflowDraftService } from "../../../workflows/draft/workflow-draft-se
10
10
  import { WorkflowDraftConflictError, WorkflowDraftStore } from "../../../workflows/authoring/workflow-draft-store.js";
11
11
  import "../../../workflows/authoring/index.js";
12
12
  import "../../../workflows/draft/index.js";
13
+ import { ProjectWorkflowPresetRepository } from "../../../workflows/project-presets/project-workflow-preset-repository.js";
13
14
  import { basename, join } from "node:path";
14
15
  import { readFile, stat } from "node:fs/promises";
15
16
  //#region src/gateway/hono/routes/workflows.ts
16
17
  init_agent_scope();
18
+ const WORKFLOW_CONTEXT_KINDS = new Set([
19
+ "project",
20
+ "task",
21
+ "note",
22
+ "session",
23
+ "attachment",
24
+ "memory"
25
+ ]);
26
+ function parseWorkflowContextRefs(value) {
27
+ if (value === void 0) return void 0;
28
+ if (!Array.isArray(value) || value.length > 50) throw new Error("contextRefs must be an array with at most 50 items");
29
+ return value.map((candidate) => {
30
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) throw new Error("Invalid workflow context reference");
31
+ const ref = candidate;
32
+ const kind = typeof ref.kind === "string" ? ref.kind : "";
33
+ const id = typeof ref.id === "string" ? ref.id.trim() : "";
34
+ if (!WORKFLOW_CONTEXT_KINDS.has(kind) || !id || id.length > 512) throw new Error("Invalid workflow context reference");
35
+ const role = typeof ref.role === "string" ? ref.role.trim() : void 0;
36
+ const title = typeof ref.title === "string" ? ref.title.trim() : void 0;
37
+ if ((role?.length ?? 0) > 64 || (title?.length ?? 0) > 256) throw new Error("Invalid workflow context reference");
38
+ return {
39
+ kind,
40
+ id,
41
+ ...role ? { role } : {},
42
+ ...title ? { title } : {}
43
+ };
44
+ });
45
+ }
17
46
  function registerWorkflowRoutes(authenticated, deps) {
18
47
  const { service } = deps;
19
48
  const workflowRunService = service.createWorkflowRunService();
@@ -38,6 +67,38 @@ function registerWorkflowRoutes(authenticated, deps) {
38
67
  return c.json({ error: err instanceof Error ? err.message : "Workflow definition not found" }, 404);
39
68
  }
40
69
  });
70
+ authenticated.get("/api/workflows/project-presets", (c) => {
71
+ const projectId = c.req.query("projectId")?.trim();
72
+ if (!projectId) return c.json({ error: "projectId is required" }, 400);
73
+ if (!service.projects.get(projectId)) return c.json({ error: "Project not found" }, 404);
74
+ return c.json({ presets: new ProjectWorkflowPresetRepository().list(projectId) });
75
+ });
76
+ authenticated.put("/api/workflows/project-presets/:definitionId", async (c) => {
77
+ const definitionId = c.req.param("definitionId").trim();
78
+ const body = await readJsonBody(c.req.raw);
79
+ const projectId = body.projectId?.trim();
80
+ if (!projectId) return c.json({ error: "projectId is required" }, 400);
81
+ if (!service.projects.get(projectId)) return c.json({ error: "Project not found" }, 404);
82
+ try {
83
+ createWorkflowCatalog().load(definitionId);
84
+ const contextRefs = parseWorkflowContextRefs(body.contextRefs) ?? [];
85
+ if (contextRefs.some((ref) => ref.kind !== "task" && ref.kind !== "note")) return c.json({ error: "Project workflow presets support task and note context only" }, 400);
86
+ const preset = new ProjectWorkflowPresetRepository().save({
87
+ projectId,
88
+ definitionId,
89
+ contextRefs
90
+ });
91
+ return c.json({ preset });
92
+ } catch (cause) {
93
+ return c.json({ error: cause instanceof Error ? cause.message : "Could not save project workflow" }, 400);
94
+ }
95
+ });
96
+ authenticated.delete("/api/workflows/project-presets/:definitionId", (c) => {
97
+ const projectId = c.req.query("projectId")?.trim();
98
+ if (!projectId) return c.json({ error: "projectId is required" }, 400);
99
+ const removed = new ProjectWorkflowPresetRepository().remove(projectId, c.req.param("definitionId"));
100
+ return c.json({ removed });
101
+ });
41
102
  authenticated.post("/api/workflows/definitions/validate", async (c) => {
42
103
  const body = await readJsonBody(c.req.raw);
43
104
  const result = validateWorkflowDefinitionInput({
@@ -206,6 +267,7 @@ function registerWorkflowRoutes(authenticated, deps) {
206
267
  const catalog = createWorkflowCatalog();
207
268
  try {
208
269
  if (!catalog.remove(id)) return c.json({ error: "User workflow not found or cannot delete built-in workflow" }, 404);
270
+ new ProjectWorkflowPresetRepository().removeDefinition(id);
209
271
  const drafts = new WorkflowDraftStore().list(id);
210
272
  for (const draft of drafts) new WorkflowDraftStore().remove(draft.id);
211
273
  return c.json({ removed: true });
@@ -228,6 +290,12 @@ function registerWorkflowRoutes(authenticated, deps) {
228
290
  const taskRunId = body.taskRunId?.trim();
229
291
  const projectId = body.projectId?.trim();
230
292
  if (projectId && !service.projects.get(projectId)) return c.json({ error: "Project not found" }, 404);
293
+ let contextRefs;
294
+ try {
295
+ contextRefs = parseWorkflowContextRefs(body.contextRefs);
296
+ } catch (cause) {
297
+ return c.json({ error: cause instanceof Error ? cause.message : "Invalid workflow context references" }, 400);
298
+ }
231
299
  const explicitAgentId = body.agentId ?? c.req.query("agentId");
232
300
  const agentId = projectId ? resolveProjectAgentId({
233
301
  config: service.currentConfig,
@@ -240,6 +308,7 @@ function registerWorkflowRoutes(authenticated, deps) {
240
308
  definitionId,
241
309
  taskRunId,
242
310
  projectId,
311
+ contextRefs,
243
312
  input: body.inputEnvelope ? void 0 : body.input,
244
313
  inputEnvelope: body.inputEnvelope,
245
314
  goal: body.goal,
@@ -1,10 +1,10 @@
1
1
  import { buildDefaultCorsOrigins, isAllInterfacesHost, isLoopbackHost, resolveEffectiveGatewayPort, resolveGatewayServiceListenPort } from "./host.js";
2
2
  import { defaultGatewayBindMode, isContainerEnvironment, resolveGatewayBindHost, resolveGatewayBindHostSync, resolveGatewayBindMode, resolveGatewayEffectiveHost } from "../config/gateway-bind.js";
3
+ import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
4
+ import { resolveGatewayListenHost, resolveGatewayListenPlan } from "./listen.js";
3
5
  import { buckets } from "./rate-limit/buckets.js";
4
6
  import { isGatewayStrictSecurityEnabled } from "./rate-limit/env-flags.js";
5
7
  import "./rate-limit/index.js";
6
- import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
7
- import { resolveGatewayListenHost, resolveGatewayListenPlan } from "./listen.js";
8
8
  import { assertGatewayRuntimeConfig } from "./runtime-config.js";
9
9
  import { restartGatewayProcessWithFreshPid } from "./respawn.js";
10
10
  import { GatewayService } from "./service.js";
@@ -1,8 +1,8 @@
1
1
  import { isAllInterfacesHost, isLoopbackHost, resolveGatewayCorsOrigins } from "./host.js";
2
- import { isAuthRateLimitGloballyDisabled, isGatewayStrictSecurityEnabled } from "./rate-limit/env-flags.js";
3
- import "./rate-limit/index.js";
4
2
  import { resolveGatewayListenPlan } from "./listen.js";
5
3
  import { assertTailscaleExposureCompatible } from "./tailscale-lifecycle.js";
4
+ import { isAuthRateLimitGloballyDisabled, isGatewayStrictSecurityEnabled } from "./rate-limit/env-flags.js";
5
+ import "./rate-limit/index.js";
6
6
  //#region src/gateway/runtime-config.ts
7
7
  function hasSharedSecret(auth) {
8
8
  if (auth.mode === "trusted-proxy") return true;
@@ -1,10 +1,10 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { isAuthRateLimitGloballyDisabled, isGatewayStrictSecurityEnabled } from "../rate-limit/env-flags.js";
4
- import "../rate-limit/index.js";
5
3
  import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../auth.js";
6
4
  import { resolveGatewayListenPlan } from "../listen.js";
7
5
  import { collectExposureConflicts, isRemoteGatewayInsecure, isTailnetBindUnavailable } from "../../remote-access/exposure-guards.js";
6
+ import { isAuthRateLimitGloballyDisabled, isGatewayStrictSecurityEnabled } from "../rate-limit/env-flags.js";
7
+ import "../rate-limit/index.js";
8
8
  import { assertGatewayRuntimeConfig } from "../runtime-config.js";
9
9
  //#region src/gateway/security/audit.ts
10
10
  init_logger();
@@ -4,12 +4,12 @@ import { loadConfig, saveConfig } from "../../config/loader.js";
4
4
  import { getModelRegistry } from "../../providers/model-registry.js";
5
5
  import { init_providers } from "../../providers/index.js";
6
6
  import { disposeAllSessionMcpRuntimes } from "../../agent/mcp/bundle-mcp-runtime.js";
7
- import { sanitizeTunnelConfig } from "../../tunnel/tunnel-config.js";
8
7
  import { reloadImageGenerationProviders } from "../../agent/image/generation/provider-registry.js";
9
8
  import "../../agent/mcp/bundle-mcp-tools.js";
10
9
  import { ConfigHotReloader } from "../../config/reload.js";
11
10
  import "../../config/index.js";
12
11
  import { computeBundledExtensionExtensionsPatch } from "../../extensions/bundled-extension-activation.js";
12
+ import { sanitizeTunnelConfig } from "../../tunnel/tunnel-config.js";
13
13
  //#region src/gateway/service/config-coordinator.ts
14
14
  init_providers();
15
15
  init_logger();
@@ -67,6 +67,7 @@ export declare class GatewayService {
67
67
  private workflowRunServiceInstance;
68
68
  private taskRunDispatcher;
69
69
  private taskRunDispatchTimer;
70
+ private managedComposioEventPoller?;
70
71
  private mobileNotifications;
71
72
  private connectorSupervisor;
72
73
  private connectorLearningCoordinator;