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/index.js CHANGED
@@ -13748,6 +13748,12 @@ var init_provider_cli_adapter = __esm({
13748
13748
  accumulatedRawBuffer = "";
13749
13749
  /** Current visible terminal screen snapshot */
13750
13750
  terminalScreen = new TerminalScreen(24, 80);
13751
+ static MAX_RESPONSE_BUFFER = 8e3;
13752
+ static MAX_RECENT_OUTPUT_BUFFER = 1e3;
13753
+ responseBufferDroppedChars = 0;
13754
+ recentOutputDroppedChars = 0;
13755
+ accumulatedBufferDroppedChars = 0;
13756
+ accumulatedRawBufferDroppedChars = 0;
13751
13757
  /** Max accumulated buffer size. Sized to comfortably hold a single long
13752
13758
  * Hermes turn (tool calls + reasoning + final bubble) without the
13753
13759
  * rolling window pushing the turn's ╭─ opening line out of view. */
@@ -13765,6 +13771,23 @@ var init_provider_cli_adapter = __esm({
13765
13771
  providerResolutionMeta;
13766
13772
  static FINISH_RETRY_DELAY_MS = 300;
13767
13773
  static MAX_FINISH_RETRIES = 2;
13774
+ getBufferState() {
13775
+ const build = (droppedChars, maxChars) => droppedChars > 0 ? { truncated: true, droppedChars, maxChars } : void 0;
13776
+ const responseBuffer = build(this.responseBufferDroppedChars, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
13777
+ const recentOutputBuffer = build(this.recentOutputDroppedChars, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
13778
+ const accumulatedBuffer = build(this.accumulatedBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
13779
+ const accumulatedRawBuffer = build(this.accumulatedRawBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
13780
+ if (!responseBuffer && !recentOutputBuffer && !accumulatedBuffer && !accumulatedRawBuffer) return void 0;
13781
+ return {
13782
+ ...responseBuffer ? { responseBuffer } : {},
13783
+ ...recentOutputBuffer ? { recentOutputBuffer } : {},
13784
+ ...accumulatedBuffer ? { accumulatedBuffer } : {},
13785
+ ...accumulatedRawBuffer ? { accumulatedRawBuffer } : {}
13786
+ };
13787
+ }
13788
+ recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
13789
+ return Math.max(0, previousLength + appendedLength - nextLength);
13790
+ }
13768
13791
  buildCommittedMessagesActivitySignature() {
13769
13792
  const last = this.committedMessages[this.committedMessages.length - 1];
13770
13793
  return [
@@ -14130,7 +14153,9 @@ var init_provider_cli_adapter = __esm({
14130
14153
  this.scheduleStartupSettleCheck();
14131
14154
  }
14132
14155
  if (this.isWaitingForResponse && cleanData) {
14133
- this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, 8e3);
14156
+ const previousResponseLen = this.responseBuffer.length;
14157
+ this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
14158
+ this.responseBufferDroppedChars += this.recordBoundedAppendDrop(previousResponseLen, cleanData.length, this.responseBuffer.length);
14134
14159
  }
14135
14160
  if (cleanData.trim()) {
14136
14161
  if (this.serverConn) {
@@ -14139,14 +14164,19 @@ var init_provider_cli_adapter = __esm({
14139
14164
  this.logBuffer.push({ message: cleanData.trim(), level: "info" });
14140
14165
  }
14141
14166
  }
14167
+ const prevRecentLen = this.recentOutputBuffer.length;
14142
14168
  const prevAccumulatedLen = this.accumulatedBuffer.length;
14143
14169
  const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
14144
- this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, 1e3);
14170
+ this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
14145
14171
  this.accumulatedBuffer = appendBoundedText(this.accumulatedBuffer, cleanData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
14146
14172
  this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
14173
+ const droppedRecent = this.recordBoundedAppendDrop(prevRecentLen, cleanData.length, this.recentOutputBuffer.length);
14174
+ const droppedClean = this.recordBoundedAppendDrop(prevAccumulatedLen, cleanData.length, this.accumulatedBuffer.length);
14175
+ const droppedRaw = this.recordBoundedAppendDrop(prevAccumulatedRawLen, rawData.length, this.accumulatedRawBuffer.length);
14176
+ this.recentOutputDroppedChars += droppedRecent;
14177
+ this.accumulatedBufferDroppedChars += droppedClean;
14178
+ this.accumulatedRawBufferDroppedChars += droppedRaw;
14147
14179
  if (this.currentTurnScope) {
14148
- const droppedClean = prevAccumulatedLen + cleanData.length - this.accumulatedBuffer.length;
14149
- const droppedRaw = prevAccumulatedRawLen + rawData.length - this.accumulatedRawBuffer.length;
14150
14180
  if (droppedClean > 0) {
14151
14181
  this.currentTurnScope.bufferStart = Math.max(0, this.currentTurnScope.bufferStart - droppedClean);
14152
14182
  }
@@ -14976,13 +15006,15 @@ var init_provider_cli_adapter = __esm({
14976
15006
  effectiveModal = parsedModal;
14977
15007
  }
14978
15008
  }
15009
+ const bufferState = this.getBufferState();
14979
15010
  return {
14980
15011
  status: effectiveStatus,
14981
15012
  messages: [...this.committedMessages],
14982
15013
  workingDir: this.workingDir,
14983
15014
  activeModal: effectiveModal,
14984
15015
  errorMessage: this.parseErrorMessage || void 0,
14985
- errorReason: this.parseErrorMessage ? "parse_error" : void 0
15016
+ errorReason: this.parseErrorMessage ? "parse_error" : void 0,
15017
+ ...bufferState ? { bufferState } : {}
14986
15018
  };
14987
15019
  }
14988
15020
  seedCommittedMessages(messages) {
@@ -15164,10 +15196,12 @@ var init_provider_cli_adapter = __esm({
15164
15196
  messages: hydratedMessages,
15165
15197
  activeModal: parsed.activeModal ?? this.activeModal,
15166
15198
  providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
15199
+ ...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
15167
15200
  ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
15168
15201
  };
15169
15202
  } else {
15170
15203
  const messages = [...this.committedMessages];
15204
+ const bufferState = this.getBufferState();
15171
15205
  result = {
15172
15206
  id: "cli_session",
15173
15207
  status: this.currentStatus,
@@ -15178,7 +15212,8 @@ var init_provider_cli_adapter = __esm({
15178
15212
  index: typeof message.index === "number" ? message.index : index,
15179
15213
  receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
15180
15214
  })),
15181
- activeModal: this.activeModal
15215
+ activeModal: this.activeModal,
15216
+ ...bufferState ? { bufferState } : {}
15182
15217
  };
15183
15218
  }
15184
15219
  const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
@@ -49617,7 +49652,7 @@ function sendToPeer(peer, data) {
49617
49652
  return false;
49618
49653
  }
49619
49654
  const json2 = JSON.stringify(data);
49620
- if (messageType === "command_result" && json2.length > MAX_INLINE_JSON_MESSAGE_CHARS) {
49655
+ if (messageType === "command_result" && Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_CHARS) {
49621
49656
  return sendChunkedCommandResult(peer, peerId, requestId, json2);
49622
49657
  }
49623
49658
  try {
@@ -49630,21 +49665,51 @@ function sendToPeer(peer, data) {
49630
49665
  return false;
49631
49666
  }
49632
49667
  }
49668
+ function buildCommandResultChunkEnvelope(requestId, chunkId, index, total, data) {
49669
+ return JSON.stringify({
49670
+ type: "command_result_chunk",
49671
+ id: requestId,
49672
+ chunkId,
49673
+ index,
49674
+ total,
49675
+ data
49676
+ });
49677
+ }
49678
+ function splitJsonIntoCommandResultChunks(json2, requestId, chunkId) {
49679
+ const chunks = [];
49680
+ let offset = 0;
49681
+ while (offset < json2.length) {
49682
+ let end = Math.min(json2.length, offset + JSON_CHUNK_PAYLOAD_CHARS);
49683
+ while (end > offset) {
49684
+ const candidate = json2.slice(offset, end);
49685
+ const envelope = buildCommandResultChunkEnvelope(requestId, chunkId, chunks.length, MAX_JSON_CHUNKS, candidate);
49686
+ if (Buffer.byteLength(envelope, "utf8") <= MAX_INLINE_JSON_MESSAGE_BYTES) break;
49687
+ end = offset + Math.max(1, Math.floor((end - offset) * 0.8));
49688
+ }
49689
+ chunks.push(json2.slice(offset, end));
49690
+ if (chunks.length > MAX_JSON_CHUNKS) return [];
49691
+ offset = end;
49692
+ }
49693
+ return chunks;
49694
+ }
49633
49695
  function sendChunkedCommandResult(peer, peerId, requestId, json2) {
49634
49696
  const chunkId = requestId || `command_result_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
49635
- const total = Math.ceil(json2.length / JSON_CHUNK_PAYLOAD_CHARS);
49697
+ const chunks = splitJsonIntoCommandResultChunks(json2, requestId, chunkId);
49698
+ const total = chunks.length;
49699
+ if (total === 0 || total > MAX_JSON_CHUNKS) {
49700
+ log(`command_result send failed: peer=${peerId} id=${requestId || "-"} reason=too_many_chunks chunks=${total || "unknown"}`);
49701
+ return false;
49702
+ }
49636
49703
  logDebug(`command_result chunked: peer=${peerId} id=${requestId || "-"} chars=${json2.length} chunks=${total}`);
49637
49704
  for (let index = 0; index < total; index += 1) {
49638
- const chunk = json2.slice(index * JSON_CHUNK_PAYLOAD_CHARS, (index + 1) * JSON_CHUNK_PAYLOAD_CHARS);
49705
+ const chunk = chunks[index] || "";
49639
49706
  try {
49640
- peer.dataChannel?.sendMessage(JSON.stringify({
49641
- type: "command_result_chunk",
49642
- id: requestId,
49643
- chunkId,
49644
- index,
49645
- total,
49646
- data: chunk
49647
- }));
49707
+ const envelope = buildCommandResultChunkEnvelope(requestId, chunkId, index, total, chunk);
49708
+ if (Buffer.byteLength(envelope, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES) {
49709
+ log(`command_result send failed: peer=${peerId} id=${requestId || "-"} chunk=${index + 1}/${total} reason=chunk_too_large`);
49710
+ return false;
49711
+ }
49712
+ peer.dataChannel?.sendMessage(envelope);
49648
49713
  } catch (error48) {
49649
49714
  log(`command_result send failed: peer=${peerId} id=${requestId || "-"} chunk=${index + 1}/${total} error=${error48?.message || error48}`);
49650
49715
  return false;
@@ -49652,10 +49717,58 @@ function sendChunkedCommandResult(peer, peerId, requestId, json2) {
49652
49717
  }
49653
49718
  return true;
49654
49719
  }
49720
+ function parseChunkedJsonMessage(peerId, parsed) {
49721
+ const chunkType = typeof parsed?.type === "string" ? parsed.type : "";
49722
+ if (!chunkType.endsWith("_chunk")) return parsed;
49723
+ const chunkId = typeof parsed?.chunkId === "string" ? parsed.chunkId : "";
49724
+ const id = typeof parsed?.id === "string" ? parsed.id : "";
49725
+ const index = Number(parsed?.index);
49726
+ const total = Number(parsed?.total);
49727
+ const data = typeof parsed?.data === "string" ? parsed.data : "";
49728
+ if (!chunkId || !Number.isInteger(index) || !Number.isInteger(total) || index < 0 || total <= 0 || total > MAX_JSON_CHUNKS || index >= total || !data) {
49729
+ log(`chunked JSON ignored: peer=${peerId} type=${chunkType || "unknown"} reason=malformed`);
49730
+ return null;
49731
+ }
49732
+ const now = Date.now();
49733
+ incomingJsonChunks.forEach((entry2, key2) => {
49734
+ if (now - entry2.createdAt > JSON_CHUNK_TTL_MS) incomingJsonChunks.delete(key2);
49735
+ });
49736
+ const key = `${peerId}:${chunkId}`;
49737
+ let entry = incomingJsonChunks.get(key);
49738
+ if (!entry || entry.total !== total || entry.type !== chunkType) {
49739
+ entry = { total, chunks: new Array(total).fill(""), received: 0, createdAt: now, type: chunkType, id };
49740
+ incomingJsonChunks.set(key, entry);
49741
+ }
49742
+ if (!entry.chunks[index]) {
49743
+ entry.chunks[index] = data;
49744
+ entry.received += 1;
49745
+ }
49746
+ if (entry.received < entry.total) return null;
49747
+ incomingJsonChunks.delete(key);
49748
+ try {
49749
+ return JSON.parse(entry.chunks.join(""));
49750
+ } catch (error48) {
49751
+ log(`chunked JSON parse failed: peer=${peerId} type=${chunkType} id=${entry.id || "-"} error=${error48?.message || error48}`);
49752
+ return CHUNK_PARSE_FAILED;
49753
+ }
49754
+ }
49655
49755
  function routeDataChannelMessage(peerId, msg, peers, handlers) {
49656
49756
  const text = typeof msg === "string" ? msg : msg.toString("utf-8");
49657
49757
  try {
49658
- const parsed = JSON.parse(text);
49758
+ let parsed = JSON.parse(text);
49759
+ const chunked = parseChunkedJsonMessage(peerId, parsed);
49760
+ if (chunked === null) return;
49761
+ if (chunked === CHUNK_PARSE_FAILED) {
49762
+ const peer = peers.get(peerId);
49763
+ const id = typeof parsed?.id === "string" ? parsed.id : "";
49764
+ if (parsed?.type === "command_chunk") {
49765
+ sendToPeer(peer, { type: "command_result", id, success: false, error: "Failed to reassemble chunked command" });
49766
+ } else if (id) {
49767
+ sendToPeer(peer, { id, type: "response", success: false, error: "Failed to reassemble chunked request" });
49768
+ }
49769
+ return;
49770
+ }
49771
+ parsed = chunked;
49659
49772
  if (parsed.type !== "command" && parsed.type !== "pty_input" && parsed.type !== "pty_resize" && parsed.type !== "ping" && parsed.type !== "pong") {
49660
49773
  logDebug(`Files message from peer ${peerId}: type=${parsed.type}`);
49661
49774
  }
@@ -49951,7 +50064,7 @@ async function handleFileRequest(peerId, req, peers, handlers) {
49951
50064
  }
49952
50065
  sendToPeer(peer, response);
49953
50066
  }
49954
- var MAX_INLINE_JSON_MESSAGE_CHARS, JSON_CHUNK_PAYLOAD_CHARS;
50067
+ 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;
49955
50068
  var init_data_channel_router = __esm({
49956
50069
  "src/daemon-p2p/data-channel-router.ts"() {
49957
50070
  "use strict";
@@ -49959,18 +50072,23 @@ var init_data_channel_router = __esm({
49959
50072
  init_permission();
49960
50073
  init_log();
49961
50074
  MAX_INLINE_JSON_MESSAGE_CHARS = 6e4;
49962
- JSON_CHUNK_PAYLOAD_CHARS = 32e3;
50075
+ MAX_INLINE_JSON_MESSAGE_BYTES = 6e4;
50076
+ JSON_CHUNK_PAYLOAD_CHARS = 16e3;
50077
+ JSON_CHUNK_TTL_MS = 6e4;
50078
+ MAX_JSON_CHUNKS = 1024;
50079
+ CHUNK_PARSE_FAILED = /* @__PURE__ */ Symbol("chunk_parse_failed");
50080
+ incomingJsonChunks = /* @__PURE__ */ new Map();
49963
50081
  }
49964
50082
  });
49965
50083
 
49966
50084
  // src/daemon-p2p/screenshot-sender.ts
49967
- var CHUNK_SIZE, MAX_INLINE_JSON_MESSAGE_BYTES, JSON_CHUNK_PAYLOAD_CHARS2, ScreenshotSender;
50085
+ var CHUNK_SIZE, MAX_INLINE_JSON_MESSAGE_BYTES2, JSON_CHUNK_PAYLOAD_CHARS2, ScreenshotSender;
49968
50086
  var init_screenshot_sender = __esm({
49969
50087
  "src/daemon-p2p/screenshot-sender.ts"() {
49970
50088
  "use strict";
49971
50089
  init_log();
49972
50090
  CHUNK_SIZE = 6e4;
49973
- MAX_INLINE_JSON_MESSAGE_BYTES = 6e4;
50091
+ MAX_INLINE_JSON_MESSAGE_BYTES2 = 6e4;
49974
50092
  JSON_CHUNK_PAYLOAD_CHARS2 = 16e3;
49975
50093
  ScreenshotSender = class {
49976
50094
  _ssDebugDone = false;
@@ -50014,7 +50132,7 @@ var init_screenshot_sender = __esm({
50014
50132
  type: "topic_update",
50015
50133
  update
50016
50134
  });
50017
- if (Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES) {
50135
+ if (Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES2) {
50018
50136
  return this.sendChunkedTopicUpdate(peer, update, json2);
50019
50137
  }
50020
50138
  try {
@@ -50053,6 +50171,10 @@ var init_screenshot_sender = __esm({
50053
50171
  let sentAny = false;
50054
50172
  for (const peer of peers.values()) {
50055
50173
  if (peer.state !== "connected" || !peer.dataChannel?.isOpen()) continue;
50174
+ if (Buffer.byteLength(msg, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES2) {
50175
+ if (this.sendChunkedSessionOutput(peer, sessionId, msg)) sentAny = true;
50176
+ continue;
50177
+ }
50056
50178
  try {
50057
50179
  peer.dataChannel.sendMessage(msg);
50058
50180
  sentAny = true;
@@ -50061,6 +50183,27 @@ var init_screenshot_sender = __esm({
50061
50183
  }
50062
50184
  return sentAny;
50063
50185
  }
50186
+ sendChunkedSessionOutput(peer, sessionId, json2) {
50187
+ const chunkId = `session_output:${sessionId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`;
50188
+ const total = Math.ceil(json2.length / JSON_CHUNK_PAYLOAD_CHARS2);
50189
+ logDebug(`session_output chunked: peer=${peer.peerId || "unknown"} sessionId=${sessionId || "-"} chars=${json2.length} chunks=${total}`);
50190
+ for (let index = 0; index < total; index += 1) {
50191
+ const chunk = json2.slice(index * JSON_CHUNK_PAYLOAD_CHARS2, (index + 1) * JSON_CHUNK_PAYLOAD_CHARS2);
50192
+ try {
50193
+ peer.dataChannel?.sendMessage(JSON.stringify({
50194
+ type: "session_output_chunk",
50195
+ sessionId,
50196
+ chunkId,
50197
+ index,
50198
+ total,
50199
+ data: chunk
50200
+ }));
50201
+ } catch {
50202
+ return false;
50203
+ }
50204
+ }
50205
+ return true;
50206
+ }
50064
50207
  sendScreenshot(peers, base64Data, targetSessionId) {
50065
50208
  const buffer = Buffer.from(base64Data, "base64");
50066
50209
  return this.sendScreenshotBuffer(peers, buffer, targetSessionId);
@@ -58894,7 +59037,7 @@ var init_adhdev_daemon = __esm({
58894
59037
  init_version();
58895
59038
  init_src();
58896
59039
  init_runtime_defaults();
58897
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.55" });
59040
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.56" });
58898
59041
  AdhdevDaemon = class _AdhdevDaemon {
58899
59042
  localHttpServer = null;
58900
59043
  localWss = null;