"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// index.ts
var client_exports = {};
__export(client_exports, {
  BlockStreamToMarkdownStream: () => BlockStreamToMarkdownStream,
  BlockStreamToStreamingBlockStream: () => BlockStreamToStreamingBlockStream,
  FileEventStreamToBlockStream: () => FileEventStreamToBlockStream,
  Steamship: () => Steamship,
  SteamshipStream: () => SteamshipStream,
  default: () => client_default
});
module.exports = __toCommonJS(client_exports);

// src/client.ts
var import_eventsource_parser = require("eventsource-parser");

// src/operations/package.ts
var PackageClient = class {
  constructor(client) {
    this.client = client;
  }
  async createInstance(params) {
    if (!params.handle) {
      const workspace_ = await this.client.workspace.create({});
      params.handle = workspace_.handle;
    }
    const { version, handle, fetchIfExists = true, config } = params;
    const response = await this.client.post("package/instance/create", {
      packageHandle: params.package,
      packageVersionHandle: version,
      handle,
      fetchIfExists,
      config
    });
    const json = await response.json();
    return json?.packageInstance;
  }
  /**
   * Invoke a method on a package using its base_url.
   *
   * @param params
   * @param client
   */
  async invoke(params) {
    let base_url = params.base_url;
    if (!base_url) {
      throw new Error("base_url is required");
    }
    if (base_url[base_url.length - 1] != "/") {
      base_url = `${base_url}/`;
    }
    return await this.client.invokePackageMethod(base_url, params.method, {
      method: params.verb || "POST",
      body: JSON.stringify(params.payload || {}),
      json: true
    });
  }
};
var package_default = PackageClient;

// src/operations/agent.ts
var AgentClient = class {
  constructor(client) {
    this.client = client;
  }
  /**
   * Respond to the provided input asynchronously, returning a Task representing completion and a File object
   * in which the response will be asynchronously streamed.
   *
   * @param params
   */
  async respondAsync(params) {
    const resp = await this.client.package.invoke({
      base_url: params.url,
      method: "async_prompt",
      payload: params.input,
      verb: "POST"
    });
    const json = await resp.json();
    return json;
  }
  /**
   * Respond to the provided input synchronously, returning a list of Block objects.
   *
   * @param params
   */
  async respond(params) {
    const resp = await this.client.package.invoke({
      base_url: params.url,
      method: "prompt",
      payload: params.input,
      verb: "POST"
    });
    const json = await resp.json();
    return json;
  }
  /**
   * Respond to the provided input synchronously, returning a list of Block objects.
   *
   * @param params
   */
  async post(params) {
    return await this.client.package.invoke({
      base_url: params.url,
      method: params.path,
      payload: params.arguments,
      verb: "POST"
    });
  }
  /**
   * Respond to the provided input synchronously, returning a list of Block objects.
   *
   * @param params
   */
  async get(params) {
    return await this.client.package.invoke({
      base_url: params.url,
      method: params.path,
      payload: params.arguments,
      verb: "GET"
    });
  }
};
var agent_default = AgentClient;

// src/operations/workspace.ts
var WorkspaceClient = class {
  constructor(client) {
    this.client = client;
  }
  /**
   * Creates a new Workspace.
   *
   * @param params
   * @param client
   */
  async create(params) {
    const { handle, fetch_if_exists = true } = params;
    const response = await this.client.post("workspace/create", { handle, fetch_if_exists });
    const json = await response.json();
    return json?.workspace;
  }
};
var workspace_default = WorkspaceClient;

// src/operations/file.ts
var FileClient = class {
  constructor(client) {
    this.client = client;
  }
  /**
   * Creates a new Workspace.
   *
   * @param params
   */
  async stream(params) {
    return await this.client.eventStream(`file/${params.id}/stream`, {});
  }
  /**
   * Fetch the raw content of the file.
   *
   * @param params
   */
  async raw(params) {
    return await this.client.get(`file/${params.id}/raw`, {});
  }
  /**
   * Fetch a Steamship File.
   *
   * @param params
   */
  async get(params) {
    let response = await this.client.post(`file/get`, { id: params.id });
    let json = await response.json();
    return json?.file || json?.data?.file;
  }
};
var file_default = FileClient;

