conversationalist 0.0.1

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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +369 -0
  3. package/dist/adapters/anthropic/index.d.ts +76 -0
  4. package/dist/adapters/anthropic/index.d.ts.map +1 -0
  5. package/dist/adapters/anthropic/index.js +147 -0
  6. package/dist/adapters/anthropic/index.js.map +10 -0
  7. package/dist/adapters/gemini/index.d.ts +79 -0
  8. package/dist/adapters/gemini/index.d.ts.map +1 -0
  9. package/dist/adapters/gemini/index.js +148 -0
  10. package/dist/adapters/gemini/index.js.map +10 -0
  11. package/dist/adapters/openai/index.d.ts +65 -0
  12. package/dist/adapters/openai/index.d.ts.map +1 -0
  13. package/dist/adapters/openai/index.js +127 -0
  14. package/dist/adapters/openai/index.js.map +10 -0
  15. package/dist/context.d.ts +35 -0
  16. package/dist/context.d.ts.map +1 -0
  17. package/dist/conversation/append.d.ts +25 -0
  18. package/dist/conversation/append.d.ts.map +1 -0
  19. package/dist/conversation/create.d.ts +14 -0
  20. package/dist/conversation/create.d.ts.map +1 -0
  21. package/dist/conversation/index.d.ts +9 -0
  22. package/dist/conversation/index.d.ts.map +1 -0
  23. package/dist/conversation/modify.d.ts +9 -0
  24. package/dist/conversation/modify.d.ts.map +1 -0
  25. package/dist/conversation/query.d.ts +34 -0
  26. package/dist/conversation/query.d.ts.map +1 -0
  27. package/dist/conversation/serialization.d.ts +13 -0
  28. package/dist/conversation/serialization.d.ts.map +1 -0
  29. package/dist/conversation/system-messages.d.ts +31 -0
  30. package/dist/conversation/system-messages.d.ts.map +1 -0
  31. package/dist/conversation/tool-tracking.d.ts +26 -0
  32. package/dist/conversation/tool-tracking.d.ts.map +1 -0
  33. package/dist/conversation/transform.d.ts +9 -0
  34. package/dist/conversation/transform.d.ts.map +1 -0
  35. package/dist/conversation.d.ts +39 -0
  36. package/dist/conversation.d.ts.map +1 -0
  37. package/dist/environment.d.ts +23 -0
  38. package/dist/environment.d.ts.map +1 -0
  39. package/dist/errors.d.ts +67 -0
  40. package/dist/errors.d.ts.map +1 -0
  41. package/dist/index.d.ts +17 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +14378 -0
  44. package/dist/index.js.map +87 -0
  45. package/dist/message.d.ts +2 -0
  46. package/dist/message.d.ts.map +1 -0
  47. package/dist/multi-modal.d.ts +27 -0
  48. package/dist/multi-modal.d.ts.map +1 -0
  49. package/dist/schemas.d.ts +30 -0
  50. package/dist/schemas.d.ts.map +1 -0
  51. package/dist/streaming.d.ts +37 -0
  52. package/dist/streaming.d.ts.map +1 -0
  53. package/dist/types.d.ts +78 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/utilities.d.ts +79 -0
  56. package/dist/utilities.d.ts.map +1 -0
  57. package/dist/with-conversation.d.ts +125 -0
  58. package/dist/with-conversation.d.ts.map +1 -0
  59. package/package.json +113 -0
