@seanhogg/builderforce-memory 2026.7.12 → 2026.9.27
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 +10 -0
- package/dist/bridges/AnthropicBridge.d.ts +9 -1
- package/dist/bridges/AnthropicBridge.d.ts.map +1 -1
- package/dist/bridges/AnthropicBridge.js +58 -2
- package/dist/bridges/AnthropicBridge.js.map +1 -1
- package/dist/bridges/CachingBridge.d.ts +9 -1
- package/dist/bridges/CachingBridge.d.ts.map +1 -1
- package/dist/bridges/CachingBridge.js +24 -1
- package/dist/bridges/CachingBridge.js.map +1 -1
- package/dist/bridges/OpenAIBridge.d.ts +4 -1
- package/dist/bridges/OpenAIBridge.d.ts.map +1 -1
- package/dist/bridges/OpenAIBridge.js +40 -2
- package/dist/bridges/OpenAIBridge.js.map +1 -1
- package/dist/bridges/SemanticCachingBridge.d.ts +8 -1
- package/dist/bridges/SemanticCachingBridge.d.ts.map +1 -1
- package/dist/bridges/SemanticCachingBridge.js +26 -1
- package/dist/bridges/SemanticCachingBridge.js.map +1 -1
- package/dist/bridges/TransformerBridge.d.ts +13 -0
- package/dist/bridges/TransformerBridge.d.ts.map +1 -1
- package/dist/bridges/VertexAIBridge.d.ts +102 -0
- package/dist/bridges/VertexAIBridge.d.ts.map +1 -0
- package/dist/bridges/VertexAIBridge.js +224 -0
- package/dist/bridges/VertexAIBridge.js.map +1 -0
- package/dist/bridges/index.d.ts +3 -1
- package/dist/bridges/index.d.ts.map +1 -1
- package/dist/bridges/index.js +1 -0
- package/dist/bridges/index.js.map +1 -1
- package/dist/eval/EvalHarness.d.ts +37 -0
- package/dist/eval/EvalHarness.d.ts.map +1 -0
- package/dist/eval/EvalHarness.js +178 -0
- package/dist/eval/EvalHarness.js.map +1 -0
- package/dist/eval/graders.d.ts +76 -0
- package/dist/eval/graders.d.ts.map +1 -0
- package/dist/eval/graders.js +168 -0
- package/dist/eval/graders.js.map +1 -0
- package/dist/eval/index.d.ts +26 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +26 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/types.d.ts +97 -0
- package/dist/eval/types.d.ts.map +1 -0
- package/dist/eval/types.js +5 -0
- package/dist/eval/types.js.map +1 -0
- package/dist/evermind/contract.d.ts +40 -0
- package/dist/evermind/contract.d.ts.map +1 -0
- package/dist/evermind/contract.js +13 -0
- package/dist/evermind/contract.js.map +1 -0
- package/dist/evermind/index.d.ts +15 -0
- package/dist/evermind/index.d.ts.map +1 -0
- package/dist/evermind/index.js +4 -0
- package/dist/evermind/index.js.map +1 -0
- package/dist/evermind/memoryBlock.d.ts +7 -0
- package/dist/evermind/memoryBlock.d.ts.map +1 -0
- package/dist/evermind/memoryBlock.js +37 -0
- package/dist/evermind/memoryBlock.js.map +1 -0
- package/dist/evermind/recall.d.ts +55 -0
- package/dist/evermind/recall.d.ts.map +1 -0
- package/dist/evermind/recall.js +105 -0
- package/dist/evermind/recall.js.map +1 -0
- package/dist/index.d.ts +18 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/ingest/IngestionPipeline.d.ts +95 -0
- package/dist/ingest/IngestionPipeline.d.ts.map +1 -0
- package/dist/ingest/IngestionPipeline.js +295 -0
- package/dist/ingest/IngestionPipeline.js.map +1 -0
- package/dist/ingest/index.d.ts +10 -0
- package/dist/ingest/index.d.ts.map +1 -0
- package/dist/ingest/index.js +8 -0
- package/dist/ingest/index.js.map +1 -0
- package/dist/ingest/parsers.d.ts +53 -0
- package/dist/ingest/parsers.d.ts.map +1 -0
- package/dist/ingest/parsers.js +306 -0
- package/dist/ingest/parsers.js.map +1 -0
- package/dist/ingest/types.d.ts +114 -0
- package/dist/ingest/types.d.ts.map +1 -0
- package/dist/ingest/types.js +19 -0
- package/dist/ingest/types.js.map +1 -0
- package/dist/memory/MemoryStore.d.ts +33 -0
- package/dist/memory/MemoryStore.d.ts.map +1 -1
- package/dist/memory/MemoryStore.js +29 -3
- package/dist/memory/MemoryStore.js.map +1 -1
- package/dist/memory/index.d.ts +1 -1
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/orchestration/AgentGraph.d.ts +104 -0
- package/dist/orchestration/AgentGraph.d.ts.map +1 -0
- package/dist/orchestration/AgentGraph.js +364 -0
- package/dist/orchestration/AgentGraph.js.map +1 -0
- package/dist/orchestration/checkpoint.d.ts +58 -0
- package/dist/orchestration/checkpoint.d.ts.map +1 -0
- package/dist/orchestration/checkpoint.js +92 -0
- package/dist/orchestration/checkpoint.js.map +1 -0
- package/dist/orchestration/index.d.ts +14 -0
- package/dist/orchestration/index.d.ts.map +1 -0
- package/dist/orchestration/index.js +10 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/patterns.d.ts +159 -0
- package/dist/orchestration/patterns.d.ts.map +1 -0
- package/dist/orchestration/patterns.js +371 -0
- package/dist/orchestration/patterns.js.map +1 -0
- package/dist/orchestration/types.d.ts +146 -0
- package/dist/orchestration/types.d.ts.map +1 -0
- package/dist/orchestration/types.js +20 -0
- package/dist/orchestration/types.js.map +1 -0
- package/dist/rag/EnterpriseRetriever.d.ts +114 -0
- package/dist/rag/EnterpriseRetriever.d.ts.map +1 -0
- package/dist/rag/EnterpriseRetriever.js +240 -0
- package/dist/rag/EnterpriseRetriever.js.map +1 -0
- package/dist/rag/index.d.ts +6 -0
- package/dist/rag/index.d.ts.map +1 -0
- package/dist/rag/index.js +5 -0
- package/dist/rag/index.js.map +1 -0
- package/dist/retrieval/bm25.d.ts +48 -1
- package/dist/retrieval/bm25.d.ts.map +1 -1
- package/dist/retrieval/bm25.js +59 -13
- package/dist/retrieval/bm25.js.map +1 -1
- package/dist/retrieval/index.d.ts +2 -2
- package/dist/retrieval/index.d.ts.map +1 -1
- package/dist/retrieval/index.js +1 -1
- package/dist/retrieval/index.js.map +1 -1
- package/dist/telemetry/InstrumentedBridge.d.ts +62 -0
- package/dist/telemetry/InstrumentedBridge.d.ts.map +1 -0
- package/dist/telemetry/InstrumentedBridge.js +120 -0
- package/dist/telemetry/InstrumentedBridge.js.map +1 -0
- package/dist/telemetry/MetricsRegistry.d.ts +88 -0
- package/dist/telemetry/MetricsRegistry.d.ts.map +1 -0
- package/dist/telemetry/MetricsRegistry.js +167 -0
- package/dist/telemetry/MetricsRegistry.js.map +1 -0
- package/dist/telemetry/Tracer.d.ts +137 -0
- package/dist/telemetry/Tracer.d.ts.map +1 -0
- package/dist/telemetry/Tracer.js +244 -0
- package/dist/telemetry/Tracer.js.map +1 -0
- package/dist/telemetry/exporters.d.ts +68 -0
- package/dist/telemetry/exporters.d.ts.map +1 -0
- package/dist/telemetry/exporters.js +145 -0
- package/dist/telemetry/exporters.js.map +1 -0
- package/dist/telemetry/index.d.ts +19 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +12 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/pricing.d.ts +74 -0
- package/dist/telemetry/pricing.d.ts.map +1 -0
- package/dist/telemetry/pricing.js +98 -0
- package/dist/telemetry/pricing.js.map +1 -0
- package/dist/telemetry/traceparent.d.ts +50 -0
- package/dist/telemetry/traceparent.d.ts.map +1 -0
- package/dist/telemetry/traceparent.js +77 -0
- package/dist/telemetry/traceparent.js.map +1 -0
- package/dist/telemetry/types.d.ts +90 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +17 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/vectorstore/MemoryVectorStore.d.ts +72 -0
- package/dist/vectorstore/MemoryVectorStore.d.ts.map +1 -0
- package/dist/vectorstore/MemoryVectorStore.js +205 -0
- package/dist/vectorstore/MemoryVectorStore.js.map +1 -0
- package/dist/vectorstore/RestVectorStore.d.ts +79 -0
- package/dist/vectorstore/RestVectorStore.d.ts.map +1 -0
- package/dist/vectorstore/RestVectorStore.js +170 -0
- package/dist/vectorstore/RestVectorStore.js.map +1 -0
- package/dist/vectorstore/dialects.d.ts +101 -0
- package/dist/vectorstore/dialects.d.ts.map +1 -0
- package/dist/vectorstore/dialects.js +618 -0
- package/dist/vectorstore/dialects.js.map +1 -0
- package/dist/vectorstore/filter.d.ts +42 -0
- package/dist/vectorstore/filter.d.ts.map +1 -0
- package/dist/vectorstore/filter.js +132 -0
- package/dist/vectorstore/filter.js.map +1 -0
- package/dist/vectorstore/index.d.ts +15 -0
- package/dist/vectorstore/index.d.ts.map +1 -0
- package/dist/vectorstore/index.js +11 -0
- package/dist/vectorstore/index.js.map +1 -0
- package/dist/vectorstore/types.d.ts +151 -0
- package/dist/vectorstore/types.d.ts.map +1 -0
- package/dist/vectorstore/types.js +30 -0
- package/dist/vectorstore/types.js.map +1 -0
- package/package.json +39 -5
- package/src/bridges/AnthropicBridge.ts +68 -3
- package/src/bridges/CachingBridge.ts +28 -2
- package/src/bridges/OpenAIBridge.ts +48 -3
- package/src/bridges/SemanticCachingBridge.ts +29 -2
- package/src/bridges/TransformerBridge.ts +16 -0
- package/src/bridges/VertexAIBridge.ts +297 -0
- package/src/bridges/index.ts +3 -1
- package/src/eval/EvalHarness.ts +214 -0
- package/src/eval/graders.ts +218 -0
- package/src/eval/index.ts +26 -0
- package/src/eval/types.ts +107 -0
- package/src/evermind/contract.ts +39 -0
- package/src/evermind/index.ts +21 -0
- package/src/evermind/memoryBlock.ts +38 -0
- package/src/evermind/recall.ts +122 -0
- package/src/index.ts +232 -0
- package/src/ingest/IngestionPipeline.ts +378 -0
- package/src/ingest/index.ts +46 -0
- package/src/ingest/parsers.ts +318 -0
- package/src/ingest/types.ts +116 -0
- package/src/memory/MemoryStore.ts +55 -3
- package/src/memory/index.ts +1 -1
- package/src/orchestration/AgentGraph.ts +462 -0
- package/src/orchestration/checkpoint.ts +129 -0
- package/src/orchestration/index.ts +63 -0
- package/src/orchestration/patterns.ts +532 -0
- package/src/orchestration/types.ts +128 -0
- package/src/rag/EnterpriseRetriever.ts +348 -0
- package/src/rag/index.ts +18 -0
- package/src/retrieval/bm25.ts +71 -13
- package/src/retrieval/index.ts +2 -2
- package/src/telemetry/InstrumentedBridge.ts +152 -0
- package/src/telemetry/MetricsRegistry.ts +263 -0
- package/src/telemetry/Tracer.ts +310 -0
- package/src/telemetry/exporters.ts +187 -0
- package/src/telemetry/index.ts +56 -0
- package/src/telemetry/pricing.ts +129 -0
- package/src/telemetry/traceparent.ts +89 -0
- package/src/telemetry/types.ts +105 -0
- package/src/vectorstore/MemoryVectorStore.ts +250 -0
- package/src/vectorstore/RestVectorStore.ts +236 -0
- package/src/vectorstore/dialects.ts +702 -0
- package/src/vectorstore/filter.ts +148 -0
- package/src/vectorstore/index.ts +53 -0
- package/src/vectorstore/types.ts +149 -0
package/README.md
CHANGED
|
@@ -69,6 +69,16 @@ Generic build step types (compose your own pipeline via the step registry):
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
+
## Evermind recall contract (`@seanhogg/builderforce-memory/evermind`)
|
|
73
|
+
|
|
74
|
+
A dependency-free subpath a browser chat client can import without the rest of the runtime:
|
|
75
|
+
|
|
76
|
+
- `EvermindRecallItem`, `EvermindRecallResult` — what a project Evermind recall returns.
|
|
77
|
+
- `rankEvermindRecall`, `recallTokens`, `hashRecallQuery` — the lexical recall ranker.
|
|
78
|
+
- `countReconciledMemories` — which recalled memories an answer restates (write-through reconcile).
|
|
79
|
+
- `formatEvermindMemoryBlock` — the recalled-memory prompt block, each item neutralised with `sanitizeRecalledFact`.
|
|
80
|
+
- `EVERMIND_MIN_TEACH_CHARS` — the teach floor below which a turn is never contributed.
|
|
81
|
+
|
|
72
82
|
## Installation
|
|
73
83
|
|
|
74
84
|
```bash
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Uses the /v1/messages endpoint. System prompts are passed as the top-level
|
|
5
5
|
* `system` field (not a message role), per the Anthropic spec.
|
|
6
6
|
*/
|
|
7
|
-
import type { TransformerBridge, BridgeGenerateOptions } from './TransformerBridge.js';
|
|
7
|
+
import type { TransformerBridge, BridgeGenerateOptions, BridgeCallInfo } from './TransformerBridge.js';
|
|
8
8
|
export interface AnthropicBridgeOptions {
|
|
9
9
|
/** Anthropic API key. */
|
|
10
10
|
apiKey: string;
|
|
@@ -38,7 +38,15 @@ export declare class AnthropicBridge implements TransformerBridge {
|
|
|
38
38
|
private readonly _systemPrompt;
|
|
39
39
|
private readonly _maxTokens;
|
|
40
40
|
private readonly _cacheSystem;
|
|
41
|
+
private _lastCall;
|
|
41
42
|
constructor(opts: AnthropicBridgeOptions);
|
|
43
|
+
/**
|
|
44
|
+
* Provider-reported usage for the last call. Anthropic splits input tokens
|
|
45
|
+
* three ways — fresh, cache read, and cache write — and each is billed at a
|
|
46
|
+
* different rate, so a cost model that only reads `input_tokens` is wrong on
|
|
47
|
+
* exactly the cache-heavy traffic this bridge is tuned to produce.
|
|
48
|
+
*/
|
|
49
|
+
get lastCall(): BridgeCallInfo | undefined;
|
|
42
50
|
generate(prompt: string, opts?: BridgeGenerateOptions): Promise<string>;
|
|
43
51
|
stream(prompt: string, opts?: BridgeGenerateOptions): AsyncIterable<string>;
|
|
44
52
|
private _buildBody;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnthropicBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/AnthropicBridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"AnthropicBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/AnthropicBridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEvG,MAAM,WAAW,sBAAsB;IACnC,yBAAyB;IACzB,MAAM,EAAU,MAAM,CAAC;IACvB;;;;OAIG;IACH,KAAK,CAAC,EAAU,MAAM,CAAC;IACvB,2DAA2D;IAC3D,UAAU,CAAC,EAAK,MAAM,CAAC;IACvB,4CAA4C;IAC5C,YAAY,CAAC,EAAG,MAAM,CAAC;IACvB,iEAAiE;IACjE,SAAS,CAAC,EAAM,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAI,OAAO,CAAC;CAC3B;AAID,qBAAa,eAAgB,YAAW,iBAAiB;IACrD,QAAQ,CAAC,iBAAiB,EAAG,IAAI,CAAU;IAE3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAW;IAExC,OAAO,CAAC,SAAS,CAA6B;gBAElC,IAAI,EAAE,sBAAsB;IASxC;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,cAAc,GAAG,SAAS,CAEzC;IAEK,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC;IA0B1E,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,aAAa,CAAC,MAAM,CAAC;IA4CtF,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,MAAM;CAWjB"}
|
|
@@ -14,6 +14,7 @@ export class AnthropicBridge {
|
|
|
14
14
|
_systemPrompt;
|
|
15
15
|
_maxTokens;
|
|
16
16
|
_cacheSystem;
|
|
17
|
+
_lastCall;
|
|
17
18
|
constructor(opts) {
|
|
18
19
|
this._apiKey = opts.apiKey;
|
|
19
20
|
this._model = opts.model ?? 'claude-haiku-4-5';
|
|
@@ -22,6 +23,15 @@ export class AnthropicBridge {
|
|
|
22
23
|
this._maxTokens = opts.maxTokens ?? 1024;
|
|
23
24
|
this._cacheSystem = opts.cacheSystem ?? true;
|
|
24
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Provider-reported usage for the last call. Anthropic splits input tokens
|
|
28
|
+
* three ways — fresh, cache read, and cache write — and each is billed at a
|
|
29
|
+
* different rate, so a cost model that only reads `input_tokens` is wrong on
|
|
30
|
+
* exactly the cache-heavy traffic this bridge is tuned to produce.
|
|
31
|
+
*/
|
|
32
|
+
get lastCall() {
|
|
33
|
+
return this._lastCall;
|
|
34
|
+
}
|
|
25
35
|
async generate(prompt, opts = {}) {
|
|
26
36
|
const body = this._buildBody(prompt, opts, false);
|
|
27
37
|
const res = await this._fetch(body);
|
|
@@ -34,6 +44,9 @@ export class AnthropicBridge {
|
|
|
34
44
|
if (typeof content !== 'string') {
|
|
35
45
|
throw new SSMError('BRIDGE_RESPONSE_INVALID', 'Unexpected Anthropic response shape.');
|
|
36
46
|
}
|
|
47
|
+
this._lastCall = {
|
|
48
|
+
usage: readAnthropicUsage(json.usage, json.model ?? opts.model ?? this._model),
|
|
49
|
+
};
|
|
37
50
|
return content;
|
|
38
51
|
}
|
|
39
52
|
async *stream(prompt, opts = {}) {
|
|
@@ -46,7 +59,32 @@ export class AnthropicBridge {
|
|
|
46
59
|
if (!res.body) {
|
|
47
60
|
throw new SSMError('BRIDGE_RESPONSE_INVALID', 'Anthropic streaming response has no body.');
|
|
48
61
|
}
|
|
49
|
-
|
|
62
|
+
const model = opts.model ?? this._model;
|
|
63
|
+
let input = 0, output = 0, cacheRead = 0, cacheWrite = 0, reportedModel = model;
|
|
64
|
+
yield* parseAnthropicStream(res.body, (event) => {
|
|
65
|
+
// `message_start` carries the input split; `message_delta` the running
|
|
66
|
+
// output count. Both are folded so the final usage is provider-measured.
|
|
67
|
+
const start = event.message?.usage;
|
|
68
|
+
const delta = event.usage;
|
|
69
|
+
const usage = start ?? delta;
|
|
70
|
+
if (!usage)
|
|
71
|
+
return;
|
|
72
|
+
if (typeof event.message?.model === 'string')
|
|
73
|
+
reportedModel = event.message.model;
|
|
74
|
+
input = Math.max(input, Number(usage.input_tokens) || 0);
|
|
75
|
+
output = Math.max(output, Number(usage.output_tokens) || 0);
|
|
76
|
+
cacheRead = Math.max(cacheRead, Number(usage.cache_read_input_tokens) || 0);
|
|
77
|
+
cacheWrite = Math.max(cacheWrite, Number(usage.cache_creation_input_tokens) || 0);
|
|
78
|
+
});
|
|
79
|
+
this._lastCall = {
|
|
80
|
+
usage: {
|
|
81
|
+
model: reportedModel,
|
|
82
|
+
inputTokens: input,
|
|
83
|
+
outputTokens: output,
|
|
84
|
+
cachedInputTokens: cacheRead,
|
|
85
|
+
cacheWriteTokens: cacheWrite,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
50
88
|
}
|
|
51
89
|
_buildBody(prompt, opts, stream) {
|
|
52
90
|
const sys = opts.systemPrompt ?? this._systemPrompt;
|
|
@@ -81,7 +119,7 @@ export class AnthropicBridge {
|
|
|
81
119
|
}
|
|
82
120
|
}
|
|
83
121
|
// ── SSE parser (Anthropic event format) ──────────────────────────────────────
|
|
84
|
-
async function* parseAnthropicStream(body) {
|
|
122
|
+
async function* parseAnthropicStream(body, onEvent) {
|
|
85
123
|
const reader = body.getReader();
|
|
86
124
|
const decoder = new TextDecoder();
|
|
87
125
|
let buffer = '';
|
|
@@ -100,6 +138,7 @@ async function* parseAnthropicStream(body) {
|
|
|
100
138
|
const data = trimmed.slice(6);
|
|
101
139
|
try {
|
|
102
140
|
const event = JSON.parse(data);
|
|
141
|
+
onEvent?.(event);
|
|
103
142
|
// content_block_delta events carry the streamed text
|
|
104
143
|
if (event['type'] === 'content_block_delta') {
|
|
105
144
|
const text = event.delta?.text;
|
|
@@ -117,4 +156,21 @@ async function* parseAnthropicStream(body) {
|
|
|
117
156
|
reader.releaseLock();
|
|
118
157
|
}
|
|
119
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Maps an Anthropic `usage` object onto the canonical {@link LlmUsage} shape.
|
|
161
|
+
* Absent when the response omits usage (an older gateway shim), in which case
|
|
162
|
+
* `InstrumentedBridge` falls back to an estimate and flags it as such.
|
|
163
|
+
*/
|
|
164
|
+
function readAnthropicUsage(usage, model) {
|
|
165
|
+
if (!usage || typeof usage !== 'object')
|
|
166
|
+
return undefined;
|
|
167
|
+
const u = usage;
|
|
168
|
+
return {
|
|
169
|
+
model,
|
|
170
|
+
inputTokens: Number(u['input_tokens']) || 0,
|
|
171
|
+
outputTokens: Number(u['output_tokens']) || 0,
|
|
172
|
+
cachedInputTokens: Number(u['cache_read_input_tokens']) || 0,
|
|
173
|
+
cacheWriteTokens: Number(u['cache_creation_input_tokens']) || 0,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
120
176
|
//# sourceMappingURL=AnthropicBridge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnthropicBridge.js","sourceRoot":"","sources":["../../src/bridges/AnthropicBridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"AnthropicBridge.js","sourceRoot":"","sources":["../../src/bridges/AnthropicBridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AA8BjD,MAAM,OAAO,GAAG,uCAAuC,CAAC;AAExD,MAAM,OAAO,eAAe;IACf,iBAAiB,GAAG,IAAa,CAAC;IAE1B,OAAO,CAAe;IACtB,MAAM,CAAgB;IACtB,WAAW,CAAW;IACtB,aAAa,CAAS;IACtB,UAAU,CAAY;IACtB,YAAY,CAAW;IAEhC,SAAS,CAA6B;IAE9C,YAAY,IAA4B;QACpC,IAAI,CAAC,OAAO,GAAS,IAAI,CAAC,MAAM,CAAC;QACjC,IAAI,CAAC,MAAM,GAAU,IAAI,CAAC,KAAK,IAAS,kBAAkB,CAAC;QAC3D,IAAI,CAAC,WAAW,GAAK,IAAI,CAAC,UAAU,IAAI,YAAY,CAAC;QACrD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC;QAC7C,IAAI,CAAC,UAAU,GAAM,IAAI,CAAC,SAAS,IAAO,IAAI,CAAC;QAC/C,IAAI,CAAC,YAAY,GAAI,IAAI,CAAC,WAAW,IAAK,IAAI,CAAC;IACnD,CAAC;IAED;;;;;OAKG;IACH,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc,EAAE,OAA8B,EAAE;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAClD,MAAM,GAAG,GAAI,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAErC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,QAAQ,CACd,uBAAuB,EACvB,0BAA0B,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAClD,CAAC;QACN,CAAC;QAED,MAAM,IAAI,GAAM,MAAM,GAAG,CAAC,IAAI,EAA6B,CAAC;QAC5D,MAAM,OAAO,GAAI,IAAY,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QACjD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,QAAQ,CAAC,yBAAyB,EAAE,sCAAsC,CAAC,CAAC;QAC1F,CAAC;QACD,IAAI,CAAC,SAAS,GAAG;YACb,KAAK,EAAE,kBAAkB,CACpB,IAAY,CAAC,KAAK,EAClB,IAAY,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CACnD;SACJ,CAAC;QACF,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,MAAc,EAAE,OAA8B,EAAE;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,MAAM,GAAG,GAAI,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAErC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,QAAQ,CACd,uBAAuB,EACvB,oCAAoC,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAC5D,CAAC;QACN,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACZ,MAAM,IAAI,QAAQ,CAAC,yBAAyB,EAAE,2CAA2C,CAAC,CAAC;QAC/F,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;QACxC,IAAI,KAAK,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,SAAS,GAAG,CAAC,EAAE,UAAU,GAAG,CAAC,EAAE,aAAa,GAAG,KAAK,CAAC;QAEhF,KAAK,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;YAC5C,uEAAuE;YACvE,yEAAyE;YACzE,MAAM,KAAK,GAAI,KAAa,CAAC,OAAO,EAAE,KAAK,CAAC;YAC5C,MAAM,KAAK,GAAI,KAAa,CAAC,KAAK,CAAC;YACnC,MAAM,KAAK,GAAG,KAAK,IAAI,KAAK,CAAC;YAC7B,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,IAAI,OAAQ,KAAa,CAAC,OAAO,EAAE,KAAK,KAAK,QAAQ;gBAAE,aAAa,GAAI,KAAa,CAAC,OAAO,CAAC,KAAK,CAAC;YACpG,KAAK,GAAQ,IAAI,CAAC,GAAG,CAAC,KAAK,EAAO,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;YACnE,MAAM,GAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAM,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;YACpE,SAAS,GAAI,IAAI,CAAC,GAAG,CAAC,SAAS,EAAG,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9E,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;QACtF,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,GAAG;YACb,KAAK,EAAE;gBACH,KAAK,EAAE,aAAa;gBACpB,WAAW,EAAE,KAAK;gBAClB,YAAY,EAAE,MAAM;gBACpB,iBAAiB,EAAE,SAAS;gBAC5B,gBAAgB,EAAE,UAAU;aAC/B;SACJ,CAAC;IACN,CAAC;IAEO,UAAU,CAAC,MAAc,EAAE,IAA2B,EAAE,MAAe;QAC3E,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,CAAC;QACpD,MAAM,IAAI,GAA4B;YAClC,KAAK,EAAO,IAAI,CAAC,KAAK,IAAQ,IAAI,CAAC,MAAM;YACzC,UAAU,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU;YAC7C,QAAQ,EAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;SAClD,CAAC;QACF,IAAI,GAAG,EAAE,CAAC;YACN,kEAAkE;YAClE,qEAAqE;YACrE,mEAAmE;YACnE,2DAA2D;YAC3D,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,YAAY;gBAC9B,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC;gBACrE,CAAC,CAAC,GAAG,CAAC;QACd,CAAC;QACD,IAAI,MAAM;YAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;QAClC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAEO,MAAM,CAAC,IAAY;QACvB,OAAO,KAAK,CAAC,OAAO,EAAE;YAClB,MAAM,EAAG,MAAM;YACf,OAAO,EAAE;gBACL,cAAc,EAAQ,kBAAkB;gBACxC,WAAW,EAAW,IAAI,CAAC,OAAO;gBAClC,mBAAmB,EAAG,IAAI,CAAC,WAAW;aACzC;YACD,IAAI;SACP,CAAC,CAAC;IACP,CAAC;CACJ;AAED,gFAAgF;AAEhF,KAAK,SAAS,CAAC,CAAC,oBAAoB,CAChC,IAAgC,EAChC,OAAkD;IAElD,MAAM,MAAM,GAAI,IAAI,CAAC,SAAS,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,MAAM,GAAM,EAAE,CAAC;IAEnB,IAAI,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;YACV,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAEhB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAY,CAAC,CAAC,qDAAqD;YAErF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACvB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC;oBAAE,SAAS;gBAE5C,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC9B,IAAI,CAAC;oBACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;oBAC1D,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;oBACjB,qDAAqD;oBACrD,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,qBAAqB,EAAE,CAAC;wBAC1C,MAAM,IAAI,GAAI,KAAa,CAAC,KAAK,EAAE,IAAI,CAAC;wBACxC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;4BAAE,MAAM,IAAI,CAAC;oBAChE,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACL,2BAA2B;gBAC/B,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;YAAS,CAAC;QACP,MAAM,CAAC,WAAW,EAAE,CAAC;IACzB,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,KAAc,EAAE,KAAa;IACrD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,OAAO;QACH,KAAK;QACL,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC;QAC3C,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC;QAC7C,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,IAAI,CAAC;QAC5D,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,IAAI,CAAC;KAClE,CAAC;AACN,CAAC"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* Streaming is delegated straight through and never cached — a token stream is
|
|
16
16
|
* consumed once and caching it would defeat its purpose.
|
|
17
17
|
*/
|
|
18
|
-
import type { TransformerBridge, BridgeGenerateOptions } from './TransformerBridge.js';
|
|
18
|
+
import type { TransformerBridge, BridgeGenerateOptions, BridgeCallInfo } from './TransformerBridge.js';
|
|
19
19
|
import { ResponseCache, type ResponseCacheOptions } from './ResponseCache.js';
|
|
20
20
|
export interface CachingBridgeOptions extends ResponseCacheOptions {
|
|
21
21
|
/**
|
|
@@ -28,11 +28,19 @@ export interface CachingBridgeOptions extends ResponseCacheOptions {
|
|
|
28
28
|
export declare class CachingBridge implements TransformerBridge {
|
|
29
29
|
private readonly _inner;
|
|
30
30
|
private readonly _cache;
|
|
31
|
+
private _lastCall;
|
|
31
32
|
constructor(inner: TransformerBridge, opts?: CachingBridgeOptions);
|
|
32
33
|
/** Mirrors the wrapped bridge so callers can still gate on streaming support. */
|
|
33
34
|
get supportsStreaming(): boolean;
|
|
34
35
|
/** The underlying cache — exposed for stats inspection and manual eviction. */
|
|
35
36
|
get cache(): ResponseCache;
|
|
37
|
+
/**
|
|
38
|
+
* A hit is declared here rather than inferred downstream, which is what turns
|
|
39
|
+
* the cache-hit rate into a measured metric. On a miss the inner bridge's own
|
|
40
|
+
* provider-reported usage is passed through unchanged, so decorating a bridge
|
|
41
|
+
* never downgrades its cost accounting to an estimate.
|
|
42
|
+
*/
|
|
43
|
+
get lastCall(): BridgeCallInfo | undefined;
|
|
36
44
|
generate(prompt: string, opts?: BridgeGenerateOptions): Promise<string>;
|
|
37
45
|
/**
|
|
38
46
|
* Streaming is delegated to the inner bridge unchanged and is never cached.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CachingBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/CachingBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"CachingBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/CachingBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvG,OAAO,EAAE,aAAa,EAAiB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE7F,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAC9D;;;;OAIG;IACH,KAAK,CAAC,EAAG,aAAa,CAAC;CAC1B;AAED,qBAAa,aAAc,YAAW,iBAAiB;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IAExC,OAAO,CAAC,SAAS,CAA6B;gBAElC,KAAK,EAAE,iBAAiB,EAAE,IAAI,GAAE,oBAAyB;IAKrE,iFAAiF;IACjF,IAAI,iBAAiB,IAAI,OAAO,CAE/B;IAED,+EAA+E;IAC/E,IAAI,KAAK,IAAI,aAAa,CAEzB;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,cAAc,GAAG,SAAS,CAEzC;IAEK,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC;IAgCjF;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC,MAAM,CAAC;CAM9E"}
|
|
@@ -19,6 +19,7 @@ import { ResponseCache, buildCacheKey } from './ResponseCache.js';
|
|
|
19
19
|
export class CachingBridge {
|
|
20
20
|
_inner;
|
|
21
21
|
_cache;
|
|
22
|
+
_lastCall;
|
|
22
23
|
constructor(inner, opts = {}) {
|
|
23
24
|
this._inner = inner;
|
|
24
25
|
this._cache = opts.cache ?? new ResponseCache(opts);
|
|
@@ -31,6 +32,15 @@ export class CachingBridge {
|
|
|
31
32
|
get cache() {
|
|
32
33
|
return this._cache;
|
|
33
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* A hit is declared here rather than inferred downstream, which is what turns
|
|
37
|
+
* the cache-hit rate into a measured metric. On a miss the inner bridge's own
|
|
38
|
+
* provider-reported usage is passed through unchanged, so decorating a bridge
|
|
39
|
+
* never downgrades its cost accounting to an estimate.
|
|
40
|
+
*/
|
|
41
|
+
get lastCall() {
|
|
42
|
+
return this._lastCall;
|
|
43
|
+
}
|
|
34
44
|
async generate(prompt, opts = {}) {
|
|
35
45
|
const key = buildCacheKey({
|
|
36
46
|
prompt,
|
|
@@ -41,10 +51,23 @@ export class CachingBridge {
|
|
|
41
51
|
topP: opts.topP,
|
|
42
52
|
});
|
|
43
53
|
const cached = this._cache.get(key);
|
|
44
|
-
if (cached !== undefined)
|
|
54
|
+
if (cached !== undefined) {
|
|
55
|
+
this._lastCall = {
|
|
56
|
+
cacheHit: true,
|
|
57
|
+
cacheTier: 'exact',
|
|
58
|
+
usage: {
|
|
59
|
+
model: opts.model ?? 'unknown',
|
|
60
|
+
inputTokens: 0,
|
|
61
|
+
outputTokens: 0,
|
|
62
|
+
localCacheHit: true,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
45
65
|
return cached;
|
|
66
|
+
}
|
|
46
67
|
const value = await this._inner.generate(prompt, opts);
|
|
47
68
|
this._cache.set(key, value, Date.now());
|
|
69
|
+
const inner = this._inner.lastCall;
|
|
70
|
+
this._lastCall = { cacheHit: false, ...(inner?.usage ? { usage: inner.usage } : {}) };
|
|
48
71
|
return value;
|
|
49
72
|
}
|
|
50
73
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CachingBridge.js","sourceRoot":"","sources":["../../src/bridges/CachingBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,aAAa,EAAE,aAAa,EAA6B,MAAM,oBAAoB,CAAC;AAW7F,MAAM,OAAO,aAAa;IACL,MAAM,CAAqB;IAC3B,MAAM,CAAiB;
|
|
1
|
+
{"version":3,"file":"CachingBridge.js","sourceRoot":"","sources":["../../src/bridges/CachingBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,aAAa,EAAE,aAAa,EAA6B,MAAM,oBAAoB,CAAC;AAW7F,MAAM,OAAO,aAAa;IACL,MAAM,CAAqB;IAC3B,MAAM,CAAiB;IAEhC,SAAS,CAA6B;IAE9C,YAAY,KAAwB,EAAE,OAA6B,EAAE;QACjE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,iFAAiF;IACjF,IAAI,iBAAiB;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC;IACzC,CAAC;IAED,+EAA+E;IAC/E,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACH,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc,EAAE,OAA8B,EAAE;QAC3D,MAAM,GAAG,GAAG,aAAa,CAAC;YACtB,MAAM;YACN,KAAK,EAAS,IAAI,CAAC,KAAK;YACxB,YAAY,EAAG,IAAI,CAAC,YAAY;YAChC,SAAS,EAAK,IAAI,CAAC,SAAS;YAC5B,WAAW,EAAG,IAAI,CAAC,WAAW;YAC9B,IAAI,EAAU,IAAI,CAAC,IAAI;SAC1B,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC,SAAS,GAAG;gBACb,QAAQ,EAAG,IAAI;gBACf,SAAS,EAAE,OAAO;gBAClB,KAAK,EAAM;oBACP,KAAK,EAAc,IAAI,CAAC,KAAK,IAAI,SAAS;oBAC1C,WAAW,EAAQ,CAAC;oBACpB,YAAY,EAAO,CAAC;oBACpB,aAAa,EAAM,IAAI;iBAC1B;aACJ,CAAC;YACF,OAAO,MAAM,CAAC;QAClB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QACtF,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,MAAc,EAAE,IAA4B;QAC/C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;CACJ"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Supports both non-streaming and streaming (SSE) completions.
|
|
5
5
|
* Compatible with any OpenAI-compatible endpoint via the `baseUrl` option.
|
|
6
6
|
*/
|
|
7
|
-
import type { TransformerBridge, BridgeGenerateOptions } from './TransformerBridge.js';
|
|
7
|
+
import type { TransformerBridge, BridgeGenerateOptions, BridgeCallInfo } from './TransformerBridge.js';
|
|
8
8
|
export interface OpenAIBridgeOptions {
|
|
9
9
|
/** OpenAI API key (or compatible service key). */
|
|
10
10
|
apiKey: string;
|
|
@@ -18,6 +18,7 @@ export interface OpenAIBridgeOptions {
|
|
|
18
18
|
maxTokens?: number;
|
|
19
19
|
}
|
|
20
20
|
export declare class OpenAIBridge implements TransformerBridge {
|
|
21
|
+
private _lastCall;
|
|
21
22
|
readonly supportsStreaming: true;
|
|
22
23
|
private readonly _apiKey;
|
|
23
24
|
private readonly _model;
|
|
@@ -25,6 +26,8 @@ export declare class OpenAIBridge implements TransformerBridge {
|
|
|
25
26
|
private readonly _systemPrompt;
|
|
26
27
|
private readonly _maxTokens;
|
|
27
28
|
constructor(opts: OpenAIBridgeOptions);
|
|
29
|
+
/** Provider-reported usage for the last call — see {@link BridgeCallInfo}. */
|
|
30
|
+
get lastCall(): BridgeCallInfo | undefined;
|
|
28
31
|
generate(prompt: string, opts?: BridgeGenerateOptions): Promise<string>;
|
|
29
32
|
stream(prompt: string, opts?: BridgeGenerateOptions): AsyncIterable<string>;
|
|
30
33
|
private _buildBody;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenAIBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/OpenAIBridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"OpenAIBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/OpenAIBridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEvG,MAAM,WAAW,mBAAmB;IAChC,kDAAkD;IAClD,MAAM,EAAU,MAAM,CAAC;IACvB,4CAA4C;IAC5C,KAAK,CAAC,EAAU,MAAM,CAAC;IACvB,0DAA0D;IAC1D,OAAO,CAAC,EAAQ,MAAM,CAAC;IACvB,qDAAqD;IACrD,YAAY,CAAC,EAAG,MAAM,CAAC;IACvB,wCAAwC;IACxC,SAAS,CAAC,EAAM,MAAM,CAAC;CAC1B;AAED,qBAAa,YAAa,YAAW,iBAAiB;IAClD,OAAO,CAAC,SAAS,CAA6B;IAE9C,QAAQ,CAAC,iBAAiB,EAAG,IAAI,CAAU;IAE3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;gBAE3B,IAAI,EAAE,mBAAmB;IAQrC,8EAA8E;IAC9E,IAAI,QAAQ,IAAI,cAAc,GAAG,SAAS,CAEzC;IAEK,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC;IAuB1E,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,aAAa,CAAC,MAAM,CAAC;IA6BtF,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,MAAM;CAUjB"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { SSMError } from '../errors/SSMError.js';
|
|
8
8
|
export class OpenAIBridge {
|
|
9
|
+
_lastCall;
|
|
9
10
|
supportsStreaming = true;
|
|
10
11
|
_apiKey;
|
|
11
12
|
_model;
|
|
@@ -19,6 +20,10 @@ export class OpenAIBridge {
|
|
|
19
20
|
this._systemPrompt = opts.systemPrompt ?? '';
|
|
20
21
|
this._maxTokens = opts.maxTokens ?? 512;
|
|
21
22
|
}
|
|
23
|
+
/** Provider-reported usage for the last call — see {@link BridgeCallInfo}. */
|
|
24
|
+
get lastCall() {
|
|
25
|
+
return this._lastCall;
|
|
26
|
+
}
|
|
22
27
|
async generate(prompt, opts = {}) {
|
|
23
28
|
const body = this._buildBody(prompt, opts, false);
|
|
24
29
|
const res = await this._fetch(body);
|
|
@@ -31,6 +36,9 @@ export class OpenAIBridge {
|
|
|
31
36
|
if (typeof content !== 'string') {
|
|
32
37
|
throw new SSMError('BRIDGE_RESPONSE_INVALID', 'Unexpected OpenAI response shape.');
|
|
33
38
|
}
|
|
39
|
+
this._lastCall = {
|
|
40
|
+
usage: readOpenAIUsage(json.usage, json.model ?? opts.model ?? this._model),
|
|
41
|
+
};
|
|
34
42
|
return content;
|
|
35
43
|
}
|
|
36
44
|
async *stream(prompt, opts = {}) {
|
|
@@ -43,7 +51,16 @@ export class OpenAIBridge {
|
|
|
43
51
|
if (!res.body) {
|
|
44
52
|
throw new SSMError('BRIDGE_RESPONSE_INVALID', 'OpenAI streaming response has no body.');
|
|
45
53
|
}
|
|
46
|
-
|
|
54
|
+
const model = opts.model ?? this._model;
|
|
55
|
+
let usage;
|
|
56
|
+
yield* parseOpenAIStream(res.body, (event) => {
|
|
57
|
+
// Only emitted because `_buildBody` sets `stream_options.include_usage`;
|
|
58
|
+
// without it OpenAI streams no usage at all and cost would be a guess.
|
|
59
|
+
const reported = readOpenAIUsage(event.usage, event.model ?? model);
|
|
60
|
+
if (reported)
|
|
61
|
+
usage = reported;
|
|
62
|
+
});
|
|
63
|
+
this._lastCall = usage ? { usage } : {};
|
|
47
64
|
}
|
|
48
65
|
_buildBody(prompt, opts, stream) {
|
|
49
66
|
const sys = opts.systemPrompt ?? this._systemPrompt;
|
|
@@ -58,6 +75,10 @@ export class OpenAIBridge {
|
|
|
58
75
|
temperature: opts.temperature ?? 0.7,
|
|
59
76
|
top_p: opts.topP ?? 0.9,
|
|
60
77
|
stream,
|
|
78
|
+
// Without this the streaming response carries no usage block, so
|
|
79
|
+
// cost-per-request on streamed calls would silently fall back to an
|
|
80
|
+
// estimate. Non-streaming requests reject the field, hence the guard.
|
|
81
|
+
...(stream ? { stream_options: { include_usage: true } } : {}),
|
|
61
82
|
});
|
|
62
83
|
}
|
|
63
84
|
_fetch(body) {
|
|
@@ -72,7 +93,7 @@ export class OpenAIBridge {
|
|
|
72
93
|
}
|
|
73
94
|
}
|
|
74
95
|
// ── SSE parser ────────────────────────────────────────────────────────────────
|
|
75
|
-
async function* parseOpenAIStream(body) {
|
|
96
|
+
async function* parseOpenAIStream(body, onEvent) {
|
|
76
97
|
const reader = body.getReader();
|
|
77
98
|
const decoder = new TextDecoder();
|
|
78
99
|
let buffer = '';
|
|
@@ -93,6 +114,7 @@ async function* parseOpenAIStream(body) {
|
|
|
93
114
|
return;
|
|
94
115
|
try {
|
|
95
116
|
const chunk = JSON.parse(data);
|
|
117
|
+
onEvent?.(chunk);
|
|
96
118
|
const delta = chunk.choices?.[0]?.delta?.content;
|
|
97
119
|
if (typeof delta === 'string' && delta.length > 0)
|
|
98
120
|
yield delta;
|
|
@@ -107,4 +129,20 @@ async function* parseOpenAIStream(body) {
|
|
|
107
129
|
reader.releaseLock();
|
|
108
130
|
}
|
|
109
131
|
}
|
|
132
|
+
/** Maps an OpenAI `usage` object onto the canonical {@link LlmUsage} shape. */
|
|
133
|
+
function readOpenAIUsage(usage, model) {
|
|
134
|
+
if (!usage || typeof usage !== 'object')
|
|
135
|
+
return undefined;
|
|
136
|
+
const u = usage;
|
|
137
|
+
const cached = Number(u['prompt_tokens_details']?.['cached_tokens']) || 0;
|
|
138
|
+
const prompt = Number(u['prompt_tokens']) || 0;
|
|
139
|
+
return {
|
|
140
|
+
model,
|
|
141
|
+
// OpenAI reports `prompt_tokens` INCLUSIVE of cached tokens; the canonical
|
|
142
|
+
// shape keeps them disjoint so the two rates are applied exactly once each.
|
|
143
|
+
inputTokens: Math.max(0, prompt - cached),
|
|
144
|
+
outputTokens: Number(u['completion_tokens']) || 0,
|
|
145
|
+
cachedInputTokens: cached,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
110
148
|
//# sourceMappingURL=OpenAIBridge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenAIBridge.js","sourceRoot":"","sources":["../../src/bridges/OpenAIBridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"OpenAIBridge.js","sourceRoot":"","sources":["../../src/bridges/OpenAIBridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Streaming is delegated straight through and never cached.
|
|
13
13
|
*/
|
|
14
|
-
import type { TransformerBridge, BridgeGenerateOptions } from './TransformerBridge.js';
|
|
14
|
+
import type { TransformerBridge, BridgeGenerateOptions, BridgeCallInfo } from './TransformerBridge.js';
|
|
15
15
|
import { SemanticCache, type SemanticCacheOptions } from '../cache/SemanticCache.js';
|
|
16
16
|
export interface SemanticCachingBridgeOptions extends Omit<SemanticCacheOptions, never> {
|
|
17
17
|
/** Provide a shared SemanticCache instance instead of constructing one. */
|
|
@@ -20,10 +20,17 @@ export interface SemanticCachingBridgeOptions extends Omit<SemanticCacheOptions,
|
|
|
20
20
|
export declare class SemanticCachingBridge implements TransformerBridge {
|
|
21
21
|
private readonly _inner;
|
|
22
22
|
private readonly _cache;
|
|
23
|
+
private _lastCall;
|
|
23
24
|
constructor(inner: TransformerBridge, opts: SemanticCachingBridgeOptions);
|
|
24
25
|
get supportsStreaming(): boolean;
|
|
25
26
|
/** The underlying SemanticCache — exposed for stats inspection. */
|
|
26
27
|
get cache(): SemanticCache;
|
|
28
|
+
/**
|
|
29
|
+
* Reports which tier answered (`l1` local vector scan, `l2` shared backend, or
|
|
30
|
+
* a miss), so the saving from paraphrase reuse is attributable per tier rather
|
|
31
|
+
* than lumped into one "cache" number.
|
|
32
|
+
*/
|
|
33
|
+
get lastCall(): BridgeCallInfo | undefined;
|
|
27
34
|
generate(prompt: string, opts?: BridgeGenerateOptions): Promise<string>;
|
|
28
35
|
/** Streaming is delegated unchanged and never cached. */
|
|
29
36
|
stream(prompt: string, opts?: BridgeGenerateOptions): AsyncIterable<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SemanticCachingBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/SemanticCachingBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"SemanticCachingBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/SemanticCachingBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvG,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAErF,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAC;IACnF,2EAA2E;IAC3E,KAAK,CAAC,EAAG,aAAa,CAAC;CAC1B;AAED,qBAAa,qBAAsB,YAAW,iBAAiB;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IAExC,OAAO,CAAC,SAAS,CAA6B;gBAElC,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,4BAA4B;IAKxE,IAAI,iBAAiB,IAAI,OAAO,CAE/B;IAED,mEAAmE;IACnE,IAAI,KAAK,IAAI,aAAa,CAEzB;IAED;;;;OAIG;IACH,IAAI,QAAQ,IAAI,cAAc,GAAG,SAAS,CAEzC;IAEK,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC;IA4BjF,yDAAyD;IACzD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC,MAAM,CAAC;CAM9E"}
|
|
@@ -15,6 +15,7 @@ import { SemanticCache } from '../cache/SemanticCache.js';
|
|
|
15
15
|
export class SemanticCachingBridge {
|
|
16
16
|
_inner;
|
|
17
17
|
_cache;
|
|
18
|
+
_lastCall;
|
|
18
19
|
constructor(inner, opts) {
|
|
19
20
|
this._inner = inner;
|
|
20
21
|
this._cache = opts.cache ?? new SemanticCache(opts);
|
|
@@ -26,11 +27,35 @@ export class SemanticCachingBridge {
|
|
|
26
27
|
get cache() {
|
|
27
28
|
return this._cache;
|
|
28
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Reports which tier answered (`l1` local vector scan, `l2` shared backend, or
|
|
32
|
+
* a miss), so the saving from paraphrase reuse is attributable per tier rather
|
|
33
|
+
* than lumped into one "cache" number.
|
|
34
|
+
*/
|
|
35
|
+
get lastCall() {
|
|
36
|
+
return this._lastCall;
|
|
37
|
+
}
|
|
29
38
|
async generate(prompt, opts = {}) {
|
|
30
39
|
// Match on system + prompt meaning so different system contexts don't
|
|
31
40
|
// cross-hit; partition further by model via the stored meta.
|
|
32
41
|
const queryText = opts.systemPrompt ? `${opts.systemPrompt}\n${prompt}` : prompt;
|
|
33
|
-
const { response } = await this._cache.getOrGenerate(queryText, () => this._inner.generate(prompt, opts), opts.model ? { model: opts.model } : undefined);
|
|
42
|
+
const { response, cached, tier } = await this._cache.getOrGenerate(queryText, () => this._inner.generate(prompt, opts), opts.model ? { model: opts.model } : undefined);
|
|
43
|
+
if (cached) {
|
|
44
|
+
this._lastCall = {
|
|
45
|
+
cacheHit: true,
|
|
46
|
+
...(tier ? { cacheTier: tier } : {}),
|
|
47
|
+
usage: {
|
|
48
|
+
model: opts.model ?? 'unknown',
|
|
49
|
+
inputTokens: 0,
|
|
50
|
+
outputTokens: 0,
|
|
51
|
+
localCacheHit: true,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const inner = this._inner.lastCall;
|
|
57
|
+
this._lastCall = { cacheHit: false, ...(inner?.usage ? { usage: inner.usage } : {}) };
|
|
58
|
+
}
|
|
34
59
|
return response;
|
|
35
60
|
}
|
|
36
61
|
/** Streaming is delegated unchanged and never cached. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SemanticCachingBridge.js","sourceRoot":"","sources":["../../src/bridges/SemanticCachingBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,aAAa,EAA6B,MAAM,2BAA2B,CAAC;AAOrF,MAAM,OAAO,qBAAqB;IACb,MAAM,CAAqB;IAC3B,MAAM,CAAiB;
|
|
1
|
+
{"version":3,"file":"SemanticCachingBridge.js","sourceRoot":"","sources":["../../src/bridges/SemanticCachingBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,aAAa,EAA6B,MAAM,2BAA2B,CAAC;AAOrF,MAAM,OAAO,qBAAqB;IACb,MAAM,CAAqB;IAC3B,MAAM,CAAiB;IAEhC,SAAS,CAA6B;IAE9C,YAAY,KAAwB,EAAE,IAAkC;QACpE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,iBAAiB;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC;IACzC,CAAC;IAED,mEAAmE;IACnE,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH,IAAI,QAAQ;QACR,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc,EAAE,OAA8B,EAAE;QAC3D,sEAAsE;QACtE,6DAA6D;QAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACjF,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAC9D,SAAS,EACT,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,EACxC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CACjD,CAAC;QAEF,IAAI,MAAM,EAAE,CAAC;YACT,IAAI,CAAC,SAAS,GAAG;gBACb,QAAQ,EAAG,IAAI;gBACf,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpC,KAAK,EAAM;oBACP,KAAK,EAAU,IAAI,CAAC,KAAK,IAAI,SAAS;oBACtC,WAAW,EAAI,CAAC;oBAChB,YAAY,EAAG,CAAC;oBAChB,aAAa,EAAE,IAAI;iBACtB;aACJ,CAAC;QACN,CAAC;aAAM,CAAC;YACJ,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YACnC,IAAI,CAAC,SAAS,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1F,CAAC;QACD,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,yDAAyD;IACzD,MAAM,CAAC,MAAc,EAAE,IAA4B;QAC/C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;CACJ"}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* distillation. The interface is structural — any object with the right
|
|
7
7
|
* shape works, no base class required.
|
|
8
8
|
*/
|
|
9
|
+
import type { BridgeCallInfo } from '../telemetry/types.js';
|
|
10
|
+
export type { BridgeCallInfo };
|
|
9
11
|
export interface BridgeGenerateOptions {
|
|
10
12
|
/** Max tokens to generate. Default per-adapter (typically 512). */
|
|
11
13
|
maxTokens?: number;
|
|
@@ -24,6 +26,17 @@ export interface TransformerBridge {
|
|
|
24
26
|
* Must resolve to the assistant's reply text only (not including the prompt).
|
|
25
27
|
*/
|
|
26
28
|
generate(prompt: string, opts?: BridgeGenerateOptions): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Usage and cache outcome of the most recent `generate()`/`stream()`.
|
|
31
|
+
*
|
|
32
|
+
* Optional so third-party bridges stay valid, but every bridge in this package
|
|
33
|
+
* populates it: it is what lets `InstrumentedBridge` report *provider-measured*
|
|
34
|
+
* tokens and cost instead of a character-count estimate, and what lets the
|
|
35
|
+
* caching decorators declare a hit so the cache-hit rate is a fact rather than
|
|
36
|
+
* an inference. Not concurrency-safe by design — read it immediately after the
|
|
37
|
+
* call, or use `InstrumentedBridge`, which does.
|
|
38
|
+
*/
|
|
39
|
+
readonly lastCall?: BridgeCallInfo;
|
|
27
40
|
/**
|
|
28
41
|
* Streaming variant — yields tokens incrementally.
|
|
29
42
|
* Check `supportsStreaming` before calling.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransformerBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/TransformerBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,qBAAqB;IAClC,mEAAmE;IACnE,SAAS,CAAC,EAAM,MAAM,CAAC;IACvB,iEAAiE;IACjE,WAAW,CAAC,EAAI,MAAM,CAAC;IACvB,+DAA+D;IAC/D,IAAI,CAAC,EAAW,MAAM,CAAC;IACvB,wEAAwE;IACxE,YAAY,CAAC,EAAG,MAAM,CAAC;IACvB,sDAAsD;IACtD,KAAK,CAAC,EAAU,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAC9B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAExE;;;OAGG;IACH,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAE7E,4DAA4D;IAC5D,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;CACvC"}
|
|
1
|
+
{"version":3,"file":"TransformerBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/TransformerBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B,MAAM,WAAW,qBAAqB;IAClC,mEAAmE;IACnE,SAAS,CAAC,EAAM,MAAM,CAAC;IACvB,iEAAiE;IACjE,WAAW,CAAC,EAAI,MAAM,CAAC;IACvB,+DAA+D;IAC/D,IAAI,CAAC,EAAW,MAAM,CAAC;IACvB,wEAAwE;IACxE,YAAY,CAAC,EAAG,MAAM,CAAC;IACvB,sDAAsD;IACtD,KAAK,CAAC,EAAU,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAC9B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAExE;;;;;;;;;OASG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAEnC;;;OAGG;IACH,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAE7E,4DAA4D;IAC5D,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;CACvC"}
|