@zhushanwen/subagent-engine-sdk 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/dist/best-effort.cjs +88 -0
  2. package/dist/best-effort.d.cts +14 -0
  3. package/dist/best-effort.d.ts +14 -0
  4. package/dist/best-effort.js +8 -0
  5. package/dist/chunk-2DIMPZCQ.js +0 -0
  6. package/dist/chunk-365AUV6N.js +67 -0
  7. package/dist/chunk-3K2P2CM2.js +127 -0
  8. package/dist/chunk-75QEMUGV.js +58 -0
  9. package/dist/chunk-7I4XGL5J.js +95 -0
  10. package/dist/chunk-A75XDJIC.js +227 -0
  11. package/dist/chunk-DSQ7JQKM.js +39 -0
  12. package/dist/chunk-EJMF63R5.js +19 -0
  13. package/dist/chunk-GT6YLLN4.js +46 -0
  14. package/dist/chunk-HYES77BR.js +109 -0
  15. package/dist/chunk-JSBRDJBE.js +30 -0
  16. package/dist/chunk-LEOBWKRM.js +128 -0
  17. package/dist/chunk-N3RL6OVM.js +38 -0
  18. package/dist/chunk-OPMY4G4M.js +27 -0
  19. package/dist/chunk-PPEPBVCC.js +120 -0
  20. package/dist/chunk-PYO3YR7W.js +16 -0
  21. package/dist/chunk-RDH3ZOV6.js +46 -0
  22. package/dist/chunk-RULLX6C6.js +11 -0
  23. package/dist/chunk-X24SFZYW.js +6646 -0
  24. package/dist/chunk-YFSN3D5N.js +216 -0
  25. package/dist/chunk-ZOFFJNJD.js +136 -0
  26. package/dist/chunk-ZXEAW25V.js +132 -0
  27. package/dist/cli-entry.cjs +119 -0
  28. package/dist/cli-entry.d.cts +24 -0
  29. package/dist/cli-entry.d.ts +24 -0
  30. package/dist/cli-entry.js +8 -0
  31. package/dist/contract-types-sSlgppBC.d.cts +352 -0
  32. package/dist/contract-types-sSlgppBC.d.ts +352 -0
  33. package/dist/data-dir.cjs +117 -0
  34. package/dist/data-dir.d.cts +20 -0
  35. package/dist/data-dir.d.ts +20 -0
  36. package/dist/data-dir.js +12 -0
  37. package/dist/env.cjs +205 -0
  38. package/dist/env.d.cts +73 -0
  39. package/dist/env.d.ts +73 -0
  40. package/dist/env.js +16 -0
  41. package/dist/error-codes-DHco5-i_.d.cts +118 -0
  42. package/dist/error-codes-Dhss2Kmk.d.ts +118 -0
  43. package/dist/error-message.cjs +40 -0
  44. package/dist/error-message.d.cts +3 -0
  45. package/dist/error-message.d.ts +3 -0
  46. package/dist/error-message.js +7 -0
  47. package/dist/index.cjs +8375 -0
  48. package/dist/index.d.cts +23 -0
  49. package/dist/index.d.ts +23 -0
  50. package/dist/index.js +268 -0
  51. package/dist/journal-io.cjs +70 -0
  52. package/dist/journal-io.d.cts +12 -0
  53. package/dist/journal-io.d.ts +12 -0
  54. package/dist/journal-io.js +7 -0
  55. package/dist/journal-replay.cjs +256 -0
  56. package/dist/journal-replay.d.cts +45 -0
  57. package/dist/journal-replay.d.ts +45 -0
  58. package/dist/journal-replay.js +17 -0
  59. package/dist/kill-chain.cjs +221 -0
  60. package/dist/kill-chain.d.cts +74 -0
  61. package/dist/kill-chain.d.ts +74 -0
  62. package/dist/kill-chain.js +23 -0
  63. package/dist/logger.cjs +84 -0
  64. package/dist/logger.d.cts +24 -0
  65. package/dist/logger.d.ts +24 -0
  66. package/dist/logger.js +11 -0
  67. package/dist/logs/stderr-rotation.cjs +151 -0
  68. package/dist/logs/stderr-rotation.d.cts +37 -0
  69. package/dist/logs/stderr-rotation.d.ts +37 -0
  70. package/dist/logs/stderr-rotation.js +23 -0
  71. package/dist/nesting-guard.cjs +95 -0
  72. package/dist/nesting-guard.d.cts +65 -0
  73. package/dist/nesting-guard.d.ts +65 -0
  74. package/dist/nesting-guard.js +15 -0
  75. package/dist/node-executor.cjs +180 -0
  76. package/dist/node-executor.d.cts +63 -0
  77. package/dist/node-executor.d.ts +63 -0
  78. package/dist/node-executor.js +16 -0
  79. package/dist/paths.cjs +55 -0
  80. package/dist/paths.d.cts +8 -0
  81. package/dist/paths.d.ts +8 -0
  82. package/dist/paths.js +15 -0
  83. package/dist/port-contract.cjs +35 -0
  84. package/dist/port-contract.d.cts +88 -0
  85. package/dist/port-contract.d.ts +88 -0
  86. package/dist/port-contract.js +7 -0
  87. package/dist/protocol/index.cjs +400 -0
  88. package/dist/protocol/index.d.cts +685 -0
  89. package/dist/protocol/index.d.ts +685 -0
  90. package/dist/protocol/index.js +89 -0
  91. package/dist/relay-env.cjs +71 -0
  92. package/dist/relay-env.d.cts +37 -0
  93. package/dist/relay-env.d.ts +37 -0
  94. package/dist/relay-env.js +23 -0
  95. package/dist/schema-emulation.cjs +6680 -0
  96. package/dist/schema-emulation.d.cts +39 -0
  97. package/dist/schema-emulation.d.ts +39 -0
  98. package/dist/schema-emulation.js +11 -0
  99. package/dist/spawn.cjs +200 -0
  100. package/dist/spawn.d.cts +80 -0
  101. package/dist/spawn.d.ts +80 -0
  102. package/dist/spawn.js +16 -0
  103. package/dist/ui-channels.cjs +120 -0
  104. package/dist/ui-channels.d.cts +60 -0
  105. package/dist/ui-channels.d.ts +60 -0
  106. package/dist/ui-channels.js +9 -0
  107. package/dist/ui-types.cjs +18 -0
  108. package/dist/ui-types.d.cts +62 -0
  109. package/dist/ui-types.d.ts +62 -0
  110. package/dist/ui-types.js +1 -0
  111. package/package.json +58 -0
  112. package/src/best-effort.ts +37 -0
  113. package/src/cli-entry.ts +77 -0
  114. package/src/data-dir.ts +88 -0
  115. package/src/env.ts +265 -0
  116. package/src/error-message.ts +22 -0
  117. package/src/index.ts +63 -0
  118. package/src/journal-io.ts +82 -0
  119. package/src/journal-replay.ts +432 -0
  120. package/src/kill-chain.ts +265 -0
  121. package/src/logger.ts +105 -0
  122. package/src/logs/stderr-rotation.ts +166 -0
  123. package/src/nesting-guard.ts +140 -0
  124. package/src/node-executor.ts +272 -0
  125. package/src/paths.ts +48 -0
  126. package/src/port-contract.ts +117 -0
  127. package/src/protocol/contract-types.ts +378 -0
  128. package/src/protocol/engine-protocol.ts +81 -0
  129. package/src/protocol/error-codes.ts +179 -0
  130. package/src/protocol/frames.ts +145 -0
  131. package/src/protocol/index.ts +12 -0
  132. package/src/protocol/methods.ts +229 -0
  133. package/src/protocol/reverse-channels.ts +274 -0
  134. package/src/protocol/schema.ts +154 -0
  135. package/src/relay-env.ts +60 -0
  136. package/src/schema-emulation.ts +192 -0
  137. package/src/spawn.ts +246 -0
  138. package/src/ui-channels.ts +219 -0
  139. package/src/ui-types.ts +84 -0
