@animalabs/membrane 0.1.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.
Files changed (131) hide show
  1. package/dist/context/index.d.ts +10 -0
  2. package/dist/context/index.d.ts.map +1 -0
  3. package/dist/context/index.js +9 -0
  4. package/dist/context/index.js.map +1 -0
  5. package/dist/context/process.d.ts +22 -0
  6. package/dist/context/process.d.ts.map +1 -0
  7. package/dist/context/process.js +369 -0
  8. package/dist/context/process.js.map +1 -0
  9. package/dist/context/types.d.ts +118 -0
  10. package/dist/context/types.d.ts.map +1 -0
  11. package/dist/context/types.js +60 -0
  12. package/dist/context/types.js.map +1 -0
  13. package/dist/index.d.ts +12 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +18 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/membrane.d.ts +96 -0
  18. package/dist/membrane.d.ts.map +1 -0
  19. package/dist/membrane.js +893 -0
  20. package/dist/membrane.js.map +1 -0
  21. package/dist/providers/anthropic.d.ts +36 -0
  22. package/dist/providers/anthropic.d.ts.map +1 -0
  23. package/dist/providers/anthropic.js +265 -0
  24. package/dist/providers/anthropic.js.map +1 -0
  25. package/dist/providers/index.d.ts +8 -0
  26. package/dist/providers/index.d.ts.map +1 -0
  27. package/dist/providers/index.js +8 -0
  28. package/dist/providers/index.js.map +1 -0
  29. package/dist/providers/openai-compatible.d.ts +74 -0
  30. package/dist/providers/openai-compatible.d.ts.map +1 -0
  31. package/dist/providers/openai-compatible.js +412 -0
  32. package/dist/providers/openai-compatible.js.map +1 -0
  33. package/dist/providers/openai.d.ts +69 -0
  34. package/dist/providers/openai.d.ts.map +1 -0
  35. package/dist/providers/openai.js +455 -0
  36. package/dist/providers/openai.js.map +1 -0
  37. package/dist/providers/openrouter.d.ts +76 -0
  38. package/dist/providers/openrouter.d.ts.map +1 -0
  39. package/dist/providers/openrouter.js +492 -0
  40. package/dist/providers/openrouter.js.map +1 -0
  41. package/dist/transforms/chat.d.ts +52 -0
  42. package/dist/transforms/chat.d.ts.map +1 -0
  43. package/dist/transforms/chat.js +136 -0
  44. package/dist/transforms/chat.js.map +1 -0
  45. package/dist/transforms/index.d.ts +6 -0
  46. package/dist/transforms/index.d.ts.map +1 -0
  47. package/dist/transforms/index.js +6 -0
  48. package/dist/transforms/index.js.map +1 -0
  49. package/dist/transforms/prefill.d.ts +89 -0
  50. package/dist/transforms/prefill.d.ts.map +1 -0
  51. package/dist/transforms/prefill.js +401 -0
  52. package/dist/transforms/prefill.js.map +1 -0
  53. package/dist/types/config.d.ts +103 -0
  54. package/dist/types/config.d.ts.map +1 -0
  55. package/dist/types/config.js +21 -0
  56. package/dist/types/config.js.map +1 -0
  57. package/dist/types/content.d.ts +81 -0
  58. package/dist/types/content.d.ts.map +1 -0
  59. package/dist/types/content.js +40 -0
  60. package/dist/types/content.js.map +1 -0
  61. package/dist/types/errors.d.ts +42 -0
  62. package/dist/types/errors.d.ts.map +1 -0
  63. package/dist/types/errors.js +208 -0
  64. package/dist/types/errors.js.map +1 -0
  65. package/dist/types/index.d.ts +18 -0
  66. package/dist/types/index.d.ts.map +1 -0
  67. package/dist/types/index.js +9 -0
  68. package/dist/types/index.js.map +1 -0
  69. package/dist/types/message.d.ts +46 -0
  70. package/dist/types/message.d.ts.map +1 -0
  71. package/dist/types/message.js +38 -0
  72. package/dist/types/message.js.map +1 -0
  73. package/dist/types/provider.d.ts +155 -0
  74. package/dist/types/provider.d.ts.map +1 -0
  75. package/dist/types/provider.js +5 -0
  76. package/dist/types/provider.js.map +1 -0
  77. package/dist/types/request.d.ts +78 -0
  78. package/dist/types/request.d.ts.map +1 -0
  79. package/dist/types/request.js +5 -0
  80. package/dist/types/request.js.map +1 -0
  81. package/dist/types/response.d.ts +131 -0
  82. package/dist/types/response.d.ts.map +1 -0
  83. package/dist/types/response.js +7 -0
  84. package/dist/types/response.js.map +1 -0
  85. package/dist/types/streaming.d.ts +164 -0
  86. package/dist/types/streaming.d.ts.map +1 -0
  87. package/dist/types/streaming.js +5 -0
  88. package/dist/types/streaming.js.map +1 -0
  89. package/dist/types/tools.d.ts +71 -0
  90. package/dist/types/tools.d.ts.map +1 -0
  91. package/dist/types/tools.js +5 -0
  92. package/dist/types/tools.js.map +1 -0
  93. package/dist/utils/index.d.ts +5 -0
  94. package/dist/utils/index.d.ts.map +1 -0
  95. package/dist/utils/index.js +5 -0
  96. package/dist/utils/index.js.map +1 -0
  97. package/dist/utils/stream-parser.d.ts +53 -0
  98. package/dist/utils/stream-parser.d.ts.map +1 -0
  99. package/dist/utils/stream-parser.js +359 -0
  100. package/dist/utils/stream-parser.js.map +1 -0
  101. package/dist/utils/tool-parser.d.ts +130 -0
  102. package/dist/utils/tool-parser.d.ts.map +1 -0
  103. package/dist/utils/tool-parser.js +571 -0
  104. package/dist/utils/tool-parser.js.map +1 -0
  105. package/package.json +37 -0
  106. package/src/context/index.ts +24 -0
  107. package/src/context/process.ts +520 -0
  108. package/src/context/types.ts +231 -0
  109. package/src/index.ts +23 -0
  110. package/src/membrane.ts +1174 -0
  111. package/src/providers/anthropic.ts +340 -0
  112. package/src/providers/index.ts +31 -0
  113. package/src/providers/openai-compatible.ts +570 -0
  114. package/src/providers/openai.ts +625 -0
  115. package/src/providers/openrouter.ts +662 -0
  116. package/src/transforms/chat.ts +212 -0
  117. package/src/transforms/index.ts +22 -0
  118. package/src/transforms/prefill.ts +585 -0
  119. package/src/types/config.ts +172 -0
  120. package/src/types/content.ts +181 -0
  121. package/src/types/errors.ts +277 -0
  122. package/src/types/index.ts +154 -0
  123. package/src/types/message.ts +89 -0
  124. package/src/types/provider.ts +249 -0
  125. package/src/types/request.ts +131 -0
  126. package/src/types/response.ts +223 -0
  127. package/src/types/streaming.ts +231 -0
  128. package/src/types/tools.ts +92 -0
  129. package/src/utils/index.ts +15 -0
  130. package/src/utils/stream-parser.ts +440 -0
  131. package/src/utils/tool-parser.ts +715 -0
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Context management module
3
+ *
4
+ * Handles rolling context, cache marker placement, and state management
5
+ * for efficient prompt caching with LLMs.
6
+ */
7
+ export { processContext } from './process.js';
8
+ export { createInitialState, defaultTokenEstimator, DEFAULT_CONTEXT_CONFIG, } from './types.js';
9
+ export type { ContextInput, ContextOutput, ContextState, ContextConfig, ContextInfo, ContextStreamOptions, CacheMarker, } from './types.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,oBAAoB,EACpB,WAAW,GACZ,MAAM,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Context management module
3
+ *
4
+ * Handles rolling context, cache marker placement, and state management
5
+ * for efficient prompt caching with LLMs.
6
+ */
7
+ export { processContext } from './process.js';
8
+ export { createInitialState, defaultTokenEstimator, DEFAULT_CONTEXT_CONFIG, } from './types.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Context processing - main entry point
3
+ */
4
+ import type { Membrane } from '../membrane.js';
5
+ import type { ContextInput, ContextState, ContextOutput, ContextStreamOptions } from './types.js';
6
+ /**
7
+ * Process context and stream LLM response.
8
+ *
9
+ * This function handles:
10
+ * - Rolling/truncation based on thresholds
11
+ * - Cache marker placement for prompt caching
12
+ * - Hard limit enforcement
13
+ * - State management
14
+ *
15
+ * @param membrane - Configured Membrane instance
16
+ * @param input - Messages, config, and context settings
17
+ * @param state - Previous state (null for first call)
18
+ * @param options - Stream options
19
+ * @returns Response, updated state, and context info
20
+ */
21
+ export declare function processContext(membrane: Membrane, input: ContextInput, state: ContextState | null, options?: ContextStreamOptions): Promise<ContextOutput>;
22
+ //# sourceMappingURL=process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/context/process.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EAGb,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAWpB;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,YAAY,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,aAAa,CAAC,CAmHxB"}
@@ -0,0 +1,369 @@
1
+ /**
2
+ * Context processing - main entry point
3
+ */
4
+ import { createInitialState, defaultTokenEstimator, DEFAULT_CONTEXT_CONFIG, } from './types.js';
5
+ // ============================================================================
6
+ // Main Entry Point
7
+ // ============================================================================
8
+ /**
9
+ * Process context and stream LLM response.
10
+ *
11
+ * This function handles:
12
+ * - Rolling/truncation based on thresholds
13
+ * - Cache marker placement for prompt caching
14
+ * - Hard limit enforcement
15
+ * - State management
16
+ *
17
+ * @param membrane - Configured Membrane instance
18
+ * @param input - Messages, config, and context settings
19
+ * @param state - Previous state (null for first call)
20
+ * @param options - Stream options
21
+ * @returns Response, updated state, and context info
22
+ */
23
+ export async function processContext(membrane, input, state, options) {
24
+ // Merge config with defaults
25
+ const contextConfig = mergeConfig(input.context);
26
+ const tokenEstimator = contextConfig.tokenEstimator ?? defaultTokenEstimator;
27
+ // Initialize or continue state
28
+ let currentState = state ?? createInitialState();
29
+ // Detect discontinuity (new conversation or branch switch)
30
+ const isDiscontinuous = detectDiscontinuity(input.messages, currentState);
31
+ if (isDiscontinuous) {
32
+ currentState = createInitialState();
33
+ }
34
+ // Calculate tokens for all messages
35
+ const messageTokens = input.messages.map(m => ({
36
+ message: m,
37
+ tokens: tokenEstimator(m),
38
+ id: getMessageId(m),
39
+ }));
40
+ const totalTokens = messageTokens.reduce((sum, m) => sum + m.tokens, 0);
41
+ const totalCharacters = calculateCharacters(input.messages);
42
+ // Determine if we should roll
43
+ const rollDecision = shouldRoll(currentState, input.messages.length, totalTokens, totalCharacters, contextConfig);
44
+ // Apply rolling/truncation if needed
45
+ let keptMessages = input.messages;
46
+ let messagesDropped = 0;
47
+ let didRoll = false;
48
+ let hardLimitHit = false;
49
+ if (rollDecision.shouldRoll) {
50
+ const truncateResult = truncateMessages(messageTokens, rollDecision.targetTokens, rollDecision.targetMessages, contextConfig);
51
+ keptMessages = truncateResult.kept.map(m => m.message);
52
+ messagesDropped = truncateResult.dropped;
53
+ didRoll = true;
54
+ hardLimitHit = rollDecision.reason === 'hard_limit';
55
+ }
56
+ // Recalculate tokens after truncation
57
+ const keptTokens = keptMessages.map(m => ({
58
+ message: m,
59
+ tokens: tokenEstimator(m),
60
+ id: getMessageId(m),
61
+ }));
62
+ const keptTotalTokens = keptTokens.reduce((sum, m) => sum + m.tokens, 0);
63
+ // Place cache markers
64
+ const cacheMarkers = placeCacheMarkers(keptMessages, keptTokens, currentState, didRoll, contextConfig);
65
+ // Apply cache markers to messages
66
+ const messagesWithCache = applyCacheMarkers(keptMessages, cacheMarkers);
67
+ // Calculate cached/uncached tokens
68
+ const lastMarker = cacheMarkers[cacheMarkers.length - 1];
69
+ const cachedTokens = lastMarker?.tokenEstimate ?? 0;
70
+ const uncachedTokens = keptTotalTokens - cachedTokens;
71
+ // Build request
72
+ const request = {
73
+ messages: messagesWithCache,
74
+ system: input.system,
75
+ tools: input.tools,
76
+ config: input.config,
77
+ };
78
+ // Stream response
79
+ const response = await membrane.stream(request, {
80
+ onChunk: options?.onChunk,
81
+ signal: options?.signal,
82
+ });
83
+ // Update state
84
+ const newState = {
85
+ cacheMarkers,
86
+ windowMessageIds: keptMessages.map(m => getMessageId(m)),
87
+ messagesSinceRoll: didRoll ? 1 : currentState.messagesSinceRoll + 1,
88
+ tokensSinceRoll: didRoll ? keptTotalTokens : currentState.tokensSinceRoll + keptTotalTokens,
89
+ inGracePeriod: rollDecision.enteredGrace || (currentState.inGracePeriod && !didRoll),
90
+ lastRollTime: didRoll ? new Date().toISOString() : currentState.lastRollTime,
91
+ };
92
+ // Build info
93
+ const info = {
94
+ didRoll,
95
+ messagesDropped,
96
+ messagesKept: keptMessages.length,
97
+ cacheMarkers,
98
+ cachedTokens,
99
+ uncachedTokens,
100
+ totalTokens: keptTotalTokens,
101
+ hardLimitHit,
102
+ };
103
+ return { response, state: newState, info };
104
+ }
105
+ // ============================================================================
106
+ // Helper Functions
107
+ // ============================================================================
108
+ function mergeConfig(config) {
109
+ return {
110
+ rolling: {
111
+ ...DEFAULT_CONTEXT_CONFIG.rolling,
112
+ ...config.rolling,
113
+ },
114
+ limits: {
115
+ ...DEFAULT_CONTEXT_CONFIG.limits,
116
+ ...config.limits,
117
+ },
118
+ cache: {
119
+ ...DEFAULT_CONTEXT_CONFIG.cache,
120
+ ...config.cache,
121
+ },
122
+ tokenEstimator: config.tokenEstimator,
123
+ };
124
+ }
125
+ function getMessageId(message) {
126
+ return message.metadata?.sourceId ?? `msg-${Math.random().toString(36).slice(2)}`;
127
+ }
128
+ function detectDiscontinuity(messages, state) {
129
+ if (state.windowMessageIds.length === 0) {
130
+ return false; // First call, not a discontinuity
131
+ }
132
+ const currentIds = new Set(messages.map(m => getMessageId(m)));
133
+ const overlap = state.windowMessageIds.filter(id => currentIds.has(id));
134
+ // If less than 50% overlap, consider it a new conversation
135
+ return overlap.length < state.windowMessageIds.length * 0.5;
136
+ }
137
+ function calculateCharacters(messages) {
138
+ let chars = 0;
139
+ for (const msg of messages) {
140
+ for (const block of msg.content) {
141
+ if (block.type === 'text') {
142
+ chars += block.text.length;
143
+ }
144
+ else if (block.type === 'tool_result') {
145
+ const content = typeof block.content === 'string'
146
+ ? block.content
147
+ : JSON.stringify(block.content);
148
+ chars += content.length;
149
+ }
150
+ // Images not counted for character limits
151
+ }
152
+ }
153
+ return chars;
154
+ }
155
+ function shouldRoll(state, messageCount, totalTokens, totalCharacters, config) {
156
+ const { rolling, limits } = config;
157
+ const unit = rolling.unit ?? 'messages';
158
+ const threshold = rolling.threshold;
159
+ const grace = rolling.grace ?? 0;
160
+ const maxThreshold = threshold + grace;
161
+ // Check hard limits first (always enforced)
162
+ if (limits?.maxCharacters && totalCharacters > limits.maxCharacters) {
163
+ return {
164
+ shouldRoll: true,
165
+ reason: 'hard_limit',
166
+ targetTokens: limits.maxTokens,
167
+ targetMessages: limits.maxMessages,
168
+ enteredGrace: false,
169
+ };
170
+ }
171
+ if (limits?.maxTokens && totalTokens > limits.maxTokens) {
172
+ return {
173
+ shouldRoll: true,
174
+ reason: 'hard_limit',
175
+ targetTokens: limits.maxTokens,
176
+ targetMessages: limits.maxMessages,
177
+ enteredGrace: false,
178
+ };
179
+ }
180
+ if (limits?.maxMessages && messageCount > limits.maxMessages) {
181
+ return {
182
+ shouldRoll: true,
183
+ reason: 'hard_limit',
184
+ targetTokens: limits.maxTokens,
185
+ targetMessages: limits.maxMessages,
186
+ enteredGrace: false,
187
+ };
188
+ }
189
+ // Check rolling threshold
190
+ const current = unit === 'messages' ? state.messagesSinceRoll : state.tokensSinceRoll;
191
+ if (current >= maxThreshold) {
192
+ // Exceeded grace, must roll
193
+ return {
194
+ shouldRoll: true,
195
+ reason: 'grace_exceeded',
196
+ targetTokens: unit === 'tokens' ? threshold : undefined,
197
+ targetMessages: unit === 'messages' ? threshold : undefined,
198
+ enteredGrace: false,
199
+ };
200
+ }
201
+ if (!state.inGracePeriod && current >= threshold) {
202
+ // Just entered grace period
203
+ return {
204
+ shouldRoll: false,
205
+ enteredGrace: true,
206
+ };
207
+ }
208
+ return {
209
+ shouldRoll: false,
210
+ enteredGrace: false,
211
+ };
212
+ }
213
+ function truncateMessages(messages, targetTokens, targetMessages, config) {
214
+ // Truncate from the beginning, keeping most recent
215
+ if (targetMessages && messages.length > targetMessages) {
216
+ const startIdx = messages.length - targetMessages;
217
+ return {
218
+ kept: messages.slice(startIdx),
219
+ dropped: startIdx,
220
+ };
221
+ }
222
+ if (targetTokens) {
223
+ let tokenSum = 0;
224
+ let startIdx = messages.length;
225
+ // Count from end backwards
226
+ for (let i = messages.length - 1; i >= 0; i--) {
227
+ tokenSum += messages[i].tokens;
228
+ if (tokenSum > targetTokens) {
229
+ startIdx = i + 1;
230
+ break;
231
+ }
232
+ startIdx = i;
233
+ }
234
+ return {
235
+ kept: messages.slice(startIdx),
236
+ dropped: startIdx,
237
+ };
238
+ }
239
+ // Default: use buffer from config
240
+ const buffer = config?.rolling.buffer ?? 20;
241
+ const unit = config?.rolling.unit ?? 'messages';
242
+ if (unit === 'messages') {
243
+ const targetCount = Math.max(buffer * 2, messages.length - buffer);
244
+ if (messages.length > targetCount) {
245
+ const startIdx = messages.length - targetCount;
246
+ return {
247
+ kept: messages.slice(startIdx),
248
+ dropped: startIdx,
249
+ };
250
+ }
251
+ }
252
+ return { kept: messages, dropped: 0 };
253
+ }
254
+ function placeCacheMarkers(messages, messageTokens, state, didRoll, config) {
255
+ const cacheConfig = config.cache ?? {};
256
+ if (cacheConfig.enabled === false) {
257
+ return [];
258
+ }
259
+ const numPoints = cacheConfig.points ?? 1;
260
+ const minTokens = cacheConfig.minTokens ?? 1024;
261
+ const preferUser = cacheConfig.preferUserMessages ?? true;
262
+ const totalTokens = messageTokens.reduce((sum, m) => sum + m.tokens, 0);
263
+ // Not enough tokens for caching
264
+ if (totalTokens < minTokens) {
265
+ return [];
266
+ }
267
+ // If we didn't roll, try to keep existing markers stable
268
+ if (!didRoll && state.cacheMarkers.length > 0) {
269
+ const currentIds = new Set(messages.map(m => getMessageId(m)));
270
+ const validMarkers = state.cacheMarkers.filter(m => currentIds.has(m.messageId));
271
+ if (validMarkers.length > 0) {
272
+ // Recalculate token estimates for valid markers
273
+ return validMarkers.map(marker => {
274
+ const idx = messages.findIndex(m => getMessageId(m) === marker.messageId);
275
+ const tokenEstimate = messageTokens
276
+ .slice(0, idx + 1)
277
+ .reduce((sum, m) => sum + m.tokens, 0);
278
+ return {
279
+ messageId: marker.messageId,
280
+ messageIndex: idx,
281
+ tokenEstimate,
282
+ };
283
+ });
284
+ }
285
+ }
286
+ // Place new markers using arithmetic positioning
287
+ const markers = [];
288
+ const buffer = config.rolling.buffer ?? 20;
289
+ // For single point: place at (length - buffer)
290
+ // For multiple points: distribute evenly in cacheable portion
291
+ const cacheableEnd = Math.max(0, messages.length - buffer);
292
+ if (cacheableEnd === 0) {
293
+ return []; // Nothing to cache
294
+ }
295
+ // Calculate step size for multiple cache points
296
+ const step = Math.floor(cacheableEnd / numPoints);
297
+ if (step === 0) {
298
+ return []; // Not enough messages for requested cache points
299
+ }
300
+ let runningTokens = 0;
301
+ let currentIdx = 0;
302
+ for (let point = 1; point <= numPoints; point++) {
303
+ const targetIdx = Math.min(point * step - 1, cacheableEnd - 1);
304
+ // Accumulate tokens up to target
305
+ while (currentIdx <= targetIdx && currentIdx < messageTokens.length) {
306
+ runningTokens += messageTokens[currentIdx].tokens;
307
+ currentIdx++;
308
+ }
309
+ let markerIdx = targetIdx;
310
+ let markerTokens = runningTokens;
311
+ // Adjust to user message if preferred
312
+ if (preferUser) {
313
+ const adjusted = findNearestUserMessage(messages, markerIdx, messageTokens);
314
+ if (adjusted) {
315
+ markerIdx = adjusted.index;
316
+ markerTokens = adjusted.tokens;
317
+ }
318
+ }
319
+ // Skip if below minimum
320
+ if (markerTokens < minTokens) {
321
+ continue;
322
+ }
323
+ // Skip if duplicate
324
+ if (markers.some(m => m.messageIndex === markerIdx)) {
325
+ continue;
326
+ }
327
+ markers.push({
328
+ messageId: getMessageId(messages[markerIdx]),
329
+ messageIndex: markerIdx,
330
+ tokenEstimate: markerTokens,
331
+ });
332
+ }
333
+ return markers;
334
+ }
335
+ function findNearestUserMessage(messages, startIdx, messageTokens) {
336
+ // Search backwards for a user message (non-assistant participant)
337
+ const maxSearch = 5;
338
+ let tokens = messageTokens.slice(0, startIdx + 1).reduce((sum, m) => sum + m.tokens, 0);
339
+ for (let i = startIdx; i >= Math.max(0, startIdx - maxSearch); i--) {
340
+ const msg = messages[i];
341
+ // Heuristic: if participant isn't a common assistant name, it's probably a user
342
+ const participant = msg.participant.toLowerCase();
343
+ const isUser = !['claude', 'assistant', 'bot', 'ai'].includes(participant);
344
+ if (isUser) {
345
+ return { index: i, tokens };
346
+ }
347
+ tokens -= messageTokens[i].tokens;
348
+ }
349
+ return null;
350
+ }
351
+ function applyCacheMarkers(messages, cacheMarkers) {
352
+ if (cacheMarkers.length === 0) {
353
+ return messages;
354
+ }
355
+ const markerIndices = new Set(cacheMarkers.map(m => m.messageIndex));
356
+ return messages.map((msg, idx) => {
357
+ if (markerIndices.has(idx)) {
358
+ return {
359
+ ...msg,
360
+ metadata: {
361
+ ...msg.metadata,
362
+ cacheControl: { type: 'ephemeral' },
363
+ },
364
+ };
365
+ }
366
+ return msg;
367
+ });
368
+ }
369
+ //# sourceMappingURL=process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/context/process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Context management types
3
+ */
4
+ import type { NormalizedMessage, NormalizedResponse, AbortedResponse, GenerationConfig, ToolDefinition } from '../types/index.js';
5
+ export interface CacheMarker {
6
+ /** Message ID (from metadata.sourceId) */
7
+ messageId: string;
8
+ /** Index in the message array */
9
+ messageIndex: number;
10
+ /** Estimated tokens up to this point */
11
+ tokenEstimate: number;
12
+ }
13
+ export interface ContextConfig {
14
+ /** Rolling configuration */
15
+ rolling: {
16
+ /** Threshold before roll triggers */
17
+ threshold: number;
18
+ /** Buffer to leave uncached after roll */
19
+ buffer: number;
20
+ /** Grace period before forced roll (optional) */
21
+ grace?: number;
22
+ /** Unit for threshold/buffer/grace (default: 'messages') */
23
+ unit?: 'messages' | 'tokens';
24
+ };
25
+ /** Hard limits (always enforced) */
26
+ limits?: {
27
+ /** Maximum characters (default: 500000) */
28
+ maxCharacters?: number;
29
+ /** Maximum tokens */
30
+ maxTokens?: number;
31
+ /** Maximum messages */
32
+ maxMessages?: number;
33
+ };
34
+ /** Cache settings */
35
+ cache?: {
36
+ /** Enable caching (default: true) */
37
+ enabled?: boolean;
38
+ /** Number of cache points (default: 1, max: 4 for Anthropic) */
39
+ points?: 1 | 2 | 3 | 4;
40
+ /** Minimum tokens before caching (default: 1024) */
41
+ minTokens?: number;
42
+ /** Prefer user messages for cache markers (OpenRouter workaround) */
43
+ preferUserMessages?: boolean;
44
+ };
45
+ /** Custom token estimator (default: chars / 4) */
46
+ tokenEstimator?: (message: NormalizedMessage) => number;
47
+ }
48
+ export interface ContextState {
49
+ /** Current cache markers */
50
+ cacheMarkers: CacheMarker[];
51
+ /** Message IDs in current window (for continuity detection) */
52
+ windowMessageIds: string[];
53
+ /** Messages since last roll */
54
+ messagesSinceRoll: number;
55
+ /** Tokens since last roll */
56
+ tokensSinceRoll: number;
57
+ /** Whether we're in grace period */
58
+ inGracePeriod: boolean;
59
+ /** Last roll timestamp (ISO string) */
60
+ lastRollTime?: string;
61
+ }
62
+ export interface ContextInput {
63
+ /** Conversation messages */
64
+ messages: NormalizedMessage[];
65
+ /** System prompt */
66
+ system?: string;
67
+ /** Tool definitions */
68
+ tools?: ToolDefinition[];
69
+ /** Generation config (model, maxTokens, etc.) */
70
+ config: GenerationConfig;
71
+ /** Context management config */
72
+ context: ContextConfig;
73
+ }
74
+ export interface ContextInfo {
75
+ /** Whether a roll occurred */
76
+ didRoll: boolean;
77
+ /** Number of messages dropped in roll */
78
+ messagesDropped: number;
79
+ /** Number of messages kept */
80
+ messagesKept: number;
81
+ /** Current cache markers */
82
+ cacheMarkers: CacheMarker[];
83
+ /** Estimated cached tokens */
84
+ cachedTokens: number;
85
+ /** Estimated uncached tokens */
86
+ uncachedTokens: number;
87
+ /** Total estimated tokens */
88
+ totalTokens: number;
89
+ /** Whether hard limit was hit */
90
+ hardLimitHit: boolean;
91
+ }
92
+ export interface ContextOutput {
93
+ /** The LLM response (may be aborted) */
94
+ response: NormalizedResponse | AbortedResponse;
95
+ /** Updated state (save this for next call) */
96
+ state: ContextState;
97
+ /** Info about what happened */
98
+ info: ContextInfo;
99
+ }
100
+ export interface ContextStreamOptions {
101
+ /** Callback for streaming chunks */
102
+ onChunk?: (chunk: string) => void;
103
+ /** Abort signal */
104
+ signal?: AbortSignal;
105
+ }
106
+ /**
107
+ * Create initial empty state
108
+ */
109
+ export declare function createInitialState(): ContextState;
110
+ /**
111
+ * Default token estimator (chars / 4)
112
+ */
113
+ export declare function defaultTokenEstimator(message: NormalizedMessage): number;
114
+ /**
115
+ * Default context config
116
+ */
117
+ export declare const DEFAULT_CONTEXT_CONFIG: ContextConfig;
118
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/context/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Context management types
3
+ */
4
+ // ============================================================================
5
+ // Helpers
6
+ // ============================================================================
7
+ /**
8
+ * Create initial empty state
9
+ */
10
+ export function createInitialState() {
11
+ return {
12
+ cacheMarkers: [],
13
+ windowMessageIds: [],
14
+ messagesSinceRoll: 0,
15
+ tokensSinceRoll: 0,
16
+ inGracePeriod: false,
17
+ };
18
+ }
19
+ /**
20
+ * Default token estimator (chars / 4)
21
+ */
22
+ export function defaultTokenEstimator(message) {
23
+ let chars = 0;
24
+ for (const block of message.content) {
25
+ if (block.type === 'text') {
26
+ chars += block.text.length;
27
+ }
28
+ else if (block.type === 'tool_result') {
29
+ const content = typeof block.content === 'string'
30
+ ? block.content
31
+ : JSON.stringify(block.content);
32
+ chars += content.length;
33
+ }
34
+ else if (block.type === 'image') {
35
+ // Images: ~1500 tokens regardless of size (Anthropic)
36
+ chars += 6000; // 1500 * 4
37
+ }
38
+ }
39
+ return Math.ceil(chars / 4);
40
+ }
41
+ /**
42
+ * Default context config
43
+ */
44
+ export const DEFAULT_CONTEXT_CONFIG = {
45
+ rolling: {
46
+ threshold: 50,
47
+ buffer: 20,
48
+ unit: 'messages',
49
+ },
50
+ limits: {
51
+ maxCharacters: 500000,
52
+ },
53
+ cache: {
54
+ enabled: true,
55
+ points: 1,
56
+ minTokens: 1024,
57
+ preferUserMessages: true,
58
+ },
59
+ };
60
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/context/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4KH,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,YAAY,EAAE,EAAE;QAChB,gBAAgB,EAAE,EAAE;QACpB,iBAAiB,EAAE,CAAC;QACpB,eAAe,EAAE,CAAC;QAClB,aAAa,EAAE,KAAK;KACrB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA0B;IAC9D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7B,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACxC,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;gBAC/C,CAAC,CAAC,KAAK,CAAC,OAAO;gBACf,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAClC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;QAC1B,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAClC,sDAAsD;YACtD,KAAK,IAAI,IAAI,CAAC,CAAC,WAAW;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,OAAO,EAAE;QACP,SAAS,EAAE,EAAE;QACb,MAAM,EAAE,EAAE;QACV,IAAI,EAAE,UAAU;KACjB;IACD,MAAM,EAAE;QACN,aAAa,EAAE,MAAM;KACtB;IACD,KAAK,EAAE;QACL,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,IAAI;QACf,kBAAkB,EAAE,IAAI;KACzB;CACF,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Membrane - LLM middleware
3
+ *
4
+ * A selective boundary that transforms what passes through.
5
+ */
6
+ export { Membrane } from './membrane.js';
7
+ export * from './types/index.js';
8
+ export * from './transforms/index.js';
9
+ export * from './providers/index.js';
10
+ export * from './utils/index.js';
11
+ export * from './context/index.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,oBAAoB,CAAC"}