@@ -0,0 +1,79 @@
1
+ import type { Conversation } from '../../types';
2
+ /**
3
+ * Gemini text part.
4
+ */
5
+ export interface GeminiTextPart {
6
+ text: string;
7
+ }
8
+ /**
9
+ * Gemini inline data part (for images).
10
+ */
11
+ export interface GeminiInlineDataPart {
12
+ inlineData: {
13
+ mimeType: string;
14
+ data: string;
15
+ };
16
+ }
17
+ /**
18
+ * Gemini file data part (for URLs).
19
+ */
20
+ export interface GeminiFileDataPart {
21
+ fileData: {
22
+ mimeType?: string;
23
+ fileUri: string;
24
+ };
25
+ }
26
+ /**
27
+ * Gemini function call part.
28
+ */
29
+ export interface GeminiFunctionCallPart {
30
+ functionCall: {
31
+ name: string;
32
+ args: Record<string, unknown>;
33
+ };
34
+ }
35
+ /**
36
+ * Gemini function response part.
37
+ */
38
+ export interface GeminiFunctionResponsePart {
39
+ functionResponse: {
40
+ name: string;
41
+ response: unknown;
42
+ };
43
+ }
44
+ /**
45
+ * Gemini content part union type.
46
+ */
47
+ export type GeminiPart = GeminiTextPart | GeminiInlineDataPart | GeminiFileDataPart | GeminiFunctionCallPart | GeminiFunctionResponsePart;
48
+ /**
49
+ * Gemini content (message) format.
50
+ */
51
+ export interface GeminiContent {
52
+ role: 'user' | 'model';
53
+ parts: GeminiPart[];
54
+ }
55
+ /**
56
+ * Result of converting a conversation to Gemini format.
57
+ */
58
+ export interface GeminiConversation {
59
+ systemInstruction?: GeminiContent;
60
+ contents: GeminiContent[];
61
+ }
62
+ /**
63
+ * Converts a conversation to Google Gemini API format.
64
+ * System messages are extracted to `systemInstruction`.
65
+ * Tool calls become functionCall parts, tool results become functionResponse parts.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * import { toGeminiMessages } from 'conversationalist/gemini';
70
+ *
71
+ * const { systemInstruction, contents } = toGeminiMessages(conversation);
72
+ * const response = await genAI.getGenerativeModel({ model: 'gemini-pro' }).generateContent({
73
+ * systemInstruction,
74
+ * contents,
75
+ * });
76
+ * ```
77
+ */
78
+ export declare function toGeminiMessages(conversation: Conversation): GeminiConversation;
79
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/gemini/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAiC,MAAM,aAAa,CAAC;AAE/E;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,gBAAgB,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAClB,cAAc,GACd,oBAAoB,GACpB,kBAAkB,GAClB,sBAAsB,GACtB,0BAA0B,CAAC;AAE/B;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,CAAC,EAAE,aAAa,CAAC;IAClC,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AA+GD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,kBAAkB,CAkF/E"}
@@ -0,0 +1,148 @@
1
+ // src/adapters/gemini/index.ts
2
+ function toGeminiParts(content) {
3
+ if (typeof content === "string") {
4
+ return content ? [{ text: content }] : [];
5
+ }
6
+ const parts = [];
7
+ for (const part of content) {
8
+ if (part.type === "text") {
9
+ if (part.text) {
10
+ parts.push({ text: part.text });
11
+ }
12
+ } else if (part.type === "image") {
13
+ const url = part.url ?? "";
14
+ if (url.startsWith("data:")) {
15
+ const matches = url.match(/^data:([^;]+);base64,(.+)$/);
16
+ if (matches) {
17
+ parts.push({
18
+ inlineData: {
19
+ mimeType: matches[1],
20
+ data: matches[2]
21
+ }
22
+ });
23
+ }
24
+ } else {
25
+ const fileData = { fileUri: url };
26
+ if (part.mimeType !== undefined) {
27
+ fileData.mimeType = part.mimeType;
28
+ }
29
+ parts.push({ fileData });
30
+ }
31
+ }
32
+ }
33
+ return parts;
34
+ }
35
+ function toFunctionCallPart(toolCall) {
36
+ let args;
37
+ if (typeof toolCall.arguments === "string") {
38
+ try {
39
+ args = JSON.parse(toolCall.arguments);
40
+ } catch {
41
+ args = { _raw: toolCall.arguments };
42
+ }
43
+ } else {
44
+ args = toolCall.arguments;
45
+ }
46
+ return {
47
+ functionCall: {
48
+ name: toolCall.name,
49
+ args
50
+ }
51
+ };
52
+ }
53
+ function toFunctionResponsePart(toolResult, functionName) {
54
+ return {
55
+ functionResponse: {
56
+ name: functionName,
57
+ response: toolResult.content
58
+ }
59
+ };
60
+ }
61
+ function extractSystemInstruction(messages) {
62
+ const systemMessages = messages.filter((m) => (m.role === "system" || m.role === "developer") && !m.hidden);
63
+ if (systemMessages.length === 0) {
64
+ return;
65
+ }
66
+ const parts = [];
67
+ for (const msg of systemMessages) {
68
+ parts.push(...toGeminiParts(msg.content));
69
+ }
70
+ if (parts.length === 0) {
71
+ return;
72
+ }
73
+ return {
74
+ role: "user",
75
+ parts
76
+ };
77
+ }
78
+ function toGeminiMessages(conversation) {
79
+ const systemInstruction = extractSystemInstruction(conversation.messages);
80
+ const toolCallNames = new Map;
81
+ for (const message of conversation.messages) {
82
+ if (message.role === "tool-use" && message.toolCall) {
83
+ toolCallNames.set(message.toolCall.id, message.toolCall.name);
84
+ }
85
+ }
86
+ const contents = [];
87
+ let currentRole = null;
88
+ let currentParts = [];
89
+ const flushCurrent = () => {
90
+ if (currentRole && currentParts.length > 0) {
91
+ contents.push({
92
+ role: currentRole,
93
+ parts: currentParts
94
+ });
95
+ currentParts = [];
96
+ }
97
+ currentRole = null;
98
+ };
99
+ for (const message of conversation.messages) {
100
+ if (message.hidden)
101
+ continue;
102
+ if (message.role === "system" || message.role === "developer") {
103
+ continue;
104
+ }
105
+ if (message.role === "snapshot") {
106
+ continue;
107
+ }
108
+ let targetRole;
109
+ let parts = [];
110
+ if (message.role === "user") {
111
+ targetRole = "user";
112
+ parts = toGeminiParts(message.content);
113
+ } else if (message.role === "assistant") {
114
+ targetRole = "model";
115
+ parts = toGeminiParts(message.content);
116
+ } else if (message.role === "tool-use" && message.toolCall) {
117
+ targetRole = "model";
118
+ parts = [toFunctionCallPart(message.toolCall)];
119
+ } else if (message.role === "tool-result" && message.toolResult) {
120
+ targetRole = "user";
121
+ const functionName = toolCallNames.get(message.toolResult.callId) ?? "unknown";
122
+ parts = [toFunctionResponsePart(message.toolResult, functionName)];
123
+ } else {
124
+ continue;
125
+ }
126
+ if (parts.length === 0) {
127
+ continue;
128
+ }
129
+ if (currentRole === targetRole) {
130
+ currentParts.push(...parts);
131
+ } else {
132
+ flushCurrent();
133
+ currentRole = targetRole;
134
+ currentParts = parts;
135
+ }
136
+ }
137
+ flushCurrent();
138
+ const result = { contents };
139
+ if (systemInstruction !== undefined) {
140
+ result.systemInstruction = systemInstruction;
141
+ }
142
+ return result;
143
+ }
144
+ export {
145
+ toGeminiMessages
146
+ };
147
+
148
+ //# debugId=0C64ADAD8EC3A21464756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/adapters/gemini/index.ts"],
4
+ "sourcesContent": [
5
+ "import type { MultiModalContent } from '@lasercat/homogenaize';\n\nimport type { Conversation, Message, ToolCall, ToolResult } from '../../types';\n\n/**\n * Gemini text part.\n */\nexport interface GeminiTextPart {\n text: string;\n}\n\n/**\n * Gemini inline data part (for images).\n */\nexport interface GeminiInlineDataPart {\n inlineData: {\n mimeType: string;\n data: string;\n };\n}\n\n/**\n * Gemini file data part (for URLs).\n */\nexport interface GeminiFileDataPart {\n fileData: {\n mimeType?: string;\n fileUri: string;\n };\n}\n\n/**\n * Gemini function call part.\n */\nexport interface GeminiFunctionCallPart {\n functionCall: {\n name: string;\n args: Record<string, unknown>;\n };\n}\n\n/**\n * Gemini function response part.\n */\nexport interface GeminiFunctionResponsePart {\n functionResponse: {\n name: string;\n response: unknown;\n };\n}\n\n/**\n * Gemini content part union type.\n */\nexport type GeminiPart =\n | GeminiTextPart\n | GeminiInlineDataPart\n | GeminiFileDataPart\n | GeminiFunctionCallPart\n | GeminiFunctionResponsePart;\n\n/**\n * Gemini content (message) format.\n */\nexport interface GeminiContent {\n role: 'user' | 'model';\n parts: GeminiPart[];\n}\n\n/**\n * Result of converting a conversation to Gemini format.\n */\nexport interface GeminiConversation {\n systemInstruction?: GeminiContent;\n contents: GeminiContent[];\n}\n\n/**\n * Converts internal multi-modal content to Gemini parts.\n */\nfunction toGeminiParts(content: string | ReadonlyArray<MultiModalContent>): GeminiPart[] {\n if (typeof content === 'string') {\n return content ? [{ text: content }] : [];\n }\n\n const parts: GeminiPart[] = [];\n for (const part of content) {\n if (part.type === 'text') {\n if (part.text) {\n parts.push({ text: part.text });\n }\n } else if (part.type === 'image') {\n const url = part.url ?? '';\n if (url.startsWith('data:')) {\n // Base64 data URL\n const matches = url.match(/^data:([^;]+);base64,(.+)$/);\n if (matches) {\n parts.push({\n inlineData: {\n mimeType: matches[1]!,\n data: matches[2]!,\n },\n });\n }\n } else {\n // File URI\n const fileData: GeminiFileDataPart['fileData'] = { fileUri: url };\n if (part.mimeType !== undefined) {\n fileData.mimeType = part.mimeType;\n }\n parts.push({ fileData });\n }\n }\n }\n\n return parts;\n}\n\n/**\n * Converts an internal ToolCall to Gemini functionCall part.\n */\nfunction toFunctionCallPart(toolCall: ToolCall): GeminiFunctionCallPart {\n let args: Record<string, unknown>;\n if (typeof toolCall.arguments === 'string') {\n try {\n args = JSON.parse(toolCall.arguments) as Record<string, unknown>;\n } catch {\n args = { _raw: toolCall.arguments };\n }\n } else {\n args = toolCall.arguments as Record<string, unknown>;\n }\n\n return {\n functionCall: {\n name: toolCall.name,\n args,\n },\n };\n}\n\n/**\n * Converts an internal ToolResult to Gemini functionResponse part.\n * Note: Gemini needs the function name, which we track via a map from the conversation.\n */\nfunction toFunctionResponsePart(\n toolResult: ToolResult,\n functionName: string,\n): GeminiFunctionResponsePart {\n return {\n functionResponse: {\n name: functionName,\n response: toolResult.content,\n },\n };\n}\n\n/**\n * Collects system message content from a conversation for Gemini's systemInstruction.\n */\nfunction extractSystemInstruction(\n messages: ReadonlyArray<Message>,\n): GeminiContent | undefined {\n const systemMessages = messages.filter(\n (m) => (m.role === 'system' || m.role === 'developer') && !m.hidden,\n );\n\n if (systemMessages.length === 0) {\n return undefined;\n }\n\n const parts: GeminiPart[] = [];\n for (const msg of systemMessages) {\n parts.push(...toGeminiParts(msg.content));\n }\n\n if (parts.length === 0) {\n return undefined;\n }\n\n return {\n role: 'user', // systemInstruction uses 'user' role in Gemini\n parts,\n };\n}\n\n/**\n * Converts a conversation to Google Gemini API format.\n * System messages are extracted to `systemInstruction`.\n * Tool calls become functionCall parts, tool results become functionResponse parts.\n *\n * @example\n * ```ts\n * import { toGeminiMessages } from 'conversationalist/gemini';\n *\n * const { systemInstruction, contents } = toGeminiMessages(conversation);\n * const response = await genAI.getGenerativeModel({ model: 'gemini-pro' }).generateContent({\n * systemInstruction,\n * contents,\n * });\n * ```\n */\nexport function toGeminiMessages(conversation: Conversation): GeminiConversation {\n const systemInstruction = extractSystemInstruction(conversation.messages);\n\n // Build a map of tool call IDs to function names for tool results\n const toolCallNames = new Map<string, string>();\n for (const message of conversation.messages) {\n if (message.role === 'tool-use' && message.toolCall) {\n toolCallNames.set(message.toolCall.id, message.toolCall.name);\n }\n }\n\n const contents: GeminiContent[] = [];\n\n // Track pending parts to merge consecutive same-role messages\n let currentRole: 'user' | 'model' | null = null;\n let currentParts: GeminiPart[] = [];\n\n const flushCurrent = () => {\n if (currentRole && currentParts.length > 0) {\n contents.push({\n role: currentRole,\n parts: currentParts,\n });\n currentParts = [];\n }\n currentRole = null;\n };\n\n for (const message of conversation.messages) {\n if (message.hidden) continue;\n\n // Skip system messages (already extracted)\n if (message.role === 'system' || message.role === 'developer') {\n continue;\n }\n\n // Skip snapshots\n if (message.role === 'snapshot') {\n continue;\n }\n\n let targetRole: 'user' | 'model';\n let parts: GeminiPart[] = [];\n\n if (message.role === 'user') {\n targetRole = 'user';\n parts = toGeminiParts(message.content);\n } else if (message.role === 'assistant') {\n targetRole = 'model';\n parts = toGeminiParts(message.content);\n } else if (message.role === 'tool-use' && message.toolCall) {\n targetRole = 'model';\n parts = [toFunctionCallPart(message.toolCall)];\n } else if (message.role === 'tool-result' && message.toolResult) {\n targetRole = 'user';\n const functionName = toolCallNames.get(message.toolResult.callId) ?? 'unknown';\n parts = [toFunctionResponsePart(message.toolResult, functionName)];\n } else {\n continue;\n }\n\n if (parts.length === 0) {\n continue;\n }\n\n // Merge with current or start new\n if (currentRole === targetRole) {\n currentParts.push(...parts);\n } else {\n flushCurrent();\n currentRole = targetRole;\n currentParts = parts;\n }\n }\n\n flushCurrent();\n\n const result: GeminiConversation = { contents };\n if (systemInstruction !== undefined) {\n result.systemInstruction = systemInstruction;\n }\n return result;\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "0C64ADAD8EC3A21464756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,65 @@
1
+ import type { Conversation } from '../../types';
2
+ /**
3
+ * OpenAI text content part.
4
+ */
5
+ export interface OpenAITextContentPart {
6
+ type: 'text';
7
+ text: string;
8
+ }
9
+ /**
10
+ * OpenAI image content part.
11
+ */
12
+ export interface OpenAIImageContentPart {
13
+ type: 'image_url';
14
+ image_url: {
15
+ url: string;
16
+ detail?: 'auto' | 'low' | 'high';
17
+ };
18
+ }
19
+ /**
20
+ * OpenAI content part union type.
21
+ */
22
+ export type OpenAIContentPart = OpenAITextContentPart | OpenAIImageContentPart;
23
+ /**
24
+ * OpenAI tool call format.
25
+ */
26
+ export interface OpenAIToolCall {
27
+ id: string;
28
+ type: 'function';
29
+ function: {
30
+ name: string;
31
+ arguments: string;
32
+ };
33
+ }
34
+ /**
35
+ * OpenAI message format for the Chat Completions API.
36
+ */
37
+ export interface OpenAIMessage {
38
+ role: 'system' | 'user' | 'assistant' | 'tool';
39
+ content: string | OpenAIContentPart[] | null;
40
+ name?: string;
41
+ tool_calls?: OpenAIToolCall[];
42
+ tool_call_id?: string;
43
+ }
44
+ /**
45
+ * Converts a conversation to OpenAI Chat Completions API message format.
46
+ * Handles role mapping, tool calls, and multi-modal content.
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * import { toOpenAIMessages } from 'conversationalist/openai';
51
+ *
52
+ * const messages = toOpenAIMessages(conversation);
53
+ * const response = await openai.chat.completions.create({
54
+ * model: 'gpt-4',
55
+ * messages,
56
+ * });
57
+ * ```
58
+ */
59
+ export declare function toOpenAIMessages(conversation: Conversation): OpenAIMessage[];
60
+ /**
61
+ * Groups consecutive tool-use messages into a single assistant message with multiple tool_calls.
62
+ * This is useful when the model made multiple tool calls in sequence.
63
+ */
64
+ export declare function toOpenAIMessagesGrouped(conversation: Conversation): OpenAIMessage[];
65
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/openai/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAiC,MAAM,aAAa,CAAC;AAE/E;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;KAClC,CAAC;CACH;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,qBAAqB,GAAG,sBAAsB,CAAC;AAE/E;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAAC;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAiHD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,aAAa,EAAE,CAW5E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,YAAY,GAAG,aAAa,EAAE,CAsCnF"}
@@ -0,0 +1,127 @@
1
+ // src/adapters/openai/index.ts
2
+ function toOpenAIContent(content) {
3
+ if (typeof content === "string") {
4
+ return content;
5
+ }
6
+ const parts = [];
7
+ for (const part of content) {
8
+ if (part.type === "text") {
9
+ parts.push({ type: "text", text: part.text ?? "" });
10
+ } else if (part.type === "image") {
11
+ parts.push({
12
+ type: "image_url",
13
+ image_url: { url: part.url ?? "" }
14
+ });
15
+ }
16
+ }
17
+ return parts.length === 1 && parts[0]?.type === "text" ? parts[0].text : parts;
18
+ }
19
+ function toOpenAIToolCall(toolCall) {
20
+ return {
21
+ id: toolCall.id,
22
+ type: "function",
23
+ function: {
24
+ name: toolCall.name,
25
+ arguments: typeof toolCall.arguments === "string" ? toolCall.arguments : JSON.stringify(toolCall.arguments)
26
+ }
27
+ };
28
+ }
29
+ function convertMessage(message) {
30
+ if (message.hidden) {
31
+ return null;
32
+ }
33
+ switch (message.role) {
34
+ case "system":
35
+ case "developer":
36
+ return {
37
+ role: "system",
38
+ content: toOpenAIContent(message.content)
39
+ };
40
+ case "user":
41
+ return {
42
+ role: "user",
43
+ content: toOpenAIContent(message.content)
44
+ };
45
+ case "assistant":
46
+ return {
47
+ role: "assistant",
48
+ content: toOpenAIContent(message.content)
49
+ };
50
+ case "tool-use":
51
+ if (!message.toolCall) {
52
+ return null;
53
+ }
54
+ return {
55
+ role: "assistant",
56
+ content: null,
57
+ tool_calls: [toOpenAIToolCall(message.toolCall)]
58
+ };
59
+ case "tool-result":
60
+ if (!message.toolResult) {
61
+ return null;
62
+ }
63
+ return {
64
+ role: "tool",
65
+ content: stringifyToolResult(message.toolResult),
66
+ tool_call_id: message.toolResult.callId
67
+ };
68
+ case "snapshot":
69
+ return null;
70
+ default:
71
+ return null;
72
+ }
73
+ }
74
+ function stringifyToolResult(result) {
75
+ if (typeof result.content === "string") {
76
+ return result.content;
77
+ }
78
+ return JSON.stringify(result.content);
79
+ }
80
+ function toOpenAIMessages(conversation) {
81
+ const messages = [];
82
+ for (const message of conversation.messages) {
83
+ const converted = convertMessage(message);
84
+ if (converted) {
85
+ messages.push(converted);
86
+ }
87
+ }
88
+ return messages;
89
+ }
90
+ function toOpenAIMessagesGrouped(conversation) {
91
+ const messages = [];
92
+ let pendingToolCalls = [];
93
+ for (const message of conversation.messages) {
94
+ if (message.hidden)
95
+ continue;
96
+ if (message.role === "tool-use" && message.toolCall) {
97
+ pendingToolCalls.push(toOpenAIToolCall(message.toolCall));
98
+ continue;
99
+ }
100
+ if (pendingToolCalls.length > 0) {
101
+ messages.push({
102
+ role: "assistant",
103
+ content: null,
104
+ tool_calls: pendingToolCalls
105
+ });
106
+ pendingToolCalls = [];
107
+ }
108
+ const converted = convertMessage(message);
109
+ if (converted && message.role !== "tool-use") {
110
+ messages.push(converted);
111
+ }
112
+ }
113
+ if (pendingToolCalls.length > 0) {
114
+ messages.push({
115
+ role: "assistant",
116
+ content: null,
117
+ tool_calls: pendingToolCalls
118
+ });
119
+ }
120
+ return messages;
121
+ }
122
+ export {
123
+ toOpenAIMessagesGrouped,
124
+ toOpenAIMessages
125
+ };
126
+
127
+ //# debugId=45A34764E7499FFC64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/adapters/openai/index.ts"],
4
+ "sourcesContent": [
5
+ "import type { MultiModalContent } from '@lasercat/homogenaize';\n\nimport type { Conversation, Message, ToolCall, ToolResult } from '../../types';\n\n/**\n * OpenAI text content part.\n */\nexport interface OpenAITextContentPart {\n type: 'text';\n text: string;\n}\n\n/**\n * OpenAI image content part.\n */\nexport interface OpenAIImageContentPart {\n type: 'image_url';\n image_url: {\n url: string;\n detail?: 'auto' | 'low' | 'high';\n };\n}\n\n/**\n * OpenAI content part union type.\n */\nexport type OpenAIContentPart = OpenAITextContentPart | OpenAIImageContentPart;\n\n/**\n * OpenAI tool call format.\n */\nexport interface OpenAIToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n}\n\n/**\n * OpenAI message format for the Chat Completions API.\n */\nexport interface OpenAIMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content: string | OpenAIContentPart[] | null;\n name?: string;\n tool_calls?: OpenAIToolCall[];\n tool_call_id?: string;\n}\n\n/**\n * Converts internal multi-modal content to OpenAI content parts format.\n */\nfunction toOpenAIContent(\n content: string | ReadonlyArray<MultiModalContent>,\n): string | OpenAIContentPart[] {\n if (typeof content === 'string') {\n return content;\n }\n\n const parts: OpenAIContentPart[] = [];\n for (const part of content) {\n if (part.type === 'text') {\n parts.push({ type: 'text', text: part.text ?? '' });\n } else if (part.type === 'image') {\n parts.push({\n type: 'image_url',\n image_url: { url: part.url ?? '' },\n });\n }\n }\n\n return parts.length === 1 && parts[0]?.type === 'text' ? parts[0].text : parts;\n}\n\n/**\n * Converts an internal ToolCall to OpenAI format.\n */\nfunction toOpenAIToolCall(toolCall: ToolCall): OpenAIToolCall {\n return {\n id: toolCall.id,\n type: 'function',\n function: {\n name: toolCall.name,\n arguments:\n typeof toolCall.arguments === 'string'\n ? toolCall.arguments\n : JSON.stringify(toolCall.arguments),\n },\n };\n}\n\n/**\n * Converts a single message to OpenAI format.\n * Returns null for messages that should be skipped.\n */\nfunction convertMessage(message: Message): OpenAIMessage | null {\n // Skip hidden messages\n if (message.hidden) {\n return null;\n }\n\n switch (message.role) {\n case 'system':\n case 'developer':\n return {\n role: 'system',\n content: toOpenAIContent(message.content),\n };\n\n case 'user':\n return {\n role: 'user',\n content: toOpenAIContent(message.content),\n };\n\n case 'assistant':\n return {\n role: 'assistant',\n content: toOpenAIContent(message.content),\n };\n\n case 'tool-use':\n if (!message.toolCall) {\n return null;\n }\n return {\n role: 'assistant',\n content: null,\n tool_calls: [toOpenAIToolCall(message.toolCall)],\n };\n\n case 'tool-result':\n if (!message.toolResult) {\n return null;\n }\n return {\n role: 'tool',\n content: stringifyToolResult(message.toolResult),\n tool_call_id: message.toolResult.callId,\n };\n\n case 'snapshot':\n // Snapshots are internal state, not sent to API\n return null;\n\n default:\n return null;\n }\n}\n\n/**\n * Converts a tool result to a string for OpenAI.\n */\nfunction stringifyToolResult(result: ToolResult): string {\n if (typeof result.content === 'string') {\n return result.content;\n }\n return JSON.stringify(result.content);\n}\n\n/**\n * Converts a conversation to OpenAI Chat Completions API message format.\n * Handles role mapping, tool calls, and multi-modal content.\n *\n * @example\n * ```ts\n * import { toOpenAIMessages } from 'conversationalist/openai';\n *\n * const messages = toOpenAIMessages(conversation);\n * const response = await openai.chat.completions.create({\n * model: 'gpt-4',\n * messages,\n * });\n * ```\n */\nexport function toOpenAIMessages(conversation: Conversation): OpenAIMessage[] {\n const messages: OpenAIMessage[] = [];\n\n for (const message of conversation.messages) {\n const converted = convertMessage(message);\n if (converted) {\n messages.push(converted);\n }\n }\n\n return messages;\n}\n\n/**\n * Groups consecutive tool-use messages into a single assistant message with multiple tool_calls.\n * This is useful when the model made multiple tool calls in sequence.\n */\nexport function toOpenAIMessagesGrouped(conversation: Conversation): OpenAIMessage[] {\n const messages: OpenAIMessage[] = [];\n let pendingToolCalls: OpenAIToolCall[] = [];\n\n for (const message of conversation.messages) {\n if (message.hidden) continue;\n\n if (message.role === 'tool-use' && message.toolCall) {\n pendingToolCalls.push(toOpenAIToolCall(message.toolCall));\n continue;\n }\n\n // Flush pending tool calls before adding a new message\n if (pendingToolCalls.length > 0) {\n messages.push({\n role: 'assistant',\n content: null,\n tool_calls: pendingToolCalls,\n });\n pendingToolCalls = [];\n }\n\n const converted = convertMessage(message);\n if (converted && message.role !== 'tool-use') {\n messages.push(converted);\n }\n }\n\n // Flush any remaining tool calls\n if (pendingToolCalls.length > 0) {\n messages.push({\n role: 'assistant',\n content: null,\n tool_calls: pendingToolCalls,\n });\n }\n\n return messages;\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "45A34764E7499FFC64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,35 @@
1
+ import { type ConversationEnvironment } from './environment';
2
+ import type { Conversation, Message } from './types';
3
+ /**
4
+ * Returns the last N messages from the conversation.
5
+ * By default excludes system messages and hidden messages.
6
+ */
7
+ export declare function getRecentMessages(conversation: Conversation, count: number, options?: {
8
+ includeHidden?: boolean;
9
+ includeSystem?: boolean;
10
+ }): ReadonlyArray<Message>;
11
+ /**
12
+ * Truncates conversation to keep only messages from the specified position onwards.
13
+ * Optionally preserves system messages regardless of position.
14
+ */
15
+ export declare function truncateFromPosition(conversation: Conversation, position: number, options?: {
16
+ preserveSystemMessages?: boolean;
17
+ }, environment?: Partial<ConversationEnvironment>): Conversation;
18
+ /**
19
+ * Estimates total tokens in a conversation using the provided estimator function.
20
+ */
21
+ export declare function estimateConversationTokens(conversation: Conversation, estimateTokens: (message: Message) => number): number;
22
+ /**
23
+ * Simple character-based token estimator.
24
+ * Approximates ~4 characters per token (rough average for English text).
25
+ */
26
+ export declare function simpleTokenEstimator(message: Message): number;
27
+ /**
28
+ * Truncates conversation to fit within an estimated token limit.
29
+ * Removes oldest messages first while preserving system messages and optionally the last N messages.
30
+ */
31
+ export declare function truncateToTokenLimit(conversation: Conversation, maxTokens: number, estimateTokens: (message: Message) => number, options?: {
32
+ preserveSystemMessages?: boolean;
33
+ preserveLastN?: number;
34
+ }, environment?: Partial<ConversationEnvironment>): Conversation;
35
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,uBAAuB,EAE7B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGrD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,GACA,aAAa,CAAC,OAAO,CAAC,CAWxB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,EACD,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CAqCd;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,GAC3C,MAAM,CAKR;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAG7D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,EAC5C,OAAO,CAAC,EAAE;IACR,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,EACD,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CA6Gd"}
@@ -0,0 +1,25 @@
1
+ import { type ConversationEnvironment } from '../environment';
2
+ import type { Conversation, MessageInput } from '../types';
3
+ /**
4
+ * Appends one or more messages to a conversation.
5
+ * Validates that tool results reference existing function calls.
6
+ * Returns a new immutable conversation with the messages added.
7
+ */
8
+ export declare function appendMessages(conversation: Conversation, ...inputs: MessageInput[]): Conversation;
9
+ export declare function appendMessages(conversation: Conversation, ...inputsAndEnvironment: [
10
+ ...MessageInput[],
11
+ Partial<ConversationEnvironment> | undefined
12
+ ]): Conversation;
13
+ /**
14
+ * Appends a user message to the conversation.
15
+ */
16
+ export declare function appendUserMessage(conversation: Conversation, content: MessageInput['content'], metadata?: Record<string, unknown>, environment?: Partial<ConversationEnvironment>): Conversation;
17
+ /**
18
+ * Appends an assistant message to the conversation.
19
+ */
20
+ export declare function appendAssistantMessage(conversation: Conversation, content: MessageInput['content'], metadata?: Record<string, unknown>, environment?: Partial<ConversationEnvironment>): Conversation;
21
+ /**
22
+ * Appends a system message to the conversation.
23
+ */
24
+ export declare function appendSystemMessage(conversation: Conversation, content: string, metadata?: Record<string, unknown>, environment?: Partial<ConversationEnvironment>): Conversation;
25
+ //# sourceMappingURL=append.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"append.d.ts","sourceRoot":"","sources":["../../src/conversation/append.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,uBAAuB,EAG7B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAW,YAAY,EAAE,MAAM,UAAU,CAAC;AAmCpE;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,YAAY,EAAE,YAAY,EAC1B,GAAG,MAAM,EAAE,YAAY,EAAE,GACxB,YAAY,CAAC;AAChB,wBAAgB,cAAc,CAC5B,YAAY,EAAE,YAAY,EAC1B,GAAG,oBAAoB,EAAE;IACvB,GAAG,YAAY,EAAE;IACjB,OAAO,CAAC,uBAAuB,CAAC,GAAG,SAAS;CAC7C,GACA,YAAY,CAAC;AA2DhB;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,EAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CAEd;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,EAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CAMd;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CAEd"}
@@ -0,0 +1,14 @@
1
+ import { type ConversationEnvironment } from '../environment';
2
+ import type { Conversation, ConversationStatus } from '../types';
3
+ /**
4
+ * Creates a new empty conversation with the specified options.
5
+ * Returns an immutable conversation object with timestamps set to the current time.
6
+ */
7
+ export declare function createConversation(options?: {
8
+ id?: string;
9
+ title?: string;
10
+ status?: ConversationStatus;
11
+ metadata?: Record<string, unknown>;
12
+ tags?: string[];
13
+ }, environment?: Partial<ConversationEnvironment>): Conversation;
14
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/conversation/create.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,uBAAuB,EAE7B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAGjE;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,CAAC,EAAE;IACR,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,EACD,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CAcd"}
@@ -0,0 +1,9 @@
1
+ export type { ConversationEnvironment } from '../environment';
2
+ export { createConversation } from './create';
3
+ export { appendAssistantMessage, appendMessages, appendSystemMessage, appendUserMessage, } from './append';
4
+ export { computeConversationStatistics, getConversationMessages, getMessageAtPosition, getMessageByIdentifier, searchConversationMessages, } from './query';
5
+ export { collapseSystemMessages, getFirstSystemMessage, getSystemMessages, hasSystemMessage, prependSystemMessage, replaceSystemMessage, } from './system-messages';
6
+ export { redactMessageAtPosition } from './modify';
7
+ export { deserializeConversation, serializeConversation } from './serialization';
8
+ export { toChatMessages } from './transform';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conversation/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAG9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAG9C,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,6BAA6B,EAC7B,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAGnD,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGjF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type ConversationEnvironment } from '../environment';
2
+ import type { Conversation } from '../types';
3
+ /**
4
+ * Replaces the content of a message at the specified position with a placeholder.
5
+ * Preserves all other message properties except toolCall, toolResult, and tokenUsage.
6
+ * Throws if the position is out of bounds.
7
+ */
8
+ export declare function redactMessageAtPosition(conversation: Conversation, position: number, placeholder?: string, environment?: Partial<ConversationEnvironment>): Conversation;
9
+ //# sourceMappingURL=modify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modify.d.ts","sourceRoot":"","sources":["../../src/conversation/modify.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,uBAAuB,EAE7B,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,YAAY,EAAW,MAAM,UAAU,CAAC;AAGtD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,MAAqB,EAClC,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CA2Bd"}
@@ -0,0 +1,34 @@
1
+ import type { Conversation, Message } from '../types';
2
+ /**
3
+ * Returns all messages from a conversation.
4
+ * By default excludes hidden messages unless includeHidden is true.
5
+ */
6
+ export declare function getConversationMessages(conversation: Conversation, options?: {
7
+ includeHidden?: boolean;
8
+ }): ReadonlyArray<Message>;
9
+ /**
10
+ * Returns the message at the specified position index.
11
+ * Returns undefined if no message exists at that position.
12
+ */
13
+ export declare function getMessageAtPosition(conversation: Conversation, position: number): Message | undefined;
14
+ /**
15
+ * Finds a message by its unique identifier.
16
+ * Returns undefined if no message with that ID exists.
17
+ */
18
+ export declare function getMessageByIdentifier(conversation: Conversation, id: string): Message | undefined;
19
+ /**
20
+ * Filters messages using a custom predicate function.
21
+ * Returns all messages for which the predicate returns true.
22
+ */
23
+ export declare function searchConversationMessages(conversation: Conversation, predicate: (m: Message) => boolean): Message[];
24
+ /**
25
+ * Computes statistics about a conversation's messages.
26
+ * Returns totals, counts by role, hidden message count, and image count.
27
+ */
28
+ export declare function computeConversationStatistics(conversation: Conversation): {
29
+ total: number;
30
+ byRole: Record<string, number>;
31
+ hidden: number;
32
+ withImages: number;
33
+ };
34
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/conversation/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAGtD;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,YAAY,EAC1B,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC,aAAa,CAAC,OAAO,CAAC,CAKxB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,GACf,OAAO,GAAG,SAAS,CAErB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,YAAY,EAC1B,EAAE,EAAE,MAAM,GACT,OAAO,GAAG,SAAS,CAErB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,GACjC,OAAO,EAAE,CAEX;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,YAAY,EAAE,YAAY,GAAG;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,CAiBA"}