@xopcai/xopc 0.0.230 → 0.0.231

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 (150) 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/{agent-avatar-dicebear-Bp_wmuGW.js → agent-avatar-dicebear-CBqUnlvL.js} +1 -1
  4. package/dist/gateway/static/root/assets/agents-7YO6znTT.js +68 -0
  5. package/dist/gateway/static/root/assets/{app-management-settings-panel-CwAPK4Jm.js → app-management-settings-panel-DP7YVRPn.js} +1 -1
  6. package/dist/gateway/static/root/assets/{appearance-settings-DsGLvqTb.js → appearance-settings-CVQ5n7y6.js} +1 -1
  7. package/dist/gateway/static/root/assets/{apps-page-Ee9qOQEx.js → apps-page-DSCia0DT.js} +1 -1
  8. package/dist/gateway/static/root/assets/{attachment-load-B4qqigAQ.js → attachment-load-mmr_mHRr.js} +1 -1
  9. package/dist/gateway/static/root/assets/{automations-page-B8ImehSW.js → automations-page-DfY-T6Ga.js} +1 -1
  10. package/dist/gateway/static/root/assets/automations-workspace-BpvD54D6.js +6 -0
  11. package/dist/gateway/static/root/assets/{binary-plugins-DaJbyYc2.js → binary-plugins-CO9QMEh2.js} +1 -1
  12. package/dist/gateway/static/root/assets/{block-editor-Kl25XWJc.js → block-editor-CE14CVOy.js} +3 -3
  13. package/dist/gateway/static/root/assets/browser-settings-page-CeESA4Oj.js +8 -0
  14. package/dist/gateway/static/root/assets/{browser-workflows-page-DjMxs33B.js → browser-workflows-page-1wgXyoSO.js} +2 -2
  15. package/dist/gateway/static/root/assets/capabilities-settings-panel-B_OXTojB.js +7 -0
  16. package/dist/gateway/static/root/assets/capability-presets-settings-panel-D5nZecxV.js +3 -0
  17. package/dist/gateway/static/root/assets/channels-settings-BzmnWx6X.js +1 -0
  18. package/dist/gateway/static/root/assets/{chat-terminal-dock-BiU_4Rq6.js → chat-terminal-dock-CdRW6Euc.js} +2 -2
  19. package/dist/gateway/static/root/assets/cloud-C4-yfnnk.js +1 -0
  20. package/dist/gateway/static/root/assets/connectors-page-DX6OkwFQ.js +2 -0
  21. package/dist/gateway/static/root/assets/{cron-expression-Cs_5pUPT.js → cron-expression-DYSMZsms.js} +1 -1
  22. package/dist/gateway/static/root/assets/{date-picker-y1kWrFVU.js → date-picker-DGCfX4tK.js} +1 -1
  23. package/dist/gateway/static/root/assets/{dependency-picker-skc62zrn.js → dependency-picker-DHDa4ht1.js} +1 -1
  24. package/dist/gateway/static/root/assets/{desktop-pet-ux9DxchT.js → desktop-pet-CMO-J3cG.js} +1 -1
  25. package/dist/gateway/static/root/assets/{desktop-pet-settings-BVVCBgYK.js → desktop-pet-settings-MmOR4A3u.js} +1 -1
  26. package/dist/gateway/static/root/assets/{directory-picker-path-field-V8vZP0Dy.js → directory-picker-path-field-B9qoxDcn.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-debug-page-Dh6DDuvQ.js → extension-debug-page-DdH0dG2_.js} +1 -1
  28. package/dist/gateway/static/root/assets/{extension-page-8OKQDEat.js → extension-page-Clg-KktN.js} +1 -1
  29. package/dist/gateway/static/root/assets/{extension-settings-page-BgSV0Nny.js → extension-settings-page-eP3fJ2M6.js} +1 -1
  30. package/dist/gateway/static/root/assets/files-Dp8_uGTO.js +1 -0
  31. package/dist/gateway/static/root/assets/{gateway-config-api-Dlc6eaTG.js → gateway-config-api-DEHnF4Wm.js} +1 -1
  32. package/dist/gateway/static/root/assets/{gateway-settings-DqQgiAUv.js → gateway-settings-DKkEXXj9.js} +1 -1
  33. package/dist/gateway/static/root/assets/{heartbeat-settings-Pxqk5GFH.js → heartbeat-settings-DlBPNubY.js} +1 -1
  34. package/dist/gateway/static/root/assets/home-page-BnOrLRfs.js +1 -0
  35. package/dist/gateway/static/root/assets/index-0xQO5B_Q.js +70 -0
  36. package/dist/gateway/static/root/assets/index-CCyIdGuQ.css +2 -0
  37. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BSFNqxzY.js → keyboard-shortcuts-settings-BvpEeHnm.js} +1 -1
  38. package/dist/gateway/static/root/assets/local-app-workbench-page-Ch1rdUo8.js +2 -0
  39. package/dist/gateway/static/root/assets/{local-apps-page-DzU6yZ9-.js → local-apps-page-Bzvn99eH.js} +1 -1
  40. package/dist/gateway/static/root/assets/logs-page-zxx2ExlY.js +2 -0
  41. package/dist/gateway/static/root/assets/{management-settings-B8hM56HS.js → management-settings-BQaeyOYm.js} +1 -1
  42. package/dist/gateway/static/root/assets/{markdown-split-DRbZjxMK.js → markdown-split-D9tmIiEm.js} +1 -1
  43. package/dist/gateway/static/root/assets/markdown-view-B1bGSQqt.css +1 -0
  44. package/dist/gateway/static/root/assets/{media-plugins-B8vMe5VX.js → media-plugins-D8I7OGnT.js} +1 -1
  45. package/dist/gateway/static/root/assets/models-hub-cache-0RjEwafI.js +1 -0
  46. package/dist/gateway/static/root/assets/{notes-api-BFsOGYkd.js → notes-api-EpgG-OQc.js} +1 -1
  47. package/dist/gateway/static/root/assets/{notes-page-B-YZ7iuK.js → notes-page-CCvjGMhN.js} +1 -1
  48. package/dist/gateway/static/root/assets/notes-workbench-9cgh77VH.js +4 -0
  49. package/dist/gateway/static/root/assets/oauth-api-BwNLwbI8.js +1 -0
  50. package/dist/gateway/static/root/assets/{product-open-page-DkWcyki5.js → product-open-page-MmMswmOU.js} +1 -1
  51. package/dist/gateway/static/root/assets/project-detail-page-hf6pmH4p.js +1 -0
  52. package/dist/gateway/static/root/assets/projects-page-By2U-Wdh.js +1 -0
  53. package/dist/gateway/static/root/assets/remote-access-hub-CUcpp7CQ.js +1 -0
  54. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Bq_ETeal.js → runtime-tools-settings-panel-Dx6o7sLu.js} +1 -1
  55. package/dist/gateway/static/root/assets/{schema-form-BogTlrsP.js → schema-form-Cdd9c4vt.js} +1 -1
  56. package/dist/gateway/static/root/assets/sessions-page-ByI82xS1.js +1 -0
  57. package/dist/gateway/static/root/assets/settings-advanced-gate-BCoI5IJ8.js +1 -0
  58. package/dist/gateway/static/root/assets/{settings-form-section-Coy1Cbp6.js → settings-form-section-D0YxMnhm.js} +1 -1
  59. package/dist/gateway/static/root/assets/{settings-loading-skeleton-B5GU7iCG.js → settings-loading-skeleton-y53gEKsF.js} +1 -1
  60. package/dist/gateway/static/root/assets/{settings-page-Dd-BRu12.js → settings-page-BoE_tToG.js} +1 -1
  61. package/dist/gateway/static/root/assets/{setup-status-panel-CwEFAVWx.js → setup-status-panel-BQmyb5KC.js} +1 -1
  62. package/dist/gateway/static/root/assets/share-preview-page-DiqBn-oE.js +2 -0
  63. package/dist/gateway/static/root/assets/shares-settings-Bf3VpZ-R.js +1 -0
  64. package/dist/gateway/static/root/assets/skill-reload-api-CXHlbuGS.js +1 -0
  65. package/dist/gateway/static/root/assets/{skills-page-Brxb6QnW.js → skills-page-CZwhWiRl.js} +1 -1
  66. package/dist/gateway/static/root/assets/{skills-page.utils-FB5LtEGm.js → skills-page.utils-kBGr8opZ.js} +1 -1
  67. package/dist/gateway/static/root/assets/{system-settings-panel-ChosWt8n.js → system-settings-panel-CPBs6lWi.js} +1 -1
  68. package/dist/gateway/static/root/assets/task-detail-page-Bo0KSZ2v.js +1 -0
  69. package/dist/gateway/static/root/assets/theme-store-Qgvo0Ga7.js +1 -0
  70. package/dist/gateway/static/root/assets/{use-autosave-2SqnmSKD.js → use-autosave-C4YcEiP9.js} +1 -1
  71. package/dist/gateway/static/root/assets/user-context-page-Cnj7gMX2.js +1 -0
  72. package/dist/gateway/static/root/assets/{voice-api-key-field-DtTIF6M8.js → voice-api-key-field-BML8zCwZ.js} +1 -1
  73. package/dist/gateway/static/root/assets/{work-discovery-overlay-CK3aZDdE.js → work-discovery-overlay-CKIdPEen.js} +1 -1
  74. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BjOuddkX.js → workflow-run-setup-panel-BK44Vm5W.js} +2 -2
  75. package/dist/gateway/static/root/assets/workflows-page-CB98MTwG.js +5 -0
  76. package/dist/gateway/static/root/index.html +10 -6
  77. package/dist/package.js +1 -1
  78. package/dist/src/agent/service.d.ts +1 -0
  79. package/dist/src/agent/service.js +5 -2
  80. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  81. package/dist/src/agent/tools/write.js +9 -12
  82. package/dist/src/agent/tools/xopc-use-tool.js +2 -2
  83. package/dist/src/auth/oauth/index.js +2 -2
  84. package/dist/src/auth/oauth/registry.d.ts +1 -1
  85. package/dist/src/auth/oauth/registry.js +5 -1
  86. package/dist/src/auth/oauth/xopc-cloud.d.ts +1 -0
  87. package/dist/src/auth/oauth/xopc-cloud.js +8 -2
  88. package/dist/src/files/file-service.d.ts +36 -0
  89. package/dist/src/files/file-service.js +282 -0
  90. package/dist/src/gateway/heartbeat/service.js +1 -1
  91. package/dist/src/gateway/hono/app.js +2 -2
  92. package/dist/src/gateway/hono/routes/files.d.ts +3 -0
  93. package/dist/src/gateway/hono/routes/files.js +172 -0
  94. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  95. package/dist/src/gateway/hono/routes/projects.js +0 -508
  96. package/dist/src/gateway/hono/routes/shares.js +410 -21
  97. package/dist/src/gateway/hono/routes/voice.js +1 -1
  98. package/dist/src/gateway/hono/routes/workspace.js +15 -974
  99. package/dist/src/gateway/service.js +9 -9
  100. package/dist/src/heartbeat/index.js +1 -1
  101. package/dist/src/share/hosted-session-share.d.ts +104 -0
  102. package/dist/src/share/hosted-session-share.js +276 -0
  103. package/dist/src/share/note-share-service.js +4 -24
  104. package/dist/src/share/session-share-projector.d.ts +31 -0
  105. package/dist/src/share/session-share-projector.js +79 -0
  106. package/dist/src/share/session-share-service.d.ts +89 -0
  107. package/dist/src/share/session-share-service.js +325 -0
  108. package/dist/src/share/share-asset-ticket.d.ts +7 -0
  109. package/dist/src/share/share-asset-ticket.js +30 -0
  110. package/dist/src/share/share-landing.d.ts +4 -3
  111. package/dist/src/share/share-landing.js +5 -5
  112. package/dist/src/share/share-store.d.ts +27 -2
  113. package/dist/src/share/share-store.js +71 -8
  114. package/dist/src/share/share-types.d.ts +17 -2
  115. package/dist/src/tui/backends/embedded-backend.js +1 -1
  116. package/dist/src/tui/backends/gateway-realtime-backend.js +11 -3
  117. package/package.json +1 -1
  118. package/dist/gateway/static/root/assets/agents-CKG93dlc.js +0 -68
  119. package/dist/gateway/static/root/assets/automations-workspace-BNFAfNwC.js +0 -6
  120. package/dist/gateway/static/root/assets/browser-settings-page-Cg6NgwE_.js +0 -8
  121. package/dist/gateway/static/root/assets/capabilities-settings-panel-NvJKgF1u.js +0 -7
  122. package/dist/gateway/static/root/assets/capability-presets-settings-panel-C2uBdALe.js +0 -3
  123. package/dist/gateway/static/root/assets/channels-settings-CIcYKMEs.js +0 -1
  124. package/dist/gateway/static/root/assets/connectors-page-CEEcmUiP.js +0 -2
  125. package/dist/gateway/static/root/assets/home-page-1xjo6wE4.js +0 -1
  126. package/dist/gateway/static/root/assets/index-Bbd_dXui.js +0 -70
  127. package/dist/gateway/static/root/assets/index-D_hrEKXM.css +0 -2
  128. package/dist/gateway/static/root/assets/local-app-workbench-page-heQ4-PJ7.js +0 -2
  129. package/dist/gateway/static/root/assets/logs-page-BblnS6Jy.js +0 -2
  130. package/dist/gateway/static/root/assets/markdown-view-CLzTdVLW.css +0 -1
  131. package/dist/gateway/static/root/assets/notes-workbench-CAM09C8b.js +0 -4
  132. package/dist/gateway/static/root/assets/project-detail-page-BIPIwgU2.js +0 -1
  133. package/dist/gateway/static/root/assets/projects-page-B_kzTn1K.js +0 -1
  134. package/dist/gateway/static/root/assets/remote-access-hub-CtD8DsD-.js +0 -1
  135. package/dist/gateway/static/root/assets/sessions-page-B8n9HI1y.js +0 -1
  136. package/dist/gateway/static/root/assets/settings-advanced-gate-xlhdRTME.js +0 -1
  137. package/dist/gateway/static/root/assets/share-preview-page-DzXw9UQJ.js +0 -2
  138. package/dist/gateway/static/root/assets/shares-settings-Bk6UQOwS.js +0 -1
  139. package/dist/gateway/static/root/assets/skill-reload-api-DrmQZ3Au.js +0 -1
  140. package/dist/gateway/static/root/assets/task-detail-page-CW2sJbdc.js +0 -1
  141. package/dist/gateway/static/root/assets/theme-store-DOdCjyuw.js +0 -1
  142. package/dist/gateway/static/root/assets/user-context-page-Bq9KB-Oj.js +0 -1
  143. package/dist/gateway/static/root/assets/workflows-page-CcbGEQol.js +0 -5
  144. package/dist/src/gateway/file-path-classifier.d.ts +0 -30
  145. package/dist/src/gateway/file-path-classifier.js +0 -105
  146. package/dist/src/gateway/file-reference-errors.d.ts +0 -6
  147. package/dist/src/gateway/file-reference-errors.js +0 -21
  148. package/dist/src/gateway/file-reference-registry.d.ts +0 -34
  149. package/dist/src/gateway/file-reference-registry.js +0 -45
  150. /package/dist/gateway/static/root/assets/{markdown-view-DvM5PWEH.js → markdown-view-RxNHwlNo.js} +0 -0
