@mininglamp-oss/octo-runtime 1.1.0 → 1.1.2
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/README.md +4 -2
- package/apps/cli/README.md +3 -1
- package/apps/cli/dist/build-info.json +2 -2
- package/apps/cli/dist/extras.d.ts +4 -2
- package/apps/cli/dist/extras.js +20 -21
- package/apps/cli/dist/help.js +3 -0
- package/apps/cli/dist/logs.d.ts +10 -0
- package/apps/cli/dist/logs.js +186 -0
- package/apps/cli/dist/main.d.ts +1 -0
- package/apps/cli/dist/main.js +94 -19
- package/apps/cli/dist/{default_adapters.json → manifest.json} +10 -0
- package/apps/cli/dist/module-manifest.d.ts +3 -0
- package/apps/cli/dist/module-manifest.js +11 -0
- package/apps/cli/dist/openclaw.js +30 -6
- package/apps/cli/dist/output.js +3 -0
- package/apps/cli/dist/playboard.js +10 -8
- package/apps/cli/dist/status-output.d.ts +10 -0
- package/apps/cli/dist/status-output.js +65 -0
- package/apps/cli/dist/worker.d.ts +1 -0
- package/apps/cli/dist/worker.js +18 -0
- package/dist/public/host.d.ts +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-acp-client/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-acp/package.json +4 -4
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-antigravity/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-claude-code/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-codebuddy/package.json +4 -4
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-codex/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/adapter.d.ts +54 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/adapter.js +399 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/client.d.ts +14 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/client.js +156 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/index.d.ts +29 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/index.js +273 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/interactions.d.ts +27 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/interactions.js +161 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/package.json +17 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-hermes/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-kimi-code/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-mcode/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/compatibility.d.ts +24 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/compatibility.js +181 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/gateway.d.ts +9 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/gateway.js +24 -8
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/index.js +229 -225
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-opencode/package.json +4 -4
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-qodercli/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-qoderclicn/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/approval.d.ts +4 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/approval.js +5 -6
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/index.d.ts +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/index.js +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/module-manifest.d.ts +33 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/module-manifest.js +118 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/runtime-log-worker.js +7 -5
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/runtime-log.d.ts +3 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/runtime-log.js +45 -10
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/service-status.d.ts +11 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/service-status.js +70 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/package.json +5 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-zcode-gui/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/build-info.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/extras.d.ts +4 -2
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/extras.js +20 -21
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/help.js +3 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/logs.d.ts +10 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/logs.js +186 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/main.d.ts +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/main.js +94 -19
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/{default_adapters.json → manifest.json} +10 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/module-manifest.d.ts +3 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/module-manifest.js +11 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/openclaw.js +30 -6
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/output.js +3 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/playboard.js +10 -8
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/status-output.d.ts +10 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/status-output.js +65 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/worker.d.ts +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/worker.js +18 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/package.json +23 -9
- package/node_modules/@mininglamp-oss/octo-runtime-cross-service/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-executor-core/dist/model-input.d.ts +1 -1
- package/node_modules/@mininglamp-oss/octo-runtime-executor-core/dist/model-input.js +13 -9
- package/node_modules/@mininglamp-oss/octo-runtime-executor-core/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/heartbeat.d.ts +16 -0
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/heartbeat.js +59 -0
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/invocation-manifest.d.ts +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/invocation-manifest.js +4 -1
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/manifest-adapters.d.ts +6 -0
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/manifest-adapters.js +88 -0
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/module-specifier.d.ts +1 -2
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/module-specifier.js +2 -9
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/process.d.ts +7 -2
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/process.js +138 -9
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/runner.js +3 -92
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/serve.js +36 -12
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/server.d.ts +4 -1
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/server.js +14 -6
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/service.js +2 -1
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/supervisor.d.ts +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/supervisor.js +57 -34
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/package.json +8 -16
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/config-schema.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/application/im-channel.js +18 -18
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/contracts.d.ts +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/execution/dispatcher.js +24 -0
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/contexts.js +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/mentions.d.ts +5 -2
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/mentions.js +19 -5
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/normalize.js +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/package.json +6 -6
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-wecom/config-schema.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-wecom/package.json +5 -5
- package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/config-schema.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/dist/index.js +1 -1
- package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/dist/store.d.ts +4 -1
- package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/dist/store.js +54 -4
- package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/dist/extra-config.d.ts +8 -1
- package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/dist/extra-config.js +27 -12
- package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/dist/extra-service.js +39 -2
- package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/dist/index.d.ts +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/package.json +4 -4
- package/node_modules/@mininglamp-oss/octo-runtime-protocol/package.json +1 -1
- package/node_modules/import-meta-resolve/index.d.ts +19 -0
- package/node_modules/import-meta-resolve/index.d.ts.map +1 -0
- package/node_modules/import-meta-resolve/index.js +47 -0
- package/node_modules/import-meta-resolve/lib/errors.d.ts +24 -0
- package/node_modules/import-meta-resolve/lib/errors.d.ts.map +1 -0
- package/node_modules/import-meta-resolve/lib/errors.js +504 -0
- package/node_modules/import-meta-resolve/lib/get-format.d.ts +13 -0
- package/node_modules/import-meta-resolve/lib/get-format.d.ts.map +1 -0
- package/node_modules/import-meta-resolve/lib/get-format.js +159 -0
- package/node_modules/import-meta-resolve/lib/package-json-reader.d.ts +31 -0
- package/node_modules/import-meta-resolve/lib/package-json-reader.d.ts.map +1 -0
- package/node_modules/import-meta-resolve/lib/package-json-reader.js +177 -0
- package/node_modules/import-meta-resolve/lib/resolve.d.ts +29 -0
- package/node_modules/import-meta-resolve/lib/resolve.d.ts.map +1 -0
- package/node_modules/import-meta-resolve/lib/resolve.js +1301 -0
- package/node_modules/import-meta-resolve/lib/utils.d.ts +6 -0
- package/node_modules/import-meta-resolve/lib/utils.d.ts.map +1 -0
- package/node_modules/import-meta-resolve/lib/utils.js +47 -0
- package/node_modules/import-meta-resolve/license +74 -0
- package/node_modules/import-meta-resolve/package.json +78 -0
- package/node_modules/import-meta-resolve/readme.md +252 -0
- package/package.json +30 -26
- package/packages/octo-runtime-extra-channel-gateway/config-schema.json +2 -2
- package/packages/octo-runtime-extra-channel-wecom/config-schema.json +2 -2
- package/packages/octo-runtime-extra-webui/config-schema.json +2 -2
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// CLI 自有执行 worker。顶层 Kernel 仍由 CLI 调用进程创建;SDK 原生入口不使用此装配。
|
|
2
|
+
import { loadManifestAdapters } from "@mininglamp-oss/octo-runtime-executor-kernel/manifest-adapters";
|
|
3
|
+
import { serveWorker } from "@mininglamp-oss/octo-runtime-executor-kernel";
|
|
4
|
+
import { readExtraDirectory } from "@mininglamp-oss/octo-runtime-host-sdk";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
const adapters = await loadManifestAdapters();
|
|
7
|
+
// 旧显式清单允许省略 type;以所选实例真实类型判断,不猜包名,也不在父进程重复实例化。
|
|
8
|
+
if (adapters.some((adapter) => adapter.metadata.type === "openclaw")) {
|
|
9
|
+
const profileRoot = process.env.OCTO_RUNTIME_CLI_PROFILE_ROOT;
|
|
10
|
+
if (!profileRoot)
|
|
11
|
+
throw new Error("CLI_PROFILE_ROOT_REQUIRED");
|
|
12
|
+
const { initializeCliOpenClaw, syncCliOpenClawToolEnvironment } = await import("./openclaw.js");
|
|
13
|
+
await initializeCliOpenClaw(profileRoot);
|
|
14
|
+
if (process.env.OCTO_RUNTIME_CLI_SYNC_OPENCLAW_TOOLS === "1")
|
|
15
|
+
await syncCliOpenClawToolEnvironment(profileRoot, await readExtraDirectory(join(dirname(profileRoot), "extras")));
|
|
16
|
+
}
|
|
17
|
+
// 产品连接准备完成后才建立既有 list/probe 握手;所有实例仅交给唯一 Core 注册一次。
|
|
18
|
+
serveWorker(adapters);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mininglamp-oss/octo-runtime-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,14 +8,28 @@
|
|
|
8
8
|
},
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.
|
|
11
|
+
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.2",
|
|
12
12
|
"json5": "2.2.3",
|
|
13
|
-
"@mininglamp-oss/octo-runtime-extra-channel-gateway": "1.1.
|
|
14
|
-
"@mininglamp-oss/octo-runtime-host-sdk": "1.1.
|
|
15
|
-
"@mininglamp-oss/octo-runtime-adapter-openclaw": "1.1.
|
|
16
|
-
"@mininglamp-oss/octo-runtime-cross-service": "1.1.
|
|
17
|
-
"@mininglamp-oss/octo-runtime-protocol": "1.1.
|
|
18
|
-
"@mininglamp-oss/octo-runtime-executor-kernel": "1.1.
|
|
19
|
-
"@mininglamp-oss/octo-runtime-executor-core": "1.1.
|
|
13
|
+
"@mininglamp-oss/octo-runtime-extra-channel-gateway": "1.1.2",
|
|
14
|
+
"@mininglamp-oss/octo-runtime-host-sdk": "1.1.2",
|
|
15
|
+
"@mininglamp-oss/octo-runtime-adapter-openclaw": "1.1.2",
|
|
16
|
+
"@mininglamp-oss/octo-runtime-cross-service": "1.1.2",
|
|
17
|
+
"@mininglamp-oss/octo-runtime-protocol": "1.1.2",
|
|
18
|
+
"@mininglamp-oss/octo-runtime-executor-kernel": "1.1.2",
|
|
19
|
+
"@mininglamp-oss/octo-runtime-executor-core": "1.1.2",
|
|
20
|
+
"@mininglamp-oss/octo-runtime-adapter-antigravity": "1.1.2",
|
|
21
|
+
"@mininglamp-oss/octo-runtime-adapter-claude-code": "1.1.2",
|
|
22
|
+
"@mininglamp-oss/octo-runtime-adapter-codebuddy": "1.1.2",
|
|
23
|
+
"@mininglamp-oss/octo-runtime-adapter-codex": "1.1.2",
|
|
24
|
+
"@mininglamp-oss/octo-runtime-adapter-hermes": "1.1.2",
|
|
25
|
+
"@mininglamp-oss/octo-runtime-adapter-grok-build": "1.1.2",
|
|
26
|
+
"@mininglamp-oss/octo-runtime-adapter-kimi-code": "1.1.2",
|
|
27
|
+
"@mininglamp-oss/octo-runtime-adapter-mcode": "1.1.2",
|
|
28
|
+
"@mininglamp-oss/octo-runtime-adapter-opencode": "1.1.2",
|
|
29
|
+
"@mininglamp-oss/octo-runtime-adapter-qodercli": "1.1.2",
|
|
30
|
+
"@mininglamp-oss/octo-runtime-adapter-qoderclicn": "1.1.2",
|
|
31
|
+
"@mininglamp-oss/octo-runtime-adapter-zcode-gui": "1.1.2",
|
|
32
|
+
"@mininglamp-oss/octo-runtime-extra-channel-wecom": "1.1.2",
|
|
33
|
+
"@mininglamp-oss/octo-runtime-extra-webui": "1.1.2"
|
|
20
34
|
}
|
|
21
35
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mininglamp-oss/octo-runtime-cross-service",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Native user-service lifecycle backends for Octo Runtime",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"README.md"
|
|
12
12
|
],
|
|
13
13
|
"engines": {
|
|
14
|
-
"node": "
|
|
14
|
+
"node": "^24.0.0 || ^26.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {}
|
|
17
17
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ContextEnvelope, InvokeRequest } from "@mininglamp-oss/octo-runtime-protocol";
|
|
2
|
-
/**
|
|
2
|
+
/** 仅渲染允许进入模型的本轮业务 Context;Markdown 指引保留原文,排序后的 payload 用 CDATA 包裹,不修改输入。 */
|
|
3
3
|
export declare function renderModelContexts(context: ContextEnvelope): string;
|
|
4
4
|
/**
|
|
5
5
|
* Core 冻结原请求后、派发 Adapter 前调用一次;接入方不应预先渲染而造成 Context 重复。
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
const MODEL_CONTEXT_PATTERNS = [/^extra\.[^/]+\/[^/]+$/, /^octo\.content\/(inline|references)$/];
|
|
2
|
-
/**
|
|
2
|
+
/** 仅渲染允许进入模型的本轮业务 Context;Markdown 指引保留原文,排序后的 payload 用 CDATA 包裹,不修改输入。 */
|
|
3
3
|
export function renderModelContexts(context) {
|
|
4
4
|
const items = context.items.filter((item) => MODEL_CONTEXT_PATTERNS.some((pattern) => pattern.test(item.namespace + "/" + item.name)));
|
|
5
5
|
if (!items.length)
|
|
6
6
|
return "";
|
|
7
7
|
return [
|
|
8
|
-
"
|
|
8
|
+
"<!-- Context information begins: the following is the current context -->",
|
|
9
9
|
"<contexts>",
|
|
10
|
-
...items.map((item) =>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
...items.map((item) => {
|
|
11
|
+
// 拆分 CDATA 终止符为相邻区段,避免材料中的标记提前结束数据边界;不解析内部内容。
|
|
12
|
+
const data = JSON.stringify(sorted(item.payload)).replaceAll("]]>", "]]]]><![CDATA[>");
|
|
13
|
+
return [
|
|
14
|
+
` <context-item namespace="${item.namespace}" name="${item.name}">`,
|
|
15
|
+
...(item.guidance ? [` <guidence>${item.guidance}</guidence>`] : []),
|
|
16
|
+
` <data><![CDATA[${data}]]></data>`,
|
|
17
|
+
" </context-item>"
|
|
18
|
+
].join("\n");
|
|
19
|
+
}),
|
|
16
20
|
"</contexts>",
|
|
17
|
-
"
|
|
21
|
+
"<!-- Context information ends -->"
|
|
18
22
|
].join("\n");
|
|
19
23
|
}
|
|
20
24
|
function sorted(value) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mininglamp-oss/octo-runtime-executor-core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.
|
|
9
|
-
"@mininglamp-oss/octo-runtime-protocol": "1.1.
|
|
8
|
+
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.2",
|
|
9
|
+
"@mininglamp-oss/octo-runtime-protocol": "1.1.2"
|
|
10
10
|
},
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"files": [
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** A paused supervisor cannot establish worker failure; require a fresh probe after a gap. */
|
|
2
|
+
export declare class WorkerHeartbeat {
|
|
3
|
+
#private;
|
|
4
|
+
private readonly wallNow;
|
|
5
|
+
private readonly monotonicNow;
|
|
6
|
+
activeMs: number;
|
|
7
|
+
healthyMs: number;
|
|
8
|
+
constructor(wallNow?: () => number, monotonicNow?: () => number);
|
|
9
|
+
tick(): {
|
|
10
|
+
type: "ping";
|
|
11
|
+
id: number;
|
|
12
|
+
} | {
|
|
13
|
+
type: "waiting" | "expired";
|
|
14
|
+
};
|
|
15
|
+
pong(id: unknown): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
/** A paused supervisor cannot establish worker failure; require a fresh probe after a gap. */
|
|
3
|
+
export class WorkerHeartbeat {
|
|
4
|
+
wallNow;
|
|
5
|
+
monotonicNow;
|
|
6
|
+
#wall;
|
|
7
|
+
#mono;
|
|
8
|
+
#sequence = 0;
|
|
9
|
+
#pending;
|
|
10
|
+
#answered = false;
|
|
11
|
+
activeMs = 0;
|
|
12
|
+
healthyMs = 0;
|
|
13
|
+
constructor(wallNow = Date.now, monotonicNow = () => performance.now()) {
|
|
14
|
+
this.wallNow = wallNow;
|
|
15
|
+
this.monotonicNow = monotonicNow;
|
|
16
|
+
this.#wall = wallNow();
|
|
17
|
+
this.#mono = monotonicNow();
|
|
18
|
+
}
|
|
19
|
+
#gap(wall, mono) {
|
|
20
|
+
return (wall < this.#wall ||
|
|
21
|
+
mono < this.#mono ||
|
|
22
|
+
wall - this.#wall >= 5000 ||
|
|
23
|
+
mono - this.#mono >= 5000);
|
|
24
|
+
}
|
|
25
|
+
tick() {
|
|
26
|
+
const wall = this.wallNow(), mono = this.monotonicNow();
|
|
27
|
+
// Either clock can reveal suspend or a blocked supervisor; discard pre-gap liveness evidence.
|
|
28
|
+
if (this.#gap(wall, mono)) {
|
|
29
|
+
this.#pending = undefined;
|
|
30
|
+
this.#answered = false;
|
|
31
|
+
this.healthyMs = 0;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const elapsed = mono - this.#mono;
|
|
35
|
+
this.activeMs += elapsed;
|
|
36
|
+
if (this.#answered)
|
|
37
|
+
this.healthyMs += elapsed;
|
|
38
|
+
}
|
|
39
|
+
this.#wall = wall;
|
|
40
|
+
this.#mono = mono;
|
|
41
|
+
this.#answered = false;
|
|
42
|
+
// Ordinary timer ticks never renew an unanswered probe's fixed deadline.
|
|
43
|
+
if (this.#pending)
|
|
44
|
+
return { type: mono >= this.#pending.deadline ? "expired" : "waiting" };
|
|
45
|
+
this.#pending = { id: ++this.#sequence, deadline: mono + 5000 };
|
|
46
|
+
return { type: "ping", id: this.#sequence };
|
|
47
|
+
}
|
|
48
|
+
pong(id) {
|
|
49
|
+
const wall = this.wallNow(), mono = this.monotonicNow();
|
|
50
|
+
// A queued or stale pong cannot establish post-resume health or extend the new deadline.
|
|
51
|
+
if (this.#gap(wall, mono) ||
|
|
52
|
+
!this.#pending ||
|
|
53
|
+
id !== this.#pending.id ||
|
|
54
|
+
mono >= this.#pending.deadline)
|
|
55
|
+
return;
|
|
56
|
+
this.#pending = undefined;
|
|
57
|
+
this.#answered = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/invocation-manifest.d.ts
CHANGED
|
@@ -31,4 +31,5 @@ export declare class InvocationManifest {
|
|
|
31
31
|
* 无法验证身份时保留清单并报告 unsupported_identity;worker 已消失不证明 Windows 后代已清空。
|
|
32
32
|
*/
|
|
33
33
|
export declare function reapOrphanedInvocationManifest(path: string): Promise<OrphanReapResult>;
|
|
34
|
+
/** 查询系统启动时间以区分 PID 复用;失败时不返回可用于回收的身份,绝不以 PID 本身兜底。 */
|
|
34
35
|
export declare function processStartIdentity(pid: number): Promise<string | undefined>;
|
package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/invocation-manifest.js
CHANGED
|
@@ -110,6 +110,7 @@ export async function reapOrphanedInvocationManifest(path) {
|
|
|
110
110
|
await rm(path, { force: true });
|
|
111
111
|
return { found: true, reaped: true, pid: host.pid };
|
|
112
112
|
}
|
|
113
|
+
/** 查询系统启动时间以区分 PID 复用;失败时不返回可用于回收的身份,绝不以 PID 本身兜底。 */
|
|
113
114
|
export async function processStartIdentity(pid) {
|
|
114
115
|
if (!Number.isSafeInteger(pid) || pid < 1)
|
|
115
116
|
return undefined;
|
|
@@ -141,7 +142,9 @@ export async function processStartIdentity(pid) {
|
|
|
141
142
|
"-NoProfile",
|
|
142
143
|
"-NonInteractive",
|
|
143
144
|
"-Command",
|
|
144
|
-
|
|
145
|
+
// 直接调用系统进程对象,避免 Get-Process 的命令发现/模块自动加载占用身份查询预算。
|
|
146
|
+
// 保持 UTC ticks 身份格式;不增加超时,也不缓存可能已经复用的 PID。
|
|
147
|
+
`$PSModuleAutoLoadingPreference='None'; $target=[System.Diagnostics.Process]::GetProcessById(${pid}); try { [Console]::Out.Write($target.StartTime.ToUniversalTime().Ticks.ToString([Globalization.CultureInfo]::InvariantCulture)) } finally { $target.Dispose() }`
|
|
145
148
|
], { encoding: "utf8", timeout: 10_000, windowsHide: true }, (error, stdout) => {
|
|
146
149
|
const value = stdout.trim();
|
|
147
150
|
resolve(error || !/^\d+$/.test(value) ? undefined : `windows:${value}`);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { parseModuleManifest, readModuleManifest, resolveModuleSpecifier } from "@mininglamp-oss/octo-runtime-adapter-sdk/module-manifest";
|
|
2
|
+
/**
|
|
3
|
+
* 仅供清单驱动的 worker 在自身进程装配:只实例化所选模块,返回后由入口注册及 serveWorker。
|
|
4
|
+
* CLI 可在注册前用实际 metadata 做产品准备;SDK 原生 import 入口不经过此文件加载边界。
|
|
5
|
+
*/
|
|
6
|
+
export async function loadManifestAdapters() {
|
|
7
|
+
const index = process.argv.indexOf("--manifest");
|
|
8
|
+
const entries = process.argv.includes("--adapters-from-ipc")
|
|
9
|
+
? await receiveAdapters()
|
|
10
|
+
: index >= 0 && process.argv[index + 1]
|
|
11
|
+
? (await readModuleManifest(process.argv[index + 1], { legacy: true })).adapters
|
|
12
|
+
: (() => {
|
|
13
|
+
throw new Error("usage: octo-runtime-executor-kernel --manifest <file>");
|
|
14
|
+
})();
|
|
15
|
+
const adapters = [];
|
|
16
|
+
for (const entry of entries) {
|
|
17
|
+
const specifier = resolveModuleSpecifier(entry.module, entry.sourceManifest);
|
|
18
|
+
const loaded = await import(specifier);
|
|
19
|
+
const exports = asRecord(loaded, `adapter module ${entry.module}`);
|
|
20
|
+
const exported = exports[entry.export];
|
|
21
|
+
if (exported === undefined)
|
|
22
|
+
throw new Error(`missing export ${entry.export} from ${entry.module}`);
|
|
23
|
+
// 动态模块先校验工厂与 Adapter 形状,再交给唯一 Core 注册;不提前探测未选模块。
|
|
24
|
+
const instance = entry.factory ? callFactory(exported, entry) : exported;
|
|
25
|
+
if (!isHostedAdapter(instance))
|
|
26
|
+
throw new TypeError(`${entry.module}#${entry.export} is not an Octo Runtime adapter`);
|
|
27
|
+
if (entry.type && instance.metadata.type !== entry.type)
|
|
28
|
+
throw new Error(`manifest type ${entry.type} does not match adapter ${instance.metadata.type}`);
|
|
29
|
+
adapters.push(instance);
|
|
30
|
+
}
|
|
31
|
+
return adapters;
|
|
32
|
+
}
|
|
33
|
+
/** 内部启动消息只携带 JSON 模块声明,不传函数/实例;就绪仍沿用既有 list/probe 握手。 */
|
|
34
|
+
function receiveAdapters() {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const cleanup = () => {
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
process.off("message", onMessage);
|
|
39
|
+
process.off("disconnect", onDisconnect);
|
|
40
|
+
};
|
|
41
|
+
const onDisconnect = () => {
|
|
42
|
+
cleanup();
|
|
43
|
+
reject(new Error("Adapter initialization channel disconnected"));
|
|
44
|
+
};
|
|
45
|
+
const onMessage = (message) => {
|
|
46
|
+
if (!isRecord(message) || message.type !== "kernel.adapters")
|
|
47
|
+
return;
|
|
48
|
+
cleanup();
|
|
49
|
+
try {
|
|
50
|
+
// 快照已经解析为绝对位置;这个路径只用于结构校验,不读取或生成任何文件。
|
|
51
|
+
resolve(parseModuleManifest({ version: 1, adapters: message.adapters, extras: [] }, process.cwd(), { legacy: true }).adapters);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
reject(error instanceof Error ? error : new Error("Invalid Adapter initialization"));
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const timer = setTimeout(() => {
|
|
58
|
+
cleanup();
|
|
59
|
+
reject(new Error("Adapter initialization timed out"));
|
|
60
|
+
}, 15000);
|
|
61
|
+
process.on("message", onMessage);
|
|
62
|
+
process.once("disconnect", onDisconnect);
|
|
63
|
+
if (!process.connected)
|
|
64
|
+
onDisconnect();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function callFactory(value, entry) {
|
|
68
|
+
if (typeof value !== "function")
|
|
69
|
+
throw new TypeError(`${entry.module}#${entry.export} is marked as a factory but is not callable`);
|
|
70
|
+
return value(entry.options);
|
|
71
|
+
}
|
|
72
|
+
function isHostedAdapter(value) {
|
|
73
|
+
if (!isRecord(value) || !isRecord(value.metadata))
|
|
74
|
+
return false;
|
|
75
|
+
return (typeof value.metadata.type === "string" &&
|
|
76
|
+
Array.isArray(value.metadata.agentSources) &&
|
|
77
|
+
value.metadata.agentSources.length > 0 &&
|
|
78
|
+
value.metadata.agentSources.every((source) => source === "preset" || source === "provisioned") &&
|
|
79
|
+
typeof value.invoke === "function");
|
|
80
|
+
}
|
|
81
|
+
function asRecord(value, label) {
|
|
82
|
+
if (!isRecord(value))
|
|
83
|
+
throw new TypeError(`${label} must be an object`);
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
function isRecord(value) {
|
|
87
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
88
|
+
}
|
package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/module-specifier.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function resolveAdapterModuleSpecifier(module: string, manifestPath: string): string;
|
|
1
|
+
export { resolveModuleSpecifier as resolveAdapterModuleSpecifier } from "@mininglamp-oss/octo-runtime-adapter-sdk/module-manifest";
|
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/** 内部加载边界:按本机路径语义识别文件,避免把 Windows 盘符交给 ESM 当作 URL 协议。 */
|
|
4
|
-
export function resolveAdapterModuleSpecifier(module, manifestPath) {
|
|
5
|
-
// 相对路径属于 manifest 所在目录;包名及现有 URL 保持 Node 的解析语义。
|
|
6
|
-
return module.startsWith(".") || isAbsolute(module)
|
|
7
|
-
? pathToFileURL(resolve(dirname(manifestPath), module)).href
|
|
8
|
-
: module;
|
|
9
|
-
}
|
|
1
|
+
// 内部兼容入口,CLI 与 runner 共用原始 manifest 锚点下的 ESM 解析。
|
|
2
|
+
export { resolveModuleSpecifier as resolveAdapterModuleSpecifier } from "@mininglamp-oss/octo-runtime-adapter-sdk/module-manifest";
|
|
@@ -2,14 +2,17 @@ import { type ChildProcess, type ChildProcessByStdio } from "node:child_process"
|
|
|
2
2
|
import type { Readable, Writable } from "node:stream";
|
|
3
3
|
import type { HostedAdapterMetadata } from "./index.js";
|
|
4
4
|
import { WorkerRpcClient } from "./rpc.js";
|
|
5
|
+
import type { AdapterModuleEntry } from "@mininglamp-oss/octo-runtime-adapter-sdk/module-manifest";
|
|
5
6
|
export interface SpawnWorkerOptions {
|
|
6
7
|
entrypoint: string;
|
|
7
8
|
/** CLI JSON 来源;SDK 的直接 import 入口不需要此参数。 */
|
|
8
9
|
manifest?: string;
|
|
10
|
+
/** CLI 已解析的不可变装配快照;与 manifest 互斥,不改变 SDK 自有 worker 的入口。 */
|
|
11
|
+
adapterModules?: AdapterModuleEntry[];
|
|
9
12
|
env?: NodeJS.ProcessEnv;
|
|
10
13
|
/** 取消就绪等待并请求回收子进程;POSIX 使用进程组,Windows taskkill 不保证父先退后的后代回收。 */
|
|
11
14
|
signal?: AbortSignal;
|
|
12
|
-
/**
|
|
15
|
+
/** 启动快照发送和首次 RPC 就绪握手共用的最大等待时间。 */
|
|
13
16
|
readyTimeoutMs?: number;
|
|
14
17
|
onSpawn?: (child: ChildProcess) => Promise<void>;
|
|
15
18
|
}
|
|
@@ -21,10 +24,12 @@ export interface WorkerProcess {
|
|
|
21
24
|
close(): Promise<void>;
|
|
22
25
|
stderr(): string;
|
|
23
26
|
}
|
|
27
|
+
/** Kernel 内部传递关闭预算;公开 WorkerProcess.close() 仍然无参数。故障恢复不等待日志排空。 */
|
|
28
|
+
export declare function closeWorker(worker: WorkerProcess, until: number, immediate?: boolean): Promise<void>;
|
|
24
29
|
/**
|
|
25
30
|
* 启动 Node worker,以首次 list RPC 成功作为就绪确认,再返回客户端与进程所有权。
|
|
26
31
|
* 入口/manifest/环境错误在启动阶段携带有界 stderr 抛出;失败路径仍须回收已创建的进程。
|
|
27
32
|
* owner 必须等待 close;清理失败不能当作可安全启动替代 worker 的普通启动错误。
|
|
28
33
|
*/
|
|
29
|
-
export declare function spawnWorker({ entrypoint, manifest, env, signal, onSpawn, readyTimeoutMs }: SpawnWorkerOptions): Promise<WorkerProcess>;
|
|
34
|
+
export declare function spawnWorker({ entrypoint, manifest, adapterModules, env, signal, onSpawn, readyTimeoutMs }: SpawnWorkerOptions): Promise<WorkerProcess>;
|
|
30
35
|
export {};
|
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
import { createProcessCleanup } from "@mininglamp-oss/octo-runtime-adapter-sdk/process-cleanup";
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
2
|
+
import { execFile, spawn } from "node:child_process";
|
|
3
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
3
4
|
import { WorkerRpcClient } from "./rpc.js";
|
|
5
|
+
// Reserve more time for tree cleanup until the worker confirms it has started shutdown.
|
|
6
|
+
// A cooperating worker can use its existing 2.5 s shutdown + 1 s logging bounds.
|
|
7
|
+
const WINDOWS_CLOSE_GRACE_MS = 4_000;
|
|
8
|
+
const WINDOWS_TREE_CLEANUP_RESERVE_MS = 1_900;
|
|
9
|
+
const WINDOWS_COOPERATIVE_CLEANUP_RESERVE_MS = 1_000;
|
|
10
|
+
const closeOptions = new WeakMap();
|
|
11
|
+
/** Kernel 内部传递关闭预算;公开 WorkerProcess.close() 仍然无参数。故障恢复不等待日志排空。 */
|
|
12
|
+
export function closeWorker(worker, until, immediate = false) {
|
|
13
|
+
closeOptions.set(worker, { until, immediate });
|
|
14
|
+
return worker.close();
|
|
15
|
+
}
|
|
4
16
|
/**
|
|
5
17
|
* 启动 Node worker,以首次 list RPC 成功作为就绪确认,再返回客户端与进程所有权。
|
|
6
18
|
* 入口/manifest/环境错误在启动阶段携带有界 stderr 抛出;失败路径仍须回收已创建的进程。
|
|
7
19
|
* owner 必须等待 close;清理失败不能当作可安全启动替代 worker 的普通启动错误。
|
|
8
20
|
*/
|
|
9
|
-
export async function spawnWorker({ entrypoint, manifest, env = process.env, signal, onSpawn, readyTimeoutMs = 15_000 }) {
|
|
21
|
+
export async function spawnWorker({ entrypoint, manifest, adapterModules, env = process.env, signal, onSpawn, readyTimeoutMs = 15_000 }) {
|
|
10
22
|
if (signal?.aborted)
|
|
11
23
|
throw new Error("adapter-host spawn cancelled");
|
|
24
|
+
if (manifest && adapterModules !== undefined)
|
|
25
|
+
throw new TypeError("manifest and adapterModules are mutually exclusive");
|
|
12
26
|
if (!Number.isFinite(readyTimeoutMs) || readyTimeoutMs < 1) {
|
|
13
27
|
throw new Error("adapter-host readyTimeoutMs must be positive");
|
|
14
28
|
}
|
|
15
|
-
//
|
|
16
|
-
const child = spawn(process.execPath, [
|
|
29
|
+
// 快照通过已有 Node IPC 发送,不占命令行/环境长度,不落盘;永不序列化模块实例。
|
|
30
|
+
const child = spawn(process.execPath, [
|
|
31
|
+
entrypoint,
|
|
32
|
+
...(manifest ? ["--manifest", manifest] : []),
|
|
33
|
+
...(adapterModules === undefined ? [] : ["--adapters-from-ipc"])
|
|
34
|
+
], {
|
|
17
35
|
argv0: "octo-runtime-executor-kernel",
|
|
18
36
|
env,
|
|
19
37
|
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
@@ -38,8 +56,16 @@ export async function spawnWorker({ entrypoint, manifest, env = process.env, sig
|
|
|
38
56
|
child.on("error", (error) => client.close(error));
|
|
39
57
|
let adapters;
|
|
40
58
|
try {
|
|
59
|
+
// 先登记进程所有权;快照发送也可能因子进程未读取 IPC 而阻塞,须纳入就绪预算。
|
|
41
60
|
await onSpawn?.(child);
|
|
42
|
-
|
|
61
|
+
const initialize = async () => {
|
|
62
|
+
if (adapterModules !== undefined)
|
|
63
|
+
await new Promise((resolve, reject) => {
|
|
64
|
+
child.send({ type: "kernel.adapters", adapters: adapterModules }, (error) => error ? reject(error) : resolve());
|
|
65
|
+
});
|
|
66
|
+
return client.list();
|
|
67
|
+
};
|
|
68
|
+
adapters = await waitForReady(initialize(), readyTimeoutMs, signal);
|
|
43
69
|
}
|
|
44
70
|
catch (error) {
|
|
45
71
|
client.close(error instanceof Error ? error : new Error(errorMessage(error)));
|
|
@@ -51,18 +77,121 @@ export async function spawnWorker({ entrypoint, manifest, env = process.env, sig
|
|
|
51
77
|
}
|
|
52
78
|
throw new Error(`${errorMessage(error)}${stderr ? `: ${stderr}` : ""}`, { cause: error });
|
|
53
79
|
}
|
|
54
|
-
|
|
80
|
+
let closing;
|
|
81
|
+
const worker = {
|
|
55
82
|
client,
|
|
56
83
|
child,
|
|
57
84
|
adapters,
|
|
58
|
-
//
|
|
59
|
-
// Windows
|
|
85
|
+
// 关闭 RPC 后等待正常收尾与平台清理;POSIX 不以 leader exit 结束进程组回收。
|
|
86
|
+
// Windows 排空后须保留 leader 到 taskkill;宽限内提前退出不能当作树已清空。
|
|
60
87
|
close() {
|
|
88
|
+
if (closing)
|
|
89
|
+
return closing;
|
|
90
|
+
const { until = Date.now() + 5000, immediate = false } = closeOptions.get(worker) ?? {};
|
|
61
91
|
client.close();
|
|
62
|
-
|
|
92
|
+
// Windows 的 kill(SIGTERM) 是强制终止;先用 EOF 触发现有子进程收尾。
|
|
93
|
+
// S02:POSIX 仍回收整个所属进程组,不能只因 leader 退出而跳过 cleanup。
|
|
94
|
+
return (closing = (async () => {
|
|
95
|
+
const drained = process.platform === "win32" && !immediate
|
|
96
|
+
? await endWindowsWorkerInput(child, until)
|
|
97
|
+
: undefined;
|
|
98
|
+
try {
|
|
99
|
+
// 启动回滚与 POSIX 保留共享清理;Windows 正常关闭须验证本次 taskkill 的结果。
|
|
100
|
+
// leader 在通知后退出时,不能再用它的退出状态掩盖 taskkill 未能找到树的错误。
|
|
101
|
+
if (process.platform === "win32" && drained !== "skipped")
|
|
102
|
+
await cleanupWindowsWorker(child, until);
|
|
103
|
+
else
|
|
104
|
+
await cleanup();
|
|
105
|
+
// Reaping the OS tree does not erase an observed Adapter cleanup failure.
|
|
106
|
+
if (drained === "incomplete")
|
|
107
|
+
throw Object.assign(new Error("EXECUTOR_CLEANUP_INCOMPLETE"), {
|
|
108
|
+
code: "EXECUTOR_CLEANUP_INCOMPLETE"
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
if (process.platform === "win32") {
|
|
113
|
+
// 正常收尾或 fallback 结束后释放本层管道;回收失败仍向调用方传播。
|
|
114
|
+
child.stdin.destroy();
|
|
115
|
+
child.stdout.destroy();
|
|
116
|
+
child.stderr.destroy();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
})());
|
|
63
120
|
},
|
|
64
121
|
stderr: () => stderr
|
|
65
122
|
};
|
|
123
|
+
return worker;
|
|
124
|
+
}
|
|
125
|
+
/** 只回收本次 worker 的树。命令和退出确认共用截止时间,任何命令错误都保留为回收失败。 */
|
|
126
|
+
async function cleanupWindowsWorker(child, until) {
|
|
127
|
+
const incomplete = (cause) => Object.assign(new Error("PROCESS_TREE_CLEANUP_INCOMPLETE", { cause }), {
|
|
128
|
+
code: "PROCESS_TREE_CLEANUP_INCOMPLETE"
|
|
129
|
+
});
|
|
130
|
+
if (child.pid === undefined || child.exitCode !== null || child.signalCode !== null)
|
|
131
|
+
throw incomplete();
|
|
132
|
+
const remaining = until - Date.now();
|
|
133
|
+
if (remaining <= 0)
|
|
134
|
+
throw incomplete();
|
|
135
|
+
await new Promise((resolve, reject) => {
|
|
136
|
+
execFile("taskkill", ["/PID", String(child.pid), "/T", "/F"], { windowsHide: true, timeout: remaining }, (error) => (error ? reject(incomplete(error)) : resolve()));
|
|
137
|
+
});
|
|
138
|
+
const confirmUntil = Math.min(until, Date.now() + 200);
|
|
139
|
+
while (child.exitCode === null && child.signalCode === null) {
|
|
140
|
+
const left = confirmUntil - Date.now();
|
|
141
|
+
if (left <= 0)
|
|
142
|
+
throw Object.assign(new Error("PROCESS_CLEANUP_TIMEOUT"), {
|
|
143
|
+
code: "PROCESS_CLEANUP_TIMEOUT"
|
|
144
|
+
});
|
|
145
|
+
await delay(Math.min(10, left));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** 私有正常关闭阶段:EOF 触发排空,IPC 只确认排空结果,实际进程树仍由 cleanup 回收。 */
|
|
149
|
+
function endWindowsWorkerInput(child, until) {
|
|
150
|
+
if (child.exitCode !== null || child.signalCode !== null || child.stdin.destroyed)
|
|
151
|
+
return Promise.resolve("skipped");
|
|
152
|
+
return new Promise((resolve) => {
|
|
153
|
+
const graceUntil = Math.min(Date.now() + WINDOWS_CLOSE_GRACE_MS, until - WINDOWS_COOPERATIVE_CLEANUP_RESERVE_MS);
|
|
154
|
+
let settled = false;
|
|
155
|
+
const finish = (result) => {
|
|
156
|
+
if (settled)
|
|
157
|
+
return;
|
|
158
|
+
settled = true;
|
|
159
|
+
clearTimeout(timer);
|
|
160
|
+
child.off("close", fallback);
|
|
161
|
+
child.off("error", fallback);
|
|
162
|
+
child.stdin.off("error", fallback);
|
|
163
|
+
child.off("message", onMessage);
|
|
164
|
+
resolve(result);
|
|
165
|
+
};
|
|
166
|
+
const fallback = () => finish("fallback");
|
|
167
|
+
const onMessage = (message) => {
|
|
168
|
+
if (!message || typeof message !== "object" || !("type" in message))
|
|
169
|
+
return;
|
|
170
|
+
if (message.type === "worker.stopping") {
|
|
171
|
+
// This is progress, not cleanup success. Repeated messages never extend the deadline.
|
|
172
|
+
clearTimeout(timer);
|
|
173
|
+
timer = setTimeout(fallback, Math.max(0, graceUntil - Date.now()));
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (message.type === "worker.drained" &&
|
|
177
|
+
"cleanup" in message &&
|
|
178
|
+
(message.cleanup === "complete" || message.cleanup === "incomplete"))
|
|
179
|
+
finish(message.cleanup);
|
|
180
|
+
};
|
|
181
|
+
let timer = setTimeout(fallback, Math.max(0, Math.min(graceUntil, until - WINDOWS_TREE_CLEANUP_RESERVE_MS) - Date.now()));
|
|
182
|
+
// 先监听再发送 EOF;worker 排空后仍存活,输出在通知/超时前持续消费。
|
|
183
|
+
child.once("close", fallback);
|
|
184
|
+
child.once("error", fallback);
|
|
185
|
+
child.stdin.once("error", fallback);
|
|
186
|
+
child.on("message", onMessage);
|
|
187
|
+
try {
|
|
188
|
+
child.stdin.end();
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
// EPIPE 等故障不新增公开错误合同;真正的回收失败仍由 cleanup 抛出。
|
|
192
|
+
fallback();
|
|
193
|
+
}
|
|
194
|
+
});
|
|
66
195
|
}
|
|
67
196
|
function waitForReady(operation, timeoutMs, signal) {
|
|
68
197
|
return new Promise((resolve, reject) => {
|