oasis_test_v2 2.2.78 → 2.2.79
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 +160 -12
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1054,12 +1054,13 @@ function sanitizeRuntimeQuotas(value2, now = Date.now()) {
|
|
|
1054
1054
|
}
|
|
1055
1055
|
return result;
|
|
1056
1056
|
}
|
|
1057
|
-
var RUNTIME_QUOTA_POLL_MS, RUNTIME_QUOTA_STALE_MS, statuses;
|
|
1057
|
+
var RUNTIME_QUOTA_POLL_MS, RUNTIME_QUOTA_STALE_MS, RUNTIME_QUOTA_REFRESH_MIN_GAP_MS, statuses;
|
|
1058
1058
|
var init_runtime_quota = __esm({
|
|
1059
1059
|
"../contract/src/runtime-quota.ts"() {
|
|
1060
1060
|
"use strict";
|
|
1061
1061
|
RUNTIME_QUOTA_POLL_MS = 5 * 6e4;
|
|
1062
1062
|
RUNTIME_QUOTA_STALE_MS = 2 * RUNTIME_QUOTA_POLL_MS;
|
|
1063
|
+
RUNTIME_QUOTA_REFRESH_MIN_GAP_MS = 3e4;
|
|
1063
1064
|
statuses = /* @__PURE__ */ new Set(["ok", "unavailable", "unauthenticated", "unsupported", "error", "rate_limited"]);
|
|
1064
1065
|
}
|
|
1065
1066
|
});
|
|
@@ -234828,6 +234829,9 @@ function isDispatchLayerFailure(detail) {
|
|
|
234828
234829
|
const reason = detail?.reason;
|
|
234829
234830
|
return typeof reason === "string" && reason.startsWith("dispatch ");
|
|
234830
234831
|
}
|
|
234832
|
+
function externalRefOf(a) {
|
|
234833
|
+
return a.contentKind === "external" && a.contentRef ? { externalRef: a.contentRef } : {};
|
|
234834
|
+
}
|
|
234831
234835
|
function buildWorkorderActivity(input) {
|
|
234832
234836
|
const { workorderId, snap, events } = input;
|
|
234833
234837
|
const ref2 = input.ref ?? ((id) => ({ id }));
|
|
@@ -234855,7 +234859,7 @@ function buildWorkorderActivity(input) {
|
|
|
234855
234859
|
} else if (isRootBrief) {
|
|
234856
234860
|
list2.push({ id: a.id, revisionId: a.workId, name: "\u4EFB\u52A1\u76EE\u6807", path: "\u4EFB\u52A1\u76EE\u6807.md", nodeId });
|
|
234857
234861
|
} else {
|
|
234858
|
-
list2.push({ id: a.id, revisionId: a.workId, name: a.name, nodeId });
|
|
234862
|
+
list2.push({ id: a.id, revisionId: a.workId, name: a.name, nodeId, ...externalRefOf(a) });
|
|
234859
234863
|
}
|
|
234860
234864
|
artifactsByWork.set(a.workId, list2);
|
|
234861
234865
|
}
|
|
@@ -235214,6 +235218,7 @@ function buildWorkorderActivity(input) {
|
|
|
235214
235218
|
const workOfIssue = /* @__PURE__ */ new Map();
|
|
235215
235219
|
const reasonWorksOfIssue = /* @__PURE__ */ new Map();
|
|
235216
235220
|
const recoveryLetterIssueIds = /* @__PURE__ */ new Set();
|
|
235221
|
+
const backpressureIssueIds = /* @__PURE__ */ new Set();
|
|
235217
235222
|
const plainComments = [];
|
|
235218
235223
|
const escalations = [];
|
|
235219
235224
|
const gapCreatedSeq = /* @__PURE__ */ new Map();
|
|
@@ -235445,6 +235450,7 @@ function buildWorkorderActivity(input) {
|
|
|
235445
235450
|
const isGap = issueKind === "gap";
|
|
235446
235451
|
const raisedFrom = str5(ev.raisedByNodeId);
|
|
235447
235452
|
const isBackpressure = !isEscalation && !isGap && !!raisedFrom && raisedFrom !== nodeId;
|
|
235453
|
+
if (isBackpressure) backpressureIssueIds.add(issueId);
|
|
235448
235454
|
const body2 = str5(ev.body) ?? "";
|
|
235449
235455
|
if (isEscalation) {
|
|
235450
235456
|
const linkedGapId = str5(ev.gapId);
|
|
@@ -235492,6 +235498,11 @@ function buildWorkorderActivity(input) {
|
|
|
235492
235498
|
/* 回压是**执行中断**(这一轮走不下去了,要外部介入);唤醒信那档不是中断,仍是进行中。
|
|
235493
235499
|
缺口走不到这里了(F4 在上面 break)。 */
|
|
235494
235500
|
phase: isBackpressure ? "stuck" : "running",
|
|
235501
|
+
/* 回压卡**不喊**:砖红只给「此刻等人动手」的那张(奕璇 2026-09-22)。轮到动手的是被回压节点的
|
|
235502
|
+
负责人——真人时由他那一轮喊(砖红 + 去处理),agent 时它自己在跑(暖橙)。提要求这一段在
|
|
235503
|
+
开口那一刻就结束了,与缺口中断的执行卡同一条先例(F1:上一段结束就转灰,该喊的是下游那张)。
|
|
235504
|
+
不写这两个字段时前端退回老规则(开着 + stuck ⇒ 砖红),同一件事页面上会有两张红卡。 */
|
|
235505
|
+
...isBackpressure ? { segmentOpen: false, awaitingHuman: false } : {},
|
|
235495
235506
|
status: isBackpressure ? ACTIVITY_COPY.backpressure(
|
|
235496
235507
|
nameOf2(authorId),
|
|
235497
235508
|
nodeName(nodeId),
|
|
@@ -235501,11 +235512,15 @@ function buildWorkorderActivity(input) {
|
|
|
235501
235512
|
此前只有缺口/回压被排除,留言仍是「正文当小状态 + 展开区再印一遍」,
|
|
235502
235513
|
全库实测最长 8096 字印两遍(`ws:wo-56bba3c1`),一张卡顶掉整屏。 */
|
|
235503
235514
|
artifacts: [],
|
|
235504
|
-
/*
|
|
235505
|
-
|
|
235506
|
-
|
|
235507
|
-
|
|
235508
|
-
|
|
235515
|
+
/* 按钮只长在「人能点、而且轮到人动手」的那张卡上(奕璇 2026-09-22):
|
|
235516
|
+
· 回压卡**一个按钮都没有**:它署名的是提要求的一方(多为 agent),轮到动手的是被回压节点的
|
|
235517
|
+
负责人。负责人是真人时「去处理」挂在系统给他开的那一轮上(见事件循环之后
|
|
235518
|
+
`backpressureAwaitingOwner` 那一段),落点、target 与原先这颗一样;负责人是 agent 时
|
|
235519
|
+
它自己会跑,没有人要动手。
|
|
235520
|
+
· 唤醒信给「查看沟通」直达留言线——线是投影出来的、恒存在,id 这里就能算。
|
|
235521
|
+
· 唤醒信算不出对面是谁(该产物没负责人 / 负责人就是作者)时退回「去处理」,但**只在署名的
|
|
235522
|
+
是真人时**给:agent / 系统署名的卡挂「去处理」,点的人进去没有一件是他该做的事。 */
|
|
235523
|
+
actions: isBackpressure ? [] : !commentTargetId ? isHumanActorId(authorId) ? [{ kind: "open_issue", label: BUTTON.handle, target: issueId }] : [] : [{ kind: "open_thread", label: BUTTON.view, target: commentThreadSessionId(authorId, commentTargetId), variant: "quiet" }]
|
|
235509
235524
|
});
|
|
235510
235525
|
break;
|
|
235511
235526
|
}
|
|
@@ -235816,6 +235831,18 @@ function buildWorkorderActivity(input) {
|
|
|
235816
235831
|
const message = (input.runFailures ?? []).filter((f2) => f2.nodeId === card2.nodeId && f2.startedAt >= card2.at && f2.startedAt <= trip.at && f2.message.trim()).sort((a, b2) => a.startedAt.localeCompare(b2.startedAt)).at(-1)?.message;
|
|
235817
235832
|
return message ? firstSentence(message) : void 0;
|
|
235818
235833
|
};
|
|
235834
|
+
for (const card2 of executionCards) {
|
|
235835
|
+
const workId = card2.openWorkId;
|
|
235836
|
+
if (!workId || !isHumanActorId(card2.executorId)) continue;
|
|
235837
|
+
const issueId = [...backpressureIssueIds].find((id) => reasonWorksOfIssue.get(id)?.includes(workId) && !issueById.get(id)?.resolvedAt && !plainResolveEvents.has(id));
|
|
235838
|
+
if (!issueId) continue;
|
|
235839
|
+
card2.phase = "not_started";
|
|
235840
|
+
card2.phaseLabel = PHASE_LABEL.escalationPending;
|
|
235841
|
+
card2.segmentOpen = true;
|
|
235842
|
+
card2.awaitingHuman = true;
|
|
235843
|
+
card2.status = ACTIVITY_COPY.backpressureAwaitingOwner(nameOf2(card2.executorId), nodeName(card2.nodeId));
|
|
235844
|
+
card2.actions = [{ kind: "open_issue", label: BUTTON.handle, target: issueId, variant: "primary" }];
|
|
235845
|
+
}
|
|
235819
235846
|
for (const card2 of executionCards) {
|
|
235820
235847
|
const trips = card2.stopLossTrips;
|
|
235821
235848
|
if (!trips?.length) continue;
|
|
@@ -236327,6 +236354,11 @@ var init_activity2 = __esm({
|
|
|
236327
236354
|
①「缺口卡」也删掉(F4):它和执行卡挂的是同一段运行、同一份轨迹,点哪张打开的都一样。 */
|
|
236328
236355
|
/** 回压(下游对上游提修改要求)——发起人 2026-09-08 认可的措辞。 */
|
|
236329
236356
|
backpressure: (raiser, upstream, owner) => `${raiser} \u5BF9\u300A${upstream}\u300B\u63D0\u51FA\u4FEE\u6539\u8981\u6C42\uFF0C\u9700\u8981 @${owner} \u5904\u7406\u3002`,
|
|
236357
|
+
/**
|
|
236358
|
+
* 被回压节点的负责人是**真人**时,系统为他开的那一轮(奕璇 2026-09-22 定):这一轮不会自己跑,
|
|
236359
|
+
* 是在等他动手——不能再说「正在根据反馈调整」(`issueDriven`),那句会让一张没人在动的卡挂成「进行中」。
|
|
236360
|
+
*/
|
|
236361
|
+
backpressureAwaitingOwner: (owner, node2) => `\u7B49 @${owner} \u6839\u636E\u4FEE\u6539\u8981\u6C42\u8C03\u6574\u300A${node2}\u300B\u3002`,
|
|
236330
236362
|
/**
|
|
236331
236363
|
* 留言 / 批注——**一句索引,正文不上卡**(发起人 2026-09-09 定)。
|
|
236332
236364
|
*
|
|
@@ -236410,7 +236442,10 @@ var init_activity2 = __esm({
|
|
|
236410
236442
|
* 所以仍然要 override,只是换成和 `stuck` 一族同一个词。
|
|
236411
236443
|
*/
|
|
236412
236444
|
failed: "\u6267\u884C\u4E2D\u65AD",
|
|
236413
|
-
/**
|
|
236445
|
+
/**
|
|
236446
|
+
* 升级卡没人处理那一档。**不写「待你处理」**:别人看到的字要和该处理的人看到的一样。
|
|
236447
|
+
* 被回压的真人负责人那一轮(等他按修改要求动手)也用这个词——同样是「这一段卡在人身上」。
|
|
236448
|
+
*/
|
|
236414
236449
|
escalationPending: "\u5F85\u5904\u7406"
|
|
236415
236450
|
};
|
|
236416
236451
|
COORDINATOR_CARD_PREFIX = "coordinator:";
|
|
@@ -236569,7 +236604,7 @@ function artifactsOfWork(work, input) {
|
|
|
236569
236604
|
} else if (isRootBrief) {
|
|
236570
236605
|
list2.push({ id: a.id, revisionId: a.workId, name: "\u4EFB\u52A1\u76EE\u6807", path: "\u4EFB\u52A1\u76EE\u6807.md", nodeId: artifactNodeId });
|
|
236571
236606
|
} else {
|
|
236572
|
-
list2.push({ id: a.id, revisionId: a.workId, name: a.name, nodeId: artifactNodeId });
|
|
236607
|
+
list2.push({ id: a.id, revisionId: a.workId, name: a.name, nodeId: artifactNodeId, ...externalRefOf(a) });
|
|
236573
236608
|
}
|
|
236574
236609
|
}
|
|
236575
236610
|
return list2;
|
|
@@ -243748,6 +243783,10 @@ function nodesDomain(deps) {
|
|
|
243748
243783
|
}
|
|
243749
243784
|
if (rows.length > 0) console.log(`[nodes] \u989D\u5EA6\u6C34\u5408\uFF1A\u4ECE\u5E93\u91CC\u8BFB\u56DE ${rows.length} \u6761\u8FD0\u884C\u65F6\u989D\u5EA6`);
|
|
243750
243785
|
}).catch((err) => console.warn(`[nodes] \u989D\u5EA6\u6C34\u5408\u5931\u8D25\uFF08\u7167\u65E7\u7B49\u4E0B\u4E00\u6B21\u91C7\u96C6\uFF09\uFF1A${err instanceof Error ? err.message : String(err)}`));
|
|
243786
|
+
const quotaRefreshWaiters = /* @__PURE__ */ new Map();
|
|
243787
|
+
const quotaRefreshInFlight = /* @__PURE__ */ new Map();
|
|
243788
|
+
const QUOTA_REFRESH_TIMEOUT_MS = 4e4;
|
|
243789
|
+
const QUOTA_CAPABLE_KINDS = /* @__PURE__ */ new Set(["codex", "claude-code"]);
|
|
243751
243790
|
const UPDATE_TIMEOUT_MS = 15e4;
|
|
243752
243791
|
const nodeUpdates = /* @__PURE__ */ new Map();
|
|
243753
243792
|
function runtimeInfoOf(r) {
|
|
@@ -243829,6 +243868,45 @@ function nodesDomain(deps) {
|
|
|
243829
243868
|
}
|
|
243830
243869
|
return { version: null, source: null };
|
|
243831
243870
|
}
|
|
243871
|
+
async function refreshNodeQuotas(nodeId) {
|
|
243872
|
+
const running = quotaRefreshInFlight.get(nodeId);
|
|
243873
|
+
if (running) return running;
|
|
243874
|
+
const hub = deps.getHub();
|
|
243875
|
+
if (!hub) return { ok: false, code: "no-gateway", reason: "\u672C\u90E8\u7F72\u6CA1\u6709\u8282\u70B9\u7F51\u5173\uFF0C\u591F\u4E0D\u5230\u90A3\u53F0\u673A\u5668" };
|
|
243876
|
+
const daemon = hub.connectedDaemons().find((d) => d.daemonId === nodeId);
|
|
243877
|
+
if (!daemon) {
|
|
243878
|
+
return { ok: false, code: "offline", reason: "\u8FD9\u53F0\u8282\u70B9\u5F53\u524D\u4E0D\u5728\u7EBF\uFF0C\u770B\u5230\u7684\u662F\u5B83\u6700\u540E\u4E00\u6B21\u4E0A\u62A5\u7684\u989D\u5EA6\uFF1B\u628A\u673A\u5668\u8FDE\u56DE\u6765\u4E4B\u540E\u624D\u80FD\u91CD\u91C7" };
|
|
243879
|
+
}
|
|
243880
|
+
if (!daemon.meta.supportsQuotaRefresh) {
|
|
243881
|
+
return { ok: false, code: "unsupported-version", reason: "\u8FD9\u53F0\u8282\u70B9\u7684\u7A0B\u5E8F\u7248\u672C\u8FD8\u4E0D\u652F\u6301\u989D\u5EA6\u91CD\u91C7\uFF0C\u66F4\u65B0\u8282\u70B9\u4E4B\u540E\u53EF\u7528" };
|
|
243882
|
+
}
|
|
243883
|
+
if (!daemon.meta.adapters.some((kind) => QUOTA_CAPABLE_KINDS.has(kind))) {
|
|
243884
|
+
return { ok: false, code: "no-quota-runtime", reason: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u4F1A\u4E0A\u62A5\u989D\u5EA6\u7684\u8FD0\u884C\u65F6\uFF08\u53EA\u6709 Claude Code \u548C Codex \u80FD\u67E5\u5230\u8BA2\u9605\u989D\u5EA6\uFF09" };
|
|
243885
|
+
}
|
|
243886
|
+
const requestId = (0, import_node_crypto62.randomUUID)();
|
|
243887
|
+
const task = new Promise((resolve12) => {
|
|
243888
|
+
const timer = setTimeout(() => {
|
|
243889
|
+
quotaRefreshWaiters.delete(requestId);
|
|
243890
|
+
resolve12({ ok: false, code: "timeout", reason: `\u8FD9\u53F0\u8282\u70B9\u6CA1\u5728 ${Math.round(QUOTA_REFRESH_TIMEOUT_MS / 1e3)} \u79D2\u5185\u56DE\u8BDD\uFF0C\u9875\u9762\u4E0A\u4ECD\u662F\u5B83\u4E0A\u6B21\u62A5\u7684\u989D\u5EA6` });
|
|
243891
|
+
}, QUOTA_REFRESH_TIMEOUT_MS);
|
|
243892
|
+
quotaRefreshWaiters.set(requestId, {
|
|
243893
|
+
// 节点自己说没采(连点被最小间隔挡下、这台机器上采集出错)→ 原样把它那句话带回前端。
|
|
243894
|
+
resolve: (r) => resolve12(r.ok ? { ok: true } : { ok: false, code: "node", ...r.reason ? { reason: r.reason } : {} }),
|
|
243895
|
+
timer
|
|
243896
|
+
});
|
|
243897
|
+
const sent = hub.dispatch(nodeId, { type: "refresh_quotas", requestId });
|
|
243898
|
+
if (sent) return;
|
|
243899
|
+
const waiter = quotaRefreshWaiters.get(requestId);
|
|
243900
|
+
if (!waiter) return;
|
|
243901
|
+
quotaRefreshWaiters.delete(requestId);
|
|
243902
|
+
clearTimeout(waiter.timer);
|
|
243903
|
+
resolve12({ ok: false, code: "offline", reason: "\u6307\u4EE4\u6CA1\u9001\u5230\u8FD9\u53F0\u8282\u70B9\uFF08\u8FDE\u63A5\u521A\u65AD\u5F00\uFF09\uFF0C\u9875\u9762\u4E0A\u4ECD\u662F\u5B83\u4E0A\u6B21\u62A5\u7684\u989D\u5EA6" });
|
|
243904
|
+
}).finally(() => {
|
|
243905
|
+
quotaRefreshInFlight.delete(nodeId);
|
|
243906
|
+
});
|
|
243907
|
+
quotaRefreshInFlight.set(nodeId, task);
|
|
243908
|
+
return task;
|
|
243909
|
+
}
|
|
243832
243910
|
let hubWired = false;
|
|
243833
243911
|
function wireHub(hub) {
|
|
243834
243912
|
if (hubWired) return;
|
|
@@ -243865,6 +243943,14 @@ function nodesDomain(deps) {
|
|
|
243865
243943
|
}
|
|
243866
243944
|
})().catch((err) => console.warn(`[nodes] \u6545\u969C\u81EA\u52A8\u89E3\u9664\u5931\u8D25(node=${daemonId})\uFF1A${err instanceof Error ? err.message : String(err)}`));
|
|
243867
243945
|
});
|
|
243946
|
+
hub.addMessageListener((_daemonId, msg) => {
|
|
243947
|
+
if (msg.type !== "quota_refresh_result") return;
|
|
243948
|
+
const waiter = quotaRefreshWaiters.get(msg.requestId);
|
|
243949
|
+
if (!waiter) return;
|
|
243950
|
+
quotaRefreshWaiters.delete(msg.requestId);
|
|
243951
|
+
clearTimeout(waiter.timer);
|
|
243952
|
+
waiter.resolve({ ok: msg.ok, ...msg.reason ? { reason: msg.reason } : {} });
|
|
243953
|
+
});
|
|
243868
243954
|
hub.addMessageListener(async (daemonId, msg) => {
|
|
243869
243955
|
if (msg.type !== "hello") return;
|
|
243870
243956
|
const d = hub.connectedDaemons().find((c) => c.daemonId === daemonId);
|
|
@@ -244286,6 +244372,22 @@ function nodesDomain(deps) {
|
|
|
244286
244372
|
nodeUpdates.set(nodeId, tracked);
|
|
244287
244373
|
return { status: 200, body: { ok: true, alreadyLatest: false, updateStatus: publicUpdateStatus(tracked, activeRunCount) } };
|
|
244288
244374
|
});
|
|
244375
|
+
router.post("/api/nodes/:nodeId/quotas/refresh", async (req) => {
|
|
244376
|
+
const nodeId = req.params["nodeId"];
|
|
244377
|
+
if (!nodeId) return { status: 400, body: { error: "missing nodeId" } };
|
|
244378
|
+
const scope2 = req.auth.companyId !== void 0 ? { companyId: req.auth.companyId } : void 0;
|
|
244379
|
+
const node2 = (await deps.nodeStore.listNodes(scope2)).find((n) => n.id === nodeId);
|
|
244380
|
+
if (!node2) return { status: 404, body: { error: "NODE_NOT_FOUND", message: "\u8282\u70B9\u4E0D\u5B58\u5728\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u7EC4\u7EC7" } };
|
|
244381
|
+
const outcome = await refreshNodeQuotas(nodeId);
|
|
244382
|
+
return {
|
|
244383
|
+
status: 200,
|
|
244384
|
+
body: {
|
|
244385
|
+
refreshed: outcome.ok,
|
|
244386
|
+
...outcome.code ? { code: outcome.code } : {},
|
|
244387
|
+
...outcome.reason ? { reason: outcome.reason } : {}
|
|
244388
|
+
}
|
|
244389
|
+
};
|
|
244390
|
+
});
|
|
244289
244391
|
router.delete("/api/runtimes/:runtimeId", async (req) => {
|
|
244290
244392
|
const runtimeId = req.params["runtimeId"];
|
|
244291
244393
|
if (!runtimeId) return { status: 400, body: { error: "missing runtimeId" } };
|
|
@@ -287960,11 +288062,12 @@ async function readClaudeQuota(binary, signal, deps = {}) {
|
|
|
287960
288062
|
// ../cli/src/daemon/quota/monitor.ts
|
|
287961
288063
|
var read2 = (runtime, signal) => runtime.kind === "codex" ? readCodexQuota(runtime.binary ?? "codex", signal) : readClaudeQuota(runtime.binary ?? "claude", signal, { version: runtime.version });
|
|
287962
288064
|
var RuntimeQuotaMonitor = class {
|
|
287963
|
-
constructor(runtimes, send, reader = read2, intervalMs = RUNTIME_QUOTA_POLL_MS) {
|
|
288065
|
+
constructor(runtimes, send, reader = read2, intervalMs = RUNTIME_QUOTA_POLL_MS, minGapMs = RUNTIME_QUOTA_REFRESH_MIN_GAP_MS) {
|
|
287964
288066
|
this.runtimes = runtimes;
|
|
287965
288067
|
this.send = send;
|
|
287966
288068
|
this.reader = reader;
|
|
287967
288069
|
this.intervalMs = intervalMs;
|
|
288070
|
+
this.minGapMs = minGapMs;
|
|
287968
288071
|
}
|
|
287969
288072
|
cache = [];
|
|
287970
288073
|
collectedAt;
|
|
@@ -287994,6 +288097,41 @@ var RuntimeQuotaMonitor = class {
|
|
|
287994
288097
|
});
|
|
287995
288098
|
return this.pending;
|
|
287996
288099
|
}
|
|
288100
|
+
/**
|
|
288101
|
+
* 人点了页面上的「刷新」(服务端下发 `refresh_quotas`,ADR 0620):**现在就去问上游**。
|
|
288102
|
+
*
|
|
288103
|
+
* 与 {@link refresh} 的唯一区别就是**不看那 5 分钟**——那条节流是背景轮询的节奏,
|
|
288104
|
+
* 对一个正盯着页面等结果的人没有任何意义。换上的是一条窄得多的闸:
|
|
288105
|
+
* {@link RUNTIME_QUOTA_REFRESH_MIN_GAP_MS}(30 秒)。连点被它挡下,且挡下时**如实说**
|
|
288106
|
+
* 「刚在 N 秒前采过」,不假装采了一次(发起人方申的定则:会静默降级的动作必须回报走了哪条路)。
|
|
288107
|
+
*
|
|
288108
|
+
* provider 自己给的 `retryAt` 退避**不在**绕过范围内:那是上游明说的「别来了」,
|
|
288109
|
+
* 谁点按钮都不该越过它。被它挡住的那个 runtime 在 `collect` 里照旧沿用上一次的结果。
|
|
288110
|
+
*/
|
|
288111
|
+
forceRefresh() {
|
|
288112
|
+
if (this.stopped) return Promise.resolve({ ok: false, reason: "\u8FD9\u53F0\u8282\u70B9\u6B63\u5728\u505C\u673A\uFF0C\u6CA1\u6709\u91CD\u91C7\u989D\u5EA6" });
|
|
288113
|
+
if (this.collectableKinds().length === 0) {
|
|
288114
|
+
return Promise.resolve({ ok: false, reason: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u4F1A\u4E0A\u62A5\u989D\u5EA6\u7684\u8FD0\u884C\u65F6\uFF08\u53EA\u6709 Claude Code \u548C Codex \u80FD\u67E5\u5230\u8BA2\u9605\u989D\u5EA6\uFF09" });
|
|
288115
|
+
}
|
|
288116
|
+
if (this.pending) return this.pending.then(() => ({ ok: true }));
|
|
288117
|
+
const sinceMs = this.collectedAt === void 0 ? Number.POSITIVE_INFINITY : Date.now() - this.collectedAt;
|
|
288118
|
+
if (sinceMs < this.minGapMs) {
|
|
288119
|
+
return Promise.resolve({
|
|
288120
|
+
ok: false,
|
|
288121
|
+
reason: `\u989D\u5EA6\u521A\u5728 ${Math.max(1, Math.round(sinceMs / 1e3))} \u79D2\u524D\u91C7\u8FC7\uFF0C\u9875\u9762\u4E0A\u5C31\u662F\u6700\u65B0\u6570\u636E\uFF1B${Math.ceil((this.minGapMs - sinceMs) / 1e3)} \u79D2\u540E\u53EF\u4EE5\u518D\u91C7\u4E00\u6B21`
|
|
288122
|
+
});
|
|
288123
|
+
}
|
|
288124
|
+
this.pending = this.collect().finally(() => {
|
|
288125
|
+
this.pending = void 0;
|
|
288126
|
+
});
|
|
288127
|
+
return this.pending.then(() => ({ ok: true }));
|
|
288128
|
+
}
|
|
288129
|
+
/** 这台机器上真的会上报额度的 runtime(白名单硬编码在 collect 里,两处取同一份判据)。 */
|
|
288130
|
+
collectableKinds() {
|
|
288131
|
+
const kinds = [];
|
|
288132
|
+
for (const r of this.runtimes) if (r.kind === "codex" || r.kind === "claude-code") kinds.push(r.kind);
|
|
288133
|
+
return kinds;
|
|
288134
|
+
}
|
|
287997
288135
|
async collect() {
|
|
287998
288136
|
const result = [];
|
|
287999
288137
|
for (const runtime of this.runtimes) {
|
|
@@ -288843,6 +288981,13 @@ var DaemonWsClient = class {
|
|
|
288843
288981
|
void this.reportRuntimeModels({ force: true, requestId: msg.requestId });
|
|
288844
288982
|
break;
|
|
288845
288983
|
}
|
|
288984
|
+
case "refresh_quotas": {
|
|
288985
|
+
const requestId = msg.requestId;
|
|
288986
|
+
void this.quotaMonitor.forceRefresh().catch((err) => ({ ok: false, reason: `\u91CD\u91C7\u989D\u5EA6\u65F6\u51FA\u9519\uFF1A${err instanceof Error ? err.message : String(err)}` })).then((r) => {
|
|
288987
|
+
this.send({ type: "quota_refresh_result", requestId, ok: r.ok, ...r.reason ? { reason: r.reason } : {} });
|
|
288988
|
+
});
|
|
288989
|
+
break;
|
|
288990
|
+
}
|
|
288846
288991
|
case "update": {
|
|
288847
288992
|
this.pendingUpdatePkg = msg.pkg;
|
|
288848
288993
|
if (!this.onUpdate) {
|
|
@@ -289069,6 +289214,9 @@ var DaemonWsClient = class {
|
|
|
289069
289214
|
supportsChunkedMessages: true,
|
|
289070
289215
|
// Bug 0107:本 daemon 认 `input_receipt_query`。恒 true——handler 随包发。
|
|
289071
289216
|
supportsInputReceiptQuery: true,
|
|
289217
|
+
// ADR 0620:本 daemon 认 `refresh_quotas`(人点刷新时现去问一遍上游额度)。恒 true——
|
|
289218
|
+
// 采集器随包发。服务端据此对老节点当场回「升级后可用」,不必发一帧出去等超时。
|
|
289219
|
+
supportsQuotaRefresh: true,
|
|
289072
289220
|
...activeSessions.length > 0 ? { activeSessions } : {},
|
|
289073
289221
|
// 始终带字段(空数组也带)作为新协议能力标志;服务端仅对支持该字段的节点做缺席确认。
|
|
289074
289222
|
pendingDispatchIds: [...this.pendingDispatchIds]
|
|
@@ -291915,7 +292063,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
291915
292063
|
}
|
|
291916
292064
|
}
|
|
291917
292065
|
}
|
|
291918
|
-
var CLI_VERSION = "2.2.
|
|
292066
|
+
var CLI_VERSION = "2.2.79" ? "2.2.79" : "dev";
|
|
291919
292067
|
function apiHeaders(token, company) {
|
|
291920
292068
|
const headers = {
|
|
291921
292069
|
authorization: `Bearer ${token}`,
|
|
@@ -295814,7 +295962,7 @@ function shimScript() {
|
|
|
295814
295962
|
}
|
|
295815
295963
|
|
|
295816
295964
|
// src/index.ts
|
|
295817
|
-
var PKG_VERSION = true ? "2.2.
|
|
295965
|
+
var PKG_VERSION = true ? "2.2.79" : "dev";
|
|
295818
295966
|
var LOCAL_BIN = localBin();
|
|
295819
295967
|
var NPM_PREFIX = npmPrefix();
|
|
295820
295968
|
var INSTANCE = DEFAULT_INSTANCE;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oasis_test_v2",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.79",
|
|
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": "eff5efb149ef3cf0f6ee828e0380936a97e7657c"
|
|
30
30
|
}
|
|
31
31
|
}
|