@@ -11,7 +11,7 @@
11
11
  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=20260713-1" />
12
12
  <link rel="manifest" href="/site.webmanifest?v=20260713-1" />
13
13
  <title>XOPC — Keep what matters moving.</title>
14
- <script type="module" crossorigin src="/assets/index-Bbd_dXui.js"></script>
14
+ <script type="module" crossorigin src="/assets/index-0xQO5B_Q.js"></script>
15
15
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-aKtaBQYM.js">
16
16
  <link rel="modulepreload" crossorigin href="/assets/preload-helper-zJ_50EbN.js">
17
17
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-BOUWij0V.js">
@@ -31,13 +31,14 @@
31
31
  <link rel="modulepreload" crossorigin href="/assets/schemas-zIBW3wiV.js">
32
32
  <link rel="modulepreload" crossorigin href="/assets/product-delivery-tRr-7IxY.js">
33
33
  <link rel="modulepreload" crossorigin href="/assets/copy-to-clipboard-HOJ79TWv.js">
34
- <link rel="modulepreload" crossorigin href="/assets/markdown-view-DvM5PWEH.js">
34
+ <link rel="modulepreload" crossorigin href="/assets/markdown-view-RxNHwlNo.js">
35
35
  <link rel="modulepreload" crossorigin href="/assets/dist-J_ySZvz0.js">
