oasis_test 0.1.137 → 0.1.139
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/index.js +599 -135
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -719,11 +719,16 @@ var init_link_windows = __esm({
|
|
|
719
719
|
browserStaleAfterMs: 45e3,
|
|
720
720
|
/**
|
|
721
721
|
* 会话进程发完 `session_exited` 后等 ack 的时限(`session-process.ts`)。
|
|
722
|
-
*
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
|
|
726
|
-
|
|
722
|
+
*
|
|
723
|
+
* ADR 0300 D7:取 90 s 覆盖一次 serve 重启(实测停服 27.6~27.9 s,数据面会话最慢 38.6 s 连回,
|
|
724
|
+
* 证据 C/D)。会话进程在这段时间里**不退出**、保持数据面重连;serve 回来后 `ws.on("open")` 会
|
|
725
|
+
* 重发 outbox 里未回执的 `session_exited`(`session-process.ts` 的 `for (const m of this.outbox)`),
|
|
726
|
+
* 服务端 `reconcileChatExitFrame` 按 `dispatchId` 幂等收口——退出帧不再随停服窗口蒸发、账本不再
|
|
727
|
+
* 停在 running 等时钟扫描判孤儿。仍小于会话自尽窗 `SESSION_LIMITS.suicideAfterUnreachableMs`(5 min),
|
|
728
|
+
* 等 ack 期间不会先自尽。**更狠的一层**(进程被 TTL/自尽强杀于窗口内时把未回执帧落 `exit.json`、
|
|
729
|
+
* 由 daemon 信使补发)属 D7 后续,另计。
|
|
730
|
+
*/
|
|
731
|
+
exitAckWaitMs: 9e4,
|
|
727
732
|
/** hub 对「暂无人认领」的会话在 serve 冷启动后挂起重判的宽限(`daemon-hub.ts`)。 */
|
|
728
733
|
hubColdStartGraceMs: 9e4,
|
|
729
734
|
/** orphan-sweep 判「账上在跑、四张认领表都不认」为孤儿的宽限(`serve.ts`)。 */
|
|
@@ -19191,7 +19196,9 @@ var init_kernel_bridge = __esm({
|
|
|
19191
19196
|
handActorId: args.hand ?? null,
|
|
19192
19197
|
...args.intent !== void 0 ? { intent: args.intent } : {},
|
|
19193
19198
|
...args.source !== void 0 ? { source: args.source } : {},
|
|
19194
|
-
|
|
19199
|
+
// Escalation hands responsibility to the workorder owner; never address only the stalled executor.
|
|
19200
|
+
// Human/team lead delivery additionally uses the same live recipient projection as the Inbox.
|
|
19201
|
+
recipients: [...new Set([brief?.owner ?? art?.owner].filter((id) => !!id))],
|
|
19195
19202
|
attachments: []
|
|
19196
19203
|
}
|
|
19197
19204
|
});
|
|
@@ -33366,14 +33373,14 @@ var require_axios = __commonJS({
|
|
|
33366
33373
|
navigator: _navigator,
|
|
33367
33374
|
origin
|
|
33368
33375
|
});
|
|
33369
|
-
var
|
|
33376
|
+
var platform2 = {
|
|
33370
33377
|
...utils,
|
|
33371
33378
|
...platform$1
|
|
33372
33379
|
};
|
|
33373
33380
|
function toURLEncodedForm(data, options) {
|
|
33374
|
-
return toFormData(data, new
|
|
33381
|
+
return toFormData(data, new platform2.classes.URLSearchParams(), {
|
|
33375
33382
|
visitor: function(value2, key, path40, helpers) {
|
|
33376
|
-
if (
|
|
33383
|
+
if (platform2.isNode && utils$1.isBuffer(value2)) {
|
|
33377
33384
|
this.append(key, value2.toString("base64"));
|
|
33378
33385
|
return false;
|
|
33379
33386
|
}
|
|
@@ -33526,8 +33533,8 @@ var require_axios = __commonJS({
|
|
|
33526
33533
|
maxContentLength: -1,
|
|
33527
33534
|
maxBodyLength: -1,
|
|
33528
33535
|
env: {
|
|
33529
|
-
FormData:
|
|
33530
|
-
Blob:
|
|
33536
|
+
FormData: platform2.classes.FormData,
|
|
33537
|
+
Blob: platform2.classes.Blob
|
|
33531
33538
|
},
|
|
33532
33539
|
validateStatus: function validateStatus(status) {
|
|
33533
33540
|
return status >= 200 && status < 300;
|
|
@@ -33890,7 +33897,7 @@ var require_axios = __commonJS({
|
|
|
33890
33897
|
}
|
|
33891
33898
|
var DATA_URL_PATTERN = /^(?:([^;]+);)?(?:[^;]+;)?(base64|),([\s\S]*)$/;
|
|
33892
33899
|
function fromDataURI(uri, asBlob, options) {
|
|
33893
|
-
const _Blob = options && options.Blob ||
|
|
33900
|
+
const _Blob = options && options.Blob || platform2.classes.Blob;
|
|
33894
33901
|
const protocol = parseProtocol(uri);
|
|
33895
33902
|
if (asBlob === void 0 && _Blob) {
|
|
33896
33903
|
asBlob = true;
|
|
@@ -34048,7 +34055,7 @@ var require_axios = __commonJS({
|
|
|
34048
34055
|
}
|
|
34049
34056
|
};
|
|
34050
34057
|
var readBlob$1 = readBlob;
|
|
34051
|
-
var BOUNDARY_ALPHABET =
|
|
34058
|
+
var BOUNDARY_ALPHABET = platform2.ALPHABET.ALPHA_DIGIT + "-_";
|
|
34052
34059
|
var textEncoder = typeof TextEncoder === "function" ? new TextEncoder() : new util__default["default"].TextEncoder();
|
|
34053
34060
|
var CRLF = "\r\n";
|
|
34054
34061
|
var CRLF_BYTES = textEncoder.encode(CRLF);
|
|
@@ -34094,7 +34101,7 @@ var require_axios = __commonJS({
|
|
|
34094
34101
|
const {
|
|
34095
34102
|
tag = "form-data-boundary",
|
|
34096
34103
|
size = 25,
|
|
34097
|
-
boundary = tag + "-" +
|
|
34104
|
+
boundary = tag + "-" + platform2.generateString(size, BOUNDARY_ALPHABET)
|
|
34098
34105
|
} = options || {};
|
|
34099
34106
|
if (!utils$1.isFormData(form)) {
|
|
34100
34107
|
throw TypeError("FormData instance required");
|
|
@@ -34323,7 +34330,7 @@ var require_axios = __commonJS({
|
|
|
34323
34330
|
var isBrotliSupported = utils$1.isFunction(zlib__default["default"].createBrotliDecompress);
|
|
34324
34331
|
var { http: httpFollow, https: httpsFollow } = followRedirects__default["default"];
|
|
34325
34332
|
var isHttps = /https:?/;
|
|
34326
|
-
var supportedProtocols =
|
|
34333
|
+
var supportedProtocols = platform2.protocols.map((protocol) => {
|
|
34327
34334
|
return protocol + ":";
|
|
34328
34335
|
});
|
|
34329
34336
|
var flushOnFinish = (stream2, [throttled, flush]) => {
|
|
@@ -34575,7 +34582,7 @@ var require_axios = __commonJS({
|
|
|
34575
34582
|
}
|
|
34576
34583
|
});
|
|
34577
34584
|
const fullPath = buildFullPath(config2.baseURL, config2.url, config2.allowAbsoluteUrls);
|
|
34578
|
-
const parsed = new URL(fullPath,
|
|
34585
|
+
const parsed = new URL(fullPath, platform2.hasBrowserEnv ? platform2.origin : void 0);
|
|
34579
34586
|
const protocol = parsed.protocol || supportedProtocols[0];
|
|
34580
34587
|
if (protocol === "data:") {
|
|
34581
34588
|
if (config2.maxContentLength > -1) {
|
|
@@ -34983,14 +34990,14 @@ var require_axios = __commonJS({
|
|
|
34983
34990
|
}
|
|
34984
34991
|
});
|
|
34985
34992
|
};
|
|
34986
|
-
var isURLSameOrigin =
|
|
34987
|
-
url2 = new URL(url2,
|
|
34993
|
+
var isURLSameOrigin = platform2.hasStandardBrowserEnv ? /* @__PURE__ */ ((origin2, isMSIE) => (url2) => {
|
|
34994
|
+
url2 = new URL(url2, platform2.origin);
|
|
34988
34995
|
return origin2.protocol === url2.protocol && origin2.host === url2.host && (isMSIE || origin2.port === url2.port);
|
|
34989
34996
|
})(
|
|
34990
|
-
new URL(
|
|
34991
|
-
|
|
34997
|
+
new URL(platform2.origin),
|
|
34998
|
+
platform2.navigator && /(msie|trident)/i.test(platform2.navigator.userAgent)
|
|
34992
34999
|
) : () => true;
|
|
34993
|
-
var cookies =
|
|
35000
|
+
var cookies = platform2.hasStandardBrowserEnv ? (
|
|
34994
35001
|
// Standard browser envs support document.cookie
|
|
34995
35002
|
{
|
|
34996
35003
|
write(name, value2, expires, path40, domain2, secure, sameSite) {
|
|
@@ -35131,7 +35138,7 @@ var require_axios = __commonJS({
|
|
|
35131
35138
|
);
|
|
35132
35139
|
}
|
|
35133
35140
|
if (utils$1.isFormData(data)) {
|
|
35134
|
-
if (
|
|
35141
|
+
if (platform2.hasStandardBrowserEnv || platform2.hasStandardBrowserWebWorkerEnv) {
|
|
35135
35142
|
headers.setContentType(void 0);
|
|
35136
35143
|
} else if (utils$1.isFunction(data.getHeaders)) {
|
|
35137
35144
|
const formHeaders = data.getHeaders();
|
|
@@ -35143,7 +35150,7 @@ var require_axios = __commonJS({
|
|
|
35143
35150
|
});
|
|
35144
35151
|
}
|
|
35145
35152
|
}
|
|
35146
|
-
if (
|
|
35153
|
+
if (platform2.hasStandardBrowserEnv) {
|
|
35147
35154
|
withXSRFToken && utils$1.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));
|
|
35148
35155
|
if (withXSRFToken || withXSRFToken !== false && isURLSameOrigin(newConfig.url)) {
|
|
35149
35156
|
const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName);
|
|
@@ -35281,7 +35288,7 @@ var require_axios = __commonJS({
|
|
|
35281
35288
|
}
|
|
35282
35289
|
}
|
|
35283
35290
|
const protocol = parseProtocol(_config.url);
|
|
35284
|
-
if (protocol &&
|
|
35291
|
+
if (protocol && platform2.protocols.indexOf(protocol) === -1) {
|
|
35285
35292
|
reject(
|
|
35286
35293
|
new AxiosError$1(
|
|
35287
35294
|
"Unsupported protocol " + protocol + ":",
|
|
@@ -35441,7 +35448,7 @@ var require_axios = __commonJS({
|
|
|
35441
35448
|
const encodeText = isFetchSupported && (typeof TextEncoder$1 === "function" ? /* @__PURE__ */ ((encoder) => (str2) => encoder.encode(str2))(new TextEncoder$1()) : async (str2) => new Uint8Array(await new Request(str2).arrayBuffer()));
|
|
35442
35449
|
const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => {
|
|
35443
35450
|
let duplexAccessed = false;
|
|
35444
|
-
const hasContentType = new Request(
|
|
35451
|
+
const hasContentType = new Request(platform2.origin, {
|
|
35445
35452
|
body: new ReadableStream$1(),
|
|
35446
35453
|
method: "POST",
|
|
35447
35454
|
get duplex() {
|
|
@@ -35478,7 +35485,7 @@ var require_axios = __commonJS({
|
|
|
35478
35485
|
return body2.size;
|
|
35479
35486
|
}
|
|
35480
35487
|
if (utils$1.isSpecCompliantForm(body2)) {
|
|
35481
|
-
const _request = new Request(
|
|
35488
|
+
const _request = new Request(platform2.origin, {
|
|
35482
35489
|
method: "POST",
|
|
35483
35490
|
body: body2
|
|
35484
35491
|
});
|
|
@@ -150194,6 +150201,40 @@ var init_live_chat = __esm({
|
|
|
150194
150201
|
}
|
|
150195
150202
|
};
|
|
150196
150203
|
}
|
|
150204
|
+
/**
|
|
150205
|
+
* serve 重启后**重挂**一个占位轮(ADR 0300 D4)。该会话在本进程注册表里已有轮(真轮或另一个占位轮)
|
|
150206
|
+
* 则不动、返回 null——保证幂等且绝不覆盖真轮。占位轮 status=running、缓冲为空、句柄不带 appendInput
|
|
150207
|
+
* (`canAppend` 因此为 false),`kill()` 走注入的 `onStop`(账本收口)并把本轮标 error 让在挂的观众
|
|
150208
|
+
* 就地收到终止。节点重连时恢复路的 {@link start} 会替掉它。
|
|
150209
|
+
*/
|
|
150210
|
+
reopenForRecovery(chatSessionId, opts) {
|
|
150211
|
+
if (this.turns.has(chatSessionId)) return null;
|
|
150212
|
+
let ctrl;
|
|
150213
|
+
const handle = {
|
|
150214
|
+
runtimeSessionId: opts.runtimeSessionId,
|
|
150215
|
+
...opts.runId ? { runId: opts.runId } : {},
|
|
150216
|
+
canAppendInput: false,
|
|
150217
|
+
kill: () => {
|
|
150218
|
+
try {
|
|
150219
|
+
opts.onStop?.();
|
|
150220
|
+
} finally {
|
|
150221
|
+
ctrl?.finish("error");
|
|
150222
|
+
}
|
|
150223
|
+
}
|
|
150224
|
+
};
|
|
150225
|
+
ctrl = this.start(chatSessionId, handle);
|
|
150226
|
+
const turn = this.turns.get(chatSessionId);
|
|
150227
|
+
if (turn) turn.recovering = true;
|
|
150228
|
+
return ctrl;
|
|
150229
|
+
}
|
|
150230
|
+
/** 占位轮的最后一个观众断开即回收:没真 runtime 喂它,留着只会占内存、也会让 `isRunning` 恒真。 */
|
|
150231
|
+
evictIfEmptyRecovering(chatSessionId, turn) {
|
|
150232
|
+
if (!turn.recovering || turn.status !== "running") return;
|
|
150233
|
+
if (turn.subscribers.size > 0 || turn.liveSubscribers.size > 0) return;
|
|
150234
|
+
if (this.turns.get(chatSessionId) !== turn) return;
|
|
150235
|
+
if (turn.evictTimer) clearTimeout(turn.evictTimer);
|
|
150236
|
+
this.turns.delete(chatSessionId);
|
|
150237
|
+
}
|
|
150197
150238
|
emitLive(turn, event) {
|
|
150198
150239
|
turn.liveTurnId = event.turnId;
|
|
150199
150240
|
const mergeField = this.mergeableLiveField(event);
|
|
@@ -150267,6 +150308,7 @@ var init_live_chat = __esm({
|
|
|
150267
150308
|
gap,
|
|
150268
150309
|
detach: () => {
|
|
150269
150310
|
turn.subscribers.delete(sub);
|
|
150311
|
+
this.evictIfEmptyRecovering(chatSessionId, turn);
|
|
150270
150312
|
}
|
|
150271
150313
|
};
|
|
150272
150314
|
}
|
|
@@ -150286,6 +150328,7 @@ var init_live_chat = __esm({
|
|
|
150286
150328
|
epoch: turn.liveEpoch,
|
|
150287
150329
|
detach: () => {
|
|
150288
150330
|
turn.liveSubscribers.delete(sub);
|
|
150331
|
+
this.evictIfEmptyRecovering(chatSessionId, turn);
|
|
150289
150332
|
}
|
|
150290
150333
|
};
|
|
150291
150334
|
}
|
|
@@ -150409,7 +150452,9 @@ var init_live_chat = __esm({
|
|
|
150409
150452
|
* 建单草案 submit 发生在这一轮内:用它给草案盖上「产出轮次」标记,供 friday 重进对话页把每版
|
|
150410
150453
|
* 草案归位到产出它的那条助手消息(message.runId 对齐)。 */
|
|
150411
150454
|
runFor(chatSessionId) {
|
|
150412
|
-
|
|
150455
|
+
const turn = this.turns.get(chatSessionId);
|
|
150456
|
+
if (!turn || turn.recovering) return void 0;
|
|
150457
|
+
return turn.runId;
|
|
150413
150458
|
}
|
|
150414
150459
|
/**
|
|
150415
150460
|
* 反查该会话当前驻留那一轮**这一段**的 assistant 行 id(无进行中/grace 轮、或还没落库时
|
|
@@ -150418,7 +150463,9 @@ var init_live_chat = __esm({
|
|
|
150418
150463
|
* 两段共用同一个 runId,钉不出前后段的区别,而那正是本字段存在的理由。
|
|
150419
150464
|
*/
|
|
150420
150465
|
messageFor(chatSessionId) {
|
|
150421
|
-
|
|
150466
|
+
const turn = this.turns.get(chatSessionId);
|
|
150467
|
+
if (!turn || turn.recovering) return void 0;
|
|
150468
|
+
return turn.assistantMessageId;
|
|
150422
150469
|
}
|
|
150423
150470
|
/** 测试/排障用:当前驻留的会话数。 */
|
|
150424
150471
|
size() {
|
|
@@ -184602,16 +184649,16 @@ var init_tool_home = __esm({
|
|
|
184602
184649
|
});
|
|
184603
184650
|
|
|
184604
184651
|
// ../connectors/src/_base/install.ts
|
|
184605
|
-
function installPlan(cmd,
|
|
184652
|
+
function installPlan(cmd, platform2, toolsPrefix) {
|
|
184606
184653
|
if (cmd === "lark-cli") {
|
|
184607
|
-
const npm =
|
|
184654
|
+
const npm = platform2 === "win32" ? "npm.cmd" : "npm";
|
|
184608
184655
|
return [{ file: npm, args: ["install", "-g", "--prefix", toolsPrefix, "@larksuite/cli"], ensureDir: toolsPrefix }];
|
|
184609
184656
|
}
|
|
184610
184657
|
const pkg = cmd === "gh" ? { brew: "gh", apt: "gh", dnf: "gh", pacman: "github-cli", apk: "github-cli", winget: "GitHub.cli", choco: "gh", scoop: "gh" } : { brew: "git", apt: "git", dnf: "git", pacman: "git", apk: "git", winget: "Git.Git", choco: "git", scoop: "git" };
|
|
184611
|
-
if (
|
|
184658
|
+
if (platform2 === "darwin") {
|
|
184612
184659
|
return [{ file: "brew", args: ["install", pkg.brew], requires: "brew" }];
|
|
184613
184660
|
}
|
|
184614
|
-
if (
|
|
184661
|
+
if (platform2 === "win32") {
|
|
184615
184662
|
return [
|
|
184616
184663
|
{ file: "winget", args: ["install", "--silent", "--accept-package-agreements", "--accept-source-agreements", "-e", "--id", pkg.winget], requires: "winget" },
|
|
184617
184664
|
{ file: "choco", args: ["install", "-y", pkg.choco], requires: "choco" },
|
|
@@ -194314,6 +194361,35 @@ ${task}` : task;
|
|
|
194314
194361
|
}
|
|
194315
194362
|
});
|
|
194316
194363
|
|
|
194364
|
+
// ../adapters/src/_core/pdeathsig.ts
|
|
194365
|
+
function pdeathsigAvailable(probe = defaultProbe) {
|
|
194366
|
+
if (cachedAvailable === void 0) cachedAvailable = probe();
|
|
194367
|
+
return cachedAvailable;
|
|
194368
|
+
}
|
|
194369
|
+
function defaultProbe() {
|
|
194370
|
+
if (os6.platform() !== "linux") return false;
|
|
194371
|
+
try {
|
|
194372
|
+
const help = (0, import_node_child_process13.execFileSync)("setpriv", ["--help"], { stdio: ["ignore", "pipe", "ignore"], timeout: 2e3 }).toString();
|
|
194373
|
+
return help.includes("--pdeathsig");
|
|
194374
|
+
} catch {
|
|
194375
|
+
return false;
|
|
194376
|
+
}
|
|
194377
|
+
}
|
|
194378
|
+
function pdeathsigWrap(bin, args) {
|
|
194379
|
+
return { bin: "setpriv", args: ["--pdeathsig", "SIGKILL", "--", bin, ...args] };
|
|
194380
|
+
}
|
|
194381
|
+
function shouldBindRuntimePdeathsig() {
|
|
194382
|
+
return process.env["OASIS_BIND_RUNTIME_PDEATHSIG"] === "1" && pdeathsigAvailable();
|
|
194383
|
+
}
|
|
194384
|
+
var import_node_child_process13, os6, cachedAvailable;
|
|
194385
|
+
var init_pdeathsig = __esm({
|
|
194386
|
+
"../adapters/src/_core/pdeathsig.ts"() {
|
|
194387
|
+
"use strict";
|
|
194388
|
+
import_node_child_process13 = require("node:child_process");
|
|
194389
|
+
os6 = __toESM(require("node:os"), 1);
|
|
194390
|
+
}
|
|
194391
|
+
});
|
|
194392
|
+
|
|
194317
194393
|
// ../adapters/src/_core/subprocess.ts
|
|
194318
194394
|
async function materialize(job, cfg) {
|
|
194319
194395
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
@@ -194416,11 +194492,12 @@ async function runStreamJson(job, cfg) {
|
|
|
194416
194492
|
...cfg.workRoot !== void 0 ? { workRoot: cfg.workRoot } : {},
|
|
194417
194493
|
...cfg.env !== void 0 ? { extraEnvEarly: cfg.env } : {}
|
|
194418
194494
|
});
|
|
194419
|
-
const
|
|
194495
|
+
const direct = shouldBindRuntimePdeathsig() ? pdeathsigWrap(cfg.bin, args) : { bin: cfg.bin, args };
|
|
194496
|
+
const child = containerized ? (0, import_node_child_process14.spawn)(containerized.bin, containerized.args, {
|
|
194420
194497
|
cwd: dir,
|
|
194421
194498
|
env: scrubLeakyEnv(process.env),
|
|
194422
194499
|
stdio: ["ignore", "pipe", "pipe"]
|
|
194423
|
-
}) : (0,
|
|
194500
|
+
}) : (0, import_node_child_process14.spawn)(direct.bin, direct.args, {
|
|
194424
194501
|
cwd: dir,
|
|
194425
194502
|
env: buildEnv(job, cfg),
|
|
194426
194503
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -194525,11 +194602,12 @@ async function runOneShotText(job, cfg) {
|
|
|
194525
194602
|
...cfg.workRoot !== void 0 ? { workRoot: cfg.workRoot } : {},
|
|
194526
194603
|
...cfg.env !== void 0 ? { extraEnvEarly: cfg.env } : {}
|
|
194527
194604
|
});
|
|
194528
|
-
const
|
|
194605
|
+
const direct = shouldBindRuntimePdeathsig() ? pdeathsigWrap(cfg.bin, args) : { bin: cfg.bin, args };
|
|
194606
|
+
const child = containerized ? (0, import_node_child_process14.spawn)(containerized.bin, containerized.args, {
|
|
194529
194607
|
cwd: dir,
|
|
194530
194608
|
env: scrubLeakyEnv(process.env),
|
|
194531
194609
|
stdio: ["ignore", "pipe", "pipe"]
|
|
194532
|
-
}) : (0,
|
|
194610
|
+
}) : (0, import_node_child_process14.spawn)(direct.bin, direct.args, {
|
|
194533
194611
|
cwd: dir,
|
|
194534
194612
|
env: buildEnv(job, cfg),
|
|
194535
194613
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -194608,11 +194686,11 @@ async function runOneShotText(job, cfg) {
|
|
|
194608
194686
|
}
|
|
194609
194687
|
});
|
|
194610
194688
|
}
|
|
194611
|
-
var
|
|
194689
|
+
var import_node_child_process14, import_node_crypto29, fs14, path16, readline4;
|
|
194612
194690
|
var init_subprocess = __esm({
|
|
194613
194691
|
"../adapters/src/_core/subprocess.ts"() {
|
|
194614
194692
|
"use strict";
|
|
194615
|
-
|
|
194693
|
+
import_node_child_process14 = require("node:child_process");
|
|
194616
194694
|
import_node_crypto29 = require("node:crypto");
|
|
194617
194695
|
fs14 = __toESM(require("node:fs"), 1);
|
|
194618
194696
|
path16 = __toESM(require("node:path"), 1);
|
|
@@ -194625,6 +194703,7 @@ var init_subprocess = __esm({
|
|
|
194625
194703
|
init_transcript();
|
|
194626
194704
|
init_filter_extra_args();
|
|
194627
194705
|
init_root_bypass();
|
|
194706
|
+
init_pdeathsig();
|
|
194628
194707
|
}
|
|
194629
194708
|
});
|
|
194630
194709
|
|
|
@@ -198164,6 +198243,22 @@ async function startOasisServer(opts) {
|
|
|
198164
198243
|
return;
|
|
198165
198244
|
}
|
|
198166
198245
|
const fromSeq = Math.max(0, Number(url.searchParams.get("fromSeq") ?? "0") || 0);
|
|
198246
|
+
const reopenRecoveringTurn = async () => {
|
|
198247
|
+
if (!opts.chatTurns) return;
|
|
198248
|
+
const active = await opts.chatTurns.activeTurn(sid).catch(() => null);
|
|
198249
|
+
if (!active || active.status !== "running") return;
|
|
198250
|
+
liveChat.reopenForRecovery(sid, {
|
|
198251
|
+
runtimeSessionId: cs.runtimeSessionId ?? active.dispatchId ?? "",
|
|
198252
|
+
...active.assistantRunId ? { runId: active.assistantRunId } : {},
|
|
198253
|
+
onStop: () => {
|
|
198254
|
+
void opts.chatTurns?.settleTurn(active.id, {
|
|
198255
|
+
status: "cancelled",
|
|
198256
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
198257
|
+
lastError: `\u7528\u6237\u5728 serve \u91CD\u542F\u6062\u590D\u7A97\u53E3\u5185\u505C\u6B62\uFF08\u8F6E ${active.id}\uFF09`
|
|
198258
|
+
}).catch(() => void 0);
|
|
198259
|
+
}
|
|
198260
|
+
});
|
|
198261
|
+
};
|
|
198167
198262
|
const liveProtocol = url.searchParams.get("protocol") === "v2" || wantsLiveProtocol(req);
|
|
198168
198263
|
if (liveProtocol) {
|
|
198169
198264
|
const sub2 = (frame) => {
|
|
@@ -198172,7 +198267,11 @@ async function startOasisServer(opts) {
|
|
|
198172
198267
|
`);
|
|
198173
198268
|
if (frame.operation === "turn_completed" || frame.operation === "turn_failed") res.end();
|
|
198174
198269
|
};
|
|
198175
|
-
|
|
198270
|
+
let att2 = liveChat.attachLive(sid, fromSeq, sub2);
|
|
198271
|
+
if (!att2) {
|
|
198272
|
+
await reopenRecoveringTurn();
|
|
198273
|
+
att2 = liveChat.attachLive(sid, fromSeq, sub2);
|
|
198274
|
+
}
|
|
198176
198275
|
if (!att2) {
|
|
198177
198276
|
res.writeHead(204).end();
|
|
198178
198277
|
return;
|
|
@@ -198199,9 +198298,10 @@ async function startOasisServer(opts) {
|
|
|
198199
198298
|
res.end();
|
|
198200
198299
|
return;
|
|
198201
198300
|
}
|
|
198301
|
+
const attached2 = att2;
|
|
198202
198302
|
res.on("close", () => {
|
|
198203
198303
|
stopKa2();
|
|
198204
|
-
|
|
198304
|
+
attached2.detach();
|
|
198205
198305
|
});
|
|
198206
198306
|
return;
|
|
198207
198307
|
}
|
|
@@ -198211,7 +198311,11 @@ async function startOasisServer(opts) {
|
|
|
198211
198311
|
`);
|
|
198212
198312
|
if (part.type === "done") res.end();
|
|
198213
198313
|
};
|
|
198214
|
-
|
|
198314
|
+
let att = liveChat.attach(sid, fromSeq, sub);
|
|
198315
|
+
if (!att) {
|
|
198316
|
+
await reopenRecoveringTurn();
|
|
198317
|
+
att = liveChat.attach(sid, fromSeq, sub);
|
|
198318
|
+
}
|
|
198215
198319
|
if (!att) {
|
|
198216
198320
|
res.writeHead(204).end();
|
|
198217
198321
|
return;
|
|
@@ -198237,9 +198341,10 @@ async function startOasisServer(opts) {
|
|
|
198237
198341
|
res.end();
|
|
198238
198342
|
return;
|
|
198239
198343
|
}
|
|
198344
|
+
const attached = att;
|
|
198240
198345
|
res.on("close", () => {
|
|
198241
198346
|
stopKa();
|
|
198242
|
-
|
|
198347
|
+
attached.detach();
|
|
198243
198348
|
});
|
|
198244
198349
|
return;
|
|
198245
198350
|
}
|
|
@@ -205206,6 +205311,7 @@ async function sweepOrphanRuns(deps) {
|
|
|
205206
205311
|
const inFlight = await deps.inFlightRunIds();
|
|
205207
205312
|
const aliveArtifacts = await deps.aliveArtifactIds?.() ?? /* @__PURE__ */ new Set();
|
|
205208
205313
|
const apiActive = await deps.apiActiveDispatchIds?.() ?? /* @__PURE__ */ new Set();
|
|
205314
|
+
const liveSessions = await deps.liveSessionRunIds?.() ?? /* @__PURE__ */ new Set();
|
|
205209
205315
|
const orphaned = [];
|
|
205210
205316
|
const cappedOut = [];
|
|
205211
205317
|
const rescued = [];
|
|
@@ -205231,7 +205337,7 @@ async function sweepOrphanRuns(deps) {
|
|
|
205231
205337
|
}
|
|
205232
205338
|
continue;
|
|
205233
205339
|
}
|
|
205234
|
-
const claimed = inFlight.has(run.id) || run.artifactId !== null && aliveArtifacts.has(run.artifactId) || apiActive.has(run.id);
|
|
205340
|
+
const claimed = inFlight.has(run.id) || run.artifactId !== null && aliveArtifacts.has(run.artifactId) || apiActive.has(run.id) || liveSessions.has(run.id);
|
|
205235
205341
|
if (!inFlight.has(run.id) && !(run.artifactId !== null && aliveArtifacts.has(run.artifactId)) && apiActive.has(run.id) && ageMs > deps.orphanGraceMs) {
|
|
205236
205342
|
rescued.push(run.id);
|
|
205237
205343
|
deps.log?.(
|
|
@@ -205268,7 +205374,7 @@ async function sweepDroppedDispatches(deps) {
|
|
|
205268
205374
|
const result = {
|
|
205269
205375
|
scanned: 0,
|
|
205270
205376
|
redispatched: [],
|
|
205271
|
-
skipped: { inFlight: 0, ledgerOpen: 0, backoff: 0, notAgent: 0, failed: 0 }
|
|
205377
|
+
skipped: { inFlight: 0, ledgerOpen: 0, backoff: 0, notAgent: 0, blocked: 0, failed: 0 }
|
|
205272
205378
|
};
|
|
205273
205379
|
const createdBefore = new Date(deps.now - deps.graceMs).toISOString();
|
|
205274
205380
|
const candidates = await deps.listNeverStarted(createdBefore, CANDIDATE_LIMIT);
|
|
@@ -205301,6 +205407,10 @@ async function sweepDroppedDispatches(deps) {
|
|
|
205301
205407
|
continue;
|
|
205302
205408
|
}
|
|
205303
205409
|
try {
|
|
205410
|
+
if (deps.beforeRedispatch && !await deps.beforeRedispatch(c)) {
|
|
205411
|
+
result.skipped.blocked++;
|
|
205412
|
+
continue;
|
|
205413
|
+
}
|
|
205304
205414
|
await deps.redispatch(c.workId, c.workorderId);
|
|
205305
205415
|
result.redispatched.push(c.workId);
|
|
205306
205416
|
} catch {
|
|
@@ -205354,6 +205464,35 @@ var init_dispatch_mapping_rebuild = __esm({
|
|
|
205354
205464
|
}
|
|
205355
205465
|
});
|
|
205356
205466
|
|
|
205467
|
+
// ../server/src/dispatch-binding-diagnosis.ts
|
|
205468
|
+
async function prepareDroppedDispatch(work, deps) {
|
|
205469
|
+
const { kernel } = deps;
|
|
205470
|
+
await kernel.refreshModel?.();
|
|
205471
|
+
const node2 = kernel.model.artifacts.get(work.nodeId);
|
|
205472
|
+
const snap = await kernel.getStore().transaction((tx) => tx.loadWorkorder(work.workorderId));
|
|
205473
|
+
const current = snap?.works.find((w2) => w2.id === work.workId);
|
|
205474
|
+
if (!snap || !current || current.status !== "running" || current.startedAt || current.sessionRef || current.endedAt || !snap.nodes.some((n) => n.id === work.nodeId && n.latestWorkId === current.id && !n.cancelledAt) || !node2 || node2.workspace !== work.workorderId || lifecycleOf(kernel.model, node2.id) !== "active" || kernel.model.pausedWorkorders.has(work.workorderId) || isHeld(kernel.model, node2.id)) return false;
|
|
205475
|
+
if (snap.issues.some((i) => i.kind === "escalation" && i.aboutNodeId === node2.id && !i.resolvedAt && i.intent !== "advisory")) return false;
|
|
205476
|
+
if (!work.assigneeActorId) return false;
|
|
205477
|
+
const binding = await deps.bindingFor(work.assigneeActorId);
|
|
205478
|
+
if (!binding?.nodeId) return true;
|
|
205479
|
+
const runtimeNode = await deps.nodeFor(binding.nodeId);
|
|
205480
|
+
if (runtimeNode && runtimeNode.status !== "deleted") return true;
|
|
205481
|
+
await kernel.escalate({
|
|
205482
|
+
artifactId: node2.id,
|
|
205483
|
+
actor: SYSTEM_ACTOR,
|
|
205484
|
+
source: "dispatch:missing-node",
|
|
205485
|
+
reason: `\u8FD9\u4E00\u6B65\u8FD8\u6CA1\u6709\u542F\u52A8\uFF1A\u6267\u884C\u4EBA\u7684\u8FD0\u884C\u65F6\u7ED1\u5B9A\u6307\u5411${runtimeNode ? "\u5DF2\u5220\u9664" : "\u672A\u6CE8\u518C"}\u7684\u8282\u70B9 ${binding.nodeId}\u3002\u8BF7\u6062\u590D\u8BE5\u8282\u70B9\uFF0C\u6216\u4E3A\u6267\u884C\u4EBA ${work.assigneeActorId} \u9009\u62E9\u5DF2\u6709\u4E14\u914D\u7F6E\u6B63\u786E\u7684\u8282\u70B9\uFF1B\u4FEE\u590D\u540E\u5173\u95ED\u8FD9\u6761\u4E0A\u62A5\uFF0C\u6D41\u7A0B\u624D\u4F1A\u7EE7\u7EED\u3002\u672C\u6B21\u68C0\u67E5\u6CA1\u6709\u7EC8\u6B62\u4F1A\u8BDD\uFF0C\u4E5F\u6CA1\u6709\u6D88\u8017 work \u91CD\u8BD5\u6B21\u6570\u3002`
|
|
205486
|
+
});
|
|
205487
|
+
return false;
|
|
205488
|
+
}
|
|
205489
|
+
var init_dispatch_binding_diagnosis = __esm({
|
|
205490
|
+
"../server/src/dispatch-binding-diagnosis.ts"() {
|
|
205491
|
+
"use strict";
|
|
205492
|
+
init_src5();
|
|
205493
|
+
}
|
|
205494
|
+
});
|
|
205495
|
+
|
|
205357
205496
|
// ../server/src/zero-output-breaker.ts
|
|
205358
205497
|
function absorb(b2, r, startedMs) {
|
|
205359
205498
|
b2.count += 1;
|
|
@@ -205878,14 +206017,14 @@ function classifyDeployRun(facts) {
|
|
|
205878
206017
|
if (facts.anyContainingInProgress) return { kind: "running", note: "\u627F\u8F7D\u672C\u6B21\u4EA4\u4ED8\u7684\u90E8\u7F72 run \u4ECD\u5728\u8FDB\u884C" };
|
|
205879
206018
|
return { kind: "pending", note: "\u8FD8\u6CA1\u770B\u5230\u627F\u8F7D\u672C\u6B21\u4EA4\u4ED8\u7684\u90E8\u7F72 run" };
|
|
205880
206019
|
}
|
|
205881
|
-
var
|
|
206020
|
+
var import_node_child_process15, import_node_util5, execFile5, GhDeployProvider;
|
|
205882
206021
|
var init_deploy_provider = __esm({
|
|
205883
206022
|
"../server/src/git/deploy-provider.ts"() {
|
|
205884
206023
|
"use strict";
|
|
205885
|
-
|
|
206024
|
+
import_node_child_process15 = require("node:child_process");
|
|
205886
206025
|
import_node_util5 = require("node:util");
|
|
205887
206026
|
init_remote_util();
|
|
205888
|
-
execFile5 = (0, import_node_util5.promisify)(
|
|
206027
|
+
execFile5 = (0, import_node_util5.promisify)(import_node_child_process15.execFile);
|
|
205889
206028
|
GhDeployProvider = class {
|
|
205890
206029
|
constructor(opts = {}) {
|
|
205891
206030
|
this.opts = opts;
|
|
@@ -206121,14 +206260,14 @@ function makeDefaultBranchResolver(opts) {
|
|
|
206121
206260
|
}
|
|
206122
206261
|
};
|
|
206123
206262
|
}
|
|
206124
|
-
var
|
|
206263
|
+
var import_node_child_process16, import_node_util6, execFile6;
|
|
206125
206264
|
var init_default_branch = __esm({
|
|
206126
206265
|
"../server/src/git/default-branch.ts"() {
|
|
206127
206266
|
"use strict";
|
|
206128
|
-
|
|
206267
|
+
import_node_child_process16 = require("node:child_process");
|
|
206129
206268
|
import_node_util6 = require("node:util");
|
|
206130
206269
|
init_remote_util();
|
|
206131
|
-
execFile6 = (0, import_node_util6.promisify)(
|
|
206270
|
+
execFile6 = (0, import_node_util6.promisify)(import_node_child_process16.execFile);
|
|
206132
206271
|
}
|
|
206133
206272
|
});
|
|
206134
206273
|
|
|
@@ -207463,6 +207602,14 @@ var init_daemon_hub = __esm({
|
|
|
207463
207602
|
sessionMeta = /* @__PURE__ */ new Map();
|
|
207464
207603
|
sessionConnectListeners = [];
|
|
207465
207604
|
sessionDisconnectListeners = [];
|
|
207605
|
+
// ── ADR 0300 D2「日志复制」:帧号 + 累积 ackSeq + 幂等摄入 ────────────────────────────
|
|
207606
|
+
// 只对自报 supportsFrameSeq 的会话生效;老会话这三张表始终为空、逐字走原 outbox 语义。
|
|
207607
|
+
/** 自报支持帧号的 dispatchId。 */
|
|
207608
|
+
frameSeqSupported = /* @__PURE__ */ new Set();
|
|
207609
|
+
/** 每 dispatch 已按序摄入的最高节点帧号(累积水位)。跨重连保留、`session_exited` 后延迟清。 */
|
|
207610
|
+
frameWatermark = /* @__PURE__ */ new Map();
|
|
207611
|
+
/** 每 dispatch 上次回 ackSeq 的时刻——把流式期间的回执节流到 ~250ms 一次。 */
|
|
207612
|
+
lastAckSeqAt = /* @__PURE__ */ new Map();
|
|
207466
207613
|
/**
|
|
207467
207614
|
* 「这次派发归谁管、现在什么状态」的认领口。**必须由 hub 汇总,不能各 adapter 自己判**——
|
|
207468
207615
|
* serve 里同时有两个 DaemonHubAdapter(chat 一个、dispatch 一个),一次派发只属于其中一个。
|
|
@@ -207697,12 +207844,33 @@ var init_daemon_hub = __esm({
|
|
|
207697
207844
|
for (const l of this.sessionConnectListeners) l({ dispatchId, sessionId: msg.sessionId, nodeId });
|
|
207698
207845
|
void this.judgeSession(dispatchId, ws);
|
|
207699
207846
|
}
|
|
207847
|
+
if (msg.supportsFrameSeq) {
|
|
207848
|
+
this.frameSeqSupported.add(dispatchId);
|
|
207849
|
+
this.sendAckSeq(ws, dispatchId, true);
|
|
207850
|
+
}
|
|
207700
207851
|
return;
|
|
207701
207852
|
}
|
|
207702
207853
|
if (!registered) {
|
|
207703
207854
|
ws.close(1008, "session_hello required first");
|
|
207704
207855
|
return;
|
|
207705
207856
|
}
|
|
207857
|
+
if (this.frameSeqSupported.has(dispatchId)) {
|
|
207858
|
+
const seq = typeof msg.seq === "number" ? msg.seq : void 0;
|
|
207859
|
+
if (seq !== void 0) {
|
|
207860
|
+
const wm = this.frameWatermark.get(dispatchId) ?? 0;
|
|
207861
|
+
if (seq <= wm) {
|
|
207862
|
+
this.sendAckSeq(ws, dispatchId, false);
|
|
207863
|
+
return;
|
|
207864
|
+
}
|
|
207865
|
+
this.frameWatermark.set(dispatchId, seq);
|
|
207866
|
+
}
|
|
207867
|
+
for (const listener of this.messageListeners) listener(nodeId, msg);
|
|
207868
|
+
this.onMessage?.(nodeId, msg);
|
|
207869
|
+
const isExit = msg.type === "session_exited";
|
|
207870
|
+
this.sendAckSeq(ws, dispatchId, isExit);
|
|
207871
|
+
if (isExit) this.scheduleFrameStateCleanup(dispatchId);
|
|
207872
|
+
return;
|
|
207873
|
+
}
|
|
207706
207874
|
for (const listener of this.messageListeners) listener(nodeId, msg);
|
|
207707
207875
|
this.onMessage?.(nodeId, msg);
|
|
207708
207876
|
if (msg.type === "session_exited" && ws.readyState === import_websocket.default.OPEN) {
|
|
@@ -207718,6 +207886,23 @@ var init_daemon_hub = __esm({
|
|
|
207718
207886
|
});
|
|
207719
207887
|
ws.on("error", (err) => console.error(`[hub] session ${dispatchId} error:`, err.message));
|
|
207720
207888
|
}
|
|
207889
|
+
/** ADR 0300 D2:回带当前摄入水位的累积回执。流式期间节流到 ~250ms 一次,hello / 收尾帧立即回。 */
|
|
207890
|
+
sendAckSeq(ws, dispatchId, force) {
|
|
207891
|
+
if (ws.readyState !== import_websocket.default.OPEN) return;
|
|
207892
|
+
const now = Date.now();
|
|
207893
|
+
if (!force && now - (this.lastAckSeqAt.get(dispatchId) ?? 0) < 250) return;
|
|
207894
|
+
this.lastAckSeqAt.set(dispatchId, now);
|
|
207895
|
+
ws.send(JSON.stringify({ type: "ack", dispatchId, ackSeq: this.frameWatermark.get(dispatchId) ?? 0 }));
|
|
207896
|
+
}
|
|
207897
|
+
/** `session_exited` 后延迟清帧号状态:给重连重放的收尾帧留一个去重窗口,之后回收避免无界增长。 */
|
|
207898
|
+
scheduleFrameStateCleanup(dispatchId) {
|
|
207899
|
+
const t = setTimeout(() => {
|
|
207900
|
+
this.frameSeqSupported.delete(dispatchId);
|
|
207901
|
+
this.frameWatermark.delete(dispatchId);
|
|
207902
|
+
this.lastAckSeqAt.delete(dispatchId);
|
|
207903
|
+
}, 6e4);
|
|
207904
|
+
t.unref?.();
|
|
207905
|
+
}
|
|
207721
207906
|
/**
|
|
207722
207907
|
* 注册一个认领判断。返回:
|
|
207723
207908
|
* live —— 这次派发在我这儿还活着(别动它)
|
|
@@ -207830,6 +208015,22 @@ var init_daemon_hub = __esm({
|
|
|
207830
208015
|
hasSession(dispatchId) {
|
|
207831
208016
|
return this.sessionSockets.get(dispatchId)?.readyState === import_websocket.default.OPEN;
|
|
207832
208017
|
}
|
|
208018
|
+
/**
|
|
208019
|
+
* 当前持有**活着数据面连接**的全部 dispatchId(ADR-0300 D8:hub 有活连接即认领)。
|
|
208020
|
+
*
|
|
208021
|
+
* orphan-sweep 的认领来源此前只有 dispatcher 在途表、chat 在途表、节点 hello、HTTP 活性——
|
|
208022
|
+
* 独立会话进程(协调者、D2′ 后搬出 daemon 的会话)**不在这四者里**,但它们自己握着一根到 hub 的
|
|
208023
|
+
* 数据面 WS。这些会话 `run.id === dispatchId`(协调者:`job.dispatchId = coordinate:*`),
|
|
208024
|
+
* 于是「hub 此刻还连着它」就是最直接的判活。不接这条线,7 天里 183 条协调者会话被误判孤儿闭合
|
|
208025
|
+
* (ADR-0300 证据 E)。只增不减:命中只能**阻止**误闭合,永不会导致误闭合。
|
|
208026
|
+
*/
|
|
208027
|
+
liveSessionDispatchIds() {
|
|
208028
|
+
const ids2 = /* @__PURE__ */ new Set();
|
|
208029
|
+
for (const [dispatchId, ws] of this.sessionSockets) {
|
|
208030
|
+
if (ws.readyState === import_websocket.default.OPEN) ids2.add(dispatchId);
|
|
208031
|
+
}
|
|
208032
|
+
return ids2;
|
|
208033
|
+
}
|
|
207833
208034
|
/** 往会话进程直投一帧(kill / append_input / ping)。返回是否写进了 OPEN 的 socket。 */
|
|
207834
208035
|
sendToSession(dispatchId, msg) {
|
|
207835
208036
|
const ws = this.sessionSockets.get(dispatchId);
|
|
@@ -214668,6 +214869,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
214668
214869
|
if (!isOwnerRecipient && !isLeadRecipient) continue;
|
|
214669
214870
|
const gaps = unresolvedGapsOf(model, a.id);
|
|
214670
214871
|
const escalations = unresolvedEscalationsOf(model, a.id);
|
|
214872
|
+
const representedEscalations = /* @__PURE__ */ new Set();
|
|
214671
214873
|
const who = isOwnerRecipient ? "\uFF08\u4F60\u662F\u5DE5\u5355\u5F52\u5C5E\u4EBA\uFF09" : "\uFF08\u4F60\u662F\u5361\u4F4F\u8282\u70B9 owner \u7684\u4E0A\u7EA7\uFF09";
|
|
214672
214874
|
for (const gap of gaps) {
|
|
214673
214875
|
const byGapId = escalations.filter((entry) => entry.gapId === gap.gapId);
|
|
@@ -214681,6 +214883,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
214681
214883
|
const exactEscalation = byGapId.at(-1) ?? (samePartGaps.length === 1 ? samePartEscalations.at(-1) : void 0) ?? (gaps.length === 1 ? partlessEscalations.at(-1) : void 0);
|
|
214682
214884
|
const gapSince = exactEscalation?.at ?? gap.lastReportedAt ?? model.lastOpAt.get(a.id) ?? "";
|
|
214683
214885
|
const gapReportCount = gap.reportCount ?? 1;
|
|
214886
|
+
if (exactEscalation) representedEscalations.add(exactEscalation.escalationId);
|
|
214684
214887
|
gapItems.push({
|
|
214685
214888
|
kind: "gap-escalation",
|
|
214686
214889
|
artifactId: a.id,
|
|
@@ -214709,8 +214912,8 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
214709
214912
|
}
|
|
214710
214913
|
});
|
|
214711
214914
|
}
|
|
214712
|
-
if (
|
|
214713
|
-
for (const e of escalations) {
|
|
214915
|
+
if (escalations.length > 0) {
|
|
214916
|
+
for (const e of escalations.filter((e2) => !representedEscalations.has(e2.escalationId))) {
|
|
214714
214917
|
gapItems.push({
|
|
214715
214918
|
kind: "gap-escalation",
|
|
214716
214919
|
artifactId: a.id,
|
|
@@ -214961,6 +215164,152 @@ var init_inbox = __esm({
|
|
|
214961
215164
|
}
|
|
214962
215165
|
});
|
|
214963
215166
|
|
|
215167
|
+
// ../server/src/domains/collab/escalation-attention.ts
|
|
215168
|
+
function escalationDeliveryConfig(env) {
|
|
215169
|
+
const positive = (key, fallback) => {
|
|
215170
|
+
if (!env[key]) return fallback;
|
|
215171
|
+
const n = Number(env[key]);
|
|
215172
|
+
if (!Number.isFinite(n) || n <= 0) throw new Error(`${key} must be a positive number`);
|
|
215173
|
+
return n;
|
|
215174
|
+
};
|
|
215175
|
+
const policy = {
|
|
215176
|
+
reminderMs: positive("OASIS_ESCALATION_REMINDER_MS", DEFAULT_ESCALATION_REMINDERS.reminderMs),
|
|
215177
|
+
acknowledgedReminderMs: positive("OASIS_ESCALATION_ACK_REMINDER_MS", DEFAULT_ESCALATION_REMINDERS.acknowledgedReminderMs)
|
|
215178
|
+
};
|
|
215179
|
+
const webhooks = /* @__PURE__ */ new Map();
|
|
215180
|
+
if (env.OASIS_ESCALATION_WEBHOOKS) {
|
|
215181
|
+
try {
|
|
215182
|
+
const entries = JSON.parse(env.OASIS_ESCALATION_WEBHOOKS);
|
|
215183
|
+
if (!entries || Array.isArray(entries) || typeof entries !== "object") throw new Error();
|
|
215184
|
+
for (const [companyId, endpoint] of Object.entries(entries)) {
|
|
215185
|
+
const url = new URL(endpoint.url);
|
|
215186
|
+
if (!companyId || !["https:", "http:"].includes(url.protocol) || url.username || url.password || endpoint.token !== void 0 && typeof endpoint.token !== "string") throw new Error();
|
|
215187
|
+
webhooks.set(companyId, endpoint);
|
|
215188
|
+
}
|
|
215189
|
+
} catch {
|
|
215190
|
+
throw new Error("OASIS_ESCALATION_WEBHOOKS must map company IDs to { url, token? } endpoints");
|
|
215191
|
+
}
|
|
215192
|
+
}
|
|
215193
|
+
return { policy, webhooks };
|
|
215194
|
+
}
|
|
215195
|
+
function withEscalationAttention(items, companyId, markers, now, policy = DEFAULT_ESCALATION_REMINDERS) {
|
|
215196
|
+
const byScope = new Map(markers.map((m2) => [m2.scope, m2.readAt]));
|
|
215197
|
+
return items.map((item) => {
|
|
215198
|
+
if (item.kind !== "gap-escalation" || !item.escalationId) return item;
|
|
215199
|
+
const start = Date.parse(item.since);
|
|
215200
|
+
if (!Number.isFinite(start)) return item;
|
|
215201
|
+
const ackAt = byScope.get(escalationAttentionScope(companyId, item.escalationId, "ack"));
|
|
215202
|
+
const ack = ackAt ? Date.parse(ackAt) : NaN;
|
|
215203
|
+
const acknowledged = Number.isFinite(ack) && ack >= start;
|
|
215204
|
+
const firstDue = acknowledged ? ack + policy.acknowledgedReminderMs : start;
|
|
215205
|
+
const due = now >= firstDue;
|
|
215206
|
+
const step = Math.max(0, Math.floor((now - firstDue) / policy.reminderMs));
|
|
215207
|
+
const dueAt = new Date(firstDue + step * policy.reminderMs).toISOString();
|
|
215208
|
+
const deliveredAt = byScope.get(escalationAttentionScope(companyId, item.escalationId, "webhook"));
|
|
215209
|
+
return { ...item, attention: {
|
|
215210
|
+
reminderKey: `${item.escalationId}:${dueAt}`,
|
|
215211
|
+
dueAt,
|
|
215212
|
+
needsAcknowledgement: due,
|
|
215213
|
+
...acknowledged ? { acknowledgedAt: ackAt } : {},
|
|
215214
|
+
...deliveredAt ? { deliveredAt } : {}
|
|
215215
|
+
} };
|
|
215216
|
+
});
|
|
215217
|
+
}
|
|
215218
|
+
async function sendEscalationWebhook(url, token, batch, item, deliveryId) {
|
|
215219
|
+
const response = await fetch(url, {
|
|
215220
|
+
method: "POST",
|
|
215221
|
+
redirect: "error",
|
|
215222
|
+
signal: AbortSignal.timeout(1e4),
|
|
215223
|
+
headers: { "content-type": "application/json", ...token ? { authorization: `Bearer ${token}` } : {} },
|
|
215224
|
+
body: JSON.stringify({ deliveryId, companyId: batch.companyId, recipientActorId: batch.actorId, item })
|
|
215225
|
+
});
|
|
215226
|
+
await response.body?.cancel();
|
|
215227
|
+
if (!response.ok) throw new Error(`Delivery HTTP ${response.status}`);
|
|
215228
|
+
}
|
|
215229
|
+
var escalationAttentionScope, DEFAULT_ESCALATION_REMINDERS, EscalationDeliveryWorker;
|
|
215230
|
+
var init_escalation_attention = __esm({
|
|
215231
|
+
"../server/src/domains/collab/escalation-attention.ts"() {
|
|
215232
|
+
"use strict";
|
|
215233
|
+
escalationAttentionScope = (companyId, issueId, kind) => `escalation-${kind}:${JSON.stringify([companyId, issueId])}`;
|
|
215234
|
+
DEFAULT_ESCALATION_REMINDERS = {
|
|
215235
|
+
reminderMs: 15 * 6e4,
|
|
215236
|
+
acknowledgedReminderMs: 4 * 60 * 6e4
|
|
215237
|
+
};
|
|
215238
|
+
EscalationDeliveryWorker = class {
|
|
215239
|
+
constructor(deps) {
|
|
215240
|
+
this.deps = deps;
|
|
215241
|
+
}
|
|
215242
|
+
running = false;
|
|
215243
|
+
stopped = false;
|
|
215244
|
+
cursor = "";
|
|
215245
|
+
/** Already-started transport is bounded by its timeout; do not start new deliveries during shutdown. */
|
|
215246
|
+
stop() {
|
|
215247
|
+
this.stopped = true;
|
|
215248
|
+
}
|
|
215249
|
+
async tick() {
|
|
215250
|
+
if (this.running || this.stopped) return;
|
|
215251
|
+
this.running = true;
|
|
215252
|
+
try {
|
|
215253
|
+
const pending = [];
|
|
215254
|
+
let attempts = 0;
|
|
215255
|
+
for (const batch of await this.deps.batches()) {
|
|
215256
|
+
if (this.stopped) return;
|
|
215257
|
+
const markers = await this.deps.markers.listMarkers(batch.actorId);
|
|
215258
|
+
const items = withEscalationAttention(
|
|
215259
|
+
batch.items,
|
|
215260
|
+
batch.companyId,
|
|
215261
|
+
markers,
|
|
215262
|
+
(this.deps.now ?? Date.now)(),
|
|
215263
|
+
this.deps.policy
|
|
215264
|
+
);
|
|
215265
|
+
for (const item of items) {
|
|
215266
|
+
const attention2 = item.attention;
|
|
215267
|
+
if (!item.escalationId || !attention2?.needsAcknowledgement) continue;
|
|
215268
|
+
if (attention2.deliveredAt && Date.parse(attention2.deliveredAt) >= Date.parse(attention2.dueAt)) continue;
|
|
215269
|
+
pending.push({ batch, item, key: JSON.stringify([batch.companyId, batch.actorId, item.escalationId]) });
|
|
215270
|
+
}
|
|
215271
|
+
}
|
|
215272
|
+
pending.sort((a, b2) => a.key < b2.key ? -1 : a.key > b2.key ? 1 : 0);
|
|
215273
|
+
const afterCursor = pending.findIndex((p2) => p2.key > this.cursor);
|
|
215274
|
+
const start = afterCursor < 0 ? 0 : afterCursor;
|
|
215275
|
+
for (let offset = 0; offset < pending.length; offset++) {
|
|
215276
|
+
if (this.stopped) break;
|
|
215277
|
+
if (attempts++ >= (this.deps.maxPerTick ?? 20)) break;
|
|
215278
|
+
const { batch, item: queued, key } = pending[(start + offset) % pending.length];
|
|
215279
|
+
this.cursor = key;
|
|
215280
|
+
try {
|
|
215281
|
+
const current = this.deps.currentItem ? await this.deps.currentItem(batch, queued.escalationId) : queued;
|
|
215282
|
+
if (!current) continue;
|
|
215283
|
+
const item = withEscalationAttention(
|
|
215284
|
+
[current],
|
|
215285
|
+
batch.companyId,
|
|
215286
|
+
await this.deps.markers.listMarkers(batch.actorId),
|
|
215287
|
+
(this.deps.now ?? Date.now)(),
|
|
215288
|
+
this.deps.policy
|
|
215289
|
+
)[0];
|
|
215290
|
+
const attention2 = item.attention;
|
|
215291
|
+
if (this.stopped || !attention2.needsAcknowledgement || attention2.deliveredAt && Date.parse(attention2.deliveredAt) >= Date.parse(attention2.dueAt)) continue;
|
|
215292
|
+
const id = JSON.stringify([batch.companyId, batch.actorId, attention2.reminderKey]);
|
|
215293
|
+
await this.deps.send(batch, item, id);
|
|
215294
|
+
await this.deps.markers.markRead(
|
|
215295
|
+
batch.actorId,
|
|
215296
|
+
escalationAttentionScope(batch.companyId, item.escalationId, "webhook"),
|
|
215297
|
+
attention2.dueAt
|
|
215298
|
+
);
|
|
215299
|
+
} catch {
|
|
215300
|
+
this.deps.log(`[escalation-delivery] delivery failed; retained for retry (${key})`);
|
|
215301
|
+
}
|
|
215302
|
+
}
|
|
215303
|
+
} catch {
|
|
215304
|
+
this.deps.log("[escalation-delivery] scan failed; will retry");
|
|
215305
|
+
} finally {
|
|
215306
|
+
this.running = false;
|
|
215307
|
+
}
|
|
215308
|
+
}
|
|
215309
|
+
};
|
|
215310
|
+
}
|
|
215311
|
+
});
|
|
215312
|
+
|
|
214964
215313
|
// ../server/src/domains/collab/inbox-chat.ts
|
|
214965
215314
|
function mergeInbox(kernelItems, chatItems) {
|
|
214966
215315
|
if (chatItems.length === 0) return kernelItems;
|
|
@@ -216408,7 +216757,23 @@ function collabDomain(opts) {
|
|
|
216408
216757
|
const { reviews, works } = collectWaitingRows(snaps, me, policy);
|
|
216409
216758
|
waitingItems = buildWaitingInbox(reviews, works, policy, (/* @__PURE__ */ new Date()).toISOString(), me);
|
|
216410
216759
|
}
|
|
216411
|
-
|
|
216760
|
+
const items = mergeInbox(kernelItems, [...chatItems, ...waitingItems]);
|
|
216761
|
+
return { status: 200, body: { items: opts.readMarkers ? withEscalationAttention(items, req.auth.companyId ?? opts.defaultCompanyId ?? "", markers, Date.now(), opts.escalationReminders) : items } };
|
|
216762
|
+
});
|
|
216763
|
+
router.post("/api/inbox/escalations/:id/acknowledge", async (req) => {
|
|
216764
|
+
if (!opts.readMarkers) return { status: 503, body: { error: { code: "not_configured", message: "\u63A5\u624B\u8BB0\u5F55\u672A\u88C5\u914D" } } };
|
|
216765
|
+
const { kernel, registry: registry2 } = await resolveCtx(req.auth.companyId);
|
|
216766
|
+
await kernel.refreshModel?.();
|
|
216767
|
+
const leadOf = await buildLeadResolver(registry2);
|
|
216768
|
+
const item = buildInbox(kernel.model, req.auth.actor, leadOf).find((i) => i.escalationId === req.params.id);
|
|
216769
|
+
if (!item?.escalationId) return { status: 404, body: { error: { code: "not_found", message: "\u5F85\u529E\u4E0D\u5B58\u5728\u6216\u4E0D\u5C5E\u4E8E\u4F60" } } };
|
|
216770
|
+
const acknowledgedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
216771
|
+
await opts.readMarkers.markRead(
|
|
216772
|
+
req.auth.actor,
|
|
216773
|
+
escalationAttentionScope(req.auth.companyId ?? opts.defaultCompanyId ?? "", item.escalationId, "ack"),
|
|
216774
|
+
acknowledgedAt
|
|
216775
|
+
);
|
|
216776
|
+
return { status: 200, body: { acknowledgedAt } };
|
|
216412
216777
|
});
|
|
216413
216778
|
const companyOf = (req) => req.auth.companyId ?? "company:default";
|
|
216414
216779
|
const noTagStore = { status: 501, body: { error: { code: "not_implemented", message: "\u672C\u90E8\u7F72\u672A\u542F\u7528\u5DE5\u5355\u6807\u7B7E" } } };
|
|
@@ -216647,6 +217012,7 @@ var init_collab = __esm({
|
|
|
216647
217012
|
init_workorders();
|
|
216648
217013
|
init_workorder_detail();
|
|
216649
217014
|
init_inbox();
|
|
217015
|
+
init_escalation_attention();
|
|
216650
217016
|
init_inbox_chat();
|
|
216651
217017
|
init_waiting_inbox();
|
|
216652
217018
|
init_src3();
|
|
@@ -216660,6 +217026,7 @@ var init_collab = __esm({
|
|
|
216660
217026
|
init_workorder_detail();
|
|
216661
217027
|
init_workorder_metrics();
|
|
216662
217028
|
init_inbox();
|
|
217029
|
+
init_escalation_attention();
|
|
216663
217030
|
init_letter_read_backfill();
|
|
216664
217031
|
init_audit();
|
|
216665
217032
|
init_dashboard();
|
|
@@ -216686,7 +217053,7 @@ function prepareReadonlyGitBundles(input) {
|
|
|
216686
217053
|
if (repos.length === 0) return null;
|
|
216687
217054
|
const targets = collectTargets(repos, input.pinnedRevisions);
|
|
216688
217055
|
if (targets.length === 0) return null;
|
|
216689
|
-
const bundleRoot = input.bundleRoot ??
|
|
217056
|
+
const bundleRoot = input.bundleRoot ?? os7.tmpdir();
|
|
216690
217057
|
fs23.mkdirSync(bundleRoot, { recursive: true });
|
|
216691
217058
|
const root = fs23.mkdtempSync(path24.join(bundleRoot, "oasis-git-bundles-"));
|
|
216692
217059
|
const files = {};
|
|
@@ -216833,7 +217200,7 @@ function createBundle(root, target, input) {
|
|
|
216833
217200
|
function verifyBundleReadable(dir, bundlePath, _bundleRef, commit, expectedTree, env) {
|
|
216834
217201
|
fs23.rmSync(dir, { recursive: true, force: true });
|
|
216835
217202
|
try {
|
|
216836
|
-
(0,
|
|
217203
|
+
(0, import_node_child_process17.execFileSync)("git", ["clone", bundlePath, dir], { stdio: "ignore", ...env ? { env } : {} });
|
|
216837
217204
|
git2(dir, ["cat-file", "-e", `${commit}^{commit}`], env, "COMMIT_NOT_FOUND");
|
|
216838
217205
|
const head = git2(dir, ["rev-parse", "HEAD"], env, "COMMIT_NOT_FOUND").trim();
|
|
216839
217206
|
if (head.toLowerCase() !== commit.toLowerCase()) {
|
|
@@ -216875,11 +217242,11 @@ function ensureSourceRepo(work, repo, commit, env) {
|
|
|
216875
217242
|
function gitInitBare(dir, env) {
|
|
216876
217243
|
if (fs23.existsSync(path24.join(dir, "objects"))) return;
|
|
216877
217244
|
fs23.mkdirSync(dir, { recursive: true });
|
|
216878
|
-
(0,
|
|
217245
|
+
(0, import_node_child_process17.execFileSync)("git", ["init", "--bare", dir], { stdio: "ignore", ...env ? { env } : {} });
|
|
216879
217246
|
}
|
|
216880
217247
|
function git2(cwd, args, env, fallback, timeout) {
|
|
216881
217248
|
try {
|
|
216882
|
-
return (0,
|
|
217249
|
+
return (0, import_node_child_process17.execFileSync)("git", ["-C", cwd, ...args], {
|
|
216883
217250
|
encoding: "utf8",
|
|
216884
217251
|
stdio: ["ignore", "pipe", "pipe"],
|
|
216885
217252
|
...timeout ? { timeout } : {},
|
|
@@ -216903,14 +217270,14 @@ function classifyGitError(fallback, err, where) {
|
|
|
216903
217270
|
function oneLine(msg) {
|
|
216904
217271
|
return msg.split("\n").map((s2) => s2.trim()).filter(Boolean).slice(0, 3).join(" ");
|
|
216905
217272
|
}
|
|
216906
|
-
var
|
|
217273
|
+
var import_node_child_process17, import_node_crypto45, fs23, os7, path24, GitReadonlyBundleError, HEX40, FETCH_TIMEOUT_MS2;
|
|
216907
217274
|
var init_readonly_bundle = __esm({
|
|
216908
217275
|
"../server/src/git/readonly-bundle.ts"() {
|
|
216909
217276
|
"use strict";
|
|
216910
|
-
|
|
217277
|
+
import_node_child_process17 = require("node:child_process");
|
|
216911
217278
|
import_node_crypto45 = require("node:crypto");
|
|
216912
217279
|
fs23 = __toESM(require("node:fs"), 1);
|
|
216913
|
-
|
|
217280
|
+
os7 = __toESM(require("node:os"), 1);
|
|
216914
217281
|
path24 = __toESM(require("node:path"), 1);
|
|
216915
217282
|
init_remote_util();
|
|
216916
217283
|
GitReadonlyBundleError = class extends Error {
|
|
@@ -219417,7 +219784,9 @@ function createChatSessionsDomain(opts) {
|
|
|
219417
219784
|
router.get("/api/chat-sessions/:id/turns/active", async (req) => {
|
|
219418
219785
|
if (!opts.chatTurns) throw new ApiError(404, "NOT_FOUND", "\u672C\u5B9E\u4F8B\u672A\u63A5\u4F1A\u8BDD\u8F6E\u6B21\u8D26\u672C");
|
|
219419
219786
|
const session = await store.getSession(req.params.id);
|
|
219420
|
-
if (!session || session.humanActorId !== req.auth.actor
|
|
219787
|
+
if (!session || session.humanActorId !== req.auth.actor && session.aiActorId !== req.auth.actor) {
|
|
219788
|
+
throw new ApiError(404, "NOT_FOUND", "session not found");
|
|
219789
|
+
}
|
|
219421
219790
|
const turn = await opts.chatTurns.activeTurn(req.params.id);
|
|
219422
219791
|
return { status: 200, body: { turn } };
|
|
219423
219792
|
});
|
|
@@ -224127,11 +224496,11 @@ var init_engine = __esm({
|
|
|
224127
224496
|
constructor(table = /* @__PURE__ */ new Map()) {
|
|
224128
224497
|
this.table = table;
|
|
224129
224498
|
}
|
|
224130
|
-
set(
|
|
224131
|
-
this.table.set(`${
|
|
224499
|
+
set(platform2, platformUserId, actor) {
|
|
224500
|
+
this.table.set(`${platform2}:${platformUserId}`, actor);
|
|
224132
224501
|
}
|
|
224133
|
-
resolve(
|
|
224134
|
-
return this.table.get(`${
|
|
224502
|
+
resolve(platform2, platformUserId) {
|
|
224503
|
+
return this.table.get(`${platform2}:${platformUserId}`) ?? null;
|
|
224135
224504
|
}
|
|
224136
224505
|
};
|
|
224137
224506
|
}
|
|
@@ -224670,7 +225039,7 @@ ${HIGH_RISK_COMMANDS}`;
|
|
|
224670
225039
|
const downstreams = consumersOf(m2, p2.id).map((a) => a.id);
|
|
224671
225040
|
const task = [
|
|
224672
225041
|
`## \u672C\u6B21\u4E3A\u4EC0\u4E48\u5524\u8D77\u4F60`,
|
|
224673
|
-
`\u8282\u70B9 **${p2.id}**${brief ? `\uFF08${brief}\uFF09` : ""} \u5DF2\u963B\u585E\u7EA6 **${mins} \u5206\u949F**\u6CA1\u8FDB\u5C55\u3002\
|
|
225042
|
+
`\u8282\u70B9 **${p2.id}**${brief ? `\uFF08${brief}\uFF09` : ""} \u5DF2\u963B\u585E\u7EA6 **${mins} \u5206\u949F**\u6CA1\u8FDB\u5C55\u3002\u673A\u68B0\u8BCA\u65AD\u5C06\u5176\u5F52\u5165**\u56FE\u75C5\u6216\u5C1A\u672A\u5B9A\u4F4D\u7684\u6B8B\u5DEE**\u3002\u672A\u53D1\u73B0\u5DF2\u77E5\u8FD0\u884C\u65F6\u4FE1\u53F7\u4E0D\u7B49\u4E8E\u6392\u9664\u4E86\u8FD0\u884C\u65F6\u6545\u969C\uFF1B\u6CA1\u6709\u5728\u8DD1\u4F1A\u8BDD\u65F6\uFF0C\u8BF7\u5148\u6838\u5BF9\u7ED1\u5B9A\u3001\u8282\u70B9\u6CE8\u518C\u72B6\u6001\u548C\u6D3E\u53D1\u9001\u8FBE\u60C5\u51B5\uFF0C\u518D\u51B3\u5B9A\u662F\u5426\u6539\u56FE\u3002`,
|
|
224674
225043
|
``,
|
|
224675
225044
|
`## \u75C5\u5386\uFF08\u673A\u68B0\u8BCA\u65AD\uFF1B\u5148\u8BFB\u8FD9\u4E2A\uFF09`,
|
|
224676
225045
|
caseFile,
|
|
@@ -225801,6 +226170,7 @@ var init_src10 = __esm({
|
|
|
225801
226170
|
init_orphan_sweep();
|
|
225802
226171
|
init_dispatch_drop_sweep();
|
|
225803
226172
|
init_dispatch_mapping_rebuild();
|
|
226173
|
+
init_dispatch_binding_diagnosis();
|
|
225804
226174
|
init_zero_output_breaker();
|
|
225805
226175
|
init_dispatch_exit_reconcile();
|
|
225806
226176
|
init_session_exit_outcome();
|
|
@@ -225839,6 +226209,7 @@ var init_src10 = __esm({
|
|
|
225839
226209
|
init_node_store();
|
|
225840
226210
|
init_tokens();
|
|
225841
226211
|
init_collab();
|
|
226212
|
+
init_collab();
|
|
225842
226213
|
init_closure_report();
|
|
225843
226214
|
init_workorders();
|
|
225844
226215
|
init_workorder_detail();
|
|
@@ -233741,22 +234112,22 @@ var init_trajectory = __esm({
|
|
|
233741
234112
|
|
|
233742
234113
|
// src/index.ts
|
|
233743
234114
|
var fs42 = __toESM(require("node:fs"));
|
|
233744
|
-
var
|
|
234115
|
+
var os14 = __toESM(require("node:os"));
|
|
233745
234116
|
var path39 = __toESM(require("node:path"));
|
|
233746
|
-
var
|
|
234117
|
+
var import_node_child_process23 = require("node:child_process");
|
|
233747
234118
|
var import_node_crypto66 = require("node:crypto");
|
|
233748
234119
|
|
|
233749
234120
|
// ../cli/src/cli.ts
|
|
233750
234121
|
var fs37 = __toESM(require("node:fs"), 1);
|
|
233751
|
-
var
|
|
234122
|
+
var os12 = __toESM(require("node:os"), 1);
|
|
233752
234123
|
var path34 = __toESM(require("node:path"), 1);
|
|
233753
234124
|
var import_node_crypto64 = require("node:crypto");
|
|
233754
234125
|
|
|
233755
234126
|
// ../cli/src/serve.ts
|
|
233756
234127
|
var fs31 = __toESM(require("node:fs"), 1);
|
|
233757
|
-
var
|
|
234128
|
+
var os8 = __toESM(require("node:os"), 1);
|
|
233758
234129
|
var path28 = __toESM(require("node:path"), 1);
|
|
233759
|
-
var
|
|
234130
|
+
var import_node_child_process18 = require("node:child_process");
|
|
233760
234131
|
var import_node_crypto60 = require("node:crypto");
|
|
233761
234132
|
var import_node_url7 = require("node:url");
|
|
233762
234133
|
|
|
@@ -234333,8 +234704,10 @@ var SESSION_TOKEN_GRACE_MS = 15 * 6e4;
|
|
|
234333
234704
|
function makeResumeRetryProxy(first, spawnFallback) {
|
|
234334
234705
|
const outCbs = [];
|
|
234335
234706
|
const telCbs = [];
|
|
234707
|
+
const liveCbs = [];
|
|
234336
234708
|
const outBuf = [];
|
|
234337
234709
|
const telBuf = [];
|
|
234710
|
+
const liveBuf = [];
|
|
234338
234711
|
let sawOutput = false;
|
|
234339
234712
|
let active = first;
|
|
234340
234713
|
const fanOut = (chunk) => {
|
|
@@ -234345,12 +234718,17 @@ function makeResumeRetryProxy(first, spawnFallback) {
|
|
|
234345
234718
|
if (telCbs.length) for (const cb of telCbs) cb(e);
|
|
234346
234719
|
else telBuf.push(e);
|
|
234347
234720
|
};
|
|
234721
|
+
const fanLive = (e) => {
|
|
234722
|
+
if (liveCbs.length) for (const cb of liveCbs) cb(e);
|
|
234723
|
+
else liveBuf.push(e);
|
|
234724
|
+
};
|
|
234348
234725
|
const wire = (s2) => {
|
|
234349
234726
|
s2.onOutput((c) => {
|
|
234350
234727
|
sawOutput = true;
|
|
234351
234728
|
fanOut(c);
|
|
234352
234729
|
});
|
|
234353
234730
|
s2.onTelemetry?.((e) => fanTel(e));
|
|
234731
|
+
s2.onLiveEvent?.((e) => fanLive(e));
|
|
234354
234732
|
};
|
|
234355
234733
|
wire(first);
|
|
234356
234734
|
const isSessionNotFound2 = (err) => {
|
|
@@ -234382,6 +234760,10 @@ function makeResumeRetryProxy(first, spawnFallback) {
|
|
|
234382
234760
|
for (const e of telBuf.splice(0)) cb(e);
|
|
234383
234761
|
telCbs.push(cb);
|
|
234384
234762
|
},
|
|
234763
|
+
onLiveEvent(cb) {
|
|
234764
|
+
for (const e of liveBuf.splice(0)) cb(e);
|
|
234765
|
+
liveCbs.push(cb);
|
|
234766
|
+
},
|
|
234385
234767
|
done,
|
|
234386
234768
|
kill: () => active.kill?.() ?? Promise.resolve(),
|
|
234387
234769
|
// ADR-0093 chat 道:插入能力必须穿过这层代理,否则「带 sessionId 的 resume」这条**常路径**
|
|
@@ -234392,6 +234774,11 @@ function makeResumeRetryProxy(first, spawnFallback) {
|
|
|
234392
234774
|
get canAppendInput() {
|
|
234393
234775
|
return active.canAppendInput !== false && typeof active.appendInput === "function";
|
|
234394
234776
|
},
|
|
234777
|
+
// supportsLiveProtocol 恒读 active(兜底重派后 active 换成 second):不能按 first 快照,否则回退会话的
|
|
234778
|
+
// 能力位会指向已死的首次尝试。
|
|
234779
|
+
get supportsLiveProtocol() {
|
|
234780
|
+
return active.supportsLiveProtocol === true;
|
|
234781
|
+
},
|
|
234395
234782
|
get nativeSessionId() {
|
|
234396
234783
|
return active.nativeSessionId;
|
|
234397
234784
|
}
|
|
@@ -234452,15 +234839,15 @@ function oasisWrapperScript() {
|
|
|
234452
234839
|
const main = path28.join(repoRoot, "packages/cli/src/main.ts");
|
|
234453
234840
|
const key = (0, import_node_crypto60.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
|
|
234454
234841
|
const uid = typeof process.getuid === "function" ? process.getuid() : "na";
|
|
234455
|
-
const stable = path28.join(
|
|
234842
|
+
const stable = path28.join(os8.tmpdir(), `oasis-cli-wrapper-${uid}-${key}`);
|
|
234456
234843
|
let dir;
|
|
234457
234844
|
try {
|
|
234458
234845
|
fs31.mkdirSync(stable, { recursive: true, mode: 448 });
|
|
234459
234846
|
const st = fs31.lstatSync(stable);
|
|
234460
234847
|
const mine = st.isDirectory() && !st.isSymbolicLink() && (typeof process.getuid !== "function" || st.uid === process.getuid());
|
|
234461
|
-
dir = mine ? stable : fs31.mkdtempSync(path28.join(
|
|
234848
|
+
dir = mine ? stable : fs31.mkdtempSync(path28.join(os8.tmpdir(), "oasis-cli-"));
|
|
234462
234849
|
} catch {
|
|
234463
|
-
dir = fs31.mkdtempSync(path28.join(
|
|
234850
|
+
dir = fs31.mkdtempSync(path28.join(os8.tmpdir(), "oasis-cli-"));
|
|
234464
234851
|
}
|
|
234465
234852
|
const wrapper = path28.join(dir, "oasis");
|
|
234466
234853
|
fs31.writeFileSync(wrapper, `#!/usr/bin/env bash
|
|
@@ -234538,7 +234925,7 @@ async function runDeterministicKnowledgeLint(service, config2) {
|
|
|
234538
234925
|
if (!wrapper) throw new Error(`\u8FDE\u63A5\u5668 ${config2.connectorSlug} \u5C1A\u672A\u914D\u7F6E\u6216 wrapper \u4E0D\u53EF\u7528`);
|
|
234539
234926
|
const args = [...connector.knowledgeLintArgs({ libraryRef: config2.libraryRef, rootRef: config2.rootRef })];
|
|
234540
234927
|
const result = await new Promise((resolveResult) => {
|
|
234541
|
-
(0,
|
|
234928
|
+
(0, import_node_child_process18.execFile)(wrapper, args, {
|
|
234542
234929
|
env: { ...process.env, ...provision.env },
|
|
234543
234930
|
timeout: 12e4,
|
|
234544
234931
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -234808,7 +235195,7 @@ async function startServe(opts) {
|
|
|
234808
235195
|
);
|
|
234809
235196
|
const issuer = createTokenIssuer({ secretFile: path28.join(opts.dir, "session-token-secret") });
|
|
234810
235197
|
const apiActivity = createApiActivityLedger();
|
|
234811
|
-
const operatorActor = `actor:human:${
|
|
235198
|
+
const operatorActor = `actor:human:${os8.userInfo().username}`;
|
|
234812
235199
|
const operatorToken = issuer.issue(operatorActor);
|
|
234813
235200
|
fs31.writeFileSync(path28.join(opts.dir, "operator-token"), operatorToken, { mode: 384 });
|
|
234814
235201
|
let nodeTokens = createNodeTokenStore(path28.join(opts.dir, "node-tokens.json"));
|
|
@@ -234929,6 +235316,7 @@ async function startServe(opts) {
|
|
|
234929
235316
|
let chatSessionStore;
|
|
234930
235317
|
let chatTurnStore;
|
|
234931
235318
|
let readMarkerStore;
|
|
235319
|
+
const escalationDelivery = escalationDeliveryConfig(process.env);
|
|
234932
235320
|
if (pgDsn && pgPool) {
|
|
234933
235321
|
projectStateStore = await PostgresProjectStateStore.open(pgPool, pgSchema);
|
|
234934
235322
|
artifactStateStore = await PostgresArtifactStateStore.open(pgPool, pgSchema);
|
|
@@ -235963,6 +236351,8 @@ async function startServe(opts) {
|
|
|
235963
236351
|
chatSession: chatSessionStore,
|
|
235964
236352
|
// ADR-0086:chat 知会条目(与 readMarkers 成对)
|
|
235965
236353
|
readMarkers: readMarkerStore,
|
|
236354
|
+
escalationReminders: escalationDelivery.policy,
|
|
236355
|
+
defaultCompanyId,
|
|
235966
236356
|
// 工单标签词表(组织级受控、旁账,与 playbook-overrides 同款侧存)。
|
|
235967
236357
|
tags: workorderTagStore,
|
|
235968
236358
|
...opts.sla ? { sla: opts.sla } : {},
|
|
@@ -237504,6 +237894,8 @@ async function startServe(opts) {
|
|
|
237504
237894
|
ledgerWarn("cancel(map-miss)")(err);
|
|
237505
237895
|
}
|
|
237506
237896
|
},
|
|
237897
|
+
// Inbox is the notification contract (ADR 0090). Escalation delivery reconciles persisted Inbox
|
|
237898
|
+
// items below; it must not depend on this one-shot effect or its legacy recipient list.
|
|
237507
237899
|
async notify(_actorIds, _payload) {
|
|
237508
237900
|
}
|
|
237509
237901
|
};
|
|
@@ -237524,6 +237916,14 @@ async function startServe(opts) {
|
|
|
237524
237916
|
return live;
|
|
237525
237917
|
},
|
|
237526
237918
|
isAgent: async (actorId) => await executorKindOf(actorId) === "agent",
|
|
237919
|
+
beforeRedispatch: async (work) => {
|
|
237920
|
+
return prepareDroppedDispatch(work, {
|
|
237921
|
+
kernel: newKernel,
|
|
237922
|
+
// This sweep belongs to the default engine; legacy workorder.companyId is often empty.
|
|
237923
|
+
bindingFor: async (actorId) => (await actors.resolveCtx(defaultCompanyId)).service.resolveBinding()(actorId),
|
|
237924
|
+
nodeFor: (nodeId) => nodeStore.getNode(nodeId)
|
|
237925
|
+
});
|
|
237926
|
+
},
|
|
237527
237927
|
// resumeEligible=false:补派一律起**全新会话**。引擎那次派发的取值是节点状态的函数
|
|
237528
237928
|
//(activate.ts:`latestAcceptId == null && !lastProposedRejected`),本模块拿不到,
|
|
237529
237929
|
// 而两个方向的代价不对称——该续没续只是少一点上下文,不该续却续了就把返工要隔离的
|
|
@@ -238371,7 +238771,45 @@ async function startServe(opts) {
|
|
|
238371
238771
|
return { fused, starving, stuck, recovered };
|
|
238372
238772
|
}
|
|
238373
238773
|
const slaEscalating = /* @__PURE__ */ new Set();
|
|
238774
|
+
const escalationDeliveryWorker = new EscalationDeliveryWorker({
|
|
238775
|
+
markers: readMarkerStore,
|
|
238776
|
+
policy: escalationDelivery.policy,
|
|
238777
|
+
batches: async () => {
|
|
238778
|
+
const batches = [];
|
|
238779
|
+
for (const companyId of escalationDelivery.webhooks.keys()) {
|
|
238780
|
+
const companyEngine = await getEngine(companyId);
|
|
238781
|
+
await companyEngine.kernel.refreshModel();
|
|
238782
|
+
const leadOf2 = await buildLeadResolver(companyEngine.registry);
|
|
238783
|
+
const recipients = /* @__PURE__ */ new Set();
|
|
238784
|
+
for (const node2 of companyEngine.kernel.model.artifacts.values()) {
|
|
238785
|
+
recipients.add(node2.owner);
|
|
238786
|
+
const lead = leadOf2?.(node2.owner);
|
|
238787
|
+
if (lead) recipients.add(lead);
|
|
238788
|
+
}
|
|
238789
|
+
for (const actorId of recipients) {
|
|
238790
|
+
const items = buildInbox(companyEngine.kernel.model, actorId, leadOf2).filter((item) => item.escalationId && item.artifactId && lifecycleOf(companyEngine.kernel.model, item.artifactId) === "active");
|
|
238791
|
+
if (items.length) batches.push({ companyId, actorId, items });
|
|
238792
|
+
}
|
|
238793
|
+
}
|
|
238794
|
+
return batches;
|
|
238795
|
+
},
|
|
238796
|
+
currentItem: async (batch, issueId) => {
|
|
238797
|
+
const companyEngine = await getEngine(batch.companyId);
|
|
238798
|
+
await companyEngine.kernel.refreshModel();
|
|
238799
|
+
const leadOf2 = await buildLeadResolver(companyEngine.registry);
|
|
238800
|
+
return buildInbox(companyEngine.kernel.model, batch.actorId, leadOf2).find((item) => item.escalationId === issueId && item.artifactId && lifecycleOf(companyEngine.kernel.model, item.artifactId) === "active");
|
|
238801
|
+
},
|
|
238802
|
+
send: async (batch, item, deliveryId) => {
|
|
238803
|
+
const endpoint = escalationDelivery.webhooks.get(batch.companyId);
|
|
238804
|
+
await sendEscalationWebhook(endpoint.url, endpoint.token, batch, item, deliveryId);
|
|
238805
|
+
},
|
|
238806
|
+
log: (message) => console.warn(message)
|
|
238807
|
+
});
|
|
238808
|
+
if (!escalationDelivery.webhooks.size) {
|
|
238809
|
+
console.warn("[escalation-delivery] \u7AD9\u5916\u6E20\u9053\u672A\u914D\u7F6E\uFF1A\u5347\u7EA7\u5C06\u901A\u8FC7 Inbox \u5F39\u7A97\u548C\u50AC\u529E\u63D0\u9192\uFF1B\u6D4F\u89C8\u5668\u5173\u95ED\u65F6\u65E0\u6CD5\u7AD9\u5916\u9001\u8FBE\u3002\u914D\u7F6E OASIS_ESCALATION_WEBHOOKS \u53EF\u63A5\u90AE\u4EF6/IM \u7F51\u5173\u3002");
|
|
238810
|
+
}
|
|
238374
238811
|
const slaTimer = setInterval(() => {
|
|
238812
|
+
void escalationDeliveryWorker.tick();
|
|
238375
238813
|
void (async () => {
|
|
238376
238814
|
const now = Date.now();
|
|
238377
238815
|
for (const a of kernel.model.artifacts.values()) {
|
|
@@ -238683,6 +239121,7 @@ ${nodeFault}` : "");
|
|
|
238683
239121
|
for (const c of chatLiveSessions.values()) ids2.add(c.sessionId);
|
|
238684
239122
|
return ids2;
|
|
238685
239123
|
};
|
|
239124
|
+
const liveSessionRunIds = () => hub?.liveSessionDispatchIds() ?? /* @__PURE__ */ new Set();
|
|
238686
239125
|
const aliveArtifactIds = () => {
|
|
238687
239126
|
const ids2 = /* @__PURE__ */ new Set();
|
|
238688
239127
|
for (const d of hub?.connectedDaemons() ?? []) {
|
|
@@ -238713,6 +239152,8 @@ ${nodeFault}` : "");
|
|
|
238713
239152
|
aliveArtifactIds,
|
|
238714
239153
|
apiActiveDispatchIds,
|
|
238715
239154
|
// D1(ADR-0078):判活第二条线
|
|
239155
|
+
liveSessionRunIds,
|
|
239156
|
+
// ADR-0300 D8:hub 活数据面连接(协调者/独立会话进程)
|
|
238716
239157
|
closeRun,
|
|
238717
239158
|
now: Date.now(),
|
|
238718
239159
|
orphanGraceMs,
|
|
@@ -238892,6 +239333,7 @@ ${nodeFault}` : "");
|
|
|
238892
239333
|
close: async () => {
|
|
238893
239334
|
for (const timer of dispatchTimers) clearInterval(timer);
|
|
238894
239335
|
clearInterval(slaTimer);
|
|
239336
|
+
escalationDeliveryWorker.stop();
|
|
238895
239337
|
if (mirrorTimer) clearInterval(mirrorTimer);
|
|
238896
239338
|
if (gitTimer) clearInterval(gitTimer);
|
|
238897
239339
|
if (coordTimer) clearInterval(coordTimer);
|
|
@@ -238991,7 +239433,7 @@ function log2(tag, msg, extra) {
|
|
|
238991
239433
|
}
|
|
238992
239434
|
|
|
238993
239435
|
// ../cli/src/daemon/session-lock.ts
|
|
238994
|
-
var
|
|
239436
|
+
var import_node_child_process19 = require("node:child_process");
|
|
238995
239437
|
var fs32 = __toESM(require("node:fs"), 1);
|
|
238996
239438
|
var path29 = __toESM(require("node:path"), 1);
|
|
238997
239439
|
var flockAvailable = null;
|
|
@@ -238999,7 +239441,7 @@ function hasFlock() {
|
|
|
238999
239441
|
if (flockAvailable !== null) return flockAvailable;
|
|
239000
239442
|
if (process.platform !== "linux") return flockAvailable = false;
|
|
239001
239443
|
try {
|
|
239002
|
-
const r = (0,
|
|
239444
|
+
const r = (0, import_node_child_process19.spawnSync)("flock", ["--version"], { stdio: "ignore", timeout: 3e3 });
|
|
239003
239445
|
flockAvailable = r.status === 0;
|
|
239004
239446
|
} catch {
|
|
239005
239447
|
flockAvailable = false;
|
|
@@ -239014,7 +239456,7 @@ function acquireSessionLock(lockPath) {
|
|
|
239014
239456
|
fs32.unlinkSync(readyFile);
|
|
239015
239457
|
} catch {
|
|
239016
239458
|
}
|
|
239017
|
-
const child = (0,
|
|
239459
|
+
const child = (0, import_node_child_process19.spawn)("flock", ["-n", lockPath, "-c", `printf ok > '${readyFile}'; exec cat`], {
|
|
239018
239460
|
stdio: ["pipe", "ignore", "ignore"],
|
|
239019
239461
|
detached: true
|
|
239020
239462
|
});
|
|
@@ -239025,7 +239467,7 @@ function acquireSessionLock(lockPath) {
|
|
|
239025
239467
|
ready = true;
|
|
239026
239468
|
break;
|
|
239027
239469
|
}
|
|
239028
|
-
(0,
|
|
239470
|
+
(0, import_node_child_process19.spawnSync)("sleep", ["0.02"], { stdio: "ignore" });
|
|
239029
239471
|
}
|
|
239030
239472
|
try {
|
|
239031
239473
|
fs32.unlinkSync(readyFile);
|
|
@@ -239056,7 +239498,7 @@ function isSessionLocked(lockPath) {
|
|
|
239056
239498
|
if (!hasFlock()) return false;
|
|
239057
239499
|
if (!fs32.existsSync(lockPath)) return false;
|
|
239058
239500
|
try {
|
|
239059
|
-
const r = (0,
|
|
239501
|
+
const r = (0, import_node_child_process19.spawnSync)("flock", ["-n", lockPath, "-c", "true"], { stdio: "ignore", timeout: 3e3 });
|
|
239060
239502
|
return r.status !== 0;
|
|
239061
239503
|
} catch {
|
|
239062
239504
|
return true;
|
|
@@ -239131,7 +239573,10 @@ async function runSession(dispatchId, job, deps) {
|
|
|
239131
239573
|
var RECONNECT_MIN_MS = 1e3;
|
|
239132
239574
|
var RECONNECT_MAX_MS = 3e4;
|
|
239133
239575
|
var EXIT_ACK_WAIT_MS = LINK_WINDOWS.exitAckWaitMs;
|
|
239576
|
+
var OUTBOX_MAX_FRAMES = 8e3;
|
|
239577
|
+
var isKeyFrame = (m2) => m2.type === "session_started" || m2.type === "session_exited";
|
|
239134
239578
|
async function runSessionProcess(specFile, adapter) {
|
|
239579
|
+
process.env["OASIS_BIND_RUNTIME_PDEATHSIG"] = "1";
|
|
239135
239580
|
const spec = readSpec(specFile);
|
|
239136
239581
|
const { dispatchId, job, auth, sessionDir } = spec;
|
|
239137
239582
|
const lock = acquireSessionLock(path30.join(sessionDir, "lock"));
|
|
@@ -239185,6 +239630,10 @@ var SessionProcessState = class {
|
|
|
239185
239630
|
* 而会话其实正在跑。
|
|
239186
239631
|
*/
|
|
239187
239632
|
outbox = [];
|
|
239633
|
+
/** ADR 0300 D2:每 dispatch 单调帧号,任何副作用之前分配。 */
|
|
239634
|
+
frameSeq = 0;
|
|
239635
|
+
/** 收到过带 `ackSeq` 的 ack = 本服务端会按帧号去重;只有它为真,重连才敢重放**全部**帧(含输出)。 */
|
|
239636
|
+
serverSupportsDedup = false;
|
|
239188
239637
|
/** append_input 串行链——保证回帧次序 = 到达次序(server 侧按 FIFO 认领等待者)。 */
|
|
239189
239638
|
appendChain = Promise.resolve();
|
|
239190
239639
|
async run() {
|
|
@@ -239250,9 +239699,12 @@ var SessionProcessState = class {
|
|
|
239250
239699
|
daemonVersion: this.spec.daemonVersion,
|
|
239251
239700
|
// 自报身份要够服务端对上账:chat 道的对账键是 artifactId(run.id=chat-run:* ≠ dispatchId),
|
|
239252
239701
|
// 只报 dispatchId 的话 serve 重启后它认不出这是条活会话,会当成野进程 evict 掉。
|
|
239253
|
-
...this.spec.job.artifactId ? { jobArtifactId: this.spec.job.artifactId } : {}
|
|
239702
|
+
...this.spec.job.artifactId ? { jobArtifactId: this.spec.job.artifactId } : {},
|
|
239703
|
+
// ADR 0300 D2:自报支持帧号;新服务端据此回带 ackSeq 的 hello-ack,届时才把 serverSupportsDedup 置真。
|
|
239704
|
+
supportsFrameSeq: true
|
|
239254
239705
|
});
|
|
239255
|
-
|
|
239706
|
+
const toResend = this.serverSupportsDedup ? this.outbox : this.outbox.filter(isKeyFrame);
|
|
239707
|
+
for (const m2 of toResend) this.rawSend(m2);
|
|
239256
239708
|
});
|
|
239257
239709
|
ws.on("message", (raw) => {
|
|
239258
239710
|
let msg;
|
|
@@ -239300,8 +239752,14 @@ var SessionProcessState = class {
|
|
|
239300
239752
|
}
|
|
239301
239753
|
case "ack":
|
|
239302
239754
|
if (msg.dispatchId !== this.spec.dispatchId) return;
|
|
239303
|
-
|
|
239304
|
-
|
|
239755
|
+
if (typeof msg.ackSeq === "number") {
|
|
239756
|
+
this.serverSupportsDedup = true;
|
|
239757
|
+
const wm = msg.ackSeq;
|
|
239758
|
+
this.outbox = this.outbox.filter((f2) => (f2.seq ?? 0) > wm);
|
|
239759
|
+
} else {
|
|
239760
|
+
this.outbox.length = 0;
|
|
239761
|
+
}
|
|
239762
|
+
if (this.outbox.length === 0) this.exitAckResolve?.();
|
|
239305
239763
|
return;
|
|
239306
239764
|
case "ping":
|
|
239307
239765
|
this.rawSend({ type: "pong" });
|
|
@@ -239316,14 +239774,20 @@ var SessionProcessState = class {
|
|
|
239316
239774
|
this.ws.send(JSON.stringify(msg));
|
|
239317
239775
|
return true;
|
|
239318
239776
|
}
|
|
239319
|
-
/**
|
|
239777
|
+
/** ADR 0300 D2:给帧派单调 seq、进 outbox(超上限丢最老)、再尽力发。返回带 seq 的帧。 */
|
|
239778
|
+
stampAndBuffer(msg) {
|
|
239779
|
+
const framed = { ...msg, seq: ++this.frameSeq };
|
|
239780
|
+
this.outbox.push(framed);
|
|
239781
|
+
if (this.outbox.length > OUTBOX_MAX_FRAMES) this.outbox.splice(0, this.outbox.length - OUTBOX_MAX_FRAMES);
|
|
239782
|
+
return framed;
|
|
239783
|
+
}
|
|
239784
|
+
/** 关键帧(started/exited):必达,进 outbox,ack 到达(按 ackSeq 或整清)才删。 */
|
|
239320
239785
|
sendKeyFrame(msg) {
|
|
239321
|
-
this.
|
|
239322
|
-
this.rawSend(msg);
|
|
239786
|
+
this.rawSend(this.stampAndBuffer(msg));
|
|
239323
239787
|
}
|
|
239324
|
-
/**
|
|
239788
|
+
/** 输出/事件帧:ADR 0300 D2 起也进 outbox 带 seq——断线期不再丢;服务端按 ackSeq 累积回执后即从 outbox 排掉。 */
|
|
239325
239789
|
sendStream(msg) {
|
|
239326
|
-
this.rawSend(msg);
|
|
239790
|
+
this.rawSend(this.stampAndBuffer(msg));
|
|
239327
239791
|
}
|
|
239328
239792
|
// ── 看门狗(D2′.5 防线 3 + 防线 1 后半)──────────────────────────────────
|
|
239329
239793
|
startWatchdog() {
|
|
@@ -239348,7 +239812,7 @@ var SessionProcessState = class {
|
|
|
239348
239812
|
await this.handle?.kill();
|
|
239349
239813
|
} catch {
|
|
239350
239814
|
}
|
|
239351
|
-
this.
|
|
239815
|
+
this.sendKeyFrame({
|
|
239352
239816
|
type: "session_exited",
|
|
239353
239817
|
dispatchId: this.spec.dispatchId,
|
|
239354
239818
|
sessionId: this.handle?.id ?? this.spec.dispatchId,
|
|
@@ -239395,7 +239859,7 @@ init_src8();
|
|
|
239395
239859
|
init_src7();
|
|
239396
239860
|
|
|
239397
239861
|
// ../cli/src/daemon/detect-adapters.ts
|
|
239398
|
-
var
|
|
239862
|
+
var import_node_child_process20 = require("node:child_process");
|
|
239399
239863
|
init_src7();
|
|
239400
239864
|
var KNOWN2 = [
|
|
239401
239865
|
{ adapter: "claude-code", binary: "claude" },
|
|
@@ -239419,7 +239883,7 @@ var LIVE_PROTOCOL_RUNTIMES = /* @__PURE__ */ new Set(["claude-code"]);
|
|
|
239419
239883
|
function resolveOnPath2(binary) {
|
|
239420
239884
|
try {
|
|
239421
239885
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
239422
|
-
const out = (0,
|
|
239886
|
+
const out = (0, import_node_child_process20.execFileSync)(cmd, [binary], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
239423
239887
|
const first = out.split("\n")[0]?.trim();
|
|
239424
239888
|
return first || binary;
|
|
239425
239889
|
} catch {
|
|
@@ -239428,7 +239892,7 @@ function resolveOnPath2(binary) {
|
|
|
239428
239892
|
}
|
|
239429
239893
|
function versionOf(binary) {
|
|
239430
239894
|
try {
|
|
239431
|
-
return (0,
|
|
239895
|
+
return (0, import_node_child_process20.execFileSync)(binary, ["--version"], {
|
|
239432
239896
|
encoding: "utf8",
|
|
239433
239897
|
stdio: ["ignore", "pipe", "ignore"],
|
|
239434
239898
|
timeout: 1500
|
|
@@ -240384,7 +240848,7 @@ async function startNode(opts) {
|
|
|
240384
240848
|
}
|
|
240385
240849
|
|
|
240386
240850
|
// ../cli/src/exec.ts
|
|
240387
|
-
var
|
|
240851
|
+
var os11 = __toESM(require("node:os"), 1);
|
|
240388
240852
|
var UnsafeExecArgvError = class extends Error {
|
|
240389
240853
|
code = "ERR_UNSAFE_EXEC_ARGV";
|
|
240390
240854
|
constructor(message) {
|
|
@@ -240421,7 +240885,7 @@ function planExec(opts) {
|
|
|
240421
240885
|
function computeExitCode(code2, signal) {
|
|
240422
240886
|
if (code2 !== null) return code2;
|
|
240423
240887
|
if (signal) {
|
|
240424
|
-
const num2 =
|
|
240888
|
+
const num2 = os11.constants.signals[signal];
|
|
240425
240889
|
return 128 + (typeof num2 === "number" ? num2 : 1);
|
|
240426
240890
|
}
|
|
240427
240891
|
return 1;
|
|
@@ -240445,7 +240909,7 @@ function forwardSignal(child, sig, killGroup = (pgid, signal) => {
|
|
|
240445
240909
|
}
|
|
240446
240910
|
|
|
240447
240911
|
// ../cli/src/daemon/machine-id.ts
|
|
240448
|
-
var
|
|
240912
|
+
var import_node_child_process21 = require("node:child_process");
|
|
240449
240913
|
var import_node_fs20 = require("node:fs");
|
|
240450
240914
|
var import_node_crypto62 = require("node:crypto");
|
|
240451
240915
|
var import_node_os12 = require("node:os");
|
|
@@ -240461,7 +240925,7 @@ function linuxMachineId() {
|
|
|
240461
240925
|
}
|
|
240462
240926
|
function macMachineId() {
|
|
240463
240927
|
try {
|
|
240464
|
-
const out = (0,
|
|
240928
|
+
const out = (0, import_node_child_process21.execFileSync)("ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"], {
|
|
240465
240929
|
encoding: "utf8",
|
|
240466
240930
|
timeout: 2e3,
|
|
240467
240931
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -240474,7 +240938,7 @@ function macMachineId() {
|
|
|
240474
240938
|
}
|
|
240475
240939
|
function windowsMachineId() {
|
|
240476
240940
|
try {
|
|
240477
|
-
const out = (0,
|
|
240941
|
+
const out = (0, import_node_child_process21.execFileSync)("reg", [
|
|
240478
240942
|
"query",
|
|
240479
240943
|
"HKLM\\SOFTWARE\\Microsoft\\Cryptography",
|
|
240480
240944
|
"/v",
|
|
@@ -242184,7 +242648,7 @@ function ownFlagsFromDecl(command) {
|
|
|
242184
242648
|
|
|
242185
242649
|
// ../cli/src/connector-effect-runner.ts
|
|
242186
242650
|
var import_node_crypto63 = require("node:crypto");
|
|
242187
|
-
var
|
|
242651
|
+
var import_node_child_process22 = require("node:child_process");
|
|
242188
242652
|
init_src8();
|
|
242189
242653
|
function stableKey(effect) {
|
|
242190
242654
|
const keyFields = Object.fromEntries(Object.entries(effect.keyFields).sort(([a], [b2]) => a.localeCompare(b2)));
|
|
@@ -242243,7 +242707,7 @@ function productionApi() {
|
|
|
242243
242707
|
}
|
|
242244
242708
|
function execute(bin, args) {
|
|
242245
242709
|
return new Promise((resolve10, reject) => {
|
|
242246
|
-
const child = (0,
|
|
242710
|
+
const child = (0, import_node_child_process22.spawn)(bin, args, { stdio: "inherit", env: process.env });
|
|
242247
242711
|
child.once("error", reject);
|
|
242248
242712
|
child.once("exit", (code2, signal) => resolve10(code2 ?? (signal ? 128 : 1)));
|
|
242249
242713
|
});
|
|
@@ -242673,7 +243137,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242673
243137
|
const res = await fetch(`${httpBase2}/api/nodes/exchange`, {
|
|
242674
243138
|
method: "POST",
|
|
242675
243139
|
headers: { "content-type": "application/json" },
|
|
242676
|
-
body: JSON.stringify({ enrollToken, nodeId, hostname:
|
|
243140
|
+
body: JSON.stringify({ enrollToken, nodeId, hostname: os12.hostname() })
|
|
242677
243141
|
});
|
|
242678
243142
|
if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
|
|
242679
243143
|
const body2 = await res.json();
|
|
@@ -242706,7 +243170,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242706
243170
|
const binPath = path34.join(prefix, "bin", "oasis_test");
|
|
242707
243171
|
const svcArgs = `node --server-ws ${serverUrl} --dir ${dir}${nodeName ? ` --name ${nodeName}` : ""}`;
|
|
242708
243172
|
if (process.platform === "linux") {
|
|
242709
|
-
const svcFile = path34.join(
|
|
243173
|
+
const svcFile = path34.join(os12.homedir(), ".config/systemd/user/oasis-node.service");
|
|
242710
243174
|
fs37.mkdirSync(path34.dirname(svcFile), { recursive: true });
|
|
242711
243175
|
if (spawnSync3("systemctl", ["--user", "is-active", "--quiet", "oasis-node"], {}).status === 0)
|
|
242712
243176
|
spawnSync3("systemctl", ["--user", "stop", "oasis-node"], { stdio: "inherit" });
|
|
@@ -242719,7 +243183,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242719
243183
|
`ExecStart=${binPath} ${svcArgs}`,
|
|
242720
243184
|
// Carry the install-time PATH so the detached daemon detects CLIs in user dirs
|
|
242721
243185
|
// (~/.npm-global/bin, ~/.local/bin) — systemd --user otherwise gives a minimal PATH.
|
|
242722
|
-
`Environment=PATH=${process.env["PATH"] ?? ""}:${path34.join(
|
|
243186
|
+
`Environment=PATH=${process.env["PATH"] ?? ""}:${path34.join(os12.homedir(), ".npm-global/bin")}:${path34.join(os12.homedir(), ".local/bin")}:/usr/local/bin`,
|
|
242723
243187
|
"Restart=on-failure",
|
|
242724
243188
|
"RestartSec=5",
|
|
242725
243189
|
"StandardOutput=journal",
|
|
@@ -242731,23 +243195,23 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242731
243195
|
].join("\n"));
|
|
242732
243196
|
spawnSync3("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
|
|
242733
243197
|
spawnSync3("systemctl", ["--user", "enable", "--now", "oasis-node"], { stdio: "inherit" });
|
|
242734
|
-
spawnSync3("loginctl", ["enable-linger",
|
|
243198
|
+
spawnSync3("loginctl", ["enable-linger", os12.userInfo().username], { stdio: "ignore" });
|
|
242735
243199
|
println("\u2713 Oasis node service started (systemd --user oasis-node)");
|
|
242736
243200
|
println(" Status : systemctl --user status oasis-node");
|
|
242737
243201
|
println(" Logs : journalctl --user -u oasis-node -f");
|
|
242738
243202
|
println(" Stop : systemctl --user stop oasis-node");
|
|
242739
243203
|
} else if (process.platform === "darwin") {
|
|
242740
|
-
const plist = path34.join(
|
|
243204
|
+
const plist = path34.join(os12.homedir(), "Library/LaunchAgents/com.oasis.node.plist");
|
|
242741
243205
|
fs37.mkdirSync(path34.dirname(plist), { recursive: true });
|
|
242742
243206
|
spawnSync3("launchctl", ["unload", plist], { stdio: "ignore" });
|
|
242743
243207
|
const argXml = [binPath, "node", "--server-ws", serverUrl, "--dir", dir, ...nodeName ? ["--name", nodeName] : []].map((a) => `<string>${a}</string>`).join("");
|
|
242744
|
-
fs37.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>com.oasis.node</string><key>ProgramArguments</key><array>${argXml}</array><key>RunAtLoad</key><true/><key>KeepAlive</key><true/><key>StandardOutPath</key><string>${
|
|
243208
|
+
fs37.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>com.oasis.node</string><key>ProgramArguments</key><array>${argXml}</array><key>RunAtLoad</key><true/><key>KeepAlive</key><true/><key>StandardOutPath</key><string>${os12.homedir()}/.oasis-node.log</string><key>StandardErrorPath</key><string>${os12.homedir()}/.oasis-node.err</string></dict></plist>`);
|
|
242745
243209
|
spawnSync3("launchctl", ["load", plist], { stdio: "inherit" });
|
|
242746
243210
|
println("\u2713 Oasis node service started (macOS LaunchAgent com.oasis.node)");
|
|
242747
|
-
println(` Logs : tail -f ${
|
|
243211
|
+
println(` Logs : tail -f ${os12.homedir()}/.oasis-node.log`);
|
|
242748
243212
|
println(` Stop : launchctl unload ${plist}`);
|
|
242749
243213
|
} else {
|
|
242750
|
-
spawnSync3("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${path34.join(
|
|
243214
|
+
spawnSync3("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${path34.join(os12.homedir(), ".oasis-node.log")} 2>&1 &`], { stdio: "inherit" });
|
|
242751
243215
|
println(`\u2713 Oasis node started in background (nohup). Logs: ~/.oasis-node.log`);
|
|
242752
243216
|
println(" Note: no automatic restart on reboot in this environment.");
|
|
242753
243217
|
}
|
|
@@ -242846,8 +243310,8 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242846
243310
|
if (command === "serve" && positional[0] === "install") {
|
|
242847
243311
|
const absDir = path34.resolve(dir);
|
|
242848
243312
|
const name = `oasis-serve-${path34.basename(absDir)}`;
|
|
242849
|
-
const unitDir = flags.get("unit-dir") ?? path34.join(
|
|
242850
|
-
const bin = flags.get("bin") ?? path34.join(
|
|
243313
|
+
const unitDir = flags.get("unit-dir") ?? path34.join(os12.homedir(), ".config", "systemd", "user");
|
|
243314
|
+
const bin = flags.get("bin") ?? path34.join(os12.homedir(), ".local", "bin", "oasis");
|
|
242851
243315
|
const port = flags.get("port") ?? "7320";
|
|
242852
243316
|
const extra = (flags.get("dispatch") === "true" ? ` --dispatch true` : "") + (flags.has("model") ? ` --model ${flags.get("model")}` : "");
|
|
242853
243317
|
const unit = [
|
|
@@ -243191,7 +243655,7 @@ Trace: ${run.traceRunId}`);
|
|
|
243191
243655
|
if (plan.inject.mode === "env") {
|
|
243192
243656
|
childEnv[plan.inject.envName] = value2;
|
|
243193
243657
|
} else {
|
|
243194
|
-
tmpDir = await fs37.promises.mkdtemp(path34.join(
|
|
243658
|
+
tmpDir = await fs37.promises.mkdtemp(path34.join(os12.tmpdir(), "oasis-var-exec-"));
|
|
243195
243659
|
const keyfile = path34.join(tmpDir, "value");
|
|
243196
243660
|
await fs37.promises.writeFile(keyfile, value2, { mode: 384 });
|
|
243197
243661
|
childEnv[plan.inject.fileEnv] = keyfile;
|
|
@@ -243965,7 +244429,7 @@ ${res.warning}`);
|
|
|
243965
244429
|
for (const a of st.artifacts) println(` - ${a.path}\uFF08${a.kind ?? "?"}\uFF09status=${a.status ?? "?"}${a.mtime ? ` \xB7 ${new Date(a.mtime).toISOString()}` : ""}`);
|
|
243966
244430
|
if (flags.get("pull") === "true") {
|
|
243967
244431
|
const odPublic2 = (flags.get("od-public-url") ?? process.env["OASIS_OPEN_DESIGN_PUBLIC_URL"] ?? "https://design.open-friday.com").replace(/\/$/, "");
|
|
243968
|
-
const { dir: dir3, entry: entry2 } = await harvestBoard(odBase2, fetch, odPublic2,
|
|
244432
|
+
const { dir: dir3, entry: entry2 } = await harvestBoard(odBase2, fetch, odPublic2, os12.tmpdir(), st.boardKey, st.runs[0]?.runId ?? "status-pull");
|
|
243969
244433
|
println(`[design] \u5DF2\u62C9\u5230\u672C\u5730\uFF1A${dir3}\uFF08\u5165\u53E3 ${entry2}\uFF09`);
|
|
243970
244434
|
println(`[design] \u8BFB\u5B8C\u6EE1\u610F\u5373\u4EA4\u7A3F\uFF1Aoasis propose ${artifactId2} --from-dir ${dir3} --reason "<\u8FD9\u7248\u505A\u4E86\u4EC0\u4E48>"`);
|
|
243971
244435
|
} else {
|
|
@@ -245335,10 +245799,10 @@ function runtimeAssetSourceRoots(input) {
|
|
|
245335
245799
|
|
|
245336
245800
|
// src/paths.ts
|
|
245337
245801
|
var fs40 = __toESM(require("node:fs"));
|
|
245338
|
-
var
|
|
245802
|
+
var os13 = __toESM(require("node:os"));
|
|
245339
245803
|
var path37 = __toESM(require("node:path"));
|
|
245340
245804
|
var DEFAULT_INSTANCE = "default";
|
|
245341
|
-
var home = () =>
|
|
245805
|
+
var home = () => os13.homedir();
|
|
245342
245806
|
var oasisDir = () => path37.join(home(), ".oasis");
|
|
245343
245807
|
var versionsDir = () => path37.join(oasisDir(), "versions");
|
|
245344
245808
|
var versionDir = (label) => path37.join(versionsDir(), label);
|
|
@@ -245537,7 +246001,7 @@ function shimScript() {
|
|
|
245537
246001
|
}
|
|
245538
246002
|
|
|
245539
246003
|
// src/index.ts
|
|
245540
|
-
var PKG_VERSION = true ? "0.1.
|
|
246004
|
+
var PKG_VERSION = true ? "0.1.139" : "dev";
|
|
245541
246005
|
var LOCAL_BIN = localBin();
|
|
245542
246006
|
var NPM_PREFIX = npmPrefix();
|
|
245543
246007
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -245637,7 +246101,7 @@ function installSoftware(label) {
|
|
|
245637
246101
|
function setupAutostart(name) {
|
|
245638
246102
|
const inst = instancePaths(name);
|
|
245639
246103
|
const cmd = `${process.execPath} "${inst.binFile}" --_daemon --instance ${name}`;
|
|
245640
|
-
const home2 =
|
|
246104
|
+
const home2 = os14.homedir();
|
|
245641
246105
|
const pnpmHome = process.env["PNPM_HOME"] || path39.join(home2, ".local", "share", "pnpm");
|
|
245642
246106
|
const extraBins = [
|
|
245643
246107
|
path39.join(home2, ".npm-global", "bin"),
|
|
@@ -245647,7 +246111,7 @@ function setupAutostart(name) {
|
|
|
245647
246111
|
];
|
|
245648
246112
|
const daemonPath = sanitizeDaemonPath([process.env["PATH"] ?? "", ...extraBins].filter(Boolean).join(":"));
|
|
245649
246113
|
if (process.platform === "linux") {
|
|
245650
|
-
const unitDir = path39.join(
|
|
246114
|
+
const unitDir = path39.join(os14.homedir(), ".config", "systemd", "user");
|
|
245651
246115
|
fs42.mkdirSync(unitDir, { recursive: true });
|
|
245652
246116
|
const unit = systemdUnitName(name);
|
|
245653
246117
|
fs42.mkdirSync(path39.dirname(inst.logFile), { recursive: true });
|
|
@@ -245660,19 +246124,19 @@ function setupAutostart(name) {
|
|
|
245660
246124
|
}));
|
|
245661
246125
|
if (name === DEFAULT_INSTANCE) {
|
|
245662
246126
|
try {
|
|
245663
|
-
(0,
|
|
246127
|
+
(0, import_node_child_process23.execSync)(`systemctl --user disable --now ${LEGACY_SYSTEMD_UNIT} 2>/dev/null`, { stdio: "ignore" });
|
|
245664
246128
|
} catch {
|
|
245665
246129
|
}
|
|
245666
246130
|
}
|
|
245667
246131
|
try {
|
|
245668
|
-
(0,
|
|
246132
|
+
(0, import_node_child_process23.execSync)(`systemctl --user daemon-reload && systemctl --user enable --now ${unit}`, { stdio: "ignore" });
|
|
245669
246133
|
return true;
|
|
245670
246134
|
} catch {
|
|
245671
246135
|
}
|
|
245672
246136
|
return false;
|
|
245673
246137
|
} else if (process.platform === "darwin") {
|
|
245674
246138
|
const label = launchdLabel(name);
|
|
245675
|
-
const plist = path39.join(
|
|
246139
|
+
const plist = path39.join(os14.homedir(), "Library", "LaunchAgents", `${label}.plist`);
|
|
245676
246140
|
fs42.mkdirSync(path39.dirname(plist), { recursive: true });
|
|
245677
246141
|
fs42.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?>
|
|
245678
246142
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -245685,7 +246149,7 @@ function setupAutostart(name) {
|
|
|
245685
246149
|
<key>StandardErrorPath</key><string>${inst.logFile}</string>
|
|
245686
246150
|
</dict></plist>`);
|
|
245687
246151
|
try {
|
|
245688
|
-
(0,
|
|
246152
|
+
(0, import_node_child_process23.execSync)(`launchctl load "${plist}"`, { stdio: "ignore" });
|
|
245689
246153
|
return true;
|
|
245690
246154
|
} catch {
|
|
245691
246155
|
}
|
|
@@ -245696,7 +246160,7 @@ function setupAutostart(name) {
|
|
|
245696
246160
|
function spawnDaemon() {
|
|
245697
246161
|
fs42.mkdirSync(path39.dirname(LOG_FILE), { recursive: true });
|
|
245698
246162
|
const log3 = fs42.openSync(LOG_FILE, "a");
|
|
245699
|
-
const child = (0,
|
|
246163
|
+
const child = (0, import_node_child_process23.spawn)(process.execPath, [INST.binFile, "--_daemon", "--instance", INSTANCE], {
|
|
245700
246164
|
detached: true,
|
|
245701
246165
|
stdio: ["ignore", log3, log3],
|
|
245702
246166
|
// 与 systemd unit 里那条 Environment 等价——detached 兜底路径不能少,否则同一实例在两条
|
|
@@ -245721,24 +246185,24 @@ function stopDaemon(name) {
|
|
|
245721
246185
|
}
|
|
245722
246186
|
if (process.platform === "linux") {
|
|
245723
246187
|
try {
|
|
245724
|
-
(0,
|
|
246188
|
+
(0, import_node_child_process23.execSync)(`systemctl --user stop ${systemdUnitName(name)} 2>/dev/null`, { stdio: "ignore" });
|
|
245725
246189
|
} catch {
|
|
245726
246190
|
}
|
|
245727
246191
|
if (name === DEFAULT_INSTANCE) {
|
|
245728
246192
|
try {
|
|
245729
|
-
(0,
|
|
246193
|
+
(0, import_node_child_process23.execSync)(`systemctl --user stop ${LEGACY_SYSTEMD_UNIT} 2>/dev/null`, { stdio: "ignore" });
|
|
245730
246194
|
} catch {
|
|
245731
246195
|
}
|
|
245732
246196
|
}
|
|
245733
246197
|
} else if (process.platform === "darwin") {
|
|
245734
246198
|
const label = launchdLabel(name);
|
|
245735
246199
|
try {
|
|
245736
|
-
(0,
|
|
246200
|
+
(0, import_node_child_process23.execSync)(`launchctl unload "$HOME/Library/LaunchAgents/${label}.plist" 2>/dev/null`, { stdio: "ignore" });
|
|
245737
246201
|
} catch {
|
|
245738
246202
|
}
|
|
245739
246203
|
if (name === DEFAULT_INSTANCE && label !== LEGACY_LAUNCHD_LABEL) {
|
|
245740
246204
|
try {
|
|
245741
|
-
(0,
|
|
246205
|
+
(0, import_node_child_process23.execSync)(`launchctl unload "$HOME/Library/LaunchAgents/${LEGACY_LAUNCHD_LABEL}.plist" 2>/dev/null`, { stdio: "ignore" });
|
|
245742
246206
|
} catch {
|
|
245743
246207
|
}
|
|
245744
246208
|
}
|
|
@@ -245757,7 +246221,7 @@ function selfUpdate() {
|
|
|
245757
246221
|
const inner = `{ echo "[oasis] self-update \u2192 ${PKG_NAME}@latest (registry ${OFFICIAL}, \u5931\u8D25\u56DE\u843D\u9ED8\u8BA4\u6E90)"; sleep 2; { ${installOfficial} || ${installFallback}; } && ${printVersion} && ${startCmd}; } >> '${LOG_FILE}' 2>&1`;
|
|
245758
246222
|
const hasSystemd = process.platform === "linux" && (() => {
|
|
245759
246223
|
try {
|
|
245760
|
-
(0,
|
|
246224
|
+
(0, import_node_child_process23.execSync)("systemd-run --user --scope --quiet -- true", { stdio: "ignore" });
|
|
245761
246225
|
return true;
|
|
245762
246226
|
} catch {
|
|
245763
246227
|
return false;
|
|
@@ -245765,13 +246229,13 @@ function selfUpdate() {
|
|
|
245765
246229
|
})();
|
|
245766
246230
|
const log3 = fs42.openSync(LOG_FILE, "a");
|
|
245767
246231
|
if (hasSystemd) {
|
|
245768
|
-
const child = (0,
|
|
246232
|
+
const child = (0, import_node_child_process23.spawn)("systemd-run", ["--user", "--scope", "--quiet", "sh", "-c", inner], {
|
|
245769
246233
|
detached: true,
|
|
245770
246234
|
stdio: ["ignore", log3, log3]
|
|
245771
246235
|
});
|
|
245772
246236
|
child.unref();
|
|
245773
246237
|
} else {
|
|
245774
|
-
const child = (0,
|
|
246238
|
+
const child = (0, import_node_child_process23.spawn)("sh", ["-c", inner], { detached: true, stdio: ["ignore", log3, log3] });
|
|
245775
246239
|
child.unref();
|
|
245776
246240
|
}
|
|
245777
246241
|
}
|
|
@@ -245833,7 +246297,7 @@ async function startOneInstance(o) {
|
|
|
245833
246297
|
const res = await fetch(`${httpBase(serverUrl)}/api/nodes/exchange`, {
|
|
245834
246298
|
method: "POST",
|
|
245835
246299
|
headers: { "content-type": "application/json" },
|
|
245836
|
-
body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname:
|
|
246300
|
+
body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname: os14.hostname() })
|
|
245837
246301
|
});
|
|
245838
246302
|
if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
|
|
245839
246303
|
const body2 = await res.json();
|
|
@@ -245884,7 +246348,7 @@ function derivedNodeIdFor(name) {
|
|
|
245884
246348
|
if (name === DEFAULT_INSTANCE) return resolveNodeId();
|
|
245885
246349
|
const user = (() => {
|
|
245886
246350
|
try {
|
|
245887
|
-
return
|
|
246351
|
+
return os14.userInfo().username;
|
|
245888
246352
|
} catch {
|
|
245889
246353
|
return process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
245890
246354
|
}
|
|
@@ -245894,7 +246358,7 @@ function derivedNodeIdFor(name) {
|
|
|
245894
246358
|
function userScopeAvailable() {
|
|
245895
246359
|
if (process.platform !== "linux") return false;
|
|
245896
246360
|
try {
|
|
245897
|
-
(0,
|
|
246361
|
+
(0, import_node_child_process23.execSync)("systemd-run --user --scope --quiet -- true", { stdio: "ignore" });
|
|
245898
246362
|
return true;
|
|
245899
246363
|
} catch {
|
|
245900
246364
|
return false;
|
|
@@ -245925,11 +246389,11 @@ function spawnSessionProcess(spec) {
|
|
|
245925
246389
|
const logFd = fs42.openSync(path39.join(dir, "session.log"), "a");
|
|
245926
246390
|
const argv = [INST.binFile, "--_session", specFile];
|
|
245927
246391
|
const env = { ...process.env, OASIS_CLI_HOME: pinnedDir };
|
|
245928
|
-
const child = userScopeAvailable() ? (0,
|
|
246392
|
+
const child = userScopeAvailable() ? (0, import_node_child_process23.spawn)(
|
|
245929
246393
|
"systemd-run",
|
|
245930
246394
|
["--user", "--scope", "--quiet", `--setenv=OASIS_CLI_HOME=${pinnedDir}`, process.execPath, ...argv],
|
|
245931
246395
|
{ detached: true, stdio: ["ignore", logFd, logFd], env }
|
|
245932
|
-
) : (0,
|
|
246396
|
+
) : (0, import_node_child_process23.spawn)(process.execPath, argv, { detached: true, stdio: ["ignore", logFd, logFd], env });
|
|
245933
246397
|
child.unref();
|
|
245934
246398
|
return true;
|
|
245935
246399
|
} catch (e) {
|