@ai-matrx/desktop-protocol 0.21.79 → 0.21.81

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/client.cjs CHANGED
@@ -144,7 +144,7 @@ var import_zod2 = require("zod");
144
144
  var import_zod = require("zod");
145
145
  var import_uuid = require("@ai-matrx/kit/uuid");
146
146
  var PROTOCOL_MAJOR = 1;
147
- var PROTOCOL_MINOR = 77;
147
+ var PROTOCOL_MINOR = 78;
148
148
  var PROTOCOL_VERSION = `${PROTOCOL_MAJOR}.${PROTOCOL_MINOR}`;
149
149
  var ProtocolVersion = import_zod.z.string().regex(/^[1-9][0-9]{0,2}\.[0-9]{1,3}$/);
150
150
  var RequestId = import_zod.z.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
@@ -3564,7 +3564,9 @@ var ColdChat = import_zod31.z.strictObject({
3564
3564
  /** It can be shown in its window (started in the desktop app). */
3565
3565
  openable: import_zod31.z.boolean(),
3566
3566
  /** How its window was decided, or why it can't be opened. */
3567
- how: import_zod31.z.string().max(200).nullable()
3567
+ how: import_zod31.z.string().max(200).nullable(),
3568
+ /** 1.78: the person hid this chat from Matrx's lists (our Hide, as on ChatRow.hidden); absent = shown. */
3569
+ hidden: import_zod31.z.boolean().optional()
3568
3570
  });
3569
3571
  var AppsChatsColdParams = import_zod31.z.strictObject({ app_key: AppKey });