36
36
  <link rel="modulepreload" crossorigin href="/assets/vendor-swr-BIWyz7Rc.js">
37
37
  <link rel="modulepreload" crossorigin href="/assets/check-DUBLcKHA.js">
38
38
  <link rel="modulepreload" crossorigin href="/assets/settings-shell-dialog-layer-BU3UuiJr.js">
39
39
  <link rel="modulepreload" crossorigin href="/assets/popover-select-CccGri5Y.js">
40
40
  <link rel="modulepreload" crossorigin href="/assets/circle-check-C23XjkUj.js">
41
+ <link rel="modulepreload" crossorigin href="/assets/cloud-C4-yfnnk.js">
41
42
  <link rel="modulepreload" crossorigin href="/assets/copy-Dv6d4Dvw.js">
42
43
  <link rel="modulepreload" crossorigin href="/assets/ellipsis-0k4rZLoy.js">
43
44
  <link rel="modulepreload" crossorigin href="/assets/external-link-DjqjBmc3.js">
@@ -45,25 +46,28 @@
45
46
  <link rel="modulepreload" crossorigin href="/assets/eye-CABVeTq0.js">
46
47
  <link rel="modulepreload" crossorigin href="/assets/file-code-corner-byQA1VfD.js">
47
48
  <link rel="modulepreload" crossorigin href="/assets/globe-DSSGFWFn.js">
48
- <link rel="modulepreload" crossorigin href="/assets/notes-api-BFsOGYkd.js">
49
+ <link rel="modulepreload" crossorigin href="/assets/notes-api-EpgG-OQc.js">
49
50
  <link rel="modulepreload" crossorigin href="/assets/loader-circle-CifKLtgG.js">
50
51
  <link rel="modulepreload" crossorigin href="/assets/rotate-cw-LIg3Am9S.js">
51
52
  <link rel="modulepreload" crossorigin href="/assets/search-DA7gz22f.js">
52
53
  <link rel="modulepreload" crossorigin href="/assets/middleware-Pd0e8Igk.js">
54
+ <link rel="modulepreload" crossorigin href="/assets/files-Dp8_uGTO.js">
53
55
  <link rel="modulepreload" crossorigin href="/assets/tool-activity-R8V9l6nk.js">
54
56
  <link rel="modulepreload" crossorigin href="/assets/button-CSEbl4zT.js">
55
57
  <link rel="modulepreload" crossorigin href="/assets/gateway-startup-retry-B_zrtccP.js">
56
58
  <link rel="modulepreload" crossorigin href="/assets/registry-api-BFZrVYfy.js">
57
59
  <link rel="modulepreload" crossorigin href="/assets/config-reload-event-Bjh2zoKp.js">
58
60
  <link rel="modulepreload" crossorigin href="/assets/gateway-config-swr-BWGjnmDl.js">
61
+ <link rel="modulepreload" crossorigin href="/assets/models-hub-cache-0RjEwafI.js">
59
62
  <link rel="modulepreload" crossorigin href="/assets/electron-env-DH5wF8X8.js">
63
+ <link rel="modulepreload" crossorigin href="/assets/oauth-api-BwNLwbI8.js">
60
64
  <link rel="modulepreload" crossorigin href="/assets/form-field-width-DJw_jULe.js">
61
65
  <link rel="modulepreload" crossorigin href="/assets/interaction-BmQogeqz.js">
62
66
  <link rel="modulepreload" crossorigin href="/assets/is-masked-secret-DOkL5b_X.js">
