oasis_test_v2 2.2.53 → 2.2.54

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 +425 -109
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -3799,6 +3799,64 @@ function accumulateClaudeUsage(acc, p2) {
3799
3799
  if (acc.finalUsage || acc.costUsd != null) acc.saw = true;
3800
3800
  }
3801
3801
  }
3802
+ function newClaudeRunningUsage() {
3803
+ return { byMessage: /* @__PURE__ */ new Map(), currentMessageId: null, lastKey: "" };
3804
+ }
3805
+ function mergeMessageMax(acc, messageId, snapshot) {
3806
+ if (!snapshot) return;
3807
+ const prev = acc.byMessage.get(messageId) ?? { input: 0, output: 0, cacheRead: 0, cacheCreation: 0 };
3808
+ acc.byMessage.set(messageId, {
3809
+ input: Math.max(prev.input, snapshot.input ?? 0),
3810
+ output: Math.max(prev.output, snapshot.output ?? 0),
3811
+ cacheRead: Math.max(prev.cacheRead, snapshot.cacheRead ?? 0),
3812
+ cacheCreation: Math.max(prev.cacheCreation, snapshot.cacheCreation ?? 0)
3813
+ });
3814
+ }
3815
+ function observeClaudeRunningUsage(acc, p2) {
3816
+ if (stringOf(p2["parent_tool_use_id"])) return void 0;
3817
+ if (p2["type"] === "assistant") {
3818
+ const msg = objectOf(p2["message"]);
3819
+ const id = stringOf(msg?.id);
3820
+ if (!id) return void 0;
3821
+ mergeMessageMax(acc, id, parseResultUsage(msg?.usage));
3822
+ const model = stringOf(msg?.model);
3823
+ if (model) acc.model = model;
3824
+ } else if (p2["type"] === "stream_event") {
3825
+ const event = objectOf(p2["event"]);
3826
+ if (event?.type === "message_start") {
3827
+ const msg = objectOf(event.message);
3828
+ const id = stringOf(msg?.id);
3829
+ if (!id) return void 0;
3830
+ acc.currentMessageId = id;
3831
+ mergeMessageMax(acc, id, parseResultUsage(msg?.usage));
3832
+ } else if (event?.type === "message_delta" && acc.currentMessageId) {
3833
+ mergeMessageMax(acc, acc.currentMessageId, parseResultUsage(event.usage));
3834
+ } else {
3835
+ return void 0;
3836
+ }
3837
+ } else {
3838
+ return void 0;
3839
+ }
3840
+ if (acc.byMessage.size === 0) return void 0;
3841
+ let input = 0, output = 0, cacheRead = 0, cacheCreation = 0;
3842
+ for (const b2 of acc.byMessage.values()) {
3843
+ input += b2.input;
3844
+ output += b2.output;
3845
+ cacheRead += b2.cacheRead;
3846
+ cacheCreation += b2.cacheCreation;
3847
+ }
3848
+ const key2 = `${input}/${output}/${cacheRead}/${cacheCreation}`;
3849
+ if (key2 === acc.lastKey || input + output + cacheRead + cacheCreation === 0) return void 0;
3850
+ acc.lastKey = key2;
3851
+ return {
3852
+ inputTokens: input,
3853
+ outputTokens: output,
3854
+ totalTokens: input + output,
3855
+ cacheReadTokens: cacheRead,
3856
+ cacheCreationTokens: cacheCreation,
3857
+ costUsdMicros: null
3858
+ };
3859
+ }
3802
3860
  function buildClaudeUsage(acc) {
3803
3861
  if (!acc.saw) return void 0;
3804
3862
  const input = acc.finalUsage?.input ?? acc.input;
@@ -4117,6 +4175,8 @@ var init_claude_code = __esm({
4117
4175
  const STDERR_MAX_LINES = 40;
4118
4176
  const STDERR_MAX_BYTES = 4e3;
4119
4177
  const usageAcc = newClaudeUsageAcc();
4178
+ const runningUsage = newClaudeRunningUsage();
4179
+ const usageCheckpointCbs = [];
4120
4180
  let sessionModel;
4121
4181
  const outputCbs = [];
4122
4182
  const liveParser = createClaudeLiveParserState(`claude-live:${id}`, { readSubagentCalls: readSubagentTranscriptCalls });
@@ -4149,6 +4209,11 @@ var init_claude_code = __esm({
4149
4209
  maybeCloseInputOnResult();
4150
4210
  }
4151
4211
  accumulateClaudeUsage(usageAcc, p2);
4212
+ const running = observeClaudeRunningUsage(runningUsage, p2);
4213
+ if (running) {
4214
+ const model = runningUsage.model ?? sessionModel;
4215
+ for (const cb of usageCheckpointCbs) cb({ usage: running, ...model ? { model } : {} });
4216
+ }
4152
4217
  if (!sessionModel) {
4153
4218
  if (p2["type"] === "system" && typeof p2["model"] === "string" && p2["model"]) sessionModel = p2["model"];
4154
4219
  else if (p2["type"] === "assistant") {
@@ -4300,6 +4365,9 @@ var init_claude_code = __esm({
4300
4365
  onLiveEvent(cb) {
4301
4366
  liveEventCbs.push(cb);
4302
4367
  },
4368
+ onUsageCheckpoint(cb) {
4369
+ usageCheckpointCbs.push(cb);
4370
+ },
4303
4371
  // ADR-0093 对话追加:把这条 user 输入作为一条 stream-json 消息续写进 stdin(同会话下一回合)。
4304
4372
  // 非 appendMode → unsupported;已退出/已在关 stdin → session-closing。
4305
4373
  get canAppendInput() {
@@ -4384,6 +4452,7 @@ function withResilience(inner, cfg = {}) {
4384
4452
  const telemetryCbs = [];
4385
4453
  const liveEventCbs = [];
4386
4454
  const normalizedCbs = [];
4455
+ const usageCheckpointCbs = [];
4387
4456
  let supportsNormalized = false;
4388
4457
  const exitCbs = [];
4389
4458
  let outerId = null;
@@ -4451,6 +4520,9 @@ function withResilience(inner, cfg = {}) {
4451
4520
  bumpIdle();
4452
4521
  for (const cb of normalizedCbs) cb(event);
4453
4522
  });
4523
+ handle.onUsageCheckpoint?.((checkpoint) => {
4524
+ for (const cb of usageCheckpointCbs) cb(checkpoint);
4525
+ });
4454
4526
  handle.onExit((info) => {
4455
4527
  if (done) return;
4456
4528
  done = true;
@@ -4531,6 +4603,11 @@ function withResilience(inner, cfg = {}) {
4531
4603
  onNormalizedProviderEvent: (cb) => {
4532
4604
  normalizedCbs.push(cb);
4533
4605
  },
4606
+ // 运行中用量检查点:同四条流,走本层扇出——重跑换手后新 attempt 的检查点照样送到同一个订阅者。
4607
+ // 换手后新 attempt 从 0 重新累计,与它最终交出的终值同口径(终值也只是最后一个 attempt 的)。
4608
+ onUsageCheckpoint: (cb) => {
4609
+ usageCheckpointCbs.push(cb);
4610
+ },
4534
4611
  finishNormalizedTurn: (signal) => {
4535
4612
  activeHandle?.finishNormalizedTurn?.(signal);
4536
4613
  },
@@ -5806,6 +5883,8 @@ async function runProtocolSession(job, cfg) {
5806
5883
  const outputCbs = [];
5807
5884
  const telemetryCbs = [];
5808
5885
  const liveCbs = [];
5886
+ const usageCbs = [];
5887
+ let lastUsageKey = "";
5809
5888
  const appendByKey = /* @__PURE__ */ new Map();
5810
5889
  const exitCbs = [];
5811
5890
  const state = cfg.createState();
@@ -5881,6 +5960,14 @@ async function runProtocolSession(job, cfg) {
5881
5960
  const event = { kind: line2.kind, payload: line2.payload, seq: ++eventSeq, ts: (/* @__PURE__ */ new Date()).toISOString() };
5882
5961
  for (const cb of telemetryCbs) cb(event);
5883
5962
  }
5963
+ if (cfg.runningUsage && usageCbs.length) {
5964
+ const checkpoint = cfg.runningUsage(state);
5965
+ const key2 = checkpoint ? JSON.stringify(checkpoint.usage) : "";
5966
+ if (checkpoint && key2 !== lastUsageKey) {
5967
+ lastUsageKey = key2;
5968
+ for (const cb of usageCbs) cb(checkpoint);
5969
+ }
5970
+ }
5884
5971
  if (!started) pendingTurnMessages.push(message);
5885
5972
  else completeTurn(message);
5886
5973
  };
@@ -5974,6 +6061,9 @@ async function runProtocolSession(job, cfg) {
5974
6061
  onLiveEvent(cb) {
5975
6062
  liveCbs.push(cb);
5976
6063
  },
6064
+ ...cfg.runningUsage ? { onUsageCheckpoint(cb) {
6065
+ usageCbs.push(cb);
6066
+ } } : {},
5977
6067
  get canAppendInput() {
5978
6068
  return !closing && started && !exited;
5979
6069
  },
@@ -6045,8 +6135,15 @@ function addCodexBuckets(acc, add) {
6045
6135
  acc.cacheWrite += add.cacheWrite;
6046
6136
  acc.output += add.output;
6047
6137
  }
6048
- function codexUsageFromBuckets(b2) {
6049
- return usageFromBuckets(b2);
6138
+ function codexRunUsage(usageByTurn, runTurnIds) {
6139
+ const usage = { input: 0, cacheRead: 0, cacheWrite: 0, output: 0 };
6140
+ let sawUsage = false;
6141
+ for (const entry of usageByTurn) {
6142
+ if (entry.turnId !== void 0 && !runTurnIds.has(entry.turnId)) continue;
6143
+ addCodexBuckets(usage, entry.buckets);
6144
+ sawUsage = true;
6145
+ }
6146
+ return sawUsage ? usageFromBuckets(usage) : void 0;
6050
6147
  }
6051
6148
  function parseCodexSessionId(lines) {
6052
6149
  const first = lines[0];
@@ -6092,30 +6189,16 @@ function parseCodexTokenUsage(lines, sinceMs) {
6092
6189
  let sawWindowed = false;
6093
6190
  let sawTimestamp = false;
6094
6191
  for (const line2 of lines) {
6095
- if (!line2 || line2.indexOf("token_count") === -1) continue;
6096
- let o;
6097
- try {
6098
- o = JSON.parse(line2);
6099
- } catch {
6100
- continue;
6101
- }
6102
- if (o?.type !== "event_msg" || o.payload?.type !== "token_count") continue;
6103
- const info = o.payload.info;
6104
- if (!info) continue;
6105
- const total = bucketsOf(info.total_token_usage);
6106
- if (total) lastTotal = total;
6107
- const turn = bucketsOf(info.last_token_usage);
6108
- if (turn) lastTurn = turn;
6192
+ const row = readCodexTokenCountLine(line2);
6193
+ if (!row) continue;
6194
+ if (row.total) lastTotal = row.total;
6195
+ if (row.turn) lastTurn = row.turn;
6109
6196
  if (sinceMs === void 0) continue;
6110
- const ts3 = typeof o.timestamp === "string" ? Date.parse(o.timestamp) : Number.NaN;
6111
- if (!Number.isFinite(ts3)) continue;
6197
+ if (!Number.isFinite(row.ts)) continue;
6112
6198
  sawTimestamp = true;
6113
- if (ts3 < sinceMs || !turn) continue;
6199
+ if (row.ts < sinceMs || !row.turn) continue;
6114
6200
  sawWindowed = true;
6115
- windowed.input += turn.input;
6116
- windowed.cacheRead += turn.cacheRead;
6117
- windowed.cacheWrite += turn.cacheWrite;
6118
- windowed.output += turn.output;
6201
+ addCodexBuckets(windowed, row.turn);
6119
6202
  }
6120
6203
  if (sinceMs !== void 0 && sawTimestamp) {
6121
6204
  return sawWindowed ? usageFromBuckets(windowed) : void 0;
@@ -6123,6 +6206,25 @@ function parseCodexTokenUsage(lines, sinceMs) {
6123
6206
  if (sinceMs !== void 0 && lastTurn) return usageFromBuckets(lastTurn);
6124
6207
  return lastTotal ? usageFromBuckets(lastTotal) : void 0;
6125
6208
  }
6209
+ function readCodexTokenCountLine(line2) {
6210
+ if (!line2 || line2.indexOf("token_count") === -1) return void 0;
6211
+ let o;
6212
+ try {
6213
+ o = JSON.parse(line2);
6214
+ } catch {
6215
+ return void 0;
6216
+ }
6217
+ if (o?.type !== "event_msg" || o.payload?.type !== "token_count") return void 0;
6218
+ const info = o.payload.info;
6219
+ if (!info) return void 0;
6220
+ const total = bucketsOf(info.total_token_usage);
6221
+ const turn = bucketsOf(info.last_token_usage);
6222
+ return {
6223
+ ts: typeof o.timestamp === "string" ? Date.parse(o.timestamp) : Number.NaN,
6224
+ ...turn ? { turn } : {},
6225
+ ...total ? { total } : {}
6226
+ };
6227
+ }
6126
6228
  function parseCodexModel(lines) {
6127
6229
  let model;
6128
6230
  for (const line2 of lines) {
@@ -6210,46 +6312,47 @@ function telemetryFromRolloutLines(lines, sinceMs) {
6210
6312
  }
6211
6313
  function scanCodexTelemetry(workdir, sinceMs, sessionsRoot = codexSessionsRoot(), preferSessionId) {
6212
6314
  try {
6213
- const files = listRecentRollouts(sessionsRoot, sinceMs);
6214
- const readLines = (f2) => {
6215
- try {
6216
- return fs8.readFileSync(f2, "utf8").split("\n");
6217
- } catch {
6218
- return null;
6219
- }
6220
- };
6315
+ const found2 = locateCodexRollout(workdir, sinceMs, sessionsRoot, preferSessionId);
6316
+ if (found2) return telemetryFromRolloutLines(found2.lines, sinceMs);
6317
+ } catch {
6318
+ }
6319
+ return {};
6320
+ }
6321
+ function locateCodexRollout(workdir, sinceMs, sessionsRoot = codexSessionsRoot(), preferSessionId) {
6322
+ const files = listRecentRollouts(sessionsRoot, sinceMs);
6323
+ const readLines = (f2) => {
6324
+ try {
6325
+ return fs8.readFileSync(f2, "utf8").split("\n");
6326
+ } catch {
6327
+ return null;
6328
+ }
6329
+ };
6330
+ for (const f2 of files) {
6331
+ const lines = readLines(f2);
6332
+ if (!lines) continue;
6333
+ let meta;
6334
+ try {
6335
+ meta = JSON.parse(lines[0] ?? "");
6336
+ } catch {
6337
+ continue;
6338
+ }
6339
+ if (meta?.type === "session_meta" && meta.payload?.cwd === workdir) return { file: f2, lines };
6340
+ }
6341
+ if (preferSessionId) {
6342
+ const suffix = `-${preferSessionId}.jsonl`;
6221
6343
  for (const f2 of files) {
6344
+ const byName = f2.endsWith(suffix);
6222
6345
  const lines = readLines(f2);
6223
6346
  if (!lines) continue;
6224
- let meta;
6225
- try {
6226
- meta = JSON.parse(lines[0] ?? "");
6227
- } catch {
6228
- continue;
6229
- }
6230
- if (meta?.type === "session_meta" && meta.payload?.cwd === workdir) {
6231
- return telemetryFromRolloutLines(lines, sinceMs);
6232
- }
6347
+ const sid = parseCodexSessionId(lines);
6348
+ if (byName || sid === preferSessionId) return { file: f2, lines };
6233
6349
  }
6234
- if (preferSessionId) {
6235
- const suffix = `-${preferSessionId}.jsonl`;
6236
- for (const f2 of files) {
6237
- const byName = f2.endsWith(suffix);
6238
- const lines = readLines(f2);
6239
- if (!lines) continue;
6240
- const sid = parseCodexSessionId(lines);
6241
- if (byName || sid === preferSessionId) {
6242
- return telemetryFromRolloutLines(lines, sinceMs);
6243
- }
6244
- }
6245
- for (const f2 of findRolloutsBySessionId(sessionsRoot, preferSessionId)) {
6246
- const lines = readLines(f2);
6247
- if (lines) return telemetryFromRolloutLines(lines, sinceMs);
6248
- }
6350
+ for (const f2 of findRolloutsBySessionId(sessionsRoot, preferSessionId)) {
6351
+ const lines = readLines(f2);
6352
+ if (lines) return { file: f2, lines };
6249
6353
  }
6250
- } catch {
6251
6354
  }
6252
- return {};
6355
+ return void 0;
6253
6356
  }
6254
6357
  function createCodexNormalizeState() {
6255
6358
  return {
@@ -6465,7 +6568,7 @@ function codexTurnErrorMessage(value2) {
6465
6568
  const detail = typeof error2?.additionalDetails === "string" ? error2.additionalDetails.trim() : "";
6466
6569
  return [summary, detail].filter(Boolean).join("\n").slice(0, 4e3);
6467
6570
  }
6468
- var import_node_child_process7, import_node_crypto9, fs8, os5, path10, readline2, CODEX_BLOCKED_FLAGS, CODEX_ARGV_PROMPT_MAX_BYTES, CODEX_APP_SERVER_BLOCKED_FLAGS, CodexAdapter;
6571
+ var import_node_child_process7, import_node_crypto9, fs8, os5, path10, readline2, CODEX_BLOCKED_FLAGS, CODEX_ARGV_PROMPT_MAX_BYTES, CodexRolloutUsageTail, CODEX_APP_SERVER_BLOCKED_FLAGS, CodexAdapter;
6469
6572
  var init_codex = __esm({
6470
6573
  "../adapters/src/codex/index.ts"() {
6471
6574
  "use strict";
@@ -6503,6 +6606,46 @@ var init_codex = __esm({
6503
6606
  // Multica 实证:codex --listen stdio:// 是 daemon↔CLI 传输协议;改会断链
6504
6607
  ]);
6505
6608
  CODEX_ARGV_PROMPT_MAX_BYTES = 1e5;
6609
+ CodexRolloutUsageTail = class {
6610
+ constructor(file, sinceMs) {
6611
+ this.file = file;
6612
+ this.sinceMs = sinceMs;
6613
+ }
6614
+ offset = 0;
6615
+ rest = "";
6616
+ acc = { input: 0, cacheRead: 0, cacheWrite: 0, output: 0 };
6617
+ saw = false;
6618
+ /** 读新追加的行,返回当前窗内累计;还没有任何窗内轮次返回 undefined。读失败抛给调用方(调用方吞)。 */
6619
+ poll() {
6620
+ const fd = fs8.openSync(this.file, "r");
6621
+ try {
6622
+ const size = fs8.fstatSync(fd).size;
6623
+ if (size < this.offset) {
6624
+ this.offset = 0;
6625
+ this.rest = "";
6626
+ this.saw = false;
6627
+ this.acc.input = this.acc.cacheRead = this.acc.cacheWrite = this.acc.output = 0;
6628
+ }
6629
+ if (size > this.offset) {
6630
+ const buf = Buffer.alloc(size - this.offset);
6631
+ const n = fs8.readSync(fd, buf, 0, buf.length, this.offset);
6632
+ this.offset += n;
6633
+ const text6 = this.rest + buf.subarray(0, n).toString("utf8");
6634
+ const lines = text6.split("\n");
6635
+ this.rest = lines.pop() ?? "";
6636
+ for (const line2 of lines) {
6637
+ const row = readCodexTokenCountLine(line2);
6638
+ if (!row?.turn || !Number.isFinite(row.ts) || row.ts < this.sinceMs) continue;
6639
+ addCodexBuckets(this.acc, row.turn);
6640
+ this.saw = true;
6641
+ }
6642
+ }
6643
+ } finally {
6644
+ fs8.closeSync(fd);
6645
+ }
6646
+ return this.saw ? usageFromBuckets(this.acc) : void 0;
6647
+ }
6648
+ };
6506
6649
  CODEX_APP_SERVER_BLOCKED_FLAGS = /* @__PURE__ */ new Map([
6507
6650
  ["app-server", "boolean"],
6508
6651
  ["--stdio", "boolean"],
@@ -6713,18 +6856,21 @@ ${task}` : task;
6713
6856
  }
6714
6857
  }
6715
6858
  model ??= state.threadModel ?? resolvedModel2;
6716
- const usage = { input: 0, cacheRead: 0, cacheWrite: 0, output: 0 };
6717
- let sawUsage = false;
6718
- for (const entry of state.usageByTurn) {
6719
- if (entry.turnId !== void 0 && !state.runTurnIds.has(entry.turnId)) continue;
6720
- addCodexBuckets(usage, entry.buckets);
6721
- sawUsage = true;
6722
- }
6859
+ const usage = codexRunUsage(state.usageByTurn, state.runTurnIds);
6723
6860
  return {
6724
- ...sawUsage ? { usage: codexUsageFromBuckets(usage) } : {},
6861
+ ...usage ? { usage } : {},
6725
6862
  ...model ? { model } : {}
6726
6863
  };
6727
6864
  },
6865
+ // 运行中净累计(ADR usage-statistics-ledger D2):与上面终值**同一个函数**算——同一套「只算本次
6866
+ // run 发起的轮次」过滤、同一套累加,所以检查点永远 ≤ 终值、不会因为口径差推出负的段。
6867
+ // 重放的上一轮通知先到、本轮 turnId 后才登记时,这一拍先不计它,登记后的下一拍补上(只增不减)。
6868
+ runningUsage: (state) => {
6869
+ const usage = codexRunUsage(state.usageByTurn, state.runTurnIds);
6870
+ if (!usage) return void 0;
6871
+ const model = state.threadModel ?? resolvedModel2;
6872
+ return { usage, ...model ? { model } : {} };
6873
+ },
6728
6874
  async append(input, state, send) {
6729
6875
  if (!state.threadId || !state.turnId || !state.active) return { accepted: false, reason: "session-closing" };
6730
6876
  if (input.interrupt) {
@@ -6935,8 +7081,39 @@ ${task}` : task;
6935
7081
  const callbacks = [];
6936
7082
  let exited;
6937
7083
  let killReason = null;
7084
+ const usageCheckpointCbs = [];
7085
+ let usageTail;
7086
+ let usagePoll = null;
7087
+ let lastUsageKey = "";
7088
+ let locateAttemptsLeft = 8;
7089
+ const pollRolloutUsage = () => {
7090
+ if (exited || !usageCheckpointCbs.length) return;
7091
+ try {
7092
+ if (!usageTail) {
7093
+ if (locateAttemptsLeft <= 0) return;
7094
+ locateAttemptsLeft--;
7095
+ const found2 = locateCodexRollout(dir, startedAtMs, codexSessionsRoot(), job.runtimeSessionId);
7096
+ if (!found2) return;
7097
+ usageTail = new CodexRolloutUsageTail(found2.file, startedAtMs);
7098
+ }
7099
+ const usage = usageTail.poll();
7100
+ const key2 = usage ? JSON.stringify(usage) : "";
7101
+ if (!usage || key2 === lastUsageKey) return;
7102
+ lastUsageKey = key2;
7103
+ const model = job.model ?? this.opts.model;
7104
+ for (const cb of usageCheckpointCbs) cb({ usage, ...model ? { model } : {} });
7105
+ } catch {
7106
+ }
7107
+ };
7108
+ const stopUsagePoll = () => {
7109
+ if (usagePoll) {
7110
+ clearInterval(usagePoll);
7111
+ usagePoll = null;
7112
+ }
7113
+ };
6938
7114
  const finish = (info) => {
6939
7115
  if (exited) return;
7116
+ stopUsagePoll();
6940
7117
  if (job.workdirKey) {
6941
7118
  unlockWorkdir(dir);
6942
7119
  touchMetaExit(dir, { at: (/* @__PURE__ */ new Date()).toISOString(), ...info.reason ? { reason: info.reason } : {}, runId: id });
@@ -7017,6 +7194,14 @@ ${task}` : task;
7017
7194
  },
7018
7195
  onTelemetry(cb) {
7019
7196
  telemetryCbs.push(cb);
7197
+ },
7198
+ onUsageCheckpoint: (cb) => {
7199
+ usageCheckpointCbs.push(cb);
7200
+ const pollMs = this.opts.usagePollMs ?? 15e3;
7201
+ if (!usagePoll && !exited && pollMs > 0) {
7202
+ usagePoll = setInterval(pollRolloutUsage, pollMs);
7203
+ usagePoll.unref?.();
7204
+ }
7020
7205
  }
7021
7206
  };
7022
7207
  }
@@ -136609,11 +136794,11 @@ function headRejected(model, id) {
136609
136794
  function pinnedReviewerOf(model, artifactId, role) {
136610
136795
  let best = null;
136611
136796
  for (const attempt of model.concludeAttempts.get(artifactId) ?? []) {
136612
- const bucket = attempt.gate?.requirements.find(
136797
+ const bucket2 = attempt.gate?.requirements.find(
136613
136798
  (r) => r.source === "type" && (r.roles ?? []).includes(role)
136614
136799
  );
136615
- if (!bucket) continue;
136616
- const eligible = new Set(bucket.eligible);
136800
+ if (!bucket2) continue;
136801
+ const eligible = new Set(bucket2.eligible);
136617
136802
  for (const rev of revisionsOf(model, artifactId)) {
136618
136803
  for (const v2 of model.reviews.get(rev.id) ?? []) {
136619
136804
  if (v2.seq <= attempt.seq) continue;
@@ -143140,9 +143325,9 @@ function groupRequirementsForPreview(rows) {
143140
143325
  const groups = /* @__PURE__ */ new Map();
143141
143326
  for (const r of rows) {
143142
143327
  const key2 = r.reviewGroup ?? (r.source === "manual" || r.source === "closure" ? r.actor : "default");
143143
- const bucket = groups.get(key2);
143144
- if (bucket) {
143145
- if (!bucket.eligible.includes(r.actor)) bucket.eligible.push(r.actor);
143328
+ const bucket2 = groups.get(key2);
143329
+ if (bucket2) {
143330
+ if (!bucket2.eligible.includes(r.actor)) bucket2.eligible.push(r.actor);
143146
143331
  } else {
143147
143332
  groups.set(key2, { source: r.source, eligible: [r.actor] });
143148
143333
  }
@@ -214031,8 +214216,8 @@ var init_memory_trace_store = __esm({
214031
214216
  cost
214032
214217
  );
214033
214218
  }
214034
- accumulateRow(actorId, instanceId, runtimeKind, model, bucket, granularity, input, output, total, cacheRead, cacheCreation, cost) {
214035
- const key2 = `${actorId}|${instanceId ?? ""}|${model ?? ""}|${bucket}|${granularity}`;
214219
+ accumulateRow(actorId, instanceId, runtimeKind, model, bucket2, granularity, input, output, total, cacheRead, cacheCreation, cost) {
214220
+ const key2 = `${actorId}|${instanceId ?? ""}|${model ?? ""}|${bucket2}|${granularity}`;
214036
214221
  const existing = this.usageAggregates.get(key2);
214037
214222
  if (existing) {
214038
214223
  existing.runCount += 1;
@@ -214048,7 +214233,7 @@ var init_memory_trace_store = __esm({
214048
214233
  runtimeInstanceId: instanceId,
214049
214234
  runtimeKind,
214050
214235
  effectiveModel: model,
214051
- bucket,
214236
+ bucket: bucket2,
214052
214237
  granularity,
214053
214238
  runCount: 1,
214054
214239
  inputTokens: input,
@@ -233099,9 +233284,9 @@ function buildOrganizationUsageSummary(input) {
233099
233284
  addUsage(total, usage);
233100
233285
  const key2 = bucketKey(formatter, run.startedAt, input.bucketKind);
233101
233286
  if (key2) {
233102
- const bucket = buckets.get(key2) ?? { key: key2, ...emptyUsage() };
233103
- addUsage(bucket, usage);
233104
- buckets.set(key2, bucket);
233287
+ const bucket2 = buckets.get(key2) ?? { key: key2, ...emptyUsage() };
233288
+ addUsage(bucket2, usage);
233289
+ buckets.set(key2, bucket2);
233105
233290
  }
233106
233291
  const workspace = run.artifactId ? workspaceByArtifact.get(run.artifactId) : void 0;
233107
233292
  const workorder = workspace ? workorderById.get(workspace) : void 0;
@@ -233703,9 +233888,9 @@ function buildUsageOverview(input) {
233703
233888
  for (let i = a; i <= b2 && i < partial2.length; i += 1) partial2[i] = true;
233704
233889
  }
233705
233890
  }
233706
- const trend = input.resolved.buckets.map((bucket, i) => ({
233707
- start: bucket.start,
233708
- end: bucket.end,
233891
+ const trend = input.resolved.buckets.map((bucket2, i) => ({
233892
+ start: bucket2.start,
233893
+ end: bucket2.end,
233709
233894
  amount: trendAcc[i].toAmount(),
233710
233895
  partial: partial2[i]
233711
233896
  }));
@@ -234788,9 +234973,9 @@ function collabDomain(opts) {
234788
234973
  }
234789
234974
  const from = req.query.get("from");
234790
234975
  const to = req.query.get("to");
234791
- const bucket = req.query.get("bucket");
234976
+ const bucket2 = req.query.get("bucket");
234792
234977
  const timeZone = req.query.get("timeZone") ?? "UTC";
234793
- if (!from || !to || bucket !== "hour" && bucket !== "day") {
234978
+ if (!from || !to || bucket2 !== "hour" && bucket2 !== "day") {
234794
234979
  return { status: 400, body: { error: { code: "bad_request", message: "from / to / bucket(hour|day) \u5FC5\u586B" } } };
234795
234980
  }
234796
234981
  const fromMs = Date.parse(from);
@@ -234821,7 +235006,7 @@ function collabDomain(opts) {
234821
235006
  }
234822
235007
  return {
234823
235008
  status: 200,
234824
- body: buildOrganizationUsageSummary({ model: kernel.model, runs, bucketKind: bucket, timeZone, runtimeHostnames, runtimeNodeNames })
235009
+ body: buildOrganizationUsageSummary({ model: kernel.model, runs, bucketKind: bucket2, timeZone, runtimeHostnames, runtimeNodeNames })
234825
235010
  };
234826
235011
  });
234827
235012
  const usageCompanyOf = (req) => req.auth.companyId ?? opts.defaultCompanyId;
@@ -237998,10 +238183,10 @@ function runtimeUsageBucket(startedAt, granularity) {
237998
238183
  function bucketRuntimeRuns(runtimeInstanceId, runs, granularity) {
237999
238184
  const rows = /* @__PURE__ */ new Map();
238000
238185
  for (const run of runs) {
238001
- const bucket = runtimeUsageBucket(run.startedAt, granularity);
238002
- if (!bucket) continue;
238186
+ const bucket2 = runtimeUsageBucket(run.startedAt, granularity);
238187
+ if (!bucket2) continue;
238003
238188
  const model = resolvedModel(run.effectiveModel);
238004
- const key2 = `${bucket}\0${run.actorId}\0${model ?? ""}`;
238189
+ const key2 = `${bucket2}\0${run.actorId}\0${model ?? ""}`;
238005
238190
  let row = rows.get(key2);
238006
238191
  if (!row) {
238007
238192
  row = {
@@ -238009,7 +238194,7 @@ function bucketRuntimeRuns(runtimeInstanceId, runs, granularity) {
238009
238194
  runtimeInstanceId,
238010
238195
  runtimeKind: run.runtimeKind,
238011
238196
  effectiveModel: model,
238012
- bucket,
238197
+ bucket: bucket2,
238013
238198
  runCount: 0,
238014
238199
  inputTokens: 0,
238015
238200
  outputTokens: 0,
@@ -238078,9 +238263,9 @@ function runtimeUsageFromLedger(runtimeInstanceId, slice) {
238078
238263
  const rows = /* @__PURE__ */ new Map();
238079
238264
  const runById = new Map(slice.runs.map((r) => [r.id, r]));
238080
238265
  const rowOf = (bucketIndex2, run) => {
238081
- const bucket = bucketLabelOf(slice, bucketIndex2);
238266
+ const bucket2 = bucketLabelOf(slice, bucketIndex2);
238082
238267
  const model = resolvedModel(run.effectiveModel);
238083
- const key2 = `${bucket}\0${run.actorId}\0${model ?? ""}`;
238268
+ const key2 = `${bucket2}\0${run.actorId}\0${model ?? ""}`;
238084
238269
  let row = rows.get(key2);
238085
238270
  if (!row) {
238086
238271
  row = {
@@ -238088,7 +238273,7 @@ function runtimeUsageFromLedger(runtimeInstanceId, slice) {
238088
238273
  runtimeInstanceId,
238089
238274
  runtimeKind: run.runtimeKind,
238090
238275
  effectiveModel: model,
238091
- bucket,
238276
+ bucket: bucket2,
238092
238277
  runCount: 0,
238093
238278
  inputTokens: 0,
238094
238279
  outputTokens: 0,
@@ -267494,15 +267679,15 @@ async function deadlineClockTick(deps, dedupe3) {
267494
267679
  const overdue = deps.now - deadline;
267495
267680
  if (overdue > result.oldestDueDelayMs) result.oldestDueDelayMs = overdue;
267496
267681
  const phase = overdue >= 0 ? "due" : "early";
267497
- const bucket = `${c.workId}@${deadline}@${phase}`;
267498
- if (dedupe3.has(c.workorderId, bucket)) {
267682
+ const bucket2 = `${c.workId}@${deadline}@${phase}`;
267683
+ if (dedupe3.has(c.workorderId, bucket2)) {
267499
267684
  result.deduped++;
267500
267685
  continue;
267501
267686
  }
267502
267687
  const buckets = toPing.get(c.workorderId) ?? [];
267503
- buckets.push(bucket);
267688
+ buckets.push(bucket2);
267504
267689
  toPing.set(c.workorderId, buckets);
267505
- dedupe3.mark(c.workorderId, bucket);
267690
+ dedupe3.mark(c.workorderId, bucket2);
267506
267691
  }
267507
267692
  if (page.nextCursor) result.backlog = toPing.size + result.deduped;
267508
267693
  for (const [workorderId, buckets] of toPing) {
@@ -274788,8 +274973,8 @@ async function startServe(opts) {
274788
274973
  const live = engineRouter.liveEntries().find((x2) => x2.engine.kernel.model.artifacts.has(artifactId));
274789
274974
  const engine2 = live?.engine ?? await getEngine(defaultCompanyId);
274790
274975
  if (!engine2.kernel.model.artifacts.has(artifactId)) continue;
274791
- const bucket = byEngine.get(engine2);
274792
- if (bucket) bucket.push(artifactId);
274976
+ const bucket2 = byEngine.get(engine2);
274977
+ if (bucket2) bucket2.push(artifactId);
274793
274978
  else byEngine.set(engine2, [artifactId]);
274794
274979
  }
274795
274980
  for (const [engine2, ids2] of byEngine) {
@@ -277295,6 +277480,108 @@ function isSessionLocked(lockPath) {
277295
277480
  init_src();
277296
277481
  init_src2();
277297
277482
  init_src8();
277483
+
277484
+ // ../cli/src/daemon/usage-checkpoints.ts
277485
+ var USAGE_CHECKPOINT_MIN_INTERVAL_MS = 3e4;
277486
+ function bucket(value2) {
277487
+ return typeof value2 === "number" && Number.isFinite(value2) ? value2 : null;
277488
+ }
277489
+ function maxBucket(a, b2) {
277490
+ const x2 = bucket(a);
277491
+ const y = bucket(b2);
277492
+ if (x2 === null) return y;
277493
+ if (y === null) return x2;
277494
+ return Math.max(x2, y);
277495
+ }
277496
+ function mergeMonotonicUsage(prev, next) {
277497
+ if (!prev) return next;
277498
+ const inputTokens = maxBucket(prev.inputTokens, next.inputTokens);
277499
+ const outputTokens = maxBucket(prev.outputTokens, next.outputTokens);
277500
+ return {
277501
+ inputTokens,
277502
+ outputTokens,
277503
+ totalTokens: inputTokens === null && outputTokens === null ? null : (inputTokens ?? 0) + (outputTokens ?? 0),
277504
+ cacheReadTokens: maxBucket(prev.cacheReadTokens, next.cacheReadTokens),
277505
+ cacheCreationTokens: maxBucket(prev.cacheCreationTokens, next.cacheCreationTokens),
277506
+ costUsdMicros: maxBucket(prev.costUsdMicros, next.costUsdMicros)
277507
+ };
277508
+ }
277509
+ var UsageCheckpointEmitter = class {
277510
+ constructor(deps) {
277511
+ this.deps = deps;
277512
+ this.minIntervalMs = deps.minIntervalMs ?? USAGE_CHECKPOINT_MIN_INTERVAL_MS;
277513
+ this.now = deps.now ?? Date.now;
277514
+ }
277515
+ usageSeq = 0;
277516
+ latest = null;
277517
+ lastSentKey = "";
277518
+ lastSentAt = Number.NEGATIVE_INFINITY;
277519
+ timer = null;
277520
+ closed = false;
277521
+ minIntervalMs;
277522
+ now;
277523
+ /** adapter 报来一次累计值。observedAt 取报来的这一刻——窗口末尾才发出去时,时刻仍是它被观测到的那一刻。 */
277524
+ observe(checkpoint) {
277525
+ if (this.closed) return;
277526
+ const usage = mergeMonotonicUsage(this.latest?.usage ?? null, checkpoint.usage);
277527
+ const model = checkpoint.model ?? this.latest?.model;
277528
+ const changed = JSON.stringify(usage) !== JSON.stringify(this.latest?.usage ?? null);
277529
+ if (!changed && model === this.latest?.model) return;
277530
+ this.latest = { usage, ...model ? { model } : {}, observedAt: changed ? this.now() : this.latest.observedAt };
277531
+ this.pump();
277532
+ }
277533
+ /** 退出前补发:还有没发出去的最新值就立刻发(不受节流),之后本 run 不再发任何检查点。 */
277534
+ flush() {
277535
+ if (this.closed) return;
277536
+ this.clearTimer();
277537
+ if (this.hasUnsent() && this.deps.accepts()) this.emit();
277538
+ this.closed = true;
277539
+ }
277540
+ /** 已发出的检查点帧数(观测/测试用)。 */
277541
+ get sent() {
277542
+ return this.usageSeq;
277543
+ }
277544
+ hasUnsent() {
277545
+ return this.latest !== null && JSON.stringify(this.latest.usage) !== this.lastSentKey;
277546
+ }
277547
+ pump() {
277548
+ if (this.closed || !this.hasUnsent() || !this.deps.accepts()) return;
277549
+ const wait = this.lastSentAt + this.minIntervalMs - this.now();
277550
+ if (wait <= 0) {
277551
+ this.clearTimer();
277552
+ this.emit();
277553
+ return;
277554
+ }
277555
+ if (this.timer) return;
277556
+ this.timer = setTimeout(() => {
277557
+ this.timer = null;
277558
+ this.pump();
277559
+ }, wait);
277560
+ this.timer.unref?.();
277561
+ }
277562
+ emit() {
277563
+ const latest = this.latest;
277564
+ const frame = {
277565
+ type: "session_usage",
277566
+ dispatchId: this.deps.dispatchId,
277567
+ usageSeq: ++this.usageSeq,
277568
+ observedAt: new Date(latest.observedAt).toISOString(),
277569
+ usage: latest.usage,
277570
+ ...latest.model ? { model: latest.model } : {}
277571
+ };
277572
+ this.lastSentKey = JSON.stringify(latest.usage);
277573
+ this.lastSentAt = this.now();
277574
+ this.deps.send(frame);
277575
+ }
277576
+ clearTimer() {
277577
+ if (this.timer) {
277578
+ clearTimeout(this.timer);
277579
+ this.timer = null;
277580
+ }
277581
+ }
277582
+ };
277583
+
277584
+ // ../cli/src/daemon/session-runner.ts
277298
277585
  async function preflightOasisAccess(job) {
277299
277586
  const base = job.server.url.replace(/\/+$/, "");
277300
277587
  try {
@@ -277351,12 +277638,21 @@ async function runSession(dispatchId, job, deps) {
277351
277638
  deps.sink.stream({ type: "session_live_event", dispatchId, event });
277352
277639
  normalizer.onLiveEvent(event);
277353
277640
  });
277641
+ const acceptsUsageCheckpoints = deps.sink.acceptsUsageCheckpoints?.bind(deps.sink);
277642
+ const usageCheckpoints = acceptsUsageCheckpoints && handle.onUsageCheckpoint ? new UsageCheckpointEmitter({
277643
+ dispatchId,
277644
+ accepts: acceptsUsageCheckpoints,
277645
+ send: (frame) => deps.sink.stream(frame),
277646
+ ...deps.usageCheckpointIntervalMs !== void 0 ? { minIntervalMs: deps.usageCheckpointIntervalMs } : {}
277647
+ }) : null;
277648
+ if (usageCheckpoints) handle.onUsageCheckpoint((checkpoint) => usageCheckpoints.observe(checkpoint));
277354
277649
  let restoreFailedBeforeStart = false;
277355
277650
  handle.onExit((info) => {
277356
277651
  if (info.fileRestoreError) restoreFailedBeforeStart = true;
277357
277652
  normalizer.turnFinished(isHealthySessionExit(info) ? "completed" : "failed");
277358
277653
  log2("[node-cli]", ` \u25A0 session_exited id=${handle.id} code=${info.code ?? "killed"} total=${Date.now() - t0}ms`);
277359
277654
  if (info.transcriptRef) log2("[node-cli]", ` transcript: ${info.transcriptRef}`);
277655
+ usageCheckpoints?.flush();
277360
277656
  deps.sink.keyFrame({ type: "session_exited", dispatchId, sessionId: handle.id, info });
277361
277657
  deps.onExited?.();
277362
277658
  });
@@ -277459,6 +277755,11 @@ var SessionProcessState = class {
277459
277755
  frameSeq = 0;
277460
277756
  /** 收到过带 `ackSeq` 的 ack = 本服务端会按帧号去重;只有它为真,重连才敢重放**全部**帧(含输出)。 */
277461
277757
  serverSupportsDedup = false;
277758
+ /**
277759
+ * 当前这根连接上的服务端 ping 声明过 `acceptsUsageCheckpoints`(ADR usage-statistics-ledger D2)。
277760
+ * **按连接记**:连上/断开都清零,等这根连接上的下一个 ping 再说——重连到的可能是没升级的服务端。
277761
+ */
277762
+ serverAcceptsUsageCheckpoints = false;
277462
277763
  /** append_input 串行链——保证回帧次序 = 到达次序(server 侧按 FIFO 认领等待者)。 */
277463
277764
  appendChain = Promise.resolve();
277464
277765
  async run() {
@@ -277472,8 +277773,10 @@ var SessionProcessState = class {
277472
277773
  preflight: this.spec.preflight,
277473
277774
  sink: {
277474
277775
  keyFrame: (m2) => this.sendKeyFrame(m2),
277475
- stream: (m2) => this.sendStream(m2)
277776
+ stream: (m2) => this.sendStream(m2),
277777
+ acceptsUsageCheckpoints: () => this.connected && this.serverAcceptsUsageCheckpoints
277476
277778
  },
277779
+ ...this.spec.limits?.usageCheckpointIntervalMs !== void 0 ? { usageCheckpointIntervalMs: this.spec.limits.usageCheckpointIntervalMs } : {},
277477
277780
  onHandle: (h) => {
277478
277781
  this.handle = h;
277479
277782
  if (this.stopping) {
@@ -277513,6 +277816,7 @@ var SessionProcessState = class {
277513
277816
  this.ws = ws;
277514
277817
  ws.on("open", () => {
277515
277818
  this.connected = true;
277819
+ this.serverAcceptsUsageCheckpoints = false;
277516
277820
  this.unreachableSince = null;
277517
277821
  this.reconnectMs = RECONNECT_MIN_MS;
277518
277822
  log2("[session]", `${this.spec.dispatchId}: \u6570\u636E\u9762\u5DF2\u8FDE\u4E0A ${this.spec.auth.gatewayUrl}`);
@@ -277548,6 +277852,7 @@ var SessionProcessState = class {
277548
277852
  });
277549
277853
  ws.on("close", () => {
277550
277854
  this.connected = false;
277855
+ this.serverAcceptsUsageCheckpoints = false;
277551
277856
  this.unreachableSince ??= Date.now();
277552
277857
  if (this.stopping) return;
277553
277858
  setTimeout(() => this.connect(), this.reconnectMs).unref?.();
@@ -277594,6 +277899,7 @@ var SessionProcessState = class {
277594
277899
  if (this.outbox.length === 0) this.exitAckResolve?.();
277595
277900
  return;
277596
277901
  case "ping":
277902
+ this.serverAcceptsUsageCheckpoints = msg.acceptsUsageCheckpoints === true;
277597
277903
  this.rawSend({ type: "pong" });
277598
277904
  return;
277599
277905
  default:
@@ -277696,21 +278002,21 @@ var import_node_os9 = require("node:os");
277696
278002
  function object6(value2) {
277697
278003
  return value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : {};
277698
278004
  }
277699
- function window2(bucket, minutes, used, reset) {
278005
+ function window2(bucket2, minutes, used, reset) {
277700
278006
  if (typeof minutes !== "number" || !Number.isFinite(minutes) || minutes <= 0 || typeof used !== "number" || !Number.isFinite(used) || used < 0 || used > 100) return [];
277701
278007
  const ms = typeof reset === "number" ? reset * 1e3 : typeof reset === "string" ? Date.parse(reset) : NaN;
277702
278008
  const resetsAt = Number.isFinite(ms) && Math.abs(ms) < 864e13 ? new Date(ms).toISOString() : void 0;
277703
- return [{ bucket, windowMinutes: minutes, usedPercent: used, ...resetsAt ? { resetsAt } : {} }];
278009
+ return [{ bucket: bucket2, windowMinutes: minutes, usedPercent: used, ...resetsAt ? { resetsAt } : {} }];
277704
278010
  }
277705
278011
  function parseCodexQuota(value2) {
277706
278012
  const response = object6(value2);
277707
278013
  const buckets = response.rateLimitsByLimitId !== null && response.rateLimitsByLimitId !== void 0 ? object6(response.rateLimitsByLimitId) : { codex: response.rateLimits };
277708
- return Object.entries(buckets).slice(0, 16).flatMap(([bucket, raw]) => {
277709
- if (!/^[a-zA-Z0-9_.-]{1,80}$/.test(bucket)) return [];
278014
+ return Object.entries(buckets).slice(0, 16).flatMap(([bucket2, raw]) => {
278015
+ if (!/^[a-zA-Z0-9_.-]{1,80}$/.test(bucket2)) return [];
277710
278016
  const limits = object6(raw);
277711
278017
  return [limits.primary, limits.secondary].flatMap((v2) => {
277712
278018
  const w2 = object6(v2);
277713
- return window2(bucket, w2.windowDurationMins, w2.usedPercent, w2.resetsAt);
278019
+ return window2(bucket2, w2.windowDurationMins, w2.usedPercent, w2.resetsAt);
277714
278020
  });
277715
278021
  });
277716
278022
  }
@@ -278508,6 +278814,12 @@ var DaemonWsClient = class {
278508
278814
  this.stop();
278509
278815
  }
278510
278816
  serverSupportsChunkedMessages = false;
278817
+ /**
278818
+ * 当前控制面连接上的服务端 ping 声明过 `acceptsUsageCheckpoints`(ADR usage-statistics-ledger D2)。
278819
+ * 与 serverSupportsChunkedMessages 同口径:按连接记,新连接清零、等它自己的 ping。
278820
+ * 只影响本进程内跑的会话(没有 sessionAuth 的回落路径);独立会话进程看它自己那根连接。
278821
+ */
278822
+ serverAcceptsUsageCheckpoints = false;
278511
278823
  connect() {
278512
278824
  if (this.stopped) return;
278513
278825
  const ws = new import_websocket.default(this.serverUrl, {
@@ -278522,6 +278834,7 @@ var DaemonWsClient = class {
278522
278834
  });
278523
278835
  this.ws = ws;
278524
278836
  this.serverSupportsChunkedMessages = false;
278837
+ this.serverAcceptsUsageCheckpoints = false;
278525
278838
  ws.on("open", () => {
278526
278839
  log2("[node-cli]", `connected id=${this.daemonId}`);
278527
278840
  this.authRejectStreak = 0;
@@ -278559,6 +278872,7 @@ var DaemonWsClient = class {
278559
278872
  clearInterval(this.pingTimer);
278560
278873
  this.pingTimer = null;
278561
278874
  }
278875
+ this.serverAcceptsUsageCheckpoints = false;
278562
278876
  if (this.stopped) return;
278563
278877
  const authRejected = this.lastErrorWasAuthReject;
278564
278878
  this.lastErrorWasAuthReject = false;
@@ -278624,7 +278938,8 @@ var DaemonWsClient = class {
278624
278938
  sink: {
278625
278939
  keyFrame: (m2) => this.sendKeyFrame(dispatchId, m2),
278626
278940
  // 流帧走 sendStream:断链期间有界暂存、重连补发(serve 重启窗口内的输出不再静默丢)。
278627
- stream: (m2) => this.sendStream(m2)
278941
+ stream: (m2) => this.sendStream(m2),
278942
+ acceptsUsageCheckpoints: () => this.ws?.readyState === import_websocket.default.OPEN && this.serverAcceptsUsageCheckpoints
278628
278943
  },
278629
278944
  onHandle: (handle) => {
278630
278945
  this.sessions.register(dispatchId, handle, {
@@ -278668,6 +278983,7 @@ var DaemonWsClient = class {
278668
278983
  }
278669
278984
  case "ping":
278670
278985
  this.serverSupportsChunkedMessages = msg.supportsChunkedMessages === true;
278986
+ this.serverAcceptsUsageCheckpoints = msg.acceptsUsageCheckpoints === true;
278671
278987
  this.send({ type: "pong" });
278672
278988
  break;
278673
278989
  case "ack":
@@ -282023,10 +282339,10 @@ async function runCli(argv, println = console.log, progressln = console.error) {
282023
282339
  const byLabel = items.filter((x2) => (x2.label ?? "").toLowerCase() === lower);
282024
282340
  const byId = items.filter((x2) => x2.id.startsWith(ref2) || x2.id.replace(/-/g, "").startsWith(ref2));
282025
282341
  const byExpert = items.filter((x2) => (x2.expertName ?? "").toLowerCase() === lower || x2.expertActorId === ref2 || x2.expertActorId.endsWith(`:${ref2}`));
282026
- for (const bucket of [byLabel, byId, byExpert]) {
282027
- if (bucket.length === 1) return bucket[0];
282028
- if (bucket.length > 1) {
282029
- const lines = ["`" + ref2 + "` \u649E\u5230\u591A\u4E2A\u59D4\u6D3E\uFF0C\u6311\u4E00\u4E2A\u66F4\u5177\u4F53\u7684\u91CD\u53D1\uFF08\u7528 label \u6216 id \u524D\u7F00\uFF09\uFF1A", ...bucket.map(describe)];
282342
+ for (const bucket2 of [byLabel, byId, byExpert]) {
282343
+ if (bucket2.length === 1) return bucket2[0];
282344
+ if (bucket2.length > 1) {
282345
+ const lines = ["`" + ref2 + "` \u649E\u5230\u591A\u4E2A\u59D4\u6D3E\uFF0C\u6311\u4E00\u4E2A\u66F4\u5177\u4F53\u7684\u91CD\u53D1\uFF08\u7528 label \u6216 id \u524D\u7F00\uFF09\uFF1A", ...bucket2.map(describe)];
282030
282346
  throw new Error(lines.join("\n"));
282031
282347
  }
282032
282348
  }
@@ -284918,7 +285234,7 @@ function shimScript() {
284918
285234
  }
284919
285235
 
284920
285236
  // src/index.ts
284921
- var PKG_VERSION = true ? "2.2.53" : "dev";
285237
+ var PKG_VERSION = true ? "2.2.54" : "dev";
284922
285238
  var LOCAL_BIN = localBin();
284923
285239
  var NPM_PREFIX = npmPrefix();
284924
285240
  var INSTANCE = DEFAULT_INSTANCE;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oasis_test_v2",
3
- "version": "2.2.53",
3
+ "version": "2.2.54",
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": "46614ef3a8da815b6d8cc5b25e93715780efec1c"
29
+ "sourceHead": "f63f447c49d3571103041e7a042fca92fe0ab371"
30
30
  }
31
31
  }