@providerprotocol/ai 0.0.34 → 0.0.36
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 +546 -3
- package/dist/anthropic/index.d.ts +2 -1
- package/dist/anthropic/index.js +151 -145
- package/dist/anthropic/index.js.map +1 -1
- package/dist/cerebras/index.d.ts +392 -0
- package/dist/cerebras/index.js +648 -0
- package/dist/cerebras/index.js.map +1 -0
- package/dist/chunk-2YXFLRQ6.js +49 -0
- package/dist/chunk-2YXFLRQ6.js.map +1 -0
- package/dist/chunk-4OGB7JZA.js +157 -0
- package/dist/chunk-4OGB7JZA.js.map +1 -0
- package/dist/chunk-4RX4VQCB.js +31 -0
- package/dist/chunk-4RX4VQCB.js.map +1 -0
- package/dist/chunk-5IWHCXKN.js +30 -0
- package/dist/chunk-5IWHCXKN.js.map +1 -0
- package/dist/{chunk-3C7O2RNO.js → chunk-A2IM7PGT.js} +6 -4
- package/dist/{chunk-3C7O2RNO.js.map → chunk-A2IM7PGT.js.map} +1 -1
- package/dist/{chunk-3D6XGGVG.js → chunk-ARVM24K2.js} +2 -2
- package/dist/{chunk-4J6OFUKX.js → chunk-AY55T37A.js} +70 -162
- package/dist/chunk-AY55T37A.js.map +1 -0
- package/dist/{chunk-ILR2D5PN.js → chunk-BRP5XJ6Q.js} +2 -86
- package/dist/chunk-BRP5XJ6Q.js.map +1 -0
- package/dist/chunk-C4JP64VW.js +298 -0
- package/dist/chunk-C4JP64VW.js.map +1 -0
- package/dist/chunk-COS4ON4G.js +111 -0
- package/dist/chunk-COS4ON4G.js.map +1 -0
- package/dist/chunk-CRP6Y7NF.js +31 -0
- package/dist/chunk-CRP6Y7NF.js.map +1 -0
- package/dist/chunk-EPB3GQNL.js +118 -0
- package/dist/chunk-EPB3GQNL.js.map +1 -0
- package/dist/chunk-ETBFOLQN.js +34 -0
- package/dist/chunk-ETBFOLQN.js.map +1 -0
- package/dist/chunk-I53CI6ZZ.js +142 -0
- package/dist/chunk-I53CI6ZZ.js.map +1 -0
- package/dist/chunk-IDZOVWP3.js +29 -0
- package/dist/chunk-IDZOVWP3.js.map +1 -0
- package/dist/chunk-JA3UZALR.js +88 -0
- package/dist/chunk-JA3UZALR.js.map +1 -0
- package/dist/{chunk-WAKD3OO5.js → chunk-N5DX5JW3.js} +31 -31
- package/dist/chunk-N5DX5JW3.js.map +1 -0
- package/dist/chunk-OIEWDFQU.js +97 -0
- package/dist/chunk-OIEWDFQU.js.map +1 -0
- package/dist/{chunk-TOJCZMVU.js → chunk-PMK5LZ5Z.js} +40 -40
- package/dist/chunk-PMK5LZ5Z.js.map +1 -0
- package/dist/{chunk-6S222DHN.js → chunk-RJGTRQ47.js} +20 -1
- package/dist/chunk-RJGTRQ47.js.map +1 -0
- package/dist/chunk-UFFJDYCE.js +94 -0
- package/dist/chunk-UFFJDYCE.js.map +1 -0
- package/dist/chunk-VGKZIGVI.js +222 -0
- package/dist/chunk-VGKZIGVI.js.map +1 -0
- package/dist/{chunk-KUPF5KHT.js → chunk-Y5H7C5J4.js} +2 -2
- package/dist/{embedding-D2BYIehX.d.ts → embedding-BXA72PlJ.d.ts} +1 -1
- package/dist/google/index.d.ts +2 -1
- package/dist/google/index.js +202 -199
- package/dist/google/index.js.map +1 -1
- package/dist/groq/index.d.ts +410 -0
- package/dist/groq/index.js +649 -0
- package/dist/groq/index.js.map +1 -0
- package/dist/http/index.d.ts +3 -2
- package/dist/http/index.js +5 -4
- package/dist/image-stream-CCgwB7ve.d.ts +11 -0
- package/dist/index.d.ts +8 -118
- package/dist/index.js +520 -769
- package/dist/index.js.map +1 -1
- package/dist/{llm-BQJZj3cD.d.ts → llm-ByUFPcFH.d.ts} +12 -1632
- package/dist/middleware/logging/index.d.ts +76 -0
- package/dist/middleware/logging/index.js +74 -0
- package/dist/middleware/logging/index.js.map +1 -0
- package/dist/middleware/parsed-object/index.d.ts +45 -0
- package/dist/middleware/parsed-object/index.js +73 -0
- package/dist/middleware/parsed-object/index.js.map +1 -0
- package/dist/middleware/pubsub/index.d.ts +97 -0
- package/dist/middleware/pubsub/index.js +160 -0
- package/dist/middleware/pubsub/index.js.map +1 -0
- package/dist/middleware/pubsub/server/express/index.d.ts +66 -0
- package/dist/middleware/pubsub/server/express/index.js +11 -0
- package/dist/middleware/pubsub/server/express/index.js.map +1 -0
- package/dist/middleware/pubsub/server/fastify/index.d.ts +67 -0
- package/dist/middleware/pubsub/server/fastify/index.js +11 -0
- package/dist/middleware/pubsub/server/fastify/index.js.map +1 -0
- package/dist/middleware/pubsub/server/h3/index.d.ts +70 -0
- package/dist/middleware/pubsub/server/h3/index.js +11 -0
- package/dist/middleware/pubsub/server/h3/index.js.map +1 -0
- package/dist/middleware/pubsub/server/index.d.ts +78 -0
- package/dist/middleware/pubsub/server/index.js +34 -0
- package/dist/middleware/pubsub/server/index.js.map +1 -0
- package/dist/middleware/pubsub/server/webapi/index.d.ts +63 -0
- package/dist/middleware/pubsub/server/webapi/index.js +11 -0
- package/dist/middleware/pubsub/server/webapi/index.js.map +1 -0
- package/dist/ollama/index.d.ts +2 -1
- package/dist/ollama/index.js +48 -45
- package/dist/ollama/index.js.map +1 -1
- package/dist/openai/index.d.ts +2 -1
- package/dist/openai/index.js +319 -313
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +2 -1
- package/dist/openrouter/index.js +381 -385
- package/dist/openrouter/index.js.map +1 -1
- package/dist/proxy/index.d.ts +10 -914
- package/dist/proxy/index.js +275 -1007
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/server/express/index.d.ts +161 -0
- package/dist/proxy/server/express/index.js +24 -0
- package/dist/proxy/server/express/index.js.map +1 -0
- package/dist/proxy/server/fastify/index.d.ts +162 -0
- package/dist/proxy/server/fastify/index.js +24 -0
- package/dist/proxy/server/fastify/index.js.map +1 -0
- package/dist/proxy/server/h3/index.d.ts +189 -0
- package/dist/proxy/server/h3/index.js +28 -0
- package/dist/proxy/server/h3/index.js.map +1 -0
- package/dist/proxy/server/index.d.ts +151 -0
- package/dist/proxy/server/index.js +48 -0
- package/dist/proxy/server/index.js.map +1 -0
- package/dist/proxy/server/webapi/index.d.ts +278 -0
- package/dist/proxy/server/webapi/index.js +32 -0
- package/dist/proxy/server/webapi/index.js.map +1 -0
- package/dist/responses/index.d.ts +650 -0
- package/dist/responses/index.js +930 -0
- package/dist/responses/index.js.map +1 -0
- package/dist/{retry-8Ch-WWgX.d.ts → retry-BDMo4AVu.d.ts} +1 -1
- package/dist/stream-S7nwQRqM.d.ts +1643 -0
- package/dist/types-CE4B7pno.d.ts +96 -0
- package/dist/utils/index.d.ts +53 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/xai/index.d.ts +2 -1
- package/dist/xai/index.js +310 -310
- package/dist/xai/index.js.map +1 -1
- package/package.json +82 -4
- package/dist/chunk-4J6OFUKX.js.map +0 -1
- package/dist/chunk-6S222DHN.js.map +0 -1
- package/dist/chunk-ILR2D5PN.js.map +0 -1
- package/dist/chunk-TOJCZMVU.js.map +0 -1
- package/dist/chunk-WAKD3OO5.js.map +0 -1
- /package/dist/{chunk-3D6XGGVG.js.map → chunk-ARVM24K2.js.map} +0 -0
- /package/dist/{chunk-KUPF5KHT.js.map → chunk-Y5H7C5J4.js.map} +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { M as Middleware } from '../../llm-ByUFPcFH.js';
|
|
2
|
+
import '../../stream-S7nwQRqM.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Logging middleware for request/response visibility.
|
|
6
|
+
*
|
|
7
|
+
* Provides configurable logging for LLM, embedding, and image operations,
|
|
8
|
+
* including timing, error tracking, and optional event logging.
|
|
9
|
+
*
|
|
10
|
+
* @module middleware/logging
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Log levels for filtering output.
|
|
15
|
+
*/
|
|
16
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
17
|
+
/**
|
|
18
|
+
* Options for logging middleware.
|
|
19
|
+
*/
|
|
20
|
+
interface LoggingOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Minimum log level to output.
|
|
23
|
+
* @default 'info'
|
|
24
|
+
*/
|
|
25
|
+
level?: LogLevel;
|
|
26
|
+
/**
|
|
27
|
+
* Log individual stream events.
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
logStreamEvents?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Log tool calls and results.
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
logToolCalls?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Custom logger function. If not provided, uses console.log.
|
|
38
|
+
* @param level - The log level
|
|
39
|
+
* @param message - The log message
|
|
40
|
+
* @param data - Optional additional data
|
|
41
|
+
*/
|
|
42
|
+
logger?(level: LogLevel, message: string, data?: Record<string, unknown>): void;
|
|
43
|
+
/**
|
|
44
|
+
* Prefix for all log messages.
|
|
45
|
+
* @default '[PP]'
|
|
46
|
+
*/
|
|
47
|
+
prefix?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Creates a logging middleware for visibility into request lifecycle.
|
|
51
|
+
*
|
|
52
|
+
* This middleware logs the start, end, and errors of requests,
|
|
53
|
+
* with optional logging of stream events and tool calls.
|
|
54
|
+
*
|
|
55
|
+
* @param options - Configuration options
|
|
56
|
+
* @returns A middleware that logs request lifecycle events
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* import { llm } from '@providerprotocol/ai';
|
|
61
|
+
* import { loggingMiddleware } from '@providerprotocol/ai/middleware/logging';
|
|
62
|
+
* import { anthropic } from '@providerprotocol/ai/anthropic';
|
|
63
|
+
*
|
|
64
|
+
* const model = llm({
|
|
65
|
+
* model: anthropic('claude-sonnet-4-20250514'),
|
|
66
|
+
* middleware: [loggingMiddleware({ level: 'debug' })],
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* // Logs: [PP] [anthropic] Starting llm request (streaming)
|
|
70
|
+
* // Logs: [PP] [anthropic] Completed in 1234ms
|
|
71
|
+
* const result = await model.generate('Hello');
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
declare function loggingMiddleware(options?: LoggingOptions): Middleware;
|
|
75
|
+
|
|
76
|
+
export { type LogLevel, type LoggingOptions, loggingMiddleware };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// src/middleware/logging.ts
|
|
2
|
+
var LOG_LEVELS = {
|
|
3
|
+
debug: 0,
|
|
4
|
+
info: 1,
|
|
5
|
+
warn: 2,
|
|
6
|
+
error: 3
|
|
7
|
+
};
|
|
8
|
+
function loggingMiddleware(options = {}) {
|
|
9
|
+
const {
|
|
10
|
+
level = "info",
|
|
11
|
+
logStreamEvents = false,
|
|
12
|
+
logToolCalls = true,
|
|
13
|
+
logger,
|
|
14
|
+
prefix = "[PP]"
|
|
15
|
+
} = options;
|
|
16
|
+
const minLevel = LOG_LEVELS[level];
|
|
17
|
+
const log = (logLevel, message, data) => {
|
|
18
|
+
if (LOG_LEVELS[logLevel] < minLevel) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const fullMessage = `${prefix} ${message}`;
|
|
22
|
+
if (logger) {
|
|
23
|
+
logger(logLevel, fullMessage, data);
|
|
24
|
+
} else {
|
|
25
|
+
const consoleMethod = logLevel === "error" ? console.error : logLevel === "warn" ? console.warn : console.log;
|
|
26
|
+
if (data) {
|
|
27
|
+
consoleMethod(fullMessage, data);
|
|
28
|
+
} else {
|
|
29
|
+
consoleMethod(fullMessage);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
name: "logging",
|
|
35
|
+
onStart(ctx) {
|
|
36
|
+
const streamingLabel = ctx.streaming ? "(streaming)" : "";
|
|
37
|
+
log("info", `[${ctx.provider}] Starting ${ctx.modality} request ${streamingLabel}`.trim());
|
|
38
|
+
log("debug", `[${ctx.provider}] Model: ${ctx.modelId}`);
|
|
39
|
+
},
|
|
40
|
+
onEnd(ctx) {
|
|
41
|
+
const duration = ctx.endTime ? ctx.endTime - ctx.startTime : 0;
|
|
42
|
+
log("info", `[${ctx.provider}] Completed in ${duration}ms`);
|
|
43
|
+
},
|
|
44
|
+
onError(error, ctx) {
|
|
45
|
+
const duration = Date.now() - ctx.startTime;
|
|
46
|
+
log("error", `[${ctx.provider}] Error after ${duration}ms: ${error.message}`);
|
|
47
|
+
},
|
|
48
|
+
onAbort(error, ctx) {
|
|
49
|
+
const duration = Date.now() - ctx.startTime;
|
|
50
|
+
log("warn", `[${ctx.provider}] Aborted after ${duration}ms: ${error.message}`);
|
|
51
|
+
},
|
|
52
|
+
onStreamEvent(event, ctx) {
|
|
53
|
+
if (logStreamEvents) {
|
|
54
|
+
log("debug", `Stream event: ${event.type}`, { index: event.index });
|
|
55
|
+
}
|
|
56
|
+
return event;
|
|
57
|
+
},
|
|
58
|
+
onToolCall(tool, params, ctx) {
|
|
59
|
+
if (logToolCalls) {
|
|
60
|
+
log("info", `[${ctx.provider}] Tool call: ${tool.name}`);
|
|
61
|
+
log("debug", `[${ctx.provider}] Tool params:`, { params });
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
onToolResult(tool, result, ctx) {
|
|
65
|
+
if (logToolCalls) {
|
|
66
|
+
log("debug", `[${ctx.provider}] Tool result: ${tool.name}`, { result });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
loggingMiddleware
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/middleware/logging.ts"],"sourcesContent":["/**\n * @fileoverview Logging middleware for request/response visibility.\n *\n * Provides configurable logging for LLM, embedding, and image operations,\n * including timing, error tracking, and optional event logging.\n *\n * @module middleware/logging\n */\n\nimport type { Middleware, MiddlewareContext, StreamContext } from '../types/middleware.ts';\nimport type { StreamEvent } from '../types/stream.ts';\n\n/**\n * Log levels for filtering output.\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\n/**\n * Options for logging middleware.\n */\nexport interface LoggingOptions {\n /**\n * Minimum log level to output.\n * @default 'info'\n */\n level?: LogLevel;\n\n /**\n * Log individual stream events.\n * @default false\n */\n logStreamEvents?: boolean;\n\n /**\n * Log tool calls and results.\n * @default true\n */\n logToolCalls?: boolean;\n\n /**\n * Custom logger function. If not provided, uses console.log.\n * @param level - The log level\n * @param message - The log message\n * @param data - Optional additional data\n */\n logger?(level: LogLevel, message: string, data?: Record<string, unknown>): void;\n\n /**\n * Prefix for all log messages.\n * @default '[PP]'\n */\n prefix?: string;\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/**\n * Creates a logging middleware for visibility into request lifecycle.\n *\n * This middleware logs the start, end, and errors of requests,\n * with optional logging of stream events and tool calls.\n *\n * @param options - Configuration options\n * @returns A middleware that logs request lifecycle events\n *\n * @example\n * ```typescript\n * import { llm } from '@providerprotocol/ai';\n * import { loggingMiddleware } from '@providerprotocol/ai/middleware/logging';\n * import { anthropic } from '@providerprotocol/ai/anthropic';\n *\n * const model = llm({\n * model: anthropic('claude-sonnet-4-20250514'),\n * middleware: [loggingMiddleware({ level: 'debug' })],\n * });\n *\n * // Logs: [PP] [anthropic] Starting llm request (streaming)\n * // Logs: [PP] [anthropic] Completed in 1234ms\n * const result = await model.generate('Hello');\n * ```\n */\nexport function loggingMiddleware(options: LoggingOptions = {}): Middleware {\n const {\n level = 'info',\n logStreamEvents = false,\n logToolCalls = true,\n logger,\n prefix = '[PP]',\n } = options;\n\n const minLevel = LOG_LEVELS[level];\n\n const log = (logLevel: LogLevel, message: string, data?: Record<string, unknown>) => {\n if (LOG_LEVELS[logLevel] < minLevel) {\n return;\n }\n\n const fullMessage = `${prefix} ${message}`;\n\n if (logger) {\n logger(logLevel, fullMessage, data);\n } else {\n const consoleMethod = logLevel === 'error' ? console.error : logLevel === 'warn' ? console.warn : console.log;\n if (data) {\n consoleMethod(fullMessage, data);\n } else {\n consoleMethod(fullMessage);\n }\n }\n };\n\n return {\n name: 'logging',\n\n onStart(ctx: MiddlewareContext): void {\n const streamingLabel = ctx.streaming ? '(streaming)' : '';\n log('info', `[${ctx.provider}] Starting ${ctx.modality} request ${streamingLabel}`.trim());\n log('debug', `[${ctx.provider}] Model: ${ctx.modelId}`);\n },\n\n onEnd(ctx: MiddlewareContext): void {\n const duration = ctx.endTime ? ctx.endTime - ctx.startTime : 0;\n log('info', `[${ctx.provider}] Completed in ${duration}ms`);\n },\n\n onError(error: Error, ctx: MiddlewareContext): void {\n const duration = Date.now() - ctx.startTime;\n log('error', `[${ctx.provider}] Error after ${duration}ms: ${error.message}`);\n },\n\n onAbort(error: Error, ctx: MiddlewareContext): void {\n const duration = Date.now() - ctx.startTime;\n log('warn', `[${ctx.provider}] Aborted after ${duration}ms: ${error.message}`);\n },\n\n onStreamEvent(event: StreamEvent, ctx: StreamContext): StreamEvent {\n if (logStreamEvents) {\n log('debug', `Stream event: ${event.type}`, { index: event.index });\n }\n return event;\n },\n\n onToolCall(tool, params, ctx: MiddlewareContext): void {\n if (logToolCalls) {\n log('info', `[${ctx.provider}] Tool call: ${tool.name}`);\n log('debug', `[${ctx.provider}] Tool params:`, { params });\n }\n },\n\n onToolResult(tool, result, ctx: MiddlewareContext): void {\n if (logToolCalls) {\n log('debug', `[${ctx.provider}] Tool result: ${tool.name}`, { result });\n }\n },\n };\n}\n"],"mappings":";AAsDA,IAAM,aAAuC;AAAA,EAC3C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AA2BO,SAAS,kBAAkB,UAA0B,CAAC,GAAe;AAC1E,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf;AAAA,IACA,SAAS;AAAA,EACX,IAAI;AAEJ,QAAM,WAAW,WAAW,KAAK;AAEjC,QAAM,MAAM,CAAC,UAAoB,SAAiB,SAAmC;AACnF,QAAI,WAAW,QAAQ,IAAI,UAAU;AACnC;AAAA,IACF;AAEA,UAAM,cAAc,GAAG,MAAM,IAAI,OAAO;AAExC,QAAI,QAAQ;AACV,aAAO,UAAU,aAAa,IAAI;AAAA,IACpC,OAAO;AACL,YAAM,gBAAgB,aAAa,UAAU,QAAQ,QAAQ,aAAa,SAAS,QAAQ,OAAO,QAAQ;AAC1G,UAAI,MAAM;AACR,sBAAc,aAAa,IAAI;AAAA,MACjC,OAAO;AACL,sBAAc,WAAW;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,QAAQ,KAA8B;AACpC,YAAM,iBAAiB,IAAI,YAAY,gBAAgB;AACvD,UAAI,QAAQ,IAAI,IAAI,QAAQ,cAAc,IAAI,QAAQ,YAAY,cAAc,GAAG,KAAK,CAAC;AACzF,UAAI,SAAS,IAAI,IAAI,QAAQ,YAAY,IAAI,OAAO,EAAE;AAAA,IACxD;AAAA,IAEA,MAAM,KAA8B;AAClC,YAAM,WAAW,IAAI,UAAU,IAAI,UAAU,IAAI,YAAY;AAC7D,UAAI,QAAQ,IAAI,IAAI,QAAQ,kBAAkB,QAAQ,IAAI;AAAA,IAC5D;AAAA,IAEA,QAAQ,OAAc,KAA8B;AAClD,YAAM,WAAW,KAAK,IAAI,IAAI,IAAI;AAClC,UAAI,SAAS,IAAI,IAAI,QAAQ,iBAAiB,QAAQ,OAAO,MAAM,OAAO,EAAE;AAAA,IAC9E;AAAA,IAEA,QAAQ,OAAc,KAA8B;AAClD,YAAM,WAAW,KAAK,IAAI,IAAI,IAAI;AAClC,UAAI,QAAQ,IAAI,IAAI,QAAQ,mBAAmB,QAAQ,OAAO,MAAM,OAAO,EAAE;AAAA,IAC/E;AAAA,IAEA,cAAc,OAAoB,KAAiC;AACjE,UAAI,iBAAiB;AACnB,YAAI,SAAS,iBAAiB,MAAM,IAAI,IAAI,EAAE,OAAO,MAAM,MAAM,CAAC;AAAA,MACpE;AACA,aAAO;AAAA,IACT;AAAA,IAEA,WAAW,MAAM,QAAQ,KAA8B;AACrD,UAAI,cAAc;AAChB,YAAI,QAAQ,IAAI,IAAI,QAAQ,gBAAgB,KAAK,IAAI,EAAE;AACvD,YAAI,SAAS,IAAI,IAAI,QAAQ,kBAAkB,EAAE,OAAO,CAAC;AAAA,MAC3D;AAAA,IACF;AAAA,IAEA,aAAa,MAAM,QAAQ,KAA8B;AACvD,UAAI,cAAc;AAChB,YAAI,SAAS,IAAI,IAAI,QAAQ,kBAAkB,KAAK,IAAI,IAAI,EAAE,OAAO,CAAC;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { M as Middleware } from '../../llm-ByUFPcFH.js';
|
|
2
|
+
import { E as EventDelta, S as StreamEvent } from '../../stream-S7nwQRqM.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Parsed object middleware for incremental JSON parsing.
|
|
6
|
+
*
|
|
7
|
+
* This middleware parses partial JSON from ObjectDelta and ToolCallDelta
|
|
8
|
+
* stream events, providing incremental structured data during streaming.
|
|
9
|
+
*
|
|
10
|
+
* @module middleware/parsed-object
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Event delta with parsed JSON data.
|
|
15
|
+
* Extended by parsedObjectMiddleware when parsing is enabled.
|
|
16
|
+
*/
|
|
17
|
+
interface ParsedEventDelta extends EventDelta {
|
|
18
|
+
/** Incrementally parsed JSON value */
|
|
19
|
+
parsed?: unknown;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Stream event with parsed JSON data.
|
|
23
|
+
* Returned by parsedObjectMiddleware for ObjectDelta and ToolCallDelta events.
|
|
24
|
+
*/
|
|
25
|
+
interface ParsedStreamEvent extends Omit<StreamEvent, 'delta'> {
|
|
26
|
+
delta: ParsedEventDelta;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Options for parsed object middleware.
|
|
30
|
+
*/
|
|
31
|
+
interface ParsedObjectOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Parse ObjectDelta events (structured output responses).
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
parseObjects?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Parse ToolCallDelta events (tool call arguments).
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
parseToolCalls?: boolean;
|
|
42
|
+
}
|
|
43
|
+
declare function parsedObjectMiddleware(options?: ParsedObjectOptions): Middleware;
|
|
44
|
+
|
|
45
|
+
export { type ParsedEventDelta, type ParsedObjectOptions, type ParsedStreamEvent, parsedObjectMiddleware };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parsePartialJson
|
|
3
|
+
} from "../../chunk-I53CI6ZZ.js";
|
|
4
|
+
import {
|
|
5
|
+
StreamEventType
|
|
6
|
+
} from "../../chunk-RJGTRQ47.js";
|
|
7
|
+
|
|
8
|
+
// src/middleware/parsed-object.ts
|
|
9
|
+
var ACCUMULATED_TEXT_KEY = "parsedObject:text";
|
|
10
|
+
var ACCUMULATED_ARGS_KEY = "parsedObject:args";
|
|
11
|
+
function getAccumulatedText(state) {
|
|
12
|
+
let map = state.get(ACCUMULATED_TEXT_KEY);
|
|
13
|
+
if (!map) {
|
|
14
|
+
map = /* @__PURE__ */ new Map();
|
|
15
|
+
state.set(ACCUMULATED_TEXT_KEY, map);
|
|
16
|
+
}
|
|
17
|
+
return map;
|
|
18
|
+
}
|
|
19
|
+
function getAccumulatedArgs(state) {
|
|
20
|
+
let map = state.get(ACCUMULATED_ARGS_KEY);
|
|
21
|
+
if (!map) {
|
|
22
|
+
map = /* @__PURE__ */ new Map();
|
|
23
|
+
state.set(ACCUMULATED_ARGS_KEY, map);
|
|
24
|
+
}
|
|
25
|
+
return map;
|
|
26
|
+
}
|
|
27
|
+
function parsedObjectMiddleware(options = {}) {
|
|
28
|
+
const { parseObjects = true, parseToolCalls = true } = options;
|
|
29
|
+
return {
|
|
30
|
+
name: "parsed-object",
|
|
31
|
+
onStreamEvent(event, ctx) {
|
|
32
|
+
if (parseObjects && event.type === StreamEventType.ObjectDelta) {
|
|
33
|
+
const accumulatedText = getAccumulatedText(ctx.state);
|
|
34
|
+
const current = accumulatedText.get(event.index) ?? "";
|
|
35
|
+
const newText = current + (event.delta.text ?? "");
|
|
36
|
+
accumulatedText.set(event.index, newText);
|
|
37
|
+
const parseResult = parsePartialJson(newText);
|
|
38
|
+
const parsedEvent = {
|
|
39
|
+
...event,
|
|
40
|
+
delta: {
|
|
41
|
+
...event.delta,
|
|
42
|
+
parsed: parseResult.value
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
return parsedEvent;
|
|
46
|
+
}
|
|
47
|
+
if (parseToolCalls && event.type === StreamEventType.ToolCallDelta) {
|
|
48
|
+
const accumulatedArgs = getAccumulatedArgs(ctx.state);
|
|
49
|
+
const current = accumulatedArgs.get(event.index) ?? "";
|
|
50
|
+
const newJson = current + (event.delta.argumentsJson ?? "");
|
|
51
|
+
accumulatedArgs.set(event.index, newJson);
|
|
52
|
+
const parseResult = parsePartialJson(newJson);
|
|
53
|
+
const parsedEvent = {
|
|
54
|
+
...event,
|
|
55
|
+
delta: {
|
|
56
|
+
...event.delta,
|
|
57
|
+
parsed: parseResult.value
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
return parsedEvent;
|
|
61
|
+
}
|
|
62
|
+
return event;
|
|
63
|
+
},
|
|
64
|
+
onStreamEnd(ctx) {
|
|
65
|
+
ctx.state.delete(ACCUMULATED_TEXT_KEY);
|
|
66
|
+
ctx.state.delete(ACCUMULATED_ARGS_KEY);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
parsedObjectMiddleware
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/middleware/parsed-object.ts"],"sourcesContent":["/**\n * @fileoverview Parsed object middleware for incremental JSON parsing.\n *\n * This middleware parses partial JSON from ObjectDelta and ToolCallDelta\n * stream events, providing incremental structured data during streaming.\n *\n * @module middleware/parsed-object\n */\n\nimport type { Middleware, StreamContext } from '../types/middleware.ts';\nimport type { EventDelta, StreamEvent } from '../types/stream.ts';\nimport { StreamEventType } from '../types/stream.ts';\nimport { parsePartialJson } from '../utils/partial-json.ts';\n\n/**\n * Event delta with parsed JSON data.\n * Extended by parsedObjectMiddleware when parsing is enabled.\n */\nexport interface ParsedEventDelta extends EventDelta {\n /** Incrementally parsed JSON value */\n parsed?: unknown;\n}\n\n/**\n * Stream event with parsed JSON data.\n * Returned by parsedObjectMiddleware for ObjectDelta and ToolCallDelta events.\n */\nexport interface ParsedStreamEvent extends Omit<StreamEvent, 'delta'> {\n delta: ParsedEventDelta;\n}\n\n/**\n * Options for parsed object middleware.\n */\nexport interface ParsedObjectOptions {\n /**\n * Parse ObjectDelta events (structured output responses).\n * @default true\n */\n parseObjects?: boolean;\n\n /**\n * Parse ToolCallDelta events (tool call arguments).\n * @default true\n */\n parseToolCalls?: boolean;\n}\n\n/**\n * Creates a middleware that parses partial JSON from stream events.\n *\n * This middleware accumulates text from ObjectDelta events and tool\n * argument JSON from ToolCallDelta events, then parses them incrementally\n * using partial JSON parsing. The parsed result is added to the event's\n * `parsed` field.\n *\n * @param options - Configuration options\n * @returns A middleware that adds parsed JSON to stream events\n *\n * @example\n * ```typescript\n * import { llm } from '@providerprotocol/ai';\n * import { parsedObjectMiddleware } from '@providerprotocol/ai/middleware/parsed-object';\n * import { anthropic } from '@providerprotocol/ai/anthropic';\n *\n * const model = llm({\n * model: anthropic('claude-sonnet-4-20250514'),\n * structure: mySchema,\n * middleware: [parsedObjectMiddleware()],\n * });\n *\n * for await (const event of model.stream('Extract data from this text')) {\n * if (event.type === 'object_delta') {\n * // event.delta.parsed contains incrementally parsed object\n * console.log(event.delta.parsed);\n * }\n * }\n * ```\n */\n/** State key for accumulated object text */\nconst ACCUMULATED_TEXT_KEY = 'parsedObject:text';\n/** State key for accumulated tool arguments */\nconst ACCUMULATED_ARGS_KEY = 'parsedObject:args';\n\n/**\n * Gets or creates the accumulated text map from state.\n */\nfunction getAccumulatedText(state: Map<string, unknown>): Map<number, string> {\n let map = state.get(ACCUMULATED_TEXT_KEY) as Map<number, string> | undefined;\n if (!map) {\n map = new Map();\n state.set(ACCUMULATED_TEXT_KEY, map);\n }\n return map;\n}\n\n/**\n * Gets or creates the accumulated args map from state.\n */\nfunction getAccumulatedArgs(state: Map<string, unknown>): Map<number, string> {\n let map = state.get(ACCUMULATED_ARGS_KEY) as Map<number, string> | undefined;\n if (!map) {\n map = new Map();\n state.set(ACCUMULATED_ARGS_KEY, map);\n }\n return map;\n}\n\nexport function parsedObjectMiddleware(options: ParsedObjectOptions = {}): Middleware {\n const { parseObjects = true, parseToolCalls = true } = options;\n\n return {\n name: 'parsed-object',\n\n onStreamEvent(event: StreamEvent, ctx: StreamContext): StreamEvent | StreamEvent[] | null {\n if (parseObjects && event.type === StreamEventType.ObjectDelta) {\n const accumulatedText = getAccumulatedText(ctx.state);\n const current = accumulatedText.get(event.index) ?? '';\n const newText = current + (event.delta.text ?? '');\n accumulatedText.set(event.index, newText);\n\n const parseResult = parsePartialJson(newText);\n\n const parsedEvent: ParsedStreamEvent = {\n ...event,\n delta: {\n ...event.delta,\n parsed: parseResult.value,\n },\n };\n return parsedEvent as StreamEvent;\n }\n\n if (parseToolCalls && event.type === StreamEventType.ToolCallDelta) {\n const accumulatedArgs = getAccumulatedArgs(ctx.state);\n const current = accumulatedArgs.get(event.index) ?? '';\n const newJson = current + (event.delta.argumentsJson ?? '');\n accumulatedArgs.set(event.index, newJson);\n\n const parseResult = parsePartialJson(newJson);\n\n const parsedEvent: ParsedStreamEvent = {\n ...event,\n delta: {\n ...event.delta,\n parsed: parseResult.value,\n },\n };\n return parsedEvent as StreamEvent;\n }\n\n return event;\n },\n\n onStreamEnd(ctx: StreamContext): void {\n // Clean up accumulated state to prevent memory buildup in long sessions\n ctx.state.delete(ACCUMULATED_TEXT_KEY);\n ctx.state.delete(ACCUMULATED_ARGS_KEY);\n },\n };\n}\n"],"mappings":";;;;;;;;AAgFA,IAAM,uBAAuB;AAE7B,IAAM,uBAAuB;AAK7B,SAAS,mBAAmB,OAAkD;AAC5E,MAAI,MAAM,MAAM,IAAI,oBAAoB;AACxC,MAAI,CAAC,KAAK;AACR,UAAM,oBAAI,IAAI;AACd,UAAM,IAAI,sBAAsB,GAAG;AAAA,EACrC;AACA,SAAO;AACT;AAKA,SAAS,mBAAmB,OAAkD;AAC5E,MAAI,MAAM,MAAM,IAAI,oBAAoB;AACxC,MAAI,CAAC,KAAK;AACR,UAAM,oBAAI,IAAI;AACd,UAAM,IAAI,sBAAsB,GAAG;AAAA,EACrC;AACA,SAAO;AACT;AAEO,SAAS,uBAAuB,UAA+B,CAAC,GAAe;AACpF,QAAM,EAAE,eAAe,MAAM,iBAAiB,KAAK,IAAI;AAEvD,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,cAAc,OAAoB,KAAwD;AACxF,UAAI,gBAAgB,MAAM,SAAS,gBAAgB,aAAa;AAC9D,cAAM,kBAAkB,mBAAmB,IAAI,KAAK;AACpD,cAAM,UAAU,gBAAgB,IAAI,MAAM,KAAK,KAAK;AACpD,cAAM,UAAU,WAAW,MAAM,MAAM,QAAQ;AAC/C,wBAAgB,IAAI,MAAM,OAAO,OAAO;AAExC,cAAM,cAAc,iBAAiB,OAAO;AAE5C,cAAM,cAAiC;AAAA,UACrC,GAAG;AAAA,UACH,OAAO;AAAA,YACL,GAAG,MAAM;AAAA,YACT,QAAQ,YAAY;AAAA,UACtB;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAEA,UAAI,kBAAkB,MAAM,SAAS,gBAAgB,eAAe;AAClE,cAAM,kBAAkB,mBAAmB,IAAI,KAAK;AACpD,cAAM,UAAU,gBAAgB,IAAI,MAAM,KAAK,KAAK;AACpD,cAAM,UAAU,WAAW,MAAM,MAAM,iBAAiB;AACxD,wBAAgB,IAAI,MAAM,OAAO,OAAO;AAExC,cAAM,cAAc,iBAAiB,OAAO;AAE5C,cAAM,cAAiC;AAAA,UACrC,GAAG;AAAA,UACH,OAAO;AAAA,YACL,GAAG,MAAM;AAAA,YACT,QAAQ,YAAY;AAAA,UACtB;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,YAAY,KAA0B;AAEpC,UAAI,MAAM,OAAO,oBAAoB;AACrC,UAAI,MAAM,OAAO,oBAAoB;AAAA,IACvC;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { M as Middleware } from '../../llm-ByUFPcFH.js';
|
|
2
|
+
import { M as MemoryAdapterOptions, P as PubSubAdapter, a as PubSubOptions } from '../../types-CE4B7pno.js';
|
|
3
|
+
export { C as CompletionCallback, S as StoredStream, b as SubscriptionCallback, U as Unsubscribe } from '../../types-CE4B7pno.js';
|
|
4
|
+
import '../../stream-S7nwQRqM.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview In-memory storage adapter for pub-sub middleware.
|
|
8
|
+
*
|
|
9
|
+
* Provides a simple Map-based implementation for temporary stream
|
|
10
|
+
* storage during active generation.
|
|
11
|
+
*
|
|
12
|
+
* @module middleware/pubsub/memory-adapter
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates an in-memory storage adapter for pub-sub middleware.
|
|
17
|
+
*
|
|
18
|
+
* Stores streams in a Map. Throws when maxStreams is exceeded.
|
|
19
|
+
* Streams are created lazily on first append or subscribe.
|
|
20
|
+
*
|
|
21
|
+
* @param options - Adapter configuration
|
|
22
|
+
* @returns A PubSubAdapter instance
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';
|
|
27
|
+
*
|
|
28
|
+
* const adapter = memoryAdapter({ maxStreams: 500 });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
declare function memoryAdapter(options?: MemoryAdapterOptions): PubSubAdapter;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @fileoverview Pub-sub middleware for stream resumption.
|
|
35
|
+
*
|
|
36
|
+
* Enables reconnecting clients to catch up on missed events during
|
|
37
|
+
* active generation. The middleware buffers events and publishes them
|
|
38
|
+
* to subscribers. Server routes handle reconnection logic using the
|
|
39
|
+
* exported `createSubscriberStream` utility.
|
|
40
|
+
*
|
|
41
|
+
* @module middleware/pubsub
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Gets the stream ID from middleware state.
|
|
46
|
+
*
|
|
47
|
+
* @param state - Middleware state map
|
|
48
|
+
* @returns Stream ID or undefined if not set
|
|
49
|
+
*/
|
|
50
|
+
declare function getStreamId(state: Map<string, unknown>): string | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Gets the adapter from middleware state.
|
|
53
|
+
*
|
|
54
|
+
* @param state - Middleware state map
|
|
55
|
+
* @returns Adapter or undefined if not set
|
|
56
|
+
*/
|
|
57
|
+
declare function getAdapter(state: Map<string, unknown>): PubSubAdapter | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Creates pub-sub middleware for stream buffering and publishing.
|
|
60
|
+
*
|
|
61
|
+
* The middleware:
|
|
62
|
+
* - Creates stream entries for new requests
|
|
63
|
+
* - Buffers all stream events
|
|
64
|
+
* - Publishes events to subscribers
|
|
65
|
+
* - On stream end: notifies subscribers, then removes from adapter
|
|
66
|
+
*
|
|
67
|
+
* Server routes handle reconnection logic using `streamSubscriber`.
|
|
68
|
+
*
|
|
69
|
+
* @param options - Middleware configuration
|
|
70
|
+
* @returns Middleware instance
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* import { llm } from '@providerprotocol/ai';
|
|
75
|
+
* import { anthropic } from '@providerprotocol/ai/anthropic';
|
|
76
|
+
* import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';
|
|
77
|
+
* import { h3 } from '@providerprotocol/ai/middleware/pubsub/server';
|
|
78
|
+
*
|
|
79
|
+
* const adapter = memoryAdapter();
|
|
80
|
+
*
|
|
81
|
+
* export default defineEventHandler(async (event) => {
|
|
82
|
+
* const { input, conversationId } = await readBody(event);
|
|
83
|
+
*
|
|
84
|
+
* // Fire and forget - subscriber connects immediately, events flow when ready
|
|
85
|
+
* const model = llm({
|
|
86
|
+
* model: anthropic('claude-sonnet-4-20250514'),
|
|
87
|
+
* middleware: [pubsubMiddleware({ adapter, streamId: conversationId })],
|
|
88
|
+
* });
|
|
89
|
+
* model.stream(input).then(turn => saveToDatabase(turn));
|
|
90
|
+
*
|
|
91
|
+
* return h3.streamSubscriber(conversationId, adapter, event);
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
declare function pubsubMiddleware(options?: PubSubOptions): Middleware;
|
|
96
|
+
|
|
97
|
+
export { MemoryAdapterOptions, PubSubAdapter, PubSubOptions, getAdapter, getStreamId, memoryAdapter, pubsubMiddleware };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// src/middleware/pubsub/memory-adapter.ts
|
|
2
|
+
function memoryAdapter(options = {}) {
|
|
3
|
+
const { maxStreams = 1e3 } = options;
|
|
4
|
+
const streams = /* @__PURE__ */ new Map();
|
|
5
|
+
const eventCursors = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
const scheduleCallback = (callback) => {
|
|
7
|
+
queueMicrotask(() => {
|
|
8
|
+
try {
|
|
9
|
+
callback();
|
|
10
|
+
} catch {
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
const getOrCreate = (streamId) => {
|
|
15
|
+
let entry = streams.get(streamId);
|
|
16
|
+
if (!entry) {
|
|
17
|
+
if (streams.size >= maxStreams) {
|
|
18
|
+
throw new Error(`Maximum concurrent streams (${maxStreams}) exceeded`);
|
|
19
|
+
}
|
|
20
|
+
entry = {
|
|
21
|
+
stream: {
|
|
22
|
+
streamId,
|
|
23
|
+
createdAt: Date.now(),
|
|
24
|
+
events: []
|
|
25
|
+
},
|
|
26
|
+
subscribers: /* @__PURE__ */ new Set()
|
|
27
|
+
};
|
|
28
|
+
streams.set(streamId, entry);
|
|
29
|
+
}
|
|
30
|
+
return entry;
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
async exists(streamId) {
|
|
34
|
+
return streams.has(streamId);
|
|
35
|
+
},
|
|
36
|
+
async append(streamId, event) {
|
|
37
|
+
const entry = getOrCreate(streamId);
|
|
38
|
+
entry.stream.events.push(event);
|
|
39
|
+
eventCursors.set(event, entry.stream.events.length - 1);
|
|
40
|
+
},
|
|
41
|
+
async getEvents(streamId) {
|
|
42
|
+
const entry = streams.get(streamId);
|
|
43
|
+
return entry ? [...entry.stream.events] : [];
|
|
44
|
+
},
|
|
45
|
+
subscribe(streamId, onEvent, onComplete) {
|
|
46
|
+
const entry = getOrCreate(streamId);
|
|
47
|
+
const subscriber = { onEvent, onComplete };
|
|
48
|
+
entry.subscribers.add(subscriber);
|
|
49
|
+
return () => {
|
|
50
|
+
entry.subscribers.delete(subscriber);
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
publish(streamId, event) {
|
|
54
|
+
const entry = streams.get(streamId);
|
|
55
|
+
if (!entry) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const cursor = eventCursors.get(event) ?? entry.stream.events.length - 1;
|
|
59
|
+
for (const subscriber of entry.subscribers) {
|
|
60
|
+
scheduleCallback(() => {
|
|
61
|
+
subscriber.onEvent(event, cursor);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
async remove(streamId) {
|
|
66
|
+
const entry = streams.get(streamId);
|
|
67
|
+
if (entry) {
|
|
68
|
+
for (const subscriber of entry.subscribers) {
|
|
69
|
+
scheduleCallback(subscriber.onComplete);
|
|
70
|
+
}
|
|
71
|
+
streams.delete(streamId);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/middleware/pubsub/index.ts
|
|
78
|
+
var STATE_KEY_STREAM_ID = "pubsub:streamId";
|
|
79
|
+
var STATE_KEY_ADAPTER = "pubsub:adapter";
|
|
80
|
+
function getStreamId(state) {
|
|
81
|
+
return state.get(STATE_KEY_STREAM_ID);
|
|
82
|
+
}
|
|
83
|
+
function getAdapter(state) {
|
|
84
|
+
return state.get(STATE_KEY_ADAPTER);
|
|
85
|
+
}
|
|
86
|
+
function pubsubMiddleware(options = {}) {
|
|
87
|
+
const {
|
|
88
|
+
adapter = memoryAdapter(),
|
|
89
|
+
streamId
|
|
90
|
+
} = options;
|
|
91
|
+
const appendChains = /* @__PURE__ */ new Map();
|
|
92
|
+
const enqueueAppend = (id, event) => {
|
|
93
|
+
const state = appendChains.get(id) ?? { chain: Promise.resolve() };
|
|
94
|
+
const task = state.chain.catch(() => {
|
|
95
|
+
}).then(async () => {
|
|
96
|
+
await adapter.append(id, event);
|
|
97
|
+
adapter.publish(id, event);
|
|
98
|
+
});
|
|
99
|
+
state.chain = task.catch(() => {
|
|
100
|
+
});
|
|
101
|
+
appendChains.set(id, state);
|
|
102
|
+
};
|
|
103
|
+
const waitForAppends = async (id) => {
|
|
104
|
+
const state = appendChains.get(id);
|
|
105
|
+
if (!state) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
await state.chain.catch(() => {
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
const clearAppendState = (id) => {
|
|
112
|
+
appendChains.delete(id);
|
|
113
|
+
};
|
|
114
|
+
const finalizeStreamByState = async (state) => {
|
|
115
|
+
const id = state.get(STATE_KEY_STREAM_ID);
|
|
116
|
+
if (!id) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
await waitForAppends(id);
|
|
120
|
+
clearAppendState(id);
|
|
121
|
+
await adapter.remove(id).catch(() => {
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
return {
|
|
125
|
+
name: "pubsub",
|
|
126
|
+
onStart(ctx) {
|
|
127
|
+
ctx.state.set(STATE_KEY_ADAPTER, adapter);
|
|
128
|
+
if (streamId) {
|
|
129
|
+
ctx.state.set(STATE_KEY_STREAM_ID, streamId);
|
|
130
|
+
adapter.subscribe(streamId, () => {
|
|
131
|
+
}, () => {
|
|
132
|
+
})();
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
onStreamEvent(event, ctx) {
|
|
136
|
+
const id = ctx.state.get(STATE_KEY_STREAM_ID);
|
|
137
|
+
if (!id) {
|
|
138
|
+
return event;
|
|
139
|
+
}
|
|
140
|
+
enqueueAppend(id, event);
|
|
141
|
+
return event;
|
|
142
|
+
},
|
|
143
|
+
async onStreamEnd(ctx) {
|
|
144
|
+
await finalizeStreamByState(ctx.state);
|
|
145
|
+
},
|
|
146
|
+
async onError(_error, ctx) {
|
|
147
|
+
await finalizeStreamByState(ctx.state);
|
|
148
|
+
},
|
|
149
|
+
async onAbort(_error, ctx) {
|
|
150
|
+
await finalizeStreamByState(ctx.state);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
export {
|
|
155
|
+
getAdapter,
|
|
156
|
+
getStreamId,
|
|
157
|
+
memoryAdapter,
|
|
158
|
+
pubsubMiddleware
|
|
159
|
+
};
|
|
160
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/middleware/pubsub/memory-adapter.ts","../../../src/middleware/pubsub/index.ts"],"sourcesContent":["/**\n * @fileoverview In-memory storage adapter for pub-sub middleware.\n *\n * Provides a simple Map-based implementation for temporary stream\n * storage during active generation.\n *\n * @module middleware/pubsub/memory-adapter\n */\n\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type {\n PubSubAdapter,\n StoredStream,\n SubscriptionCallback,\n CompletionCallback,\n Unsubscribe,\n MemoryAdapterOptions,\n} from './types.ts';\n\ninterface MutableStoredStream {\n streamId: string;\n createdAt: number;\n events: StreamEvent[];\n}\n\ninterface Subscriber {\n onEvent: SubscriptionCallback;\n onComplete: CompletionCallback;\n}\n\ninterface StreamEntry {\n stream: MutableStoredStream;\n subscribers: Set<Subscriber>;\n}\n\n/**\n * Creates an in-memory storage adapter for pub-sub middleware.\n *\n * Stores streams in a Map. Throws when maxStreams is exceeded.\n * Streams are created lazily on first append or subscribe.\n *\n * @param options - Adapter configuration\n * @returns A PubSubAdapter instance\n *\n * @example\n * ```typescript\n * import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';\n *\n * const adapter = memoryAdapter({ maxStreams: 500 });\n * ```\n */\nexport function memoryAdapter(options: MemoryAdapterOptions = {}): PubSubAdapter {\n const { maxStreams = 1000 } = options;\n\n const streams = new Map<string, StreamEntry>();\n const eventCursors = new WeakMap<StreamEvent, number>();\n\n const scheduleCallback = (callback: () => void): void => {\n queueMicrotask(() => {\n try {\n callback();\n } catch {\n // Subscriber errors should not affect other subscribers\n }\n });\n };\n\n const getOrCreate = (streamId: string): StreamEntry => {\n let entry = streams.get(streamId);\n if (!entry) {\n if (streams.size >= maxStreams) {\n throw new Error(`Maximum concurrent streams (${maxStreams}) exceeded`);\n }\n entry = {\n stream: {\n streamId,\n createdAt: Date.now(),\n events: [],\n },\n subscribers: new Set(),\n };\n streams.set(streamId, entry);\n }\n return entry;\n };\n\n return {\n async exists(streamId): Promise<boolean> {\n return streams.has(streamId);\n },\n\n async append(streamId, event): Promise<void> {\n const entry = getOrCreate(streamId);\n entry.stream.events.push(event);\n eventCursors.set(event, entry.stream.events.length - 1);\n },\n\n async getEvents(streamId): Promise<StreamEvent[]> {\n const entry = streams.get(streamId);\n return entry ? [...entry.stream.events] : [];\n },\n\n subscribe(streamId, onEvent, onComplete): Unsubscribe {\n const entry = getOrCreate(streamId);\n const subscriber: Subscriber = { onEvent, onComplete };\n entry.subscribers.add(subscriber);\n\n return () => {\n entry.subscribers.delete(subscriber);\n };\n },\n\n publish(streamId, event): void {\n const entry = streams.get(streamId);\n if (!entry) {\n return;\n }\n\n const cursor = eventCursors.get(event) ?? entry.stream.events.length - 1;\n for (const subscriber of entry.subscribers) {\n scheduleCallback(() => {\n subscriber.onEvent(event, cursor);\n });\n }\n },\n\n async remove(streamId): Promise<void> {\n const entry = streams.get(streamId);\n if (entry) {\n for (const subscriber of entry.subscribers) {\n scheduleCallback(subscriber.onComplete);\n }\n streams.delete(streamId);\n }\n },\n };\n}\n","/**\n * @fileoverview Pub-sub middleware for stream resumption.\n *\n * Enables reconnecting clients to catch up on missed events during\n * active generation. The middleware buffers events and publishes them\n * to subscribers. Server routes handle reconnection logic using the\n * exported `createSubscriberStream` utility.\n *\n * @module middleware/pubsub\n */\n\nimport type {\n Middleware,\n MiddlewareContext,\n StreamContext,\n} from '../../types/middleware.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { PubSubAdapter, PubSubOptions } from './types.ts';\nimport { memoryAdapter } from './memory-adapter.ts';\n\nexport type {\n PubSubAdapter,\n PubSubOptions,\n StoredStream,\n SubscriptionCallback,\n CompletionCallback,\n Unsubscribe,\n MemoryAdapterOptions,\n} from './types.ts';\nexport { memoryAdapter } from './memory-adapter.ts';\n\nconst STATE_KEY_STREAM_ID = 'pubsub:streamId';\nconst STATE_KEY_ADAPTER = 'pubsub:adapter';\n\ninterface AppendChainState {\n chain: Promise<void>;\n}\n\n/**\n * Gets the stream ID from middleware state.\n *\n * @param state - Middleware state map\n * @returns Stream ID or undefined if not set\n */\nexport function getStreamId(state: Map<string, unknown>): string | undefined {\n return state.get(STATE_KEY_STREAM_ID) as string | undefined;\n}\n\n/**\n * Gets the adapter from middleware state.\n *\n * @param state - Middleware state map\n * @returns Adapter or undefined if not set\n */\nexport function getAdapter(state: Map<string, unknown>): PubSubAdapter | undefined {\n return state.get(STATE_KEY_ADAPTER) as PubSubAdapter | undefined;\n}\n\n/**\n * Creates pub-sub middleware for stream buffering and publishing.\n *\n * The middleware:\n * - Creates stream entries for new requests\n * - Buffers all stream events\n * - Publishes events to subscribers\n * - On stream end: notifies subscribers, then removes from adapter\n *\n * Server routes handle reconnection logic using `streamSubscriber`.\n *\n * @param options - Middleware configuration\n * @returns Middleware instance\n *\n * @example\n * ```typescript\n * import { llm } from '@providerprotocol/ai';\n * import { anthropic } from '@providerprotocol/ai/anthropic';\n * import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';\n * import { h3 } from '@providerprotocol/ai/middleware/pubsub/server';\n *\n * const adapter = memoryAdapter();\n *\n * export default defineEventHandler(async (event) => {\n * const { input, conversationId } = await readBody(event);\n *\n * // Fire and forget - subscriber connects immediately, events flow when ready\n * const model = llm({\n * model: anthropic('claude-sonnet-4-20250514'),\n * middleware: [pubsubMiddleware({ adapter, streamId: conversationId })],\n * });\n * model.stream(input).then(turn => saveToDatabase(turn));\n *\n * return h3.streamSubscriber(conversationId, adapter, event);\n * });\n * ```\n */\nexport function pubsubMiddleware(options: PubSubOptions = {}): Middleware {\n const {\n adapter = memoryAdapter(),\n streamId,\n } = options;\n\n const appendChains = new Map<string, AppendChainState>();\n\n const enqueueAppend = (id: string, event: StreamEvent): void => {\n const state = appendChains.get(id) ?? { chain: Promise.resolve() };\n\n const task = state.chain\n .catch(() => {})\n .then(async () => {\n await adapter.append(id, event);\n adapter.publish(id, event);\n });\n\n state.chain = task.catch(() => {});\n appendChains.set(id, state);\n };\n\n const waitForAppends = async (id: string): Promise<void> => {\n const state = appendChains.get(id);\n if (!state) {\n return;\n }\n\n await state.chain.catch(() => {});\n };\n\n const clearAppendState = (id: string): void => {\n appendChains.delete(id);\n };\n\n /**\n * Finalizes a stream by marking completion and removing from adapter.\n *\n * Called on any terminal state (complete, error, abort). After finalization,\n * the stream is removed from the adapter. Apps should use `.then()` to persist\n * completed conversations and serve them from their own storage on reconnect.\n */\n const finalizeStreamByState = async (state: Map<string, unknown>): Promise<void> => {\n const id = state.get(STATE_KEY_STREAM_ID) as string | undefined;\n if (!id) {\n return;\n }\n\n await waitForAppends(id);\n clearAppendState(id);\n\n // Remove from adapter (notifies subscribers) - apps persist via .then()\n await adapter.remove(id).catch(() => {});\n };\n\n return {\n name: 'pubsub',\n\n onStart(ctx: MiddlewareContext): void {\n ctx.state.set(STATE_KEY_ADAPTER, adapter);\n\n if (streamId) {\n ctx.state.set(STATE_KEY_STREAM_ID, streamId);\n // Ensure stream exists immediately so exists() returns true\n // before first token arrives (prevents duplicate generations)\n adapter.subscribe(streamId, () => {}, () => {})();\n }\n },\n\n onStreamEvent(event: StreamEvent, ctx: StreamContext): StreamEvent {\n const id = ctx.state.get(STATE_KEY_STREAM_ID) as string | undefined;\n if (!id) {\n return event;\n }\n\n enqueueAppend(id, event);\n\n return event;\n },\n\n async onStreamEnd(ctx: StreamContext): Promise<void> {\n await finalizeStreamByState(ctx.state);\n },\n\n async onError(_error: Error, ctx: MiddlewareContext): Promise<void> {\n await finalizeStreamByState(ctx.state);\n },\n\n async onAbort(_error: Error, ctx: MiddlewareContext): Promise<void> {\n await finalizeStreamByState(ctx.state);\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { P as PubSubAdapter } from '../../../../types-CE4B7pno.js';
|
|
2
|
+
import '../../../../stream-S7nwQRqM.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Express/Connect adapter for pub-sub stream resumption.
|
|
6
|
+
*
|
|
7
|
+
* Provides utilities for Express.js or Connect-based servers
|
|
8
|
+
* to handle stream reconnections.
|
|
9
|
+
*
|
|
10
|
+
* @module middleware/pubsub/server/express
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Express Response interface (minimal type to avoid dependency).
|
|
15
|
+
*/
|
|
16
|
+
interface ExpressResponse {
|
|
17
|
+
setHeader(name: string, value: string): void;
|
|
18
|
+
write(chunk: string): boolean;
|
|
19
|
+
end(): void;
|
|
20
|
+
on(event: 'close', listener: () => void): void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Stream buffered and live events to an Express response.
|
|
24
|
+
*
|
|
25
|
+
* Handles reconnection for Express routes:
|
|
26
|
+
* 1. Replays buffered events from the adapter
|
|
27
|
+
* 2. Subscribes to live events until completion signal
|
|
28
|
+
* 3. Ends when stream completes or client disconnects
|
|
29
|
+
*
|
|
30
|
+
* @param streamId - The stream ID to subscribe to
|
|
31
|
+
* @param adapter - The pub-sub adapter instance
|
|
32
|
+
* @param res - Express response object
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* import { llm } from '@providerprotocol/ai';
|
|
37
|
+
* import { anthropic } from '@providerprotocol/ai/anthropic';
|
|
38
|
+
* import { pubsubMiddleware, memoryAdapter } from '@providerprotocol/ai/middleware/pubsub';
|
|
39
|
+
* import { express } from '@providerprotocol/ai/middleware/pubsub/server';
|
|
40
|
+
*
|
|
41
|
+
* const adapter = memoryAdapter();
|
|
42
|
+
*
|
|
43
|
+
* app.post('/api/chat', async (req, res) => {
|
|
44
|
+
* const { input, conversationId } = req.body;
|
|
45
|
+
*
|
|
46
|
+
* if (!await adapter.exists(conversationId)) {
|
|
47
|
+
* const model = llm({
|
|
48
|
+
* model: anthropic('claude-sonnet-4-20250514'),
|
|
49
|
+
* middleware: [pubsubMiddleware({ adapter, streamId: conversationId })],
|
|
50
|
+
* });
|
|
51
|
+
* model.stream(input).then(turn => saveToDatabase(conversationId, turn));
|
|
52
|
+
* }
|
|
53
|
+
*
|
|
54
|
+
* return express.streamSubscriber(conversationId, adapter, res);
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare function streamSubscriber(streamId: string, adapter: PubSubAdapter, res: ExpressResponse): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Express adapter namespace for pub-sub server utilities.
|
|
61
|
+
*/
|
|
62
|
+
declare const express: {
|
|
63
|
+
streamSubscriber: typeof streamSubscriber;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export { express, streamSubscriber };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|