3570
3572
  var AppsChatsColdResult = import_zod31.z.strictObject({
@@ -3647,12 +3649,30 @@ var SpendChat = import_zod31.z.strictObject({
3647
3649
  repo: import_zod31.z.string().max(200).nullable(),
3648
3650
  window: import_zod31.z.string().max(64).nullable(),
3649
3651
  spend: SpendScopes,
3650
- helpers: nonNegInt
3652
+ helpers: nonNegInt,
3653
+ /** 1.78: the person hid this chat from Matrx's lists (our Hide, as on ChatRow.hidden); absent = shown. */
3654
+ hidden: import_zod31.z.boolean().optional()
3651
3655
  });
3652
3656
  var SpendHelper = import_zod31.z.strictObject({ model: import_zod31.z.string().max(120), steps: nonNegInt, over_steps: import_zod31.z.boolean(), description: import_zod31.z.string().max(400) });
3653
- var SpendLive = import_zod31.z.strictObject({ id: ChatId, title: import_zod31.z.string().max(1e3), window: import_zod31.z.string().max(64).nullable(), helpers: import_zod31.z.array(SpendHelper).max(200) });
3657
+ var SpendLive = import_zod31.z.strictObject({
3658
+ id: ChatId,
3659
+ title: import_zod31.z.string().max(1e3),
3660
+ window: import_zod31.z.string().max(64).nullable(),
3661
+ helpers: import_zod31.z.array(SpendHelper).max(200),
3662
+ /** 1.78: the person hid this chat from Matrx's lists (our Hide, as on ChatRow.hidden); absent = shown. */
3663
+ hidden: import_zod31.z.boolean().optional()
3664
+ });
3654
3665
  var SpendIdleScope = import_zod31.z.strictObject({ count: nonNegInt, tokens: nonNegInt, cost: import_zod31.z.number(), avoidable: import_zod31.z.number() });
3655
- var SpendIdle = import_zod31.z.strictObject({ id: ChatId, chat: import_zod31.z.string().max(1e3), who: import_zod31.z.string().max(400), today: SpendIdleScope, week: SpendIdleScope, last_ms: epochMs });
3666
+ var SpendIdle = import_zod31.z.strictObject({
3667
+ id: ChatId,
3668
+ chat: import_zod31.z.string().max(1e3),
3669
+ who: import_zod31.z.string().max(400),
3670
+ today: SpendIdleScope,
3671
+ week: SpendIdleScope,
3672
+ last_ms: epochMs,
3673
+ /** 1.78: the person hid this chat from Matrx's lists (our Hide, as on ChatRow.hidden); absent = shown. */
3674
+ hidden: import_zod31.z.boolean().optional()
3675
+ });
3656
3676
  var SpendStart = import_zod31.z.strictObject({ repo: import_zod31.z.string().max(200), count: nonNegInt, median: nonNegInt, latest: import_zod31.z.array(nonNegInt).max(20), alarm: import_zod31.z.string().max(400).nullable() });
3657
3677
  var SpendDay = import_zod31.z.strictObject({ date: import_zod31.z.string().regex(/^\d{4}-\d{2}-\d{2}$/), main: import_zod31.z.number(), helpers: import_zod31.z.number() });
3658
3678
  var AppsSpendParams = import_zod31.z.strictObject({ app_key: AppKey });
@@ -5130,6 +5150,9 @@ var NESTED_RESULTS = /* @__PURE__ */ new Map([
5130
5150
  ["apps.projects.unfile", [["chat", "ChatRow"]]],
5131
5151
  ["apps.projects.move", [["chat", "ChatRow"]]],
5132
5152
  ["apps.chats.star", [["chat", "ChatRow"]]],
5153
+ // 1.78: our Hide on the cold and spend rows.
5154
+ ["apps.chats.cold", [["waiting", "ColdChat"], ["recently_cold", "ColdChat"]]],
5155
+ ["apps.spend", [["chats", "SpendChat"], ["live", "SpendLive"], ["idle", "SpendIdle"]]],
5133
5156
  ["apps.chats.place", [["chat", "ChatRow"]]],
5134
5157
  ["apps.accounts.usage", [["accounts", "AccountUsage"]]],
5135
5158
  ["resources.snapshot", [["disks", "ResourcesDisk"]]],
@@ -5206,6 +5229,7 @@ function createDesktopClient(options) {
5206
5229
  const makeSocket = options.webSocket ?? defaultWebSocket();
5207
5230
  const heartbeatMs = options.heartbeatMs ?? 25e3;
5208
5231
  const requestTimeoutMs = options.requestTimeoutMs ?? 7e4;
5232
+ const firstFrameMs = options.firstFrameMs ?? requestTimeoutMs;
5209
5233
  const protocolVersion = options.protocolVersion ?? `${PROTOCOL_MAJOR}.${PROTOCOL_MINOR}`;
5210
5234
  const backoff = (0, import_realtime.createBackoff)({ ...options.backoff, now: timers.now });
5211
5235
  const diagnose = options.onDiagnostic ?? ((d) => {
@@ -5243,6 +5267,7 @@ function createDesktopClient(options) {
5243
5267
  let probeTimer = null;
5244
5268
  let lastHeardAt = 0;
5245
5269
  let heardCount = 0;
5270
+ let pongs = 0;
5246
5271
  let closedByUser = false;
5247
5272
  const newId = (prefix) => `${prefix}${(++nextId).toString(36)}`;
5248
5273
  function setState(patch) {
@@ -5290,6 +5315,7 @@ function createDesktopClient(options) {
5290
5315
  ws.onopen = () => {
5291
5316
  if (generation !== socketGeneration) return;
5292
5317
  lastHeardAt = timers.now();
5318
+ pongs = 0;
5293
5319
  helloId = newId("h");
5294
5320
  setState({ status: "handshaking" });
5295
5321
  sendJson({ type: "hello", id: helloId, protocolVersion, clientType: options.clientType, clientVersion: options.clientVersion });
@@ -5305,6 +5331,8 @@ function createDesktopClient(options) {
5305
5331
  };
5306
5332
  ws.onclose = (event) => {
5307
5333
  if (generation !== socketGeneration) return;
5334
+ const ev = event;
5335
+ reportClose(ev.code, ev.reason ?? "", ev.wasClean ?? false);
5308
5336
  onSocketGone(generation, event.code, null);
5309
5337
  };
5310
5338
  }
@@ -5316,6 +5344,7 @@ function createDesktopClient(options) {
5316
5344
  const silentMs = timers.now() - lastHeardAt;
5317
5345
  if (silentMs >= heartbeatMs * 2) {
5318
5346
  diagnose({ kind: "heartbeat_timeout", silentMs });
5347
+ reportClose(null, "heartbeat timeout", false);
5319
5348
  const dead = socket;
5320
5349
  onSocketGone(generation, null, new DesktopProtocolError("TIMEOUT", "Connection went silent", { retryable: true }));
5321
5350
  try {
@@ -5328,6 +5357,9 @@ function createDesktopClient(options) {
5328
5357
  scheduleHeartbeat(generation);
5329
5358
  }, heartbeatMs);
5330
5359
  }
5360
+ function reportClose(code, reason, wasClean) {
5361
+ diagnose({ kind: "socket_closed", code, reason: reason.slice(0, 120), wasClean, idleSinceLastRxMs: Math.max(0, timers.now() - lastHeardAt), pongs });
5362
+ }
5331
5363
  function onSocketGone(generation, code, error) {
5332
5364
  if (generation !== socketGeneration) return;
5333
5365
  socketGeneration++;
@@ -5416,7 +5448,10 @@ function createDesktopClient(options) {
5416
5448
  }
5417
5449
  function onMessage(data) {
5418
5450
  if (typeof data === "string") {
5419
- if (data === PONG_TEXT) return;
5451
+ if (data === PONG_TEXT) {
5452
+ pongs++;
5453
+ return;
5454
+ }
5420
5455
  let json;
5421
5456
  try {
5422
5457
  json = JSON.parse(data);
@@ -5447,6 +5482,10 @@ function createDesktopClient(options) {
5447
5482
  onFrame(frame.header, frame.payload);
5448
5483
  }
5449
5484
  function onEnvelope(msg) {
5485
+ if (msg.type !== "event") {
5486
+ const heard = streams.get(msg.id);
5487
+ if (heard) clearFirstFrame(heard);
5488
+ }
5450
5489
  switch (msg.type) {
5451
5490
  case "response": {
5452
5491
  if (msg.id === helloId) return onWelcome(msg.result);
@@ -5588,6 +5627,7 @@ function createDesktopClient(options) {
5588
5627
  diagnose({ kind: "unknown_stream", sid: header.sid });
5589
5628
  return;
5590
5629
  }
5630
+ clearFirstFrame(s);
5591
5631
  const isData = header.channel === FrameChannel.DATA || header.channel === FrameChannel.STDERR;
5592
5632
  const isSnapshot = header.channel === FrameChannel.SNAPSHOT;
5593
5633
  if (!isData && !isSnapshot) {
@@ -5633,8 +5673,29 @@ function createDesktopClient(options) {
5633
5673
  socket.send(encodeFrame({ version: FRAME_VERSION, flags: 0, channel: FrameChannel.STDIN, cid: 0, sid: s.sid, seq: s.sendSeq }, chunk));
5634
5674
  }
5635
5675
  }
5676
+ function clearFirstFrame(s) {
5677
+ if (s.firstFrameTimer === null) return;
5678
+ timers.clearTimeout(s.firstFrameTimer);
5679
+ s.firstFrameTimer = null;
5680
+ }
5681
+ function armFirstFrame(s) {
5682
+ clearFirstFrame(s);
5683
+ const waitMs = s.options.firstFrameMs ?? firstFrameMs;
5684
+ const id = s.id;
5685
+ s.firstFrameTimer = timers.setTimeout(() => {
5686
+ s.firstFrameTimer = null;
5687
+ if (s.ended || s.id !== id) return;
5688
+ diagnose({ kind: "first_frame_timeout", id, op: s.op, waitedMs: waitMs });
5689
+ streams.delete(id);
5690
+ if (s.sid !== null) bySid.delete(s.sid);
5691
+ abandon(id);
5692
+ endStream(s, null, new DesktopProtocolError("TIMEOUT", `${s.op}: no answer within ${waitMs} ms`, { retryable: true }));
5693
+ wake();
5694
+ }, waitMs);
5695
+ }
5636
5696
  function endStream(s, reason, error) {
5637
5697
  if (s.ended) return;
5698
+ clearFirstFrame(s);
5638
5699
  s.ended = true;
5639
5700
  s.sendQueue = [];
5640
5701
  if (!s.resultSettled) {
@@ -5657,7 +5718,7 @@ function createDesktopClient(options) {
5657
5718
  const params = { resource_id: s.resourceId, mode: s.options.mode ?? "control" };
5658
5719
  if (s.lastSeq > 0) params.since_seq = s.lastSeq;
5659
5720
  if (s.options.windowBytes !== void 0) params.window_bytes = s.options.windowBytes;
5660
- sendJson({ id, type: "request", cap: "session", op: "attach", params });
5721
+ if (sendJson({ id, type: "request", cap: "session", op: "attach", params })) armFirstFrame(s);
5661
5722
  }
5662
5723
  function safeCall(where, fn) {
5663
5724
  try {
@@ -5766,7 +5827,8 @@ function createDesktopClient(options) {
5766
5827
  resolveDone,
5767
5828
  rejectDone,
5768
5829
  ended: false,
5769
- reattaching: false
5830
+ reattaching: false,
5831
+ firstFrameTimer: null
5770
5832
  };
5771
5833
  const start = async () => {
5772
5834
  let welcome;
@@ -5785,7 +5847,9 @@ function createDesktopClient(options) {
5785
5847
  if (!sendJson({ id: s.id, type: "request", ...capOf(op), params: wire })) {
5786
5848
  streams.delete(s.id);
5787
5849
  endStream(s, null, new DesktopProtocolError("DEVICE_OFFLINE", "Connection lost", { retryable: true }));
5850
+ return;
5788
5851
  }
5852
+ armFirstFrame(s);
5789
5853
  };
5790
5854
  void start();
5791
5855
  opts.signal?.addEventListener("abort", () => handle.cancel(), { once: true });
@@ -5861,6 +5925,7 @@ function createDesktopClient(options) {
5861
5925
  if (heardCount > heardBefore) return;
5862
5926
  const silentMs = timers.now() - lastHeardAt;
5863
5927
  diagnose({ kind: "heartbeat_timeout", silentMs });
5928
+ reportClose(null, "wake probe timeout", false);
5864
5929
  const dead = socket;
5865
5930
  onSocketGone(generation, null, new DesktopProtocolError("TIMEOUT", "Connection went silent", { retryable: true }));
5866
5931
  try {