@maximem/synap-js-sdk 0.5.8 → 0.5.9
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 +5 -1
- package/dist/anticipation-cache-LPNKMRBH.cjs +20 -0
- package/dist/anticipation-cache-LPNKMRBH.cjs.map +1 -0
- package/dist/anticipation-cache-RWKF55J4.js +20 -0
- package/dist/{chunk-FXGLT6AT.js → chunk-I7TWR4S6.js} +59 -3
- package/dist/chunk-I7TWR4S6.js.map +1 -0
- package/dist/{chunk-T6U5PVAD.cjs → chunk-ICUFS3B5.cjs} +449 -12
- package/dist/chunk-ICUFS3B5.cjs.map +1 -0
- package/dist/{chunk-ODVOQOSO.js → chunk-R72YL6Q4.js} +445 -8
- package/dist/chunk-R72YL6Q4.js.map +1 -0
- package/dist/{chunk-HCULAVJC.cjs → chunk-RE4DDIWO.cjs} +66 -10
- package/dist/chunk-RE4DDIWO.cjs.map +1 -0
- package/dist/chunk-T372OL3Q.cjs.map +1 -1
- package/dist/chunk-ZKOJDUN4.cjs.map +1 -1
- package/dist/env-55ULHNJZ.cjs.map +1 -1
- package/dist/{errors-Bl3vY1eb.d.cts → errors-Bdayqlzy.d.cts} +88 -2
- package/dist/{errors-Bl3vY1eb.d.ts → errors-Bdayqlzy.d.ts} +88 -2
- package/dist/grpc/index.cjs +4 -4
- package/dist/grpc/index.cjs.map +1 -1
- package/dist/grpc/index.d.cts +8 -3
- package/dist/grpc/index.d.ts +8 -3
- package/dist/grpc/index.js +3 -3
- package/dist/index.cjs +1300 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +258 -5
- package/dist/index.d.ts +258 -5
- package/dist/index.js +1253 -69
- package/dist/index.js.map +1 -1
- package/dist/onnx-encoder-4RSL6ID4.cjs +103 -0
- package/dist/onnx-encoder-4RSL6ID4.cjs.map +1 -0
- package/dist/onnx-encoder-NP35KH4H.js +103 -0
- package/dist/onnx-encoder-NP35KH4H.js.map +1 -0
- package/dist/{stream-client-VWKINE47.js → stream-client-3WHXGW4U.js} +2 -2
- package/dist/stream-client-L6OQPZN7.cjs +16 -0
- package/dist/stream-client-L6OQPZN7.cjs.map +1 -0
- package/package.json +4 -2
- package/dist/anticipation-cache-LRE3TLK4.cjs +0 -14
- package/dist/anticipation-cache-LRE3TLK4.cjs.map +0 -1
- package/dist/anticipation-cache-WLU4NMD5.js +0 -14
- package/dist/chunk-FXGLT6AT.js.map +0 -1
- package/dist/chunk-HCULAVJC.cjs.map +0 -1
- package/dist/chunk-ODVOQOSO.js.map +0 -1
- package/dist/chunk-T6U5PVAD.cjs.map +0 -1
- package/dist/stream-client-N46JBT5A.cjs +0 -16
- package/dist/stream-client-N46JBT5A.cjs.map +0 -1
- /package/dist/{anticipation-cache-WLU4NMD5.js.map → anticipation-cache-RWKF55J4.js.map} +0 -0
- /package/dist/{stream-client-VWKINE47.js.map → stream-client-3WHXGW4U.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4;
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
var _chunkICUFS3B5cjs = require('./chunk-ICUFS3B5.cjs');
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
var _chunkZKOJDUN4cjs = require('./chunk-ZKOJDUN4.cjs');
|
|
@@ -55,6 +57,7 @@ var ENDPOINTS = {
|
|
|
55
57
|
context_fetch_client: { method: "POST", path: "/v1/context/client/fetch", idempotent: true },
|
|
56
58
|
context_fetch_conversation: { method: "POST", path: "/v1/context/conversation/fetch", idempotent: true },
|
|
57
59
|
context_for_prompt: { method: "GET", path: "/v1/conversations/{conversation_id}/context-for-prompt", idempotent: true },
|
|
60
|
+
conversation_turns: { method: "GET", path: "/v1/conversations/{conversation_id}/messages", idempotent: true },
|
|
58
61
|
conversations_ingest: { method: "POST", path: "/v1/conversations/ingest", idempotent: false },
|
|
59
62
|
conversations_messages: { method: "POST", path: "/v1/conversations/messages", idempotent: false },
|
|
60
63
|
conversations_messages_batch: { method: "POST", path: "/v1/conversations/messages/batch", idempotent: false },
|
|
@@ -132,7 +135,7 @@ var HEARTBEAT_INTERVAL_MS = 24e4;
|
|
|
132
135
|
var MAX_CONNECTIONS = 20;
|
|
133
136
|
var cached;
|
|
134
137
|
function supportsDispatcher() {
|
|
135
|
-
return typeof process !== "undefined" && _optionalChain([process, 'access',
|
|
138
|
+
return typeof process !== "undefined" && _optionalChain([process, 'access', _2 => _2.versions, 'optionalAccess', _3 => _3.node]) !== void 0 && // Edge builds of Next expose a partial `process` shim, but no real Node.
|
|
136
139
|
typeof globalThis.EdgeRuntime === "undefined";
|
|
137
140
|
}
|
|
138
141
|
async function getKeepAliveDispatcher(options = {}) {
|
|
@@ -173,7 +176,7 @@ var Heartbeat = (_class = class {
|
|
|
173
176
|
void Promise.resolve(this.ping()).catch(() => {
|
|
174
177
|
});
|
|
175
178
|
}, this.intervalMs);
|
|
176
|
-
_optionalChain([this, 'access',
|
|
179
|
+
_optionalChain([this, 'access', _4 => _4.timer, 'access', _5 => _5.unref, 'optionalCall', _6 => _6()]);
|
|
177
180
|
}
|
|
178
181
|
stop() {
|
|
179
182
|
if (this.timer !== null) {
|
|
@@ -226,7 +229,7 @@ var HttpTransport = (_class2 = class {
|
|
|
226
229
|
this.keepAliveOptions = _nullishCoalesce(options.keepAlive, () => ( {}));
|
|
227
230
|
this.heartbeat = new Heartbeat(
|
|
228
231
|
() => this.pingHealth(),
|
|
229
|
-
_nullishCoalesce(_optionalChain([options, 'access',
|
|
232
|
+
_nullishCoalesce(_optionalChain([options, 'access', _7 => _7.keepAlive, 'optionalAccess', _8 => _8.heartbeatIntervalMs]), () => ( HEARTBEAT_INTERVAL_MS))
|
|
230
233
|
);
|
|
231
234
|
}
|
|
232
235
|
/** Start keeping the connection warm. Opt-in: it is pointless in serverless. */
|
|
@@ -315,7 +318,7 @@ var HttpTransport = (_class2 = class {
|
|
|
315
318
|
await sleep(decision.delaySeconds * 1e3, options.signal);
|
|
316
319
|
}
|
|
317
320
|
}
|
|
318
|
-
throw _nullishCoalesce(_optionalChain([last, 'optionalAccess',
|
|
321
|
+
throw _nullishCoalesce(_optionalChain([last, 'optionalAccess', _9 => _9.error]), () => ( new (0, _chunkT372OL3Qcjs.SynapError)("Request failed with no recorded error")));
|
|
319
322
|
}
|
|
320
323
|
async attempt(name, options, correlationId) {
|
|
321
324
|
const spec = ENDPOINTS[name];
|
|
@@ -394,17 +397,17 @@ function isOutcomeUnknown(error) {
|
|
|
394
397
|
return true;
|
|
395
398
|
}
|
|
396
399
|
function isConnectionRefusal(error) {
|
|
397
|
-
const code = _nullishCoalesce(_optionalChain([error, 'optionalAccess',
|
|
400
|
+
const code = _nullishCoalesce(_optionalChain([error, 'optionalAccess', _10 => _10.cause, 'optionalAccess', _11 => _11.code]), () => ( _optionalChain([error, 'optionalAccess', _12 => _12.code])));
|
|
398
401
|
return code === "ECONNREFUSED" || code === "ENOTFOUND" || code === "EAI_AGAIN" || code === "ECONNRESET" || code === "EHOSTUNREACH";
|
|
399
402
|
}
|
|
400
403
|
function toTransportError(error, correlationId) {
|
|
401
404
|
if (error instanceof _chunkT372OL3Qcjs.SynapError) return error;
|
|
402
|
-
const name = _optionalChain([error, 'optionalAccess',
|
|
405
|
+
const name = _optionalChain([error, 'optionalAccess', _13 => _13.name]);
|
|
403
406
|
if (name === "AbortError" || name === "TimeoutError") {
|
|
404
407
|
return new (0, _chunkT372OL3Qcjs.NetworkTimeoutError)("Request timed out", { correlationId, cause: error });
|
|
405
408
|
}
|
|
406
409
|
return new (0, _chunkT372OL3Qcjs.ServiceUnavailableError)(
|
|
407
|
-
`Network request failed: ${_nullishCoalesce(_optionalChain([error, 'optionalAccess',
|
|
410
|
+
`Network request failed: ${_nullishCoalesce(_optionalChain([error, 'optionalAccess', _14 => _14.message]), () => ( String(error)))}`,
|
|
408
411
|
{ correlationId, cause: error }
|
|
409
412
|
);
|
|
410
413
|
}
|
|
@@ -485,11 +488,11 @@ function stringOrNull(v) {
|
|
|
485
488
|
}
|
|
486
489
|
function withTimeout(ms, external) {
|
|
487
490
|
const controller = new AbortController();
|
|
488
|
-
const onExternalAbort = () => controller.abort(_optionalChain([external, 'optionalAccess',
|
|
491
|
+
const onExternalAbort = () => controller.abort(_optionalChain([external, 'optionalAccess', _15 => _15.reason]));
|
|
489
492
|
const timer = setTimeout(() => {
|
|
490
493
|
controller.abort(new (0, _chunkT372OL3Qcjs.NetworkTimeoutError)(`Timed out after ${ms}ms`));
|
|
491
494
|
}, ms);
|
|
492
|
-
_optionalChain([timer, 'access',
|
|
495
|
+
_optionalChain([timer, 'access', _16 => _16.unref, 'optionalCall', _17 => _17()]);
|
|
493
496
|
if (external) {
|
|
494
497
|
if (external.aborted) onExternalAbort();
|
|
495
498
|
else external.addEventListener("abort", onExternalAbort, { once: true });
|
|
@@ -498,7 +501,7 @@ function withTimeout(ms, external) {
|
|
|
498
501
|
signal: controller.signal,
|
|
499
502
|
dispose() {
|
|
500
503
|
clearTimeout(timer);
|
|
501
|
-
_optionalChain([external, 'optionalAccess',
|
|
504
|
+
_optionalChain([external, 'optionalAccess', _18 => _18.removeEventListener, 'call', _19 => _19("abort", onExternalAbort)]);
|
|
502
505
|
}
|
|
503
506
|
};
|
|
504
507
|
}
|
|
@@ -506,17 +509,97 @@ function sleep(ms, signal) {
|
|
|
506
509
|
if (ms <= 0) return Promise.resolve();
|
|
507
510
|
return new Promise((resolve, reject) => {
|
|
508
511
|
const timer = setTimeout(() => {
|
|
509
|
-
_optionalChain([signal, 'optionalAccess',
|
|
512
|
+
_optionalChain([signal, 'optionalAccess', _20 => _20.removeEventListener, 'call', _21 => _21("abort", onAbort)]);
|
|
510
513
|
resolve();
|
|
511
514
|
}, ms);
|
|
512
515
|
function onAbort() {
|
|
513
516
|
clearTimeout(timer);
|
|
514
|
-
reject(_nullishCoalesce(_optionalChain([signal, 'optionalAccess',
|
|
517
|
+
reject(_nullishCoalesce(_optionalChain([signal, 'optionalAccess', _22 => _22.reason]), () => ( new Error("Aborted"))));
|
|
515
518
|
}
|
|
516
|
-
_optionalChain([signal, 'optionalAccess',
|
|
519
|
+
_optionalChain([signal, 'optionalAccess', _23 => _23.addEventListener, 'call', _24 => _24("abort", onAbort, { once: true })]);
|
|
517
520
|
});
|
|
518
521
|
}
|
|
519
522
|
|
|
523
|
+
// src/context/ranked.ts
|
|
524
|
+
var RESPONSE_SHAPES = ["by_type", "ranked"];
|
|
525
|
+
var MEMORY_TYPES = [
|
|
526
|
+
"facts",
|
|
527
|
+
"preferences",
|
|
528
|
+
"episodes",
|
|
529
|
+
"emotions",
|
|
530
|
+
"temporal_events"
|
|
531
|
+
];
|
|
532
|
+
var EXCERPT_CATEGORY = "excerpts";
|
|
533
|
+
function wireRankScore(item) {
|
|
534
|
+
const md = item.metadata;
|
|
535
|
+
let raw = md !== null && typeof md === "object" ? md["rank_score"] : void 0;
|
|
536
|
+
if (raw === void 0 || raw === null) raw = item["rank_score"];
|
|
537
|
+
return typeof raw === "number" && Number.isFinite(raw) ? raw : null;
|
|
538
|
+
}
|
|
539
|
+
function wireCategory(item, fallback = "") {
|
|
540
|
+
if (item.source === "chunks") return EXCERPT_CATEGORY;
|
|
541
|
+
const category = item["category"];
|
|
542
|
+
if (typeof category === "string" && category !== "") return category;
|
|
543
|
+
const contextType = item["context_type"];
|
|
544
|
+
if (typeof contextType === "string" && contextType !== "") return contextType;
|
|
545
|
+
return fallback;
|
|
546
|
+
}
|
|
547
|
+
function byRankScore(a, b) {
|
|
548
|
+
const sa = wireRankScore(a);
|
|
549
|
+
const sb = wireRankScore(b);
|
|
550
|
+
if (sa === null && sb === null) return 0;
|
|
551
|
+
if (sa === null) return 1;
|
|
552
|
+
if (sb === null) return -1;
|
|
553
|
+
return sb - sa;
|
|
554
|
+
}
|
|
555
|
+
function rankItems(byType) {
|
|
556
|
+
const flat = [];
|
|
557
|
+
for (const type of MEMORY_TYPES) {
|
|
558
|
+
const list = byType[type];
|
|
559
|
+
if (!Array.isArray(list)) continue;
|
|
560
|
+
for (const it of list) {
|
|
561
|
+
if (it === null || typeof it !== "object") continue;
|
|
562
|
+
flat.push({
|
|
563
|
+
...it,
|
|
564
|
+
category: wireCategory(it, type),
|
|
565
|
+
id: it.id || it.item_id || ""
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
flat.sort(byRankScore);
|
|
570
|
+
return flat.map((it, n2) => ({ ...it, rank: n2 + 1 }));
|
|
571
|
+
}
|
|
572
|
+
function applyResponseShape(raw, shape = "by_type") {
|
|
573
|
+
const wire = raw["items"];
|
|
574
|
+
if (shape !== "ranked" && !Array.isArray(wire)) return raw;
|
|
575
|
+
const source = Array.isArray(wire) ? wire : rankItems(raw);
|
|
576
|
+
const items = source.map((it) => ({
|
|
577
|
+
...it,
|
|
578
|
+
id: it.id || it.item_id || "",
|
|
579
|
+
category: wireCategory(it)
|
|
580
|
+
}));
|
|
581
|
+
const out = { ...raw, items };
|
|
582
|
+
for (const type of MEMORY_TYPES) {
|
|
583
|
+
out[type] = items.filter((it) => it["category"] === type);
|
|
584
|
+
}
|
|
585
|
+
out["excerpts"] = items.filter((it) => it["category"] === EXCERPT_CATEGORY);
|
|
586
|
+
return out;
|
|
587
|
+
}
|
|
588
|
+
var RANKED_LABELS = {
|
|
589
|
+
facts: "fact",
|
|
590
|
+
preferences: "preference",
|
|
591
|
+
episodes: "episode",
|
|
592
|
+
emotions: "emotion",
|
|
593
|
+
temporal_events: "temporal event",
|
|
594
|
+
[EXCERPT_CATEGORY]: "excerpt"
|
|
595
|
+
};
|
|
596
|
+
function rankedLabel(category) {
|
|
597
|
+
return _nullishCoalesce(RANKED_LABELS[category], () => ( (category !== "" ? category : "item")));
|
|
598
|
+
}
|
|
599
|
+
function sortByRankScore(items) {
|
|
600
|
+
return [...items].sort(byRankScore);
|
|
601
|
+
}
|
|
602
|
+
|
|
520
603
|
// src/context/fetch.ts
|
|
521
604
|
var ENDPOINT_BY_SCOPE = {
|
|
522
605
|
user: "context_fetch_user",
|
|
@@ -539,6 +622,7 @@ function buildFetchRequest(scope, options) {
|
|
|
539
622
|
const precisionLevel = _nullishCoalesce(opt(options, "precision_level", "precisionLevel"), () => ( "high"));
|
|
540
623
|
const queryDate = opt(options, "query_date", "queryDate");
|
|
541
624
|
const perQuery = opt(options, "max_results_per_query", "maxResultsPerQuery");
|
|
625
|
+
const responseShape = responseShapeOf(options);
|
|
542
626
|
const mode = _nullishCoalesce(options.mode, () => ( "fast"));
|
|
543
627
|
if (searchQuery !== void 0 && !Array.isArray(searchQuery)) {
|
|
544
628
|
throw new (0, _chunkT372OL3Qcjs.InvalidInputError)("search_query must be an array when provided");
|
|
@@ -556,6 +640,7 @@ function buildFetchRequest(scope, options) {
|
|
|
556
640
|
if (precisionLevel !== "high") body["precision_level"] = precisionLevel;
|
|
557
641
|
if (queryDate) body["query_date"] = queryDate;
|
|
558
642
|
if (perQuery) body["max_results_per_query"] = perQuery;
|
|
643
|
+
if (responseShape !== "by_type") body["response_shape"] = responseShape;
|
|
559
644
|
if (options.include_conversation_context === false) {
|
|
560
645
|
body["include_conversation_context"] = false;
|
|
561
646
|
}
|
|
@@ -603,22 +688,49 @@ function buildFetchRequest(scope, options) {
|
|
|
603
688
|
return { endpoint: ENDPOINT_BY_SCOPE[scope], body };
|
|
604
689
|
}
|
|
605
690
|
var VALID_CONTEXT_MODES = ["in-conversation", "conversation-summary"];
|
|
691
|
+
function responseShapeOf(options) {
|
|
692
|
+
const shape = _nullishCoalesce(opt(options, "response_shape", "responseShape"), () => ( "by_type"));
|
|
693
|
+
if (!RESPONSE_SHAPES.includes(shape)) {
|
|
694
|
+
throw new (0, _chunkT372OL3Qcjs.InvalidInputError)(
|
|
695
|
+
`Invalid response_shape '${shape}'. Must be one of: ${RESPONSE_SHAPES.join(", ")}`
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
return shape;
|
|
699
|
+
}
|
|
606
700
|
async function fetchContext(transport, scope, options = {}, hooks = {}) {
|
|
607
701
|
const startedAt = Date.now();
|
|
608
702
|
transport.checkCustomerId(
|
|
609
703
|
opt(options, "customer_id", "customerId"),
|
|
610
704
|
`${scope}.context.fetch`
|
|
611
705
|
);
|
|
612
|
-
const
|
|
706
|
+
const responseShape = responseShapeOf(options);
|
|
707
|
+
const network = async () => {
|
|
708
|
+
const { endpoint, body } = buildFetchRequest(scope, options);
|
|
709
|
+
const result = await transport.request(endpoint, { body });
|
|
710
|
+
return applyResponseShape(_nullishCoalesce(_optionalChain([result, 'optionalAccess', _25 => _25["context"]]), () => ( {})), responseShape);
|
|
711
|
+
};
|
|
712
|
+
const anticipated = await _asyncNullishCoalesce(await _optionalChain([hooks, 'access', _26 => _26.beforeFetch, 'optionalCall', _27 => _27(scope, options)]), async () => ( null));
|
|
713
|
+
if (anticipated !== null && anticipated.borderline) {
|
|
714
|
+
const pending = network();
|
|
715
|
+
pending.catch(() => void 0);
|
|
716
|
+
let timer;
|
|
717
|
+
const late = new Promise((resolve) => {
|
|
718
|
+
timer = setTimeout(() => resolve(null), _nullishCoalesce(anticipated.raceDeadlineMs, () => ( 250)));
|
|
719
|
+
});
|
|
720
|
+
const won = await Promise.race([pending.then((r) => r, () => null), late]);
|
|
721
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
722
|
+
if (won !== null) {
|
|
723
|
+
_optionalChain([hooks, 'access', _28 => _28.onAssembled, 'optionalCall', _29 => _29(scope, options, won, startedAt)]);
|
|
724
|
+
return won;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
613
727
|
if (anticipated !== null) {
|
|
614
|
-
_optionalChain([hooks, 'access',
|
|
615
|
-
_optionalChain([hooks, 'access',
|
|
616
|
-
return anticipated.response;
|
|
617
|
-
}
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
const response = _nullishCoalesce(_optionalChain([result, 'optionalAccess', _30 => _30["context"]]), () => ( {}));
|
|
621
|
-
_optionalChain([hooks, 'access', _31 => _31.onAssembled, 'optionalCall', _32 => _32(scope, options, response, startedAt)]);
|
|
728
|
+
_optionalChain([hooks, 'access', _30 => _30.onServedFromCache, 'optionalCall', _31 => _31(scope, options, anticipated)]);
|
|
729
|
+
_optionalChain([hooks, 'access', _32 => _32.onAssembled, 'optionalCall', _33 => _33(scope, options, anticipated.response, startedAt)]);
|
|
730
|
+
return applyResponseShape(anticipated.response, responseShape);
|
|
731
|
+
}
|
|
732
|
+
const response = await network();
|
|
733
|
+
_optionalChain([hooks, 'access', _34 => _34.onAssembled, 'optionalCall', _35 => _35(scope, options, response, startedAt)]);
|
|
622
734
|
return response;
|
|
623
735
|
}
|
|
624
736
|
|
|
@@ -738,6 +850,17 @@ function normalizeConversationContext(value) {
|
|
|
738
850
|
conversationId: pick(value["conversationId"], value.conversation_id, null)
|
|
739
851
|
};
|
|
740
852
|
}
|
|
853
|
+
function normalizeRetrievalHealth(raw) {
|
|
854
|
+
if (!raw || typeof raw !== "object") return null;
|
|
855
|
+
const r = raw;
|
|
856
|
+
const warnings = r["warnings"];
|
|
857
|
+
return {
|
|
858
|
+
degraded: r["degraded"] === void 0 ? true : Boolean(r["degraded"]),
|
|
859
|
+
level: _nullishCoalesce(r["level"], () => ( null)),
|
|
860
|
+
code: _nullishCoalesce(r["code"], () => ( null)),
|
|
861
|
+
warnings: Array.isArray(warnings) ? warnings.map((w) => String(w)) : []
|
|
862
|
+
};
|
|
863
|
+
}
|
|
741
864
|
function normalizeContextResponse(result = {}) {
|
|
742
865
|
const context = _nullishCoalesce(result["context"], () => ( result));
|
|
743
866
|
return {
|
|
@@ -754,7 +877,15 @@ function normalizeContextResponse(result = {}) {
|
|
|
754
877
|
)
|
|
755
878
|
),
|
|
756
879
|
metadata: normalizeContextMetadata(obj(context.metadata)),
|
|
757
|
-
|
|
880
|
+
// `retrieval` is a SIBLING of `context` in the body, so it is read off the
|
|
881
|
+
// envelope first and only then off a bare context. Reading it from
|
|
882
|
+
// `context` alone is how the Python SDK dropped it.
|
|
883
|
+
retrieval: normalizeRetrievalHealth(
|
|
884
|
+
pick(result["retrieval"], context["retrieval"], null)
|
|
885
|
+
),
|
|
886
|
+
rawResponse: pick(context["rawResponse"], context["raw_response"], {}),
|
|
887
|
+
// Only for a ranked fetch, so a by-type result has exactly the keys it had.
|
|
888
|
+
...Array.isArray(context.items) ? { items: context.items, excerpts: Array.isArray(context.excerpts) ? context.excerpts : [] } : {}
|
|
758
889
|
};
|
|
759
890
|
}
|
|
760
891
|
|
|
@@ -1002,7 +1133,7 @@ function createMemoriesInterface(transport, onForgotten) {
|
|
|
1002
1133
|
transport.checkCustomerId(_nullishCoalesce(o2["customer_id"], () => ( o2["customerId"])), "memories.forget");
|
|
1003
1134
|
const body = buildForgetBody(options);
|
|
1004
1135
|
const result = await transport.request("memories_forget", { body });
|
|
1005
|
-
const removed = !!_optionalChain([result, 'optionalAccess',
|
|
1136
|
+
const removed = !!_optionalChain([result, 'optionalAccess', _36 => _36.deleted_ids, 'optionalAccess', _37 => _37.length]) || _optionalChain([result, 'optionalAccess', _38 => _38.status]) === "deleted" || _optionalChain([result, 'optionalAccess', _39 => _39.status]) === "partial";
|
|
1006
1137
|
if (removed && onForgotten) {
|
|
1007
1138
|
try {
|
|
1008
1139
|
onForgotten({
|
|
@@ -1042,14 +1173,14 @@ function sleep2(ms, signal) {
|
|
|
1042
1173
|
if (ms <= 0) return Promise.resolve();
|
|
1043
1174
|
return new Promise((resolve, reject) => {
|
|
1044
1175
|
const timer = setTimeout(() => {
|
|
1045
|
-
_optionalChain([signal, 'optionalAccess',
|
|
1176
|
+
_optionalChain([signal, 'optionalAccess', _40 => _40.removeEventListener, 'call', _41 => _41("abort", onAbort)]);
|
|
1046
1177
|
resolve();
|
|
1047
1178
|
}, ms);
|
|
1048
1179
|
function onAbort() {
|
|
1049
1180
|
clearTimeout(timer);
|
|
1050
|
-
reject(_nullishCoalesce(_optionalChain([signal, 'optionalAccess',
|
|
1181
|
+
reject(_nullishCoalesce(_optionalChain([signal, 'optionalAccess', _42 => _42.reason]), () => ( new Error("Aborted"))));
|
|
1051
1182
|
}
|
|
1052
|
-
_optionalChain([signal, 'optionalAccess',
|
|
1183
|
+
_optionalChain([signal, 'optionalAccess', _43 => _43.addEventListener, 'call', _44 => _44("abort", onAbort, { once: true })]);
|
|
1053
1184
|
});
|
|
1054
1185
|
}
|
|
1055
1186
|
|
|
@@ -1069,6 +1200,27 @@ function validateInstanceId(instanceId) {
|
|
|
1069
1200
|
}
|
|
1070
1201
|
}
|
|
1071
1202
|
|
|
1203
|
+
// src/agent-model.ts
|
|
1204
|
+
var AGENT_MODEL_KEY = "agent_model";
|
|
1205
|
+
var AGENT_CONTEXT_WINDOW_KEY = "agent_context_window";
|
|
1206
|
+
function agentModelOf(options) {
|
|
1207
|
+
const o2 = _nullishCoalesce(options, () => ( {}));
|
|
1208
|
+
const window = _nullishCoalesce(o2["context_window"], () => ( o2["contextWindow"]));
|
|
1209
|
+
return {
|
|
1210
|
+
model: typeof o2["model"] === "string" ? o2["model"] : void 0,
|
|
1211
|
+
contextWindow: typeof window === "number" ? window : void 0
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
function withAgentModel(metadata, perCall, defaults, asStrings = false) {
|
|
1215
|
+
const model = perCall.model || defaults.model;
|
|
1216
|
+
const window = perCall.contextWindow || defaults.contextWindow;
|
|
1217
|
+
if (!model && !window) return metadata;
|
|
1218
|
+
const out = { ..._nullishCoalesce(metadata, () => ( {})) };
|
|
1219
|
+
if (model) out[AGENT_MODEL_KEY] = String(model);
|
|
1220
|
+
if (window) out[AGENT_CONTEXT_WINDOW_KEY] = asStrings ? String(Math.trunc(window)) : Math.trunc(window);
|
|
1221
|
+
return out;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1072
1224
|
// src/conversation/interface.ts
|
|
1073
1225
|
var COMPACTION_LEVELS = [
|
|
1074
1226
|
"low",
|
|
@@ -1197,10 +1349,50 @@ var CompactionSubscribers = class {
|
|
|
1197
1349
|
}
|
|
1198
1350
|
}
|
|
1199
1351
|
};
|
|
1352
|
+
function storedBatchRows(bodies, result) {
|
|
1353
|
+
const r = _nullishCoalesce(result, () => ( {}));
|
|
1354
|
+
const results = Array.isArray(r["results"]) ? r["results"] : [];
|
|
1355
|
+
const errors = Array.isArray(r["errors"]) ? r["errors"] : [];
|
|
1356
|
+
const failed = new Set(errors.map((e) => _optionalChain([e, 'optionalAccess', _45 => _45["index"]])));
|
|
1357
|
+
const stored = bodies.filter((_, index) => !failed.has(index));
|
|
1358
|
+
if (stored.length !== results.length) return [];
|
|
1359
|
+
const pairs = [];
|
|
1360
|
+
stored.forEach((body, i) => {
|
|
1361
|
+
const row = results[i];
|
|
1362
|
+
if (row && typeof row === "object" && row["message_id"]) pairs.push([body, row]);
|
|
1363
|
+
});
|
|
1364
|
+
return pairs;
|
|
1365
|
+
}
|
|
1200
1366
|
function createConversationNamespace(transport, subscribers = new CompactionSubscribers(), onWrite = () => {
|
|
1201
1367
|
}, onTurn = () => {
|
|
1202
1368
|
}, onFetched = () => {
|
|
1203
|
-
}, localShortTerm = { prompt: () => null, compacted: () => null }) {
|
|
1369
|
+
}, localShortTerm = { prompt: () => null, compacted: () => null }, agentModel = () => ({})) {
|
|
1370
|
+
const writesInFlight = /* @__PURE__ */ new Map();
|
|
1371
|
+
const withTurnModel = (body, options) => {
|
|
1372
|
+
const metadata = withAgentModel(
|
|
1373
|
+
body["metadata"],
|
|
1374
|
+
agentModelOf(options),
|
|
1375
|
+
agentModel()
|
|
1376
|
+
);
|
|
1377
|
+
return metadata === void 0 ? body : { ...body, metadata };
|
|
1378
|
+
};
|
|
1379
|
+
const writeStarted = (conversationId) => {
|
|
1380
|
+
writesInFlight.set(conversationId, (_nullishCoalesce(writesInFlight.get(conversationId), () => ( 0))) + 1);
|
|
1381
|
+
};
|
|
1382
|
+
const writeLanded = (conversationId) => {
|
|
1383
|
+
const remaining = (_nullishCoalesce(writesInFlight.get(conversationId), () => ( 0))) - 1;
|
|
1384
|
+
if (remaining > 0) writesInFlight.set(conversationId, remaining);
|
|
1385
|
+
else writesInFlight.delete(conversationId);
|
|
1386
|
+
};
|
|
1387
|
+
const confirmation = (result, conversationId) => {
|
|
1388
|
+
const r = _nullishCoalesce(result, () => ( {}));
|
|
1389
|
+
const count = r["conversation_message_count"];
|
|
1390
|
+
return {
|
|
1391
|
+
...typeof r["message_id"] === "string" ? { messageId: r["message_id"] } : {},
|
|
1392
|
+
serverMessageCount: typeof count === "number" ? count : null,
|
|
1393
|
+
inFlight: _nullishCoalesce(writesInFlight.get(conversationId), () => ( 0))
|
|
1394
|
+
};
|
|
1395
|
+
};
|
|
1204
1396
|
const convId = (v) => {
|
|
1205
1397
|
const id = typeof v === "string" ? v : _nullishCoalesce(v.conversation_id, () => ( v.conversationId));
|
|
1206
1398
|
if (!id) throw new (0, _chunkT372OL3Qcjs.InvalidInputError)("conversation_id is required");
|
|
@@ -1213,13 +1405,21 @@ function createConversationNamespace(transport, subscribers = new CompactionSubs
|
|
|
1213
1405
|
_nullishCoalesce(options["customer_id"], () => ( options["customerId"])),
|
|
1214
1406
|
"conversation.record_message"
|
|
1215
1407
|
);
|
|
1216
|
-
const body = buildRecordMessageBody(options);
|
|
1217
|
-
const
|
|
1408
|
+
const body = withTurnModel(buildRecordMessageBody(options), options);
|
|
1409
|
+
const conversationId = String(_nullishCoalesce(body["conversation_id"], () => ( "")));
|
|
1410
|
+
writeStarted(conversationId);
|
|
1411
|
+
let result;
|
|
1412
|
+
try {
|
|
1413
|
+
result = await transport.request("conversations_messages", { body });
|
|
1414
|
+
} finally {
|
|
1415
|
+
writeLanded(conversationId);
|
|
1416
|
+
}
|
|
1218
1417
|
onTurn({
|
|
1219
|
-
conversationId
|
|
1418
|
+
conversationId,
|
|
1220
1419
|
role: String(_nullishCoalesce(body["role"], () => ( "user"))),
|
|
1221
1420
|
content: String(_nullishCoalesce(body["content"], () => ( ""))),
|
|
1222
|
-
timestamp: body["timestamp"]
|
|
1421
|
+
timestamp: body["timestamp"],
|
|
1422
|
+
...confirmation(result, conversationId)
|
|
1223
1423
|
});
|
|
1224
1424
|
onWrite({
|
|
1225
1425
|
userId: body["user_id"],
|
|
@@ -1238,16 +1438,18 @@ function createConversationNamespace(transport, subscribers = new CompactionSubs
|
|
|
1238
1438
|
"conversation.record_messages_batch"
|
|
1239
1439
|
);
|
|
1240
1440
|
}
|
|
1241
|
-
const bodies = messages.map(buildRecordMessageBody);
|
|
1441
|
+
const bodies = messages.map((m) => withTurnModel(buildRecordMessageBody(m), m));
|
|
1242
1442
|
const result = await transport.request("conversations_messages_batch", {
|
|
1243
1443
|
body: { messages: bodies }
|
|
1244
1444
|
});
|
|
1245
|
-
for (const body of bodies) {
|
|
1445
|
+
for (const [body, row] of storedBatchRows(bodies, result)) {
|
|
1446
|
+
const conversationId = String(_nullishCoalesce(body["conversation_id"], () => ( "")));
|
|
1246
1447
|
onTurn({
|
|
1247
|
-
conversationId
|
|
1448
|
+
conversationId,
|
|
1248
1449
|
role: String(_nullishCoalesce(body["role"], () => ( "user"))),
|
|
1249
1450
|
content: String(_nullishCoalesce(body["content"], () => ( ""))),
|
|
1250
|
-
timestamp: body["timestamp"]
|
|
1451
|
+
timestamp: body["timestamp"],
|
|
1452
|
+
...confirmation(row, conversationId)
|
|
1251
1453
|
});
|
|
1252
1454
|
}
|
|
1253
1455
|
for (const body of bodies) {
|
|
@@ -1282,13 +1484,24 @@ function createConversationNamespace(transport, subscribers = new CompactionSubs
|
|
|
1282
1484
|
},
|
|
1283
1485
|
get_context_for_prompt: async (options = {}) => {
|
|
1284
1486
|
const id = convId(options);
|
|
1487
|
+
const search = (_nullishCoalesce(_nullishCoalesce(options.search_history, () => ( options.searchHistory)), () => ( true))) && localShortTerm.historyExcerpts;
|
|
1488
|
+
const withHistory = async (response2) => {
|
|
1489
|
+
if (!search) return response2;
|
|
1490
|
+
try {
|
|
1491
|
+
return await localShortTerm.historyExcerpts(id, response2, options.query);
|
|
1492
|
+
} catch (e6) {
|
|
1493
|
+
return response2;
|
|
1494
|
+
}
|
|
1495
|
+
};
|
|
1285
1496
|
const local = localShortTerm.prompt(id, _nullishCoalesce(options.style, () => ( "structured")));
|
|
1286
|
-
if (local !== null) return local;
|
|
1497
|
+
if (local !== null) return withHistory(local);
|
|
1287
1498
|
const result = await transport.request("context_for_prompt", {
|
|
1288
1499
|
pathParams: { conversation_id: id },
|
|
1289
1500
|
query: { style: _nullishCoalesce(options.style, () => ( "structured")) }
|
|
1290
1501
|
});
|
|
1291
|
-
|
|
1502
|
+
const response = _nullishCoalesce(_nullishCoalesce(_optionalChain([result, 'optionalAccess', _46 => _46["context_for_prompt"]]), () => ( result)), () => ( {}));
|
|
1503
|
+
_optionalChain([localShortTerm, 'access', _47 => _47.reseed, 'optionalCall', _48 => _48(id, response)]);
|
|
1504
|
+
return withHistory(response);
|
|
1292
1505
|
},
|
|
1293
1506
|
async compact(options) {
|
|
1294
1507
|
return transport.request("conversations_compact", { body: buildCompactBody(options) });
|
|
@@ -1463,32 +1676,40 @@ function jsonOrText(value) {
|
|
|
1463
1676
|
(_k, v) => typeof v === "bigint" ? String(v) : v
|
|
1464
1677
|
);
|
|
1465
1678
|
return out === void 0 ? String(value) : out;
|
|
1466
|
-
} catch (
|
|
1679
|
+
} catch (e7) {
|
|
1467
1680
|
try {
|
|
1468
1681
|
return String(value);
|
|
1469
|
-
} catch (
|
|
1682
|
+
} catch (e8) {
|
|
1470
1683
|
return "";
|
|
1471
1684
|
}
|
|
1472
1685
|
}
|
|
1473
1686
|
}
|
|
1474
|
-
function createInstanceNamespace(credentials, cache, onTurn) {
|
|
1687
|
+
function createInstanceNamespace(credentials, cache, onTurn, agentModel = () => ({}), onToolResult) {
|
|
1475
1688
|
let client = null;
|
|
1476
1689
|
const openSessions = /* @__PURE__ */ new Map();
|
|
1477
1690
|
let dispatchCompaction = null;
|
|
1478
1691
|
let applyCompaction = null;
|
|
1692
|
+
let onListen = null;
|
|
1693
|
+
let onConversationState = null;
|
|
1479
1694
|
const internals = {
|
|
1480
1695
|
onCompactionUpdate(conversationId, bundle) {
|
|
1481
|
-
_optionalChain([applyCompaction, 'optionalCall',
|
|
1482
|
-
_optionalChain([dispatchCompaction, 'optionalCall',
|
|
1696
|
+
_optionalChain([applyCompaction, 'optionalCall', _49 => _49(bundle)]);
|
|
1697
|
+
_optionalChain([dispatchCompaction, 'optionalCall', _50 => _50(conversationId, bundle)]);
|
|
1483
1698
|
},
|
|
1484
1699
|
setCompactionApplier(apply) {
|
|
1485
1700
|
applyCompaction = apply;
|
|
1486
1701
|
},
|
|
1702
|
+
setOnListen(handle) {
|
|
1703
|
+
onListen = handle;
|
|
1704
|
+
},
|
|
1705
|
+
setConversationStateHandler(handle) {
|
|
1706
|
+
onConversationState = handle;
|
|
1707
|
+
},
|
|
1487
1708
|
sendContextUsed(event) {
|
|
1488
|
-
_optionalChain([client, 'optionalAccess',
|
|
1709
|
+
_optionalChain([client, 'optionalAccess', _51 => _51.sendContextUsed, 'call', _52 => _52(event)]);
|
|
1489
1710
|
},
|
|
1490
1711
|
sendContextAssembled(event) {
|
|
1491
|
-
_optionalChain([client, 'optionalAccess',
|
|
1712
|
+
_optionalChain([client, 'optionalAccess', _53 => _53.sendContextAssembled, 'call', _54 => _54(event)]);
|
|
1492
1713
|
},
|
|
1493
1714
|
setCompactionDispatcher(dispatch) {
|
|
1494
1715
|
dispatchCompaction = dispatch;
|
|
@@ -1510,7 +1731,7 @@ function createInstanceNamespace(credentials, cache, onTurn) {
|
|
|
1510
1731
|
...customerId ? { customer_id: customerId } : {}
|
|
1511
1732
|
});
|
|
1512
1733
|
openSessions.set(conversationId, sessionId);
|
|
1513
|
-
} catch (
|
|
1734
|
+
} catch (e9) {
|
|
1514
1735
|
}
|
|
1515
1736
|
}
|
|
1516
1737
|
const namespace = {
|
|
@@ -1518,7 +1739,11 @@ function createInstanceNamespace(credentials, cache, onTurn) {
|
|
|
1518
1739
|
if (client !== null) {
|
|
1519
1740
|
throw new (0, _chunkT372OL3Qcjs.ListeningAlreadyActiveError)("Listening is already active on this instance");
|
|
1520
1741
|
}
|
|
1521
|
-
|
|
1742
|
+
try {
|
|
1743
|
+
_optionalChain([onListen, 'optionalCall', _55 => _55()]);
|
|
1744
|
+
} catch (e10) {
|
|
1745
|
+
}
|
|
1746
|
+
const { GrpcStreamClient } = await Promise.resolve().then(() => _interopRequireWildcard(require("./stream-client-L6OQPZN7.cjs")));
|
|
1522
1747
|
const onContext = _nullishCoalesce(options.on_context, () => ( options.onContext));
|
|
1523
1748
|
const onDisconnect = _nullishCoalesce(options.on_disconnect, () => ( options.onDisconnect));
|
|
1524
1749
|
const onReconnect = _nullishCoalesce(options.on_reconnect, () => ( options.onReconnect));
|
|
@@ -1532,15 +1757,18 @@ function createInstanceNamespace(credentials, cache, onTurn) {
|
|
|
1532
1757
|
onCompactionUpdate: (conversationId, bundle) => {
|
|
1533
1758
|
internals.onCompactionUpdate(conversationId, bundle);
|
|
1534
1759
|
},
|
|
1760
|
+
onConversationState: (conversationId, messageCount) => {
|
|
1761
|
+
_optionalChain([onConversationState, 'optionalCall', _56 => _56(conversationId, messageCount)]);
|
|
1762
|
+
},
|
|
1535
1763
|
onStateChange: (state) => {
|
|
1536
1764
|
if (state !== "connected") openSessions.clear();
|
|
1537
1765
|
if (state === "reconnecting") {
|
|
1538
1766
|
reconnectAttempts += 1;
|
|
1539
|
-
_optionalChain([onReconnect, 'optionalCall',
|
|
1767
|
+
_optionalChain([onReconnect, 'optionalCall', _57 => _57(reconnectAttempts)]);
|
|
1540
1768
|
} else if (state === "disconnected") {
|
|
1541
|
-
const stopped = _nullishCoalesce(_optionalChain([stream, 'optionalAccess',
|
|
1769
|
+
const stopped = _nullishCoalesce(_optionalChain([stream, 'optionalAccess', _58 => _58.lastError]), () => ( null));
|
|
1542
1770
|
const reason = stopped === null ? "stream disconnected" : `credit_stop:${_nullishCoalesce(stopped.reason, () => ( "unknown"))}`;
|
|
1543
|
-
_optionalChain([onDisconnect, 'optionalCall',
|
|
1771
|
+
_optionalChain([onDisconnect, 'optionalCall', _59 => _59(reason)]);
|
|
1544
1772
|
}
|
|
1545
1773
|
}
|
|
1546
1774
|
});
|
|
@@ -1550,7 +1778,7 @@ function createInstanceNamespace(credentials, cache, onTurn) {
|
|
|
1550
1778
|
} catch (error) {
|
|
1551
1779
|
if (error instanceof _chunkT372OL3Qcjs.SynapError) throw error;
|
|
1552
1780
|
throw new (0, _chunkT372OL3Qcjs.SynapError)(
|
|
1553
|
-
`Could not open the Synap anticipation stream: ${_nullishCoalesce(_optionalChain([error, 'optionalAccess',
|
|
1781
|
+
`Could not open the Synap anticipation stream: ${_nullishCoalesce(_optionalChain([error, 'optionalAccess', _60 => _60.message]), () => ( String(error)))}`,
|
|
1554
1782
|
{ cause: error }
|
|
1555
1783
|
);
|
|
1556
1784
|
}
|
|
@@ -1575,7 +1803,7 @@ function createInstanceNamespace(credentials, cache, onTurn) {
|
|
|
1575
1803
|
session_id: sessionId,
|
|
1576
1804
|
conversation_id: conversationId
|
|
1577
1805
|
});
|
|
1578
|
-
} catch (
|
|
1806
|
+
} catch (e11) {
|
|
1579
1807
|
}
|
|
1580
1808
|
},
|
|
1581
1809
|
async send_message(options) {
|
|
@@ -1596,7 +1824,7 @@ function createInstanceNamespace(credentials, cache, onTurn) {
|
|
|
1596
1824
|
_nullishCoalesce(_nullishCoalesce(options.customer_id, () => ( options.customerId)), () => ( ""))
|
|
1597
1825
|
);
|
|
1598
1826
|
if (eventType === "user_message" || eventType === "assistant_message") {
|
|
1599
|
-
_optionalChain([onTurn, 'optionalCall',
|
|
1827
|
+
_optionalChain([onTurn, 'optionalCall', _61 => _61({
|
|
1600
1828
|
conversationId,
|
|
1601
1829
|
role: _nullishCoalesce(options.role, () => ( "user")),
|
|
1602
1830
|
content: options.content
|
|
@@ -1610,7 +1838,7 @@ function createInstanceNamespace(credentials, cache, onTurn) {
|
|
|
1610
1838
|
user_id: _nullishCoalesce(_nullishCoalesce(options.user_id, () => ( options.userId)), () => ( "")),
|
|
1611
1839
|
customer_id: _nullishCoalesce(_nullishCoalesce(options.customer_id, () => ( options.customerId)), () => ( "")),
|
|
1612
1840
|
session_id: _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(options.session_id, () => ( options.sessionId)), () => ( openSessions.get(conversationId))), () => ( "")),
|
|
1613
|
-
metadata: _nullishCoalesce(options.metadata, () => ( {})),
|
|
1841
|
+
metadata: _nullishCoalesce(withAgentModel(options.metadata, agentModelOf(options), agentModel(), true), () => ( {})),
|
|
1614
1842
|
timestamp_ms: Date.now(),
|
|
1615
1843
|
tool_name: _nullishCoalesce(_nullishCoalesce(options.tool_name, () => ( options.toolName)), () => ( "")),
|
|
1616
1844
|
// Python serialises tool_args with json.dumps into tool_args_json.
|
|
@@ -1640,6 +1868,10 @@ function createInstanceNamespace(credentials, cache, onTurn) {
|
|
|
1640
1868
|
});
|
|
1641
1869
|
},
|
|
1642
1870
|
async record_tool_result(options) {
|
|
1871
|
+
const conversationId = _nullishCoalesce(_nullishCoalesce(options.conversation_id, () => ( options.conversationId)), () => ( ""));
|
|
1872
|
+
if (conversationId) {
|
|
1873
|
+
_optionalChain([onToolResult, 'optionalCall', _62 => _62({ conversationId, result: options.result, toolName: _nullishCoalesce(_nullishCoalesce(options.tool_name, () => ( options.toolName)), () => ( "")) })]);
|
|
1874
|
+
}
|
|
1643
1875
|
await namespace.send_message({
|
|
1644
1876
|
content: "",
|
|
1645
1877
|
role: "tool",
|
|
@@ -1690,7 +1922,7 @@ function createInstanceNamespace(credentials, cache, onTurn) {
|
|
|
1690
1922
|
}
|
|
1691
1923
|
|
|
1692
1924
|
// src/version.ts
|
|
1693
|
-
var SDK_VERSION = "0.5.
|
|
1925
|
+
var SDK_VERSION = "0.5.9";
|
|
1694
1926
|
|
|
1695
1927
|
// src/registry.ts
|
|
1696
1928
|
var instances = /* @__PURE__ */ new Map();
|
|
@@ -1731,6 +1963,34 @@ function unregisterIfOwner(key, client) {
|
|
|
1731
1963
|
// src/cache/short-term-store.ts
|
|
1732
1964
|
var DEFAULT_MAX_CONVERSATIONS = 100;
|
|
1733
1965
|
var DEFAULT_MAX_AGE_MS = 12 * 60 * 60 * 1e3;
|
|
1966
|
+
var CONTEXT_BLOCK_PREFIX = "## Conversation so far (compacted";
|
|
1967
|
+
function contextBlockOf(cc) {
|
|
1968
|
+
const block = cc["context_block"];
|
|
1969
|
+
if (typeof block === "string" && block) return block;
|
|
1970
|
+
const summary = cc["summary"];
|
|
1971
|
+
if (typeof summary === "string" && summary.startsWith(CONTEXT_BLOCK_PREFIX)) return summary;
|
|
1972
|
+
return null;
|
|
1973
|
+
}
|
|
1974
|
+
function localMessageCount(entry) {
|
|
1975
|
+
return entry.compactedMessageCount + entry.recentTurns.length;
|
|
1976
|
+
}
|
|
1977
|
+
function isComplete(entry) {
|
|
1978
|
+
return entry.participant && entry.synced && !entry.shared && entry.serverMessageCount !== null && entry.serverMessageCount <= localMessageCount(entry);
|
|
1979
|
+
}
|
|
1980
|
+
function heldIn(turn, turns) {
|
|
1981
|
+
return turns.some(
|
|
1982
|
+
(held) => turn.message_id && held.message_id ? held.message_id === turn.message_id : held.role === turn.role && held.content === turn.content
|
|
1983
|
+
);
|
|
1984
|
+
}
|
|
1985
|
+
function turnsAfter(localTurns, serverTurns) {
|
|
1986
|
+
const newer = [];
|
|
1987
|
+
for (let i = localTurns.length - 1; i >= 0; i -= 1) {
|
|
1988
|
+
const turn = localTurns[i];
|
|
1989
|
+
if (heldIn(turn, serverTurns)) break;
|
|
1990
|
+
newer.unshift(turn);
|
|
1991
|
+
}
|
|
1992
|
+
return newer;
|
|
1993
|
+
}
|
|
1734
1994
|
function parseIso(value) {
|
|
1735
1995
|
if (value === null || value === void 0 || value === "") return null;
|
|
1736
1996
|
if (value instanceof Date) return value.getTime();
|
|
@@ -1750,11 +2010,23 @@ var ShortTermStore = class {
|
|
|
1750
2010
|
#maxConversations;
|
|
1751
2011
|
#maxAgeMs;
|
|
1752
2012
|
#now;
|
|
2013
|
+
/**
|
|
2014
|
+
* Every turn appended here is also kept in the archive (a TurnStore), which
|
|
2015
|
+
* a compaction does not prune: the turns it covers stay searchable locally
|
|
2016
|
+
* (history-search.ts). Python: `ShortTermContextStore.attach_archive`.
|
|
2017
|
+
*/
|
|
2018
|
+
#archive = null;
|
|
1753
2019
|
constructor(options = {}) {
|
|
1754
2020
|
this.#maxConversations = _nullishCoalesce(options.maxConversations, () => ( DEFAULT_MAX_CONVERSATIONS));
|
|
1755
2021
|
this.#maxAgeMs = _nullishCoalesce(options.maxAgeMs, () => ( DEFAULT_MAX_AGE_MS));
|
|
1756
2022
|
this.#now = _nullishCoalesce(options.now, () => ( (() => Date.now())));
|
|
1757
2023
|
}
|
|
2024
|
+
attachArchive(archive) {
|
|
2025
|
+
this.#archive = archive;
|
|
2026
|
+
}
|
|
2027
|
+
get archive() {
|
|
2028
|
+
return this.#archive;
|
|
2029
|
+
}
|
|
1758
2030
|
/** The entry, or null. Age-evicts on read, as Python does. */
|
|
1759
2031
|
get(conversationId) {
|
|
1760
2032
|
if (!conversationId) return null;
|
|
@@ -1780,23 +2052,88 @@ var ShortTermStore = class {
|
|
|
1780
2052
|
* exists yet (the first turn, before any compaction has arrived) a fresh one
|
|
1781
2053
|
* is created with an empty summary; the next `compaction_update` fills the
|
|
1782
2054
|
* summary fields in and prunes the turns it covers.
|
|
2055
|
+
*
|
|
2056
|
+
* `confirmation` is what the write learned from the server. See
|
|
2057
|
+
* `TurnConfirmation` and `noteServerCount`.
|
|
1783
2058
|
*/
|
|
1784
|
-
appendTurn(conversationId, role, content, timestamp) {
|
|
2059
|
+
appendTurn(conversationId, role, content, timestamp, confirmation = {}) {
|
|
1785
2060
|
if (!conversationId) return;
|
|
1786
2061
|
const stamp = _nullishCoalesce(timestamp, () => ( new Date(this.#now()).toISOString()));
|
|
2062
|
+
if (this.#archive !== null) {
|
|
2063
|
+
try {
|
|
2064
|
+
this.#archive.add(conversationId, role, content, stamp, { messageId: _nullishCoalesce(confirmation.messageId, () => ( null)) });
|
|
2065
|
+
} catch (e12) {
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
1787
2068
|
const entry = _nullishCoalesce(this.#entries.get(conversationId), () => ( this.#blank(conversationId)));
|
|
1788
|
-
|
|
2069
|
+
const messageId = confirmation.messageId;
|
|
2070
|
+
const alreadyHeld = Boolean(messageId) && entry.recentTurns.some((t) => t.message_id === messageId);
|
|
2071
|
+
if (!alreadyHeld) {
|
|
2072
|
+
const turn = { role, content, timestamp: stamp };
|
|
2073
|
+
if (messageId) turn.message_id = messageId;
|
|
2074
|
+
entry.recentTurns.push(turn);
|
|
2075
|
+
}
|
|
2076
|
+
const count = confirmation.serverMessageCount;
|
|
2077
|
+
if (count !== null && count !== void 0) {
|
|
2078
|
+
this.#noteCount(entry, Number(count), _nullishCoalesce(confirmation.inFlight, () => ( 0)));
|
|
2079
|
+
}
|
|
1789
2080
|
entry.lastActivityAt = _nullishCoalesce(parseIso(stamp), () => ( this.#now()));
|
|
1790
2081
|
this.#touch(conversationId, entry);
|
|
1791
2082
|
this.#evict();
|
|
1792
2083
|
}
|
|
2084
|
+
/**
|
|
2085
|
+
* Record the server's message count for a conversation.
|
|
2086
|
+
*
|
|
2087
|
+
* The streamed write path's half of `appendTurn`'s confirmation: a streamed
|
|
2088
|
+
* turn is appended when it is sent, and the count arrives later, once the
|
|
2089
|
+
* server has written it. A count for a conversation this process holds
|
|
2090
|
+
* nothing for is ignored.
|
|
2091
|
+
*/
|
|
2092
|
+
noteServerCount(conversationId, count) {
|
|
2093
|
+
if (!conversationId) return;
|
|
2094
|
+
const entry = this.#entries.get(conversationId);
|
|
2095
|
+
if (entry !== void 0) this.#noteCount(entry, Number(count), 0);
|
|
2096
|
+
}
|
|
2097
|
+
/**
|
|
2098
|
+
* Compare the server's count with what the entry holds.
|
|
2099
|
+
*
|
|
2100
|
+
* The count is taken after one of this process's own writes, so it proves
|
|
2101
|
+
* the process takes part in the conversation.
|
|
2102
|
+
*
|
|
2103
|
+
* Server ahead of an entry that was in sync: something else wrote, and the
|
|
2104
|
+
* entry is marked shared for good. Server ahead of an entry that was never
|
|
2105
|
+
* in sync: this process joined late (a restart, an eviction), and `reseed`
|
|
2106
|
+
* will fix it. `inFlight` covers this process's own writes that the server
|
|
2107
|
+
* has counted and the entry has not appended yet, so two concurrent writes
|
|
2108
|
+
* do not look like a second writer.
|
|
2109
|
+
*/
|
|
2110
|
+
#noteCount(entry, count, inFlight) {
|
|
2111
|
+
entry.participant = true;
|
|
2112
|
+
if (count > localMessageCount(entry) + inFlight) {
|
|
2113
|
+
if (entry.synced) entry.shared = true;
|
|
2114
|
+
} else if (entry.serverMessageCount === null) {
|
|
2115
|
+
entry.synced = true;
|
|
2116
|
+
}
|
|
2117
|
+
entry.serverMessageCount = Math.max(_nullishCoalesce(entry.serverMessageCount, () => ( 0)), count);
|
|
2118
|
+
}
|
|
1793
2119
|
/**
|
|
1794
2120
|
* Apply a `compaction_update` bundle.
|
|
1795
2121
|
*
|
|
1796
2122
|
* Replaces the summary fields from the bundle's `conversation_context` and
|
|
1797
|
-
*
|
|
1798
|
-
*
|
|
1799
|
-
*
|
|
2123
|
+
* drops the buffered turns the new summary covers.
|
|
2124
|
+
*
|
|
2125
|
+
* Which turns those are is decided by count, not by clock. The bundle says
|
|
2126
|
+
* how many messages the summary covers and how many the conversation held
|
|
2127
|
+
* when the bundle was built, so the last `total - compacted` of its
|
|
2128
|
+
* `recent_turns` are exactly the uncovered messages. Turns this process
|
|
2129
|
+
* appended after the server took that count are kept behind them. Timestamps
|
|
2130
|
+
* cannot do this job: the REST write returns the time of the response and
|
|
2131
|
+
* not of the stored row, a caller may supply its own message time, and a
|
|
2132
|
+
* streamed turn is stamped when a background write runs.
|
|
2133
|
+
*
|
|
2134
|
+
* A bundle from a server that sends no counts falls back to the older
|
|
2135
|
+
* timestamp prune, and the entry is left out of sync so it is never used to
|
|
2136
|
+
* answer on its own.
|
|
1800
2137
|
*/
|
|
1801
2138
|
applyCompaction(bundle) {
|
|
1802
2139
|
if (typeof bundle !== "object" || bundle === null) return;
|
|
@@ -1806,22 +2143,84 @@ var ShortTermStore = class {
|
|
|
1806
2143
|
);
|
|
1807
2144
|
if (!conversationId) return;
|
|
1808
2145
|
const endTs = parseIso(_nullishCoalesce(cc["end_timestamp"], () => ( cc["compacted_at"])));
|
|
2146
|
+
const compactedAt = parseIso(cc["compacted_at"]);
|
|
2147
|
+
const compactedCount = Number(_nullishCoalesce(cc["compacted_message_count"], () => ( 0))) || 0;
|
|
2148
|
+
const totalCount = Number(_nullishCoalesce(cc["total_message_count"], () => ( 0))) || 0;
|
|
1809
2149
|
const entry = _nullishCoalesce(this.#entries.get(conversationId), () => ( this.#blank(conversationId)));
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
2150
|
+
const heldAt = parseIso(entry.compactedAt);
|
|
2151
|
+
if (compactedAt !== null && heldAt !== null && compactedAt < heldAt) return;
|
|
2152
|
+
const block = contextBlockOf(cc);
|
|
2153
|
+
if (block) {
|
|
2154
|
+
entry.contextBlock = block;
|
|
2155
|
+
entry.summary = cc["summary"] || block;
|
|
2156
|
+
entry.factualParagraph = null;
|
|
2157
|
+
entry.conversationalParagraph = null;
|
|
2158
|
+
} else {
|
|
2159
|
+
entry.summary = cc["summary"] || entry.summary;
|
|
2160
|
+
entry.factualParagraph = cc["factual_paragraph"] || entry.factualParagraph;
|
|
2161
|
+
entry.conversationalParagraph = cc["conversational_paragraph"] || entry.conversationalParagraph;
|
|
2162
|
+
}
|
|
1813
2163
|
entry.currentState = { ..._nullishCoalesce(cc["current_state"], () => ( {})) };
|
|
1814
2164
|
entry.keyExtractions = { ..._nullishCoalesce(cc["key_extractions"], () => ( {})) };
|
|
1815
2165
|
entry.compactionId = cc["compaction_id"] || entry.compactionId;
|
|
1816
2166
|
entry.compactedAt = cc["compacted_at"] || entry.compactedAt;
|
|
1817
2167
|
entry.endTimestamp = cc["end_timestamp"] || entry.endTimestamp;
|
|
1818
|
-
if (
|
|
1819
|
-
|
|
2168
|
+
if (compactedCount > 0 && compactedCount <= totalCount) {
|
|
2169
|
+
const uncovered = totalCount - compactedCount;
|
|
2170
|
+
const serverTurns = Array.isArray(cc["recent_turns"]) ? cc["recent_turns"] : [];
|
|
2171
|
+
const tail = uncovered > 0 ? serverTurns.slice(-uncovered).map((t) => ({ ...t })) : [];
|
|
2172
|
+
const ahead = localMessageCount(entry) - totalCount;
|
|
2173
|
+
const newer = entry.synced && ahead > 0 ? entry.recentTurns.slice(-ahead).filter((t) => !heldIn(t, tail)) : [];
|
|
2174
|
+
entry.recentTurns = [...tail, ...newer];
|
|
2175
|
+
entry.compactedMessageCount = compactedCount;
|
|
2176
|
+
entry.serverMessageCount = Math.max(_nullishCoalesce(entry.serverMessageCount, () => ( 0)), totalCount);
|
|
2177
|
+
entry.synced = tail.length === uncovered;
|
|
2178
|
+
} else {
|
|
2179
|
+
if (endTs !== null && entry.recentTurns.length > 0) {
|
|
2180
|
+
entry.recentTurns = entry.recentTurns.filter((t) => isAfter(t.timestamp, endTs));
|
|
2181
|
+
}
|
|
2182
|
+
entry.synced = false;
|
|
1820
2183
|
}
|
|
1821
2184
|
entry.lastActivityAt = this.#now();
|
|
1822
2185
|
this.#touch(conversationId, entry);
|
|
1823
2186
|
this.#evict();
|
|
1824
2187
|
}
|
|
2188
|
+
/**
|
|
2189
|
+
* Bring an entry back in step from a `/context-for-prompt` response.
|
|
2190
|
+
*
|
|
2191
|
+
* Called after the server was asked because the entry was not complete. The
|
|
2192
|
+
* response lists every message the server's summary does not cover, which is
|
|
2193
|
+
* what `recentTurns` is meant to hold.
|
|
2194
|
+
*
|
|
2195
|
+
* Only an entry that already exists is reseeded. Creating one here would let
|
|
2196
|
+
* a process that never writes to the conversation answer from a snapshot it
|
|
2197
|
+
* has no way to refresh.
|
|
2198
|
+
*
|
|
2199
|
+
* If the server's summary is not the one cached here, the entry cannot
|
|
2200
|
+
* render it, so it stays out of sync until the next bundle brings the
|
|
2201
|
+
* summary itself.
|
|
2202
|
+
*
|
|
2203
|
+
* Turns held locally and absent from the response are kept when they come
|
|
2204
|
+
* after everything the response has: they were written or sent after the
|
|
2205
|
+
* server read its messages.
|
|
2206
|
+
*/
|
|
2207
|
+
reseed(conversationId, state) {
|
|
2208
|
+
if (!conversationId) return;
|
|
2209
|
+
const entry = this.#entries.get(conversationId);
|
|
2210
|
+
if (entry === void 0 || entry.shared) return;
|
|
2211
|
+
entry.serverMessageCount = Math.max(
|
|
2212
|
+
_nullishCoalesce(entry.serverMessageCount, () => ( 0)),
|
|
2213
|
+
Number(state.totalMessageCount) || 0
|
|
2214
|
+
);
|
|
2215
|
+
if ((state.compactionId || null) !== entry.compactionId) {
|
|
2216
|
+
entry.synced = false;
|
|
2217
|
+
return;
|
|
2218
|
+
}
|
|
2219
|
+
const serverTurns = state.recentMessages.map((m) => ({ ...m }));
|
|
2220
|
+
entry.recentTurns = [...serverTurns, ...turnsAfter(entry.recentTurns, serverTurns)];
|
|
2221
|
+
entry.compactedMessageCount = Number(state.compactedMessageCount) || 0;
|
|
2222
|
+
entry.synced = true;
|
|
2223
|
+
}
|
|
1825
2224
|
invalidate(conversationId) {
|
|
1826
2225
|
this.#entries.delete(conversationId);
|
|
1827
2226
|
}
|
|
@@ -1832,6 +2231,7 @@ var ShortTermStore = class {
|
|
|
1832
2231
|
return {
|
|
1833
2232
|
conversationId,
|
|
1834
2233
|
summary: null,
|
|
2234
|
+
contextBlock: null,
|
|
1835
2235
|
factualParagraph: null,
|
|
1836
2236
|
conversationalParagraph: null,
|
|
1837
2237
|
currentState: {},
|
|
@@ -1840,7 +2240,12 @@ var ShortTermStore = class {
|
|
|
1840
2240
|
compactedAt: null,
|
|
1841
2241
|
endTimestamp: null,
|
|
1842
2242
|
recentTurns: [],
|
|
1843
|
-
lastActivityAt: this.#now()
|
|
2243
|
+
lastActivityAt: this.#now(),
|
|
2244
|
+
compactedMessageCount: 0,
|
|
2245
|
+
serverMessageCount: null,
|
|
2246
|
+
participant: false,
|
|
2247
|
+
synced: false,
|
|
2248
|
+
shared: false
|
|
1844
2249
|
};
|
|
1845
2250
|
}
|
|
1846
2251
|
/** Re-insert so this key becomes the most recently used. */
|
|
@@ -1857,6 +2262,520 @@ var ShortTermStore = class {
|
|
|
1857
2262
|
}
|
|
1858
2263
|
};
|
|
1859
2264
|
|
|
2265
|
+
// src/cache/turn-store.ts
|
|
2266
|
+
var SWEEP_EVERY_WRITES = 50;
|
|
2267
|
+
function bytesOf(text) {
|
|
2268
|
+
return new TextEncoder().encode(text).length;
|
|
2269
|
+
}
|
|
2270
|
+
var TurnStore = (_class3 = class {
|
|
2271
|
+
|
|
2272
|
+
__init4() {this.onDisk = false}
|
|
2273
|
+
#now;
|
|
2274
|
+
#seq = 0;
|
|
2275
|
+
#writes = 0;
|
|
2276
|
+
#conversations = /* @__PURE__ */ new Map();
|
|
2277
|
+
#vectors = /* @__PURE__ */ new Map();
|
|
2278
|
+
constructor(options = {}) {;_class3.prototype.__init4.call(this);
|
|
2279
|
+
this.limits = _nullishCoalesce(options.limits, () => ( { ..._chunkICUFS3B5cjs.HISTORY_SEARCH.store_limits }));
|
|
2280
|
+
this.#now = _nullishCoalesce(options.now, () => ( (() => Date.now() / 1e3)));
|
|
2281
|
+
}
|
|
2282
|
+
add(conversationId, role, content, timestamp, options = {}) {
|
|
2283
|
+
this.addMany(conversationId, [
|
|
2284
|
+
{ role, content, timestamp: _nullishCoalesce(timestamp, () => ( "")), message_id: _nullishCoalesce(options.messageId, () => ( null)), position: _nullishCoalesce(options.position, () => ( null)) }
|
|
2285
|
+
]);
|
|
2286
|
+
}
|
|
2287
|
+
/**
|
|
2288
|
+
* Insert turns not held yet; returns how many were new. A turn held without
|
|
2289
|
+
* an id or position (a streamed write) gets them when the same role and
|
|
2290
|
+
* text come back from the server.
|
|
2291
|
+
*/
|
|
2292
|
+
addMany(conversationId, turns) {
|
|
2293
|
+
if (!conversationId) return 0;
|
|
2294
|
+
const conv = _nullishCoalesce(this.#conversations.get(conversationId), () => ( { lastActivity: 0, turns: [] }));
|
|
2295
|
+
let added = 0;
|
|
2296
|
+
for (const turn of turns) {
|
|
2297
|
+
const role = String(turn.role || "user");
|
|
2298
|
+
const content = String(_nullishCoalesce(turn.content, () => ( "")));
|
|
2299
|
+
if (!content) continue;
|
|
2300
|
+
const messageId = turn.message_id ? String(turn.message_id) : null;
|
|
2301
|
+
const raw = turn.position;
|
|
2302
|
+
const position = typeof raw === "number" && Number.isInteger(raw) ? raw : /^\d+$/.test(String(_nullishCoalesce(raw, () => ( "")))) ? Number(raw) : null;
|
|
2303
|
+
const ts = turn.timestamp instanceof Date ? turn.timestamp.toISOString() : String(_nullishCoalesce(turn.timestamp, () => ( "")));
|
|
2304
|
+
if (messageId !== null) {
|
|
2305
|
+
const held = conv.turns.find((t) => t.message_id === messageId);
|
|
2306
|
+
if (held !== void 0) {
|
|
2307
|
+
if (position !== null) held.position = position;
|
|
2308
|
+
continue;
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
const same = conv.turns.find(
|
|
2312
|
+
(t) => t.role === role && t.content === content && (t.message_id === null || t.position === null)
|
|
2313
|
+
);
|
|
2314
|
+
if (same !== void 0) {
|
|
2315
|
+
same.message_id = _nullishCoalesce(same.message_id, () => ( messageId));
|
|
2316
|
+
same.position = _nullishCoalesce(position, () => ( same.position));
|
|
2317
|
+
continue;
|
|
2318
|
+
}
|
|
2319
|
+
conv.turns.push({ seq: ++this.#seq, role, content, timestamp: ts, message_id: messageId, position });
|
|
2320
|
+
added += 1;
|
|
2321
|
+
}
|
|
2322
|
+
conv.lastActivity = this.#now();
|
|
2323
|
+
this.#conversations.set(conversationId, conv);
|
|
2324
|
+
this.#trim(conv);
|
|
2325
|
+
this.#writes += 1;
|
|
2326
|
+
if (this.#writes % SWEEP_EVERY_WRITES === 0) this.sweep();
|
|
2327
|
+
return added;
|
|
2328
|
+
}
|
|
2329
|
+
#trim(conv) {
|
|
2330
|
+
const limits = this.limits;
|
|
2331
|
+
let size = conv.turns.reduce((n2, t) => n2 + bytesOf(t.content), 0);
|
|
2332
|
+
while (conv.turns.length > limits.max_turns_per_conversation || size > limits.max_bytes_per_conversation) {
|
|
2333
|
+
const excess = Math.max(conv.turns.length - limits.max_turns_per_conversation, 1);
|
|
2334
|
+
const order = [...conv.turns].sort(
|
|
2335
|
+
(a, b) => (_nullishCoalesce(a.position, () => ( Number.MAX_SAFE_INTEGER))) - (_nullishCoalesce(b.position, () => ( Number.MAX_SAFE_INTEGER))) || a.seq - b.seq
|
|
2336
|
+
);
|
|
2337
|
+
const gone = new Set(order.slice(0, excess).map((t) => t.seq));
|
|
2338
|
+
if (gone.size === 0) break;
|
|
2339
|
+
for (const t of conv.turns) if (gone.has(t.seq)) size -= bytesOf(t.content);
|
|
2340
|
+
conv.turns = conv.turns.filter((t) => !gone.has(t.seq));
|
|
2341
|
+
for (const vectors of this.#vectors.values()) for (const seq of gone) vectors.delete(seq);
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
/** Idle conversations, then the least recently used beyond the count, then more until the bytes fit. */
|
|
2345
|
+
sweep() {
|
|
2346
|
+
const limits = this.limits;
|
|
2347
|
+
const now = this.#now();
|
|
2348
|
+
for (const [id, conv] of this.#conversations) {
|
|
2349
|
+
if (conv.lastActivity < now - limits.idle_ttl_seconds) this.drop(id);
|
|
2350
|
+
}
|
|
2351
|
+
const byRecent = [...this.#conversations.entries()].sort((a, b) => b[1].lastActivity - a[1].lastActivity);
|
|
2352
|
+
for (const [id] of byRecent.slice(limits.max_conversations)) this.drop(id);
|
|
2353
|
+
while (this.sizeBytes() > limits.max_file_bytes) {
|
|
2354
|
+
const oldest = this.conversations()[0];
|
|
2355
|
+
if (oldest === void 0) break;
|
|
2356
|
+
this.drop(oldest);
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
drop(conversationId) {
|
|
2360
|
+
const conv = this.#conversations.get(conversationId);
|
|
2361
|
+
if (conv === void 0) return;
|
|
2362
|
+
for (const vectors of this.#vectors.values()) for (const t of conv.turns) vectors.delete(t.seq);
|
|
2363
|
+
this.#conversations.delete(conversationId);
|
|
2364
|
+
}
|
|
2365
|
+
clear() {
|
|
2366
|
+
this.#conversations.clear();
|
|
2367
|
+
this.#vectors.clear();
|
|
2368
|
+
}
|
|
2369
|
+
close() {
|
|
2370
|
+
}
|
|
2371
|
+
/** In conversation order: by server position where known, else as written here. */
|
|
2372
|
+
turns(conversationId) {
|
|
2373
|
+
const conv = this.#conversations.get(conversationId);
|
|
2374
|
+
if (conv === void 0) return [];
|
|
2375
|
+
const bySeq = [...conv.turns].sort((a, b) => a.seq - b.seq);
|
|
2376
|
+
const key = /* @__PURE__ */ new Map();
|
|
2377
|
+
let top = 0;
|
|
2378
|
+
let step = 0;
|
|
2379
|
+
for (const t of bySeq) {
|
|
2380
|
+
if (t.position !== null) {
|
|
2381
|
+
key.set(t.seq, t.position);
|
|
2382
|
+
top = Math.max(top, t.position);
|
|
2383
|
+
step = 0;
|
|
2384
|
+
} else {
|
|
2385
|
+
step += 1;
|
|
2386
|
+
key.set(t.seq, top + step * 1e-6);
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
return bySeq.sort((a, b) => (_nullishCoalesce(key.get(a.seq), () => ( 0))) - (_nullishCoalesce(key.get(b.seq), () => ( 0))) || a.seq - b.seq).map((t) => ({ ...t }));
|
|
2390
|
+
}
|
|
2391
|
+
/** Turns the server also holds: archived tool results are local only. Python: `count`. */
|
|
2392
|
+
count(conversationId) {
|
|
2393
|
+
return (_nullishCoalesce(_optionalChain([this, 'access', _63 => _63.#conversations, 'access', _64 => _64.get, 'call', _65 => _65(conversationId), 'optionalAccess', _66 => _66.turns]), () => ( []))).filter((t) => t.role !== "tool").length;
|
|
2394
|
+
}
|
|
2395
|
+
sizeBytes() {
|
|
2396
|
+
let n2 = 0;
|
|
2397
|
+
for (const conv of this.#conversations.values()) for (const t of conv.turns) n2 += bytesOf(t.content);
|
|
2398
|
+
return n2;
|
|
2399
|
+
}
|
|
2400
|
+
/** Conversation ids, least recently active first. */
|
|
2401
|
+
conversations() {
|
|
2402
|
+
return [...this.#conversations.entries()].sort((a, b) => a[1].lastActivity - b[1].lastActivity).map(([id]) => id);
|
|
2403
|
+
}
|
|
2404
|
+
vectors(seqs, model) {
|
|
2405
|
+
const held = this.#vectors.get(model);
|
|
2406
|
+
const out = /* @__PURE__ */ new Map();
|
|
2407
|
+
if (held === void 0) return out;
|
|
2408
|
+
for (const seq of seqs) {
|
|
2409
|
+
const v = held.get(seq);
|
|
2410
|
+
if (v !== void 0) out.set(seq, v);
|
|
2411
|
+
}
|
|
2412
|
+
return out;
|
|
2413
|
+
}
|
|
2414
|
+
putVectors(model, items) {
|
|
2415
|
+
const held = _nullishCoalesce(this.#vectors.get(model), () => ( /* @__PURE__ */ new Map()));
|
|
2416
|
+
for (const [seq, vec] of items) held.set(seq, vec);
|
|
2417
|
+
this.#vectors.set(model, held);
|
|
2418
|
+
}
|
|
2419
|
+
}, _class3);
|
|
2420
|
+
|
|
2421
|
+
// src/cache/history-search.ts
|
|
2422
|
+
var WORD_RE = /[\p{L}\p{N}\p{M}]+/gu;
|
|
2423
|
+
var FORMS = _nullishCoalesce(_chunkICUFS3B5cjs.HISTORY_SEARCH.irregular_forms, () => ( {}));
|
|
2424
|
+
function tokenize2(text) {
|
|
2425
|
+
const out = [];
|
|
2426
|
+
for (const word of _nullishCoalesce((text || "").toLowerCase().match(WORD_RE), () => ( []))) {
|
|
2427
|
+
if (/^[\x00-\x7f]+$/.test(word)) out.push(..._chunkICUFS3B5cjs.tokenize.call(void 0, _nullishCoalesce(FORMS[word], () => ( word))));
|
|
2428
|
+
else out.push(word);
|
|
2429
|
+
}
|
|
2430
|
+
return out;
|
|
2431
|
+
}
|
|
2432
|
+
var LITERAL_SOURCE = String.raw`"([^"]{3,})"|\b([A-Z0-9][A-Z0-9-]{3,})\b|(\d[\d,.:/-]*\d|\d)`;
|
|
2433
|
+
var SENTENCE_RE = /(?<=[.!?])\s+/;
|
|
2434
|
+
function literalsOf(query) {
|
|
2435
|
+
const out = [];
|
|
2436
|
+
for (const m of (query || "").matchAll(new RegExp(LITERAL_SOURCE, "g"))) {
|
|
2437
|
+
const quoted = m[1];
|
|
2438
|
+
const value = quoted || m[2] || m[3];
|
|
2439
|
+
if (value && (quoted || /\d/.test(value))) out.push(value.toLowerCase());
|
|
2440
|
+
}
|
|
2441
|
+
return out;
|
|
2442
|
+
}
|
|
2443
|
+
function cosine(a, b) {
|
|
2444
|
+
let dot = 0;
|
|
2445
|
+
let na = 0;
|
|
2446
|
+
let nb = 0;
|
|
2447
|
+
const n2 = Math.min(a.length, b.length);
|
|
2448
|
+
for (let i = 0; i < n2; i++) {
|
|
2449
|
+
dot += a[i] * b[i];
|
|
2450
|
+
na += a[i] * a[i];
|
|
2451
|
+
nb += b[i] * b[i];
|
|
2452
|
+
}
|
|
2453
|
+
return na && nb ? dot / (Math.sqrt(na) * Math.sqrt(nb)) : 0;
|
|
2454
|
+
}
|
|
2455
|
+
function words(text) {
|
|
2456
|
+
return text.split(/\s+/).filter(Boolean);
|
|
2457
|
+
}
|
|
2458
|
+
function excerptOf(content, terms, literals, maxWords) {
|
|
2459
|
+
let sentences = content.trim().split(SENTENCE_RE).filter((s2) => s2.trim());
|
|
2460
|
+
if (sentences.length === 0) sentences = [content.trim()];
|
|
2461
|
+
const score = (sentence) => {
|
|
2462
|
+
const low = sentence.toLowerCase();
|
|
2463
|
+
const held = new Set(tokenize2(sentence));
|
|
2464
|
+
let n2 = 0;
|
|
2465
|
+
for (const t of terms) if (held.has(t)) n2 += 1;
|
|
2466
|
+
for (const lit of literals) if (low.includes(lit)) n2 += 2;
|
|
2467
|
+
return n2;
|
|
2468
|
+
};
|
|
2469
|
+
let best = 0;
|
|
2470
|
+
for (let i = 1; i < sentences.length; i++) if (score(sentences[i]) > score(sentences[best])) best = i;
|
|
2471
|
+
let lo = best;
|
|
2472
|
+
let hi = best;
|
|
2473
|
+
let count = words(sentences[best]).length;
|
|
2474
|
+
for (; ; ) {
|
|
2475
|
+
let grew = false;
|
|
2476
|
+
for (const j of [hi + 1, lo - 1]) {
|
|
2477
|
+
if (j >= 0 && j < sentences.length && count + words(sentences[j]).length <= maxWords) {
|
|
2478
|
+
count += words(sentences[j]).length;
|
|
2479
|
+
lo = Math.min(lo, j);
|
|
2480
|
+
hi = Math.max(hi, j);
|
|
2481
|
+
grew = true;
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
if (!grew) break;
|
|
2485
|
+
}
|
|
2486
|
+
let text = sentences.slice(lo, hi + 1).join(" ");
|
|
2487
|
+
if (words(text).length > maxWords) text = words(text).slice(0, maxWords).join(" ") + " ...";
|
|
2488
|
+
return (lo > 0 ? "... " : "") + text + (hi < sentences.length - 1 && !text.endsWith("...") ? " ..." : "");
|
|
2489
|
+
}
|
|
2490
|
+
var FENCE = /^\s*(?:```|~~~)/;
|
|
2491
|
+
var TABLE_RULE = /^\s*\|?\s*:?-{2,}/;
|
|
2492
|
+
var SENTENCE = /(?<=[.!?])\s+/;
|
|
2493
|
+
function splitPassages(content, maxWords) {
|
|
2494
|
+
const text = (_nullishCoalesce(content, () => ( ""))).trim();
|
|
2495
|
+
if (words(text).length <= maxWords) return text ? [text] : [];
|
|
2496
|
+
const out = [];
|
|
2497
|
+
const lines = text.split("\n");
|
|
2498
|
+
let i = 0;
|
|
2499
|
+
while (i < lines.length) {
|
|
2500
|
+
const line = lines[i];
|
|
2501
|
+
if (FENCE.test(line)) {
|
|
2502
|
+
let j2 = i + 1;
|
|
2503
|
+
while (j2 < lines.length && !FENCE.test(lines[j2])) j2 += 1;
|
|
2504
|
+
out.push(...windowsOf(lines.slice(i + 1, j2), maxWords));
|
|
2505
|
+
i = j2 + 1;
|
|
2506
|
+
continue;
|
|
2507
|
+
}
|
|
2508
|
+
if (line.trim().startsWith("|")) {
|
|
2509
|
+
let j2 = i;
|
|
2510
|
+
while (j2 < lines.length && lines[j2].trim().startsWith("|")) j2 += 1;
|
|
2511
|
+
const rows = lines.slice(i, j2).filter((r) => !TABLE_RULE.test(r)).map((r) => r.trim());
|
|
2512
|
+
const [header, body] = rows.length > 1 ? [rows[0], rows.slice(1)] : ["", rows];
|
|
2513
|
+
for (const row of body) {
|
|
2514
|
+
const both = `${header} ${row}`.trim();
|
|
2515
|
+
out.push(words(both).length <= Math.trunc(maxWords * 3 / 2) ? both : row);
|
|
2516
|
+
}
|
|
2517
|
+
i = j2;
|
|
2518
|
+
continue;
|
|
2519
|
+
}
|
|
2520
|
+
let j = i;
|
|
2521
|
+
while (j < lines.length && lines[j].trim() && !FENCE.test(lines[j]) && !lines[j].trim().startsWith("|")) j += 1;
|
|
2522
|
+
if (j === i) {
|
|
2523
|
+
i += 1;
|
|
2524
|
+
continue;
|
|
2525
|
+
}
|
|
2526
|
+
const block = lines.slice(i, j);
|
|
2527
|
+
if (block.length > 1 && block.every((b) => words(b).length <= 25)) {
|
|
2528
|
+
out.push(...windowsOf(block, maxWords));
|
|
2529
|
+
} else {
|
|
2530
|
+
const sentences = block.map((b) => b.trim()).join(" ").split(SENTENCE).filter((x) => x.trim());
|
|
2531
|
+
out.push(...windowsOf(sentences, maxWords));
|
|
2532
|
+
}
|
|
2533
|
+
i = j;
|
|
2534
|
+
}
|
|
2535
|
+
const kept = out.filter((x) => x.trim());
|
|
2536
|
+
return kept.length ? kept : [text];
|
|
2537
|
+
}
|
|
2538
|
+
function windowsOf(pieces, maxWords) {
|
|
2539
|
+
const out = [];
|
|
2540
|
+
let cur = [];
|
|
2541
|
+
let used = 0;
|
|
2542
|
+
for (const raw of pieces) {
|
|
2543
|
+
const piece = raw.trim();
|
|
2544
|
+
if (!piece) continue;
|
|
2545
|
+
const n2 = words(piece).length;
|
|
2546
|
+
if (cur.length && used + n2 > maxWords) {
|
|
2547
|
+
out.push(cur.join(" "));
|
|
2548
|
+
cur = [];
|
|
2549
|
+
used = 0;
|
|
2550
|
+
}
|
|
2551
|
+
if (n2 > maxWords) {
|
|
2552
|
+
const w = words(piece);
|
|
2553
|
+
for (let k = 0; k < w.length; k += maxWords) out.push(w.slice(k, k + maxWords).join(" "));
|
|
2554
|
+
continue;
|
|
2555
|
+
}
|
|
2556
|
+
cur.push(piece);
|
|
2557
|
+
used += n2;
|
|
2558
|
+
}
|
|
2559
|
+
if (cur.length) out.push(cur.join(" "));
|
|
2560
|
+
return out;
|
|
2561
|
+
}
|
|
2562
|
+
function askedKinds(query) {
|
|
2563
|
+
const out = [];
|
|
2564
|
+
for (const [name, spec] of Object.entries(_nullishCoalesce(_chunkICUFS3B5cjs.HISTORY_SEARCH.asked_kinds, () => ( {})))) {
|
|
2565
|
+
if (name.startsWith("$") || typeof spec !== "object") continue;
|
|
2566
|
+
if (new RegExp(spec.query, "i").test(_nullishCoalesce(query, () => ( "")))) out.push(new RegExp(spec.value));
|
|
2567
|
+
}
|
|
2568
|
+
return out;
|
|
2569
|
+
}
|
|
2570
|
+
function asksHowItStarted(query) {
|
|
2571
|
+
const spec = _chunkICUFS3B5cjs.HISTORY_SEARCH.early_query;
|
|
2572
|
+
if (!_optionalChain([spec, 'optionalAccess', _67 => _67.pattern])) return false;
|
|
2573
|
+
return new RegExp(spec.pattern, (_nullishCoalesce(spec.flags, () => ( ""))).includes("i") ? "i" : "").test(_nullishCoalesce(query, () => ( "")));
|
|
2574
|
+
}
|
|
2575
|
+
async function searchTurns(turns, query, options = {}) {
|
|
2576
|
+
const params = _chunkICUFS3B5cjs.HISTORY_SEARCH;
|
|
2577
|
+
const k = params.max_excerpts;
|
|
2578
|
+
const skip = new Set(_nullishCoalesce(options.exclude, () => ( [])));
|
|
2579
|
+
const pool = turns.filter((t) => t.content && !skip.has(t.content) && !skip.has(_nullishCoalesce(t.message_id, () => ( ""))));
|
|
2580
|
+
const terms = new Set(tokenize2(query || ""));
|
|
2581
|
+
const literals = literalsOf(query);
|
|
2582
|
+
if (pool.length === 0 || terms.size === 0 && literals.length === 0 && !options.encoder) return [];
|
|
2583
|
+
const maxWords = params.max_words_per_excerpt;
|
|
2584
|
+
const units = [];
|
|
2585
|
+
pool.forEach((t, ti) => {
|
|
2586
|
+
if (!params.passages) {
|
|
2587
|
+
units.push({ seq: t.seq, content: t.content, turn: ti, first: true, last: true, part: -1 });
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
const parts = splitPassages(t.content, maxWords);
|
|
2591
|
+
parts.forEach((part, pi) => {
|
|
2592
|
+
units.push({
|
|
2593
|
+
seq: t.seq,
|
|
2594
|
+
content: part,
|
|
2595
|
+
turn: ti,
|
|
2596
|
+
first: pi === 0,
|
|
2597
|
+
last: pi === parts.length - 1,
|
|
2598
|
+
part: parts.length > 1 ? pi : -1
|
|
2599
|
+
});
|
|
2600
|
+
});
|
|
2601
|
+
});
|
|
2602
|
+
const docs = units.map((u) => tokenize2(u.content));
|
|
2603
|
+
const bm = new (0, _chunkICUFS3B5cjs.BM25)(docs);
|
|
2604
|
+
const termList = [...terms];
|
|
2605
|
+
const rows = units.map((turn, i) => {
|
|
2606
|
+
const held = new Set(docs[i]);
|
|
2607
|
+
let matched = 0;
|
|
2608
|
+
for (const t of terms) if (held.has(t)) matched += 1;
|
|
2609
|
+
const low = turn.content.toLowerCase();
|
|
2610
|
+
let literal = 0;
|
|
2611
|
+
for (const lit of literals) if (low.includes(lit)) literal += 1;
|
|
2612
|
+
return { i, bm25: matched ? bm.score(termList, i) : 0, matched, literal };
|
|
2613
|
+
});
|
|
2614
|
+
const need = Math.min(params.min_matched_terms, Math.max(1, terms.size));
|
|
2615
|
+
const rareCap = Math.max(1, Math.trunc((_nullishCoalesce(params.rare_term_max_share, () => ( 0))) * units.length));
|
|
2616
|
+
const rare = /* @__PURE__ */ new Set();
|
|
2617
|
+
for (const t of terms) {
|
|
2618
|
+
let n3 = 0;
|
|
2619
|
+
for (const doc of docs) if (doc.includes(t)) n3 += 1;
|
|
2620
|
+
if (n3 > 0 && n3 <= rareCap) rare.add(t);
|
|
2621
|
+
}
|
|
2622
|
+
let eligible;
|
|
2623
|
+
if (params.passages) {
|
|
2624
|
+
const turnTerms = /* @__PURE__ */ new Map();
|
|
2625
|
+
for (const r of rows) {
|
|
2626
|
+
const held = _nullishCoalesce(turnTerms.get(units[r.i].turn), () => ( /* @__PURE__ */ new Set()));
|
|
2627
|
+
for (const t of docs[r.i]) if (terms.has(t)) held.add(t);
|
|
2628
|
+
turnTerms.set(units[r.i].turn, held);
|
|
2629
|
+
}
|
|
2630
|
+
eligible = rows.filter(
|
|
2631
|
+
(r) => r.literal > 0 || r.matched > 0 && (turnTerms.get(units[r.i].turn).size >= need || docs[r.i].some((t) => rare.has(t)))
|
|
2632
|
+
);
|
|
2633
|
+
} else {
|
|
2634
|
+
eligible = rows.filter(
|
|
2635
|
+
(r) => r.literal > 0 || r.matched >= need || r.matched > 0 && docs[r.i].some((t) => rare.has(t))
|
|
2636
|
+
);
|
|
2637
|
+
}
|
|
2638
|
+
const rrf = params.rrf_k;
|
|
2639
|
+
const fused = /* @__PURE__ */ new Map();
|
|
2640
|
+
const via = /* @__PURE__ */ new Map();
|
|
2641
|
+
for (const r of eligible) fused.set(r.i, 0);
|
|
2642
|
+
const add = (i, rank, how) => {
|
|
2643
|
+
fused.set(i, (_nullishCoalesce(fused.get(i), () => ( 0))) + 1 / (rrf + rank + 1));
|
|
2644
|
+
if (!via.has(i)) via.set(i, how);
|
|
2645
|
+
};
|
|
2646
|
+
eligible.filter((r) => r.literal > 0).sort((a, b) => b.literal - a.literal || a.i - b.i).forEach((r, rank) => add(r.i, rank, "literal"));
|
|
2647
|
+
eligible.filter((r) => r.bm25 > 0).sort((a, b) => b.bm25 - a.bm25 || a.i - b.i).forEach((r, rank) => add(r.i, rank, "bm25"));
|
|
2648
|
+
const kinds = askedKinds(query);
|
|
2649
|
+
if (kinds.length) {
|
|
2650
|
+
rows.filter((r) => r.matched > 0 && kinds.some((k2) => k2.test(units[r.i].content))).sort((a, b) => b.bm25 - a.bm25 || a.i - b.i).forEach((r, rank) => add(r.i, rank, "kind"));
|
|
2651
|
+
}
|
|
2652
|
+
if (options.encoder) {
|
|
2653
|
+
const ranked2 = await embeddingRanks(units, query, options.encoder, _nullishCoalesce(options.store, () => ( null)), _nullishCoalesce(params.min_cosine, () => ( 0.4)));
|
|
2654
|
+
ranked2.forEach(([i], rank) => add(i, rank, "embedding"));
|
|
2655
|
+
}
|
|
2656
|
+
if (fused.size === 0) return [];
|
|
2657
|
+
const n2 = Math.max(pool.length - 1, 1);
|
|
2658
|
+
const weight = asksHowItStarted(query) ? 0 : params.recency_weight;
|
|
2659
|
+
const top = /* @__PURE__ */ new Map();
|
|
2660
|
+
const ranked = /* @__PURE__ */ new Map();
|
|
2661
|
+
for (const [u, v] of fused) {
|
|
2662
|
+
const ti = units[u].turn;
|
|
2663
|
+
const score = v + weight * (ti / n2) / (rrf + 1);
|
|
2664
|
+
ranked.set(ti, [..._nullishCoalesce(ranked.get(ti), () => ( [])), [score, u]]);
|
|
2665
|
+
const held = top.get(ti);
|
|
2666
|
+
if (!held || score > held[0]) top.set(ti, [score, u]);
|
|
2667
|
+
}
|
|
2668
|
+
const best = [...top.keys()].sort((a, b) => top.get(b)[0] - top.get(a)[0] || a - b).slice(0, k);
|
|
2669
|
+
const perTurn = _nullishCoalesce(params.passages_per_turn, () => ( 1));
|
|
2670
|
+
const shown = (ti) => {
|
|
2671
|
+
const unit = units[top.get(ti)[1]];
|
|
2672
|
+
if (!params.passages || unit.first && unit.last) return excerptOf(pool[ti].content, terms, literals, maxWords);
|
|
2673
|
+
const picked = [...ranked.get(ti)].sort((a, b) => b[0] - a[0] || b[1] - a[1]).slice(0, perTurn).map(([, u]) => u).sort((a, b) => a - b);
|
|
2674
|
+
const parts = [];
|
|
2675
|
+
for (const u of picked) parts.push((units[u].first || parts.length ? "" : "... ") + units[u].content);
|
|
2676
|
+
return parts.join(" ... ") + (units[picked[picked.length - 1]].last ? "" : " ...");
|
|
2677
|
+
};
|
|
2678
|
+
const found = /* @__PURE__ */ new Map();
|
|
2679
|
+
for (const ti of best) {
|
|
2680
|
+
found.set(ti, {
|
|
2681
|
+
position: pool[ti].position,
|
|
2682
|
+
role: pool[ti].role,
|
|
2683
|
+
timestamp: pool[ti].timestamp,
|
|
2684
|
+
score: top.get(ti)[0],
|
|
2685
|
+
via: _nullishCoalesce(via.get(top.get(ti)[1]), () => ( "")),
|
|
2686
|
+
text: shown(ti)
|
|
2687
|
+
});
|
|
2688
|
+
}
|
|
2689
|
+
const before2 = _nullishCoalesce(params.previous_turns, () => ( 0));
|
|
2690
|
+
const tail = _nullishCoalesce(params.previous_turn_words, () => ( 40));
|
|
2691
|
+
for (const i of best) {
|
|
2692
|
+
for (let j = i - before2; j < i; j++) {
|
|
2693
|
+
if (j < 0 || found.has(j)) continue;
|
|
2694
|
+
const hit = pool[i].position;
|
|
2695
|
+
const prev = pool[j].position;
|
|
2696
|
+
if (hit && prev && hit - prev > before2) continue;
|
|
2697
|
+
const w = words(pool[j].content);
|
|
2698
|
+
found.set(j, {
|
|
2699
|
+
position: prev,
|
|
2700
|
+
role: pool[j].role,
|
|
2701
|
+
timestamp: pool[j].timestamp,
|
|
2702
|
+
score: 0,
|
|
2703
|
+
via: "previous",
|
|
2704
|
+
text: w.length <= tail ? w.join(" ") : "... " + w.slice(-tail).join(" ")
|
|
2705
|
+
});
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
return [...found.keys()].sort((a, b) => a - b).map((i) => found.get(i));
|
|
2709
|
+
}
|
|
2710
|
+
async function embeddingRanks(pool, query, encoder, store, minCosine) {
|
|
2711
|
+
const keyOf = (u) => (_nullishCoalesce(u.part, () => ( -1))) < 0 ? encoder.model : `${encoder.model}#p${u.part}`;
|
|
2712
|
+
const vectors = /* @__PURE__ */ new Map();
|
|
2713
|
+
if (store !== null) {
|
|
2714
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
2715
|
+
pool.forEach((u, i) => byKey.set(keyOf(u), [..._nullishCoalesce(byKey.get(keyOf(u)), () => ( [])), i]));
|
|
2716
|
+
for (const [key, idx] of byKey) {
|
|
2717
|
+
const held = store.vectors(idx.map((i) => pool[i].seq), key);
|
|
2718
|
+
for (const i of idx) {
|
|
2719
|
+
const v = held.get(pool[i].seq);
|
|
2720
|
+
if (v) vectors.set(i, v);
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
const missing = pool.map((_, i) => i).filter((i) => !vectors.has(i));
|
|
2725
|
+
if (missing.length > 0) {
|
|
2726
|
+
const fresh = await encoder.encode(missing.map((i) => pool[i].content));
|
|
2727
|
+
const put = /* @__PURE__ */ new Map();
|
|
2728
|
+
missing.forEach((i, j) => {
|
|
2729
|
+
const v = Float32Array.from(_nullishCoalesce(fresh[j], () => ( [])));
|
|
2730
|
+
vectors.set(i, v);
|
|
2731
|
+
const key = keyOf(pool[i]);
|
|
2732
|
+
put.set(key, (_nullishCoalesce(put.get(key), () => ( /* @__PURE__ */ new Map()))).set(pool[i].seq, v));
|
|
2733
|
+
});
|
|
2734
|
+
if (store) for (const [key, items] of put) store.putVectors(key, items);
|
|
2735
|
+
}
|
|
2736
|
+
const q = await _asyncNullishCoalesce((await (_nullishCoalesce(encoder.encodeQuery, () => ( encoder.encode))).call(encoder, [query]))[0], async () => ( []));
|
|
2737
|
+
return pool.map((_, i) => [i, cosine(q, _nullishCoalesce(vectors.get(i), () => ( [])))]).filter(([, c]) => c >= minCosine).sort((a, b) => b[1] - a[1]);
|
|
2738
|
+
}
|
|
2739
|
+
function toolResultText(result, toolName) {
|
|
2740
|
+
let text = typeof result === "string" ? result : _nullishCoalesce(JSON.stringify(result), () => ( String(result)));
|
|
2741
|
+
const limit = _nullishCoalesce(_chunkICUFS3B5cjs.HISTORY_SEARCH.tool_result_max_chars, () => ( 16e3));
|
|
2742
|
+
if (text.length > limit) text = text.slice(0, limit) + " ...[cut]";
|
|
2743
|
+
return `[tool result: ${toolName || "tool"}] ${text}`;
|
|
2744
|
+
}
|
|
2745
|
+
function renderExcerpts(excerpts, latest = "") {
|
|
2746
|
+
if (excerpts.length === 0) return "";
|
|
2747
|
+
const lines = [_chunkICUFS3B5cjs.HISTORY_SEARCH.heading];
|
|
2748
|
+
for (const e of excerpts) {
|
|
2749
|
+
let where = e.position ? `turn ${e.position}, ${e.role}` : `${e.role}, earlier`;
|
|
2750
|
+
if (e.timestamp) {
|
|
2751
|
+
const ago = before(e.timestamp, latest);
|
|
2752
|
+
where += `, ${e.timestamp}` + (ago ? ` (${ago})` : "");
|
|
2753
|
+
}
|
|
2754
|
+
lines.push(`- ${where}: "${e.text}"`);
|
|
2755
|
+
}
|
|
2756
|
+
return lines.join("\n");
|
|
2757
|
+
}
|
|
2758
|
+
var ZONED = /(?:Z|[+-]\d{2}:\d{2})$/;
|
|
2759
|
+
function instant(stamp) {
|
|
2760
|
+
const text = (_nullishCoalesce(stamp, () => ( ""))).trim();
|
|
2761
|
+
if (!ZONED.test(text)) return null;
|
|
2762
|
+
const ms = Date.parse(text);
|
|
2763
|
+
return Number.isNaN(ms) ? null : ms / 1e3;
|
|
2764
|
+
}
|
|
2765
|
+
function before(stamp, latest) {
|
|
2766
|
+
const at = instant(stamp);
|
|
2767
|
+
const now = instant(latest);
|
|
2768
|
+
if (at === null || now === null || now < at) return "";
|
|
2769
|
+
const seconds = Math.trunc(now - at);
|
|
2770
|
+
for (const [unit, size] of [["day", 86400], ["hour", 3600], ["minute", 60]]) {
|
|
2771
|
+
if (seconds >= size) {
|
|
2772
|
+
const n2 = Math.trunc(seconds / size);
|
|
2773
|
+
return `${n2} ${unit}${n2 !== 1 ? "s" : ""} before the latest message`;
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
return "less than a minute before the latest message";
|
|
2777
|
+
}
|
|
2778
|
+
|
|
1860
2779
|
// src/context/overlay.ts
|
|
1861
2780
|
var MAX_TURNS = 20;
|
|
1862
2781
|
var TOKEN_BUDGET = 2e3;
|
|
@@ -1885,7 +2804,23 @@ function overlayLocalRecentTurns(response, store, conversationId, configured) {
|
|
|
1885
2804
|
if (entry === null) return;
|
|
1886
2805
|
const existing = _nullishCoalesce(response.conversation_context, () => ( null));
|
|
1887
2806
|
if (existing !== null && !verbatimOverlayEnabled(configured)) return;
|
|
1888
|
-
const
|
|
2807
|
+
const serverCompaction = existing === null ? null : existing["compaction_id"];
|
|
2808
|
+
const localIsWhole = isComplete(entry) && (!serverCompaction || serverCompaction === entry.compactionId);
|
|
2809
|
+
let sourceTurns = entry.recentTurns;
|
|
2810
|
+
if (existing !== null && !localIsWhole) {
|
|
2811
|
+
const raw = Array.isArray(existing["recent_turns"]) ? existing["recent_turns"] : [];
|
|
2812
|
+
const serverTurns = raw.map((t) => ({
|
|
2813
|
+
role: String(_nullishCoalesce(t["role"], () => ( "user"))),
|
|
2814
|
+
content: String(_nullishCoalesce(t["content"], () => ( ""))),
|
|
2815
|
+
timestamp: String(_nullishCoalesce(t["timestamp"], () => ( "")))
|
|
2816
|
+
}));
|
|
2817
|
+
sourceTurns = [...serverTurns, ...turnsAfter(entry.recentTurns, serverTurns)];
|
|
2818
|
+
}
|
|
2819
|
+
const localTurns = budgetRecentTurns(sourceTurns).map((t) => ({
|
|
2820
|
+
role: t.role,
|
|
2821
|
+
content: t.content,
|
|
2822
|
+
timestamp: t.timestamp
|
|
2823
|
+
}));
|
|
1889
2824
|
const serverField = (name) => existing === null ? void 0 : existing[name];
|
|
1890
2825
|
const orLocal = (name, local) => {
|
|
1891
2826
|
const value = serverField(name);
|
|
@@ -1902,7 +2837,7 @@ function overlayLocalRecentTurns(response, store, conversationId, configured) {
|
|
|
1902
2837
|
compacted_at: orLocal("compacted_at", entry.compactedAt),
|
|
1903
2838
|
conversation_id: conversationId
|
|
1904
2839
|
};
|
|
1905
|
-
} catch (
|
|
2840
|
+
} catch (e13) {
|
|
1906
2841
|
}
|
|
1907
2842
|
}
|
|
1908
2843
|
|
|
@@ -1915,7 +2850,7 @@ function stringify(value) {
|
|
|
1915
2850
|
if (t === "string" || t === "number" || t === "boolean") return String(value);
|
|
1916
2851
|
try {
|
|
1917
2852
|
return _nullishCoalesce(JSON.stringify(value), () => ( ""));
|
|
1918
|
-
} catch (
|
|
2853
|
+
} catch (e14) {
|
|
1919
2854
|
return String(value);
|
|
1920
2855
|
}
|
|
1921
2856
|
}
|
|
@@ -1940,14 +2875,28 @@ function buildRecentMessages(turns) {
|
|
|
1940
2875
|
role: t.role || "user",
|
|
1941
2876
|
content: _nullishCoalesce(t.content, () => ( "")),
|
|
1942
2877
|
timestamp: t.timestamp,
|
|
1943
|
-
message_id: `local-${idx}`
|
|
2878
|
+
message_id: t.message_id || `local-${idx}`
|
|
1944
2879
|
}));
|
|
1945
2880
|
}
|
|
1946
2881
|
function compactedMessageCount(_entry) {
|
|
1947
2882
|
return 0;
|
|
1948
2883
|
}
|
|
2884
|
+
function blockOf(entry) {
|
|
2885
|
+
if (entry.contextBlock) return entry.contextBlock.trim();
|
|
2886
|
+
if (entry.summary && entry.summary.startsWith(CONTEXT_BLOCK_PREFIX)) return entry.summary.trim();
|
|
2887
|
+
return null;
|
|
2888
|
+
}
|
|
1949
2889
|
function formatStructured(entry, recent) {
|
|
1950
2890
|
const parts = [];
|
|
2891
|
+
const block = blockOf(entry);
|
|
2892
|
+
if (block) {
|
|
2893
|
+
parts.push(block);
|
|
2894
|
+
if (recent.length > 0) {
|
|
2895
|
+
parts.push(`## Recent Turns (${recent.length})`);
|
|
2896
|
+
for (const m of recent) parts.push(`**${m.role}**: ${m.content}`);
|
|
2897
|
+
}
|
|
2898
|
+
return parts.filter(Boolean).join("\n\n").trim();
|
|
2899
|
+
}
|
|
1951
2900
|
if (entry.summary) {
|
|
1952
2901
|
parts.push("## Summary");
|
|
1953
2902
|
parts.push(entry.summary.trim());
|
|
@@ -1982,9 +2931,11 @@ function formatStructured(entry, recent) {
|
|
|
1982
2931
|
}
|
|
1983
2932
|
function formatNarrative(entry, recent) {
|
|
1984
2933
|
const parts = [];
|
|
1985
|
-
|
|
1986
|
-
if (
|
|
1987
|
-
else if (entry.
|
|
2934
|
+
const block = blockOf(entry);
|
|
2935
|
+
if (block) parts.push(block);
|
|
2936
|
+
else if (entry.summary) parts.push(entry.summary.trim());
|
|
2937
|
+
if (!block && entry.conversationalParagraph) parts.push(entry.conversationalParagraph.trim());
|
|
2938
|
+
else if (!block && entry.factualParagraph) parts.push(entry.factualParagraph.trim());
|
|
1988
2939
|
if (recent.length > 0) {
|
|
1989
2940
|
const tail = recent.map((m) => `${m.role}: ${m.content}`).join("\n");
|
|
1990
2941
|
parts.push(`Recent exchanges:
|
|
@@ -1994,6 +2945,10 @@ ${tail}`);
|
|
|
1994
2945
|
}
|
|
1995
2946
|
function formatBullets(entry, recent) {
|
|
1996
2947
|
const parts = [];
|
|
2948
|
+
const block = blockOf(entry);
|
|
2949
|
+
if (block) {
|
|
2950
|
+
return [block, ...recent.map((m) => `- ${m.role}: ${m.content}`)].join("\n").trim();
|
|
2951
|
+
}
|
|
1997
2952
|
if (entry.summary) parts.push(`- Summary: ${entry.summary.trim()}`);
|
|
1998
2953
|
for (const [k, v] of Object.entries(_nullishCoalesce(entry.currentState, () => ( {})))) {
|
|
1999
2954
|
parts.push(`- ${k}: ${stringify(v)}`);
|
|
@@ -2031,7 +2986,9 @@ function renderForPrompt(entry, style = DEFAULT_STYLE, now = Date.now) {
|
|
|
2031
2986
|
recent_messages: recent,
|
|
2032
2987
|
recent_message_count: recent.length,
|
|
2033
2988
|
compacted_message_count: compacted,
|
|
2034
|
-
total_message_count: recent.length + compacted
|
|
2989
|
+
total_message_count: recent.length + compacted,
|
|
2990
|
+
context_block: blockOf(entry),
|
|
2991
|
+
compaction_id: entry.compactionId
|
|
2035
2992
|
};
|
|
2036
2993
|
}
|
|
2037
2994
|
function renderCompacted(entry, format = "structured", correlationId = "") {
|
|
@@ -2176,10 +3133,10 @@ function servedItemIds(hit) {
|
|
|
2176
3133
|
}
|
|
2177
3134
|
return ids;
|
|
2178
3135
|
}
|
|
2179
|
-
function tryServeFromCache(cache, scope, params, maxItems) {
|
|
3136
|
+
async function tryServeFromCache(cache, scope, params, maxItems) {
|
|
2180
3137
|
try {
|
|
2181
3138
|
const scoped = scopeLookupParams(scope, params);
|
|
2182
|
-
const hit = cache.
|
|
3139
|
+
const hit = await cache.lookupAsync({
|
|
2183
3140
|
searchQuery: _nullishCoalesce(scoped.searchQuery, () => ( null)),
|
|
2184
3141
|
entityId: _nullishCoalesce(scoped.entityId, () => ( null)),
|
|
2185
3142
|
customerId: _nullishCoalesce(scoped.customerId, () => ( null)),
|
|
@@ -2190,7 +3147,7 @@ function tryServeFromCache(cache, scope, params, maxItems) {
|
|
|
2190
3147
|
});
|
|
2191
3148
|
if (hit === null) return { response: null, hit: null };
|
|
2192
3149
|
return { response: buildAnticipationResponse(hit), hit };
|
|
2193
|
-
} catch (
|
|
3150
|
+
} catch (e15) {
|
|
2194
3151
|
return { response: null, hit: null };
|
|
2195
3152
|
}
|
|
2196
3153
|
}
|
|
@@ -2267,6 +3224,8 @@ function mergeScopeResults(scopeResults) {
|
|
|
2267
3224
|
episodes: [],
|
|
2268
3225
|
emotions: [],
|
|
2269
3226
|
temporal_events: [],
|
|
3227
|
+
items: [],
|
|
3228
|
+
excerpts: [],
|
|
2270
3229
|
scope_map: {},
|
|
2271
3230
|
conversation_context: null,
|
|
2272
3231
|
profile: null,
|
|
@@ -2276,6 +3235,8 @@ function mergeScopeResults(scopeResults) {
|
|
|
2276
3235
|
total_items: 0,
|
|
2277
3236
|
metadata: null
|
|
2278
3237
|
};
|
|
3238
|
+
const rankedSeen = /* @__PURE__ */ new Set();
|
|
3239
|
+
const rankedItems = [];
|
|
2279
3240
|
for (const [scopeName, response] of scopeResults) {
|
|
2280
3241
|
out.scopes_queried.push(scopeName);
|
|
2281
3242
|
if (out.metadata === null && response.metadata !== void 0) {
|
|
@@ -2300,8 +3261,32 @@ function mergeScopeResults(scopeResults) {
|
|
|
2300
3261
|
out[collection].push(item);
|
|
2301
3262
|
}
|
|
2302
3263
|
}
|
|
3264
|
+
const excerpts = response["excerpts"];
|
|
3265
|
+
if (Array.isArray(excerpts)) {
|
|
3266
|
+
for (const item of excerpts) {
|
|
3267
|
+
const id = itemId2(item);
|
|
3268
|
+
if (id !== void 0) {
|
|
3269
|
+
if (seen.has(id)) continue;
|
|
3270
|
+
seen.add(id);
|
|
3271
|
+
out.scope_map[id] = scopeName;
|
|
3272
|
+
}
|
|
3273
|
+
out.excerpts.push(item);
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
const ranked = response["items"];
|
|
3277
|
+
if (Array.isArray(ranked)) {
|
|
3278
|
+
for (const item of ranked) {
|
|
3279
|
+
const id = itemId2(item);
|
|
3280
|
+
if (id !== void 0) {
|
|
3281
|
+
if (rankedSeen.has(id)) continue;
|
|
3282
|
+
rankedSeen.add(id);
|
|
3283
|
+
}
|
|
3284
|
+
rankedItems.push(item);
|
|
3285
|
+
}
|
|
3286
|
+
}
|
|
2303
3287
|
}
|
|
2304
|
-
out.
|
|
3288
|
+
out.items = sortByRankScore(rankedItems).map((item, n2) => ({ ...item, rank: n2 + 1 }));
|
|
3289
|
+
out.total_items = ITEM_COLLECTIONS.reduce((n2, c) => n2 + out[c].length, 0) + out.excerpts.length;
|
|
2305
3290
|
return out;
|
|
2306
3291
|
}
|
|
2307
3292
|
function oneDecimal(value) {
|
|
@@ -2327,7 +3312,18 @@ function formatForPrompt(ctx, options = {}) {
|
|
|
2327
3312
|
const includeScope = _nullishCoalesce(options.includeScope, () => ( false));
|
|
2328
3313
|
const includeConversationContext = _nullishCoalesce(options.includeConversationContext, () => ( true));
|
|
2329
3314
|
const sections = [];
|
|
2330
|
-
|
|
3315
|
+
const ranked = _nullishCoalesce(ctx.items, () => ( []));
|
|
3316
|
+
if (ranked.length > 0) {
|
|
3317
|
+
const lines = ranked.map((it, n2) => {
|
|
3318
|
+
let label = rankedLabel(String(_nullishCoalesce(it["category"], () => ( ""))));
|
|
3319
|
+
if (includeScope) label += `, scope: ${scopeOf(ctx, it)}`;
|
|
3320
|
+
return `${n2 + 1}. [${label}] ${String(_nullishCoalesce(it.content, () => ( "")))}`;
|
|
3321
|
+
});
|
|
3322
|
+
sections.push(`### Memories
|
|
3323
|
+
${lines.join("\n")}`);
|
|
3324
|
+
}
|
|
3325
|
+
const typed = ranked.length === 0;
|
|
3326
|
+
if (typed && ctx.facts.length > 0) {
|
|
2331
3327
|
const lines = ctx.facts.map((f) => {
|
|
2332
3328
|
let line = `- ${String(_nullishCoalesce(f.content, () => ( "")))}`;
|
|
2333
3329
|
if (includeScope) line += ` [scope: ${scopeOf(ctx, f)}]`;
|
|
@@ -2336,7 +3332,7 @@ function formatForPrompt(ctx, options = {}) {
|
|
|
2336
3332
|
sections.push(`### Facts
|
|
2337
3333
|
${lines.join("\n")}`);
|
|
2338
3334
|
}
|
|
2339
|
-
if (ctx.preferences.length > 0) {
|
|
3335
|
+
if (typed && ctx.preferences.length > 0) {
|
|
2340
3336
|
const lines = ctx.preferences.map((p) => {
|
|
2341
3337
|
const extras = [];
|
|
2342
3338
|
if (includeScope) extras.push(`scope: ${scopeOf(ctx, p)}`);
|
|
@@ -2349,7 +3345,7 @@ ${lines.join("\n")}`);
|
|
|
2349
3345
|
sections.push(`### Preferences
|
|
2350
3346
|
${lines.join("\n")}`);
|
|
2351
3347
|
}
|
|
2352
|
-
if (ctx.episodes.length > 0) {
|
|
3348
|
+
if (typed && ctx.episodes.length > 0) {
|
|
2353
3349
|
const lines = ctx.episodes.map((e) => {
|
|
2354
3350
|
let line = `- ${String(_nullishCoalesce(e["summary"], () => ( "")))}`;
|
|
2355
3351
|
if (includeScope) line += ` [scope: ${scopeOf(ctx, e)}]`;
|
|
@@ -2358,7 +3354,7 @@ ${lines.join("\n")}`);
|
|
|
2358
3354
|
sections.push(`### Episodes
|
|
2359
3355
|
${lines.join("\n")}`);
|
|
2360
3356
|
}
|
|
2361
|
-
if (ctx.emotions.length > 0) {
|
|
3357
|
+
if (typed && ctx.emotions.length > 0) {
|
|
2362
3358
|
const lines = ctx.emotions.map((em) => {
|
|
2363
3359
|
const extras = [];
|
|
2364
3360
|
if (includeScope) extras.push(`scope: ${scopeOf(ctx, em)}`);
|
|
@@ -2372,7 +3368,7 @@ ${lines.join("\n")}`);
|
|
|
2372
3368
|
sections.push(`### Emotions
|
|
2373
3369
|
${lines.join("\n")}`);
|
|
2374
3370
|
}
|
|
2375
|
-
if (ctx.temporal_events.length > 0) {
|
|
3371
|
+
if (typed && ctx.temporal_events.length > 0) {
|
|
2376
3372
|
const lines = ctx.temporal_events.map((te) => {
|
|
2377
3373
|
const extras = [];
|
|
2378
3374
|
if (includeScope) extras.push(`scope: ${scopeOf(ctx, te)}`);
|
|
@@ -2626,7 +3622,10 @@ function buildTool(target, options = {}, onWarning = () => {
|
|
|
2626
3622
|
}
|
|
2627
3623
|
|
|
2628
3624
|
// src/client.ts
|
|
2629
|
-
|
|
3625
|
+
function localModelOff() {
|
|
3626
|
+
return ["off", "0", "false", "no", "none"].includes((_nullishCoalesce(_chunkZKOJDUN4cjs.getEnv.call(void 0, "SYNAP_SDK_LOCAL_MODEL"), () => ( ""))).trim().toLowerCase());
|
|
3627
|
+
}
|
|
3628
|
+
var SynapClient = (_class4 = class _SynapClient {
|
|
2630
3629
|
// Native-private (`#`), not TypeScript `private`. TS `private` is erased at
|
|
2631
3630
|
// compile time, so the field stays enumerable at runtime and a JS consumer
|
|
2632
3631
|
// can still reach it. These two were public and made `client.transport
|
|
@@ -2652,7 +3651,16 @@ var SynapClient = class {
|
|
|
2652
3651
|
#registryKeys;
|
|
2653
3652
|
#compactionSubscribers;
|
|
2654
3653
|
#shortTerm;
|
|
3654
|
+
/** Every raw turn, past compaction, for local history search. */
|
|
3655
|
+
#turnStore;
|
|
3656
|
+
/** A local embedding model for history search; null = keywords only. */
|
|
3657
|
+
#localEncoder = null;
|
|
3658
|
+
/** `history_search_model`: "auto", an "onnx:..." name, or null for none. */
|
|
3659
|
+
#localModelName = "auto";
|
|
3660
|
+
#localModelStarted = false;
|
|
3661
|
+
#backfillAfter = /* @__PURE__ */ new Map();
|
|
2655
3662
|
#stVerbatimOverlay;
|
|
3663
|
+
#agentModel = {};
|
|
2656
3664
|
#logger;
|
|
2657
3665
|
#stAuthoritative;
|
|
2658
3666
|
#turns;
|
|
@@ -2690,13 +3698,13 @@ var SynapClient = class {
|
|
|
2690
3698
|
userAgent: `@maximem/synap-js-sdk/${SDK_VERSION}`
|
|
2691
3699
|
});
|
|
2692
3700
|
if (options.heartbeat) this.#transport.startHeartbeat();
|
|
2693
|
-
this.#anticipationCache = new (0,
|
|
3701
|
+
this.#anticipationCache = new (0, _chunkICUFS3B5cjs.AnticipationCache)();
|
|
2694
3702
|
this.#fetchHooks = {
|
|
2695
|
-
beforeFetch: (scope, options2) => {
|
|
3703
|
+
beforeFetch: async (scope, options2) => {
|
|
2696
3704
|
const o2 = options2;
|
|
2697
3705
|
if (_nullishCoalesce(o2["query_date"], () => ( o2["queryDate"]))) return null;
|
|
2698
3706
|
if (_nullishCoalesce(o2["max_results_per_query"], () => ( o2["maxResultsPerQuery"]))) return null;
|
|
2699
|
-
const attempt = tryServeFromCache(
|
|
3707
|
+
const attempt = await tryServeFromCache(
|
|
2700
3708
|
this.#anticipationCache,
|
|
2701
3709
|
scope,
|
|
2702
3710
|
{
|
|
@@ -2710,7 +3718,7 @@ var SynapClient = class {
|
|
|
2710
3718
|
// on entity and conversation alone, so a bundle prefetched for one
|
|
2711
3719
|
// rung answered a caller standing at another, entirely inside this
|
|
2712
3720
|
// process and invisible to every server log.
|
|
2713
|
-
scopeRung:
|
|
3721
|
+
scopeRung: _chunkICUFS3B5cjs.rungKey.call(void 0,
|
|
2714
3722
|
_nullishCoalesce(o2["scope_path"], () => ( o2["scopePath"]))
|
|
2715
3723
|
)
|
|
2716
3724
|
},
|
|
@@ -2720,7 +3728,9 @@ var SynapClient = class {
|
|
|
2720
3728
|
return {
|
|
2721
3729
|
response: attempt.response,
|
|
2722
3730
|
servedItemIds: servedItemIds(attempt.hit),
|
|
2723
|
-
bundleId: _nullishCoalesce(attempt.hit.bundleIds[0], () => ( ""))
|
|
3731
|
+
bundleId: _nullishCoalesce(attempt.hit.bundleIds[0], () => ( "")),
|
|
3732
|
+
borderline: attempt.hit.band === "borderline",
|
|
3733
|
+
raceDeadlineMs: _chunkICUFS3B5cjs.SEMANTIC_MATCH.race_deadline_ms
|
|
2724
3734
|
};
|
|
2725
3735
|
},
|
|
2726
3736
|
onAssembled: (scope, options2, response, startedAt) => {
|
|
@@ -2735,9 +3745,19 @@ var SynapClient = class {
|
|
|
2735
3745
|
this.client = { context: { fetch: async (o2 = {}) => fetchContext(this.#transport, "client", o2, this.#fetchHooks) } };
|
|
2736
3746
|
this.#compactionSubscribers = new CompactionSubscribers();
|
|
2737
3747
|
this.#shortTerm = new ShortTermStore();
|
|
3748
|
+
this.#turnStore = new TurnStore();
|
|
3749
|
+
this.#shortTerm.attachArchive(this.#turnStore);
|
|
2738
3750
|
this.#stVerbatimOverlay = _nullishCoalesce(options.st_verbatim_overlay, () => ( options.stVerbatimOverlay));
|
|
3751
|
+
this.#agentModel = {
|
|
3752
|
+
model: _nullishCoalesce(options.agent_model, () => ( options.agentModel)),
|
|
3753
|
+
contextWindow: _nullishCoalesce(options.agent_context_window, () => ( options.agentContextWindow))
|
|
3754
|
+
};
|
|
2739
3755
|
this.#logger = options.logger;
|
|
2740
3756
|
this.#stAuthoritative = _nullishCoalesce(options.sdk_st_authoritative, () => ( options.sdkStAuthoritative));
|
|
3757
|
+
this.#localEncoder = _nullishCoalesce(_nullishCoalesce(options.history_search_encoder, () => ( options.historySearchEncoder)), () => ( null));
|
|
3758
|
+
const modelOption = options.history_search_model !== void 0 ? options.history_search_model : options.historySearchModel;
|
|
3759
|
+
this.#localModelName = modelOption === void 0 ? "auto" : modelOption;
|
|
3760
|
+
if (_optionalChain([this, 'access', _68 => _68.#localEncoder, 'optionalAccess', _69 => _69.model]) === _chunkICUFS3B5cjs.SEMANTIC_MATCH.model) this.#anticipationCache.setEncoder(this.#localEncoder);
|
|
2741
3761
|
this.#turns = new TurnCounter();
|
|
2742
3762
|
this.conversation = createConversationNamespace(
|
|
2743
3763
|
this.#transport,
|
|
@@ -2754,17 +3774,24 @@ var SynapClient = class {
|
|
|
2754
3774
|
},
|
|
2755
3775
|
// Buffer the turn locally so the next fetch sees it, ahead of the server
|
|
2756
3776
|
// having persisted and compacted it.
|
|
2757
|
-
({ conversationId, role, content, timestamp }) => {
|
|
2758
|
-
this.#shortTerm.appendTurn(conversationId, role, content, timestamp
|
|
3777
|
+
({ conversationId, role, content, timestamp, messageId, serverMessageCount, inFlight }) => {
|
|
3778
|
+
this.#shortTerm.appendTurn(conversationId, role, content, timestamp, {
|
|
3779
|
+
messageId,
|
|
3780
|
+
serverMessageCount,
|
|
3781
|
+
inFlight
|
|
3782
|
+
});
|
|
2759
3783
|
},
|
|
2760
3784
|
(response, conversationId, userId, scopePath) => {
|
|
2761
3785
|
overlayLocalRecentTurns(response, this.#shortTerm, conversationId, this.#stVerbatimOverlay);
|
|
2762
|
-
this.#injectUserSummary(response, conversationId, userId,
|
|
3786
|
+
this.#injectUserSummary(response, conversationId, userId, _chunkICUFS3B5cjs.rungKey.call(void 0, scopePath));
|
|
2763
3787
|
},
|
|
2764
3788
|
{
|
|
2765
3789
|
prompt: (conversationId, style) => this.#localPrompt(conversationId, style),
|
|
2766
|
-
compacted: (conversationId, format) => this.#localCompacted(conversationId, format)
|
|
2767
|
-
|
|
3790
|
+
compacted: (conversationId, format) => this.#localCompacted(conversationId, format),
|
|
3791
|
+
reseed: (conversationId, response) => this.#reseedShortTerm(conversationId, response),
|
|
3792
|
+
historyExcerpts: (conversationId, response, query) => this.#withHistoryExcerpts(conversationId, response, query)
|
|
3793
|
+
},
|
|
3794
|
+
() => this.#agentModel
|
|
2768
3795
|
);
|
|
2769
3796
|
this.memories = createMemoriesInterface(this.#transport, ({ userId, customerId }) => {
|
|
2770
3797
|
for (const id of /* @__PURE__ */ new Set([userId, customerId])) {
|
|
@@ -2778,11 +3805,17 @@ var SynapClient = class {
|
|
|
2778
3805
|
this.#anticipationCache,
|
|
2779
3806
|
({ conversationId, role, content }) => {
|
|
2780
3807
|
this.#shortTerm.appendTurn(conversationId, role, content);
|
|
2781
|
-
}
|
|
3808
|
+
},
|
|
3809
|
+
() => this.#agentModel,
|
|
3810
|
+
({ conversationId, result, toolName }) => this.archive_tool_result(conversationId, result, { tool_name: toolName })
|
|
2782
3811
|
);
|
|
3812
|
+
this.instance._internal.setOnListen(() => this.#startLocalModel());
|
|
2783
3813
|
this.instance._internal.setCompactionApplier((bundle) => {
|
|
2784
3814
|
this.#shortTerm.applyCompaction(bundle);
|
|
2785
3815
|
});
|
|
3816
|
+
this.instance._internal.setConversationStateHandler((conversationId, messageCount) => {
|
|
3817
|
+
this.#shortTerm.noteServerCount(conversationId, messageCount);
|
|
3818
|
+
});
|
|
2786
3819
|
if (options._force_new !== true) {
|
|
2787
3820
|
const incumbent = registerIfAbsent(registryKey, this);
|
|
2788
3821
|
if (incumbent !== void 0) return incumbent;
|
|
@@ -2900,7 +3933,7 @@ var SynapClient = class {
|
|
|
2900
3933
|
this.#registryKeys.push(resolvedInstanceId);
|
|
2901
3934
|
}
|
|
2902
3935
|
}
|
|
2903
|
-
} catch (
|
|
3936
|
+
} catch (e16) {
|
|
2904
3937
|
}
|
|
2905
3938
|
}
|
|
2906
3939
|
/**
|
|
@@ -2942,6 +3975,14 @@ var SynapClient = class {
|
|
|
2942
3975
|
this.#transport.setRetryPolicy(_nullishCoalesce(_nullishCoalesce(options.retryPolicy, () => ( options.retry_policy)), () => ( null)));
|
|
2943
3976
|
}
|
|
2944
3977
|
if (options.logger !== void 0) this.#logger = options.logger;
|
|
3978
|
+
const model = _nullishCoalesce(options.agent_model, () => ( options.agentModel));
|
|
3979
|
+
const window = _nullishCoalesce(options.agent_context_window, () => ( options.agentContextWindow));
|
|
3980
|
+
if (model !== void 0 || window !== void 0) {
|
|
3981
|
+
this.#agentModel = {
|
|
3982
|
+
model: _nullishCoalesce(model, () => ( this.#agentModel.model)),
|
|
3983
|
+
contextWindow: _nullishCoalesce(window, () => ( this.#agentModel.contextWindow))
|
|
3984
|
+
};
|
|
3985
|
+
}
|
|
2945
3986
|
}
|
|
2946
3987
|
/**
|
|
2947
3988
|
* Fetch and merge context across every scope with an identifier, in one call.
|
|
@@ -2975,9 +4016,11 @@ var SynapClient = class {
|
|
|
2975
4016
|
include_scope_labels: includeScopeLabels = false,
|
|
2976
4017
|
context_mode: contextMode = "in-conversation",
|
|
2977
4018
|
include_profile: includeProfile = true,
|
|
2978
|
-
last_n_conversations: lastNConversations = 1
|
|
4019
|
+
last_n_conversations: lastNConversations = 1,
|
|
4020
|
+
response_shape: responseShape = "by_type"
|
|
2979
4021
|
} = options;
|
|
2980
4022
|
validateConversationId(conversationId);
|
|
4023
|
+
responseShapeOf({ response_shape: responseShape });
|
|
2981
4024
|
const wants = (scope) => scopes === void 0 || scopes.includes(scope);
|
|
2982
4025
|
const shared = {
|
|
2983
4026
|
search_query: searchQuery,
|
|
@@ -2989,7 +4032,8 @@ var SynapClient = class {
|
|
|
2989
4032
|
// threaded three call sites by hand and missed the client branch, which
|
|
2990
4033
|
// sits one indent deeper; spreading removes that whole class of miss.
|
|
2991
4034
|
query_date: queryDate,
|
|
2992
|
-
max_results_per_query: maxResultsPerQuery
|
|
4035
|
+
max_results_per_query: maxResultsPerQuery,
|
|
4036
|
+
response_shape: responseShape
|
|
2993
4037
|
};
|
|
2994
4038
|
const labels = [];
|
|
2995
4039
|
const tasks = [];
|
|
@@ -3054,7 +4098,7 @@ var SynapClient = class {
|
|
|
3054
4098
|
merged.conversation_context = await this.conversation.context.get_context_for_prompt({
|
|
3055
4099
|
conversation_id: conversationId
|
|
3056
4100
|
});
|
|
3057
|
-
} catch (
|
|
4101
|
+
} catch (e17) {
|
|
3058
4102
|
}
|
|
3059
4103
|
}
|
|
3060
4104
|
merged.formatted_context = formatForPrompt(merged, {
|
|
@@ -3106,7 +4150,7 @@ var SynapClient = class {
|
|
|
3106
4150
|
// not carry the caller's words.
|
|
3107
4151
|
query_count: distinctQueryCount(_nullishCoalesce(options["search_query"], () => ( options["searchQuery"])))
|
|
3108
4152
|
});
|
|
3109
|
-
} catch (
|
|
4153
|
+
} catch (e18) {
|
|
3110
4154
|
}
|
|
3111
4155
|
}
|
|
3112
4156
|
/**
|
|
@@ -3131,7 +4175,7 @@ var SynapClient = class {
|
|
|
3131
4175
|
}),
|
|
3132
4176
|
scope
|
|
3133
4177
|
});
|
|
3134
|
-
} catch (
|
|
4178
|
+
} catch (e19) {
|
|
3135
4179
|
}
|
|
3136
4180
|
}
|
|
3137
4181
|
/**
|
|
@@ -3152,25 +4196,139 @@ var SynapClient = class {
|
|
|
3152
4196
|
/**
|
|
3153
4197
|
* Whether the SDK is authoritative for short-term context.
|
|
3154
4198
|
*
|
|
3155
|
-
* Resolution order matches Python's `_is_st_authoritative`:
|
|
3156
|
-
*
|
|
3157
|
-
*
|
|
4199
|
+
* Resolution order matches Python's `_is_st_authoritative`:
|
|
4200
|
+
* `SYNAP_SDK_ST_AUTHORITATIVE` first, as an explicit override in either
|
|
4201
|
+
* direction, then the option. Off by default. Being enabled does not mean
|
|
4202
|
+
* the local store is used: that also takes an entry that holds the whole
|
|
4203
|
+
* conversation, see `isComplete`.
|
|
3158
4204
|
*/
|
|
3159
4205
|
#isStAuthoritative() {
|
|
3160
|
-
if (this.#stAuthoritative === true) return true;
|
|
3161
4206
|
const raw = (_nullishCoalesce(_chunkZKOJDUN4cjs.getEnv.call(void 0, "SYNAP_SDK_ST_AUTHORITATIVE"), () => ( ""))).trim().toLowerCase();
|
|
3162
|
-
|
|
4207
|
+
if (["0", "false", "no", "off"].includes(raw)) return false;
|
|
4208
|
+
if (["1", "true", "yes", "on"].includes(raw)) return true;
|
|
4209
|
+
return this.#stAuthoritative === true;
|
|
3163
4210
|
}
|
|
3164
4211
|
/**
|
|
3165
4212
|
* Render `get_context_for_prompt` from the local store, or null to fall
|
|
3166
|
-
* through to the network.
|
|
3167
|
-
*
|
|
3168
|
-
*
|
|
4213
|
+
* through to the network.
|
|
4214
|
+
*
|
|
4215
|
+
* The store answers only when it holds the whole conversation: the server
|
|
4216
|
+
* has confirmed a count the entry accounts for. An entry that is merely
|
|
4217
|
+
* present is not enough. After a restart or an eviction it holds one turn,
|
|
4218
|
+
* and rendering that as the conversation drops everything said before it.
|
|
4219
|
+
*/
|
|
4220
|
+
/**
|
|
4221
|
+
* `response` with the earlier turns that best match `query` (by default the
|
|
4222
|
+
* latest user message) appended, when a compaction exists. The search runs
|
|
4223
|
+
* here, over the turn archive. Python: `_with_history_excerpts`.
|
|
3169
4224
|
*/
|
|
4225
|
+
async #withHistoryExcerpts(conversationId, response, query) {
|
|
4226
|
+
const r = _nullishCoalesce(response, () => ( {}));
|
|
4227
|
+
const store = this.#turnStore;
|
|
4228
|
+
const recent = Array.isArray(r["recent_messages"]) ? r["recent_messages"] : [];
|
|
4229
|
+
store.addMany(
|
|
4230
|
+
conversationId,
|
|
4231
|
+
recent.map((m) => ({
|
|
4232
|
+
role: String(_nullishCoalesce(m["role"], () => ( "user"))),
|
|
4233
|
+
content: String(_nullishCoalesce(m["content"], () => ( ""))),
|
|
4234
|
+
timestamp: String(_nullishCoalesce(m["timestamp"], () => ( ""))),
|
|
4235
|
+
message_id: typeof m["message_id"] === "string" ? m["message_id"] : null
|
|
4236
|
+
}))
|
|
4237
|
+
);
|
|
4238
|
+
const entry = this.#shortTerm.get(conversationId);
|
|
4239
|
+
const total = Math.max(Number(_nullishCoalesce(r["total_message_count"], () => ( 0))) || 0, Number(_nullishCoalesce(_optionalChain([entry, 'optionalAccess', _70 => _70.serverMessageCount]), () => ( 0))) || 0);
|
|
4240
|
+
this.#maybeBackfillTurns(conversationId, total);
|
|
4241
|
+
if (!r["context_block"]) return response;
|
|
4242
|
+
const turns = store.turns(conversationId);
|
|
4243
|
+
let q = query;
|
|
4244
|
+
if (!q) {
|
|
4245
|
+
const latest = [...recent].reverse().find((m) => m["role"] === "user");
|
|
4246
|
+
q = latest ? String(_nullishCoalesce(latest["content"], () => ( ""))) : _nullishCoalesce(_optionalChain([[...turns], 'access', _71 => _71.reverse, 'call', _72 => _72(), 'access', _73 => _73.find, 'call', _74 => _74((t) => t.role === "user"), 'optionalAccess', _75 => _75.content]), () => ( ""));
|
|
4247
|
+
}
|
|
4248
|
+
if (!q) return response;
|
|
4249
|
+
const exclude = /* @__PURE__ */ new Set();
|
|
4250
|
+
for (const m of recent) {
|
|
4251
|
+
if (typeof m["message_id"] === "string" && m["message_id"]) exclude.add(m["message_id"]);
|
|
4252
|
+
exclude.add(String(_nullishCoalesce(m["content"], () => ( ""))));
|
|
4253
|
+
}
|
|
4254
|
+
this.#startLocalModel();
|
|
4255
|
+
const hits = await searchTurns(turns, q, { exclude, encoder: this.#localEncoder, store });
|
|
4256
|
+
if (hits.length === 0) return response;
|
|
4257
|
+
const block = renderExcerpts(hits, turns.length ? turns[turns.length - 1].timestamp : "");
|
|
4258
|
+
return {
|
|
4259
|
+
...r,
|
|
4260
|
+
history_excerpts: hits.map((h) => ({ position: h.position, role: h.role, text: h.text })),
|
|
4261
|
+
history_block: block,
|
|
4262
|
+
formatted_context: (String(_nullishCoalesce(r["formatted_context"], () => ( ""))).trimEnd() + "\n\n" + block).trim()
|
|
4263
|
+
};
|
|
4264
|
+
}
|
|
4265
|
+
/**
|
|
4266
|
+
* Keep what a tool returned in this process's turn archive, so history search
|
|
4267
|
+
* can find it after a compaction. Never sent anywhere: the server's
|
|
4268
|
+
* conversation holds what people said, and a compaction is made from that.
|
|
4269
|
+
* `instance.record_tool_result` calls this too. Python: `archive_tool_result`.
|
|
4270
|
+
*/
|
|
4271
|
+
archive_tool_result(conversationId, result, options = {}) {
|
|
4272
|
+
if (!conversationId || result === null || result === void 0) return;
|
|
4273
|
+
try {
|
|
4274
|
+
this.#turnStore.add(
|
|
4275
|
+
conversationId,
|
|
4276
|
+
"tool",
|
|
4277
|
+
toolResultText(result, _nullishCoalesce(options.tool_name, () => ( options.toolName))),
|
|
4278
|
+
_nullishCoalesce(options.timestamp, () => ( (/* @__PURE__ */ new Date()).toISOString()))
|
|
4279
|
+
);
|
|
4280
|
+
} catch (e20) {
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
static __initStatic() {this.BACKFILL_COOLDOWN_MS = 6e4}
|
|
4284
|
+
static __initStatic2() {this.BACKFILL_PAGE = 500}
|
|
4285
|
+
/** Fetch, in the background, turns the server holds and the archive does not. */
|
|
4286
|
+
/**
|
|
4287
|
+
* Load the local embedding model in the background, once. Searches and
|
|
4288
|
+
* lookups before it is ready match by words. Python: `_start_history_encoder`.
|
|
4289
|
+
*/
|
|
4290
|
+
#startLocalModel() {
|
|
4291
|
+
if (this.#localModelStarted) return;
|
|
4292
|
+
this.#localModelStarted = true;
|
|
4293
|
+
if (localModelOff()) return;
|
|
4294
|
+
const name = this.#localModelName === "auto" ? _chunkICUFS3B5cjs.SEMANTIC_MATCH.model : this.#localModelName;
|
|
4295
|
+
if (!name) return;
|
|
4296
|
+
const callerEncoder = this.#localEncoder;
|
|
4297
|
+
void Promise.resolve().then(() => _interopRequireWildcard(require("./onnx-encoder-4RSL6ID4.cjs"))).then(({ canRunLocalModel, loadOnnxEncoder }) => canRunLocalModel() ? loadOnnxEncoder(name) : null).then((encoder) => {
|
|
4298
|
+
if (encoder === null) return;
|
|
4299
|
+
if (callerEncoder === null) this.#localEncoder = encoder;
|
|
4300
|
+
if (encoder.model === _chunkICUFS3B5cjs.SEMANTIC_MATCH.model) this.#anticipationCache.setEncoder(encoder);
|
|
4301
|
+
}).catch(() => {
|
|
4302
|
+
});
|
|
4303
|
+
}
|
|
4304
|
+
#maybeBackfillTurns(conversationId, total) {
|
|
4305
|
+
if (total <= this.#turnStore.count(conversationId)) return;
|
|
4306
|
+
const now = Date.now();
|
|
4307
|
+
if (now < (_nullishCoalesce(this.#backfillAfter.get(conversationId), () => ( 0)))) return;
|
|
4308
|
+
this.#backfillAfter.set(conversationId, now + _SynapClient.BACKFILL_COOLDOWN_MS);
|
|
4309
|
+
void this.#backfillTurns(conversationId, total);
|
|
4310
|
+
}
|
|
4311
|
+
async #backfillTurns(conversationId, total) {
|
|
4312
|
+
try {
|
|
4313
|
+
let start = 1;
|
|
4314
|
+
while (start <= total) {
|
|
4315
|
+
const result = await this.#transport.request("conversation_turns", {
|
|
4316
|
+
pathParams: { conversation_id: conversationId },
|
|
4317
|
+
query: { start, limit: _SynapClient.BACKFILL_PAGE }
|
|
4318
|
+
});
|
|
4319
|
+
const page = _nullishCoalesce((_nullishCoalesce(result, () => ( {})))["turns"], () => ( []));
|
|
4320
|
+
this.#turnStore.addMany(conversationId, page);
|
|
4321
|
+
if (page.length < _SynapClient.BACKFILL_PAGE) break;
|
|
4322
|
+
start += _SynapClient.BACKFILL_PAGE;
|
|
4323
|
+
}
|
|
4324
|
+
} catch (error) {
|
|
4325
|
+
this.#warn(`Turn backfill for ${conversationId} failed: ${String(error)}`);
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
3170
4328
|
#localPrompt(conversationId, style) {
|
|
3171
4329
|
if (!this.#isStAuthoritative()) return null;
|
|
3172
4330
|
const entry = this.#shortTerm.get(conversationId);
|
|
3173
|
-
if (entry === null) return null;
|
|
4331
|
+
if (entry === null || !isComplete(entry)) return null;
|
|
3174
4332
|
if (entry.compactionId === null && entry.recentTurns.length === 0) return null;
|
|
3175
4333
|
return renderForPrompt(entry, style);
|
|
3176
4334
|
}
|
|
@@ -3178,9 +4336,29 @@ var SynapClient = class {
|
|
|
3178
4336
|
#localCompacted(conversationId, format) {
|
|
3179
4337
|
if (!this.#isStAuthoritative()) return null;
|
|
3180
4338
|
const entry = this.#shortTerm.get(conversationId);
|
|
3181
|
-
if (entry === null || entry.compactionId === null) return null;
|
|
4339
|
+
if (entry === null || entry.compactionId === null || !isComplete(entry)) return null;
|
|
3182
4340
|
return renderCompacted(entry, format);
|
|
3183
4341
|
}
|
|
4342
|
+
/**
|
|
4343
|
+
* Bring the local store back in step from the server's answer.
|
|
4344
|
+
*
|
|
4345
|
+
* Only for a conversation this process writes to. The server's answer lists
|
|
4346
|
+
* every message its summary does not cover, which is exactly what the entry
|
|
4347
|
+
* was missing.
|
|
4348
|
+
*/
|
|
4349
|
+
#reseedShortTerm(conversationId, response) {
|
|
4350
|
+
if (!this.#isStAuthoritative()) return;
|
|
4351
|
+
const entry = this.#shortTerm.get(conversationId);
|
|
4352
|
+
if (entry === null || !entry.participant) return;
|
|
4353
|
+
const r = _nullishCoalesce(response, () => ( {}));
|
|
4354
|
+
const recent = Array.isArray(r["recent_messages"]) ? r["recent_messages"] : [];
|
|
4355
|
+
this.#shortTerm.reseed(conversationId, {
|
|
4356
|
+
compactionId: typeof r["compaction_id"] === "string" ? r["compaction_id"] : null,
|
|
4357
|
+
recentMessages: recent,
|
|
4358
|
+
compactedMessageCount: Number(_nullishCoalesce(r["compacted_message_count"], () => ( 0))) || 0,
|
|
4359
|
+
totalMessageCount: Number(_nullishCoalesce(r["total_message_count"], () => ( 0))) || 0
|
|
4360
|
+
});
|
|
4361
|
+
}
|
|
3184
4362
|
/** Every diagnostic the SDK emits passes through here. */
|
|
3185
4363
|
#warn(message) {
|
|
3186
4364
|
if (this.#logger !== void 0) {
|
|
@@ -3201,7 +4379,7 @@ var SynapClient = class {
|
|
|
3201
4379
|
this.#transport.close();
|
|
3202
4380
|
this.#anticipationCache.clear();
|
|
3203
4381
|
}
|
|
3204
|
-
};
|
|
4382
|
+
}, _class4.__initStatic(), _class4.__initStatic2(), _class4);
|
|
3205
4383
|
function pick3(o2, snake, camel) {
|
|
3206
4384
|
const a = o2[snake];
|
|
3207
4385
|
return a !== void 0 ? a : o2[camel];
|
|
@@ -3209,7 +4387,7 @@ function pick3(o2, snake, camel) {
|
|
|
3209
4387
|
function resolveBaseUrl(options) {
|
|
3210
4388
|
const explicit = _nullishCoalesce(options.baseUrl, () => ( options.api_base_url));
|
|
3211
4389
|
if (explicit !== void 0) return explicit;
|
|
3212
|
-
const fromEnv = _optionalChain([_chunkZKOJDUN4cjs.getEnv.call(void 0, "SYNAP_BASE_URL"), 'optionalAccess',
|
|
4390
|
+
const fromEnv = _optionalChain([_chunkZKOJDUN4cjs.getEnv.call(void 0, "SYNAP_BASE_URL"), 'optionalAccess', _76 => _76.trim, 'call', _77 => _77()]);
|
|
3213
4391
|
return fromEnv !== void 0 && fromEnv !== "" ? fromEnv : void 0;
|
|
3214
4392
|
}
|
|
3215
4393
|
function resolveCredentials(options) {
|
|
@@ -3277,5 +4455,11 @@ function resolveCredentials(options) {
|
|
|
3277
4455
|
|
|
3278
4456
|
|
|
3279
4457
|
|
|
3280
|
-
|
|
4458
|
+
|
|
4459
|
+
|
|
4460
|
+
|
|
4461
|
+
|
|
4462
|
+
|
|
4463
|
+
|
|
4464
|
+
exports.ANY_SCOPE = _chunkICUFS3B5cjs.ANY_SCOPE; exports.AgentUnavailableError = _chunkT372OL3Qcjs.AgentUnavailableError; exports.AnticipationCache = _chunkICUFS3B5cjs.AnticipationCache; exports.AuthenticationError = _chunkT372OL3Qcjs.AuthenticationError; exports.BM25 = _chunkICUFS3B5cjs.BM25; exports.COMPACTION_LEVELS = COMPACTION_LEVELS; exports.CONTRACT = _chunkICUFS3B5cjs.CONTRACT; exports.ConflictError = _chunkT372OL3Qcjs.ConflictError; exports.ConnectionError = _chunkT372OL3Qcjs.ConnectionError; exports.ContextNotFoundError = _chunkT372OL3Qcjs.ContextNotFoundError; exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL; exports.DEFAULT_DOCUMENT_TYPE = DEFAULT_DOCUMENT_TYPE; exports.DEFAULT_INGEST_MODE = DEFAULT_INGEST_MODE; exports.DEFAULT_RETRY_POLICY = DEFAULT_RETRY_POLICY; exports.DEFAULT_TIMEOUTS = DEFAULT_TIMEOUTS; exports.DOCUMENT_TYPES = DOCUMENT_TYPES; exports.ENDPOINTS = ENDPOINTS; exports.EXCERPT_CATEGORY = EXCERPT_CATEGORY; exports.FORGET_MODES = FORGET_MODES; exports.HttpTransport = HttpTransport; exports.INGEST_MODES = INGEST_MODES; exports.ITEM_COLLECTIONS = ITEM_COLLECTIONS; exports.InsufficientCreditsError = _chunkT372OL3Qcjs.InsufficientCreditsError; exports.InvalidConversationIdError = _chunkT372OL3Qcjs.InvalidConversationIdError; exports.InvalidInputError = _chunkT372OL3Qcjs.InvalidInputError; exports.InvalidInstanceIdError = _chunkT372OL3Qcjs.InvalidInstanceIdError; exports.ListeningAlreadyActiveError = _chunkT372OL3Qcjs.ListeningAlreadyActiveError; exports.ListeningNotActiveError = _chunkT372OL3Qcjs.ListeningNotActiveError; exports.MEMORY_TYPES = MEMORY_TYPES; exports.NetworkTimeoutError = _chunkT372OL3Qcjs.NetworkTimeoutError; exports.PermanentError = _chunkT372OL3Qcjs.PermanentError; exports.RESPONSE_SHAPES = RESPONSE_SHAPES; exports.RateLimitError = _chunkT372OL3Qcjs.RateLimitError; exports.SDKError = _chunkT372OL3Qcjs.SDKError; exports.SDK_VERSION = SDK_VERSION; exports.ServiceUnavailableError = _chunkT372OL3Qcjs.ServiceUnavailableError; exports.SessionExpiredError = _chunkT372OL3Qcjs.SessionExpiredError; exports.SynapClient = SynapClient; exports.SynapError = _chunkT372OL3Qcjs.SynapError; exports.SynapPermanentError = _chunkT372OL3Qcjs.SynapPermanentError; exports.SynapTransientError = _chunkT372OL3Qcjs.SynapTransientError; exports.THRESHOLDS = _chunkICUFS3B5cjs.THRESHOLDS; exports.TranscriptConflictError = _chunkT372OL3Qcjs.TranscriptConflictError; exports.TransientError = _chunkT372OL3Qcjs.TransientError; exports.applyResponseShape = applyResponseShape; exports.flattenContextItems = flattenContextItems; exports.formatForPrompt = formatForPrompt; exports.isOutcomeUnknown = isOutcomeUnknown; exports.isRecallQuery = _chunkICUFS3B5cjs.isRecallQuery; exports.isSynapError = _chunkT372OL3Qcjs.isSynapError; exports.mergeScopeResults = mergeScopeResults; exports.rankItems = rankItems; exports.resolvePath = resolvePath; exports.shouldRetry = shouldRetry; exports.stem = _chunkICUFS3B5cjs.stem; exports.tokenize = _chunkICUFS3B5cjs.tokenize; exports.wireRankScore = wireRankScore;
|
|
3281
4465
|
//# sourceMappingURL=index.cjs.map
|