@@ -0,0 +1,39 @@
1
+ // src/relay-env.ts
2
+ var RELAY_ENV_SOCKET = "XYZ_SUBAGENT_RELAY_SOCKET";
3
+ var RELAY_ENV_NODE = "XYZ_SUBAGENT_RELAY_NODE";
4
+ var RELAY_ENV_SCRIPT = "XYZ_SUBAGENT_RELAY_SCRIPT";
5
+ var RELAY_ENV_SESSION_ID = "XYZ_SUBAGENT_RELAY_SESSION_ID";
6
+ var RELAY_ENV_RECORD_ID = "XYZ_SUBAGENT_RELAY_RECORD_ID";
7
+ var RELAY_PROTOCOL_VERSION = 1;
8
+ var RELAY_EXIT_CODES = {
9
+ /** 握手被拒:协议版本不匹配(安装损坏,重装应用)。 */
10
+ VERSION_MISMATCH: 10,
11
+ /** relay socket 不可达(runtime 未运行或已重启)。 */
12
+ SOCKET_UNREACHABLE: 11,
13
+ /** socket 中途断开(runtime 崩溃等)——代理生命线断即退。 */
14
+ SOCKET_CLOSED: 12,
15
+ /** 归属 env(SESSION_ID/RECORD_ID)缺失——防无归属帧污染广播。 */
16
+ MISSING_IDENTITY: 13
17
+ };
18
+ function isRelayActive(env) {
19
+ return Boolean(env[RELAY_ENV_SOCKET] && env[RELAY_ENV_NODE] && env[RELAY_ENV_SCRIPT]);
20
+ }
21
+ function readRelayForwardEnv(env) {
22
+ const socket = env[RELAY_ENV_SOCKET];
23
+ const node = env[RELAY_ENV_NODE];
24
+ const script = env[RELAY_ENV_SCRIPT];
25
+ if (!isRelayActive(env)) return void 0;
26
+ return { socket, node, script };
27
+ }
28
+
29
+ export {
30
+ RELAY_ENV_SOCKET,
31
+ RELAY_ENV_NODE,
32
+ RELAY_ENV_SCRIPT,
33
+ RELAY_ENV_SESSION_ID,
34
+ RELAY_ENV_RECORD_ID,
35
+ RELAY_PROTOCOL_VERSION,
36
+ RELAY_EXIT_CODES,
37
+ isRelayActive,
38
+ readRelayForwardEnv
39
+ };
@@ -0,0 +1,19 @@
1
+ import {
2
+ getLogger
3
+ } from "./chunk-75QEMUGV.js";
4
+
5
+ // src/best-effort.ts
6
+ var logger = getLogger("subagents");
7
+ function bestEffort(err, context, level = "debug") {
8
+ const detail = err instanceof Error ? err.message : err;
9
+ const msg = `[subagents] best-effort ${context} failed`;
10
+ if (level === "error") {
11
+ logger.error(msg, { detail });
12
+ } else {
13
+ logger.debug(msg, { detail });
14
+ }
15
+ }
16
+
17
+ export {
18
+ bestEffort
19
+ };
@@ -0,0 +1,46 @@
1
+ import {
2
+ getLogger
3
+ } from "./chunk-75QEMUGV.js";
4
+
5
+ // src/data-dir.ts
6
+ var logger = getLogger("subagents");
7
+ var XYZ_DATA_DIR_ENV = "XYZ_AGENT_DATA_DIR";
8
+ var WARNED_SLOT_KEY = /* @__PURE__ */ Symbol.for("@zhushanwen/subagent-engine-sdk.data-dir-warned");
9
+ function getWarnedSlot() {
10
+ let slot = Reflect.get(globalThis, WARNED_SLOT_KEY);
11
+ if (!slot) {
12
+ slot = { current: false };
13
+ Reflect.set(globalThis, WARNED_SLOT_KEY, slot);
14
+ }
15
+ return slot;
16
+ }
17
+ function resetDataDirWarnForTests() {
18
+ getWarnedSlot().current = false;
19
+ }
20
+ function resolveEngineDataDir(env, opts = {}) {
21
+ const fromEnv = env[XYZ_DATA_DIR_ENV]?.trim();
22
+ if (fromEnv !== void 0 && fromEnv !== "") return fromEnv;
23
+ const fallback = opts.fallbackDataRoot?.trim();
24
+ if (fallback === void 0 || fallback === "") {
25
+ throw new Error(
26
+ `[subagent-engine-sdk] engine_not_found: ${XYZ_DATA_DIR_ENV} is not set and no fallback data root was injected. Recovery: the host must inject ${XYZ_DATA_DIR_ENV} into the engine process env (xyz-agent runtime / pi extension host do this at spawn), or pass { fallbackDataRoot } when calling resolveEngineDataDir from a host that resolves the data root itself.`
27
+ );
28
+ }
29
+ if (!getWarnedSlot().current) {
30
+ getWarnedSlot().current = true;
31
+ const warn = opts.warn ?? defaultWarn;
32
+ warn(
33
+ `[engine-data-dir] ${XYZ_DATA_DIR_ENV} is not set; engine journal/pool fall back to the injected data root (${fallback}). The xyz-agent host normally injects this env \u2014 if you are running inside xyz-agent, check the runtime spawn env; standalone installs intentionally use the injected root.`
34
+ );
35
+ }
36
+ return fallback;
37
+ }
38
+ function defaultWarn(msg) {
39
+ logger.warn(msg);
40
+ }
41
+
42
+ export {
43
+ XYZ_DATA_DIR_ENV,
44
+ resetDataDirWarnForTests,
45
+ resolveEngineDataDir
46
+ };
@@ -0,0 +1,109 @@
1
+ // src/logs/stderr-rotation.ts
2
+ import * as fs from "fs";
3
+ import { dirname, join } from "path";
4
+ var BYTES_PER_KB = 1024;
5
+ var DEFAULT_MAX_FILE_MB = 50;
6
+ var MS_PER_SECOND = 1e3;
7
+ var SECONDS_PER_MINUTE = 60;
8
+ var MINUTES_PER_HOUR = 60;
9
+ var HOURS_PER_DAY = 24;
10
+ var DEFAULT_STDERR_MAX_BYTES = DEFAULT_MAX_FILE_MB * BYTES_PER_KB * BYTES_PER_KB;
11
+ var DAY_MS = HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MS_PER_SECOND;
12
+ var DEFAULT_STDERR_KEEP_DAYS = 7;
13
+ function positiveIntEnv(env, key) {
14
+ const raw = env[key];
15
+ if (raw === void 0 || raw.trim() === "") return void 0;
16
+ const n = Number(raw);
17
+ return Number.isFinite(n) && n > 0 ? n : void 0;
18
+ }
19
+ function stderrRotationParams(env) {
20
+ return {
21
+ maxBytes: positiveIntEnv(env, "XYZ_LOG_MAX_BYTES") ?? DEFAULT_STDERR_MAX_BYTES,
22
+ keepDays: positiveIntEnv(env, "XYZ_LOG_KEEP_DAYS") ?? DEFAULT_STDERR_KEEP_DAYS
23
+ };
24
+ }
25
+ function stderrLogPathFor(engineDataDir, pid, prefix) {
26
+ return join(engineDataDir, "logs", `${prefix}${pid}.log`);
27
+ }
28
+ function stderrLogPidOf(fileName, prefix) {
29
+ if (!fileName.startsWith(prefix)) return void 0;
30
+ const rest = fileName.slice(prefix.length);
31
+ const pidToken = rest.split(".", 1)[0] ?? "";
32
+ if (!/^\d+$/.test(pidToken)) return void 0;
33
+ return Number(pidToken);
34
+ }
35
+ function isPidAlive(pid) {
36
+ try {
37
+ process.kill(pid, 0);
38
+ return true;
39
+ } catch (err) {
40
+ return err.code === "EPERM";
41
+ }
42
+ }
43
+ function rotateStderrLogIfNeeded(path, params) {
44
+ let size;
45
+ try {
46
+ size = fs.statSync(path).size;
47
+ } catch {
48
+ return false;
49
+ }
50
+ if (size <= params.maxBytes) return false;
51
+ const rotated = `${path}.${Date.now()}`;
52
+ try {
53
+ fs.renameSync(path, rotated);
54
+ return true;
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+ function cleanupStaleStderrLogs(logsDir, env, prefix, now = Date.now()) {
60
+ const params = stderrRotationParams(env);
61
+ const expiryMs = params.keepDays * DAY_MS;
62
+ let deleted = 0;
63
+ let skipped = 0;
64
+ let names;
65
+ try {
66
+ names = fs.readdirSync(logsDir);
67
+ } catch {
68
+ return { deleted, skipped };
69
+ }
70
+ for (const name of names) {
71
+ const pid = stderrLogPidOf(name, prefix);
72
+ if (pid === void 0) continue;
73
+ if (isPidAlive(pid)) {
74
+ skipped += 1;
75
+ continue;
76
+ }
77
+ const full = join(logsDir, name);
78
+ try {
79
+ if (fs.statSync(full).mtimeMs > now - expiryMs) {
80
+ skipped += 1;
81
+ continue;
82
+ }
83
+ } catch {
84
+ continue;
85
+ }
86
+ try {
87
+ fs.rmSync(full, { force: true });
88
+ deleted += 1;
89
+ } catch {
90
+ skipped += 1;
91
+ }
92
+ }
93
+ return { deleted, skipped };
94
+ }
95
+ function cleanupSiblingStderrLogs(logPath, env, prefix, now) {
96
+ return cleanupStaleStderrLogs(dirname(logPath), env, prefix, now);
97
+ }
98
+
99
+ export {
100
+ DEFAULT_STDERR_MAX_BYTES,
101
+ DEFAULT_STDERR_KEEP_DAYS,
102
+ stderrRotationParams,
103
+ stderrLogPathFor,
104
+ stderrLogPidOf,
105
+ isPidAlive,
106
+ rotateStderrLogIfNeeded,
107
+ cleanupStaleStderrLogs,
108
+ cleanupSiblingStderrLogs
109
+ };
@@ -0,0 +1,30 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ export {
28
+ __commonJS,
29
+ __toESM
30
+ };
@@ -0,0 +1,128 @@
1
+ import {
2
+ toErrorMessage
3
+ } from "./chunk-PYO3YR7W.js";
4
+ import {
5
+ engineTimeoutDetail
6
+ } from "./chunk-PPEPBVCC.js";
7
+ import {
8
+ getLogger
9
+ } from "./chunk-75QEMUGV.js";
10
+
11
+ // src/kill-chain.ts
12
+ var logger = getLogger("subagents");
13
+ var MS_PER_SECOND = 1e3;
14
+ var DEFAULT_KILL_GRACE_MS = 5e3;
15
+ var SIGKILL_REAP_TIMEOUT_MS = 1e4;
16
+ var HOST_TIMEOUT_ABORT_REASON = "agent-call-timeout";
17
+ async function killChain(child, opts) {
18
+ if (child.exitCode !== null || child.signalCode !== null) return "terminated";
19
+ const exited = waitForExit(child);
20
+ safeKill(child, "SIGTERM");
21
+ const graceful = await raceTimeout(exited, opts.graceMs, opts.unrefTimers === true);
22
+ if (graceful === "settled") return "terminated";
23
+ if (child.exitCode !== null || child.signalCode !== null) return "terminated";
24
+ if (opts.escalationNote !== void 0) {
25
+ logger.warn(
26
+ `[kill-chain] ${opts.escalationNote} still alive ${opts.graceMs / MS_PER_SECOND}s after SIGTERM, escalating to SIGKILL`
27
+ );
28
+ }
29
+ safeKill(child, "SIGKILL");
30
+ await raceTimeout(exited, SIGKILL_REAP_TIMEOUT_MS, opts.unrefTimers === true);
31
+ return "killed";
32
+ }
33
+ function safeKill(child, signal) {
34
+ try {
35
+ child.kill(signal);
36
+ } catch (err) {
37
+ logger.debug(
38
+ `[kill-chain] ${signal} on exited process: ${toErrorMessage(err)}`
39
+ );
40
+ }
41
+ }
42
+ function synthesizeTimeoutOutcome(task, stdoutTail, engineId) {
43
+ return {
44
+ content: "",
45
+ // slug 进错误信息:单看 outcome(record 之外)也能定位是哪个任务超时
46
+ error: `engine_timeout: [slug=${task.description ?? "unknown"}] ${engineTimeoutDetail(stdoutTail)}`,
47
+ // 被信号杀死:退出码语义为 null(§3.3.5 AgentOutcome.exitCode 注释)
48
+ exitCode: null,
49
+ engineId
50
+ };
51
+ }
52
+ var DEFAULT_NATIVE_INTERRUPT_GRACE_MS = 3e3;
53
+ function abortWithFallback(child, signal, tryNativeInterrupt, opts) {
54
+ const graceMs = opts?.graceMs ?? DEFAULT_KILL_GRACE_MS;
55
+ const nativeGraceMs = opts?.nativeGraceMs ?? DEFAULT_NATIVE_INTERRUPT_GRACE_MS;
56
+ return new Promise((resolve) => {
57
+ let settled = false;
58
+ function finish(result) {
59
+ if (settled) return;
60
+ settled = true;
61
+ signal.removeEventListener("abort", onAbort);
62
+ resolve(result);
63
+ }
64
+ function onExit() {
65
+ finish("terminated");
66
+ }
67
+ function runChain() {
68
+ void (async () => {
69
+ if (tryNativeInterrupt) {
70
+ try {
71
+ await tryNativeInterrupt();
72
+ } catch (err) {
73
+ logger.debug(
74
+ `[kill-chain] native interrupt failed, falling back to kill chain: ${toErrorMessage(err)}`
75
+ );
76
+ }
77
+ const stopped = await raceTimeout(waitForExit(child), nativeGraceMs);
78
+ if (stopped === "settled" || settled) return;
79
+ }
80
+ finish(await killChain(child, { graceMs }));
81
+ })();
82
+ }
83
+ function onAbort() {
84
+ runChain();
85
+ }
86
+ child.once("exit", onExit);
87
+ if (child.exitCode !== null || child.signalCode !== null) {
88
+ finish("terminated");
89
+ return;
90
+ }
91
+ if (signal.aborted) runChain();
92
+ else signal.addEventListener("abort", onAbort, { once: true });
93
+ });
94
+ }
95
+ function waitForExit(child) {
96
+ return new Promise((resolve) => {
97
+ if (child.exitCode !== null || child.signalCode !== null) {
98
+ resolve();
99
+ return;
100
+ }
101
+ child.once("exit", () => resolve());
102
+ });
103
+ }
104
+ function raceTimeout(p, ms, unref = false) {
105
+ return new Promise((resolve) => {
106
+ const timer = setTimeout(() => resolve("timeout"), ms);
107
+ if (unref) timer.unref();
108
+ p.then(
109
+ () => {
110
+ clearTimeout(timer);
111
+ resolve("settled");
112
+ },
113
+ () => {
114
+ clearTimeout(timer);
115
+ resolve("settled");
116
+ }
117
+ );
118
+ });
119
+ }
120
+
121
+ export {
122
+ DEFAULT_KILL_GRACE_MS,
123
+ HOST_TIMEOUT_ABORT_REASON,
124
+ killChain,
125
+ synthesizeTimeoutOutcome,
126
+ DEFAULT_NATIVE_INTERRUPT_GRACE_MS,
127
+ abortWithFallback
128
+ };
@@ -0,0 +1,38 @@
1
+ import {
2
+ configureLoggerSink,
3
+ getLogger
4
+ } from "./chunk-75QEMUGV.js";
5
+
6
+ // src/cli-entry.ts
7
+ import * as readline from "readline";
8
+ var INBOUND_LOG_CHARS = 200;
9
+ function runEngineCliEntry(opts) {
10
+ const logger = getLogger(opts.component);
11
+ const server = opts.server;
12
+ configureLoggerSink({
13
+ log(level, component, message, data) {
14
+ process.stderr.write(`[${level}] [${component}] ${message}${data !== void 0 ? ` ${JSON.stringify(data)}` : ""}
15
+ `);
16
+ void server.reverseRequest("host/log", { level, component, message }).catch(() => void 0);
17
+ }
18
+ });
19
+ const rl = readline.createInterface({ input: process.stdin, crlfDelay: Infinity });
20
+ rl.on("line", (line) => {
21
+ const text = line.trim();
22
+ if (text === "") return;
23
+ try {
24
+ server.handleFrame(JSON.parse(text));
25
+ } catch (err) {
26
+ logger.warn(`unparseable inbound protocol line (ignored): ${text.slice(0, INBOUND_LOG_CHARS)}`, {
27
+ reason: err instanceof Error ? err.message : String(err)
28
+ });
29
+ }
30
+ });
31
+ rl.on("close", () => {
32
+ logger.debug("stdin closed (host exit path)");
33
+ });
34
+ }
35
+
36
+ export {
37
+ runEngineCliEntry
38
+ };
@@ -0,0 +1,27 @@
1
+ // src/paths.ts
2
+ import { join } from "path";
3
+ var MAX_SEG_CHARS = 80;
4
+ function sanitizeSeg(input) {
5
+ const s = input.replace(/[^A-Za-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
6
+ return s.length > 0 ? s.slice(0, MAX_SEG_CHARS) : "default";
7
+ }
8
+ function resolveEnginesRoot(dataDir) {
9
+ return join(dataDir, "engines");
10
+ }
11
+ function resolveEngineDir(dataDir, engineId) {
12
+ return join(resolveEnginesRoot(dataDir), sanitizeSeg(engineId));
13
+ }
14
+ function resolvePoolDir(dataDir, engineId, poolKey) {
15
+ return join(resolveEngineDir(dataDir, sanitizeSeg(engineId)), sanitizeSeg(poolKey));
16
+ }
17
+ function resolveJournalPath(dataDir, engineId, poolKey, taskId) {
18
+ return join(resolvePoolDir(dataDir, engineId, poolKey), `journal-${sanitizeSeg(taskId)}.jsonl`);
19
+ }
20
+
21
+ export {
22
+ sanitizeSeg,
23
+ resolveEnginesRoot,
24
+ resolveEngineDir,
25
+ resolvePoolDir,
26
+ resolveJournalPath
27
+ };
@@ -0,0 +1,120 @@
1
+ // src/protocol/engine-protocol.ts
2
+ var ENGINE_PROTOCOL_VERSION = 1;
3
+ var SUPPORTED_PROTOCOL_RANGE = { min: 1, max: 2 };
4
+ function isProtocolVersionCompatible(version) {
5
+ return Number.isInteger(version) && version >= SUPPORTED_PROTOCOL_RANGE.min && version < SUPPORTED_PROTOCOL_RANGE.max;
6
+ }
7
+ var REVERSE_REQUEST_TIMEOUT_MS = 1e4;
8
+ var HANDSHAKE_TIMEOUT_MS = 1e4;
9
+ var CANCEL_SETTLE_GRACE_MS = 3e3;
10
+ var CRASH_REBUILD_MAX_ATTEMPTS = 3;
11
+ var CRASH_REBUILD_BACKOFF_STEP_1_MS = 1e3;
12
+ var CRASH_REBUILD_BACKOFF_STEP_2_MS = 2e3;
13
+ var CRASH_REBUILD_BACKOFF_STEP_3_MS = 4e3;
14
+ var CRASH_REBUILD_BACKOFF_MS = [
15
+ CRASH_REBUILD_BACKOFF_STEP_1_MS,
16
+ CRASH_REBUILD_BACKOFF_STEP_2_MS,
17
+ CRASH_REBUILD_BACKOFF_STEP_3_MS
18
+ ];
19
+ var STDERR_TAIL_CHARS = 400;
20
+ var ENGINE_EVENT_COALESCE_ENV = "XYZ_ENGINE_EVENT_COALESCE";
21
+ var ENGINE_EVENT_COALESCE_DEFAULT = "0";
22
+
23
+ // src/protocol/error-codes.ts
24
+ var ENGINE_PROTOCOL_ERROR_CODES = [
25
+ "engine_not_found",
26
+ "engine_protocol_mismatch",
27
+ "engine_capability_unsupported",
28
+ "engine_capability_mismatch",
29
+ "engine_model_unknown",
30
+ "engine_model_mismatch",
31
+ "engine_handshake_timeout",
32
+ "engine_crashed",
33
+ "engine_probe_failed"
34
+ ];
35
+ function isEngineProtocolErrorCode(value) {
36
+ return typeof value === "string" && ENGINE_PROTOCOL_ERROR_CODES.includes(value);
37
+ }
38
+ var ENGINE_ERROR_CODE_PREFIX = "engine_";
39
+ function isEngineErrorPassthroughCode(value) {
40
+ return !isEngineProtocolErrorCode(value) && value.startsWith(ENGINE_ERROR_CODE_PREFIX);
41
+ }
42
+ var EngineSdkError = class extends Error {
43
+ code;
44
+ recovery;
45
+ data;
46
+ constructor(code, detail, recovery, data) {
47
+ super(`${code}: ${detail}`);
48
+ this.name = "EngineSdkError";
49
+ this.code = code;
50
+ this.recovery = recovery;
51
+ this.data = data;
52
+ }
53
+ /** 协议 error 帧载荷投影。 */
54
+ toStructured() {
55
+ return { code: this.code, message: this.message, recovery: this.recovery, data: this.data };
56
+ }
57
+ };
58
+ function engineProtocolMismatchError(engineVersion) {
59
+ return new EngineSdkError(
60
+ "engine_protocol_mismatch",
61
+ `engine speaks protocol v${engineVersion}, host supports [${SUPPORTED_PROTOCOL_RANGE.min}, ${SUPPORTED_PROTOCOL_RANGE.max})`,
62
+ "Upgrade the engine package (or the host) so both sides speak a protocol version in the supported range, then re-run the task. The engine is marked unavailable until then.",
63
+ {
64
+ engineProtocolVersion: engineVersion,
65
+ supportedMin: SUPPORTED_PROTOCOL_RANGE.min,
66
+ supportedMaxExclusive: SUPPORTED_PROTOCOL_RANGE.max
67
+ }
68
+ );
69
+ }
70
+ function engineConversationUnsupportedError(engineId) {
71
+ return new EngineSdkError(
72
+ "engine_capability_unsupported",
73
+ `engine '${engineId}' \u4E0D\u652F\u6301 conversation\uFF08capabilities.conversation = 'unsupported'\uFF0Cmanifest \u65E0 conversation gate \u4F4D\u2014\u2014\u65E0\u540C\u8FDB\u7A0B idle \u590D\u7528\uFF0Cmessage/close \u4EA4\u4E92\u63A7\u5236\u9762\u4E0D\u53EF\u7528\uFF09`,
74
+ `\u53BB\u6389 conversation \u53C2\u6570\uFF08\u4E00\u6B21\u6027\u4EFB\u52A1\u9ED8\u8BA4\u5F62\u6001\uFF09\uFF0C\u6216\u4FEE manifest capabilities / \u5347\u7EA7\u5F15\u64CE\u5305\uFF08\u82E5\u5F15\u64CE\u5B9E\u9645\u652F\u6301\u8BE5\u80FD\u529B\uFF09`,
75
+ { engineId, capability: "conversation", declared: "unsupported" }
76
+ );
77
+ }
78
+ function assertChatConversationSupported(engineId, capabilities) {
79
+ if (capabilities.conversation === "unsupported") {
80
+ throw engineConversationUnsupportedError(engineId);
81
+ }
82
+ }
83
+ var DETAIL_ECHO_MAX_CHARS = 200;
84
+ var STDOUT_TAIL_ECHO_CHARS = 2e3;
85
+ function truncate(text, max) {
86
+ return text.length <= max ? text : `${text.slice(0, max)}...`;
87
+ }
88
+ var ENGINE_TIMEOUT_RECOVERY = "The engine was killed by the host timeout chain. Inspect the captured stdout tail, then re-run with a larger timeout, a narrower task, or `engine: pi`.";
89
+ function engineTimeoutDetail(stdoutTail) {
90
+ return `host timeout chain exhausted (SIGTERM -> grace -> SIGKILL). Stdout tail (last ${STDOUT_TAIL_ECHO_CHARS} chars): ${truncate(stdoutTail, STDOUT_TAIL_ECHO_CHARS)}. Recovery: ${ENGINE_TIMEOUT_RECOVERY}`;
91
+ }
92
+ function schemaEmulationFailedDetail(error, tail) {
93
+ return `structured output emulation failed after tolerant extraction and one host-side retry: ${error}. Raw output tail: ${truncate(tail, DETAIL_ECHO_MAX_CHARS)}. Recovery: retry with a strengthened prompt or relax the schema; if it still fails switch to a schema-native engine (engine: pi).`;
94
+ }
95
+
96
+ export {
97
+ ENGINE_PROTOCOL_VERSION,
98
+ SUPPORTED_PROTOCOL_RANGE,
99
+ isProtocolVersionCompatible,
100
+ REVERSE_REQUEST_TIMEOUT_MS,
101
+ HANDSHAKE_TIMEOUT_MS,
102
+ CANCEL_SETTLE_GRACE_MS,
103
+ CRASH_REBUILD_MAX_ATTEMPTS,
104
+ CRASH_REBUILD_BACKOFF_MS,
105
+ STDERR_TAIL_CHARS,
106
+ ENGINE_EVENT_COALESCE_ENV,
107
+ ENGINE_EVENT_COALESCE_DEFAULT,
108
+ ENGINE_PROTOCOL_ERROR_CODES,
109
+ isEngineProtocolErrorCode,
110
+ ENGINE_ERROR_CODE_PREFIX,
111
+ isEngineErrorPassthroughCode,
112
+ EngineSdkError,
113
+ engineProtocolMismatchError,
114
+ engineConversationUnsupportedError,
115
+ assertChatConversationSupported,
116
+ STDOUT_TAIL_ECHO_CHARS,
117
+ ENGINE_TIMEOUT_RECOVERY,
118
+ engineTimeoutDetail,
119
+ schemaEmulationFailedDetail
120
+ };
@@ -0,0 +1,16 @@
1
+ // src/error-message.ts
2
+ function toErrorMessage(e) {
3
+ if (e instanceof Error) return e.message;
4
+ if (typeof e === "object" && e !== null) {
5
+ try {
6
+ return JSON.stringify(e);
7
+ } catch {
8
+ return String(e);
9
+ }
10
+ }
11
+ return String(e);
12
+ }
13
+
14
+ export {
15
+ toErrorMessage
16
+ };
@@ -0,0 +1,46 @@
1
+ // src/journal-io.ts
2
+ import { readFileSync } from "fs";
3
+ function replayJournal(path) {
4
+ let raw;
5
+ try {
6
+ raw = readFileSync(path, "utf8");
7
+ } catch {
8
+ return [];
9
+ }
10
+ const lines = [];
11
+ for (const row of raw.split("\n")) {
12
+ const trimmed = row.trim();
13
+ if (trimmed === "") continue;
14
+ const parsed = parseLine(trimmed);
15
+ if (parsed !== void 0) lines.push(parsed);
16
+ }
17
+ lines.sort((a, b) => a.seq - b.seq);
18
+ return lines.map((l) => l.event);
19
+ }
20
+ function parseLine(trimmed) {
21
+ let parsed;
22
+ try {
23
+ parsed = JSON.parse(trimmed);
24
+ } catch {
25
+ return void 0;
26
+ }
27
+ if (typeof parsed !== "object" || parsed === null) return void 0;
28
+ const rec = parsed;
29
+ const event = rec.event;
30
+ if (rec.v !== 1 || typeof rec.ts !== "number" || typeof rec.seq !== "number") return void 0;
31
+ if (typeof event !== "object" || event === null || typeof event.type !== "string") {
32
+ return void 0;
33
+ }
34
+ return {
35
+ v: 1,
36
+ ts: rec.ts,
37
+ taskId: typeof rec.taskId === "string" ? rec.taskId : "",
38
+ engineId: typeof rec.engineId === "string" ? rec.engineId : "",
39
+ seq: rec.seq,
40
+ event
41
+ };
42
+ }
43
+
44
+ export {
45
+ replayJournal
46
+ };
@@ -0,0 +1,11 @@
1
+ // src/port-contract.ts
2
+ function parseCtxModel(ref) {
3
+ if (ref === void 0 || ref.trim() === "") return void 0;
4
+ const slash = ref.indexOf("/");
5
+ if (slash <= 0 || slash === ref.length - 1) return void 0;
6
+ return { provider: ref.slice(0, slash), id: ref.slice(slash + 1) };
7
+ }
8
+
9
+ export {
10
+ parseCtxModel
11
+ };