getpatter 0.5.0 → 0.5.2

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
@@ -213,7 +213,7 @@ var init_elevenlabs_convai = __esm({
213
213
  init_logger();
214
214
  ELEVENLABS_CONVAI_URL = "wss://api.elevenlabs.io/v1/convai/conversation";
215
215
  ElevenLabsConvAIAdapter = class {
216
- constructor(apiKey, agentId = "", voiceId = "21m00Tcm4TlvDq8ikWAM", _modelId = "eleven_turbo_v2_5", _language = "en", firstMessage = "") {
216
+ constructor(apiKey, agentId = "", voiceId = "EXAVITQu4vr4xnSDxMaL", _modelId = "eleven_turbo_v2_5", _language = "en", firstMessage = "") {
217
217
  this.apiKey = apiKey;
218
218
  this.agentId = agentId;
219
219
  this.voiceId = voiceId;
@@ -2748,7 +2748,7 @@ async function queryDeepgramCost(metricsAcc, deepgramKey, deepgramRequestId) {
2748
2748
  const usd = reqData.response?.details?.usd;
2749
2749
  if (usd != null) {
2750
2750
  metricsAcc.setActualSttCost(usd);
2751
- getLogger().info(`Deepgram actual cost: $${usd}`);
2751
+ getLogger().debug(`Deepgram actual cost: $${usd}`);
2752
2752
  }
2753
2753
  }
2754
2754
  }
@@ -2816,7 +2816,7 @@ var init_stream_handler = __esm({
2816
2816
  ttsProvider: ttsProviderName,
2817
2817
  pricing: deps.pricing
2818
2818
  });
2819
- getLogger().info(`WebSocket connection opened (${deps.bridge.label})`);
2819
+ getLogger().debug(`WebSocket connection opened (${deps.bridge.label})`);
2820
2820
  }
2821
2821
  // ---------------------------------------------------------------------------
2822
2822
  // Public: called by the provider-specific parsers in server.ts
@@ -2832,9 +2832,12 @@ var init_stream_handler = __esm({
2832
2832
  this.metricsAcc.callId = callId;
2833
2833
  if (customParams.caller && !this.caller) this.caller = customParams.caller;
2834
2834
  if (customParams.callee && !this.callee) this.callee = customParams.callee;
2835
- getLogger().info(`Call started: ${callId}`);
2835
+ const mode = this.deps.agent.engine ? `engine=${this.deps.agent.engine.kind ?? "unknown"}` : "pipeline";
2836
+ getLogger().info(
2837
+ `Call started: ${callId} (${this.deps.bridge.label}, ${mode}, ${sanitizeLogValue(this.caller || "?")} \u2192 ${sanitizeLogValue(this.callee || "?")})`
2838
+ );
2836
2839
  if (Object.keys(customParams).length > 0) {
2837
- getLogger().info(`Custom params: ${sanitizeLogValue(JSON.stringify(customParams))}`);
2840
+ getLogger().debug(`Custom params: ${sanitizeLogValue(JSON.stringify(customParams))}`);
2838
2841
  }
2839
2842
  this.deps.metricsStore.recordCallStart({
2840
2843
  call_id: callId,
@@ -2882,7 +2885,7 @@ var init_stream_handler = __esm({
2882
2885
  }
2883
2886
  });
2884
2887
  if (recResp.ok) {
2885
- getLogger().info(`Recording started for ${callId}`);
2888
+ getLogger().debug(`Recording started for ${callId}`);
2886
2889
  } else {
2887
2890
  getLogger().warn(`could not start recording: ${await recResp.text()}`);
2888
2891
  }
@@ -2937,7 +2940,7 @@ var init_stream_handler = __esm({
2937
2940
  }
2938
2941
  /** Handle a DTMF keypress event (Twilio only). */
2939
2942
  async handleDtmf(digit) {
2940
- getLogger().info(`DTMF: ${digit}`);
2943
+ getLogger().debug(`DTMF: ${digit}`);
2941
2944
  if (this.adapter instanceof OpenAIRealtimeAdapter) {
2942
2945
  await this.adapter.sendText(`The user pressed key ${digit} on their phone keypad.`);
2943
2946
  }
@@ -2999,14 +3002,14 @@ var init_stream_handler = __esm({
2999
3002
  this.stt = await this.deps.bridge.createStt(this.deps.agent);
3000
3003
  this.tts = await createTTS(this.deps.agent);
3001
3004
  if (!this.stt) {
3002
- getLogger().info(`Pipeline mode (${label}): no STT configured`);
3005
+ getLogger().debug(`Pipeline mode (${label}): no STT configured`);
3003
3006
  }
3004
3007
  if (!this.tts) {
3005
- getLogger().info(`Pipeline mode (${label}): no TTS configured`);
3008
+ getLogger().debug(`Pipeline mode (${label}): no TTS configured`);
3006
3009
  }
3007
3010
  try {
3008
3011
  if (this.stt) await this.stt.connect();
3009
- getLogger().info(`Pipeline mode (${label}): STT + TTS connected`);
3012
+ getLogger().debug(`Pipeline mode (${label}): STT + TTS connected`);
3010
3013
  } catch (e) {
3011
3014
  getLogger().error(`Pipeline connect FAILED (${label}):`, e);
3012
3015
  try {
@@ -3039,7 +3042,24 @@ var init_stream_handler = __esm({
3039
3042
  this.history.push({ role: "assistant", text: this.deps.agent.firstMessage, timestamp: Date.now() });
3040
3043
  }
3041
3044
  }
3042
- if (!this.deps.onMessage && this.deps.config.openaiKey) {
3045
+ if (this.deps.agent.llm) {
3046
+ if (this.deps.onMessage) {
3047
+ throw new Error(
3048
+ "Cannot pass both agent({ llm }) and serve({ onMessage }). Pick one \u2014 `llm` for built-in LLMs, `onMessage` for custom logic."
3049
+ );
3050
+ }
3051
+ this.llmLoop = new LLMLoop(
3052
+ "",
3053
+ // apiKey unused when llmProvider is supplied
3054
+ "",
3055
+ // model unused when llmProvider is supplied
3056
+ resolvedPrompt,
3057
+ this.deps.agent.tools,
3058
+ this.deps.agent.llm
3059
+ );
3060
+ const llmLabel = this.deps.agent.llm.constructor?.name ?? "custom";
3061
+ getLogger().debug(`Built-in LLM loop active (pipeline, ${label}, llm=${llmLabel})`);
3062
+ } else if (!this.deps.onMessage && this.deps.config.openaiKey) {
3043
3063
  let llmModel = this.deps.agent.model || "gpt-4o-mini";
3044
3064
  if (llmModel.includes("realtime")) llmModel = "gpt-4o-mini";
3045
3065
  this.llmLoop = new LLMLoop(
@@ -3048,7 +3068,7 @@ var init_stream_handler = __esm({
3048
3068
  resolvedPrompt,
3049
3069
  this.deps.agent.tools
3050
3070
  );
3051
- getLogger().info(`Built-in LLM loop active (pipeline, ${label})`);
3071
+ getLogger().debug(`Built-in LLM loop active (pipeline, ${label})`);
3052
3072
  }
3053
3073
  if (this.stt) {
3054
3074
  this.stt.onTranscript(async (transcript) => {
@@ -3109,7 +3129,7 @@ var init_stream_handler = __esm({
3109
3129
  }
3110
3130
  async processTranscript(transcript) {
3111
3131
  if (transcript.text && this.isSpeaking) {
3112
- getLogger().info(
3132
+ getLogger().debug(
3113
3133
  `Barge-in: caller spoke over agent (${sanitizeLogValue(transcript.text.slice(0, 40))})`
3114
3134
  );
3115
3135
  this.isSpeaking = false;
@@ -3144,17 +3164,17 @@ var init_stream_handler = __esm({
3144
3164
  "cool"
3145
3165
  ]);
3146
3166
  if (HALLUCINATIONS.has(stripped) || stripped === "") {
3147
- getLogger().info(`Dropped likely STT hallucination: ${sanitizeLogValue(normalised.slice(0, 40))}`);
3167
+ getLogger().debug(`Dropped likely STT hallucination: ${sanitizeLogValue(normalised.slice(0, 40))}`);
3148
3168
  return;
3149
3169
  }
3150
3170
  if (sinceLastMs < 2e3 && normalised === this.lastCommitText) {
3151
- getLogger().info(
3171
+ getLogger().debug(
3152
3172
  `Dropped duplicate final transcript (${(sinceLastMs / 1e3).toFixed(1)}s since last): ${sanitizeLogValue(normalised.slice(0, 40))}`
3153
3173
  );
3154
3174
  return;
3155
3175
  }
3156
3176
  if (sinceLastMs < 500) {
3157
- getLogger().info(
3177
+ getLogger().debug(
3158
3178
  `Dropped back-to-back final transcript (${(sinceLastMs / 1e3).toFixed(2)}s since last): ${sanitizeLogValue(normalised.slice(0, 40))}`
3159
3179
  );
3160
3180
  return;
@@ -3162,7 +3182,7 @@ var init_stream_handler = __esm({
3162
3182
  this.lastCommitText = normalised;
3163
3183
  this.lastCommitAt = now;
3164
3184
  const label = this.deps.bridge.label;
3165
- getLogger().info(`User (${label} pipeline): ${sanitizeLogValue(transcript.text)}`);
3185
+ getLogger().debug(`User (${label} pipeline): ${sanitizeLogValue(transcript.text)}`);
3166
3186
  this.metricsAcc.startTurn();
3167
3187
  this.metricsAcc.recordSttComplete(transcript.text);
3168
3188
  if (this.deps.onTranscript) {
@@ -3177,7 +3197,7 @@ var init_stream_handler = __esm({
3177
3197
  const hookCtx = this.buildHookContext();
3178
3198
  const filteredTranscript = await hookExecutor.runAfterTranscribe(transcript.text, hookCtx);
3179
3199
  if (filteredTranscript === null) {
3180
- getLogger().info(`afterTranscribe hook vetoed turn (${label})`);
3200
+ getLogger().debug(`afterTranscribe hook vetoed turn (${label})`);
3181
3201
  this.metricsAcc.recordTurnInterrupted();
3182
3202
  return;
3183
3203
  }
@@ -3265,7 +3285,7 @@ var init_stream_handler = __esm({
3265
3285
  if (!this.llmLoop) {
3266
3286
  const guard = checkGuardrails(responseText, this.deps.agent.guardrails);
3267
3287
  if (guard) {
3268
- getLogger().info(`Guardrail '${guard.name}' triggered (pipeline)`);
3288
+ getLogger().debug(`Guardrail '${guard.name}' triggered (pipeline)`);
3269
3289
  responseText = guard.replacement ?? "I'm sorry, I can't respond to that.";
3270
3290
  }
3271
3291
  this.metricsAcc.recordLlmComplete();
@@ -3343,7 +3363,7 @@ var init_stream_handler = __esm({
3343
3363
  this.adapter = this.deps.buildAIAdapter(resolvedPrompt);
3344
3364
  try {
3345
3365
  await this.adapter.connect();
3346
- getLogger().info(`AI adapter connected (${label})`);
3366
+ getLogger().debug(`AI adapter connected (${label})`);
3347
3367
  } catch (e) {
3348
3368
  getLogger().error(`AI adapter connect FAILED (${label}):`, e);
3349
3369
  try {
@@ -3385,7 +3405,7 @@ var init_stream_handler = __esm({
3385
3405
  this.deps.bridge.sendMark(this.ws, `audio_${this.chunkCount}`, this.streamSid);
3386
3406
  } else if (type === "transcript_input") {
3387
3407
  const inputText = eventData;
3388
- getLogger().info(`User (${this.deps.bridge.label}): ${sanitizeLogValue(inputText)}`);
3408
+ getLogger().debug(`User (${this.deps.bridge.label}): ${sanitizeLogValue(inputText)}`);
3389
3409
  this.history.push({ role: "user", text: inputText, timestamp: Date.now() });
3390
3410
  this.metricsAcc.startTurn();
3391
3411
  this.currentAgentText = "";
@@ -3403,7 +3423,7 @@ var init_stream_handler = __esm({
3403
3423
  if (outputText) {
3404
3424
  const triggered = checkGuardrails(outputText, this.deps.agent.guardrails);
3405
3425
  if (triggered) {
3406
- getLogger().info(`Guardrail '${triggered.name}' triggered`);
3426
+ getLogger().debug(`Guardrail '${triggered.name}' triggered`);
3407
3427
  if (this.adapter instanceof OpenAIRealtimeAdapter) {
3408
3428
  this.adapter.cancelResponse();
3409
3429
  await this.adapter.sendText(triggered.replacement ?? "I'm sorry, I can't respond to that.");
@@ -3462,7 +3482,7 @@ var init_stream_handler = __esm({
3462
3482
  await adapter.sendFunctionResult(fc.call_id, JSON.stringify({ error: "Invalid phone number format", status: "rejected" }));
3463
3483
  return;
3464
3484
  }
3465
- getLogger().info(`Transferring call to ${transferTo}`);
3485
+ getLogger().debug(`Transferring call to ${transferTo}`);
3466
3486
  await adapter.sendFunctionResult(fc.call_id, JSON.stringify({ status: "transferring", to: transferTo }));
3467
3487
  await this.deps.bridge.transferCall(this.callId, transferTo);
3468
3488
  if (this.deps.onTranscript) {
@@ -3478,7 +3498,7 @@ var init_stream_handler = __esm({
3478
3498
  endArgs = {};
3479
3499
  }
3480
3500
  const reason = endArgs.reason ?? "conversation_complete";
3481
- getLogger().info(`Ending call (${this.deps.bridge.label}): ${reason}`);
3501
+ getLogger().debug(`Ending call (${this.deps.bridge.label}): ${reason}`);
3482
3502
  await adapter.sendFunctionResult(fc.call_id, JSON.stringify({ status: "ending", reason }));
3483
3503
  await this.deps.bridge.endCall(this.callId, this.ws);
3484
3504
  if (this.deps.onTranscript) {
@@ -3530,6 +3550,11 @@ var init_stream_handler = __esm({
3530
3550
  transcript: [...this.history.entries],
3531
3551
  metrics: finalMetrics
3532
3552
  };
3553
+ const cost = finalMetrics.cost?.total ?? 0;
3554
+ const latencyP95 = finalMetrics.latency_p95?.total_ms ?? 0;
3555
+ getLogger().info(
3556
+ `Call ended: ${this.callId} (${finalMetrics.duration_seconds.toFixed(1)}s, ${finalMetrics.turns.length} turns, cost=$${cost.toFixed(4)}, p95=${Math.round(latencyP95)}ms)`
3557
+ );
3533
3558
  this.deps.metricsStore.recordCallEnd(
3534
3559
  callEndData,
3535
3560
  finalMetrics
@@ -3631,7 +3656,7 @@ function buildAIAdapter(config, agent, resolvedPrompt) {
3631
3656
  return new ElevenLabsConvAIAdapter(
3632
3657
  engine.apiKey,
3633
3658
  engine.agentId,
3634
- agent.voice ?? "21m00Tcm4TlvDq8ikWAM",
3659
+ agent.voice ?? "EXAVITQu4vr4xnSDxMaL",
3635
3660
  "eleven_turbo_v2_5",
3636
3661
  agent.language ?? "en",
3637
3662
  agent.firstMessage ?? ""
@@ -3978,14 +4003,8 @@ var init_server = __esm({
3978
4003
  res.json({ status: "ok", mode: "local" });
3979
4004
  });
3980
4005
  if (this.dashboard) {
3981
- if (!this.dashboardToken) {
3982
- getLogger().warn(
3983
- "Dashboard is enabled without authentication. Set dashboardToken to protect call data. This is safe for local development but should not be exposed on a public network."
3984
- );
3985
- }
3986
4006
  mountDashboard(app, this.metricsStore, this.dashboardToken);
3987
4007
  mountApi(app, this.metricsStore, this.dashboardToken);
3988
- getLogger().info("Dashboard: http://127.0.0.1:" + port + "/");
3989
4008
  }
3990
4009
  app.post("/webhooks/twilio/status", (req, res) => {
3991
4010
  if (this.config.twilioToken) {
@@ -4202,7 +4221,6 @@ var init_server = __esm({
4202
4221
  socket.destroy();
4203
4222
  return;
4204
4223
  }
4205
- getLogger().info(`Upgrade request: ${req.url}`);
4206
4224
  this.wss.handleUpgrade(req, socket, head, (ws) => {
4207
4225
  wsConnectionsByIp.set(remoteIp, (wsConnectionsByIp.get(remoteIp) ?? 0) + 1);
4208
4226
  ws.once("close", () => {
@@ -4218,7 +4236,6 @@ var init_server = __esm({
4218
4236
  });
4219
4237
  this.wss.on("connection", (ws, req) => {
4220
4238
  const url = new URL(req.url ?? "", `http://localhost`);
4221
- getLogger().info(`WebSocket connected: ${req.url}`);
4222
4239
  this.activeConnections.add(ws);
4223
4240
  ws.once("close", () => {
4224
4241
  this.activeConnections.delete(ws);
@@ -4232,19 +4249,19 @@ var init_server = __esm({
4232
4249
  });
4233
4250
  await new Promise((resolve) => {
4234
4251
  this.server.listen(port, "127.0.0.1", () => {
4235
- getLogger().info(`
4236
- \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
4237
- \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
4238
- \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
4239
- \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
4240
- \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
4241
- \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
4242
-
4243
- Connect AI agents to phone numbers in 4 lines of code
4244
- `);
4245
4252
  getLogger().info(`Server on port ${port}`);
4246
4253
  getLogger().info(`Webhook: https://${this.config.webhookUrl}`);
4247
- getLogger().info(`Phone: ${this.config.phoneNumber}`);
4254
+ getLogger().info(`Phone: ${this.config.phoneNumber}`);
4255
+ if (this.dashboard) {
4256
+ console.log("\n\u2500\u2500\u2500\u2500 Dashboard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
4257
+ getLogger().info(`URL: http://127.0.0.1:${port}/`);
4258
+ if (!this.dashboardToken) {
4259
+ getLogger().warn(
4260
+ "Dashboard is enabled without authentication. Set dashboardToken to protect call data. This is safe for local development but should not be exposed on a public network."
4261
+ );
4262
+ }
4263
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
4264
+ }
4248
4265
  resolve();
4249
4266
  });
4250
4267
  });
@@ -4290,7 +4307,6 @@ Connect AI agents to phone numbers in 4 lines of code
4290
4307
  return;
4291
4308
  }
4292
4309
  const event = data.event;
4293
- getLogger().info(`WS event: ${event}`);
4294
4310
  if (event === "start") {
4295
4311
  handler.setStreamSid(data.streamSid ?? "");
4296
4312
  const callSid = data.start?.callSid ?? "";
@@ -4336,7 +4352,6 @@ Connect AI agents to phone numbers in 4 lines of code
4336
4352
  }
4337
4353
  const event = data.event ?? "";
4338
4354
  if (event === "connected") return;
4339
- getLogger().info(`Telnyx event: ${event}`);
4340
4355
  if (event === "start" && !streamStarted) {
4341
4356
  streamStarted = true;
4342
4357
  const callControlId = data.start?.call_control_id ?? "";
@@ -4438,829 +4453,28 @@ Connect AI agents to phone numbers in 4 lines of code
4438
4453
  }
4439
4454
  });
4440
4455
 
4441
- // node_modules/cloudflared/lib/constants.js
4442
- var require_constants = __commonJS({
4443
- "node_modules/cloudflared/lib/constants.js"(exports2, module2) {
4444
- "use strict";
4445
- var __create2 = Object.create;
4446
- var __defProp2 = Object.defineProperty;
4447
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
4448
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
4449
- var __getProtoOf2 = Object.getPrototypeOf;
4450
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
4451
- var __export2 = (target, all) => {
4452
- for (var name in all)
4453
- __defProp2(target, name, { get: all[name], enumerable: true });
4454
- };
4455
- var __copyProps2 = (to, from, except, desc) => {
4456
- if (from && typeof from === "object" || typeof from === "function") {
4457
- for (let key of __getOwnPropNames2(from))
4458
- if (!__hasOwnProp2.call(to, key) && key !== except)
4459
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
4460
- }
4461
- return to;
4462
- };
4463
- var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps2(
4464
- // If the importer is in node compatibility mode or this is not an ESM
4465
- // file that has been converted to a CommonJS file using a Babel-
4466
- // compatible transform (i.e. "__esModule" has not been set), then set
4467
- // "default" to the CommonJS "module.exports" for node compatibility.
4468
- isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target,
4469
- mod
4470
- ));
4471
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
4472
- var constants_exports = {};
4473
- __export2(constants_exports, {
4474
- CLOUDFLARED_VERSION: () => CLOUDFLARED_VERSION,
4475
- DEFAULT_CLOUDFLARED_BIN: () => DEFAULT_CLOUDFLARED_BIN,
4476
- RELEASE_BASE: () => RELEASE_BASE,
4477
- bin: () => bin,
4478
- use: () => use
4479
- });
4480
- module2.exports = __toCommonJS2(constants_exports);
4481
- var import_node_path = __toESM2(require("path"));
4482
- var DEFAULT_CLOUDFLARED_BIN = import_node_path.default.join(
4483
- __dirname,
4484
- "..",
4485
- "bin",
4486
- process.platform === "win32" ? "cloudflared.exe" : "cloudflared"
4487
- );
4488
- var bin = process.env.CLOUDFLARED_BIN || DEFAULT_CLOUDFLARED_BIN;
4489
- function use(executable) {
4490
- bin = executable;
4491
- }
4492
- var CLOUDFLARED_VERSION = process.env.CLOUDFLARED_VERSION || "latest";
4493
- var RELEASE_BASE = "https://github.com/cloudflare/cloudflared/releases/";
4494
- }
4495
- });
4496
-
4497
- // node_modules/cloudflared/lib/error.js
4498
- var require_error = __commonJS({
4499
- "node_modules/cloudflared/lib/error.js"(exports2, module2) {
4500
- "use strict";
4501
- var __defProp2 = Object.defineProperty;
4502
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
4503
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
4504
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
4505
- var __export2 = (target, all) => {
4506
- for (var name in all)
4507
- __defProp2(target, name, { get: all[name], enumerable: true });
4508
- };
4509
- var __copyProps2 = (to, from, except, desc) => {
4510
- if (from && typeof from === "object" || typeof from === "function") {
4511
- for (let key of __getOwnPropNames2(from))
4512
- if (!__hasOwnProp2.call(to, key) && key !== except)
4513
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
4514
- }
4515
- return to;
4516
- };
4517
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
4518
- var error_exports = {};
4519
- __export2(error_exports, {
4520
- UnsupportedError: () => UnsupportedError
4521
- });
4522
- module2.exports = __toCommonJS2(error_exports);
4523
- var UnsupportedError = class extends Error {
4524
- constructor(message) {
4525
- super(message);
4526
- }
4527
- };
4528
- }
4456
+ // src/banner.ts
4457
+ var banner_exports = {};
4458
+ __export(banner_exports, {
4459
+ showBanner: () => showBanner
4529
4460
  });
4530
-
4531
- // node_modules/cloudflared/lib/install.js
4532
- var require_install = __commonJS({
4533
- "node_modules/cloudflared/lib/install.js"(exports2, module2) {
4534
- "use strict";
4535
- var __create2 = Object.create;
4536
- var __defProp2 = Object.defineProperty;
4537
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
4538
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
4539
- var __getProtoOf2 = Object.getPrototypeOf;
4540
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
4541
- var __export2 = (target, all) => {
4542
- for (var name in all)
4543
- __defProp2(target, name, { get: all[name], enumerable: true });
4544
- };
4545
- var __copyProps2 = (to, from, except, desc) => {
4546
- if (from && typeof from === "object" || typeof from === "function") {
4547
- for (let key of __getOwnPropNames2(from))
4548
- if (!__hasOwnProp2.call(to, key) && key !== except)
4549
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
4550
- }
4551
- return to;
4552
- };
4553
- var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps2(
4554
- // If the importer is in node compatibility mode or this is not an ESM
4555
- // file that has been converted to a CommonJS file using a Babel-
4556
- // compatible transform (i.e. "__esModule" has not been set), then set
4557
- // "default" to the CommonJS "module.exports" for node compatibility.
4558
- isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target,
4559
- mod
4560
- ));
4561
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
4562
- var install_exports = {};
4563
- __export2(install_exports, {
4564
- install: () => install,
4565
- install_linux: () => install_linux,
4566
- install_macos: () => install_macos,
4567
- install_windows: () => install_windows
4568
- });
4569
- module2.exports = __toCommonJS2(install_exports);
4570
- var import_node_fs = __toESM2(require("fs"));
4571
- var import_node_path = __toESM2(require("path"));
4572
- var import_node_https = __toESM2(require("https"));
4573
- var import_node_child_process = require("child_process");
4574
- var import_constants = require_constants();
4575
- var import_error = require_error();
4576
- var LINUX_URL = {
4577
- arm64: "cloudflared-linux-arm64",
4578
- arm: "cloudflared-linux-arm",
4579
- x64: "cloudflared-linux-amd64",
4580
- ia32: "cloudflared-linux-386"
4581
- };
4582
- var MACOS_URL = {
4583
- arm64: "cloudflared-darwin-arm64.tgz",
4584
- x64: "cloudflared-darwin-amd64.tgz"
4585
- };
4586
- var WINDOWS_URL = {
4587
- x64: "cloudflared-windows-amd64.exe",
4588
- ia32: "cloudflared-windows-386.exe"
4589
- };
4590
- function resolve_base(version2) {
4591
- if (version2 === "latest") {
4592
- return `${import_constants.RELEASE_BASE}latest/download/`;
4593
- }
4594
- return `${import_constants.RELEASE_BASE}download/${version2}/`;
4595
- }
4596
- async function install(to, version2 = import_constants.CLOUDFLARED_VERSION) {
4597
- if (process.platform === "linux") {
4598
- return install_linux(to, version2);
4599
- } else if (process.platform === "darwin") {
4600
- return install_macos(to, version2);
4601
- } else if (process.platform === "win32") {
4602
- return install_windows(to, version2);
4603
- } else {
4604
- throw new import_error.UnsupportedError("Unsupported platform: " + process.platform);
4605
- }
4606
- }
4607
- async function install_linux(to, version2 = import_constants.CLOUDFLARED_VERSION) {
4608
- const file = LINUX_URL[process.arch];
4609
- if (file === void 0) {
4610
- throw new import_error.UnsupportedError("Unsupported architecture: " + process.arch);
4611
- }
4612
- await download(resolve_base(version2) + file, to);
4613
- import_node_fs.default.chmodSync(to, "755");
4614
- return to;
4615
- }
4616
- async function install_macos(to, version2 = import_constants.CLOUDFLARED_VERSION) {
4617
- let arch = process.arch;
4618
- if (version2 !== "latest" && version_number(version2) < 20240802) {
4619
- arch = "x64";
4620
- }
4621
- const file = MACOS_URL[arch];
4622
- if (file === void 0) {
4623
- throw new import_error.UnsupportedError("Unsupported architecture: " + arch);
4624
- }
4625
- await download(resolve_base(version2) + file, `${to}.tgz`);
4626
- process.env.VERBOSE && console.log(`Extracting to ${to}`);
4627
- (0, import_node_child_process.execSync)(`tar -xzf ${import_node_path.default.basename(`${to}.tgz`)}`, { cwd: import_node_path.default.dirname(to) });
4628
- import_node_fs.default.unlinkSync(`${to}.tgz`);
4629
- import_node_fs.default.renameSync(`${import_node_path.default.dirname(to)}/cloudflared`, to);
4630
- return to;
4631
- }
4632
- async function install_windows(to, version2 = import_constants.CLOUDFLARED_VERSION) {
4633
- const file = WINDOWS_URL[process.arch];
4634
- if (file === void 0) {
4635
- throw new import_error.UnsupportedError("Unsupported architecture: " + process.arch);
4636
- }
4637
- await download(resolve_base(version2) + file, to);
4638
- return to;
4639
- }
4640
- function download(url, to, redirect = 0) {
4641
- if (redirect === 0) {
4642
- process.env.VERBOSE && console.log(`Downloading ${url} to ${to}`);
4643
- } else {
4644
- process.env.VERBOSE && console.log(`Redirecting to ${url}`);
4645
- }
4646
- if (!import_node_fs.default.existsSync(import_node_path.default.dirname(to))) {
4647
- import_node_fs.default.mkdirSync(import_node_path.default.dirname(to), { recursive: true });
4648
- }
4649
- return new Promise((resolve, reject) => {
4650
- const request = import_node_https.default.get(url, (res) => {
4651
- const redirect_code = [301, 302, 303, 307, 308];
4652
- if (redirect_code.includes(res.statusCode) && res.headers.location !== void 0) {
4653
- request.destroy();
4654
- const redirection = res.headers.location;
4655
- resolve(download(redirection, to, redirect + 1));
4656
- return;
4657
- }
4658
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
4659
- const file = import_node_fs.default.createWriteStream(to);
4660
- file.on("finish", () => {
4661
- file.close(() => resolve(to));
4662
- });
4663
- file.on("error", (err) => {
4664
- import_node_fs.default.unlink(to, () => reject(err));
4665
- });
4666
- res.pipe(file);
4667
- } else {
4668
- request.destroy();
4669
- reject(new Error(`HTTP response with status code: ${res.statusCode}`));
4670
- }
4671
- });
4672
- request.on("error", (err) => {
4673
- reject(err);
4674
- });
4675
- request.end();
4676
- });
4677
- }
4678
- function version_number(semver) {
4679
- const [major, minor, patch] = semver.split(".").map(Number);
4680
- return major * 1e4 + minor * 100 + patch;
4681
- }
4682
- }
4683
- });
4684
-
4685
- // node_modules/cloudflared/lib/regex.js
4686
- var require_regex = __commonJS({
4687
- "node_modules/cloudflared/lib/regex.js"(exports2, module2) {
4688
- "use strict";
4689
- var __defProp2 = Object.defineProperty;
4690
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
4691
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
4692
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
4693
- var __export2 = (target, all) => {
4694
- for (var name in all)
4695
- __defProp2(target, name, { get: all[name], enumerable: true });
4696
- };
4697
- var __copyProps2 = (to, from, except, desc) => {
4698
- if (from && typeof from === "object" || typeof from === "function") {
4699
- for (let key of __getOwnPropNames2(from))
4700
- if (!__hasOwnProp2.call(to, key) && key !== except)
4701
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
4702
- }
4703
- return to;
4704
- };
4705
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
4706
- var regex_exports = {};
4707
- __export2(regex_exports, {
4708
- config_regex: () => config_regex,
4709
- conn_regex: () => conn_regex,
4710
- connectorID_regex: () => connectorID_regex,
4711
- disconnect_regex: () => disconnect_regex,
4712
- index_regex: () => index_regex,
4713
- ip_regex: () => ip_regex,
4714
- location_regex: () => location_regex,
4715
- metrics_regex: () => metrics_regex,
4716
- tunnelID_regex: () => tunnelID_regex
4717
- });
4718
- module2.exports = __toCommonJS2(regex_exports);
4719
- var conn_regex = /connection[= ]([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12})/i;
4720
- var ip_regex = /ip=([0-9.]+)/;
4721
- var location_regex = /location=([A-Za-z0-9]+)/;
4722
- var index_regex = /connIndex=(\d)/;
4723
- var disconnect_regex = /Unregistered tunnel connection connIndex=(\d)/i;
4724
- var tunnelID_regex = /tunnelID=([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12})/i;
4725
- var connectorID_regex = /Connector ID: ([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12})/i;
4726
- var metrics_regex = /metrics server on ([0-9.:]+\/metrics)/;
4727
- var config_regex = /config="(.+[^\\])"/;
4728
- }
4729
- });
4730
-
4731
- // node_modules/cloudflared/lib/handler.js
4732
- var require_handler = __commonJS({
4733
- "node_modules/cloudflared/lib/handler.js"(exports2, module2) {
4734
- "use strict";
4735
- var __defProp2 = Object.defineProperty;
4736
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
4737
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
4738
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
4739
- var __export2 = (target, all) => {
4740
- for (var name in all)
4741
- __defProp2(target, name, { get: all[name], enumerable: true });
4742
- };
4743
- var __copyProps2 = (to, from, except, desc) => {
4744
- if (from && typeof from === "object" || typeof from === "function") {
4745
- for (let key of __getOwnPropNames2(from))
4746
- if (!__hasOwnProp2.call(to, key) && key !== except)
4747
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
4748
- }
4749
- return to;
4750
- };
4751
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
4752
- var handler_exports = {};
4753
- __export2(handler_exports, {
4754
- ConfigHandler: () => ConfigHandler,
4755
- ConnectionHandler: () => ConnectionHandler,
4756
- TryCloudflareHandler: () => TryCloudflareHandler
4757
- });
4758
- module2.exports = __toCommonJS2(handler_exports);
4759
- var import_node_stream = require("stream");
4760
- var import_regex2 = require_regex();
4761
- var ConnectionHandler = class {
4762
- constructor(tunnel) {
4763
- this.connections = [];
4764
- this.connected_handler = (output, tunnel2) => {
4765
- const conn_match = output.match(import_regex2.conn_regex);
4766
- const ip_match = output.match(import_regex2.ip_regex);
4767
- const location_match = output.match(import_regex2.location_regex);
4768
- const index_match = output.match(import_regex2.index_regex);
4769
- if (conn_match && ip_match && location_match && index_match) {
4770
- const connection = {
4771
- id: conn_match[1],
4772
- ip: ip_match[1],
4773
- location: location_match[1]
4774
- };
4775
- this.connections[Number(index_match[1])] = connection;
4776
- tunnel2.emit("connected", connection);
4777
- }
4778
- };
4779
- this.disconnected_handler = (output, tunnel2) => {
4780
- const index_match = output.includes("terminated") ? output.match(import_regex2.index_regex) : null;
4781
- if (index_match) {
4782
- const index = Number(index_match[1]);
4783
- if (this.connections[index]) {
4784
- tunnel2.emit("disconnected", this.connections[index]);
4785
- this.connections[index] = void 0;
4786
- }
4787
- }
4788
- };
4789
- tunnel.addHandler(this.connected_handler.bind(this));
4790
- tunnel.addHandler(this.disconnected_handler.bind(this));
4791
- }
4792
- };
4793
- var TryCloudflareHandler = class {
4794
- constructor(tunnel) {
4795
- this.url_handler = (output, tunnel2) => {
4796
- const url_match = output.match(/https:\/\/([a-z0-9-]+)\.trycloudflare\.com/);
4797
- if (url_match) {
4798
- tunnel2.emit("url", url_match[0]);
4799
- }
4800
- };
4801
- tunnel.addHandler(this.url_handler.bind(this));
4802
- }
4803
- };
4804
- var ConfigHandler = class extends import_node_stream.EventEmitter {
4805
- constructor(tunnel) {
4806
- super();
4807
- this.config_handler = (output, tunnel2) => {
4808
- const config_match = output.match(/\bconfig="(.+?)" version=(\d+)/);
4809
- if (config_match) {
4810
- try {
4811
- const config_str = config_match[1].replace(/\\"/g, '"');
4812
- const config = JSON.parse(config_str);
4813
- const version2 = parseInt(config_match[2], 10);
4814
- this.emit("config", {
4815
- config,
4816
- version: version2
4817
- });
4818
- if (config && typeof config === "object" && "ingress" in config && Array.isArray(config.ingress)) {
4819
- for (const ingress of config.ingress) {
4820
- if ("hostname" in ingress) {
4821
- tunnel2.emit("url", ingress.hostname);
4822
- }
4823
- }
4824
- }
4825
- } catch (error) {
4826
- this.emit("error", new Error(`Failed to parse config: ${error}`));
4827
- }
4828
- }
4829
- };
4830
- tunnel.addHandler(this.config_handler.bind(this));
4831
- }
4832
- on(event, listener) {
4833
- return super.on(event, listener);
4834
- }
4835
- once(event, listener) {
4836
- return super.once(event, listener);
4837
- }
4838
- off(event, listener) {
4839
- return super.off(event, listener);
4840
- }
4841
- emit(event, ...args) {
4842
- return super.emit(event, ...args);
4843
- }
4844
- };
4845
- }
4846
- });
4847
-
4848
- // node_modules/cloudflared/lib/tunnel.js
4849
- var require_tunnel = __commonJS({
4850
- "node_modules/cloudflared/lib/tunnel.js"(exports2, module2) {
4851
- "use strict";
4852
- var __defProp2 = Object.defineProperty;
4853
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
4854
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
4855
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
4856
- var __export2 = (target, all) => {
4857
- for (var name in all)
4858
- __defProp2(target, name, { get: all[name], enumerable: true });
4859
- };
4860
- var __copyProps2 = (to, from, except, desc) => {
4861
- if (from && typeof from === "object" || typeof from === "function") {
4862
- for (let key of __getOwnPropNames2(from))
4863
- if (!__hasOwnProp2.call(to, key) && key !== except)
4864
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
4865
- }
4866
- return to;
4867
- };
4868
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
4869
- var tunnel_exports2 = {};
4870
- __export2(tunnel_exports2, {
4871
- Tunnel: () => Tunnel,
4872
- build_args: () => build_args,
4873
- build_options: () => build_options,
4874
- tunnel: () => tunnel
4875
- });
4876
- module2.exports = __toCommonJS2(tunnel_exports2);
4877
- var import_node_child_process = require("child_process");
4878
- var import_node_events = require("events");
4879
- var import_constants = require_constants();
4880
- var import_handler = require_handler();
4881
- var Tunnel = class _Tunnel extends import_node_events.EventEmitter {
4882
- constructor(options = ["tunnel", "--hello-world"]) {
4883
- super();
4884
- this.outputHandlers = [];
4885
- this.stop = this._stop.bind(this);
4886
- this.setupDefaultHandlers();
4887
- const args = Array.isArray(options) ? options : build_args(options);
4888
- this._process = this.createProcess(args);
4889
- this.setupEventHandlers();
4890
- }
4891
- get process() {
4892
- return this._process;
4893
- }
4894
- setupDefaultHandlers() {
4895
- new import_handler.ConnectionHandler(this);
4896
- new import_handler.TryCloudflareHandler(this);
4897
- }
4898
- /**
4899
- * Add a custom output handler
4900
- * @param handler Function to handle cloudflared output
4901
- */
4902
- addHandler(handler) {
4903
- this.outputHandlers.push(handler);
4904
- }
4905
- /**
4906
- * Remove a previously added output handler
4907
- * @param handler The handler to remove
4908
- */
4909
- removeHandler(handler) {
4910
- const index = this.outputHandlers.indexOf(handler);
4911
- if (index !== -1) {
4912
- this.outputHandlers.splice(index, 1);
4913
- }
4914
- }
4915
- processOutput(output) {
4916
- for (const handler of this.outputHandlers) {
4917
- try {
4918
- handler(output, this);
4919
- } catch (error) {
4920
- this.emit("error", error instanceof Error ? error : new Error(String(error)));
4921
- }
4922
- }
4923
- }
4924
- setupEventHandlers() {
4925
- this.on("stdout", (output) => {
4926
- this.processOutput(output);
4927
- });
4928
- this.on("stderr", (output) => {
4929
- this.processOutput(output);
4930
- });
4931
- }
4932
- createProcess(args) {
4933
- var _a, _b;
4934
- const child = (0, import_node_child_process.spawn)(import_constants.bin, args, { stdio: ["ignore", "pipe", "pipe"] });
4935
- child.on("error", (error) => this.emit("error", error));
4936
- child.on("exit", (code, signal) => this.emit("exit", code, signal));
4937
- if (process.env.VERBOSE) {
4938
- child.stdout.pipe(process.stdout);
4939
- child.stderr.pipe(process.stderr);
4940
- }
4941
- (_a = child.stdout) == null ? void 0 : _a.on("data", (data) => this.emit("stdout", data.toString()));
4942
- (_b = child.stderr) == null ? void 0 : _b.on("data", (data) => this.emit("stderr", data.toString()));
4943
- return child;
4944
- }
4945
- _stop() {
4946
- return this.process.kill("SIGINT");
4947
- }
4948
- on(event, listener) {
4949
- return super.on(event, listener);
4950
- }
4951
- once(event, listener) {
4952
- return super.once(event, listener);
4953
- }
4954
- off(event, listener) {
4955
- return super.off(event, listener);
4956
- }
4957
- emit(event, ...args) {
4958
- return super.emit(event, ...args);
4959
- }
4960
- /**
4961
- * Create a quick tunnel without a Cloudflare account.
4962
- * @param url The local service URL to connect to. If not provided, the hello world mode will be used.
4963
- * @param options The options to pass to cloudflared.
4964
- */
4965
- static quick(url, options = {}) {
4966
- const args = ["tunnel"];
4967
- if (url) {
4968
- args.push("--url", url);
4969
- } else {
4970
- args.push("--hello-world");
4971
- }
4972
- args.push(...build_options(options));
4973
- return new _Tunnel(args);
4974
- }
4975
- /**
4976
- * Create a tunnel with a Cloudflare account.
4977
- * @param token The Cloudflare Tunnel token.
4978
- * @param options The options to pass to cloudflared.
4979
- */
4980
- static withToken(token, options = {}) {
4981
- options["--token"] = token;
4982
- return new _Tunnel(build_args(options));
4983
- }
4984
- };
4985
- function tunnel(options = {}) {
4986
- return new Tunnel(options);
4987
- }
4988
- function build_args(options) {
4989
- const args = "--hello-world" in options ? ["tunnel"] : ["tunnel", "run"];
4990
- args.push(...build_options(options));
4991
- return args;
4992
- }
4993
- function build_options(options) {
4994
- const opts = [];
4995
- for (const [key, value] of Object.entries(options)) {
4996
- if (typeof value === "string") {
4997
- opts.push(`${key}`, value);
4998
- } else if (typeof value === "number") {
4999
- opts.push(`${key}`, value.toString());
5000
- } else if (typeof value === "boolean") {
5001
- if (value === true) {
5002
- opts.push(`${key}`);
5003
- }
5004
- }
5005
- }
5006
- return opts;
5007
- }
5008
- }
5009
- });
5010
-
5011
- // node_modules/cloudflared/lib/service.js
5012
- var require_service = __commonJS({
5013
- "node_modules/cloudflared/lib/service.js"(exports2, module2) {
4461
+ function showBanner() {
4462
+ console.log("\n" + BANNER);
4463
+ }
4464
+ var BANNER;
4465
+ var init_banner = __esm({
4466
+ "src/banner.ts"() {
5014
4467
  "use strict";
5015
- var __create2 = Object.create;
5016
- var __defProp2 = Object.defineProperty;
5017
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
5018
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
5019
- var __getProtoOf2 = Object.getPrototypeOf;
5020
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
5021
- var __export2 = (target, all) => {
5022
- for (var name in all)
5023
- __defProp2(target, name, { get: all[name], enumerable: true });
5024
- };
5025
- var __copyProps2 = (to, from, except, desc) => {
5026
- if (from && typeof from === "object" || typeof from === "function") {
5027
- for (let key of __getOwnPropNames2(from))
5028
- if (!__hasOwnProp2.call(to, key) && key !== except)
5029
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
5030
- }
5031
- return to;
5032
- };
5033
- var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps2(
5034
- // If the importer is in node compatibility mode or this is not an ESM
5035
- // file that has been converted to a CommonJS file using a Babel-
5036
- // compatible transform (i.e. "__esModule" has not been set), then set
5037
- // "default" to the CommonJS "module.exports" for node compatibility.
5038
- isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", { value: mod, enumerable: true }) : target,
5039
- mod
5040
- ));
5041
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
5042
- var service_exports = {};
5043
- __export2(service_exports, {
5044
- AlreadyInstalledError: () => AlreadyInstalledError2,
5045
- LINUX_SERVICE_PATH: () => LINUX_SERVICE_PATH,
5046
- MACOS_SERVICE_PATH: () => MACOS_SERVICE_PATH2,
5047
- NotInstalledError: () => NotInstalledError2,
5048
- clean: () => clean,
5049
- current: () => current,
5050
- err: () => err,
5051
- exists: () => exists,
5052
- identifier: () => identifier2,
5053
- install: () => install,
5054
- journal: () => journal,
5055
- log: () => log2,
5056
- service: () => service2,
5057
- service_name: () => service_name,
5058
- uninstall: () => uninstall
5059
- });
5060
- module2.exports = __toCommonJS2(service_exports);
5061
- var import_node_os = __toESM2(require("os"));
5062
- var import_node_fs = __toESM2(require("fs"));
5063
- var import_node_child_process = require("child_process");
5064
- var import_constants = require_constants();
5065
- var import_regex2 = require_regex();
5066
- var identifier2 = "com.cloudflare.cloudflared";
5067
- var service_name = "cloudflared.service";
5068
- var MACOS_SERVICE_PATH2 = {
5069
- PLIST: is_root() ? `/Library/LaunchDaemons/${identifier2}.plist` : `${import_node_os.default.homedir()}/Library/LaunchAgents/${identifier2}.plist`,
5070
- OUT: is_root() ? `/Library/Logs/${identifier2}.out.log` : `${import_node_os.default.homedir()}/Library/Logs/${identifier2}.out.log`,
5071
- ERR: is_root() ? `/Library/Logs/${identifier2}.err.log` : `${import_node_os.default.homedir()}/Library/Logs/${identifier2}.err.log`
5072
- };
5073
- var LINUX_SERVICE_PATH = {
5074
- SYSTEMD: `/etc/systemd/system/${service_name}`,
5075
- SERVICE: "/etc/init.d/cloudflared",
5076
- SERVICE_OUT: "/var/log/cloudflared.log",
5077
- SERVICE_ERR: "/var/log/cloudflared.err"
5078
- };
5079
- var service2 = { install, uninstall, exists, log: log2, err, current, clean, journal };
5080
- var AlreadyInstalledError2 = class extends Error {
5081
- constructor() {
5082
- super("service is already installed");
5083
- }
5084
- };
5085
- var NotInstalledError2 = class extends Error {
5086
- constructor() {
5087
- super("service is not installed");
5088
- }
5089
- };
5090
- function install(token) {
5091
- if (!["darwin", "linux"].includes(process.platform)) {
5092
- throw new Error(`Not Implemented on platform ${process.platform}`);
5093
- }
5094
- if (exists()) {
5095
- throw new AlreadyInstalledError2();
5096
- }
5097
- const args = ["service", "install"];
5098
- if (token) {
5099
- args.push(token);
5100
- }
5101
- const result = (0, import_node_child_process.spawnSync)(import_constants.bin, args);
5102
- if (result.status !== 0) {
5103
- throw new Error(`service install failed: ${result.stderr.toString()}`);
5104
- }
5105
- }
5106
- function uninstall() {
5107
- if (!["darwin", "linux"].includes(process.platform)) {
5108
- throw new Error(`Not Implemented on platform ${process.platform}`);
5109
- }
5110
- if (!exists()) {
5111
- throw new NotInstalledError2();
5112
- }
5113
- const result = (0, import_node_child_process.spawnSync)(import_constants.bin, ["service", "uninstall"]);
5114
- if (result.status !== 0) {
5115
- throw new Error(`service uninstall failed: ${result.stderr.toString()}`);
5116
- }
5117
- if (process.platform === "darwin") {
5118
- import_node_fs.default.rmSync(MACOS_SERVICE_PATH2.OUT);
5119
- import_node_fs.default.rmSync(MACOS_SERVICE_PATH2.ERR);
5120
- } else if (process.platform === "linux" && !is_systemd()) {
5121
- import_node_fs.default.rmSync(LINUX_SERVICE_PATH.SERVICE_OUT);
5122
- import_node_fs.default.rmSync(LINUX_SERVICE_PATH.SERVICE_ERR);
5123
- }
5124
- }
5125
- function log2() {
5126
- if (!exists()) {
5127
- throw new NotInstalledError2();
5128
- }
5129
- if (process.platform === "darwin") {
5130
- return import_node_fs.default.readFileSync(MACOS_SERVICE_PATH2.OUT, "utf8");
5131
- }
5132
- if (process.platform === "linux" && !is_systemd()) {
5133
- return import_node_fs.default.readFileSync(LINUX_SERVICE_PATH.SERVICE_OUT, "utf8");
5134
- }
5135
- throw new Error(`Not Implemented on platform ${process.platform}`);
5136
- }
5137
- function err() {
5138
- if (!exists()) {
5139
- throw new NotInstalledError2();
5140
- }
5141
- if (process.platform === "darwin") {
5142
- return import_node_fs.default.readFileSync(MACOS_SERVICE_PATH2.ERR, "utf8");
5143
- }
5144
- if (process.platform === "linux" && !is_systemd()) {
5145
- return import_node_fs.default.readFileSync(LINUX_SERVICE_PATH.SERVICE_ERR, "utf8");
5146
- }
5147
- throw new Error(`Not Implemented on platform ${process.platform}`);
5148
- }
5149
- function journal(n = 300) {
5150
- if (process.platform === "linux" && is_systemd()) {
5151
- const args = ["-u", service_name, "-o", "cat", "-n", n.toString()];
5152
- return (0, import_node_child_process.spawnSync)("journalctl", args).stdout.toString();
5153
- }
5154
- throw new Error(`Not Implemented on platform ${process.platform}`);
5155
- }
5156
- function current() {
5157
- var _a, _b, _c, _d;
5158
- if (!["darwin", "linux"].includes(process.platform)) {
5159
- throw new Error(`Not Implemented on platform ${process.platform}`);
5160
- }
5161
- if (!exists()) {
5162
- throw new NotInstalledError2();
5163
- }
5164
- const log22 = is_systemd() ? journal() : err();
5165
- let tunnelID = "";
5166
- let connectorID = "";
5167
- const connections = [];
5168
- let metrics = "";
5169
- let config = {};
5170
- for (const line of log22.split("\n")) {
5171
- try {
5172
- if (line.match(import_regex2.tunnelID_regex)) {
5173
- tunnelID = ((_a = line.match(import_regex2.tunnelID_regex)) == null ? void 0 : _a[1]) ?? "";
5174
- } else if (line.match(import_regex2.connectorID_regex)) {
5175
- connectorID = ((_b = line.match(import_regex2.connectorID_regex)) == null ? void 0 : _b[1]) ?? "";
5176
- } else if (line.match(import_regex2.conn_regex) && line.match(import_regex2.location_regex) && line.match(import_regex2.ip_regex) && line.match(import_regex2.index_regex)) {
5177
- const [, id] = line.match(import_regex2.conn_regex) ?? [];
5178
- const [, location] = line.match(import_regex2.location_regex) ?? [];
5179
- const [, ip] = line.match(import_regex2.ip_regex) ?? [];
5180
- const [, idx] = line.match(import_regex2.index_regex) ?? [];
5181
- connections[parseInt(idx)] = { id, ip, location };
5182
- } else if (line.match(import_regex2.disconnect_regex)) {
5183
- const [, idx] = line.match(import_regex2.disconnect_regex) ?? [];
5184
- if (parseInt(idx) in connections) {
5185
- connections[parseInt(idx)] = { id: "", ip: "", location: "" };
5186
- }
5187
- } else if (line.match(import_regex2.metrics_regex)) {
5188
- metrics = ((_c = line.match(import_regex2.metrics_regex)) == null ? void 0 : _c[1]) ?? "";
5189
- } else if (line.match(import_regex2.config_regex)) {
5190
- config = JSON.parse(((_d = line.match(import_regex2.config_regex)) == null ? void 0 : _d[1].replace(/\\/g, "")) ?? "{}");
5191
- }
5192
- } catch (err2) {
5193
- if (process.env.VERBOSE) {
5194
- console.error("log parsing failed", err2);
5195
- }
5196
- }
5197
- }
5198
- return { tunnelID, connectorID, connections, metrics, config };
5199
- }
5200
- function clean() {
5201
- if (process.platform !== "darwin") {
5202
- throw new Error(`Not Implemented on platform ${process.platform}`);
5203
- }
5204
- if (exists()) {
5205
- throw new AlreadyInstalledError2();
5206
- }
5207
- import_node_fs.default.rmSync(MACOS_SERVICE_PATH2.OUT, { force: true });
5208
- import_node_fs.default.rmSync(MACOS_SERVICE_PATH2.ERR, { force: true });
5209
- }
5210
- function exists() {
5211
- if (process.platform === "darwin") {
5212
- return import_node_fs.default.existsSync(MACOS_SERVICE_PATH2.PLIST);
5213
- } else if (process.platform === "linux") {
5214
- return is_systemd() ? import_node_fs.default.existsSync(LINUX_SERVICE_PATH.SYSTEMD) : import_node_fs.default.existsSync(LINUX_SERVICE_PATH.SERVICE);
5215
- }
5216
- throw new Error(`Not Implemented on platform ${process.platform}`);
5217
- }
5218
- function is_root() {
5219
- var _a;
5220
- return ((_a = process.getuid) == null ? void 0 : _a.call(process)) === 0;
5221
- }
5222
- function is_systemd() {
5223
- return process.platform === "linux" && import_node_fs.default.existsSync("/run/systemd/system");
5224
- }
5225
- }
5226
- });
4468
+ BANNER = `
4469
+ \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
4470
+ \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
4471
+ \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
4472
+ \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
4473
+ \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
4474
+ \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
5227
4475
 
5228
- // node_modules/cloudflared/lib/lib.js
5229
- var require_lib = __commonJS({
5230
- "node_modules/cloudflared/lib/lib.js"(exports2, module2) {
5231
- "use strict";
5232
- var __defProp2 = Object.defineProperty;
5233
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
5234
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
5235
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
5236
- var __export2 = (target, all) => {
5237
- for (var name in all)
5238
- __defProp2(target, name, { get: all[name], enumerable: true });
5239
- };
5240
- var __copyProps2 = (to, from, except, desc) => {
5241
- if (from && typeof from === "object" || typeof from === "function") {
5242
- for (let key of __getOwnPropNames2(from))
5243
- if (!__hasOwnProp2.call(to, key) && key !== except)
5244
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
5245
- }
5246
- return to;
5247
- };
5248
- var __reExport = (target, mod, secondTarget) => (__copyProps2(target, mod, "default"), secondTarget && __copyProps2(secondTarget, mod, "default"));
5249
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
5250
- var lib_exports = {};
5251
- __export2(lib_exports, {
5252
- AlreadyInstalledError: () => import_service.AlreadyInstalledError,
5253
- MACOS_SERVICE_PATH: () => import_service.MACOS_SERVICE_PATH,
5254
- NotInstalledError: () => import_service.NotInstalledError,
5255
- identifier: () => import_service.identifier,
5256
- service: () => import_service.service
5257
- });
5258
- module2.exports = __toCommonJS2(lib_exports);
5259
- __reExport(lib_exports, require_constants(), module2.exports);
5260
- __reExport(lib_exports, require_install(), module2.exports);
5261
- __reExport(lib_exports, require_tunnel(), module2.exports);
5262
- var import_service = require_service();
5263
- __reExport(lib_exports, require_handler(), module2.exports);
4476
+ Connect AI agents to phone numbers in 4 lines of code
4477
+ `;
5264
4478
  }
5265
4479
  });
5266
4480
 
@@ -5272,7 +4486,7 @@ __export(tunnel_exports, {
5272
4486
  async function startTunnel(port, timeoutMs = 3e4) {
5273
4487
  let tunnelMod;
5274
4488
  try {
5275
- tunnelMod = await Promise.resolve().then(() => __toESM(require_lib()));
4489
+ tunnelMod = await import("cloudflared");
5276
4490
  } catch {
5277
4491
  throw new Error(
5278
4492
  'Built-in tunnel requires the "cloudflared" package. Install it with:\n\n npm install cloudflared\n\nOr provide your own webhookUrl instead of using tunnel: true.'
@@ -6535,6 +5749,7 @@ var require_node_cron = __commonJS({
6535
5749
  var index_exports = {};
6536
5750
  __export(index_exports, {
6537
5751
  AllProvidersFailedError: () => AllProvidersFailedError,
5752
+ AnthropicLLM: () => LLM2,
6538
5753
  AssemblyAISTT: () => STT5,
6539
5754
  AuthenticationError: () => AuthenticationError,
6540
5755
  BackgroundAudioPlayer: () => BackgroundAudioPlayer,
@@ -6542,6 +5757,7 @@ __export(index_exports, {
6542
5757
  CallMetricsAccumulator: () => CallMetricsAccumulator,
6543
5758
  CartesiaSTT: () => STT3,
6544
5759
  CartesiaTTS: () => TTS3,
5760
+ CerebrasLLM: () => LLM4,
6545
5761
  ChatContext: () => ChatContext,
6546
5762
  CloudflareTunnel: () => CloudflareTunnel,
6547
5763
  DEFAULT_MIN_SENTENCE_LEN: () => DEFAULT_MIN_SENTENCE_LEN,
@@ -6555,11 +5771,14 @@ __export(index_exports, {
6555
5771
  GEMINI_DEFAULT_INPUT_SR: () => GEMINI_DEFAULT_INPUT_SR,
6556
5772
  GEMINI_DEFAULT_OUTPUT_SR: () => GEMINI_DEFAULT_OUTPUT_SR,
6557
5773
  GeminiLiveAdapter: () => GeminiLiveAdapter,
5774
+ GoogleLLM: () => LLM5,
5775
+ GroqLLM: () => LLM3,
6558
5776
  Guardrail: () => Guardrail,
6559
5777
  IVRActivity: () => IVRActivity,
6560
5778
  LLMLoop: () => LLMLoop,
6561
5779
  LMNTTTS: () => TTS5,
6562
5780
  MetricsStore: () => MetricsStore,
5781
+ OpenAILLM: () => LLM,
6563
5782
  OpenAILLMProvider: () => OpenAILLMProvider,
6564
5783
  OpenAIRealtime: () => Realtime,
6565
5784
  OpenAIRealtimeAdapter: () => OpenAIRealtimeAdapter,
@@ -6830,6 +6049,7 @@ var Static = class {
6830
6049
  };
6831
6050
 
6832
6051
  // src/client.ts
6052
+ init_logger();
6833
6053
  var DEFAULT_BACKEND_URL2 = "wss://api.getpatter.com";
6834
6054
  var DEFAULT_REST_URL = "https://api.getpatter.com";
6835
6055
  function sttConfigToDict(cfg) {
@@ -6938,6 +6158,8 @@ var Patter = class {
6938
6158
  "Unknown engine. Expected OpenAIRealtime or ElevenLabsConvAI instance."
6939
6159
  );
6940
6160
  }
6161
+ } else if (!working.provider && (working.stt !== void 0 || working.tts !== void 0 || working.llm !== void 0)) {
6162
+ working = { ...working, provider: "pipeline" };
6941
6163
  }
6942
6164
  if (working.provider) {
6943
6165
  const valid = ["openai_realtime", "elevenlabs_convai", "pipeline"];
@@ -6945,6 +6167,19 @@ var Patter = class {
6945
6167
  throw new Error(`provider must be one of: ${valid.join(", ")}. Got: '${working.provider}'`);
6946
6168
  }
6947
6169
  }
6170
+ if (working.llm !== void 0) {
6171
+ const llm = working.llm;
6172
+ if (!llm || typeof llm.stream !== "function") {
6173
+ throw new Error(
6174
+ "`llm` must be an LLMProvider instance (e.g. new AnthropicLLM()). Got a value without a `.stream` method."
6175
+ );
6176
+ }
6177
+ if (working.engine) {
6178
+ getLogger().warn(
6179
+ "agent({ engine, llm }): `llm` is ignored when `engine` is set \u2014 realtime/ConvAI engines run their own model. Remove `llm` or switch to pipeline mode (stt + tts + llm) to silence this warning."
6180
+ );
6181
+ }
6182
+ }
6948
6183
  if (working.tools) {
6949
6184
  if (!Array.isArray(working.tools)) {
6950
6185
  throw new TypeError("tools must be an array");
@@ -6987,6 +6222,8 @@ var Patter = class {
6987
6222
  if (wantsCloudflared && webhookUrl) {
6988
6223
  throw new Error("Cannot use both tunnel: true and webhookUrl. Pick one.");
6989
6224
  }
6225
+ const { showBanner: showBanner2 } = await Promise.resolve().then(() => (init_banner(), banner_exports));
6226
+ showBanner2();
6990
6227
  if (wantsCloudflared) {
6991
6228
  const { startTunnel: startTunnel2 } = await Promise.resolve().then(() => (init_tunnel(), tunnel_exports));
6992
6229
  this.tunnelHandle = await startTunnel2(port);
@@ -8888,7 +8125,8 @@ var ELEVENLABS_VOICE_ID_BY_NAME = {
8888
8125
  glinda: "z9fAnlkpzviPz146aGWa",
8889
8126
  giovanni: "zcAOhNBS3c14rBihAFp1",
8890
8127
  mimi: "zrHiDhphv9ZnVXBqCLjz",
8891
- alloy: "21m00Tcm4TlvDq8ikWAM"
8128
+ sarah: "EXAVITQu4vr4xnSDxMaL",
8129
+ alloy: "EXAVITQu4vr4xnSDxMaL"
8892
8130
  };
8893
8131
  var VOICE_ID_PATTERN = /^[A-Za-z0-9]{20}$/;
8894
8132
  function resolveVoiceId(voice) {
@@ -8897,7 +8135,7 @@ function resolveVoiceId(voice) {
8897
8135
  return ELEVENLABS_VOICE_ID_BY_NAME[voice.toLowerCase()] ?? voice;
8898
8136
  }
8899
8137
  var ElevenLabsTTS = class {
8900
- constructor(apiKey, voiceId = "21m00Tcm4TlvDq8ikWAM", modelId = "eleven_turbo_v2_5", outputFormat = "pcm_16000") {
8138
+ constructor(apiKey, voiceId = "EXAVITQu4vr4xnSDxMaL", modelId = "eleven_turbo_v2_5", outputFormat = "pcm_16000") {
8901
8139
  this.apiKey = apiKey;
8902
8140
  this.modelId = modelId;
8903
8141
  this.outputFormat = outputFormat;
@@ -8968,7 +8206,7 @@ var TTS = class extends ElevenLabsTTS {
8968
8206
  }
8969
8207
  super(
8970
8208
  key,
8971
- opts.voiceId ?? "21m00Tcm4TlvDq8ikWAM",
8209
+ opts.voiceId ?? "EXAVITQu4vr4xnSDxMaL",
8972
8210
  opts.modelId ?? "eleven_turbo_v2_5",
8973
8211
  opts.outputFormat ?? "pcm_16000"
8974
8212
  );
@@ -9464,6 +8702,621 @@ var TTS5 = class extends LMNTTTS {
9464
8702
  }
9465
8703
  };
9466
8704
 
8705
+ // src/llm/openai.ts
8706
+ init_llm_loop();
8707
+ var LLM = class extends OpenAILLMProvider {
8708
+ constructor(opts = {}) {
8709
+ const key = opts.apiKey ?? process.env.OPENAI_API_KEY;
8710
+ if (!key) {
8711
+ throw new Error(
8712
+ "OpenAI LLM requires an apiKey. Pass { apiKey: 'sk-...' } or set OPENAI_API_KEY."
8713
+ );
8714
+ }
8715
+ super(key, opts.model ?? "gpt-4o-mini");
8716
+ }
8717
+ };
8718
+
8719
+ // src/providers/anthropic-llm.ts
8720
+ init_logger();
8721
+ var DEFAULT_ANTHROPIC_URL = "https://api.anthropic.com/v1/messages";
8722
+ var DEFAULT_ANTHROPIC_VERSION = "2023-06-01";
8723
+ var DEFAULT_MODEL = "claude-3-5-sonnet-20241022";
8724
+ var DEFAULT_MAX_TOKENS = 1024;
8725
+ var AnthropicLLMProvider = class {
8726
+ apiKey;
8727
+ model;
8728
+ maxTokens;
8729
+ temperature;
8730
+ url;
8731
+ anthropicVersion;
8732
+ constructor(options) {
8733
+ if (!options.apiKey) {
8734
+ throw new Error(
8735
+ "Anthropic API key is required. Pass it via { apiKey } or set the ANTHROPIC_API_KEY environment variable before constructing the provider."
8736
+ );
8737
+ }
8738
+ this.apiKey = options.apiKey;
8739
+ this.model = options.model ?? DEFAULT_MODEL;
8740
+ this.maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
8741
+ this.temperature = options.temperature;
8742
+ this.url = options.baseUrl ?? DEFAULT_ANTHROPIC_URL;
8743
+ this.anthropicVersion = options.anthropicVersion ?? DEFAULT_ANTHROPIC_VERSION;
8744
+ }
8745
+ async *stream(messages, tools) {
8746
+ const { system, messages: anthropicMessages } = toAnthropicMessages(messages);
8747
+ const anthropicTools = tools ? toAnthropicTools(tools) : null;
8748
+ const body = {
8749
+ model: this.model,
8750
+ messages: anthropicMessages,
8751
+ max_tokens: this.maxTokens,
8752
+ stream: true
8753
+ };
8754
+ if (system) body.system = system;
8755
+ if (anthropicTools && anthropicTools.length > 0) body.tools = anthropicTools;
8756
+ if (this.temperature !== void 0) body.temperature = this.temperature;
8757
+ const response = await fetch(this.url, {
8758
+ method: "POST",
8759
+ headers: {
8760
+ "Content-Type": "application/json",
8761
+ "x-api-key": this.apiKey,
8762
+ "anthropic-version": this.anthropicVersion
8763
+ },
8764
+ body: JSON.stringify(body),
8765
+ signal: AbortSignal.timeout(3e4)
8766
+ });
8767
+ if (!response.ok) {
8768
+ const errText = await response.text();
8769
+ getLogger().error(`Anthropic API error: ${response.status} ${errText}`);
8770
+ return;
8771
+ }
8772
+ const reader = response.body?.getReader();
8773
+ if (!reader) return;
8774
+ const decoder = new TextDecoder();
8775
+ let buffer = "";
8776
+ const toolIndexByBlock = /* @__PURE__ */ new Map();
8777
+ const toolIdByBlock = /* @__PURE__ */ new Map();
8778
+ let nextIndex = 0;
8779
+ while (true) {
8780
+ const { done, value } = await reader.read();
8781
+ if (done) break;
8782
+ buffer += decoder.decode(value, { stream: true });
8783
+ const lines = buffer.split("\n");
8784
+ buffer = lines.pop() || "";
8785
+ for (const line of lines) {
8786
+ const trimmed = line.trim();
8787
+ if (!trimmed.startsWith("data: ")) continue;
8788
+ const data = trimmed.slice(6);
8789
+ if (!data || data === "[DONE]") continue;
8790
+ let event;
8791
+ try {
8792
+ event = JSON.parse(data);
8793
+ } catch {
8794
+ continue;
8795
+ }
8796
+ if (event.type === "content_block_start" && event.content_block?.type === "tool_use") {
8797
+ const blockIdx = event.index ?? 0;
8798
+ const toolId = event.content_block.id ?? "";
8799
+ const toolName = event.content_block.name ?? "";
8800
+ const patterIndex = nextIndex++;
8801
+ toolIndexByBlock.set(blockIdx, patterIndex);
8802
+ toolIdByBlock.set(blockIdx, toolId);
8803
+ yield {
8804
+ type: "tool_call",
8805
+ index: patterIndex,
8806
+ id: toolId,
8807
+ name: toolName,
8808
+ arguments: ""
8809
+ };
8810
+ continue;
8811
+ }
8812
+ if (event.type === "content_block_delta") {
8813
+ if (event.delta?.type === "text_delta" && event.delta.text) {
8814
+ yield { type: "text", content: event.delta.text };
8815
+ continue;
8816
+ }
8817
+ if (event.delta?.type === "input_json_delta" && event.delta.partial_json) {
8818
+ const blockIdx = event.index ?? 0;
8819
+ const patterIndex = toolIndexByBlock.get(blockIdx);
8820
+ if (patterIndex !== void 0) {
8821
+ yield {
8822
+ type: "tool_call",
8823
+ index: patterIndex,
8824
+ id: toolIdByBlock.get(blockIdx),
8825
+ arguments: event.delta.partial_json
8826
+ };
8827
+ }
8828
+ }
8829
+ }
8830
+ }
8831
+ }
8832
+ yield { type: "done" };
8833
+ }
8834
+ };
8835
+ function toAnthropicTools(tools) {
8836
+ return tools.map((t) => {
8837
+ const fn = t.function ?? t;
8838
+ return {
8839
+ name: String(fn.name ?? ""),
8840
+ description: String(fn.description ?? ""),
8841
+ input_schema: fn.parameters ?? { type: "object", properties: {} }
8842
+ };
8843
+ });
8844
+ }
8845
+ function toAnthropicMessages(messages) {
8846
+ const systemParts = [];
8847
+ const out = [];
8848
+ for (const rawMsg of messages) {
8849
+ const role = rawMsg.role;
8850
+ if (role === "system") {
8851
+ if (typeof rawMsg.content === "string" && rawMsg.content) {
8852
+ systemParts.push(rawMsg.content);
8853
+ }
8854
+ continue;
8855
+ }
8856
+ if (role === "user") {
8857
+ if (typeof rawMsg.content === "string") {
8858
+ out.push({ role: "user", content: rawMsg.content });
8859
+ } else if (rawMsg.content) {
8860
+ out.push({ role: "user", content: rawMsg.content });
8861
+ }
8862
+ continue;
8863
+ }
8864
+ if (role === "assistant") {
8865
+ const blocks = [];
8866
+ if (typeof rawMsg.content === "string" && rawMsg.content) {
8867
+ blocks.push({ type: "text", text: rawMsg.content });
8868
+ }
8869
+ for (const tc of rawMsg.tool_calls ?? []) {
8870
+ let args = {};
8871
+ try {
8872
+ args = JSON.parse(tc.function?.arguments ?? "{}");
8873
+ } catch {
8874
+ args = {};
8875
+ }
8876
+ blocks.push({
8877
+ type: "tool_use",
8878
+ id: tc.id ?? "",
8879
+ name: tc.function?.name ?? "",
8880
+ input: args
8881
+ });
8882
+ }
8883
+ if (blocks.length > 0) {
8884
+ out.push({ role: "assistant", content: blocks });
8885
+ }
8886
+ continue;
8887
+ }
8888
+ if (role === "tool") {
8889
+ const contentStr = typeof rawMsg.content === "string" ? rawMsg.content : JSON.stringify(rawMsg.content);
8890
+ out.push({
8891
+ role: "user",
8892
+ content: [
8893
+ {
8894
+ type: "tool_result",
8895
+ tool_use_id: rawMsg.tool_call_id ?? "",
8896
+ content: contentStr
8897
+ }
8898
+ ]
8899
+ });
8900
+ continue;
8901
+ }
8902
+ }
8903
+ return { system: systemParts.join("\n\n"), messages: out };
8904
+ }
8905
+
8906
+ // src/llm/anthropic.ts
8907
+ var LLM2 = class extends AnthropicLLMProvider {
8908
+ constructor(opts = {}) {
8909
+ const key = opts.apiKey ?? process.env.ANTHROPIC_API_KEY;
8910
+ if (!key) {
8911
+ throw new Error(
8912
+ "Anthropic LLM requires an apiKey. Pass { apiKey: 'sk-ant-...' } or set ANTHROPIC_API_KEY."
8913
+ );
8914
+ }
8915
+ super({
8916
+ apiKey: key,
8917
+ model: opts.model,
8918
+ maxTokens: opts.maxTokens,
8919
+ temperature: opts.temperature,
8920
+ baseUrl: opts.baseUrl,
8921
+ anthropicVersion: opts.anthropicVersion
8922
+ });
8923
+ }
8924
+ };
8925
+
8926
+ // src/providers/groq-llm.ts
8927
+ init_logger();
8928
+ var GROQ_BASE_URL = "https://api.groq.com/openai/v1";
8929
+ var DEFAULT_MODEL2 = "llama-3.3-70b-versatile";
8930
+ var GroqLLMProvider = class {
8931
+ apiKey;
8932
+ model;
8933
+ baseUrl;
8934
+ constructor(options) {
8935
+ if (!options.apiKey) {
8936
+ throw new Error(
8937
+ "Groq API key is required. Pass it via { apiKey } or read GROQ_API_KEY from the environment."
8938
+ );
8939
+ }
8940
+ this.apiKey = options.apiKey;
8941
+ this.model = options.model ?? DEFAULT_MODEL2;
8942
+ this.baseUrl = options.baseUrl ?? GROQ_BASE_URL;
8943
+ }
8944
+ async *stream(messages, tools) {
8945
+ const body = {
8946
+ model: this.model,
8947
+ messages,
8948
+ stream: true
8949
+ };
8950
+ if (tools) body.tools = tools;
8951
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
8952
+ method: "POST",
8953
+ headers: {
8954
+ "Content-Type": "application/json",
8955
+ Authorization: `Bearer ${this.apiKey}`
8956
+ },
8957
+ body: JSON.stringify(body),
8958
+ signal: AbortSignal.timeout(3e4)
8959
+ });
8960
+ if (!response.ok) {
8961
+ const errText = await response.text();
8962
+ getLogger().error(`Groq API error: ${response.status} ${errText}`);
8963
+ return;
8964
+ }
8965
+ yield* parseOpenAISseStream(response);
8966
+ }
8967
+ };
8968
+ async function* parseOpenAISseStream(response) {
8969
+ const reader = response.body?.getReader();
8970
+ if (!reader) return;
8971
+ const decoder = new TextDecoder();
8972
+ let buffer = "";
8973
+ while (true) {
8974
+ const { done, value } = await reader.read();
8975
+ if (done) break;
8976
+ buffer += decoder.decode(value, { stream: true });
8977
+ const lines = buffer.split("\n");
8978
+ buffer = lines.pop() || "";
8979
+ for (const line of lines) {
8980
+ const trimmed = line.trim();
8981
+ if (!trimmed || !trimmed.startsWith("data: ")) continue;
8982
+ const data = trimmed.slice(6);
8983
+ if (data === "[DONE]") continue;
8984
+ let chunk;
8985
+ try {
8986
+ chunk = JSON.parse(data);
8987
+ } catch {
8988
+ continue;
8989
+ }
8990
+ const delta = chunk.choices?.[0]?.delta;
8991
+ if (!delta) continue;
8992
+ if (delta.content) {
8993
+ yield { type: "text", content: delta.content };
8994
+ }
8995
+ if (delta.tool_calls) {
8996
+ for (const tc of delta.tool_calls) {
8997
+ yield {
8998
+ type: "tool_call",
8999
+ index: tc.index,
9000
+ id: tc.id,
9001
+ name: tc.function?.name,
9002
+ arguments: tc.function?.arguments
9003
+ };
9004
+ }
9005
+ }
9006
+ }
9007
+ }
9008
+ }
9009
+
9010
+ // src/llm/groq.ts
9011
+ var LLM3 = class extends GroqLLMProvider {
9012
+ constructor(opts = {}) {
9013
+ const key = opts.apiKey ?? process.env.GROQ_API_KEY;
9014
+ if (!key) {
9015
+ throw new Error(
9016
+ "Groq LLM requires an apiKey. Pass { apiKey: 'gsk_...' } or set GROQ_API_KEY."
9017
+ );
9018
+ }
9019
+ super({
9020
+ apiKey: key,
9021
+ model: opts.model,
9022
+ baseUrl: opts.baseUrl
9023
+ });
9024
+ }
9025
+ };
9026
+
9027
+ // src/providers/cerebras-llm.ts
9028
+ init_logger();
9029
+ var CEREBRAS_BASE_URL = "https://api.cerebras.ai/v1";
9030
+ var DEFAULT_MODEL3 = "llama3.1-8b";
9031
+ var CerebrasLLMProvider = class {
9032
+ apiKey;
9033
+ model;
9034
+ baseUrl;
9035
+ gzipCompression;
9036
+ constructor(options) {
9037
+ if (!options.apiKey) {
9038
+ throw new Error(
9039
+ "Cerebras API key is required. Pass it via { apiKey } or read CEREBRAS_API_KEY from the environment."
9040
+ );
9041
+ }
9042
+ this.apiKey = options.apiKey;
9043
+ this.model = options.model ?? DEFAULT_MODEL3;
9044
+ this.baseUrl = options.baseUrl ?? CEREBRAS_BASE_URL;
9045
+ this.gzipCompression = options.gzipCompression ?? false;
9046
+ }
9047
+ async *stream(messages, tools) {
9048
+ const body = {
9049
+ model: this.model,
9050
+ messages,
9051
+ stream: true
9052
+ };
9053
+ if (tools) body.tools = tools;
9054
+ const headers = {
9055
+ "Content-Type": "application/json",
9056
+ Authorization: `Bearer ${this.apiKey}`
9057
+ };
9058
+ let payload = JSON.stringify(body);
9059
+ if (this.gzipCompression) {
9060
+ const compressed = await gzipEncode(payload);
9061
+ if (compressed) {
9062
+ payload = compressed;
9063
+ headers["Content-Encoding"] = "gzip";
9064
+ }
9065
+ }
9066
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
9067
+ method: "POST",
9068
+ headers,
9069
+ body: payload,
9070
+ signal: AbortSignal.timeout(3e4)
9071
+ });
9072
+ if (!response.ok) {
9073
+ const errText = await response.text();
9074
+ getLogger().error(`Cerebras API error: ${response.status} ${errText}`);
9075
+ return;
9076
+ }
9077
+ yield* parseOpenAISseStream(response);
9078
+ }
9079
+ };
9080
+ async function gzipEncode(data) {
9081
+ const CompressionCtor = globalThis.CompressionStream;
9082
+ if (!CompressionCtor) return null;
9083
+ const stream = new CompressionCtor("gzip");
9084
+ const writer = stream.writable.getWriter();
9085
+ const encoder = new TextEncoder();
9086
+ await writer.write(encoder.encode(data));
9087
+ await writer.close();
9088
+ const chunks = [];
9089
+ const reader = stream.readable.getReader();
9090
+ while (true) {
9091
+ const { done, value } = await reader.read();
9092
+ if (done) break;
9093
+ if (value) chunks.push(value);
9094
+ }
9095
+ const total = chunks.reduce((n, c) => n + c.length, 0);
9096
+ const out = new Uint8Array(total);
9097
+ let offset = 0;
9098
+ for (const c of chunks) {
9099
+ out.set(c, offset);
9100
+ offset += c.length;
9101
+ }
9102
+ return out;
9103
+ }
9104
+
9105
+ // src/llm/cerebras.ts
9106
+ var LLM4 = class extends CerebrasLLMProvider {
9107
+ constructor(opts = {}) {
9108
+ const key = opts.apiKey ?? process.env.CEREBRAS_API_KEY;
9109
+ if (!key) {
9110
+ throw new Error(
9111
+ "Cerebras LLM requires an apiKey. Pass { apiKey: 'csk-...' } or set CEREBRAS_API_KEY."
9112
+ );
9113
+ }
9114
+ super({
9115
+ apiKey: key,
9116
+ model: opts.model,
9117
+ baseUrl: opts.baseUrl,
9118
+ gzipCompression: opts.gzipCompression
9119
+ });
9120
+ }
9121
+ };
9122
+
9123
+ // src/providers/google-llm.ts
9124
+ init_logger();
9125
+ var DEFAULT_MODEL4 = "gemini-2.5-flash";
9126
+ var DEFAULT_BASE_URL3 = "https://generativelanguage.googleapis.com/v1beta";
9127
+ var GoogleLLMProvider = class {
9128
+ apiKey;
9129
+ model;
9130
+ baseUrl;
9131
+ temperature;
9132
+ maxOutputTokens;
9133
+ constructor(options) {
9134
+ if (!options.apiKey) {
9135
+ throw new Error(
9136
+ "Google API key is required. Pass it via { apiKey } or read GOOGLE_API_KEY from the environment."
9137
+ );
9138
+ }
9139
+ this.apiKey = options.apiKey;
9140
+ this.model = options.model ?? DEFAULT_MODEL4;
9141
+ this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL3;
9142
+ this.temperature = options.temperature;
9143
+ this.maxOutputTokens = options.maxOutputTokens;
9144
+ }
9145
+ async *stream(messages, tools) {
9146
+ const { systemInstruction, contents } = toGeminiContents(messages);
9147
+ const geminiTools = tools ? toGeminiTools(tools) : null;
9148
+ const body = { contents };
9149
+ if (systemInstruction) {
9150
+ body.systemInstruction = { role: "system", parts: [{ text: systemInstruction }] };
9151
+ }
9152
+ if (geminiTools) body.tools = geminiTools;
9153
+ const generationConfig = {};
9154
+ if (this.temperature !== void 0) generationConfig.temperature = this.temperature;
9155
+ if (this.maxOutputTokens !== void 0)
9156
+ generationConfig.maxOutputTokens = this.maxOutputTokens;
9157
+ if (Object.keys(generationConfig).length > 0) body.generationConfig = generationConfig;
9158
+ const url = `${this.baseUrl}/models/${encodeURIComponent(this.model)}:streamGenerateContent?alt=sse&key=${encodeURIComponent(this.apiKey)}`;
9159
+ const response = await fetch(url, {
9160
+ method: "POST",
9161
+ headers: { "Content-Type": "application/json" },
9162
+ body: JSON.stringify(body),
9163
+ signal: AbortSignal.timeout(3e4)
9164
+ });
9165
+ if (!response.ok) {
9166
+ const errText = await response.text();
9167
+ getLogger().error(`Gemini API error: ${response.status} ${errText}`);
9168
+ return;
9169
+ }
9170
+ const reader = response.body?.getReader();
9171
+ if (!reader) return;
9172
+ const decoder = new TextDecoder();
9173
+ let buffer = "";
9174
+ let nextIndex = 0;
9175
+ while (true) {
9176
+ const { done, value } = await reader.read();
9177
+ if (done) break;
9178
+ buffer += decoder.decode(value, { stream: true });
9179
+ const lines = buffer.split("\n");
9180
+ buffer = lines.pop() || "";
9181
+ for (const line of lines) {
9182
+ const trimmed = line.trim();
9183
+ if (!trimmed.startsWith("data: ")) continue;
9184
+ const data = trimmed.slice(6);
9185
+ if (!data) continue;
9186
+ let payload;
9187
+ try {
9188
+ payload = JSON.parse(data);
9189
+ } catch {
9190
+ continue;
9191
+ }
9192
+ const candidate = payload.candidates?.[0];
9193
+ const parts = candidate?.content?.parts ?? [];
9194
+ for (const part of parts) {
9195
+ if (part.functionCall) {
9196
+ const args = part.functionCall.args ?? {};
9197
+ const callId = part.functionCall.id ?? `gemini_call_${nextIndex}`;
9198
+ yield {
9199
+ type: "tool_call",
9200
+ index: nextIndex,
9201
+ id: callId,
9202
+ name: part.functionCall.name ?? "",
9203
+ arguments: JSON.stringify(args)
9204
+ };
9205
+ nextIndex++;
9206
+ continue;
9207
+ }
9208
+ if (part.text) {
9209
+ yield { type: "text", content: part.text };
9210
+ }
9211
+ }
9212
+ }
9213
+ }
9214
+ yield { type: "done" };
9215
+ }
9216
+ };
9217
+ function toGeminiTools(tools) {
9218
+ const functionDeclarations = tools.map((t) => {
9219
+ const fn = t.function ?? t;
9220
+ return {
9221
+ name: String(fn.name ?? ""),
9222
+ description: String(fn.description ?? ""),
9223
+ parameters: fn.parameters ?? { type: "object", properties: {} }
9224
+ };
9225
+ });
9226
+ if (functionDeclarations.length === 0) return [];
9227
+ return [{ functionDeclarations }];
9228
+ }
9229
+ function toGeminiContents(messages) {
9230
+ const systemParts = [];
9231
+ const contents = [];
9232
+ for (const rawMsg of messages) {
9233
+ const role = rawMsg.role;
9234
+ if (role === "system") {
9235
+ if (typeof rawMsg.content === "string" && rawMsg.content) {
9236
+ systemParts.push(rawMsg.content);
9237
+ }
9238
+ continue;
9239
+ }
9240
+ if (role === "user") {
9241
+ if (typeof rawMsg.content === "string" && rawMsg.content) {
9242
+ contents.push({ role: "user", parts: [{ text: rawMsg.content }] });
9243
+ }
9244
+ continue;
9245
+ }
9246
+ if (role === "assistant") {
9247
+ const parts = [];
9248
+ if (typeof rawMsg.content === "string" && rawMsg.content) {
9249
+ parts.push({ text: rawMsg.content });
9250
+ }
9251
+ for (const tc of rawMsg.tool_calls ?? []) {
9252
+ let args = {};
9253
+ try {
9254
+ const parsed = JSON.parse(tc.function?.arguments ?? "{}");
9255
+ if (parsed && typeof parsed === "object") args = parsed;
9256
+ } catch {
9257
+ args = {};
9258
+ }
9259
+ parts.push({
9260
+ functionCall: {
9261
+ name: tc.function?.name ?? "",
9262
+ args,
9263
+ id: tc.id
9264
+ }
9265
+ });
9266
+ }
9267
+ if (parts.length > 0) contents.push({ role: "model", parts });
9268
+ continue;
9269
+ }
9270
+ if (role === "tool") {
9271
+ const raw = rawMsg.content;
9272
+ let response;
9273
+ if (typeof raw === "string") {
9274
+ try {
9275
+ const parsed = JSON.parse(raw);
9276
+ response = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : { result: parsed };
9277
+ } catch {
9278
+ response = { result: raw };
9279
+ }
9280
+ } else {
9281
+ response = raw ?? {};
9282
+ }
9283
+ contents.push({
9284
+ role: "user",
9285
+ parts: [
9286
+ {
9287
+ functionResponse: {
9288
+ name: rawMsg.name ?? rawMsg.tool_call_id ?? "",
9289
+ response,
9290
+ id: rawMsg.tool_call_id
9291
+ }
9292
+ }
9293
+ ]
9294
+ });
9295
+ continue;
9296
+ }
9297
+ }
9298
+ return { systemInstruction: systemParts.join("\n\n"), contents };
9299
+ }
9300
+
9301
+ // src/llm/google.ts
9302
+ var LLM5 = class extends GoogleLLMProvider {
9303
+ constructor(opts = {}) {
9304
+ const key = opts.apiKey ?? process.env.GEMINI_API_KEY ?? process.env.GOOGLE_API_KEY;
9305
+ if (!key) {
9306
+ throw new Error(
9307
+ "Google LLM requires an apiKey. Pass { apiKey: 'AIza...' } or set GEMINI_API_KEY (or GOOGLE_API_KEY)."
9308
+ );
9309
+ }
9310
+ super({
9311
+ apiKey: key,
9312
+ model: opts.model,
9313
+ baseUrl: opts.baseUrl,
9314
+ temperature: opts.temperature,
9315
+ maxOutputTokens: opts.maxOutputTokens
9316
+ });
9317
+ }
9318
+ };
9319
+
9467
9320
  // src/carriers/twilio.ts
9468
9321
  var Carrier = class {
9469
9322
  kind = "twilio";
@@ -10178,6 +10031,7 @@ function isAudioConfig(value) {
10178
10031
  // Annotate the CommonJS export names for ESM import in node:
10179
10032
  0 && (module.exports = {
10180
10033
  AllProvidersFailedError,
10034
+ AnthropicLLM,
10181
10035
  AssemblyAISTT,
10182
10036
  AuthenticationError,
10183
10037
  BackgroundAudioPlayer,
@@ -10185,6 +10039,7 @@ function isAudioConfig(value) {
10185
10039
  CallMetricsAccumulator,
10186
10040
  CartesiaSTT,
10187
10041
  CartesiaTTS,
10042
+ CerebrasLLM,
10188
10043
  ChatContext,
10189
10044
  CloudflareTunnel,
10190
10045
  DEFAULT_MIN_SENTENCE_LEN,
@@ -10198,11 +10053,14 @@ function isAudioConfig(value) {
10198
10053
  GEMINI_DEFAULT_INPUT_SR,
10199
10054
  GEMINI_DEFAULT_OUTPUT_SR,
10200
10055
  GeminiLiveAdapter,
10056
+ GoogleLLM,
10057
+ GroqLLM,
10201
10058
  Guardrail,
10202
10059
  IVRActivity,
10203
10060
  LLMLoop,
10204
10061
  LMNTTTS,
10205
10062
  MetricsStore,
10063
+ OpenAILLM,
10206
10064
  OpenAILLMProvider,
10207
10065
  OpenAIRealtime,
10208
10066
  OpenAIRealtimeAdapter,