// src/operations/block.ts
var BlockClient = class {
  constructor(client) {
    this.client = client;
  }
  /**
   * Fetch the raw content of the block.
   *
   * @param params
   * @param client
   */
  async raw(params) {
    return await this.client.get(`block/${params.id}/raw`, {});
  }
  /**
   * Fetch the raw content of the block.
   *
   * @param params
   * @param client
   */
  async get(params) {
    try {
      let response = await this.client.post(`block/get`, { id: params.id });
      let json = await response.json();
      const block = json?.block || json?.data?.block;
      if (!block) {
        const delay = (ms) => new Promise((res) => setTimeout(res, ms));
        await delay(5e3);
        let response2 = await this.client.post(`block/get`, { id: params.id });
        let json2 = await response2.json();
        return json2?.block || json2?.data?.block;
      }
      return block;
    } catch (ex) {
      const delay = (ms) => new Promise((res) => setTimeout(res, ms));
      await delay(5e3);
      let response = await this.client.post(`block/get`, { id: params.id });
      let json = await response.json();
      return json?.block || json?.data?.block;
    }
  }
};
var block_default = BlockClient;

// src/base.ts
var ClientBase = class {
  constructor() {
    this.package = new package_default(this);
    this.workspace = new workspace_default(this);
    this.agent = new agent_default(this);
    this.block = new block_default(this);
    this.file = new file_default(this);
  }
};

// src/schema/client.ts
var API_BASE_PRODUCTION = "https://api.steamship.com/api/v1/";
var DEFAULT_CONFIGURATION = {
  apiBase: API_BASE_PRODUCTION,
  appBase: API_BASE_PRODUCTION
};

// src/client.ts
var Steamship = class _Steamship extends ClientBase {
  /**
   * Create a new Steamship API client.
   *
   * @param config
   */
  constructor(config) {
    super();
    this.config = { ...DEFAULT_CONFIGURATION, ...config };
  }
  workspaceHandleFromBaseUrl(baseUrl) {
    try {
      const urlParts = baseUrl.split("//");
      const domainAndPath = urlParts[1];
      const pathParts = domainAndPath.split("/");
      const workspace = pathParts[1];
      return workspace;
    } catch (ex) {
      throw Error(`Error trying to parse workspace handle out of base url: ${baseUrl}`);
    }
  }
  makeHeaders(props) {
    let _headers = {};
    if (this.config.apiKey) {
      _headers["Authorization"] = `Bearer ${this.config.apiKey}`;
    }
    if (props.json) {
      _headers["Content-Type"] = `application/json`;
    }
    if (props.workspace) {
      _headers["x-workspace-handle"] = props.workspace;
    } else if (props.workspaceId) {
      _headers["x-workspace-id"] = props.workspaceId;
    }
    return {
      ..._headers,
      ...props.existing
    };
  }
  /**
   * Return the fully-specified URL for an API path.
   *
   * @param path
   */
  url(path) {
    return `${this.config.apiBase}${path}`;
  }
  /**
   * Invoke an API method on a Steamship package.
   *
   * @param apiBase
   * @param path API Path rooted in apiBase provided in the configuration object.
   * @param opts Javascript `fetch` options. API Key and Content-Type are auto-applied.
   */
  async invokePackageMethod(apiBase, path, opts) {
    const workspace = this.workspaceHandleFromBaseUrl(apiBase);
    if (!opts.workspace) {
      opts.workspace = workspace;
    }
    const _url = `${apiBase}${path}`;
    opts["headers"] = this.makeHeaders({
      json: true,
      existing: opts.headers,
      workspace: opts.workspace || this.config.workspace,
      workspaceId: opts.workspaceId || this.config.workspaceId,
      baseUrl: opts.baseUrl
    });
    try {
      return await fetch(
        _url,
        opts
      );
    } catch (ex) {
      console.log(ex);
      throw ex;
    }
  }
  /**
   * Invoke an API method on Steamship.
   *
   * @param path API Path rooted in apiBase provided in the configuration object.
   * @param opts Javascript `fetch` options. API Key and Content-Type are auto-applied.
   */
  async invokeApi(path, opts) {
    const _url = this.url(path);
    opts["headers"] = this.makeHeaders({
      json: true,
      existing: opts.headers,
      workspace: opts.workspace || this.config.workspace,
      workspaceId: opts.workspaceId || this.config.workspaceId,
      baseUrl: opts.baseUrl
    });
    const resp = await fetch(_url, opts);
    return resp;
  }
  /**
   * Perform a `get` against the Steamship API.
   * @param path API Path rooted in apiBase provided in the configuration object.
   */
  async get(path) {
    return this.invokeApi(path, { method: "GET" });
  }
  /**
   * Perform a 'post' against the Steamship API
   * @param path API Path rooted in apiBase provided in the configuration object.
   * @param payload Payload, as a JSON object, to be provided as JSON to Steamship.
   */
  async post(path, payload) {
    return this.invokeApi(path, {
      method: "POST",
      body: JSON.stringify(payload)
    });
  }
  switchWorkspace({ workspace, workspaceId }) {
    let newConfig = { ...this.config };
    delete newConfig.workspace;
    delete newConfig.workspaceId;
    newConfig.workspace = workspace;
    newConfig.workspaceId = workspaceId;
    return new _Steamship(newConfig);
  }
  async eventStream(path, opts) {
    const res = await this.invokeApi(path, opts);
    const decoder4 = new TextDecoder();
    return new ReadableStream({
      async start(controller) {
        function onParse(event) {
          if (event.type === "event") {
            const data = event.data;
            try {
              let json = JSON.parse(data);
              if (json[event.event]) {
                json = json[event.event];
              }
              event.data = json;
              controller.enqueue(event);
            } catch (e) {
              controller.error(e);
            }
          } else {
            console.log("Parser encountered something other than an event");
          }
        }
        const parser = (0, import_eventsource_parser.createParser)(onParse);
        for await (const chunk of res.body) {
          parser.feed(decoder4.decode(chunk));
        }
        controller.close();
      }
    });
  }
};

