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/dist/markdown/index.js
CHANGED
|
@@ -5001,6 +5001,263 @@ class EventEmission {
|
|
|
5001
5001
|
}
|
|
5002
5002
|
}
|
|
5003
5003
|
|
|
5004
|
+
// src/errors.ts
|
|
5005
|
+
class ConversationalistError extends Error {
|
|
5006
|
+
code;
|
|
5007
|
+
context;
|
|
5008
|
+
cause;
|
|
5009
|
+
constructor(code, message, options2) {
|
|
5010
|
+
super(message);
|
|
5011
|
+
this.name = "ConversationalistError";
|
|
5012
|
+
this.code = code;
|
|
5013
|
+
this.context = options2?.context;
|
|
5014
|
+
this.cause = options2?.cause;
|
|
5015
|
+
if (Error.captureStackTrace) {
|
|
5016
|
+
Error.captureStackTrace(this, ConversationalistError);
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
toDetailedString() {
|
|
5020
|
+
const parts = [`[${this.code}] ${this.message}`];
|
|
5021
|
+
if (this.context && Object.keys(this.context).length > 0) {
|
|
5022
|
+
parts.push(`Context: ${JSON.stringify(this.context, null, 2)}`);
|
|
5023
|
+
}
|
|
5024
|
+
if (this.cause) {
|
|
5025
|
+
parts.push(`Caused by: ${this.cause.message}`);
|
|
5026
|
+
}
|
|
5027
|
+
return parts.join(`
|
|
5028
|
+
`);
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
function createInvalidPositionError(expected, actual) {
|
|
5032
|
+
return new ConversationalistError("error:invalid-position", `invalid position: expected ${expected}, got ${actual}`, { context: { expected, actual } });
|
|
5033
|
+
}
|
|
5034
|
+
function createInvalidToolReferenceError(callId) {
|
|
5035
|
+
return new ConversationalistError("error:invalid-tool-reference", `tool result references non-existent tool-use: ${callId}`, { context: { callId } });
|
|
5036
|
+
}
|
|
5037
|
+
function createSerializationError(message, cause) {
|
|
5038
|
+
return new ConversationalistError("error:serialization", message, { cause });
|
|
5039
|
+
}
|
|
5040
|
+
function createValidationError(message, context, cause) {
|
|
5041
|
+
return new ConversationalistError("error:validation", message, { context, cause });
|
|
5042
|
+
}
|
|
5043
|
+
function createIntegrityError(message, context) {
|
|
5044
|
+
return new ConversationalistError("error:integrity", message, { context });
|
|
5045
|
+
}
|
|
5046
|
+
|
|
5047
|
+
// src/schemas.ts
|
|
5048
|
+
import { z } from "zod";
|
|
5049
|
+
var isPlainObject = (value) => {
|
|
5050
|
+
if (!value || typeof value !== "object")
|
|
5051
|
+
return false;
|
|
5052
|
+
const prototype = Reflect.getPrototypeOf(value);
|
|
5053
|
+
return prototype === Object.prototype || prototype === null;
|
|
5054
|
+
};
|
|
5055
|
+
function toMultiModalContent(value) {
|
|
5056
|
+
const result = { type: value.type };
|
|
5057
|
+
if (value.text !== undefined)
|
|
5058
|
+
result.text = value.text;
|
|
5059
|
+
if (value.url !== undefined)
|
|
5060
|
+
result.url = value.url;
|
|
5061
|
+
if (value.mimeType !== undefined)
|
|
5062
|
+
result.mimeType = value.mimeType;
|
|
5063
|
+
return result;
|
|
5064
|
+
}
|
|
5065
|
+
var jsonValueSchema = z.lazy(() => {
|
|
5066
|
+
const jsonObjectSchema = z.preprocess((value, ctx) => {
|
|
5067
|
+
if (!isPlainObject(value)) {
|
|
5068
|
+
ctx.addIssue({
|
|
5069
|
+
code: z.ZodIssueCode.custom,
|
|
5070
|
+
message: "expected a plain object"
|
|
5071
|
+
});
|
|
5072
|
+
return z.NEVER;
|
|
5073
|
+
}
|
|
5074
|
+
return value;
|
|
5075
|
+
}, z.record(z.string(), jsonValueSchema));
|
|
5076
|
+
return z.union([
|
|
5077
|
+
z.string(),
|
|
5078
|
+
z.number().refine((value) => Number.isFinite(value), {
|
|
5079
|
+
message: "expected a finite number"
|
|
5080
|
+
}),
|
|
5081
|
+
z.boolean(),
|
|
5082
|
+
z.null(),
|
|
5083
|
+
z.array(jsonValueSchema),
|
|
5084
|
+
jsonObjectSchema
|
|
5085
|
+
]);
|
|
5086
|
+
});
|
|
5087
|
+
var multiModalContentSchema = z.discriminatedUnion("type", [
|
|
5088
|
+
z.object({
|
|
5089
|
+
type: z.literal("text"),
|
|
5090
|
+
text: z.string()
|
|
5091
|
+
}),
|
|
5092
|
+
z.object({
|
|
5093
|
+
type: z.literal("image"),
|
|
5094
|
+
url: z.string().url(),
|
|
5095
|
+
mimeType: z.string().optional(),
|
|
5096
|
+
text: z.string().optional()
|
|
5097
|
+
})
|
|
5098
|
+
]).transform(toMultiModalContent);
|
|
5099
|
+
var messageRoleSchema = z.enum([
|
|
5100
|
+
"user",
|
|
5101
|
+
"assistant",
|
|
5102
|
+
"system",
|
|
5103
|
+
"developer",
|
|
5104
|
+
"tool-use",
|
|
5105
|
+
"tool-result",
|
|
5106
|
+
"snapshot"
|
|
5107
|
+
]);
|
|
5108
|
+
var toolCallSchema = z.object({
|
|
5109
|
+
id: z.string(),
|
|
5110
|
+
name: z.string(),
|
|
5111
|
+
arguments: jsonValueSchema
|
|
5112
|
+
}).strict();
|
|
5113
|
+
var toolResultSchema = z.object({
|
|
5114
|
+
callId: z.string(),
|
|
5115
|
+
outcome: z.enum(["success", "error"]),
|
|
5116
|
+
content: jsonValueSchema
|
|
5117
|
+
}).strict();
|
|
5118
|
+
var tokenUsageSchema = z.object({
|
|
5119
|
+
prompt: z.number().int().min(0),
|
|
5120
|
+
completion: z.number().int().min(0),
|
|
5121
|
+
total: z.number().int().min(0)
|
|
5122
|
+
});
|
|
5123
|
+
var messageInputSchema = z.object({
|
|
5124
|
+
role: messageRoleSchema,
|
|
5125
|
+
content: z.union([z.string(), z.array(multiModalContentSchema)]),
|
|
5126
|
+
metadata: z.record(z.string(), jsonValueSchema).optional(),
|
|
5127
|
+
hidden: z.boolean().optional(),
|
|
5128
|
+
toolCall: toolCallSchema.optional(),
|
|
5129
|
+
toolResult: toolResultSchema.optional(),
|
|
5130
|
+
tokenUsage: tokenUsageSchema.optional(),
|
|
5131
|
+
goalCompleted: z.boolean().optional()
|
|
5132
|
+
}).strict();
|
|
5133
|
+
var messageSchema = z.object({
|
|
5134
|
+
id: z.string(),
|
|
5135
|
+
role: messageRoleSchema,
|
|
5136
|
+
content: z.union([z.string(), z.array(multiModalContentSchema)]),
|
|
5137
|
+
position: z.number().int().min(0),
|
|
5138
|
+
createdAt: z.string(),
|
|
5139
|
+
metadata: z.record(z.string(), jsonValueSchema),
|
|
5140
|
+
hidden: z.boolean(),
|
|
5141
|
+
toolCall: toolCallSchema.optional(),
|
|
5142
|
+
toolResult: toolResultSchema.optional(),
|
|
5143
|
+
tokenUsage: tokenUsageSchema.optional(),
|
|
5144
|
+
goalCompleted: z.boolean().optional()
|
|
5145
|
+
}).strict();
|
|
5146
|
+
var conversationStatusSchema = z.enum([
|
|
5147
|
+
"active",
|
|
5148
|
+
"archived",
|
|
5149
|
+
"deleted"
|
|
5150
|
+
]);
|
|
5151
|
+
var conversationShape = {
|
|
5152
|
+
schemaVersion: z.number().int().min(1),
|
|
5153
|
+
id: z.string(),
|
|
5154
|
+
title: z.string().optional(),
|
|
5155
|
+
status: conversationStatusSchema,
|
|
5156
|
+
metadata: z.record(z.string(), jsonValueSchema),
|
|
5157
|
+
ids: z.array(z.string()),
|
|
5158
|
+
messages: z.record(z.string(), messageSchema),
|
|
5159
|
+
createdAt: z.string(),
|
|
5160
|
+
updatedAt: z.string()
|
|
5161
|
+
};
|
|
5162
|
+
var conversationSchema = z.object(conversationShape).strict();
|
|
5163
|
+
|
|
5164
|
+
// src/conversation/integrity.ts
|
|
5165
|
+
function validateConversationIntegrity(conversation) {
|
|
5166
|
+
const issues = [];
|
|
5167
|
+
const seenIds = new Set;
|
|
5168
|
+
conversation.ids.forEach((id, index) => {
|
|
5169
|
+
if (seenIds.has(id)) {
|
|
5170
|
+
issues.push({
|
|
5171
|
+
code: "integrity:duplicate-message-id",
|
|
5172
|
+
message: `duplicate message id in ids: ${id}`,
|
|
5173
|
+
data: { id, position: index }
|
|
5174
|
+
});
|
|
5175
|
+
} else {
|
|
5176
|
+
seenIds.add(id);
|
|
5177
|
+
}
|
|
5178
|
+
if (!conversation.messages[id]) {
|
|
5179
|
+
issues.push({
|
|
5180
|
+
code: "integrity:missing-message",
|
|
5181
|
+
message: `missing message for id ${id}`,
|
|
5182
|
+
data: { id, position: index }
|
|
5183
|
+
});
|
|
5184
|
+
}
|
|
5185
|
+
});
|
|
5186
|
+
for (const id of Object.keys(conversation.messages)) {
|
|
5187
|
+
if (!seenIds.has(id)) {
|
|
5188
|
+
issues.push({
|
|
5189
|
+
code: "integrity:unlisted-message",
|
|
5190
|
+
message: `message ${id} is not listed in ids`,
|
|
5191
|
+
data: { id }
|
|
5192
|
+
});
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5195
|
+
const toolUses = new Map;
|
|
5196
|
+
conversation.ids.forEach((id, index) => {
|
|
5197
|
+
const message = conversation.messages[id];
|
|
5198
|
+
if (!message)
|
|
5199
|
+
return;
|
|
5200
|
+
if (message.role === "tool-use" && message.toolCall) {
|
|
5201
|
+
if (toolUses.has(message.toolCall.id)) {
|
|
5202
|
+
issues.push({
|
|
5203
|
+
code: "integrity:duplicate-tool-call",
|
|
5204
|
+
message: `duplicate toolCall.id ${message.toolCall.id}`,
|
|
5205
|
+
data: { toolCallId: message.toolCall.id, messageId: message.id }
|
|
5206
|
+
});
|
|
5207
|
+
} else {
|
|
5208
|
+
toolUses.set(message.toolCall.id, { position: index, messageId: message.id });
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5211
|
+
});
|
|
5212
|
+
conversation.ids.forEach((id, index) => {
|
|
5213
|
+
const message = conversation.messages[id];
|
|
5214
|
+
if (!message)
|
|
5215
|
+
return;
|
|
5216
|
+
if (message.role === "tool-result" && message.toolResult) {
|
|
5217
|
+
const toolUse = toolUses.get(message.toolResult.callId);
|
|
5218
|
+
if (!toolUse) {
|
|
5219
|
+
issues.push({
|
|
5220
|
+
code: "integrity:orphan-tool-result",
|
|
5221
|
+
message: `tool-result references missing tool-use ${message.toolResult.callId}`,
|
|
5222
|
+
data: { callId: message.toolResult.callId, messageId: message.id }
|
|
5223
|
+
});
|
|
5224
|
+
} else if (toolUse.position >= index) {
|
|
5225
|
+
issues.push({
|
|
5226
|
+
code: "integrity:tool-result-before-call",
|
|
5227
|
+
message: `tool-result ${message.toolResult.callId} occurs before tool-use`,
|
|
5228
|
+
data: {
|
|
5229
|
+
callId: message.toolResult.callId,
|
|
5230
|
+
messageId: message.id,
|
|
5231
|
+
toolUseMessageId: toolUse.messageId
|
|
5232
|
+
}
|
|
5233
|
+
});
|
|
5234
|
+
}
|
|
5235
|
+
}
|
|
5236
|
+
});
|
|
5237
|
+
return issues;
|
|
5238
|
+
}
|
|
5239
|
+
function assertConversationIntegrity(conversation) {
|
|
5240
|
+
const issues = validateConversationIntegrity(conversation);
|
|
5241
|
+
if (issues.length === 0)
|
|
5242
|
+
return;
|
|
5243
|
+
throw createIntegrityError("conversation integrity check failed", { issues });
|
|
5244
|
+
}
|
|
5245
|
+
|
|
5246
|
+
// src/conversation/validation.ts
|
|
5247
|
+
function assertConversationSafe(conversation) {
|
|
5248
|
+
const parsed = conversationSchema.safeParse(conversation);
|
|
5249
|
+
if (!parsed.success) {
|
|
5250
|
+
throw createValidationError("conversation failed schema validation", {
|
|
5251
|
+
issues: parsed.error.issues
|
|
5252
|
+
});
|
|
5253
|
+
}
|
|
5254
|
+
assertConversationIntegrity(conversation);
|
|
5255
|
+
}
|
|
5256
|
+
function ensureConversationSafe(conversation) {
|
|
5257
|
+
assertConversationSafe(conversation);
|
|
5258
|
+
return conversation;
|
|
5259
|
+
}
|
|
5260
|
+
|
|
5004
5261
|
// src/utilities/content.ts
|
|
5005
5262
|
function normalizeContent(content) {
|
|
5006
5263
|
if (content === undefined)
|
|
@@ -5165,6 +5422,92 @@ var cloneMessageWithPosition = (message, position, content) => {
|
|
|
5165
5422
|
}
|
|
5166
5423
|
return createMessage(baseMessage);
|
|
5167
5424
|
};
|
|
5425
|
+
var createMessageBlock = (message, estimator) => ({
|
|
5426
|
+
messages: [message],
|
|
5427
|
+
minPosition: message.position,
|
|
5428
|
+
maxPosition: message.position,
|
|
5429
|
+
tokenCount: estimator(message)
|
|
5430
|
+
});
|
|
5431
|
+
var buildMessageBlocks = (messages, estimator, preserveToolPairs) => {
|
|
5432
|
+
if (!preserveToolPairs) {
|
|
5433
|
+
const blocks2 = messages.map((message) => createMessageBlock(message, estimator));
|
|
5434
|
+
const messageToBlock2 = new Map;
|
|
5435
|
+
for (const block of blocks2) {
|
|
5436
|
+
const message = block.messages[0];
|
|
5437
|
+
if (message) {
|
|
5438
|
+
messageToBlock2.set(message.id, block);
|
|
5439
|
+
}
|
|
5440
|
+
}
|
|
5441
|
+
return { blocks: blocks2, messageToBlock: messageToBlock2 };
|
|
5442
|
+
}
|
|
5443
|
+
const blocks = [];
|
|
5444
|
+
const toolUses = new Map;
|
|
5445
|
+
for (const message of messages) {
|
|
5446
|
+
if (message.role === "tool-use" && message.toolCall) {
|
|
5447
|
+
const block = createMessageBlock(message, estimator);
|
|
5448
|
+
toolUses.set(message.toolCall.id, block);
|
|
5449
|
+
blocks.push(block);
|
|
5450
|
+
continue;
|
|
5451
|
+
}
|
|
5452
|
+
if (message.role === "tool-result" && message.toolResult) {
|
|
5453
|
+
const existing = toolUses.get(message.toolResult.callId);
|
|
5454
|
+
if (existing) {
|
|
5455
|
+
existing.messages.push(message);
|
|
5456
|
+
existing.maxPosition = Math.max(existing.maxPosition, message.position);
|
|
5457
|
+
existing.tokenCount += estimator(message);
|
|
5458
|
+
continue;
|
|
5459
|
+
}
|
|
5460
|
+
const orphanBlock = createMessageBlock(message, estimator);
|
|
5461
|
+
orphanBlock.orphanToolResult = true;
|
|
5462
|
+
blocks.push(orphanBlock);
|
|
5463
|
+
continue;
|
|
5464
|
+
}
|
|
5465
|
+
blocks.push(createMessageBlock(message, estimator));
|
|
5466
|
+
}
|
|
5467
|
+
const filteredBlocks = blocks.filter((block) => !block.orphanToolResult);
|
|
5468
|
+
const messageToBlock = new Map;
|
|
5469
|
+
for (const block of filteredBlocks) {
|
|
5470
|
+
for (const message of block.messages) {
|
|
5471
|
+
messageToBlock.set(message.id, block);
|
|
5472
|
+
}
|
|
5473
|
+
}
|
|
5474
|
+
return { blocks: filteredBlocks, messageToBlock };
|
|
5475
|
+
};
|
|
5476
|
+
var collectBlocksForMessages = (messages, messageToBlock) => {
|
|
5477
|
+
const blocks = [];
|
|
5478
|
+
const seen = new Set;
|
|
5479
|
+
for (const message of messages) {
|
|
5480
|
+
const block = messageToBlock.get(message.id);
|
|
5481
|
+
if (block && !seen.has(block)) {
|
|
5482
|
+
seen.add(block);
|
|
5483
|
+
blocks.push(block);
|
|
5484
|
+
}
|
|
5485
|
+
}
|
|
5486
|
+
return blocks;
|
|
5487
|
+
};
|
|
5488
|
+
var collectMessagesFromBlocks = (blocks) => {
|
|
5489
|
+
const messages = [];
|
|
5490
|
+
const seen = new Set;
|
|
5491
|
+
for (const block of blocks) {
|
|
5492
|
+
for (const message of block.messages) {
|
|
5493
|
+
if (!seen.has(message.id)) {
|
|
5494
|
+
seen.add(message.id);
|
|
5495
|
+
messages.push(message);
|
|
5496
|
+
}
|
|
5497
|
+
}
|
|
5498
|
+
}
|
|
5499
|
+
messages.sort((a, b) => a.position - b.position);
|
|
5500
|
+
return messages;
|
|
5501
|
+
};
|
|
5502
|
+
var ensureTruncationSafe = (conversation, preserveToolPairs, operation) => {
|
|
5503
|
+
try {
|
|
5504
|
+
return ensureConversationSafe(conversation);
|
|
5505
|
+
} catch (error2) {
|
|
5506
|
+
if (!preserveToolPairs && error2 instanceof ConversationalistError && error2.code === "error:integrity")
|
|
5507
|
+
throw createIntegrityError(`${operation} produced invalid tool linkage; use preserveToolPairs: true to keep tool interactions intact`, { preserveToolPairs, issues: error2.context?.["issues"] });
|
|
5508
|
+
throw error2;
|
|
5509
|
+
}
|
|
5510
|
+
};
|
|
5168
5511
|
function estimateConversationTokens(conversation, estimateTokens, environment) {
|
|
5169
5512
|
let estimator = estimateTokens;
|
|
5170
5513
|
let env = environment;
|
|
@@ -5177,6 +5520,7 @@ function estimateConversationTokens(conversation, estimateTokens, environment) {
|
|
|
5177
5520
|
return getOrderedMessages(conversation).reduce((total, message) => total + finalEstimator(message), 0);
|
|
5178
5521
|
}
|
|
5179
5522
|
function truncateToTokenLimit(conversation, maxTokens, optionsOrEstimator, environment) {
|
|
5523
|
+
assertConversationSafe(conversation);
|
|
5180
5524
|
let options2 = {};
|
|
5181
5525
|
let env = environment;
|
|
5182
5526
|
if (typeof optionsOrEstimator === "function") {
|
|
@@ -5198,54 +5542,56 @@ function truncateToTokenLimit(conversation, maxTokens, optionsOrEstimator, envir
|
|
|
5198
5542
|
const estimator = options2.estimateTokens ?? resolvedEnvironment.estimateTokens;
|
|
5199
5543
|
const preserveSystem = options2.preserveSystemMessages ?? true;
|
|
5200
5544
|
const preserveLastN = options2.preserveLastN ?? 0;
|
|
5545
|
+
const preserveToolPairs = options2.preserveToolPairs ?? true;
|
|
5201
5546
|
const currentTokens = estimateConversationTokens(conversation, estimator, resolvedEnvironment);
|
|
5202
5547
|
if (currentTokens <= maxTokens) {
|
|
5203
5548
|
return conversation;
|
|
5204
5549
|
}
|
|
5205
5550
|
const now = resolvedEnvironment.now();
|
|
5206
5551
|
const orderedMessages = getOrderedMessages(conversation);
|
|
5552
|
+
const { blocks, messageToBlock } = buildMessageBlocks(orderedMessages, estimator, preserveToolPairs);
|
|
5207
5553
|
const systemMessages = preserveSystem ? orderedMessages.filter((m) => m.role === "system") : [];
|
|
5208
5554
|
const nonSystemMessages = orderedMessages.filter((m) => m.role !== "system");
|
|
5209
5555
|
const protectedMessages = preserveLastN > 0 ? nonSystemMessages.slice(-preserveLastN) : [];
|
|
5210
|
-
const
|
|
5211
|
-
const
|
|
5212
|
-
const
|
|
5556
|
+
const systemBlocks = collectBlocksForMessages(systemMessages, messageToBlock);
|
|
5557
|
+
const protectedBlocks = collectBlocksForMessages(protectedMessages, messageToBlock);
|
|
5558
|
+
const lockedBlocks = new Set([...systemBlocks, ...protectedBlocks]);
|
|
5559
|
+
const removableBlocks = blocks.filter((block) => !lockedBlocks.has(block));
|
|
5560
|
+
const systemTokens = systemBlocks.reduce((sum, block) => sum + block.tokenCount, 0);
|
|
5561
|
+
const protectedTokens = protectedBlocks.reduce((sum, block) => sum + block.tokenCount, 0);
|
|
5213
5562
|
const availableTokens = maxTokens - systemTokens - protectedTokens;
|
|
5563
|
+
let selectedBlocks = [];
|
|
5214
5564
|
if (availableTokens <= 0) {
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
const messageTokens = estimator(message);
|
|
5229
|
-
if (usedTokens + messageTokens <= availableTokens) {
|
|
5230
|
-
keptRemovable.unshift(message);
|
|
5231
|
-
usedTokens += messageTokens;
|
|
5232
|
-
} else {
|
|
5233
|
-
break;
|
|
5565
|
+
selectedBlocks = [...systemBlocks, ...protectedBlocks];
|
|
5566
|
+
} else {
|
|
5567
|
+
const sortedRemovable = [...removableBlocks].sort((a, b) => a.maxPosition - b.maxPosition);
|
|
5568
|
+
const keptRemovable = [];
|
|
5569
|
+
let usedTokens = 0;
|
|
5570
|
+
for (let i = sortedRemovable.length - 1;i >= 0; i--) {
|
|
5571
|
+
const block = sortedRemovable[i];
|
|
5572
|
+
if (usedTokens + block.tokenCount <= availableTokens) {
|
|
5573
|
+
keptRemovable.unshift(block);
|
|
5574
|
+
usedTokens += block.tokenCount;
|
|
5575
|
+
} else {
|
|
5576
|
+
break;
|
|
5577
|
+
}
|
|
5234
5578
|
}
|
|
5579
|
+
selectedBlocks = [...systemBlocks, ...keptRemovable, ...protectedBlocks];
|
|
5235
5580
|
}
|
|
5236
|
-
const allMessages =
|
|
5237
|
-
allMessages.sort((a, b) => a.position - b.position);
|
|
5581
|
+
const allMessages = collectMessagesFromBlocks(selectedBlocks);
|
|
5238
5582
|
const renumbered = allMessages.map((message, index) => cloneMessageWithPosition(message, index, copyContent(message.content)));
|
|
5239
|
-
|
|
5583
|
+
const next2 = toReadonly({
|
|
5240
5584
|
...conversation,
|
|
5241
5585
|
ids: renumbered.map((message) => message.id),
|
|
5242
5586
|
messages: toIdRecord(renumbered),
|
|
5243
5587
|
updatedAt: now
|
|
5244
5588
|
});
|
|
5589
|
+
return ensureTruncationSafe(next2, preserveToolPairs, "truncateToTokenLimit");
|
|
5245
5590
|
}
|
|
5246
5591
|
function getRecentMessages(conversation, count, options2) {
|
|
5247
5592
|
const includeHidden = options2?.includeHidden ?? false;
|
|
5248
5593
|
const includeSystem = options2?.includeSystem ?? false;
|
|
5594
|
+
const preserveToolPairs = options2?.preserveToolPairs ?? true;
|
|
5249
5595
|
const filtered = getOrderedMessages(conversation).filter((m) => {
|
|
5250
5596
|
if (!includeHidden && m.hidden)
|
|
5251
5597
|
return false;
|
|
@@ -5253,66 +5599,58 @@ function getRecentMessages(conversation, count, options2) {
|
|
|
5253
5599
|
return false;
|
|
5254
5600
|
return true;
|
|
5255
5601
|
});
|
|
5256
|
-
|
|
5602
|
+
if (!preserveToolPairs) {
|
|
5603
|
+
return filtered.slice(-count);
|
|
5604
|
+
}
|
|
5605
|
+
const { messageToBlock } = buildMessageBlocks(filtered, () => 0, preserveToolPairs);
|
|
5606
|
+
const tail = filtered.slice(-count);
|
|
5607
|
+
const blocks = collectBlocksForMessages(tail, messageToBlock);
|
|
5608
|
+
return collectMessagesFromBlocks(blocks);
|
|
5257
5609
|
}
|
|
5258
5610
|
function truncateFromPosition(conversation, position, options2, environment) {
|
|
5611
|
+
assertConversationSafe(conversation);
|
|
5259
5612
|
const preserveSystem = options2?.preserveSystemMessages ?? true;
|
|
5613
|
+
const preserveToolPairs = options2?.preserveToolPairs ?? true;
|
|
5260
5614
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5261
5615
|
const now = resolvedEnvironment.now();
|
|
5262
5616
|
const ordered = getOrderedMessages(conversation);
|
|
5617
|
+
const { messageToBlock } = buildMessageBlocks(ordered, () => 0, preserveToolPairs);
|
|
5263
5618
|
const systemMessages = preserveSystem ? ordered.filter((m) => m.role === "system" && m.position < position) : [];
|
|
5264
5619
|
const keptMessages = ordered.filter((m) => m.position >= position);
|
|
5265
|
-
const
|
|
5620
|
+
const systemBlocks = collectBlocksForMessages(systemMessages, messageToBlock);
|
|
5621
|
+
const keptBlocks = collectBlocksForMessages(keptMessages, messageToBlock);
|
|
5622
|
+
const allMessages = collectMessagesFromBlocks([...systemBlocks, ...keptBlocks]);
|
|
5266
5623
|
const renumbered = allMessages.map((message, index) => cloneMessageWithPosition(message, index, copyContent(message.content)));
|
|
5267
|
-
|
|
5624
|
+
const next2 = toReadonly({
|
|
5268
5625
|
...conversation,
|
|
5269
5626
|
ids: renumbered.map((message) => message.id),
|
|
5270
5627
|
messages: toIdRecord(renumbered),
|
|
5271
5628
|
updatedAt: now
|
|
5272
5629
|
});
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
// src/errors.ts
|
|
5276
|
-
class ConversationalistError extends Error {
|
|
5277
|
-
code;
|
|
5278
|
-
context;
|
|
5279
|
-
cause;
|
|
5280
|
-
constructor(code, message, options2) {
|
|
5281
|
-
super(message);
|
|
5282
|
-
this.name = "ConversationalistError";
|
|
5283
|
-
this.code = code;
|
|
5284
|
-
this.context = options2?.context;
|
|
5285
|
-
this.cause = options2?.cause;
|
|
5286
|
-
if (Error.captureStackTrace) {
|
|
5287
|
-
Error.captureStackTrace(this, ConversationalistError);
|
|
5288
|
-
}
|
|
5289
|
-
}
|
|
5290
|
-
toDetailedString() {
|
|
5291
|
-
const parts = [`[${this.code}] ${this.message}`];
|
|
5292
|
-
if (this.context && Object.keys(this.context).length > 0) {
|
|
5293
|
-
parts.push(`Context: ${JSON.stringify(this.context, null, 2)}`);
|
|
5294
|
-
}
|
|
5295
|
-
if (this.cause) {
|
|
5296
|
-
parts.push(`Caused by: ${this.cause.message}`);
|
|
5297
|
-
}
|
|
5298
|
-
return parts.join(`
|
|
5299
|
-
`);
|
|
5300
|
-
}
|
|
5301
|
-
}
|
|
5302
|
-
function createInvalidPositionError(expected, actual) {
|
|
5303
|
-
return new ConversationalistError("error:invalid-position", `invalid position: expected ${expected}, got ${actual}`, { context: { expected, actual } });
|
|
5304
|
-
}
|
|
5305
|
-
function createInvalidToolReferenceError(callId) {
|
|
5306
|
-
return new ConversationalistError("error:invalid-tool-reference", `tool result references non-existent tool-use: ${callId}`, { context: { callId } });
|
|
5307
|
-
}
|
|
5308
|
-
function createSerializationError(message, cause) {
|
|
5309
|
-
return new ConversationalistError("error:serialization", message, { cause });
|
|
5630
|
+
return ensureTruncationSafe(next2, preserveToolPairs, "truncateFromPosition");
|
|
5310
5631
|
}
|
|
5311
5632
|
|
|
5312
5633
|
// src/types.ts
|
|
5313
5634
|
var CURRENT_SCHEMA_VERSION = 3;
|
|
5314
5635
|
|
|
5315
|
-
// src/conversation.ts
|
|
5636
|
+
// src/conversation/create.ts
|
|
5637
|
+
function createConversation(options2, environment) {
|
|
5638
|
+
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5639
|
+
const now = resolvedEnvironment.now();
|
|
5640
|
+
const conv = {
|
|
5641
|
+
schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
5642
|
+
id: options2?.id ?? resolvedEnvironment.randomId(),
|
|
5643
|
+
title: options2?.title,
|
|
5644
|
+
status: options2?.status ?? "active",
|
|
5645
|
+
metadata: { ...options2?.metadata ?? {} },
|
|
5646
|
+
ids: [],
|
|
5647
|
+
messages: {},
|
|
5648
|
+
createdAt: now,
|
|
5649
|
+
updatedAt: now
|
|
5650
|
+
};
|
|
5651
|
+
return ensureConversationSafe(toReadonly(conv));
|
|
5652
|
+
}
|
|
5653
|
+
// src/conversation/tool-tracking.ts
|
|
5316
5654
|
var buildToolUseIndex = (messages) => messages.reduce((index, message) => {
|
|
5317
5655
|
if (message.role === "tool-use" && message.toolCall) {
|
|
5318
5656
|
index.set(message.toolCall.id, { name: message.toolCall.name });
|
|
@@ -5329,44 +5667,34 @@ var assertToolReference = (index, callId) => {
|
|
|
5329
5667
|
throw createInvalidToolReferenceError(callId);
|
|
5330
5668
|
}
|
|
5331
5669
|
};
|
|
5670
|
+
|
|
5671
|
+
// src/conversation/append.ts
|
|
5332
5672
|
function partitionAppendArgs(args) {
|
|
5333
|
-
|
|
5673
|
+
const filtered = args.filter((arg) => arg !== undefined);
|
|
5674
|
+
if (filtered.length === 0) {
|
|
5334
5675
|
return { inputs: [] };
|
|
5335
5676
|
}
|
|
5336
|
-
const last =
|
|
5677
|
+
const last = filtered[filtered.length - 1];
|
|
5337
5678
|
if (isConversationEnvironmentParameter(last)) {
|
|
5338
5679
|
return {
|
|
5339
|
-
inputs:
|
|
5680
|
+
inputs: filtered.slice(0, -1),
|
|
5340
5681
|
environment: last
|
|
5341
5682
|
};
|
|
5342
5683
|
}
|
|
5343
|
-
return { inputs:
|
|
5344
|
-
}
|
|
5345
|
-
function createConversation(options2, environment) {
|
|
5346
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5347
|
-
const now = resolvedEnvironment.now();
|
|
5348
|
-
const conv = {
|
|
5349
|
-
schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
5350
|
-
id: options2?.id ?? resolvedEnvironment.randomId(),
|
|
5351
|
-
title: options2?.title,
|
|
5352
|
-
status: options2?.status ?? "active",
|
|
5353
|
-
metadata: { ...options2?.metadata ?? {} },
|
|
5354
|
-
ids: [],
|
|
5355
|
-
messages: {},
|
|
5356
|
-
createdAt: now,
|
|
5357
|
-
updatedAt: now
|
|
5358
|
-
};
|
|
5359
|
-
return toReadonly(conv);
|
|
5684
|
+
return { inputs: filtered };
|
|
5360
5685
|
}
|
|
5361
5686
|
function appendMessages(conversation, ...args) {
|
|
5687
|
+
return appendMessagesInternal(conversation, args, true);
|
|
5688
|
+
}
|
|
5689
|
+
var appendMessagesInternal = (conversation, args, validate) => {
|
|
5362
5690
|
const { inputs, environment } = partitionAppendArgs(args);
|
|
5363
5691
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5364
5692
|
const now = resolvedEnvironment.now();
|
|
5365
5693
|
const startPosition = conversation.ids.length;
|
|
5366
|
-
const initialToolUses = buildToolUseIndex(getOrderedMessages(conversation));
|
|
5694
|
+
const initialToolUses = validate ? buildToolUseIndex(getOrderedMessages(conversation)) : new Map;
|
|
5367
5695
|
const { messages } = inputs.reduce((state, input, index) => {
|
|
5368
5696
|
const processedInput = resolvedEnvironment.plugins.reduce((acc, plugin) => plugin(acc), input);
|
|
5369
|
-
if (processedInput.role === "tool-result" && processedInput.toolResult) {
|
|
5697
|
+
if (validate && processedInput.role === "tool-result" && processedInput.toolResult) {
|
|
5370
5698
|
assertToolReference(state.toolUses, processedInput.toolResult.callId);
|
|
5371
5699
|
}
|
|
5372
5700
|
const normalizedContent = normalizeContent(processedInput.content);
|
|
@@ -5393,7 +5721,16 @@ function appendMessages(conversation, ...args) {
|
|
|
5393
5721
|
} else {
|
|
5394
5722
|
message = createMessage(baseMessage);
|
|
5395
5723
|
}
|
|
5396
|
-
|
|
5724
|
+
let toolUses = state.toolUses;
|
|
5725
|
+
if (processedInput.role === "tool-use" && processedInput.toolCall) {
|
|
5726
|
+
if (validate && state.toolUses.has(processedInput.toolCall.id)) {
|
|
5727
|
+
throw createIntegrityError("duplicate toolCall.id in conversation", {
|
|
5728
|
+
toolCallId: processedInput.toolCall.id,
|
|
5729
|
+
messageId: baseMessage.id
|
|
5730
|
+
});
|
|
5731
|
+
}
|
|
5732
|
+
toolUses = validate ? registerToolUse(state.toolUses, processedInput.toolCall) : state.toolUses;
|
|
5733
|
+
}
|
|
5397
5734
|
return {
|
|
5398
5735
|
toolUses,
|
|
5399
5736
|
messages: [...state.messages, message]
|
|
@@ -5406,17 +5743,25 @@ function appendMessages(conversation, ...args) {
|
|
|
5406
5743
|
messages: { ...conversation.messages, ...toIdRecord(messages) },
|
|
5407
5744
|
updatedAt: now
|
|
5408
5745
|
};
|
|
5409
|
-
|
|
5410
|
-
|
|
5746
|
+
const readonly = toReadonly(next2);
|
|
5747
|
+
return validate ? ensureConversationSafe(readonly) : readonly;
|
|
5748
|
+
};
|
|
5411
5749
|
function appendUserMessage(conversation, content, metadata, environment) {
|
|
5412
|
-
|
|
5750
|
+
const resolvedEnvironment = isConversationEnvironmentParameter(metadata) ? metadata : environment;
|
|
5751
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
5752
|
+
return appendMessages(conversation, { role: "user", content, metadata: resolvedMetadata }, resolvedEnvironment);
|
|
5413
5753
|
}
|
|
5414
5754
|
function appendAssistantMessage(conversation, content, metadata, environment) {
|
|
5415
|
-
|
|
5755
|
+
const resolvedEnvironment = isConversationEnvironmentParameter(metadata) ? metadata : environment;
|
|
5756
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
5757
|
+
return appendMessages(conversation, { role: "assistant", content, metadata: resolvedMetadata }, resolvedEnvironment);
|
|
5416
5758
|
}
|
|
5417
5759
|
function appendSystemMessage(conversation, content, metadata, environment) {
|
|
5418
|
-
|
|
5760
|
+
const resolvedEnvironment = isConversationEnvironmentParameter(metadata) ? metadata : environment;
|
|
5761
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
5762
|
+
return appendMessages(conversation, { role: "system", content, metadata: resolvedMetadata }, resolvedEnvironment);
|
|
5419
5763
|
}
|
|
5764
|
+
// src/conversation/query.ts
|
|
5420
5765
|
function getMessages(conversation, options2) {
|
|
5421
5766
|
const includeHidden = options2?.includeHidden ?? false;
|
|
5422
5767
|
const ordered = getOrderedMessages(conversation);
|
|
@@ -5450,6 +5795,7 @@ function getStatistics(conversation) {
|
|
|
5450
5795
|
}, { byRole: {}, hidden: 0, withImages: 0 });
|
|
5451
5796
|
return { total: ordered.length, ...stats };
|
|
5452
5797
|
}
|
|
5798
|
+
// src/conversation/system-messages.ts
|
|
5453
5799
|
function hasSystemMessage(conversation) {
|
|
5454
5800
|
return getOrderedMessages(conversation).some((m) => m.role === "system");
|
|
5455
5801
|
}
|
|
@@ -5460,7 +5806,8 @@ function getSystemMessages(conversation) {
|
|
|
5460
5806
|
return getOrderedMessages(conversation).filter((m) => m.role === "system");
|
|
5461
5807
|
}
|
|
5462
5808
|
function prependSystemMessage(conversation, content, metadata, environment) {
|
|
5463
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5809
|
+
const resolvedEnvironment = resolveConversationEnvironment(isConversationEnvironmentParameter(metadata) ? metadata : environment);
|
|
5810
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
5464
5811
|
const now = resolvedEnvironment.now();
|
|
5465
5812
|
const newMessage = createMessage({
|
|
5466
5813
|
id: resolvedEnvironment.randomId(),
|
|
@@ -5468,7 +5815,7 @@ function prependSystemMessage(conversation, content, metadata, environment) {
|
|
|
5468
5815
|
content,
|
|
5469
5816
|
position: 0,
|
|
5470
5817
|
createdAt: now,
|
|
5471
|
-
metadata: { ...
|
|
5818
|
+
metadata: { ...resolvedMetadata ?? {} },
|
|
5472
5819
|
hidden: false,
|
|
5473
5820
|
toolCall: undefined,
|
|
5474
5821
|
toolResult: undefined,
|
|
@@ -5487,20 +5834,21 @@ function prependSystemMessage(conversation, content, metadata, environment) {
|
|
|
5487
5834
|
toolResult: message.toolResult,
|
|
5488
5835
|
tokenUsage: message.tokenUsage
|
|
5489
5836
|
}));
|
|
5490
|
-
return toReadonly({
|
|
5837
|
+
return ensureConversationSafe(toReadonly({
|
|
5491
5838
|
...conversation,
|
|
5492
5839
|
ids: [newMessage.id, ...ordered.map((message) => message.id)],
|
|
5493
5840
|
messages: toIdRecord([newMessage, ...renumberedMessages]),
|
|
5494
5841
|
updatedAt: now
|
|
5495
|
-
});
|
|
5842
|
+
}));
|
|
5496
5843
|
}
|
|
5497
5844
|
function replaceSystemMessage(conversation, content, metadata, environment) {
|
|
5498
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5845
|
+
const resolvedEnvironment = resolveConversationEnvironment(isConversationEnvironmentParameter(metadata) ? metadata : environment);
|
|
5846
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
5499
5847
|
const now = resolvedEnvironment.now();
|
|
5500
5848
|
const ordered = getOrderedMessages(conversation);
|
|
5501
5849
|
const firstSystemIndex = ordered.findIndex((m) => m.role === "system");
|
|
5502
5850
|
if (firstSystemIndex === -1) {
|
|
5503
|
-
return prependSystemMessage(conversation, content,
|
|
5851
|
+
return prependSystemMessage(conversation, content, resolvedMetadata, resolvedEnvironment);
|
|
5504
5852
|
}
|
|
5505
5853
|
const original = ordered[firstSystemIndex];
|
|
5506
5854
|
const replaced = createMessage({
|
|
@@ -5509,7 +5857,7 @@ function replaceSystemMessage(conversation, content, metadata, environment) {
|
|
|
5509
5857
|
content,
|
|
5510
5858
|
position: original.position,
|
|
5511
5859
|
createdAt: original.createdAt,
|
|
5512
|
-
metadata: { ...
|
|
5860
|
+
metadata: { ...resolvedMetadata ?? original.metadata },
|
|
5513
5861
|
hidden: original.hidden,
|
|
5514
5862
|
toolCall: undefined,
|
|
5515
5863
|
toolResult: undefined,
|
|
@@ -5521,13 +5869,13 @@ function replaceSystemMessage(conversation, content, metadata, environment) {
|
|
|
5521
5869
|
messages: { ...conversation.messages, [replaced.id]: replaced },
|
|
5522
5870
|
updatedAt: now
|
|
5523
5871
|
};
|
|
5524
|
-
return toReadonly(next2);
|
|
5872
|
+
return ensureConversationSafe(toReadonly(next2));
|
|
5525
5873
|
}
|
|
5526
5874
|
function collapseSystemMessages(conversation, environment) {
|
|
5527
5875
|
const ordered = getOrderedMessages(conversation);
|
|
5528
5876
|
const systemMessages = ordered.filter((m) => m.role === "system");
|
|
5529
5877
|
if (systemMessages.length <= 1) {
|
|
5530
|
-
return conversation;
|
|
5878
|
+
return ensureConversationSafe(conversation);
|
|
5531
5879
|
}
|
|
5532
5880
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5533
5881
|
const now = resolvedEnvironment.now();
|
|
@@ -5583,9 +5931,42 @@ function collapseSystemMessages(conversation, environment) {
|
|
|
5583
5931
|
messages: toIdRecord(renumbered),
|
|
5584
5932
|
updatedAt: now
|
|
5585
5933
|
};
|
|
5586
|
-
return toReadonly(next2);
|
|
5934
|
+
return ensureConversationSafe(toReadonly(next2));
|
|
5587
5935
|
}
|
|
5588
|
-
|
|
5936
|
+
// src/utilities/tool-results.ts
|
|
5937
|
+
function copyToolResult(toolResult) {
|
|
5938
|
+
return { ...toolResult };
|
|
5939
|
+
}
|
|
5940
|
+
function redactToolResult(toolResult, placeholder) {
|
|
5941
|
+
return { ...toolResult, content: placeholder };
|
|
5942
|
+
}
|
|
5943
|
+
|
|
5944
|
+
// src/conversation/modify.ts
|
|
5945
|
+
var isRedactMessageOptions = (value) => {
|
|
5946
|
+
if (!value || typeof value !== "object")
|
|
5947
|
+
return false;
|
|
5948
|
+
const candidate = value;
|
|
5949
|
+
return "placeholder" in candidate || "redactToolArguments" in candidate || "redactToolResults" in candidate || "clearToolMetadata" in candidate;
|
|
5950
|
+
};
|
|
5951
|
+
function redactMessageAtPosition(conversation, position, placeholderOrOptions, environment) {
|
|
5952
|
+
let placeholder = "[REDACTED]";
|
|
5953
|
+
let options2 = {};
|
|
5954
|
+
let env = environment;
|
|
5955
|
+
if (typeof placeholderOrOptions === "string") {
|
|
5956
|
+
placeholder = placeholderOrOptions;
|
|
5957
|
+
} else if (placeholderOrOptions) {
|
|
5958
|
+
if (!environment && isConversationEnvironmentParameter(placeholderOrOptions)) {
|
|
5959
|
+
env = placeholderOrOptions;
|
|
5960
|
+
} else if (isRedactMessageOptions(placeholderOrOptions)) {
|
|
5961
|
+
options2 = placeholderOrOptions;
|
|
5962
|
+
if (options2.placeholder) {
|
|
5963
|
+
placeholder = options2.placeholder;
|
|
5964
|
+
}
|
|
5965
|
+
}
|
|
5966
|
+
}
|
|
5967
|
+
const redactToolArguments = options2.redactToolArguments ?? true;
|
|
5968
|
+
const redactToolResults = options2.redactToolResults ?? true;
|
|
5969
|
+
const clearToolMetadata = options2.clearToolMetadata ?? false;
|
|
5589
5970
|
if (position < 0 || position >= conversation.ids.length) {
|
|
5590
5971
|
throw createInvalidPositionError(conversation.ids.length - 1, position);
|
|
5591
5972
|
}
|
|
@@ -5594,6 +5975,22 @@ function redactMessageAtPosition(conversation, position, placeholder = "[REDACTE
|
|
|
5594
5975
|
if (!original) {
|
|
5595
5976
|
throw createInvalidPositionError(conversation.ids.length - 1, position);
|
|
5596
5977
|
}
|
|
5978
|
+
let toolCall = original.toolCall ? { ...original.toolCall } : undefined;
|
|
5979
|
+
let toolResult = original.toolResult ? { ...original.toolResult } : undefined;
|
|
5980
|
+
if (clearToolMetadata) {
|
|
5981
|
+
toolCall = undefined;
|
|
5982
|
+
toolResult = undefined;
|
|
5983
|
+
} else {
|
|
5984
|
+
if (original.role === "tool-use" && toolCall) {
|
|
5985
|
+
toolCall = {
|
|
5986
|
+
...toolCall,
|
|
5987
|
+
arguments: redactToolArguments ? placeholder : toolCall.arguments
|
|
5988
|
+
};
|
|
5989
|
+
}
|
|
5990
|
+
if (original.role === "tool-result" && toolResult) {
|
|
5991
|
+
toolResult = redactToolResults ? redactToolResult(toolResult, placeholder) : { ...toolResult };
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
5597
5994
|
const redacted = createMessage({
|
|
5598
5995
|
id: original.id,
|
|
5599
5996
|
role: original.role,
|
|
@@ -5602,11 +5999,11 @@ function redactMessageAtPosition(conversation, position, placeholder = "[REDACTE
|
|
|
5602
5999
|
createdAt: original.createdAt,
|
|
5603
6000
|
metadata: { ...original.metadata },
|
|
5604
6001
|
hidden: original.hidden,
|
|
5605
|
-
toolCall
|
|
5606
|
-
toolResult
|
|
5607
|
-
tokenUsage: undefined
|
|
6002
|
+
toolCall,
|
|
6003
|
+
toolResult,
|
|
6004
|
+
tokenUsage: original.tokenUsage ? { ...original.tokenUsage } : undefined
|
|
5608
6005
|
});
|
|
5609
|
-
const resolvedEnvironment = resolveConversationEnvironment(
|
|
6006
|
+
const resolvedEnvironment = resolveConversationEnvironment(env);
|
|
5610
6007
|
const now = resolvedEnvironment.now();
|
|
5611
6008
|
const next2 = {
|
|
5612
6009
|
...conversation,
|
|
@@ -5614,70 +6011,62 @@ function redactMessageAtPosition(conversation, position, placeholder = "[REDACTE
|
|
|
5614
6011
|
messages: { ...conversation.messages, [redacted.id]: redacted },
|
|
5615
6012
|
updatedAt: now
|
|
5616
6013
|
};
|
|
5617
|
-
return toReadonly(next2);
|
|
6014
|
+
return ensureConversationSafe(toReadonly(next2));
|
|
5618
6015
|
}
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
messages = { ...rawMessages };
|
|
5644
|
-
if (isStringArray(rawIds) && rawIds.length > 0) {
|
|
5645
|
-
ids = [...rawIds];
|
|
5646
|
-
} else {
|
|
5647
|
-
ids = Object.values(messages).sort((a, b) => a.position - b.position).map((message) => message.id);
|
|
5648
|
-
}
|
|
5649
|
-
}
|
|
5650
|
-
if (ids.length > 0) {
|
|
5651
|
-
ids = ids.filter((id) => (id in messages));
|
|
5652
|
-
const missing = Object.keys(messages).filter((id) => !ids.includes(id));
|
|
5653
|
-
if (missing.length > 0) {
|
|
5654
|
-
const sortedMissing = missing.sort((a, b) => (messages[a]?.position ?? 0) - (messages[b]?.position ?? 0));
|
|
5655
|
-
ids = [...ids, ...sortedMissing];
|
|
5656
|
-
}
|
|
5657
|
-
}
|
|
5658
|
-
if (!("schemaVersion" in json)) {
|
|
6016
|
+
// src/conversation/serialization.ts
|
|
6017
|
+
function normalizeToolResult(toolResult) {
|
|
6018
|
+
if (!toolResult)
|
|
6019
|
+
return;
|
|
6020
|
+
return {
|
|
6021
|
+
callId: toolResult.callId,
|
|
6022
|
+
outcome: toolResult.outcome,
|
|
6023
|
+
content: toolResult.content
|
|
6024
|
+
};
|
|
6025
|
+
}
|
|
6026
|
+
function normalizeMessage(message) {
|
|
6027
|
+
const base = {
|
|
6028
|
+
id: message.id,
|
|
6029
|
+
role: message.role,
|
|
6030
|
+
content: message.content,
|
|
6031
|
+
position: message.position,
|
|
6032
|
+
createdAt: message.createdAt,
|
|
6033
|
+
metadata: message.metadata,
|
|
6034
|
+
hidden: message.hidden,
|
|
6035
|
+
toolCall: message.toolCall ? { ...message.toolCall } : undefined,
|
|
6036
|
+
toolResult: normalizeToolResult(message.toolResult),
|
|
6037
|
+
tokenUsage: message.tokenUsage ? { ...message.tokenUsage } : undefined
|
|
6038
|
+
};
|
|
6039
|
+
if (isAssistantMessage(message)) {
|
|
5659
6040
|
return {
|
|
5660
|
-
...
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
messages
|
|
6041
|
+
...base,
|
|
6042
|
+
role: "assistant",
|
|
6043
|
+
goalCompleted: message.goalCompleted
|
|
5664
6044
|
};
|
|
5665
6045
|
}
|
|
5666
|
-
return
|
|
6046
|
+
return base;
|
|
5667
6047
|
}
|
|
5668
6048
|
function deserializeConversation(json) {
|
|
5669
|
-
const
|
|
6049
|
+
const parsed = conversationSchema.safeParse(json);
|
|
6050
|
+
if (!parsed.success) {
|
|
6051
|
+
throw createSerializationError("failed to deserialize conversation: invalid data");
|
|
6052
|
+
}
|
|
6053
|
+
const data = parsed.data;
|
|
5670
6054
|
try {
|
|
5671
|
-
const
|
|
5672
|
-
|
|
6055
|
+
const messageIds = new Set(Object.keys(data.messages));
|
|
6056
|
+
const orderedMessages = data.ids.map((id, index) => {
|
|
6057
|
+
const message = data.messages[id];
|
|
5673
6058
|
if (!message) {
|
|
5674
6059
|
throw createSerializationError(`missing message for id ${id}`);
|
|
5675
6060
|
}
|
|
5676
6061
|
if (message.position !== index) {
|
|
5677
6062
|
throw createInvalidPositionError(index, message.position);
|
|
5678
6063
|
}
|
|
5679
|
-
|
|
6064
|
+
messageIds.delete(id);
|
|
6065
|
+
return normalizeMessage(message);
|
|
5680
6066
|
});
|
|
6067
|
+
if (messageIds.size > 0) {
|
|
6068
|
+
throw createSerializationError(`messages not listed in ids: ${[...messageIds].join(", ")}`);
|
|
6069
|
+
}
|
|
5681
6070
|
orderedMessages.reduce((state, message) => {
|
|
5682
6071
|
if (message.role === "tool-use" && message.toolCall) {
|
|
5683
6072
|
return {
|
|
@@ -5689,24 +6078,28 @@ function deserializeConversation(json) {
|
|
|
5689
6078
|
}
|
|
5690
6079
|
return state;
|
|
5691
6080
|
}, { toolUses: new Map });
|
|
5692
|
-
const messageInstances = orderedMessages.map((
|
|
6081
|
+
const messageInstances = orderedMessages.map((message) => createMessage(message));
|
|
5693
6082
|
const conv = {
|
|
5694
|
-
schemaVersion:
|
|
5695
|
-
id:
|
|
5696
|
-
title:
|
|
5697
|
-
status:
|
|
5698
|
-
metadata: { ...
|
|
6083
|
+
schemaVersion: data.schemaVersion,
|
|
6084
|
+
id: data.id,
|
|
6085
|
+
title: data.title,
|
|
6086
|
+
status: data.status,
|
|
6087
|
+
metadata: { ...data.metadata },
|
|
5699
6088
|
ids: orderedMessages.map((message) => message.id),
|
|
5700
6089
|
messages: toIdRecord(messageInstances),
|
|
5701
|
-
createdAt:
|
|
5702
|
-
updatedAt:
|
|
6090
|
+
createdAt: data.createdAt,
|
|
6091
|
+
updatedAt: data.updatedAt
|
|
5703
6092
|
};
|
|
5704
|
-
|
|
6093
|
+
const readonly = toReadonly(conv);
|
|
6094
|
+
assertConversationIntegrity(readonly);
|
|
6095
|
+
return readonly;
|
|
5705
6096
|
} catch (error2) {
|
|
5706
6097
|
throw createSerializationError(`failed to deserialize conversation: ${error2 instanceof Error ? error2.message : String(error2)}`, error2);
|
|
5707
6098
|
}
|
|
5708
6099
|
}
|
|
6100
|
+
// src/conversation/transform.ts
|
|
5709
6101
|
function toChatMessages(conversation) {
|
|
6102
|
+
assertConversationSafe(conversation);
|
|
5710
6103
|
const roleMap = {
|
|
5711
6104
|
user: "user",
|
|
5712
6105
|
assistant: "assistant",
|
|
@@ -5728,7 +6121,6 @@ function toChatMessages(conversation) {
|
|
|
5728
6121
|
}
|
|
5729
6122
|
return result;
|
|
5730
6123
|
}
|
|
5731
|
-
|
|
5732
6124
|
// src/streaming.ts
|
|
5733
6125
|
var STREAMING_KEY = "__streaming";
|
|
5734
6126
|
var cloneMessage = (original, overrides = {}) => {
|
|
@@ -5761,7 +6153,8 @@ function getStreamingMessage(conversation) {
|
|
|
5761
6153
|
return getOrderedMessages(conversation).find(isStreamingMessage);
|
|
5762
6154
|
}
|
|
5763
6155
|
function appendStreamingMessage(conversation, role, metadata, environment) {
|
|
5764
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
6156
|
+
const resolvedEnvironment = resolveConversationEnvironment(isConversationEnvironmentParameter(metadata) ? metadata : environment);
|
|
6157
|
+
const resolvedMetadata = isConversationEnvironmentParameter(metadata) ? undefined : metadata;
|
|
5765
6158
|
const now = resolvedEnvironment.now();
|
|
5766
6159
|
const messageId = resolvedEnvironment.randomId();
|
|
5767
6160
|
const newMessage = createMessage({
|
|
@@ -5770,7 +6163,7 @@ function appendStreamingMessage(conversation, role, metadata, environment) {
|
|
|
5770
6163
|
content: "",
|
|
5771
6164
|
position: conversation.ids.length,
|
|
5772
6165
|
createdAt: now,
|
|
5773
|
-
metadata: { ...
|
|
6166
|
+
metadata: { ...resolvedMetadata ?? {}, [STREAMING_KEY]: true },
|
|
5774
6167
|
hidden: false,
|
|
5775
6168
|
toolCall: undefined,
|
|
5776
6169
|
toolResult: undefined,
|
|
@@ -5782,14 +6175,14 @@ function appendStreamingMessage(conversation, role, metadata, environment) {
|
|
|
5782
6175
|
messages: { ...conversation.messages, [messageId]: newMessage },
|
|
5783
6176
|
updatedAt: now
|
|
5784
6177
|
});
|
|
5785
|
-
return { conversation: updatedConversation, messageId };
|
|
6178
|
+
return { conversation: ensureConversationSafe(updatedConversation), messageId };
|
|
5786
6179
|
}
|
|
5787
6180
|
function updateStreamingMessage(conversation, messageId, content, environment) {
|
|
5788
6181
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5789
6182
|
const now = resolvedEnvironment.now();
|
|
5790
6183
|
const original = conversation.messages[messageId];
|
|
5791
6184
|
if (!original) {
|
|
5792
|
-
return conversation;
|
|
6185
|
+
return ensureConversationSafe(conversation);
|
|
5793
6186
|
}
|
|
5794
6187
|
const overrides = {
|
|
5795
6188
|
content: typeof content === "string" ? content : [...content]
|
|
@@ -5798,44 +6191,45 @@ function updateStreamingMessage(conversation, messageId, content, environment) {
|
|
|
5798
6191
|
overrides.tokenUsage = { ...original.tokenUsage };
|
|
5799
6192
|
}
|
|
5800
6193
|
const updated = cloneMessage(original, overrides);
|
|
5801
|
-
return toReadonly({
|
|
6194
|
+
return ensureConversationSafe(toReadonly({
|
|
5802
6195
|
...conversation,
|
|
5803
6196
|
ids: [...conversation.ids],
|
|
5804
6197
|
messages: { ...conversation.messages, [updated.id]: updated },
|
|
5805
6198
|
updatedAt: now
|
|
5806
|
-
});
|
|
6199
|
+
}));
|
|
5807
6200
|
}
|
|
5808
6201
|
function finalizeStreamingMessage(conversation, messageId, options2, environment) {
|
|
5809
|
-
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
6202
|
+
const resolvedEnvironment = resolveConversationEnvironment(isConversationEnvironmentParameter(options2) ? options2 : environment);
|
|
6203
|
+
const resolvedOptions = isConversationEnvironmentParameter(options2) ? undefined : options2;
|
|
5810
6204
|
const now = resolvedEnvironment.now();
|
|
5811
6205
|
const original = conversation.messages[messageId];
|
|
5812
6206
|
if (!original) {
|
|
5813
|
-
return conversation;
|
|
6207
|
+
return ensureConversationSafe(conversation);
|
|
5814
6208
|
}
|
|
5815
6209
|
const { [STREAMING_KEY]: _, ...restMetadata } = original.metadata;
|
|
5816
6210
|
const finalMetadata = {
|
|
5817
6211
|
...restMetadata,
|
|
5818
|
-
...
|
|
6212
|
+
...resolvedOptions?.metadata ?? {}
|
|
5819
6213
|
};
|
|
5820
6214
|
const finalizeOverrides = {
|
|
5821
6215
|
metadata: finalMetadata
|
|
5822
6216
|
};
|
|
5823
|
-
if (
|
|
5824
|
-
finalizeOverrides.tokenUsage = { ...
|
|
6217
|
+
if (resolvedOptions?.tokenUsage) {
|
|
6218
|
+
finalizeOverrides.tokenUsage = { ...resolvedOptions.tokenUsage };
|
|
5825
6219
|
}
|
|
5826
6220
|
const updated = cloneMessage(original, finalizeOverrides);
|
|
5827
|
-
return toReadonly({
|
|
6221
|
+
return ensureConversationSafe(toReadonly({
|
|
5828
6222
|
...conversation,
|
|
5829
6223
|
ids: [...conversation.ids],
|
|
5830
6224
|
messages: { ...conversation.messages, [updated.id]: updated },
|
|
5831
6225
|
updatedAt: now
|
|
5832
|
-
});
|
|
6226
|
+
}));
|
|
5833
6227
|
}
|
|
5834
6228
|
function cancelStreamingMessage(conversation, messageId, environment) {
|
|
5835
6229
|
const resolvedEnvironment = resolveConversationEnvironment(environment);
|
|
5836
6230
|
const now = resolvedEnvironment.now();
|
|
5837
6231
|
if (!conversation.messages[messageId]) {
|
|
5838
|
-
return conversation;
|
|
6232
|
+
return ensureConversationSafe(conversation);
|
|
5839
6233
|
}
|
|
5840
6234
|
const messages = getOrderedMessages(conversation).filter((m) => m.id !== messageId).map((message, index) => message.position === index ? message : (() => {
|
|
5841
6235
|
const overrides = {
|
|
@@ -5846,12 +6240,12 @@ function cancelStreamingMessage(conversation, messageId, environment) {
|
|
|
5846
6240
|
}
|
|
5847
6241
|
return cloneMessage(message, overrides);
|
|
5848
6242
|
})());
|
|
5849
|
-
return toReadonly({
|
|
6243
|
+
return ensureConversationSafe(toReadonly({
|
|
5850
6244
|
...conversation,
|
|
5851
6245
|
ids: messages.map((message) => message.id),
|
|
5852
6246
|
messages: toIdRecord(messages),
|
|
5853
6247
|
updatedAt: now
|
|
5854
|
-
});
|
|
6248
|
+
}));
|
|
5855
6249
|
}
|
|
5856
6250
|
|
|
5857
6251
|
// src/history.ts
|
|
@@ -5863,8 +6257,9 @@ class ConversationHistory extends EventTarget {
|
|
|
5863
6257
|
super();
|
|
5864
6258
|
this.environment = resolveConversationEnvironment(environment);
|
|
5865
6259
|
this.events = createEventTarget();
|
|
6260
|
+
const safeInitial = ensureConversationSafe(initial);
|
|
5866
6261
|
this.currentNode = {
|
|
5867
|
-
conversation:
|
|
6262
|
+
conversation: safeInitial,
|
|
5868
6263
|
parent: null,
|
|
5869
6264
|
children: []
|
|
5870
6265
|
};
|
|
@@ -6062,8 +6457,8 @@ class ConversationHistory extends EventTarget {
|
|
|
6062
6457
|
collapseSystemMessages() {
|
|
6063
6458
|
this.push(collapseSystemMessages(this.current, this.env));
|
|
6064
6459
|
}
|
|
6065
|
-
redactMessageAtPosition(position,
|
|
6066
|
-
this.push(redactMessageAtPosition(this.current, position,
|
|
6460
|
+
redactMessageAtPosition(position, placeholderOrOptions) {
|
|
6461
|
+
this.push(redactMessageAtPosition(this.current, position, placeholderOrOptions, this.env));
|
|
6067
6462
|
}
|
|
6068
6463
|
truncateFromPosition(position, options2) {
|
|
6069
6464
|
this.push(truncateFromPosition(this.current, position, options2, this.env));
|
|
@@ -6169,23 +6564,6 @@ function isConversation(value) {
|
|
|
6169
6564
|
|
|
6170
6565
|
// src/utilities/markdown.ts
|
|
6171
6566
|
var import_gray_matter = __toESM(require_gray_matter(), 1);
|
|
6172
|
-
|
|
6173
|
-
// src/utilities/tool-results.ts
|
|
6174
|
-
function copyToolResult(toolResult) {
|
|
6175
|
-
return { ...toolResult };
|
|
6176
|
-
}
|
|
6177
|
-
function redactToolResult(toolResult, placeholder) {
|
|
6178
|
-
const result = { ...toolResult, content: placeholder };
|
|
6179
|
-
if (result.result !== undefined) {
|
|
6180
|
-
result.result = placeholder;
|
|
6181
|
-
}
|
|
6182
|
-
if (result.error !== undefined) {
|
|
6183
|
-
result.error = placeholder;
|
|
6184
|
-
}
|
|
6185
|
-
return result;
|
|
6186
|
-
}
|
|
6187
|
-
|
|
6188
|
-
// src/utilities/markdown.ts
|
|
6189
6567
|
var ROLE_LABELS = {
|
|
6190
6568
|
user: "User",
|
|
6191
6569
|
assistant: "Assistant",
|
|
@@ -6195,7 +6573,6 @@ var ROLE_LABELS = {
|
|
|
6195
6573
|
"tool-result": "Tool Result",
|
|
6196
6574
|
snapshot: "Snapshot"
|
|
6197
6575
|
};
|
|
6198
|
-
var ROLE_DISPLAY_NAMES = ROLE_LABELS;
|
|
6199
6576
|
var LABEL_TO_ROLE = {
|
|
6200
6577
|
User: "user",
|
|
6201
6578
|
Assistant: "assistant",
|
|
@@ -6205,7 +6582,6 @@ var LABEL_TO_ROLE = {
|
|
|
6205
6582
|
"Tool Result": "tool-result",
|
|
6206
6583
|
Snapshot: "snapshot"
|
|
6207
6584
|
};
|
|
6208
|
-
var DISPLAY_NAME_TO_ROLE = LABEL_TO_ROLE;
|
|
6209
6585
|
function getRoleLabel(role) {
|
|
6210
6586
|
return ROLE_LABELS[role];
|
|
6211
6587
|
}
|
|
@@ -6288,6 +6664,7 @@ function formatMessageContent(message) {
|
|
|
6288
6664
|
`);
|
|
6289
6665
|
}
|
|
6290
6666
|
function toMarkdown(conversation, options2 = {}) {
|
|
6667
|
+
assertConversationSafe(conversation);
|
|
6291
6668
|
const resolved = resolveMarkdownOptions(options2);
|
|
6292
6669
|
const prepared = prepareConversationForMarkdown(conversation, resolved);
|
|
6293
6670
|
if (resolved.includeMetadata) {
|
|
@@ -6298,7 +6675,7 @@ function toMarkdown(conversation, options2 = {}) {
|
|
|
6298
6675
|
function toMarkdownSimple(conversation) {
|
|
6299
6676
|
const sections = [];
|
|
6300
6677
|
for (const message of getOrderedMessages(conversation)) {
|
|
6301
|
-
const roleName =
|
|
6678
|
+
const roleName = ROLE_LABELS[message.role];
|
|
6302
6679
|
const header = `### ${roleName}`;
|
|
6303
6680
|
const content = formatMessageContent(message);
|
|
6304
6681
|
sections.push(`${header}
|
|
@@ -6349,7 +6726,7 @@ function toMarkdownWithMetadata(conversation, _options) {
|
|
|
6349
6726
|
}
|
|
6350
6727
|
const messageSections = [];
|
|
6351
6728
|
for (const message of getOrderedMessages(conversation)) {
|
|
6352
|
-
const roleName =
|
|
6729
|
+
const roleName = ROLE_LABELS[message.role];
|
|
6353
6730
|
const header = `### ${roleName} (${message.id})`;
|
|
6354
6731
|
const content = formatMessageContent(message);
|
|
6355
6732
|
messageSections.push(`${header}
|
|
@@ -6374,10 +6751,13 @@ function generateId() {
|
|
|
6374
6751
|
function fromMarkdown(markdown) {
|
|
6375
6752
|
const trimmed = markdown.trim();
|
|
6376
6753
|
const hasFrontmatter = trimmed.startsWith("---");
|
|
6377
|
-
|
|
6378
|
-
|
|
6754
|
+
const conversation = hasFrontmatter ? parseMarkdownWithMetadata(trimmed) : parseMarkdownSimple(trimmed);
|
|
6755
|
+
try {
|
|
6756
|
+
assertConversationSafe(conversation);
|
|
6757
|
+
} catch (error2) {
|
|
6758
|
+
throw new MarkdownParseError(`Invalid markdown conversation: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
6379
6759
|
}
|
|
6380
|
-
return
|
|
6760
|
+
return conversation;
|
|
6381
6761
|
}
|
|
6382
6762
|
function parseMarkdownWithMetadata(trimmed) {
|
|
6383
6763
|
let parsed;
|
|
@@ -6396,7 +6776,7 @@ function parseMarkdownWithMetadata(trimmed) {
|
|
|
6396
6776
|
let match;
|
|
6397
6777
|
while ((match = messagePattern.exec(body)) !== null) {
|
|
6398
6778
|
const [, roleDisplay, messageId, contentBody] = match;
|
|
6399
|
-
const role =
|
|
6779
|
+
const role = LABEL_TO_ROLE[roleDisplay];
|
|
6400
6780
|
if (!role) {
|
|
6401
6781
|
throw new MarkdownParseError(`Unknown role: ${roleDisplay}`);
|
|
6402
6782
|
}
|
|
@@ -6453,7 +6833,7 @@ function parseMarkdownSimple(body) {
|
|
|
6453
6833
|
let position = 0;
|
|
6454
6834
|
while ((match = messagePattern.exec(body)) !== null) {
|
|
6455
6835
|
const [, roleDisplay, contentBody] = match;
|
|
6456
|
-
const role =
|
|
6836
|
+
const role = LABEL_TO_ROLE[roleDisplay];
|
|
6457
6837
|
if (!role) {
|
|
6458
6838
|
throw new MarkdownParseError(`Unknown role: ${roleDisplay}`);
|
|
6459
6839
|
}
|
|
@@ -6502,4 +6882,4 @@ export {
|
|
|
6502
6882
|
LABEL_TO_ROLE
|
|
6503
6883
|
};
|
|
6504
6884
|
|
|
6505
|
-
//# debugId=
|
|
6885
|
+
//# debugId=C9F3624DCBE2A76564756E2164756E21
|