63
67
  <link rel="modulepreload" crossorigin href="/assets/activity-store-M0nAY5XB.js">
64
- <link rel="modulepreload" crossorigin href="/assets/theme-store-DOdCjyuw.js">
65
- <link rel="stylesheet" crossorigin href="/assets/markdown-view-CLzTdVLW.css">
66
- <link rel="stylesheet" crossorigin href="/assets/index-D_hrEKXM.css">
68
+ <link rel="modulepreload" crossorigin href="/assets/theme-store-Qgvo0Ga7.js">
69
+ <link rel="stylesheet" crossorigin href="/assets/markdown-view-B1bGSQqt.css">
70
+ <link rel="stylesheet" crossorigin href="/assets/index-CCyIdGuQ.css">
67
71
  </head>
68
72
  <body>
69
73
  <div id="root"></div>
package/dist/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.0.230";
2
+ var version = "0.0.231";
3
3
  //#endregion
4
4
  export { version };
@@ -108,6 +108,7 @@ export declare class AgentService {
108
108
  getAgentSkillAvailability(agentId: string): AgentSkillAvailabilityPayload;
109
109
  getSessionSkillAvailability(sessionKey: string): Promise<AgentSkillAvailabilityPayload>;
110
110
  getSessionWorkspaceTrust(sessionKey: string): Promise<WorkspaceTrustState>;
111
+ getResolvedWorkspaceForSession(sessionKey: string): string;
111
112
  setSessionWorkspaceTrust(sessionKey: string, trusted: boolean): Promise<WorkspaceTrustState>;
112
113
  getWorkspaceTrust(workspacePath: string): WorkspaceTrustState;
113
114
  setWorkspaceTrust(workspacePath: string, trusted: boolean): WorkspaceTrustState;
@@ -10,12 +10,12 @@ import { init_providers, resolveModel } from "../providers/index.js";
10
10
  import { extractTextContent } from "./context/workspace.js";
11
11
  import { effectiveWorkspacePathForSession } from "../session/session-workspace.js";
12
12
  import { getProjectForSession } from "../projects/workspace.js";
13
- import { resolveAgentTurnTimeoutMs } from "./orchestration/run-agent-turn-with-timeout.js";
14
- import { resolveResponseLanguageForSession } from "./prompt/response-language.js";
15
13
  import { resolveWorkspaceSkillsDir, resolveWorkspaceSkillsLockPath } from "./skills/workspace-skills-dir.js";
16
14
  import { removeSkillsLockEntry } from "./skills/hub-lock.js";
17
15
  import { installSkillFromZip } from "./skills/managed-store.js";
18
16
  import { pullSkillFromSource } from "./skills/hub-pull.js";
17
+ import { resolveAgentTurnTimeoutMs } from "./orchestration/run-agent-turn-with-timeout.js";
18
+ import { resolveResponseLanguageForSession } from "./prompt/response-language.js";
19
19
  import { normalizeSkillInstallTarget } from "./skills/install-target.js";
20
20
  import { onSessionTranscriptUpdate } from "../session/transcript-events.js";
21
21
  import { persistInboundAttachments } from "../channels/attachments/inbound-persist.js";
@@ -509,6 +509,9 @@ var AgentService = class {
509
509
  await this.sessionHydrator.workspace(sessionKey);
510
510
  return this.agentManager.getSessionWorkspaceTrust(sessionKey);
511
511
  }
512
+ getResolvedWorkspaceForSession(sessionKey) {
513
+ return this.agentManager.getResolvedWorkspaceForSession(sessionKey);
514
+ }
512
515
  async setSessionWorkspaceTrust(sessionKey, trusted) {
513
516
  await this.sessionHydrator.workspace(sessionKey);
514
517
  return this.agentManager.setSessionWorkspaceTrust(sessionKey, trusted);
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveSkillsDir } from "../../config/paths.js";
2
2
  import { parseFrontmatter } from "../../markdown/frontmatter.js";
3
- import { fuzzyFindText, normalizeForFuzzyMatch, normalizeToLF, restoreLineEndings } from "../tools/edit-diff.js";
4
3
  import { resolveWorkspaceSkillsDir } from "./workspace-skills-dir.js";
5
4
  import { formatScanSummary, scanSkillDirectory } from "./scanner.js";
5
+ import { fuzzyFindText, normalizeForFuzzyMatch, normalizeToLF, restoreLineEndings } from "../tools/edit-diff.js";
6
6
  import { join, resolve, sep } from "path";
7
7
  import { existsSync, realpathSync } from "fs";
8
8
  import { mkdir, writeFile } from "fs/promises";
@@ -1,9 +1,10 @@
1
1
  import { checkFileSafety } from "../prompt/safety.js";
2
2
  import { isBareProfileMarkdownFileName, resolvePathUnderWorkspace, resolveProfileMarkdownPathIfBareName } from "./tool-paths.js";
3
3
  import { appendProductDeliveryText } from "../../../packages/gateway-contract/src/product-delivery.js";
4
+ import { fileResourceId, fileSpaceId } from "../../files/file-service.js";
4
5
  import { evaluateFilePolicy } from "../sandbox/exec-policy.js";
5
- import { basename, dirname } from "path";
6
- import { mkdir, writeFile } from "fs/promises";
6
+ import { basename, dirname, relative, sep } from "path";
7
+ import { mkdir, realpath, writeFile } from "fs/promises";
7
8
  import { Type } from "@sinclair/typebox";
8
9
  //#region src/agent/tools/write.ts
9
10
  const MAX_FILE_SIZE = 10 * 1024 * 1024;
@@ -59,30 +60,26 @@ function createWriteFileTool(workspace, options) {
59
60
  const target = writesProfileFile ? resolveProfileMarkdownPathIfBareName(p.path, options.profileMarkdownRoot) : resolvePathUnderWorkspace(p.path, workspace);
60
61
  await mkdir(dirname(target), { recursive: true });
61
62
  await writeFile(target, p.content, "utf-8");
62
- const delivery = {
63
+ const delivery = writesProfileFile ? void 0 : await Promise.all([realpath(workspace), realpath(target)]).then(([root, canonicalTarget]) => ({
63
64
  version: 1,
64
65
  operation: "updated",
65
66
  primary: {
66
67
  kind: "file",
67
- id: target,
68
+ id: fileResourceId(fileSpaceId(root), relative(root, canonicalTarget).split(sep).join("/")),
68
69
  title: basename(target),
69
70
  summary: `${contentBytes} bytes written`,
70
- capabilities: [
71
- "preview",
72
- "reveal",
73
- "share"
74
- ]
71
+ capabilities: ["preview", "share"]
75
72
  }
76
- };
73
+ }));
77
74
  return {
78
75
  content: [{
79
76
  type: "text",
80
- text: appendProductDeliveryText(`File written: ${target}`, delivery)
77
+ text: delivery ? appendProductDeliveryText(`File written: ${target}`, delivery) : `File written: ${target}`
81
78
  }],
82
79
  details: {
83
80
  size: contentBytes,
84
81
  path: target,
85
- delivery
82
+ ...delivery ? { delivery } : {}
86
83
  }
87
84
  };
88
85
  } catch (error) {
@@ -11,10 +11,10 @@ import { TaskRunRepository } from "../../tasks/task-run-repository.js";
11
11
  import { TaskReadModelProjector } from "../../tasks/task-read-model-projector.js";
12
12
  import { TaskCommandSchema, TaskContextInputSchema } from "../../../packages/gateway-contract/src/tasks.js";
13
13
  import { appendProductDeliveryText } from "../../../packages/gateway-contract/src/product-delivery.js";
14
- import { CreateAutomationSchema, UpdateAutomationSchema } from "../../automations/domain/validation.js";
15
- import "../../automations/index.js";
16
14
  import { isValidProjectAgentId, normalizeProjectAgentId, resolveProjectAgentId } from "../../projects/project-agent.js";
17
15
  import "../../projects/index.js";
16
+ import { CreateAutomationSchema, UpdateAutomationSchema } from "../../automations/domain/validation.js";
17
+ import "../../automations/index.js";
18
18
  import { TaskContextRepository } from "../../tasks/task-context-repository.js";
19
19
  import { TaskDependencyError, TaskDependencyService } from "../../tasks/task-dependency-service.js";
20
20
  import { TaskApplicationService } from "../../tasks/task-application-service.js";
@@ -8,7 +8,7 @@ import { init_kimi_coding, kimiCodingOAuthProvider } from "./kimi-coding.js";
8
8
  import { init_minimax_cn, minimaxCnOAuthProvider } from "./minimax-cn.js";
9
9
  import { init_minimax, minimaxOAuthProvider } from "./minimax.js";
10
10
  import { init_openai_codex, loginOpenAICodex, openaiCodexOAuthProvider, refreshOpenAICodexToken } from "./openai-codex.js";
11
- import { init_xopc_cloud, xopcCloudOAuthProvider, xopcTunnelOAuthProvider } from "./xopc-cloud.js";
11
+ import { init_xopc_cloud, xopcCloudOAuthProvider, xopcShareOAuthProvider, xopcTunnelOAuthProvider } from "./xopc-cloud.js";
12
12
  import { OAUTH_PROVIDER_DEFINITIONS, getModelOAuthProviderIds, getOAuthProviderDefinition, getOAuthProviderIds, getOAuthProviderInterfaces, init_registry, isOAuthOnlyProvider } from "./registry.js";
13
13
  //#region src/auth/oauth/index.ts
14
14
  init_anthropic();
@@ -22,4 +22,4 @@ init_openai_codex();
22
22
  init_xopc_cloud();
23
23
  init_registry();
24
24
  //#endregion
25
- export { OAUTH_PROVIDER_DEFINITIONS, anthropicOAuthProvider, getModelOAuthProviderIds, getOAuthProviderDefinition, getOAuthProviderIds, getOAuthProviderInterfaces, githubCopilotOAuthProvider, antigravityOAuthProvider as googleAntigravityOAuthProvider, geminiCliOAuthProvider as googleGeminiCliOAuthProvider, isOAuthOnlyProvider, kimiCodingOAuthProvider, loginAnthropic, loginAntigravity, loginGeminiCli, loginOpenAICodex, minimaxCnOAuthProvider, minimaxOAuthProvider, openaiCodexOAuthProvider, refreshAnthropicToken, refreshAntigravityToken, refreshGoogleCloudToken, refreshOpenAICodexToken, xopcCloudOAuthProvider, xopcTunnelOAuthProvider };
25
+ export { OAUTH_PROVIDER_DEFINITIONS, anthropicOAuthProvider, getModelOAuthProviderIds, getOAuthProviderDefinition, getOAuthProviderIds, getOAuthProviderInterfaces, githubCopilotOAuthProvider, antigravityOAuthProvider as googleAntigravityOAuthProvider, geminiCliOAuthProvider as googleGeminiCliOAuthProvider, isOAuthOnlyProvider, kimiCodingOAuthProvider, loginAnthropic, loginAntigravity, loginGeminiCli, loginOpenAICodex, minimaxCnOAuthProvider, minimaxOAuthProvider, openaiCodexOAuthProvider, refreshAnthropicToken, refreshAntigravityToken, refreshGoogleCloudToken, refreshOpenAICodexToken, xopcCloudOAuthProvider, xopcShareOAuthProvider, xopcTunnelOAuthProvider };
@@ -2,7 +2,7 @@ import type { OAuthProviderInterface } from './types.js';
2
2
  export interface OAuthProviderDefinition {
3
3
  displayName: string;
4
4
  oauthOnly?: boolean;
5
- purpose: 'models' | 'tunnel';
5
+ purpose: 'models' | 'tunnel' | 'share';
6
6
  provider: OAuthProviderInterface;
7
7
  profileId: string;
8
8
  urlPrompt: string;
@@ -9,7 +9,7 @@ import { init_kimi_coding, kimiCodingOAuthProvider } from "./kimi-coding.js";
9
9
  import { init_minimax_cn, minimaxCnOAuthProvider } from "./minimax-cn.js";
10
10
  import { init_minimax, minimaxOAuthProvider } from "./minimax.js";
11
11
  import { init_openai_codex, openaiCodexOAuthProvider } from "./openai-codex.js";
12
- import { init_xopc_cloud, xopcCloudOAuthProvider, xopcTunnelOAuthProvider } from "./xopc-cloud.js";
12
+ import { init_xopc_cloud, xopcCloudOAuthProvider, xopcShareOAuthProvider, xopcTunnelOAuthProvider } from "./xopc-cloud.js";
13
13
  //#region src/auth/oauth/registry.ts
14
14
  function definition(provider, purpose, displayName = provider.name) {
15
15
  return {
@@ -55,6 +55,10 @@ var init_registry = __esmMin((() => {
55
55
  ...definition(xopcTunnelOAuthProvider, "tunnel"),
56
56
  oauthOnly: true
57
57
  },
58
+ "xopc-share": {
59
+ ...definition(xopcShareOAuthProvider, "share"),
60
+ oauthOnly: true
61
+ },
58
62
  anthropic: definition(anthropicOAuthProvider, "models", "Anthropic (Claude)"),
59
63
  minimax: definition(minimaxOAuthProvider, "models", "MiniMax (幂维智能)"),
60
64
  "minimax-cn": {
@@ -1,3 +1,4 @@
1
1
  import type { OAuthProviderInterface } from './types.js';
2
2
  export declare const xopcCloudOAuthProvider: OAuthProviderInterface;
3
3
  export declare const xopcTunnelOAuthProvider: OAuthProviderInterface;
4
+ export declare const xopcShareOAuthProvider: OAuthProviderInterface;
@@ -388,13 +388,14 @@ function createXopcOAuthProvider(options) {
388
388
  getApiKey: (value) => value.access
389
389
  };
390
390
  }
391
- var CLIENT_ID, DEFAULT_CONSOLE_URL, MODEL_SERVICE_SCOPE, TUNNEL_REGISTRATION_SCOPE, CALLBACK_PATH, AUTHORIZATION_TIMEOUT_MS, xopcCloudOAuthProvider, xopcTunnelOAuthProvider;
391
+ var CLIENT_ID, DEFAULT_CONSOLE_URL, MODEL_SERVICE_SCOPE, TUNNEL_REGISTRATION_SCOPE, HOSTED_SHARE_SCOPE, CALLBACK_PATH, AUTHORIZATION_TIMEOUT_MS, xopcCloudOAuthProvider, xopcTunnelOAuthProvider, xopcShareOAuthProvider;
392
392
  var init_xopc_cloud = __esmMin((() => {
393
393
  init_pkce();
394
394
  CLIENT_ID = "xopc-native";
395
395
  DEFAULT_CONSOLE_URL = "https://console.xopc.ai";
396
396
  MODEL_SERVICE_SCOPE = "models:read models:invoke account:usage connectors:read connectors:manage connectors:execute offline_access";
397
397
  TUNNEL_REGISTRATION_SCOPE = "tunnel:register";
398
+ HOSTED_SHARE_SCOPE = "shares:read shares:write offline_access";
398
399
  CALLBACK_PATH = "/oauth/callback";
399
400
  AUTHORIZATION_TIMEOUT_MS = 5 * 6e4;
400
401
  xopcCloudOAuthProvider = createXopcOAuthProvider({
@@ -407,7 +408,12 @@ var init_xopc_cloud = __esmMin((() => {
407
408
  name: "XOPC Public Tunnel",
408
409
  scope: TUNNEL_REGISTRATION_SCOPE
409
410
  });
411
+ xopcShareOAuthProvider = createXopcOAuthProvider({
412
+ id: "xopc-share",
413
+ name: "XOPC Hosted Share",
414
+ scope: HOSTED_SHARE_SCOPE
415
+ });
410
416
  }));
411
417
  //#endregion
412
418
  init_xopc_cloud();
413
- export { init_xopc_cloud, xopcCloudOAuthProvider, xopcTunnelOAuthProvider };
419
+ export { init_xopc_cloud, xopcCloudOAuthProvider, xopcShareOAuthProvider, xopcTunnelOAuthProvider };
@@ -0,0 +1,36 @@
1
+ import type { FileResource, FileSpace } from '@xopcai/gateway-contract';
2
+ import type { Config } from '../config/schema.js';
3
+ import { type ProjectService } from '../projects/index.js';
4
+ export type ResolvedFileSpace = FileSpace & {
5
+ root: string;
6
+ };
7
+ export declare function fileSpaceId(root: string): string;
8
+ export declare function fileResourceId(spaceId: string, relativePath: string): string;
9
+ export declare function parseFileResourceId(id: string): {
10
+ spaceId: string;
11
+ relativePath: string;
12
+ };
13
+ export declare function resolveFilePath(root: string, path: string, mustExist?: boolean): Promise<string>;
14
+ export declare class FileServiceError extends Error {
15
+ readonly status: 400 | 403 | 404 | 409;
16
+ constructor(status: 400 | 403 | 404 | 409, message: string);
17
+ }
18
+ export declare function fileResourceFromPath(space: ResolvedFileSpace, absolutePath: string): Promise<FileResource>;
19
+ export declare class FileSpaceService {
20
+ private readonly getConfig;
21
+ private readonly projects;
22
+ private readonly resolveSessionWorkspace;
23
+ private readonly dynamicSpaces;
24
+ private cache;
25
+ constructor(getConfig: () => Config, projects: ProjectService, resolveSessionWorkspace: (sessionKey: string) => string);
26
+ private createSpace;
27
+ list(): Promise<ResolvedFileSpace[]>;
28
+ forContext(kind: 'agent' | 'project' | 'session', id: string): Promise<ResolvedFileSpace>;
29
+ get(id: string): Promise<ResolvedFileSpace>;
30
+ resource(id: string): Promise<{
31
+ space: ResolvedFileSpace;
32
+ resource: FileResource;
33
+ absolutePath: string;
34
+ }>;
35
+ children(spaceId: string, path?: string): Promise<FileResource[]>;
36
+ }
@@ -0,0 +1,282 @@
1
+ import { init_agent_scope, listAgentEntries, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
2
+ import { resolveProjectAgentId } from "../projects/project-agent.js";
3
+ import "../projects/index.js";
4
+ import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
5
+ import { constants } from "node:fs";
6
+ import { createHash } from "node:crypto";
7
+ import { access, lstat, opendir, realpath, stat } from "node:fs/promises";
8
+ //#region src/files/file-service.ts
9
+ init_agent_scope();
10
+ const SKIPPED_NAMES = new Set([
11
+ ".DS_Store",
12
+ ".git",
13
+ "node_modules"
14
+ ]);
15
+ const TEXT_EXTENSIONS = new Set([
16
+ "css",
17
+ "csv",
18
+ "html",
19
+ "htm",
20
+ "js",
21
+ "json",
22
+ "jsx",
23
+ "md",
24
+ "mjs",
25
+ "cjs",
26
+ "svg",
27
+ "ts",
28
+ "tsx",
29
+ "txt",
30
+ "xml",
31
+ "yaml",
32
+ "yml"
33
+ ]);
34
+ const MIME_TYPES = {
35
+ png: "image/png",
36
+ jpg: "image/jpeg",
37
+ jpeg: "image/jpeg",
38
+ gif: "image/gif",
39
+ webp: "image/webp",
40
+ svg: "image/svg+xml",
41
+ md: "text/markdown",
42
+ txt: "text/plain",
43
+ json: "application/json",
44
+ html: "text/html",
45
+ htm: "text/html",
46
+ css: "text/css",
47
+ js: "text/javascript",
48
+ mjs: "text/javascript",
49
+ cjs: "text/javascript",
50
+ ts: "text/typescript",
51
+ tsx: "text/typescript",
52
+ csv: "text/csv",
53
+ xml: "application/xml",
54
+ yaml: "application/yaml",
55
+ yml: "application/yaml",
56
+ pdf: "application/pdf",
57
+ mp3: "audio/mpeg",
58
+ wav: "audio/wav",
59
+ ogg: "audio/ogg",
60
+ m4a: "audio/mp4",
61
+ mp4: "video/mp4",
62
+ mov: "video/quicktime",
63
+ webm: "video/webm"
64
+ };
65
+ function isWithin(root, target) {
66
+ const rel = relative(root, target);
67
+ return rel === "" || !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel);
68
+ }
69
+ function normalizeRelativePath(input) {
70
+ const normalized = input.replace(/\\/g, "/").replace(/^\/+/, "").replace(/\/+$/, "");
71
+ if (normalized.includes("\0") || normalized.split("/").some((part) => part === "..")) throw new FileServiceError(400, "Invalid file path");
72
+ return normalized.split("/").filter((part) => part && part !== ".").join("/");
73
+ }
74
+ function mimeType(name, directory) {
75
+ if (directory) return "inode/directory";
76
+ return MIME_TYPES[name.includes(".") ? name.split(".").pop().toLowerCase() : ""] ?? "application/octet-stream";
77
+ }
78
+ function capabilities(name, directory, writable) {
79
+ if (directory) return writable ? ["upload"] : [];
80
+ const extension = name.includes(".") ? name.split(".").pop().toLowerCase() : "";
81
+ const result = ["download", "share"];
82
+ if (MIME_TYPES[extension] || TEXT_EXTENSIONS.has(extension)) result.unshift("preview");
83
+ if (writable && TEXT_EXTENSIONS.has(extension)) result.push("edit");
84
+ return result;
85
+ }
86
+ function fileSpaceId(root) {
87
+ return createHash("sha256").update(root).digest("base64url").slice(0, 24);
88
+ }
89
+ function fileResourceId(spaceId, relativePath) {
90
+ return `${spaceId}.${Buffer.from(normalizeRelativePath(relativePath)).toString("base64url")}`;
91
+ }
92
+ function parseFileResourceId(id) {
93
+ const separator = id.indexOf(".");
94
+ if (separator <= 0) throw new FileServiceError(400, "Invalid file id");
95
+ try {
96
+ return {
97
+ spaceId: id.slice(0, separator),
98
+ relativePath: normalizeRelativePath(Buffer.from(id.slice(separator + 1), "base64url").toString("utf8"))
99
+ };
100
+ } catch (error) {
101
+ if (error instanceof FileServiceError) throw error;
102
+ throw new FileServiceError(400, "Invalid file id");
103
+ }
104
+ }
105
+ async function resolveFilePath(root, path, mustExist = true) {
106
+ const canonicalRoot = await realpath(root).catch(() => {
107
+ throw new FileServiceError(404, "File space is unavailable");
108
+ });
109
+ const candidate = resolve(canonicalRoot, normalizeRelativePath(path));
110
+ if (!isWithin(canonicalRoot, candidate)) throw new FileServiceError(400, "Invalid file path");
111
+ if (!mustExist) {
112
+ if (!isWithin(canonicalRoot, await realpath(dirname(candidate)).catch(() => {
113
+ throw new FileServiceError(404, "Parent directory not found");
114
+ }))) throw new FileServiceError(400, "Invalid file path");
115
+ return candidate;
116
+ }
117
+ const canonicalTarget = await realpath(candidate).catch(() => {
118
+ throw new FileServiceError(404, "File not found");
119
+ });
120
+ if (!isWithin(canonicalRoot, canonicalTarget)) throw new FileServiceError(400, "File is outside its space");
121
+ return canonicalTarget;
122
+ }
123
+ var FileServiceError = class extends Error {
124
+ constructor(status, message) {
125
+ super(message);
126
+ this.status = status;
127
+ }
128
+ };
129
+ async function fileResourceFromPath(space, absolutePath) {
130
+ const info = await stat(absolutePath);
131
+ const revisionInfo = await stat(absolutePath, { bigint: true });
132
+ const relativePath = relative(await realpath(space.root), absolutePath).split(sep).join("/");
133
+ const name = basename(absolutePath);
134
+ const directory = info.isDirectory();
135
+ return {
136
+ id: fileResourceId(space.id, relativePath),
137
+ spaceId: space.id,
138
+ name,
139
+ relativePath,
140
+ parentPath: dirname(relativePath).split(sep).join("/").replace(/^\.$/, ""),
141
+ kind: directory ? "directory" : "file",
142
+ mimeType: mimeType(name, directory),
143
+ size: info.size,
144
+ modifiedAt: Math.max(0, Math.round(info.mtimeMs)),
145
+ revision: `${revisionInfo.mtimeNs}:${revisionInfo.ctimeNs}:${revisionInfo.ino}:${revisionInfo.size}`,
146
+ capabilities: capabilities(name, directory, space.writable)
147
+ };
148
+ }
149
+ var FileSpaceService = class {
150
+ dynamicSpaces = /* @__PURE__ */ new Map();
151
+ cache = null;
152
+ constructor(getConfig, projects, resolveSessionWorkspace) {
153
+ this.getConfig = getConfig;
154
+ this.projects = projects;
155
+ this.resolveSessionWorkspace = resolveSessionWorkspace;
156
+ }
157
+ async createSpace(root, title, bindings) {
158
+ const canonicalRoot = await realpath(root).catch(() => null);
159
+ if (!canonicalRoot) return null;
160
+ const rootStat = await stat(canonicalRoot).catch(() => null);
161
+ if (!rootStat?.isDirectory()) return null;
162
+ const writable = await access(canonicalRoot, constants.W_OK).then(() => true).catch(() => false);
163
+ return {
164
+ id: fileSpaceId(canonicalRoot),
165
+ title,
166
+ kind: "workspace",
167
+ bindings,
168
+ writable,
169
+ root: canonicalRoot,
170
+ lastActivityAt: Math.max(0, Math.round(rootStat.mtimeMs))
171
+ };
172
+ }
173
+ async list() {
174
+ if (this.cache && Date.now() - this.cache.at < 5e3) return this.cache.spaces;
175
+ const config = this.getConfig();
176
+ const spaces = [];
177
+ for (const agent of listAgentEntries(config)) {
178
+ const space = await this.createSpace(resolveAgentWorkspaceDir(config, agent.id), agent.id, [{
179
+ kind: "agent",
180
+ id: agent.id
181
+ }]);
182
+ if (space) spaces.push(space);
183
+ }
184
+ let offset = 0;
185
+ while (true) {
186
+ const page = this.projects.list({
187
+ limit: 500,
188
+ offset
189
+ });
190
+ for (const project of page.items) {
191
+ const agentId = resolveProjectAgentId({
192
+ config,
193
+ projects: this.projects,
194
+ projectId: project.id
195
+ });
196
+ const root = project.workspaceRoot ?? resolveAgentWorkspaceDir(config, agentId);
197
+ const space = await this.createSpace(root, project.name, [{
198
+ kind: "project",
199
+ id: project.id
200
+ }]);
201
+ if (space) spaces.push(space);
202
+ }
203
+ if (!page.hasMore || page.items.length === 0) break;
204
+ offset += page.items.length;
205
+ }
206
+ const merged = /* @__PURE__ */ new Map();
207
+ for (const space of [...spaces, ...this.dynamicSpaces.values()]) {
208
+ const existing = merged.get(space.id);
209
+ if (existing) existing.bindings = [...existing.bindings, ...space.bindings.filter((binding) => !existing.bindings.some((item) => item.kind === binding.kind && item.id === binding.id))];
210
+ else merged.set(space.id, {
211
+ ...space,
212
+ bindings: [...space.bindings]
213
+ });
214
+ }
215
+ const result = [...merged.values()].sort((a, b) => (b.lastActivityAt ?? 0) - (a.lastActivityAt ?? 0));
216
+ this.cache = {
217
+ at: Date.now(),
218
+ spaces: result
219
+ };
220
+ return result;
221
+ }
222
+ async forContext(kind, id) {
223
+ let root;
224
+ let title = id;
225
+ if (kind === "agent") root = resolveAgentWorkspaceDir(this.getConfig(), id);
226
+ if (kind === "project") {
227
+ const project = this.projects.get(id);
228
+ if (project) {
229
+ const config = this.getConfig();
230
+ const agentId = resolveProjectAgentId({
231
+ config,
232
+ projects: this.projects,
233
+ projectId: id
234
+ });
235
+ root = project.workspaceRoot ?? resolveAgentWorkspaceDir(config, agentId);
236
+ }
237
+ title = project?.name ?? id;
238
+ }
239
+ if (kind === "session") root = this.resolveSessionWorkspace(id);
240
+ if (!root) throw new FileServiceError(404, "File space not found");
241
+ const space = await this.createSpace(root, title, [{
242
+ kind,
243
+ id
244
+ }]);
245
+ if (!space) throw new FileServiceError(404, "File space is unavailable");
246
+ this.dynamicSpaces.set(space.id, space);
247
+ this.cache = null;
248
+ return space;
249
+ }
250
+ async get(id) {
251
+ const space = (await this.list()).find((item) => item.id === id);
252
+ if (!space) throw new FileServiceError(404, "File space not found");
253
+ return space;
254
+ }
255
+ async resource(id) {
256
+ const locator = parseFileResourceId(id);
257
+ const space = await this.get(locator.spaceId);
258
+ const absolutePath = await resolveFilePath(space.root, locator.relativePath);
259
+ return {
260
+ space,
261
+ resource: await fileResourceFromPath(space, absolutePath),
262
+ absolutePath
263
+ };
264
+ }
265
+ async children(spaceId, path = "") {
266
+ const space = await this.get(spaceId);
267
+ const directory = await resolveFilePath(space.root, path);
268
+ if (!(await stat(directory)).isDirectory()) throw new FileServiceError(400, "Path is not a directory");
269
+ const entries = [];
270
+ const dir = await opendir(directory);
271
+ for await (const entry of dir) {
272
+ if (SKIPPED_NAMES.has(entry.name)) continue;
273
+ const target = resolve(directory, entry.name);
274
+ const linkInfo = await lstat(target).catch(() => null);
275
+ if (!linkInfo || linkInfo.isSymbolicLink()) continue;
276
+ entries.push(await fileResourceFromPath(space, target));
277
+ }
278
+ return entries.sort((a, b) => a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === "directory" ? -1 : 1);
279
+ }
280
+ };
281
+ //#endregion
282
+ export { FileServiceError, FileSpaceService, fileResourceFromPath, fileResourceId, fileSpaceId, parseFileResourceId, resolveFilePath };
@@ -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";
@@ -155,7 +155,7 @@ function createHonoApp(config) {
155
155
  if (/^\/api\/notes\/[^/]+\/media$/.test(path)) return true;
156
156
  return path === "/api/notes" && contentType?.includes("multipart/form-data") === true;
157
157
  };
158
- const isProjectFileUploadRequest = (path, method, contentType) => method === "POST" && /^\/api\/projects\/[^/]+\/files\/upload$/.test(path) && contentType?.includes("multipart/form-data") === true;
158
+ const isFileUploadRequest = (path, method, contentType) => method === "POST" && /^\/api\/files\/spaces\/[^/]+\/upload$/.test(path) && contentType?.includes("multipart/form-data") === true;
159
159
  const discussionUploadBodyMax = (path, method, contentType) => {
160
160
  if (method !== "PUT" || contentType?.includes("multipart/form-data") !== true) return void 0;
161
161
  if (/^\/api\/discussions\/[^/]+\/recording$/.test(path)) return NOTE_MEDIA_BODY_MAX;
@@ -176,7 +176,7 @@ function createHonoApp(config) {
176
176
  }));
177
177
  app.use("/api/*", async (c, next) => {
178
178
  const contentType = c.req.header("content-type");
179
- const maxSize = c.req.method === "POST" && c.req.path === "/api/tasks" || c.req.method === "POST" && /^\/api\/sessions\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "POST" && /^\/api\/tasks\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "PATCH" && /^\/api\/sessions\/[^/]+\/inputs\/[^/]+$/.test(c.req.path) ? SESSION_INPUT_BODY_MAX : c.req.path === "/api/skills/upload" ? SKILL_UPLOAD_BODY_MAX : c.req.path === "/api/voice/transcriptions" ? VOICE_TRANSCRIBE_BODY_MAX : c.req.path === "/api/media" && c.req.method === "POST" ? MEDIA_UPLOAD_BODY_MAX : isNoteMediaUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : isProjectFileUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : discussionUploadBodyMax(c.req.path, c.req.method, contentType) ?? DEFAULT_API_BODY_MAX;
179
+ const maxSize = c.req.method === "POST" && c.req.path === "/api/tasks" || c.req.method === "POST" && /^\/api\/sessions\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "POST" && /^\/api\/tasks\/[^/]+\/inputs$/.test(c.req.path) || c.req.method === "PATCH" && /^\/api\/sessions\/[^/]+\/inputs\/[^/]+$/.test(c.req.path) ? SESSION_INPUT_BODY_MAX : c.req.path === "/api/skills/upload" ? SKILL_UPLOAD_BODY_MAX : c.req.path === "/api/voice/transcriptions" ? VOICE_TRANSCRIBE_BODY_MAX : c.req.path === "/api/media" && c.req.method === "POST" ? MEDIA_UPLOAD_BODY_MAX : isNoteMediaUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : isFileUploadRequest(c.req.path, c.req.method, contentType) ? NOTE_MEDIA_BODY_MAX : discussionUploadBodyMax(c.req.path, c.req.method, contentType) ?? DEFAULT_API_BODY_MAX;
180
180
  const maxSizeMb = Math.ceil(maxSize / (1024 * 1024));
181
181
  return bodyLimit({
182
182
  maxSize,
@@ -0,0 +1,3 @@
1
+ import type { Hono } from 'hono';
2
+ import type { AuthenticatedRouteDeps } from './deps.js';
3
+ export declare function registerFilesRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void;