conversationalist 0.0.10 → 0.0.11
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 +89 -15
- package/dist/adapters/anthropic/index.d.ts.map +1 -1
- package/dist/adapters/anthropic/index.js +255 -2
- package/dist/adapters/anthropic/index.js.map +8 -4
- package/dist/adapters/gemini/index.d.ts.map +1 -1
- package/dist/adapters/gemini/index.js +255 -3
- package/dist/adapters/gemini/index.js.map +8 -4
- package/dist/adapters/openai/index.d.ts.map +1 -1
- package/dist/adapters/openai/index.js +247 -3
- package/dist/adapters/openai/index.js.map +8 -4
- package/dist/context.d.ts +6 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/conversation/append.d.ts +5 -0
- package/dist/conversation/append.d.ts.map +1 -1
- package/dist/conversation/create.d.ts +9 -0
- package/dist/conversation/create.d.ts.map +1 -1
- package/dist/conversation/index.d.ts +8 -3
- package/dist/conversation/index.d.ts.map +1 -1
- package/dist/conversation/integrity.d.ts +16 -0
- package/dist/conversation/integrity.d.ts.map +1 -0
- package/dist/conversation/modify.d.ts +8 -2
- package/dist/conversation/modify.d.ts.map +1 -1
- package/dist/conversation/serialization.d.ts +0 -17
- package/dist/conversation/serialization.d.ts.map +1 -1
- package/dist/conversation/system-messages.d.ts.map +1 -1
- package/dist/conversation/tool-interactions.d.ts +45 -0
- package/dist/conversation/tool-interactions.d.ts.map +1 -0
- package/dist/conversation/transform.d.ts.map +1 -1
- package/dist/conversation/validation.d.ts +8 -0
- package/dist/conversation/validation.d.ts.map +1 -0
- package/dist/errors.d.ts +6 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/export/index.js +249 -12
- package/dist/export/index.js.map +10 -6
- package/dist/history.d.ts +4 -1
- package/dist/history.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +604 -231
- package/dist/index.js.map +24 -13
- package/dist/markdown/index.js +595 -215
- package/dist/markdown/index.js.map +22 -12
- package/dist/schemas/index.js +35 -19
- package/dist/schemas/index.js.map +3 -3
- package/dist/schemas.d.ts +15 -35
- package/dist/schemas.d.ts.map +1 -1
- package/dist/streaming.d.ts.map +1 -1
- package/dist/types.d.ts +0 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/utilities/index.d.ts +0 -1
- package/dist/utilities/index.d.ts.map +1 -1
- package/dist/utilities/markdown.d.ts.map +1 -1
- package/dist/utilities/tool-calls.d.ts +2 -6
- package/dist/utilities/tool-calls.d.ts.map +1 -1
- package/dist/utilities/tool-results.d.ts.map +1 -1
- package/dist/utilities/transient.d.ts.map +1 -1
- package/dist/utilities.d.ts +0 -1
- package/dist/utilities.d.ts.map +1 -1
- package/dist/versioning/index.d.ts +0 -1
- package/dist/versioning/index.d.ts.map +1 -1
- package/dist/versioning/index.js +1 -52
- package/dist/versioning/index.js.map +4 -5
- package/dist/with-conversation.d.ts +4 -1
- package/dist/with-conversation.d.ts.map +1 -1
- package/package.json +6 -4
- package/dist/conversation.d.ts +0 -109
- package/dist/conversation.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -148,6 +148,72 @@ conversation = appendMessages(
|
|
|
148
148
|
);
|
|
149
149
|
```
|
|
150
150
|
|
|
151
|
+
Tool payloads are typed as `JSONValue` to keep conversations JSON-serializable.
|
|
152
|
+
|
|
153
|
+
You can also use tool-specific helpers to reduce agent-loop glue code:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import {
|
|
157
|
+
appendToolResult,
|
|
158
|
+
appendToolUse,
|
|
159
|
+
getPendingToolCalls,
|
|
160
|
+
getToolInteractions,
|
|
161
|
+
} from 'conversationalist';
|
|
162
|
+
|
|
163
|
+
conversation = appendToolUse(conversation, {
|
|
164
|
+
toolId: 'getWeather',
|
|
165
|
+
callId: 'call_123',
|
|
166
|
+
args: { city: 'NYC' },
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
conversation = appendToolResult(conversation, {
|
|
170
|
+
callId: 'call_123',
|
|
171
|
+
outcome: 'success',
|
|
172
|
+
result: { tempF: 72, condition: 'sunny' },
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const pending = getPendingToolCalls(conversation);
|
|
176
|
+
const interactions = getToolInteractions(conversation);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Correctness Guarantees
|
|
180
|
+
|
|
181
|
+
Conversationalist treats integrity and JSON-safety as first-class invariants:
|
|
182
|
+
|
|
183
|
+
- `conversation.ids` and `conversation.messages` stay in sync.
|
|
184
|
+
- Every `tool-result` references an earlier `tool-use`.
|
|
185
|
+
- `toolCall.id` values are unique per conversation.
|
|
186
|
+
- Conversation payloads are JSON-serializable (`JSONValue` everywhere).
|
|
187
|
+
|
|
188
|
+
`validateConversationIntegrity`/`assertConversationIntegrity` are the canonical integrity
|
|
189
|
+
checks and are used internally at public boundaries (adapters, markdown import,
|
|
190
|
+
deserialization, truncation, redaction).
|
|
191
|
+
|
|
192
|
+
Safe APIs (default) validate schema + integrity and throw on failure. Unsafe escape hatches
|
|
193
|
+
skip validation and require manual checks:
|
|
194
|
+
|
|
195
|
+
- `createConversationUnsafe`
|
|
196
|
+
- `appendUnsafeMessage`
|
|
197
|
+
|
|
198
|
+
Schema validation is strict; unknown fields are rejected. Use `metadata` for extensions.
|
|
199
|
+
|
|
200
|
+
For custom transforms, validate the shape and then re-assert integrity:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
import {
|
|
204
|
+
assertConversationIntegrity,
|
|
205
|
+
validateConversationIntegrity,
|
|
206
|
+
conversationSchema,
|
|
207
|
+
} from 'conversationalist';
|
|
208
|
+
|
|
209
|
+
const issues = validateConversationIntegrity(conversation);
|
|
210
|
+
// issues: IntegrityIssue[]
|
|
211
|
+
|
|
212
|
+
assertConversationIntegrity(conversation);
|
|
213
|
+
|
|
214
|
+
conversationSchema.parse(conversation);
|
|
215
|
+
```
|
|
216
|
+
|
|
151
217
|
### Streaming
|
|
152
218
|
|
|
153
219
|
Streaming helpers let you append a placeholder, update it as chunks arrive, and finalize
|
|
@@ -183,9 +249,18 @@ import { simpleTokenEstimator, truncateToTokenLimit } from 'conversationalist';
|
|
|
183
249
|
conversation = truncateToTokenLimit(conversation, 4000, {
|
|
184
250
|
preserveSystemMessages: true,
|
|
185
251
|
preserveLastN: 2,
|
|
252
|
+
preserveToolPairs: true, // default
|
|
186
253
|
});
|
|
187
254
|
```
|
|
188
255
|
|
|
256
|
+
By default, truncation and recent-message helpers treat a `tool-use` + `tool-result`
|
|
257
|
+
as an atomic block (`preserveToolPairs: true`) so tool results are never stranded.
|
|
258
|
+
If a tool block doesn't fit inside the budget, both messages are dropped. Set
|
|
259
|
+
`preserveToolPairs: false` to revert to message-level truncation. When disabled,
|
|
260
|
+
truncation can strand tool results; Conversationalist throws an integrity error
|
|
261
|
+
instead of returning invalid history. For agent loops, keep
|
|
262
|
+
`preserveToolPairs: true` to preserve tool interactions.
|
|
263
|
+
|
|
189
264
|
#### Custom Token Counters
|
|
190
265
|
|
|
191
266
|
You can provide a custom token estimator (e.g. using `tiktoken` or `anthropic-tokenizer`) by passing it in the options or by binding it to your environment.
|
|
@@ -605,26 +680,22 @@ const restoredWithEnv = ConversationHistory.from(snapshot, {
|
|
|
605
680
|
|
|
606
681
|
### Schema Versioning
|
|
607
682
|
|
|
608
|
-
Conversations include a `schemaVersion` field for forward compatibility.
|
|
683
|
+
Conversations include a `schemaVersion` field for forward compatibility. Deserialization expects the current schema version; migrate legacy data before calling `deserializeConversation`.
|
|
609
684
|
|
|
610
685
|
```ts
|
|
611
686
|
import { deserializeConversation } from 'conversationalist';
|
|
612
|
-
import {
|
|
613
|
-
migrateConversation,
|
|
614
|
-
CURRENT_SCHEMA_VERSION,
|
|
615
|
-
} from 'conversationalist/versioning';
|
|
687
|
+
import { CURRENT_SCHEMA_VERSION } from 'conversationalist/versioning';
|
|
616
688
|
|
|
617
|
-
|
|
618
|
-
const legacyData = JSON.parse(oldStorage);
|
|
619
|
-
const migrated = migrateConversation(legacyData);
|
|
620
|
-
// migrated.schemaVersion === CURRENT_SCHEMA_VERSION
|
|
621
|
-
|
|
622
|
-
const conversation = deserializeConversation(migrated);
|
|
689
|
+
const conversation = deserializeConversation(JSON.parse(storage));
|
|
623
690
|
```
|
|
624
691
|
|
|
625
692
|
Conversations are already JSON-serializable; persist them directly and apply utilities
|
|
626
693
|
like `stripTransientMetadata` or `redactMessageAtPosition` when you need to sanitize data.
|
|
627
694
|
|
|
695
|
+
`redactMessageAtPosition` preserves tool linkage by default (call IDs and outcomes stay intact),
|
|
696
|
+
and supports `redactToolArguments`, `redactToolResults`, or `clearToolMetadata` for stricter
|
|
697
|
+
scrubbing.
|
|
698
|
+
|
|
628
699
|
### Transient Metadata Convention
|
|
629
700
|
|
|
630
701
|
Keys prefixed with `_` are considered transient—temporary UI state that shouldn't be persisted:
|
|
@@ -909,12 +980,15 @@ Svelte 5's runes pair perfectly with **Conversationalist**. You can use the `Con
|
|
|
909
980
|
| Category | Key Functions |
|
|
910
981
|
| :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
911
982
|
| **Creation** | `createConversation`, `deserializeConversation` |
|
|
912
|
-
| **Appending** | `appendUserMessage`, `appendAssistantMessage`, `appendSystemMessage`, `appendMessages`
|
|
983
|
+
| **Appending** | `appendUserMessage`, `appendAssistantMessage`, `appendSystemMessage`, `appendToolUse`, `appendToolResult`, `appendMessages` |
|
|
984
|
+
| **Unsafe** | `createConversationUnsafe`, `appendUnsafeMessage` |
|
|
913
985
|
| **Streaming** | `appendStreamingMessage`, `updateStreamingMessage`, `finalizeStreamingMessage`, `cancelStreamingMessage` |
|
|
914
986
|
| **Modification** | `redactMessageAtPosition`, `replaceSystemMessage`, `collapseSystemMessages` |
|
|
915
|
-
| **Context** | `truncateToTokenLimit`, `getRecentMessages`, `estimateConversationTokens`
|
|
987
|
+
| **Context** | `truncateToTokenLimit`, `truncateFromPosition`, `getRecentMessages`, `estimateConversationTokens` |
|
|
916
988
|
| **Querying** | `getMessages`, `getMessageIds`, `getMessageById`, `getStatistics` |
|
|
917
|
-
| **Conversion** | `toChatMessages
|
|
989
|
+
| **Conversion** | `toChatMessages` |
|
|
990
|
+
| **Tooling** | `getPendingToolCalls`, `getToolInteractions`, `pairToolCallsWithResults` |
|
|
991
|
+
| **Integrity** | `validateConversationIntegrity`, `assertConversationIntegrity` |
|
|
918
992
|
| **Markdown** | `toMarkdown`, `fromMarkdown`, `conversationHistoryToMarkdown`, `conversationHistoryFromMarkdown` (from `conversationalist/markdown`) |
|
|
919
993
|
| **Export** | `exportMarkdown`, `normalizeLineEndings` (from `conversationalist/export`) |
|
|
920
994
|
| **Schemas** | `conversationSchema`, `messageSchema`, `messageInputSchema`, `messageRoleSchema`, `multiModalContentSchema`, `jsonValueSchema`, `toolCallSchema`, `toolResultSchema`, `tokenUsageSchema` (from `conversationalist/schemas`) |
|
|
@@ -922,7 +996,7 @@ Svelte 5's runes pair perfectly with **Conversationalist**. You can use the `Con
|
|
|
922
996
|
| **Role Labels** | `ROLE_LABELS`, `LABEL_TO_ROLE`, `getRoleLabel`, `getRoleFromLabel` (from `conversationalist/markdown`) |
|
|
923
997
|
| **Transient** | `isTransientKey`, `stripTransientFromRecord`, `stripTransientMetadata` |
|
|
924
998
|
| **Redaction** | `redactPii`, `createPIIRedactionPlugin`, `createPIIRedaction`, `DEFAULT_PII_RULES` (from `conversationalist/redaction`) |
|
|
925
|
-
| **Versioning** | `
|
|
999
|
+
| **Versioning** | `CURRENT_SCHEMA_VERSION` (from `conversationalist/versioning`) |
|
|
926
1000
|
| **Sort** | `sortObjectKeys`, `sortMessagesByPosition` (from `conversationalist/sort`) |
|
|
927
1001
|
| **History** | `ConversationHistory` |
|
|
928
1002
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/anthropic/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/anthropic/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAiC,MAAM,aAAa,CAAC;AAG/E;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,oBAAoB,GAAG,0BAA0B,GAAG,uBAAuB,CAAC;AAExF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC7B,kBAAkB,GAClB,mBAAmB,GACnB,qBAAqB,GACrB,wBAAwB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAAC;CAC3C;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAoHD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,YAAY,GAAG,qBAAqB,CAmFrF"}
|
|
@@ -1,3 +1,247 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
class ConversationalistError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
context;
|
|
5
|
+
cause;
|
|
6
|
+
constructor(code, message, options) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "ConversationalistError";
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.context = options?.context;
|
|
11
|
+
this.cause = options?.cause;
|
|
12
|
+
if (Error.captureStackTrace) {
|
|
13
|
+
Error.captureStackTrace(this, ConversationalistError);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
toDetailedString() {
|
|
17
|
+
const parts = [`[${this.code}] ${this.message}`];
|
|
18
|
+
if (this.context && Object.keys(this.context).length > 0) {
|
|
19
|
+
parts.push(`Context: ${JSON.stringify(this.context, null, 2)}`);
|
|
20
|
+
}
|
|
21
|
+
if (this.cause) {
|
|
22
|
+
parts.push(`Caused by: ${this.cause.message}`);
|
|
23
|
+
}
|
|
24
|
+
return parts.join(`
|
|
25
|
+
`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function createValidationError(message, context, cause) {
|
|
29
|
+
return new ConversationalistError("error:validation", message, { context, cause });
|
|
30
|
+
}
|
|
31
|
+
function createIntegrityError(message, context) {
|
|
32
|
+
return new ConversationalistError("error:integrity", message, { context });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/schemas.ts
|
|
36
|
+
import { z } from "zod";
|
|
37
|
+
var isPlainObject = (value) => {
|
|
38
|
+
if (!value || typeof value !== "object")
|
|
39
|
+
return false;
|
|
40
|
+
const prototype = Reflect.getPrototypeOf(value);
|
|
41
|
+
return prototype === Object.prototype || prototype === null;
|
|
42
|
+
};
|
|
43
|
+
function toMultiModalContent(value) {
|
|
44
|
+
const result = { type: value.type };
|
|
45
|
+
if (value.text !== undefined)
|
|
46
|
+
result.text = value.text;
|
|
47
|
+
if (value.url !== undefined)
|
|
48
|
+
result.url = value.url;
|
|
49
|
+
if (value.mimeType !== undefined)
|
|
50
|
+
result.mimeType = value.mimeType;
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
var jsonValueSchema = z.lazy(() => {
|
|
54
|
+
const jsonObjectSchema = z.preprocess((value, ctx) => {
|
|
55
|
+
if (!isPlainObject(value)) {
|
|
56
|
+
ctx.addIssue({
|
|
57
|
+
code: z.ZodIssueCode.custom,
|
|
58
|
+
message: "expected a plain object"
|
|
59
|
+
});
|
|
60
|
+
return z.NEVER;
|
|
61
|
+
}
|
|
62
|
+
return value;
|
|
63
|
+
}, z.record(z.string(), jsonValueSchema));
|
|
64
|
+
return z.union([
|
|
65
|
+
z.string(),
|
|
66
|
+
z.number().refine((value) => Number.isFinite(value), {
|
|
67
|
+
message: "expected a finite number"
|
|
68
|
+
}),
|
|
69
|
+
z.boolean(),
|
|
70
|
+
z.null(),
|
|
71
|
+
z.array(jsonValueSchema),
|
|
72
|
+
jsonObjectSchema
|
|
73
|
+
]);
|
|
74
|
+
});
|
|
75
|
+
var multiModalContentSchema = z.discriminatedUnion("type", [
|
|
76
|
+
z.object({
|
|
77
|
+
type: z.literal("text"),
|
|
78
|
+
text: z.string()
|
|
79
|
+
}),
|
|
80
|
+
z.object({
|
|
81
|
+
type: z.literal("image"),
|
|
82
|
+
url: z.string().url(),
|
|
83
|
+
mimeType: z.string().optional(),
|
|
84
|
+
text: z.string().optional()
|
|
85
|
+
})
|
|
86
|
+
]).transform(toMultiModalContent);
|
|
87
|
+
var messageRoleSchema = z.enum([
|
|
88
|
+
"user",
|
|
89
|
+
"assistant",
|
|
90
|
+
"system",
|
|
91
|
+
"developer",
|
|
92
|
+
"tool-use",
|
|
93
|
+
"tool-result",
|
|
94
|
+
"snapshot"
|
|
95
|
+
]);
|
|
96
|
+
var toolCallSchema = z.object({
|
|
97
|
+
id: z.string(),
|
|
98
|
+
name: z.string(),
|
|
99
|
+
arguments: jsonValueSchema
|
|
100
|
+
}).strict();
|
|
101
|
+
var toolResultSchema = z.object({
|
|
102
|
+
callId: z.string(),
|
|
103
|
+
outcome: z.enum(["success", "error"]),
|
|
104
|
+
content: jsonValueSchema
|
|
105
|
+
}).strict();
|
|
106
|
+
var tokenUsageSchema = z.object({
|
|
107
|
+
prompt: z.number().int().min(0),
|
|
108
|
+
completion: z.number().int().min(0),
|
|
109
|
+
total: z.number().int().min(0)
|
|
110
|
+
});
|
|
111
|
+
var messageInputSchema = z.object({
|
|
112
|
+
role: messageRoleSchema,
|
|
113
|
+
content: z.union([z.string(), z.array(multiModalContentSchema)]),
|
|
114
|
+
metadata: z.record(z.string(), jsonValueSchema).optional(),
|
|
115
|
+
hidden: z.boolean().optional(),
|
|
116
|
+
toolCall: toolCallSchema.optional(),
|
|
117
|
+
toolResult: toolResultSchema.optional(),
|
|
118
|
+
tokenUsage: tokenUsageSchema.optional(),
|
|
119
|
+
goalCompleted: z.boolean().optional()
|
|
120
|
+
}).strict();
|
|
121
|
+
var messageSchema = z.object({
|
|
122
|
+
id: z.string(),
|
|
123
|
+
role: messageRoleSchema,
|
|
124
|
+
content: z.union([z.string(), z.array(multiModalContentSchema)]),
|
|
125
|
+
position: z.number().int().min(0),
|
|
126
|
+
createdAt: z.string(),
|
|
127
|
+
metadata: z.record(z.string(), jsonValueSchema),
|
|
128
|
+
hidden: z.boolean(),
|
|
129
|
+
toolCall: toolCallSchema.optional(),
|
|
130
|
+
toolResult: toolResultSchema.optional(),
|
|
131
|
+
tokenUsage: tokenUsageSchema.optional(),
|
|
132
|
+
goalCompleted: z.boolean().optional()
|
|
133
|
+
}).strict();
|
|
134
|
+
var conversationStatusSchema = z.enum([
|
|
135
|
+
"active",
|
|
136
|
+
"archived",
|
|
137
|
+
"deleted"
|
|
138
|
+
]);
|
|
139
|
+
var conversationShape = {
|
|
140
|
+
schemaVersion: z.number().int().min(1),
|
|
141
|
+
id: z.string(),
|
|
142
|
+
title: z.string().optional(),
|
|
143
|
+
status: conversationStatusSchema,
|
|
144
|
+
metadata: z.record(z.string(), jsonValueSchema),
|
|
145
|
+
ids: z.array(z.string()),
|
|
146
|
+
messages: z.record(z.string(), messageSchema),
|
|
147
|
+
createdAt: z.string(),
|
|
148
|
+
updatedAt: z.string()
|
|
149
|
+
};
|
|
150
|
+
var conversationSchema = z.object(conversationShape).strict();
|
|
151
|
+
|
|
152
|
+
// src/conversation/integrity.ts
|
|
153
|
+
function validateConversationIntegrity(conversation) {
|
|
154
|
+
const issues = [];
|
|
155
|
+
const seenIds = new Set;
|
|
156
|
+
conversation.ids.forEach((id, index) => {
|
|
157
|
+
if (seenIds.has(id)) {
|
|
158
|
+
issues.push({
|
|
159
|
+
code: "integrity:duplicate-message-id",
|
|
160
|
+
message: `duplicate message id in ids: ${id}`,
|
|
161
|
+
data: { id, position: index }
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
seenIds.add(id);
|
|
165
|
+
}
|
|
166
|
+
if (!conversation.messages[id]) {
|
|
167
|
+
issues.push({
|
|
168
|
+
code: "integrity:missing-message",
|
|
169
|
+
message: `missing message for id ${id}`,
|
|
170
|
+
data: { id, position: index }
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
for (const id of Object.keys(conversation.messages)) {
|
|
175
|
+
if (!seenIds.has(id)) {
|
|
176
|
+
issues.push({
|
|
177
|
+
code: "integrity:unlisted-message",
|
|
178
|
+
message: `message ${id} is not listed in ids`,
|
|
179
|
+
data: { id }
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const toolUses = new Map;
|
|
184
|
+
conversation.ids.forEach((id, index) => {
|
|
185
|
+
const message = conversation.messages[id];
|
|
186
|
+
if (!message)
|
|
187
|
+
return;
|
|
188
|
+
if (message.role === "tool-use" && message.toolCall) {
|
|
189
|
+
if (toolUses.has(message.toolCall.id)) {
|
|
190
|
+
issues.push({
|
|
191
|
+
code: "integrity:duplicate-tool-call",
|
|
192
|
+
message: `duplicate toolCall.id ${message.toolCall.id}`,
|
|
193
|
+
data: { toolCallId: message.toolCall.id, messageId: message.id }
|
|
194
|
+
});
|
|
195
|
+
} else {
|
|
196
|
+
toolUses.set(message.toolCall.id, { position: index, messageId: message.id });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
conversation.ids.forEach((id, index) => {
|
|
201
|
+
const message = conversation.messages[id];
|
|
202
|
+
if (!message)
|
|
203
|
+
return;
|
|
204
|
+
if (message.role === "tool-result" && message.toolResult) {
|
|
205
|
+
const toolUse = toolUses.get(message.toolResult.callId);
|
|
206
|
+
if (!toolUse) {
|
|
207
|
+
issues.push({
|
|
208
|
+
code: "integrity:orphan-tool-result",
|
|
209
|
+
message: `tool-result references missing tool-use ${message.toolResult.callId}`,
|
|
210
|
+
data: { callId: message.toolResult.callId, messageId: message.id }
|
|
211
|
+
});
|
|
212
|
+
} else if (toolUse.position >= index) {
|
|
213
|
+
issues.push({
|
|
214
|
+
code: "integrity:tool-result-before-call",
|
|
215
|
+
message: `tool-result ${message.toolResult.callId} occurs before tool-use`,
|
|
216
|
+
data: {
|
|
217
|
+
callId: message.toolResult.callId,
|
|
218
|
+
messageId: message.id,
|
|
219
|
+
toolUseMessageId: toolUse.messageId
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
return issues;
|
|
226
|
+
}
|
|
227
|
+
function assertConversationIntegrity(conversation) {
|
|
228
|
+
const issues = validateConversationIntegrity(conversation);
|
|
229
|
+
if (issues.length === 0)
|
|
230
|
+
return;
|
|
231
|
+
throw createIntegrityError("conversation integrity check failed", { issues });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// src/conversation/validation.ts
|
|
235
|
+
function assertConversationSafe(conversation) {
|
|
236
|
+
const parsed = conversationSchema.safeParse(conversation);
|
|
237
|
+
if (!parsed.success) {
|
|
238
|
+
throw createValidationError("conversation failed schema validation", {
|
|
239
|
+
issues: parsed.error.issues
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
assertConversationIntegrity(conversation);
|
|
243
|
+
}
|
|
244
|
+
|
|
1
245
|
// src/utilities/message-store.ts
|
|
2
246
|
function getOrderedMessages(conversation) {
|
|
3
247
|
const ordered = [];
|
|
@@ -47,11 +291,19 @@ function toAnthropicContent(content) {
|
|
|
47
291
|
return blocks.length === 1 && blocks[0]?.type === "text" ? blocks[0].text : blocks;
|
|
48
292
|
}
|
|
49
293
|
function toToolUseBlock(toolCall) {
|
|
294
|
+
let input = toolCall.arguments;
|
|
295
|
+
if (typeof toolCall.arguments === "string") {
|
|
296
|
+
try {
|
|
297
|
+
input = JSON.parse(toolCall.arguments);
|
|
298
|
+
} catch {
|
|
299
|
+
input = toolCall.arguments;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
50
302
|
return {
|
|
51
303
|
type: "tool_use",
|
|
52
304
|
id: toolCall.id,
|
|
53
305
|
name: toolCall.name,
|
|
54
|
-
input
|
|
306
|
+
input
|
|
55
307
|
};
|
|
56
308
|
}
|
|
57
309
|
function toToolResultBlock(toolResult) {
|
|
@@ -87,6 +339,7 @@ function extractSystemContent(messages) {
|
|
|
87
339
|
`);
|
|
88
340
|
}
|
|
89
341
|
function toAnthropicMessages(conversation) {
|
|
342
|
+
assertConversationSafe(conversation);
|
|
90
343
|
const ordered = getOrderedMessages(conversation);
|
|
91
344
|
const system = extractSystemContent(ordered);
|
|
92
345
|
const messages = [];
|
|
@@ -157,4 +410,4 @@ export {
|
|
|
157
410
|
toAnthropicMessages
|
|
158
411
|
};
|
|
159
412
|
|
|
160
|
-
//# debugId=
|
|
413
|
+
//# debugId=FA4FB5174F303A6B64756E2164756E21
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../../src/utilities/message-store.ts", "../../../src/adapters/anthropic/index.ts"],
|
|
3
|
+
"sources": ["../../../src/errors.ts", "../../../src/schemas.ts", "../../../src/conversation/integrity.ts", "../../../src/conversation/validation.ts", "../../../src/utilities/message-store.ts", "../../../src/adapters/anthropic/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
+
"/**\n * Error codes for Conversationalist errors (kebab-case with `error:` prefix).\n */\nexport type ConversationalistErrorCode =\n | 'error:locked'\n | 'error:invalid-input'\n | 'error:invalid-position'\n | 'error:invalid-tool-reference'\n | 'error:duplicate-id'\n | 'error:not-found'\n | 'error:serialization'\n | 'error:validation'\n | 'error:integrity';\n\n/**\n * Base error class for all Conversationalist errors.\n *\n * Provides structured error information with error codes, context data,\n * and cause chains for better debugging.\n */\nexport class ConversationalistError extends Error {\n /** Structured error code */\n readonly code: ConversationalistErrorCode;\n\n /** Additional context data */\n readonly context?: Record<string, unknown> | undefined;\n\n /** Underlying cause (if any) */\n override readonly cause?: Error | undefined;\n\n constructor(\n code: ConversationalistErrorCode,\n message: string,\n options?: {\n context?: Record<string, unknown> | undefined;\n cause?: Error | undefined;\n },\n ) {\n super(message);\n this.name = 'ConversationalistError';\n this.code = code;\n this.context = options?.context;\n this.cause = options?.cause;\n\n // Maintain proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ConversationalistError);\n }\n }\n\n /**\n * Formats the error as a detailed string with code and context.\n */\n toDetailedString(): string {\n const parts = [`[${this.code}] ${this.message}`];\n\n if (this.context && Object.keys(this.context).length > 0) {\n parts.push(`Context: ${JSON.stringify(this.context, null, 2)}`);\n }\n\n if (this.cause) {\n parts.push(`Caused by: ${this.cause.message}`);\n }\n\n return parts.join('\\n');\n }\n}\n\n/**\n * Creates a lock error (ERR_LOCKED).\n * Thrown when a conversation is already being modified.\n */\nexport function createLockedError(conversationId: string): ConversationalistError {\n return new ConversationalistError(\n 'error:locked',\n `conversation ${conversationId} is locked (concurrent modification detected)`,\n { context: { conversationId } },\n );\n}\n\n/**\n * Creates an invalid input error (ERR_INVALID_INPUT).\n * Thrown when message input data is invalid.\n */\nexport function createInvalidInputError(\n message: string,\n context?: Record<string, unknown>,\n): ConversationalistError {\n return new ConversationalistError('error:invalid-input', message, { context });\n}\n\n/**\n * Creates an invalid position error (ERR_INVALID_POSITION).\n * Thrown when positions are non-contiguous or invalid.\n */\nexport function createInvalidPositionError(\n expected: number,\n actual: number,\n): ConversationalistError {\n return new ConversationalistError(\n 'error:invalid-position',\n `invalid position: expected ${expected}, got ${actual}`,\n { context: { expected, actual } },\n );\n}\n\n/**\n * Creates an invalid tool reference error (ERR_INVALID_TOOL_REFERENCE).\n * Thrown when a tool result references a non-existent tool-use message.\n */\nexport function createInvalidToolReferenceError(callId: string): ConversationalistError {\n return new ConversationalistError(\n 'error:invalid-tool-reference',\n `tool result references non-existent tool-use: ${callId}`,\n { context: { callId } },\n );\n}\n\n/**\n * Creates a duplicate ID error (ERR_DUPLICATE_ID).\n * Thrown when a conversation with the given ID already exists.\n */\nexport function createDuplicateIdError(id: string): ConversationalistError {\n return new ConversationalistError(\n 'error:duplicate-id',\n `conversation with id ${id} already exists`,\n { context: { id } },\n );\n}\n\n/**\n * Creates a not found error (ERR_NOT_FOUND).\n * Thrown when a conversation cannot be found.\n */\nexport function createNotFoundError(id: string): ConversationalistError {\n return new ConversationalistError(\n 'error:not-found',\n `conversation with id ${id} not found`,\n {\n context: { id },\n },\n );\n}\n\n/**\n * Creates a serialization error (ERR_SERIALIZATION).\n * Thrown when JSON serialization/deserialization fails.\n */\nexport function createSerializationError(\n message: string,\n cause?: Error,\n): ConversationalistError {\n return new ConversationalistError('error:serialization', message, { cause });\n}\n\n/**\n * Creates a validation error (ERR_VALIDATION).\n * Thrown when data validation fails (e.g., Zod schema validation).\n */\nexport function createValidationError(\n message: string,\n context?: Record<string, unknown>,\n cause?: Error,\n): ConversationalistError {\n return new ConversationalistError('error:validation', message, { context, cause });\n}\n\n/**\n * Creates an integrity error (ERR_INTEGRITY).\n * Thrown when conversation invariants are violated.\n */\nexport function createIntegrityError(\n message: string,\n context?: Record<string, unknown>,\n): ConversationalistError {\n return new ConversationalistError('error:integrity', message, { context });\n}\n",
|
|
6
|
+
"import type { MultiModalContent } from '@lasercat/homogenaize';\nimport { z } from 'zod';\n\nimport type {\n Conversation,\n ConversationStatus,\n JSONValue,\n Message,\n MessageInput,\n MessageRole,\n TokenUsage,\n ToolCall,\n ToolResult,\n} from './types';\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (!value || typeof value !== 'object') return false;\n const prototype = Reflect.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\ntype RawMultiModalContent = {\n type: 'text' | 'image';\n text?: string | undefined;\n url?: string | undefined;\n mimeType?: string | undefined;\n};\n\nfunction toMultiModalContent(value: RawMultiModalContent): MultiModalContent {\n const result: MultiModalContent = { type: value.type };\n if (value.text !== undefined) result.text = value.text;\n if (value.url !== undefined) result.url = value.url;\n if (value.mimeType !== undefined) result.mimeType = value.mimeType;\n return result;\n}\n\n/**\n * Zod schema for JSON-serializable values.\n */\nexport const jsonValueSchema: z.ZodType<JSONValue> = z.lazy(() => {\n const jsonObjectSchema = z.preprocess(\n (value, ctx) => {\n if (!isPlainObject(value)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'expected a plain object',\n });\n return z.NEVER;\n }\n return value;\n },\n z.record(z.string(), jsonValueSchema),\n );\n\n return z.union([\n z.string(),\n z.number().refine((value) => Number.isFinite(value), {\n message: 'expected a finite number',\n }),\n z.boolean(),\n z.null(),\n z.array(jsonValueSchema),\n jsonObjectSchema,\n ]);\n}) satisfies z.ZodType<JSONValue>;\n\n/**\n * Zod schema for multi-modal content parts (text or image).\n */\nexport const multiModalContentSchema = z\n .discriminatedUnion('type', [\n z.object({\n type: z.literal('text'),\n text: z.string(),\n }),\n z.object({\n type: z.literal('image'),\n url: z.string().url(),\n mimeType: z.string().optional(),\n text: z.string().optional(),\n }),\n ])\n .transform(toMultiModalContent) satisfies z.ZodType<MultiModalContent>;\n\n/**\n * Zod schema for valid message roles.\n */\nexport const messageRoleSchema = z.enum([\n 'user',\n 'assistant',\n 'system',\n 'developer',\n 'tool-use',\n 'tool-result',\n 'snapshot',\n]) satisfies z.ZodType<MessageRole>;\n\n/**\n * Zod schema for tool call metadata.\n */\nexport const toolCallSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n arguments: jsonValueSchema,\n })\n .strict() satisfies z.ZodType<ToolCall>;\n\n/**\n * Zod schema for tool result metadata.\n */\nexport const toolResultSchema = z\n .object({\n callId: z.string(),\n outcome: z.enum(['success', 'error']),\n content: jsonValueSchema,\n })\n .strict() satisfies z.ZodType<ToolResult>;\n\n/**\n * Zod schema for token usage accounting.\n */\nexport const tokenUsageSchema = z.object({\n prompt: z.number().int().min(0),\n completion: z.number().int().min(0),\n total: z.number().int().min(0),\n}) satisfies z.ZodType<TokenUsage>;\n\n/**\n * Zod schema for message input payloads.\n */\nexport const messageInputSchema = z\n .object({\n role: messageRoleSchema,\n content: z.union([z.string(), z.array(multiModalContentSchema)]),\n metadata: z.record(z.string(), jsonValueSchema).optional(),\n hidden: z.boolean().optional(),\n toolCall: toolCallSchema.optional(),\n toolResult: toolResultSchema.optional(),\n tokenUsage: tokenUsageSchema.optional(),\n goalCompleted: z.boolean().optional(),\n })\n .strict() satisfies z.ZodType<MessageInput>;\n\n/**\n * Zod schema for messages.\n */\nexport const messageSchema = z\n .object({\n id: z.string(),\n role: messageRoleSchema,\n content: z.union([z.string(), z.array(multiModalContentSchema)]),\n position: z.number().int().min(0),\n createdAt: z.string(),\n metadata: z.record(z.string(), jsonValueSchema),\n hidden: z.boolean(),\n toolCall: toolCallSchema.optional(),\n toolResult: toolResultSchema.optional(),\n tokenUsage: tokenUsageSchema.optional(),\n goalCompleted: z.boolean().optional(),\n })\n .strict() satisfies z.ZodType<Message>;\n\n/**\n * Zod schema for conversation status values.\n */\nexport const conversationStatusSchema = z.enum([\n 'active',\n 'archived',\n 'deleted',\n]) satisfies z.ZodType<ConversationStatus>;\n\n/**\n * Raw conversation shape for storage systems that need direct access to fields.\n */\nexport const conversationShape = {\n schemaVersion: z.number().int().min(1),\n id: z.string(),\n title: z.string().optional(),\n status: conversationStatusSchema,\n metadata: z.record(z.string(), jsonValueSchema),\n ids: z.array(z.string()),\n messages: z.record(z.string(), messageSchema),\n createdAt: z.string(),\n updatedAt: z.string(),\n} as const;\n\n/**\n * Zod schema for serialized conversations.\n */\nexport const conversationSchema = z\n .object(conversationShape)\n .strict() satisfies z.ZodType<Conversation>;\n",
|
|
7
|
+
"import { createIntegrityError } from '../errors';\nimport type { Conversation } from '../types';\n\nexport type IntegrityIssueCode =\n | 'integrity:missing-message'\n | 'integrity:unlisted-message'\n | 'integrity:duplicate-message-id'\n | 'integrity:orphan-tool-result'\n | 'integrity:tool-result-before-call'\n | 'integrity:duplicate-tool-call';\n\nexport interface IntegrityIssue {\n code: IntegrityIssueCode;\n message: string;\n data?: Record<string, unknown> | undefined;\n}\n\n/**\n * Validates conversation invariants and returns a list of issues.\n */\nexport function validateConversationIntegrity(\n conversation: Conversation,\n): IntegrityIssue[] {\n const issues: IntegrityIssue[] = [];\n const seenIds = new Set<string>();\n\n conversation.ids.forEach((id, index) => {\n if (seenIds.has(id)) {\n issues.push({\n code: 'integrity:duplicate-message-id',\n message: `duplicate message id in ids: ${id}`,\n data: { id, position: index },\n });\n } else {\n seenIds.add(id);\n }\n\n if (!conversation.messages[id]) {\n issues.push({\n code: 'integrity:missing-message',\n message: `missing message for id ${id}`,\n data: { id, position: index },\n });\n }\n });\n\n for (const id of Object.keys(conversation.messages)) {\n if (!seenIds.has(id)) {\n issues.push({\n code: 'integrity:unlisted-message',\n message: `message ${id} is not listed in ids`,\n data: { id },\n });\n }\n }\n\n const toolUses = new Map<string, { position: number; messageId: string }>();\n\n conversation.ids.forEach((id, index) => {\n const message = conversation.messages[id];\n if (!message) return;\n\n if (message.role === 'tool-use' && message.toolCall) {\n if (toolUses.has(message.toolCall.id)) {\n issues.push({\n code: 'integrity:duplicate-tool-call',\n message: `duplicate toolCall.id ${message.toolCall.id}`,\n data: { toolCallId: message.toolCall.id, messageId: message.id },\n });\n } else {\n toolUses.set(message.toolCall.id, { position: index, messageId: message.id });\n }\n }\n });\n\n conversation.ids.forEach((id, index) => {\n const message = conversation.messages[id];\n if (!message) return;\n\n if (message.role === 'tool-result' && message.toolResult) {\n const toolUse = toolUses.get(message.toolResult.callId);\n if (!toolUse) {\n issues.push({\n code: 'integrity:orphan-tool-result',\n message: `tool-result references missing tool-use ${message.toolResult.callId}`,\n data: { callId: message.toolResult.callId, messageId: message.id },\n });\n } else if (toolUse.position >= index) {\n issues.push({\n code: 'integrity:tool-result-before-call',\n message: `tool-result ${message.toolResult.callId} occurs before tool-use`,\n data: {\n callId: message.toolResult.callId,\n messageId: message.id,\n toolUseMessageId: toolUse.messageId,\n },\n });\n }\n }\n });\n\n return issues;\n}\n\n/**\n * Throws an integrity error if the conversation fails validation.\n */\nexport function assertConversationIntegrity(conversation: Conversation): void {\n const issues = validateConversationIntegrity(conversation);\n if (issues.length === 0) return;\n\n throw createIntegrityError('conversation integrity check failed', { issues });\n}\n",
|
|
8
|
+
"import { createValidationError } from '../errors';\nimport { conversationSchema } from '../schemas';\nimport type { Conversation } from '../types';\nimport { assertConversationIntegrity } from './integrity';\n\n/**\n * Ensures a conversation conforms to the schema (JSON-safe) and integrity rules.\n * Internal helper for public API enforcement points.\n */\nexport function assertConversationSafe(conversation: Conversation): void {\n const parsed = conversationSchema.safeParse(conversation);\n if (!parsed.success) {\n throw createValidationError('conversation failed schema validation', {\n issues: parsed.error.issues,\n });\n }\n\n assertConversationIntegrity(conversation);\n}\n\nexport function ensureConversationSafe(conversation: Conversation): Conversation {\n assertConversationSafe(conversation);\n return conversation;\n}\n",
|
|
5
9
|
"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
|
|
10
|
+
"import type { MultiModalContent } from '@lasercat/homogenaize';\n\nimport { assertConversationSafe } from '../../conversation/validation';\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 let input: unknown = toolCall.arguments;\n if (typeof toolCall.arguments === 'string') {\n try {\n input = JSON.parse(toolCall.arguments) as unknown;\n } catch {\n input = toolCall.arguments;\n }\n }\n return {\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.name,\n input,\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 assertConversationSafe(conversation);\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"
|
|
7
11
|
],
|
|
8
|
-
"mappings": ";
|
|
9
|
-
"debugId": "
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "FA4FB5174F303A6B64756E2164756E21",
|
|
10
14
|
"names": []
|
|
11
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/gemini/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/gemini/index.ts"],"names":[],"mappings":"AAGA,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;AA8JD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,kBAAkB,CAoF/E"}
|