@agentxjs/devtools 1.9.5-dev → 2.0.0
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 +284 -0
- package/dist/bdd/cli.d.ts +1 -0
- package/dist/bdd/cli.js +117 -0
- package/dist/bdd/cli.js.map +1 -0
- package/dist/bdd/index.d.ts +202 -0
- package/dist/bdd/index.js +381 -0
- package/dist/bdd/index.js.map +1 -0
- package/dist/chunk-6OHXS7LW.js +297 -0
- package/dist/chunk-6OHXS7LW.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-DR45HEV4.js +152 -0
- package/dist/chunk-DR45HEV4.js.map +1 -0
- package/dist/chunk-J6L73HM5.js +301 -0
- package/dist/chunk-J6L73HM5.js.map +1 -0
- package/dist/chunk-S7J75AXG.js +64 -0
- package/dist/chunk-S7J75AXG.js.map +1 -0
- package/dist/fixtures/index.d.ts +49 -0
- package/dist/fixtures/index.js +22 -0
- package/dist/fixtures/index.js.map +1 -0
- package/dist/index.d.ts +240 -0
- package/dist/index.js +269 -0
- package/dist/index.js.map +1 -0
- package/dist/mock/index.d.ts +115 -0
- package/dist/mock/index.js +11 -0
- package/dist/mock/index.js.map +1 -0
- package/dist/recorder/index.d.ts +120 -0
- package/dist/recorder/index.js +10 -0
- package/dist/recorder/index.js.map +1 -0
- package/dist/types-C6Lf3vz2.d.ts +78 -0
- package/package.json +63 -8
- package/src/Devtools.ts +11 -14
- package/src/bdd/agent-doc-tester.ts +130 -0
- package/src/bdd/agent-ui-tester.ts +88 -0
- package/src/bdd/cli.ts +166 -0
- package/src/bdd/cucumber.config.ts +40 -0
- package/src/bdd/dev-server.ts +82 -0
- package/src/bdd/index.ts +41 -0
- package/src/bdd/paths.ts +140 -0
- package/src/bdd/playwright.ts +110 -0
- package/src/env.ts +97 -0
- package/src/index.ts +6 -1
- package/src/mock/MockDriver.ts +21 -12
- package/src/recorder/RecordingDriver.ts +1 -5
- package/scripts/record-fixture.ts +0 -148
- package/tsconfig.json +0 -10
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
// fixtures/index.ts
|
|
2
|
+
var SIMPLE_REPLY = {
|
|
3
|
+
name: "simple-reply",
|
|
4
|
+
description: "Simple text response without tool calls",
|
|
5
|
+
events: [
|
|
6
|
+
{
|
|
7
|
+
type: "message_start",
|
|
8
|
+
delay: 0,
|
|
9
|
+
data: {
|
|
10
|
+
message: {
|
|
11
|
+
id: "msg_mock_001",
|
|
12
|
+
model: "claude-mock"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: "text_content_block_start",
|
|
18
|
+
delay: 5,
|
|
19
|
+
index: 0,
|
|
20
|
+
data: {}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
type: "text_delta",
|
|
24
|
+
delay: 5,
|
|
25
|
+
data: { text: "Hello! " }
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: "text_delta",
|
|
29
|
+
delay: 10,
|
|
30
|
+
data: { text: "How can I " }
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
type: "text_delta",
|
|
34
|
+
delay: 10,
|
|
35
|
+
data: { text: "help you " }
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: "text_delta",
|
|
39
|
+
delay: 10,
|
|
40
|
+
data: { text: "today?" }
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: "text_content_block_stop",
|
|
44
|
+
delay: 5,
|
|
45
|
+
index: 0,
|
|
46
|
+
data: {}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: "message_stop",
|
|
50
|
+
delay: 5,
|
|
51
|
+
data: {
|
|
52
|
+
stopReason: "end_turn"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
};
|
|
57
|
+
var LONG_REPLY = {
|
|
58
|
+
name: "long-reply",
|
|
59
|
+
description: "Longer multi-sentence response",
|
|
60
|
+
events: [
|
|
61
|
+
{
|
|
62
|
+
type: "message_start",
|
|
63
|
+
delay: 0,
|
|
64
|
+
data: {
|
|
65
|
+
message: {
|
|
66
|
+
id: "msg_mock_002",
|
|
67
|
+
model: "claude-mock"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: "text_content_block_start",
|
|
73
|
+
delay: 5,
|
|
74
|
+
index: 0,
|
|
75
|
+
data: {}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
type: "text_delta",
|
|
79
|
+
delay: 5,
|
|
80
|
+
data: { text: "I'd be happy to help you with that!\n\n" }
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
type: "text_delta",
|
|
84
|
+
delay: 10,
|
|
85
|
+
data: { text: "Here's what I can do:\n" }
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
type: "text_delta",
|
|
89
|
+
delay: 10,
|
|
90
|
+
data: { text: "1. Answer your questions\n" }
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: "text_delta",
|
|
94
|
+
delay: 10,
|
|
95
|
+
data: { text: "2. Help with coding tasks\n" }
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: "text_delta",
|
|
99
|
+
delay: 10,
|
|
100
|
+
data: { text: "3. Assist with writing\n\n" }
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: "text_delta",
|
|
104
|
+
delay: 10,
|
|
105
|
+
data: { text: "What would you like to work on?" }
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
type: "text_content_block_stop",
|
|
109
|
+
delay: 5,
|
|
110
|
+
index: 0,
|
|
111
|
+
data: {}
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: "message_stop",
|
|
115
|
+
delay: 5,
|
|
116
|
+
data: {
|
|
117
|
+
stopReason: "end_turn"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
};
|
|
122
|
+
var TOOL_CALL = {
|
|
123
|
+
name: "tool-call",
|
|
124
|
+
description: "Response that includes a tool call",
|
|
125
|
+
events: [
|
|
126
|
+
{
|
|
127
|
+
type: "message_start",
|
|
128
|
+
delay: 0,
|
|
129
|
+
data: {
|
|
130
|
+
message: {
|
|
131
|
+
id: "msg_mock_003",
|
|
132
|
+
model: "claude-mock"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
type: "text_content_block_start",
|
|
138
|
+
delay: 5,
|
|
139
|
+
index: 0,
|
|
140
|
+
data: {}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: "text_delta",
|
|
144
|
+
delay: 5,
|
|
145
|
+
data: { text: "Let me check that for you." }
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
type: "text_content_block_stop",
|
|
149
|
+
delay: 5,
|
|
150
|
+
index: 0,
|
|
151
|
+
data: {}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
type: "tool_use_content_block_start",
|
|
155
|
+
delay: 10,
|
|
156
|
+
index: 1,
|
|
157
|
+
data: {
|
|
158
|
+
id: "tool_001",
|
|
159
|
+
name: "get_current_time"
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: "input_json_delta",
|
|
164
|
+
delay: 5,
|
|
165
|
+
index: 1,
|
|
166
|
+
data: { partialJson: "{" }
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
type: "input_json_delta",
|
|
170
|
+
delay: 5,
|
|
171
|
+
index: 1,
|
|
172
|
+
data: { partialJson: '"timezone":' }
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: "input_json_delta",
|
|
176
|
+
delay: 5,
|
|
177
|
+
index: 1,
|
|
178
|
+
data: { partialJson: '"UTC"' }
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: "input_json_delta",
|
|
182
|
+
delay: 5,
|
|
183
|
+
index: 1,
|
|
184
|
+
data: { partialJson: "}" }
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
type: "tool_use_content_block_stop",
|
|
188
|
+
delay: 5,
|
|
189
|
+
index: 1,
|
|
190
|
+
data: {}
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
type: "message_stop",
|
|
194
|
+
delay: 5,
|
|
195
|
+
data: {
|
|
196
|
+
stopReason: "tool_use"
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
// After tool result, continue with text
|
|
200
|
+
{
|
|
201
|
+
type: "message_start",
|
|
202
|
+
delay: 50,
|
|
203
|
+
data: {
|
|
204
|
+
message: {
|
|
205
|
+
id: "msg_mock_003b",
|
|
206
|
+
model: "claude-mock"
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
type: "text_content_block_start",
|
|
212
|
+
delay: 5,
|
|
213
|
+
index: 0,
|
|
214
|
+
data: {}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
type: "text_delta",
|
|
218
|
+
delay: 5,
|
|
219
|
+
data: { text: "The current time is 2:30 PM UTC." }
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
type: "text_content_block_stop",
|
|
223
|
+
delay: 5,
|
|
224
|
+
index: 0,
|
|
225
|
+
data: {}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
type: "message_stop",
|
|
229
|
+
delay: 5,
|
|
230
|
+
data: {
|
|
231
|
+
stopReason: "end_turn"
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
};
|
|
236
|
+
var ERROR_RESPONSE = {
|
|
237
|
+
name: "error",
|
|
238
|
+
description: "Simulates an API error",
|
|
239
|
+
events: [
|
|
240
|
+
{
|
|
241
|
+
type: "error_received",
|
|
242
|
+
delay: 50,
|
|
243
|
+
data: {
|
|
244
|
+
message: "Rate limit exceeded. Please try again later.",
|
|
245
|
+
errorCode: "rate_limit_error"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
]
|
|
249
|
+
};
|
|
250
|
+
var EMPTY_RESPONSE = {
|
|
251
|
+
name: "empty",
|
|
252
|
+
description: "Empty response with no content",
|
|
253
|
+
events: [
|
|
254
|
+
{
|
|
255
|
+
type: "message_start",
|
|
256
|
+
delay: 0,
|
|
257
|
+
data: {
|
|
258
|
+
message: {
|
|
259
|
+
id: "msg_mock_empty",
|
|
260
|
+
model: "claude-mock"
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
type: "message_stop",
|
|
266
|
+
delay: 5,
|
|
267
|
+
data: {
|
|
268
|
+
stopReason: "end_turn"
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
]
|
|
272
|
+
};
|
|
273
|
+
var BUILTIN_FIXTURES = /* @__PURE__ */ new Map([
|
|
274
|
+
["simple-reply", SIMPLE_REPLY],
|
|
275
|
+
["long-reply", LONG_REPLY],
|
|
276
|
+
["tool-call", TOOL_CALL],
|
|
277
|
+
["error", ERROR_RESPONSE],
|
|
278
|
+
["empty", EMPTY_RESPONSE]
|
|
279
|
+
]);
|
|
280
|
+
function getFixture(name) {
|
|
281
|
+
return BUILTIN_FIXTURES.get(name);
|
|
282
|
+
}
|
|
283
|
+
function listFixtures() {
|
|
284
|
+
return Array.from(BUILTIN_FIXTURES.keys());
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export {
|
|
288
|
+
SIMPLE_REPLY,
|
|
289
|
+
LONG_REPLY,
|
|
290
|
+
TOOL_CALL,
|
|
291
|
+
ERROR_RESPONSE,
|
|
292
|
+
EMPTY_RESPONSE,
|
|
293
|
+
BUILTIN_FIXTURES,
|
|
294
|
+
getFixture,
|
|
295
|
+
listFixtures
|
|
296
|
+
};
|
|
297
|
+
//# sourceMappingURL=chunk-6OHXS7LW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../fixtures/index.ts"],"sourcesContent":["/**\n * Built-in Fixtures for MockDriver\n *\n * These fixtures simulate common conversation patterns.\n * They can be used directly or as templates for custom fixtures.\n */\n\nimport type { Fixture } from \"../src/types\";\n\n/**\n * Simple text reply - no tool calls\n *\n * Simulates: \"Hello!\" -> \"Hello! How can I help you today?\"\n */\nexport const SIMPLE_REPLY: Fixture = {\n name: \"simple-reply\",\n description: \"Simple text response without tool calls\",\n events: [\n {\n type: \"message_start\",\n delay: 0,\n data: {\n message: {\n id: \"msg_mock_001\",\n model: \"claude-mock\",\n },\n },\n },\n {\n type: \"text_content_block_start\",\n delay: 5,\n index: 0,\n data: {},\n },\n {\n type: \"text_delta\",\n delay: 5,\n data: { text: \"Hello! \" },\n },\n {\n type: \"text_delta\",\n delay: 10,\n data: { text: \"How can I \" },\n },\n {\n type: \"text_delta\",\n delay: 10,\n data: { text: \"help you \" },\n },\n {\n type: \"text_delta\",\n delay: 10,\n data: { text: \"today?\" },\n },\n {\n type: \"text_content_block_stop\",\n delay: 5,\n index: 0,\n data: {},\n },\n {\n type: \"message_stop\",\n delay: 5,\n data: {\n stopReason: \"end_turn\",\n },\n },\n ],\n};\n\n/**\n * Multi-paragraph response\n *\n * Simulates a longer response with multiple sentences\n */\nexport const LONG_REPLY: Fixture = {\n name: \"long-reply\",\n description: \"Longer multi-sentence response\",\n events: [\n {\n type: \"message_start\",\n delay: 0,\n data: {\n message: {\n id: \"msg_mock_002\",\n model: \"claude-mock\",\n },\n },\n },\n {\n type: \"text_content_block_start\",\n delay: 5,\n index: 0,\n data: {},\n },\n {\n type: \"text_delta\",\n delay: 5,\n data: { text: \"I'd be happy to help you with that!\\n\\n\" },\n },\n {\n type: \"text_delta\",\n delay: 10,\n data: { text: \"Here's what I can do:\\n\" },\n },\n {\n type: \"text_delta\",\n delay: 10,\n data: { text: \"1. Answer your questions\\n\" },\n },\n {\n type: \"text_delta\",\n delay: 10,\n data: { text: \"2. Help with coding tasks\\n\" },\n },\n {\n type: \"text_delta\",\n delay: 10,\n data: { text: \"3. Assist with writing\\n\\n\" },\n },\n {\n type: \"text_delta\",\n delay: 10,\n data: { text: \"What would you like to work on?\" },\n },\n {\n type: \"text_content_block_stop\",\n delay: 5,\n index: 0,\n data: {},\n },\n {\n type: \"message_stop\",\n delay: 5,\n data: {\n stopReason: \"end_turn\",\n },\n },\n ],\n};\n\n/**\n * Tool call response - demonstrates tool_use flow\n *\n * Simulates: \"What time is it?\" -> tool_call(get_current_time) -> \"It's 2:30 PM\"\n */\nexport const TOOL_CALL: Fixture = {\n name: \"tool-call\",\n description: \"Response that includes a tool call\",\n events: [\n {\n type: \"message_start\",\n delay: 0,\n data: {\n message: {\n id: \"msg_mock_003\",\n model: \"claude-mock\",\n },\n },\n },\n {\n type: \"text_content_block_start\",\n delay: 5,\n index: 0,\n data: {},\n },\n {\n type: \"text_delta\",\n delay: 5,\n data: { text: \"Let me check that for you.\" },\n },\n {\n type: \"text_content_block_stop\",\n delay: 5,\n index: 0,\n data: {},\n },\n {\n type: \"tool_use_content_block_start\",\n delay: 10,\n index: 1,\n data: {\n id: \"tool_001\",\n name: \"get_current_time\",\n },\n },\n {\n type: \"input_json_delta\",\n delay: 5,\n index: 1,\n data: { partialJson: \"{\" },\n },\n {\n type: \"input_json_delta\",\n delay: 5,\n index: 1,\n data: { partialJson: '\"timezone\":' },\n },\n {\n type: \"input_json_delta\",\n delay: 5,\n index: 1,\n data: { partialJson: '\"UTC\"' },\n },\n {\n type: \"input_json_delta\",\n delay: 5,\n index: 1,\n data: { partialJson: \"}\" },\n },\n {\n type: \"tool_use_content_block_stop\",\n delay: 5,\n index: 1,\n data: {},\n },\n {\n type: \"message_stop\",\n delay: 5,\n data: {\n stopReason: \"tool_use\",\n },\n },\n // After tool result, continue with text\n {\n type: \"message_start\",\n delay: 50,\n data: {\n message: {\n id: \"msg_mock_003b\",\n model: \"claude-mock\",\n },\n },\n },\n {\n type: \"text_content_block_start\",\n delay: 5,\n index: 0,\n data: {},\n },\n {\n type: \"text_delta\",\n delay: 5,\n data: { text: \"The current time is 2:30 PM UTC.\" },\n },\n {\n type: \"text_content_block_stop\",\n delay: 5,\n index: 0,\n data: {},\n },\n {\n type: \"message_stop\",\n delay: 5,\n data: {\n stopReason: \"end_turn\",\n },\n },\n ],\n};\n\n/**\n * Error response\n */\nexport const ERROR_RESPONSE: Fixture = {\n name: \"error\",\n description: \"Simulates an API error\",\n events: [\n {\n type: \"error_received\",\n delay: 50,\n data: {\n message: \"Rate limit exceeded. Please try again later.\",\n errorCode: \"rate_limit_error\",\n },\n },\n ],\n};\n\n/**\n * Empty response (for edge case testing)\n */\nexport const EMPTY_RESPONSE: Fixture = {\n name: \"empty\",\n description: \"Empty response with no content\",\n events: [\n {\n type: \"message_start\",\n delay: 0,\n data: {\n message: {\n id: \"msg_mock_empty\",\n model: \"claude-mock\",\n },\n },\n },\n {\n type: \"message_stop\",\n delay: 5,\n data: {\n stopReason: \"end_turn\",\n },\n },\n ],\n};\n\n/**\n * All built-in fixtures\n */\nexport const BUILTIN_FIXTURES: Map<string, Fixture> = new Map([\n [\"simple-reply\", SIMPLE_REPLY],\n [\"long-reply\", LONG_REPLY],\n [\"tool-call\", TOOL_CALL],\n [\"error\", ERROR_RESPONSE],\n [\"empty\", EMPTY_RESPONSE],\n]);\n\n/**\n * Get a built-in fixture by name\n */\nexport function getFixture(name: string): Fixture | undefined {\n return BUILTIN_FIXTURES.get(name);\n}\n\n/**\n * List all built-in fixture names\n */\nexport function listFixtures(): string[] {\n return Array.from(BUILTIN_FIXTURES.keys());\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
__require
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=chunk-DGUM43GV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// src/recorder/RecordingDriver.ts
|
|
2
|
+
import { createLogger } from "commonxjs/logger";
|
|
3
|
+
var logger = createLogger("devtools/RecordingDriver");
|
|
4
|
+
var RecordingDriver = class {
|
|
5
|
+
name = "RecordingDriver";
|
|
6
|
+
realDriver;
|
|
7
|
+
fixtureName;
|
|
8
|
+
fixtureDescription;
|
|
9
|
+
recordedEvents = [];
|
|
10
|
+
recordingStartTime = 0;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.realDriver = options.driver;
|
|
13
|
+
this.fixtureName = options.name;
|
|
14
|
+
this.fixtureDescription = options.description;
|
|
15
|
+
logger.info("RecordingDriver created", { name: this.fixtureName });
|
|
16
|
+
}
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Driver Interface Properties (delegate to real driver)
|
|
19
|
+
// ============================================================================
|
|
20
|
+
get sessionId() {
|
|
21
|
+
return this.realDriver.sessionId;
|
|
22
|
+
}
|
|
23
|
+
get state() {
|
|
24
|
+
return this.realDriver.state;
|
|
25
|
+
}
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Lifecycle Methods (delegate to real driver)
|
|
28
|
+
// ============================================================================
|
|
29
|
+
async initialize() {
|
|
30
|
+
await this.realDriver.initialize();
|
|
31
|
+
this.recordingStartTime = Date.now();
|
|
32
|
+
this.recordedEvents = [];
|
|
33
|
+
logger.info("RecordingDriver initialized, recording started", {
|
|
34
|
+
name: this.fixtureName
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async dispose() {
|
|
38
|
+
await this.realDriver.dispose();
|
|
39
|
+
logger.info("RecordingDriver disposed", {
|
|
40
|
+
name: this.fixtureName,
|
|
41
|
+
eventsRecorded: this.recordedEvents.length
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Core Methods
|
|
46
|
+
// ============================================================================
|
|
47
|
+
/**
|
|
48
|
+
* Receive a user message and return stream of events
|
|
49
|
+
*
|
|
50
|
+
* Wraps the real driver's receive() and records all events.
|
|
51
|
+
*/
|
|
52
|
+
async *receive(message) {
|
|
53
|
+
logger.debug("RecordingDriver receiving message", {
|
|
54
|
+
name: this.fixtureName
|
|
55
|
+
});
|
|
56
|
+
for await (const event of this.realDriver.receive(message)) {
|
|
57
|
+
this.recordEvent(event);
|
|
58
|
+
yield event;
|
|
59
|
+
}
|
|
60
|
+
logger.debug("RecordingDriver receive completed", {
|
|
61
|
+
name: this.fixtureName,
|
|
62
|
+
eventsRecorded: this.recordedEvents.length
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Interrupt current operation (delegate to real driver)
|
|
67
|
+
*/
|
|
68
|
+
interrupt() {
|
|
69
|
+
this.realDriver.interrupt();
|
|
70
|
+
}
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// Recording Methods
|
|
73
|
+
// ============================================================================
|
|
74
|
+
/**
|
|
75
|
+
* Record an event
|
|
76
|
+
*/
|
|
77
|
+
recordEvent(event) {
|
|
78
|
+
this.recordedEvents.push({
|
|
79
|
+
event,
|
|
80
|
+
timestamp: Date.now()
|
|
81
|
+
});
|
|
82
|
+
logger.debug("Event recorded", {
|
|
83
|
+
type: event.type,
|
|
84
|
+
totalEvents: this.recordedEvents.length
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get the recorded fixture
|
|
89
|
+
*/
|
|
90
|
+
getFixture() {
|
|
91
|
+
const events = [];
|
|
92
|
+
let lastTimestamp = this.recordingStartTime;
|
|
93
|
+
for (const recorded of this.recordedEvents) {
|
|
94
|
+
const delay = recorded.timestamp - lastTimestamp;
|
|
95
|
+
lastTimestamp = recorded.timestamp;
|
|
96
|
+
events.push({
|
|
97
|
+
type: recorded.event.type,
|
|
98
|
+
delay: Math.max(0, delay),
|
|
99
|
+
data: recorded.event.data
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
name: this.fixtureName,
|
|
104
|
+
description: this.fixtureDescription,
|
|
105
|
+
recordedAt: this.recordingStartTime,
|
|
106
|
+
events
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Save the recorded fixture to a JSON file
|
|
111
|
+
*/
|
|
112
|
+
async saveFixture(filePath) {
|
|
113
|
+
const fixture = this.getFixture();
|
|
114
|
+
const json = JSON.stringify(fixture, null, 2);
|
|
115
|
+
const { writeFile } = await import("fs/promises");
|
|
116
|
+
await writeFile(filePath, json, "utf-8");
|
|
117
|
+
logger.info("Fixture saved", {
|
|
118
|
+
path: filePath,
|
|
119
|
+
name: fixture.name,
|
|
120
|
+
eventCount: fixture.events.length
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get the number of recorded events
|
|
125
|
+
*/
|
|
126
|
+
get eventCount() {
|
|
127
|
+
return this.recordedEvents.length;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Clear recorded events (start fresh recording)
|
|
131
|
+
*/
|
|
132
|
+
clearRecording() {
|
|
133
|
+
this.recordedEvents = [];
|
|
134
|
+
this.recordingStartTime = Date.now();
|
|
135
|
+
logger.debug("Recording cleared");
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get raw recorded events (for debugging)
|
|
139
|
+
*/
|
|
140
|
+
getRawEvents() {
|
|
141
|
+
return [...this.recordedEvents];
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
function createRecordingDriver(options) {
|
|
145
|
+
return new RecordingDriver(options);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export {
|
|
149
|
+
RecordingDriver,
|
|
150
|
+
createRecordingDriver
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=chunk-DR45HEV4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/recorder/RecordingDriver.ts"],"sourcesContent":["/**\n * RecordingDriver - Wraps a real driver to record events\n *\n * Used to capture real LLM API responses and save them as fixtures.\n * These fixtures can then be played back by MockDriver for testing.\n *\n * Usage:\n * ```typescript\n * import { createClaudeDriver } from \"@agentxjs/claude-driver\";\n * import { RecordingDriver } from \"@agentxjs/devtools/recorder\";\n *\n * // Create real driver\n * const realDriver = createClaudeDriver(config);\n *\n * // Wrap with recorder\n * const recorder = new RecordingDriver({\n * driver: realDriver,\n * name: \"my-scenario\",\n * description: \"User asks about weather\",\n * });\n *\n * await recorder.initialize();\n *\n * // Use like a normal driver - events are recorded\n * for await (const event of recorder.receive({ content: \"Hello\" })) {\n * console.log(event);\n * }\n *\n * // Save the fixture\n * await recorder.saveFixture(\"./fixtures/my-scenario.json\");\n * ```\n */\n\nimport type { Driver, DriverState, DriverStreamEvent } from \"@agentxjs/core/driver\";\nimport type { UserMessage } from \"@agentxjs/core/agent\";\nimport type { Fixture, FixtureEvent } from \"../types\";\nimport { createLogger } from \"commonxjs/logger\";\n\nconst logger = createLogger(\"devtools/RecordingDriver\");\n\n/**\n * Options for RecordingDriver\n */\nexport interface RecordingDriverOptions {\n /**\n * The real driver to wrap\n */\n driver: Driver;\n\n /**\n * Fixture name for the recording\n */\n name: string;\n\n /**\n * Description for the recording\n */\n description?: string;\n}\n\n/**\n * Recorded event with timing\n */\ninterface RecordedEvent {\n event: DriverStreamEvent;\n timestamp: number;\n}\n\n/**\n * RecordingDriver - Records events from a real driver\n *\n * Implements the new Driver interface by wrapping a real driver\n * and intercepting events from receive().\n */\nexport class RecordingDriver implements Driver {\n readonly name = \"RecordingDriver\";\n\n private readonly realDriver: Driver;\n private readonly fixtureName: string;\n private readonly fixtureDescription?: string;\n\n private recordedEvents: RecordedEvent[] = [];\n private recordingStartTime: number = 0;\n\n constructor(options: RecordingDriverOptions) {\n this.realDriver = options.driver;\n this.fixtureName = options.name;\n this.fixtureDescription = options.description;\n\n logger.info(\"RecordingDriver created\", { name: this.fixtureName });\n }\n\n // ============================================================================\n // Driver Interface Properties (delegate to real driver)\n // ============================================================================\n\n get sessionId(): string | null {\n return this.realDriver.sessionId;\n }\n\n get state(): DriverState {\n return this.realDriver.state;\n }\n\n // ============================================================================\n // Lifecycle Methods (delegate to real driver)\n // ============================================================================\n\n async initialize(): Promise<void> {\n await this.realDriver.initialize();\n this.recordingStartTime = Date.now();\n this.recordedEvents = [];\n logger.info(\"RecordingDriver initialized, recording started\", {\n name: this.fixtureName,\n });\n }\n\n async dispose(): Promise<void> {\n await this.realDriver.dispose();\n logger.info(\"RecordingDriver disposed\", {\n name: this.fixtureName,\n eventsRecorded: this.recordedEvents.length,\n });\n }\n\n // ============================================================================\n // Core Methods\n // ============================================================================\n\n /**\n * Receive a user message and return stream of events\n *\n * Wraps the real driver's receive() and records all events.\n */\n async *receive(message: UserMessage): AsyncIterable<DriverStreamEvent> {\n logger.debug(\"RecordingDriver receiving message\", {\n name: this.fixtureName,\n });\n\n // Call the real driver and intercept events\n for await (const event of this.realDriver.receive(message)) {\n // Record the event\n this.recordEvent(event);\n\n // Pass through to caller\n yield event;\n }\n\n logger.debug(\"RecordingDriver receive completed\", {\n name: this.fixtureName,\n eventsRecorded: this.recordedEvents.length,\n });\n }\n\n /**\n * Interrupt current operation (delegate to real driver)\n */\n interrupt(): void {\n this.realDriver.interrupt();\n }\n\n // ============================================================================\n // Recording Methods\n // ============================================================================\n\n /**\n * Record an event\n */\n private recordEvent(event: DriverStreamEvent): void {\n this.recordedEvents.push({\n event,\n timestamp: Date.now(),\n });\n\n logger.debug(\"Event recorded\", {\n type: event.type,\n totalEvents: this.recordedEvents.length,\n });\n }\n\n /**\n * Get the recorded fixture\n */\n getFixture(): Fixture {\n const events: FixtureEvent[] = [];\n let lastTimestamp = this.recordingStartTime;\n\n for (const recorded of this.recordedEvents) {\n const delay = recorded.timestamp - lastTimestamp;\n lastTimestamp = recorded.timestamp;\n\n events.push({\n type: recorded.event.type,\n delay: Math.max(0, delay),\n data: recorded.event.data,\n });\n }\n\n return {\n name: this.fixtureName,\n description: this.fixtureDescription,\n recordedAt: this.recordingStartTime,\n events,\n };\n }\n\n /**\n * Save the recorded fixture to a JSON file\n */\n async saveFixture(filePath: string): Promise<void> {\n const fixture = this.getFixture();\n const json = JSON.stringify(fixture, null, 2);\n\n // Use dynamic import for Node.js fs\n const { writeFile } = await import(\"node:fs/promises\");\n await writeFile(filePath, json, \"utf-8\");\n\n logger.info(\"Fixture saved\", {\n path: filePath,\n name: fixture.name,\n eventCount: fixture.events.length,\n });\n }\n\n /**\n * Get the number of recorded events\n */\n get eventCount(): number {\n return this.recordedEvents.length;\n }\n\n /**\n * Clear recorded events (start fresh recording)\n */\n clearRecording(): void {\n this.recordedEvents = [];\n this.recordingStartTime = Date.now();\n logger.debug(\"Recording cleared\");\n }\n\n /**\n * Get raw recorded events (for debugging)\n */\n getRawEvents(): RecordedEvent[] {\n return [...this.recordedEvents];\n }\n}\n\n/**\n * Create a RecordingDriver that wraps a real driver\n */\nexport function createRecordingDriver(options: RecordingDriverOptions): RecordingDriver {\n return new RecordingDriver(options);\n}\n"],"mappings":"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","names":[]}
|