@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.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Bp_wmuGW.js → agent-avatar-dicebear-CBqUnlvL.js} +1 -1
- package/dist/gateway/static/root/assets/agents-7YO6znTT.js +68 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-CwAPK4Jm.js → app-management-settings-panel-DP7YVRPn.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DsGLvqTb.js → appearance-settings-CVQ5n7y6.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-Ee9qOQEx.js → apps-page-DSCia0DT.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-B4qqigAQ.js → attachment-load-mmr_mHRr.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-B8ImehSW.js → automations-page-DfY-T6Ga.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-BpvD54D6.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-DaJbyYc2.js → binary-plugins-CO9QMEh2.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-Kl25XWJc.js → block-editor-CE14CVOy.js} +3 -3
- package/dist/gateway/static/root/assets/browser-settings-page-CeESA4Oj.js +8 -0
- package/dist/gateway/static/root/assets/{browser-workflows-page-DjMxs33B.js → browser-workflows-page-1wgXyoSO.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-B_OXTojB.js +7 -0
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-D5nZecxV.js +3 -0
- package/dist/gateway/static/root/assets/channels-settings-BzmnWx6X.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-BiU_4Rq6.js → chat-terminal-dock-CdRW6Euc.js} +2 -2
- package/dist/gateway/static/root/assets/cloud-C4-yfnnk.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-DX6OkwFQ.js +2 -0
- package/dist/gateway/static/root/assets/{cron-expression-Cs_5pUPT.js → cron-expression-DYSMZsms.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-y1kWrFVU.js → date-picker-DGCfX4tK.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-skc62zrn.js → dependency-picker-DHDa4ht1.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-ux9DxchT.js → desktop-pet-CMO-J3cG.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BVVCBgYK.js → desktop-pet-settings-MmOR4A3u.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-V8vZP0Dy.js → directory-picker-path-field-B9qoxDcn.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-Dh6DDuvQ.js → extension-debug-page-DdH0dG2_.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-8OKQDEat.js → extension-page-Clg-KktN.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BgSV0Nny.js → extension-settings-page-eP3fJ2M6.js} +1 -1
- package/dist/gateway/static/root/assets/files-Dp8_uGTO.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-api-Dlc6eaTG.js → gateway-config-api-DEHnF4Wm.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-DqQgiAUv.js → gateway-settings-DKkEXXj9.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-Pxqk5GFH.js → heartbeat-settings-DlBPNubY.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-BnOrLRfs.js +1 -0
- package/dist/gateway/static/root/assets/index-0xQO5B_Q.js +70 -0
- package/dist/gateway/static/root/assets/index-CCyIdGuQ.css +2 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BSFNqxzY.js → keyboard-shortcuts-settings-BvpEeHnm.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-Ch1rdUo8.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DzU6yZ9-.js → local-apps-page-Bzvn99eH.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-zxx2ExlY.js +2 -0
- package/dist/gateway/static/root/assets/{management-settings-B8hM56HS.js → management-settings-BQaeyOYm.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-DRbZjxMK.js → markdown-split-D9tmIiEm.js} +1 -1
- package/dist/gateway/static/root/assets/markdown-view-B1bGSQqt.css +1 -0
- package/dist/gateway/static/root/assets/{media-plugins-B8vMe5VX.js → media-plugins-D8I7OGnT.js} +1 -1
- package/dist/gateway/static/root/assets/models-hub-cache-0RjEwafI.js +1 -0
- package/dist/gateway/static/root/assets/{notes-api-BFsOGYkd.js → notes-api-EpgG-OQc.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-B-YZ7iuK.js → notes-page-CCvjGMhN.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-9cgh77VH.js +4 -0
- package/dist/gateway/static/root/assets/oauth-api-BwNLwbI8.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-DkWcyki5.js → product-open-page-MmMswmOU.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-hf6pmH4p.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-By2U-Wdh.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-CUcpp7CQ.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Bq_ETeal.js → runtime-tools-settings-panel-Dx6o7sLu.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-BogTlrsP.js → schema-form-Cdd9c4vt.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-ByI82xS1.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BCoI5IJ8.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-Coy1Cbp6.js → settings-form-section-D0YxMnhm.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-B5GU7iCG.js → settings-loading-skeleton-y53gEKsF.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-Dd-BRu12.js → settings-page-BoE_tToG.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-CwEFAVWx.js → setup-status-panel-BQmyb5KC.js} +1 -1
- package/dist/gateway/static/root/assets/share-preview-page-DiqBn-oE.js +2 -0
- package/dist/gateway/static/root/assets/shares-settings-Bf3VpZ-R.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CXHlbuGS.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-Brxb6QnW.js → skills-page-CZwhWiRl.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-FB5LtEGm.js → skills-page.utils-kBGr8opZ.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-ChosWt8n.js → system-settings-panel-CPBs6lWi.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-Bo0KSZ2v.js +1 -0
- package/dist/gateway/static/root/assets/theme-store-Qgvo0Ga7.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-2SqnmSKD.js → use-autosave-C4YcEiP9.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-Cnj7gMX2.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-DtTIF6M8.js → voice-api-key-field-BML8zCwZ.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-CK3aZDdE.js → work-discovery-overlay-CKIdPEen.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BjOuddkX.js → workflow-run-setup-panel-BK44Vm5W.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-CB98MTwG.js +5 -0
- package/dist/gateway/static/root/index.html +10 -6
- package/dist/package.js +1 -1
- package/dist/src/agent/service.d.ts +1 -0
- package/dist/src/agent/service.js +5 -2
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/tools/write.js +9 -12
- package/dist/src/agent/tools/xopc-use-tool.js +2 -2
- package/dist/src/auth/oauth/index.js +2 -2
- package/dist/src/auth/oauth/registry.d.ts +1 -1
- package/dist/src/auth/oauth/registry.js +5 -1
- package/dist/src/auth/oauth/xopc-cloud.d.ts +1 -0
- package/dist/src/auth/oauth/xopc-cloud.js +8 -2
- package/dist/src/files/file-service.d.ts +36 -0
- package/dist/src/files/file-service.js +282 -0
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/app.js +2 -2
- package/dist/src/gateway/hono/routes/files.d.ts +3 -0
- package/dist/src/gateway/hono/routes/files.js +172 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/projects.js +0 -508
- package/dist/src/gateway/hono/routes/shares.js +410 -21
- package/dist/src/gateway/hono/routes/voice.js +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +15 -974
- package/dist/src/gateway/service.js +9 -9
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/share/hosted-session-share.d.ts +104 -0
- package/dist/src/share/hosted-session-share.js +276 -0
- package/dist/src/share/note-share-service.js +4 -24
- package/dist/src/share/session-share-projector.d.ts +31 -0
- package/dist/src/share/session-share-projector.js +79 -0
- package/dist/src/share/session-share-service.d.ts +89 -0
- package/dist/src/share/session-share-service.js +325 -0
- package/dist/src/share/share-asset-ticket.d.ts +7 -0
- package/dist/src/share/share-asset-ticket.js +30 -0
- package/dist/src/share/share-landing.d.ts +4 -3
- package/dist/src/share/share-landing.js +5 -5
- package/dist/src/share/share-store.d.ts +27 -2
- package/dist/src/share/share-store.js +71 -8
- package/dist/src/share/share-types.d.ts +17 -2
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/tui/backends/gateway-realtime-backend.js +11 -3
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-CKG93dlc.js +0 -68
- package/dist/gateway/static/root/assets/automations-workspace-BNFAfNwC.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-Cg6NgwE_.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-NvJKgF1u.js +0 -7
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-C2uBdALe.js +0 -3
- package/dist/gateway/static/root/assets/channels-settings-CIcYKMEs.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-CEEcmUiP.js +0 -2
- package/dist/gateway/static/root/assets/home-page-1xjo6wE4.js +0 -1
- package/dist/gateway/static/root/assets/index-Bbd_dXui.js +0 -70
- package/dist/gateway/static/root/assets/index-D_hrEKXM.css +0 -2
- package/dist/gateway/static/root/assets/local-app-workbench-page-heQ4-PJ7.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-BblnS6Jy.js +0 -2
- package/dist/gateway/static/root/assets/markdown-view-CLzTdVLW.css +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-CAM09C8b.js +0 -4
- package/dist/gateway/static/root/assets/project-detail-page-BIPIwgU2.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-B_kzTn1K.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CtD8DsD-.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-B8n9HI1y.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-xlhdRTME.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-DzXw9UQJ.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-Bk6UQOwS.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DrmQZ3Au.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-CW2sJbdc.js +0 -1
- package/dist/gateway/static/root/assets/theme-store-DOdCjyuw.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-Bq9KB-Oj.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-CcbGEQol.js +0 -5
- package/dist/src/gateway/file-path-classifier.d.ts +0 -30
- package/dist/src/gateway/file-path-classifier.js +0 -105
- package/dist/src/gateway/file-reference-errors.d.ts +0 -6
- package/dist/src/gateway/file-reference-errors.js +0 -21
- package/dist/src/gateway/file-reference-registry.d.ts +0 -34
- package/dist/src/gateway/file-reference-registry.js +0 -45
- /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-
|
|
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-
|
|
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-
|
|
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-
|
|
65
|
-
<link rel="stylesheet" crossorigin href="/assets/markdown-view-
|
|
66
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
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
|
@@ -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:
|
|
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": {
|
|
@@ -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
|
|
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 :
|
|
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,
|