conversationalist 0.0.7 → 0.0.9
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 +158 -104
- package/dist/adapters/anthropic/index.d.ts +11 -6
- package/dist/adapters/anthropic/index.d.ts.map +1 -1
- package/dist/adapters/anthropic/index.js +16 -3
- package/dist/adapters/anthropic/index.js.map +5 -4
- package/dist/adapters/gemini/index.d.ts +2 -2
- package/dist/adapters/gemini/index.d.ts.map +1 -1
- package/dist/adapters/gemini/index.js +52 -9
- package/dist/adapters/gemini/index.js.map +5 -4
- package/dist/adapters/openai/index.d.ts +32 -5
- package/dist/adapters/openai/index.d.ts.map +1 -1
- package/dist/adapters/openai/index.js +30 -8
- package/dist/adapters/openai/index.js.map +5 -4
- package/dist/context.d.ts.map +1 -1
- package/dist/conversation/append.d.ts +4 -4
- package/dist/conversation/append.d.ts.map +1 -1
- package/dist/conversation/create.d.ts +2 -3
- package/dist/conversation/create.d.ts.map +1 -1
- package/dist/conversation/index.d.ts +2 -2
- package/dist/conversation/index.d.ts.map +1 -1
- package/dist/conversation/modify.d.ts.map +1 -1
- package/dist/conversation/query.d.ts +9 -5
- package/dist/conversation/query.d.ts.map +1 -1
- package/dist/conversation/serialization.d.ts +6 -28
- package/dist/conversation/serialization.d.ts.map +1 -1
- package/dist/conversation/system-messages.d.ts +3 -3
- package/dist/conversation/system-messages.d.ts.map +1 -1
- package/dist/conversation/transform.d.ts.map +1 -1
- package/dist/conversation.d.ts +74 -18
- package/dist/conversation.d.ts.map +1 -1
- package/dist/export/index.d.ts +7 -0
- package/dist/export/index.d.ts.map +1 -0
- package/dist/export/index.js +3762 -0
- package/dist/export/index.js.map +62 -0
- package/dist/history.d.ts +102 -24
- package/dist/history.d.ts.map +1 -1
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +392 -4075
- package/dist/index.js.map +15 -60
- package/dist/markdown/index.d.ts +15 -0
- package/dist/markdown/index.d.ts.map +1 -0
- package/dist/markdown/index.js +4969 -0
- package/dist/markdown/index.js.map +69 -0
- package/dist/message.d.ts +1 -1
- package/dist/message.d.ts.map +1 -1
- package/dist/multi-modal.d.ts +3 -0
- package/dist/multi-modal.d.ts.map +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +59 -0
- package/dist/plugins/index.js.map +10 -0
- package/dist/plugins/pii-redaction.d.ts +10 -1
- package/dist/plugins/pii-redaction.d.ts.map +1 -1
- package/dist/redaction/index.d.ts +2 -0
- package/dist/redaction/index.d.ts.map +1 -0
- package/dist/redaction/index.js +59 -0
- package/dist/redaction/index.js.map +10 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +114 -0
- package/dist/schemas/index.js.map +10 -0
- package/dist/schemas.d.ts +324 -15
- package/dist/schemas.d.ts.map +1 -1
- package/dist/sort/index.d.ts +2 -0
- package/dist/sort/index.d.ts.map +1 -0
- package/dist/sort/index.js +32 -0
- package/dist/sort/index.js.map +10 -0
- package/dist/streaming.d.ts +3 -3
- package/dist/streaming.d.ts.map +1 -1
- package/dist/types.d.ts +72 -50
- package/dist/types.d.ts.map +1 -1
- package/dist/utilities/index.d.ts +1 -3
- package/dist/utilities/index.d.ts.map +1 -1
- package/dist/utilities/line-endings.d.ts +5 -0
- package/dist/utilities/line-endings.d.ts.map +1 -0
- package/dist/utilities/markdown.d.ts +1 -1
- package/dist/utilities/markdown.d.ts.map +1 -1
- package/dist/utilities/message-store.d.ts +6 -0
- package/dist/utilities/message-store.d.ts.map +1 -0
- package/dist/utilities/message.d.ts +9 -3
- package/dist/utilities/message.d.ts.map +1 -1
- package/dist/utilities/tool-calls.d.ts +4 -4
- package/dist/utilities/tool-calls.d.ts.map +1 -1
- package/dist/utilities/tool-results.d.ts +10 -0
- package/dist/utilities/tool-results.d.ts.map +1 -0
- package/dist/utilities/transient.d.ts +2 -2
- package/dist/utilities/transient.d.ts.map +1 -1
- package/dist/utilities.d.ts +3 -5
- package/dist/utilities.d.ts.map +1 -1
- package/dist/versioning/index.d.ts +3 -0
- package/dist/versioning/index.d.ts.map +1 -0
- package/dist/versioning/index.js +58 -0
- package/dist/versioning/index.js.map +11 -0
- package/dist/with-conversation.d.ts +8 -8
- package/dist/with-conversation.d.ts.map +1 -1
- package/package.json +26 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/adapters/anthropic/index.ts"],
|
|
3
|
+
"sources": ["../../../src/utilities/message-store.ts", "../../../src/adapters/anthropic/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {
|
|
5
|
+
"import type { Conversation, Message } from '../types';\n\nexport function getOrderedMessages(conversation: Conversation): Message[] {\n const ordered: Message[] = [];\n for (const id of conversation.ids) {\n const message = conversation.messages[id];\n if (message) {\n ordered.push(message);\n }\n }\n return ordered;\n}\n\nexport function toIdRecord<T extends { id: string }>(\n items: readonly T[],\n): Record<string, T> {\n const record: Record<string, T> = {};\n for (const item of items) {\n record[item.id] = item;\n }\n return record;\n}\n",
|
|
6
|
+
"import type { MultiModalContent } from '@lasercat/homogenaize';\n\nimport type { Conversation, Message, ToolCall, ToolResult } from '../../types';\nimport { getOrderedMessages } from '../../utilities/message-store';\n\n/**\n * Anthropic text content block.\n */\nexport interface AnthropicTextBlock {\n type: 'text';\n text: string;\n}\n\n/**\n * Anthropic image content block.\n */\nexport interface AnthropicBase64ImageSource {\n type: 'base64';\n media_type: string;\n data: string;\n}\n\nexport interface AnthropicUrlImageSource {\n type: 'url';\n url: string;\n}\n\nexport type AnthropicImageSource = AnthropicBase64ImageSource | AnthropicUrlImageSource;\n\nexport interface AnthropicImageBlock {\n type: 'image';\n source: AnthropicImageSource;\n}\n\n/**\n * Anthropic tool use content block.\n */\nexport interface AnthropicToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: unknown;\n}\n\n/**\n * Anthropic tool result content block.\n */\nexport interface AnthropicToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n content: string;\n is_error?: boolean;\n}\n\n/**\n * Anthropic content block union type.\n */\nexport type AnthropicContentBlock =\n | AnthropicTextBlock\n | AnthropicImageBlock\n | AnthropicToolUseBlock\n | AnthropicToolResultBlock;\n\n/**\n * Anthropic message format for the Messages API.\n */\nexport interface AnthropicMessage {\n role: 'user' | 'assistant';\n content: string | AnthropicContentBlock[];\n}\n\n/**\n * Result of converting a conversation to Anthropic format.\n * System messages are extracted separately since Anthropic uses a top-level system parameter.\n */\nexport interface AnthropicConversation {\n system?: string;\n messages: AnthropicMessage[];\n}\n\n/**\n * Converts internal multi-modal content to Anthropic content blocks.\n */\nfunction toAnthropicContent(\n content: string | ReadonlyArray<MultiModalContent>,\n): string | AnthropicContentBlock[] {\n if (typeof content === 'string') {\n return content;\n }\n\n const blocks: AnthropicContentBlock[] = [];\n for (const part of content) {\n if (part.type === 'text') {\n blocks.push({ type: 'text', text: part.text ?? '' });\n } else if (part.type === 'image') {\n // Anthropic supports both URL and base64\n const url = part.url ?? '';\n if (url.startsWith('data:')) {\n // Base64 data URL\n const matches = url.match(/^data:([^;]+);base64,(.+)$/);\n if (matches && matches[1] && matches[2]) {\n blocks.push({\n type: 'image',\n source: {\n type: 'base64',\n media_type: matches[1],\n data: matches[2],\n },\n });\n }\n } else {\n // Regular URL\n blocks.push({\n type: 'image',\n source: {\n type: 'url',\n url,\n },\n });\n }\n }\n }\n\n return blocks.length === 1 && blocks[0]?.type === 'text' ? blocks[0].text : blocks;\n}\n\n/**\n * Converts an internal ToolCall to Anthropic tool_use block.\n */\nfunction toToolUseBlock(toolCall: ToolCall): AnthropicToolUseBlock {\n return {\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.name,\n input:\n typeof toolCall.arguments === 'string'\n ? JSON.parse(toolCall.arguments)\n : toolCall.arguments,\n };\n}\n\n/**\n * Converts an internal ToolResult to Anthropic tool_result block.\n */\nfunction toToolResultBlock(toolResult: ToolResult): AnthropicToolResultBlock {\n const result: AnthropicToolResultBlock = {\n type: 'tool_result',\n tool_use_id: toolResult.callId,\n content:\n typeof toolResult.content === 'string'\n ? toolResult.content\n : JSON.stringify(toolResult.content),\n };\n\n if (toolResult.outcome === 'error') {\n result.is_error = true;\n }\n\n return result;\n}\n\n/**\n * Collects system message content from a conversation.\n */\nfunction extractSystemContent(messages: ReadonlyArray<Message>): string | 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: string[] = [];\n for (const msg of systemMessages) {\n if (typeof msg.content === 'string') {\n parts.push(msg.content);\n } else {\n for (const part of msg.content) {\n if (part.type === 'text') {\n parts.push(part.text ?? '');\n }\n }\n }\n }\n\n return parts.join('\\n\\n');\n}\n\n/**\n * Converts a conversation to Anthropic Messages API format.\n * System messages are extracted to the top-level `system` field.\n * Tool calls become tool_use blocks, tool results become tool_result blocks.\n *\n * @example\n * ```ts\n * import { toAnthropicMessages } from 'conversationalist/anthropic';\n *\n * const { system, messages } = toAnthropicMessages(conversation);\n * const response = await anthropic.messages.create({\n * model: 'claude-3-opus-20240229',\n * system,\n * messages,\n * });\n * ```\n */\nexport function toAnthropicMessages(conversation: Conversation): AnthropicConversation {\n const ordered = getOrderedMessages(conversation);\n const system = extractSystemContent(ordered);\n const messages: AnthropicMessage[] = [];\n\n // Track pending content blocks to merge consecutive same-role messages\n let currentRole: 'user' | 'assistant' | null = null;\n let currentBlocks: AnthropicContentBlock[] = [];\n\n const flushCurrent = () => {\n if (currentRole && currentBlocks.length > 0) {\n messages.push({\n role: currentRole,\n content:\n currentBlocks.length === 1 && currentBlocks[0]?.type === 'text'\n ? currentBlocks[0].text\n : currentBlocks,\n });\n currentBlocks = [];\n }\n currentRole = null;\n };\n\n for (const message of ordered) {\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' | 'assistant';\n let blocks: AnthropicContentBlock[] = [];\n\n if (message.role === 'user') {\n targetRole = 'user';\n const content = toAnthropicContent(message.content);\n if (typeof content === 'string') {\n blocks = [{ type: 'text', text: content }];\n } else {\n blocks = content;\n }\n } else if (message.role === 'assistant') {\n targetRole = 'assistant';\n const content = toAnthropicContent(message.content);\n if (typeof content === 'string') {\n blocks = [{ type: 'text', text: content }];\n } else {\n blocks = content;\n }\n } else if (message.role === 'tool-use' && message.toolCall) {\n targetRole = 'assistant';\n blocks = [toToolUseBlock(message.toolCall)];\n } else if (message.role === 'tool-result' && message.toolResult) {\n targetRole = 'user';\n blocks = [toToolResultBlock(message.toolResult)];\n } else {\n continue;\n }\n\n // Merge with current or start new\n if (currentRole === targetRole) {\n currentBlocks.push(...blocks);\n } else {\n flushCurrent();\n currentRole = targetRole;\n currentBlocks = blocks;\n }\n }\n\n flushCurrent();\n\n const result: AnthropicConversation = { messages };\n if (system !== undefined) {\n result.system = system;\n }\n return result;\n}\n"
|
|
6
7
|
],
|
|
7
|
-
"mappings": ";
|
|
8
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "77199835081EDC2864756E2164756E21",
|
|
9
10
|
"names": []
|
|
10
11
|
}
|
|
@@ -19,7 +19,7 @@ export interface GeminiInlineDataPart {
|
|
|
19
19
|
*/
|
|
20
20
|
export interface GeminiFileDataPart {
|
|
21
21
|
fileData: {
|
|
22
|
-
mimeType
|
|
22
|
+
mimeType: string;
|
|
23
23
|
fileUri: string;
|
|
24
24
|
};
|
|
25
25
|
}
|
|
@@ -38,7 +38,7 @@ export interface GeminiFunctionCallPart {
|
|
|
38
38
|
export interface GeminiFunctionResponsePart {
|
|
39
39
|
functionResponse: {
|
|
40
40
|
name: string;
|
|
41
|
-
response: unknown
|
|
41
|
+
response: Record<string, unknown>;
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
@@ -1 +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;
|
|
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;AAG/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,EAAE,MAAM,CAAC;QACjB,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,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,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;AAkJD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,kBAAkB,CAmF/E"}
|
|
@@ -1,4 +1,46 @@
|
|
|
1
|
+
// src/utilities/message-store.ts
|
|
2
|
+
function getOrderedMessages(conversation) {
|
|
3
|
+
const ordered = [];
|
|
4
|
+
for (const id of conversation.ids) {
|
|
5
|
+
const message = conversation.messages[id];
|
|
6
|
+
if (message) {
|
|
7
|
+
ordered.push(message);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return ordered;
|
|
11
|
+
}
|
|
12
|
+
|
|
1
13
|
// src/adapters/gemini/index.ts
|
|
14
|
+
var DEFAULT_FILE_MIME_TYPE = "application/octet-stream";
|
|
15
|
+
var MIME_TYPE_BY_EXTENSION = {
|
|
16
|
+
bmp: "image/bmp",
|
|
17
|
+
gif: "image/gif",
|
|
18
|
+
heic: "image/heic",
|
|
19
|
+
heif: "image/heif",
|
|
20
|
+
jpeg: "image/jpeg",
|
|
21
|
+
jpg: "image/jpeg",
|
|
22
|
+
png: "image/png",
|
|
23
|
+
svg: "image/svg+xml",
|
|
24
|
+
webp: "image/webp"
|
|
25
|
+
};
|
|
26
|
+
function inferMimeType(url) {
|
|
27
|
+
const trimmed = url.split("#")[0]?.split("?")[0] ?? "";
|
|
28
|
+
const dotIndex = trimmed.lastIndexOf(".");
|
|
29
|
+
if (dotIndex === -1) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const extension = trimmed.slice(dotIndex + 1).toLowerCase();
|
|
33
|
+
return MIME_TYPE_BY_EXTENSION[extension];
|
|
34
|
+
}
|
|
35
|
+
function resolveMimeType(url, explicit) {
|
|
36
|
+
return explicit ?? inferMimeType(url) ?? DEFAULT_FILE_MIME_TYPE;
|
|
37
|
+
}
|
|
38
|
+
function normalizeGeminiResponse(content) {
|
|
39
|
+
if (content !== null && typeof content === "object") {
|
|
40
|
+
return content;
|
|
41
|
+
}
|
|
42
|
+
return { result: content };
|
|
43
|
+
}
|
|
2
44
|
function toGeminiParts(content) {
|
|
3
45
|
if (typeof content === "string") {
|
|
4
46
|
return content ? [{ text: content }] : [];
|
|
@@ -22,10 +64,10 @@ function toGeminiParts(content) {
|
|
|
22
64
|
});
|
|
23
65
|
}
|
|
24
66
|
} else {
|
|
25
|
-
const fileData = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
67
|
+
const fileData = {
|
|
68
|
+
fileUri: url,
|
|
69
|
+
mimeType: resolveMimeType(url, part.mimeType)
|
|
70
|
+
};
|
|
29
71
|
parts.push({ fileData });
|
|
30
72
|
}
|
|
31
73
|
}
|
|
@@ -54,7 +96,7 @@ function toFunctionResponsePart(toolResult, functionName) {
|
|
|
54
96
|
return {
|
|
55
97
|
functionResponse: {
|
|
56
98
|
name: functionName,
|
|
57
|
-
response: toolResult.content
|
|
99
|
+
response: normalizeGeminiResponse(toolResult.content)
|
|
58
100
|
}
|
|
59
101
|
};
|
|
60
102
|
}
|
|
@@ -76,9 +118,10 @@ function extractSystemInstruction(messages) {
|
|
|
76
118
|
};
|
|
77
119
|
}
|
|
78
120
|
function toGeminiMessages(conversation) {
|
|
79
|
-
const
|
|
121
|
+
const ordered = getOrderedMessages(conversation);
|
|
122
|
+
const systemInstruction = extractSystemInstruction(ordered);
|
|
80
123
|
const toolCallNames = new Map;
|
|
81
|
-
for (const message of
|
|
124
|
+
for (const message of ordered) {
|
|
82
125
|
if (message.role === "tool-use" && message.toolCall) {
|
|
83
126
|
toolCallNames.set(message.toolCall.id, message.toolCall.name);
|
|
84
127
|
}
|
|
@@ -96,7 +139,7 @@ function toGeminiMessages(conversation) {
|
|
|
96
139
|
}
|
|
97
140
|
currentRole = null;
|
|
98
141
|
};
|
|
99
|
-
for (const message of
|
|
142
|
+
for (const message of ordered) {
|
|
100
143
|
if (message.hidden)
|
|
101
144
|
continue;
|
|
102
145
|
if (message.role === "system" || message.role === "developer") {
|
|
@@ -145,4 +188,4 @@ export {
|
|
|
145
188
|
toGeminiMessages
|
|
146
189
|
};
|
|
147
190
|
|
|
148
|
-
//# debugId=
|
|
191
|
+
//# debugId=88465330F0A95D8664756E2164756E21
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/adapters/gemini/index.ts"],
|
|
3
|
+
"sources": ["../../../src/utilities/message-store.ts", "../../../src/adapters/gemini/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {
|
|
5
|
+
"import type { Conversation, Message } from '../types';\n\nexport function getOrderedMessages(conversation: Conversation): Message[] {\n const ordered: Message[] = [];\n for (const id of conversation.ids) {\n const message = conversation.messages[id];\n if (message) {\n ordered.push(message);\n }\n }\n return ordered;\n}\n\nexport function toIdRecord<T extends { id: string }>(\n items: readonly T[],\n): Record<string, T> {\n const record: Record<string, T> = {};\n for (const item of items) {\n record[item.id] = item;\n }\n return record;\n}\n",
|
|
6
|
+
"import type { MultiModalContent } from '@lasercat/homogenaize';\n\nimport type { Conversation, Message, ToolCall, ToolResult } from '../../types';\nimport { getOrderedMessages } from '../../utilities/message-store';\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: Record<string, 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\nconst DEFAULT_FILE_MIME_TYPE = 'application/octet-stream';\n\nconst MIME_TYPE_BY_EXTENSION: Record<string, string> = {\n bmp: 'image/bmp',\n gif: 'image/gif',\n heic: 'image/heic',\n heif: 'image/heif',\n jpeg: 'image/jpeg',\n jpg: 'image/jpeg',\n png: 'image/png',\n svg: 'image/svg+xml',\n webp: 'image/webp',\n};\n\nfunction inferMimeType(url: string): string | undefined {\n const trimmed = url.split('#')[0]?.split('?')[0] ?? '';\n const dotIndex = trimmed.lastIndexOf('.');\n if (dotIndex === -1) {\n return undefined;\n }\n const extension = trimmed.slice(dotIndex + 1).toLowerCase();\n return MIME_TYPE_BY_EXTENSION[extension];\n}\n\nfunction resolveMimeType(url: string, explicit?: string): string {\n return explicit ?? inferMimeType(url) ?? DEFAULT_FILE_MIME_TYPE;\n}\n\nfunction normalizeGeminiResponse(content: unknown): Record<string, unknown> {\n if (content !== null && typeof content === 'object') {\n return content as Record<string, unknown>;\n }\n return { result: content };\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'] = {\n fileUri: url,\n mimeType: resolveMimeType(url, 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: normalizeGeminiResponse(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 ordered = getOrderedMessages(conversation);\n const systemInstruction = extractSystemInstruction(ordered);\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 ordered) {\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 ordered) {\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
|
],
|
|
7
|
-
"mappings": ";
|
|
8
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "88465330F0A95D8664756E2164756E21",
|
|
9
10
|
"names": []
|
|
10
11
|
}
|
|
@@ -32,15 +32,42 @@ export interface OpenAIToolCall {
|
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
* OpenAI message format for the Chat Completions API.
|
|
35
|
+
* OpenAI system message format for the Chat Completions API.
|
|
36
|
+
*/
|
|
37
|
+
export interface OpenAISystemMessage {
|
|
38
|
+
role: 'system';
|
|
39
|
+
content: string | OpenAITextContentPart[];
|
|
40
|
+
name?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* OpenAI user message format for the Chat Completions API.
|
|
36
44
|
*/
|
|
37
|
-
export interface
|
|
38
|
-
role: '
|
|
39
|
-
content: string | OpenAIContentPart[]
|
|
45
|
+
export interface OpenAIUserMessage {
|
|
46
|
+
role: 'user';
|
|
47
|
+
content: string | OpenAIContentPart[];
|
|
48
|
+
name?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* OpenAI assistant message format for the Chat Completions API.
|
|
52
|
+
*/
|
|
53
|
+
export interface OpenAIAssistantMessage {
|
|
54
|
+
role: 'assistant';
|
|
55
|
+
content: string | OpenAITextContentPart[] | null;
|
|
40
56
|
name?: string;
|
|
41
57
|
tool_calls?: OpenAIToolCall[];
|
|
42
|
-
tool_call_id?: string;
|
|
43
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* OpenAI tool message format for the Chat Completions API.
|
|
61
|
+
*/
|
|
62
|
+
export interface OpenAIToolMessage {
|
|
63
|
+
role: 'tool';
|
|
64
|
+
content: string | OpenAITextContentPart[];
|
|
65
|
+
tool_call_id: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* OpenAI message format for the Chat Completions API.
|
|
69
|
+
*/
|
|
70
|
+
export type OpenAIMessage = OpenAISystemMessage | OpenAIUserMessage | OpenAIAssistantMessage | OpenAIToolMessage;
|
|
44
71
|
/**
|
|
45
72
|
* Converts a conversation to OpenAI Chat Completions API message format.
|
|
46
73
|
* Handles role mapping, tool calls, and multi-modal content.
|
|
@@ -1 +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;
|
|
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;AAG/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,mBAAmB;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAAC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,qBAAqB,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAAC;IAC1C,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,mBAAmB,GACnB,iBAAiB,GACjB,sBAAsB,GACtB,iBAAiB,CAAC;AA4ItB;;;;;;;;;;;;;;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"}
|
|
@@ -1,20 +1,42 @@
|
|
|
1
|
+
// src/utilities/message-store.ts
|
|
2
|
+
function getOrderedMessages(conversation) {
|
|
3
|
+
const ordered = [];
|
|
4
|
+
for (const id of conversation.ids) {
|
|
5
|
+
const message = conversation.messages[id];
|
|
6
|
+
if (message) {
|
|
7
|
+
ordered.push(message);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return ordered;
|
|
11
|
+
}
|
|
12
|
+
|
|
1
13
|
// src/adapters/openai/index.ts
|
|
2
|
-
function toOpenAIContent(content) {
|
|
14
|
+
function toOpenAIContent(content, options = {}) {
|
|
3
15
|
if (typeof content === "string") {
|
|
4
16
|
return content;
|
|
5
17
|
}
|
|
18
|
+
const allowImages = options.allowImages ?? true;
|
|
6
19
|
const parts = [];
|
|
7
20
|
for (const part of content) {
|
|
8
21
|
if (part.type === "text") {
|
|
9
22
|
parts.push({ type: "text", text: part.text ?? "" });
|
|
10
|
-
} else if (part.type === "image") {
|
|
23
|
+
} else if (part.type === "image" && allowImages) {
|
|
11
24
|
parts.push({
|
|
12
25
|
type: "image_url",
|
|
13
26
|
image_url: { url: part.url ?? "" }
|
|
14
27
|
});
|
|
15
28
|
}
|
|
16
29
|
}
|
|
17
|
-
|
|
30
|
+
if (parts.length === 0) {
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
if (parts.length === 1 && parts[0]?.type === "text") {
|
|
34
|
+
return parts[0].text;
|
|
35
|
+
}
|
|
36
|
+
return allowImages ? parts : parts;
|
|
37
|
+
}
|
|
38
|
+
function toOpenAITextContent(content) {
|
|
39
|
+
return toOpenAIContent(content, { allowImages: false });
|
|
18
40
|
}
|
|
19
41
|
function toOpenAIToolCall(toolCall) {
|
|
20
42
|
return {
|
|
@@ -35,7 +57,7 @@ function convertMessage(message) {
|
|
|
35
57
|
case "developer":
|
|
36
58
|
return {
|
|
37
59
|
role: "system",
|
|
38
|
-
content:
|
|
60
|
+
content: toOpenAITextContent(message.content)
|
|
39
61
|
};
|
|
40
62
|
case "user":
|
|
41
63
|
return {
|
|
@@ -45,7 +67,7 @@ function convertMessage(message) {
|
|
|
45
67
|
case "assistant":
|
|
46
68
|
return {
|
|
47
69
|
role: "assistant",
|
|
48
|
-
content:
|
|
70
|
+
content: toOpenAITextContent(message.content)
|
|
49
71
|
};
|
|
50
72
|
case "tool-use":
|
|
51
73
|
if (!message.toolCall) {
|
|
@@ -79,7 +101,7 @@ function stringifyToolResult(result) {
|
|
|
79
101
|
}
|
|
80
102
|
function toOpenAIMessages(conversation) {
|
|
81
103
|
const messages = [];
|
|
82
|
-
for (const message of conversation
|
|
104
|
+
for (const message of getOrderedMessages(conversation)) {
|
|
83
105
|
const converted = convertMessage(message);
|
|
84
106
|
if (converted) {
|
|
85
107
|
messages.push(converted);
|
|
@@ -90,7 +112,7 @@ function toOpenAIMessages(conversation) {
|
|
|
90
112
|
function toOpenAIMessagesGrouped(conversation) {
|
|
91
113
|
const messages = [];
|
|
92
114
|
let pendingToolCalls = [];
|
|
93
|
-
for (const message of conversation
|
|
115
|
+
for (const message of getOrderedMessages(conversation)) {
|
|
94
116
|
if (message.hidden)
|
|
95
117
|
continue;
|
|
96
118
|
if (message.role === "tool-use" && message.toolCall) {
|
|
@@ -124,4 +146,4 @@ export {
|
|
|
124
146
|
toOpenAIMessages
|
|
125
147
|
};
|
|
126
148
|
|
|
127
|
-
//# debugId=
|
|
149
|
+
//# debugId=76C027000C92020164756E2164756E21
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/adapters/openai/index.ts"],
|
|
3
|
+
"sources": ["../../../src/utilities/message-store.ts", "../../../src/adapters/openai/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {
|
|
5
|
+
"import type { Conversation, Message } from '../types';\n\nexport function getOrderedMessages(conversation: Conversation): Message[] {\n const ordered: Message[] = [];\n for (const id of conversation.ids) {\n const message = conversation.messages[id];\n if (message) {\n ordered.push(message);\n }\n }\n return ordered;\n}\n\nexport function toIdRecord<T extends { id: string }>(\n items: readonly T[],\n): Record<string, T> {\n const record: Record<string, T> = {};\n for (const item of items) {\n record[item.id] = item;\n }\n return record;\n}\n",
|
|
6
|
+
"import type { MultiModalContent } from '@lasercat/homogenaize';\n\nimport type { Conversation, Message, ToolCall, ToolResult } from '../../types';\nimport { getOrderedMessages } from '../../utilities/message-store';\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 system message format for the Chat Completions API.\n */\nexport interface OpenAISystemMessage {\n role: 'system';\n content: string | OpenAITextContentPart[];\n name?: string;\n}\n\n/**\n * OpenAI user message format for the Chat Completions API.\n */\nexport interface OpenAIUserMessage {\n role: 'user';\n content: string | OpenAIContentPart[];\n name?: string;\n}\n\n/**\n * OpenAI assistant message format for the Chat Completions API.\n */\nexport interface OpenAIAssistantMessage {\n role: 'assistant';\n content: string | OpenAITextContentPart[] | null;\n name?: string;\n tool_calls?: OpenAIToolCall[];\n}\n\n/**\n * OpenAI tool message format for the Chat Completions API.\n */\nexport interface OpenAIToolMessage {\n role: 'tool';\n content: string | OpenAITextContentPart[];\n tool_call_id: string;\n}\n\n/**\n * OpenAI message format for the Chat Completions API.\n */\nexport type OpenAIMessage =\n | OpenAISystemMessage\n | OpenAIUserMessage\n | OpenAIAssistantMessage\n | OpenAIToolMessage;\n\n/**\n * Converts internal multi-modal content to OpenAI content parts format.\n */\nfunction toOpenAIContent(\n content: string | ReadonlyArray<MultiModalContent>,\n options: { allowImages: false },\n): string | OpenAITextContentPart[];\nfunction toOpenAIContent(\n content: string | ReadonlyArray<MultiModalContent>,\n options?: { allowImages?: true },\n): string | OpenAIContentPart[];\nfunction toOpenAIContent(\n content: string | ReadonlyArray<MultiModalContent>,\n options: { allowImages?: boolean } = {},\n): string | OpenAIContentPart[] | OpenAITextContentPart[] {\n if (typeof content === 'string') {\n return content;\n }\n\n const allowImages = options.allowImages ?? true;\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' && allowImages) {\n parts.push({\n type: 'image_url',\n image_url: { url: part.url ?? '' },\n });\n }\n }\n\n if (parts.length === 0) {\n return '';\n }\n\n if (parts.length === 1 && parts[0]?.type === 'text') {\n return parts[0].text;\n }\n\n return allowImages ? parts : (parts as OpenAITextContentPart[]);\n}\n\n/**\n * Converts internal multi-modal content to OpenAI text-only format.\n */\nfunction toOpenAITextContent(\n content: string | ReadonlyArray<MultiModalContent>,\n): string | OpenAITextContentPart[] {\n return toOpenAIContent(content, { allowImages: false });\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: toOpenAITextContent(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: toOpenAITextContent(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 getOrderedMessages(conversation)) {\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 getOrderedMessages(conversation)) {\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
|
],
|
|
7
|
-
"mappings": ";
|
|
8
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "76C027000C92020164756E2164756E21",
|
|
9
10
|
"names": []
|
|
10
11
|
}
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,uBAAuB,EAG5B,oBAAoB,EACrB,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAoB,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAIvF,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAgChC;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,YAAY,EAC1B,cAAc,CAAC,EAAE,cAAc,EAC/B,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,MAAM,CAqBR;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM,EACjB,kBAAkB,CAAC,EAAE,eAAe,GAAG,cAAc,EACrD,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CAmHd;AAED;;;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,CAwBd"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ConversationEnvironment } from '../environment';
|
|
2
|
-
import type { Conversation, MessageInput } from '../types';
|
|
2
|
+
import type { Conversation, JSONValue, MessageInput } from '../types';
|
|
3
3
|
/**
|
|
4
4
|
* Appends one or more messages to a conversation.
|
|
5
5
|
* Validates that tool results reference existing function calls.
|
|
@@ -13,13 +13,13 @@ export declare function appendMessages(conversation: Conversation, ...inputsAndE
|
|
|
13
13
|
/**
|
|
14
14
|
* Appends a user message to the conversation.
|
|
15
15
|
*/
|
|
16
|
-
export declare function appendUserMessage(conversation: Conversation, content: MessageInput['content'], metadata?: Record<string,
|
|
16
|
+
export declare function appendUserMessage(conversation: Conversation, content: MessageInput['content'], metadata?: Record<string, JSONValue>, environment?: Partial<ConversationEnvironment>): Conversation;
|
|
17
17
|
/**
|
|
18
18
|
* Appends an assistant message to the conversation.
|
|
19
19
|
*/
|
|
20
|
-
export declare function appendAssistantMessage(conversation: Conversation, content: MessageInput['content'], metadata?: Record<string,
|
|
20
|
+
export declare function appendAssistantMessage(conversation: Conversation, content: MessageInput['content'], metadata?: Record<string, JSONValue>, environment?: Partial<ConversationEnvironment>): Conversation;
|
|
21
21
|
/**
|
|
22
22
|
* Appends a system message to the conversation.
|
|
23
23
|
*/
|
|
24
|
-
export declare function appendSystemMessage(conversation: Conversation, content: string, metadata?: Record<string,
|
|
24
|
+
export declare function appendSystemMessage(conversation: Conversation, content: string, metadata?: Record<string, JSONValue>, environment?: Partial<ConversationEnvironment>): Conversation;
|
|
25
25
|
//# sourceMappingURL=append.d.ts.map
|
|
@@ -1 +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,
|
|
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,EAEV,YAAY,EACZ,SAAS,EAET,YAAY,EACb,MAAM,UAAU,CAAC;AAoClB;;;;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;AAwEhB;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,EAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EACpC,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,SAAS,CAAC,EACpC,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,SAAS,CAAC,EACpC,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CAEd"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ConversationEnvironment } from '../environment';
|
|
2
|
-
import type { Conversation, ConversationStatus } from '../types';
|
|
2
|
+
import type { Conversation, ConversationStatus, JSONValue } from '../types';
|
|
3
3
|
/**
|
|
4
4
|
* Creates a new empty conversation with the specified options.
|
|
5
5
|
* Returns an immutable conversation object with timestamps set to the current time.
|
|
@@ -8,7 +8,6 @@ export declare function createConversation(options?: {
|
|
|
8
8
|
id?: string;
|
|
9
9
|
title?: string;
|
|
10
10
|
status?: ConversationStatus;
|
|
11
|
-
metadata?: Record<string,
|
|
12
|
-
tags?: string[];
|
|
11
|
+
metadata?: Record<string, JSONValue>;
|
|
13
12
|
}, environment?: Partial<ConversationEnvironment>): Conversation;
|
|
14
13
|
//# sourceMappingURL=create.d.ts.map
|
|
@@ -1 +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;
|
|
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,SAAS,EAAE,MAAM,UAAU,CAAC;AAI5E;;;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,SAAS,CAAC,CAAC;CACtC,EACD,WAAW,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC7C,YAAY,CAed"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export type { ConversationEnvironment } from '../environment';
|
|
2
2
|
export { createConversation } from './create';
|
|
3
3
|
export { appendAssistantMessage, appendMessages, appendSystemMessage, appendUserMessage, } from './append';
|
|
4
|
-
export {
|
|
4
|
+
export { getMessageAtPosition, getMessageById, getMessageIds, getMessages, getStatistics, searchConversationMessages, } from './query';
|
|
5
5
|
export { collapseSystemMessages, getFirstSystemMessage, getSystemMessages, hasSystemMessage, prependSystemMessage, replaceSystemMessage, } from './system-messages';
|
|
6
6
|
export { redactMessageAtPosition } from './modify';
|
|
7
|
-
export { deserializeConversation,
|
|
7
|
+
export { deserializeConversation, migrateConversation } from './serialization';
|
|
8
8
|
export { toChatMessages } from './transform';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +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,
|
|
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,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,WAAW,EACX,aAAa,EACb,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,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAG/E,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -1 +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,
|
|
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,CAgCd"}
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import type { Conversation, Message } from '../types';
|
|
2
2
|
/**
|
|
3
|
-
* Returns all messages from a conversation.
|
|
3
|
+
* Returns all messages from a conversation in order.
|
|
4
4
|
* By default excludes hidden messages unless includeHidden is true.
|
|
5
5
|
*/
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function getMessages(conversation: Conversation, options?: {
|
|
7
7
|
includeHidden?: boolean;
|
|
8
|
-
}):
|
|
8
|
+
}): Message[];
|
|
9
9
|
/**
|
|
10
10
|
* Returns the message at the specified position index.
|
|
11
11
|
* Returns undefined if no message exists at that position.
|
|
12
12
|
*/
|
|
13
13
|
export declare function getMessageAtPosition(conversation: Conversation, position: number): Message | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Returns all message IDs for the conversation in order.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getMessageIds(conversation: Conversation): string[];
|
|
14
18
|
/**
|
|
15
19
|
* Finds a message by its unique identifier.
|
|
16
20
|
* Returns undefined if no message with that ID exists.
|
|
17
21
|
*/
|
|
18
|
-
export declare function
|
|
22
|
+
export declare function getMessageById(conversation: Conversation, id: string): Message | undefined;
|
|
19
23
|
/**
|
|
20
24
|
* Filters messages using a custom predicate function.
|
|
21
25
|
* Returns all messages for which the predicate returns true.
|
|
@@ -25,7 +29,7 @@ export declare function searchConversationMessages(conversation: Conversation, p
|
|
|
25
29
|
* Computes statistics about a conversation's messages.
|
|
26
30
|
* Returns totals, counts by role, hidden message count, and image count.
|
|
27
31
|
*/
|
|
28
|
-
export declare function
|
|
32
|
+
export declare function getStatistics(conversation: Conversation): {
|
|
29
33
|
total: number;
|
|
30
34
|
byRole: Record<string, number>;
|
|
31
35
|
hidden: number;
|
|
@@ -1 +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;
|
|
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;AAItD;;;GAGG;AACH,wBAAgB,WAAW,CACzB,YAAY,EAAE,YAAY,EAC1B,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC,OAAO,EAAE,CAIX;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,GACf,OAAO,GAAG,SAAS,CAGrB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,EAAE,CAElE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,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,aAAa,CAAC,YAAY,EAAE,YAAY,GAAG;IACzD,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,CAkBA"}
|