echo-ai-sdk-ts 2.2.0 → 2.4.0
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/README.md +35 -0
- package/dist/index.d.mts +181 -2
- package/dist/index.d.ts +181 -2
- package/dist/index.js +472 -112
- package/dist/index.mjs +455 -104
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -741,14 +741,14 @@ var require_url_state_machine = __commonJS({
|
|
|
741
741
|
return url.replace(/\u0009|\u000A|\u000D/g, "");
|
|
742
742
|
}
|
|
743
743
|
function shortenPath(url) {
|
|
744
|
-
const
|
|
745
|
-
if (
|
|
744
|
+
const path2 = url.path;
|
|
745
|
+
if (path2.length === 0) {
|
|
746
746
|
return;
|
|
747
747
|
}
|
|
748
|
-
if (url.scheme === "file" &&
|
|
748
|
+
if (url.scheme === "file" && path2.length === 1 && isNormalizedWindowsDriveLetter(path2[0])) {
|
|
749
749
|
return;
|
|
750
750
|
}
|
|
751
|
-
|
|
751
|
+
path2.pop();
|
|
752
752
|
}
|
|
753
753
|
function includesCredentials(url) {
|
|
754
754
|
return url.username !== "" || url.password !== "";
|
|
@@ -3016,7 +3016,7 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
3016
3016
|
return new originalPromise(executor);
|
|
3017
3017
|
}
|
|
3018
3018
|
function promiseResolvedWith(value) {
|
|
3019
|
-
return newPromise((
|
|
3019
|
+
return newPromise((resolve2) => resolve2(value));
|
|
3020
3020
|
}
|
|
3021
3021
|
function promiseRejectedWith(reason) {
|
|
3022
3022
|
return originalPromiseReject(reason);
|
|
@@ -3186,8 +3186,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
3186
3186
|
return new TypeError("Cannot " + name + " a stream using a released reader");
|
|
3187
3187
|
}
|
|
3188
3188
|
function defaultReaderClosedPromiseInitialize(reader) {
|
|
3189
|
-
reader._closedPromise = newPromise((
|
|
3190
|
-
reader._closedPromise_resolve =
|
|
3189
|
+
reader._closedPromise = newPromise((resolve2, reject) => {
|
|
3190
|
+
reader._closedPromise_resolve = resolve2;
|
|
3191
3191
|
reader._closedPromise_reject = reject;
|
|
3192
3192
|
});
|
|
3193
3193
|
}
|
|
@@ -3361,8 +3361,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
3361
3361
|
}
|
|
3362
3362
|
let resolvePromise;
|
|
3363
3363
|
let rejectPromise;
|
|
3364
|
-
const promise = newPromise((
|
|
3365
|
-
resolvePromise =
|
|
3364
|
+
const promise = newPromise((resolve2, reject) => {
|
|
3365
|
+
resolvePromise = resolve2;
|
|
3366
3366
|
rejectPromise = reject;
|
|
3367
3367
|
});
|
|
3368
3368
|
const readRequest = {
|
|
@@ -3467,8 +3467,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
3467
3467
|
const reader = this._reader;
|
|
3468
3468
|
let resolvePromise;
|
|
3469
3469
|
let rejectPromise;
|
|
3470
|
-
const promise = newPromise((
|
|
3471
|
-
resolvePromise =
|
|
3470
|
+
const promise = newPromise((resolve2, reject) => {
|
|
3471
|
+
resolvePromise = resolve2;
|
|
3472
3472
|
rejectPromise = reject;
|
|
3473
3473
|
});
|
|
3474
3474
|
const readRequest = {
|
|
@@ -4487,8 +4487,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
4487
4487
|
}
|
|
4488
4488
|
let resolvePromise;
|
|
4489
4489
|
let rejectPromise;
|
|
4490
|
-
const promise = newPromise((
|
|
4491
|
-
resolvePromise =
|
|
4490
|
+
const promise = newPromise((resolve2, reject) => {
|
|
4491
|
+
resolvePromise = resolve2;
|
|
4492
4492
|
rejectPromise = reject;
|
|
4493
4493
|
});
|
|
4494
4494
|
const readIntoRequest = {
|
|
@@ -4800,10 +4800,10 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
4800
4800
|
wasAlreadyErroring = true;
|
|
4801
4801
|
reason = void 0;
|
|
4802
4802
|
}
|
|
4803
|
-
const promise = newPromise((
|
|
4803
|
+
const promise = newPromise((resolve2, reject) => {
|
|
4804
4804
|
stream._pendingAbortRequest = {
|
|
4805
4805
|
_promise: void 0,
|
|
4806
|
-
_resolve:
|
|
4806
|
+
_resolve: resolve2,
|
|
4807
4807
|
_reject: reject,
|
|
4808
4808
|
_reason: reason,
|
|
4809
4809
|
_wasAlreadyErroring: wasAlreadyErroring
|
|
@@ -4820,9 +4820,9 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
4820
4820
|
if (state === "closed" || state === "errored") {
|
|
4821
4821
|
return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`));
|
|
4822
4822
|
}
|
|
4823
|
-
const promise = newPromise((
|
|
4823
|
+
const promise = newPromise((resolve2, reject) => {
|
|
4824
4824
|
const closeRequest = {
|
|
4825
|
-
_resolve:
|
|
4825
|
+
_resolve: resolve2,
|
|
4826
4826
|
_reject: reject
|
|
4827
4827
|
};
|
|
4828
4828
|
stream._closeRequest = closeRequest;
|
|
@@ -4835,9 +4835,9 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
4835
4835
|
return promise;
|
|
4836
4836
|
}
|
|
4837
4837
|
function WritableStreamAddWriteRequest(stream) {
|
|
4838
|
-
const promise = newPromise((
|
|
4838
|
+
const promise = newPromise((resolve2, reject) => {
|
|
4839
4839
|
const writeRequest = {
|
|
4840
|
-
_resolve:
|
|
4840
|
+
_resolve: resolve2,
|
|
4841
4841
|
_reject: reject
|
|
4842
4842
|
};
|
|
4843
4843
|
stream._writeRequests.push(writeRequest);
|
|
@@ -5453,8 +5453,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
5453
5453
|
return new TypeError("Cannot " + name + " a stream using a released writer");
|
|
5454
5454
|
}
|
|
5455
5455
|
function defaultWriterClosedPromiseInitialize(writer) {
|
|
5456
|
-
writer._closedPromise = newPromise((
|
|
5457
|
-
writer._closedPromise_resolve =
|
|
5456
|
+
writer._closedPromise = newPromise((resolve2, reject) => {
|
|
5457
|
+
writer._closedPromise_resolve = resolve2;
|
|
5458
5458
|
writer._closedPromise_reject = reject;
|
|
5459
5459
|
writer._closedPromiseState = "pending";
|
|
5460
5460
|
});
|
|
@@ -5490,8 +5490,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
5490
5490
|
writer._closedPromiseState = "resolved";
|
|
5491
5491
|
}
|
|
5492
5492
|
function defaultWriterReadyPromiseInitialize(writer) {
|
|
5493
|
-
writer._readyPromise = newPromise((
|
|
5494
|
-
writer._readyPromise_resolve =
|
|
5493
|
+
writer._readyPromise = newPromise((resolve2, reject) => {
|
|
5494
|
+
writer._readyPromise_resolve = resolve2;
|
|
5495
5495
|
writer._readyPromise_reject = reject;
|
|
5496
5496
|
});
|
|
5497
5497
|
writer._readyPromiseState = "pending";
|
|
@@ -5578,7 +5578,7 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
5578
5578
|
source._disturbed = true;
|
|
5579
5579
|
let shuttingDown = false;
|
|
5580
5580
|
let currentWrite = promiseResolvedWith(void 0);
|
|
5581
|
-
return newPromise((
|
|
5581
|
+
return newPromise((resolve2, reject) => {
|
|
5582
5582
|
let abortAlgorithm;
|
|
5583
5583
|
if (signal !== void 0) {
|
|
5584
5584
|
abortAlgorithm = () => {
|
|
@@ -5723,7 +5723,7 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
5723
5723
|
if (isError) {
|
|
5724
5724
|
reject(error);
|
|
5725
5725
|
} else {
|
|
5726
|
-
|
|
5726
|
+
resolve2(void 0);
|
|
5727
5727
|
}
|
|
5728
5728
|
return null;
|
|
5729
5729
|
}
|
|
@@ -6004,8 +6004,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6004
6004
|
let branch1;
|
|
6005
6005
|
let branch2;
|
|
6006
6006
|
let resolveCancelPromise;
|
|
6007
|
-
const cancelPromise = newPromise((
|
|
6008
|
-
resolveCancelPromise =
|
|
6007
|
+
const cancelPromise = newPromise((resolve2) => {
|
|
6008
|
+
resolveCancelPromise = resolve2;
|
|
6009
6009
|
});
|
|
6010
6010
|
function pullAlgorithm() {
|
|
6011
6011
|
if (reading) {
|
|
@@ -6096,8 +6096,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6096
6096
|
let branch1;
|
|
6097
6097
|
let branch2;
|
|
6098
6098
|
let resolveCancelPromise;
|
|
6099
|
-
const cancelPromise = newPromise((
|
|
6100
|
-
resolveCancelPromise =
|
|
6099
|
+
const cancelPromise = newPromise((resolve2) => {
|
|
6100
|
+
resolveCancelPromise = resolve2;
|
|
6101
6101
|
});
|
|
6102
6102
|
function forwardReaderError(thisReader) {
|
|
6103
6103
|
uponRejection(thisReader._closedPromise, (r) => {
|
|
@@ -6877,8 +6877,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6877
6877
|
const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1);
|
|
6878
6878
|
const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy);
|
|
6879
6879
|
let startPromise_resolve;
|
|
6880
|
-
const startPromise = newPromise((
|
|
6881
|
-
startPromise_resolve =
|
|
6880
|
+
const startPromise = newPromise((resolve2) => {
|
|
6881
|
+
startPromise_resolve = resolve2;
|
|
6882
6882
|
});
|
|
6883
6883
|
InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm);
|
|
6884
6884
|
SetUpTransformStreamDefaultControllerFromTransformer(this, transformer);
|
|
@@ -6971,8 +6971,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
6971
6971
|
if (stream._backpressureChangePromise !== void 0) {
|
|
6972
6972
|
stream._backpressureChangePromise_resolve();
|
|
6973
6973
|
}
|
|
6974
|
-
stream._backpressureChangePromise = newPromise((
|
|
6975
|
-
stream._backpressureChangePromise_resolve =
|
|
6974
|
+
stream._backpressureChangePromise = newPromise((resolve2) => {
|
|
6975
|
+
stream._backpressureChangePromise_resolve = resolve2;
|
|
6976
6976
|
});
|
|
6977
6977
|
stream._backpressure = backpressure;
|
|
6978
6978
|
}
|
|
@@ -7140,8 +7140,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
7140
7140
|
return controller._finishPromise;
|
|
7141
7141
|
}
|
|
7142
7142
|
const readable = stream._readable;
|
|
7143
|
-
controller._finishPromise = newPromise((
|
|
7144
|
-
controller._finishPromise_resolve =
|
|
7143
|
+
controller._finishPromise = newPromise((resolve2, reject) => {
|
|
7144
|
+
controller._finishPromise_resolve = resolve2;
|
|
7145
7145
|
controller._finishPromise_reject = reject;
|
|
7146
7146
|
});
|
|
7147
7147
|
const cancelPromise = controller._cancelAlgorithm(reason);
|
|
@@ -7167,8 +7167,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
7167
7167
|
return controller._finishPromise;
|
|
7168
7168
|
}
|
|
7169
7169
|
const readable = stream._readable;
|
|
7170
|
-
controller._finishPromise = newPromise((
|
|
7171
|
-
controller._finishPromise_resolve =
|
|
7170
|
+
controller._finishPromise = newPromise((resolve2, reject) => {
|
|
7171
|
+
controller._finishPromise_resolve = resolve2;
|
|
7172
7172
|
controller._finishPromise_reject = reject;
|
|
7173
7173
|
});
|
|
7174
7174
|
const flushPromise = controller._flushAlgorithm();
|
|
@@ -7198,8 +7198,8 @@ var require_ponyfill_es2018 = __commonJS({
|
|
|
7198
7198
|
return controller._finishPromise;
|
|
7199
7199
|
}
|
|
7200
7200
|
const writable = stream._writable;
|
|
7201
|
-
controller._finishPromise = newPromise((
|
|
7202
|
-
controller._finishPromise_resolve =
|
|
7201
|
+
controller._finishPromise = newPromise((resolve2, reject) => {
|
|
7202
|
+
controller._finishPromise_resolve = resolve2;
|
|
7203
7203
|
controller._finishPromise_reject = reject;
|
|
7204
7204
|
});
|
|
7205
7205
|
const cancelPromise = controller._cancelAlgorithm(reason);
|
|
@@ -7391,7 +7391,7 @@ var AIModelGateway = class {
|
|
|
7391
7391
|
}
|
|
7392
7392
|
if (attempt < 3) {
|
|
7393
7393
|
const backoffMs = Math.pow(attempt, 2) * 500;
|
|
7394
|
-
await new Promise((
|
|
7394
|
+
await new Promise((resolve2) => setTimeout(resolve2, backoffMs));
|
|
7395
7395
|
}
|
|
7396
7396
|
}
|
|
7397
7397
|
}
|
|
@@ -7424,7 +7424,7 @@ var AIModelGateway = class {
|
|
|
7424
7424
|
}
|
|
7425
7425
|
if (attempt < 3) {
|
|
7426
7426
|
const backoffMs = Math.pow(attempt, 2) * 500;
|
|
7427
|
-
await new Promise((
|
|
7427
|
+
await new Promise((resolve2) => setTimeout(resolve2, backoffMs));
|
|
7428
7428
|
}
|
|
7429
7429
|
}
|
|
7430
7430
|
}
|
|
@@ -7819,7 +7819,7 @@ function consumeBody() {
|
|
|
7819
7819
|
let accum = [];
|
|
7820
7820
|
let accumBytes = 0;
|
|
7821
7821
|
let abort = false;
|
|
7822
|
-
return new Body.Promise(function(
|
|
7822
|
+
return new Body.Promise(function(resolve2, reject) {
|
|
7823
7823
|
let resTimeout;
|
|
7824
7824
|
if (_this4.timeout) {
|
|
7825
7825
|
resTimeout = setTimeout(function() {
|
|
@@ -7853,7 +7853,7 @@ function consumeBody() {
|
|
|
7853
7853
|
}
|
|
7854
7854
|
clearTimeout(resTimeout);
|
|
7855
7855
|
try {
|
|
7856
|
-
|
|
7856
|
+
resolve2(Buffer.concat(accum, accumBytes));
|
|
7857
7857
|
} catch (err) {
|
|
7858
7858
|
reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, "system", err));
|
|
7859
7859
|
}
|
|
@@ -8528,7 +8528,7 @@ function fetch3(url, opts) {
|
|
|
8528
8528
|
throw new Error("native promise missing, set fetch.Promise to your favorite alternative");
|
|
8529
8529
|
}
|
|
8530
8530
|
Body.Promise = fetch3.Promise;
|
|
8531
|
-
return new fetch3.Promise(function(
|
|
8531
|
+
return new fetch3.Promise(function(resolve2, reject) {
|
|
8532
8532
|
const request = new Request2(url, opts);
|
|
8533
8533
|
const options = getNodeRequestOptions(request);
|
|
8534
8534
|
const send = (options.protocol === "https:" ? https : http).request;
|
|
@@ -8661,7 +8661,7 @@ function fetch3(url, opts) {
|
|
|
8661
8661
|
requestOpts.body = void 0;
|
|
8662
8662
|
requestOpts.headers.delete("content-length");
|
|
8663
8663
|
}
|
|
8664
|
-
|
|
8664
|
+
resolve2(fetch3(new Request2(locationURL, requestOpts)));
|
|
8665
8665
|
finalize();
|
|
8666
8666
|
return;
|
|
8667
8667
|
}
|
|
@@ -8682,7 +8682,7 @@ function fetch3(url, opts) {
|
|
|
8682
8682
|
const codings = headers.get("Content-Encoding");
|
|
8683
8683
|
if (!request.compress || request.method === "HEAD" || codings === null || res.statusCode === 204 || res.statusCode === 304) {
|
|
8684
8684
|
response = new Response2(body, response_options);
|
|
8685
|
-
|
|
8685
|
+
resolve2(response);
|
|
8686
8686
|
return;
|
|
8687
8687
|
}
|
|
8688
8688
|
const zlibOptions = {
|
|
@@ -8692,7 +8692,7 @@ function fetch3(url, opts) {
|
|
|
8692
8692
|
if (codings == "gzip" || codings == "x-gzip") {
|
|
8693
8693
|
body = body.pipe(zlib.createGunzip(zlibOptions));
|
|
8694
8694
|
response = new Response2(body, response_options);
|
|
8695
|
-
|
|
8695
|
+
resolve2(response);
|
|
8696
8696
|
return;
|
|
8697
8697
|
}
|
|
8698
8698
|
if (codings == "deflate" || codings == "x-deflate") {
|
|
@@ -8704,12 +8704,12 @@ function fetch3(url, opts) {
|
|
|
8704
8704
|
body = body.pipe(zlib.createInflateRaw());
|
|
8705
8705
|
}
|
|
8706
8706
|
response = new Response2(body, response_options);
|
|
8707
|
-
|
|
8707
|
+
resolve2(response);
|
|
8708
8708
|
});
|
|
8709
8709
|
raw.on("end", function() {
|
|
8710
8710
|
if (!response) {
|
|
8711
8711
|
response = new Response2(body, response_options);
|
|
8712
|
-
|
|
8712
|
+
resolve2(response);
|
|
8713
8713
|
}
|
|
8714
8714
|
});
|
|
8715
8715
|
return;
|
|
@@ -8717,11 +8717,11 @@ function fetch3(url, opts) {
|
|
|
8717
8717
|
if (codings == "br" && typeof zlib.createBrotliDecompress === "function") {
|
|
8718
8718
|
body = body.pipe(zlib.createBrotliDecompress());
|
|
8719
8719
|
response = new Response2(body, response_options);
|
|
8720
|
-
|
|
8720
|
+
resolve2(response);
|
|
8721
8721
|
return;
|
|
8722
8722
|
}
|
|
8723
8723
|
response = new Response2(body, response_options);
|
|
8724
|
-
|
|
8724
|
+
resolve2(response);
|
|
8725
8725
|
});
|
|
8726
8726
|
writeToStream(req, request);
|
|
8727
8727
|
});
|
|
@@ -9084,13 +9084,13 @@ var MultipartBody = class {
|
|
|
9084
9084
|
// node_modules/@anthropic-ai/sdk/_shims/node-runtime.mjs
|
|
9085
9085
|
var import_ponyfill_es2018 = __toESM(require_ponyfill_es2018(), 1);
|
|
9086
9086
|
var fileFromPathWarned = false;
|
|
9087
|
-
async function fileFromPath2(
|
|
9087
|
+
async function fileFromPath2(path2, ...args) {
|
|
9088
9088
|
const { fileFromPath: _fileFromPath } = await import("./fileFromPath-4L47H5QG.mjs");
|
|
9089
9089
|
if (!fileFromPathWarned) {
|
|
9090
|
-
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(
|
|
9090
|
+
console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path2)}) instead`);
|
|
9091
9091
|
fileFromPathWarned = true;
|
|
9092
9092
|
}
|
|
9093
|
-
return await _fileFromPath(
|
|
9093
|
+
return await _fileFromPath(path2, ...args);
|
|
9094
9094
|
}
|
|
9095
9095
|
var defaultHttpAgent = new import_agentkeepalive.default({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
9096
9096
|
var defaultHttpsAgent = new import_agentkeepalive.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1e3 });
|
|
@@ -9721,8 +9721,8 @@ async function defaultParseResponse(props) {
|
|
|
9721
9721
|
}
|
|
9722
9722
|
var APIPromise = class _APIPromise extends Promise {
|
|
9723
9723
|
constructor(responsePromise, parseResponse = defaultParseResponse) {
|
|
9724
|
-
super((
|
|
9725
|
-
|
|
9724
|
+
super((resolve2) => {
|
|
9725
|
+
resolve2(null);
|
|
9726
9726
|
});
|
|
9727
9727
|
this.responsePromise = responsePromise;
|
|
9728
9728
|
this.parseResponse = parseResponse;
|
|
@@ -9822,26 +9822,26 @@ var APIClient = class {
|
|
|
9822
9822
|
defaultIdempotencyKey() {
|
|
9823
9823
|
return `stainless-node-retry-${uuid4()}`;
|
|
9824
9824
|
}
|
|
9825
|
-
get(
|
|
9826
|
-
return this.methodRequest("get",
|
|
9825
|
+
get(path2, opts) {
|
|
9826
|
+
return this.methodRequest("get", path2, opts);
|
|
9827
9827
|
}
|
|
9828
|
-
post(
|
|
9829
|
-
return this.methodRequest("post",
|
|
9828
|
+
post(path2, opts) {
|
|
9829
|
+
return this.methodRequest("post", path2, opts);
|
|
9830
9830
|
}
|
|
9831
|
-
patch(
|
|
9832
|
-
return this.methodRequest("patch",
|
|
9831
|
+
patch(path2, opts) {
|
|
9832
|
+
return this.methodRequest("patch", path2, opts);
|
|
9833
9833
|
}
|
|
9834
|
-
put(
|
|
9835
|
-
return this.methodRequest("put",
|
|
9834
|
+
put(path2, opts) {
|
|
9835
|
+
return this.methodRequest("put", path2, opts);
|
|
9836
9836
|
}
|
|
9837
|
-
delete(
|
|
9838
|
-
return this.methodRequest("delete",
|
|
9837
|
+
delete(path2, opts) {
|
|
9838
|
+
return this.methodRequest("delete", path2, opts);
|
|
9839
9839
|
}
|
|
9840
|
-
methodRequest(method,
|
|
9841
|
-
return this.request(Promise.resolve(opts).then((opts2) => ({ method, path, ...opts2 })));
|
|
9840
|
+
methodRequest(method, path2, opts) {
|
|
9841
|
+
return this.request(Promise.resolve(opts).then((opts2) => ({ method, path: path2, ...opts2 })));
|
|
9842
9842
|
}
|
|
9843
|
-
getAPIList(
|
|
9844
|
-
return this.requestAPIList(Page, { method: "get", path, ...opts });
|
|
9843
|
+
getAPIList(path2, Page, opts) {
|
|
9844
|
+
return this.requestAPIList(Page, { method: "get", path: path2, ...opts });
|
|
9845
9845
|
}
|
|
9846
9846
|
calculateContentLength(body) {
|
|
9847
9847
|
if (typeof body === "string") {
|
|
@@ -9857,10 +9857,10 @@ var APIClient = class {
|
|
|
9857
9857
|
return null;
|
|
9858
9858
|
}
|
|
9859
9859
|
buildRequest(options) {
|
|
9860
|
-
const { method, path, query, headers = {} } = options;
|
|
9860
|
+
const { method, path: path2, query, headers = {} } = options;
|
|
9861
9861
|
const body = isMultipartBody(options.body) ? options.body.body : options.body ? JSON.stringify(options.body, null, 2) : null;
|
|
9862
9862
|
const contentLength = this.calculateContentLength(body);
|
|
9863
|
-
const url = this.buildURL(
|
|
9863
|
+
const url = this.buildURL(path2, query);
|
|
9864
9864
|
if ("timeout" in options)
|
|
9865
9865
|
validatePositiveInteger("timeout", options.timeout);
|
|
9866
9866
|
const timeout = options.timeout ?? this.timeout;
|
|
@@ -9969,8 +9969,8 @@ var APIClient = class {
|
|
|
9969
9969
|
const request = this.makeRequest(options, null);
|
|
9970
9970
|
return new PagePromise(this, request, Page);
|
|
9971
9971
|
}
|
|
9972
|
-
buildURL(
|
|
9973
|
-
const url = isAbsoluteURL(
|
|
9972
|
+
buildURL(path2, query) {
|
|
9973
|
+
const url = isAbsoluteURL(path2) ? new URL(path2) : new URL(this.baseURL + (this.baseURL.endsWith("/") && path2.startsWith("/") ? path2.slice(1) : path2));
|
|
9974
9974
|
const defaultQuery = this.defaultQuery();
|
|
9975
9975
|
if (!isEmptyObj(defaultQuery)) {
|
|
9976
9976
|
query = { ...defaultQuery, ...query };
|
|
@@ -10255,7 +10255,7 @@ var startsWithSchemeRegexp = new RegExp("^(?:[a-z]+:)?//", "i");
|
|
|
10255
10255
|
var isAbsoluteURL = (url) => {
|
|
10256
10256
|
return startsWithSchemeRegexp.test(url);
|
|
10257
10257
|
};
|
|
10258
|
-
var sleep = (ms) => new Promise((
|
|
10258
|
+
var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
10259
10259
|
var validatePositiveInteger = (name, n) => {
|
|
10260
10260
|
if (typeof n !== "number" || !Number.isInteger(n)) {
|
|
10261
10261
|
throw new AnthropicError(`${name} must be an integer`);
|
|
@@ -10448,12 +10448,12 @@ var MessageStream = class _MessageStream {
|
|
|
10448
10448
|
}
|
|
10449
10449
|
return this._emit("error", new AnthropicError(String(error)));
|
|
10450
10450
|
});
|
|
10451
|
-
__classPrivateFieldSet3(this, _MessageStream_connectedPromise, new Promise((
|
|
10452
|
-
__classPrivateFieldSet3(this, _MessageStream_resolveConnectedPromise,
|
|
10451
|
+
__classPrivateFieldSet3(this, _MessageStream_connectedPromise, new Promise((resolve2, reject) => {
|
|
10452
|
+
__classPrivateFieldSet3(this, _MessageStream_resolveConnectedPromise, resolve2, "f");
|
|
10453
10453
|
__classPrivateFieldSet3(this, _MessageStream_rejectConnectedPromise, reject, "f");
|
|
10454
10454
|
}), "f");
|
|
10455
|
-
__classPrivateFieldSet3(this, _MessageStream_endPromise, new Promise((
|
|
10456
|
-
__classPrivateFieldSet3(this, _MessageStream_resolveEndPromise,
|
|
10455
|
+
__classPrivateFieldSet3(this, _MessageStream_endPromise, new Promise((resolve2, reject) => {
|
|
10456
|
+
__classPrivateFieldSet3(this, _MessageStream_resolveEndPromise, resolve2, "f");
|
|
10457
10457
|
__classPrivateFieldSet3(this, _MessageStream_rejectEndPromise, reject, "f");
|
|
10458
10458
|
}), "f");
|
|
10459
10459
|
__classPrivateFieldGet4(this, _MessageStream_connectedPromise, "f").catch(() => {
|
|
@@ -10582,11 +10582,11 @@ var MessageStream = class _MessageStream {
|
|
|
10582
10582
|
* const message = await stream.emitted('message') // rejects if the stream errors
|
|
10583
10583
|
*/
|
|
10584
10584
|
emitted(event) {
|
|
10585
|
-
return new Promise((
|
|
10585
|
+
return new Promise((resolve2, reject) => {
|
|
10586
10586
|
__classPrivateFieldSet3(this, _MessageStream_catchingPromiseCreated, true, "f");
|
|
10587
10587
|
if (event !== "error")
|
|
10588
10588
|
this.once("error", reject);
|
|
10589
|
-
this.once(event,
|
|
10589
|
+
this.once(event, resolve2);
|
|
10590
10590
|
});
|
|
10591
10591
|
}
|
|
10592
10592
|
async done() {
|
|
@@ -10797,7 +10797,7 @@ var MessageStream = class _MessageStream {
|
|
|
10797
10797
|
if (done) {
|
|
10798
10798
|
return { value: void 0, done: true };
|
|
10799
10799
|
}
|
|
10800
|
-
return new Promise((
|
|
10800
|
+
return new Promise((resolve2, reject) => readQueue.push({ resolve: resolve2, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
|
|
10801
10801
|
}
|
|
10802
10802
|
const chunk = pushQueue.shift();
|
|
10803
10803
|
return { value: chunk, done: false };
|
|
@@ -11068,6 +11068,9 @@ var AgentExecutor = class {
|
|
|
11068
11068
|
this.systemPrompt = options.systemPrompt;
|
|
11069
11069
|
this.telemetry = options.telemetry;
|
|
11070
11070
|
}
|
|
11071
|
+
getMemory() {
|
|
11072
|
+
return this.memory;
|
|
11073
|
+
}
|
|
11071
11074
|
async execute(sessionId, userInput, maxIterations = 5) {
|
|
11072
11075
|
if (!sessionId) throw new ValidationError("execute", "sessionId is required.");
|
|
11073
11076
|
if (!userInput) throw new ValidationError("execute", "userInput is required.");
|
|
@@ -13127,14 +13130,14 @@ var MemoryVectorStore = class {
|
|
|
13127
13130
|
return scored.filter((e) => e.score >= minScore).sort((a, b) => b.score - a.score).slice(0, k);
|
|
13128
13131
|
}
|
|
13129
13132
|
/** Save the entire store to a JSON file. */
|
|
13130
|
-
async saveToFile(
|
|
13133
|
+
async saveToFile(path2) {
|
|
13131
13134
|
const data = JSON.stringify(this.entries);
|
|
13132
|
-
await fs.writeFile(
|
|
13135
|
+
await fs.writeFile(path2, data, "utf8");
|
|
13133
13136
|
}
|
|
13134
13137
|
/** Load store entries from a JSON file. */
|
|
13135
|
-
async loadFromFile(
|
|
13138
|
+
async loadFromFile(path2) {
|
|
13136
13139
|
try {
|
|
13137
|
-
const data = await fs.readFile(
|
|
13140
|
+
const data = await fs.readFile(path2, "utf8");
|
|
13138
13141
|
this.entries = JSON.parse(data);
|
|
13139
13142
|
} catch (e) {
|
|
13140
13143
|
if (e.code !== "ENOENT") throw e;
|
|
@@ -13230,11 +13233,11 @@ var KnowledgeBase = class {
|
|
|
13230
13233
|
if (results.length === 0) return "";
|
|
13231
13234
|
return results.map((r, i) => `[Source ${i + 1} (${(r.score * 100).toFixed(0)}% match)]: ${r.content}`).join("\n\n");
|
|
13232
13235
|
}
|
|
13233
|
-
async save(
|
|
13234
|
-
await this.store.saveToFile(
|
|
13236
|
+
async save(path2) {
|
|
13237
|
+
await this.store.saveToFile(path2);
|
|
13235
13238
|
}
|
|
13236
|
-
async load(
|
|
13237
|
-
await this.store.loadFromFile(
|
|
13239
|
+
async load(path2) {
|
|
13240
|
+
await this.store.loadFromFile(path2);
|
|
13238
13241
|
}
|
|
13239
13242
|
async embed(text) {
|
|
13240
13243
|
const res = await this.openai.embeddings.create({ model: this.embeddingModel, input: text });
|
|
@@ -13255,6 +13258,10 @@ var OPENAI_PRICING = {
|
|
|
13255
13258
|
var ConversationAnalytics = class {
|
|
13256
13259
|
records = /* @__PURE__ */ new Map();
|
|
13257
13260
|
queryFrequency = /* @__PURE__ */ new Map();
|
|
13261
|
+
outcomeTracker;
|
|
13262
|
+
constructor(outcomeTracker) {
|
|
13263
|
+
this.outcomeTracker = outcomeTracker;
|
|
13264
|
+
}
|
|
13258
13265
|
estimateTokens(text) {
|
|
13259
13266
|
return Math.ceil(text.length / 4);
|
|
13260
13267
|
}
|
|
@@ -13263,7 +13270,7 @@ var ConversationAnalytics = class {
|
|
|
13263
13270
|
const rate = type === "input" ? pricing.input : pricing.output;
|
|
13264
13271
|
return tokens / 1e6 * rate;
|
|
13265
13272
|
}
|
|
13266
|
-
startConversation(sessionId, model = "gpt-4o-mini") {
|
|
13273
|
+
startConversation(sessionId, model = "gpt-4o-mini", variantId) {
|
|
13267
13274
|
if (!this.records.has(sessionId)) {
|
|
13268
13275
|
this.records.set(sessionId, {
|
|
13269
13276
|
sessionId,
|
|
@@ -13275,7 +13282,8 @@ var ConversationAnalytics = class {
|
|
|
13275
13282
|
totalCostUsd: 0,
|
|
13276
13283
|
topQueries: [],
|
|
13277
13284
|
responseTimes: [],
|
|
13278
|
-
model
|
|
13285
|
+
model,
|
|
13286
|
+
variantId
|
|
13279
13287
|
});
|
|
13280
13288
|
}
|
|
13281
13289
|
}
|
|
@@ -13332,10 +13340,39 @@ var ConversationAnalytics = class {
|
|
|
13332
13340
|
const avgResponseTime = allResponseTimes.length > 0 ? allResponseTimes.reduce((a, b) => a + b, 0) / allResponseTimes.length : 0;
|
|
13333
13341
|
const totalTokens = all.reduce((s, r) => s + r.totalTokens, 0);
|
|
13334
13342
|
const totalCost = all.reduce((s, r) => s + r.totalCostUsd, 0);
|
|
13343
|
+
let totalValue = 0;
|
|
13344
|
+
if (this.outcomeTracker) {
|
|
13345
|
+
totalValue = this.outcomeTracker.getGlobalStats().totalValueUsd;
|
|
13346
|
+
}
|
|
13335
13347
|
const now = Date.now();
|
|
13336
13348
|
const firstConvo = all.length > 0 ? Math.min(...all.map((r) => r.startTime)) : now;
|
|
13337
13349
|
const hourSpan = Math.max(1, (now - firstConvo) / 36e5);
|
|
13338
13350
|
const topQueries = [...this.queryFrequency.entries()].sort((a, b) => b[1] - a[1]).slice(0, 20).map(([query, count]) => ({ query, count }));
|
|
13351
|
+
const variants = {};
|
|
13352
|
+
const groupedByVariant = all.reduce((acc, r) => {
|
|
13353
|
+
const v = r.variantId || "default";
|
|
13354
|
+
if (!acc[v]) acc[v] = [];
|
|
13355
|
+
acc[v].push(r);
|
|
13356
|
+
return acc;
|
|
13357
|
+
}, {});
|
|
13358
|
+
for (const [variantId, vRecords] of Object.entries(groupedByVariant)) {
|
|
13359
|
+
const vTotal = vRecords.length;
|
|
13360
|
+
const vResolved = vRecords.filter((r) => r.resolved).length;
|
|
13361
|
+
let vValue = 0;
|
|
13362
|
+
if (this.outcomeTracker) {
|
|
13363
|
+
vRecords.forEach((r) => {
|
|
13364
|
+
const outRecords = this.outcomeTracker.outcomes?.get(r.sessionId) || [];
|
|
13365
|
+
vValue += outRecords.reduce((s, o) => s + o.valueUsd, 0);
|
|
13366
|
+
});
|
|
13367
|
+
}
|
|
13368
|
+
const vCost = vRecords.reduce((s, r) => s + r.totalCostUsd, 0);
|
|
13369
|
+
variants[variantId] = {
|
|
13370
|
+
totalConversations: vTotal,
|
|
13371
|
+
totalValueGeneratedUsd: vValue,
|
|
13372
|
+
resolutionRate: vTotal > 0 ? vResolved / vTotal : 0,
|
|
13373
|
+
roi: vCost > 0 ? (vValue - vCost) / vCost : 0
|
|
13374
|
+
};
|
|
13375
|
+
}
|
|
13339
13376
|
return {
|
|
13340
13377
|
totalConversations: total,
|
|
13341
13378
|
resolvedCount: resolved,
|
|
@@ -13345,6 +13382,8 @@ var ConversationAnalytics = class {
|
|
|
13345
13382
|
avgResponseTimeMs: Math.round(avgResponseTime),
|
|
13346
13383
|
totalTokensUsed: totalTokens,
|
|
13347
13384
|
totalCostUsd: Math.round(totalCost * 1e8) / 1e8,
|
|
13385
|
+
totalValueGeneratedUsd: Math.round(totalValue * 100) / 100,
|
|
13386
|
+
roi: totalCost > 0 ? (totalValue - totalCost) / totalCost : 0,
|
|
13348
13387
|
avgTokensPerConversation: Math.round(totalTokens / total),
|
|
13349
13388
|
avgCostPerConversation: Math.round(totalCost / total * 1e8) / 1e8,
|
|
13350
13389
|
topQueries,
|
|
@@ -13361,6 +13400,8 @@ var ConversationAnalytics = class {
|
|
|
13361
13400
|
avgResponseTimeMs: 0,
|
|
13362
13401
|
totalTokensUsed: 0,
|
|
13363
13402
|
totalCostUsd: 0,
|
|
13403
|
+
totalValueGeneratedUsd: 0,
|
|
13404
|
+
roi: 0,
|
|
13364
13405
|
avgTokensPerConversation: 0,
|
|
13365
13406
|
avgCostPerConversation: 0,
|
|
13366
13407
|
topQueries: [],
|
|
@@ -13501,23 +13542,223 @@ var HandoffManager = class {
|
|
|
13501
13542
|
}
|
|
13502
13543
|
};
|
|
13503
13544
|
|
|
13545
|
+
// src/core/session.ts
|
|
13546
|
+
import * as fs2 from "fs/promises";
|
|
13547
|
+
import * as path from "path";
|
|
13548
|
+
var MemorySessionStore = class {
|
|
13549
|
+
store = /* @__PURE__ */ new Map();
|
|
13550
|
+
async get(sessionId) {
|
|
13551
|
+
return this.store.get(sessionId) || null;
|
|
13552
|
+
}
|
|
13553
|
+
async set(sessionId, data) {
|
|
13554
|
+
this.store.set(sessionId, data);
|
|
13555
|
+
}
|
|
13556
|
+
async delete(sessionId) {
|
|
13557
|
+
this.store.delete(sessionId);
|
|
13558
|
+
}
|
|
13559
|
+
async clear() {
|
|
13560
|
+
this.store.clear();
|
|
13561
|
+
}
|
|
13562
|
+
};
|
|
13563
|
+
var FileSessionStore = class {
|
|
13564
|
+
dir;
|
|
13565
|
+
constructor(dir = "./.sessions") {
|
|
13566
|
+
this.dir = path.resolve(dir);
|
|
13567
|
+
}
|
|
13568
|
+
getPath(sessionId) {
|
|
13569
|
+
return path.join(this.dir, `${sessionId}.json`);
|
|
13570
|
+
}
|
|
13571
|
+
async ensureDir() {
|
|
13572
|
+
try {
|
|
13573
|
+
await fs2.mkdir(this.dir, { recursive: true });
|
|
13574
|
+
} catch {
|
|
13575
|
+
}
|
|
13576
|
+
}
|
|
13577
|
+
async get(sessionId) {
|
|
13578
|
+
try {
|
|
13579
|
+
const data = await fs2.readFile(this.getPath(sessionId), "utf8");
|
|
13580
|
+
return JSON.parse(data);
|
|
13581
|
+
} catch {
|
|
13582
|
+
return null;
|
|
13583
|
+
}
|
|
13584
|
+
}
|
|
13585
|
+
async set(sessionId, data) {
|
|
13586
|
+
await this.ensureDir();
|
|
13587
|
+
await fs2.writeFile(this.getPath(sessionId), JSON.stringify(data), "utf8");
|
|
13588
|
+
}
|
|
13589
|
+
async delete(sessionId) {
|
|
13590
|
+
try {
|
|
13591
|
+
await fs2.unlink(this.getPath(sessionId));
|
|
13592
|
+
} catch {
|
|
13593
|
+
}
|
|
13594
|
+
}
|
|
13595
|
+
async clear() {
|
|
13596
|
+
try {
|
|
13597
|
+
const files = await fs2.readdir(this.dir);
|
|
13598
|
+
for (const file of files) {
|
|
13599
|
+
if (file.endsWith(".json")) {
|
|
13600
|
+
await fs2.unlink(path.join(this.dir, file));
|
|
13601
|
+
}
|
|
13602
|
+
}
|
|
13603
|
+
} catch {
|
|
13604
|
+
}
|
|
13605
|
+
}
|
|
13606
|
+
};
|
|
13607
|
+
|
|
13608
|
+
// src/analytics/outcome.ts
|
|
13609
|
+
var OutcomeTracker = class {
|
|
13610
|
+
sessionOutcomes = /* @__PURE__ */ new Map();
|
|
13611
|
+
/** Record a successful business outcome for a session. */
|
|
13612
|
+
record(sessionId, type, valueUsd = 0, metadata) {
|
|
13613
|
+
const list = this.sessionOutcomes.get(sessionId) || [];
|
|
13614
|
+
list.push({ type, valueUsd, timestamp: Date.now(), metadata });
|
|
13615
|
+
this.sessionOutcomes.set(sessionId, list);
|
|
13616
|
+
}
|
|
13617
|
+
/** Get all outcomes for a specific session. */
|
|
13618
|
+
getSessionOutcomes(sessionId) {
|
|
13619
|
+
return this.sessionOutcomes.get(sessionId) || [];
|
|
13620
|
+
}
|
|
13621
|
+
/** Calculate total value generated for a session. */
|
|
13622
|
+
getSessionValue(sessionId) {
|
|
13623
|
+
return this.getSessionOutcomes(sessionId).reduce((sum, o) => sum + o.valueUsd, 0);
|
|
13624
|
+
}
|
|
13625
|
+
/** Get global stats for all outcomes. */
|
|
13626
|
+
getGlobalStats() {
|
|
13627
|
+
const all = [...this.sessionOutcomes.values()].flat();
|
|
13628
|
+
const totalValue = all.reduce((sum, o) => sum + o.valueUsd, 0);
|
|
13629
|
+
const countByType = {};
|
|
13630
|
+
for (const o of all) {
|
|
13631
|
+
countByType[o.type] = (countByType[o.type] || 0) + 1;
|
|
13632
|
+
}
|
|
13633
|
+
return {
|
|
13634
|
+
totalOutcomes: all.length,
|
|
13635
|
+
totalValueUsd: totalValue,
|
|
13636
|
+
outcomesByType: countByType
|
|
13637
|
+
};
|
|
13638
|
+
}
|
|
13639
|
+
/** Reset all stats. */
|
|
13640
|
+
clear() {
|
|
13641
|
+
this.sessionOutcomes.clear();
|
|
13642
|
+
}
|
|
13643
|
+
};
|
|
13644
|
+
|
|
13645
|
+
// src/analytics/redact.ts
|
|
13646
|
+
var DEFAULT_REDACTION_RULES = [
|
|
13647
|
+
{
|
|
13648
|
+
name: "email",
|
|
13649
|
+
pattern: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
|
|
13650
|
+
placeholder: "[REDACTED_EMAIL]"
|
|
13651
|
+
},
|
|
13652
|
+
{
|
|
13653
|
+
name: "phone",
|
|
13654
|
+
pattern: /\b(?:\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g,
|
|
13655
|
+
placeholder: "[REDACTED_PHONE]"
|
|
13656
|
+
},
|
|
13657
|
+
{
|
|
13658
|
+
name: "credit_card",
|
|
13659
|
+
// Standard 16 digit match with optional dashes or spaces
|
|
13660
|
+
pattern: /\b(?:\d[ -]*?){13,16}\b/g,
|
|
13661
|
+
placeholder: "[REDACTED_CC]"
|
|
13662
|
+
},
|
|
13663
|
+
{
|
|
13664
|
+
name: "ssn",
|
|
13665
|
+
// Standard US SSN
|
|
13666
|
+
pattern: /\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g,
|
|
13667
|
+
placeholder: "[REDACTED_SSN]"
|
|
13668
|
+
}
|
|
13669
|
+
];
|
|
13670
|
+
var PIIRedactor = class {
|
|
13671
|
+
rules;
|
|
13672
|
+
constructor(rules) {
|
|
13673
|
+
this.rules = rules || DEFAULT_REDACTION_RULES;
|
|
13674
|
+
}
|
|
13675
|
+
/** Scans text and replaces any matched patterns with their placeholders. */
|
|
13676
|
+
redact(text) {
|
|
13677
|
+
if (!text) return text;
|
|
13678
|
+
let redacted = text;
|
|
13679
|
+
for (const rule of this.rules) {
|
|
13680
|
+
redacted = redacted.replace(rule.pattern, rule.placeholder);
|
|
13681
|
+
}
|
|
13682
|
+
return redacted;
|
|
13683
|
+
}
|
|
13684
|
+
/** Adds custom redaction rules to the engine. */
|
|
13685
|
+
addRule(rule) {
|
|
13686
|
+
this.rules.push(rule);
|
|
13687
|
+
}
|
|
13688
|
+
};
|
|
13689
|
+
|
|
13690
|
+
// src/analytics/experiment.ts
|
|
13691
|
+
import * as crypto2 from "crypto";
|
|
13692
|
+
var ExperimentManager = class {
|
|
13693
|
+
experiments = /* @__PURE__ */ new Map();
|
|
13694
|
+
constructor(experiments) {
|
|
13695
|
+
if (experiments) {
|
|
13696
|
+
experiments.forEach((e) => this.registerExperiment(e));
|
|
13697
|
+
}
|
|
13698
|
+
}
|
|
13699
|
+
registerExperiment(exp) {
|
|
13700
|
+
this.experiments.set(exp.name, exp);
|
|
13701
|
+
}
|
|
13702
|
+
/**
|
|
13703
|
+
* Assigns a user to a specific variant based on deterministic hashing of their sessionId.
|
|
13704
|
+
* This guarantees 'sticky sessions' where the same user always gets the same A/B test variant.
|
|
13705
|
+
*/
|
|
13706
|
+
assignVariant(experimentName, sessionId) {
|
|
13707
|
+
const exp = this.experiments.get(experimentName);
|
|
13708
|
+
if (!exp || exp.variants.length === 0) return null;
|
|
13709
|
+
if (exp.variants.length === 1) return exp.variants[0].id;
|
|
13710
|
+
const totalWeight = exp.variants.reduce((sum, v) => sum + v.weight, 0);
|
|
13711
|
+
const hash = crypto2.createHash("md5").update(`${experimentName}_${sessionId}`).digest("hex");
|
|
13712
|
+
const hashInt = parseInt(hash.slice(0, 8), 16);
|
|
13713
|
+
const bucket = hashInt % totalWeight;
|
|
13714
|
+
let cumulative = 0;
|
|
13715
|
+
for (const variant of exp.variants) {
|
|
13716
|
+
cumulative += variant.weight;
|
|
13717
|
+
if (bucket < cumulative) {
|
|
13718
|
+
return variant.id;
|
|
13719
|
+
}
|
|
13720
|
+
}
|
|
13721
|
+
return exp.variants[0].id;
|
|
13722
|
+
}
|
|
13723
|
+
/** Retrieves the variant config object for an assigned variant id. */
|
|
13724
|
+
getVariantConfig(experimentName, variantId) {
|
|
13725
|
+
const exp = this.experiments.get(experimentName);
|
|
13726
|
+
if (!exp) return null;
|
|
13727
|
+
const v = exp.variants.find((v2) => v2.id === variantId);
|
|
13728
|
+
return v ? v.config : null;
|
|
13729
|
+
}
|
|
13730
|
+
};
|
|
13731
|
+
|
|
13504
13732
|
// src/widget/bot.ts
|
|
13505
13733
|
var CustomerSupportBot = class {
|
|
13506
13734
|
executor;
|
|
13507
13735
|
connector;
|
|
13508
13736
|
knowledgeBase;
|
|
13509
13737
|
analytics;
|
|
13738
|
+
outcomeTracker;
|
|
13739
|
+
sessionStore;
|
|
13510
13740
|
handoff;
|
|
13741
|
+
piiRedactor;
|
|
13742
|
+
experimentManager;
|
|
13511
13743
|
greeting;
|
|
13744
|
+
defaultSystemPrompt;
|
|
13512
13745
|
middlewares = [];
|
|
13513
13746
|
constructor(config) {
|
|
13514
|
-
this.
|
|
13747
|
+
this.outcomeTracker = new OutcomeTracker();
|
|
13748
|
+
this.analytics = new ConversationAnalytics(this.outcomeTracker);
|
|
13749
|
+
this.sessionStore = config.sessionStore || new MemorySessionStore();
|
|
13515
13750
|
if (config.knowledgeBase) {
|
|
13516
13751
|
this.knowledgeBase = new KnowledgeBase(config.knowledgeBase);
|
|
13517
13752
|
}
|
|
13518
13753
|
if (config.handoff) {
|
|
13519
13754
|
this.handoff = new HandoffManager(config.handoff);
|
|
13520
13755
|
}
|
|
13756
|
+
if (config.enablePIIRedaction) {
|
|
13757
|
+
this.piiRedactor = new PIIRedactor();
|
|
13758
|
+
}
|
|
13759
|
+
if (config.experiments && config.experiments.length > 0) {
|
|
13760
|
+
this.experimentManager = new ExperimentManager(config.experiments);
|
|
13761
|
+
}
|
|
13521
13762
|
const tools = [];
|
|
13522
13763
|
if (config.apiConnector) {
|
|
13523
13764
|
this.connector = new APIConnector(config.apiConnector);
|
|
@@ -13549,11 +13790,12 @@ Your role:
|
|
|
13549
13790
|
- If you can't find an answer, politely suggest contacting human support
|
|
13550
13791
|
- Always maintain a warm, professional tone
|
|
13551
13792
|
- Never make up data \u2014 always verify through the API or context when available`;
|
|
13793
|
+
this.defaultSystemPrompt = config.systemPrompt || defaultSystemPrompt;
|
|
13552
13794
|
this.executor = new AgentExecutor({
|
|
13553
13795
|
gateway: config.gateway,
|
|
13554
13796
|
memory: config.memory || new InMemoryStore(100),
|
|
13555
13797
|
tools,
|
|
13556
|
-
systemPrompt:
|
|
13798
|
+
systemPrompt: this.defaultSystemPrompt,
|
|
13557
13799
|
telemetry: config.telemetry
|
|
13558
13800
|
});
|
|
13559
13801
|
this.greeting = config.greeting || `Hello! \u{1F44B} Welcome to ${config.companyName}. How can I help you today?`;
|
|
@@ -13562,17 +13804,34 @@ Your role:
|
|
|
13562
13804
|
use(middleware) {
|
|
13563
13805
|
this.middlewares.push(middleware);
|
|
13564
13806
|
}
|
|
13807
|
+
/** Record a business outcome for ROI tracking. */
|
|
13808
|
+
trackOutcome(sessionId, type, valueUsd = 0, metadata) {
|
|
13809
|
+
this.outcomeTracker.record(sessionId, type, valueUsd, metadata);
|
|
13810
|
+
}
|
|
13565
13811
|
/** Process a customer message and return the bot's response. */
|
|
13566
13812
|
async chat(sessionId, message) {
|
|
13567
|
-
this.
|
|
13568
|
-
|
|
13813
|
+
const activeMessage = this.piiRedactor ? this.piiRedactor.redact(message) : message;
|
|
13814
|
+
let variantId;
|
|
13815
|
+
if (this.experimentManager) {
|
|
13816
|
+
variantId = this.experimentManager.assignVariant("default_experiment", sessionId) || void 0;
|
|
13817
|
+
if (variantId) {
|
|
13818
|
+
const config = this.experimentManager.getVariantConfig("default_experiment", variantId);
|
|
13819
|
+
if (config && config.systemPrompt) {
|
|
13820
|
+
this.executor.systemPrompt = config.systemPrompt;
|
|
13821
|
+
} else {
|
|
13822
|
+
this.executor.systemPrompt = this.defaultSystemPrompt;
|
|
13823
|
+
}
|
|
13824
|
+
}
|
|
13825
|
+
}
|
|
13826
|
+
this.analytics.startConversation(sessionId, "gpt-4o-mini", variantId);
|
|
13827
|
+
this.analytics.recordQuery(sessionId, activeMessage);
|
|
13569
13828
|
const startTime = Date.now();
|
|
13570
13829
|
for (const mw of this.middlewares) {
|
|
13571
|
-
const result2 = await mw({ sessionId, message, bot: this });
|
|
13830
|
+
const result2 = await mw({ sessionId, message: activeMessage, bot: this });
|
|
13572
13831
|
if (typeof result2 === "string") return result2;
|
|
13573
13832
|
}
|
|
13574
13833
|
if (this.handoff) {
|
|
13575
|
-
const trigger = this.handoff.shouldEscalate(sessionId,
|
|
13834
|
+
const trigger = this.handoff.shouldEscalate(sessionId, activeMessage);
|
|
13576
13835
|
if (trigger) {
|
|
13577
13836
|
const history = await this.executor.memory.getMessages(sessionId);
|
|
13578
13837
|
let summary = "Customer needs assistance.";
|
|
@@ -13580,32 +13839,34 @@ Your role:
|
|
|
13580
13839
|
summary = await this.executor.gateway.chat([
|
|
13581
13840
|
{ role: "system", content: "Summarize the customer's problem in one concise sentence for a human support agent context." },
|
|
13582
13841
|
...history,
|
|
13583
|
-
{ role: "user", content:
|
|
13842
|
+
{ role: "user", content: activeMessage }
|
|
13584
13843
|
]);
|
|
13585
13844
|
} catch {
|
|
13586
13845
|
}
|
|
13587
|
-
const reply = await this.handoff.escalate(sessionId, trigger, history,
|
|
13846
|
+
const reply = await this.handoff.escalate(sessionId, trigger, history, activeMessage, summary);
|
|
13588
13847
|
this.analytics.markHandedOff(sessionId);
|
|
13589
13848
|
return reply;
|
|
13590
13849
|
}
|
|
13591
13850
|
}
|
|
13592
|
-
let enhancedMessage =
|
|
13851
|
+
let enhancedMessage = activeMessage;
|
|
13593
13852
|
if (this.knowledgeBase) {
|
|
13594
|
-
const context = await this.knowledgeBase.query(
|
|
13853
|
+
const context = await this.knowledgeBase.query(activeMessage);
|
|
13595
13854
|
if (context) {
|
|
13596
13855
|
enhancedMessage = `Context from Knowledge Base:
|
|
13597
13856
|
${context}
|
|
13598
13857
|
|
|
13599
|
-
User Question: ${
|
|
13858
|
+
User Question: ${activeMessage}`;
|
|
13600
13859
|
}
|
|
13601
13860
|
}
|
|
13602
13861
|
try {
|
|
13603
13862
|
const reply = await this.executor.execute(sessionId, enhancedMessage, 8);
|
|
13604
13863
|
this.analytics.recordResponse(sessionId, reply, Date.now() - startTime);
|
|
13864
|
+
const history = await this.executor.getMemory().getMessages(sessionId);
|
|
13865
|
+
await this.sessionStore.set(sessionId, { history, lastUpdated: Date.now() });
|
|
13605
13866
|
return reply;
|
|
13606
13867
|
} catch (e) {
|
|
13607
13868
|
if (this.handoff) {
|
|
13608
|
-
return this.handoff.escalate(sessionId, "low_confidence", [],
|
|
13869
|
+
return this.handoff.escalate(sessionId, "low_confidence", [], activeMessage, `Error: ${e.message}`);
|
|
13609
13870
|
}
|
|
13610
13871
|
throw e;
|
|
13611
13872
|
}
|
|
@@ -13809,6 +14070,87 @@ async function startChatServer(config) {
|
|
|
13809
14070
|
console.log(` GET /health \u2014 Health check`);
|
|
13810
14071
|
});
|
|
13811
14072
|
}
|
|
14073
|
+
|
|
14074
|
+
// src/channels/base.ts
|
|
14075
|
+
var ChannelAdapter = class {
|
|
14076
|
+
bot;
|
|
14077
|
+
constructor(config) {
|
|
14078
|
+
this.bot = config.bot;
|
|
14079
|
+
}
|
|
14080
|
+
/**
|
|
14081
|
+
* Normalize incoming messages from different platforms
|
|
14082
|
+
* and route them to the core bot brain.
|
|
14083
|
+
*/
|
|
14084
|
+
async handleMessage(sessionId, text) {
|
|
14085
|
+
return this.bot.chat(sessionId, text);
|
|
14086
|
+
}
|
|
14087
|
+
};
|
|
14088
|
+
|
|
14089
|
+
// src/channels/slack.ts
|
|
14090
|
+
var SlackAdapter = class extends ChannelAdapter {
|
|
14091
|
+
constructor(config) {
|
|
14092
|
+
super(config);
|
|
14093
|
+
}
|
|
14094
|
+
async start() {
|
|
14095
|
+
console.log("[SlackAdapter] Initializing Slack connection...");
|
|
14096
|
+
}
|
|
14097
|
+
async stop() {
|
|
14098
|
+
}
|
|
14099
|
+
/** Handler for Slack events (to be used by Express middleware). */
|
|
14100
|
+
async handleEvent(event) {
|
|
14101
|
+
if (event.type === "message" && !event.bot_id && event.text) {
|
|
14102
|
+
const sessionId = `slack_${event.channel}_${event.user}`;
|
|
14103
|
+
const reply = await this.handleMessage(sessionId, event.text);
|
|
14104
|
+
}
|
|
14105
|
+
}
|
|
14106
|
+
};
|
|
14107
|
+
|
|
14108
|
+
// src/channels/telegram.ts
|
|
14109
|
+
var TelegramAdapter = class extends ChannelAdapter {
|
|
14110
|
+
token;
|
|
14111
|
+
polling = false;
|
|
14112
|
+
offset = 0;
|
|
14113
|
+
constructor(config) {
|
|
14114
|
+
super(config);
|
|
14115
|
+
this.token = config.token;
|
|
14116
|
+
}
|
|
14117
|
+
async start() {
|
|
14118
|
+
this.polling = true;
|
|
14119
|
+
this.runPollingLoop();
|
|
14120
|
+
console.log("[TelegramAdapter] Started polling for updates...");
|
|
14121
|
+
}
|
|
14122
|
+
async stop() {
|
|
14123
|
+
this.polling = false;
|
|
14124
|
+
}
|
|
14125
|
+
async runPollingLoop() {
|
|
14126
|
+
while (this.polling) {
|
|
14127
|
+
try {
|
|
14128
|
+
const response = await fetch(`https://api.telegram.org/bot${this.token}/getUpdates?offset=${this.offset}&timeout=30`);
|
|
14129
|
+
const data = await response.json();
|
|
14130
|
+
if (data.ok && data.result && data.result.length > 0) {
|
|
14131
|
+
for (const update of data.result) {
|
|
14132
|
+
this.offset = update.update_id + 1;
|
|
14133
|
+
if (update.message?.text) {
|
|
14134
|
+
const chatId = update.message.chat.id.toString();
|
|
14135
|
+
const reply = await this.handleMessage(`tg_${chatId}`, update.message.text);
|
|
14136
|
+
await this.sendMessage(chatId, reply);
|
|
14137
|
+
}
|
|
14138
|
+
}
|
|
14139
|
+
}
|
|
14140
|
+
} catch (e) {
|
|
14141
|
+
console.error(`[TelegramAdapter] Error: ${e.message}`);
|
|
14142
|
+
await new Promise((r) => setTimeout(r, 5e3));
|
|
14143
|
+
}
|
|
14144
|
+
}
|
|
14145
|
+
}
|
|
14146
|
+
async sendMessage(chatId, text) {
|
|
14147
|
+
await fetch(`https://api.telegram.org/bot${this.token}/sendMessage`, {
|
|
14148
|
+
method: "POST",
|
|
14149
|
+
headers: { "Content-Type": "application/json" },
|
|
14150
|
+
body: JSON.stringify({ chat_id: chatId, text })
|
|
14151
|
+
});
|
|
14152
|
+
}
|
|
14153
|
+
};
|
|
13812
14154
|
export {
|
|
13813
14155
|
AIModelGateway,
|
|
13814
14156
|
APIConnector,
|
|
@@ -13821,6 +14163,7 @@ export {
|
|
|
13821
14163
|
BaseSpeakerRecognizer,
|
|
13822
14164
|
BaseTTSProvider,
|
|
13823
14165
|
CachedGateway,
|
|
14166
|
+
ChannelAdapter,
|
|
13824
14167
|
ChatAgent,
|
|
13825
14168
|
ChatMessageSchema,
|
|
13826
14169
|
ChatRequestSchema,
|
|
@@ -13829,21 +14172,29 @@ export {
|
|
|
13829
14172
|
ConfigurationError,
|
|
13830
14173
|
ConversationAnalytics,
|
|
13831
14174
|
CustomerSupportBot,
|
|
14175
|
+
DEFAULT_REDACTION_RULES,
|
|
13832
14176
|
EchoAI,
|
|
13833
14177
|
EchoVoice,
|
|
14178
|
+
ExperimentManager,
|
|
14179
|
+
FileSessionStore,
|
|
13834
14180
|
GatewayRoutingError,
|
|
13835
14181
|
HandoffManager,
|
|
13836
14182
|
InMemoryStore,
|
|
13837
14183
|
KnowledgeBase,
|
|
14184
|
+
MemorySessionStore,
|
|
13838
14185
|
MemoryVectorStore,
|
|
13839
14186
|
OPENAI_PRICING,
|
|
13840
14187
|
OpenAITTS,
|
|
13841
14188
|
OpenAIWhisperSTT,
|
|
14189
|
+
OutcomeTracker,
|
|
14190
|
+
PIIRedactor,
|
|
13842
14191
|
PromptRegistry,
|
|
13843
14192
|
PromptTemplate,
|
|
13844
14193
|
PromptVersionError,
|
|
13845
14194
|
ProviderDependencyError,
|
|
14195
|
+
SlackAdapter,
|
|
13846
14196
|
StructuredOutputError,
|
|
14197
|
+
TelegramAdapter,
|
|
13847
14198
|
ToolAgent,
|
|
13848
14199
|
ToolExecutionError,
|
|
13849
14200
|
UsageMetricsSchema,
|