@maximem/synap-js-sdk 0.5.7 → 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 +1304 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +281 -5
- package/dist/index.d.ts +281 -5
- package/dist/index.js +1257 -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
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local search over a conversation's earlier turns.
|
|
3
|
+
*
|
|
4
|
+
* Port of `maximem_synap/cache/history_search.py`; see it for the design.
|
|
5
|
+
* Cascade, cheapest first: literal values in the query, then BM25 (the
|
|
6
|
+
* anticipation cache's tokenizer and parameters), then an embedding model
|
|
7
|
+
* when one is supplied. Ranks are fused by reciprocal rank with a small recency prior, and
|
|
8
|
+
* excerpts are shown in conversation order. The rendered block reaches the
|
|
9
|
+
* LLM prompt and is byte-identical to Python's.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** A local embedding model. `model` names it, so vectors from another model are never compared. */
|
|
13
|
+
interface Encoder {
|
|
14
|
+
model: string;
|
|
15
|
+
encode(texts: string[]): number[][] | Promise<number[][]>;
|
|
16
|
+
/** Optional: a model trained with a query prefix (e5) encodes queries here and turns with `encode`. */
|
|
17
|
+
encodeQuery?(texts: string[]): number[][] | Promise<number[][]>;
|
|
18
|
+
}
|
|
19
|
+
|
|
1
20
|
/**
|
|
2
21
|
* In-memory TTL cache for context bundles pushed over gRPC.
|
|
3
22
|
*
|
|
@@ -22,6 +41,7 @@
|
|
|
22
41
|
*
|
|
23
42
|
* All thresholds come from the shared behavior contract.
|
|
24
43
|
*/
|
|
44
|
+
|
|
25
45
|
/** Sentinel scope that matches any requester. */
|
|
26
46
|
declare const ANY_SCOPE = "_any";
|
|
27
47
|
interface BundleItem {
|
|
@@ -47,11 +67,18 @@ interface ContextBundle {
|
|
|
47
67
|
*/
|
|
48
68
|
scopeRung?: string | null;
|
|
49
69
|
}
|
|
70
|
+
declare const MATCHERS: readonly ["bm25", "semantic"];
|
|
71
|
+
type Matcher = (typeof MATCHERS)[number];
|
|
50
72
|
interface LookupResult {
|
|
51
73
|
itemsByType: Record<string, BundleItem[]>;
|
|
52
74
|
bundleIds: string[];
|
|
53
75
|
score: number;
|
|
54
76
|
coverage: number;
|
|
77
|
+
/**
|
|
78
|
+
* A semantic match below the sure bar is "borderline": the caller may still
|
|
79
|
+
* ask the server, with a short deadline. Python: `_match_band`.
|
|
80
|
+
*/
|
|
81
|
+
band?: 'sure' | 'borderline';
|
|
55
82
|
}
|
|
56
83
|
interface LookupParams {
|
|
57
84
|
searchQuery?: readonly string[] | null;
|
|
@@ -67,8 +94,13 @@ interface LookupParams {
|
|
|
67
94
|
*/
|
|
68
95
|
scopeRung?: string | null;
|
|
69
96
|
maxItems?: number;
|
|
97
|
+
/**
|
|
98
|
+
* The search queries' vectors under the cache's encoder, from `lookupAsync`.
|
|
99
|
+
* With them (and matcher "semantic") the lookup matches by meaning.
|
|
100
|
+
*/
|
|
101
|
+
queryVectors?: readonly (readonly number[])[] | null;
|
|
70
102
|
}
|
|
71
|
-
type ExitReason = 'empty' | 'recall_bypass' | 'no_query_tokens' | 'novel_term_gate' | 'empty_corpus' | 'no_items_above_threshold' | 'coverage_gate' | 'hit';
|
|
103
|
+
type ExitReason = 'empty' | 'recall_bypass' | 'no_query_tokens' | 'novel_term_gate' | 'empty_corpus' | 'no_items_above_threshold' | 'coverage_gate' | 'asked_kind_missing' | 'hit';
|
|
72
104
|
interface LookupTelemetry {
|
|
73
105
|
searchQuery: string[];
|
|
74
106
|
entityId: string | null;
|
|
@@ -122,6 +154,19 @@ interface AnticipationCacheOptions {
|
|
|
122
154
|
/** Injected in tests. Defaults to a monotonic clock. */
|
|
123
155
|
now?: () => number;
|
|
124
156
|
onLookup?: (telemetry: LookupTelemetry) => void;
|
|
157
|
+
/**
|
|
158
|
+
* The local embedding model, usually handed over later with `setEncoder`
|
|
159
|
+
* once it has loaded. Until then, and with matcher "bm25", lookups are BM25.
|
|
160
|
+
*/
|
|
161
|
+
encoder?: Encoder | null;
|
|
162
|
+
matcher?: Matcher;
|
|
163
|
+
minCosine?: number;
|
|
164
|
+
serveMinCosine?: number;
|
|
165
|
+
askedKind?: boolean;
|
|
166
|
+
itemQuestions?: boolean;
|
|
167
|
+
canonical?: 'off' | 'canon' | 'both';
|
|
168
|
+
bundleServeMinCosine?: number;
|
|
169
|
+
sureMinCosine?: number;
|
|
125
170
|
}
|
|
126
171
|
declare class AnticipationCache {
|
|
127
172
|
#private;
|
|
@@ -134,11 +179,52 @@ declare class AnticipationCache {
|
|
|
134
179
|
private corpusVocab;
|
|
135
180
|
private bm25;
|
|
136
181
|
private bm25Dirty;
|
|
182
|
+
private encoder;
|
|
183
|
+
private readonly matcher;
|
|
184
|
+
private readonly minCosine;
|
|
185
|
+
private readonly serveMinCosine;
|
|
186
|
+
private readonly askedKind;
|
|
187
|
+
private readonly itemQuestions;
|
|
188
|
+
private readonly canonical;
|
|
189
|
+
private readonly bundleServeMinCosine;
|
|
190
|
+
private readonly sureMinCosine;
|
|
191
|
+
/** Embedding runs one batch after another; `whenEmbedded` awaits the queue. */
|
|
192
|
+
private embedding;
|
|
137
193
|
constructor(options?: AnticipationCacheOptions);
|
|
194
|
+
/**
|
|
195
|
+
* Hand over the local embedding model once it has loaded. Items already
|
|
196
|
+
* cached are embedded off the lookup path.
|
|
197
|
+
*/
|
|
198
|
+
setEncoder(encoder: Encoder | null): void;
|
|
199
|
+
/** True when lookups match by meaning: matcher "semantic" and a model loaded. */
|
|
200
|
+
get semantic(): boolean;
|
|
201
|
+
/** Resolves once every item stored so far has had its turn to be embedded. */
|
|
202
|
+
whenEmbedded(): Promise<void>;
|
|
203
|
+
/**
|
|
204
|
+
* Give `items` their vectors, queued behind any earlier batch, so neither a
|
|
205
|
+
* bundle arriving on the stream nor a lookup waits for the model. A lookup
|
|
206
|
+
* before they are ready matches those items by BM25 alone.
|
|
207
|
+
*/
|
|
208
|
+
private embedItems;
|
|
138
209
|
get size(): number;
|
|
139
210
|
get itemCount(): number;
|
|
140
211
|
store(bundle: ContextBundle): void;
|
|
212
|
+
/**
|
|
213
|
+
* `lookup`, matching by meaning when a model is loaded: embeds the queries,
|
|
214
|
+
* then looks up with their vectors. A query the model cannot embed is looked
|
|
215
|
+
* up by BM25, as without a model. Python does this inside `lookup`.
|
|
216
|
+
*/
|
|
217
|
+
lookupAsync(params: LookupParams): Promise<LookupResult | null>;
|
|
141
218
|
lookup(params: LookupParams): LookupResult | null;
|
|
219
|
+
/**
|
|
220
|
+
* Match by meaning: a lookup is a hit when an item's cosine to a query
|
|
221
|
+
* reaches `minCosine`, and the hit also serves the items at `serveMinCosine`
|
|
222
|
+
* or above. An item with no vector yet is matched by BM25 with its novel-term
|
|
223
|
+
* gate, as before. Python: `_semantic_lookup`, which explains the choices.
|
|
224
|
+
*/
|
|
225
|
+
private semanticLookup;
|
|
226
|
+
/** A hit: renew the leases of the bundles used, report, merge the items. */
|
|
227
|
+
private serve;
|
|
142
228
|
/**
|
|
143
229
|
* Drop this entity's bundles after a write, so the cache stops serving a
|
|
144
230
|
* pre-write view. Gated on the flag: this is the write-path hook.
|
|
@@ -379,4 +465,4 @@ declare const TransientError: typeof SynapTransientError;
|
|
|
379
465
|
declare const PermanentError: typeof SynapPermanentError;
|
|
380
466
|
declare const ConnectionError: typeof NetworkTimeoutError;
|
|
381
467
|
|
|
382
|
-
export { AnticipationCache as A, type BundleItem as B, ConflictError as C,
|
|
468
|
+
export { AnticipationCache as A, type BundleItem as B, ConflictError as C, TransientError as D, type Encoder as E, isSynapError as F, InsufficientCreditsError as I, ListeningAlreadyActiveError as L, NetworkTimeoutError as N, PermanentError as P, RateLimitError as R, SynapError as S, TranscriptConflictError as T, type AnticipationCacheSnapshot as a, ANY_SCOPE as b, AgentUnavailableError as c, type AnticipationCacheOptions as d, AuthenticationError as e, ConnectionError as f, type ContextBundle as g, ContextNotFoundError as h, type ExitReason as i, InvalidConversationIdError as j, InvalidInputError as k, InvalidInstanceIdError as l, ListeningNotActiveError as m, type LookupParams as n, type LookupResult as o, type LookupTelemetry as p, SDKError as q, ServiceUnavailableError as r, SessionExpiredError as s, type SnapshotBundle as t, type SnapshotItemPreview as u, type SnapshotItemRecord as v, type SynapErrorCode as w, type SynapErrorOptions as x, SynapPermanentError as y, SynapTransientError as z };
|
package/dist/grpc/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
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; }
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var _chunkRE4DDIWOcjs = require('../chunk-RE4DDIWO.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
var _chunkT372OL3Qcjs = require('../chunk-T372OL3Q.cjs');
|
|
@@ -39,8 +39,8 @@ async function listen(options) {
|
|
|
39
39
|
throw new (0, _chunkT372OL3Qcjs.ListeningNotActiveError)(availability.detail);
|
|
40
40
|
}
|
|
41
41
|
const [{ GrpcStreamClient: StreamClient }, { AnticipationCache }, { getEnv }] = await Promise.all([
|
|
42
|
-
Promise.resolve().then(() => _interopRequireWildcard(require("../stream-client-
|
|
43
|
-
Promise.resolve().then(() => _interopRequireWildcard(require("../anticipation-cache-
|
|
42
|
+
Promise.resolve().then(() => _interopRequireWildcard(require("../stream-client-L6OQPZN7.cjs"))),
|
|
43
|
+
Promise.resolve().then(() => _interopRequireWildcard(require("../anticipation-cache-LPNKMRBH.cjs"))),
|
|
44
44
|
Promise.resolve().then(() => _interopRequireWildcard(require("../env-55ULHNJZ.cjs")))
|
|
45
45
|
]);
|
|
46
46
|
const apiKey = _nullishCoalesce(_nullishCoalesce(options.apiKey, () => ( getEnv("SYNAP_API_KEY"))), () => ( ""));
|
|
@@ -83,5 +83,5 @@ async function listen(options) {
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
exports.GrpcStreamClient =
|
|
86
|
+
exports.GrpcStreamClient = _chunkRE4DDIWOcjs.GrpcStreamClient; exports.PROTO_SHA = _chunkRE4DDIWOcjs.PROTO_SHA; exports.checkGrpcAvailability = checkGrpcAvailability; exports.listen = listen;
|
|
87
87
|
//# sourceMappingURL=index.cjs.map
|
package/dist/grpc/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/
|
|
1
|
+
{"version":3,"sources":["/Users/anish/maximemai/maximem_synap/synap/sdk/js/dist/grpc/index.cjs","../../src/grpc/index.ts"],"names":[],"mappings":"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","file":"/Users/anish/maximemai/maximem_synap/synap/sdk/js/dist/grpc/index.cjs","sourcesContent":[null,"/**\n * gRPC anticipation stream: availability and loading.\n *\n * This is a SUBPATH export (`@maximem/synap-js-sdk/grpc`) and is never\n * imported by the main entry point. Three reasons, all of which have bitten\n * someone already:\n *\n * 1. `@grpc/grpc-js` plus its protos is roughly 5MB. HTTP-only and Edge users\n * should not pay for it (gotcha G-Q).\n * 2. grpc-js is built on `node:http2`, `node:net` and `node:tls`. Merely\n * importing it on Edge or Workers fails the *build*, not the call. Keeping\n * it behind a subpath plus a lazy `import()` means importing the SDK on\n * Edge stays safe.\n * 3. It is an `optionalDependency`, so it may legitimately be absent.\n *\n * ## Proto loading\n *\n * The stream is live. The proto ships as an INLINED JSON descriptor\n * (./descriptor.ts) loaded through `proto-loader.fromJSON`, not through\n * `loadSync(path)`. proto-loader's file-based path reads the `.proto` off disk\n * at runtime, which breaks under webpack/turbopack bundling and Vercel's `nft`\n * file tracing: at deploy time rather than at test time (gotcha G-P). Inlining\n * gets the same result as ts-proto codegen without a codegen toolchain.\n */\n\nimport { ListeningNotActiveError } from '../errors.js';\nexport { GrpcStreamClient } from './stream-client.js';\nexport type {\n StreamState, StreamCredentials, StreamClientOptions, ConversationEventInput,\n} from './stream-client.js';\nexport { PROTO_SHA } from './descriptor.js';\n\nexport type GrpcAvailability =\n | { available: true }\n | { available: false; reason: 'not-node' | 'module-missing'; detail: string };\n\n/**\n * Whether a gRPC stream could run here.\n *\n * Deliberately does not throw: callers use this to decide whether to offer the\n * stream at all, and a hard failure at that point is unhelpful.\n */\nexport async function checkGrpcAvailability(): Promise<GrpcAvailability> {\n const isNode =\n typeof process !== 'undefined' &&\n process.versions?.node !== undefined &&\n typeof (globalThis as { EdgeRuntime?: unknown }).EdgeRuntime === 'undefined';\n\n if (!isNode) {\n return {\n available: false,\n reason: 'not-node',\n detail:\n 'gRPC needs raw TCP and node:http2, which Edge runtimes and Workers do ' +\n 'not provide. HTTP context fetching works normally here; only the ' +\n 'anticipation stream is unavailable. Reaching Edge would require a ' +\n 'gRPC-Web or Connect endpoint on the server, which does not exist yet.',\n };\n }\n\n try {\n await import(/* @vite-ignore */ '@grpc/grpc-js');\n return { available: true };\n } catch (error) {\n return {\n available: false,\n reason: 'module-missing',\n detail:\n '@grpc/grpc-js is an optional dependency and is not installed. Run ' +\n '`npm install @grpc/grpc-js` to enable the anticipation stream. ' +\n `(${(error as Error)?.message ?? String(error)})`,\n };\n }\n}\n\nexport interface ListenOptions {\n conversationId: string;\n userId?: string;\n customerId?: string;\n onBundle?: (bundle: unknown) => void;\n}\n\nexport interface ListeningSession {\n stop(): Promise<void>;\n readonly active: boolean;\n}\n\n/**\n * Start the anticipation stream directly, without a SynapClient.\n *\n * Most callers want `client.instance.listen()` instead, which shares the\n * client's credentials and anticipation cache. This exists for the case where\n * only the stream is wanted.\n *\n * **Opt-in, and off by default.** The removed wrapper called `listen()`\n * unconditionally during init, so every user had a stream whether they asked\n * for one or not. Making it opt-in is the right default, but it is not a\n * neutral change: fewer streams means fewer anticipation hits and therefore\n * MORE billed cloud fetches for existing users. That has to be announced\n * rather than discovered (gotcha G-Y).\n */\nexport async function listen(\n options: ListenOptions & {\n apiKey?: string;\n clientId?: string;\n instanceId?: string;\n host?: string;\n port?: number;\n useTls?: boolean;\n },\n): Promise<ListeningSession> {\n if (!options.conversationId) {\n // conversation_id is not a scope tier, but the stream genuinely requires\n // one: it is what the server keys the anticipation session on.\n throw new ListeningNotActiveError('conversation_id is required to start a listening stream');\n }\n\n const availability = await checkGrpcAvailability();\n if (!availability.available) {\n throw new ListeningNotActiveError(availability.detail);\n }\n\n const [{ GrpcStreamClient: StreamClient }, { AnticipationCache }, { getEnv }] = await Promise.all([\n import('./stream-client.js'),\n import('../context/anticipation-cache.js'),\n import('../util/env.js'),\n ]);\n\n const apiKey = options.apiKey ?? getEnv('SYNAP_API_KEY') ?? '';\n if (apiKey === '') {\n throw new ListeningNotActiveError(\n 'No Synap API key found. Set SYNAP_API_KEY or pass apiKey.',\n );\n }\n\n const cache = new AnticipationCache();\n const client = new StreamClient(\n {\n apiKey,\n clientId: options.clientId ?? getEnv('SYNAP_CLIENT_ID') ?? '',\n instanceId: options.instanceId ?? getEnv('SYNAP_INSTANCE_ID') ?? '',\n },\n cache,\n {\n ...(options.host !== undefined ? { host: options.host } : {}),\n ...(options.port !== undefined ? { port: options.port } : {}),\n ...(options.useTls !== undefined ? { useTls: options.useTls } : {}),\n ...(options.onBundle !== undefined ? { onContext: options.onBundle } : {}),\n },\n );\n await client.connect();\n client.sendSessionControl({\n action: 'start',\n conversation_id: options.conversationId,\n ...(options.userId !== undefined ? { user_id: options.userId } : {}),\n ...(options.customerId !== undefined ? { customer_id: options.customerId } : {}),\n });\n\n return {\n stop: () => client.disconnect(),\n get active() { return client.isConnected; },\n };\n}\n"]}
|
package/dist/grpc/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AnticipationCache, S as SynapError } from '../errors-
|
|
1
|
+
import { A as AnticipationCache, S as SynapError } from '../errors-Bdayqlzy.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Bidirectional gRPC stream client for the Synap anticipation channel.
|
|
@@ -36,6 +36,11 @@ interface StreamClientOptions {
|
|
|
36
36
|
onContext?: (bundle: Record<string, unknown>) => void;
|
|
37
37
|
/** Fires only for `compaction_update` bundles. Backs the compaction subscriptions. */
|
|
38
38
|
onCompactionUpdate?: (conversationId: string, bundle: Record<string, unknown>) => void;
|
|
39
|
+
/**
|
|
40
|
+
* The server's message count for a conversation, sent after it has written a
|
|
41
|
+
* streamed message. See `ConversationState` in the proto.
|
|
42
|
+
*/
|
|
43
|
+
onConversationState?: (conversationId: string, messageCount: number) => void;
|
|
39
44
|
/**
|
|
40
45
|
* Where the outbox journal lives, so buffered events survive a restart.
|
|
41
46
|
* Defaults to `~/.synap`, the same root Python uses. `''` turns it off, and
|
|
@@ -128,14 +133,14 @@ declare class GrpcStreamClient {
|
|
|
128
133
|
*
|
|
129
134
|
* Source: synap/proto/synap_service.proto
|
|
130
135
|
* Generator: synap/sdk/scripts/gen_proto_descriptor.mjs
|
|
131
|
-
* Proto SHA:
|
|
136
|
+
* Proto SHA: 9857182b0cf458b4
|
|
132
137
|
*
|
|
133
138
|
* The proto is inlined as a JSON descriptor rather than loaded from disk so
|
|
134
139
|
* that bundlers and Vercel file tracing cannot lose it. Regenerate with
|
|
135
140
|
* `npm run sync-behavior` in synap/sdk/js.
|
|
136
141
|
*/
|
|
137
142
|
/** sha256 (first 16 hex chars) of the proto this descriptor was built from. */
|
|
138
|
-
declare const PROTO_SHA = "
|
|
143
|
+
declare const PROTO_SHA = "9857182b0cf458b4";
|
|
139
144
|
|
|
140
145
|
/**
|
|
141
146
|
* gRPC anticipation stream: availability and loading.
|
package/dist/grpc/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as AnticipationCache, S as SynapError } from '../errors-
|
|
1
|
+
import { A as AnticipationCache, S as SynapError } from '../errors-Bdayqlzy.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Bidirectional gRPC stream client for the Synap anticipation channel.
|
|
@@ -36,6 +36,11 @@ interface StreamClientOptions {
|
|
|
36
36
|
onContext?: (bundle: Record<string, unknown>) => void;
|
|
37
37
|
/** Fires only for `compaction_update` bundles. Backs the compaction subscriptions. */
|
|
38
38
|
onCompactionUpdate?: (conversationId: string, bundle: Record<string, unknown>) => void;
|
|
39
|
+
/**
|
|
40
|
+
* The server's message count for a conversation, sent after it has written a
|
|
41
|
+
* streamed message. See `ConversationState` in the proto.
|
|
42
|
+
*/
|
|
43
|
+
onConversationState?: (conversationId: string, messageCount: number) => void;
|
|
39
44
|
/**
|
|
40
45
|
* Where the outbox journal lives, so buffered events survive a restart.
|
|
41
46
|
* Defaults to `~/.synap`, the same root Python uses. `''` turns it off, and
|
|
@@ -128,14 +133,14 @@ declare class GrpcStreamClient {
|
|
|
128
133
|
*
|
|
129
134
|
* Source: synap/proto/synap_service.proto
|
|
130
135
|
* Generator: synap/sdk/scripts/gen_proto_descriptor.mjs
|
|
131
|
-
* Proto SHA:
|
|
136
|
+
* Proto SHA: 9857182b0cf458b4
|
|
132
137
|
*
|
|
133
138
|
* The proto is inlined as a JSON descriptor rather than loaded from disk so
|
|
134
139
|
* that bundlers and Vercel file tracing cannot lose it. Regenerate with
|
|
135
140
|
* `npm run sync-behavior` in synap/sdk/js.
|
|
136
141
|
*/
|
|
137
142
|
/** sha256 (first 16 hex chars) of the proto this descriptor was built from. */
|
|
138
|
-
declare const PROTO_SHA = "
|
|
143
|
+
declare const PROTO_SHA = "9857182b0cf458b4";
|
|
139
144
|
|
|
140
145
|
/**
|
|
141
146
|
* gRPC anticipation stream: availability and loading.
|
package/dist/grpc/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GrpcStreamClient,
|
|
3
3
|
PROTO_SHA
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-I7TWR4S6.js";
|
|
5
5
|
import {
|
|
6
6
|
ListeningNotActiveError
|
|
7
7
|
} from "../chunk-BWMPKLFG.js";
|
|
@@ -39,8 +39,8 @@ async function listen(options) {
|
|
|
39
39
|
throw new ListeningNotActiveError(availability.detail);
|
|
40
40
|
}
|
|
41
41
|
const [{ GrpcStreamClient: StreamClient }, { AnticipationCache }, { getEnv }] = await Promise.all([
|
|
42
|
-
import("../stream-client-
|
|
43
|
-
import("../anticipation-cache-
|
|
42
|
+
import("../stream-client-3WHXGW4U.js"),
|
|
43
|
+
import("../anticipation-cache-RWKF55J4.js"),
|
|
44
44
|
import("../env-QCUKKW36.js")
|
|
45
45
|
]);
|
|
46
46
|
const apiKey = options.apiKey ?? getEnv("SYNAP_API_KEY") ?? "";
|