@providerprotocol/ai 0.0.36 → 0.0.37
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 +28 -0
- package/dist/anthropic/index.d.ts +2 -2
- package/dist/anthropic/index.js +12 -10
- package/dist/anthropic/index.js.map +1 -1
- package/dist/cerebras/index.d.ts +2 -2
- package/dist/cerebras/index.js +12 -10
- package/dist/cerebras/index.js.map +1 -1
- package/dist/{chunk-UFFJDYCE.js → chunk-7GTWHZY2.js} +2 -2
- package/dist/{chunk-OIEWDFQU.js → chunk-FYSZFIZS.js} +2 -2
- package/dist/chunk-GIDT7C6I.js +37 -0
- package/dist/chunk-GIDT7C6I.js.map +1 -0
- package/dist/{chunk-IDZOVWP3.js → chunk-IK6NRCW5.js} +7 -7
- package/dist/{chunk-VGKZIGVI.js → chunk-LTEMH3CI.js} +2 -2
- package/dist/{chunk-RJGTRQ47.js → chunk-MJI74VEJ.js} +6 -1
- package/dist/chunk-MJI74VEJ.js.map +1 -0
- package/dist/{chunk-AY55T37A.js → chunk-SBGZJVTJ.js} +4 -30
- package/dist/chunk-SBGZJVTJ.js.map +1 -0
- package/dist/{chunk-A2IM7PGT.js → chunk-TUTYMOBL.js} +2 -2
- package/dist/{chunk-BRP5XJ6Q.js → chunk-WU4U6IHF.js} +2 -2
- package/dist/chunk-WU4U6IHF.js.map +1 -0
- package/dist/{chunk-C4JP64VW.js → chunk-YQLR3XOA.js} +2 -2
- package/dist/chunk-ZKNPQBIE.js +265 -0
- package/dist/chunk-ZKNPQBIE.js.map +1 -0
- package/dist/{chunk-4OGB7JZA.js → chunk-ZRVNAET3.js} +2 -2
- package/dist/{embedding-BXA72PlJ.d.ts → embedding-CwZ1ZNWv.d.ts} +1 -1
- package/dist/google/index.d.ts +2 -2
- package/dist/google/index.js +12 -10
- package/dist/google/index.js.map +1 -1
- package/dist/groq/index.d.ts +2 -2
- package/dist/groq/index.js +12 -10
- package/dist/groq/index.js.map +1 -1
- package/dist/http/index.d.ts +3 -3
- package/dist/http/index.js +2 -1
- package/dist/{image-stream-CCgwB7ve.d.ts → image-stream-CeQHtjxS.d.ts} +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +86 -283
- package/dist/index.js.map +1 -1
- package/dist/{llm-ByUFPcFH.d.ts → llm-DS_-l71X.d.ts} +11 -3
- package/dist/middleware/logging/index.d.ts +2 -2
- package/dist/middleware/parsed-object/index.d.ts +2 -2
- package/dist/middleware/parsed-object/index.js +1 -1
- package/dist/middleware/persistence/index.d.ts +128 -0
- package/dist/middleware/persistence/index.js +144 -0
- package/dist/middleware/persistence/index.js.map +1 -0
- package/dist/middleware/pubsub/index.d.ts +4 -4
- package/dist/middleware/pubsub/server/express/index.d.ts +2 -2
- package/dist/middleware/pubsub/server/fastify/index.d.ts +2 -2
- package/dist/middleware/pubsub/server/h3/index.d.ts +2 -2
- package/dist/middleware/pubsub/server/index.d.ts +2 -2
- package/dist/middleware/pubsub/server/webapi/index.d.ts +2 -2
- package/dist/ollama/index.d.ts +2 -2
- package/dist/ollama/index.js +12 -10
- package/dist/ollama/index.js.map +1 -1
- package/dist/openai/index.d.ts +2 -2
- package/dist/openai/index.js +12 -10
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +2 -2
- package/dist/openrouter/index.js +12 -10
- package/dist/openrouter/index.js.map +1 -1
- package/dist/proxy/index.d.ts +4 -4
- package/dist/proxy/index.js +20 -18
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/server/express/index.d.ts +4 -4
- package/dist/proxy/server/express/index.js +3 -3
- package/dist/proxy/server/fastify/index.d.ts +4 -4
- package/dist/proxy/server/fastify/index.js +3 -3
- package/dist/proxy/server/h3/index.d.ts +4 -4
- package/dist/proxy/server/h3/index.js +3 -3
- package/dist/proxy/server/index.d.ts +4 -4
- package/dist/proxy/server/index.js +9 -9
- package/dist/proxy/server/webapi/index.d.ts +4 -4
- package/dist/proxy/server/webapi/index.js +3 -3
- package/dist/responses/index.d.ts +2 -2
- package/dist/responses/index.js +12 -10
- package/dist/responses/index.js.map +1 -1
- package/dist/{retry-BDMo4AVu.d.ts → retry-CgoBNa51.d.ts} +1 -1
- package/dist/{stream-S7nwQRqM.d.ts → stream-sXhBtWjl.d.ts} +4 -0
- package/dist/{types-CE4B7pno.d.ts → types-Cr4F0tVy.d.ts} +1 -1
- package/dist/xai/index.d.ts +2 -2
- package/dist/xai/index.js +12 -10
- package/dist/xai/index.js.map +1 -1
- package/package.json +6 -1
- package/dist/chunk-AY55T37A.js.map +0 -1
- package/dist/chunk-BRP5XJ6Q.js.map +0 -1
- package/dist/chunk-RJGTRQ47.js.map +0 -1
- /package/dist/{chunk-UFFJDYCE.js.map → chunk-7GTWHZY2.js.map} +0 -0
- /package/dist/{chunk-OIEWDFQU.js.map → chunk-FYSZFIZS.js.map} +0 -0
- /package/dist/{chunk-IDZOVWP3.js.map → chunk-IK6NRCW5.js.map} +0 -0
- /package/dist/{chunk-VGKZIGVI.js.map → chunk-LTEMH3CI.js.map} +0 -0
- /package/dist/{chunk-A2IM7PGT.js.map → chunk-TUTYMOBL.js.map} +0 -0
- /package/dist/{chunk-C4JP64VW.js.map → chunk-YQLR3XOA.js.map} +0 -0
- /package/dist/{chunk-4OGB7JZA.js.map → chunk-ZRVNAET3.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as ImageSource, c as ImageBlock, S as StreamEvent, d as Tool, M as Message,
|
|
1
|
+
import { I as ImageSource, c as ImageBlock, T as Turn, S as StreamEvent, d as Tool, M as Message, U as UserContent, A as AssistantContent, e as MessageType, a as MessageJSON, f as ToolUseStrategy, J as JSONSchema, g as AssistantMessage, h as TokenUsage, C as ContentBlock, i as StreamResult } from './stream-sXhBtWjl.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @fileoverview Error types for the Unified Provider Protocol.
|
|
@@ -467,7 +467,7 @@ interface Middleware {
|
|
|
467
467
|
*/
|
|
468
468
|
onEnd?(ctx: MiddlewareContext): void | Promise<void>;
|
|
469
469
|
/**
|
|
470
|
-
* Called on
|
|
470
|
+
* Called on non-cancellation errors during execution.
|
|
471
471
|
* Called for all middleware that have this hook, regardless of order.
|
|
472
472
|
*
|
|
473
473
|
* @param error - The error that occurred
|
|
@@ -496,6 +496,14 @@ interface Middleware {
|
|
|
496
496
|
* @param ctx - The middleware context with mutable response
|
|
497
497
|
*/
|
|
498
498
|
onResponse?(ctx: MiddlewareContext): void | Promise<void>;
|
|
499
|
+
/**
|
|
500
|
+
* Called when a complete Turn has been assembled (LLM only).
|
|
501
|
+
* Called in reverse middleware order.
|
|
502
|
+
*
|
|
503
|
+
* @param turn - The completed Turn
|
|
504
|
+
* @param ctx - The middleware context
|
|
505
|
+
*/
|
|
506
|
+
onTurn?(turn: Turn, ctx: MiddlewareContext): void | Promise<void>;
|
|
499
507
|
/**
|
|
500
508
|
* Called for each stream event. Can transform, filter, or expand events.
|
|
501
509
|
*
|
|
@@ -1762,4 +1770,4 @@ interface BoundLLMModel<TParams = unknown> {
|
|
|
1762
1770
|
stream(request: LLMRequest<TParams>): LLMStreamResult;
|
|
1763
1771
|
}
|
|
1764
1772
|
|
|
1765
|
-
export { type MiddlewareModality as $, type BoundLLMModel as A, type BoundEmbeddingModel as B, type InferenceInput as C, type ImageInput as D, type EmbeddingInput as E, type ImageEditInput as F, type ImageGenerateOptions as G, type GeneratedImage as H, type ImageStreamResult as I, type ImageUsage as J, type KeyStrategy as K, type LLMOptions as L, type Middleware as M, type ImageResult as N, type ImageStreamEvent as O, type ProviderIdentity as P, type ImageCapabilities as Q, type RetryStrategy as R, type ImageRequest as S, Thread as T, UPPError as U, type ImageEditRequest as V, type ImageResponse as W, type BoundImageModel as X, type ImageModelInput as Y, type MiddlewareContext as Z, type StreamContext as _, type
|
|
1773
|
+
export { type MiddlewareModality as $, type BoundLLMModel as A, type BoundEmbeddingModel as B, type InferenceInput as C, type ImageInput as D, type EmbeddingInput as E, type ImageEditInput as F, type ImageGenerateOptions as G, type GeneratedImage as H, type ImageStreamResult as I, type ImageUsage as J, type KeyStrategy as K, type LLMOptions as L, type Middleware as M, type ImageResult as N, type ImageStreamEvent as O, type ProviderIdentity as P, type ImageCapabilities as Q, type RetryStrategy as R, type ImageRequest as S, Thread as T, UPPError as U, type ImageEditRequest as V, type ImageResponse as W, type BoundImageModel as X, type ImageModelInput as Y, type MiddlewareContext as Z, type StreamContext as _, type ThreadJSON as a, type AnyRequest as a0, type AnyResponse as a1, type ImageProviderStreamResult as b, type ProviderConfig as c, type EmbeddingUsage as d, type Provider as e, type Modality as f, ErrorCode as g, type ModelReference as h, type LLMInstance as i, type ImageOptions as j, type ImageInstance as k, type LLMHandler as l, type EmbeddingHandler as m, type ImageHandler as n, Image as o, ModalityType as p, type LLMProvider as q, type EmbeddingProvider as r, type ImageProvider as s, type EmbeddingRequest as t, type EmbeddingResponse as u, type EmbeddingVector as v, type LLMCapabilities as w, type LLMRequest as x, type LLMResponse as y, type LLMStreamResult as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as Middleware } from '../../llm-
|
|
2
|
-
import { E as EventDelta, S as StreamEvent } from '../../stream-
|
|
1
|
+
import { M as Middleware } from '../../llm-DS_-l71X.js';
|
|
2
|
+
import { E as EventDelta, S as StreamEvent } from '../../stream-sXhBtWjl.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @fileoverview Parsed object middleware for incremental JSON parsing.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { T as Thread, a as ThreadJSON, M as Middleware } from '../../llm-DS_-l71X.js';
|
|
2
|
+
import { T as Turn } from '../../stream-sXhBtWjl.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Persistence middleware for thread storage.
|
|
6
|
+
*
|
|
7
|
+
* Loads a conversation thread before execution and saves it after completion.
|
|
8
|
+
* Designed for LLM requests; other modalities are ignored.
|
|
9
|
+
*
|
|
10
|
+
* @module middleware/persistence
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Load result for persistence adapters.
|
|
15
|
+
*/
|
|
16
|
+
type PersistenceLoadResult = Thread | ThreadJSON | null | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Adapter configuration for persistence middleware.
|
|
19
|
+
*/
|
|
20
|
+
interface PersistenceAdapterConfig {
|
|
21
|
+
/**
|
|
22
|
+
* Unique identifier for the conversation.
|
|
23
|
+
*/
|
|
24
|
+
id: string;
|
|
25
|
+
/**
|
|
26
|
+
* Loads a thread for the provided ID.
|
|
27
|
+
*
|
|
28
|
+
* Return a Thread instance, ThreadJSON, or null/undefined for new threads.
|
|
29
|
+
*
|
|
30
|
+
* @param id - Conversation identifier
|
|
31
|
+
*/
|
|
32
|
+
load(id: string): Promise<PersistenceLoadResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Persists the thread after a turn completes.
|
|
35
|
+
*
|
|
36
|
+
* @param id - Conversation identifier
|
|
37
|
+
* @param thread - Updated thread instance
|
|
38
|
+
* @param turn - Completed turn (undefined if not available)
|
|
39
|
+
*/
|
|
40
|
+
save(id: string, thread: Thread, turn: Turn | undefined): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Persistence adapter implementation.
|
|
44
|
+
*
|
|
45
|
+
* Provides a thin wrapper around load/save callbacks.
|
|
46
|
+
*/
|
|
47
|
+
declare class PersistenceAdapter {
|
|
48
|
+
readonly id: string;
|
|
49
|
+
private readonly loader;
|
|
50
|
+
private readonly saver;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a persistence adapter.
|
|
53
|
+
*
|
|
54
|
+
* @param config - Adapter configuration
|
|
55
|
+
*/
|
|
56
|
+
constructor(config: PersistenceAdapterConfig);
|
|
57
|
+
/**
|
|
58
|
+
* Loads a thread for the provided ID.
|
|
59
|
+
*
|
|
60
|
+
* @param id - Conversation identifier
|
|
61
|
+
*/
|
|
62
|
+
load(id: string): Promise<PersistenceLoadResult>;
|
|
63
|
+
/**
|
|
64
|
+
* Persists the thread after a turn completes.
|
|
65
|
+
*
|
|
66
|
+
* @param id - Conversation identifier
|
|
67
|
+
* @param thread - Updated thread instance
|
|
68
|
+
* @param turn - Completed turn (undefined if not available)
|
|
69
|
+
*/
|
|
70
|
+
save(id: string, thread: Thread, turn: Turn | undefined): Promise<void>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Options for persistence middleware.
|
|
74
|
+
*/
|
|
75
|
+
interface PersistenceOptions {
|
|
76
|
+
/**
|
|
77
|
+
* Adapter instance for loading and saving threads.
|
|
78
|
+
*/
|
|
79
|
+
adapter: PersistenceAdapter;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Gets the loaded thread from middleware state.
|
|
83
|
+
*
|
|
84
|
+
* @param state - Middleware state map
|
|
85
|
+
* @returns Thread instance or undefined if not set
|
|
86
|
+
*/
|
|
87
|
+
declare function getThread(state: Map<string, unknown>): Thread | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Gets the conversation ID from middleware state.
|
|
90
|
+
*
|
|
91
|
+
* @param state - Middleware state map
|
|
92
|
+
* @returns Conversation ID or undefined if not set
|
|
93
|
+
*/
|
|
94
|
+
declare function getThreadId(state: Map<string, unknown>): string | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Creates persistence middleware for thread storage.
|
|
97
|
+
*
|
|
98
|
+
* Loads a thread before requests and saves it after completion. The middleware
|
|
99
|
+
* prepends loaded messages that are not already present in the request so turn
|
|
100
|
+
* slicing excludes persisted history without duplicating explicit history.
|
|
101
|
+
*
|
|
102
|
+
* @param options - Middleware configuration
|
|
103
|
+
* @returns Middleware instance
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* import { llm } from '@providerprotocol/ai';
|
|
108
|
+
* import { anthropic } from '@providerprotocol/ai/anthropic';
|
|
109
|
+
* import { persistenceMiddleware, PersistenceAdapter } from '@providerprotocol/ai/middleware/persistence';
|
|
110
|
+
*
|
|
111
|
+
* const model = llm({
|
|
112
|
+
* model: anthropic('claude-sonnet-4-20250514'),
|
|
113
|
+
* system: 'You are a helpful assistant.',
|
|
114
|
+
* middleware: [
|
|
115
|
+
* persistenceMiddleware({
|
|
116
|
+
* adapter: new PersistenceAdapter({
|
|
117
|
+
* id: 'conversation-id',
|
|
118
|
+
* load: async (id) => loadThreadFromMemory(id),
|
|
119
|
+
* save: async (id, thread) => saveThreadToMemory(id, thread),
|
|
120
|
+
* }),
|
|
121
|
+
* }),
|
|
122
|
+
* ],
|
|
123
|
+
* });
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
declare function persistenceMiddleware(options: PersistenceOptions): Middleware;
|
|
127
|
+
|
|
128
|
+
export { PersistenceAdapter, type PersistenceAdapterConfig, type PersistenceLoadResult, type PersistenceOptions, getThread, getThreadId, persistenceMiddleware };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Thread
|
|
3
|
+
} from "../../chunk-ZKNPQBIE.js";
|
|
4
|
+
import "../../chunk-WU4U6IHF.js";
|
|
5
|
+
import {
|
|
6
|
+
toError
|
|
7
|
+
} from "../../chunk-GIDT7C6I.js";
|
|
8
|
+
import "../../chunk-COS4ON4G.js";
|
|
9
|
+
|
|
10
|
+
// src/middleware/persistence.ts
|
|
11
|
+
var STATE_KEY_THREAD = "persistence:thread";
|
|
12
|
+
var STATE_KEY_ID = "persistence:id";
|
|
13
|
+
var TURN_START_INDEX_KEY = "llm:turnStartIndex";
|
|
14
|
+
var isLLMRequest = (request) => "messages" in request;
|
|
15
|
+
var PersistenceAdapter = class {
|
|
16
|
+
id;
|
|
17
|
+
loader;
|
|
18
|
+
saver;
|
|
19
|
+
/**
|
|
20
|
+
* Creates a persistence adapter.
|
|
21
|
+
*
|
|
22
|
+
* @param config - Adapter configuration
|
|
23
|
+
*/
|
|
24
|
+
constructor(config) {
|
|
25
|
+
this.id = config.id;
|
|
26
|
+
this.loader = config.load;
|
|
27
|
+
this.saver = config.save;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Loads a thread for the provided ID.
|
|
31
|
+
*
|
|
32
|
+
* @param id - Conversation identifier
|
|
33
|
+
*/
|
|
34
|
+
async load(id) {
|
|
35
|
+
return this.loader(id);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Persists the thread after a turn completes.
|
|
39
|
+
*
|
|
40
|
+
* @param id - Conversation identifier
|
|
41
|
+
* @param thread - Updated thread instance
|
|
42
|
+
* @param turn - Completed turn (undefined if not available)
|
|
43
|
+
*/
|
|
44
|
+
async save(id, thread, turn) {
|
|
45
|
+
await this.saver(id, thread, turn);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
function getThread(state) {
|
|
49
|
+
return state.get(STATE_KEY_THREAD);
|
|
50
|
+
}
|
|
51
|
+
function getThreadId(state) {
|
|
52
|
+
return state.get(STATE_KEY_ID);
|
|
53
|
+
}
|
|
54
|
+
function persistenceMiddleware(options) {
|
|
55
|
+
const { adapter } = options;
|
|
56
|
+
if (!adapter?.id) {
|
|
57
|
+
throw new Error("persistenceMiddleware requires an adapter with a non-empty id");
|
|
58
|
+
}
|
|
59
|
+
if (typeof adapter.load !== "function" || typeof adapter.save !== "function") {
|
|
60
|
+
throw new Error("persistenceMiddleware requires an adapter with load and save functions");
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
name: "persistence",
|
|
64
|
+
async onRequest(ctx) {
|
|
65
|
+
if (ctx.modality !== "llm" || !isLLMRequest(ctx.request)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
ctx.state.set(STATE_KEY_ID, adapter.id);
|
|
69
|
+
let loaded;
|
|
70
|
+
try {
|
|
71
|
+
loaded = await adapter.load(adapter.id);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
const err = toError(error);
|
|
74
|
+
throw new Error(`Persistence adapter failed to load thread "${adapter.id}": ${err.message}`, {
|
|
75
|
+
cause: err
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
let thread;
|
|
79
|
+
if (!loaded) {
|
|
80
|
+
thread = new Thread();
|
|
81
|
+
} else if (loaded instanceof Thread) {
|
|
82
|
+
thread = loaded;
|
|
83
|
+
} else {
|
|
84
|
+
try {
|
|
85
|
+
thread = Thread.fromJSON(loaded);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
const err = toError(error);
|
|
88
|
+
throw new Error(`Persistence adapter failed to deserialize thread "${adapter.id}": ${err.message}`, {
|
|
89
|
+
cause: err
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
ctx.state.set(STATE_KEY_THREAD, thread);
|
|
94
|
+
if (thread.messages.length > 0) {
|
|
95
|
+
const existingIds = new Set(ctx.request.messages.map((message) => message.id));
|
|
96
|
+
const missing = thread.messages.filter((message) => !existingIds.has(message.id));
|
|
97
|
+
if (missing.length > 0) {
|
|
98
|
+
ctx.request.messages.unshift(...missing);
|
|
99
|
+
const currentIndex = ctx.state.get(TURN_START_INDEX_KEY);
|
|
100
|
+
const nextIndex = (typeof currentIndex === "number" ? currentIndex : 0) + missing.length;
|
|
101
|
+
ctx.state.set(TURN_START_INDEX_KEY, nextIndex);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
async onTurn(turn, ctx) {
|
|
106
|
+
if (ctx.modality !== "llm") {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const thread = getThread(ctx.state);
|
|
110
|
+
if (!thread) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (isLLMRequest(ctx.request)) {
|
|
114
|
+
const turnMessageIds = new Set(turn.messages.map((message) => message.id));
|
|
115
|
+
const existingIds = new Set(thread.messages.map((message) => message.id));
|
|
116
|
+
for (const message of ctx.request.messages) {
|
|
117
|
+
if (turnMessageIds.has(message.id)) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (!existingIds.has(message.id)) {
|
|
121
|
+
thread.push(message);
|
|
122
|
+
existingIds.add(message.id);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
thread.append(turn);
|
|
127
|
+
try {
|
|
128
|
+
await adapter.save(adapter.id, thread, turn);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
const err = toError(error);
|
|
131
|
+
throw new Error(`Persistence adapter failed to save thread "${adapter.id}": ${err.message}`, {
|
|
132
|
+
cause: err
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
PersistenceAdapter,
|
|
140
|
+
getThread,
|
|
141
|
+
getThreadId,
|
|
142
|
+
persistenceMiddleware
|
|
143
|
+
};
|
|
144
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/middleware/persistence.ts"],"sourcesContent":["/**\n * @fileoverview Persistence middleware for thread storage.\n *\n * Loads a conversation thread before execution and saves it after completion.\n * Designed for LLM requests; other modalities are ignored.\n *\n * @module middleware/persistence\n */\n\nimport type { Middleware, MiddlewareContext } from '../types/middleware.ts';\nimport type { LLMRequest } from '../types/llm.ts';\nimport type { Turn } from '../types/turn.ts';\nimport type { ThreadJSON } from '../types/thread.ts';\nimport { Thread } from '../types/thread.ts';\nimport { toError } from '../utils/error.ts';\n\nconst STATE_KEY_THREAD = 'persistence:thread';\nconst STATE_KEY_ID = 'persistence:id';\nconst TURN_START_INDEX_KEY = 'llm:turnStartIndex';\n\nconst isLLMRequest = (request: MiddlewareContext['request']): request is LLMRequest => (\n 'messages' in request\n);\n\n/**\n * Load result for persistence adapters.\n */\nexport type PersistenceLoadResult = Thread | ThreadJSON | null | undefined;\n\n/**\n * Adapter configuration for persistence middleware.\n */\nexport interface PersistenceAdapterConfig {\n /**\n * Unique identifier for the conversation.\n */\n id: string;\n\n /**\n * Loads a thread for the provided ID.\n *\n * Return a Thread instance, ThreadJSON, or null/undefined for new threads.\n *\n * @param id - Conversation identifier\n */\n load(id: string): Promise<PersistenceLoadResult>;\n\n /**\n * Persists the thread after a turn completes.\n *\n * @param id - Conversation identifier\n * @param thread - Updated thread instance\n * @param turn - Completed turn (undefined if not available)\n */\n save(id: string, thread: Thread, turn: Turn | undefined): Promise<void>;\n}\n\n/**\n * Persistence adapter implementation.\n *\n * Provides a thin wrapper around load/save callbacks.\n */\nexport class PersistenceAdapter {\n readonly id: string;\n\n private readonly loader: PersistenceAdapterConfig['load'];\n\n private readonly saver: PersistenceAdapterConfig['save'];\n\n /**\n * Creates a persistence adapter.\n *\n * @param config - Adapter configuration\n */\n constructor(config: PersistenceAdapterConfig) {\n this.id = config.id;\n this.loader = config.load;\n this.saver = config.save;\n }\n\n /**\n * Loads a thread for the provided ID.\n *\n * @param id - Conversation identifier\n */\n async load(id: string): Promise<PersistenceLoadResult> {\n return this.loader(id);\n }\n\n /**\n * Persists the thread after a turn completes.\n *\n * @param id - Conversation identifier\n * @param thread - Updated thread instance\n * @param turn - Completed turn (undefined if not available)\n */\n async save(id: string, thread: Thread, turn: Turn | undefined): Promise<void> {\n await this.saver(id, thread, turn);\n }\n}\n\n/**\n * Options for persistence middleware.\n */\nexport interface PersistenceOptions {\n /**\n * Adapter instance for loading and saving threads.\n */\n adapter: PersistenceAdapter;\n}\n\n/**\n * Gets the loaded thread from middleware state.\n *\n * @param state - Middleware state map\n * @returns Thread instance or undefined if not set\n */\nexport function getThread(state: Map<string, unknown>): Thread | undefined {\n return state.get(STATE_KEY_THREAD) as Thread | undefined;\n}\n\n/**\n * Gets the conversation ID from middleware state.\n *\n * @param state - Middleware state map\n * @returns Conversation ID or undefined if not set\n */\nexport function getThreadId(state: Map<string, unknown>): string | undefined {\n return state.get(STATE_KEY_ID) as string | undefined;\n}\n\n/**\n * Creates persistence middleware for thread storage.\n *\n * Loads a thread before requests and saves it after completion. The middleware\n * prepends loaded messages that are not already present in the request so turn\n * slicing excludes persisted history without duplicating explicit history.\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 { persistenceMiddleware, PersistenceAdapter } from '@providerprotocol/ai/middleware/persistence';\n *\n * const model = llm({\n * model: anthropic('claude-sonnet-4-20250514'),\n * system: 'You are a helpful assistant.',\n * middleware: [\n * persistenceMiddleware({\n * adapter: new PersistenceAdapter({\n * id: 'conversation-id',\n * load: async (id) => loadThreadFromMemory(id),\n * save: async (id, thread) => saveThreadToMemory(id, thread),\n * }),\n * }),\n * ],\n * });\n * ```\n */\nexport function persistenceMiddleware(options: PersistenceOptions): Middleware {\n const { adapter } = options;\n\n if (!adapter?.id) {\n throw new Error('persistenceMiddleware requires an adapter with a non-empty id');\n }\n if (typeof adapter.load !== 'function' || typeof adapter.save !== 'function') {\n throw new Error('persistenceMiddleware requires an adapter with load and save functions');\n }\n\n return {\n name: 'persistence',\n\n async onRequest(ctx: MiddlewareContext): Promise<void> {\n if (ctx.modality !== 'llm' || !isLLMRequest(ctx.request)) {\n return;\n }\n\n ctx.state.set(STATE_KEY_ID, adapter.id);\n\n let loaded: PersistenceLoadResult;\n try {\n loaded = await adapter.load(adapter.id);\n } catch (error) {\n const err = toError(error);\n throw new Error(`Persistence adapter failed to load thread \"${adapter.id}\": ${err.message}`, {\n cause: err,\n });\n }\n\n let thread: Thread;\n if (!loaded) {\n thread = new Thread();\n } else if (loaded instanceof Thread) {\n thread = loaded;\n } else {\n try {\n thread = Thread.fromJSON(loaded);\n } catch (error) {\n const err = toError(error);\n throw new Error(`Persistence adapter failed to deserialize thread \"${adapter.id}\": ${err.message}`, {\n cause: err,\n });\n }\n }\n\n ctx.state.set(STATE_KEY_THREAD, thread);\n\n if (thread.messages.length > 0) {\n const existingIds = new Set(ctx.request.messages.map((message) => message.id));\n const missing = thread.messages.filter((message) => !existingIds.has(message.id));\n if (missing.length > 0) {\n ctx.request.messages.unshift(...missing);\n const currentIndex = ctx.state.get(TURN_START_INDEX_KEY);\n const nextIndex = (typeof currentIndex === 'number' ? currentIndex : 0) + missing.length;\n ctx.state.set(TURN_START_INDEX_KEY, nextIndex);\n }\n }\n },\n\n async onTurn(turn: Turn, ctx: MiddlewareContext): Promise<void> {\n if (ctx.modality !== 'llm') {\n return;\n }\n\n const thread = getThread(ctx.state);\n if (!thread) {\n return;\n }\n\n if (isLLMRequest(ctx.request)) {\n const turnMessageIds = new Set(turn.messages.map((message) => message.id));\n const existingIds = new Set(thread.messages.map((message) => message.id));\n for (const message of ctx.request.messages) {\n if (turnMessageIds.has(message.id)) {\n continue;\n }\n if (!existingIds.has(message.id)) {\n thread.push(message);\n existingIds.add(message.id);\n }\n }\n }\n\n thread.append(turn);\n\n try {\n await adapter.save(adapter.id, thread, turn);\n } catch (error) {\n const err = toError(error);\n throw new Error(`Persistence adapter failed to save thread \"${adapter.id}\": ${err.message}`, {\n cause: err,\n });\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { M as Middleware } from '../../llm-
|
|
2
|
-
import { M as MemoryAdapterOptions, P as PubSubAdapter, a as PubSubOptions } from '../../types-
|
|
3
|
-
export { C as CompletionCallback, S as StoredStream, b as SubscriptionCallback, U as Unsubscribe } from '../../types-
|
|
4
|
-
import '../../stream-
|
|
1
|
+
import { M as Middleware } from '../../llm-DS_-l71X.js';
|
|
2
|
+
import { M as MemoryAdapterOptions, P as PubSubAdapter, a as PubSubOptions } from '../../types-Cr4F0tVy.js';
|
|
3
|
+
export { C as CompletionCallback, S as StoredStream, b as SubscriptionCallback, U as Unsubscribe } from '../../types-Cr4F0tVy.js';
|
|
4
|
+
import '../../stream-sXhBtWjl.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @fileoverview In-memory storage adapter for pub-sub middleware.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PubSubAdapter } from '../../../../types-
|
|
2
|
-
import '../../../../stream-
|
|
1
|
+
import { P as PubSubAdapter } from '../../../../types-Cr4F0tVy.js';
|
|
2
|
+
import '../../../../stream-sXhBtWjl.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @fileoverview Express/Connect adapter for pub-sub stream resumption.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PubSubAdapter } from '../../../../types-
|
|
2
|
-
import '../../../../stream-
|
|
1
|
+
import { P as PubSubAdapter } from '../../../../types-Cr4F0tVy.js';
|
|
2
|
+
import '../../../../stream-sXhBtWjl.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @fileoverview Fastify adapter for pub-sub stream resumption.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PubSubAdapter } from '../../../../types-
|
|
2
|
-
import '../../../../stream-
|
|
1
|
+
import { P as PubSubAdapter } from '../../../../types-Cr4F0tVy.js';
|
|
2
|
+
import '../../../../stream-sXhBtWjl.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @fileoverview H3/Nitro/Nuxt adapter for pub-sub stream resumption.
|
|
@@ -6,8 +6,8 @@ import { streamSubscriber } from './express/index.js';
|
|
|
6
6
|
export { express } from './express/index.js';
|
|
7
7
|
import { createSubscriberStream } from './webapi/index.js';
|
|
8
8
|
export { webapi } from './webapi/index.js';
|
|
9
|
-
export { P as PubSubAdapter } from '../../../types-
|
|
10
|
-
import '../../../stream-
|
|
9
|
+
export { P as PubSubAdapter } from '../../../types-Cr4F0tVy.js';
|
|
10
|
+
import '../../../stream-sXhBtWjl.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Server adapters namespace for pub-sub stream resumption.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PubSubAdapter } from '../../../../types-
|
|
2
|
-
import '../../../../stream-
|
|
1
|
+
import { P as PubSubAdapter } from '../../../../types-Cr4F0tVy.js';
|
|
2
|
+
import '../../../../stream-sXhBtWjl.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @fileoverview Web API adapter for pub-sub stream resumption.
|
package/dist/ollama/index.d.ts
CHANGED
package/dist/ollama/index.js
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseJsonResponse
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-TUTYMOBL.js";
|
|
4
4
|
import {
|
|
5
5
|
resolveApiKey
|
|
6
6
|
} from "../chunk-ARVM24K2.js";
|
|
7
7
|
import {
|
|
8
8
|
createProvider
|
|
9
9
|
} from "../chunk-JA3UZALR.js";
|
|
10
|
+
import {
|
|
11
|
+
doFetch,
|
|
12
|
+
doStreamFetch,
|
|
13
|
+
normalizeHttpError
|
|
14
|
+
} from "../chunk-SBGZJVTJ.js";
|
|
15
|
+
import {
|
|
16
|
+
StreamEventType,
|
|
17
|
+
objectDelta
|
|
18
|
+
} from "../chunk-MJI74VEJ.js";
|
|
10
19
|
import {
|
|
11
20
|
AssistantMessage,
|
|
12
21
|
isAssistantMessage,
|
|
13
22
|
isToolResultMessage,
|
|
14
23
|
isUserMessage
|
|
15
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-WU4U6IHF.js";
|
|
16
25
|
import {
|
|
17
|
-
doFetch,
|
|
18
|
-
doStreamFetch,
|
|
19
|
-
normalizeHttpError,
|
|
20
26
|
toError
|
|
21
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-GIDT7C6I.js";
|
|
22
28
|
import {
|
|
23
29
|
ErrorCode,
|
|
24
30
|
ModalityType,
|
|
25
31
|
UPPError
|
|
26
32
|
} from "../chunk-COS4ON4G.js";
|
|
27
|
-
import {
|
|
28
|
-
StreamEventType,
|
|
29
|
-
objectDelta
|
|
30
|
-
} from "../chunk-RJGTRQ47.js";
|
|
31
33
|
|
|
32
34
|
// src/providers/ollama/transform.ts
|
|
33
35
|
function normalizeSystem(system) {
|