// Force strict mode and setup for ESM
"use strict";
import {
  init_esbuild_shims
} from "./chunk-A4BMJM77.js";
import {
  __name
} from "./chunk-J2S4EL5Y.js";

// packages/acp-bridge/src/ndJsonStream.ts
init_esbuild_shims();
function ndJsonStream(output, input, hooks) {
  const textEncoder = new TextEncoder();
  const textDecoder = new TextDecoder();
  const readable = new ReadableStream({
    async start(controller) {
      const pending = [];
      const reader = input.getReader();
      try {
        while (true) {
          const { value, done } = await reader.read();
          if (done) break;
          if (!value) continue;
          readChunk(value, pending, controller, textDecoder, hooks);
        }
      } finally {
        reader.releaseLock();
        controller.close();
      }
    }
  });
  const writable = new WritableStream({
    async write(message) {
      const content = JSON.stringify(message);
      const payload = textEncoder.encode(content);
      const frame = new Uint8Array(payload.byteLength + 1);
      frame.set(payload);
      frame[payload.byteLength] = 10;
      const writer = output.getWriter();
      try {
        await writer.write(frame);
        callHook(hooks?.onMessageSent, payload.byteLength);
        callHook(hooks?.onMessageObserved, {
          direction: "sent",
          bytes: payload.byteLength,
          message
        });
      } finally {
        writer.releaseLock();
      }
    }
  });
  return { readable, writable };
}
__name(ndJsonStream, "ndJsonStream");
function readChunk(chunk, pending, controller, textDecoder, hooks) {
  let start = 0;
  let newline = chunk.indexOf(10, start);
  while (newline !== -1) {
    const lineBytes = takeLineBytes(pending, chunk.subarray(start, newline));
    handleLine(lineBytes, controller, textDecoder, hooks);
    start = newline + 1;
    newline = chunk.indexOf(10, start);
  }
  if (start < chunk.length) {
    pending.push(chunk.subarray(start));
  }
}
__name(readChunk, "readChunk");
function takeLineBytes(pending, current) {
  if (pending.length === 0) return current;
  const totalLength = pending.reduce((sum, part) => sum + part.byteLength, 0) + current.byteLength;
  const line = new Uint8Array(totalLength);
  let offset = 0;
  for (const part of pending) {
    line.set(part, offset);
    offset += part.byteLength;
  }
  line.set(current, offset);
  pending.length = 0;
  return line;
}
__name(takeLineBytes, "takeLineBytes");
function handleLine(lineBytes, controller, textDecoder, hooks) {
  const line = textDecoder.decode(lineBytes);
  const trimmedLine = line.trim();
  if (!trimmedLine) return;
  try {
    const message = JSON.parse(trimmedLine);
    controller.enqueue(message);
    const bytes = jsonPayloadByteLength(lineBytes);
    callHook(hooks?.onMessageReceived, bytes);
    callHook(hooks?.onMessageObserved, {
      direction: "received",
      bytes,
      message
    });
  } catch (err) {
    console.error("Failed to parse JSON message:", trimmedLine, err);
  }
}
__name(handleLine, "handleLine");
function jsonPayloadByteLength(lineBytes) {
  return lineBytes[lineBytes.byteLength - 1] === 13 ? lineBytes.byteLength - 1 : lineBytes.byteLength;
}
__name(jsonPayloadByteLength, "jsonPayloadByteLength");
function callHook(hook, value) {
  try {
    hook?.(value);
  } catch {
  }
}
__name(callHook, "callHook");

export {
  ndJsonStream
};
/**
 * @license
 * Copyright 2026 Qwen Team
 * SPDX-License-Identifier: Apache-2.0
 */
