@mappies/miniwat-agent 0.4.0 → 0.8.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 +914 -1
- package/dist/index.cjs +490 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -6
- package/dist/index.d.ts +86 -6
- package/dist/index.js +488 -7
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,14 +1,41 @@
|
|
|
1
1
|
// src/entities/agent.ts
|
|
2
|
-
import { Message, MessageType } from "@mappies/miniwat-agent-core";
|
|
3
|
-
import { PassThrough } from "stream";
|
|
2
|
+
import { ResponseMessage, Message, MessageType, StopReason } from "@mappies/miniwat-agent-core";
|
|
3
|
+
import { PassThrough, Readable } from "stream";
|
|
4
|
+
var verbose = !!process.env.VERBOSE;
|
|
5
|
+
function log(...data) {
|
|
6
|
+
if (verbose) console.log(data);
|
|
7
|
+
}
|
|
4
8
|
var Agent = class {
|
|
5
9
|
constructor(config) {
|
|
6
10
|
this.model = config.model;
|
|
7
11
|
this.instruction = config.instruction;
|
|
8
12
|
this.toolDispatcher = config.toolDispatcher;
|
|
13
|
+
this.planner = config.planner;
|
|
14
|
+
this.maxToolCalls = config.maxToolCalls;
|
|
9
15
|
}
|
|
10
16
|
async invoke(prompt, session, option) {
|
|
11
|
-
|
|
17
|
+
option = {
|
|
18
|
+
maxToolCalls: this.maxToolCalls,
|
|
19
|
+
...option
|
|
20
|
+
};
|
|
21
|
+
return this.planner ? this.invokeWithPlanner(this.planner, prompt, session, option) : this.invokeDirect(prompt, session, option);
|
|
22
|
+
}
|
|
23
|
+
async stream(prompt, session, option) {
|
|
24
|
+
option = {
|
|
25
|
+
maxToolCalls: this.maxToolCalls,
|
|
26
|
+
...option
|
|
27
|
+
};
|
|
28
|
+
return this.planner ? this.streamWithPlanner(this.planner, prompt, session, option) : this.streamDirect(prompt, session, option);
|
|
29
|
+
}
|
|
30
|
+
async invokeDirect(prompt, session, option) {
|
|
31
|
+
if (!session.messages) {
|
|
32
|
+
session.messages = [];
|
|
33
|
+
}
|
|
34
|
+
session.messages.push(new Message({
|
|
35
|
+
type: MessageType.User,
|
|
36
|
+
content: prompt,
|
|
37
|
+
createdTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
38
|
+
}));
|
|
12
39
|
const response = await this.model.invoke(session.messages, {
|
|
13
40
|
...option,
|
|
14
41
|
instruction: this.instruction
|
|
@@ -19,7 +46,41 @@ var Agent = class {
|
|
|
19
46
|
}
|
|
20
47
|
return response;
|
|
21
48
|
}
|
|
22
|
-
async
|
|
49
|
+
async invokeWithPlanner(planner, prompt, session, option) {
|
|
50
|
+
const plan = await planner.createPlan(prompt, session.messages);
|
|
51
|
+
log(">>>", plan);
|
|
52
|
+
if (!session.messages) {
|
|
53
|
+
session.messages = [];
|
|
54
|
+
}
|
|
55
|
+
session.messages.push(new Message({
|
|
56
|
+
type: MessageType.User,
|
|
57
|
+
content: prompt,
|
|
58
|
+
createdTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
59
|
+
}));
|
|
60
|
+
if (plan.directAnswer) {
|
|
61
|
+
const message = new Message({
|
|
62
|
+
type: MessageType.Agent,
|
|
63
|
+
content: plan.directAnswer.content,
|
|
64
|
+
createdTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
65
|
+
});
|
|
66
|
+
session.messages.push(message);
|
|
67
|
+
return new ResponseMessage({
|
|
68
|
+
message,
|
|
69
|
+
stopReason: StopReason.END_TURN,
|
|
70
|
+
tokenUsage: plan.directAnswer.tokenUsage
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const response = await this.executePlan(planner, plan, session, option);
|
|
74
|
+
session.messages.push(response.message);
|
|
75
|
+
if (option?.event?.onResponse) {
|
|
76
|
+
await option.event.onResponse(response.message);
|
|
77
|
+
}
|
|
78
|
+
return response;
|
|
79
|
+
}
|
|
80
|
+
async streamDirect(prompt, session, option) {
|
|
81
|
+
if (!session.messages) {
|
|
82
|
+
session.messages = [];
|
|
83
|
+
}
|
|
23
84
|
session.messages.push(new Message({
|
|
24
85
|
type: MessageType.User,
|
|
25
86
|
content: prompt,
|
|
@@ -51,7 +112,7 @@ var Agent = class {
|
|
|
51
112
|
content,
|
|
52
113
|
createdTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
53
114
|
});
|
|
54
|
-
session.messages
|
|
115
|
+
session.messages?.push(responseMessage);
|
|
55
116
|
if (option?.event?.onResponse) {
|
|
56
117
|
await option.event.onResponse(responseMessage);
|
|
57
118
|
}
|
|
@@ -73,6 +134,174 @@ var Agent = class {
|
|
|
73
134
|
source.pipe(tee);
|
|
74
135
|
return tee;
|
|
75
136
|
}
|
|
137
|
+
async streamWithPlanner(planner, prompt, session, option) {
|
|
138
|
+
const plan = await planner.createPlan(prompt, session.messages);
|
|
139
|
+
log(">>>", plan);
|
|
140
|
+
if (!session.messages) {
|
|
141
|
+
session.messages = [];
|
|
142
|
+
}
|
|
143
|
+
session.messages.push(new Message({
|
|
144
|
+
type: MessageType.User,
|
|
145
|
+
content: prompt,
|
|
146
|
+
createdTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
147
|
+
}));
|
|
148
|
+
if (plan.directAnswer) {
|
|
149
|
+
const textContent = plan.directAnswer.content;
|
|
150
|
+
const message = new Message({
|
|
151
|
+
type: MessageType.Agent,
|
|
152
|
+
content: textContent,
|
|
153
|
+
createdTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
154
|
+
});
|
|
155
|
+
session.messages.push(message);
|
|
156
|
+
if (option?.event?.onResponse) {
|
|
157
|
+
await option.event.onResponse(message);
|
|
158
|
+
}
|
|
159
|
+
const resultDirectStream = new Readable({
|
|
160
|
+
read() {
|
|
161
|
+
this.push(Buffer.from(textContent, "utf8"));
|
|
162
|
+
this.push(null);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
resultDirectStream.promise = Promise.resolve();
|
|
166
|
+
return resultDirectStream;
|
|
167
|
+
}
|
|
168
|
+
const source = new PassThrough();
|
|
169
|
+
(async () => {
|
|
170
|
+
try {
|
|
171
|
+
await this.executePlan(planner, plan, session, option, source);
|
|
172
|
+
source.end();
|
|
173
|
+
} catch (err) {
|
|
174
|
+
source.destroy(err);
|
|
175
|
+
}
|
|
176
|
+
})();
|
|
177
|
+
const tee = new PassThrough();
|
|
178
|
+
const chunks = [];
|
|
179
|
+
let sourceEnded = false;
|
|
180
|
+
let resolveCompleted;
|
|
181
|
+
let rejectCompleted;
|
|
182
|
+
tee.promise = new Promise((resolve, reject) => {
|
|
183
|
+
resolveCompleted = resolve;
|
|
184
|
+
rejectCompleted = reject;
|
|
185
|
+
});
|
|
186
|
+
source.on("data", (chunk) => {
|
|
187
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
188
|
+
});
|
|
189
|
+
source.on("end", async () => {
|
|
190
|
+
sourceEnded = true;
|
|
191
|
+
(async () => {
|
|
192
|
+
const content = Buffer.concat(chunks).toString("utf8");
|
|
193
|
+
if (content.trim().length > 0) {
|
|
194
|
+
let responseMessage = new Message({
|
|
195
|
+
type: MessageType.Agent,
|
|
196
|
+
content,
|
|
197
|
+
createdTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
198
|
+
});
|
|
199
|
+
session.messages?.push(responseMessage);
|
|
200
|
+
if (option?.event?.onResponse) {
|
|
201
|
+
await option.event.onResponse(responseMessage);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
resolveCompleted();
|
|
205
|
+
})().catch(rejectCompleted);
|
|
206
|
+
});
|
|
207
|
+
source.on("error", (error) => {
|
|
208
|
+
rejectCompleted(error);
|
|
209
|
+
tee.destroy(error);
|
|
210
|
+
});
|
|
211
|
+
tee.on("close", () => {
|
|
212
|
+
if (!sourceEnded && !source.destroyed) {
|
|
213
|
+
const err = new Error("Stream closed before completion");
|
|
214
|
+
rejectCompleted(err);
|
|
215
|
+
source.destroy(err);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
source.pipe(tee);
|
|
219
|
+
return tee;
|
|
220
|
+
}
|
|
221
|
+
async executePlan(planner, plan, session, option, outputStream) {
|
|
222
|
+
let activeTask = plan.getNextPendingTask();
|
|
223
|
+
if (option?.event?.onPlanUpdated) {
|
|
224
|
+
await option.event.onPlanUpdated(plan);
|
|
225
|
+
}
|
|
226
|
+
while (activeTask?.id) {
|
|
227
|
+
log(`[Planner] Processing Step ${activeTask.id}: ${activeTask.description}`);
|
|
228
|
+
plan.updateTaskStatus(activeTask.id, "running");
|
|
229
|
+
if (option?.event?.onPlanUpdated) {
|
|
230
|
+
await option.event.onPlanUpdated(plan);
|
|
231
|
+
}
|
|
232
|
+
const stepInstruction = plan.getInstruction(activeTask);
|
|
233
|
+
const conversationContext = (session.messages ?? []).slice(0, -1).map((message) => `${message.type}: ${message.content}`).join("\n\n");
|
|
234
|
+
const turnMessages = [
|
|
235
|
+
new Message({
|
|
236
|
+
type: MessageType.User,
|
|
237
|
+
content: `${conversationContext ? `CONVERSATION HISTORY
|
|
238
|
+
${conversationContext}
|
|
239
|
+
|
|
240
|
+
` : ""}${plan.getExecutionContext(activeTask.id)}`
|
|
241
|
+
})
|
|
242
|
+
];
|
|
243
|
+
let turnResultText = "";
|
|
244
|
+
const isLastTask = !plan.tasks?.find((t) => t.id > activeTask.id);
|
|
245
|
+
if (isLastTask) {
|
|
246
|
+
const stepStream = await this.model.stream(turnMessages, {
|
|
247
|
+
...option,
|
|
248
|
+
toolsEnabled: true,
|
|
249
|
+
instruction: { system: { value: stepInstruction } }
|
|
250
|
+
});
|
|
251
|
+
log("[Planner] Messages", turnMessages);
|
|
252
|
+
log("[Planner] SystemPrompt", stepInstruction);
|
|
253
|
+
for await (const chunk of stepStream) {
|
|
254
|
+
const textChunk = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
255
|
+
turnResultText += textChunk;
|
|
256
|
+
if (outputStream && !outputStream.destroyed) {
|
|
257
|
+
outputStream.write(textChunk);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
const taskInvoke = await this.model.invoke(turnMessages, {
|
|
262
|
+
...option,
|
|
263
|
+
toolsEnabled: true,
|
|
264
|
+
instruction: { system: { value: stepInstruction } }
|
|
265
|
+
});
|
|
266
|
+
turnResultText = taskInvoke.message.content || "";
|
|
267
|
+
log("[Planner] Messages", turnMessages);
|
|
268
|
+
log("[Planner] SystemPrompt", stepInstruction);
|
|
269
|
+
log("[Planner] Result", turnResultText);
|
|
270
|
+
}
|
|
271
|
+
plan.appendLogToTask(activeTask.id, turnResultText);
|
|
272
|
+
if (isLastTask) {
|
|
273
|
+
plan.updateTaskStatus(activeTask.id, "completed");
|
|
274
|
+
} else {
|
|
275
|
+
log(`[Reflection] Auditing output for Step ${activeTask.id}...`);
|
|
276
|
+
const isSuccessful = await planner.reflect(activeTask, turnResultText);
|
|
277
|
+
if (isSuccessful) {
|
|
278
|
+
plan.updateTaskStatus(activeTask.id, "completed");
|
|
279
|
+
log(`[Planner] Step ${activeTask.id} passed verification.`);
|
|
280
|
+
} else {
|
|
281
|
+
plan.updateTaskStatus(activeTask.id, "failed");
|
|
282
|
+
log(`[Planner] Step ${activeTask.id} failed verification. Re-planning...`);
|
|
283
|
+
await planner.replan(plan, activeTask, turnResultText);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (option?.event?.onPlanUpdated) {
|
|
287
|
+
await option.event.onPlanUpdated(plan);
|
|
288
|
+
}
|
|
289
|
+
activeTask = plan.getNextPendingTask();
|
|
290
|
+
}
|
|
291
|
+
if (option?.event?.onPlanUpdated) {
|
|
292
|
+
await option.event.onPlanUpdated(plan);
|
|
293
|
+
}
|
|
294
|
+
const finalAgentMsg = new Message({
|
|
295
|
+
type: MessageType.Agent,
|
|
296
|
+
content: plan.getLastCompletedOutput(),
|
|
297
|
+
createdTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
298
|
+
});
|
|
299
|
+
return new ResponseMessage({
|
|
300
|
+
message: finalAgentMsg,
|
|
301
|
+
stopReason: StopReason.END_TURN,
|
|
302
|
+
tokenUsage: { totalTokens: 0, inputTokens: 0, outputTokens: 0 }
|
|
303
|
+
});
|
|
304
|
+
}
|
|
76
305
|
};
|
|
77
306
|
|
|
78
307
|
// src/entities/agentConfig.ts
|
|
@@ -81,6 +310,8 @@ var AgentConfig = class {
|
|
|
81
310
|
this.instruction = data.instruction;
|
|
82
311
|
this.model = data.model;
|
|
83
312
|
this.toolDispatcher = data.toolDispatcher;
|
|
313
|
+
this.planner = data.planner;
|
|
314
|
+
this.maxToolCalls = data.maxToolCalls;
|
|
84
315
|
}
|
|
85
316
|
};
|
|
86
317
|
|
|
@@ -90,12 +321,262 @@ var Session = class {
|
|
|
90
321
|
constructor(data) {
|
|
91
322
|
this.id = data?.id || randomUUID();
|
|
92
323
|
this.name = data?.name;
|
|
93
|
-
this.messages = data?.messages
|
|
324
|
+
this.messages = data?.messages;
|
|
325
|
+
this.createdTimestamp = data?.createdTimestamp;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
// src/entities/planners/task.ts
|
|
330
|
+
var Task = class {
|
|
331
|
+
constructor(task) {
|
|
332
|
+
this.id = task.id;
|
|
333
|
+
this.description = task.description;
|
|
334
|
+
this.status = task.status;
|
|
335
|
+
this.executionLogs = task.executionLogs;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
// src/entities/planners/plan.ts
|
|
340
|
+
var Plan = class {
|
|
341
|
+
constructor(plan) {
|
|
342
|
+
this.id = plan?.id;
|
|
343
|
+
this.userGoal = plan?.userGoal;
|
|
344
|
+
this.tasks = plan?.tasks;
|
|
345
|
+
this.directAnswer = plan?.directAnswer;
|
|
346
|
+
this.createdAt = plan?.createdAt;
|
|
347
|
+
}
|
|
348
|
+
getInstruction(currentTask) {
|
|
349
|
+
return `You are working on one task which is a part of a structured plan.
|
|
350
|
+
|
|
351
|
+
Complete only the CURRENT TASK.
|
|
352
|
+
The current task is considered complete once you have gathered enough information to produce useful recommendations.
|
|
353
|
+
Do not attempt exhaustive research.
|
|
354
|
+
If the tool-use limit is reached, stop researching and complete the task using the information already gathered.
|
|
355
|
+
If additional information would only improve completeness rather than change the recommendation, stop researching and summarize what you have.
|
|
356
|
+
Treat completed task results as established context.
|
|
357
|
+
Do not repeat work already completed by previous tasks unless verification is necessary.
|
|
358
|
+
Use tools only for information required by the current task that is not already available.
|
|
359
|
+
|
|
360
|
+
CURRENT TASK:
|
|
361
|
+
${currentTask.description ?? ""}
|
|
362
|
+
`;
|
|
363
|
+
}
|
|
364
|
+
getExecutionContext(currentTaskId) {
|
|
365
|
+
const taskDirectives = (this.tasks ?? []).map((t) => `Step ${t.id} [${t.status || "pending"}]: ${t.description}`).join("\n");
|
|
366
|
+
const completedTaskResults = (this.tasks ?? []).filter((t) => t.id !== currentTaskId && t.status === "completed" && (t.executionLogs?.length ?? 0) > 0).map((t) => `Step ${t.id}: ${t.description}
|
|
367
|
+
Result:
|
|
368
|
+
${t.executionLogs[t.executionLogs.length - 1]}`).join("\n\n");
|
|
369
|
+
return `OVERALL GOAL
|
|
370
|
+
${this.userGoal ?? ""}
|
|
371
|
+
|
|
372
|
+
PLAN
|
|
373
|
+
${taskDirectives}
|
|
374
|
+
|
|
375
|
+
COMPLETED TASK RESULTS
|
|
376
|
+
${completedTaskResults || "None."}`;
|
|
377
|
+
}
|
|
378
|
+
getLastCompletedOutput() {
|
|
379
|
+
if (!this.tasks) {
|
|
380
|
+
return "";
|
|
381
|
+
}
|
|
382
|
+
for (let i = this.tasks.length - 1; i >= 0; i--) {
|
|
383
|
+
const task = this.tasks[i];
|
|
384
|
+
if (task.status === "completed" && task.executionLogs?.length) {
|
|
385
|
+
return task.executionLogs[task.executionLogs.length - 1];
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return "";
|
|
389
|
+
}
|
|
390
|
+
getNextPendingTask() {
|
|
391
|
+
if (!Array.isArray(this.tasks) || this.tasks.length === 0) {
|
|
392
|
+
return void 0;
|
|
393
|
+
}
|
|
394
|
+
return this.tasks.find((task) => task.status === "pending") || void 0;
|
|
395
|
+
}
|
|
396
|
+
updateTaskStatus(taskId, status) {
|
|
397
|
+
if (!Array.isArray(this.tasks)) {
|
|
398
|
+
throw new Error(`Could not update a task's status because tasks array is undefined.`);
|
|
399
|
+
}
|
|
400
|
+
const task = this.tasks.find((t) => t.id === taskId);
|
|
401
|
+
if (!task) {
|
|
402
|
+
throw new Error(`Could not update a task's status because the given task ID ${taskId} could not be found.`);
|
|
403
|
+
}
|
|
404
|
+
task.status = status;
|
|
405
|
+
}
|
|
406
|
+
appendLogToTask(taskId, log2) {
|
|
407
|
+
if (!Array.isArray(this.tasks)) {
|
|
408
|
+
throw new Error(`Could not update a task's status because tasks array is undefined.`);
|
|
409
|
+
}
|
|
410
|
+
const task = this.tasks.find((t) => t.id === taskId);
|
|
411
|
+
if (!task) {
|
|
412
|
+
throw new Error(`Could not update a task's status because the given task ID ${taskId} could not be found.`);
|
|
413
|
+
}
|
|
414
|
+
if (!task.executionLogs) {
|
|
415
|
+
task.executionLogs = [];
|
|
416
|
+
}
|
|
417
|
+
task.executionLogs.push(log2);
|
|
418
|
+
}
|
|
419
|
+
insertTask(afterStepId, description) {
|
|
420
|
+
if (Array.isArray(this.tasks) === false) {
|
|
421
|
+
throw new Error(`Could not inject a task because the tasks is undefined.`);
|
|
422
|
+
}
|
|
423
|
+
const targetIndex = this.tasks?.findIndex((s) => s.id === afterStepId);
|
|
424
|
+
if (targetIndex === -1) throw new Error(`Could not inject a task because the task '${afterStepId}' could not be found.`);
|
|
425
|
+
for (let i = targetIndex + 1; i < this.tasks.length; i++) {
|
|
426
|
+
const task = this.tasks[i];
|
|
427
|
+
if (task.id === void 0) {
|
|
428
|
+
throw new Error(`Could not inject a task because the tasks is undefined.`);
|
|
429
|
+
}
|
|
430
|
+
task.id += 1;
|
|
431
|
+
}
|
|
432
|
+
const newTask = new Task({
|
|
433
|
+
id: afterStepId + 1,
|
|
434
|
+
description,
|
|
435
|
+
status: "pending",
|
|
436
|
+
executionLogs: []
|
|
437
|
+
});
|
|
438
|
+
this.tasks.splice(targetIndex + 1, 0, newTask);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
// src/entities/planners/defaultPlanner.ts
|
|
443
|
+
import { Message as Message2, MessageType as MessageType2 } from "@mappies/miniwat-agent-core";
|
|
444
|
+
var DefaultPlanner = class {
|
|
445
|
+
constructor(model) {
|
|
446
|
+
this.model = model;
|
|
447
|
+
}
|
|
448
|
+
async callLLM(systemPrompt, userPrompt) {
|
|
449
|
+
return this.model.invoke(
|
|
450
|
+
[
|
|
451
|
+
new Message2({ type: MessageType2.User, content: userPrompt })
|
|
452
|
+
],
|
|
453
|
+
{
|
|
454
|
+
toolsEnabled: false,
|
|
455
|
+
instruction: {
|
|
456
|
+
system: { value: systemPrompt }
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
async createPlan(userGoal, conversationHistory) {
|
|
462
|
+
const systemPrompt = `Current time: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
463
|
+
|
|
464
|
+
You are a Routing and Planning Engine.
|
|
465
|
+
Analyze the input to decide if it requires multi-step tools/scripts, or if it can be directly answered.
|
|
466
|
+
|
|
467
|
+
Only give a direct answer when multi-step plan is not required.
|
|
468
|
+
|
|
469
|
+
If a plan is needed:
|
|
470
|
+
|
|
471
|
+
- Do not include directAnswer.
|
|
472
|
+
- Each task should represent a distinct, independently executable unit of work.
|
|
473
|
+
- Keep tightly coupled retrieval and processing together when they depend on the same data.
|
|
474
|
+
- When separating steps would require passing a large or structured dataset from one task to another, do not split them into separate tasks.
|
|
475
|
+
- If the user explicitly requests a single workflow or single task, create exactly one task unless doing so is impossible.
|
|
476
|
+
|
|
477
|
+
Output in JSON with the following structure:
|
|
478
|
+
{
|
|
479
|
+
"directAnswer": "String text if a direct answer can be made without a planning.",
|
|
480
|
+
"tasks": [
|
|
481
|
+
{ "id": 1, "description": "What to do" }
|
|
482
|
+
]
|
|
483
|
+
}`;
|
|
484
|
+
const conversationContext = (conversationHistory ?? []).map((message) => `${message.type}: ${message.content}`).join("\n\n");
|
|
485
|
+
const userPrompt = `${conversationContext ? `Conversation History:
|
|
486
|
+
${conversationContext}
|
|
487
|
+
|
|
488
|
+
` : ""}User Goal: "${userGoal}"`;
|
|
489
|
+
const rawResult = await this.callLLM(systemPrompt, userPrompt);
|
|
490
|
+
const content = rawResult.message.content.trim();
|
|
491
|
+
const cleanJson = content.replace(/```json|```/g, "").trim();
|
|
492
|
+
let parsed;
|
|
493
|
+
try {
|
|
494
|
+
parsed = JSON.parse(cleanJson);
|
|
495
|
+
if (parsed.tasks?.length) {
|
|
496
|
+
parsed.directAnswer = void 0;
|
|
497
|
+
}
|
|
498
|
+
} catch {
|
|
499
|
+
parsed = {
|
|
500
|
+
tasks: [],
|
|
501
|
+
directAnswer: content
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
const taskInstances = parsed.tasks?.map((t) => new Task({
|
|
505
|
+
id: t.id,
|
|
506
|
+
description: t.description,
|
|
507
|
+
status: "pending",
|
|
508
|
+
executionLogs: []
|
|
509
|
+
})) || [];
|
|
510
|
+
return new Plan({
|
|
511
|
+
id: crypto.randomUUID(),
|
|
512
|
+
userGoal,
|
|
513
|
+
directAnswer: parsed.directAnswer ? {
|
|
514
|
+
content: parsed.directAnswer,
|
|
515
|
+
tokenUsage: rawResult.tokenUsage
|
|
516
|
+
} : void 0,
|
|
517
|
+
tasks: taskInstances
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* PURE CRITIC INTERFACE
|
|
522
|
+
* Cross-references an execution string block against the target task expectations.
|
|
523
|
+
*/
|
|
524
|
+
async reflect(task, executionOutput) {
|
|
525
|
+
const systemPrompt = `Current time: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
526
|
+
|
|
527
|
+
You are a Quality Assurance Auditor.
|
|
528
|
+
Your only job is to evaluate whether the task objective has been sufficiently completed for the overall plan to continue safely.
|
|
529
|
+
|
|
530
|
+
CRITERIA TO MEET:
|
|
531
|
+
Task Objective: ${task.description}
|
|
532
|
+
|
|
533
|
+
OUTPUT FORMAT:
|
|
534
|
+
If the task is sufficiently complete for the plan to continue, output exactly: YES
|
|
535
|
+
If the task is missing or incorrect in a way that prevents the plan from continuing safely, output: NO: <brief reason describing only the missing or incorrect part>
|
|
536
|
+
Do not include any other words or preamble.`;
|
|
537
|
+
const response = await this.callLLM(systemPrompt, `Actual Agent Execution Log Output:
|
|
538
|
+
${executionOutput}`);
|
|
539
|
+
let result = response.message.content.trim().toUpperCase().startsWith("YES");
|
|
540
|
+
return result;
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* CONTEXTUAL WORKFLOW PATCHING
|
|
544
|
+
* Invokes an LLM strategy session to formulate an actionable patch, injecting it into the state array.
|
|
545
|
+
*/
|
|
546
|
+
async replan(plan, failedTask, failureOutput) {
|
|
547
|
+
const systemPrompt = `Current time: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
548
|
+
|
|
549
|
+
You are a Master System Architect. A sub-task has failed verification.
|
|
550
|
+
Analyze the original goal and failure log to generate a single "Recovery Task" to resolve the issue.
|
|
551
|
+
|
|
552
|
+
OUTPUT FORMAT:
|
|
553
|
+
You must respond with a raw JSON object matching this exact structure:
|
|
554
|
+
{
|
|
555
|
+
"recoveryDescription": "What the agent needs to do from scratch to fix this explicit error state",
|
|
556
|
+
}`;
|
|
557
|
+
const userPrompt = `
|
|
558
|
+
Overall Goal: ${plan.userGoal}
|
|
559
|
+
Failed Step Description: ${failedTask.description}
|
|
560
|
+
Actual Failed Output Received: ${failureOutput}
|
|
561
|
+
`;
|
|
562
|
+
const response = await this.callLLM(systemPrompt, userPrompt);
|
|
563
|
+
const cleanJson = response.message.content.replace(/```json|```/g, "").trim();
|
|
564
|
+
const parsed = JSON.parse(cleanJson);
|
|
565
|
+
if (failedTask.id === void 0) {
|
|
566
|
+
throw new Error("[Planner] Cannot execute replan tracking because the target task ID is undefined.");
|
|
567
|
+
}
|
|
568
|
+
plan.insertTask(
|
|
569
|
+
failedTask.id,
|
|
570
|
+
parsed.recoveryDescription
|
|
571
|
+
);
|
|
94
572
|
}
|
|
95
573
|
};
|
|
96
574
|
export {
|
|
97
575
|
Agent,
|
|
98
576
|
AgentConfig,
|
|
99
|
-
|
|
577
|
+
DefaultPlanner,
|
|
578
|
+
Plan,
|
|
579
|
+
Session,
|
|
580
|
+
Task
|
|
100
581
|
};
|
|
101
582
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/entities/agent.ts","../src/entities/agentConfig.ts","../src/entities/session.ts"],"sourcesContent":["import { Model, ModelOption, ResponseMessage, Instruction, Message, MessageType } from \"@mappies/miniwat-agent-core\";\nimport { AgentConfig } from \"./agentConfig\";\nimport { ToolDispatcher } from \"@mappies/miniwat-mcp-core\";\nimport { PassThrough, Readable } from \"stream\";\nimport { Session } from \"./session\";\n\nexport class Agent\n{\n public readonly instruction?: Instruction\n public readonly model: Model;\n public readonly toolDispatcher?: ToolDispatcher;\n\n constructor(config: AgentConfig)\n {\n this.model = config.model;\n this.instruction = config.instruction;\n this.toolDispatcher = config.toolDispatcher;\n }\n\n async invoke(prompt: string, session: Session, option?: Omit<ModelOption, 'instruction'>): Promise<ResponseMessage>\n {\n session.messages.push(new Message({type: MessageType.User, content: prompt, createdTimestamp: new Date().toISOString()}));\n\n const response = await this.model.invoke(session.messages, {\n ...option,\n instruction: this.instruction\n });\n\n session.messages.push(response.message);\n\n if(option?.event?.onResponse)\n {\n await option.event.onResponse(response.message);\n }\n\n return response;\n }\n\n async stream(prompt: string, session: Session, option?: Omit<ModelOption, \"instruction\">): Promise<Readable>\n {\n session.messages.push(new Message({\n type: MessageType.User,\n content: prompt,\n createdTimestamp: new Date().toISOString()\n }));\n\n const source = await this.model.stream(session.messages, {\n ...option,\n instruction: this.instruction\n });\n\n const tee = new PassThrough();\n const chunks: Buffer[] = [];\n let sourceEnded = false;\n\n let resolveCompleted!: () => void;\n let rejectCompleted!: (reason?: any) => void;\n (tee as any).promise = new Promise<void>((resolve, reject) =>\n {\n resolveCompleted = resolve;\n rejectCompleted = reject;\n });\n\n source.on(\"data\", (chunk) =>\n {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n });\n\n source.on(\"end\", async () =>\n {\n sourceEnded = true;\n \n (async ()=>\n {\n const content = Buffer.concat(chunks).toString(\"utf8\");\n\n if (content.trim().length > 0)\n {\n let responseMessage = new Message({\n type: MessageType.Agent,\n content,\n createdTimestamp: new Date().toISOString()\n });\n\n session.messages.push(responseMessage);\n\n if(option?.event?.onResponse)\n {\n await option.event.onResponse(responseMessage);\n }\n }\n\n resolveCompleted();\n })().catch(rejectCompleted);\n });\n\n source.on(\"error\", (error) =>\n {\n rejectCompleted(error);\n tee.destroy(error);\n });\n\n tee.on(\"close\", () =>\n {\n if (!sourceEnded && !source.destroyed)\n {\n const err = new Error(\"Stream closed before completion\");\n rejectCompleted(err)\n source.destroy(err);\n }\n });\n\n source.pipe(tee);\n\n return tee;\n }\n}","import { Model, Instruction } from \"@mappies/miniwat-agent-core\";\nimport { ToolDispatcher } from \"@mappies/miniwat-mcp-core\";\n\nexport class AgentConfig \n{\n /**\n * Agent instruction\n */\n instruction?: Instruction;\n\n /**\n * The language model used by this agent.\n */\n model: Model;\n\n /**\n * Tool dispatcher for tools.\n */\n toolDispatcher?: ToolDispatcher;\n\n constructor(data:AgentConfig)\n {\n this.instruction = data.instruction;\n this.model = data.model;\n this.toolDispatcher = data.toolDispatcher;\n }\n}","import { Message } from \"@mappies/miniwat-agent-core\";\nimport { randomUUID } from \"crypto\";\n\nexport class Session\n{\n public readonly id: string;\n public name?:string;\n public messages: Message[];\n\n constructor(data?:Partial<Session>)\n {\n this.id = data?.id || randomUUID();\n this.name = data?.name;\n this.messages = data?.messages || []\n }\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/entities/agent.ts","../src/entities/agentConfig.ts","../src/entities/session.ts","../src/entities/planners/task.ts","../src/entities/planners/plan.ts","../src/entities/planners/defaultPlanner.ts"],"sourcesContent":["import { Model, ResponseMessage, Instruction, Message, MessageType, StopReason } from \"@mappies/miniwat-agent-core\";\nimport { AgentConfig } from \"./agentConfig\";\nimport { ToolDispatcher } from \"@mappies/miniwat-mcp-core\";\nimport { PassThrough, Readable } from \"stream\";\nimport { Session } from \"./session\";\nimport { IPlanner } from \"../interfaces/iPlanner\";\nimport { Plan } from \"./planners/plan\";\nimport { AgentOption } from \"./agentOption\";\n\nlet verbose = !!process.env.VERBOSE;\n\nfunction log(...data:any[])\n{\n if(verbose) console.log(data);\n}\n\nexport class Agent\n{\n public readonly instruction?: Instruction\n public readonly model: Model;\n public readonly toolDispatcher?: ToolDispatcher;\n public readonly planner?: IPlanner;\n public readonly maxToolCalls?: number;\n\n constructor(config: AgentConfig)\n {\n this.model = config.model;\n this.instruction = config.instruction;\n this.toolDispatcher = config.toolDispatcher;\n this.planner = config.planner;\n this.maxToolCalls = config.maxToolCalls;\n }\n\n async invoke(prompt: string, session: Session, option?: Omit<AgentOption, 'instruction'>): Promise<ResponseMessage>\n {\n option = {\n maxToolCalls: this.maxToolCalls,\n ...option\n };\n \n return this.planner ? this.invokeWithPlanner(this.planner, prompt, session, option)\n : this.invokeDirect(prompt, session, option);\n }\n\n\n async stream(prompt: string, session: Session, option?: Omit<AgentOption, \"instruction\">): Promise<Readable>\n {\n option = {\n maxToolCalls: this.maxToolCalls,\n ...option\n };\n \n return this.planner ? this.streamWithPlanner(this.planner, prompt, session, option)\n : this.streamDirect(prompt, session, option);\n }\n\n private async invokeDirect(prompt: string, session: Session, option?: Omit<AgentOption, 'instruction'>): Promise<ResponseMessage>\n {\n if(!session.messages)\n {\n session.messages = [];\n }\n\n session.messages.push(new Message({\n type: MessageType.User, \n content: prompt, \n createdTimestamp: new Date().toISOString()\n }));\n\n const response = await this.model.invoke(session.messages, {\n ...option,\n instruction: this.instruction\n });\n\n session.messages.push(response.message);\n\n if(option?.event?.onResponse)\n {\n await option.event.onResponse(response.message);\n }\n\n return response;\n }\n\n private async invokeWithPlanner(planner: IPlanner, prompt: string, session: Session, option?: Omit<AgentOption, 'instruction'>): Promise<ResponseMessage>\n {\n const plan = await planner.createPlan(prompt, session.messages);\n\n log(\">>>\", plan)\n\n if(!session.messages)\n {\n session.messages = [];\n }\n\n session.messages.push(new Message({\n type: MessageType.User, \n content: prompt, \n createdTimestamp: new Date().toISOString()\n }));\n\n if(plan.directAnswer)\n {\n const message = new Message({\n type: MessageType.Agent, \n content: plan.directAnswer.content,\n createdTimestamp: new Date().toISOString()\n });\n\n session.messages.push(message);\n\n return new ResponseMessage({\n message,\n stopReason: StopReason.END_TURN,\n tokenUsage: plan.directAnswer.tokenUsage \n })\n }\n\n // No direct answer. Execute plan.\n const response = await this.executePlan(planner, plan, session, option);\n\n session.messages.push(response.message);\n\n if(option?.event?.onResponse)\n {\n await option.event.onResponse(response.message);\n }\n\n return response;\n }\n\n private async streamDirect(prompt: string, session: Session, option?: Omit<AgentOption, \"instruction\">): Promise<Readable>\n {\n if(!session.messages)\n {\n session.messages = [];\n }\n\n session.messages.push(new Message({\n type: MessageType.User,\n content: prompt,\n createdTimestamp: new Date().toISOString()\n }));\n\n const source = await this.model.stream(session.messages, {\n ...option,\n instruction: this.instruction\n });\n\n const tee = new PassThrough();\n const chunks: Buffer[] = [];\n let sourceEnded = false;\n\n let resolveCompleted!: () => void;\n let rejectCompleted!: (reason?: any) => void;\n (tee as any).promise = new Promise<void>((resolve, reject) =>\n {\n resolveCompleted = resolve;\n rejectCompleted = reject;\n });\n\n source.on(\"data\", (chunk) =>\n {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n });\n\n source.on(\"end\", async () =>\n {\n sourceEnded = true;\n\n (async ()=>\n {\n const content = Buffer.concat(chunks).toString(\"utf8\");\n\n if (content.trim().length > 0)\n {\n let responseMessage = new Message({\n type: MessageType.Agent,\n content,\n createdTimestamp: new Date().toISOString()\n });\n\n session.messages?.push(responseMessage);\n\n if(option?.event?.onResponse)\n {\n await option.event.onResponse(responseMessage);\n }\n }\n\n resolveCompleted();\n })().catch(rejectCompleted);\n });\n\n source.on(\"error\", (error) =>\n {\n rejectCompleted(error);\n tee.destroy(error);\n });\n\n tee.on(\"close\", () =>\n {\n if (!sourceEnded && !source.destroyed)\n {\n const err = new Error(\"Stream closed before completion\");\n rejectCompleted(err)\n source.destroy(err);\n }\n });\n\n source.pipe(tee);\n\n return tee;\n }\n\n private async streamWithPlanner(planner: IPlanner, prompt: string, session: Session, option?: Omit<AgentOption, \"instruction\">): Promise<Readable>\n {\n const plan = await planner.createPlan(prompt, session.messages);\n\n log(\">>>\", plan)\n\n if(!session.messages)\n {\n session.messages = [];\n }\n\n session.messages.push(new Message({\n type: MessageType.User,\n content: prompt,\n createdTimestamp: new Date().toISOString()\n }));\n\n if (plan.directAnswer)\n {\n const textContent = plan.directAnswer.content;\n\n const message = new Message({\n type: MessageType.Agent,\n content: textContent,\n createdTimestamp: new Date().toISOString()\n });\n\n session.messages.push(message);\n\n if (option?.event?.onResponse)\n {\n await option.event!.onResponse!(message);\n }\n\n const resultDirectStream = new Readable({\n read() {\n this.push(Buffer.from(textContent, \"utf8\"));\n this.push(null); // Signifies the end of stream.\n }\n });\n\n (resultDirectStream as any).promise = Promise.resolve();\n return resultDirectStream;\n }\n\n // No direct answer. Execute plan.\n const source = new PassThrough();\n\n // Execute the multi-turn loop in the background, piping chunks directly into 'source'\n (async () => {\n try \n {\n await this.executePlan(planner, plan, session, option, source);\n\n source.end(); // Safely close the source once all tasks are complete\n } \n catch (err: any) {\n source.destroy(err);\n }\n })();\n\n\n const tee = new PassThrough();\n const chunks: Buffer[] = [];\n let sourceEnded = false;\n\n let resolveCompleted!: () => void;\n let rejectCompleted!: (reason?: any) => void;\n (tee as any).promise = new Promise<void>((resolve, reject) =>\n {\n resolveCompleted = resolve;\n rejectCompleted = reject;\n });\n\n source.on(\"data\", (chunk) =>\n {\n // Keep the internal buffer aggregator for session memory reconstruction intact\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n\n // Push the raw text token right through the pass-through stream pipeline!\n // tee.write(chunk);\n });\n\n source.on(\"end\", async () =>\n {\n sourceEnded = true;\n\n (async ()=>\n {\n const content = Buffer.concat(chunks).toString(\"utf8\");\n\n if (content.trim().length > 0)\n {\n let responseMessage = new Message({\n type: MessageType.Agent,\n content,\n createdTimestamp: new Date().toISOString()\n });\n\n session.messages?.push(responseMessage);\n\n if(option?.event?.onResponse)\n {\n await option.event.onResponse(responseMessage);\n }\n }\n\n resolveCompleted();\n })().catch(rejectCompleted);\n });\n\n source.on(\"error\", (error) =>\n {\n rejectCompleted(error);\n tee.destroy(error);\n });\n\n tee.on(\"close\", () =>\n {\n if (!sourceEnded && !source.destroyed)\n {\n const err = new Error(\"Stream closed before completion\");\n rejectCompleted(err)\n source.destroy(err);\n }\n });\n\n source.pipe(tee);\n\n return tee;\n }\n\n private async executePlan(planner: IPlanner, plan: Plan, session: Session, option?: Omit<AgentOption, 'instruction'>, outputStream?: PassThrough): Promise<ResponseMessage> \n {\n let activeTask = plan.getNextPendingTask();\n\n // Inform UI layer of initial plan setup state\n if(option?.event?.onPlanUpdated)\n {\n await option.event.onPlanUpdated(plan);\n }\n\n while (activeTask?.id) \n {\n log(`[Planner] Processing Step ${activeTask.id}: ${activeTask.description}`);\n plan.updateTaskStatus(activeTask.id, 'running');\n\n if(option?.event?.onPlanUpdated)\n {\n await option.event.onPlanUpdated(plan);\n }\n\n // 1. Build a highly focused system instruction ONLY for this active sub-task\n const stepInstruction = plan.getInstruction(activeTask);\n\n // Prepare a localized execution context for this plan only.\n const conversationContext = (session.messages ?? [])\n .slice(0, -1)\n .map(message => `${message.type}: ${message.content}`)\n .join('\\n\\n');\n\n const turnMessages = [\n new Message({ \n type: MessageType.User, \n content: `${conversationContext ? `CONVERSATION HISTORY\\n${conversationContext}\\n\\n` : ''}${plan.getExecutionContext(activeTask.id)}`\n })\n ];\n\n let turnResultText = \"\";\n\n // 2. Fork Execution based on whether we are invoking or streaming to the user\n\n // Check if this active task is the last remaining pending task in the plan\n const isLastTask = !plan.tasks?.find(t => t.id! > activeTask!.id!);\n\n if (isLastTask) \n {\n // STREAM MODE: Stream tokens directly to the user for the final step\n const stepStream = await this.model.stream(turnMessages, {\n ...option,\n toolsEnabled: true,\n instruction: { system: { value: stepInstruction } }\n });\n\n log(\"[Planner] Messages\", turnMessages)\n log(\"[Planner] SystemPrompt\", stepInstruction)\n\n for await (const chunk of stepStream) {\n const textChunk = typeof chunk === 'string' ? chunk : chunk.toString('utf8');\n turnResultText += textChunk;\n\n if (outputStream && !outputStream.destroyed) {\n outputStream.write(textChunk);\n }\n }\n } \n else\n {\n // BLOCK MODE: Silently invoke intermediate tasks without streaming to outputStream\n const taskInvoke = await this.model.invoke(turnMessages, {\n ...option,\n toolsEnabled: true,\n instruction: { system: { value: stepInstruction } }\n });\n turnResultText = taskInvoke.message.content || \"\";\n\n log(\"[Planner] Messages\", turnMessages)\n log(\"[Planner] SystemPrompt\", stepInstruction)\n log(\"[Planner] Result\", turnResultText)\n }\n\n plan.appendLogToTask(activeTask.id, turnResultText);\n\n // 3. REFLECTION PHASE: Evaluate intermediate task output before continuing.\n if (isLastTask)\n {\n plan.updateTaskStatus(activeTask.id, 'completed');\n }\n else\n {\n log(`[Reflection] Auditing output for Step ${activeTask.id}...`);\n const isSuccessful = await planner.reflect(activeTask, turnResultText);\n\n if (isSuccessful) {\n // Success path\n plan.updateTaskStatus(activeTask.id, 'completed');\n log(`[Planner] Step ${activeTask.id} passed verification.`);\n } else {\n // Failure path -> Trigger active Re-planning injection\n plan.updateTaskStatus(activeTask.id, 'failed');\n log(`[Planner] Step ${activeTask.id} failed verification. Re-planning...`);\n\n // Injects a correction step right into your Plan.tasks array natively\n await planner.replan(plan, activeTask, turnResultText);\n }\n }\n\n if(option?.event?.onPlanUpdated)\n {\n await option.event.onPlanUpdated(plan);\n }\n\n // Fetch the next task (could be a newly injected recovery task!)\n activeTask = plan.getNextPendingTask();\n }\n\n // Push final unified framework snapshot update out to listeners\n if (option?.event?.onPlanUpdated) \n {\n await option.event.onPlanUpdated(plan);\n }\n\n // Fix type mismatch by converting final output string string into structured ResponseMessage\n const finalAgentMsg = new Message({\n type: MessageType.Agent,\n content: plan.getLastCompletedOutput(),\n createdTimestamp: new Date().toISOString()\n });\n\n return new ResponseMessage({\n message: finalAgentMsg,\n stopReason: StopReason.END_TURN,\n tokenUsage: {totalTokens: 0, inputTokens: 0, outputTokens: 0}\n });\n }\n}","import { Model, Instruction } from \"@mappies/miniwat-agent-core\";\nimport { ToolDispatcher } from \"@mappies/miniwat-mcp-core\";\nimport { IPlanner } from \"../interfaces/iPlanner\";\n\nexport class AgentConfig \n{\n /**\n * Agent instruction\n */\n instruction?: Instruction;\n\n /**\n * The language model used by this agent.\n */\n model: Model;\n\n /**\n * Tool dispatcher for tools.\n */\n toolDispatcher?: ToolDispatcher;\n\n /**\n * Optional planner.\n *\n * When omitted, the agent executes prompts directly using the configured model.\n * When provided, the planner determines whether to return a direct answer or\n * execute a multi-step plan.\n */\n planner?: IPlanner;\n\n /**\n * Maximum number of tool calls allowed per model execution.\n */\n maxToolCalls?: number;\n\n constructor(data:AgentConfig)\n {\n this.instruction = data.instruction;\n this.model = data.model;\n this.toolDispatcher = data.toolDispatcher;\n this.planner = data.planner;\n this.maxToolCalls = data.maxToolCalls;\n }\n}","import { Message } from \"@mappies/miniwat-agent-core\";\nimport { randomUUID } from \"crypto\";\n\nexport class Session\n{\n public id: string;\n public name?:string;\n public messages?: Message[];\n public createdTimestamp?: string;\n\n constructor(data?:Partial<Session>)\n {\n this.id = data?.id || randomUUID();\n this.name = data?.name;\n this.messages = data?.messages;\n this.createdTimestamp = data?.createdTimestamp;\n }\n}","import { TaskStatus } from \"../../interfaces/taskStatus\";\n\nexport class Task\n{\n id?: number;\n description?: string;\n status?: TaskStatus;\n executionLogs?: string[]; \n\n constructor(task:Partial<Task>)\n {\n this.id = task.id;\n this.description = task.description;\n this.status = task.status;\n this.executionLogs = task.executionLogs;\n }\n}","import { TokenUsage } from \"@mappies/miniwat-agent-core\";\nimport { Task } from \"./task\";\nimport { TaskStatus } from \"../../interfaces/taskStatus\";\n\nexport class Plan\n{\n id?:string;\n userGoal?: string;\n tasks?: Task[];\n directAnswer?: { content: string, tokenUsage: TokenUsage }\n createdAt?: string;\n\n constructor(plan?:Partial<Plan>)\n {\n this.id = plan?.id;\n this.userGoal = plan?.userGoal;\n this.tasks = plan?.tasks;\n this.directAnswer = plan?.directAnswer;\n this.createdAt = plan?.createdAt;\n }\n\n public getInstruction(currentTask: Task): string\n {\n return `You are working on one task which is a part of a structured plan.\n\nComplete only the CURRENT TASK.\nThe current task is considered complete once you have gathered enough information to produce useful recommendations.\nDo not attempt exhaustive research.\nIf the tool-use limit is reached, stop researching and complete the task using the information already gathered.\nIf additional information would only improve completeness rather than change the recommendation, stop researching and summarize what you have.\nTreat completed task results as established context.\nDo not repeat work already completed by previous tasks unless verification is necessary.\nUse tools only for information required by the current task that is not already available.\n\nCURRENT TASK:\n${currentTask.description ?? ''}\n`;\n }\n\n public getExecutionContext(currentTaskId: number): string\n {\n const taskDirectives = (this.tasks ?? [])\n .map(t => `Step ${t.id} [${t.status || 'pending'}]: ${t.description}`)\n .join('\\n');\n\n const completedTaskResults = (this.tasks ?? [])\n .filter(t => t.id !== currentTaskId && t.status === 'completed' && (t.executionLogs?.length ?? 0) > 0)\n .map(t => `Step ${t.id}: ${t.description}\\nResult:\\n${t.executionLogs![t.executionLogs!.length - 1]}`)\n .join('\\n\\n');\n\n return `OVERALL GOAL\n${this.userGoal ?? ''}\n\nPLAN\n${taskDirectives}\n\nCOMPLETED TASK RESULTS\n${completedTaskResults || 'None.'}`;\n }\n\n public getLastCompletedOutput(): string\n {\n if(!this.tasks)\n {\n return '';\n }\n\n for(let i = this.tasks.length - 1; i >= 0; i--)\n {\n const task = this.tasks[i];\n if(task.status === 'completed' && task.executionLogs?.length)\n {\n return task.executionLogs[task.executionLogs.length - 1];\n }\n }\n\n return '';\n }\n\n public getNextPendingTask(): Task | undefined \n {\n if (!Array.isArray(this.tasks) || this.tasks.length === 0) {\n return undefined;\n }\n return this.tasks.find(task => task.status === 'pending') || undefined;\n }\n\n public updateTaskStatus(taskId: number, status: TaskStatus): void \n {\n if (!Array.isArray(this.tasks)) \n {\n throw new Error(`Could not update a task's status because tasks array is undefined.`);\n }\n\n const task = this.tasks.find(t => t.id === taskId);\n\n if (!task) \n {\n throw new Error(`Could not update a task's status because the given task ID ${taskId} could not be found.`);\n }\n\n task.status = status;\n }\n\n public appendLogToTask(taskId: number, log: string): void \n {\n if (!Array.isArray(this.tasks)) \n {\n throw new Error(`Could not update a task's status because tasks array is undefined.`);\n }\n\n const task = this.tasks.find(t => t.id === taskId);\n\n if (!task) \n {\n throw new Error(`Could not update a task's status because the given task ID ${taskId} could not be found.`);\n }\n\n if (!task.executionLogs) \n {\n task.executionLogs = [];\n }\n \n task.executionLogs.push(log);\n }\n\n public insertTask(afterStepId: number, description: string): void \n {\n if(Array.isArray(this.tasks) === false)\n {\n throw new Error(`Could not inject a task because the tasks is undefined.`)\n }\n const targetIndex = this.tasks?.findIndex(s => s.id === afterStepId);\n if (targetIndex === -1) throw new Error(`Could not inject a task because the task '${afterStepId}' could not be found.`);\n\n // Shift IDs of all subsequent steps to make room\n for (let i = targetIndex + 1; i < this.tasks.length; i++) \n {\n const task = this.tasks[i];\n\n if(task.id === undefined)\n {\n throw new Error(`Could not inject a task because the tasks is undefined.`)\n }\n\n task.id += 1;\n }\n\n // Insert a new task\n const newTask = new Task({\n id: afterStepId + 1,\n description,\n status: 'pending',\n executionLogs: []\n });\n\n this.tasks.splice(targetIndex + 1, 0, newTask);\n }\n}","import { Message, MessageType, Model, ResponseMessage } from \"@mappies/miniwat-agent-core\";\nimport { Plan } from \"./plan\";\nimport { Task } from \"./task\";\n\ninterface RawLlmPlanResponse {\n directAnswer?: string;\n tasks?: Array<{ id: number; description: string; }>;\n}\n\ninterface RawLlmReplanResponse {\n recoveryDescription: string;\n}\n\nexport class DefaultPlanner \n{\n constructor(private model: Model) {}\n\n private async callLLM(systemPrompt: string, userPrompt: string): Promise<ResponseMessage>\n {\n return this.model.invoke(\n [\n new Message({type: MessageType.User, content: userPrompt })\n ],\n {\n toolsEnabled: false,\n instruction: {\n system: { value: systemPrompt }\n }\n }\n );\n }\n\n public async createPlan(userGoal: string, conversationHistory?: Message[]): Promise<Plan> \n {\n const systemPrompt = `Current time: ${new Date().toISOString()}\\n\\nYou are a Routing and Planning Engine. \nAnalyze the input to decide if it requires multi-step tools/scripts, or if it can be directly answered. \n\nOnly give a direct answer when multi-step plan is not required.\n\nIf a plan is needed:\n\n- Do not include directAnswer.\n- Each task should represent a distinct, independently executable unit of work.\n- Keep tightly coupled retrieval and processing together when they depend on the same data.\n- When separating steps would require passing a large or structured dataset from one task to another, do not split them into separate tasks.\n- If the user explicitly requests a single workflow or single task, create exactly one task unless doing so is impossible.\n\nOutput in JSON with the following structure:\n{\n \"directAnswer\": \"String text if a direct answer can be made without a planning.\",\n \"tasks\": [\n { \"id\": 1, \"description\": \"What to do\" }\n ]\n}`;\n\n const conversationContext = (conversationHistory ?? [])\n .map(message => `${message.type}: ${message.content}`)\n .join('\\n\\n');\n\n const userPrompt = `${conversationContext ? `Conversation History:\\n${conversationContext}\\n\\n` : ''}User Goal: \"${userGoal}\"`;\n const rawResult = await this.callLLM(systemPrompt, userPrompt);\n const content = rawResult.message.content.trim();\n const cleanJson = content.replace(/```json|```/g, '').trim();\n\n let parsed: RawLlmPlanResponse;\n\n try\n {\n parsed = JSON.parse(cleanJson);\n\n if(parsed.tasks?.length)\n {\n parsed.directAnswer = undefined;\n }\n }\n catch\n {\n parsed = {\n tasks: [],\n directAnswer: content\n };\n }\n\n const taskInstances = parsed.tasks?.map(t => new Task({\n id: t.id,\n description: t.description,\n status: 'pending',\n executionLogs: []\n })) || [];\n\n return new Plan({\n id: crypto.randomUUID(),\n userGoal,\n directAnswer: parsed.directAnswer ? { \n content: parsed.directAnswer, \n tokenUsage: rawResult.tokenUsage\n } \n : undefined,\n tasks: taskInstances\n });\n }\n\n /**\n * PURE CRITIC INTERFACE\n * Cross-references an execution string block against the target task expectations.\n */\n public async reflect(task: Task, executionOutput: string): Promise<boolean>\n {\n const systemPrompt = `Current time: ${new Date().toISOString()}\\n\\nYou are a Quality Assurance Auditor.\nYour only job is to evaluate whether the task objective has been sufficiently completed for the overall plan to continue safely.\n\nCRITERIA TO MEET:\nTask Objective: ${task.description}\n\nOUTPUT FORMAT:\nIf the task is sufficiently complete for the plan to continue, output exactly: YES\nIf the task is missing or incorrect in a way that prevents the plan from continuing safely, output: NO: <brief reason describing only the missing or incorrect part>\nDo not include any other words or preamble.`;\n\n const response = await this.callLLM(systemPrompt, `Actual Agent Execution Log Output:\\n${executionOutput}`);\n \n // Clean text parsing to verify exact truth evaluations\n let result = response.message.content.trim().toUpperCase().startsWith(\"YES\");\n\n return result;\n }\n\n /**\n * CONTEXTUAL WORKFLOW PATCHING\n * Invokes an LLM strategy session to formulate an actionable patch, injecting it into the state array.\n */\n public async replan(plan: Plan, failedTask: Task, failureOutput: string): Promise<void>\n {\n const systemPrompt = `Current time: ${new Date().toISOString()}\\n\\nYou are a Master System Architect. A sub-task has failed verification.\nAnalyze the original goal and failure log to generate a single \"Recovery Task\" to resolve the issue.\n\nOUTPUT FORMAT:\nYou must respond with a raw JSON object matching this exact structure:\n{\n \"recoveryDescription\": \"What the agent needs to do from scratch to fix this explicit error state\",\n}`;\n\n const userPrompt = `\nOverall Goal: ${plan.userGoal}\nFailed Step Description: ${failedTask.description}\nActual Failed Output Received: ${failureOutput}\n`;\n\n const response = await this.callLLM(systemPrompt, userPrompt);\n const cleanJson = response.message.content.replace(/```json|```/g, '').trim();\n const parsed: RawLlmReplanResponse = JSON.parse(cleanJson);\n\n if (failedTask.id === undefined)\n {\n throw new Error(\"[Planner] Cannot execute replan tracking because the target task ID is undefined.\");\n }\n\n // Execute dynamic mutation right inside your Plan model entity!\n plan.insertTask(\n failedTask.id, \n parsed.recoveryDescription, \n );\n }\n}"],"mappings":";AAAA,SAAgB,iBAA8B,SAAS,aAAa,kBAAkB;AAGtF,SAAS,aAAa,gBAAgB;AAMtC,IAAI,UAAU,CAAC,CAAC,QAAQ,IAAI;AAE5B,SAAS,OAAO,MAChB;AACI,MAAG,QAAS,SAAQ,IAAI,IAAI;AAChC;AAEO,IAAM,QAAN,MACP;AAAA,EAOI,YAAY,QACZ;AACI,SAAK,QAAQ,OAAO;AACpB,SAAK,cAAc,OAAO;AAC1B,SAAK,iBAAiB,OAAO;AAC7B,SAAK,UAAU,OAAO;AACtB,SAAK,eAAe,OAAO;AAAA,EAC/B;AAAA,EAEA,MAAM,OAAO,QAAgB,SAAkB,QAC/C;AACI,aAAS;AAAA,MACL,cAAc,KAAK;AAAA,MACnB,GAAG;AAAA,IACP;AAEA,WAAO,KAAK,UAAU,KAAK,kBAAkB,KAAK,SAAS,QAAQ,SAAS,MAAM,IAC5D,KAAK,aAAa,QAAQ,SAAS,MAAM;AAAA,EACnE;AAAA,EAGA,MAAM,OAAO,QAAgB,SAAkB,QAC/C;AACI,aAAS;AAAA,MACL,cAAc,KAAK;AAAA,MACnB,GAAG;AAAA,IACP;AAEA,WAAO,KAAK,UAAU,KAAK,kBAAkB,KAAK,SAAS,QAAQ,SAAS,MAAM,IAC5D,KAAK,aAAa,QAAQ,SAAS,MAAM;AAAA,EACnE;AAAA,EAEA,MAAc,aAAa,QAAgB,SAAkB,QAC7D;AACI,QAAG,CAAC,QAAQ,UACZ;AACI,cAAQ,WAAW,CAAC;AAAA,IACxB;AAEA,YAAQ,SAAS,KAAK,IAAI,QAAQ;AAAA,MAC9B,MAAM,YAAY;AAAA,MAClB,SAAS;AAAA,MACT,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC7C,CAAC,CAAC;AAEF,UAAM,WAAW,MAAM,KAAK,MAAM,OAAO,QAAQ,UAAU;AAAA,MACvD,GAAG;AAAA,MACH,aAAa,KAAK;AAAA,IACtB,CAAC;AAED,YAAQ,SAAS,KAAK,SAAS,OAAO;AAEtC,QAAG,QAAQ,OAAO,YAClB;AACI,YAAM,OAAO,MAAM,WAAW,SAAS,OAAO;AAAA,IAClD;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAc,kBAAkB,SAAmB,QAAgB,SAAkB,QACrF;AACI,UAAM,OAAO,MAAM,QAAQ,WAAW,QAAQ,QAAQ,QAAQ;AAE9D,QAAI,OAAO,IAAI;AAEf,QAAG,CAAC,QAAQ,UACZ;AACI,cAAQ,WAAW,CAAC;AAAA,IACxB;AAEA,YAAQ,SAAS,KAAK,IAAI,QAAQ;AAAA,MAC9B,MAAM,YAAY;AAAA,MAClB,SAAS;AAAA,MACT,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC7C,CAAC,CAAC;AAEF,QAAG,KAAK,cACR;AACI,YAAM,UAAU,IAAI,QAAQ;AAAA,QACxB,MAAM,YAAY;AAAA,QAClB,SAAS,KAAK,aAAa;AAAA,QAC3B,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7C,CAAC;AAED,cAAQ,SAAS,KAAK,OAAO;AAE7B,aAAO,IAAI,gBAAgB;AAAA,QACf;AAAA,QACA,YAAY,WAAW;AAAA,QACvB,YAAY,KAAK,aAAa;AAAA,MAClC,CAAC;AAAA,IACb;AAGA,UAAM,WAAW,MAAM,KAAK,YAAY,SAAS,MAAM,SAAS,MAAM;AAEtE,YAAQ,SAAS,KAAK,SAAS,OAAO;AAEtC,QAAG,QAAQ,OAAO,YAClB;AACI,YAAM,OAAO,MAAM,WAAW,SAAS,OAAO;AAAA,IAClD;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAc,aAAa,QAAgB,SAAkB,QAC7D;AACI,QAAG,CAAC,QAAQ,UACZ;AACI,cAAQ,WAAW,CAAC;AAAA,IACxB;AAEA,YAAQ,SAAS,KAAK,IAAI,QAAQ;AAAA,MAC9B,MAAM,YAAY;AAAA,MAClB,SAAS;AAAA,MACT,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC7C,CAAC,CAAC;AAEF,UAAM,SAAS,MAAM,KAAK,MAAM,OAAO,QAAQ,UAAU;AAAA,MACrD,GAAG;AAAA,MACH,aAAa,KAAK;AAAA,IACtB,CAAC;AAED,UAAM,MAAM,IAAI,YAAY;AAC5B,UAAM,SAAmB,CAAC;AAC1B,QAAI,cAAc;AAElB,QAAI;AACJ,QAAI;AACJ,IAAC,IAAY,UAAU,IAAI,QAAc,CAAC,SAAS,WACnD;AACI,yBAAmB;AACnB,wBAAkB;AAAA,IACtB,CAAC;AAED,WAAO,GAAG,QAAQ,CAAC,UACnB;AACI,aAAO,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,OAAO,KAAK,CAAC,CAAC;AAAA,IAC3E,CAAC;AAED,WAAO,GAAG,OAAO,YACjB;AACI,oBAAc;AAEd,OAAC,YACD;AACI,cAAM,UAAU,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM;AAErD,YAAI,QAAQ,KAAK,EAAE,SAAS,GAC5B;AACI,cAAI,kBAAkB,IAAI,QAAQ;AAAA,YAC9B,MAAM,YAAY;AAAA,YAClB;AAAA,YACA,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,UAC7C,CAAC;AAED,kBAAQ,UAAU,KAAK,eAAe;AAEtC,cAAG,QAAQ,OAAO,YAClB;AACI,kBAAM,OAAO,MAAM,WAAW,eAAe;AAAA,UACjD;AAAA,QACJ;AAEA,yBAAiB;AAAA,MACrB,GAAG,EAAE,MAAM,eAAe;AAAA,IAC9B,CAAC;AAED,WAAO,GAAG,SAAS,CAAC,UACpB;AACI,sBAAgB,KAAK;AACrB,UAAI,QAAQ,KAAK;AAAA,IACrB,CAAC;AAED,QAAI,GAAG,SAAS,MAChB;AACI,UAAI,CAAC,eAAe,CAAC,OAAO,WAC5B;AACI,cAAM,MAAM,IAAI,MAAM,iCAAiC;AACvD,wBAAgB,GAAG;AACnB,eAAO,QAAQ,GAAG;AAAA,MACtB;AAAA,IACJ,CAAC;AAED,WAAO,KAAK,GAAG;AAEf,WAAO;AAAA,EACX;AAAA,EAEA,MAAc,kBAAkB,SAAmB,QAAgB,SAAkB,QACrF;AACI,UAAM,OAAO,MAAM,QAAQ,WAAW,QAAQ,QAAQ,QAAQ;AAE9D,QAAI,OAAO,IAAI;AAEf,QAAG,CAAC,QAAQ,UACZ;AACI,cAAQ,WAAW,CAAC;AAAA,IACxB;AAEA,YAAQ,SAAS,KAAK,IAAI,QAAQ;AAAA,MAC9B,MAAM,YAAY;AAAA,MAClB,SAAS;AAAA,MACT,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC7C,CAAC,CAAC;AAEF,QAAI,KAAK,cACT;AACI,YAAM,cAAc,KAAK,aAAa;AAEtC,YAAM,UAAU,IAAI,QAAQ;AAAA,QACxB,MAAM,YAAY;AAAA,QAClB,SAAS;AAAA,QACT,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7C,CAAC;AAED,cAAQ,SAAS,KAAK,OAAO;AAE7B,UAAI,QAAQ,OAAO,YACnB;AACI,cAAM,OAAO,MAAO,WAAY,OAAO;AAAA,MAC3C;AAEA,YAAM,qBAAqB,IAAI,SAAS;AAAA,QACpC,OAAO;AACH,eAAK,KAAK,OAAO,KAAK,aAAa,MAAM,CAAC;AAC1C,eAAK,KAAK,IAAI;AAAA,QAClB;AAAA,MACJ,CAAC;AAED,MAAC,mBAA2B,UAAU,QAAQ,QAAQ;AACtD,aAAO;AAAA,IACX;AAGA,UAAM,SAAS,IAAI,YAAY;AAG/B,KAAC,YAAY;AACT,UACA;AACI,cAAM,KAAK,YAAY,SAAS,MAAM,SAAS,QAAQ,MAAM;AAE7D,eAAO,IAAI;AAAA,MACf,SACO,KAAU;AACb,eAAO,QAAQ,GAAG;AAAA,MACtB;AAAA,IACJ,GAAG;AAGH,UAAM,MAAM,IAAI,YAAY;AAC5B,UAAM,SAAmB,CAAC;AAC1B,QAAI,cAAc;AAElB,QAAI;AACJ,QAAI;AACJ,IAAC,IAAY,UAAU,IAAI,QAAc,CAAC,SAAS,WACnD;AACI,yBAAmB;AACnB,wBAAkB;AAAA,IACtB,CAAC;AAED,WAAO,GAAG,QAAQ,CAAC,UACnB;AAEI,aAAO,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,OAAO,KAAK,CAAC,CAAC;AAAA,IAI3E,CAAC;AAED,WAAO,GAAG,OAAO,YACjB;AACI,oBAAc;AAEd,OAAC,YACD;AACI,cAAM,UAAU,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM;AAErD,YAAI,QAAQ,KAAK,EAAE,SAAS,GAC5B;AACI,cAAI,kBAAkB,IAAI,QAAQ;AAAA,YAC9B,MAAM,YAAY;AAAA,YAClB;AAAA,YACA,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,UAC7C,CAAC;AAED,kBAAQ,UAAU,KAAK,eAAe;AAEtC,cAAG,QAAQ,OAAO,YAClB;AACI,kBAAM,OAAO,MAAM,WAAW,eAAe;AAAA,UACjD;AAAA,QACJ;AAEA,yBAAiB;AAAA,MACrB,GAAG,EAAE,MAAM,eAAe;AAAA,IAC9B,CAAC;AAED,WAAO,GAAG,SAAS,CAAC,UACpB;AACI,sBAAgB,KAAK;AACrB,UAAI,QAAQ,KAAK;AAAA,IACrB,CAAC;AAED,QAAI,GAAG,SAAS,MAChB;AACI,UAAI,CAAC,eAAe,CAAC,OAAO,WAC5B;AACI,cAAM,MAAM,IAAI,MAAM,iCAAiC;AACvD,wBAAgB,GAAG;AACnB,eAAO,QAAQ,GAAG;AAAA,MACtB;AAAA,IACJ,CAAC;AAED,WAAO,KAAK,GAAG;AAEf,WAAO;AAAA,EACX;AAAA,EAEA,MAAc,YAAY,SAAmB,MAAY,SAAkB,QAA2C,cACtH;AACI,QAAI,aAAa,KAAK,mBAAmB;AAGzC,QAAG,QAAQ,OAAO,eAClB;AACI,YAAM,OAAO,MAAM,cAAc,IAAI;AAAA,IACzC;AAEA,WAAO,YAAY,IACnB;AACI,UAAI,6BAA6B,WAAW,EAAE,KAAK,WAAW,WAAW,EAAE;AAC3E,WAAK,iBAAiB,WAAW,IAAI,SAAS;AAE9C,UAAG,QAAQ,OAAO,eAClB;AACI,cAAM,OAAO,MAAM,cAAc,IAAI;AAAA,MACzC;AAGA,YAAM,kBAAkB,KAAK,eAAe,UAAU;AAGtD,YAAM,uBAAuB,QAAQ,YAAY,CAAC,GACjB,MAAM,GAAG,EAAE,EACX,IAAI,aAAW,GAAG,QAAQ,IAAI,KAAK,QAAQ,OAAO,EAAE,EACpD,KAAK,MAAM;AAE5C,YAAM,eAAe;AAAA,QACjB,IAAI,QAAQ;AAAA,UACR,MAAM,YAAY;AAAA,UAClB,SAAS,GAAG,sBAAsB;AAAA,EAAyB,mBAAmB;AAAA;AAAA,IAAS,EAAE,GAAG,KAAK,oBAAoB,WAAW,EAAE,CAAC;AAAA,QACvI,CAAC;AAAA,MACL;AAEA,UAAI,iBAAiB;AAKrB,YAAM,aAAa,CAAC,KAAK,OAAO,KAAK,OAAK,EAAE,KAAM,WAAY,EAAG;AAEjE,UAAI,YACJ;AAEI,cAAM,aAAa,MAAM,KAAK,MAAM,OAAO,cAAc;AAAA,UACrD,GAAG;AAAA,UACH,cAAc;AAAA,UACd,aAAa,EAAE,QAAQ,EAAE,OAAO,gBAAgB,EAAE;AAAA,QACtD,CAAC;AAED,YAAI,sBAAsB,YAAY;AACtC,YAAI,0BAA0B,eAAe;AAE7C,yBAAiB,SAAS,YAAY;AAClC,gBAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,MAAM,SAAS,MAAM;AAC3E,4BAAkB;AAElB,cAAI,gBAAgB,CAAC,aAAa,WAAW;AACzC,yBAAa,MAAM,SAAS;AAAA,UAChC;AAAA,QACJ;AAAA,MACJ,OAEA;AAEI,cAAM,aAAa,MAAM,KAAK,MAAM,OAAO,cAAc;AAAA,UACrD,GAAG;AAAA,UACH,cAAc;AAAA,UACd,aAAa,EAAE,QAAQ,EAAE,OAAO,gBAAgB,EAAE;AAAA,QACtD,CAAC;AACD,yBAAiB,WAAW,QAAQ,WAAW;AAE/C,YAAI,sBAAsB,YAAY;AACtC,YAAI,0BAA0B,eAAe;AAC7C,YAAI,oBAAoB,cAAc;AAAA,MAC1C;AAEA,WAAK,gBAAgB,WAAW,IAAI,cAAc;AAGlD,UAAI,YACJ;AACI,aAAK,iBAAiB,WAAW,IAAI,WAAW;AAAA,MACpD,OAEA;AACI,YAAI,yCAAyC,WAAW,EAAE,KAAK;AAC/D,cAAM,eAAe,MAAM,QAAQ,QAAQ,YAAY,cAAc;AAErE,YAAI,cAAc;AAEd,eAAK,iBAAiB,WAAW,IAAI,WAAW;AAChD,cAAI,kBAAkB,WAAW,EAAE,uBAAuB;AAAA,QAC9D,OAAO;AAEH,eAAK,iBAAiB,WAAW,IAAI,QAAQ;AAC7C,cAAI,kBAAkB,WAAW,EAAE,sCAAsC;AAGzE,gBAAM,QAAQ,OAAO,MAAM,YAAY,cAAc;AAAA,QACzD;AAAA,MACJ;AAEA,UAAG,QAAQ,OAAO,eAClB;AACI,cAAM,OAAO,MAAM,cAAc,IAAI;AAAA,MACzC;AAGA,mBAAa,KAAK,mBAAmB;AAAA,IACzC;AAGA,QAAI,QAAQ,OAAO,eACnB;AACI,YAAM,OAAO,MAAM,cAAc,IAAI;AAAA,IACzC;AAGA,UAAM,gBAAgB,IAAI,QAAQ;AAAA,MAC9B,MAAM,YAAY;AAAA,MAClB,SAAS,KAAK,uBAAuB;AAAA,MACrC,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC7C,CAAC;AAED,WAAO,IAAI,gBAAgB;AAAA,MACvB,SAAS;AAAA,MACT,YAAY,WAAW;AAAA,MACvB,YAAY,EAAC,aAAa,GAAG,aAAa,GAAG,cAAc,EAAC;AAAA,IAChE,CAAC;AAAA,EACL;AACJ;;;AC5dO,IAAM,cAAN,MACP;AAAA,EA8BI,YAAY,MACZ;AACI,SAAK,cAAc,KAAK;AACxB,SAAK,QAAQ,KAAK;AAClB,SAAK,iBAAiB,KAAK;AAC3B,SAAK,UAAU,KAAK;AACpB,SAAK,eAAe,KAAK;AAAA,EAC7B;AACJ;;;AC1CA,SAAS,kBAAkB;AAEpB,IAAM,UAAN,MACP;AAAA,EAMI,YAAY,MACZ;AACI,SAAK,KAAK,MAAM,MAAM,WAAW;AACjC,SAAK,OAAO,MAAM;AAClB,SAAK,WAAW,MAAM;AACtB,SAAK,mBAAmB,MAAM;AAAA,EAClC;AACJ;;;ACfO,IAAM,OAAN,MACP;AAAA,EAMI,YAAY,MACZ;AACI,SAAK,KAAK,KAAK;AACf,SAAK,cAAc,KAAK;AACxB,SAAK,SAAS,KAAK;AACnB,SAAK,gBAAgB,KAAK;AAAA,EAC9B;AACJ;;;ACZO,IAAM,OAAN,MACP;AAAA,EAOI,YAAY,MACZ;AACI,SAAK,KAAK,MAAM;AAChB,SAAK,WAAW,MAAM;AACtB,SAAK,QAAQ,MAAM;AACnB,SAAK,eAAe,MAAM;AAC1B,SAAK,YAAY,MAAM;AAAA,EAC3B;AAAA,EAEO,eAAe,aACtB;AACI,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYb,YAAY,eAAe,EAAE;AAAA;AAAA,EAE3B;AAAA,EAEO,oBAAoB,eAC3B;AACI,UAAM,kBAAkB,KAAK,SAAS,CAAC,GACV,IAAI,OAAK,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,SAAS,MAAM,EAAE,WAAW,EAAE,EACpE,KAAK,IAAI;AAEtC,UAAM,wBAAwB,KAAK,SAAS,CAAC,GACZ,OAAO,OAAK,EAAE,OAAO,iBAAiB,EAAE,WAAW,gBAAgB,EAAE,eAAe,UAAU,KAAK,CAAC,EACpG,IAAI,OAAK,QAAQ,EAAE,EAAE,KAAK,EAAE,WAAW;AAAA;AAAA,EAAc,EAAE,cAAe,EAAE,cAAe,SAAS,CAAC,CAAC,EAAE,EACpG,KAAK,MAAM;AAE5C,WAAO;AAAA,EACb,KAAK,YAAY,EAAE;AAAA;AAAA;AAAA,EAGnB,cAAc;AAAA;AAAA;AAAA,EAGd,wBAAwB,OAAO;AAAA,EAC7B;AAAA,EAEO,yBACP;AACI,QAAG,CAAC,KAAK,OACT;AACI,aAAO;AAAA,IACX;AAEA,aAAQ,IAAI,KAAK,MAAM,SAAS,GAAG,KAAK,GAAG,KAC3C;AACI,YAAM,OAAO,KAAK,MAAM,CAAC;AACzB,UAAG,KAAK,WAAW,eAAe,KAAK,eAAe,QACtD;AACI,eAAO,KAAK,cAAc,KAAK,cAAc,SAAS,CAAC;AAAA,MAC3D;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA,EAEO,qBACP;AACI,QAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,KAAK,KAAK,MAAM,WAAW,GAAG;AACvD,aAAO;AAAA,IACX;AACA,WAAO,KAAK,MAAM,KAAK,UAAQ,KAAK,WAAW,SAAS,KAAK;AAAA,EACjE;AAAA,EAEO,iBAAiB,QAAgB,QACxC;AACI,QAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,GAC7B;AACI,YAAM,IAAI,MAAM,oEAAoE;AAAA,IACxF;AAEA,UAAM,OAAO,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,MAAM;AAEjD,QAAI,CAAC,MACL;AACI,YAAM,IAAI,MAAM,8DAA8D,MAAM,sBAAsB;AAAA,IAC9G;AAEA,SAAK,SAAS;AAAA,EAClB;AAAA,EAEO,gBAAgB,QAAgBA,MACvC;AACI,QAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,GAC7B;AACI,YAAM,IAAI,MAAM,oEAAoE;AAAA,IACxF;AAEA,UAAM,OAAO,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,MAAM;AAEjD,QAAI,CAAC,MACL;AACI,YAAM,IAAI,MAAM,8DAA8D,MAAM,sBAAsB;AAAA,IAC9G;AAEA,QAAI,CAAC,KAAK,eACV;AACI,WAAK,gBAAgB,CAAC;AAAA,IAC1B;AAEA,SAAK,cAAc,KAAKA,IAAG;AAAA,EAC/B;AAAA,EAEO,WAAW,aAAqB,aACvC;AACI,QAAG,MAAM,QAAQ,KAAK,KAAK,MAAM,OACjC;AACI,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC7E;AACA,UAAM,cAAc,KAAK,OAAO,UAAU,OAAK,EAAE,OAAO,WAAW;AACnE,QAAI,gBAAgB,GAAI,OAAM,IAAI,MAAM,6CAA6C,WAAW,uBAAuB;AAGvH,aAAS,IAAI,cAAc,GAAG,IAAI,KAAK,MAAM,QAAQ,KACrD;AACI,YAAM,OAAO,KAAK,MAAM,CAAC;AAEzB,UAAG,KAAK,OAAO,QACf;AACI,cAAM,IAAI,MAAM,yDAAyD;AAAA,MAC7E;AAEA,WAAK,MAAM;AAAA,IACf;AAGA,UAAM,UAAU,IAAI,KAAK;AAAA,MACG,IAAI,cAAc;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,MACR,eAAe,CAAC;AAAA,IACpB,CAAC;AAEzB,SAAK,MAAM,OAAO,cAAc,GAAG,GAAG,OAAO;AAAA,EACjD;AACJ;;;AC9JA,SAAS,WAAAC,UAAS,eAAAC,oBAA2C;AAatD,IAAM,iBAAN,MACP;AAAA,EACI,YAAoB,OAAc;AAAd;AAAA,EAAe;AAAA,EAEnC,MAAc,QAAQ,cAAsB,YAC5C;AACI,WAAO,KAAK,MAAM;AAAA,MACd;AAAA,QACI,IAAIC,SAAQ,EAAC,MAAMC,aAAY,MAAM,SAAS,WAAW,CAAC;AAAA,MAC9D;AAAA,MACA;AAAA,QACI,cAAc;AAAA,QACd,aAAa;AAAA,UACT,QAAQ,EAAE,OAAO,aAAa;AAAA,QAClC;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAa,WAAW,UAAkB,qBAC1C;AACI,UAAM,eAAe,kBAAiB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqB9D,UAAM,uBAAuB,uBAAuB,CAAC,GACpB,IAAI,aAAW,GAAG,QAAQ,IAAI,KAAK,QAAQ,OAAO,EAAE,EACpD,KAAK,MAAM;AAE5C,UAAM,aAAa,GAAG,sBAAsB;AAAA,EAA0B,mBAAmB;AAAA;AAAA,IAAS,EAAE,eAAe,QAAQ;AAC3H,UAAM,YAAY,MAAM,KAAK,QAAQ,cAAc,UAAU;AAC7D,UAAM,UAAU,UAAU,QAAQ,QAAQ,KAAK;AAC/C,UAAM,YAAY,QAAQ,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AAE3D,QAAI;AAEJ,QACA;AACI,eAAS,KAAK,MAAM,SAAS;AAE7B,UAAG,OAAO,OAAO,QACjB;AACI,eAAO,eAAe;AAAA,MAC1B;AAAA,IACJ,QAEA;AACI,eAAS;AAAA,QACL,OAAO,CAAC;AAAA,QACR,cAAc;AAAA,MAClB;AAAA,IACJ;AAEA,UAAM,gBAAgB,OAAO,OAAO,IAAI,OAAK,IAAI,KAAK;AAAA,MAClD,IAAI,EAAE;AAAA,MACN,aAAa,EAAE;AAAA,MACf,QAAQ;AAAA,MACR,eAAe,CAAC;AAAA,IACpB,CAAC,CAAC,KAAK,CAAC;AAER,WAAO,IAAI,KAAK;AAAA,MACZ,IAAI,OAAO,WAAW;AAAA,MACtB;AAAA,MACA,cAAc,OAAO,eAAe;AAAA,QACI,SAAS,OAAO;AAAA,QAChB,YAAY,UAAU;AAAA,MAC1B,IACA;AAAA,MACpC,OAAO;AAAA,IACX,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,QAAQ,MAAY,iBACjC;AACI,UAAM,eAAe,kBAAiB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAIpD,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAO1B,UAAM,WAAW,MAAM,KAAK,QAAQ,cAAc;AAAA,EAAuC,eAAe,EAAE;AAG1G,QAAI,SAAS,SAAS,QAAQ,QAAQ,KAAK,EAAE,YAAY,EAAE,WAAW,KAAK;AAE3E,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,OAAO,MAAY,YAAkB,eAClD;AACI,UAAM,eAAe,kBAAiB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAS9D,UAAM,aAAa;AAAA,gBACX,KAAK,QAAQ;AAAA,2BACF,WAAW,WAAW;AAAA,iCAChB,aAAa;AAAA;AAGtC,UAAM,WAAW,MAAM,KAAK,QAAQ,cAAc,UAAU;AAC5D,UAAM,YAAY,SAAS,QAAQ,QAAQ,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AAC5E,UAAM,SAA+B,KAAK,MAAM,SAAS;AAEzD,QAAI,WAAW,OAAO,QACtB;AACI,YAAM,IAAI,MAAM,mFAAmF;AAAA,IACvG;AAGA,SAAK;AAAA,MACD,WAAW;AAAA,MACX,OAAO;AAAA,IACX;AAAA,EACJ;AACJ;","names":["log","Message","MessageType","Message","MessageType"]}
|