getpatter 0.6.5 → 0.6.7
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/{chunk-CRPJLVHB.mjs → chunk-YJX2EKON.mjs} +649 -80
- package/dist/cli.js +501 -2
- package/dist/index.d.mts +233 -10
- package/dist/index.d.ts +233 -10
- package/dist/index.js +1591 -198
- package/dist/index.mjs +883 -78
- package/dist/{test-mode-HGHI2AUV.mjs → test-mode-XFOADUNE.mjs} +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
openclawPostCallNotifier,
|
|
58
58
|
resolveLogRoot,
|
|
59
59
|
startSpan
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-YJX2EKON.mjs";
|
|
61
61
|
import {
|
|
62
62
|
OpenAIRealtime2Adapter,
|
|
63
63
|
OpenAIRealtimeAdapter,
|
|
@@ -106,6 +106,57 @@ init_esm_shims();
|
|
|
106
106
|
// src/client.ts
|
|
107
107
|
init_esm_shims();
|
|
108
108
|
|
|
109
|
+
// src/telephony/twilio.ts
|
|
110
|
+
init_esm_shims();
|
|
111
|
+
var Carrier2 = class {
|
|
112
|
+
kind = "twilio";
|
|
113
|
+
accountSid;
|
|
114
|
+
authToken;
|
|
115
|
+
constructor(opts = {}) {
|
|
116
|
+
const sid = opts.accountSid ?? process.env.TWILIO_ACCOUNT_SID;
|
|
117
|
+
const tok = opts.authToken ?? process.env.TWILIO_AUTH_TOKEN;
|
|
118
|
+
if (!sid) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
"Twilio carrier requires accountSid. Pass { accountSid: 'AC...' } or set TWILIO_ACCOUNT_SID in the environment."
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
if (!tok) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
"Twilio carrier requires authToken. Pass { authToken: '...' } or set TWILIO_AUTH_TOKEN in the environment."
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
this.accountSid = sid;
|
|
129
|
+
this.authToken = tok;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/telephony/telnyx.ts
|
|
134
|
+
init_esm_shims();
|
|
135
|
+
var Carrier3 = class {
|
|
136
|
+
kind = "telnyx";
|
|
137
|
+
apiKey;
|
|
138
|
+
connectionId;
|
|
139
|
+
publicKey;
|
|
140
|
+
constructor(opts = {}) {
|
|
141
|
+
const key = opts.apiKey ?? process.env.TELNYX_API_KEY;
|
|
142
|
+
const conn = opts.connectionId ?? process.env.TELNYX_CONNECTION_ID;
|
|
143
|
+
const pub = opts.publicKey ?? process.env.TELNYX_PUBLIC_KEY;
|
|
144
|
+
if (!key) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
"Telnyx carrier requires apiKey. Pass { apiKey: '...' } or set TELNYX_API_KEY in the environment."
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
if (!conn) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
"Telnyx carrier requires connectionId. Pass { connectionId: '...' } or set TELNYX_CONNECTION_ID in the environment."
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
this.apiKey = key;
|
|
155
|
+
this.connectionId = conn;
|
|
156
|
+
this.publicKey = pub;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
109
160
|
// src/engines/openai.ts
|
|
110
161
|
init_esm_shims();
|
|
111
162
|
var Realtime = class {
|
|
@@ -324,6 +375,575 @@ function validateAllToolSchemas(tools) {
|
|
|
324
375
|
}
|
|
325
376
|
}
|
|
326
377
|
|
|
378
|
+
// src/telemetry/index.ts
|
|
379
|
+
init_esm_shims();
|
|
380
|
+
|
|
381
|
+
// src/telemetry/client.ts
|
|
382
|
+
init_esm_shims();
|
|
383
|
+
|
|
384
|
+
// src/telemetry/consent.ts
|
|
385
|
+
init_esm_shims();
|
|
386
|
+
|
|
387
|
+
// src/telemetry/env.ts
|
|
388
|
+
init_esm_shims();
|
|
389
|
+
var CI_ENV_VARS = [
|
|
390
|
+
"CI",
|
|
391
|
+
"CONTINUOUS_INTEGRATION",
|
|
392
|
+
"GITHUB_ACTIONS",
|
|
393
|
+
"GITLAB_CI",
|
|
394
|
+
"TRAVIS",
|
|
395
|
+
"CIRCLECI",
|
|
396
|
+
"APPVEYOR",
|
|
397
|
+
"TF_BUILD",
|
|
398
|
+
"TEAMCITY_VERSION",
|
|
399
|
+
"BUILDKITE",
|
|
400
|
+
"DRONE",
|
|
401
|
+
"JENKINS_URL",
|
|
402
|
+
"HUDSON_URL",
|
|
403
|
+
"BAMBOO_BUILDKEY",
|
|
404
|
+
"CODEBUILD_BUILD_ID"
|
|
405
|
+
];
|
|
406
|
+
var TEST_ENV_VARS = ["VITEST", "JEST_WORKER_ID"];
|
|
407
|
+
function isTruthy(value) {
|
|
408
|
+
if (value === void 0) return false;
|
|
409
|
+
const v = value.trim().toLowerCase();
|
|
410
|
+
return v !== "" && v !== "0" && v !== "false" && v !== "no" && v !== "off";
|
|
411
|
+
}
|
|
412
|
+
function isCi() {
|
|
413
|
+
return CI_ENV_VARS.some((name) => isTruthy(process.env[name]));
|
|
414
|
+
}
|
|
415
|
+
function isTest() {
|
|
416
|
+
if (TEST_ENV_VARS.some((name) => process.env[name] !== void 0)) return true;
|
|
417
|
+
const node = (process.env.NODE_ENV ?? "").trim().toLowerCase();
|
|
418
|
+
const patter = (process.env.PATTER_ENV ?? "").trim().toLowerCase();
|
|
419
|
+
return node === "test" || patter === "test";
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// src/telemetry/install-id.ts
|
|
423
|
+
init_esm_shims();
|
|
424
|
+
import { randomUUID } from "crypto";
|
|
425
|
+
import * as fs from "fs";
|
|
426
|
+
import * as os from "os";
|
|
427
|
+
import * as path from "path";
|
|
428
|
+
var RUN_ID = randomUUID().replace(/-/g, "");
|
|
429
|
+
var HEX32 = /^[0-9a-f]{32}$/;
|
|
430
|
+
var VERSION_RE = /^[0-9][0-9a-z.+-]{0,31}$/;
|
|
431
|
+
var cachedInstallId = null;
|
|
432
|
+
function runId() {
|
|
433
|
+
return RUN_ID;
|
|
434
|
+
}
|
|
435
|
+
function statePath() {
|
|
436
|
+
const base = process.env.PATTER_TELEMETRY_STATE_DIR || process.env.XDG_STATE_HOME;
|
|
437
|
+
const root = base && base.length > 0 ? base : path.join(os.homedir(), ".getpatter");
|
|
438
|
+
return path.join(root, "install-id");
|
|
439
|
+
}
|
|
440
|
+
function installId() {
|
|
441
|
+
if (cachedInstallId !== null) return cachedInstallId;
|
|
442
|
+
const p = statePath();
|
|
443
|
+
try {
|
|
444
|
+
const existing = fs.readFileSync(p, "utf8").trim();
|
|
445
|
+
if (HEX32.test(existing)) {
|
|
446
|
+
cachedInstallId = existing;
|
|
447
|
+
return cachedInstallId;
|
|
448
|
+
}
|
|
449
|
+
} catch {
|
|
450
|
+
}
|
|
451
|
+
const newId = randomUUID().replace(/-/g, "");
|
|
452
|
+
try {
|
|
453
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
454
|
+
fs.writeFileSync(p, newId, "utf8");
|
|
455
|
+
cachedInstallId = newId;
|
|
456
|
+
} catch {
|
|
457
|
+
cachedInstallId = RUN_ID;
|
|
458
|
+
}
|
|
459
|
+
return cachedInstallId;
|
|
460
|
+
}
|
|
461
|
+
function versionPath() {
|
|
462
|
+
return path.join(path.dirname(statePath()), "version");
|
|
463
|
+
}
|
|
464
|
+
function previousVersion(current) {
|
|
465
|
+
const p = versionPath();
|
|
466
|
+
let prev = "";
|
|
467
|
+
try {
|
|
468
|
+
prev = fs.readFileSync(p, "utf8").trim();
|
|
469
|
+
} catch {
|
|
470
|
+
prev = "";
|
|
471
|
+
}
|
|
472
|
+
try {
|
|
473
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
474
|
+
fs.writeFileSync(p, current, "utf8");
|
|
475
|
+
} catch {
|
|
476
|
+
}
|
|
477
|
+
return VERSION_RE.test(prev) ? prev : "";
|
|
478
|
+
}
|
|
479
|
+
function daysSinceInstallBucket() {
|
|
480
|
+
let mtimeMs;
|
|
481
|
+
try {
|
|
482
|
+
mtimeMs = fs.statSync(statePath()).mtimeMs;
|
|
483
|
+
} catch {
|
|
484
|
+
return "0";
|
|
485
|
+
}
|
|
486
|
+
const days = Math.max(0, Math.floor((Date.now() - mtimeMs) / 864e5));
|
|
487
|
+
if (days === 0) return "0";
|
|
488
|
+
if (days <= 7) return "1_7";
|
|
489
|
+
if (days <= 30) return "8_30";
|
|
490
|
+
return "30_plus";
|
|
491
|
+
}
|
|
492
|
+
function firstRunPath() {
|
|
493
|
+
return path.join(path.dirname(statePath()), "first-run");
|
|
494
|
+
}
|
|
495
|
+
function isFirstRun() {
|
|
496
|
+
const p = firstRunPath();
|
|
497
|
+
try {
|
|
498
|
+
if (fs.existsSync(p)) return false;
|
|
499
|
+
} catch {
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
try {
|
|
503
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
504
|
+
fs.writeFileSync(p, "1", "utf8");
|
|
505
|
+
return true;
|
|
506
|
+
} catch {
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function optOutPath() {
|
|
511
|
+
return path.join(path.dirname(statePath()), "telemetry-disabled");
|
|
512
|
+
}
|
|
513
|
+
function isOptedOut() {
|
|
514
|
+
try {
|
|
515
|
+
return fs.existsSync(optOutPath());
|
|
516
|
+
} catch {
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// src/telemetry/consent.ts
|
|
522
|
+
function isEnabled(flag) {
|
|
523
|
+
if (isTruthy(process.env.DO_NOT_TRACK)) return false;
|
|
524
|
+
if (isTruthy(process.env.PATTER_TELEMETRY_DISABLED)) return false;
|
|
525
|
+
if (isOptedOut()) return false;
|
|
526
|
+
if (flag === false) return false;
|
|
527
|
+
if (isCi() || isTest()) return false;
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// src/telemetry/events.ts
|
|
532
|
+
init_esm_shims();
|
|
533
|
+
import * as os2 from "os";
|
|
534
|
+
|
|
535
|
+
// src/telemetry/stack.ts
|
|
536
|
+
init_esm_shims();
|
|
537
|
+
var STACK_VENDORS = /* @__PURE__ */ new Set([
|
|
538
|
+
"openai",
|
|
539
|
+
"anthropic",
|
|
540
|
+
"google",
|
|
541
|
+
"cerebras",
|
|
542
|
+
"groq",
|
|
543
|
+
"deepgram",
|
|
544
|
+
"elevenlabs",
|
|
545
|
+
"cartesia",
|
|
546
|
+
"whisper",
|
|
547
|
+
"soniox",
|
|
548
|
+
"assemblyai",
|
|
549
|
+
"speechmatics",
|
|
550
|
+
"lmnt",
|
|
551
|
+
"rime",
|
|
552
|
+
"inworld",
|
|
553
|
+
"telnyx",
|
|
554
|
+
"other"
|
|
555
|
+
]);
|
|
556
|
+
var VENDOR_ALIASES = {
|
|
557
|
+
cartesia_stt: "cartesia",
|
|
558
|
+
cartesia_tts: "cartesia",
|
|
559
|
+
openai_tts: "openai",
|
|
560
|
+
openai_transcribe: "openai",
|
|
561
|
+
elevenlabs_ws: "elevenlabs",
|
|
562
|
+
telnyx_stt: "telnyx",
|
|
563
|
+
telnyx_tts: "telnyx"
|
|
564
|
+
};
|
|
565
|
+
var RAW_UNSAFE_RE = /[^a-z0-9._-]/;
|
|
566
|
+
var DATE_SUFFIX_RE = /-\d{8}$/;
|
|
567
|
+
function vendorOf(providerKey) {
|
|
568
|
+
if (!providerKey) return "other";
|
|
569
|
+
const v = VENDOR_ALIASES[providerKey] ?? providerKey;
|
|
570
|
+
return STACK_VENDORS.has(v) ? v : "other";
|
|
571
|
+
}
|
|
572
|
+
function modelToken(vendor, rawModel) {
|
|
573
|
+
if (!rawModel) return `${vendor}-other`;
|
|
574
|
+
const m = rawModel.trim().toLowerCase();
|
|
575
|
+
if (m.length > 40 || RAW_UNSAFE_RE.test(m)) return `${vendor}-other`;
|
|
576
|
+
const token = m.replace(/_/g, "-").replace(DATE_SUFFIX_RE, "").replace(/^[-.]+|[-.]+$/g, "");
|
|
577
|
+
return token ? `${vendor}-${token}` : `${vendor}-other`;
|
|
578
|
+
}
|
|
579
|
+
function readProviderKey(obj) {
|
|
580
|
+
const ctor = obj?.constructor;
|
|
581
|
+
const key = ctor?.providerKey;
|
|
582
|
+
return typeof key === "string" && key ? key : null;
|
|
583
|
+
}
|
|
584
|
+
function readModel(obj) {
|
|
585
|
+
const rec = obj;
|
|
586
|
+
for (const attr of ["model", "modelId", "_model"]) {
|
|
587
|
+
const v = rec?.[attr];
|
|
588
|
+
if (typeof v === "string" && v) return v;
|
|
589
|
+
}
|
|
590
|
+
return "";
|
|
591
|
+
}
|
|
592
|
+
function layerDims(obj, providerField, modelField) {
|
|
593
|
+
if (obj === null || obj === void 0) return {};
|
|
594
|
+
const vendor = vendorOf(readProviderKey(obj));
|
|
595
|
+
return { [providerField]: vendor, [modelField]: modelToken(vendor, readModel(obj)) };
|
|
596
|
+
}
|
|
597
|
+
function stackDimensions(stt, tts, llm) {
|
|
598
|
+
return {
|
|
599
|
+
...layerDims(stt, "stt_provider", "stt_model"),
|
|
600
|
+
...layerDims(tts, "tts_provider", "tts_model"),
|
|
601
|
+
...layerDims(llm, "llm_provider", "llm_model")
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// src/telemetry/events.ts
|
|
606
|
+
var SCHEMA_VERSION = 5;
|
|
607
|
+
var EVENT_SDK_INITIALIZED = "sdk_initialized";
|
|
608
|
+
var EVENT_FIRST_RUN = "first_run";
|
|
609
|
+
var EVENT_CLI_COMMAND = "cli_command";
|
|
610
|
+
var EVENT_FEATURE_USED = "feature_used";
|
|
611
|
+
var EVENT_AGENT_CONFIGURED = "agent_configured";
|
|
612
|
+
var EVENT_CALL_STARTED = "call_started";
|
|
613
|
+
var EVENT_CALL_COMPLETED = "call_completed";
|
|
614
|
+
var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
615
|
+
EVENT_SDK_INITIALIZED,
|
|
616
|
+
EVENT_FIRST_RUN,
|
|
617
|
+
EVENT_CLI_COMMAND,
|
|
618
|
+
EVENT_FEATURE_USED,
|
|
619
|
+
EVENT_AGENT_CONFIGURED,
|
|
620
|
+
EVENT_CALL_STARTED,
|
|
621
|
+
EVENT_CALL_COMPLETED
|
|
622
|
+
]);
|
|
623
|
+
var DIMENSION_VALUES = {
|
|
624
|
+
carrier: /* @__PURE__ */ new Set(["twilio", "telnyx", "plivo", "none"]),
|
|
625
|
+
tunnel: /* @__PURE__ */ new Set(["static", "configured", "none"]),
|
|
626
|
+
engine: /* @__PURE__ */ new Set(["realtime", "convai", "pipeline"]),
|
|
627
|
+
provider: /* @__PURE__ */ new Set([
|
|
628
|
+
"openai",
|
|
629
|
+
"elevenlabs",
|
|
630
|
+
"deepgram",
|
|
631
|
+
"cartesia",
|
|
632
|
+
"cerebras",
|
|
633
|
+
"anthropic",
|
|
634
|
+
"google",
|
|
635
|
+
"whisper",
|
|
636
|
+
"other"
|
|
637
|
+
]),
|
|
638
|
+
// agent_configured dimensions
|
|
639
|
+
custom_tool_count_bucket: /* @__PURE__ */ new Set(["0", "1", "2_3", "4_6", "7_12", "13_plus"]),
|
|
640
|
+
integration: /* @__PURE__ */ new Set(["openclaw", "mcp", "hermes", "other", "none"]),
|
|
641
|
+
integration_kind: /* @__PURE__ */ new Set(["consult", "mcp", "none"]),
|
|
642
|
+
mcp_server_count_bucket: /* @__PURE__ */ new Set(["0", "1", "2_3", "4_plus"]),
|
|
643
|
+
// call_started / call_completed: inbound vs outbound — a core usage split.
|
|
644
|
+
direction: /* @__PURE__ */ new Set(["inbound", "outbound", "none"]),
|
|
645
|
+
// cli_command: which CLI subcommand was invoked (never args/flags values).
|
|
646
|
+
cli_command: /* @__PURE__ */ new Set(["dashboard", "eval", "telemetry", "none", "other"]),
|
|
647
|
+
// call_completed: the call's terminal outcome
|
|
648
|
+
outcome: /* @__PURE__ */ new Set(["completed", "error", "no_answer", "busy", "failed"]),
|
|
649
|
+
// call_completed: terminal error code (mirrors ErrorCode, plus "other"). Never
|
|
650
|
+
// the error message.
|
|
651
|
+
error_code: /* @__PURE__ */ new Set([
|
|
652
|
+
"config",
|
|
653
|
+
"connection",
|
|
654
|
+
"auth",
|
|
655
|
+
"timeout",
|
|
656
|
+
"rate_limit",
|
|
657
|
+
"webhook_verification",
|
|
658
|
+
"input_validation",
|
|
659
|
+
"provider_error",
|
|
660
|
+
"provision",
|
|
661
|
+
"internal",
|
|
662
|
+
"other"
|
|
663
|
+
]),
|
|
664
|
+
// feature_used (pipeline): per-layer vendor of the composed stack. A
|
|
665
|
+
// providerKey not on the closed allowlist collapses to "other"; an absent layer
|
|
666
|
+
// is omitted (the value set keeps "none" only as a safety token).
|
|
667
|
+
stt_provider: /* @__PURE__ */ new Set([...STACK_VENDORS, "none"]),
|
|
668
|
+
tts_provider: /* @__PURE__ */ new Set([...STACK_VENDORS, "none"]),
|
|
669
|
+
llm_provider: /* @__PURE__ */ new Set([...STACK_VENDORS, "none"]),
|
|
670
|
+
// sdk_initialized: anonymous deploy-shape (presence-only env/file probes).
|
|
671
|
+
invoked_by_agent: /* @__PURE__ */ new Set(["claude", "cursor", "copilot", "gemini", "windsurf", "other", "none"]),
|
|
672
|
+
serverless: /* @__PURE__ */ new Set(["lambda", "cloud_run", "vercel", "azure_functions", "none"]),
|
|
673
|
+
cloud: /* @__PURE__ */ new Set(["aws", "gcp", "azure", "fly", "none"]),
|
|
674
|
+
package_manager: /* @__PURE__ */ new Set(["npm", "pnpm", "yarn", "bun", "pip", "uv", "poetry", "pipenv", "conda", "none"]),
|
|
675
|
+
days_since_install_bucket: /* @__PURE__ */ new Set(["0", "1_7", "8_30", "30_plus"]),
|
|
676
|
+
// agent_configured: feature-adoption (Realtime tuning).
|
|
677
|
+
noise_reduction: /* @__PURE__ */ new Set(["near_field", "far_field", "none"]),
|
|
678
|
+
turn_detection: /* @__PURE__ */ new Set(["default", "custom", "none"]),
|
|
679
|
+
// call_completed: how many conversational turns the call had.
|
|
680
|
+
turn_count_bucket: /* @__PURE__ */ new Set(["0", "1", "2_3", "4_6", "7_12", "13_plus"])
|
|
681
|
+
};
|
|
682
|
+
var NUMERIC_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
683
|
+
"builtin_tool_count",
|
|
684
|
+
"latency_ms",
|
|
685
|
+
"duration_seconds",
|
|
686
|
+
"cost_usd"
|
|
687
|
+
]);
|
|
688
|
+
var STRING_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
689
|
+
"stt_model",
|
|
690
|
+
"tts_model",
|
|
691
|
+
"llm_model",
|
|
692
|
+
"previous_sdk_version"
|
|
693
|
+
]);
|
|
694
|
+
var MODEL_TOKEN_RE = /^[a-z0-9][a-z0-9.-]{0,40}$/;
|
|
695
|
+
var BOOL_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
696
|
+
"container",
|
|
697
|
+
"preambles_used",
|
|
698
|
+
"per_tool_timeouts_set",
|
|
699
|
+
"llm_fallback_configured"
|
|
700
|
+
]);
|
|
701
|
+
var ALLOWED_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
702
|
+
...Object.keys(DIMENSION_VALUES),
|
|
703
|
+
...NUMERIC_DIMENSIONS,
|
|
704
|
+
...STRING_DIMENSIONS,
|
|
705
|
+
...BOOL_DIMENSIONS
|
|
706
|
+
]);
|
|
707
|
+
function osFamily() {
|
|
708
|
+
const p = os2.platform();
|
|
709
|
+
if (p === "win32") return "windows";
|
|
710
|
+
return p || "unknown";
|
|
711
|
+
}
|
|
712
|
+
function arch2() {
|
|
713
|
+
const a = os2.arch();
|
|
714
|
+
if (a === "x64") return "x86_64";
|
|
715
|
+
if (a === "arm64") return "arm64";
|
|
716
|
+
return "other";
|
|
717
|
+
}
|
|
718
|
+
function runtimeVersion() {
|
|
719
|
+
const parts = (process.versions.node ?? "0.0").split(".");
|
|
720
|
+
return `${parts[0] ?? "0"}.${parts[1] ?? "0"}`;
|
|
721
|
+
}
|
|
722
|
+
function buildEvent(name, opts) {
|
|
723
|
+
if (!ALLOWED_EVENTS.has(name)) {
|
|
724
|
+
throw new Error(`unknown telemetry event: ${name}`);
|
|
725
|
+
}
|
|
726
|
+
const event = {
|
|
727
|
+
event: name,
|
|
728
|
+
schema_version: SCHEMA_VERSION,
|
|
729
|
+
run_id: runId(),
|
|
730
|
+
install_id: installId(),
|
|
731
|
+
sdk: "typescript",
|
|
732
|
+
sdk_version: opts.sdkVersion,
|
|
733
|
+
os: osFamily(),
|
|
734
|
+
arch: arch2(),
|
|
735
|
+
runtime: "node",
|
|
736
|
+
runtime_version: runtimeVersion(),
|
|
737
|
+
ci: isCi() || isTest()
|
|
738
|
+
};
|
|
739
|
+
for (const [key, raw] of Object.entries(opts.dimensions ?? {})) {
|
|
740
|
+
if (!ALLOWED_DIMENSIONS.has(key) || raw === null || raw === void 0) {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
let value = raw;
|
|
744
|
+
const allowed = DIMENSION_VALUES[key];
|
|
745
|
+
if (allowed && !(typeof value === "string" && allowed.has(value))) {
|
|
746
|
+
value = "other";
|
|
747
|
+
} else if (STRING_DIMENSIONS.has(key)) {
|
|
748
|
+
if (!(typeof value === "string" && MODEL_TOKEN_RE.test(value))) {
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
} else if (BOOL_DIMENSIONS.has(key) && typeof value !== "boolean") {
|
|
752
|
+
continue;
|
|
753
|
+
}
|
|
754
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
755
|
+
event[key] = value;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return event;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// src/telemetry/client.ts
|
|
762
|
+
var DEFAULT_ENDPOINT = "https://telemetry.getpatter.com/v1/ingest";
|
|
763
|
+
var TIMEOUT_MS = 3e3;
|
|
764
|
+
var BUFFER_MAX = 256;
|
|
765
|
+
var noticeShown = false;
|
|
766
|
+
var liveClients = /* @__PURE__ */ new Set();
|
|
767
|
+
var exitHookRegistered = false;
|
|
768
|
+
var pendingFlush = /* @__PURE__ */ new Set();
|
|
769
|
+
function showNoticeOnce() {
|
|
770
|
+
if (noticeShown) return;
|
|
771
|
+
noticeShown = true;
|
|
772
|
+
getLogger().info(
|
|
773
|
+
"Anonymous usage telemetry is on (no PII, no call content). Collected: a random anonymous install id, SDK version, language, OS family, runtime version, coarse feature flags, the composed stack (provider + model per layer), tool counts, integration category, and per-call duration, latency, cost, and error codes (no call content, no message text). Disable with PATTER_TELEMETRY_DISABLED=1, DO_NOT_TRACK=1, or telemetry: false. Details: https://docs.getpatter.com/telemetry"
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
function registerExitHook() {
|
|
777
|
+
if (exitHookRegistered) return;
|
|
778
|
+
exitHookRegistered = true;
|
|
779
|
+
process.once("beforeExit", () => {
|
|
780
|
+
for (const ref of [...liveClients]) {
|
|
781
|
+
const client = ref.deref();
|
|
782
|
+
if (client) void client.close();
|
|
783
|
+
else liveClients.delete(ref);
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
var TelemetryClient = class {
|
|
788
|
+
sdkVersion;
|
|
789
|
+
enabledFlag;
|
|
790
|
+
endpoint;
|
|
791
|
+
debug;
|
|
792
|
+
buffer = [];
|
|
793
|
+
inflight = null;
|
|
794
|
+
closed = false;
|
|
795
|
+
selfRef = new WeakRef(this);
|
|
796
|
+
constructor(options) {
|
|
797
|
+
this.sdkVersion = options.sdkVersion;
|
|
798
|
+
this.enabledFlag = isEnabled(options.flag);
|
|
799
|
+
this.endpoint = options.endpoint ?? process.env.PATTER_TELEMETRY_ENDPOINT ?? DEFAULT_ENDPOINT;
|
|
800
|
+
this.debug = isTruthy(process.env.PATTER_TELEMETRY_DEBUG);
|
|
801
|
+
if (this.enabledFlag && !this.debug) {
|
|
802
|
+
showNoticeOnce();
|
|
803
|
+
registerExitHook();
|
|
804
|
+
liveClients.add(this.selfRef);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
get enabled() {
|
|
808
|
+
return this.enabledFlag;
|
|
809
|
+
}
|
|
810
|
+
/** Enqueue an event. Fire-and-forget; never throws, never blocks. */
|
|
811
|
+
record(name, dimensions) {
|
|
812
|
+
if (!this.enabledFlag || this.closed) return;
|
|
813
|
+
let event;
|
|
814
|
+
try {
|
|
815
|
+
event = buildEvent(name, { sdkVersion: this.sdkVersion, dimensions });
|
|
816
|
+
} catch (err) {
|
|
817
|
+
getLogger().debug("telemetry buildEvent failed", err);
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
if (this.debug) {
|
|
821
|
+
try {
|
|
822
|
+
process.stderr.write(`[patter telemetry] ${JSON.stringify(event)}
|
|
823
|
+
`);
|
|
824
|
+
} catch {
|
|
825
|
+
}
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
try {
|
|
829
|
+
if (this.buffer.length >= BUFFER_MAX) this.buffer.shift();
|
|
830
|
+
this.buffer.push(event);
|
|
831
|
+
pendingFlush.add(this);
|
|
832
|
+
this.scheduleFlush();
|
|
833
|
+
} catch (err) {
|
|
834
|
+
getLogger().debug("telemetry enqueue failed", err);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Schedule a flush of any buffered events. Events recorded before the server
|
|
839
|
+
* is running (e.g. at `new Patter(...)`) sit in the buffer; call this once the
|
|
840
|
+
* server is up so they ship promptly. Cheap when disabled or buffer is empty.
|
|
841
|
+
*/
|
|
842
|
+
flushPending() {
|
|
843
|
+
if (!this.enabledFlag || this.debug) return;
|
|
844
|
+
try {
|
|
845
|
+
this.scheduleFlush();
|
|
846
|
+
} catch (err) {
|
|
847
|
+
getLogger().debug("telemetry flushPending failed", err);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
/** Flush remaining events (graceful shutdown). Never throws. */
|
|
851
|
+
async close() {
|
|
852
|
+
if (this.closed) return;
|
|
853
|
+
this.closed = true;
|
|
854
|
+
liveClients.delete(this.selfRef);
|
|
855
|
+
if (!this.enabledFlag || this.debug) {
|
|
856
|
+
pendingFlush.delete(this);
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
try {
|
|
860
|
+
if (this.inflight) await this.inflight;
|
|
861
|
+
await this.flush();
|
|
862
|
+
} catch (err) {
|
|
863
|
+
getLogger().debug("telemetry close flush failed", err);
|
|
864
|
+
}
|
|
865
|
+
pendingFlush.delete(this);
|
|
866
|
+
}
|
|
867
|
+
scheduleFlush() {
|
|
868
|
+
if (this.inflight) return;
|
|
869
|
+
this.inflight = this.flush().finally(() => {
|
|
870
|
+
this.inflight = null;
|
|
871
|
+
if (this.buffer.length > 0) this.scheduleFlush();
|
|
872
|
+
});
|
|
873
|
+
void this.inflight;
|
|
874
|
+
}
|
|
875
|
+
async flush() {
|
|
876
|
+
if (this.buffer.length === 0) return;
|
|
877
|
+
const events = this.buffer.splice(0, this.buffer.length);
|
|
878
|
+
pendingFlush.delete(this);
|
|
879
|
+
const controller = new AbortController();
|
|
880
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
881
|
+
timer.unref?.();
|
|
882
|
+
try {
|
|
883
|
+
await fetch(this.endpoint, {
|
|
884
|
+
method: "POST",
|
|
885
|
+
headers: { "content-type": "application/json" },
|
|
886
|
+
body: JSON.stringify(events),
|
|
887
|
+
signal: controller.signal
|
|
888
|
+
});
|
|
889
|
+
} catch (err) {
|
|
890
|
+
getLogger().debug("telemetry flush failed", err);
|
|
891
|
+
} finally {
|
|
892
|
+
clearTimeout(timer);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
// src/telemetry/environment.ts
|
|
898
|
+
init_esm_shims();
|
|
899
|
+
import * as fs2 from "fs";
|
|
900
|
+
var env = process.env;
|
|
901
|
+
function invokedByAgent() {
|
|
902
|
+
if ("CLAUDECODE" in env || "CLAUDE_CODE" in env || "CLAUDE_CODE_ENTRYPOINT" in env)
|
|
903
|
+
return "claude";
|
|
904
|
+
if ("CURSOR_TRACE_ID" in env || "CURSOR_AGENT" in env) return "cursor";
|
|
905
|
+
if ("GITHUB_COPILOT_AGENT" in env || "COPILOT_AGENT_ID" in env) return "copilot";
|
|
906
|
+
if ("GEMINI_CLI" in env || "GEMINI_AGENT" in env) return "gemini";
|
|
907
|
+
if ("WINDSURF" in env || "WINDSURF_AGENT" in env) return "windsurf";
|
|
908
|
+
if ("AIDER" in env || "OPENAI_AGENT" in env) return "other";
|
|
909
|
+
return "none";
|
|
910
|
+
}
|
|
911
|
+
function inContainer() {
|
|
912
|
+
try {
|
|
913
|
+
if (fs2.existsSync("/.dockerenv")) return true;
|
|
914
|
+
} catch {
|
|
915
|
+
}
|
|
916
|
+
if (env.KUBERNETES_SERVICE_HOST) return true;
|
|
917
|
+
try {
|
|
918
|
+
const blob = fs2.readFileSync("/proc/1/cgroup", "utf8");
|
|
919
|
+
return blob.includes("docker") || blob.includes("containerd") || blob.includes("kubepods");
|
|
920
|
+
} catch {
|
|
921
|
+
return false;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
function serverless() {
|
|
925
|
+
if (env.AWS_LAMBDA_FUNCTION_NAME) return "lambda";
|
|
926
|
+
if (env.K_SERVICE) return "cloud_run";
|
|
927
|
+
if (env.VERCEL) return "vercel";
|
|
928
|
+
if (env.AZURE_FUNCTIONS_ENVIRONMENT || env.FUNCTIONS_WORKER_RUNTIME) return "azure_functions";
|
|
929
|
+
return "none";
|
|
930
|
+
}
|
|
931
|
+
function cloud() {
|
|
932
|
+
if (env.AWS_REGION || env.AWS_EXECUTION_ENV || env.AWS_LAMBDA_FUNCTION_NAME) return "aws";
|
|
933
|
+
if (env.K_SERVICE || env.GOOGLE_CLOUD_PROJECT || env.GCP_PROJECT) return "gcp";
|
|
934
|
+
if (env.WEBSITE_INSTANCE_ID || env.AZURE_FUNCTIONS_ENVIRONMENT) return "azure";
|
|
935
|
+
if (env.FLY_APP_NAME) return "fly";
|
|
936
|
+
return "none";
|
|
937
|
+
}
|
|
938
|
+
function packageManager() {
|
|
939
|
+
const ua = env.npm_config_user_agent ?? "";
|
|
940
|
+
if (ua.startsWith("pnpm")) return "pnpm";
|
|
941
|
+
if (ua.startsWith("yarn")) return "yarn";
|
|
942
|
+
if (ua.startsWith("bun")) return "bun";
|
|
943
|
+
if (ua.startsWith("npm")) return "npm";
|
|
944
|
+
return "none";
|
|
945
|
+
}
|
|
946
|
+
|
|
327
947
|
// src/_speech-events.ts
|
|
328
948
|
init_esm_shims();
|
|
329
949
|
var logger = getLogger();
|
|
@@ -628,6 +1248,79 @@ function closeParkedConnections(slot) {
|
|
|
628
1248
|
}
|
|
629
1249
|
}
|
|
630
1250
|
}
|
|
1251
|
+
function carrierFamily(carrier) {
|
|
1252
|
+
if (carrier instanceof Carrier2) return "twilio";
|
|
1253
|
+
if (carrier instanceof Carrier3) return "telnyx";
|
|
1254
|
+
if (carrier instanceof Carrier) return "plivo";
|
|
1255
|
+
return "none";
|
|
1256
|
+
}
|
|
1257
|
+
function telemetryEngineFamily(opts) {
|
|
1258
|
+
if (opts.engine) {
|
|
1259
|
+
return opts.engine.constructor.name.toLowerCase().includes("convai") ? "convai" : "realtime";
|
|
1260
|
+
}
|
|
1261
|
+
if (opts.provider === "elevenlabs_convai") return "convai";
|
|
1262
|
+
if (opts.provider === "pipeline") return "pipeline";
|
|
1263
|
+
if (opts.provider === "openai_realtime") return "realtime";
|
|
1264
|
+
if (opts.stt || opts.tts) return "pipeline";
|
|
1265
|
+
return "realtime";
|
|
1266
|
+
}
|
|
1267
|
+
function telemetryProviderFamily(family) {
|
|
1268
|
+
if (family === "realtime") return "openai";
|
|
1269
|
+
if (family === "convai") return "elevenlabs";
|
|
1270
|
+
return "other";
|
|
1271
|
+
}
|
|
1272
|
+
function telemetryBucketCustomTools(n) {
|
|
1273
|
+
if (n <= 0) return "0";
|
|
1274
|
+
if (n === 1) return "1";
|
|
1275
|
+
if (n <= 3) return "2_3";
|
|
1276
|
+
if (n <= 6) return "4_6";
|
|
1277
|
+
if (n <= 12) return "7_12";
|
|
1278
|
+
return "13_plus";
|
|
1279
|
+
}
|
|
1280
|
+
function telemetryBucketMcp(n) {
|
|
1281
|
+
if (n <= 0) return "0";
|
|
1282
|
+
if (n === 1) return "1";
|
|
1283
|
+
if (n <= 3) return "2_3";
|
|
1284
|
+
return "4_plus";
|
|
1285
|
+
}
|
|
1286
|
+
function telemetryIntegration(opts) {
|
|
1287
|
+
const nMcp = opts.mcpServers?.length ?? 0;
|
|
1288
|
+
if (nMcp > 0) {
|
|
1289
|
+
return { integration: "mcp", integrationKind: "mcp", mcpBucket: telemetryBucketMcp(nMcp) };
|
|
1290
|
+
}
|
|
1291
|
+
if (opts.consult) {
|
|
1292
|
+
let isOpenclaw = false;
|
|
1293
|
+
const oc = opts.consult.openaiCompatible;
|
|
1294
|
+
if (oc) {
|
|
1295
|
+
const model = oc.model ?? "";
|
|
1296
|
+
const baseUrl = oc.baseUrl ?? "";
|
|
1297
|
+
isOpenclaw = model.startsWith("openclaw/") || baseUrl.includes(":18789");
|
|
1298
|
+
}
|
|
1299
|
+
return {
|
|
1300
|
+
integration: isOpenclaw ? "openclaw" : "other",
|
|
1301
|
+
integrationKind: "consult",
|
|
1302
|
+
mcpBucket: "0"
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
return { integration: "none", integrationKind: "none", mcpBucket: "0" };
|
|
1306
|
+
}
|
|
1307
|
+
function telemetryEnvironmentDims() {
|
|
1308
|
+
try {
|
|
1309
|
+
const dims = {
|
|
1310
|
+
invoked_by_agent: invokedByAgent(),
|
|
1311
|
+
container: inContainer(),
|
|
1312
|
+
serverless: serverless(),
|
|
1313
|
+
cloud: cloud(),
|
|
1314
|
+
package_manager: packageManager(),
|
|
1315
|
+
days_since_install_bucket: daysSinceInstallBucket()
|
|
1316
|
+
};
|
|
1317
|
+
const prev = previousVersion(VERSION);
|
|
1318
|
+
if (prev) dims.previous_sdk_version = prev;
|
|
1319
|
+
return dims;
|
|
1320
|
+
} catch {
|
|
1321
|
+
return {};
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
631
1324
|
var Patter = class {
|
|
632
1325
|
localConfig;
|
|
633
1326
|
embeddedServer = null;
|
|
@@ -648,6 +1341,14 @@ var Patter = class {
|
|
|
648
1341
|
* ``Cannot use both tunnel: true and webhookUrl``.
|
|
649
1342
|
*/
|
|
650
1343
|
tunnelOwnsWebhookUrl = false;
|
|
1344
|
+
/**
|
|
1345
|
+
* Anonymous usage telemetry (opt-out, default ON). Separate from
|
|
1346
|
+
* ``./observability`` (user-facing OTel). Fire-and-forget and fail-safe — it
|
|
1347
|
+
* can never block or break a call. See ``./telemetry``.
|
|
1348
|
+
*/
|
|
1349
|
+
telemetry;
|
|
1350
|
+
telemetrySeenEngines = /* @__PURE__ */ new Set();
|
|
1351
|
+
telemetrySeenAgentShapes = /* @__PURE__ */ new Set();
|
|
651
1352
|
/**
|
|
652
1353
|
* Pre-rendered first-message TTS audio per outbound call_id. Populated
|
|
653
1354
|
* by :meth:`call` when ``agent.prewarmFirstMessage`` is true; consumed
|
|
@@ -853,6 +1554,22 @@ var Patter = class {
|
|
|
853
1554
|
openaiKey: options.openaiKey,
|
|
854
1555
|
persistRoot: resolvePersistRoot(options.persist)
|
|
855
1556
|
};
|
|
1557
|
+
this.telemetry = new TelemetryClient({
|
|
1558
|
+
sdkVersion: VERSION,
|
|
1559
|
+
flag: options.telemetry
|
|
1560
|
+
});
|
|
1561
|
+
const initDims = {
|
|
1562
|
+
carrier: carrierFamily(carrier),
|
|
1563
|
+
tunnel: tunnel instanceof Static ? "static" : options.tunnel ? "configured" : "none",
|
|
1564
|
+
...telemetryEnvironmentDims()
|
|
1565
|
+
};
|
|
1566
|
+
if (this.telemetry.enabled) {
|
|
1567
|
+
try {
|
|
1568
|
+
if (isFirstRun()) this.telemetry.record("first_run", initDims);
|
|
1569
|
+
} catch {
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
this.telemetry.record("sdk_initialized", initDims);
|
|
856
1573
|
this._tunnelReady = new Promise((resolve, reject) => {
|
|
857
1574
|
this._tunnelReadyResolve = resolve;
|
|
858
1575
|
this._tunnelReadyReject = reject;
|
|
@@ -872,6 +1589,65 @@ var Patter = class {
|
|
|
872
1589
|
// === Agent definition ===
|
|
873
1590
|
/** Resolve user-supplied agent options against engine defaults and return the merged config. */
|
|
874
1591
|
agent(opts) {
|
|
1592
|
+
const family = telemetryEngineFamily(opts);
|
|
1593
|
+
let stack = { ...stackDimensions(opts.stt, opts.tts, opts.llm) };
|
|
1594
|
+
if (family === "realtime") {
|
|
1595
|
+
const engineModel = opts.engine?.model;
|
|
1596
|
+
stack = {
|
|
1597
|
+
...stack,
|
|
1598
|
+
llm_model: modelToken(
|
|
1599
|
+
"openai",
|
|
1600
|
+
opts.model ?? engineModel ?? "gpt-realtime-mini"
|
|
1601
|
+
)
|
|
1602
|
+
};
|
|
1603
|
+
}
|
|
1604
|
+
const featureKey = family + "|" + Object.entries(stack).sort().map(([k, v]) => `${k}=${v}`).join(",");
|
|
1605
|
+
if (!this.telemetrySeenEngines.has(featureKey)) {
|
|
1606
|
+
this.telemetrySeenEngines.add(featureKey);
|
|
1607
|
+
this.telemetry.record("feature_used", {
|
|
1608
|
+
engine: family,
|
|
1609
|
+
provider: telemetryProviderFamily(family),
|
|
1610
|
+
...stack
|
|
1611
|
+
});
|
|
1612
|
+
}
|
|
1613
|
+
const builtin = opts.consult ? 1 : 0;
|
|
1614
|
+
const customBucket = telemetryBucketCustomTools(opts.tools?.length ?? 0);
|
|
1615
|
+
const { integration, integrationKind, mcpBucket } = telemetryIntegration(opts);
|
|
1616
|
+
const engineObj = opts.engine;
|
|
1617
|
+
const nr = opts.openaiRealtimeNoiseReduction ?? engineObj?.noiseReduction;
|
|
1618
|
+
const noiseReduction = nr === "near_field" || nr === "far_field" ? nr : "none";
|
|
1619
|
+
const td = opts.realtimeTurnDetection ?? engineObj?.turnDetection;
|
|
1620
|
+
const turnDetection = td != null ? "custom" : "none";
|
|
1621
|
+
const preamblesUsed = Boolean(opts.toolCallPreambles);
|
|
1622
|
+
const perToolTimeoutsSet = Array.isArray(opts.tools) && opts.tools.some((t) => t.timeoutMs !== void 0);
|
|
1623
|
+
const llmFallbackConfigured = typeof opts.llm?.getAvailability === "function";
|
|
1624
|
+
const shapeKey = [
|
|
1625
|
+
builtin,
|
|
1626
|
+
customBucket,
|
|
1627
|
+
integration,
|
|
1628
|
+
integrationKind,
|
|
1629
|
+
mcpBucket,
|
|
1630
|
+
noiseReduction,
|
|
1631
|
+
turnDetection,
|
|
1632
|
+
preamblesUsed,
|
|
1633
|
+
perToolTimeoutsSet,
|
|
1634
|
+
llmFallbackConfigured
|
|
1635
|
+
].join("|");
|
|
1636
|
+
if (!this.telemetrySeenAgentShapes.has(shapeKey)) {
|
|
1637
|
+
this.telemetrySeenAgentShapes.add(shapeKey);
|
|
1638
|
+
this.telemetry.record("agent_configured", {
|
|
1639
|
+
builtin_tool_count: builtin,
|
|
1640
|
+
custom_tool_count_bucket: customBucket,
|
|
1641
|
+
integration,
|
|
1642
|
+
integration_kind: integrationKind,
|
|
1643
|
+
mcp_server_count_bucket: mcpBucket,
|
|
1644
|
+
noise_reduction: noiseReduction,
|
|
1645
|
+
turn_detection: turnDetection,
|
|
1646
|
+
preambles_used: preamblesUsed,
|
|
1647
|
+
per_tool_timeouts_set: perToolTimeoutsSet,
|
|
1648
|
+
llm_fallback_configured: llmFallbackConfigured
|
|
1649
|
+
});
|
|
1650
|
+
}
|
|
875
1651
|
let working = { ...opts };
|
|
876
1652
|
if (opts.engine) {
|
|
877
1653
|
if (opts.provider) {
|
|
@@ -1061,6 +1837,7 @@ var Patter = class {
|
|
|
1061
1837
|
opts.dashboardToken ?? "",
|
|
1062
1838
|
opts.allowInsecureDashboard ?? false
|
|
1063
1839
|
);
|
|
1840
|
+
this.embeddedServer.telemetry = this.telemetry;
|
|
1064
1841
|
this.embeddedServer.popPrewarmAudio = this.popPrewarmAudio;
|
|
1065
1842
|
this.embeddedServer.popPrewarmedConnections = this.popPrewarmedConnections;
|
|
1066
1843
|
this.embeddedServer.recordPrewarmWaste = this.recordPrewarmWaste;
|
|
@@ -1070,6 +1847,7 @@ var Patter = class {
|
|
|
1070
1847
|
await waitForTunnelPubliclyReachable(webhookUrl);
|
|
1071
1848
|
}
|
|
1072
1849
|
this._readyResolve(webhookUrl);
|
|
1850
|
+
this.telemetry.flushPending();
|
|
1073
1851
|
} catch (err) {
|
|
1074
1852
|
const e = err instanceof Error ? err : new Error(String(err));
|
|
1075
1853
|
this._readyReject(e);
|
|
@@ -1078,7 +1856,7 @@ var Patter = class {
|
|
|
1078
1856
|
}
|
|
1079
1857
|
/** Run the agent in interactive terminal-test mode (no real telephony). */
|
|
1080
1858
|
async test(opts) {
|
|
1081
|
-
const { TestSession: TestSession2 } = await import("./test-mode-
|
|
1859
|
+
const { TestSession: TestSession2 } = await import("./test-mode-XFOADUNE.mjs");
|
|
1082
1860
|
const session = new TestSession2();
|
|
1083
1861
|
await session.run({
|
|
1084
1862
|
agent: opts.agent,
|
|
@@ -1752,6 +2530,7 @@ var Patter = class {
|
|
|
1752
2530
|
* entries leak across ``serve`` / ``disconnect`` cycles. See FIX #93.
|
|
1753
2531
|
*/
|
|
1754
2532
|
async disconnect() {
|
|
2533
|
+
this.telemetry.flushPending();
|
|
1755
2534
|
for (const handle of this.prewarmTtlTimers.values()) {
|
|
1756
2535
|
clearTimeout(handle);
|
|
1757
2536
|
}
|
|
@@ -2329,6 +3108,7 @@ var PatterTool = class {
|
|
|
2329
3108
|
maxDurationSec;
|
|
2330
3109
|
recording;
|
|
2331
3110
|
started = false;
|
|
3111
|
+
hermesTelemetryEmitted = false;
|
|
2332
3112
|
/** Cached in-progress (or completed) start promise so concurrent execute()
|
|
2333
3113
|
* callers all await the same boot sequence instead of each racing into
|
|
2334
3114
|
* phone.serve(). Reset to null on failure so callers can retry after a
|
|
@@ -2485,6 +3265,20 @@ var PatterTool = class {
|
|
|
2485
3265
|
* the same wire contract.
|
|
2486
3266
|
*/
|
|
2487
3267
|
hermesHandler() {
|
|
3268
|
+
if (!this.hermesTelemetryEmitted) {
|
|
3269
|
+
this.hermesTelemetryEmitted = true;
|
|
3270
|
+
try {
|
|
3271
|
+
const tel = this.phone.telemetry;
|
|
3272
|
+
tel?.record("agent_configured", {
|
|
3273
|
+
builtin_tool_count: 0,
|
|
3274
|
+
custom_tool_count_bucket: "0",
|
|
3275
|
+
integration: "hermes",
|
|
3276
|
+
integration_kind: "none",
|
|
3277
|
+
mcp_server_count_bucket: "0"
|
|
3278
|
+
});
|
|
3279
|
+
} catch {
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
2488
3282
|
return async (args) => {
|
|
2489
3283
|
try {
|
|
2490
3284
|
const result = await this.execute(args);
|
|
@@ -7541,7 +8335,12 @@ var LLM5 = class extends GoogleLLMProvider {
|
|
|
7541
8335
|
|
|
7542
8336
|
// src/llm/openai-compatible.ts
|
|
7543
8337
|
init_esm_shims();
|
|
8338
|
+
import { createHash } from "crypto";
|
|
7544
8339
|
var DEFAULT_TIMEOUT_S = 60;
|
|
8340
|
+
function hashCaller(caller) {
|
|
8341
|
+
if (!caller) return void 0;
|
|
8342
|
+
return createHash("sha256").update(caller, "utf8").digest("hex").slice(0, 16);
|
|
8343
|
+
}
|
|
7545
8344
|
var OpenAICompatibleLLMProvider = class {
|
|
7546
8345
|
/**
|
|
7547
8346
|
* Stable pricing/dashboard key — read by stream-handler/metrics. Typed as
|
|
@@ -7560,6 +8359,7 @@ var OpenAICompatibleLLMProvider = class {
|
|
|
7560
8359
|
sessionIdPrefix;
|
|
7561
8360
|
sessionKeyHeader;
|
|
7562
8361
|
sessionKey;
|
|
8362
|
+
sessionKeyFactory;
|
|
7563
8363
|
temperature;
|
|
7564
8364
|
maxTokens;
|
|
7565
8365
|
responseFormat;
|
|
@@ -7589,6 +8389,17 @@ var OpenAICompatibleLLMProvider = class {
|
|
|
7589
8389
|
this.sessionIdPrefix = options.sessionIdPrefix;
|
|
7590
8390
|
this.sessionKeyHeader = options.sessionKeyHeader;
|
|
7591
8391
|
this.sessionKey = options.sessionKey;
|
|
8392
|
+
let sessionKeyFactory = options.sessionKeyFactory;
|
|
8393
|
+
if (!sessionKeyFactory && options.sessionKeyFrom === "caller_hash") {
|
|
8394
|
+
sessionKeyFactory = (ctx) => ctx.callerHash ? `patter-caller-${ctx.callerHash}` : void 0;
|
|
8395
|
+
} else if (options.sessionKeyFrom !== void 0 && options.sessionKeyFrom !== "caller_hash") {
|
|
8396
|
+
throw new Error(
|
|
8397
|
+
`sessionKeyFrom must be 'caller_hash' or undefined, got ${JSON.stringify(
|
|
8398
|
+
options.sessionKeyFrom
|
|
8399
|
+
)}`
|
|
8400
|
+
);
|
|
8401
|
+
}
|
|
8402
|
+
this.sessionKeyFactory = sessionKeyFactory;
|
|
7592
8403
|
this.temperature = options.temperature;
|
|
7593
8404
|
this.maxTokens = options.maxTokens;
|
|
7594
8405
|
this.responseFormat = options.responseFormat;
|
|
@@ -7612,7 +8423,7 @@ var OpenAICompatibleLLMProvider = class {
|
|
|
7612
8423
|
* - ``sessionKeyHeader`` (+ ``sessionKey``) → the static ``sessionKey`` value.
|
|
7613
8424
|
* ``sessionKey`` is a credential-grade memory scope and is never logged.
|
|
7614
8425
|
*/
|
|
7615
|
-
buildHeaders(callId) {
|
|
8426
|
+
buildHeaders(callId, caller, callee) {
|
|
7616
8427
|
const headers = {
|
|
7617
8428
|
"Content-Type": "application/json",
|
|
7618
8429
|
"User-Agent": `getpatter/${VERSION}`,
|
|
@@ -7624,11 +8435,33 @@ var OpenAICompatibleLLMProvider = class {
|
|
|
7624
8435
|
if (this.sessionIdHeader && callId) {
|
|
7625
8436
|
headers[this.sessionIdHeader] = `${this.sessionIdPrefix ?? ""}${callId}`;
|
|
7626
8437
|
}
|
|
7627
|
-
if (this.sessionKeyHeader
|
|
7628
|
-
|
|
8438
|
+
if (this.sessionKeyHeader) {
|
|
8439
|
+
const sessionKeyValue = this.resolveSessionKey(callId, caller, callee);
|
|
8440
|
+
if (sessionKeyValue) {
|
|
8441
|
+
headers[this.sessionKeyHeader] = sessionKeyValue;
|
|
8442
|
+
}
|
|
7629
8443
|
}
|
|
7630
8444
|
return headers;
|
|
7631
8445
|
}
|
|
8446
|
+
/**
|
|
8447
|
+
* Resolve the ``sessionKeyHeader`` VALUE for this call. When a
|
|
8448
|
+
* ``sessionKeyFactory`` is configured it is called with a
|
|
8449
|
+
* {@link SessionContext} (the raw ``caller`` plus its non-reversible
|
|
8450
|
+
* {@link hashCaller}) and its return value wins — a falsy return omits the
|
|
8451
|
+
* header. Otherwise the static ``sessionKey`` is used. Never logged.
|
|
8452
|
+
*/
|
|
8453
|
+
resolveSessionKey(callId, caller, callee) {
|
|
8454
|
+
if (this.sessionKeyFactory) {
|
|
8455
|
+
const ctx = {
|
|
8456
|
+
callId,
|
|
8457
|
+
caller,
|
|
8458
|
+
callee,
|
|
8459
|
+
callerHash: hashCaller(caller)
|
|
8460
|
+
};
|
|
8461
|
+
return this.sessionKeyFactory(ctx);
|
|
8462
|
+
}
|
|
8463
|
+
return this.sessionKey;
|
|
8464
|
+
}
|
|
7632
8465
|
/**
|
|
7633
8466
|
* Pre-call DNS / TLS warmup for the configured endpoint. Best-effort:
|
|
7634
8467
|
* 5 s timeout, all exceptions swallowed at debug level. The ``Authorization``
|
|
@@ -7682,10 +8515,12 @@ var OpenAICompatibleLLMProvider = class {
|
|
|
7682
8515
|
/** Stream Patter-format LLM chunks from the configured chat completions API. */
|
|
7683
8516
|
async *stream(messages, tools, opts) {
|
|
7684
8517
|
const callId = opts?.callId;
|
|
8518
|
+
const caller = opts?.caller;
|
|
8519
|
+
const callee = opts?.callee;
|
|
7685
8520
|
const body = this.buildBody(messages, tools, callId);
|
|
7686
8521
|
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
|
7687
8522
|
method: "POST",
|
|
7688
|
-
headers: this.buildHeaders(callId),
|
|
8523
|
+
headers: this.buildHeaders(callId, caller, callee),
|
|
7689
8524
|
body: JSON.stringify(body),
|
|
7690
8525
|
signal: mergeAbortSignals(opts?.signal, AbortSignal.timeout(this.timeoutMs))
|
|
7691
8526
|
});
|
|
@@ -7705,6 +8540,13 @@ var LLM6 = class extends OpenAICompatibleLLMProvider {
|
|
|
7705
8540
|
static providerKey = "openai_compatible";
|
|
7706
8541
|
};
|
|
7707
8542
|
|
|
8543
|
+
// src/llm/custom.ts
|
|
8544
|
+
init_esm_shims();
|
|
8545
|
+
var LLM7 = class extends OpenAICompatibleLLMProvider {
|
|
8546
|
+
/** Stable pricing/dashboard key — read by stream-handler/metrics. */
|
|
8547
|
+
static providerKey = "custom";
|
|
8548
|
+
};
|
|
8549
|
+
|
|
7708
8550
|
// src/llm/hermes.ts
|
|
7709
8551
|
init_esm_shims();
|
|
7710
8552
|
var BASE_URL = "http://127.0.0.1:8642/v1";
|
|
@@ -7716,7 +8558,7 @@ var SESSION_ID_HEADER = "X-Hermes-Session-Id";
|
|
|
7716
8558
|
var SESSION_ID_PREFIX = "patter-call-";
|
|
7717
8559
|
var SESSION_KEY_HEADER = "X-Hermes-Session-Key";
|
|
7718
8560
|
var DEFAULT_TIMEOUT_S2 = 120;
|
|
7719
|
-
var
|
|
8561
|
+
var LLM8 = class extends OpenAICompatibleLLMProvider {
|
|
7720
8562
|
static providerKey = "hermes";
|
|
7721
8563
|
constructor(opts = {}) {
|
|
7722
8564
|
const model = opts.model ?? process.env[MODEL_ENV] ?? DEFAULT_MODEL5;
|
|
@@ -7731,6 +8573,8 @@ var LLM7 = class extends OpenAICompatibleLLMProvider {
|
|
|
7731
8573
|
sessionIdPrefix: SESSION_ID_PREFIX,
|
|
7732
8574
|
sessionKeyHeader: SESSION_KEY_HEADER,
|
|
7733
8575
|
sessionKey: opts.sessionKey,
|
|
8576
|
+
sessionKeyFrom: opts.sessionKeyFrom,
|
|
8577
|
+
sessionKeyFactory: opts.sessionKeyFactory,
|
|
7734
8578
|
extraHeaders: opts.extraHeaders,
|
|
7735
8579
|
temperature: opts.temperature,
|
|
7736
8580
|
maxTokens: opts.maxTokens,
|
|
@@ -7755,7 +8599,7 @@ var SESSION_HEADER = "x-openclaw-session-key";
|
|
|
7755
8599
|
var SESSION_USER_PREFIX2 = "patter-call-";
|
|
7756
8600
|
var DEFAULT_TIMEOUT_S3 = 120;
|
|
7757
8601
|
var OPENCLAW_AGENT_RE = /^[A-Za-z0-9._:/-]+$/;
|
|
7758
|
-
var
|
|
8602
|
+
var LLM9 = class extends OpenAICompatibleLLMProvider {
|
|
7759
8603
|
static providerKey = "openclaw";
|
|
7760
8604
|
constructor(opts) {
|
|
7761
8605
|
const agent = opts?.agent;
|
|
@@ -8025,57 +8869,6 @@ var KrispVivaFilter = class {
|
|
|
8025
8869
|
}
|
|
8026
8870
|
};
|
|
8027
8871
|
|
|
8028
|
-
// src/telephony/twilio.ts
|
|
8029
|
-
init_esm_shims();
|
|
8030
|
-
var Carrier2 = class {
|
|
8031
|
-
kind = "twilio";
|
|
8032
|
-
accountSid;
|
|
8033
|
-
authToken;
|
|
8034
|
-
constructor(opts = {}) {
|
|
8035
|
-
const sid = opts.accountSid ?? process.env.TWILIO_ACCOUNT_SID;
|
|
8036
|
-
const tok = opts.authToken ?? process.env.TWILIO_AUTH_TOKEN;
|
|
8037
|
-
if (!sid) {
|
|
8038
|
-
throw new Error(
|
|
8039
|
-
"Twilio carrier requires accountSid. Pass { accountSid: 'AC...' } or set TWILIO_ACCOUNT_SID in the environment."
|
|
8040
|
-
);
|
|
8041
|
-
}
|
|
8042
|
-
if (!tok) {
|
|
8043
|
-
throw new Error(
|
|
8044
|
-
"Twilio carrier requires authToken. Pass { authToken: '...' } or set TWILIO_AUTH_TOKEN in the environment."
|
|
8045
|
-
);
|
|
8046
|
-
}
|
|
8047
|
-
this.accountSid = sid;
|
|
8048
|
-
this.authToken = tok;
|
|
8049
|
-
}
|
|
8050
|
-
};
|
|
8051
|
-
|
|
8052
|
-
// src/telephony/telnyx.ts
|
|
8053
|
-
init_esm_shims();
|
|
8054
|
-
var Carrier3 = class {
|
|
8055
|
-
kind = "telnyx";
|
|
8056
|
-
apiKey;
|
|
8057
|
-
connectionId;
|
|
8058
|
-
publicKey;
|
|
8059
|
-
constructor(opts = {}) {
|
|
8060
|
-
const key = opts.apiKey ?? process.env.TELNYX_API_KEY;
|
|
8061
|
-
const conn = opts.connectionId ?? process.env.TELNYX_CONNECTION_ID;
|
|
8062
|
-
const pub = opts.publicKey ?? process.env.TELNYX_PUBLIC_KEY;
|
|
8063
|
-
if (!key) {
|
|
8064
|
-
throw new Error(
|
|
8065
|
-
"Telnyx carrier requires apiKey. Pass { apiKey: '...' } or set TELNYX_API_KEY in the environment."
|
|
8066
|
-
);
|
|
8067
|
-
}
|
|
8068
|
-
if (!conn) {
|
|
8069
|
-
throw new Error(
|
|
8070
|
-
"Telnyx carrier requires connectionId. Pass { connectionId: '...' } or set TELNYX_CONNECTION_ID in the environment."
|
|
8071
|
-
);
|
|
8072
|
-
}
|
|
8073
|
-
this.apiKey = key;
|
|
8074
|
-
this.connectionId = conn;
|
|
8075
|
-
this.publicKey = pub;
|
|
8076
|
-
}
|
|
8077
|
-
};
|
|
8078
|
-
|
|
8079
8872
|
// src/public-api.ts
|
|
8080
8873
|
init_esm_shims();
|
|
8081
8874
|
var DEFAULT_GUARDRAIL_REPLACEMENT = "I'm sorry, I can't respond to that.";
|
|
@@ -8142,9 +8935,9 @@ function tool(opts) {
|
|
|
8142
8935
|
|
|
8143
8936
|
// src/chat-context.ts
|
|
8144
8937
|
init_esm_shims();
|
|
8145
|
-
import { randomUUID } from "crypto";
|
|
8938
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
8146
8939
|
function generateId() {
|
|
8147
|
-
return
|
|
8940
|
+
return randomUUID2().replace(/-/g, "").slice(0, 12);
|
|
8148
8941
|
}
|
|
8149
8942
|
function createMessage(role, content, options) {
|
|
8150
8943
|
return Object.freeze({
|
|
@@ -8559,8 +9352,8 @@ var IVRActivity = class {
|
|
|
8559
9352
|
|
|
8560
9353
|
// src/audio/background-audio.ts
|
|
8561
9354
|
init_esm_shims();
|
|
8562
|
-
import { promises as
|
|
8563
|
-
import
|
|
9355
|
+
import { promises as fs3 } from "fs";
|
|
9356
|
+
import path2 from "path";
|
|
8564
9357
|
import { fileURLToPath } from "url";
|
|
8565
9358
|
var BuiltinAudioClip = {
|
|
8566
9359
|
CITY_AMBIENCE: "city-ambience.ogg",
|
|
@@ -8573,8 +9366,8 @@ var BuiltinAudioClip = {
|
|
|
8573
9366
|
};
|
|
8574
9367
|
function builtinClipPath(clip) {
|
|
8575
9368
|
const meta = typeof import.meta !== "undefined" ? import.meta : void 0;
|
|
8576
|
-
const here = meta?.url ?
|
|
8577
|
-
return
|
|
9369
|
+
const here = meta?.url ? path2.dirname(fileURLToPath(meta.url)) : typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
9370
|
+
return path2.resolve(here, "..", "resources", "audio", clip);
|
|
8578
9371
|
}
|
|
8579
9372
|
var INT16_MIN = -32768;
|
|
8580
9373
|
var INT16_MAX = 32767;
|
|
@@ -8743,7 +9536,7 @@ var BackgroundAudioPlayer = class {
|
|
|
8743
9536
|
return source.decode(source.path);
|
|
8744
9537
|
case "builtin": {
|
|
8745
9538
|
const p = builtinClipPath(source.clip);
|
|
8746
|
-
const header = await
|
|
9539
|
+
const header = await fs3.readFile(p, { flag: "r" }).then((buf) => buf.subarray(0, 4));
|
|
8747
9540
|
if (header.toString("ascii") !== "OggS") {
|
|
8748
9541
|
throw new Error(`Bundled clip ${source.clip} is not a valid Ogg file`);
|
|
8749
9542
|
}
|
|
@@ -8790,8 +9583,8 @@ var TwilioAdapter = class _TwilioAdapter {
|
|
|
8790
9583
|
this.baseUrl = opts.region ? `https://api.${opts.region}.twilio.com/2010-04-01` : TWILIO_API_BASE;
|
|
8791
9584
|
this.authHeader = `Basic ${Buffer.from(`${accountSid}:${authToken}`).toString("base64")}`;
|
|
8792
9585
|
}
|
|
8793
|
-
async request(method,
|
|
8794
|
-
const url = `${this.baseUrl}/Accounts/${encodeURIComponent(this.accountSid)}${
|
|
9586
|
+
async request(method, path3, body) {
|
|
9587
|
+
const url = `${this.baseUrl}/Accounts/${encodeURIComponent(this.accountSid)}${path3}`;
|
|
8795
9588
|
const headers = { Authorization: this.authHeader };
|
|
8796
9589
|
if (body) headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
8797
9590
|
const response = await fetch(url, {
|
|
@@ -8802,7 +9595,7 @@ var TwilioAdapter = class _TwilioAdapter {
|
|
|
8802
9595
|
});
|
|
8803
9596
|
const text = await response.text();
|
|
8804
9597
|
if (!response.ok) {
|
|
8805
|
-
throw new Error(`Twilio ${method} ${
|
|
9598
|
+
throw new Error(`Twilio ${method} ${path3} failed: ${response.status} ${text}`);
|
|
8806
9599
|
}
|
|
8807
9600
|
if (!text) return {};
|
|
8808
9601
|
try {
|
|
@@ -8820,8 +9613,8 @@ var TwilioAdapter = class _TwilioAdapter {
|
|
|
8820
9613
|
const country = encodeURIComponent(opts.countryCode);
|
|
8821
9614
|
const queryParts = ["PageSize=1"];
|
|
8822
9615
|
if (opts.areaCode) queryParts.push(`AreaCode=${encodeURIComponent(opts.areaCode)}`);
|
|
8823
|
-
const
|
|
8824
|
-
const available = await this.request("GET",
|
|
9616
|
+
const path3 = `/AvailablePhoneNumbers/${country}/Local.json?${queryParts.join("&")}`;
|
|
9617
|
+
const available = await this.request("GET", path3);
|
|
8825
9618
|
const first = available.available_phone_numbers?.[0]?.phone_number;
|
|
8826
9619
|
if (!first) {
|
|
8827
9620
|
throw new Error(`TwilioAdapter: no numbers available for country ${opts.countryCode}`);
|
|
@@ -8921,7 +9714,7 @@ var TwilioAdapter = class _TwilioAdapter {
|
|
|
8921
9714
|
|
|
8922
9715
|
// src/providers/telnyx-adapter.ts
|
|
8923
9716
|
init_esm_shims();
|
|
8924
|
-
import { randomUUID as
|
|
9717
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
8925
9718
|
var TELNYX_API_BASE = "https://api.telnyx.com/v2";
|
|
8926
9719
|
var TelnyxAdapter = class {
|
|
8927
9720
|
apiKey;
|
|
@@ -8932,8 +9725,8 @@ var TelnyxAdapter = class {
|
|
|
8932
9725
|
this.apiKey = apiKey;
|
|
8933
9726
|
this.connectionId = connectionId;
|
|
8934
9727
|
}
|
|
8935
|
-
async request(method,
|
|
8936
|
-
const url = `${this.baseUrl}${
|
|
9728
|
+
async request(method, path3, body) {
|
|
9729
|
+
const url = `${this.baseUrl}${path3}`;
|
|
8937
9730
|
const headers = {
|
|
8938
9731
|
Authorization: `Bearer ${this.apiKey}`
|
|
8939
9732
|
};
|
|
@@ -8946,7 +9739,7 @@ var TelnyxAdapter = class {
|
|
|
8946
9739
|
});
|
|
8947
9740
|
const text = await response.text();
|
|
8948
9741
|
if (!response.ok) {
|
|
8949
|
-
throw new Error(`Telnyx ${method} ${
|
|
9742
|
+
throw new Error(`Telnyx ${method} ${path3} failed: ${response.status} ${text}`);
|
|
8950
9743
|
}
|
|
8951
9744
|
if (!text) return {};
|
|
8952
9745
|
try {
|
|
@@ -9030,7 +9823,7 @@ var TelnyxAdapter = class {
|
|
|
9030
9823
|
if (!callControlId) throw new Error("TelnyxAdapter: callControlId is required");
|
|
9031
9824
|
const encoded = encodeURIComponent(callControlId);
|
|
9032
9825
|
const body = {
|
|
9033
|
-
command_id: opts.commandId ??
|
|
9826
|
+
command_id: opts.commandId ?? randomUUID3()
|
|
9034
9827
|
};
|
|
9035
9828
|
try {
|
|
9036
9829
|
await this.request(
|
|
@@ -9304,6 +10097,12 @@ var TelnyxTTS = class {
|
|
|
9304
10097
|
|
|
9305
10098
|
// src/observability/index.ts
|
|
9306
10099
|
init_esm_shims();
|
|
10100
|
+
|
|
10101
|
+
// src/index.ts
|
|
10102
|
+
var hermes = Object.freeze({ LLM: LLM8 });
|
|
10103
|
+
var openclaw = Object.freeze({ LLM: LLM9 });
|
|
10104
|
+
var openaiCompatible = Object.freeze({ LLM: LLM6 });
|
|
10105
|
+
var custom = Object.freeze({ LLM: LLM7 });
|
|
9307
10106
|
export {
|
|
9308
10107
|
AllProvidersFailedError,
|
|
9309
10108
|
LLM2 as AnthropicLLM,
|
|
@@ -9319,6 +10118,7 @@ export {
|
|
|
9319
10118
|
LLM4 as CerebrasLLM,
|
|
9320
10119
|
ChatContext,
|
|
9321
10120
|
CloudflareTunnel,
|
|
10121
|
+
LLM7 as CustomLLM,
|
|
9322
10122
|
DEFAULT_MIN_SENTENCE_LEN,
|
|
9323
10123
|
DEFAULT_PRICING,
|
|
9324
10124
|
DTMF_EVENTS,
|
|
@@ -9342,7 +10142,7 @@ export {
|
|
|
9342
10142
|
LLM5 as GoogleLLM,
|
|
9343
10143
|
LLM3 as GroqLLM,
|
|
9344
10144
|
Guardrail,
|
|
9345
|
-
|
|
10145
|
+
LLM8 as HermesLLM,
|
|
9346
10146
|
IVRActivity,
|
|
9347
10147
|
TTS7 as InworldTTS,
|
|
9348
10148
|
KrispFrameDuration,
|
|
@@ -9368,7 +10168,7 @@ export {
|
|
|
9368
10168
|
STT3 as OpenAITranscribeSTT,
|
|
9369
10169
|
OpenAITranscriptionModel,
|
|
9370
10170
|
OpenAIVoice,
|
|
9371
|
-
|
|
10171
|
+
LLM9 as OpenClawLLM,
|
|
9372
10172
|
PRICING_LAST_UPDATED,
|
|
9373
10173
|
PRICING_VERSION,
|
|
9374
10174
|
PartialStreamError,
|
|
@@ -9437,6 +10237,7 @@ export {
|
|
|
9437
10237
|
createResampler24kTo16k,
|
|
9438
10238
|
createResampler24kTo8k,
|
|
9439
10239
|
createResampler8kTo16k,
|
|
10240
|
+
custom,
|
|
9440
10241
|
deepgram,
|
|
9441
10242
|
defineTool,
|
|
9442
10243
|
elevenlabs,
|
|
@@ -9448,6 +10249,8 @@ export {
|
|
|
9448
10249
|
geminiLive,
|
|
9449
10250
|
getLogger,
|
|
9450
10251
|
guardrail,
|
|
10252
|
+
hashCaller,
|
|
10253
|
+
hermes,
|
|
9451
10254
|
initTracing,
|
|
9452
10255
|
isRemoteUrl,
|
|
9453
10256
|
isTracingEnabled,
|
|
@@ -9460,7 +10263,9 @@ export {
|
|
|
9460
10263
|
mountDashboard,
|
|
9461
10264
|
mulawToPcm16,
|
|
9462
10265
|
notifyDashboard,
|
|
10266
|
+
openaiCompatible,
|
|
9463
10267
|
openaiTts,
|
|
10268
|
+
openclaw,
|
|
9464
10269
|
openclawConsult,
|
|
9465
10270
|
openclawPostCallNotifier,
|
|
9466
10271
|
pcm16ToMulaw,
|