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.
Files changed (2) hide show
  1. package/dist/index.js +160 -12
  2. 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
- 留言给「查看沟通」直达留言线——线是投影出来的、恒存在,id 这里就能算;
235506
- 回压仍给「去处理」落到产物预览栏(那儿才有批注的处置面)。
235507
- 留言算不出对面是谁(该产物没负责人)时退回「去处理」,别给一个开不了的落点。 */
235508
- actions: isBackpressure || !commentTargetId ? [{ kind: "open_issue", label: BUTTON.handle, target: issueId }] : [{ kind: "open_thread", label: BUTTON.view, target: commentThreadSessionId(authorId, commentTargetId), variant: "quiet" }]
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.78" ? "2.2.78" : "dev";
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.78" : "dev";
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.78",
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": "aeb1027a34d130a7b5595af797c540036767963f"
29
+ "sourceHead": "eff5efb149ef3cf0f6ee828e0380936a97e7657c"
30
30
  }
31
31
  }