// src/streaming/utils.ts
var decoder = new TextDecoder();
var isStreamTerminatingBlock = (block) => {
  for (const tag of block?.tags || []) {
    if (tag.kind == "agent-status-message" && tag.name == "request-complete") {
      return true;
    }
  }
  return false;
};

// src/streaming/block-stream-to-markdown-stream.ts
var decoder2 = new TextDecoder();
function BlockStreamToMarkdownStream(client) {
  return new TransformStream({
    transform(block, controller) {
      const blockId = block.id;
      if (!blockId) {
        controller.error(new Error("Empty Block ID"));
        return;
      }
      const contentUrl = client.url(`block/${blockId}/raw`);
      if (isStreamTerminatingBlock(block)) {
        controller.terminate();
        return;
      }
      if (block.mimeType?.startsWith("audio/")) {
        controller.enqueue(`[audio](${contentUrl})

`);
        return;
      } else if (block.mimeType?.startsWith("video/")) {
        controller.enqueue(`[video](${contentUrl})

`);
        return;
      } else if (block.mimeType?.startsWith("image/")) {
        controller.enqueue(`![image](${contentUrl})

`);
        return;
      } else {
        if (typeof block.text != "undefined") {
          if (block.text) {
            controller.enqueue(block.text + "\n\n");
          }
          return;
        }
        return new Promise(async (resolve, reject) => {
          try {
            const response = await client.block.raw({ id: blockId });
            if (!response.ok) {
              const error = new Error(
                `Got back error streaming block: ${await response.text()}`
              );
              controller.error(error);
              reject(error);
              return;
            }
            for await (const chunk of response.body) {
              const str = decoder2.decode(chunk);
              controller.enqueue(str);
            }
            controller.enqueue("\n\n");
            resolve();
          } catch (error) {
            controller.error(error);
            reject(error);
          }
        });
      }
    }
  });
}

