@clawos-dev/clawd 0.2.196 → 0.2.197-beta.396.cf8bb30

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/cli.cjs +190 -42
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -28978,7 +28978,7 @@ var require_websocket = __commonJS({
28978
28978
  var http3 = require("http");
28979
28979
  var net3 = require("net");
28980
28980
  var tls = require("tls");
28981
- var { randomBytes, createHash: createHash2 } = require("crypto");
28981
+ var { randomBytes, createHash: createHash3 } = require("crypto");
28982
28982
  var { Duplex, Readable: Readable3 } = require("stream");
28983
28983
  var { URL: URL2 } = require("url");
28984
28984
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -29638,7 +29638,7 @@ var require_websocket = __commonJS({
29638
29638
  abortHandshake(websocket, socket, "Invalid Upgrade header");
29639
29639
  return;
29640
29640
  }
29641
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
29641
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
29642
29642
  if (res.headers["sec-websocket-accept"] !== digest) {
29643
29643
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
29644
29644
  return;
@@ -30005,7 +30005,7 @@ var require_websocket_server = __commonJS({
30005
30005
  var EventEmitter3 = require("events");
30006
30006
  var http3 = require("http");
30007
30007
  var { Duplex } = require("stream");
30008
- var { createHash: createHash2 } = require("crypto");
30008
+ var { createHash: createHash3 } = require("crypto");
30009
30009
  var extension2 = require_extension();
30010
30010
  var PerMessageDeflate2 = require_permessage_deflate();
30011
30011
  var subprotocol2 = require_subprotocol();
@@ -30306,7 +30306,7 @@ var require_websocket_server = __commonJS({
30306
30306
  );
30307
30307
  }
30308
30308
  if (this._state > RUNNING) return abortHandshake(socket, 503);
30309
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
30309
+ const digest = createHash3("sha1").update(key + GUID).digest("base64");
30310
30310
  const headers = [
30311
30311
  "HTTP/1.1 101 Switching Protocols",
30312
30312
  "Upgrade: websocket",
@@ -40779,6 +40779,18 @@ function createLogger(opts = {}) {
40779
40779
  );
40780
40780
  return wrap(base);
40781
40781
  }
40782
+ function createFileOnlyLogger(opts) {
40783
+ const level = opts.level ?? "debug";
40784
+ try {
40785
+ import_node_fs2.default.mkdirSync(import_node_path2.default.dirname(opts.file), { recursive: true });
40786
+ } catch {
40787
+ }
40788
+ const base = (0, import_pino.default)(
40789
+ { level, base: {} },
40790
+ import_pino.default.destination({ dest: opts.file, mkdir: true, sync: true })
40791
+ );
40792
+ return wrap(base);
40793
+ }
40782
40794
  function pinoLevelToString(n) {
40783
40795
  if (typeof n !== "number") return null;
40784
40796
  if (n >= 50) return "error";
@@ -43286,6 +43298,14 @@ var SessionManager = class {
43286
43298
  routeFromRunner(frame, target) {
43287
43299
  const compressed = compressFrameForWire(frame);
43288
43300
  if (!compressed) return;
43301
+ if (compressed.type === "session:status") {
43302
+ const s = compressed;
43303
+ this.deps.screenIdleProbeLogger?.info("session:status wire emit", {
43304
+ sessionId: s.sessionId,
43305
+ status: s.status,
43306
+ target
43307
+ });
43308
+ }
43289
43309
  if (compressed.type === "session:event" || compressed.type === "session:status") {
43290
43310
  const sid = compressed.sessionId;
43291
43311
  if (sid) {
@@ -44291,12 +44311,24 @@ var SessionManager = class {
44291
44311
  const toolSessionId = runnerState.file.toolSessionId;
44292
44312
  const adapter = this.deps.getAdapter(runnerState.file.tool ?? "claude");
44293
44313
  const gateOpen = !adapter.canAcceptTurnEnd || !toolSessionId ? true : adapter.canAcceptTurnEnd(toolSessionId);
44314
+ this.deps.screenIdleProbeLogger?.info("feedObserverEvents turn_end batch received", {
44315
+ sessionId,
44316
+ toolSessionId,
44317
+ batchKinds: outEvents.map((e) => e.kind),
44318
+ gateOpen,
44319
+ hasCanAcceptGate: !!adapter.canAcceptTurnEnd
44320
+ });
44294
44321
  if (!gateOpen) {
44295
44322
  this.deps.logger?.info("drop turn_end (adapter gate closed)", {
44296
44323
  sessionId,
44297
44324
  toolSessionId,
44298
44325
  reason: "tui-screen-not-idle"
44299
44326
  });
44327
+ this.deps.screenIdleProbeLogger?.info("drop turn_end: adapter gate closed", {
44328
+ sessionId,
44329
+ toolSessionId,
44330
+ reason: "tui-screen-not-idle"
44331
+ });
44300
44332
  feedEvents = outEvents.filter((e) => e.kind !== "turn_end");
44301
44333
  } else {
44302
44334
  const ev = this.peekTurnEvidence(runner);
@@ -44306,7 +44338,19 @@ var SessionManager = class {
44306
44338
  ...ev,
44307
44339
  batchKinds: outEvents.map((e) => e.kind)
44308
44340
  });
44341
+ this.deps.screenIdleProbeLogger?.info("drop turn_end: empty turn (Fix B)", {
44342
+ sessionId,
44343
+ toolSessionId,
44344
+ ...ev,
44345
+ batchKinds: outEvents.map((e) => e.kind)
44346
+ });
44309
44347
  feedEvents = outEvents.filter((e) => e.kind !== "turn_end");
44348
+ } else {
44349
+ this.deps.screenIdleProbeLogger?.info("turn_end passed all filters \u2192 fed to reducer", {
44350
+ sessionId,
44351
+ toolSessionId,
44352
+ ...ev
44353
+ });
44310
44354
  }
44311
44355
  }
44312
44356
  }
@@ -44586,15 +44630,30 @@ var SessionManager = class {
44586
44630
  if (this.deps.mode !== "tui") return;
44587
44631
  const sid = this.sessionIdByToolSid(toolSessionId);
44588
44632
  const runner = sid ? this.runners.get(sid) : void 0;
44589
- if (!runner) return;
44633
+ if (!runner) {
44634
+ this.deps.screenIdleProbeLogger?.warn("dispatchTurnIdle: no runner for toolSessionId", {
44635
+ toolSessionId
44636
+ });
44637
+ return;
44638
+ }
44590
44639
  const ev = this.peekTurnEvidence(runner);
44591
44640
  if (!ev.turnEndSeenThisTurn) {
44592
44641
  this.deps.logger?.debug("screen-idle compensation skipped (no prior turn_end this turn)", {
44593
44642
  sessionId: sid,
44594
44643
  ...ev
44595
44644
  });
44645
+ this.deps.screenIdleProbeLogger?.info("dispatchTurnIdle skip: no prior turn_end this turn", {
44646
+ sessionId: sid,
44647
+ toolSessionId,
44648
+ ...ev
44649
+ });
44596
44650
  return;
44597
44651
  }
44652
+ this.deps.screenIdleProbeLogger?.info("dispatchTurnIdle inject turn_end (screen-idle compensation)", {
44653
+ sessionId: sid,
44654
+ toolSessionId,
44655
+ ...ev
44656
+ });
44598
44657
  runner.input({ kind: "inject-events", events: [{ kind: "turn_end" }] });
44599
44658
  }
44600
44659
  /**
@@ -46379,6 +46438,7 @@ var CodexAdapter = class {
46379
46438
  };
46380
46439
 
46381
46440
  // src/tools/claude-tui.ts
46441
+ var import_node_crypto5 = require("crypto");
46382
46442
  var import_node_fs16 = __toESM(require("fs"), 1);
46383
46443
  var import_node_os7 = __toESM(require("os"), 1);
46384
46444
  var import_node_path14 = __toESM(require("path"), 1);
@@ -47189,22 +47249,56 @@ function observeScreenIdle(surface, opts) {
47189
47249
  timer = null;
47190
47250
  if (disposed) return;
47191
47251
  if (opts.getPopupVisible()) {
47252
+ opts.probeLogger?.info("screen-idle fire suppressed: popup visible", {
47253
+ label: opts.probeLabel
47254
+ });
47192
47255
  timer = setTimeout(fire, opts.idleMs);
47193
47256
  return;
47194
47257
  }
47195
47258
  const obsWait = opts.getObserverWaitMs?.() ?? 0;
47196
47259
  if (obsWait > 0) {
47260
+ opts.probeLogger?.info("screen-idle fire suppressed: observer not idle", {
47261
+ label: opts.probeLabel,
47262
+ obsWait
47263
+ });
47197
47264
  timer = setTimeout(fire, Math.max(obsWait, REWAIT_MIN_MS));
47198
47265
  return;
47199
47266
  }
47200
- if (armed) return;
47267
+ if (armed) {
47268
+ opts.probeLogger?.debug("screen-idle fire noop: already armed", {
47269
+ label: opts.probeLabel
47270
+ });
47271
+ return;
47272
+ }
47201
47273
  armed = true;
47274
+ opts.probeLogger?.info("screen-idle fire triggered \u2192 armed=true, calling onIdle", {
47275
+ label: opts.probeLabel
47276
+ });
47202
47277
  opts.onIdle();
47203
47278
  };
47204
47279
  const unsub = surface.onTick((lines) => {
47205
47280
  if (disposed) return;
47206
47281
  const snap = snapOf(lines);
47207
47282
  if (snap === lastSnap) return;
47283
+ if (opts.probeLogger) {
47284
+ const prev = lastSnap;
47285
+ const meta = {
47286
+ label: opts.probeLabel,
47287
+ prevHash: prev === null ? null : shortHash(prev),
47288
+ nextHash: shortHash(snap),
47289
+ prevLen: prev?.length ?? 0,
47290
+ nextLen: snap.length
47291
+ };
47292
+ if (prev !== null) {
47293
+ const diff2 = firstLineDiff(prev, snap);
47294
+ if (diff2) {
47295
+ meta.diffRow = diff2.row;
47296
+ meta.prevRow = diff2.prev;
47297
+ meta.nextRow = diff2.next;
47298
+ }
47299
+ }
47300
+ opts.probeLogger.info("screen-idle tick snap changed", meta);
47301
+ }
47208
47302
  lastSnap = snap;
47209
47303
  armed = false;
47210
47304
  clear();
@@ -47217,13 +47311,38 @@ function observeScreenIdle(surface, opts) {
47217
47311
  clear();
47218
47312
  },
47219
47313
  isIdle() {
47220
- if (!armed) return false;
47221
- if (opts.getPopupVisible()) return false;
47314
+ const popupVisible = opts.getPopupVisible();
47222
47315
  const obsWait = opts.getObserverWaitMs?.() ?? 0;
47223
- return obsWait <= 0;
47316
+ const idle = armed && !popupVisible && obsWait <= 0;
47317
+ if (opts.probeLogger) {
47318
+ opts.probeLogger.info("screen-idle isIdle check", {
47319
+ label: opts.probeLabel,
47320
+ idle,
47321
+ armed,
47322
+ popupVisible,
47323
+ obsWait
47324
+ });
47325
+ }
47326
+ return idle;
47224
47327
  }
47225
47328
  };
47226
47329
  }
47330
+ function shortHash(s) {
47331
+ return (0, import_node_crypto5.createHash)("sha1").update(s).digest("hex").slice(0, 8);
47332
+ }
47333
+ function firstLineDiff(prev, next) {
47334
+ const p2 = prev.split("\n");
47335
+ const n = next.split("\n");
47336
+ const rows = Math.max(p2.length, n.length);
47337
+ for (let i = 0; i < rows; i++) {
47338
+ const pl = p2[i] ?? "";
47339
+ const nl = n[i] ?? "";
47340
+ if (pl !== nl) {
47341
+ return { row: i, prev: pl.slice(0, 60), next: nl.slice(0, 60) };
47342
+ }
47343
+ }
47344
+ return null;
47345
+ }
47227
47346
  var BYPASS_SETTLE_MS = 300;
47228
47347
  var SCREEN_IDLE_MS = 5e3;
47229
47348
  function createBootGate(pty, logger) {
@@ -47320,8 +47439,19 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
47320
47439
  */
47321
47440
  canAcceptTurnEnd(toolSessionId) {
47322
47441
  const state = this.tuiStates.get(toolSessionId);
47323
- if (!state) return true;
47324
- return state.screenIdle.isIdle();
47442
+ if (!state) {
47443
+ this.tuiOpts.screenIdleProbeLogger?.info(
47444
+ "canAcceptTurnEnd: no tuiState \u2192 pass (\u672A\u8DDF\u8E2A)",
47445
+ { toolSessionId }
47446
+ );
47447
+ return true;
47448
+ }
47449
+ const result = state.screenIdle.isIdle();
47450
+ this.tuiOpts.screenIdleProbeLogger?.info("canAcceptTurnEnd", {
47451
+ toolSessionId,
47452
+ result
47453
+ });
47454
+ return result;
47325
47455
  }
47326
47456
  spawn(ctx) {
47327
47457
  const args = buildTuiSpawnArgs(ctx, jsonlExistsForCtx(ctx));
@@ -47387,7 +47517,12 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
47387
47517
  getPopupVisible: () => popupObserver.visibleKind !== null,
47388
47518
  // observer 还需静止多久才满 SCREEN_IDLE_MS(复合条件 AND):屏幕静止后精确等这段剩余再补
47389
47519
  // turn_end,确保它排在尾段 text + turn_duration 全部 poll 落盘之后 = buffer 末条。
47390
- getObserverWaitMs: () => ctx.toolSessionId ? this.tuiOpts.getObserverWaitMs?.(ctx.toolSessionId, SCREEN_IDLE_MS) ?? 0 : 0
47520
+ getObserverWaitMs: () => ctx.toolSessionId ? this.tuiOpts.getObserverWaitMs?.(ctx.toolSessionId, SCREEN_IDLE_MS) ?? 0 : 0,
47521
+ // 取证 probe(可选,装配处传独立 file-only logger,跟主 daemon.log 解耦)
47522
+ ...this.tuiOpts.screenIdleProbeLogger ? {
47523
+ probeLogger: this.tuiOpts.screenIdleProbeLogger,
47524
+ probeLabel: ctx.toolSessionId ?? "<no-tsid>"
47525
+ } : {}
47391
47526
  });
47392
47527
  if (ctx.toolSessionId && this.tuiOpts.onSurfaceRegister) {
47393
47528
  this.tuiOpts.onSurfaceRegister(ctx.toolSessionId, surface);
@@ -47728,7 +47863,7 @@ async function writeInboxMcpConfig(args) {
47728
47863
  // src/shift/store.ts
47729
47864
  var import_promises = __toESM(require("fs/promises"), 1);
47730
47865
  var import_node_path19 = __toESM(require("path"), 1);
47731
- var import_node_crypto5 = require("crypto");
47866
+ var import_node_crypto6 = require("crypto");
47732
47867
 
47733
47868
  // src/shift/constants.ts
47734
47869
  var MAX_RUNS_PER_SHIFT = 30;
@@ -47824,7 +47959,7 @@ function createShiftStore(deps) {
47824
47959
  const nextRunAtMs = computeNextRunAtMs(input.schedule, now) ?? void 0;
47825
47960
  const shift = {
47826
47961
  ...input,
47827
- id: (0, import_node_crypto5.randomUUID)(),
47962
+ id: (0, import_node_crypto6.randomUUID)(),
47828
47963
  createdAtMs: now,
47829
47964
  updatedAtMs: now,
47830
47965
  state: { nextRunAtMs },
@@ -50776,7 +50911,7 @@ function lookupMime(filePathOrName) {
50776
50911
  }
50777
50912
 
50778
50913
  // src/attachment/sign-url.ts
50779
- var import_node_crypto6 = __toESM(require("crypto"), 1);
50914
+ var import_node_crypto7 = __toESM(require("crypto"), 1);
50780
50915
  var HMAC_ALGO = "sha256";
50781
50916
  function base64urlEncode(buf) {
50782
50917
  const b2 = typeof buf === "string" ? Buffer.from(buf, "utf8") : buf;
@@ -50793,7 +50928,7 @@ function decodeAbsPathFromUrl(encoded) {
50793
50928
  }
50794
50929
  function computeSig(secret, absPath, e) {
50795
50930
  const msg = e === null ? absPath : `${absPath}|${e}`;
50796
- return import_node_crypto6.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
50931
+ return import_node_crypto7.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
50797
50932
  }
50798
50933
  function signUrlParts(secret, absPath, ttlSeconds, now = Date.now) {
50799
50934
  const e = ttlSeconds === null ? null : Math.floor(now() / 1e3) + ttlSeconds;
@@ -50828,7 +50963,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
50828
50963
  if (provided.length !== expected.length) {
50829
50964
  return { ok: false, code: "BAD_SIG" };
50830
50965
  }
50831
- if (!import_node_crypto6.default.timingSafeEqual(provided, expected)) {
50966
+ if (!import_node_crypto7.default.timingSafeEqual(provided, expected)) {
50832
50967
  return { ok: false, code: "BAD_SIG" };
50833
50968
  }
50834
50969
  if (e !== null && now() / 1e3 > e) {
@@ -50840,7 +50975,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
50840
50975
  // src/attachment/upload.ts
50841
50976
  var import_node_fs25 = __toESM(require("fs"), 1);
50842
50977
  var import_node_path25 = __toESM(require("path"), 1);
50843
- var import_node_crypto7 = __toESM(require("crypto"), 1);
50978
+ var import_node_crypto8 = __toESM(require("crypto"), 1);
50844
50979
  var import_promises2 = require("stream/promises");
50845
50980
  var UploadError = class extends Error {
50846
50981
  constructor(code, message) {
@@ -50864,11 +50999,11 @@ async function writeUploadedAttachment(args) {
50864
50999
  } catch (err) {
50865
51000
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
50866
51001
  }
50867
- const hasher = import_node_crypto7.default.createHash("sha256");
51002
+ const hasher = import_node_crypto8.default.createHash("sha256");
50868
51003
  let actualSize = 0;
50869
51004
  const tmpPath = import_node_path25.default.join(
50870
51005
  attachmentsRoot,
50871
- `.upload-${process.pid}-${Date.now()}-${import_node_crypto7.default.randomBytes(4).toString("hex")}`
51006
+ `.upload-${process.pid}-${Date.now()}-${import_node_crypto8.default.randomBytes(4).toString("hex")}`
50872
51007
  );
50873
51008
  try {
50874
51009
  await (0, import_promises2.pipeline)(
@@ -51744,7 +51879,7 @@ function runAttachmentGc(args) {
51744
51879
  // src/attachment/group.ts
51745
51880
  var import_node_fs28 = __toESM(require("fs"), 1);
51746
51881
  var import_node_path29 = __toESM(require("path"), 1);
51747
- var import_node_crypto8 = __toESM(require("crypto"), 1);
51882
+ var import_node_crypto9 = __toESM(require("crypto"), 1);
51748
51883
  init_protocol();
51749
51884
  var GroupFileStore = class {
51750
51885
  dataDir;
@@ -51833,7 +51968,7 @@ var GroupFileStore = class {
51833
51968
  entries[idx] = next;
51834
51969
  } else {
51835
51970
  next = {
51836
- id: `gf-${import_node_crypto8.default.randomBytes(6).toString("base64url")}`,
51971
+ id: `gf-${import_node_crypto9.default.randomBytes(6).toString("base64url")}`,
51837
51972
  relPath: input.relPath,
51838
51973
  from: input.from,
51839
51974
  label: input.label,
@@ -51952,7 +52087,7 @@ function readDaemonSourceFromEnv(env = process.env) {
51952
52087
  // src/tunnel/tunnel-manager.ts
51953
52088
  var import_node_fs33 = __toESM(require("fs"), 1);
51954
52089
  var import_node_path34 = __toESM(require("path"), 1);
51955
- var import_node_crypto9 = __toESM(require("crypto"), 1);
52090
+ var import_node_crypto10 = __toESM(require("crypto"), 1);
51956
52091
  var import_node_child_process9 = require("child_process");
51957
52092
 
51958
52093
  // src/tunnel/tunnel-store.ts
@@ -52451,7 +52586,7 @@ var TunnelManager = class {
52451
52586
  override: this.deps.frpcBinaryOverride ?? void 0
52452
52587
  });
52453
52588
  const tomlPath = import_node_path34.default.join(this.deps.dataDir, "frpc.toml");
52454
- const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto9.default.randomBytes(3).toString("hex")}`;
52589
+ const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto10.default.randomBytes(3).toString("hex")}`;
52455
52590
  const toml = buildFrpcToml({
52456
52591
  serverAddr: t.frpsHost,
52457
52592
  serverPort: t.frpsPort,
@@ -52550,7 +52685,7 @@ async function waitForFrpcReady(proc, timeoutMs) {
52550
52685
  // src/tunnel/device-key.ts
52551
52686
  var import_node_os14 = __toESM(require("os"), 1);
52552
52687
  var import_node_path35 = __toESM(require("path"), 1);
52553
- var import_node_crypto10 = __toESM(require("crypto"), 1);
52688
+ var import_node_crypto11 = __toESM(require("crypto"), 1);
52554
52689
  var DERIVE_SALT = "clawd-tunnel-device-v1";
52555
52690
  function deriveStableDeviceKey(opts = {}) {
52556
52691
  const hostname = opts.hostname ?? import_node_os14.default.hostname();
@@ -52560,13 +52695,13 @@ function deriveStableDeviceKey(opts = {}) {
52560
52695
  const normalizedDataDir = opts.dataDir ? import_node_path35.default.resolve(opts.dataDir) : null;
52561
52696
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
52562
52697
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
52563
- return import_node_crypto10.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
52698
+ return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
52564
52699
  }
52565
52700
 
52566
52701
  // src/auth-store.ts
52567
52702
  var import_node_fs34 = __toESM(require("fs"), 1);
52568
52703
  var import_node_path36 = __toESM(require("path"), 1);
52569
- var import_node_crypto11 = __toESM(require("crypto"), 1);
52704
+ var import_node_crypto12 = __toESM(require("crypto"), 1);
52570
52705
  var AUTH_FILE_NAME = "auth.json";
52571
52706
  function authFilePath(dataDir) {
52572
52707
  return import_node_path36.default.join(dataDir, AUTH_FILE_NAME);
@@ -52598,10 +52733,10 @@ function loadOrCreateAuthFile(opts) {
52598
52733
  return next;
52599
52734
  }
52600
52735
  function defaultGenerateToken() {
52601
- return import_node_crypto11.default.randomBytes(32).toString("base64url");
52736
+ return import_node_crypto12.default.randomBytes(32).toString("base64url");
52602
52737
  }
52603
52738
  function defaultGenerateOwnerPrincipalId() {
52604
- return `owner-${import_node_crypto11.default.randomUUID()}`;
52739
+ return `owner-${import_node_crypto12.default.randomUUID()}`;
52605
52740
  }
52606
52741
  function readAuthFile(file) {
52607
52742
  try {
@@ -52723,7 +52858,7 @@ var OwnerIdentityStore = class {
52723
52858
  };
52724
52859
 
52725
52860
  // src/feishu-auth/login-flow.ts
52726
- var import_node_crypto12 = __toESM(require("crypto"), 1);
52861
+ var import_node_crypto13 = __toESM(require("crypto"), 1);
52727
52862
  var STATE_TTL_MS = 5 * 60 * 1e3;
52728
52863
  var LoginFlow = class {
52729
52864
  constructor(deps) {
@@ -52732,7 +52867,7 @@ var LoginFlow = class {
52732
52867
  deps;
52733
52868
  pendingStates = /* @__PURE__ */ new Map();
52734
52869
  start() {
52735
- const state = import_node_crypto12.default.randomBytes(16).toString("base64url");
52870
+ const state = import_node_crypto13.default.randomBytes(16).toString("base64url");
52736
52871
  const now = (this.deps.now ?? Date.now)();
52737
52872
  this.pendingStates.set(state, now);
52738
52873
  this.gcExpired(now);
@@ -54610,7 +54745,7 @@ init_protocol();
54610
54745
  // src/extension/bundle-zip.ts
54611
54746
  var import_promises5 = __toESM(require("fs/promises"), 1);
54612
54747
  var import_node_path42 = __toESM(require("path"), 1);
54613
- var import_node_crypto13 = __toESM(require("crypto"), 1);
54748
+ var import_node_crypto14 = __toESM(require("crypto"), 1);
54614
54749
  var import_jszip2 = __toESM(require_lib3(), 1);
54615
54750
  async function bundleExtensionDir(dir) {
54616
54751
  const entries = await listFilesSorted(dir);
@@ -54625,7 +54760,7 @@ async function bundleExtensionDir(dir) {
54625
54760
  compression: "DEFLATE",
54626
54761
  compressionOptions: { level: 6 }
54627
54762
  });
54628
- const sha256 = import_node_crypto13.default.createHash("sha256").update(buffer).digest("hex");
54763
+ const sha256 = import_node_crypto14.default.createHash("sha256").update(buffer).digest("hex");
54629
54764
  return { buffer, sha256 };
54630
54765
  }
54631
54766
  var FIXED_DATE = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
@@ -54693,7 +54828,7 @@ function computePublishCheck(args) {
54693
54828
  var import_promises6 = __toESM(require("fs/promises"), 1);
54694
54829
  var import_node_path44 = __toESM(require("path"), 1);
54695
54830
  var import_node_os19 = __toESM(require("os"), 1);
54696
- var import_node_crypto14 = __toESM(require("crypto"), 1);
54831
+ var import_node_crypto15 = __toESM(require("crypto"), 1);
54697
54832
  var import_jszip3 = __toESM(require_lib3(), 1);
54698
54833
 
54699
54834
  // src/extension/paths.ts
@@ -54722,7 +54857,7 @@ var InstallError = class extends Error {
54722
54857
  };
54723
54858
  async function installFromChannel(args, deps) {
54724
54859
  const { channelRef, snapshotHash, bundleZip } = args;
54725
- const computed = import_node_crypto14.default.createHash("sha256").update(bundleZip).digest("hex");
54860
+ const computed = import_node_crypto15.default.createHash("sha256").update(bundleZip).digest("hex");
54726
54861
  if (computed !== snapshotHash) {
54727
54862
  throw new InstallError(
54728
54863
  "HASH_MISMATCH",
@@ -54814,7 +54949,7 @@ async function installFromChannel(args, deps) {
54814
54949
  var import_promises7 = __toESM(require("fs/promises"), 1);
54815
54950
  var import_node_path45 = __toESM(require("path"), 1);
54816
54951
  var import_node_os20 = __toESM(require("os"), 1);
54817
- var import_node_crypto15 = __toESM(require("crypto"), 1);
54952
+ var import_node_crypto16 = __toESM(require("crypto"), 1);
54818
54953
  var import_jszip4 = __toESM(require_lib3(), 1);
54819
54954
  var UpdateError = class extends Error {
54820
54955
  constructor(code, message) {
@@ -54852,7 +54987,7 @@ async function updateFromChannel(args, deps) {
54852
54987
  if (e instanceof UpdateError) throw e;
54853
54988
  throw e;
54854
54989
  }
54855
- const computed = import_node_crypto15.default.createHash("sha256").update(bundleZip).digest("hex");
54990
+ const computed = import_node_crypto16.default.createHash("sha256").update(bundleZip).digest("hex");
54856
54991
  if (computed !== snapshotHash) {
54857
54992
  throw new UpdateError(
54858
54993
  "HASH_MISMATCH",
@@ -55557,7 +55692,7 @@ function listPidsOnPort(port) {
55557
55692
  }
55558
55693
 
55559
55694
  // src/app-builder/publish-registry.ts
55560
- var import_node_crypto16 = require("crypto");
55695
+ var import_node_crypto17 = require("crypto");
55561
55696
  var PublishJobRegistry = class {
55562
55697
  jobs = /* @__PURE__ */ new Map();
55563
55698
  has(name) {
@@ -55574,7 +55709,7 @@ var PublishJobRegistry = class {
55574
55709
  if (this.jobs.has(args.name)) {
55575
55710
  throw new Error(`already publishing: ${args.name}`);
55576
55711
  }
55577
- const jobId = args.jobId ?? `job-${(0, import_node_crypto16.randomUUID)()}`;
55712
+ const jobId = args.jobId ?? `job-${(0, import_node_crypto17.randomUUID)()}`;
55578
55713
  this.jobs.set(args.name, {
55579
55714
  jobId,
55580
55715
  name: args.name,
@@ -56534,7 +56669,7 @@ async function uninstall(deps) {
56534
56669
  }
56535
56670
 
56536
56671
  // src/handlers/index.ts
56537
- var import_node_crypto17 = require("crypto");
56672
+ var import_node_crypto18 = require("crypto");
56538
56673
  function buildMethodHandlers(deps) {
56539
56674
  return {
56540
56675
  ...buildSessionHandlers({
@@ -56567,7 +56702,7 @@ function buildMethodHandlers(deps) {
56567
56702
  const c = deps.contactStore.get(deviceId);
56568
56703
  return c ? { deviceId: c.deviceId, remoteUrl: c.remoteUrl, connectToken: c.connectToken } : null;
56569
56704
  },
56570
- genId: () => (0, import_node_crypto17.randomUUID)(),
56705
+ genId: () => (0, import_node_crypto18.randomUUID)(),
56571
56706
  now: () => Date.now(),
56572
56707
  forwardInboxPostToPeer,
56573
56708
  logger: deps.logger
@@ -57469,6 +57604,13 @@ async function startDaemon(config) {
57469
57604
  logClient
57470
57605
  });
57471
57606
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
57607
+ const screenIdleProbeLogger = createFileOnlyLogger({
57608
+ file: import_node_path55.default.join(config.dataDir, "screen-idle-probe.log"),
57609
+ level: "debug"
57610
+ });
57611
+ logger.info("screen-idle probe logger enabled", {
57612
+ file: import_node_path55.default.join(config.dataDir, "screen-idle-probe.log")
57613
+ });
57472
57614
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
57473
57615
  const pre = stateMgr.preflight();
57474
57616
  if (pre.status === "active") {
@@ -57745,6 +57887,10 @@ async function startDaemon(config) {
57745
57887
  // 新布局派生 (sessions/* + personas/<pid>/.clawd/sessions/owner/*)
57746
57888
  storeFactory: sessionStoreFactory,
57747
57889
  logger,
57890
+ // 取证 probe(可选,CLAWD_SCREEN_IDLE_PROBE=1 时启用):manager turn_end 判定链
57891
+ // 的所有决策点打到独立文件,跟 adapter 的 observeScreenIdle probe 共用同一份 file logger,
57892
+ // 便于 grep sessionId 时 tui 层 + manager 层交叉时序都在同一文件里
57893
+ ...screenIdleProbeLogger ? { screenIdleProbeLogger } : {},
57748
57894
  getAdapter,
57749
57895
  historyReader: history,
57750
57896
  dataDir: config.dataDir,
@@ -57865,7 +58011,9 @@ async function startDaemon(config) {
57865
58011
  // 屏幕静止 → 补权威 turn_end(修 turn_duration 尾随 text 覆盖 lastEventKind)
57866
58012
  onTurnIdle: (tsid) => manager.dispatchTurnIdle(tsid),
57867
58013
  // 复合条件闸:observer 还需静止多久才满 idleMs(屏幕静止后精确等这段剩余再补 turn_end)
57868
- getObserverWaitMs: (tsid, idleMs) => manager.observerIdleWaitMs(tsid, idleMs)
58014
+ getObserverWaitMs: (tsid, idleMs) => manager.observerIdleWaitMs(tsid, idleMs),
58015
+ // 取证 probe(可选,CLAWD_SCREEN_IDLE_PROBE=1 时启用;生产默认 undefined 不打)
58016
+ ...screenIdleProbeLogger ? { screenIdleProbeLogger } : {}
57869
58017
  }) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
57870
58018
  registerAdapter("claude", claudeAdapter);
57871
58019
  registerAdapter("codex", new CodexAdapter({ logger, historyReader: new CodexHistoryReader() }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.196",
3
+ "version": "0.2.197-beta.396.cf8bb30",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",