oasis_test 0.1.137 → 0.1.138
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 +522 -125
- 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
|
|
|
@@ -207830,6 +207969,22 @@ var init_daemon_hub = __esm({
|
|
|
207830
207969
|
hasSession(dispatchId) {
|
|
207831
207970
|
return this.sessionSockets.get(dispatchId)?.readyState === import_websocket.default.OPEN;
|
|
207832
207971
|
}
|
|
207972
|
+
/**
|
|
207973
|
+
* 当前持有**活着数据面连接**的全部 dispatchId(ADR-0300 D8:hub 有活连接即认领)。
|
|
207974
|
+
*
|
|
207975
|
+
* orphan-sweep 的认领来源此前只有 dispatcher 在途表、chat 在途表、节点 hello、HTTP 活性——
|
|
207976
|
+
* 独立会话进程(协调者、D2′ 后搬出 daemon 的会话)**不在这四者里**,但它们自己握着一根到 hub 的
|
|
207977
|
+
* 数据面 WS。这些会话 `run.id === dispatchId`(协调者:`job.dispatchId = coordinate:*`),
|
|
207978
|
+
* 于是「hub 此刻还连着它」就是最直接的判活。不接这条线,7 天里 183 条协调者会话被误判孤儿闭合
|
|
207979
|
+
* (ADR-0300 证据 E)。只增不减:命中只能**阻止**误闭合,永不会导致误闭合。
|
|
207980
|
+
*/
|
|
207981
|
+
liveSessionDispatchIds() {
|
|
207982
|
+
const ids2 = /* @__PURE__ */ new Set();
|
|
207983
|
+
for (const [dispatchId, ws] of this.sessionSockets) {
|
|
207984
|
+
if (ws.readyState === import_websocket.default.OPEN) ids2.add(dispatchId);
|
|
207985
|
+
}
|
|
207986
|
+
return ids2;
|
|
207987
|
+
}
|
|
207833
207988
|
/** 往会话进程直投一帧(kill / append_input / ping)。返回是否写进了 OPEN 的 socket。 */
|
|
207834
207989
|
sendToSession(dispatchId, msg) {
|
|
207835
207990
|
const ws = this.sessionSockets.get(dispatchId);
|
|
@@ -214668,6 +214823,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
214668
214823
|
if (!isOwnerRecipient && !isLeadRecipient) continue;
|
|
214669
214824
|
const gaps = unresolvedGapsOf(model, a.id);
|
|
214670
214825
|
const escalations = unresolvedEscalationsOf(model, a.id);
|
|
214826
|
+
const representedEscalations = /* @__PURE__ */ new Set();
|
|
214671
214827
|
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
214828
|
for (const gap of gaps) {
|
|
214673
214829
|
const byGapId = escalations.filter((entry) => entry.gapId === gap.gapId);
|
|
@@ -214681,6 +214837,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
214681
214837
|
const exactEscalation = byGapId.at(-1) ?? (samePartGaps.length === 1 ? samePartEscalations.at(-1) : void 0) ?? (gaps.length === 1 ? partlessEscalations.at(-1) : void 0);
|
|
214682
214838
|
const gapSince = exactEscalation?.at ?? gap.lastReportedAt ?? model.lastOpAt.get(a.id) ?? "";
|
|
214683
214839
|
const gapReportCount = gap.reportCount ?? 1;
|
|
214840
|
+
if (exactEscalation) representedEscalations.add(exactEscalation.escalationId);
|
|
214684
214841
|
gapItems.push({
|
|
214685
214842
|
kind: "gap-escalation",
|
|
214686
214843
|
artifactId: a.id,
|
|
@@ -214709,8 +214866,8 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
214709
214866
|
}
|
|
214710
214867
|
});
|
|
214711
214868
|
}
|
|
214712
|
-
if (
|
|
214713
|
-
for (const e of escalations) {
|
|
214869
|
+
if (escalations.length > 0) {
|
|
214870
|
+
for (const e of escalations.filter((e2) => !representedEscalations.has(e2.escalationId))) {
|
|
214714
214871
|
gapItems.push({
|
|
214715
214872
|
kind: "gap-escalation",
|
|
214716
214873
|
artifactId: a.id,
|
|
@@ -214961,6 +215118,152 @@ var init_inbox = __esm({
|
|
|
214961
215118
|
}
|
|
214962
215119
|
});
|
|
214963
215120
|
|
|
215121
|
+
// ../server/src/domains/collab/escalation-attention.ts
|
|
215122
|
+
function escalationDeliveryConfig(env) {
|
|
215123
|
+
const positive = (key, fallback) => {
|
|
215124
|
+
if (!env[key]) return fallback;
|
|
215125
|
+
const n = Number(env[key]);
|
|
215126
|
+
if (!Number.isFinite(n) || n <= 0) throw new Error(`${key} must be a positive number`);
|
|
215127
|
+
return n;
|
|
215128
|
+
};
|
|
215129
|
+
const policy = {
|
|
215130
|
+
reminderMs: positive("OASIS_ESCALATION_REMINDER_MS", DEFAULT_ESCALATION_REMINDERS.reminderMs),
|
|
215131
|
+
acknowledgedReminderMs: positive("OASIS_ESCALATION_ACK_REMINDER_MS", DEFAULT_ESCALATION_REMINDERS.acknowledgedReminderMs)
|
|
215132
|
+
};
|
|
215133
|
+
const webhooks = /* @__PURE__ */ new Map();
|
|
215134
|
+
if (env.OASIS_ESCALATION_WEBHOOKS) {
|
|
215135
|
+
try {
|
|
215136
|
+
const entries = JSON.parse(env.OASIS_ESCALATION_WEBHOOKS);
|
|
215137
|
+
if (!entries || Array.isArray(entries) || typeof entries !== "object") throw new Error();
|
|
215138
|
+
for (const [companyId, endpoint] of Object.entries(entries)) {
|
|
215139
|
+
const url = new URL(endpoint.url);
|
|
215140
|
+
if (!companyId || !["https:", "http:"].includes(url.protocol) || url.username || url.password || endpoint.token !== void 0 && typeof endpoint.token !== "string") throw new Error();
|
|
215141
|
+
webhooks.set(companyId, endpoint);
|
|
215142
|
+
}
|
|
215143
|
+
} catch {
|
|
215144
|
+
throw new Error("OASIS_ESCALATION_WEBHOOKS must map company IDs to { url, token? } endpoints");
|
|
215145
|
+
}
|
|
215146
|
+
}
|
|
215147
|
+
return { policy, webhooks };
|
|
215148
|
+
}
|
|
215149
|
+
function withEscalationAttention(items, companyId, markers, now, policy = DEFAULT_ESCALATION_REMINDERS) {
|
|
215150
|
+
const byScope = new Map(markers.map((m2) => [m2.scope, m2.readAt]));
|
|
215151
|
+
return items.map((item) => {
|
|
215152
|
+
if (item.kind !== "gap-escalation" || !item.escalationId) return item;
|
|
215153
|
+
const start = Date.parse(item.since);
|
|
215154
|
+
if (!Number.isFinite(start)) return item;
|
|
215155
|
+
const ackAt = byScope.get(escalationAttentionScope(companyId, item.escalationId, "ack"));
|
|
215156
|
+
const ack = ackAt ? Date.parse(ackAt) : NaN;
|
|
215157
|
+
const acknowledged = Number.isFinite(ack) && ack >= start;
|
|
215158
|
+
const firstDue = acknowledged ? ack + policy.acknowledgedReminderMs : start;
|
|
215159
|
+
const due = now >= firstDue;
|
|
215160
|
+
const step = Math.max(0, Math.floor((now - firstDue) / policy.reminderMs));
|
|
215161
|
+
const dueAt = new Date(firstDue + step * policy.reminderMs).toISOString();
|
|
215162
|
+
const deliveredAt = byScope.get(escalationAttentionScope(companyId, item.escalationId, "webhook"));
|
|
215163
|
+
return { ...item, attention: {
|
|
215164
|
+
reminderKey: `${item.escalationId}:${dueAt}`,
|
|
215165
|
+
dueAt,
|
|
215166
|
+
needsAcknowledgement: due,
|
|
215167
|
+
...acknowledged ? { acknowledgedAt: ackAt } : {},
|
|
215168
|
+
...deliveredAt ? { deliveredAt } : {}
|
|
215169
|
+
} };
|
|
215170
|
+
});
|
|
215171
|
+
}
|
|
215172
|
+
async function sendEscalationWebhook(url, token, batch, item, deliveryId) {
|
|
215173
|
+
const response = await fetch(url, {
|
|
215174
|
+
method: "POST",
|
|
215175
|
+
redirect: "error",
|
|
215176
|
+
signal: AbortSignal.timeout(1e4),
|
|
215177
|
+
headers: { "content-type": "application/json", ...token ? { authorization: `Bearer ${token}` } : {} },
|
|
215178
|
+
body: JSON.stringify({ deliveryId, companyId: batch.companyId, recipientActorId: batch.actorId, item })
|
|
215179
|
+
});
|
|
215180
|
+
await response.body?.cancel();
|
|
215181
|
+
if (!response.ok) throw new Error(`Delivery HTTP ${response.status}`);
|
|
215182
|
+
}
|
|
215183
|
+
var escalationAttentionScope, DEFAULT_ESCALATION_REMINDERS, EscalationDeliveryWorker;
|
|
215184
|
+
var init_escalation_attention = __esm({
|
|
215185
|
+
"../server/src/domains/collab/escalation-attention.ts"() {
|
|
215186
|
+
"use strict";
|
|
215187
|
+
escalationAttentionScope = (companyId, issueId, kind) => `escalation-${kind}:${JSON.stringify([companyId, issueId])}`;
|
|
215188
|
+
DEFAULT_ESCALATION_REMINDERS = {
|
|
215189
|
+
reminderMs: 15 * 6e4,
|
|
215190
|
+
acknowledgedReminderMs: 4 * 60 * 6e4
|
|
215191
|
+
};
|
|
215192
|
+
EscalationDeliveryWorker = class {
|
|
215193
|
+
constructor(deps) {
|
|
215194
|
+
this.deps = deps;
|
|
215195
|
+
}
|
|
215196
|
+
running = false;
|
|
215197
|
+
stopped = false;
|
|
215198
|
+
cursor = "";
|
|
215199
|
+
/** Already-started transport is bounded by its timeout; do not start new deliveries during shutdown. */
|
|
215200
|
+
stop() {
|
|
215201
|
+
this.stopped = true;
|
|
215202
|
+
}
|
|
215203
|
+
async tick() {
|
|
215204
|
+
if (this.running || this.stopped) return;
|
|
215205
|
+
this.running = true;
|
|
215206
|
+
try {
|
|
215207
|
+
const pending = [];
|
|
215208
|
+
let attempts = 0;
|
|
215209
|
+
for (const batch of await this.deps.batches()) {
|
|
215210
|
+
if (this.stopped) return;
|
|
215211
|
+
const markers = await this.deps.markers.listMarkers(batch.actorId);
|
|
215212
|
+
const items = withEscalationAttention(
|
|
215213
|
+
batch.items,
|
|
215214
|
+
batch.companyId,
|
|
215215
|
+
markers,
|
|
215216
|
+
(this.deps.now ?? Date.now)(),
|
|
215217
|
+
this.deps.policy
|
|
215218
|
+
);
|
|
215219
|
+
for (const item of items) {
|
|
215220
|
+
const attention2 = item.attention;
|
|
215221
|
+
if (!item.escalationId || !attention2?.needsAcknowledgement) continue;
|
|
215222
|
+
if (attention2.deliveredAt && Date.parse(attention2.deliveredAt) >= Date.parse(attention2.dueAt)) continue;
|
|
215223
|
+
pending.push({ batch, item, key: JSON.stringify([batch.companyId, batch.actorId, item.escalationId]) });
|
|
215224
|
+
}
|
|
215225
|
+
}
|
|
215226
|
+
pending.sort((a, b2) => a.key < b2.key ? -1 : a.key > b2.key ? 1 : 0);
|
|
215227
|
+
const afterCursor = pending.findIndex((p2) => p2.key > this.cursor);
|
|
215228
|
+
const start = afterCursor < 0 ? 0 : afterCursor;
|
|
215229
|
+
for (let offset = 0; offset < pending.length; offset++) {
|
|
215230
|
+
if (this.stopped) break;
|
|
215231
|
+
if (attempts++ >= (this.deps.maxPerTick ?? 20)) break;
|
|
215232
|
+
const { batch, item: queued, key } = pending[(start + offset) % pending.length];
|
|
215233
|
+
this.cursor = key;
|
|
215234
|
+
try {
|
|
215235
|
+
const current = this.deps.currentItem ? await this.deps.currentItem(batch, queued.escalationId) : queued;
|
|
215236
|
+
if (!current) continue;
|
|
215237
|
+
const item = withEscalationAttention(
|
|
215238
|
+
[current],
|
|
215239
|
+
batch.companyId,
|
|
215240
|
+
await this.deps.markers.listMarkers(batch.actorId),
|
|
215241
|
+
(this.deps.now ?? Date.now)(),
|
|
215242
|
+
this.deps.policy
|
|
215243
|
+
)[0];
|
|
215244
|
+
const attention2 = item.attention;
|
|
215245
|
+
if (this.stopped || !attention2.needsAcknowledgement || attention2.deliveredAt && Date.parse(attention2.deliveredAt) >= Date.parse(attention2.dueAt)) continue;
|
|
215246
|
+
const id = JSON.stringify([batch.companyId, batch.actorId, attention2.reminderKey]);
|
|
215247
|
+
await this.deps.send(batch, item, id);
|
|
215248
|
+
await this.deps.markers.markRead(
|
|
215249
|
+
batch.actorId,
|
|
215250
|
+
escalationAttentionScope(batch.companyId, item.escalationId, "webhook"),
|
|
215251
|
+
attention2.dueAt
|
|
215252
|
+
);
|
|
215253
|
+
} catch {
|
|
215254
|
+
this.deps.log(`[escalation-delivery] delivery failed; retained for retry (${key})`);
|
|
215255
|
+
}
|
|
215256
|
+
}
|
|
215257
|
+
} catch {
|
|
215258
|
+
this.deps.log("[escalation-delivery] scan failed; will retry");
|
|
215259
|
+
} finally {
|
|
215260
|
+
this.running = false;
|
|
215261
|
+
}
|
|
215262
|
+
}
|
|
215263
|
+
};
|
|
215264
|
+
}
|
|
215265
|
+
});
|
|
215266
|
+
|
|
214964
215267
|
// ../server/src/domains/collab/inbox-chat.ts
|
|
214965
215268
|
function mergeInbox(kernelItems, chatItems) {
|
|
214966
215269
|
if (chatItems.length === 0) return kernelItems;
|
|
@@ -216408,7 +216711,23 @@ function collabDomain(opts) {
|
|
|
216408
216711
|
const { reviews, works } = collectWaitingRows(snaps, me, policy);
|
|
216409
216712
|
waitingItems = buildWaitingInbox(reviews, works, policy, (/* @__PURE__ */ new Date()).toISOString(), me);
|
|
216410
216713
|
}
|
|
216411
|
-
|
|
216714
|
+
const items = mergeInbox(kernelItems, [...chatItems, ...waitingItems]);
|
|
216715
|
+
return { status: 200, body: { items: opts.readMarkers ? withEscalationAttention(items, req.auth.companyId ?? opts.defaultCompanyId ?? "", markers, Date.now(), opts.escalationReminders) : items } };
|
|
216716
|
+
});
|
|
216717
|
+
router.post("/api/inbox/escalations/:id/acknowledge", async (req) => {
|
|
216718
|
+
if (!opts.readMarkers) return { status: 503, body: { error: { code: "not_configured", message: "\u63A5\u624B\u8BB0\u5F55\u672A\u88C5\u914D" } } };
|
|
216719
|
+
const { kernel, registry: registry2 } = await resolveCtx(req.auth.companyId);
|
|
216720
|
+
await kernel.refreshModel?.();
|
|
216721
|
+
const leadOf = await buildLeadResolver(registry2);
|
|
216722
|
+
const item = buildInbox(kernel.model, req.auth.actor, leadOf).find((i) => i.escalationId === req.params.id);
|
|
216723
|
+
if (!item?.escalationId) return { status: 404, body: { error: { code: "not_found", message: "\u5F85\u529E\u4E0D\u5B58\u5728\u6216\u4E0D\u5C5E\u4E8E\u4F60" } } };
|
|
216724
|
+
const acknowledgedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
216725
|
+
await opts.readMarkers.markRead(
|
|
216726
|
+
req.auth.actor,
|
|
216727
|
+
escalationAttentionScope(req.auth.companyId ?? opts.defaultCompanyId ?? "", item.escalationId, "ack"),
|
|
216728
|
+
acknowledgedAt
|
|
216729
|
+
);
|
|
216730
|
+
return { status: 200, body: { acknowledgedAt } };
|
|
216412
216731
|
});
|
|
216413
216732
|
const companyOf = (req) => req.auth.companyId ?? "company:default";
|
|
216414
216733
|
const noTagStore = { status: 501, body: { error: { code: "not_implemented", message: "\u672C\u90E8\u7F72\u672A\u542F\u7528\u5DE5\u5355\u6807\u7B7E" } } };
|
|
@@ -216647,6 +216966,7 @@ var init_collab = __esm({
|
|
|
216647
216966
|
init_workorders();
|
|
216648
216967
|
init_workorder_detail();
|
|
216649
216968
|
init_inbox();
|
|
216969
|
+
init_escalation_attention();
|
|
216650
216970
|
init_inbox_chat();
|
|
216651
216971
|
init_waiting_inbox();
|
|
216652
216972
|
init_src3();
|
|
@@ -216660,6 +216980,7 @@ var init_collab = __esm({
|
|
|
216660
216980
|
init_workorder_detail();
|
|
216661
216981
|
init_workorder_metrics();
|
|
216662
216982
|
init_inbox();
|
|
216983
|
+
init_escalation_attention();
|
|
216663
216984
|
init_letter_read_backfill();
|
|
216664
216985
|
init_audit();
|
|
216665
216986
|
init_dashboard();
|
|
@@ -216686,7 +217007,7 @@ function prepareReadonlyGitBundles(input) {
|
|
|
216686
217007
|
if (repos.length === 0) return null;
|
|
216687
217008
|
const targets = collectTargets(repos, input.pinnedRevisions);
|
|
216688
217009
|
if (targets.length === 0) return null;
|
|
216689
|
-
const bundleRoot = input.bundleRoot ??
|
|
217010
|
+
const bundleRoot = input.bundleRoot ?? os7.tmpdir();
|
|
216690
217011
|
fs23.mkdirSync(bundleRoot, { recursive: true });
|
|
216691
217012
|
const root = fs23.mkdtempSync(path24.join(bundleRoot, "oasis-git-bundles-"));
|
|
216692
217013
|
const files = {};
|
|
@@ -216833,7 +217154,7 @@ function createBundle(root, target, input) {
|
|
|
216833
217154
|
function verifyBundleReadable(dir, bundlePath, _bundleRef, commit, expectedTree, env) {
|
|
216834
217155
|
fs23.rmSync(dir, { recursive: true, force: true });
|
|
216835
217156
|
try {
|
|
216836
|
-
(0,
|
|
217157
|
+
(0, import_node_child_process17.execFileSync)("git", ["clone", bundlePath, dir], { stdio: "ignore", ...env ? { env } : {} });
|
|
216837
217158
|
git2(dir, ["cat-file", "-e", `${commit}^{commit}`], env, "COMMIT_NOT_FOUND");
|
|
216838
217159
|
const head = git2(dir, ["rev-parse", "HEAD"], env, "COMMIT_NOT_FOUND").trim();
|
|
216839
217160
|
if (head.toLowerCase() !== commit.toLowerCase()) {
|
|
@@ -216875,11 +217196,11 @@ function ensureSourceRepo(work, repo, commit, env) {
|
|
|
216875
217196
|
function gitInitBare(dir, env) {
|
|
216876
217197
|
if (fs23.existsSync(path24.join(dir, "objects"))) return;
|
|
216877
217198
|
fs23.mkdirSync(dir, { recursive: true });
|
|
216878
|
-
(0,
|
|
217199
|
+
(0, import_node_child_process17.execFileSync)("git", ["init", "--bare", dir], { stdio: "ignore", ...env ? { env } : {} });
|
|
216879
217200
|
}
|
|
216880
217201
|
function git2(cwd, args, env, fallback, timeout) {
|
|
216881
217202
|
try {
|
|
216882
|
-
return (0,
|
|
217203
|
+
return (0, import_node_child_process17.execFileSync)("git", ["-C", cwd, ...args], {
|
|
216883
217204
|
encoding: "utf8",
|
|
216884
217205
|
stdio: ["ignore", "pipe", "pipe"],
|
|
216885
217206
|
...timeout ? { timeout } : {},
|
|
@@ -216903,14 +217224,14 @@ function classifyGitError(fallback, err, where) {
|
|
|
216903
217224
|
function oneLine(msg) {
|
|
216904
217225
|
return msg.split("\n").map((s2) => s2.trim()).filter(Boolean).slice(0, 3).join(" ");
|
|
216905
217226
|
}
|
|
216906
|
-
var
|
|
217227
|
+
var import_node_child_process17, import_node_crypto45, fs23, os7, path24, GitReadonlyBundleError, HEX40, FETCH_TIMEOUT_MS2;
|
|
216907
217228
|
var init_readonly_bundle = __esm({
|
|
216908
217229
|
"../server/src/git/readonly-bundle.ts"() {
|
|
216909
217230
|
"use strict";
|
|
216910
|
-
|
|
217231
|
+
import_node_child_process17 = require("node:child_process");
|
|
216911
217232
|
import_node_crypto45 = require("node:crypto");
|
|
216912
217233
|
fs23 = __toESM(require("node:fs"), 1);
|
|
216913
|
-
|
|
217234
|
+
os7 = __toESM(require("node:os"), 1);
|
|
216914
217235
|
path24 = __toESM(require("node:path"), 1);
|
|
216915
217236
|
init_remote_util();
|
|
216916
217237
|
GitReadonlyBundleError = class extends Error {
|
|
@@ -219417,7 +219738,9 @@ function createChatSessionsDomain(opts) {
|
|
|
219417
219738
|
router.get("/api/chat-sessions/:id/turns/active", async (req) => {
|
|
219418
219739
|
if (!opts.chatTurns) throw new ApiError(404, "NOT_FOUND", "\u672C\u5B9E\u4F8B\u672A\u63A5\u4F1A\u8BDD\u8F6E\u6B21\u8D26\u672C");
|
|
219419
219740
|
const session = await store.getSession(req.params.id);
|
|
219420
|
-
if (!session || session.humanActorId !== req.auth.actor
|
|
219741
|
+
if (!session || session.humanActorId !== req.auth.actor && session.aiActorId !== req.auth.actor) {
|
|
219742
|
+
throw new ApiError(404, "NOT_FOUND", "session not found");
|
|
219743
|
+
}
|
|
219421
219744
|
const turn = await opts.chatTurns.activeTurn(req.params.id);
|
|
219422
219745
|
return { status: 200, body: { turn } };
|
|
219423
219746
|
});
|
|
@@ -224127,11 +224450,11 @@ var init_engine = __esm({
|
|
|
224127
224450
|
constructor(table = /* @__PURE__ */ new Map()) {
|
|
224128
224451
|
this.table = table;
|
|
224129
224452
|
}
|
|
224130
|
-
set(
|
|
224131
|
-
this.table.set(`${
|
|
224453
|
+
set(platform2, platformUserId, actor) {
|
|
224454
|
+
this.table.set(`${platform2}:${platformUserId}`, actor);
|
|
224132
224455
|
}
|
|
224133
|
-
resolve(
|
|
224134
|
-
return this.table.get(`${
|
|
224456
|
+
resolve(platform2, platformUserId) {
|
|
224457
|
+
return this.table.get(`${platform2}:${platformUserId}`) ?? null;
|
|
224135
224458
|
}
|
|
224136
224459
|
};
|
|
224137
224460
|
}
|
|
@@ -224670,7 +224993,7 @@ ${HIGH_RISK_COMMANDS}`;
|
|
|
224670
224993
|
const downstreams = consumersOf(m2, p2.id).map((a) => a.id);
|
|
224671
224994
|
const task = [
|
|
224672
224995
|
`## \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\
|
|
224996
|
+
`\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
224997
|
``,
|
|
224675
224998
|
`## \u75C5\u5386\uFF08\u673A\u68B0\u8BCA\u65AD\uFF1B\u5148\u8BFB\u8FD9\u4E2A\uFF09`,
|
|
224676
224999
|
caseFile,
|
|
@@ -225801,6 +226124,7 @@ var init_src10 = __esm({
|
|
|
225801
226124
|
init_orphan_sweep();
|
|
225802
226125
|
init_dispatch_drop_sweep();
|
|
225803
226126
|
init_dispatch_mapping_rebuild();
|
|
226127
|
+
init_dispatch_binding_diagnosis();
|
|
225804
226128
|
init_zero_output_breaker();
|
|
225805
226129
|
init_dispatch_exit_reconcile();
|
|
225806
226130
|
init_session_exit_outcome();
|
|
@@ -225839,6 +226163,7 @@ var init_src10 = __esm({
|
|
|
225839
226163
|
init_node_store();
|
|
225840
226164
|
init_tokens();
|
|
225841
226165
|
init_collab();
|
|
226166
|
+
init_collab();
|
|
225842
226167
|
init_closure_report();
|
|
225843
226168
|
init_workorders();
|
|
225844
226169
|
init_workorder_detail();
|
|
@@ -233741,22 +234066,22 @@ var init_trajectory = __esm({
|
|
|
233741
234066
|
|
|
233742
234067
|
// src/index.ts
|
|
233743
234068
|
var fs42 = __toESM(require("node:fs"));
|
|
233744
|
-
var
|
|
234069
|
+
var os14 = __toESM(require("node:os"));
|
|
233745
234070
|
var path39 = __toESM(require("node:path"));
|
|
233746
|
-
var
|
|
234071
|
+
var import_node_child_process23 = require("node:child_process");
|
|
233747
234072
|
var import_node_crypto66 = require("node:crypto");
|
|
233748
234073
|
|
|
233749
234074
|
// ../cli/src/cli.ts
|
|
233750
234075
|
var fs37 = __toESM(require("node:fs"), 1);
|
|
233751
|
-
var
|
|
234076
|
+
var os12 = __toESM(require("node:os"), 1);
|
|
233752
234077
|
var path34 = __toESM(require("node:path"), 1);
|
|
233753
234078
|
var import_node_crypto64 = require("node:crypto");
|
|
233754
234079
|
|
|
233755
234080
|
// ../cli/src/serve.ts
|
|
233756
234081
|
var fs31 = __toESM(require("node:fs"), 1);
|
|
233757
|
-
var
|
|
234082
|
+
var os8 = __toESM(require("node:os"), 1);
|
|
233758
234083
|
var path28 = __toESM(require("node:path"), 1);
|
|
233759
|
-
var
|
|
234084
|
+
var import_node_child_process18 = require("node:child_process");
|
|
233760
234085
|
var import_node_crypto60 = require("node:crypto");
|
|
233761
234086
|
var import_node_url7 = require("node:url");
|
|
233762
234087
|
|
|
@@ -234333,8 +234658,10 @@ var SESSION_TOKEN_GRACE_MS = 15 * 6e4;
|
|
|
234333
234658
|
function makeResumeRetryProxy(first, spawnFallback) {
|
|
234334
234659
|
const outCbs = [];
|
|
234335
234660
|
const telCbs = [];
|
|
234661
|
+
const liveCbs = [];
|
|
234336
234662
|
const outBuf = [];
|
|
234337
234663
|
const telBuf = [];
|
|
234664
|
+
const liveBuf = [];
|
|
234338
234665
|
let sawOutput = false;
|
|
234339
234666
|
let active = first;
|
|
234340
234667
|
const fanOut = (chunk) => {
|
|
@@ -234345,12 +234672,17 @@ function makeResumeRetryProxy(first, spawnFallback) {
|
|
|
234345
234672
|
if (telCbs.length) for (const cb of telCbs) cb(e);
|
|
234346
234673
|
else telBuf.push(e);
|
|
234347
234674
|
};
|
|
234675
|
+
const fanLive = (e) => {
|
|
234676
|
+
if (liveCbs.length) for (const cb of liveCbs) cb(e);
|
|
234677
|
+
else liveBuf.push(e);
|
|
234678
|
+
};
|
|
234348
234679
|
const wire = (s2) => {
|
|
234349
234680
|
s2.onOutput((c) => {
|
|
234350
234681
|
sawOutput = true;
|
|
234351
234682
|
fanOut(c);
|
|
234352
234683
|
});
|
|
234353
234684
|
s2.onTelemetry?.((e) => fanTel(e));
|
|
234685
|
+
s2.onLiveEvent?.((e) => fanLive(e));
|
|
234354
234686
|
};
|
|
234355
234687
|
wire(first);
|
|
234356
234688
|
const isSessionNotFound2 = (err) => {
|
|
@@ -234382,6 +234714,10 @@ function makeResumeRetryProxy(first, spawnFallback) {
|
|
|
234382
234714
|
for (const e of telBuf.splice(0)) cb(e);
|
|
234383
234715
|
telCbs.push(cb);
|
|
234384
234716
|
},
|
|
234717
|
+
onLiveEvent(cb) {
|
|
234718
|
+
for (const e of liveBuf.splice(0)) cb(e);
|
|
234719
|
+
liveCbs.push(cb);
|
|
234720
|
+
},
|
|
234385
234721
|
done,
|
|
234386
234722
|
kill: () => active.kill?.() ?? Promise.resolve(),
|
|
234387
234723
|
// ADR-0093 chat 道:插入能力必须穿过这层代理,否则「带 sessionId 的 resume」这条**常路径**
|
|
@@ -234392,6 +234728,11 @@ function makeResumeRetryProxy(first, spawnFallback) {
|
|
|
234392
234728
|
get canAppendInput() {
|
|
234393
234729
|
return active.canAppendInput !== false && typeof active.appendInput === "function";
|
|
234394
234730
|
},
|
|
234731
|
+
// supportsLiveProtocol 恒读 active(兜底重派后 active 换成 second):不能按 first 快照,否则回退会话的
|
|
234732
|
+
// 能力位会指向已死的首次尝试。
|
|
234733
|
+
get supportsLiveProtocol() {
|
|
234734
|
+
return active.supportsLiveProtocol === true;
|
|
234735
|
+
},
|
|
234395
234736
|
get nativeSessionId() {
|
|
234396
234737
|
return active.nativeSessionId;
|
|
234397
234738
|
}
|
|
@@ -234452,15 +234793,15 @@ function oasisWrapperScript() {
|
|
|
234452
234793
|
const main = path28.join(repoRoot, "packages/cli/src/main.ts");
|
|
234453
234794
|
const key = (0, import_node_crypto60.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
|
|
234454
234795
|
const uid = typeof process.getuid === "function" ? process.getuid() : "na";
|
|
234455
|
-
const stable = path28.join(
|
|
234796
|
+
const stable = path28.join(os8.tmpdir(), `oasis-cli-wrapper-${uid}-${key}`);
|
|
234456
234797
|
let dir;
|
|
234457
234798
|
try {
|
|
234458
234799
|
fs31.mkdirSync(stable, { recursive: true, mode: 448 });
|
|
234459
234800
|
const st = fs31.lstatSync(stable);
|
|
234460
234801
|
const mine = st.isDirectory() && !st.isSymbolicLink() && (typeof process.getuid !== "function" || st.uid === process.getuid());
|
|
234461
|
-
dir = mine ? stable : fs31.mkdtempSync(path28.join(
|
|
234802
|
+
dir = mine ? stable : fs31.mkdtempSync(path28.join(os8.tmpdir(), "oasis-cli-"));
|
|
234462
234803
|
} catch {
|
|
234463
|
-
dir = fs31.mkdtempSync(path28.join(
|
|
234804
|
+
dir = fs31.mkdtempSync(path28.join(os8.tmpdir(), "oasis-cli-"));
|
|
234464
234805
|
}
|
|
234465
234806
|
const wrapper = path28.join(dir, "oasis");
|
|
234466
234807
|
fs31.writeFileSync(wrapper, `#!/usr/bin/env bash
|
|
@@ -234538,7 +234879,7 @@ async function runDeterministicKnowledgeLint(service, config2) {
|
|
|
234538
234879
|
if (!wrapper) throw new Error(`\u8FDE\u63A5\u5668 ${config2.connectorSlug} \u5C1A\u672A\u914D\u7F6E\u6216 wrapper \u4E0D\u53EF\u7528`);
|
|
234539
234880
|
const args = [...connector.knowledgeLintArgs({ libraryRef: config2.libraryRef, rootRef: config2.rootRef })];
|
|
234540
234881
|
const result = await new Promise((resolveResult) => {
|
|
234541
|
-
(0,
|
|
234882
|
+
(0, import_node_child_process18.execFile)(wrapper, args, {
|
|
234542
234883
|
env: { ...process.env, ...provision.env },
|
|
234543
234884
|
timeout: 12e4,
|
|
234544
234885
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -234808,7 +235149,7 @@ async function startServe(opts) {
|
|
|
234808
235149
|
);
|
|
234809
235150
|
const issuer = createTokenIssuer({ secretFile: path28.join(opts.dir, "session-token-secret") });
|
|
234810
235151
|
const apiActivity = createApiActivityLedger();
|
|
234811
|
-
const operatorActor = `actor:human:${
|
|
235152
|
+
const operatorActor = `actor:human:${os8.userInfo().username}`;
|
|
234812
235153
|
const operatorToken = issuer.issue(operatorActor);
|
|
234813
235154
|
fs31.writeFileSync(path28.join(opts.dir, "operator-token"), operatorToken, { mode: 384 });
|
|
234814
235155
|
let nodeTokens = createNodeTokenStore(path28.join(opts.dir, "node-tokens.json"));
|
|
@@ -234929,6 +235270,7 @@ async function startServe(opts) {
|
|
|
234929
235270
|
let chatSessionStore;
|
|
234930
235271
|
let chatTurnStore;
|
|
234931
235272
|
let readMarkerStore;
|
|
235273
|
+
const escalationDelivery = escalationDeliveryConfig(process.env);
|
|
234932
235274
|
if (pgDsn && pgPool) {
|
|
234933
235275
|
projectStateStore = await PostgresProjectStateStore.open(pgPool, pgSchema);
|
|
234934
235276
|
artifactStateStore = await PostgresArtifactStateStore.open(pgPool, pgSchema);
|
|
@@ -235963,6 +236305,8 @@ async function startServe(opts) {
|
|
|
235963
236305
|
chatSession: chatSessionStore,
|
|
235964
236306
|
// ADR-0086:chat 知会条目(与 readMarkers 成对)
|
|
235965
236307
|
readMarkers: readMarkerStore,
|
|
236308
|
+
escalationReminders: escalationDelivery.policy,
|
|
236309
|
+
defaultCompanyId,
|
|
235966
236310
|
// 工单标签词表(组织级受控、旁账,与 playbook-overrides 同款侧存)。
|
|
235967
236311
|
tags: workorderTagStore,
|
|
235968
236312
|
...opts.sla ? { sla: opts.sla } : {},
|
|
@@ -237504,6 +237848,8 @@ async function startServe(opts) {
|
|
|
237504
237848
|
ledgerWarn("cancel(map-miss)")(err);
|
|
237505
237849
|
}
|
|
237506
237850
|
},
|
|
237851
|
+
// Inbox is the notification contract (ADR 0090). Escalation delivery reconciles persisted Inbox
|
|
237852
|
+
// items below; it must not depend on this one-shot effect or its legacy recipient list.
|
|
237507
237853
|
async notify(_actorIds, _payload) {
|
|
237508
237854
|
}
|
|
237509
237855
|
};
|
|
@@ -237524,6 +237870,14 @@ async function startServe(opts) {
|
|
|
237524
237870
|
return live;
|
|
237525
237871
|
},
|
|
237526
237872
|
isAgent: async (actorId) => await executorKindOf(actorId) === "agent",
|
|
237873
|
+
beforeRedispatch: async (work) => {
|
|
237874
|
+
return prepareDroppedDispatch(work, {
|
|
237875
|
+
kernel: newKernel,
|
|
237876
|
+
// This sweep belongs to the default engine; legacy workorder.companyId is often empty.
|
|
237877
|
+
bindingFor: async (actorId) => (await actors.resolveCtx(defaultCompanyId)).service.resolveBinding()(actorId),
|
|
237878
|
+
nodeFor: (nodeId) => nodeStore.getNode(nodeId)
|
|
237879
|
+
});
|
|
237880
|
+
},
|
|
237527
237881
|
// resumeEligible=false:补派一律起**全新会话**。引擎那次派发的取值是节点状态的函数
|
|
237528
237882
|
//(activate.ts:`latestAcceptId == null && !lastProposedRejected`),本模块拿不到,
|
|
237529
237883
|
// 而两个方向的代价不对称——该续没续只是少一点上下文,不该续却续了就把返工要隔离的
|
|
@@ -238371,7 +238725,45 @@ async function startServe(opts) {
|
|
|
238371
238725
|
return { fused, starving, stuck, recovered };
|
|
238372
238726
|
}
|
|
238373
238727
|
const slaEscalating = /* @__PURE__ */ new Set();
|
|
238728
|
+
const escalationDeliveryWorker = new EscalationDeliveryWorker({
|
|
238729
|
+
markers: readMarkerStore,
|
|
238730
|
+
policy: escalationDelivery.policy,
|
|
238731
|
+
batches: async () => {
|
|
238732
|
+
const batches = [];
|
|
238733
|
+
for (const companyId of escalationDelivery.webhooks.keys()) {
|
|
238734
|
+
const companyEngine = await getEngine(companyId);
|
|
238735
|
+
await companyEngine.kernel.refreshModel();
|
|
238736
|
+
const leadOf2 = await buildLeadResolver(companyEngine.registry);
|
|
238737
|
+
const recipients = /* @__PURE__ */ new Set();
|
|
238738
|
+
for (const node2 of companyEngine.kernel.model.artifacts.values()) {
|
|
238739
|
+
recipients.add(node2.owner);
|
|
238740
|
+
const lead = leadOf2?.(node2.owner);
|
|
238741
|
+
if (lead) recipients.add(lead);
|
|
238742
|
+
}
|
|
238743
|
+
for (const actorId of recipients) {
|
|
238744
|
+
const items = buildInbox(companyEngine.kernel.model, actorId, leadOf2).filter((item) => item.escalationId && item.artifactId && lifecycleOf(companyEngine.kernel.model, item.artifactId) === "active");
|
|
238745
|
+
if (items.length) batches.push({ companyId, actorId, items });
|
|
238746
|
+
}
|
|
238747
|
+
}
|
|
238748
|
+
return batches;
|
|
238749
|
+
},
|
|
238750
|
+
currentItem: async (batch, issueId) => {
|
|
238751
|
+
const companyEngine = await getEngine(batch.companyId);
|
|
238752
|
+
await companyEngine.kernel.refreshModel();
|
|
238753
|
+
const leadOf2 = await buildLeadResolver(companyEngine.registry);
|
|
238754
|
+
return buildInbox(companyEngine.kernel.model, batch.actorId, leadOf2).find((item) => item.escalationId === issueId && item.artifactId && lifecycleOf(companyEngine.kernel.model, item.artifactId) === "active");
|
|
238755
|
+
},
|
|
238756
|
+
send: async (batch, item, deliveryId) => {
|
|
238757
|
+
const endpoint = escalationDelivery.webhooks.get(batch.companyId);
|
|
238758
|
+
await sendEscalationWebhook(endpoint.url, endpoint.token, batch, item, deliveryId);
|
|
238759
|
+
},
|
|
238760
|
+
log: (message) => console.warn(message)
|
|
238761
|
+
});
|
|
238762
|
+
if (!escalationDelivery.webhooks.size) {
|
|
238763
|
+
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");
|
|
238764
|
+
}
|
|
238374
238765
|
const slaTimer = setInterval(() => {
|
|
238766
|
+
void escalationDeliveryWorker.tick();
|
|
238375
238767
|
void (async () => {
|
|
238376
238768
|
const now = Date.now();
|
|
238377
238769
|
for (const a of kernel.model.artifacts.values()) {
|
|
@@ -238683,6 +239075,7 @@ ${nodeFault}` : "");
|
|
|
238683
239075
|
for (const c of chatLiveSessions.values()) ids2.add(c.sessionId);
|
|
238684
239076
|
return ids2;
|
|
238685
239077
|
};
|
|
239078
|
+
const liveSessionRunIds = () => hub?.liveSessionDispatchIds() ?? /* @__PURE__ */ new Set();
|
|
238686
239079
|
const aliveArtifactIds = () => {
|
|
238687
239080
|
const ids2 = /* @__PURE__ */ new Set();
|
|
238688
239081
|
for (const d of hub?.connectedDaemons() ?? []) {
|
|
@@ -238713,6 +239106,8 @@ ${nodeFault}` : "");
|
|
|
238713
239106
|
aliveArtifactIds,
|
|
238714
239107
|
apiActiveDispatchIds,
|
|
238715
239108
|
// D1(ADR-0078):判活第二条线
|
|
239109
|
+
liveSessionRunIds,
|
|
239110
|
+
// ADR-0300 D8:hub 活数据面连接(协调者/独立会话进程)
|
|
238716
239111
|
closeRun,
|
|
238717
239112
|
now: Date.now(),
|
|
238718
239113
|
orphanGraceMs,
|
|
@@ -238892,6 +239287,7 @@ ${nodeFault}` : "");
|
|
|
238892
239287
|
close: async () => {
|
|
238893
239288
|
for (const timer of dispatchTimers) clearInterval(timer);
|
|
238894
239289
|
clearInterval(slaTimer);
|
|
239290
|
+
escalationDeliveryWorker.stop();
|
|
238895
239291
|
if (mirrorTimer) clearInterval(mirrorTimer);
|
|
238896
239292
|
if (gitTimer) clearInterval(gitTimer);
|
|
238897
239293
|
if (coordTimer) clearInterval(coordTimer);
|
|
@@ -238991,7 +239387,7 @@ function log2(tag, msg, extra) {
|
|
|
238991
239387
|
}
|
|
238992
239388
|
|
|
238993
239389
|
// ../cli/src/daemon/session-lock.ts
|
|
238994
|
-
var
|
|
239390
|
+
var import_node_child_process19 = require("node:child_process");
|
|
238995
239391
|
var fs32 = __toESM(require("node:fs"), 1);
|
|
238996
239392
|
var path29 = __toESM(require("node:path"), 1);
|
|
238997
239393
|
var flockAvailable = null;
|
|
@@ -238999,7 +239395,7 @@ function hasFlock() {
|
|
|
238999
239395
|
if (flockAvailable !== null) return flockAvailable;
|
|
239000
239396
|
if (process.platform !== "linux") return flockAvailable = false;
|
|
239001
239397
|
try {
|
|
239002
|
-
const r = (0,
|
|
239398
|
+
const r = (0, import_node_child_process19.spawnSync)("flock", ["--version"], { stdio: "ignore", timeout: 3e3 });
|
|
239003
239399
|
flockAvailable = r.status === 0;
|
|
239004
239400
|
} catch {
|
|
239005
239401
|
flockAvailable = false;
|
|
@@ -239014,7 +239410,7 @@ function acquireSessionLock(lockPath) {
|
|
|
239014
239410
|
fs32.unlinkSync(readyFile);
|
|
239015
239411
|
} catch {
|
|
239016
239412
|
}
|
|
239017
|
-
const child = (0,
|
|
239413
|
+
const child = (0, import_node_child_process19.spawn)("flock", ["-n", lockPath, "-c", `printf ok > '${readyFile}'; exec cat`], {
|
|
239018
239414
|
stdio: ["pipe", "ignore", "ignore"],
|
|
239019
239415
|
detached: true
|
|
239020
239416
|
});
|
|
@@ -239025,7 +239421,7 @@ function acquireSessionLock(lockPath) {
|
|
|
239025
239421
|
ready = true;
|
|
239026
239422
|
break;
|
|
239027
239423
|
}
|
|
239028
|
-
(0,
|
|
239424
|
+
(0, import_node_child_process19.spawnSync)("sleep", ["0.02"], { stdio: "ignore" });
|
|
239029
239425
|
}
|
|
239030
239426
|
try {
|
|
239031
239427
|
fs32.unlinkSync(readyFile);
|
|
@@ -239056,7 +239452,7 @@ function isSessionLocked(lockPath) {
|
|
|
239056
239452
|
if (!hasFlock()) return false;
|
|
239057
239453
|
if (!fs32.existsSync(lockPath)) return false;
|
|
239058
239454
|
try {
|
|
239059
|
-
const r = (0,
|
|
239455
|
+
const r = (0, import_node_child_process19.spawnSync)("flock", ["-n", lockPath, "-c", "true"], { stdio: "ignore", timeout: 3e3 });
|
|
239060
239456
|
return r.status !== 0;
|
|
239061
239457
|
} catch {
|
|
239062
239458
|
return true;
|
|
@@ -239132,6 +239528,7 @@ var RECONNECT_MIN_MS = 1e3;
|
|
|
239132
239528
|
var RECONNECT_MAX_MS = 3e4;
|
|
239133
239529
|
var EXIT_ACK_WAIT_MS = LINK_WINDOWS.exitAckWaitMs;
|
|
239134
239530
|
async function runSessionProcess(specFile, adapter) {
|
|
239531
|
+
process.env["OASIS_BIND_RUNTIME_PDEATHSIG"] = "1";
|
|
239135
239532
|
const spec = readSpec(specFile);
|
|
239136
239533
|
const { dispatchId, job, auth, sessionDir } = spec;
|
|
239137
239534
|
const lock = acquireSessionLock(path30.join(sessionDir, "lock"));
|
|
@@ -239395,7 +239792,7 @@ init_src8();
|
|
|
239395
239792
|
init_src7();
|
|
239396
239793
|
|
|
239397
239794
|
// ../cli/src/daemon/detect-adapters.ts
|
|
239398
|
-
var
|
|
239795
|
+
var import_node_child_process20 = require("node:child_process");
|
|
239399
239796
|
init_src7();
|
|
239400
239797
|
var KNOWN2 = [
|
|
239401
239798
|
{ adapter: "claude-code", binary: "claude" },
|
|
@@ -239419,7 +239816,7 @@ var LIVE_PROTOCOL_RUNTIMES = /* @__PURE__ */ new Set(["claude-code"]);
|
|
|
239419
239816
|
function resolveOnPath2(binary) {
|
|
239420
239817
|
try {
|
|
239421
239818
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
239422
|
-
const out = (0,
|
|
239819
|
+
const out = (0, import_node_child_process20.execFileSync)(cmd, [binary], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
239423
239820
|
const first = out.split("\n")[0]?.trim();
|
|
239424
239821
|
return first || binary;
|
|
239425
239822
|
} catch {
|
|
@@ -239428,7 +239825,7 @@ function resolveOnPath2(binary) {
|
|
|
239428
239825
|
}
|
|
239429
239826
|
function versionOf(binary) {
|
|
239430
239827
|
try {
|
|
239431
|
-
return (0,
|
|
239828
|
+
return (0, import_node_child_process20.execFileSync)(binary, ["--version"], {
|
|
239432
239829
|
encoding: "utf8",
|
|
239433
239830
|
stdio: ["ignore", "pipe", "ignore"],
|
|
239434
239831
|
timeout: 1500
|
|
@@ -240384,7 +240781,7 @@ async function startNode(opts) {
|
|
|
240384
240781
|
}
|
|
240385
240782
|
|
|
240386
240783
|
// ../cli/src/exec.ts
|
|
240387
|
-
var
|
|
240784
|
+
var os11 = __toESM(require("node:os"), 1);
|
|
240388
240785
|
var UnsafeExecArgvError = class extends Error {
|
|
240389
240786
|
code = "ERR_UNSAFE_EXEC_ARGV";
|
|
240390
240787
|
constructor(message) {
|
|
@@ -240421,7 +240818,7 @@ function planExec(opts) {
|
|
|
240421
240818
|
function computeExitCode(code2, signal) {
|
|
240422
240819
|
if (code2 !== null) return code2;
|
|
240423
240820
|
if (signal) {
|
|
240424
|
-
const num2 =
|
|
240821
|
+
const num2 = os11.constants.signals[signal];
|
|
240425
240822
|
return 128 + (typeof num2 === "number" ? num2 : 1);
|
|
240426
240823
|
}
|
|
240427
240824
|
return 1;
|
|
@@ -240445,7 +240842,7 @@ function forwardSignal(child, sig, killGroup = (pgid, signal) => {
|
|
|
240445
240842
|
}
|
|
240446
240843
|
|
|
240447
240844
|
// ../cli/src/daemon/machine-id.ts
|
|
240448
|
-
var
|
|
240845
|
+
var import_node_child_process21 = require("node:child_process");
|
|
240449
240846
|
var import_node_fs20 = require("node:fs");
|
|
240450
240847
|
var import_node_crypto62 = require("node:crypto");
|
|
240451
240848
|
var import_node_os12 = require("node:os");
|
|
@@ -240461,7 +240858,7 @@ function linuxMachineId() {
|
|
|
240461
240858
|
}
|
|
240462
240859
|
function macMachineId() {
|
|
240463
240860
|
try {
|
|
240464
|
-
const out = (0,
|
|
240861
|
+
const out = (0, import_node_child_process21.execFileSync)("ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"], {
|
|
240465
240862
|
encoding: "utf8",
|
|
240466
240863
|
timeout: 2e3,
|
|
240467
240864
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -240474,7 +240871,7 @@ function macMachineId() {
|
|
|
240474
240871
|
}
|
|
240475
240872
|
function windowsMachineId() {
|
|
240476
240873
|
try {
|
|
240477
|
-
const out = (0,
|
|
240874
|
+
const out = (0, import_node_child_process21.execFileSync)("reg", [
|
|
240478
240875
|
"query",
|
|
240479
240876
|
"HKLM\\SOFTWARE\\Microsoft\\Cryptography",
|
|
240480
240877
|
"/v",
|
|
@@ -242184,7 +242581,7 @@ function ownFlagsFromDecl(command) {
|
|
|
242184
242581
|
|
|
242185
242582
|
// ../cli/src/connector-effect-runner.ts
|
|
242186
242583
|
var import_node_crypto63 = require("node:crypto");
|
|
242187
|
-
var
|
|
242584
|
+
var import_node_child_process22 = require("node:child_process");
|
|
242188
242585
|
init_src8();
|
|
242189
242586
|
function stableKey(effect) {
|
|
242190
242587
|
const keyFields = Object.fromEntries(Object.entries(effect.keyFields).sort(([a], [b2]) => a.localeCompare(b2)));
|
|
@@ -242243,7 +242640,7 @@ function productionApi() {
|
|
|
242243
242640
|
}
|
|
242244
242641
|
function execute(bin, args) {
|
|
242245
242642
|
return new Promise((resolve10, reject) => {
|
|
242246
|
-
const child = (0,
|
|
242643
|
+
const child = (0, import_node_child_process22.spawn)(bin, args, { stdio: "inherit", env: process.env });
|
|
242247
242644
|
child.once("error", reject);
|
|
242248
242645
|
child.once("exit", (code2, signal) => resolve10(code2 ?? (signal ? 128 : 1)));
|
|
242249
242646
|
});
|
|
@@ -242673,7 +243070,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242673
243070
|
const res = await fetch(`${httpBase2}/api/nodes/exchange`, {
|
|
242674
243071
|
method: "POST",
|
|
242675
243072
|
headers: { "content-type": "application/json" },
|
|
242676
|
-
body: JSON.stringify({ enrollToken, nodeId, hostname:
|
|
243073
|
+
body: JSON.stringify({ enrollToken, nodeId, hostname: os12.hostname() })
|
|
242677
243074
|
});
|
|
242678
243075
|
if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
|
|
242679
243076
|
const body2 = await res.json();
|
|
@@ -242706,7 +243103,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242706
243103
|
const binPath = path34.join(prefix, "bin", "oasis_test");
|
|
242707
243104
|
const svcArgs = `node --server-ws ${serverUrl} --dir ${dir}${nodeName ? ` --name ${nodeName}` : ""}`;
|
|
242708
243105
|
if (process.platform === "linux") {
|
|
242709
|
-
const svcFile = path34.join(
|
|
243106
|
+
const svcFile = path34.join(os12.homedir(), ".config/systemd/user/oasis-node.service");
|
|
242710
243107
|
fs37.mkdirSync(path34.dirname(svcFile), { recursive: true });
|
|
242711
243108
|
if (spawnSync3("systemctl", ["--user", "is-active", "--quiet", "oasis-node"], {}).status === 0)
|
|
242712
243109
|
spawnSync3("systemctl", ["--user", "stop", "oasis-node"], { stdio: "inherit" });
|
|
@@ -242719,7 +243116,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242719
243116
|
`ExecStart=${binPath} ${svcArgs}`,
|
|
242720
243117
|
// Carry the install-time PATH so the detached daemon detects CLIs in user dirs
|
|
242721
243118
|
// (~/.npm-global/bin, ~/.local/bin) — systemd --user otherwise gives a minimal PATH.
|
|
242722
|
-
`Environment=PATH=${process.env["PATH"] ?? ""}:${path34.join(
|
|
243119
|
+
`Environment=PATH=${process.env["PATH"] ?? ""}:${path34.join(os12.homedir(), ".npm-global/bin")}:${path34.join(os12.homedir(), ".local/bin")}:/usr/local/bin`,
|
|
242723
243120
|
"Restart=on-failure",
|
|
242724
243121
|
"RestartSec=5",
|
|
242725
243122
|
"StandardOutput=journal",
|
|
@@ -242731,23 +243128,23 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242731
243128
|
].join("\n"));
|
|
242732
243129
|
spawnSync3("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
|
|
242733
243130
|
spawnSync3("systemctl", ["--user", "enable", "--now", "oasis-node"], { stdio: "inherit" });
|
|
242734
|
-
spawnSync3("loginctl", ["enable-linger",
|
|
243131
|
+
spawnSync3("loginctl", ["enable-linger", os12.userInfo().username], { stdio: "ignore" });
|
|
242735
243132
|
println("\u2713 Oasis node service started (systemd --user oasis-node)");
|
|
242736
243133
|
println(" Status : systemctl --user status oasis-node");
|
|
242737
243134
|
println(" Logs : journalctl --user -u oasis-node -f");
|
|
242738
243135
|
println(" Stop : systemctl --user stop oasis-node");
|
|
242739
243136
|
} else if (process.platform === "darwin") {
|
|
242740
|
-
const plist = path34.join(
|
|
243137
|
+
const plist = path34.join(os12.homedir(), "Library/LaunchAgents/com.oasis.node.plist");
|
|
242741
243138
|
fs37.mkdirSync(path34.dirname(plist), { recursive: true });
|
|
242742
243139
|
spawnSync3("launchctl", ["unload", plist], { stdio: "ignore" });
|
|
242743
243140
|
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>${
|
|
243141
|
+
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
243142
|
spawnSync3("launchctl", ["load", plist], { stdio: "inherit" });
|
|
242746
243143
|
println("\u2713 Oasis node service started (macOS LaunchAgent com.oasis.node)");
|
|
242747
|
-
println(` Logs : tail -f ${
|
|
243144
|
+
println(` Logs : tail -f ${os12.homedir()}/.oasis-node.log`);
|
|
242748
243145
|
println(` Stop : launchctl unload ${plist}`);
|
|
242749
243146
|
} else {
|
|
242750
|
-
spawnSync3("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${path34.join(
|
|
243147
|
+
spawnSync3("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${path34.join(os12.homedir(), ".oasis-node.log")} 2>&1 &`], { stdio: "inherit" });
|
|
242751
243148
|
println(`\u2713 Oasis node started in background (nohup). Logs: ~/.oasis-node.log`);
|
|
242752
243149
|
println(" Note: no automatic restart on reboot in this environment.");
|
|
242753
243150
|
}
|
|
@@ -242846,8 +243243,8 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
242846
243243
|
if (command === "serve" && positional[0] === "install") {
|
|
242847
243244
|
const absDir = path34.resolve(dir);
|
|
242848
243245
|
const name = `oasis-serve-${path34.basename(absDir)}`;
|
|
242849
|
-
const unitDir = flags.get("unit-dir") ?? path34.join(
|
|
242850
|
-
const bin = flags.get("bin") ?? path34.join(
|
|
243246
|
+
const unitDir = flags.get("unit-dir") ?? path34.join(os12.homedir(), ".config", "systemd", "user");
|
|
243247
|
+
const bin = flags.get("bin") ?? path34.join(os12.homedir(), ".local", "bin", "oasis");
|
|
242851
243248
|
const port = flags.get("port") ?? "7320";
|
|
242852
243249
|
const extra = (flags.get("dispatch") === "true" ? ` --dispatch true` : "") + (flags.has("model") ? ` --model ${flags.get("model")}` : "");
|
|
242853
243250
|
const unit = [
|
|
@@ -243191,7 +243588,7 @@ Trace: ${run.traceRunId}`);
|
|
|
243191
243588
|
if (plan.inject.mode === "env") {
|
|
243192
243589
|
childEnv[plan.inject.envName] = value2;
|
|
243193
243590
|
} else {
|
|
243194
|
-
tmpDir = await fs37.promises.mkdtemp(path34.join(
|
|
243591
|
+
tmpDir = await fs37.promises.mkdtemp(path34.join(os12.tmpdir(), "oasis-var-exec-"));
|
|
243195
243592
|
const keyfile = path34.join(tmpDir, "value");
|
|
243196
243593
|
await fs37.promises.writeFile(keyfile, value2, { mode: 384 });
|
|
243197
243594
|
childEnv[plan.inject.fileEnv] = keyfile;
|
|
@@ -243965,7 +244362,7 @@ ${res.warning}`);
|
|
|
243965
244362
|
for (const a of st.artifacts) println(` - ${a.path}\uFF08${a.kind ?? "?"}\uFF09status=${a.status ?? "?"}${a.mtime ? ` \xB7 ${new Date(a.mtime).toISOString()}` : ""}`);
|
|
243966
244363
|
if (flags.get("pull") === "true") {
|
|
243967
244364
|
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,
|
|
244365
|
+
const { dir: dir3, entry: entry2 } = await harvestBoard(odBase2, fetch, odPublic2, os12.tmpdir(), st.boardKey, st.runs[0]?.runId ?? "status-pull");
|
|
243969
244366
|
println(`[design] \u5DF2\u62C9\u5230\u672C\u5730\uFF1A${dir3}\uFF08\u5165\u53E3 ${entry2}\uFF09`);
|
|
243970
244367
|
println(`[design] \u8BFB\u5B8C\u6EE1\u610F\u5373\u4EA4\u7A3F\uFF1Aoasis propose ${artifactId2} --from-dir ${dir3} --reason "<\u8FD9\u7248\u505A\u4E86\u4EC0\u4E48>"`);
|
|
243971
244368
|
} else {
|
|
@@ -245335,10 +245732,10 @@ function runtimeAssetSourceRoots(input) {
|
|
|
245335
245732
|
|
|
245336
245733
|
// src/paths.ts
|
|
245337
245734
|
var fs40 = __toESM(require("node:fs"));
|
|
245338
|
-
var
|
|
245735
|
+
var os13 = __toESM(require("node:os"));
|
|
245339
245736
|
var path37 = __toESM(require("node:path"));
|
|
245340
245737
|
var DEFAULT_INSTANCE = "default";
|
|
245341
|
-
var home = () =>
|
|
245738
|
+
var home = () => os13.homedir();
|
|
245342
245739
|
var oasisDir = () => path37.join(home(), ".oasis");
|
|
245343
245740
|
var versionsDir = () => path37.join(oasisDir(), "versions");
|
|
245344
245741
|
var versionDir = (label) => path37.join(versionsDir(), label);
|
|
@@ -245537,7 +245934,7 @@ function shimScript() {
|
|
|
245537
245934
|
}
|
|
245538
245935
|
|
|
245539
245936
|
// src/index.ts
|
|
245540
|
-
var PKG_VERSION = true ? "0.1.
|
|
245937
|
+
var PKG_VERSION = true ? "0.1.138" : "dev";
|
|
245541
245938
|
var LOCAL_BIN = localBin();
|
|
245542
245939
|
var NPM_PREFIX = npmPrefix();
|
|
245543
245940
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -245637,7 +246034,7 @@ function installSoftware(label) {
|
|
|
245637
246034
|
function setupAutostart(name) {
|
|
245638
246035
|
const inst = instancePaths(name);
|
|
245639
246036
|
const cmd = `${process.execPath} "${inst.binFile}" --_daemon --instance ${name}`;
|
|
245640
|
-
const home2 =
|
|
246037
|
+
const home2 = os14.homedir();
|
|
245641
246038
|
const pnpmHome = process.env["PNPM_HOME"] || path39.join(home2, ".local", "share", "pnpm");
|
|
245642
246039
|
const extraBins = [
|
|
245643
246040
|
path39.join(home2, ".npm-global", "bin"),
|
|
@@ -245647,7 +246044,7 @@ function setupAutostart(name) {
|
|
|
245647
246044
|
];
|
|
245648
246045
|
const daemonPath = sanitizeDaemonPath([process.env["PATH"] ?? "", ...extraBins].filter(Boolean).join(":"));
|
|
245649
246046
|
if (process.platform === "linux") {
|
|
245650
|
-
const unitDir = path39.join(
|
|
246047
|
+
const unitDir = path39.join(os14.homedir(), ".config", "systemd", "user");
|
|
245651
246048
|
fs42.mkdirSync(unitDir, { recursive: true });
|
|
245652
246049
|
const unit = systemdUnitName(name);
|
|
245653
246050
|
fs42.mkdirSync(path39.dirname(inst.logFile), { recursive: true });
|
|
@@ -245660,19 +246057,19 @@ function setupAutostart(name) {
|
|
|
245660
246057
|
}));
|
|
245661
246058
|
if (name === DEFAULT_INSTANCE) {
|
|
245662
246059
|
try {
|
|
245663
|
-
(0,
|
|
246060
|
+
(0, import_node_child_process23.execSync)(`systemctl --user disable --now ${LEGACY_SYSTEMD_UNIT} 2>/dev/null`, { stdio: "ignore" });
|
|
245664
246061
|
} catch {
|
|
245665
246062
|
}
|
|
245666
246063
|
}
|
|
245667
246064
|
try {
|
|
245668
|
-
(0,
|
|
246065
|
+
(0, import_node_child_process23.execSync)(`systemctl --user daemon-reload && systemctl --user enable --now ${unit}`, { stdio: "ignore" });
|
|
245669
246066
|
return true;
|
|
245670
246067
|
} catch {
|
|
245671
246068
|
}
|
|
245672
246069
|
return false;
|
|
245673
246070
|
} else if (process.platform === "darwin") {
|
|
245674
246071
|
const label = launchdLabel(name);
|
|
245675
|
-
const plist = path39.join(
|
|
246072
|
+
const plist = path39.join(os14.homedir(), "Library", "LaunchAgents", `${label}.plist`);
|
|
245676
246073
|
fs42.mkdirSync(path39.dirname(plist), { recursive: true });
|
|
245677
246074
|
fs42.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?>
|
|
245678
246075
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -245685,7 +246082,7 @@ function setupAutostart(name) {
|
|
|
245685
246082
|
<key>StandardErrorPath</key><string>${inst.logFile}</string>
|
|
245686
246083
|
</dict></plist>`);
|
|
245687
246084
|
try {
|
|
245688
|
-
(0,
|
|
246085
|
+
(0, import_node_child_process23.execSync)(`launchctl load "${plist}"`, { stdio: "ignore" });
|
|
245689
246086
|
return true;
|
|
245690
246087
|
} catch {
|
|
245691
246088
|
}
|
|
@@ -245696,7 +246093,7 @@ function setupAutostart(name) {
|
|
|
245696
246093
|
function spawnDaemon() {
|
|
245697
246094
|
fs42.mkdirSync(path39.dirname(LOG_FILE), { recursive: true });
|
|
245698
246095
|
const log3 = fs42.openSync(LOG_FILE, "a");
|
|
245699
|
-
const child = (0,
|
|
246096
|
+
const child = (0, import_node_child_process23.spawn)(process.execPath, [INST.binFile, "--_daemon", "--instance", INSTANCE], {
|
|
245700
246097
|
detached: true,
|
|
245701
246098
|
stdio: ["ignore", log3, log3],
|
|
245702
246099
|
// 与 systemd unit 里那条 Environment 等价——detached 兜底路径不能少,否则同一实例在两条
|
|
@@ -245721,24 +246118,24 @@ function stopDaemon(name) {
|
|
|
245721
246118
|
}
|
|
245722
246119
|
if (process.platform === "linux") {
|
|
245723
246120
|
try {
|
|
245724
|
-
(0,
|
|
246121
|
+
(0, import_node_child_process23.execSync)(`systemctl --user stop ${systemdUnitName(name)} 2>/dev/null`, { stdio: "ignore" });
|
|
245725
246122
|
} catch {
|
|
245726
246123
|
}
|
|
245727
246124
|
if (name === DEFAULT_INSTANCE) {
|
|
245728
246125
|
try {
|
|
245729
|
-
(0,
|
|
246126
|
+
(0, import_node_child_process23.execSync)(`systemctl --user stop ${LEGACY_SYSTEMD_UNIT} 2>/dev/null`, { stdio: "ignore" });
|
|
245730
246127
|
} catch {
|
|
245731
246128
|
}
|
|
245732
246129
|
}
|
|
245733
246130
|
} else if (process.platform === "darwin") {
|
|
245734
246131
|
const label = launchdLabel(name);
|
|
245735
246132
|
try {
|
|
245736
|
-
(0,
|
|
246133
|
+
(0, import_node_child_process23.execSync)(`launchctl unload "$HOME/Library/LaunchAgents/${label}.plist" 2>/dev/null`, { stdio: "ignore" });
|
|
245737
246134
|
} catch {
|
|
245738
246135
|
}
|
|
245739
246136
|
if (name === DEFAULT_INSTANCE && label !== LEGACY_LAUNCHD_LABEL) {
|
|
245740
246137
|
try {
|
|
245741
|
-
(0,
|
|
246138
|
+
(0, import_node_child_process23.execSync)(`launchctl unload "$HOME/Library/LaunchAgents/${LEGACY_LAUNCHD_LABEL}.plist" 2>/dev/null`, { stdio: "ignore" });
|
|
245742
246139
|
} catch {
|
|
245743
246140
|
}
|
|
245744
246141
|
}
|
|
@@ -245757,7 +246154,7 @@ function selfUpdate() {
|
|
|
245757
246154
|
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
246155
|
const hasSystemd = process.platform === "linux" && (() => {
|
|
245759
246156
|
try {
|
|
245760
|
-
(0,
|
|
246157
|
+
(0, import_node_child_process23.execSync)("systemd-run --user --scope --quiet -- true", { stdio: "ignore" });
|
|
245761
246158
|
return true;
|
|
245762
246159
|
} catch {
|
|
245763
246160
|
return false;
|
|
@@ -245765,13 +246162,13 @@ function selfUpdate() {
|
|
|
245765
246162
|
})();
|
|
245766
246163
|
const log3 = fs42.openSync(LOG_FILE, "a");
|
|
245767
246164
|
if (hasSystemd) {
|
|
245768
|
-
const child = (0,
|
|
246165
|
+
const child = (0, import_node_child_process23.spawn)("systemd-run", ["--user", "--scope", "--quiet", "sh", "-c", inner], {
|
|
245769
246166
|
detached: true,
|
|
245770
246167
|
stdio: ["ignore", log3, log3]
|
|
245771
246168
|
});
|
|
245772
246169
|
child.unref();
|
|
245773
246170
|
} else {
|
|
245774
|
-
const child = (0,
|
|
246171
|
+
const child = (0, import_node_child_process23.spawn)("sh", ["-c", inner], { detached: true, stdio: ["ignore", log3, log3] });
|
|
245775
246172
|
child.unref();
|
|
245776
246173
|
}
|
|
245777
246174
|
}
|
|
@@ -245833,7 +246230,7 @@ async function startOneInstance(o) {
|
|
|
245833
246230
|
const res = await fetch(`${httpBase(serverUrl)}/api/nodes/exchange`, {
|
|
245834
246231
|
method: "POST",
|
|
245835
246232
|
headers: { "content-type": "application/json" },
|
|
245836
|
-
body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname:
|
|
246233
|
+
body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname: os14.hostname() })
|
|
245837
246234
|
});
|
|
245838
246235
|
if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
|
|
245839
246236
|
const body2 = await res.json();
|
|
@@ -245884,7 +246281,7 @@ function derivedNodeIdFor(name) {
|
|
|
245884
246281
|
if (name === DEFAULT_INSTANCE) return resolveNodeId();
|
|
245885
246282
|
const user = (() => {
|
|
245886
246283
|
try {
|
|
245887
|
-
return
|
|
246284
|
+
return os14.userInfo().username;
|
|
245888
246285
|
} catch {
|
|
245889
246286
|
return process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
245890
246287
|
}
|
|
@@ -245894,7 +246291,7 @@ function derivedNodeIdFor(name) {
|
|
|
245894
246291
|
function userScopeAvailable() {
|
|
245895
246292
|
if (process.platform !== "linux") return false;
|
|
245896
246293
|
try {
|
|
245897
|
-
(0,
|
|
246294
|
+
(0, import_node_child_process23.execSync)("systemd-run --user --scope --quiet -- true", { stdio: "ignore" });
|
|
245898
246295
|
return true;
|
|
245899
246296
|
} catch {
|
|
245900
246297
|
return false;
|
|
@@ -245925,11 +246322,11 @@ function spawnSessionProcess(spec) {
|
|
|
245925
246322
|
const logFd = fs42.openSync(path39.join(dir, "session.log"), "a");
|
|
245926
246323
|
const argv = [INST.binFile, "--_session", specFile];
|
|
245927
246324
|
const env = { ...process.env, OASIS_CLI_HOME: pinnedDir };
|
|
245928
|
-
const child = userScopeAvailable() ? (0,
|
|
246325
|
+
const child = userScopeAvailable() ? (0, import_node_child_process23.spawn)(
|
|
245929
246326
|
"systemd-run",
|
|
245930
246327
|
["--user", "--scope", "--quiet", `--setenv=OASIS_CLI_HOME=${pinnedDir}`, process.execPath, ...argv],
|
|
245931
246328
|
{ detached: true, stdio: ["ignore", logFd, logFd], env }
|
|
245932
|
-
) : (0,
|
|
246329
|
+
) : (0, import_node_child_process23.spawn)(process.execPath, argv, { detached: true, stdio: ["ignore", logFd, logFd], env });
|
|
245933
246330
|
child.unref();
|
|
245934
246331
|
return true;
|
|
245935
246332
|
} catch (e) {
|