adhdev 0.9.55 → 0.9.56

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/cli/index.js CHANGED
@@ -14705,6 +14705,12 @@ var init_provider_cli_adapter = __esm({
14705
14705
  accumulatedRawBuffer = "";
14706
14706
  /** Current visible terminal screen snapshot */
14707
14707
  terminalScreen = new TerminalScreen(24, 80);
14708
+ static MAX_RESPONSE_BUFFER = 8e3;
14709
+ static MAX_RECENT_OUTPUT_BUFFER = 1e3;
14710
+ responseBufferDroppedChars = 0;
14711
+ recentOutputDroppedChars = 0;
14712
+ accumulatedBufferDroppedChars = 0;
14713
+ accumulatedRawBufferDroppedChars = 0;
14708
14714
  /** Max accumulated buffer size. Sized to comfortably hold a single long
14709
14715
  * Hermes turn (tool calls + reasoning + final bubble) without the
14710
14716
  * rolling window pushing the turn's ╭─ opening line out of view. */
@@ -14722,6 +14728,23 @@ var init_provider_cli_adapter = __esm({
14722
14728
  providerResolutionMeta;
14723
14729
  static FINISH_RETRY_DELAY_MS = 300;
14724
14730
  static MAX_FINISH_RETRIES = 2;
14731
+ getBufferState() {
14732
+ const build = (droppedChars, maxChars) => droppedChars > 0 ? { truncated: true, droppedChars, maxChars } : void 0;
14733
+ const responseBuffer = build(this.responseBufferDroppedChars, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
14734
+ const recentOutputBuffer = build(this.recentOutputDroppedChars, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
14735
+ const accumulatedBuffer = build(this.accumulatedBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
14736
+ const accumulatedRawBuffer = build(this.accumulatedRawBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
14737
+ if (!responseBuffer && !recentOutputBuffer && !accumulatedBuffer && !accumulatedRawBuffer) return void 0;
14738
+ return {
14739
+ ...responseBuffer ? { responseBuffer } : {},
14740
+ ...recentOutputBuffer ? { recentOutputBuffer } : {},
14741
+ ...accumulatedBuffer ? { accumulatedBuffer } : {},
14742
+ ...accumulatedRawBuffer ? { accumulatedRawBuffer } : {}
14743
+ };
14744
+ }
14745
+ recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
14746
+ return Math.max(0, previousLength + appendedLength - nextLength);
14747
+ }
14725
14748
  buildCommittedMessagesActivitySignature() {
14726
14749
  const last = this.committedMessages[this.committedMessages.length - 1];
14727
14750
  return [
@@ -15087,7 +15110,9 @@ var init_provider_cli_adapter = __esm({
15087
15110
  this.scheduleStartupSettleCheck();
15088
15111
  }
15089
15112
  if (this.isWaitingForResponse && cleanData) {
15090
- this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, 8e3);
15113
+ const previousResponseLen = this.responseBuffer.length;
15114
+ this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
15115
+ this.responseBufferDroppedChars += this.recordBoundedAppendDrop(previousResponseLen, cleanData.length, this.responseBuffer.length);
15091
15116
  }
15092
15117
  if (cleanData.trim()) {
15093
15118
  if (this.serverConn) {
@@ -15096,14 +15121,19 @@ var init_provider_cli_adapter = __esm({
15096
15121
  this.logBuffer.push({ message: cleanData.trim(), level: "info" });
15097
15122
  }
15098
15123
  }
15124
+ const prevRecentLen = this.recentOutputBuffer.length;
15099
15125
  const prevAccumulatedLen = this.accumulatedBuffer.length;
15100
15126
  const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
15101
- this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, 1e3);
15127
+ this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
15102
15128
  this.accumulatedBuffer = appendBoundedText(this.accumulatedBuffer, cleanData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
15103
15129
  this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
15130
+ const droppedRecent = this.recordBoundedAppendDrop(prevRecentLen, cleanData.length, this.recentOutputBuffer.length);
15131
+ const droppedClean = this.recordBoundedAppendDrop(prevAccumulatedLen, cleanData.length, this.accumulatedBuffer.length);
15132
+ const droppedRaw = this.recordBoundedAppendDrop(prevAccumulatedRawLen, rawData.length, this.accumulatedRawBuffer.length);
15133
+ this.recentOutputDroppedChars += droppedRecent;
15134
+ this.accumulatedBufferDroppedChars += droppedClean;
15135
+ this.accumulatedRawBufferDroppedChars += droppedRaw;
15104
15136
  if (this.currentTurnScope) {
15105
- const droppedClean = prevAccumulatedLen + cleanData.length - this.accumulatedBuffer.length;
15106
- const droppedRaw = prevAccumulatedRawLen + rawData.length - this.accumulatedRawBuffer.length;
15107
15137
  if (droppedClean > 0) {
15108
15138
  this.currentTurnScope.bufferStart = Math.max(0, this.currentTurnScope.bufferStart - droppedClean);
15109
15139
  }
@@ -15933,13 +15963,15 @@ var init_provider_cli_adapter = __esm({
15933
15963
  effectiveModal = parsedModal;
15934
15964
  }
15935
15965
  }
15966
+ const bufferState = this.getBufferState();
15936
15967
  return {
15937
15968
  status: effectiveStatus,
15938
15969
  messages: [...this.committedMessages],
15939
15970
  workingDir: this.workingDir,
15940
15971
  activeModal: effectiveModal,
15941
15972
  errorMessage: this.parseErrorMessage || void 0,
15942
- errorReason: this.parseErrorMessage ? "parse_error" : void 0
15973
+ errorReason: this.parseErrorMessage ? "parse_error" : void 0,
15974
+ ...bufferState ? { bufferState } : {}
15943
15975
  };
15944
15976
  }
15945
15977
  seedCommittedMessages(messages) {
@@ -16121,10 +16153,12 @@ var init_provider_cli_adapter = __esm({
16121
16153
  messages: hydratedMessages,
16122
16154
  activeModal: parsed.activeModal ?? this.activeModal,
16123
16155
  providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
16156
+ ...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
16124
16157
  ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
16125
16158
  };
16126
16159
  } else {
16127
16160
  const messages = [...this.committedMessages];
16161
+ const bufferState = this.getBufferState();
16128
16162
  result = {
16129
16163
  id: "cli_session",
16130
16164
  status: this.currentStatus,
@@ -16135,7 +16169,8 @@ var init_provider_cli_adapter = __esm({
16135
16169
  index: typeof message.index === "number" ? message.index : index,
16136
16170
  receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
16137
16171
  })),
16138
- activeModal: this.activeModal
16172
+ activeModal: this.activeModal,
16173
+ ...bufferState ? { bufferState } : {}
16139
16174
  };
16140
16175
  }
16141
16176
  const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
@@ -81253,7 +81288,7 @@ function sendToPeer(peer, data) {
81253
81288
  return false;
81254
81289
  }
81255
81290
  const json2 = JSON.stringify(data);
81256
- if (messageType === "command_result" && json2.length > MAX_INLINE_JSON_MESSAGE_CHARS) {
81291
+ if (messageType === "command_result" && Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_CHARS) {
81257
81292
  return sendChunkedCommandResult(peer, peerId, requestId, json2);
81258
81293
  }
81259
81294
  try {
@@ -81266,21 +81301,51 @@ function sendToPeer(peer, data) {
81266
81301
  return false;
81267
81302
  }
81268
81303
  }
81304
+ function buildCommandResultChunkEnvelope(requestId, chunkId, index, total, data) {
81305
+ return JSON.stringify({
81306
+ type: "command_result_chunk",
81307
+ id: requestId,
81308
+ chunkId,
81309
+ index,
81310
+ total,
81311
+ data
81312
+ });
81313
+ }
81314
+ function splitJsonIntoCommandResultChunks(json2, requestId, chunkId) {
81315
+ const chunks = [];
81316
+ let offset = 0;
81317
+ while (offset < json2.length) {
81318
+ let end = Math.min(json2.length, offset + JSON_CHUNK_PAYLOAD_CHARS);
81319
+ while (end > offset) {
81320
+ const candidate = json2.slice(offset, end);
81321
+ const envelope = buildCommandResultChunkEnvelope(requestId, chunkId, chunks.length, MAX_JSON_CHUNKS, candidate);
81322
+ if (Buffer.byteLength(envelope, "utf8") <= MAX_INLINE_JSON_MESSAGE_BYTES) break;
81323
+ end = offset + Math.max(1, Math.floor((end - offset) * 0.8));
81324
+ }
81325
+ chunks.push(json2.slice(offset, end));
81326
+ if (chunks.length > MAX_JSON_CHUNKS) return [];
81327
+ offset = end;
81328
+ }
81329
+ return chunks;
81330
+ }
81269
81331
  function sendChunkedCommandResult(peer, peerId, requestId, json2) {
81270
81332
  const chunkId = requestId || `command_result_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
81271
- const total = Math.ceil(json2.length / JSON_CHUNK_PAYLOAD_CHARS);
81333
+ const chunks = splitJsonIntoCommandResultChunks(json2, requestId, chunkId);
81334
+ const total = chunks.length;
81335
+ if (total === 0 || total > MAX_JSON_CHUNKS) {
81336
+ log(`command_result send failed: peer=${peerId} id=${requestId || "-"} reason=too_many_chunks chunks=${total || "unknown"}`);
81337
+ return false;
81338
+ }
81272
81339
  logDebug(`command_result chunked: peer=${peerId} id=${requestId || "-"} chars=${json2.length} chunks=${total}`);
81273
81340
  for (let index = 0; index < total; index += 1) {
81274
- const chunk = json2.slice(index * JSON_CHUNK_PAYLOAD_CHARS, (index + 1) * JSON_CHUNK_PAYLOAD_CHARS);
81341
+ const chunk = chunks[index] || "";
81275
81342
  try {
81276
- peer.dataChannel?.sendMessage(JSON.stringify({
81277
- type: "command_result_chunk",
81278
- id: requestId,
81279
- chunkId,
81280
- index,
81281
- total,
81282
- data: chunk
81283
- }));
81343
+ const envelope = buildCommandResultChunkEnvelope(requestId, chunkId, index, total, chunk);
81344
+ if (Buffer.byteLength(envelope, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES) {
81345
+ log(`command_result send failed: peer=${peerId} id=${requestId || "-"} chunk=${index + 1}/${total} reason=chunk_too_large`);
81346
+ return false;
81347
+ }
81348
+ peer.dataChannel?.sendMessage(envelope);
81284
81349
  } catch (error48) {
81285
81350
  log(`command_result send failed: peer=${peerId} id=${requestId || "-"} chunk=${index + 1}/${total} error=${error48?.message || error48}`);
81286
81351
  return false;
@@ -81288,10 +81353,58 @@ function sendChunkedCommandResult(peer, peerId, requestId, json2) {
81288
81353
  }
81289
81354
  return true;
81290
81355
  }
81356
+ function parseChunkedJsonMessage(peerId, parsed) {
81357
+ const chunkType = typeof parsed?.type === "string" ? parsed.type : "";
81358
+ if (!chunkType.endsWith("_chunk")) return parsed;
81359
+ const chunkId = typeof parsed?.chunkId === "string" ? parsed.chunkId : "";
81360
+ const id = typeof parsed?.id === "string" ? parsed.id : "";
81361
+ const index = Number(parsed?.index);
81362
+ const total = Number(parsed?.total);
81363
+ const data = typeof parsed?.data === "string" ? parsed.data : "";
81364
+ if (!chunkId || !Number.isInteger(index) || !Number.isInteger(total) || index < 0 || total <= 0 || total > MAX_JSON_CHUNKS || index >= total || !data) {
81365
+ log(`chunked JSON ignored: peer=${peerId} type=${chunkType || "unknown"} reason=malformed`);
81366
+ return null;
81367
+ }
81368
+ const now = Date.now();
81369
+ incomingJsonChunks.forEach((entry2, key2) => {
81370
+ if (now - entry2.createdAt > JSON_CHUNK_TTL_MS) incomingJsonChunks.delete(key2);
81371
+ });
81372
+ const key = `${peerId}:${chunkId}`;
81373
+ let entry = incomingJsonChunks.get(key);
81374
+ if (!entry || entry.total !== total || entry.type !== chunkType) {
81375
+ entry = { total, chunks: new Array(total).fill(""), received: 0, createdAt: now, type: chunkType, id };
81376
+ incomingJsonChunks.set(key, entry);
81377
+ }
81378
+ if (!entry.chunks[index]) {
81379
+ entry.chunks[index] = data;
81380
+ entry.received += 1;
81381
+ }
81382
+ if (entry.received < entry.total) return null;
81383
+ incomingJsonChunks.delete(key);
81384
+ try {
81385
+ return JSON.parse(entry.chunks.join(""));
81386
+ } catch (error48) {
81387
+ log(`chunked JSON parse failed: peer=${peerId} type=${chunkType} id=${entry.id || "-"} error=${error48?.message || error48}`);
81388
+ return CHUNK_PARSE_FAILED;
81389
+ }
81390
+ }
81291
81391
  function routeDataChannelMessage(peerId, msg, peers, handlers) {
81292
81392
  const text = typeof msg === "string" ? msg : msg.toString("utf-8");
81293
81393
  try {
81294
- const parsed = JSON.parse(text);
81394
+ let parsed = JSON.parse(text);
81395
+ const chunked = parseChunkedJsonMessage(peerId, parsed);
81396
+ if (chunked === null) return;
81397
+ if (chunked === CHUNK_PARSE_FAILED) {
81398
+ const peer = peers.get(peerId);
81399
+ const id = typeof parsed?.id === "string" ? parsed.id : "";
81400
+ if (parsed?.type === "command_chunk") {
81401
+ sendToPeer(peer, { type: "command_result", id, success: false, error: "Failed to reassemble chunked command" });
81402
+ } else if (id) {
81403
+ sendToPeer(peer, { id, type: "response", success: false, error: "Failed to reassemble chunked request" });
81404
+ }
81405
+ return;
81406
+ }
81407
+ parsed = chunked;
81295
81408
  if (parsed.type !== "command" && parsed.type !== "pty_input" && parsed.type !== "pty_resize" && parsed.type !== "ping" && parsed.type !== "pong") {
81296
81409
  logDebug(`Files message from peer ${peerId}: type=${parsed.type}`);
81297
81410
  }
@@ -81587,7 +81700,7 @@ async function handleFileRequest(peerId, req, peers, handlers) {
81587
81700
  }
81588
81701
  sendToPeer(peer, response);
81589
81702
  }
81590
- var MAX_INLINE_JSON_MESSAGE_CHARS, JSON_CHUNK_PAYLOAD_CHARS;
81703
+ var MAX_INLINE_JSON_MESSAGE_CHARS, MAX_INLINE_JSON_MESSAGE_BYTES, JSON_CHUNK_PAYLOAD_CHARS, JSON_CHUNK_TTL_MS, MAX_JSON_CHUNKS, CHUNK_PARSE_FAILED, incomingJsonChunks;
81591
81704
  var init_data_channel_router = __esm({
81592
81705
  "src/daemon-p2p/data-channel-router.ts"() {
81593
81706
  "use strict";
@@ -81595,18 +81708,23 @@ var init_data_channel_router = __esm({
81595
81708
  init_permission();
81596
81709
  init_log();
81597
81710
  MAX_INLINE_JSON_MESSAGE_CHARS = 6e4;
81598
- JSON_CHUNK_PAYLOAD_CHARS = 32e3;
81711
+ MAX_INLINE_JSON_MESSAGE_BYTES = 6e4;
81712
+ JSON_CHUNK_PAYLOAD_CHARS = 16e3;
81713
+ JSON_CHUNK_TTL_MS = 6e4;
81714
+ MAX_JSON_CHUNKS = 1024;
81715
+ CHUNK_PARSE_FAILED = /* @__PURE__ */ Symbol("chunk_parse_failed");
81716
+ incomingJsonChunks = /* @__PURE__ */ new Map();
81599
81717
  }
81600
81718
  });
81601
81719
 
81602
81720
  // src/daemon-p2p/screenshot-sender.ts
81603
- var CHUNK_SIZE, MAX_INLINE_JSON_MESSAGE_BYTES, JSON_CHUNK_PAYLOAD_CHARS2, ScreenshotSender;
81721
+ var CHUNK_SIZE, MAX_INLINE_JSON_MESSAGE_BYTES2, JSON_CHUNK_PAYLOAD_CHARS2, ScreenshotSender;
81604
81722
  var init_screenshot_sender = __esm({
81605
81723
  "src/daemon-p2p/screenshot-sender.ts"() {
81606
81724
  "use strict";
81607
81725
  init_log();
81608
81726
  CHUNK_SIZE = 6e4;
81609
- MAX_INLINE_JSON_MESSAGE_BYTES = 6e4;
81727
+ MAX_INLINE_JSON_MESSAGE_BYTES2 = 6e4;
81610
81728
  JSON_CHUNK_PAYLOAD_CHARS2 = 16e3;
81611
81729
  ScreenshotSender = class {
81612
81730
  _ssDebugDone = false;
@@ -81650,7 +81768,7 @@ var init_screenshot_sender = __esm({
81650
81768
  type: "topic_update",
81651
81769
  update
81652
81770
  });
81653
- if (Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES) {
81771
+ if (Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES2) {
81654
81772
  return this.sendChunkedTopicUpdate(peer, update, json2);
81655
81773
  }
81656
81774
  try {
@@ -81689,6 +81807,10 @@ var init_screenshot_sender = __esm({
81689
81807
  let sentAny = false;
81690
81808
  for (const peer of peers.values()) {
81691
81809
  if (peer.state !== "connected" || !peer.dataChannel?.isOpen()) continue;
81810
+ if (Buffer.byteLength(msg, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES2) {
81811
+ if (this.sendChunkedSessionOutput(peer, sessionId, msg)) sentAny = true;
81812
+ continue;
81813
+ }
81692
81814
  try {
81693
81815
  peer.dataChannel.sendMessage(msg);
81694
81816
  sentAny = true;
@@ -81697,6 +81819,27 @@ var init_screenshot_sender = __esm({
81697
81819
  }
81698
81820
  return sentAny;
81699
81821
  }
81822
+ sendChunkedSessionOutput(peer, sessionId, json2) {
81823
+ const chunkId = `session_output:${sessionId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`;
81824
+ const total = Math.ceil(json2.length / JSON_CHUNK_PAYLOAD_CHARS2);
81825
+ logDebug(`session_output chunked: peer=${peer.peerId || "unknown"} sessionId=${sessionId || "-"} chars=${json2.length} chunks=${total}`);
81826
+ for (let index = 0; index < total; index += 1) {
81827
+ const chunk = json2.slice(index * JSON_CHUNK_PAYLOAD_CHARS2, (index + 1) * JSON_CHUNK_PAYLOAD_CHARS2);
81828
+ try {
81829
+ peer.dataChannel?.sendMessage(JSON.stringify({
81830
+ type: "session_output_chunk",
81831
+ sessionId,
81832
+ chunkId,
81833
+ index,
81834
+ total,
81835
+ data: chunk
81836
+ }));
81837
+ } catch {
81838
+ return false;
81839
+ }
81840
+ }
81841
+ return true;
81842
+ }
81700
81843
  sendScreenshot(peers, base64Data, targetSessionId) {
81701
81844
  const buffer = Buffer.from(base64Data, "base64");
81702
81845
  return this.sendScreenshotBuffer(peers, buffer, targetSessionId);
@@ -90036,7 +90179,7 @@ var init_adhdev_daemon = __esm({
90036
90179
  init_version();
90037
90180
  init_src();
90038
90181
  init_runtime_defaults();
90039
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.55" });
90182
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.56" });
90040
90183
  AdhdevDaemon = class _AdhdevDaemon {
90041
90184
  localHttpServer = null;
90042
90185
  localWss = null;