// src/streaming/file-event-stream-to-block-stream.ts
var utf8Decoder = new TextDecoder("utf-8");
function FileEventStreamToBlockStream(client) {
  return new TransformStream({
    transform(event, controller) {
      const blockId = event.data.blockId;
      if (!blockId) {
        controller.error(new Error("Empty Block ID"));
        return;
      }
      try {
        client.block.get({ id: blockId }).then((block) => {
          return new Promise((resolve, reject) => {
            if (!block) {
              controller.error(new Error(`Block ID did not appear to exist ${blockId}`));
              reject();
              return;
            }
            controller.enqueue(block);
            resolve();
          });
        });
      } catch (e) {
        console.log(e);
        controller.error(e);
        return;
      }
    }
  });
}

// src/streaming/block-stream-to-streaming-block-stream.ts
var decoder3 = new TextDecoder();
function BlockStreamToStreamingBlockStream(client) {
  let streamingBlocks = {};
  let streamingPromises = {};
  let receivedStreamTermination = false;
  return new TransformStream({
    transform(block, controller) {
      const blockId = block.id;
      if (!blockId) {
        controller.error(new Error("Empty Block ID"));
        return;
      }
      const maybeHangup = () => {
        if (Object.keys(streamingBlocks).length == 0) {
          controller.terminate();
          return true;
        }
        return false;
      };
      if (isStreamTerminatingBlock(block)) {
        receivedStreamTermination = true;
        if (maybeHangup()) {
          return;
        }
      }
      controller.enqueue(JSON.stringify(block) + "\n");
      const isStreaming = block.streamState == "started";
      const isText = block.mimeType?.toLocaleLowerCase()?.includes("text") === true || block.mimeType?.toLocaleLowerCase()?.includes("markdown") === true;
      const shouldBeginUpdateStream = isStreaming && isText;
      if (!shouldBeginUpdateStream) {
        return;
      }
      streamingBlocks[blockId] = block;
      streamingPromises[blockId] = new Promise(
        async (resolve, reject) => {
          try {
            const response = await client.block.raw({ id: blockId });
            if (!response.ok) {
              const error = new Error(
                `Got back error streaming block: ${await response.text()}`
              );
              controller.error(error);
              reject(error);
              return;
            }
            for await (const chunk of response.body) {
              const str = decoder3.decode(chunk);
              streamingBlocks[blockId].text += str;
              controller.enqueue(
                JSON.stringify({
                  id: blockId,
                  text: streamingBlocks[blockId].text
                }) + "\n"
              );
            }
            delete streamingBlocks[blockId];
            maybeHangup();
            resolve();
          } catch (error) {
            controller.error(error);
            reject(error);
          }
        }
      );
    }
  });
}

// src/streaming/steamship-stream.ts
function _dictToURI(dict) {
  var str = [];
  for (var p in dict) {
    str.push(encodeURIComponent(p) + "=" + encodeURIComponent(dict[p]));
  }
  return str.join("&");
}
async function SteamshipStream(res, client, opts) {
  try {
    if ((res || {}).status?.state == "failed") {
      throw Error(`Exception from server: ${JSON.stringify(res)}`);
    }
    const chatFileId = res?.file?.id;
    const requestId = res?.task?.requestId || (res?.task || {})["request_id"];
    client = client.switchWorkspace({
      workspace: void 0,
      workspaceId: res?.file?.workspaceId || (res?.file || {}).workspace_id
    });
    let filterDict = {
      timeoutSeconds: opts?.streamTimeoutSeconds || 60
    };
    if (requestId) {
    }
    if (opts?.minDatetime) {
      filterDict["minDatetime"] = opts?.minDatetime;
    }
    const queryArgs = _dictToURI(filterDict);
    const _url = `file/${chatFileId}/stream?${queryArgs}`;
    const eventStream = await client.eventStream(_url, {});
    const blockStream = eventStream.pipeThrough(
      FileEventStreamToBlockStream(client)
    );
    if (opts?.format == "json") {
      return blockStream.pipeThrough(BlockStreamToStreamingBlockStream(client));
    } else {
      return blockStream.pipeThrough(BlockStreamToMarkdownStream(client));
    }
  } catch (ex) {
    console.log(ex);
    throw ex;
  }
}

// src/index.ts
var src_default = Steamship;

// index.ts
var client_default = src_default;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  BlockStreamToMarkdownStream,
  BlockStreamToStreamingBlockStream,
  FileEventStreamToBlockStream,
  Steamship,
  SteamshipStream
});
//# sourceMappingURL=index.js.map