@chaoslabs/ai-sdk 0.0.6 → 0.0.7
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/package.json +1 -1
- package/dist/__tests__/http-streaming.test.d.ts +0 -15
- package/dist/__tests__/http-streaming.test.js +0 -1401
- package/dist/__tests__/stream.test.d.ts +0 -1
- package/dist/__tests__/stream.test.js +0 -345
- package/dist/__tests__/trivial.test.d.ts +0 -1
- package/dist/__tests__/trivial.test.js +0 -6
- package/dist/blocks.d.ts +0 -108
- package/dist/blocks.js +0 -246
- package/dist/conversation.d.ts +0 -136
- package/dist/conversation.js +0 -230
- package/dist/primitives.d.ts +0 -157
- package/dist/primitives.js +0 -220
package/dist/blocks.js
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
// Chaos AI SDK - Block Utilities
|
|
2
|
-
//
|
|
3
|
-
// Helper functions for working with blocks extracted from responses.
|
|
4
|
-
import { extractBlocks, isTableBlock, isChartBlock, isTransactionActionBlock, isMarkdownBlock, isInteractiveBlock, } from './types.js';
|
|
5
|
-
// ============================================================================
|
|
6
|
-
// Block Extraction Utilities
|
|
7
|
-
// ============================================================================
|
|
8
|
-
/**
|
|
9
|
-
* Extract all table blocks from a response.
|
|
10
|
-
*/
|
|
11
|
-
export function extractTableBlocks(response) {
|
|
12
|
-
return extractBlocks(response).filter(isTableBlock);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Extract all chart blocks from a response.
|
|
16
|
-
*/
|
|
17
|
-
export function extractChartBlocks(response) {
|
|
18
|
-
return extractBlocks(response).filter(isChartBlock);
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Extract all transaction action blocks from a response.
|
|
22
|
-
*/
|
|
23
|
-
export function extractTransactionBlocks(response) {
|
|
24
|
-
return extractBlocks(response).filter(isTransactionActionBlock);
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Extract all markdown blocks from a response.
|
|
28
|
-
*/
|
|
29
|
-
export function extractMarkdownBlocks(response) {
|
|
30
|
-
return extractBlocks(response).filter(isMarkdownBlock);
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Extract all interactive blocks from a response.
|
|
34
|
-
*/
|
|
35
|
-
export function extractInteractiveBlocks(response) {
|
|
36
|
-
return extractBlocks(response).filter(isInteractiveBlock);
|
|
37
|
-
}
|
|
38
|
-
// ============================================================================
|
|
39
|
-
// Block Search Utilities
|
|
40
|
-
// ============================================================================
|
|
41
|
-
/**
|
|
42
|
-
* Find the first table block with a matching title.
|
|
43
|
-
*/
|
|
44
|
-
export function findTableByTitle(response, title) {
|
|
45
|
-
return extractTableBlocks(response).find((block) => block.title.toLowerCase().includes(title.toLowerCase()));
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Find the first chart block with a matching title.
|
|
49
|
-
*/
|
|
50
|
-
export function findChartByTitle(response, title) {
|
|
51
|
-
return extractChartBlocks(response).find((block) => block.title.toLowerCase().includes(title.toLowerCase()));
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Find transaction blocks containing a specific primitive type.
|
|
55
|
-
*/
|
|
56
|
-
export function findTransactionsByPrimitive(response, primitiveType) {
|
|
57
|
-
return extractTransactionBlocks(response).filter((block) => block.primitives?.some((p) => p.primitive === primitiveType));
|
|
58
|
-
}
|
|
59
|
-
// ============================================================================
|
|
60
|
-
// Primitive Extraction
|
|
61
|
-
// ============================================================================
|
|
62
|
-
/**
|
|
63
|
-
* Extract all primitives from all transaction blocks.
|
|
64
|
-
*/
|
|
65
|
-
export function extractPrimitives(response) {
|
|
66
|
-
const primitives = [];
|
|
67
|
-
for (const block of extractTransactionBlocks(response)) {
|
|
68
|
-
if (block.primitives) {
|
|
69
|
-
primitives.push(...block.primitives);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return primitives;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Extract primitives of a specific type.
|
|
76
|
-
*/
|
|
77
|
-
export function extractPrimitivesByType(response, primitiveType) {
|
|
78
|
-
return extractPrimitives(response).filter((p) => p.primitive === primitiveType);
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Get unique primitive types from a response.
|
|
82
|
-
*/
|
|
83
|
-
export function getPrimitiveTypes(response) {
|
|
84
|
-
const types = new Set();
|
|
85
|
-
for (const primitive of extractPrimitives(response)) {
|
|
86
|
-
types.add(primitive.primitive);
|
|
87
|
-
}
|
|
88
|
-
return Array.from(types);
|
|
89
|
-
}
|
|
90
|
-
// ============================================================================
|
|
91
|
-
// Table Utilities
|
|
92
|
-
// ============================================================================
|
|
93
|
-
/**
|
|
94
|
-
* Convert a table block to an array of objects.
|
|
95
|
-
* Each object has keys from the table headers.
|
|
96
|
-
*/
|
|
97
|
-
export function tableToObjects(table) {
|
|
98
|
-
const { tableHeaders, tableRows } = table;
|
|
99
|
-
return tableRows.map((row) => {
|
|
100
|
-
const obj = {};
|
|
101
|
-
for (let i = 0; i < tableHeaders.length; i++) {
|
|
102
|
-
obj[tableHeaders[i]] = row[i];
|
|
103
|
-
}
|
|
104
|
-
return obj;
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Get a specific column from a table block.
|
|
109
|
-
*/
|
|
110
|
-
export function getTableColumn(table, columnName) {
|
|
111
|
-
const columnIndex = table.tableHeaders.indexOf(columnName);
|
|
112
|
-
if (columnIndex === -1)
|
|
113
|
-
return [];
|
|
114
|
-
return table.tableRows.map((row) => row[columnIndex]);
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Find a row in a table by matching a column value.
|
|
118
|
-
*/
|
|
119
|
-
export function findTableRow(table, columnName, value) {
|
|
120
|
-
const columnIndex = table.tableHeaders.indexOf(columnName);
|
|
121
|
-
if (columnIndex === -1)
|
|
122
|
-
return undefined;
|
|
123
|
-
return table.tableRows.find((row) => row[columnIndex] === value);
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Get table dimensions.
|
|
127
|
-
*/
|
|
128
|
-
export function getTableDimensions(table) {
|
|
129
|
-
return {
|
|
130
|
-
columns: table.tableHeaders.length,
|
|
131
|
-
rows: table.tableRows.length,
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
// ============================================================================
|
|
135
|
-
// Chart Utilities
|
|
136
|
-
// ============================================================================
|
|
137
|
-
/**
|
|
138
|
-
* Get chart data as label-value pairs.
|
|
139
|
-
* Works with both segments and legacy data formats.
|
|
140
|
-
*/
|
|
141
|
-
export function getChartData(chart) {
|
|
142
|
-
if (chart.segments) {
|
|
143
|
-
return chart.segments.map((s) => ({ label: s.label, value: s.value }));
|
|
144
|
-
}
|
|
145
|
-
if (chart.data) {
|
|
146
|
-
return chart.data.map(([label, value]) => ({ label, value }));
|
|
147
|
-
}
|
|
148
|
-
return [];
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Get the total value of all chart segments.
|
|
152
|
-
*/
|
|
153
|
-
export function getChartTotal(chart) {
|
|
154
|
-
return getChartData(chart).reduce((sum, item) => sum + item.value, 0);
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Get chart segment percentages.
|
|
158
|
-
*/
|
|
159
|
-
export function getChartPercentages(chart) {
|
|
160
|
-
const data = getChartData(chart);
|
|
161
|
-
const total = data.reduce((sum, item) => sum + item.value, 0);
|
|
162
|
-
if (total === 0)
|
|
163
|
-
return data.map((d) => ({ label: d.label, percentage: 0 }));
|
|
164
|
-
return data.map((d) => ({
|
|
165
|
-
label: d.label,
|
|
166
|
-
percentage: (d.value / total) * 100,
|
|
167
|
-
}));
|
|
168
|
-
}
|
|
169
|
-
// ============================================================================
|
|
170
|
-
// Risk Utilities
|
|
171
|
-
// ============================================================================
|
|
172
|
-
/**
|
|
173
|
-
* Get all warnings from transaction blocks.
|
|
174
|
-
*/
|
|
175
|
-
export function getAllWarnings(response) {
|
|
176
|
-
const warnings = [];
|
|
177
|
-
for (const block of extractTransactionBlocks(response)) {
|
|
178
|
-
if (block.risks?.warnings) {
|
|
179
|
-
warnings.push(...block.risks.warnings);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return warnings;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Get all blockers from transaction blocks.
|
|
186
|
-
*/
|
|
187
|
-
export function getAllBlockers(response) {
|
|
188
|
-
const blockers = [];
|
|
189
|
-
for (const block of extractTransactionBlocks(response)) {
|
|
190
|
-
if (block.risks?.blockers) {
|
|
191
|
-
blockers.push(...block.risks.blockers);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return blockers;
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Get the highest risk level from all transaction blocks.
|
|
198
|
-
*/
|
|
199
|
-
export function getHighestRiskLevel(response) {
|
|
200
|
-
const riskLevels = ['low', 'medium', 'high', 'critical'];
|
|
201
|
-
let highestIndex = -1;
|
|
202
|
-
let highestLevel;
|
|
203
|
-
for (const block of extractTransactionBlocks(response)) {
|
|
204
|
-
if (block.risks?.level) {
|
|
205
|
-
const index = riskLevels.indexOf(block.risks.level.toLowerCase());
|
|
206
|
-
if (index > highestIndex) {
|
|
207
|
-
highestIndex = index;
|
|
208
|
-
highestLevel = block.risks.level;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
return highestLevel;
|
|
213
|
-
}
|
|
214
|
-
// ============================================================================
|
|
215
|
-
// Block Statistics
|
|
216
|
-
// ============================================================================
|
|
217
|
-
/**
|
|
218
|
-
* Count blocks by type in a response.
|
|
219
|
-
*/
|
|
220
|
-
export function countBlocksByType(response) {
|
|
221
|
-
const counts = {
|
|
222
|
-
table: 0,
|
|
223
|
-
chart: 0,
|
|
224
|
-
transaction_action: 0,
|
|
225
|
-
markdown: 0,
|
|
226
|
-
interactive: 0,
|
|
227
|
-
};
|
|
228
|
-
for (const block of extractBlocks(response)) {
|
|
229
|
-
if (block.type in counts) {
|
|
230
|
-
counts[block.type]++;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return counts;
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Check if a response contains any blocks.
|
|
237
|
-
*/
|
|
238
|
-
export function hasBlocks(response) {
|
|
239
|
-
return extractBlocks(response).length > 0;
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Check if a response contains a specific block type.
|
|
243
|
-
*/
|
|
244
|
-
export function hasBlockType(response, type) {
|
|
245
|
-
return extractBlocks(response).some((block) => block.type === type);
|
|
246
|
-
}
|
package/dist/conversation.d.ts
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import type { Chaos } from './client.js';
|
|
2
|
-
import type { InputItem, Response, RequestMetadata } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Options for creating a new conversation.
|
|
5
|
-
*/
|
|
6
|
-
export interface ConversationOptions {
|
|
7
|
-
/** Model to use (defaults to WALLET_MODEL) */
|
|
8
|
-
model?: string;
|
|
9
|
-
/** Maximum number of messages to keep in history */
|
|
10
|
-
maxHistoryLength?: number;
|
|
11
|
-
/** User identifier */
|
|
12
|
-
userId: string;
|
|
13
|
-
/** Wallet identifier */
|
|
14
|
-
walletId: string;
|
|
15
|
-
/** Optional initial session ID (auto-generated if not provided) */
|
|
16
|
-
sessionId?: string;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Statistics about the conversation.
|
|
20
|
-
*/
|
|
21
|
-
export interface ConversationStats {
|
|
22
|
-
/** Number of user turns */
|
|
23
|
-
userTurns: number;
|
|
24
|
-
/** Number of assistant turns */
|
|
25
|
-
assistantTurns: number;
|
|
26
|
-
/** Total messages in history */
|
|
27
|
-
totalMessages: number;
|
|
28
|
-
/** Session ID */
|
|
29
|
-
sessionId: string;
|
|
30
|
-
/** When the conversation started */
|
|
31
|
-
startedAt: Date;
|
|
32
|
-
/** When the last message was sent */
|
|
33
|
-
lastMessageAt: Date | null;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Manages a multi-turn conversation with history tracking.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```typescript
|
|
40
|
-
* import { Chaos, Conversation } from '@chaoslabs/ai-sdk';
|
|
41
|
-
*
|
|
42
|
-
* const chaos = new Chaos({ apiKey: 'ck-...' });
|
|
43
|
-
* const conversation = new Conversation(chaos, {
|
|
44
|
-
* userId: 'user-123',
|
|
45
|
-
* walletId: '0x...',
|
|
46
|
-
* });
|
|
47
|
-
*
|
|
48
|
-
* // Send messages - history is tracked automatically
|
|
49
|
-
* const response1 = await conversation.send("What's my portfolio value?");
|
|
50
|
-
* const response2 = await conversation.send("Which asset has the highest allocation?");
|
|
51
|
-
*
|
|
52
|
-
* // Get conversation stats
|
|
53
|
-
* console.log(conversation.stats);
|
|
54
|
-
*
|
|
55
|
-
* // Reset for a new conversation
|
|
56
|
-
* conversation.reset();
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
|
-
export declare class Conversation {
|
|
60
|
-
private client;
|
|
61
|
-
private model;
|
|
62
|
-
private maxHistoryLength;
|
|
63
|
-
private history;
|
|
64
|
-
private metadata;
|
|
65
|
-
private userTurns;
|
|
66
|
-
private assistantTurns;
|
|
67
|
-
private startedAt;
|
|
68
|
-
private lastMessageAt;
|
|
69
|
-
constructor(client: Chaos, options: ConversationOptions);
|
|
70
|
-
/**
|
|
71
|
-
* Get the current session ID.
|
|
72
|
-
*/
|
|
73
|
-
get sessionId(): string;
|
|
74
|
-
/**
|
|
75
|
-
* Get the conversation history.
|
|
76
|
-
*/
|
|
77
|
-
get messages(): readonly InputItem[];
|
|
78
|
-
/**
|
|
79
|
-
* Get conversation statistics.
|
|
80
|
-
*/
|
|
81
|
-
get stats(): ConversationStats;
|
|
82
|
-
/**
|
|
83
|
-
* Send a message and get a response.
|
|
84
|
-
* Automatically manages conversation history.
|
|
85
|
-
*/
|
|
86
|
-
send(message: string): Promise<Response>;
|
|
87
|
-
/**
|
|
88
|
-
* Add a user message to the history without sending.
|
|
89
|
-
* Useful for restoring conversation state.
|
|
90
|
-
*/
|
|
91
|
-
addUserMessage(content: string): void;
|
|
92
|
-
/**
|
|
93
|
-
* Add an assistant message to the history.
|
|
94
|
-
* Useful for restoring conversation state.
|
|
95
|
-
*/
|
|
96
|
-
addAssistantMessage(content: string): void;
|
|
97
|
-
/**
|
|
98
|
-
* Add a system message to the history.
|
|
99
|
-
*/
|
|
100
|
-
addSystemMessage(content: string): void;
|
|
101
|
-
/**
|
|
102
|
-
* Reset the conversation to start fresh.
|
|
103
|
-
* Generates a new session ID and clears history.
|
|
104
|
-
*/
|
|
105
|
-
reset(): void;
|
|
106
|
-
/**
|
|
107
|
-
* Clear the history but keep the same session ID.
|
|
108
|
-
*/
|
|
109
|
-
clearHistory(): void;
|
|
110
|
-
/**
|
|
111
|
-
* Fork this conversation to create a branch.
|
|
112
|
-
* The new conversation has the same history but a new session ID.
|
|
113
|
-
*/
|
|
114
|
-
fork(): Conversation;
|
|
115
|
-
/**
|
|
116
|
-
* Serialize the conversation to JSON for persistence.
|
|
117
|
-
*/
|
|
118
|
-
toJSON(): {
|
|
119
|
-
sessionId: string;
|
|
120
|
-
history: InputItem[];
|
|
121
|
-
metadata: RequestMetadata;
|
|
122
|
-
stats: ConversationStats;
|
|
123
|
-
};
|
|
124
|
-
/**
|
|
125
|
-
* Restore conversation state from JSON.
|
|
126
|
-
*/
|
|
127
|
-
static fromJSON(client: Chaos, data: {
|
|
128
|
-
sessionId: string;
|
|
129
|
-
history: InputItem[];
|
|
130
|
-
metadata: RequestMetadata;
|
|
131
|
-
}): Conversation;
|
|
132
|
-
/**
|
|
133
|
-
* Trim history to stay within maxHistoryLength.
|
|
134
|
-
*/
|
|
135
|
-
private trimHistory;
|
|
136
|
-
}
|
package/dist/conversation.js
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
// Chaos AI SDK - Conversation Management
|
|
2
|
-
//
|
|
3
|
-
// A class for managing multi-turn conversations with history tracking.
|
|
4
|
-
import { extractText } from './types.js';
|
|
5
|
-
import { WALLET_MODEL } from './request.js';
|
|
6
|
-
/**
|
|
7
|
-
* Manages a multi-turn conversation with history tracking.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* import { Chaos, Conversation } from '@chaoslabs/ai-sdk';
|
|
12
|
-
*
|
|
13
|
-
* const chaos = new Chaos({ apiKey: 'ck-...' });
|
|
14
|
-
* const conversation = new Conversation(chaos, {
|
|
15
|
-
* userId: 'user-123',
|
|
16
|
-
* walletId: '0x...',
|
|
17
|
-
* });
|
|
18
|
-
*
|
|
19
|
-
* // Send messages - history is tracked automatically
|
|
20
|
-
* const response1 = await conversation.send("What's my portfolio value?");
|
|
21
|
-
* const response2 = await conversation.send("Which asset has the highest allocation?");
|
|
22
|
-
*
|
|
23
|
-
* // Get conversation stats
|
|
24
|
-
* console.log(conversation.stats);
|
|
25
|
-
*
|
|
26
|
-
* // Reset for a new conversation
|
|
27
|
-
* conversation.reset();
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
export class Conversation {
|
|
31
|
-
client;
|
|
32
|
-
model;
|
|
33
|
-
maxHistoryLength;
|
|
34
|
-
history = [];
|
|
35
|
-
metadata;
|
|
36
|
-
userTurns = 0;
|
|
37
|
-
assistantTurns = 0;
|
|
38
|
-
startedAt;
|
|
39
|
-
lastMessageAt = null;
|
|
40
|
-
constructor(client, options) {
|
|
41
|
-
this.client = client;
|
|
42
|
-
this.model = options.model || WALLET_MODEL;
|
|
43
|
-
this.maxHistoryLength = options.maxHistoryLength || 50;
|
|
44
|
-
this.startedAt = new Date();
|
|
45
|
-
this.metadata = {
|
|
46
|
-
user_id: options.userId,
|
|
47
|
-
wallet_id: options.walletId,
|
|
48
|
-
session_id: options.sessionId || `session-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Get the current session ID.
|
|
53
|
-
*/
|
|
54
|
-
get sessionId() {
|
|
55
|
-
return this.metadata.session_id;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Get the conversation history.
|
|
59
|
-
*/
|
|
60
|
-
get messages() {
|
|
61
|
-
return [...this.history];
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Get conversation statistics.
|
|
65
|
-
*/
|
|
66
|
-
get stats() {
|
|
67
|
-
return {
|
|
68
|
-
userTurns: this.userTurns,
|
|
69
|
-
assistantTurns: this.assistantTurns,
|
|
70
|
-
totalMessages: this.history.length,
|
|
71
|
-
sessionId: this.metadata.session_id,
|
|
72
|
-
startedAt: this.startedAt,
|
|
73
|
-
lastMessageAt: this.lastMessageAt,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Send a message and get a response.
|
|
78
|
-
* Automatically manages conversation history.
|
|
79
|
-
*/
|
|
80
|
-
async send(message) {
|
|
81
|
-
// Add user message to history
|
|
82
|
-
this.addUserMessage(message);
|
|
83
|
-
// Send request with full history
|
|
84
|
-
const response = await this.client.chat.responses.create({
|
|
85
|
-
model: this.model,
|
|
86
|
-
input: [...this.history],
|
|
87
|
-
metadata: this.metadata,
|
|
88
|
-
});
|
|
89
|
-
// Add assistant response to history if successful
|
|
90
|
-
if (response.status === 'completed') {
|
|
91
|
-
const text = extractText(response);
|
|
92
|
-
if (text) {
|
|
93
|
-
this.addAssistantMessage(text);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
this.lastMessageAt = new Date();
|
|
97
|
-
return response;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Add a user message to the history without sending.
|
|
101
|
-
* Useful for restoring conversation state.
|
|
102
|
-
*/
|
|
103
|
-
addUserMessage(content) {
|
|
104
|
-
this.history.push({
|
|
105
|
-
type: 'message',
|
|
106
|
-
role: 'user',
|
|
107
|
-
content,
|
|
108
|
-
});
|
|
109
|
-
this.userTurns++;
|
|
110
|
-
this.trimHistory();
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Add an assistant message to the history.
|
|
114
|
-
* Useful for restoring conversation state.
|
|
115
|
-
*/
|
|
116
|
-
addAssistantMessage(content) {
|
|
117
|
-
// Store assistant responses as user messages with prefix for context
|
|
118
|
-
// This matches the pattern used in the multi-turn example
|
|
119
|
-
this.history.push({
|
|
120
|
-
type: 'message',
|
|
121
|
-
role: 'user',
|
|
122
|
-
content: `[Assistant]: ${content}`,
|
|
123
|
-
});
|
|
124
|
-
this.assistantTurns++;
|
|
125
|
-
this.trimHistory();
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Add a system message to the history.
|
|
129
|
-
*/
|
|
130
|
-
addSystemMessage(content) {
|
|
131
|
-
this.history.push({
|
|
132
|
-
type: 'message',
|
|
133
|
-
role: 'system',
|
|
134
|
-
content,
|
|
135
|
-
});
|
|
136
|
-
this.trimHistory();
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Reset the conversation to start fresh.
|
|
140
|
-
* Generates a new session ID and clears history.
|
|
141
|
-
*/
|
|
142
|
-
reset() {
|
|
143
|
-
this.history = [];
|
|
144
|
-
this.userTurns = 0;
|
|
145
|
-
this.assistantTurns = 0;
|
|
146
|
-
this.startedAt = new Date();
|
|
147
|
-
this.lastMessageAt = null;
|
|
148
|
-
this.metadata.session_id = `session-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Clear the history but keep the same session ID.
|
|
152
|
-
*/
|
|
153
|
-
clearHistory() {
|
|
154
|
-
this.history = [];
|
|
155
|
-
this.userTurns = 0;
|
|
156
|
-
this.assistantTurns = 0;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Fork this conversation to create a branch.
|
|
160
|
-
* The new conversation has the same history but a new session ID.
|
|
161
|
-
*/
|
|
162
|
-
fork() {
|
|
163
|
-
const forked = new Conversation(this.client, {
|
|
164
|
-
model: this.model,
|
|
165
|
-
maxHistoryLength: this.maxHistoryLength,
|
|
166
|
-
userId: this.metadata.user_id,
|
|
167
|
-
walletId: this.metadata.wallet_id,
|
|
168
|
-
});
|
|
169
|
-
// Copy history
|
|
170
|
-
for (const msg of this.history) {
|
|
171
|
-
if (msg.role === 'user') {
|
|
172
|
-
if (msg.content.startsWith('[Assistant]: ')) {
|
|
173
|
-
forked.history.push(msg);
|
|
174
|
-
forked.assistantTurns++;
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
forked.history.push(msg);
|
|
178
|
-
forked.userTurns++;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
forked.history.push(msg);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return forked;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Serialize the conversation to JSON for persistence.
|
|
189
|
-
*/
|
|
190
|
-
toJSON() {
|
|
191
|
-
return {
|
|
192
|
-
sessionId: this.metadata.session_id,
|
|
193
|
-
history: [...this.history],
|
|
194
|
-
metadata: { ...this.metadata },
|
|
195
|
-
stats: this.stats,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Restore conversation state from JSON.
|
|
200
|
-
*/
|
|
201
|
-
static fromJSON(client, data) {
|
|
202
|
-
const conversation = new Conversation(client, {
|
|
203
|
-
userId: data.metadata.user_id,
|
|
204
|
-
walletId: data.metadata.wallet_id,
|
|
205
|
-
sessionId: data.sessionId,
|
|
206
|
-
});
|
|
207
|
-
// Restore history
|
|
208
|
-
for (const msg of data.history) {
|
|
209
|
-
conversation.history.push(msg);
|
|
210
|
-
if (msg.role === 'user') {
|
|
211
|
-
if (msg.content.startsWith('[Assistant]: ')) {
|
|
212
|
-
conversation.assistantTurns++;
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
conversation.userTurns++;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return conversation;
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Trim history to stay within maxHistoryLength.
|
|
223
|
-
*/
|
|
224
|
-
trimHistory() {
|
|
225
|
-
if (this.history.length > this.maxHistoryLength) {
|
|
226
|
-
const excess = this.history.length - this.maxHistoryLength;
|
|
227
|
-
this.history = this.history.slice(excess);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|