@xopcai/xopc 0.0.241 → 0.0.242
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/{activity-store-CLnbVm9G.js → activity-store-MU5XrVv8.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DuBewmbW.js → agent-avatar-dicebear-B_Wc0wuL.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-DbdgX6AA.js → agent-defaults-settings-panel-Cf7U2aUi.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-BX3uRVm4.js → agents-Ce9oOnwE.js} +1 -1
- package/dist/gateway/static/root/assets/{api-DjBZe303.js → api-DLyc8BQp.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-D8evZyFQ.js → app-management-settings-panel-CACOOS-a.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-B-iul0RG.js → appearance-settings-DB5gEQhN.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-CoZd_cZu.js → apps-page-BaTFOCmR.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Cfk1lwBo.js → attachment-load-CYnYIyLr.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BTSGvaeS.js → automations-page-ChTflpmA.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-C8RRKT-a.js → automations-workspace-DK6EreCr.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-ChZyZK45.js → binary-plugins-BjbLfNwG.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-DCH9b2Ht.js → block-editor-DgAs5aJc.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-D1GPwIfx.js → browser-settings-page-CHStw5UW.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflow-inputs-jvfcgFG-.js → browser-workflow-inputs-DGQxD0vD.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-workflows-page-DrHW7XNi.js → browser-workflows-page-B9gfdd7L.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-CrXB1Q-l.js → capabilities-settings-panel-JGH6Kfkr.js} +6 -6
- package/dist/gateway/static/root/assets/{channels-settings-DWMSYaNZ.js → channels-settings-YkUaaWkY.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-status-swr-CC9MFway.js → channels-status-swr-TkU42f-W.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-DeeZrVbV.js → chat-terminal-dock-CWMPcnoN.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-DXTl1fNB.js → connectors-page-BI0FG3gA.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-expression-CiqQOeQ3.js → cron-expression-3h3rR0cf.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-CGAMGPfU.js → date-picker-Bz1sLBEx.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-CxWeUTsc.js → dependency-picker-p9DWR8uU.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-C3QmYO75.js → desktop-pet-D1TDB_gR.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-CAADkWYy.js → desktop-pet-settings-DWPZpoB7.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-FQXjDJ8P.js → extension-debug-page-BrRbK2rJ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BJE1D5Ji.js → extension-page-CD65czfS.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-5Ik2tNry.js → extension-settings-page-BRDDKhpi.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-cTj71t2a.js → gateway-config-api-CjbBsr5M.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-Bxe_R-JH.js → gateway-config-swr-HT7sLeO9.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-KXBUjNcx.js → gateway-settings-BQjmfYD4.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-DJG-I0wW.js → gateway-startup-retry-iBCtaAuT.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-C8cVzIcs.js → heartbeat-settings-BzZxLgrw.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-NdWtBda5.js → home-page--9fKq0mL.js} +1 -1
- package/dist/gateway/static/root/assets/{image-generation-api-Dc_ojQuj.js → image-generation-api-dj9TNEn2.js} +1 -1
- package/dist/gateway/static/root/assets/index-D499B1qS.css +2 -0
- package/dist/gateway/static/root/assets/{index-7i2P3312.js → index-J3FsIvTs.js} +8 -8
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-pOKl7blR.js → keyboard-shortcuts-settings-BEnuEPD3.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-C_j_od5f.js → local-app-workbench-page-FqG00zS1.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-Bi6wwKgm.js → local-apps-page-DXQtppWq.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-C5wr3_pc.js → locale-store-DVzTJSj2.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-D6PDZEVP.js → logs-page-c6CfZ8PA.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-DGlVizWi.js → management-settings-DIpBMWrA.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-CXP5zBx_.js → markdown-split-BFHyGwNF.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-view-D6LxlDxr.js → markdown-view-DR3yVwtV.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-BsENGLr2.js → media-plugins-BjjMxC5_.js} +1 -1
- package/dist/gateway/static/root/assets/{mobile-pairing-wizard-DcEz7qcX.js → mobile-pairing-wizard-CHnXZTwb.js} +1 -1
- package/dist/gateway/static/root/assets/models-hub-cache-DiXjKuuY.js +1 -0
- package/dist/gateway/static/root/assets/{notes-page-D2EqpDyo.js → notes-page-BbvtelJa.js} +1 -1
- package/dist/gateway/static/root/assets/notes-workbench-DIR37b-K.js +4 -0
- package/dist/gateway/static/root/assets/{oauth-api-C5NVcsKE.js → oauth-api-BB-VYJ5j.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-DMhf1rdz.js → product-open-page-CRm9Q66h.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-DDHi0Y4Q.js → project-detail-page-DHiLTiRW.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-CVMFKpmu.js → projects-page-God7NCcI.js} +1 -1
- package/dist/gateway/static/root/assets/{registry-api-FXdFaoWM.js → registry-api-DXsR8oGN.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-B74aErBY.js → remote-access-hub-YpF0-mx2.js} +1 -1
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-DoEfLjPB.js +5 -0
- package/dist/gateway/static/root/assets/{schema-form-BUzdHWx6.js → schema-form-BsqpbBDv.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-D2wmGNZE.js → sessions-page-CP8O1TxR.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DzdbK3j9.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-C0OBLqpu.js → settings-page-CE7ZcCTK.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-NpLQkFCh.js → setup-status-panel-CGlne9i0.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-BtbPYaYC.js → share-preview-page-Bn0qMX8V.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-rf8f1OGq.js → shares-settings-B7NeVl4g.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DDTmi4a7.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-CYk8pN97.js → skills-page-dRkeYh5P.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-DGjnz-NG.js → skills-page.utils--q8p7MAn.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-DmCRSvtd.js → system-settings-panel-C0ZCuCM4.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-6a2RdDl2.js → task-detail-page-yiMzii2b.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-DUko1ZnE.js → theme-store-Cth-eChE.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-Chfiba_x.js → tunnel-api-CC3jOB4n.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-W_P8Kiv4.js → use-autosave-PSV89QuQ.js} +1 -1
- package/dist/gateway/static/root/assets/user-context-page-Vtwg7fQc.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-BZD0j1jc.js → voice-api-key-field-DXWdJ8cR.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-BO6A8V3Z.js → voice-config-api-BDoeXgww.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-BfwEoOGL.js → work-discovery-overlay-BV_Jj5iD.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-X7Z5_lRX.js → workflow-run-setup-panel-DNHbWGPq.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-BklMzkg8.js → workflows-page-BkFIbMrz.js} +2 -2
- package/dist/gateway/static/root/index.html +11 -11
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +1 -0
- package/dist/src/agent/skills/installer.d.ts +1 -0
- package/dist/src/agent/skills/installer.js +9 -6
- package/dist/src/agent/tools/factory.d.ts +2 -0
- package/dist/src/agent/tools/factory.js +5 -1
- package/dist/src/config/schema.js +5 -3
- package/dist/src/extensions/install.js +1 -1
- package/dist/src/gateway/hono/routes/runtime-tools.js +7 -1
- package/dist/src/gateway/hono/routes/voice.js +1 -1
- package/dist/src/runtime-tools/archive.js +17 -3
- package/dist/src/runtime-tools/command.d.ts +1 -0
- package/dist/src/runtime-tools/command.js +29 -8
- package/dist/src/runtime-tools/environment.d.ts +1 -0
- package/dist/src/runtime-tools/environment.js +11 -16
- package/dist/src/runtime-tools/install-lock.d.ts +1 -1
- package/dist/src/runtime-tools/install-lock.js +34 -21
- package/dist/src/runtime-tools/manager.d.ts +1 -1
- package/dist/src/runtime-tools/manager.js +99 -64
- package/dist/src/runtime-tools/manifest-store.d.ts +2 -0
- package/dist/src/runtime-tools/manifest-store.js +29 -8
- package/dist/src/runtime-tools/paths.d.ts +2 -1
- package/dist/src/runtime-tools/paths.js +19 -8
- package/dist/src/runtime-tools/probe.d.ts +2 -0
- package/dist/src/runtime-tools/probe.js +13 -1
- package/dist/src/runtime-tools/prune.js +21 -7
- package/package.json +2 -2
- package/dist/gateway/static/root/assets/index-DTo3IcbW.css +0 -2
- package/dist/gateway/static/root/assets/models-hub-cache-Y7GUjxHx.js +0 -1
- package/dist/gateway/static/root/assets/notes-workbench-Bu0a83Oj.js +0 -4
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-Bv-akndY.js +0 -5
- package/dist/gateway/static/root/assets/settings-advanced-gate-CYCCUMEt.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BkvclZ_o.js +0 -1
- package/dist/gateway/static/root/assets/user-context-page-SeOHP6XO.js +0 -1
|
@@ -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-J3FsIvTs.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">
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
<link rel="modulepreload" crossorigin href="/assets/plus-Q2yW6OE7.js">
|
|
27
27
|
<link rel="modulepreload" crossorigin href="/assets/x-B_N4OPjy.js">
|
|
28
28
|
<link rel="modulepreload" crossorigin href="/assets/messages-_tYhRAHD.js">
|
|
29
|
-
<link rel="modulepreload" crossorigin href="/assets/locale-store-
|
|
29
|
+
<link rel="modulepreload" crossorigin href="/assets/locale-store-DVzTJSj2.js">
|
|
30
30
|
<link rel="modulepreload" crossorigin href="/assets/cn-JdwAhgNB.js">
|
|
31
31
|
<link rel="modulepreload" crossorigin href="/assets/schemas-zIBW3wiV.js">
|
|
32
32
|
<link rel="modulepreload" crossorigin href="/assets/product-delivery-dUJgmBQZ.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-DR3yVwtV.js">
|
|
35
35
|
<link rel="modulepreload" crossorigin href="/assets/dist-DqPZM2MH.js">
|
|
36
36
|
<link rel="modulepreload" crossorigin href="/assets/vendor-swr-BIWyz7Rc.js">
|
|
37
37
|
<link rel="modulepreload" crossorigin href="/assets/check-DUBLcKHA.js">
|
|
@@ -60,20 +60,20 @@
|
|
|
60
60
|
<link rel="modulepreload" crossorigin href="/assets/tool-activity-R8V9l6nk.js">
|
|
61
61
|
<link rel="modulepreload" crossorigin href="/assets/app-chrome-BeB4KgOf.js">
|
|
62
62
|
<link rel="modulepreload" crossorigin href="/assets/button-CSEbl4zT.js">
|
|
63
|
-
<link rel="modulepreload" crossorigin href="/assets/gateway-startup-retry-
|
|
64
|
-
<link rel="modulepreload" crossorigin href="/assets/registry-api-
|
|
63
|
+
<link rel="modulepreload" crossorigin href="/assets/gateway-startup-retry-iBCtaAuT.js">
|
|
64
|
+
<link rel="modulepreload" crossorigin href="/assets/registry-api-DXsR8oGN.js">
|
|
65
65
|
<link rel="modulepreload" crossorigin href="/assets/config-reload-event-Bjh2zoKp.js">
|
|
66
|
-
<link rel="modulepreload" crossorigin href="/assets/gateway-config-swr-
|
|
67
|
-
<link rel="modulepreload" crossorigin href="/assets/models-hub-cache-
|
|
66
|
+
<link rel="modulepreload" crossorigin href="/assets/gateway-config-swr-HT7sLeO9.js">
|
|
67
|
+
<link rel="modulepreload" crossorigin href="/assets/models-hub-cache-DiXjKuuY.js">
|
|
68
68
|
<link rel="modulepreload" crossorigin href="/assets/electron-env-DH5wF8X8.js">
|
|
69
|
-
<link rel="modulepreload" crossorigin href="/assets/oauth-api-
|
|
69
|
+
<link rel="modulepreload" crossorigin href="/assets/oauth-api-BB-VYJ5j.js">
|
|
70
70
|
<link rel="modulepreload" crossorigin href="/assets/form-field-width-DJw_jULe.js">
|
|
71
71
|
<link rel="modulepreload" crossorigin href="/assets/interaction-BmQogeqz.js">
|
|
72
72
|
<link rel="modulepreload" crossorigin href="/assets/is-masked-secret-DOkL5b_X.js">
|
|
73
|
-
<link rel="modulepreload" crossorigin href="/assets/activity-store-
|
|
74
|
-
<link rel="modulepreload" crossorigin href="/assets/theme-store-
|
|
73
|
+
<link rel="modulepreload" crossorigin href="/assets/activity-store-MU5XrVv8.js">
|
|
74
|
+
<link rel="modulepreload" crossorigin href="/assets/theme-store-Cth-eChE.js">
|
|
75
75
|
<link rel="stylesheet" crossorigin href="/assets/markdown-view-Y68dCxuc.css">
|
|
76
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
76
|
+
<link rel="stylesheet" crossorigin href="/assets/index-D499B1qS.css">
|
|
77
77
|
</head>
|
|
78
78
|
<body>
|
|
79
79
|
<div id="root"></div>
|
package/dist/package.js
CHANGED
|
@@ -241,6 +241,7 @@ var AgentManager = class {
|
|
|
241
241
|
getConfig: () => this.mergedConfig(),
|
|
242
242
|
getPrimaryModel: () => this.resolveModelStringToModel(this.pickDefaultModelRef()),
|
|
243
243
|
getMemoryManager: () => this.getCurrentWorkspaceRuntime().memoryManager,
|
|
244
|
+
getSkillManager: () => this.getCurrentWorkspaceRuntime().skillManager,
|
|
244
245
|
getSessionStore: this.config.getSessionStore,
|
|
245
246
|
gatewayClarify: this.config.gatewayClarify,
|
|
246
247
|
getAutomationService: this.config.getAutomationService,
|
|
@@ -13,6 +13,7 @@ export interface InstallContext {
|
|
|
13
13
|
installSpec: SkillInstallSpec;
|
|
14
14
|
timeoutMs: number;
|
|
15
15
|
}
|
|
16
|
+
export declare function skillEnvironmentId(skill: Pick<SkillEntry['skill'], 'name' | 'filePath'>, installSpec: SkillInstallSpec): string;
|
|
16
17
|
/**
|
|
17
18
|
* Check if a binary exists
|
|
18
19
|
*/
|
|
@@ -19,6 +19,13 @@ import { execFile } from "child_process";
|
|
|
19
19
|
init_logger();
|
|
20
20
|
const execFileAsync = promisify(execFile);
|
|
21
21
|
const log = createLogger("SkillInstaller");
|
|
22
|
+
function skillEnvironmentId(skill, installSpec) {
|
|
23
|
+
return createHash("sha256").update(JSON.stringify({
|
|
24
|
+
skill: skill.name,
|
|
25
|
+
path: skill.filePath,
|
|
26
|
+
installSpec
|
|
27
|
+
})).digest("hex").slice(0, 24);
|
|
28
|
+
}
|
|
22
29
|
/**
|
|
23
30
|
* Check if a binary exists
|
|
24
31
|
*/
|
|
@@ -202,11 +209,7 @@ async function installSkill(ctx) {
|
|
|
202
209
|
if (installSpec.kind === "go") {
|
|
203
210
|
if (!hasBinary("go")) return createInstallFailure({ message: "go not installed — install it explicitly from https://go.dev/doc/install" });
|
|
204
211
|
}
|
|
205
|
-
const environmentId =
|
|
206
|
-
skill: ctx.skillEntry.skill.name,
|
|
207
|
-
path: ctx.skillEntry.skill.filePath,
|
|
208
|
-
installSpec
|
|
209
|
-
})).digest("hex").slice(0, 24);
|
|
212
|
+
const environmentId = skillEnvironmentId(ctx.skillEntry.skill, installSpec);
|
|
210
213
|
const environmentDir = join(ctx.stateDir, "tools", "environments", "skills", environmentId);
|
|
211
214
|
await mkdir(environmentDir, { recursive: true });
|
|
212
215
|
if ([
|
|
@@ -285,4 +288,4 @@ async function installSkill(ctx) {
|
|
|
285
288
|
});
|
|
286
289
|
}
|
|
287
290
|
//#endregion
|
|
288
|
-
export { findInstallSpec, hasBinary, installSkill, resolveBrewExecutable };
|
|
291
|
+
export { findInstallSpec, hasBinary, installSkill, resolveBrewExecutable, skillEnvironmentId };
|
|
@@ -44,6 +44,8 @@ export interface ToolFactoryDeps {
|
|
|
44
44
|
getPrimaryModel?: () => Model<Api>;
|
|
45
45
|
/** Memory orchestration (prefetch/sync + external tools). */
|
|
46
46
|
getMemoryManager?: () => MemoryManager;
|
|
47
|
+
/** Skill runtime for the current workspace/session. */
|
|
48
|
+
getSkillManager?: () => SkillManager;
|
|
47
49
|
/** Session store for `session_search`. */
|
|
48
50
|
getSessionStore?: () => SessionStore;
|
|
49
51
|
/** When set (gateway webchat), enables the `clarify` tool. */
|
|
@@ -9,6 +9,7 @@ import { wrapToolsWithProtection } from "./executor.js";
|
|
|
9
9
|
import { buildRuntimeEnvironment } from "../../runtime-tools/environment.js";
|
|
10
10
|
import { createDefaultExternalToolGatewayTools } from "../external-tools/index.js";
|
|
11
11
|
import { createReadFileTool } from "./read.js";
|
|
12
|
+
import { skillEnvironmentId } from "../skills/installer.js";
|
|
12
13
|
import { createWriteFileTool } from "./write.js";
|
|
13
14
|
import { createListDirTool } from "./list-dir.js";
|
|
14
15
|
import { createPublishArtifactsTool } from "./publish-artifacts.js";
|
|
@@ -81,10 +82,13 @@ var AgentToolsFactory = class {
|
|
|
81
82
|
prepareRuntimeEnv = async (baseEnv) => {
|
|
82
83
|
const config = this.deps.getConfig?.();
|
|
83
84
|
if (!config) return baseEnv;
|
|
85
|
+
const indexing = this.deps.getSkillIndexingContext?.();
|
|
86
|
+
const skillEnvironmentIds = this.deps.getSkillManager?.()?.getEnabledSkillsForAgentSession(indexing).flatMap((skill) => (skill.metadata.install ?? []).map((installSpec) => skillEnvironmentId(skill, installSpec)));
|
|
84
87
|
return (await buildRuntimeEnvironment({
|
|
85
88
|
stateDir: resolveStateDir(),
|
|
86
89
|
config: config.runtimeTools,
|
|
87
|
-
baseEnv
|
|
90
|
+
baseEnv,
|
|
91
|
+
skillEnvironmentIds
|
|
88
92
|
})).env;
|
|
89
93
|
};
|
|
90
94
|
browserReadinessKey() {
|
|
@@ -8,6 +8,7 @@ import { init_public_url, validatePublicUrl } from "./public-url.js";
|
|
|
8
8
|
import { TelegramAccountConfigSchema, TelegramConfigSchema, TelegramGroupConfigSchema, TelegramTopicConfigSchema, init_config_schema } from "../../extensions/telegram/src/config-schema.js";
|
|
9
9
|
import { WeixinAccountConfigSchema, WeixinConfigSchema, init_config_schema as init_config_schema$1 } from "../../extensions/weixin/src/config-schema.js";
|
|
10
10
|
import { z } from "zod";
|
|
11
|
+
import semver from "semver";
|
|
11
12
|
//#region src/config/schema.ts
|
|
12
13
|
function getAgentDefaultModelRef(config) {
|
|
13
14
|
return config.agents.list.find((entry) => entry.enabled !== false && entry.id === config.agents.default)?.models?.chat?.primary ?? config.agents.defaults.models.chat.primary;
|
|
@@ -36,7 +37,7 @@ function parseModelRef(ref) {
|
|
|
36
37
|
model: trimmed.slice(idx + 1).trim()
|
|
37
38
|
};
|
|
38
39
|
}
|
|
39
|
-
var AgentModelRefSchema, AgentImageGenerationModelSchema, AgentModelsSchema, AgentsConfigSchema, BrowserCloudConfigSchema, BrowserExtensionConfigSchema, BrowserCloakConfigSchema, BrowserConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, SessionResetModeSchema, SessionResetConfigSchema, SessionResetByTypeSchema, SessionScopeSchema, SessionConfigSchema, ChannelsConfigSchema, SearchProviderEntrySchema, WebSearchConfigSchema, WebsiteBlocklistSchema, WebToolsConfigSchema, ToolsConfigSchema, RuntimePreferenceSchema, RuntimeProvisionSchema, LanguageRuntimeSchema, DEFAULT_RUNTIME_TOOLS_CONFIG, RuntimeToolsConfigSchema, GatewayAuthRateLimitSchema, GatewaySecuritySchema, GatewayTrustedProxySchema, GatewayAuthSchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayRemoteSchema, GatewayTlsSchema, GatewayModeSchema, HeartbeatConfigSchema, GatewayChannelConnectDeferModeSchema, TunnelConsentSchema, TunnelConfigSchema, WorkspaceImportConfigSchema, WorkspaceConfigSchema, GatewayBindModeSchema, GatewayWebchatConfigSchema, GatewayConfigSchema, ModelsDevConfigSchema, ModelCatalogConfigSchema, SttProviderConfigCatchallSchema, STTProviderConfigSchema, STTFallbackConfigSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, STTConfigSchema, TtsProviderConfigCatchallSchema, TTSProviderConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSEdgeConfigSchema, TTSSummarizationConfigSchema, TTSConfigSchema, VoiceRefinementConfigSchema, VoiceConfigSchema, MessagesConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProviderAuthConfigSchema, ProvidersConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, UpdateAutoConfigSchema, UpdateConfigSchema, CommandsConfigSchema, TuiConfigSchema, McpHttpUrlSchema, ConnectorSecretReferenceSchema, McpConfigScalarSchema, McpOAuthConfigSchema, McpServerSchema, McpConfigSchema, ConnectorsConfigSchema, ExperimentalConfigSchema, ConfigSchema;
|
|
40
|
+
var AgentModelRefSchema, AgentImageGenerationModelSchema, AgentModelsSchema, AgentsConfigSchema, BrowserCloudConfigSchema, BrowserExtensionConfigSchema, BrowserCloakConfigSchema, BrowserConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, SessionDmScopeSchema, SessionStorageConfigSchema, SessionResetModeSchema, SessionResetConfigSchema, SessionResetByTypeSchema, SessionScopeSchema, SessionConfigSchema, ChannelsConfigSchema, SearchProviderEntrySchema, WebSearchConfigSchema, WebsiteBlocklistSchema, WebToolsConfigSchema, ToolsConfigSchema, RuntimePreferenceSchema, RuntimeProvisionSchema, RuntimeVersionRequestSchema, LanguageRuntimeSchema, DEFAULT_RUNTIME_TOOLS_CONFIG, RuntimeToolsConfigSchema, GatewayAuthRateLimitSchema, GatewaySecuritySchema, GatewayTrustedProxySchema, GatewayAuthSchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayRemoteSchema, GatewayTlsSchema, GatewayModeSchema, HeartbeatConfigSchema, GatewayChannelConnectDeferModeSchema, TunnelConsentSchema, TunnelConfigSchema, WorkspaceImportConfigSchema, WorkspaceConfigSchema, GatewayBindModeSchema, GatewayWebchatConfigSchema, GatewayConfigSchema, ModelsDevConfigSchema, ModelCatalogConfigSchema, SttProviderConfigCatchallSchema, STTProviderConfigSchema, STTFallbackConfigSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, STTConfigSchema, TtsProviderConfigCatchallSchema, TTSProviderConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSEdgeConfigSchema, TTSSummarizationConfigSchema, TTSConfigSchema, VoiceRefinementConfigSchema, VoiceConfigSchema, MessagesConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProviderAuthConfigSchema, ProvidersConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, UpdateAutoConfigSchema, UpdateConfigSchema, CommandsConfigSchema, TuiConfigSchema, McpHttpUrlSchema, ConnectorSecretReferenceSchema, McpConfigScalarSchema, McpOAuthConfigSchema, McpServerSchema, McpConfigSchema, ConnectorsConfigSchema, ExperimentalConfigSchema, ConfigSchema;
|
|
40
41
|
var init_schema = __esmMin((() => {
|
|
41
42
|
init_agent_config();
|
|
42
43
|
init_cache_dir_policy();
|
|
@@ -240,9 +241,10 @@ var init_schema = __esmMin((() => {
|
|
|
240
241
|
"on-demand",
|
|
241
242
|
"disabled"
|
|
242
243
|
]);
|
|
244
|
+
RuntimeVersionRequestSchema = z.string().trim().min(1).max(128).refine((value) => !value.includes("/") && !value.includes("\\") && !value.includes("\0"), "Runtime version must not contain path separators").refine((value) => semver.validRange(value) !== null, "Runtime version must be a valid SemVer version or range");
|
|
243
245
|
LanguageRuntimeSchema = z.object({
|
|
244
246
|
enabled: z.boolean().default(true),
|
|
245
|
-
version:
|
|
247
|
+
version: RuntimeVersionRequestSchema.optional(),
|
|
246
248
|
preference: RuntimePreferenceSchema.default("managed-first"),
|
|
247
249
|
provision: RuntimeProvisionSchema.default("on-demand")
|
|
248
250
|
});
|
|
@@ -280,7 +282,7 @@ var init_schema = __esmMin((() => {
|
|
|
280
282
|
}),
|
|
281
283
|
uv: z.object({
|
|
282
284
|
enabled: z.boolean().default(true),
|
|
283
|
-
version:
|
|
285
|
+
version: RuntimeVersionRequestSchema.optional()
|
|
284
286
|
}).default({ enabled: true }),
|
|
285
287
|
download: z.object({
|
|
286
288
|
bundleDir: z.string().min(1).optional(),
|
|
@@ -8,8 +8,8 @@ import { collectExtensionPackageDependencyIssues } from "./package-contract.js";
|
|
|
8
8
|
import { dirname, isAbsolute, join, resolve, sep } from "path";
|
|
9
9
|
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
|
|
10
10
|
import { execFileSync } from "node:child_process";
|
|
11
|
-
import AdmZip from "adm-zip";
|
|
12
11
|
import semver from "semver";
|
|
12
|
+
import AdmZip from "adm-zip";
|
|
13
13
|
import { tmpdir } from "os";
|
|
14
14
|
//#region src/extensions/install.ts
|
|
15
15
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { init_paths_state, resolveStateDir } from "../../../config/paths-state.js";
|
|
2
2
|
import { RuntimeToolsConfigSchema, init_schema } from "../../../config/schema.js";
|
|
3
|
+
import { normalizeRuntimeVersionRequest } from "../../../runtime-tools/probe.js";
|
|
3
4
|
import { ManagedRuntimeManager } from "../../../runtime-tools/manager.js";
|
|
4
5
|
import { createGatewayRouteLogger } from "../lib/route-logger.js";
|
|
5
6
|
import { pruneRuntimeTools } from "../../../runtime-tools/prune.js";
|
|
@@ -82,6 +83,11 @@ function registerRuntimeToolsRoutes(authenticated, deps) {
|
|
|
82
83
|
}, 400);
|
|
83
84
|
const body = await readJson(c);
|
|
84
85
|
const version = typeof body.version === "string" && body.version.trim() ? body.version.trim() : void 0;
|
|
86
|
+
if (version && !normalizeRuntimeVersionRequest(version)) return c.json({
|
|
87
|
+
ok: false,
|
|
88
|
+
error: "invalid-version",
|
|
89
|
+
message: "Invalid runtime version"
|
|
90
|
+
}, 400);
|
|
85
91
|
return streamSSE(c, async (stream) => {
|
|
86
92
|
const manager = runtimeManager(service.currentConfig);
|
|
87
93
|
let writes = Promise.resolve();
|
|
@@ -97,7 +103,7 @@ function registerRuntimeToolsRoutes(authenticated, deps) {
|
|
|
97
103
|
};
|
|
98
104
|
manager.on("progress", onProgress);
|
|
99
105
|
try {
|
|
100
|
-
const resolved = action === "repair" ? await manager.repair(runtime) : await manager.install(runtime, version);
|
|
106
|
+
const resolved = action === "repair" ? await manager.repair(runtime, version) : await manager.install(runtime, version);
|
|
101
107
|
await writes;
|
|
102
108
|
await stream.writeSSE({
|
|
103
109
|
event: "result",
|
|
@@ -14,8 +14,8 @@ import "../../../voice/stt/index.js";
|
|
|
14
14
|
import { listSttProvidersForApi } from "../../../voice/stt/list-providers.js";
|
|
15
15
|
import "../../../voice/tts/index.js";
|
|
16
16
|
import { createGatewayRouteLogger } from "../lib/route-logger.js";
|
|
17
|
-
import { listTtsProvidersForApi } from "../../../voice/tts/list-providers.js";
|
|
18
17
|
import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
|
|
18
|
+
import { listTtsProvidersForApi } from "../../../voice/tts/list-providers.js";
|
|
19
19
|
//#region src/gateway/hono/routes/voice.ts
|
|
20
20
|
init_providers();
|
|
21
21
|
const log = createGatewayRouteLogger("Voice");
|
|
@@ -5,12 +5,15 @@ import { lstat, mkdir, readdir, readlink, rename, rm, stat } from "node:fs/promi
|
|
|
5
5
|
import AdmZip from "adm-zip";
|
|
6
6
|
//#region src/runtime-tools/archive.ts
|
|
7
7
|
const MAX_ARCHIVE_ENTRIES = 5e4;
|
|
8
|
+
const MAX_TAR_OUTPUT_BYTES = 16 * 1024 * 1024;
|
|
9
|
+
const MAX_EXTRACTED_BYTES = 2 * 1024 * 1024 * 1024;
|
|
8
10
|
function validateMemberPath(memberPath) {
|
|
9
11
|
const portablePath = memberPath.replaceAll("\\", "/");
|
|
10
12
|
const normalized = posix.normalize(portablePath);
|
|
11
13
|
if (!memberPath || isAbsolute(memberPath) || portablePath.startsWith("/") || normalized === ".." || normalized.startsWith("../")) throw new Error(`Unsafe archive member: ${memberPath}`);
|
|
12
14
|
}
|
|
13
15
|
async function validateExtractedTree(root, current = root) {
|
|
16
|
+
let totalBytes = 0;
|
|
14
17
|
for (const entry of await readdir(current)) {
|
|
15
18
|
const entryPath = join(current, entry);
|
|
16
19
|
const details = await lstat(entryPath);
|
|
@@ -19,8 +22,10 @@ async function validateExtractedTree(root, current = root) {
|
|
|
19
22
|
if (relativeTarget.split(/[\\/]/)[0] === ".." || isAbsolute(relativeTarget)) throw new Error(`Archive symlink escapes extraction root: ${entryPath}`);
|
|
20
23
|
continue;
|
|
21
24
|
}
|
|
22
|
-
|
|
25
|
+
totalBytes += details.isDirectory() ? await validateExtractedTree(root, entryPath) : details.size;
|
|
26
|
+
if (totalBytes > MAX_EXTRACTED_BYTES) throw new Error("Extracted archive exceeds size limit");
|
|
23
27
|
}
|
|
28
|
+
return totalBytes;
|
|
24
29
|
}
|
|
25
30
|
async function runTar(args) {
|
|
26
31
|
return await new Promise((resolvePromise, reject) => {
|
|
@@ -30,11 +35,19 @@ async function runTar(args) {
|
|
|
30
35
|
shell: false,
|
|
31
36
|
windowsHide: true
|
|
32
37
|
});
|
|
38
|
+
const append = (current, chunk) => {
|
|
39
|
+
if (Buffer.byteLength(current) + chunk.byteLength > MAX_TAR_OUTPUT_BYTES) {
|
|
40
|
+
child.kill("SIGKILL");
|
|
41
|
+
reject(/* @__PURE__ */ new Error("tar output exceeds size limit"));
|
|
42
|
+
return current;
|
|
43
|
+
}
|
|
44
|
+
return current + chunk.toString();
|
|
45
|
+
};
|
|
33
46
|
child.stdout?.on("data", (chunk) => {
|
|
34
|
-
stdout
|
|
47
|
+
stdout = append(stdout, chunk);
|
|
35
48
|
});
|
|
36
49
|
child.stderr?.on("data", (chunk) => {
|
|
37
|
-
stderr
|
|
50
|
+
stderr = append(stderr, chunk);
|
|
38
51
|
});
|
|
39
52
|
child.once("error", reject);
|
|
40
53
|
child.once("close", (code) => {
|
|
@@ -47,6 +60,7 @@ async function extractZip(archivePath, destination) {
|
|
|
47
60
|
const zip = new AdmZip(archivePath);
|
|
48
61
|
const entries = zip.getEntries();
|
|
49
62
|
if (entries.length > MAX_ARCHIVE_ENTRIES) throw new Error("Archive contains too many entries");
|
|
63
|
+
if (entries.reduce((total, entry) => total + entry.header.size, 0) > MAX_EXTRACTED_BYTES) throw new Error("Extracted archive exceeds size limit");
|
|
50
64
|
for (const entry of entries) validateMemberPath(entry.entryName);
|
|
51
65
|
zip.extractAllTo(destination, true, false);
|
|
52
66
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
//#region src/runtime-tools/command.ts
|
|
3
3
|
const DEFAULT_COMMAND_TIMEOUT_MS = 5e3;
|
|
4
|
+
const MAX_COMMAND_OUTPUT_BYTES = 1024 * 1024;
|
|
4
5
|
async function runRuntimeCommand(params) {
|
|
5
6
|
return await new Promise((resolve) => {
|
|
6
7
|
let stdout = "";
|
|
@@ -8,7 +9,10 @@ async function runRuntimeCommand(params) {
|
|
|
8
9
|
let settled = false;
|
|
9
10
|
let timedOut = false;
|
|
10
11
|
let aborted = false;
|
|
12
|
+
let outputTruncated = false;
|
|
13
|
+
let timeout;
|
|
11
14
|
const child = spawn(params.command, params.args, {
|
|
15
|
+
detached: process.platform !== "win32",
|
|
12
16
|
env: params.env,
|
|
13
17
|
shell: false,
|
|
14
18
|
windowsHide: process.platform === "win32",
|
|
@@ -18,36 +22,53 @@ async function runRuntimeCommand(params) {
|
|
|
18
22
|
"pipe"
|
|
19
23
|
]
|
|
20
24
|
});
|
|
25
|
+
const killChild = () => {
|
|
26
|
+
if (process.platform !== "win32" && child.pid) try {
|
|
27
|
+
process.kill(-child.pid, "SIGKILL");
|
|
28
|
+
return;
|
|
29
|
+
} catch {}
|
|
30
|
+
child.kill("SIGKILL");
|
|
31
|
+
};
|
|
21
32
|
const finish = (exitCode) => {
|
|
22
33
|
if (settled) return;
|
|
23
34
|
settled = true;
|
|
24
|
-
clearTimeout(timeout);
|
|
35
|
+
if (timeout) clearTimeout(timeout);
|
|
25
36
|
params.signal?.removeEventListener("abort", abort);
|
|
26
37
|
resolve({
|
|
27
|
-
ok: exitCode === 0 && !timedOut && !aborted,
|
|
38
|
+
ok: exitCode === 0 && !timedOut && !aborted && !outputTruncated,
|
|
28
39
|
stdout: stdout.trim(),
|
|
29
40
|
stderr: stderr.trim(),
|
|
30
41
|
exitCode,
|
|
31
42
|
timedOut,
|
|
32
|
-
aborted
|
|
43
|
+
aborted,
|
|
44
|
+
outputTruncated
|
|
33
45
|
});
|
|
34
46
|
};
|
|
35
47
|
const abort = () => {
|
|
36
48
|
aborted = true;
|
|
37
|
-
|
|
49
|
+
killChild();
|
|
38
50
|
finish(null);
|
|
39
51
|
};
|
|
52
|
+
const appendOutput = (current, chunk) => {
|
|
53
|
+
const remaining = MAX_COMMAND_OUTPUT_BYTES - Buffer.byteLength(current);
|
|
54
|
+
if (remaining <= 0 || chunk.byteLength > remaining) {
|
|
55
|
+
outputTruncated = true;
|
|
56
|
+
killChild();
|
|
57
|
+
return remaining > 0 ? current + chunk.subarray(0, remaining).toString() : current;
|
|
58
|
+
}
|
|
59
|
+
return current + chunk.toString();
|
|
60
|
+
};
|
|
40
61
|
child.stdout?.on("data", (chunk) => {
|
|
41
|
-
stdout
|
|
62
|
+
stdout = appendOutput(stdout, chunk);
|
|
42
63
|
});
|
|
43
64
|
child.stderr?.on("data", (chunk) => {
|
|
44
|
-
stderr
|
|
65
|
+
stderr = appendOutput(stderr, chunk);
|
|
45
66
|
});
|
|
46
67
|
child.once("error", () => finish(null));
|
|
47
68
|
child.once("close", finish);
|
|
48
|
-
|
|
69
|
+
timeout = setTimeout(() => {
|
|
49
70
|
timedOut = true;
|
|
50
|
-
|
|
71
|
+
killChild();
|
|
51
72
|
finish(null);
|
|
52
73
|
}, params.timeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS);
|
|
53
74
|
timeout.unref();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { applyPathPrepend } from "../infra/path-prepend.js";
|
|
1
|
+
import { applyPathPrepend, findPathKey, normalizePathPrepend } from "../infra/path-prepend.js";
|
|
2
2
|
import { ManagedRuntimeManager } from "./manager.js";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { access
|
|
3
|
+
import { delimiter, dirname, join } from "node:path";
|
|
4
|
+
import { access } from "node:fs/promises";
|
|
5
5
|
//#region src/runtime-tools/environment.ts
|
|
6
6
|
const POLLUTING_ENV_KEYS = [
|
|
7
7
|
"NODE_OPTIONS",
|
|
@@ -19,14 +19,8 @@ const POLLUTING_ENV_KEYS = [
|
|
|
19
19
|
"UV_CACHE_DIR",
|
|
20
20
|
"UV_PYTHON_INSTALL_MIRROR"
|
|
21
21
|
];
|
|
22
|
-
async function skillEnvironmentBinDirs(stateDir) {
|
|
22
|
+
async function skillEnvironmentBinDirs(stateDir, environmentIds) {
|
|
23
23
|
const root = join(stateDir, "tools", "environments", "skills");
|
|
24
|
-
let environmentIds;
|
|
25
|
-
try {
|
|
26
|
-
environmentIds = await readdir(root);
|
|
27
|
-
} catch {
|
|
28
|
-
return [];
|
|
29
|
-
}
|
|
30
24
|
const candidates = environmentIds.flatMap((id) => [join(root, id, "bin"), join(root, id, "node_modules", ".bin")]);
|
|
31
25
|
return (await Promise.all(candidates.map(async (candidate) => {
|
|
32
26
|
try {
|
|
@@ -37,6 +31,10 @@ async function skillEnvironmentBinDirs(stateDir) {
|
|
|
37
31
|
}
|
|
38
32
|
}))).filter((candidate) => candidate !== null);
|
|
39
33
|
}
|
|
34
|
+
function appendPathEntries(env, entries) {
|
|
35
|
+
const pathKey = findPathKey(env);
|
|
36
|
+
env[pathKey] = normalizePathPrepend([...(env[pathKey] ?? "").split(delimiter).filter(Boolean), ...entries]).join(delimiter);
|
|
37
|
+
}
|
|
40
38
|
async function buildRuntimeEnvironment(options) {
|
|
41
39
|
const env = { ...options.baseEnv };
|
|
42
40
|
for (const key of POLLUTING_ENV_KEYS) delete env[key];
|
|
@@ -60,12 +58,9 @@ async function buildRuntimeEnvironment(options) {
|
|
|
60
58
|
}
|
|
61
59
|
}))).filter((item) => item !== null);
|
|
62
60
|
const managedBinDirs = resolved.filter((item) => item.source === "managed").map((item) => dirname(item.executable));
|
|
63
|
-
const skillBinDirs = await skillEnvironmentBinDirs(options.stateDir);
|
|
64
|
-
applyPathPrepend(env, [
|
|
65
|
-
|
|
66
|
-
...skillBinDirs,
|
|
67
|
-
...options.extraBinDirs ?? []
|
|
68
|
-
]);
|
|
61
|
+
const skillBinDirs = await skillEnvironmentBinDirs(options.stateDir, options.skillEnvironmentIds ?? []);
|
|
62
|
+
applyPathPrepend(env, [...managedBinDirs, ...options.extraBinDirs ?? []]);
|
|
63
|
+
appendPathEntries(env, skillBinDirs);
|
|
69
64
|
if (resolved.some((item) => item.runtime === "python")) {
|
|
70
65
|
env.PYTHONNOUSERSITE = "1";
|
|
71
66
|
env.PIP_REQUIRE_VIRTUALENV = "1";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function withInstallLock<T>(path: string, metadata: Record<string, unknown>, fn: () => Promise<T
|
|
1
|
+
export declare function withInstallLock<T>(path: string, metadata: Record<string, unknown>, fn: () => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
@@ -7,38 +7,51 @@ function isProcessAlive(pid) {
|
|
|
7
7
|
try {
|
|
8
8
|
process.kill(pid, 0);
|
|
9
9
|
return true;
|
|
10
|
-
} catch {
|
|
11
|
-
return
|
|
10
|
+
} catch (error) {
|
|
11
|
+
return error.code === "EPERM";
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
async function staleLock(path) {
|
|
15
15
|
try {
|
|
16
16
|
const value = JSON.parse(await readFile(path, "utf8"));
|
|
17
|
-
|
|
18
|
-
const createdAt = typeof value.createdAt === "number" ? value.createdAt : 0;
|
|
19
|
-
return !isProcessAlive(pid) && Date.now() - createdAt > LOCK_STALE_MS;
|
|
17
|
+
return !isProcessAlive(typeof value.pid === "number" ? value.pid : 0);
|
|
20
18
|
} catch {
|
|
21
19
|
return true;
|
|
22
20
|
}
|
|
23
21
|
}
|
|
24
|
-
async function withInstallLock(path, metadata, fn) {
|
|
22
|
+
async function withInstallLock(path, metadata, fn, signal) {
|
|
25
23
|
await mkdir(dirname(path), { recursive: true });
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
const waitStartedAt = Date.now();
|
|
25
|
+
while (true) {
|
|
26
|
+
if (signal?.aborted) throw signal.reason ?? /* @__PURE__ */ new Error("Runtime installation was aborted");
|
|
27
|
+
try {
|
|
28
|
+
const handle = await open(path, "wx", 384);
|
|
29
|
+
await handle.writeFile(JSON.stringify({
|
|
30
|
+
pid: process.pid,
|
|
31
|
+
createdAt: Date.now(),
|
|
32
|
+
...metadata
|
|
33
|
+
}));
|
|
34
|
+
await handle.close();
|
|
35
|
+
break;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error.code !== "EEXIST") throw error;
|
|
38
|
+
if (await staleLock(path)) {
|
|
39
|
+
await unlink(path).catch(() => void 0);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (Date.now() - waitStartedAt > LOCK_STALE_MS) throw new Error(`Timed out waiting for runtime installation lock: ${path}`);
|
|
43
|
+
await new Promise((resolve, reject) => {
|
|
44
|
+
const timeout = setTimeout(() => {
|
|
45
|
+
signal?.removeEventListener("abort", abort);
|
|
46
|
+
resolve();
|
|
47
|
+
}, LOCK_WAIT_MS);
|
|
48
|
+
const abort = () => {
|
|
49
|
+
clearTimeout(timeout);
|
|
50
|
+
reject(signal?.reason ?? /* @__PURE__ */ new Error("Runtime installation was aborted"));
|
|
51
|
+
};
|
|
52
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
53
|
+
});
|
|
40
54
|
}
|
|
41
|
-
await new Promise((resolve) => setTimeout(resolve, LOCK_WAIT_MS));
|
|
42
55
|
}
|
|
43
56
|
try {
|
|
44
57
|
return await fn();
|
|
@@ -15,6 +15,6 @@ export declare class ManagedRuntimeManager extends EventEmitter {
|
|
|
15
15
|
private uvEnvironment;
|
|
16
16
|
status(runtime: RuntimeKind): Promise<RuntimeStatus>;
|
|
17
17
|
statusAll(): Promise<RuntimeStatus[]>;
|
|
18
|
-
repair(runtime: RuntimeKind): Promise<ResolvedRuntime>;
|
|
18
|
+
repair(runtime: RuntimeKind, requestedVersion?: string): Promise<ResolvedRuntime>;
|
|
19
19
|
private progress;
|
|
20
20
|
}
|