oasis_test_v2 2.2.100 → 2.2.101
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 +331 -82
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2240,18 +2240,23 @@ function firstSentenceSummary(text7, max = CARD_SUMMARY_MAX) {
|
|
|
2240
2240
|
const cps = [...clean2];
|
|
2241
2241
|
return cps.length > max ? `${cps.slice(0, max).join("")}\u2026` : clean2;
|
|
2242
2242
|
}
|
|
2243
|
+
function requoteStepTitle(text7, title) {
|
|
2244
|
+
const t = title?.trim();
|
|
2245
|
+
return t && text7 ? text7.split(`\u300A${t}\u300B`).join(stepQuote(t)) : text7;
|
|
2246
|
+
}
|
|
2243
2247
|
function nodePhrase(args, refs) {
|
|
2244
2248
|
const id = argStr(args, "artifactId");
|
|
2245
2249
|
const title = id ? refs.nodeTitle?.(id)?.trim() : void 0;
|
|
2246
|
-
return title ?
|
|
2250
|
+
return title ? stepQuote(title) : NEUTRAL_NODE;
|
|
2247
2251
|
}
|
|
2248
2252
|
function targetPhrase(naming, neutral) {
|
|
2249
|
-
const summary = firstSentenceSummary(naming?.summary);
|
|
2250
2253
|
const nodeTitle = naming?.nodeTitle?.trim();
|
|
2254
|
+
const raw = firstSentenceSummary(naming?.summary);
|
|
2255
|
+
const summary = requoteStepTitle(raw, nodeTitle);
|
|
2251
2256
|
if (summary) {
|
|
2252
|
-
return { phrase: nodeTitle && !summary.includes(nodeTitle) ?
|
|
2257
|
+
return { phrase: nodeTitle && !summary.includes(nodeTitle) ? `${stepQuote(nodeTitle)}\u2014\u2014${summary}` : summary, named: true };
|
|
2253
2258
|
}
|
|
2254
|
-
if (nodeTitle) return { phrase:
|
|
2259
|
+
if (nodeTitle) return { phrase: `${stepQuote(nodeTitle)}\u4E0A\u7684${neutral}`, named: true };
|
|
2255
2260
|
return { phrase: neutral, named: false };
|
|
2256
2261
|
}
|
|
2257
2262
|
function escalationPhraseOf(refs, escalationId) {
|
|
@@ -2272,7 +2277,7 @@ function describeCommandForHuman(command2, args, refs = {}) {
|
|
|
2272
2277
|
case "promote":
|
|
2273
2278
|
return `\u628A${nodePhrase(args, refs)}\u8F6C\u4E3A\u957F\u671F\u4FDD\u7559\u7684\u8282\u70B9\uFF08\u4E0D\u518D\u968F\u4EFB\u52A1\u7ED3\u675F\u56DE\u6536\uFF09\u3002`;
|
|
2274
2279
|
// continueBatch(续跑额度卡)**故意不在这里**:它的文案由引擎写好放在 `continuationBudget.request.summary`
|
|
2275
|
-
//
|
|
2280
|
+
// 里,本来就是「「节点名」尚未完成,已达到自动派发上限。累计已运行 N 轮…」这种名称式写法,没有 id。
|
|
2276
2281
|
// 重写一遍只会让同一句话有两个事实源,交给 {@link commandCardDisplayLabel} 的兜底清洗即可。
|
|
2277
2282
|
case "resolveEscalation": {
|
|
2278
2283
|
const escalation = escalationPhraseOf(refs, argStr(args, "escalationId"));
|
|
@@ -2291,16 +2296,18 @@ function describeCommandForHuman(command2, args, refs = {}) {
|
|
|
2291
2296
|
}
|
|
2292
2297
|
function commandCardDisplayLabel(command2, args, storedLabel, refs = {}) {
|
|
2293
2298
|
const described = command2 ? describeCommandForHuman(command2, args ?? {}, refs) : void 0;
|
|
2294
|
-
|
|
2299
|
+
if (described !== void 0) return described;
|
|
2300
|
+
const id = argStr(args ?? {}, "artifactId");
|
|
2301
|
+
return requoteStepTitle(stripInternalIds(storedLabel ?? ""), id ? refs.nodeTitle?.(id) : void 0);
|
|
2295
2302
|
}
|
|
2296
2303
|
function nodeRefPhrase(ref2, refs, neutral = NEUTRAL_NODE) {
|
|
2297
2304
|
const raw = (ref2 ?? "").trim();
|
|
2298
2305
|
if (!raw) return neutral;
|
|
2299
2306
|
const title = refs.nodeTitle?.(raw)?.trim();
|
|
2300
|
-
if (title) return
|
|
2307
|
+
if (title) return stepQuote(title);
|
|
2301
2308
|
if (!containsInternalId(raw)) {
|
|
2302
2309
|
const tail = raw.includes(":") ? raw.slice(raw.indexOf(":") + 1).trim() : raw;
|
|
2303
|
-
if (tail && !containsInternalId(tail)) return
|
|
2310
|
+
if (tail && !containsInternalId(tail)) return stepQuote(tail);
|
|
2304
2311
|
}
|
|
2305
2312
|
return neutral;
|
|
2306
2313
|
}
|
|
@@ -2308,8 +2315,8 @@ function actorNamePhrase(actorId, refs) {
|
|
|
2308
2315
|
const raw = (actorId ?? "").trim();
|
|
2309
2316
|
if (!raw) return NEUTRAL_APPROVER;
|
|
2310
2317
|
const name = refs.actorName?.(raw)?.trim();
|
|
2311
|
-
if (name) return name;
|
|
2312
|
-
return containsInternalId(raw) ? NEUTRAL_APPROVER : raw;
|
|
2318
|
+
if (name) return atName(name);
|
|
2319
|
+
return containsInternalId(raw) ? NEUTRAL_APPROVER : atName(raw);
|
|
2313
2320
|
}
|
|
2314
2321
|
function graphEditOpDisplayLabel(op, refs = {}) {
|
|
2315
2322
|
const node2 = nodeRefPhrase(op?.artifactId, refs);
|
|
@@ -2341,7 +2348,7 @@ function graphEditOpDisplayLabel(op, refs = {}) {
|
|
|
2341
2348
|
return op?.action ? stripInternalIds(op.action) : "\u53D8\u66F4";
|
|
2342
2349
|
}
|
|
2343
2350
|
}
|
|
2344
|
-
var PREFIXED_ID_RE, UUID_RE, SHORT_ID_RE, CARD_SUMMARY_MAX, NEUTRAL_NODE, NEUTRAL_NODE_OTHER, NEUTRAL_ESCALATION, NEUTRAL_GAP, NEUTRAL_APPROVER, argStr;
|
|
2351
|
+
var PREFIXED_ID_RE, UUID_RE, SHORT_ID_RE, CARD_SUMMARY_MAX, NEUTRAL_NODE, NEUTRAL_NODE_OTHER, NEUTRAL_ESCALATION, NEUTRAL_GAP, NEUTRAL_APPROVER, argStr, stepQuote, atName;
|
|
2345
2352
|
var init_command_card_copy = __esm({
|
|
2346
2353
|
"../contract/src/command-card-copy.ts"() {
|
|
2347
2354
|
"use strict";
|
|
@@ -2358,6 +2365,8 @@ var init_command_card_copy = __esm({
|
|
|
2358
2365
|
const v2 = args[key2];
|
|
2359
2366
|
return typeof v2 === "string" && v2.trim() ? v2.trim() : void 0;
|
|
2360
2367
|
};
|
|
2368
|
+
stepQuote = (title) => `\u300C${title}\u300D`;
|
|
2369
|
+
atName = (name) => name.startsWith("@") ? name : `@${name}`;
|
|
2361
2370
|
}
|
|
2362
2371
|
});
|
|
2363
2372
|
|
|
@@ -13705,6 +13714,7 @@ async function recordChatTurnInterruption(deps) {
|
|
|
13705
13714
|
return touched;
|
|
13706
13715
|
} catch (err) {
|
|
13707
13716
|
log3(`[chat-interrupt] items \u7ED3\u5C40\u9879\u5199\u5165\u5931\u8D25\uFF1Asession=${sessionId} turn=${turnId} ${String(err)}`);
|
|
13717
|
+
if (deps.rethrow) throw err;
|
|
13708
13718
|
return [];
|
|
13709
13719
|
}
|
|
13710
13720
|
}
|
|
@@ -166150,7 +166160,10 @@ var init_live_chat = __esm({
|
|
|
166150
166160
|
};
|
|
166151
166161
|
ctrl = this.start(chatSessionId, handle);
|
|
166152
166162
|
const turn = this.turns.get(chatSessionId);
|
|
166153
|
-
if (turn)
|
|
166163
|
+
if (turn) {
|
|
166164
|
+
turn.recovering = true;
|
|
166165
|
+
turn.recoveringLedgerTurnId = opts.ledgerTurnId;
|
|
166166
|
+
}
|
|
166154
166167
|
return ctrl;
|
|
166155
166168
|
}
|
|
166156
166169
|
/** 占位轮的最后一个观众断开即回收:没真 runtime 喂它,留着只会占内存、也会让 `isRunning` 恒真。 */
|
|
@@ -166338,6 +166351,61 @@ var init_live_chat = __esm({
|
|
|
166338
166351
|
turn.cancelCause = cause;
|
|
166339
166352
|
return true;
|
|
166340
166353
|
}
|
|
166354
|
+
/**
|
|
166355
|
+
* 该会话当前挂着的是不是一个还在跑的**占位轮**({@link reopenForRecovery} 起的,没有真句柄)。
|
|
166356
|
+
* `/stop` 据此改走台账:占位轮的 kill 只会就地收掉页面上的那一轮,真正让节点那一轮停下的是台账终态,
|
|
166357
|
+
* 必须等台账写成了才能回「停住了」(Bug 0228 评审返工)。
|
|
166358
|
+
*/
|
|
166359
|
+
isRecovering(chatSessionId) {
|
|
166360
|
+
const turn = this.turns.get(chatSessionId);
|
|
166361
|
+
return !!turn?.recovering && turn.status === "running";
|
|
166362
|
+
}
|
|
166363
|
+
/**
|
|
166364
|
+
* 当前占位轮的身份;不是占位轮 = undefined。`epoch` = 本会话的轮次序号(单调递增、不复用),
|
|
166365
|
+
* `/stop` 回来用 {@link stopSameTurn} 只收这一个占位轮;`ledgerTurnId` = 它对应的台账行,
|
|
166366
|
+
* `/stop` 在台账上只停这一行,绝不按会话现查到的下一轮去写。
|
|
166367
|
+
*/
|
|
166368
|
+
recoveringTurn(chatSessionId) {
|
|
166369
|
+
const turn = this.turns.get(chatSessionId);
|
|
166370
|
+
if (!turn?.recovering || turn.status !== "running" || !turn.recoveringLedgerTurnId) return void 0;
|
|
166371
|
+
return { epoch: turn.liveEpoch, ledgerTurnId: turn.recoveringLedgerTurnId };
|
|
166372
|
+
}
|
|
166373
|
+
/**
|
|
166374
|
+
* 当前在跑的真轮(非占位轮)的身份;没有 = undefined。`/stop` 等完本进程开轮后先记下它,
|
|
166375
|
+
* 核实它就是台账上要停的那一行,再用 {@link stopSameTurn} 按 `epoch` 只停它(Bug 0228 第四轮评审)。
|
|
166376
|
+
*/
|
|
166377
|
+
runningTurn(chatSessionId) {
|
|
166378
|
+
const turn = this.turns.get(chatSessionId);
|
|
166379
|
+
if (!turn || turn.recovering || turn.status !== "running") return void 0;
|
|
166380
|
+
return {
|
|
166381
|
+
epoch: turn.liveEpoch,
|
|
166382
|
+
...turn.runId ? { runId: turn.runId } : {},
|
|
166383
|
+
...turn.items ? { turnId: turn.items.turnId } : {}
|
|
166384
|
+
};
|
|
166385
|
+
}
|
|
166386
|
+
/**
|
|
166387
|
+
* 注册表里此刻在跑的这一轮,**认得出**就是台账行 `ledgerTurnId` 吗(Bug 0228 第五轮评审)。
|
|
166388
|
+
* 占位轮看它挂的台账行,真轮看它 items 账本的轮次 id(接了台账的开轮路上就是台账行 id)。
|
|
166389
|
+
* 认不出(没有 items 账本、或 items 沿用了老 turn_id)一律 false——调用方改去台账上按 id 核,不当成同一轮。
|
|
166390
|
+
*/
|
|
166391
|
+
isTurn(chatSessionId, ledgerTurnId) {
|
|
166392
|
+
const turn = this.turns.get(chatSessionId);
|
|
166393
|
+
if (!turn || turn.status !== "running") return false;
|
|
166394
|
+
return (turn.recovering ? turn.recoveringLedgerTurnId : turn.items?.turnId) === ledgerTurnId;
|
|
166395
|
+
}
|
|
166396
|
+
/**
|
|
166397
|
+
* 只停「还是那一轮」的轮:轮次序号等于 `epoch`(还是当初那个占位轮),或 `runId` 严格相等
|
|
166398
|
+
* (恢复路已把占位轮换成同一轮的真句柄)。换成了别的轮(下一轮、或没有 runId 的新轮)一律不动、回 false。
|
|
166399
|
+
* 与 {@link stop} 的 `expectedRunId` 不同:那边没有 runId 的轮也会停,这里不会(Bug 0228 评审返工)。
|
|
166400
|
+
*/
|
|
166401
|
+
stopSameTurn(chatSessionId, same) {
|
|
166402
|
+
const turn = this.turns.get(chatSessionId);
|
|
166403
|
+
if (!turn) return false;
|
|
166404
|
+
const isSame = turn.liveEpoch === same.epoch || !!same.runId && turn.runId === same.runId;
|
|
166405
|
+
if (!isSame) return false;
|
|
166406
|
+
this.stop(chatSessionId);
|
|
166407
|
+
return true;
|
|
166408
|
+
}
|
|
166341
166409
|
/** 该会话当前是否有一轮 running(供上层判断是否要挡并发发送)。 */
|
|
166342
166410
|
isRunning(chatSessionId) {
|
|
166343
166411
|
return this.turns.get(chatSessionId)?.status === "running";
|
|
@@ -171383,20 +171451,27 @@ async function stopLedgerTurn(deps) {
|
|
|
171383
171451
|
const now = deps.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
171384
171452
|
const log3 = deps.log ?? (() => {
|
|
171385
171453
|
});
|
|
171386
|
-
let turn = deps.turn ?? await deps.turns.activeTurn(deps.sessionId);
|
|
171454
|
+
let turn = deps.turn ?? (deps.turnId ? await deps.turns.getTurn(deps.turnId) : await deps.turns.activeTurn(deps.sessionId));
|
|
171387
171455
|
for (let attempt = 0; attempt < MAX_CAS_ATTEMPTS; attempt += 1) {
|
|
171456
|
+
if (turn?.status === "cancelled" && turn.cancelledBy === "user") {
|
|
171457
|
+
if (deps.expectedRunId && turn.assistantRunId !== deps.expectedRunId) return { stopped: false, reason: "turn-changed" };
|
|
171458
|
+
deps.onCancelled?.(turn);
|
|
171459
|
+
await recordUserStopNotice(deps, turn, turn.completedAt ?? now());
|
|
171460
|
+
return { stopped: true, ledger: true };
|
|
171461
|
+
}
|
|
171388
171462
|
if (!turn || turn.status !== "reserved" && turn.status !== "running") return { stopped: false, reason: "no-live-turn" };
|
|
171389
|
-
if (deps.expectedRunId && turn.assistantRunId
|
|
171463
|
+
if (deps.expectedRunId && turn.assistantRunId !== deps.expectedRunId) {
|
|
171390
171464
|
return { stopped: false, reason: "turn-changed" };
|
|
171391
171465
|
}
|
|
171392
171466
|
const completedAt = now();
|
|
171393
171467
|
const ok3 = await deps.turns.transitionTurn(
|
|
171394
171468
|
turn.id,
|
|
171395
171469
|
{ status: turn.status, dispatchId: turn.dispatchId },
|
|
171396
|
-
{ status: "cancelled", completedAt, lastError: `\u7528\u6237\u505C\u6B62\uFF08\u672C\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CC\u6CA1\u6709\u8FD9\u4E00\u8F6E\uFF0C\u6309\u53F0\u8D26\u6536\uFF1B\u539F\u72B6\u6001 ${turn.status}\uFF09` }
|
|
171470
|
+
{ status: "cancelled", cancelledBy: "user", completedAt, lastError: `\u7528\u6237\u505C\u6B62\uFF08\u672C\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CC\u6CA1\u6709\u8FD9\u4E00\u8F6E\uFF0C\u6309\u53F0\u8D26\u6536\uFF1B\u539F\u72B6\u6001 ${turn.status}\uFF09` }
|
|
171397
171471
|
);
|
|
171398
171472
|
if (ok3) {
|
|
171399
171473
|
log3(`[chat-stop] \u4F1A\u8BDD ${deps.sessionId} \u8F6E ${turn.id} \u6309\u53F0\u8D26\u505C\u6B62\uFF08${turn.status} \u2192 cancelled\uFF09`);
|
|
171474
|
+
deps.onCancelled?.(turn);
|
|
171400
171475
|
await recordUserStopNotice(deps, turn, completedAt);
|
|
171401
171476
|
return { stopped: true, ledger: true };
|
|
171402
171477
|
}
|
|
@@ -171417,7 +171492,8 @@ async function recordUserStopNotice(deps, turn, completedAt) {
|
|
|
171417
171492
|
cause: "user-stop",
|
|
171418
171493
|
reason: "user-stop",
|
|
171419
171494
|
now: () => completedAt,
|
|
171420
|
-
...deps.log ? { log: deps.log } : {}
|
|
171495
|
+
...deps.log ? { log: deps.log } : {},
|
|
171496
|
+
rethrow: true
|
|
171421
171497
|
});
|
|
171422
171498
|
}
|
|
171423
171499
|
var MAX_CAS_ATTEMPTS;
|
|
@@ -214800,17 +214876,10 @@ async function startOasisServer(opts) {
|
|
|
214800
214876
|
if (!active || active.status !== "running") return;
|
|
214801
214877
|
liveChat.reopenForRecovery(sid, {
|
|
214802
214878
|
runtimeSessionId: cs.runtimeSessionId ?? active.dispatchId ?? "",
|
|
214803
|
-
|
|
214804
|
-
|
|
214805
|
-
onStop
|
|
214806
|
-
|
|
214807
|
-
turns,
|
|
214808
|
-
sessionId: sid,
|
|
214809
|
-
turn: active,
|
|
214810
|
-
items: opts.resolveChatItems ? await opts.resolveChatItems(currentCompanyId).catch(() => void 0) : opts.chatItems,
|
|
214811
|
-
findAssistantMessageId: (runId) => findAssistantMessageIdByRun(chatStoreNowOrNull, sid, runId)
|
|
214812
|
-
}))().catch(() => void 0);
|
|
214813
|
-
}
|
|
214879
|
+
ledgerTurnId: active.id,
|
|
214880
|
+
...active.assistantRunId ? { runId: active.assistantRunId } : {}
|
|
214881
|
+
// 不挂 onStop:占位轮被 `/stop` 停时,由 `/stop` 先**等**台账写成(条件迁移 + 用户停止结局项,
|
|
214882
|
+
// Bug 0228)再收它;写不成就留着它、回「没停成」。在 kill 里异步发起会先回成功、失败被吞掉。
|
|
214814
214883
|
});
|
|
214815
214884
|
};
|
|
214816
214885
|
const wantsV3 = url.searchParams.get("protocol") === "v3";
|
|
@@ -214968,37 +215037,92 @@ async function startOasisServer(opts) {
|
|
|
214968
215037
|
return;
|
|
214969
215038
|
}
|
|
214970
215039
|
let expectedRunId;
|
|
215040
|
+
let expectedTurnId;
|
|
214971
215041
|
try {
|
|
214972
215042
|
const b2 = JSON.parse(rawBody);
|
|
214973
215043
|
if (typeof b2.expectedRunId === "string" && b2.expectedRunId) expectedRunId = b2.expectedRunId;
|
|
215044
|
+
if (typeof b2.expectedTurnId === "string" && b2.expectedTurnId) expectedTurnId = b2.expectedTurnId;
|
|
214974
215045
|
} catch {
|
|
214975
215046
|
}
|
|
214976
|
-
|
|
214977
|
-
|
|
214978
|
-
|
|
214979
|
-
|
|
214980
|
-
|
|
214981
|
-
|
|
214982
|
-
|
|
214983
|
-
|
|
214984
|
-
|
|
215047
|
+
const ledgerUnavailable = (err) => {
|
|
215048
|
+
console.warn(`[chat-stop] \u4F1A\u8BDD ${sid} \u6309\u53F0\u8D26\u505C\u6B62\u5931\u8D25: ${String(err)}`);
|
|
215049
|
+
return { stopped: false, reason: "ledger-unavailable" };
|
|
215050
|
+
};
|
|
215051
|
+
const stopOnLedger = async (turns, target, onCancelled) => stopLedgerTurn({
|
|
215052
|
+
turns,
|
|
215053
|
+
sessionId: sid,
|
|
215054
|
+
expectedRunId,
|
|
215055
|
+
...target,
|
|
215056
|
+
...onCancelled ? { onCancelled } : {},
|
|
215057
|
+
items: opts.resolveChatItems ? await opts.resolveChatItems(currentCompanyId).catch(() => void 0) : opts.chatItems,
|
|
215058
|
+
findAssistantMessageId: (runId) => findAssistantMessageIdByRun(chatStoreNowOrNull, sid, runId),
|
|
215059
|
+
log: (m2) => console.log(m2)
|
|
215060
|
+
}).catch(ledgerUnavailable);
|
|
215061
|
+
const resolveTurns = async () => opts.resolveChatTurns ? await opts.resolveChatTurns(currentCompanyId) : opts.chatTurns;
|
|
215062
|
+
const outcome = await (async () => {
|
|
215063
|
+
const placeholder = liveChat.recoveringTurn(sid);
|
|
215064
|
+
if (placeholder !== void 0 && (!expectedTurnId || placeholder.ledgerTurnId === expectedTurnId)) {
|
|
215065
|
+
let turns2;
|
|
215066
|
+
try {
|
|
215067
|
+
turns2 = await resolveTurns();
|
|
215068
|
+
} catch (err) {
|
|
215069
|
+
return ledgerUnavailable(err);
|
|
214985
215070
|
}
|
|
214986
|
-
if (
|
|
214987
|
-
|
|
214988
|
-
|
|
214989
|
-
|
|
214990
|
-
expectedRunId,
|
|
214991
|
-
...openedByThisProcess ? {} : { turn: active },
|
|
214992
|
-
items: opts.resolveChatItems ? await opts.resolveChatItems(currentCompanyId).catch(() => void 0) : opts.chatItems,
|
|
214993
|
-
findAssistantMessageId: (runId) => findAssistantMessageIdByRun(chatStoreNowOrNull, sid, runId),
|
|
214994
|
-
log: (m2) => console.log(m2)
|
|
214995
|
-
}).catch((err) => {
|
|
214996
|
-
console.warn(`[chat-stop] \u4F1A\u8BDD ${sid} \u6309\u53F0\u8D26\u505C\u6B62\u5931\u8D25: ${String(err)}`);
|
|
214997
|
-
return { stopped: false, reason: "turn-changed" };
|
|
215071
|
+
if (turns2) {
|
|
215072
|
+
let cancelledRunId;
|
|
215073
|
+
const onLedger = await stopOnLedger(turns2, { turnId: placeholder.ledgerTurnId }, (t) => {
|
|
215074
|
+
cancelledRunId = t.assistantRunId ?? void 0;
|
|
214998
215075
|
});
|
|
215076
|
+
if (onLedger.stopped || onLedger.reason === "no-live-turn") {
|
|
215077
|
+
liveChat.stopSameTurn(sid, { epoch: placeholder.epoch, ...cancelledRunId ? { runId: cancelledRunId } : {} });
|
|
215078
|
+
}
|
|
215079
|
+
return onLedger;
|
|
214999
215080
|
}
|
|
215000
215081
|
}
|
|
215001
|
-
|
|
215082
|
+
const noLiveTurn = { stopped: false, reason: "no-live-turn" };
|
|
215083
|
+
const inRegistry = !expectedTurnId || liveChat.isTurn(sid, expectedTurnId) ? liveChat.stop(sid, expectedRunId) : noLiveTurn;
|
|
215084
|
+
if (inRegistry.stopped || inRegistry.reason !== "no-live-turn") return inRegistry;
|
|
215085
|
+
let turns;
|
|
215086
|
+
try {
|
|
215087
|
+
turns = await resolveTurns();
|
|
215088
|
+
} catch (err) {
|
|
215089
|
+
return ledgerUnavailable(err);
|
|
215090
|
+
}
|
|
215091
|
+
if (!turns) return inRegistry;
|
|
215092
|
+
const registeredBefore = expectedTurnId ? liveChat.runningTurn(sid) : void 0;
|
|
215093
|
+
let active;
|
|
215094
|
+
try {
|
|
215095
|
+
active = expectedTurnId ? await turns.getTurn(expectedTurnId) : await turns.activeTurn(sid);
|
|
215096
|
+
} catch (err) {
|
|
215097
|
+
return ledgerUnavailable(err);
|
|
215098
|
+
}
|
|
215099
|
+
if (active && active.chatSessionId !== sid) active = null;
|
|
215100
|
+
if (!active) return inRegistry;
|
|
215101
|
+
if (active.status !== "reserved" && active.status !== "running") return stopOnLedger(turns, { turn: active });
|
|
215102
|
+
const isSameTurn = (reg, row) => reg.turnId === row.id || !!row.assistantRunId && reg.runId === row.assistantRunId || reg.turnId === void 0 && !row.assistantRunId;
|
|
215103
|
+
if (registeredBefore && isSameTurn(registeredBefore, active)) {
|
|
215104
|
+
if (expectedRunId && registeredBefore.runId && registeredBefore.runId !== expectedRunId) return { stopped: false, reason: "turn-changed" };
|
|
215105
|
+
if (liveChat.stopSameTurn(sid, { epoch: registeredBefore.epoch })) return { stopped: true };
|
|
215106
|
+
}
|
|
215107
|
+
const openedByThisProcess = Date.parse(active.reservedAt) >= serveBootedAtMs;
|
|
215108
|
+
if (openedByThisProcess) {
|
|
215109
|
+
await waitForAdmittedTurnStart(sid, { liveChat, ledgerTurnRunning: async () => true, timeoutMs: STOP_TURN_START_WAIT_MS });
|
|
215110
|
+
const registered = liveChat.runningTurn(sid);
|
|
215111
|
+
let again;
|
|
215112
|
+
try {
|
|
215113
|
+
again = await turns.getTurn(active.id);
|
|
215114
|
+
} catch (err) {
|
|
215115
|
+
return ledgerUnavailable(err);
|
|
215116
|
+
}
|
|
215117
|
+
if (!again || again.status !== "reserved" && again.status !== "running") return { stopped: false, reason: "no-live-turn" };
|
|
215118
|
+
if (registered && isSameTurn(registered, again)) {
|
|
215119
|
+
if (expectedRunId && registered.runId && registered.runId !== expectedRunId) return { stopped: false, reason: "turn-changed" };
|
|
215120
|
+
if (liveChat.stopSameTurn(sid, { epoch: registered.epoch })) return { stopped: true };
|
|
215121
|
+
}
|
|
215122
|
+
return stopOnLedger(turns, { turn: again });
|
|
215123
|
+
}
|
|
215124
|
+
return stopOnLedger(turns, { turn: active });
|
|
215125
|
+
})();
|
|
215002
215126
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify(outcome));
|
|
215003
215127
|
return;
|
|
215004
215128
|
}
|
|
@@ -224212,7 +224336,8 @@ function applyTurnPatch(t, patch) {
|
|
|
224212
224336
|
...patch.assistantRunId !== void 0 ? { assistantRunId: patch.assistantRunId } : {},
|
|
224213
224337
|
...patch.startedAt !== void 0 ? { startedAt: patch.startedAt } : {},
|
|
224214
224338
|
...patch.completedAt !== void 0 ? { completedAt: patch.completedAt } : {},
|
|
224215
|
-
...patch.lastError !== void 0 ? { lastError: patch.lastError } : {}
|
|
224339
|
+
...patch.lastError !== void 0 ? { lastError: patch.lastError } : {},
|
|
224340
|
+
...patch.cancelledBy !== void 0 ? { cancelledBy: patch.cancelledBy } : {}
|
|
224216
224341
|
};
|
|
224217
224342
|
}
|
|
224218
224343
|
var import_node_crypto49, fs23, path22, NdjsonOplogStore, DirBlobStore, MUTATORS, FileTypeRegistryStore, FileRoleRegistryStore, FileRegistryStore, FileAssistantBindStore, FileHumanPrefsStore, FileProjectStateStore, FileArtifactStateStore, FileTraceStore, MemoryChatSessionStore, FileChatSessionStore, MemoryChatTurnStore, FileChatTurnStore, MemoryReadMarkerStore, FileReadMarkerStore;
|
|
@@ -229617,7 +229742,8 @@ async function sweepDanglingChatTurns(deps) {
|
|
|
229617
229742
|
completedAt = run?.endedAt ?? new Date(deps.now).toISOString();
|
|
229618
229743
|
reason = run ? `run \u7EC8\u6001 ${run.status}` : "run \u7F3A\u5931";
|
|
229619
229744
|
exitReason = run?.exitReason ?? null;
|
|
229620
|
-
|
|
229745
|
+
const ledgerTurn = await deps.getTurnForRun?.(row.sessionId, row.runId).catch(() => null);
|
|
229746
|
+
cancelledBy = (ledgerTurn?.status === "cancelled" ? ledgerTurn.cancelledBy ?? void 0 : void 0) ?? serveRestartCauseOfRun(run);
|
|
229621
229747
|
} else {
|
|
229622
229748
|
if (deps.now - Date.parse(row.createdAt) < (deps.noRunGraceMs ?? 10 * 6e4)) continue;
|
|
229623
229749
|
status = "error";
|
|
@@ -229886,7 +230012,8 @@ async function sweepDanglingChatTurnsAcrossCompanies(deps) {
|
|
|
229886
230012
|
...log3 ? { log: (m2) => log3(companyId ? `${m2}\uFF3B${companyId}\uFF3D` : m2) } : {},
|
|
229887
230013
|
...sessionOutputsScan ? { outputsPartFor: (sid) => outputsPartProvider(sessionOutputsScan, sid, companyId) } : {},
|
|
229888
230014
|
// Bug #0185:结局项要写进**这一家**的 `chat_items`(公司分 schema,写错家等于没写)。
|
|
229889
|
-
...stores.items ? { itemsFor: () => stores.items } : {}
|
|
230015
|
+
...stores.items ? { itemsFor: () => stores.items } : {},
|
|
230016
|
+
...stores.getTurnForRun ? { getTurnForRun: stores.getTurnForRun } : {}
|
|
229890
230017
|
});
|
|
229891
230018
|
closed.push(...ids2);
|
|
229892
230019
|
} catch (err) {
|
|
@@ -229931,6 +230058,19 @@ async function reconcileSettledChatTurn(deps) {
|
|
|
229931
230058
|
succeeded ? "completed" : "failed",
|
|
229932
230059
|
deps.log ?? (() => void 0)
|
|
229933
230060
|
);
|
|
230061
|
+
if (turn.status === "cancelled" && turn.cancelledBy === "user" && deps.items) {
|
|
230062
|
+
await recordChatTurnInterruption({
|
|
230063
|
+
items: deps.items,
|
|
230064
|
+
sessionId: plan.chatSessionId,
|
|
230065
|
+
turnId,
|
|
230066
|
+
runId: plan.runId,
|
|
230067
|
+
messageId: plan.assistantMsgId,
|
|
230068
|
+
cause: "user-stop",
|
|
230069
|
+
reason: "user-stop",
|
|
230070
|
+
now: () => completedAt,
|
|
230071
|
+
...deps.log ? { log: deps.log } : {}
|
|
230072
|
+
});
|
|
230073
|
+
}
|
|
229934
230074
|
const withOutputs = await appendOutputsPart(plan.seedParts, deps.outputsPart);
|
|
229935
230075
|
await deps.chatStore.updateMessage(plan.assistantMsgId, {
|
|
229936
230076
|
status: succeeded ? "done" : "error",
|
|
@@ -240428,8 +240568,8 @@ var init_activity_trace = __esm({
|
|
|
240428
240568
|
function commandCardLine(command2) {
|
|
240429
240569
|
return command2.displayLabel?.trim() || stripInternalIds(command2.effectLabel ?? "");
|
|
240430
240570
|
}
|
|
240431
|
-
function changeConfirmSummary(r) {
|
|
240432
|
-
if (r.continuation) return `\u672C\u6279\u8F6E\u6570\u5DF2\u7528\u5B8C\uFF0C\u7B49\u4F60\u51B3\u5B9A\u662F\u5426\u7EE7\u7EED\uFF1A${r.plan.reason}`;
|
|
240571
|
+
function changeConfirmSummary(r, stepTitle) {
|
|
240572
|
+
if (r.continuation) return `\u672C\u6279\u8F6E\u6570\u5DF2\u7528\u5B8C\uFF0C\u7B49\u4F60\u51B3\u5B9A\u662F\u5426\u7EE7\u7EED\uFF1A${requoteStepTitle(r.plan.reason, stepTitle)}`;
|
|
240433
240573
|
const why = r.plan.reason.slice(0, 100);
|
|
240434
240574
|
if (r.kind === "command" && r.command) {
|
|
240435
240575
|
return `\u7BA1\u7406\u8005\u8BF7\u6C42\u6267\u884C\u4E00\u4E2A\u9AD8\u5371\u64CD\u4F5C\uFF0C\u7B49\u4F60\u6388\u6743\uFF1A${commandCardLine(r.command)}`;
|
|
@@ -240475,7 +240615,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
240475
240615
|
...extra?.avatar ? { avatar: extra.avatar } : {}
|
|
240476
240616
|
};
|
|
240477
240617
|
};
|
|
240478
|
-
const
|
|
240618
|
+
const atName2 = (id) => {
|
|
240479
240619
|
const name = resolveActor?.(id)?.name;
|
|
240480
240620
|
return name ? plainActor(name) : "";
|
|
240481
240621
|
};
|
|
@@ -240604,7 +240744,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
240604
240744
|
workspace: r.workspace,
|
|
240605
240745
|
since: r.at,
|
|
240606
240746
|
actionRequired: true,
|
|
240607
|
-
summary: changeConfirmSummary(r),
|
|
240747
|
+
summary: changeConfirmSummary(r, anchorArt?.title),
|
|
240608
240748
|
draftId: r.draftId,
|
|
240609
240749
|
// ★ 落点(2026-09-11):带上起草它的那段对话,让前端把这一行跳回**卡真正渲染着的地方**。
|
|
240610
240750
|
// 此前这一行恒跳「任务详情 ?tab=activity」,而全仓库渲染待审卡的只有 chat 页与任务页的协调者
|
|
@@ -240615,7 +240755,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
240615
240755
|
// 续跑申请的入口在任务动态那张续跑申请卡上(卡 id = 申请 id,见 activity.ts `continuationCards`)。
|
|
240616
240756
|
...r.continuation ? { activityCardId: r.continuation.requestId } : {},
|
|
240617
240757
|
...anchorArt ? { title: nodeLabel(anchorArt) } : {},
|
|
240618
|
-
detail: `${
|
|
240758
|
+
detail: `${atName2(r.proposedBy) || "\u7BA1\u7406\u8005"}\uFF1A${r.command ? commandCardLine(r.command) : requoteStepTitle(firstSentence3(r.plan.reason), anchorArt?.title)}`,
|
|
240619
240759
|
...r.kind !== "command" && opCount > 0 ? { impact: `\u6D89\u53CA ${opCount} \u5904\u6539\u52A8${r.nonMonotonicOps.length > 0 ? " \xB7 \u542B\u9500\u6BC1\u6027" : ""}` } : {},
|
|
240620
240760
|
actor: actorRef3(r.proposedBy),
|
|
240621
240761
|
...overdueField(r.at)
|
|
@@ -240656,7 +240796,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
240656
240796
|
actionRequired: true,
|
|
240657
240797
|
summary: `\u6709\u4EBA\u5728\u300C${label2}\u300D\u7684\u4FE1\u91CC @ \u4E86\u4F60\uFF0C\u7B49\u4F60\u56DE\u8BDD\uFF1A${(lastPost?.body ?? an.body).slice(0, 100)}`,
|
|
240658
240798
|
title: label2,
|
|
240659
|
-
detail: `${(lastPost ?
|
|
240799
|
+
detail: `${(lastPost ? atName2(lastPost.author) : "") || "\u6709\u4EBA"} @ \u4E86\u4F60\uFF1A${firstSentence3(lastPost?.body ?? an.body)}`,
|
|
240660
240800
|
...lastPost ? { actor: actorRef3(lastPost.author) } : {},
|
|
240661
240801
|
...overdueField(an.createdAt)
|
|
240662
240802
|
});
|
|
@@ -240681,7 +240821,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
240681
240821
|
actionRequired: false,
|
|
240682
240822
|
summary: `\u4F60\u7684\u4FE1\u6709\u65B0\u52A8\u9759\uFF08${phrase}\uFF09\u300C${nodeLabel(a)}\u300D\uFF1A${lastNote.slice(0, 100)}\u2014\u2014\u4E0D\u8BA4\u53EF\u53EF\u5728\u4FE1\u4E2D\u56DE\u5E16`,
|
|
240683
240823
|
title: nodeLabel(a),
|
|
240684
|
-
detail: `${
|
|
240824
|
+
detail: `${atName2(activity.by) || "\u5BF9\u65B9"} \u56DE\u5E94\u4E86\u4F60\u7684\u4FE1\uFF1A${firstSentence3(lastNote)}`,
|
|
240685
240825
|
actor: actorRef3(activity.by)
|
|
240686
240826
|
// 通知型不判 overdue(诊断明说),不设 overdue 字段。
|
|
240687
240827
|
});
|
|
@@ -240701,7 +240841,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
240701
240841
|
actionRequired: true,
|
|
240702
240842
|
summary: `\u5F85\u4F60\u9A8C\u6536\uFF1A${label2}\uFF08${pendingHead.id}\uFF09\u2014\u2014\u8BE5\u7248\u7B54\u590D\u4E86\u4F60\u7684\u4FE1`,
|
|
240703
240843
|
title: label2,
|
|
240704
|
-
detail: `${
|
|
240844
|
+
detail: `${atName2(pendingHead.author) || "agent"} \u4EA4\u4E86\u65B0\u7248\u7B54\u590D\u4F60\u7684\u4FE1\uFF1A${firstSentence3(pendingHead.reason)}`,
|
|
240705
240845
|
actor: actorRef3(pendingHead.author),
|
|
240706
240846
|
...overdueField(pendingHead.createdAt)
|
|
240707
240847
|
});
|
|
@@ -240728,7 +240868,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
240728
240868
|
actionRequired: true,
|
|
240729
240869
|
summary: `\u5F85\u4F60\u5BA1\u6279\uFF1A${label2}`,
|
|
240730
240870
|
title: label2,
|
|
240731
|
-
...gp ? { detail: `${
|
|
240871
|
+
...gp ? { detail: `${atName2(gp.headAuthor) || "\u4F5C\u8005"} \u4EA4\u4E86\u65B0\u7248\uFF1A${firstSentence3(headReason)}`, actor: actorRef3(gp.headAuthor) } : {},
|
|
240732
240872
|
...impactParts.length > 0 ? { impact: impactParts.join(" \xB7 ") } : {},
|
|
240733
240873
|
...overdueField(gate.at)
|
|
240734
240874
|
});
|
|
@@ -240751,7 +240891,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
240751
240891
|
actionRequired: true,
|
|
240752
240892
|
summary: `\u4EA7\u51FA\u88AB\u6253\u56DE\uFF0C\u9700\u8FD4\u5DE5\uFF1A${label2}`,
|
|
240753
240893
|
title: label2,
|
|
240754
|
-
...rejectVote ? { detail: `${
|
|
240894
|
+
...rejectVote ? { detail: `${atName2(rejectVote.author) || "\u8BC4\u5BA1"} \u6253\u56DE\uFF1A${firstSentence3(rejectVote.note ?? "\u89C1\u8BC4\u5BA1\u610F\u89C1")}`, actor: actorRef3(rejectVote.author) } : {},
|
|
240755
240895
|
...reworkDs > 0 ? { impact: `\u6321\u7740\u4E0B\u6E38 ${reworkDs} \u4E2A\u8282\u70B9` } : {},
|
|
240756
240896
|
...overdueField(latest.createdAt)
|
|
240757
240897
|
});
|
|
@@ -258700,6 +258840,16 @@ var init_daemon_adapter = __esm({
|
|
|
258700
258840
|
timer.unref?.();
|
|
258701
258841
|
this.sessionReapTimers.set(dispatchId, timer);
|
|
258702
258842
|
}
|
|
258843
|
+
/**
|
|
258844
|
+
* 这次派发的会话连接已经断了、正在等失联宽限(`onSessionDown` 起的倒计时还在走)。
|
|
258845
|
+
*
|
|
258846
|
+
* 给静默保险丝用(Bug 0279):机器掉线时「最后一次输出」总是早于「连接断开」,按输出算的静默保险丝
|
|
258847
|
+
* 几乎总是先到点,把这一轮当成「长时间没有响应」停掉(`cancelled`)——既不换候选、也不标故障。
|
|
258848
|
+
* 连接已断的那一轮交给失联收割判(`server-unreachable`),保险丝让开。
|
|
258849
|
+
*/
|
|
258850
|
+
isAwaitingSessionReap(dispatchId) {
|
|
258851
|
+
return this.sessionReapTimers.has(dispatchId);
|
|
258852
|
+
}
|
|
258703
258853
|
/** 节点失联超宽限期:只报警,不把「暂时够不到」升级成「runtime 已死」。 */
|
|
258704
258854
|
markNodeUnknown(daemonId) {
|
|
258705
258855
|
const unknown2 = [];
|
|
@@ -267319,6 +267469,7 @@ async function ensureChatTurnsTable(pool, schema = "public") {
|
|
|
267319
267469
|
completed_at timestamptz,
|
|
267320
267470
|
last_error text
|
|
267321
267471
|
)`);
|
|
267472
|
+
await pool.query(`ALTER TABLE "${s2}".chat_session_turns ADD COLUMN IF NOT EXISTS cancelled_by text`);
|
|
267322
267473
|
await pool.query(`CREATE UNIQUE INDEX IF NOT EXISTS chat_session_turns_source_uq ON "${s2}".chat_session_turns (source, source_run_id)`);
|
|
267323
267474
|
await pool.query(`CREATE UNIQUE INDEX IF NOT EXISTS chat_session_turns_msgkey_uq ON "${s2}".chat_session_turns (message_key)`);
|
|
267324
267475
|
await pool.query(`CREATE UNIQUE INDEX IF NOT EXISTS chat_session_turns_active_uq ON "${s2}".chat_session_turns (chat_session_id) WHERE status IN ('reserved','running')`);
|
|
@@ -267350,6 +267501,10 @@ function patchSets(patch) {
|
|
|
267350
267501
|
args.push(patch.lastError);
|
|
267351
267502
|
sets.push(`last_error = $${args.length}`);
|
|
267352
267503
|
}
|
|
267504
|
+
if (patch.cancelledBy !== void 0) {
|
|
267505
|
+
args.push(patch.cancelledBy);
|
|
267506
|
+
sets.push(`cancelled_by = $${args.length}`);
|
|
267507
|
+
}
|
|
267353
267508
|
return { sets, args };
|
|
267354
267509
|
}
|
|
267355
267510
|
var ident11, PostgresChatTurnStore, isUniqueViolation2, iso5, rowToTurn;
|
|
@@ -267466,7 +267621,8 @@ var init_postgres_chat_turns = __esm({
|
|
|
267466
267621
|
reservedAt: iso5(row.reserved_at),
|
|
267467
267622
|
startedAt: iso5(row.started_at),
|
|
267468
267623
|
completedAt: iso5(row.completed_at),
|
|
267469
|
-
lastError: row.last_error ?? null
|
|
267624
|
+
lastError: row.last_error ?? null,
|
|
267625
|
+
...row.cancelled_by ? { cancelledBy: row.cancelled_by } : {}
|
|
267470
267626
|
});
|
|
267471
267627
|
}
|
|
267472
267628
|
});
|
|
@@ -269726,7 +269882,7 @@ var init_postgres_chat_sessions = __esm({
|
|
|
269726
269882
|
/** 按本 schema 中的会话 + run 精确找轮,不能用 activeTurn:已取消的轮已不占 active slot。 */
|
|
269727
269883
|
async getTurnForRun(sessionId, runId) {
|
|
269728
269884
|
const r = await this.pool.query(
|
|
269729
|
-
`SELECT
|
|
269885
|
+
`SELECT * FROM ${this.s}.chat_session_turns
|
|
269730
269886
|
WHERE chat_session_id = $1 AND assistant_run_id = $2 ORDER BY reserved_at DESC LIMIT 1`,
|
|
269731
269887
|
[sessionId, runId]
|
|
269732
269888
|
);
|
|
@@ -269735,7 +269891,8 @@ var init_postgres_chat_sessions = __esm({
|
|
|
269735
269891
|
id: row.id,
|
|
269736
269892
|
status: row.status,
|
|
269737
269893
|
completedAt: row.completed_at == null ? null : new Date(row.completed_at).toISOString(),
|
|
269738
|
-
lastError: row.last_error ?? null
|
|
269894
|
+
lastError: row.last_error ?? null,
|
|
269895
|
+
...row.cancelled_by ? { cancelledBy: row.cancelled_by } : {}
|
|
269739
269896
|
} : null;
|
|
269740
269897
|
}
|
|
269741
269898
|
async getSession(id) {
|
|
@@ -289749,6 +289906,7 @@ async function startServe(opts) {
|
|
|
289749
289906
|
const exits = relay();
|
|
289750
289907
|
let sawOutput = false;
|
|
289751
289908
|
let retried = null;
|
|
289909
|
+
let retriedFinish = null;
|
|
289752
289910
|
handle.onOutput?.((c) => {
|
|
289753
289911
|
sawOutput = true;
|
|
289754
289912
|
out.push(c);
|
|
@@ -289777,8 +289935,11 @@ async function startServe(opts) {
|
|
|
289777
289935
|
}
|
|
289778
289936
|
if (sawOutput && info.reason !== "server-unreachable") return null;
|
|
289779
289937
|
if (!automationDispatchChat || !canRetryAllocation(allocator.inspect(unitOfWork)?.failures ?? 0)) return null;
|
|
289780
|
-
const
|
|
289781
|
-
if (!
|
|
289938
|
+
const isChild = await delegationStoreFor(companyId).then((store) => store.getByChildSession(plan.chatSessionId)).then(Boolean).catch(() => false);
|
|
289939
|
+
if (!isChild) {
|
|
289940
|
+
console.log(`[runtime-alloc] \u63A5\u56DE\u7684\u8F6E ${plan.chatSessionId} \u4E0D\u662F\u59D4\u6D3E\u5B50\u4F1A\u8BDD\uFF0C\u53EA\u6807\u6545\u969C\u3001\u4E0D\u6362\u5019\u9009`);
|
|
289941
|
+
return null;
|
|
289942
|
+
}
|
|
289782
289943
|
const events = await traceStore2.listEvents(plan.runId, {}).catch(() => []);
|
|
289783
289944
|
const input = events.find((e) => e.eventType === "input.message");
|
|
289784
289945
|
const payload2 = input?.payload ?? {};
|
|
@@ -289812,7 +289973,16 @@ async function startServe(opts) {
|
|
|
289812
289973
|
retried = next;
|
|
289813
289974
|
next.onOutput((c) => out.push(c));
|
|
289814
289975
|
next.onLiveEvent?.((e) => live.push(e));
|
|
289815
|
-
next.onNormalizedProviderEvent
|
|
289976
|
+
if (typeof next.onNormalizedProviderEvent === "function") {
|
|
289977
|
+
next.onNormalizedProviderEvent((e) => norm.push(e));
|
|
289978
|
+
} else {
|
|
289979
|
+
const source = attachStreamNormalizer(next, {
|
|
289980
|
+
providerName: "runtime",
|
|
289981
|
+
fallbackTurnId: `oasis-turn:${plan.runId}:retry`
|
|
289982
|
+
});
|
|
289983
|
+
source.onNormalizedProviderEvent((e) => norm.push(e));
|
|
289984
|
+
retriedFinish = (signal) => source.finishTurn(signal);
|
|
289985
|
+
}
|
|
289816
289986
|
let failure2;
|
|
289817
289987
|
try {
|
|
289818
289988
|
await next.done;
|
|
@@ -289838,7 +290008,7 @@ async function startServe(opts) {
|
|
|
289838
290008
|
}
|
|
289839
290009
|
if (prop === "kill") return () => retried?.kill ? retried.kill() : target.kill();
|
|
289840
290010
|
if (prop === "finishNormalizedTurn") {
|
|
289841
|
-
return (signal) => retried?.finishNormalizedTurn ? retried.finishNormalizedTurn(signal) : target.finishNormalizedTurn?.(signal);
|
|
290011
|
+
return (signal) => retriedFinish ? retriedFinish(signal) : retried?.finishNormalizedTurn ? retried.finishNormalizedTurn(signal) : target.finishNormalizedTurn?.(signal);
|
|
289842
290012
|
}
|
|
289843
290013
|
const value2 = Reflect.get(target, prop, receiver);
|
|
289844
290014
|
return typeof value2 === "function" ? value2.bind(target) : value2;
|
|
@@ -292039,7 +292209,7 @@ ${nodeFault}` : "");
|
|
|
292039
292209
|
for (const session of sessions2) dispatcherByJob.set(session.jobKey, d);
|
|
292040
292210
|
return sessions2;
|
|
292041
292211
|
});
|
|
292042
|
-
const chatSessions = [...chatLiveSessions.entries()].map(([jobKey, c]) => ({ jobKey, artifactId: c.artifactId, sessionId: c.sessionId }));
|
|
292212
|
+
const chatSessions = [...chatLiveSessions.entries()].filter(([, c]) => !(c.dispatchId && chatRemoteAdapter?.isAwaitingSessionReap(c.dispatchId))).map(([jobKey, c]) => ({ jobKey, artifactId: c.artifactId, sessionId: c.sessionId }));
|
|
292043
292213
|
const sessions = [...dispatcherSessions, ...chatSessions];
|
|
292044
292214
|
if (sessions.length === 0) return;
|
|
292045
292215
|
probe.retain(sessions.map((s2) => s2.sessionId));
|
|
@@ -297653,7 +297823,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
297653
297823
|
}
|
|
297654
297824
|
}
|
|
297655
297825
|
}
|
|
297656
|
-
var CLI_VERSION = "2.2.
|
|
297826
|
+
var CLI_VERSION = "2.2.101" ? "2.2.101" : "dev";
|
|
297657
297827
|
function apiHeaders(token2, company) {
|
|
297658
297828
|
const headers = {
|
|
297659
297829
|
authorization: `Bearer ${token2}`,
|
|
@@ -301494,6 +301664,71 @@ function runtimeAssetSourceRoots(input) {
|
|
|
301494
301664
|
return [...new Set(roots.map((root) => path43.resolve(root)))];
|
|
301495
301665
|
}
|
|
301496
301666
|
|
|
301667
|
+
// src/enroll-exchange.ts
|
|
301668
|
+
function enrollTokenToUse(plan, supplied) {
|
|
301669
|
+
const token2 = supplied?.trim();
|
|
301670
|
+
if (!token2) return void 0;
|
|
301671
|
+
if (plan.mode === "new") return token2;
|
|
301672
|
+
return plan.names.length === 1 ? token2 : void 0;
|
|
301673
|
+
}
|
|
301674
|
+
var EnrollExchangeError = class extends Error {
|
|
301675
|
+
constructor(message, status) {
|
|
301676
|
+
super(message);
|
|
301677
|
+
this.status = status;
|
|
301678
|
+
this.name = "EnrollExchangeError";
|
|
301679
|
+
}
|
|
301680
|
+
};
|
|
301681
|
+
var UNCHANGED = "\u672C\u673A\u6CA1\u6709\u505A\u4EFB\u4F55\u6539\u52A8\uFF08\u5B9E\u4F8B\u914D\u7F6E\u672A\u5199\u5165\uFF0C\u5B88\u62A4\u8FDB\u7A0B\u4E5F\u6CA1\u6709\u91CD\u542F\uFF09\u3002";
|
|
301682
|
+
function describeExchangeFailure(status, body2) {
|
|
301683
|
+
const serverMessage = typeof body2?.message === "string" && body2.message.trim() ? body2.message.trim() : void 0;
|
|
301684
|
+
const serverError = typeof body2?.error === "string" && body2.error.trim() ? body2.error.trim() : void 0;
|
|
301685
|
+
let why;
|
|
301686
|
+
if (status === 401) {
|
|
301687
|
+
why = "\u63A5\u5165\u4EE4\u724C\u65E0\u6548\u3001\u5DF2\u8FC7\u671F\u6216\u5DF2\u7ECF\u88AB\u7528\u8FC7\u3002\u8BF7\u56DE\u5230\u9875\u9762\u91CD\u65B0\u6253\u5F00\u63A5\u5165\u5BF9\u8BDD\u6846\uFF0C\u590D\u5236\u65B0\u751F\u6210\u7684\u547D\u4EE4\u518D\u8FD0\u884C\u4E00\u6B21\u3002";
|
|
301688
|
+
} else if (status === 409 && serverError === "NODE_UNOWNED") {
|
|
301689
|
+
why = serverMessage ?? "\u8FD9\u53F0\u673A\u5668\u5728\u7CFB\u7EDF\u91CC\u7684\u65E7\u8BB0\u5F55\u6CA1\u6709\u5F52\u5C5E\u516C\u53F8\uFF0C\u4E0D\u80FD\u88AB\u63A5\u5165\uFF1B\u8BF7\u7A0D\u540E\u91CD\u65B0\u8FD0\u884C\u63A5\u5165\u547D\u4EE4\u3002";
|
|
301690
|
+
} else if (status === 409) {
|
|
301691
|
+
why = "\u8FD9\u53F0\u673A\u5668\u5728\u7CFB\u7EDF\u91CC\u5DF2\u767B\u8BB0\u5728\u53E6\u4E00\u4E2A\u516C\u53F8\u540D\u4E0B\uFF0C\u4E0D\u80FD\u7528\u5F53\u524D\u516C\u53F8\u7684\u63A5\u5165\u4EE4\u724C\u63A5\u5165\u3002\u8BF7\u7528\u8FD9\u53F0\u673A\u5668\u6240\u5C5E\u516C\u53F8\u7684\u8D26\u53F7\u751F\u6210\u63A5\u5165\u547D\u4EE4\uFF0C\u6216\u8BF7\u8BE5\u516C\u53F8\u7684\u7BA1\u7406\u5458\u5148\u5220\u9664\u8FD9\u53F0\u673A\u5668\u540E\u518D\u8FD0\u884C\u3002";
|
|
301692
|
+
} else {
|
|
301693
|
+
const detail = serverMessage ?? serverError;
|
|
301694
|
+
why = `\u670D\u52A1\u7AEF\u62D2\u7EDD\u4E86\u8FD9\u6B21\u63A5\u5165${detail ? `\uFF1A${detail}` : ""}\u3002\u8BF7\u7A0D\u540E\u91CD\u8BD5\uFF1B\u4ECD\u7136\u5931\u8D25\u8BF7\u628A\u8FD9\u6BB5\u8F93\u51FA\u53D1\u7ED9\u7BA1\u7406\u5458\u3002`;
|
|
301695
|
+
}
|
|
301696
|
+
return `\u2717 \u63A5\u5165\u5931\u8D25\uFF08HTTP ${status}\uFF09\uFF1A${why}
|
|
301697
|
+
${UNCHANGED}`;
|
|
301698
|
+
}
|
|
301699
|
+
async function exchangeEnrollToken(o) {
|
|
301700
|
+
const doFetch = o.fetchImpl ?? fetch;
|
|
301701
|
+
let res;
|
|
301702
|
+
try {
|
|
301703
|
+
res = await doFetch(`${o.httpBase}/api/nodes/exchange`, {
|
|
301704
|
+
method: "POST",
|
|
301705
|
+
headers: { "content-type": "application/json" },
|
|
301706
|
+
body: JSON.stringify({
|
|
301707
|
+
enrollToken: o.enrollToken,
|
|
301708
|
+
nodeId: o.nodeId,
|
|
301709
|
+
hostname: o.hostname,
|
|
301710
|
+
serverUrl: o.serverUrl,
|
|
301711
|
+
...o.companyId ? { companyId: o.companyId } : {}
|
|
301712
|
+
})
|
|
301713
|
+
});
|
|
301714
|
+
} catch (e) {
|
|
301715
|
+
throw new EnrollExchangeError(
|
|
301716
|
+
`\u2717 \u63A5\u5165\u5931\u8D25\uFF1A\u8FDE\u4E0D\u4E0A\u670D\u52A1\u7AEF ${o.httpBase}\uFF08${e instanceof Error ? e.message : String(e)}\uFF09\u3002\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u65B0\u8FD0\u884C\u63A5\u5165\u547D\u4EE4\u3002
|
|
301717
|
+
${UNCHANGED}`
|
|
301718
|
+
);
|
|
301719
|
+
}
|
|
301720
|
+
if (!res.ok) {
|
|
301721
|
+
const body3 = await res.json().catch(() => null);
|
|
301722
|
+
throw new EnrollExchangeError(describeExchangeFailure(res.status, body3), res.status);
|
|
301723
|
+
}
|
|
301724
|
+
const body2 = await res.json();
|
|
301725
|
+
if (!body2.token || !body2.nodeId) {
|
|
301726
|
+
throw new EnrollExchangeError(`\u2717 \u63A5\u5165\u5931\u8D25\uFF1A\u670D\u52A1\u7AEF\u7684\u5E94\u7B54\u91CC\u7F3A\u5C11\u8282\u70B9\u8EAB\u4EFD\u3002\u8BF7\u7A0D\u540E\u91CD\u65B0\u8FD0\u884C\u63A5\u5165\u547D\u4EE4\u3002
|
|
301727
|
+
${UNCHANGED}`, res.status);
|
|
301728
|
+
}
|
|
301729
|
+
return { token: body2.token, nodeId: body2.nodeId };
|
|
301730
|
+
}
|
|
301731
|
+
|
|
301497
301732
|
// src/install.ts
|
|
301498
301733
|
var import_node_crypto97 = require("node:crypto");
|
|
301499
301734
|
var fs49 = __toESM(require("node:fs"));
|
|
@@ -301624,7 +301859,7 @@ function shimScript() {
|
|
|
301624
301859
|
}
|
|
301625
301860
|
|
|
301626
301861
|
// src/index.ts
|
|
301627
|
-
var PKG_VERSION = true ? "2.2.
|
|
301862
|
+
var PKG_VERSION = true ? "2.2.101" : "dev";
|
|
301628
301863
|
var LOCAL_BIN = localBin();
|
|
301629
301864
|
var NPM_PREFIX = npmPrefix();
|
|
301630
301865
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -301964,16 +302199,17 @@ async function startOneInstance(o) {
|
|
|
301964
302199
|
const serverChanged = !!prev?.serverUrl && normalizeServerUrl(prev.serverUrl) !== normalizeServerUrl(serverUrl);
|
|
301965
302200
|
let nodeId = serverChanged ? void 0 : prev?.nodeId;
|
|
301966
302201
|
let token2 = serverChanged ? flags.get("token") ?? process.env["OASIS_NODE_TOKEN"] : flags.get("token") ?? process.env["OASIS_NODE_TOKEN"] ?? prev?.token;
|
|
301967
|
-
const enrollToken = o.
|
|
301968
|
-
const derivedNodeId = derivedNodeIdFor(INSTANCE);
|
|
302202
|
+
const enrollToken = o.enrollToken;
|
|
301969
302203
|
if (enrollToken) {
|
|
301970
|
-
const
|
|
301971
|
-
|
|
301972
|
-
|
|
301973
|
-
|
|
302204
|
+
const exchangeNodeId = o.mode === "resume" && prev?.nodeId && !serverChanged ? prev.nodeId : derivedNodeIdFor(INSTANCE);
|
|
302205
|
+
const body2 = await exchangeEnrollToken({
|
|
302206
|
+
httpBase: httpBase(serverUrl),
|
|
302207
|
+
enrollToken,
|
|
302208
|
+
nodeId: exchangeNodeId,
|
|
302209
|
+
hostname: os15.hostname(),
|
|
302210
|
+
serverUrl,
|
|
302211
|
+
...companyId ? { companyId } : {}
|
|
301974
302212
|
});
|
|
301975
|
-
if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
|
|
301976
|
-
const body2 = await res.json();
|
|
301977
302213
|
token2 = body2.token;
|
|
301978
302214
|
nodeId = body2.nodeId;
|
|
301979
302215
|
} else if (prev?.nodeId && prev?.token && !serverChanged) {
|
|
@@ -302015,7 +302251,7 @@ async function startOneInstance(o) {
|
|
|
302015
302251
|
}
|
|
302016
302252
|
const pidNow = readPid();
|
|
302017
302253
|
const alive2 = !!pidNow && isRunning2(pidNow);
|
|
302018
|
-
if (alive2 && label2 === before && !serverChanged && !companyChanged && !nameChanged) {
|
|
302254
|
+
if (alive2 && !enrollToken && label2 === before && !serverChanged && !companyChanged && !nameChanged) {
|
|
302019
302255
|
console.log(`\u2713 ${INSTANCE}\uFF1A\u5DF2\u5728\u8DD1\uFF08PID ${pidNow}\uFF0C${label2 ?? "?"}\uFF09\uFF0C\u7248\u672C\u4E0E\u914D\u7F6E\u5747\u672A\u53D8\uFF0C\u672A\u91CD\u542F`);
|
|
302020
302256
|
return;
|
|
302021
302257
|
}
|
|
@@ -302259,9 +302495,22 @@ void (async () => {
|
|
|
302259
302495
|
} else if (plan.mode === "new" && !explicit && listInstances().length > 0) {
|
|
302260
302496
|
console.log(`\u2192 \u672C\u673A\u5DF2\u6709\u5B9E\u4F8B\uFF08${listInstances().join(", ")}\uFF09\uFF0C\u4F46\u90FD\u4E0D\u8FDE\u8BE5\u670D\u52A1\u7AEF\uFF1B\u65B0\u5EFA\u5B9E\u4F8B ${plan.names[0]}`);
|
|
302261
302497
|
}
|
|
302498
|
+
const suppliedEnrollToken = flags.get("enroll-token") ?? process.env["OASIS_ENROLL_TOKEN"];
|
|
302499
|
+
const enrollToken = enrollTokenToUse(plan, suppliedEnrollToken);
|
|
302500
|
+
if (suppliedEnrollToken?.trim() && !enrollToken) {
|
|
302501
|
+
console.log(" \u63A5\u5165\u4EE4\u724C\u53EA\u80FD\u63A5\u4E00\u53F0\uFF1A\u672C\u6B21\u540C\u65F6\u6062\u590D\u591A\u4E2A\u5B9E\u4F8B\uFF0C\u4E0D\u4F7F\u7528\u5B83\uFF1B\u8981\u91CD\u65B0\u63A5\u5165\u67D0\u4E00\u4E2A\u5B9E\u4F8B\uFF0C\u8BF7\u52A0 --instance <\u5B9E\u4F8B\u540D> \u518D\u8FD0\u884C\u3002");
|
|
302502
|
+
}
|
|
302262
302503
|
for (const name of plan.names) {
|
|
302263
302504
|
useInstance(name);
|
|
302264
|
-
await startOneInstance({
|
|
302505
|
+
await startOneInstance({
|
|
302506
|
+
mode: plan.mode,
|
|
302507
|
+
serverUrl,
|
|
302508
|
+
upgrade,
|
|
302509
|
+
flags,
|
|
302510
|
+
applyName: plan.names.length === 1,
|
|
302511
|
+
companyId,
|
|
302512
|
+
...enrollToken ? { enrollToken } : {}
|
|
302513
|
+
});
|
|
302265
302514
|
}
|
|
302266
302515
|
if (!process.env["PATH"]?.includes(path45.dirname(LOCAL_BIN)))
|
|
302267
302516
|
console.log(` add to PATH: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oasis_test_v2",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.101",
|
|
4
4
|
"description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
|
|
5
5
|
"bin": {
|
|
6
6
|
"oasis": "./dist/index.js"
|
|
@@ -26,6 +26,6 @@
|
|
|
26
26
|
"node": ">=20"
|
|
27
27
|
},
|
|
28
28
|
"oasisRelease": {
|
|
29
|
-
"sourceHead": "
|
|
29
|
+
"sourceHead": "67501849999ce34dfcf0775dfcb95c9ca22118fb"
|
|
30
30
|
}
|
|
31
31
|
}
|