promptguard-sdk 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -13
- package/dist/auto.d.ts +1 -0
- package/dist/auto.d.ts.map +1 -1
- package/dist/auto.js +5 -0
- package/dist/auto.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/langchain.d.ts +37 -1
- package/dist/integrations/langchain.d.ts.map +1 -1
- package/dist/integrations/langchain.js +64 -5
- package/dist/integrations/langchain.js.map +1 -1
- package/dist/integrations/session.d.ts +33 -0
- package/dist/integrations/session.d.ts.map +1 -0
- package/dist/integrations/session.js +71 -0
- package/dist/integrations/session.js.map +1 -0
- package/dist/integrations/vercel-ai-output.d.ts +109 -0
- package/dist/integrations/vercel-ai-output.d.ts.map +1 -0
- package/dist/integrations/vercel-ai-output.js +330 -0
- package/dist/integrations/vercel-ai-output.js.map +1 -0
- package/dist/integrations/vercel-ai.d.ts +114 -24
- package/dist/integrations/vercel-ai.d.ts.map +1 -1
- package/dist/integrations/vercel-ai.js +200 -82
- package/dist/integrations/vercel-ai.js.map +1 -1
- package/dist/patches/base.d.ts +5 -0
- package/dist/patches/base.d.ts.map +1 -1
- package/dist/patches/base.js +5 -2
- package/dist/patches/base.js.map +1 -1
- package/dist/patches/openai.d.ts +8 -0
- package/dist/patches/openai.d.ts.map +1 -1
- package/dist/patches/openai.js +16 -0
- package/dist/patches/openai.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -207,6 +207,27 @@ console.log(result.redacted);
|
|
|
207
207
|
|
|
208
208
|
## Framework Integrations
|
|
209
209
|
|
|
210
|
+
### Conversations (`session_id`)
|
|
211
|
+
|
|
212
|
+
Each scan can name the conversation it belongs to in `context.session_id`, so the Guard API can relate the turns of one conversation to each other. An integration sends the framework's **own** conversation id there, the same on every turn of one conversation, and sends **nothing** when the framework has none. It never invents one: a per-call run id would make every scan a conversation of its own.
|
|
213
|
+
|
|
214
|
+
| Integration | Where the session id comes from |
|
|
215
|
+
|---|---|
|
|
216
|
+
| LangChain.js / LangGraph.js callback handler | The call's `thread_id`: LangGraph puts its checkpointer's `configurable.thread_id` in every callback's metadata. For a plain chain or model, set `{ metadata: { thread_id } }` in the call config (`session_id` and `conversation_id` are read too, the keys LangSmith groups a thread by). |
|
|
217
|
+
| Vercel AI SDK (`promptguard()` / `promptGuardMiddleware()`) | The AI SDK has no conversation id, so a call names one: `providerOptions: { promptguard: { sessionId } }` (`providerMetadata` on `ai` 4). Providers ignore a key that is not theirs. |
|
|
218
|
+
| Auto-instrumentation (`init()`) | The OpenAI Responses API's `conversation` (an id or `{ id }`). `previous_response_id` changes every turn and is not used. Other provider APIs carry no conversation id. |
|
|
219
|
+
|
|
220
|
+
The handler and the middleware also take a `sessionId` option, used only when the call names no conversation of its own; the call's id wins. An empty string, or one over 255 characters, throws a `TypeError` there. An id over 255 characters that arrives with a call is dropped with a debug log, and the scan goes ahead without one.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
const { text } = await generateText({
|
|
224
|
+
model,
|
|
225
|
+
prompt: 'Hello!',
|
|
226
|
+
providerOptions: { promptguard: { sessionId: 'chat-42' } },
|
|
227
|
+
});
|
|
228
|
+
// this scan, and every later call naming chat-42, sends session_id: "chat-42"
|
|
229
|
+
```
|
|
230
|
+
|
|
210
231
|
### LangChain.js
|
|
211
232
|
|
|
212
233
|
```typescript
|
|
@@ -240,26 +261,55 @@ The callback handler provides rich context to PromptGuard - chain names, tool ca
|
|
|
240
261
|
|
|
241
262
|
### Vercel AI SDK
|
|
242
263
|
|
|
264
|
+
Wrap the model with `promptguard()` and use it wherever you used the original. It wraps the models of `ai` 5, 6 and 7 (specification V2, V3 and V4); on `ai` 4, use `promptGuardMiddleware()` below.
|
|
265
|
+
|
|
243
266
|
```typescript
|
|
244
267
|
import { openai } from '@ai-sdk/openai';
|
|
245
|
-
import {
|
|
268
|
+
import { generateText, streamText } from 'ai';
|
|
269
|
+
import { promptguard } from 'promptguard-sdk/integrations/vercel-ai';
|
|
270
|
+
|
|
271
|
+
const model = promptguard(openai('gpt-5-nano'), {
|
|
272
|
+
apiKey: 'pg_live_xxx', // default: PROMPTGUARD_API_KEY
|
|
273
|
+
mode: 'enforce',
|
|
274
|
+
scanResponses: true,
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const { text } = await generateText({ model, prompt: 'Hello!' });
|
|
278
|
+
const result = streamText({ model, prompt: 'Hello again!' });
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
The wrapped model keeps the original's specification version, provider, model id and type, even when the original is frozen. On `ai` 4, or if you already compose AI SDK middleware, `promptGuardMiddleware()` takes the same options and scans the same way:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
import { wrapLanguageModel } from 'ai';
|
|
246
285
|
import { promptGuardMiddleware } from 'promptguard-sdk/integrations/vercel-ai';
|
|
247
286
|
|
|
248
287
|
const model = wrapLanguageModel({
|
|
249
288
|
model: openai('gpt-5-nano'),
|
|
250
|
-
middleware: promptGuardMiddleware({
|
|
251
|
-
apiKey: 'pg_live_xxx',
|
|
252
|
-
mode: 'enforce',
|
|
253
|
-
scanResponses: true,
|
|
254
|
-
}),
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
const { text } = await generateText({
|
|
258
|
-
model,
|
|
259
|
-
prompt: 'Hello!',
|
|
289
|
+
middleware: [promptGuardMiddleware({ scanResponses: true }) /* , ...yours */],
|
|
260
290
|
});
|
|
261
291
|
```
|
|
262
292
|
|
|
293
|
+
Input is scanned before every call. In enforce mode a block throws `PromptGuardBlockedError` before the model is called, and a redaction rewrites the prompt the model receives.
|
|
294
|
+
|
|
295
|
+
With `scanResponses: true`, streamed output (`streamText()`) is scanned as well as generated output, with the same decisions and the same fail-open policy:
|
|
296
|
+
|
|
297
|
+
- **Enforce mode holds back text until it has been scanned.** Parts that carry scanned text (text deltas, tool-call input) are held. Each time `streamWindowChars` new characters (default `1000`) have arrived, everything held is scanned and, if clean, released — except the last 200 characters, which stay held and are scanned again at the head of the next window. When the model finishes, the complete text is scanned once more before that tail and the `finish` part are released. The guarantee: no text reaches your code before it has been scanned together with at least the 200 characters that follow it, so a secret up to 200 characters long is always seen whole, even across a window boundary. The cost is that text arrives in bursts, each after one Guard API round trip. Set `streamWindowChars: Infinity` to hold the whole response for a single scan at the end.
|
|
298
|
+
- **Parts with nothing to scan are not held for nothing.** Stream start, reasoning, sources, files and metadata are delivered at once when no text is held ahead of them, and queue behind held text otherwise, so the order of parts never changes. Reasoning is not scanned, as it is not with `generateText()`.
|
|
299
|
+
- **The default window is a judgement call**, not an external standard: 1000 characters is about 250 tokens, a few seconds of generation, which is about as long as one Guard API round trip — so scanning a window roughly keeps pace with generating the next. A smaller window gets the first text out sooner and costs more scans.
|
|
300
|
+
- **A block stops the stream** with `PromptGuardBlockedError` (an output `redact` is enforced as a block, as with `generateText()`). Parts already released stay delivered; nothing after the blocked window is. `generateText()` rejects with `PromptGuardBlockedError` on any block. How a block reaches a `streamText()` caller depends on where it happened and on the model's AI SDK specification version (checked against ai 5, 6 and 7). Nothing in it hangs:
|
|
301
|
+
|
|
302
|
+
| Blocked | `onError` | `textStream` / `fullStream` | `toTextStreamResponse()` | `await result.text` |
|
|
303
|
+
|---------|-----------|-----------------------------|--------------------------|---------------------|
|
|
304
|
+
| Prompt, before the model is called (any version) | Called with `PromptGuardBlockedError` | End with no text; `fullStream` carries an `error` part | 200, empty body | Rejects with `NoOutputGeneratedError` |
|
|
305
|
+
| Output, from a V3 or V4 model (ai 6 and 7) | Not called | Throw `PromptGuardBlockedError` when read | The body errors when read | Rejects with `PromptGuardBlockedError` |
|
|
306
|
+
| Output, from a V2 model (ai 5) | Called with `PromptGuardBlockedError` | End with the text released before the block; `fullStream` carries an `error` part | 200, body ends with the text released before the block | Resolves with the text released before the block |
|
|
307
|
+
|
|
308
|
+
A V2 stream ends with the AI SDK's `error` part rather than erroring, because ai 5 never settles `await result.text` on an errored stream. So on ai 5 the text alone looks like a short answer: if you read only the text, check `await result.finishReason === 'error'`, which is how a blocked stream finishes there (or use `onError` or `fullStream`). The V2 row also applies to a V2 model (a provider package still on V2) under ai 6 or 7, through `promptguard()` and through ai 6's `wrapLanguageModel`, which passes a V2 model through as it is; such a stream loses the throw ai 6 and 7 would otherwise give. ai 7's `wrapLanguageModel` upgrades a V2 model to V4 first, so the middleware there follows the V4 row.
|
|
309
|
+
- **Monitor mode never holds the stream.** Parts pass through as they arrive and the complete text is scanned once at the end.
|
|
310
|
+
- **The final scan sees what `generateText()` would.** The complete text is assembled the same way as a generated result — text first, then each tool call's input — so the same response gets the same decision streamed or not.
|
|
311
|
+
- **If the Guard API becomes unreachable mid-stream**, the held parts are released and the rest of that stream passes unscanned with a warning (`failOpen: true`, the default). With `failOpen: false` the stream stops with the `GuardApiError` instead.
|
|
312
|
+
|
|
263
313
|
### Standalone Guard API
|
|
264
314
|
|
|
265
315
|
Use the Guard client directly for maximum control:
|
|
@@ -394,13 +444,13 @@ What to do:
|
|
|
394
444
|
- **Verify at runtime** with [`verify()`](#confirming-protection-is-actually-live), which makes real calls and reports what came back, or with `getAppliedPatches()` for the patch list alone — and note that a patch being listed proves the CJS build was patched, not that your ESM imports go through it. `init()` also logs a warning when it applies zero patches.
|
|
395
445
|
- **Prefer the ESM-safe APIs**, which don't rely on module patching:
|
|
396
446
|
- LangChain: `PromptGuardCallbackHandler` (`promptguard-sdk/integrations/langchain`)
|
|
397
|
-
- Vercel AI SDK: `promptGuardMiddleware` (`promptguard-sdk/integrations/vercel-ai`)
|
|
447
|
+
- Vercel AI SDK: `promptguard(model)` or `promptGuardMiddleware` (`promptguard-sdk/integrations/vercel-ai`)
|
|
398
448
|
- Any framework: explicit `GuardClient.scan()` calls around your LLM invocations
|
|
399
449
|
- Transpiled-to-CJS TypeScript apps (the common `tsc`/`ts-node` default) are **not** affected — their `import`s compile to `require()` and hit the patched modules.
|
|
400
450
|
|
|
401
451
|
### Other limitations
|
|
402
452
|
|
|
403
|
-
- **
|
|
453
|
+
- **Auto-instrumented streaming responses are not output-scanned.** With auto-instrumentation and `scanResponses: true`, streaming calls (`stream: true`, Bedrock `ConverseStreamCommand`, etc.) skip the output scan — the patched SDK hands the stream straight to your code. Input scanning still applies. A `debug`-level log is emitted when the output scan is skipped. The Vercel AI SDK middleware is the exception: it scans `streamText()` output in windows (see [Vercel AI SDK](#vercel-ai-sdk)).
|
|
404
454
|
- **OpenAI `APIPromise` helpers are not preserved by auto-instrumentation.** Patched methods return a plain `Promise`, so `.withResponse()` / `.asResponse()` on `client.chat.completions.create(...)` are unavailable while `init()` is active. `await` the call and use the plain result instead.
|
|
405
455
|
- **Proxy client streaming:** `pg.chat.completions.create({ stream: true })` is rejected with a clear error — streaming is not yet supported by the proxy client.
|
|
406
456
|
|
package/dist/auto.d.ts
CHANGED
|
@@ -121,6 +121,7 @@ export declare function detectedUnpatched(): string[];
|
|
|
121
121
|
export declare function instrumentationReport(): {
|
|
122
122
|
patched: string[];
|
|
123
123
|
detectedUnpatched: string[];
|
|
124
|
+
middleware: string[];
|
|
124
125
|
adviceUrl: string;
|
|
125
126
|
};
|
|
126
127
|
//# sourceMappingURL=auto.d.ts.map
|
package/dist/auto.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto.d.ts","sourceRoot":"","sources":["../src/auto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,KAAK,QAAQ,EAAuB,MAAM,UAAU,CAAA;AAkB7D,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mFAAmF;IACnF,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kDAAkD;IAClD,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,IAAI,CAqCpD;AAED,wBAAgB,QAAQ,IAAI,IAAI,CAU/B;AAMD,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAEnD;AAED,wBAAgB,OAAO,IAAI,SAAS,GAAG,SAAS,CAE/C;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C;AAiED,sEAAsE;AACtE;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAW5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,IAAI;IACvC,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,SAAS,EAAE,MAAM,CAAA;CAClB,
|
|
1
|
+
{"version":3,"file":"auto.d.ts","sourceRoot":"","sources":["../src/auto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,KAAK,QAAQ,EAAuB,MAAM,UAAU,CAAA;AAkB7D,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mFAAmF;IACnF,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kDAAkD;IAClD,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,sDAAsD;IACtD,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,IAAI,CAqCpD;AAED,wBAAgB,QAAQ,IAAI,IAAI,CAU/B;AAMD,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAEnD;AAED,wBAAgB,OAAO,IAAI,SAAS,GAAG,SAAS,CAE/C;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C;AAiED,sEAAsE;AACtE;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAW5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,IAAI;IACvC,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB,CAWA"}
|
package/dist/auto.js
CHANGED
|
@@ -243,6 +243,11 @@ function instrumentationReport() {
|
|
|
243
243
|
return {
|
|
244
244
|
patched: getAppliedPatches(),
|
|
245
245
|
detectedUnpatched: detectedUnpatched(),
|
|
246
|
+
// Request-edge middleware alive in the process (cross-SDK contract v1.7.0).
|
|
247
|
+
// The Python SDK's ASGI/FastAPI middleware reports `fastapi`; this SDK has
|
|
248
|
+
// no such middleware yet, so the list is always empty rather than absent,
|
|
249
|
+
// and a cross-language health check reads the same key in both.
|
|
250
|
+
middleware: [],
|
|
246
251
|
adviceUrl: ADVICE_URL,
|
|
247
252
|
};
|
|
248
253
|
}
|
package/dist/auto.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto.js","sourceRoot":"","sources":["../src/auto.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;AAyEH,oBAqCC;AAED,4BAUC;AAMD,wCAEC;AAED,0BAEC;AAED,gCAEC;AAED,kDAEC;AAmBD,8CAEC;AA2ED,0CAEC;AAED,8CAWC;AAcD,
|
|
1
|
+
{"version":3,"file":"auto.js","sourceRoot":"","sources":["../src/auto.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type { ChatCompletionRequest, ChatCompletionResponse, Message, PromptGuar
|
|
|
31
31
|
export { PromptGuard, PromptGuardError } from "./client";
|
|
32
32
|
export { GuardApiError, GuardClient, type GuardClientConfig, type GuardContext, type GuardContextWire, GuardDecision, type GuardMessage, type GuardRequestBody, type GuardResponseBody, PromptGuardBlockedError, type ScanOptions, type ThreatDetail, } from "./guard";
|
|
33
33
|
export { PromptGuardCallbackHandler } from "./integrations/langchain";
|
|
34
|
-
export { promptGuardMiddleware } from "./integrations/vercel-ai";
|
|
34
|
+
export { promptGuardMiddleware, promptguard } from "./integrations/vercel-ai";
|
|
35
35
|
export { getLogLevel, type LogLevel, setLogLevel } from "./logger";
|
|
36
36
|
export { type CheckStatus, type VerifyCheck, type VerifyOptions, type VerifyReport, verify, } from "./verify";
|
|
37
37
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,WAAW,EAChB,IAAI,EACJ,qBAAqB,EACrB,QAAQ,GACT,MAAM,QAAQ,CAAA;AAEf,YAAY,EACV,qBAAqB,EACrB,sBAAsB,EACtB,OAAO,EACP,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAExD,OAAO,EACL,aAAa,EACb,WAAW,EACX,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,WAAW,EAChB,IAAI,EACJ,qBAAqB,EACrB,QAAQ,GACT,MAAM,QAAQ,CAAA;AAEf,YAAY,EACV,qBAAqB,EACrB,sBAAsB,EACtB,OAAO,EACP,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAExD,OAAO,EACL,aAAa,EACb,WAAW,EACX,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAE7E,OAAO,EAAE,WAAW,EAAE,KAAK,QAAQ,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAElE,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,MAAM,GACP,MAAM,UAAU,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
30
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
-
exports.verify = exports.setLogLevel = exports.getLogLevel = exports.promptGuardMiddleware = exports.PromptGuardCallbackHandler = exports.PromptGuardBlockedError = exports.GuardDecision = exports.GuardClient = exports.GuardApiError = exports.PromptGuardError = exports.PromptGuard = exports.shutdown = exports.instrumentationReport = exports.init = exports.getAppliedPatches = exports.detectedUnpatched = void 0;
|
|
31
|
+
exports.verify = exports.setLogLevel = exports.getLogLevel = exports.promptguard = exports.promptGuardMiddleware = exports.PromptGuardCallbackHandler = exports.PromptGuardBlockedError = exports.GuardDecision = exports.GuardClient = exports.GuardApiError = exports.PromptGuardError = exports.PromptGuard = exports.shutdown = exports.instrumentationReport = exports.init = exports.getAppliedPatches = exports.detectedUnpatched = void 0;
|
|
32
32
|
// Auto-instrumentation
|
|
33
33
|
var auto_1 = require("./auto");
|
|
34
34
|
Object.defineProperty(exports, "detectedUnpatched", { enumerable: true, get: function () { return auto_1.detectedUnpatched; } });
|
|
@@ -51,6 +51,7 @@ var langchain_1 = require("./integrations/langchain");
|
|
|
51
51
|
Object.defineProperty(exports, "PromptGuardCallbackHandler", { enumerable: true, get: function () { return langchain_1.PromptGuardCallbackHandler; } });
|
|
52
52
|
var vercel_ai_1 = require("./integrations/vercel-ai");
|
|
53
53
|
Object.defineProperty(exports, "promptGuardMiddleware", { enumerable: true, get: function () { return vercel_ai_1.promptGuardMiddleware; } });
|
|
54
|
+
Object.defineProperty(exports, "promptguard", { enumerable: true, get: function () { return vercel_ai_1.promptguard; } });
|
|
54
55
|
// Logging controls
|
|
55
56
|
var logger_1 = require("./logger");
|
|
56
57
|
Object.defineProperty(exports, "getLogLevel", { enumerable: true, get: function () { return logger_1.getLogLevel; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;;AAEH,uBAAuB;AACvB,+BAOe;AANb,yGAAA,iBAAiB,OAAA;AACjB,yGAAA,iBAAiB,OAAA;AAEjB,4FAAA,IAAI,OAAA;AACJ,6GAAA,qBAAqB,OAAA;AACrB,gGAAA,QAAQ,OAAA;AAcV,eAAe;AACf,mCAAwD;AAA/C,qGAAA,WAAW,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AACtC,qCAAqC;AACrC,iCAagB;AAZd,sGAAA,aAAa,OAAA;AACb,oGAAA,WAAW,OAAA;AAIX,sGAAA,aAAa,OAAA;AAIb,gHAAA,uBAAuB,OAAA;AAIzB,uDAAuD;AACvD,sDAAqE;AAA5D,uHAAA,0BAA0B,OAAA;AACnC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;;AAEH,uBAAuB;AACvB,+BAOe;AANb,yGAAA,iBAAiB,OAAA;AACjB,yGAAA,iBAAiB,OAAA;AAEjB,4FAAA,IAAI,OAAA;AACJ,6GAAA,qBAAqB,OAAA;AACrB,gGAAA,QAAQ,OAAA;AAcV,eAAe;AACf,mCAAwD;AAA/C,qGAAA,WAAW,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AACtC,qCAAqC;AACrC,iCAagB;AAZd,sGAAA,aAAa,OAAA;AACb,oGAAA,WAAW,OAAA;AAIX,sGAAA,aAAa,OAAA;AAIb,gHAAA,uBAAuB,OAAA;AAIzB,uDAAuD;AACvD,sDAAqE;AAA5D,uHAAA,0BAA0B,OAAA;AACnC,sDAA6E;AAApE,kHAAA,qBAAqB,OAAA;AAAE,wGAAA,WAAW,OAAA;AAC3C,mBAAmB;AACnB,mCAAkE;AAAzD,qGAAA,WAAW,OAAA;AAAiB,qGAAA,WAAW,OAAA;AAChD,yBAAyB;AACzB,mCAMiB;AADf,gGAAA,MAAM,OAAA"}
|
|
@@ -15,6 +15,12 @@
|
|
|
15
15
|
* // or
|
|
16
16
|
* await chain.invoke({ input: '...' }, { callbacks: [handler] });
|
|
17
17
|
* ```
|
|
18
|
+
*
|
|
19
|
+
* Every scan names its Conversation in `session_id` with the call's own
|
|
20
|
+
* thread id: the `thread_id` LangGraph puts in every callback's metadata, or a
|
|
21
|
+
* `thread_id` / `session_id` / `conversation_id` set in `config.metadata`. A
|
|
22
|
+
* call that names no thread sends no session id, unless the handler was given
|
|
23
|
+
* a `sessionId` of its own.
|
|
18
24
|
*/
|
|
19
25
|
import { type GuardClientConfig } from "../guard";
|
|
20
26
|
import { type LogLevel } from "../logger";
|
|
@@ -35,6 +41,13 @@ export interface PromptGuardCallbackOptions extends GuardClientConfig {
|
|
|
35
41
|
logLevel?: LogLevel;
|
|
36
42
|
/** Convenience shorthand for `logLevel: "silent"`. */
|
|
37
43
|
silent?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* The Conversation to name when a call carries no thread id of its own —
|
|
46
|
+
* for a handler that serves one conversation. A call's `thread_id` (or
|
|
47
|
+
* `session_id` / `conversation_id`) in its metadata always wins. Without
|
|
48
|
+
* either, no session id is sent.
|
|
49
|
+
*/
|
|
50
|
+
sessionId?: string;
|
|
38
51
|
}
|
|
39
52
|
/**
|
|
40
53
|
* LangChain callback handler that scans prompts and responses via the
|
|
@@ -73,14 +86,20 @@ export declare class PromptGuardCallbackHandler {
|
|
|
73
86
|
private readonly mode;
|
|
74
87
|
private readonly scanResponses;
|
|
75
88
|
private readonly failOpen;
|
|
89
|
+
private readonly sessionId;
|
|
76
90
|
/** Chain context per run ID for richer threat detection. */
|
|
77
91
|
private chainContext;
|
|
92
|
+
/**
|
|
93
|
+
* The session id each in-flight LLM or tool run started with: its end
|
|
94
|
+
* callback carries no metadata, and must name the same Conversation.
|
|
95
|
+
*/
|
|
96
|
+
private runSessions;
|
|
78
97
|
constructor(options: PromptGuardCallbackOptions);
|
|
79
98
|
handleLLMStart(serialized: Record<string, unknown>, prompts: string[], runId: string, parentRunId?: string, _extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>): Promise<void>;
|
|
80
99
|
handleChatModelStart(serialized: Record<string, unknown>, messages: unknown[][], runId: string, parentRunId?: string, _extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>): Promise<void>;
|
|
81
100
|
handleLLMEnd(output: unknown, runId: string): Promise<void>;
|
|
82
101
|
handleLLMError(_error: Error, runId: string): void;
|
|
83
|
-
handleChainStart(serialized: Record<string, unknown>, _inputs: Record<string, unknown>, runId: string, parentRunId?: string, tags?: string[]): Promise<void>;
|
|
102
|
+
handleChainStart(serialized: Record<string, unknown>, _inputs: Record<string, unknown>, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>): Promise<void>;
|
|
84
103
|
handleChainEnd(_outputs: Record<string, unknown>, runId: string): void;
|
|
85
104
|
handleChainError(_error: Error, runId: string): void;
|
|
86
105
|
handleToolStart(serialized: Record<string, unknown>, input: string, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>): Promise<void>;
|
|
@@ -88,6 +107,23 @@ export declare class PromptGuardCallbackHandler {
|
|
|
88
107
|
handleToolError(_error: Error, runId: string): void;
|
|
89
108
|
private safeScan;
|
|
90
109
|
private handleDecision;
|
|
110
|
+
/**
|
|
111
|
+
* Keep a run's session id for its end scan.
|
|
112
|
+
*
|
|
113
|
+
* Called only once the start scan has returned: @langchain/core starts a
|
|
114
|
+
* run outside the block whose error path calls `handleLLMError`, so a
|
|
115
|
+
* start that throws gets no end or error callback, and anything stored
|
|
116
|
+
* before it would never be removed. Nothing is stored when the end scan
|
|
117
|
+
* will not run, or would name no session.
|
|
118
|
+
*/
|
|
119
|
+
private rememberRun;
|
|
120
|
+
/** Forget a finished LLM or tool run; return the session id it started with. */
|
|
121
|
+
private endRun;
|
|
122
|
+
/**
|
|
123
|
+
* The scan's context. A start callback passes its `metadata`, and the
|
|
124
|
+
* session id is read from it; an end callback passes the `sessionId` its
|
|
125
|
+
* start remembered. Nothing is stored here.
|
|
126
|
+
*/
|
|
91
127
|
private buildContext;
|
|
92
128
|
private extractModel;
|
|
93
129
|
private mapRole;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"langchain.d.ts","sourceRoot":"","sources":["../../src/integrations/langchain.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"langchain.d.ts","sourceRoot":"","sources":["../../src/integrations/langchain.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,12 +16,19 @@
|
|
|
16
16
|
* // or
|
|
17
17
|
* await chain.invoke({ input: '...' }, { callbacks: [handler] });
|
|
18
18
|
* ```
|
|
19
|
+
*
|
|
20
|
+
* Every scan names its Conversation in `session_id` with the call's own
|
|
21
|
+
* thread id: the `thread_id` LangGraph puts in every callback's metadata, or a
|
|
22
|
+
* `thread_id` / `session_id` / `conversation_id` set in `config.metadata`. A
|
|
23
|
+
* call that names no thread sends no session id, unless the handler was given
|
|
24
|
+
* a `sessionId` of its own.
|
|
19
25
|
*/
|
|
20
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
27
|
exports.PromptGuardCallbackHandler = void 0;
|
|
22
28
|
const guard_1 = require("../guard");
|
|
23
29
|
const logger_1 = require("../logger");
|
|
24
30
|
const resolve_1 = require("../resolve");
|
|
31
|
+
const session_1 = require("./session");
|
|
25
32
|
// ---------------------------------------------------------------------------
|
|
26
33
|
// Helpers
|
|
27
34
|
// ---------------------------------------------------------------------------
|
|
@@ -88,6 +95,11 @@ class PromptGuardCallbackHandler {
|
|
|
88
95
|
this.awaitHandlers = true;
|
|
89
96
|
/** Chain context per run ID for richer threat detection. */
|
|
90
97
|
this.chainContext = new Map();
|
|
98
|
+
/**
|
|
99
|
+
* The session id each in-flight LLM or tool run started with: its end
|
|
100
|
+
* callback carries no metadata, and must name the same Conversation.
|
|
101
|
+
*/
|
|
102
|
+
this.runSessions = new Map();
|
|
91
103
|
if (options.silent)
|
|
92
104
|
(0, logger_1.setLogLevel)("silent");
|
|
93
105
|
else if (options.logLevel)
|
|
@@ -105,6 +117,7 @@ class PromptGuardCallbackHandler {
|
|
|
105
117
|
// (least surprise + no unexpected per-response Guard API cost).
|
|
106
118
|
this.scanResponses = options.scanResponses ?? false;
|
|
107
119
|
this.failOpen = options.failOpen ?? true;
|
|
120
|
+
this.sessionId = (0, session_1.validateSessionId)(options.sessionId);
|
|
108
121
|
}
|
|
109
122
|
// -- LLM callbacks -------------------------------------------------------
|
|
110
123
|
async handleLLMStart(serialized, prompts, runId, parentRunId, _extraParams, tags, metadata) {
|
|
@@ -116,6 +129,7 @@ class PromptGuardCallbackHandler {
|
|
|
116
129
|
const context = this.buildContext(runId, parentRunId, "llm", tags, metadata);
|
|
117
130
|
const decision = await this.safeScan(messages, "input", model, context);
|
|
118
131
|
this.handleDecision(decision, runId);
|
|
132
|
+
this.rememberRun(runId, context.sessionId);
|
|
119
133
|
}
|
|
120
134
|
async handleChatModelStart(serialized, messages, runId, parentRunId, _extraParams, tags, metadata) {
|
|
121
135
|
const guardMessages = [];
|
|
@@ -131,27 +145,33 @@ class PromptGuardCallbackHandler {
|
|
|
131
145
|
const context = this.buildContext(runId, parentRunId, "chat_model", tags, metadata);
|
|
132
146
|
const decision = await this.safeScan(guardMessages, "input", model, context);
|
|
133
147
|
this.handleDecision(decision, runId);
|
|
148
|
+
this.rememberRun(runId, context.sessionId);
|
|
134
149
|
}
|
|
135
150
|
async handleLLMEnd(output, runId) {
|
|
151
|
+
const sessionId = this.endRun(runId);
|
|
136
152
|
if (!this.scanResponses)
|
|
137
153
|
return;
|
|
138
154
|
const text = this.extractLLMResponse(output);
|
|
139
155
|
if (!text)
|
|
140
156
|
return;
|
|
141
|
-
const context = this.buildContext(runId, undefined, "llm_response"
|
|
157
|
+
const context = this.buildContext(runId, undefined, "llm_response", undefined, undefined, {
|
|
158
|
+
sessionId,
|
|
159
|
+
});
|
|
142
160
|
const decision = await this.safeScan([{ role: "assistant", content: text }], "output", undefined, context);
|
|
143
161
|
this.handleDecision(decision, runId);
|
|
144
162
|
}
|
|
145
163
|
handleLLMError(_error, runId) {
|
|
146
164
|
this.chainContext.delete(runId);
|
|
165
|
+
this.runSessions.delete(runId);
|
|
147
166
|
}
|
|
148
167
|
// -- Chain callbacks -----------------------------------------------------
|
|
149
|
-
async handleChainStart(serialized, _inputs, runId, parentRunId, tags) {
|
|
168
|
+
async handleChainStart(serialized, _inputs, runId, parentRunId, tags, metadata) {
|
|
150
169
|
const chainName = serialized?.id?.slice(-1)[0] ?? "unknown";
|
|
151
170
|
this.chainContext.set(runId, {
|
|
152
171
|
chain_name: chainName,
|
|
153
172
|
parent_run_id: parentRunId,
|
|
154
173
|
tags,
|
|
174
|
+
session_id: (0, session_1.sessionIdFromMetadata)(metadata),
|
|
155
175
|
});
|
|
156
176
|
}
|
|
157
177
|
handleChainEnd(_outputs, runId) {
|
|
@@ -171,19 +191,24 @@ class PromptGuardCallbackHandler {
|
|
|
171
191
|
});
|
|
172
192
|
const decision = await this.safeScan([{ role: "user", content: input }], "input", "tool", context);
|
|
173
193
|
this.handleDecision(decision, runId);
|
|
194
|
+
this.rememberRun(runId, context.sessionId);
|
|
174
195
|
}
|
|
175
196
|
async handleToolEnd(output, runId) {
|
|
197
|
+
const sessionId = this.endRun(runId);
|
|
176
198
|
if (!this.scanResponses)
|
|
177
199
|
return;
|
|
178
200
|
const text = output ? String(output) : "";
|
|
179
201
|
if (!text)
|
|
180
202
|
return;
|
|
181
|
-
const context = this.buildContext(runId, undefined, "tool_response"
|
|
203
|
+
const context = this.buildContext(runId, undefined, "tool_response", undefined, undefined, {
|
|
204
|
+
sessionId,
|
|
205
|
+
});
|
|
182
206
|
const decision = await this.safeScan([{ role: "assistant", content: text }], "output", undefined, context);
|
|
183
207
|
this.handleDecision(decision, runId);
|
|
184
208
|
}
|
|
185
209
|
handleToolError(_error, runId) {
|
|
186
210
|
this.chainContext.delete(runId);
|
|
211
|
+
this.runSessions.delete(runId);
|
|
187
212
|
}
|
|
188
213
|
// -- Internal helpers ----------------------------------------------------
|
|
189
214
|
async safeScan(messages, direction, model, context) {
|
|
@@ -224,14 +249,48 @@ class PromptGuardCallbackHandler {
|
|
|
224
249
|
`(event=${decision.eventId}, run=${runId})`);
|
|
225
250
|
}
|
|
226
251
|
}
|
|
227
|
-
|
|
252
|
+
/**
|
|
253
|
+
* Keep a run's session id for its end scan.
|
|
254
|
+
*
|
|
255
|
+
* Called only once the start scan has returned: @langchain/core starts a
|
|
256
|
+
* run outside the block whose error path calls `handleLLMError`, so a
|
|
257
|
+
* start that throws gets no end or error callback, and anything stored
|
|
258
|
+
* before it would never be removed. Nothing is stored when the end scan
|
|
259
|
+
* will not run, or would name no session.
|
|
260
|
+
*/
|
|
261
|
+
rememberRun(runId, sessionId) {
|
|
262
|
+
if (sessionId !== undefined && this.scanResponses)
|
|
263
|
+
this.runSessions.set(runId, sessionId);
|
|
264
|
+
}
|
|
265
|
+
/** Forget a finished LLM or tool run; return the session id it started with. */
|
|
266
|
+
endRun(runId) {
|
|
267
|
+
const sessionId = this.runSessions.get(runId);
|
|
268
|
+
this.runSessions.delete(runId);
|
|
269
|
+
return sessionId;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* The scan's context. A start callback passes its `metadata`, and the
|
|
273
|
+
* session id is read from it; an end callback passes the `sessionId` its
|
|
274
|
+
* start remembered. Nothing is stored here.
|
|
275
|
+
*/
|
|
276
|
+
buildContext(runId, parentRunId, component = "unknown", tags, metadata, end) {
|
|
228
277
|
const chainInfo = this.chainContext.get(runId) ??
|
|
229
278
|
(parentRunId ? this.chainContext.get(parentRunId) : undefined) ??
|
|
230
279
|
{};
|
|
280
|
+
let sessionId;
|
|
281
|
+
if (end) {
|
|
282
|
+
sessionId = end.sessionId;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
sessionId =
|
|
286
|
+
(0, session_1.sessionIdFromMetadata)(metadata) ??
|
|
287
|
+
chainInfo.session_id ??
|
|
288
|
+
this.sessionId;
|
|
289
|
+
}
|
|
231
290
|
return {
|
|
232
291
|
framework: "langchain",
|
|
233
292
|
chainName: chainInfo.chain_name,
|
|
234
|
-
sessionId:
|
|
293
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
235
294
|
metadata: {
|
|
236
295
|
component,
|
|
237
296
|
tags: tags ?? chainInfo.tags,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"langchain.js","sourceRoot":"","sources":["../../src/integrations/langchain.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"langchain.js","sourceRoot":"","sources":["../../src/integrations/langchain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Conversation a framework integration's scans belong to.
|
|
3
|
+
*
|
|
4
|
+
* The Guard API remembers a Conversation's turns when a scan names it in
|
|
5
|
+
* `context.session_id`. An integration must send the framework's real
|
|
6
|
+
* conversation id there — the same value on every turn of one conversation, a
|
|
7
|
+
* different one for another — or nothing at all. A per-call run id would make
|
|
8
|
+
* every scan a conversation of its own.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The longest session id sent: the Guard API refuses a longer one, matching
|
|
12
|
+
* the column that stores it, so it is dropped before the scan.
|
|
13
|
+
*/
|
|
14
|
+
export declare const MAX_SESSION_ID_CHARS = 255;
|
|
15
|
+
/**
|
|
16
|
+
* The metadata keys a LangChain call carries its conversation id under, in
|
|
17
|
+
* the order they are read. LangGraph copies the checkpointer's `thread_id`
|
|
18
|
+
* into every callback's metadata; `session_id` and `conversation_id` are the
|
|
19
|
+
* other two keys LangSmith groups a thread by, set through `config.metadata`.
|
|
20
|
+
*/
|
|
21
|
+
export declare const CONVERSATION_METADATA_KEYS: readonly ["thread_id", "session_id", "conversation_id"];
|
|
22
|
+
/**
|
|
23
|
+
* `value` as a session id, or `undefined` when it cannot be one: a non-empty
|
|
24
|
+
* string as it is, a finite number in its decimal form, anything else not.
|
|
25
|
+
* Nor an id over {@link MAX_SESSION_ID_CHARS}: it is dropped with a debug log
|
|
26
|
+
* and the scan goes ahead without one, never failing the call (ADR-0002).
|
|
27
|
+
*/
|
|
28
|
+
export declare function asSessionId(value: unknown): string | undefined;
|
|
29
|
+
/** The conversation id a LangChain call's metadata names, if any. */
|
|
30
|
+
export declare function sessionIdFromMetadata(metadata: Record<string, unknown> | undefined): string | undefined;
|
|
31
|
+
/** Check a `sessionId` an application passed to an integration. */
|
|
32
|
+
export declare function validateSessionId(sessionId: string | undefined): string | undefined;
|
|
33
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/integrations/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,yDAA0D,CAAA;AAEjG;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAc9D;AAED,qEAAqE;AACrE,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC5C,MAAM,GAAG,SAAS,CAOpB;AAED,mEAAmE;AACnE,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAUnF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The Conversation a framework integration's scans belong to.
|
|
4
|
+
*
|
|
5
|
+
* The Guard API remembers a Conversation's turns when a scan names it in
|
|
6
|
+
* `context.session_id`. An integration must send the framework's real
|
|
7
|
+
* conversation id there — the same value on every turn of one conversation, a
|
|
8
|
+
* different one for another — or nothing at all. A per-call run id would make
|
|
9
|
+
* every scan a conversation of its own.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CONVERSATION_METADATA_KEYS = exports.MAX_SESSION_ID_CHARS = void 0;
|
|
13
|
+
exports.asSessionId = asSessionId;
|
|
14
|
+
exports.sessionIdFromMetadata = sessionIdFromMetadata;
|
|
15
|
+
exports.validateSessionId = validateSessionId;
|
|
16
|
+
const logger_1 = require("../logger");
|
|
17
|
+
/**
|
|
18
|
+
* The longest session id sent: the Guard API refuses a longer one, matching
|
|
19
|
+
* the column that stores it, so it is dropped before the scan.
|
|
20
|
+
*/
|
|
21
|
+
exports.MAX_SESSION_ID_CHARS = 255;
|
|
22
|
+
/**
|
|
23
|
+
* The metadata keys a LangChain call carries its conversation id under, in
|
|
24
|
+
* the order they are read. LangGraph copies the checkpointer's `thread_id`
|
|
25
|
+
* into every callback's metadata; `session_id` and `conversation_id` are the
|
|
26
|
+
* other two keys LangSmith groups a thread by, set through `config.metadata`.
|
|
27
|
+
*/
|
|
28
|
+
exports.CONVERSATION_METADATA_KEYS = ["thread_id", "session_id", "conversation_id"];
|
|
29
|
+
/**
|
|
30
|
+
* `value` as a session id, or `undefined` when it cannot be one: a non-empty
|
|
31
|
+
* string as it is, a finite number in its decimal form, anything else not.
|
|
32
|
+
* Nor an id over {@link MAX_SESSION_ID_CHARS}: it is dropped with a debug log
|
|
33
|
+
* and the scan goes ahead without one, never failing the call (ADR-0002).
|
|
34
|
+
*/
|
|
35
|
+
function asSessionId(value) {
|
|
36
|
+
const id = typeof value === "number" && Number.isFinite(value)
|
|
37
|
+
? String(value)
|
|
38
|
+
: typeof value === "string" && value.trim()
|
|
39
|
+
? value
|
|
40
|
+
: undefined;
|
|
41
|
+
if (id !== undefined && id.length > exports.MAX_SESSION_ID_CHARS) {
|
|
42
|
+
logger_1.logger.debug(`session id of ${id.length} characters is over ${exports.MAX_SESSION_ID_CHARS}; scanning without one`);
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
return id;
|
|
46
|
+
}
|
|
47
|
+
/** The conversation id a LangChain call's metadata names, if any. */
|
|
48
|
+
function sessionIdFromMetadata(metadata) {
|
|
49
|
+
if (!metadata)
|
|
50
|
+
return undefined;
|
|
51
|
+
for (const key of exports.CONVERSATION_METADATA_KEYS) {
|
|
52
|
+
const sessionId = asSessionId(metadata[key]);
|
|
53
|
+
if (sessionId !== undefined)
|
|
54
|
+
return sessionId;
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
/** Check a `sessionId` an application passed to an integration. */
|
|
59
|
+
function validateSessionId(sessionId) {
|
|
60
|
+
if (sessionId === undefined)
|
|
61
|
+
return undefined;
|
|
62
|
+
if (typeof sessionId !== "string" || !sessionId.trim()) {
|
|
63
|
+
throw new TypeError(`sessionId must be a non-empty string, got ${JSON.stringify(sessionId)}`);
|
|
64
|
+
}
|
|
65
|
+
if (sessionId.length > exports.MAX_SESSION_ID_CHARS) {
|
|
66
|
+
// Configuration, not a request: refused when the integration is built.
|
|
67
|
+
throw new TypeError(`sessionId must be at most ${exports.MAX_SESSION_ID_CHARS} characters`);
|
|
68
|
+
}
|
|
69
|
+
return sessionId;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/integrations/session.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAwBH,kCAcC;AAGD,sDASC;AAGD,8CAUC;AA7DD,sCAAkC;AAElC;;;GAGG;AACU,QAAA,oBAAoB,GAAG,GAAG,CAAA;AAEvC;;;;;GAKG;AACU,QAAA,0BAA0B,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,iBAAiB,CAAU,CAAA;AAEjG;;;;;GAKG;AACH,SAAgB,WAAW,CAAC,KAAc;IACxC,MAAM,EAAE,GACN,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACjD,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACf,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE;YACzC,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,SAAS,CAAA;IACjB,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,CAAC,MAAM,GAAG,4BAAoB,EAAE,CAAC;QACzD,eAAM,CAAC,KAAK,CACV,iBAAiB,EAAE,CAAC,MAAM,uBAAuB,4BAAoB,wBAAwB,CAC9F,CAAA;QACD,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AAED,qEAAqE;AACrE,SAAgB,qBAAqB,CACnC,QAA6C;IAE7C,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAA;IAC/B,KAAK,MAAM,GAAG,IAAI,kCAA0B,EAAE,CAAC;QAC7C,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;QAC5C,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;IAC/C,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,mEAAmE;AACnE,SAAgB,iBAAiB,CAAC,SAA6B;IAC7D,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAC7C,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QACvD,MAAM,IAAI,SAAS,CAAC,6CAA6C,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IAC/F,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,GAAG,4BAAoB,EAAE,CAAC;QAC5C,uEAAuE;QACvE,MAAM,IAAI,SAAS,CAAC,6BAA6B,4BAAoB,aAAa,CAAC,CAAA;IACrF,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
|