@nuvin/nuvin-core 1.5.2 → 1.6.1
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/dist/VERSION +2 -2
- package/dist/index.d.ts +789 -16
- package/dist/index.js +1100 -196
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,8 @@ var AgentEventTypes = {
|
|
|
33
33
|
SubAgentStarted: "sub_agent_started",
|
|
34
34
|
SubAgentToolCall: "sub_agent_tool_call",
|
|
35
35
|
SubAgentToolResult: "sub_agent_tool_result",
|
|
36
|
-
SubAgentCompleted: "sub_agent_completed"
|
|
36
|
+
SubAgentCompleted: "sub_agent_completed",
|
|
37
|
+
SubAgentMetrics: "sub_agent_metrics"
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
// src/metrics.ts
|
|
@@ -375,6 +376,391 @@ var PersistingConsoleEventPort = class {
|
|
|
375
376
|
}
|
|
376
377
|
};
|
|
377
378
|
|
|
379
|
+
// src/tools/tool-call-parser.ts
|
|
380
|
+
function parseJSON(jsonString) {
|
|
381
|
+
try {
|
|
382
|
+
const parsed = JSON.parse(jsonString || "{}");
|
|
383
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
384
|
+
return {
|
|
385
|
+
success: false,
|
|
386
|
+
error: "Parsed JSON must be an object, not an array or primitive"
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
return { success: true, data: parsed };
|
|
390
|
+
} catch (error) {
|
|
391
|
+
return {
|
|
392
|
+
success: false,
|
|
393
|
+
error: error instanceof Error ? error.message : "Invalid JSON syntax"
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// src/tools/tool-validators.ts
|
|
399
|
+
var validateBashToolParams = (params) => {
|
|
400
|
+
const errors = [];
|
|
401
|
+
if (!params.cmd || typeof params.cmd !== "string") {
|
|
402
|
+
errors.push('Required parameter "cmd" must be a non-empty string');
|
|
403
|
+
}
|
|
404
|
+
if (params.cwd !== void 0 && typeof params.cwd !== "string") {
|
|
405
|
+
errors.push('Parameter "cwd" must be a string');
|
|
406
|
+
}
|
|
407
|
+
if (params.timeoutMs !== void 0) {
|
|
408
|
+
if (typeof params.timeoutMs !== "number" || params.timeoutMs < 1) {
|
|
409
|
+
errors.push('Parameter "timeoutMs" must be a positive number');
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (params.description !== void 0 && typeof params.description !== "string") {
|
|
413
|
+
errors.push('Parameter "description" must be a string');
|
|
414
|
+
}
|
|
415
|
+
if (errors.length > 0) {
|
|
416
|
+
return { valid: false, errors };
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
valid: true,
|
|
420
|
+
data: {
|
|
421
|
+
cmd: params.cmd,
|
|
422
|
+
cwd: params.cwd,
|
|
423
|
+
timeoutMs: params.timeoutMs,
|
|
424
|
+
description: params.description
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
};
|
|
428
|
+
var validateFileReadParams = (params) => {
|
|
429
|
+
const errors = [];
|
|
430
|
+
if (!params.path || typeof params.path !== "string") {
|
|
431
|
+
errors.push('Required parameter "path" must be a non-empty string');
|
|
432
|
+
}
|
|
433
|
+
if (params.lineStart !== void 0) {
|
|
434
|
+
if (typeof params.lineStart !== "number" || params.lineStart < 1) {
|
|
435
|
+
errors.push('Parameter "lineStart" must be a positive integer');
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
if (params.lineEnd !== void 0) {
|
|
439
|
+
if (typeof params.lineEnd !== "number" || params.lineEnd < 1) {
|
|
440
|
+
errors.push('Parameter "lineEnd" must be a positive integer');
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
if (params.description !== void 0 && typeof params.description !== "string") {
|
|
444
|
+
errors.push('Parameter "description" must be a string');
|
|
445
|
+
}
|
|
446
|
+
if (errors.length > 0) {
|
|
447
|
+
return { valid: false, errors };
|
|
448
|
+
}
|
|
449
|
+
return {
|
|
450
|
+
valid: true,
|
|
451
|
+
data: {
|
|
452
|
+
path: params.path,
|
|
453
|
+
lineStart: params.lineStart,
|
|
454
|
+
lineEnd: params.lineEnd,
|
|
455
|
+
description: params.description
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
};
|
|
459
|
+
var validateFileEditParams = (params) => {
|
|
460
|
+
const errors = [];
|
|
461
|
+
if (!params.file_path || typeof params.file_path !== "string") {
|
|
462
|
+
errors.push('Required parameter "file_path" must be a non-empty string');
|
|
463
|
+
}
|
|
464
|
+
if (!params.old_text || typeof params.old_text !== "string") {
|
|
465
|
+
errors.push('Required parameter "old_text" must be a string');
|
|
466
|
+
}
|
|
467
|
+
if (params.new_text === void 0 || typeof params.new_text !== "string") {
|
|
468
|
+
errors.push('Required parameter "new_text" must be a string');
|
|
469
|
+
}
|
|
470
|
+
if (params.dry_run !== void 0 && typeof params.dry_run !== "boolean") {
|
|
471
|
+
errors.push('Parameter "dry_run" must be a boolean');
|
|
472
|
+
}
|
|
473
|
+
if (params.description !== void 0 && typeof params.description !== "string") {
|
|
474
|
+
errors.push('Parameter "description" must be a string');
|
|
475
|
+
}
|
|
476
|
+
if (errors.length > 0) {
|
|
477
|
+
return { valid: false, errors };
|
|
478
|
+
}
|
|
479
|
+
return {
|
|
480
|
+
valid: true,
|
|
481
|
+
data: {
|
|
482
|
+
file_path: params.file_path,
|
|
483
|
+
old_text: params.old_text,
|
|
484
|
+
new_text: params.new_text,
|
|
485
|
+
dry_run: params.dry_run,
|
|
486
|
+
description: params.description
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
};
|
|
490
|
+
var validateFileNewParams = (params) => {
|
|
491
|
+
const errors = [];
|
|
492
|
+
if (!params.file_path || typeof params.file_path !== "string") {
|
|
493
|
+
errors.push('Required parameter "file_path" must be a non-empty string');
|
|
494
|
+
}
|
|
495
|
+
if (params.content === void 0 || typeof params.content !== "string") {
|
|
496
|
+
errors.push('Required parameter "content" must be a string');
|
|
497
|
+
}
|
|
498
|
+
if (params.description !== void 0 && typeof params.description !== "string") {
|
|
499
|
+
errors.push('Parameter "description" must be a string');
|
|
500
|
+
}
|
|
501
|
+
if (errors.length > 0) {
|
|
502
|
+
return { valid: false, errors };
|
|
503
|
+
}
|
|
504
|
+
return {
|
|
505
|
+
valid: true,
|
|
506
|
+
data: {
|
|
507
|
+
file_path: params.file_path,
|
|
508
|
+
content: params.content,
|
|
509
|
+
description: params.description
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
};
|
|
513
|
+
var validateDirLsParams = (params) => {
|
|
514
|
+
const errors = [];
|
|
515
|
+
if (params.path !== void 0 && typeof params.path !== "string") {
|
|
516
|
+
errors.push('Parameter "path" must be a string');
|
|
517
|
+
}
|
|
518
|
+
if (params.limit !== void 0) {
|
|
519
|
+
if (typeof params.limit !== "number" || params.limit < 1) {
|
|
520
|
+
errors.push('Parameter "limit" must be a positive integer');
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (params.description !== void 0 && typeof params.description !== "string") {
|
|
524
|
+
errors.push('Parameter "description" must be a string');
|
|
525
|
+
}
|
|
526
|
+
if (errors.length > 0) {
|
|
527
|
+
return { valid: false, errors };
|
|
528
|
+
}
|
|
529
|
+
return {
|
|
530
|
+
valid: true,
|
|
531
|
+
data: {
|
|
532
|
+
path: params.path,
|
|
533
|
+
limit: params.limit,
|
|
534
|
+
description: params.description
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
};
|
|
538
|
+
var validateWebSearchParams = (params) => {
|
|
539
|
+
const errors = [];
|
|
540
|
+
if (!params.query || typeof params.query !== "string") {
|
|
541
|
+
errors.push('Required parameter "query" must be a non-empty string');
|
|
542
|
+
}
|
|
543
|
+
if (params.count !== void 0) {
|
|
544
|
+
if (typeof params.count !== "number" || params.count < 1 || params.count > 50) {
|
|
545
|
+
errors.push('Parameter "count" must be a number between 1 and 50');
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (params.offset !== void 0) {
|
|
549
|
+
if (typeof params.offset !== "number" || params.offset < 0) {
|
|
550
|
+
errors.push('Parameter "offset" must be a non-negative number');
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
if (params.domains !== void 0) {
|
|
554
|
+
if (!Array.isArray(params.domains) || !params.domains.every((d) => typeof d === "string")) {
|
|
555
|
+
errors.push('Parameter "domains" must be an array of strings');
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if (params.recencyDays !== void 0) {
|
|
559
|
+
if (typeof params.recencyDays !== "number" || params.recencyDays < 1) {
|
|
560
|
+
errors.push('Parameter "recencyDays" must be a positive number');
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (params.lang !== void 0 && typeof params.lang !== "string") {
|
|
564
|
+
errors.push('Parameter "lang" must be a string');
|
|
565
|
+
}
|
|
566
|
+
if (params.region !== void 0 && typeof params.region !== "string") {
|
|
567
|
+
errors.push('Parameter "region" must be a string');
|
|
568
|
+
}
|
|
569
|
+
if (params.safe !== void 0 && typeof params.safe !== "boolean") {
|
|
570
|
+
errors.push('Parameter "safe" must be a boolean');
|
|
571
|
+
}
|
|
572
|
+
if (params.type !== void 0) {
|
|
573
|
+
if (params.type !== "web" && params.type !== "images") {
|
|
574
|
+
errors.push('Parameter "type" must be either "web" or "images"');
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (params.hydrateMeta !== void 0 && typeof params.hydrateMeta !== "boolean") {
|
|
578
|
+
errors.push('Parameter "hydrateMeta" must be a boolean');
|
|
579
|
+
}
|
|
580
|
+
if (params.description !== void 0 && typeof params.description !== "string") {
|
|
581
|
+
errors.push('Parameter "description" must be a string');
|
|
582
|
+
}
|
|
583
|
+
if (errors.length > 0) {
|
|
584
|
+
return { valid: false, errors };
|
|
585
|
+
}
|
|
586
|
+
return {
|
|
587
|
+
valid: true,
|
|
588
|
+
data: {
|
|
589
|
+
query: params.query,
|
|
590
|
+
count: params.count,
|
|
591
|
+
offset: params.offset,
|
|
592
|
+
domains: params.domains,
|
|
593
|
+
recencyDays: params.recencyDays,
|
|
594
|
+
lang: params.lang,
|
|
595
|
+
region: params.region,
|
|
596
|
+
safe: params.safe,
|
|
597
|
+
type: params.type,
|
|
598
|
+
hydrateMeta: params.hydrateMeta,
|
|
599
|
+
description: params.description
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
};
|
|
603
|
+
var validateWebFetchParams = (params) => {
|
|
604
|
+
const errors = [];
|
|
605
|
+
if (!params.url || typeof params.url !== "string") {
|
|
606
|
+
errors.push('Required parameter "url" must be a non-empty string');
|
|
607
|
+
}
|
|
608
|
+
if (params.description !== void 0 && typeof params.description !== "string") {
|
|
609
|
+
errors.push('Parameter "description" must be a string');
|
|
610
|
+
}
|
|
611
|
+
if (errors.length > 0) {
|
|
612
|
+
return { valid: false, errors };
|
|
613
|
+
}
|
|
614
|
+
return {
|
|
615
|
+
valid: true,
|
|
616
|
+
data: {
|
|
617
|
+
url: params.url,
|
|
618
|
+
description: params.description
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
};
|
|
622
|
+
var validateTodoWriteParams = (params) => {
|
|
623
|
+
const errors = [];
|
|
624
|
+
if (!params.todos || !Array.isArray(params.todos)) {
|
|
625
|
+
errors.push('Required parameter "todos" must be an array');
|
|
626
|
+
} else {
|
|
627
|
+
for (let i = 0; i < params.todos.length; i++) {
|
|
628
|
+
const todo = params.todos[i];
|
|
629
|
+
if (typeof todo !== "object" || todo === null) {
|
|
630
|
+
errors.push(`todos[${i}] must be an object`);
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
if (!todo.id || typeof todo.id !== "string") {
|
|
634
|
+
errors.push(`todos[${i}].id must be a non-empty string`);
|
|
635
|
+
}
|
|
636
|
+
if (!todo.content || typeof todo.content !== "string") {
|
|
637
|
+
errors.push(`todos[${i}].content must be a non-empty string`);
|
|
638
|
+
}
|
|
639
|
+
if (!todo.status || !["pending", "in_progress", "completed"].includes(todo.status)) {
|
|
640
|
+
errors.push(`todos[${i}].status must be one of: pending, in_progress, completed`);
|
|
641
|
+
}
|
|
642
|
+
if (!todo.priority || !["high", "medium", "low"].includes(todo.priority)) {
|
|
643
|
+
errors.push(`todos[${i}].priority must be one of: high, medium, low`);
|
|
644
|
+
}
|
|
645
|
+
if (todo.createdAt !== void 0 && typeof todo.createdAt !== "string") {
|
|
646
|
+
errors.push(`todos[${i}].createdAt must be a string`);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
if (params.description !== void 0 && typeof params.description !== "string") {
|
|
651
|
+
errors.push('Parameter "description" must be a string');
|
|
652
|
+
}
|
|
653
|
+
if (errors.length > 0) {
|
|
654
|
+
return { valid: false, errors };
|
|
655
|
+
}
|
|
656
|
+
return {
|
|
657
|
+
valid: true,
|
|
658
|
+
data: {
|
|
659
|
+
todos: params.todos,
|
|
660
|
+
description: params.description
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
};
|
|
664
|
+
var validateAssignTaskParams = (params) => {
|
|
665
|
+
const errors = [];
|
|
666
|
+
if (!params.agent || typeof params.agent !== "string") {
|
|
667
|
+
errors.push('Required parameter "agent" must be a non-empty string');
|
|
668
|
+
}
|
|
669
|
+
if (!params.task || typeof params.task !== "string") {
|
|
670
|
+
errors.push('Required parameter "task" must be a non-empty string');
|
|
671
|
+
}
|
|
672
|
+
if (!params.description || typeof params.description !== "string") {
|
|
673
|
+
errors.push('Required parameter "description" must be a non-empty string');
|
|
674
|
+
}
|
|
675
|
+
if (errors.length > 0) {
|
|
676
|
+
return { valid: false, errors };
|
|
677
|
+
}
|
|
678
|
+
return {
|
|
679
|
+
valid: true,
|
|
680
|
+
data: {
|
|
681
|
+
agent: params.agent,
|
|
682
|
+
task: params.task,
|
|
683
|
+
description: params.description
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
};
|
|
687
|
+
var toolValidators = {
|
|
688
|
+
bash_tool: validateBashToolParams,
|
|
689
|
+
file_read: validateFileReadParams,
|
|
690
|
+
file_edit: validateFileEditParams,
|
|
691
|
+
file_new: validateFileNewParams,
|
|
692
|
+
dir_ls: validateDirLsParams,
|
|
693
|
+
web_search: validateWebSearchParams,
|
|
694
|
+
web_fetch: validateWebFetchParams,
|
|
695
|
+
todo_write: validateTodoWriteParams,
|
|
696
|
+
assign_task: validateAssignTaskParams
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
// src/tools/tool-call-converter.ts
|
|
700
|
+
function convertToolCall(toolCall, options = {}) {
|
|
701
|
+
const { strict = false } = options;
|
|
702
|
+
const parseResult = parseJSON(toolCall.function.arguments);
|
|
703
|
+
if (!parseResult.success) {
|
|
704
|
+
return {
|
|
705
|
+
valid: false,
|
|
706
|
+
error: parseResult.error,
|
|
707
|
+
errorType: "parse",
|
|
708
|
+
callId: toolCall.id,
|
|
709
|
+
toolName: toolCall.function.name,
|
|
710
|
+
rawArguments: toolCall.function.arguments
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
const toolName = toolCall.function.name;
|
|
714
|
+
const parameters = parseResult.data;
|
|
715
|
+
const validator = toolValidators[toolName];
|
|
716
|
+
if (validator) {
|
|
717
|
+
const validationResult = validator(parameters);
|
|
718
|
+
if (!validationResult.valid) {
|
|
719
|
+
if (strict) {
|
|
720
|
+
return {
|
|
721
|
+
valid: false,
|
|
722
|
+
error: `Validation failed: ${validationResult.errors.join("; ")}`,
|
|
723
|
+
errorType: "validation",
|
|
724
|
+
callId: toolCall.id,
|
|
725
|
+
toolName: toolCall.function.name,
|
|
726
|
+
rawArguments: toolCall.function.arguments
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
console.warn(`[ToolCallConverter] Validation warnings for ${toolName}:`, validationResult.errors);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
return {
|
|
733
|
+
valid: true,
|
|
734
|
+
invocation: {
|
|
735
|
+
id: toolCall.id,
|
|
736
|
+
name: toolCall.function.name,
|
|
737
|
+
parameters
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
function convertToolCalls(toolCalls, options = {}) {
|
|
742
|
+
const { strict = false, throwOnError = true } = options;
|
|
743
|
+
const invocations = [];
|
|
744
|
+
for (const tc of toolCalls) {
|
|
745
|
+
const result = convertToolCall(tc, { strict });
|
|
746
|
+
if (!result.valid) {
|
|
747
|
+
const errorMsg = `Tool call ${result.callId} (${result.toolName}): ${result.error}`;
|
|
748
|
+
if (throwOnError) {
|
|
749
|
+
throw new Error(errorMsg);
|
|
750
|
+
}
|
|
751
|
+
console.error(`[ToolCallConverter] ${errorMsg}`);
|
|
752
|
+
invocations.push({
|
|
753
|
+
id: result.callId,
|
|
754
|
+
name: result.toolName,
|
|
755
|
+
parameters: {}
|
|
756
|
+
});
|
|
757
|
+
} else {
|
|
758
|
+
invocations.push(result.invocation);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return invocations;
|
|
762
|
+
}
|
|
763
|
+
|
|
378
764
|
// src/orchestrator.ts
|
|
379
765
|
var removeAttachmentTokens = (value, attachments) => {
|
|
380
766
|
return attachments.reduce((acc, attachment) => {
|
|
@@ -629,37 +1015,30 @@ var AgentOrchestrator = class {
|
|
|
629
1015
|
if (!_llm) {
|
|
630
1016
|
throw new Error("LLM provider not set");
|
|
631
1017
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
1018
|
+
const normalized = typeof content === "string" ? { text: content, displayText: content, attachments: [] } : {
|
|
1019
|
+
text: content.text ?? "",
|
|
1020
|
+
displayText: content.displayText,
|
|
1021
|
+
attachments: Array.isArray(content.attachments) ? content.attachments : []
|
|
1022
|
+
};
|
|
1023
|
+
const attachments = normalized.attachments;
|
|
1024
|
+
enhanced = this.reminders.enhance(normalized.text, { conversationId: convo });
|
|
1025
|
+
const enhancedCombined = enhanced.join("\n");
|
|
1026
|
+
const messageParts = buildMessageParts(enhancedCombined, attachments);
|
|
1027
|
+
let userContent;
|
|
1028
|
+
if (attachments.length > 0 || messageParts.some((part) => part.type === "image")) {
|
|
1029
|
+
userContent = { type: "parts", parts: messageParts };
|
|
1030
|
+
} else if (messageParts.length === 1 && messageParts[0]?.type === "text") {
|
|
1031
|
+
userContent = messageParts[0].text;
|
|
1032
|
+
} else if (messageParts.length > 0) {
|
|
1033
|
+
userContent = { type: "parts", parts: messageParts };
|
|
637
1034
|
} else {
|
|
638
|
-
|
|
639
|
-
text: content.text ?? "",
|
|
640
|
-
displayText: content.displayText,
|
|
641
|
-
attachments: Array.isArray(content.attachments) ? content.attachments : []
|
|
642
|
-
};
|
|
643
|
-
const attachments = normalized.attachments;
|
|
644
|
-
enhanced = this.reminders.enhance(normalized.text, { conversationId: convo });
|
|
645
|
-
const enhancedCombined = enhanced.join("\n");
|
|
646
|
-
const messageParts = buildMessageParts(enhancedCombined, attachments);
|
|
647
|
-
let userContent;
|
|
648
|
-
if (attachments.length > 0 || messageParts.some((part) => part.type === "image")) {
|
|
649
|
-
userContent = { type: "parts", parts: messageParts };
|
|
650
|
-
} else if (messageParts.length === 1 && messageParts[0]?.type === "text") {
|
|
651
|
-
userContent = messageParts[0].text;
|
|
652
|
-
} else if (messageParts.length > 0) {
|
|
653
|
-
userContent = { type: "parts", parts: messageParts };
|
|
654
|
-
} else {
|
|
655
|
-
userContent = enhancedCombined;
|
|
656
|
-
}
|
|
657
|
-
providerMsgs = this.context.toProviderMessages(history, this.cfg.systemPrompt, [userContent]);
|
|
658
|
-
userDisplay = resolveDisplayText(normalized.text, attachments, normalized.displayText);
|
|
659
|
-
const userTimestamp = this.clock.iso();
|
|
660
|
-
userMessages = [{ id: this.ids.uuid(), role: "user", content: userContent, timestamp: userTimestamp }];
|
|
661
|
-
await this.memory.append(convo, userMessages);
|
|
1035
|
+
userContent = enhancedCombined;
|
|
662
1036
|
}
|
|
1037
|
+
providerMsgs = this.context.toProviderMessages(history, this.cfg.systemPrompt, [userContent]);
|
|
1038
|
+
userDisplay = resolveDisplayText(normalized.text, attachments, normalized.displayText);
|
|
1039
|
+
const userTimestamp = this.clock.iso();
|
|
1040
|
+
userMessages = [{ id: this.ids.uuid(), role: "user", content: userContent, timestamp: userTimestamp }];
|
|
1041
|
+
await this.memory.append(convo, userMessages);
|
|
663
1042
|
if (opts.signal?.aborted) throw new Error("Aborted");
|
|
664
1043
|
const toolDefs = this.tools.getToolDefinitions(this.cfg.enabledTools ?? []);
|
|
665
1044
|
const toolNames = toolDefs.map((t) => t.function.name);
|
|
@@ -812,7 +1191,14 @@ var AgentOrchestrator = class {
|
|
|
812
1191
|
};
|
|
813
1192
|
const toolResultMsgs = [];
|
|
814
1193
|
for (const tr of toolResults) {
|
|
815
|
-
|
|
1194
|
+
let contentStr;
|
|
1195
|
+
if (tr.status === "error") {
|
|
1196
|
+
contentStr = tr.result;
|
|
1197
|
+
} else if (tr.type === "text") {
|
|
1198
|
+
contentStr = tr.result;
|
|
1199
|
+
} else {
|
|
1200
|
+
contentStr = JSON.stringify(tr.result, null, 2);
|
|
1201
|
+
}
|
|
816
1202
|
toolResultMsgs.push({
|
|
817
1203
|
id: tr.id,
|
|
818
1204
|
role: "tool",
|
|
@@ -838,7 +1224,14 @@ var AgentOrchestrator = class {
|
|
|
838
1224
|
tool_calls: approvedCalls
|
|
839
1225
|
});
|
|
840
1226
|
for (const tr of toolResults) {
|
|
841
|
-
|
|
1227
|
+
let contentStr;
|
|
1228
|
+
if (tr.status === "error") {
|
|
1229
|
+
contentStr = tr.result;
|
|
1230
|
+
} else if (tr.type === "text") {
|
|
1231
|
+
contentStr = tr.result;
|
|
1232
|
+
} else {
|
|
1233
|
+
contentStr = JSON.stringify(tr.result, null, 2);
|
|
1234
|
+
}
|
|
842
1235
|
accumulatedMessages.push({ role: "tool", content: contentStr, tool_call_id: tr.id, name: tr.name });
|
|
843
1236
|
}
|
|
844
1237
|
if (opts.signal?.aborted) throw new Error("Aborted");
|
|
@@ -978,14 +1371,9 @@ var AgentOrchestrator = class {
|
|
|
978
1371
|
}
|
|
979
1372
|
}
|
|
980
1373
|
toInvocations(toolCalls) {
|
|
981
|
-
return toolCalls
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
parameters = JSON.parse(tc.function.arguments || "{}");
|
|
985
|
-
} catch {
|
|
986
|
-
parameters = {};
|
|
987
|
-
}
|
|
988
|
-
return { id: tc.id, name: tc.function.name, parameters };
|
|
1374
|
+
return convertToolCalls(toolCalls, {
|
|
1375
|
+
strict: this.cfg.strictToolValidation ?? false,
|
|
1376
|
+
throwOnError: true
|
|
989
1377
|
});
|
|
990
1378
|
}
|
|
991
1379
|
};
|
|
@@ -1543,6 +1931,18 @@ var TodoStore = class {
|
|
|
1543
1931
|
}
|
|
1544
1932
|
};
|
|
1545
1933
|
|
|
1934
|
+
// src/tools/result-helpers.ts
|
|
1935
|
+
function okText(result, metadata) {
|
|
1936
|
+
return { status: "success", type: "text", result, metadata };
|
|
1937
|
+
}
|
|
1938
|
+
function okJson(result, metadata) {
|
|
1939
|
+
return { status: "success", type: "json", result, metadata };
|
|
1940
|
+
}
|
|
1941
|
+
function err(result, metadata, errorReason) {
|
|
1942
|
+
const finalMetadata = errorReason ? { ...metadata, errorReason } : metadata;
|
|
1943
|
+
return { status: "error", type: "text", result, metadata: finalMetadata };
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1546
1946
|
// src/tools/TodoWriteTool.ts
|
|
1547
1947
|
var TodoWriteTool = class {
|
|
1548
1948
|
constructor(store) {
|
|
@@ -1634,28 +2034,28 @@ When in doubt, use this tool. Being proactive with task management demonstrates
|
|
|
1634
2034
|
const todos = params?.todos;
|
|
1635
2035
|
const ctx = context;
|
|
1636
2036
|
if (!Array.isArray(todos) || todos.length === 0) {
|
|
1637
|
-
return
|
|
2037
|
+
return err('Parameter "todos" must be a non-empty array', void 0, "invalid_input" /* InvalidInput */);
|
|
1638
2038
|
}
|
|
1639
2039
|
for (let i = 0; i < todos.length; i++) {
|
|
1640
2040
|
const t = todos[i];
|
|
1641
2041
|
if (!t) continue;
|
|
1642
2042
|
if (!t.content || typeof t.content !== "string" || !t.content.trim()) {
|
|
1643
|
-
return
|
|
2043
|
+
return err(`Todo ${i + 1}: content required`, void 0, "invalid_input" /* InvalidInput */);
|
|
1644
2044
|
}
|
|
1645
2045
|
if (!["pending", "in_progress", "completed"].includes(String(t.status))) {
|
|
1646
|
-
return
|
|
2046
|
+
return err(`Todo ${i + 1}: invalid status`, void 0, "invalid_input" /* InvalidInput */);
|
|
1647
2047
|
}
|
|
1648
2048
|
if (!["high", "medium", "low"].includes(String(t.priority))) {
|
|
1649
|
-
return
|
|
2049
|
+
return err(`Todo ${i + 1}: invalid priority`, void 0, "invalid_input" /* InvalidInput */);
|
|
1650
2050
|
}
|
|
1651
2051
|
if (!t.id || typeof t.id !== "string" || !t.id.trim()) {
|
|
1652
|
-
return
|
|
2052
|
+
return err(`Todo ${i + 1}: id required`, void 0, "invalid_input" /* InvalidInput */);
|
|
1653
2053
|
}
|
|
1654
2054
|
}
|
|
1655
2055
|
const ids = todos.map((t) => t.id);
|
|
1656
2056
|
const unique = new Set(ids);
|
|
1657
2057
|
if (unique.size !== ids.length) {
|
|
1658
|
-
return
|
|
2058
|
+
return err("Todo items must have unique IDs", void 0, "invalid_input" /* InvalidInput */);
|
|
1659
2059
|
}
|
|
1660
2060
|
const conversationId = ctx?.sessionId || ctx?.conversationId || "default";
|
|
1661
2061
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1694,17 +2094,13 @@ All todo items are now completed! Ask about next steps. Completed list:
|
|
|
1694
2094
|
Your todo list has changed. DO NOT mention this explicitly to the user. Latest contents:
|
|
1695
2095
|
[${serialized}].
|
|
1696
2096
|
</system-reminder>`;
|
|
1697
|
-
return {
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
progress: `${progress}%`,
|
|
1705
|
-
allCompleted
|
|
1706
|
-
}
|
|
1707
|
-
};
|
|
2097
|
+
return okText(systemReminder, {
|
|
2098
|
+
recentChanges: true,
|
|
2099
|
+
stats,
|
|
2100
|
+
progress: `${progress}%`,
|
|
2101
|
+
allCompleted,
|
|
2102
|
+
conversationId
|
|
2103
|
+
});
|
|
1708
2104
|
}
|
|
1709
2105
|
};
|
|
1710
2106
|
|
|
@@ -1919,21 +2315,35 @@ var WebSearchTool = class {
|
|
|
1919
2315
|
};
|
|
1920
2316
|
}
|
|
1921
2317
|
provider = new GoogleCseProvider();
|
|
2318
|
+
/**
|
|
2319
|
+
* Execute web search using Google Programmable Search Engine
|
|
2320
|
+
*
|
|
2321
|
+
* @param params - Search query and optional filters (domains, recency, language, region)
|
|
2322
|
+
* @param ctx - Execution context with optional abort signal
|
|
2323
|
+
* @returns Structured JSON with search results including title, URL, snippet, and metadata
|
|
2324
|
+
*
|
|
2325
|
+
* @example
|
|
2326
|
+
* ```typescript
|
|
2327
|
+
* const result = await webSearchTool.execute({
|
|
2328
|
+
* query: 'TypeScript discriminated unions',
|
|
2329
|
+
* count: 10,
|
|
2330
|
+
* lang: 'en'
|
|
2331
|
+
* });
|
|
2332
|
+
* if (result.status === 'success' && result.type === 'json') {
|
|
2333
|
+
* console.log(result.result.count); // number of results
|
|
2334
|
+
* result.result.items.forEach(item => {
|
|
2335
|
+
* console.log(`${item.title}: ${item.url}`);
|
|
2336
|
+
* });
|
|
2337
|
+
* }
|
|
2338
|
+
* ```
|
|
2339
|
+
*/
|
|
1922
2340
|
async execute(params, ctx) {
|
|
1923
2341
|
if (ctx?.signal?.aborted) {
|
|
1924
|
-
return
|
|
1925
|
-
type: "text",
|
|
1926
|
-
status: "error",
|
|
1927
|
-
result: "Search aborted by user"
|
|
1928
|
-
};
|
|
2342
|
+
return err("Search aborted by user", void 0, "aborted" /* Aborted */);
|
|
1929
2343
|
}
|
|
1930
2344
|
const query = typeof params.query === "string" ? params.query : "";
|
|
1931
2345
|
if (!query) {
|
|
1932
|
-
return
|
|
1933
|
-
type: "text",
|
|
1934
|
-
status: "error",
|
|
1935
|
-
result: "Missing required parameter: query"
|
|
1936
|
-
};
|
|
2346
|
+
return err("Missing required parameter: query", void 0, "invalid_input" /* InvalidInput */);
|
|
1937
2347
|
}
|
|
1938
2348
|
const p = {
|
|
1939
2349
|
query: String(params.query ?? "").trim(),
|
|
@@ -1948,14 +2358,10 @@ var WebSearchTool = class {
|
|
|
1948
2358
|
hydrateMeta: params.hydrateMeta ?? false
|
|
1949
2359
|
};
|
|
1950
2360
|
if (!p.query) {
|
|
1951
|
-
return
|
|
2361
|
+
return err("Missing 'query'", void 0, "invalid_input" /* InvalidInput */);
|
|
1952
2362
|
}
|
|
1953
2363
|
if (!process.env.GOOGLE_CSE_KEY || !process.env.GOOGLE_CSE_CX) {
|
|
1954
|
-
return
|
|
1955
|
-
status: "error",
|
|
1956
|
-
type: "text",
|
|
1957
|
-
result: "GOOGLE_CSE_KEY and GOOGLE_CSE_CX are required for this tool (Google CSE only)."
|
|
1958
|
-
};
|
|
2364
|
+
return err("GOOGLE_CSE_KEY and GOOGLE_CSE_CX are required for this tool (Google CSE only).", void 0, "invalid_input" /* InvalidInput */);
|
|
1959
2365
|
}
|
|
1960
2366
|
try {
|
|
1961
2367
|
let results = await this.provider.search(p, ctx?.signal);
|
|
@@ -1969,23 +2375,30 @@ var WebSearchTool = class {
|
|
|
1969
2375
|
seen.add(k);
|
|
1970
2376
|
return true;
|
|
1971
2377
|
}).slice(0, p.count);
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
2378
|
+
const appliedFilters = {};
|
|
2379
|
+
if (p.domains.length > 0) appliedFilters.domains = p.domains;
|
|
2380
|
+
if (p.recencyDays > 0) appliedFilters.recencyDays = p.recencyDays;
|
|
2381
|
+
if (p.lang && p.lang !== "en") appliedFilters.lang = p.lang;
|
|
2382
|
+
if (p.region) appliedFilters.region = p.region;
|
|
2383
|
+
return okJson({
|
|
2384
|
+
engine: this.provider.name,
|
|
2385
|
+
count: results.length,
|
|
2386
|
+
items: results,
|
|
2387
|
+
query: p.query,
|
|
2388
|
+
appliedFilters: Object.keys(appliedFilters).length > 0 ? appliedFilters : void 0
|
|
2389
|
+
}, {
|
|
2390
|
+
offset: p.offset,
|
|
2391
|
+
totalRequested: p.count,
|
|
2392
|
+
hydrated: p.hydrateMeta
|
|
2393
|
+
});
|
|
1981
2394
|
} catch (error) {
|
|
1982
2395
|
const message = error instanceof Error ? error.message : String(error);
|
|
1983
2396
|
const isAborted = message.includes("aborted by user");
|
|
1984
|
-
return
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
2397
|
+
return err(
|
|
2398
|
+
isAborted ? "Search aborted by user" : message.slice(0, 500),
|
|
2399
|
+
void 0,
|
|
2400
|
+
isAborted ? "aborted" /* Aborted */ : "unknown" /* Unknown */
|
|
2401
|
+
);
|
|
1989
2402
|
}
|
|
1990
2403
|
}
|
|
1991
2404
|
};
|
|
@@ -2024,10 +2437,10 @@ var WebFetchTool = class {
|
|
|
2024
2437
|
async execute(params, ctx) {
|
|
2025
2438
|
const target = String(params.url ?? "");
|
|
2026
2439
|
if (!target) {
|
|
2027
|
-
return
|
|
2440
|
+
return err("URL parameter is required", void 0, "invalid_input" /* InvalidInput */);
|
|
2028
2441
|
}
|
|
2029
2442
|
if (ctx?.signal?.aborted) {
|
|
2030
|
-
return
|
|
2443
|
+
return err("Fetch aborted by user", void 0, "aborted" /* Aborted */);
|
|
2031
2444
|
}
|
|
2032
2445
|
try {
|
|
2033
2446
|
const res = await fetch(target, {
|
|
@@ -2037,33 +2450,41 @@ var WebFetchTool = class {
|
|
|
2037
2450
|
signal: ctx?.signal
|
|
2038
2451
|
});
|
|
2039
2452
|
if (!res.ok) {
|
|
2040
|
-
return {
|
|
2041
|
-
status: "error",
|
|
2042
|
-
type: "text",
|
|
2043
|
-
result: `HTTP ${res.status} ${res.statusText}`
|
|
2044
|
-
};
|
|
2453
|
+
return err(`HTTP ${res.status} ${res.statusText}`, { url: target }, "network_error" /* NetworkError */);
|
|
2045
2454
|
}
|
|
2046
2455
|
const contentType = res.headers.get("content-type") || "";
|
|
2047
2456
|
const text = await res.text();
|
|
2457
|
+
const fetchedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2458
|
+
let finalText;
|
|
2459
|
+
let format;
|
|
2048
2460
|
if (contentType.includes("application/json")) {
|
|
2049
|
-
|
|
2461
|
+
finalText = `\`\`\`json
|
|
2050
2462
|
${text}
|
|
2051
2463
|
\`\`\``;
|
|
2052
|
-
|
|
2464
|
+
format = "json";
|
|
2053
2465
|
} else if (contentType.includes("text/html")) {
|
|
2054
|
-
|
|
2055
|
-
|
|
2466
|
+
finalText = this.turndownService.turndown(text);
|
|
2467
|
+
format = "markdown";
|
|
2056
2468
|
} else {
|
|
2057
|
-
|
|
2469
|
+
finalText = text;
|
|
2470
|
+
format = "text";
|
|
2058
2471
|
}
|
|
2472
|
+
return okText(finalText, {
|
|
2473
|
+
url: target,
|
|
2474
|
+
contentType,
|
|
2475
|
+
statusCode: res.status,
|
|
2476
|
+
format,
|
|
2477
|
+
size: text.length,
|
|
2478
|
+
fetchedAt
|
|
2479
|
+
});
|
|
2059
2480
|
} catch (error) {
|
|
2060
2481
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2061
2482
|
const isAborted = errorMessage.includes("aborted") || error.name === "AbortError";
|
|
2062
|
-
return
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2483
|
+
return err(
|
|
2484
|
+
isAborted ? "Fetch aborted by user" : errorMessage,
|
|
2485
|
+
{ url: target },
|
|
2486
|
+
isAborted ? "aborted" /* Aborted */ : "network_error" /* NetworkError */
|
|
2487
|
+
);
|
|
2067
2488
|
}
|
|
2068
2489
|
}
|
|
2069
2490
|
};
|
|
@@ -2071,17 +2492,6 @@ ${text}
|
|
|
2071
2492
|
// src/tools/FileReadTool.ts
|
|
2072
2493
|
import { promises as fs3 } from "fs";
|
|
2073
2494
|
import * as path3 from "path";
|
|
2074
|
-
|
|
2075
|
-
// src/tools/result-helpers.ts
|
|
2076
|
-
function ok(result, metadata) {
|
|
2077
|
-
return { status: "success", type: "text", result, metadata };
|
|
2078
|
-
}
|
|
2079
|
-
function err(result, metadata, errorReason) {
|
|
2080
|
-
const finalMetadata = errorReason ? { ...metadata, errorReason } : metadata;
|
|
2081
|
-
return { status: "error", type: "text", result, metadata: finalMetadata };
|
|
2082
|
-
}
|
|
2083
|
-
|
|
2084
|
-
// src/tools/FileReadTool.ts
|
|
2085
2495
|
var FileReadTool = class {
|
|
2086
2496
|
name = "file_read";
|
|
2087
2497
|
rootDir;
|
|
@@ -2114,24 +2524,45 @@ var FileReadTool = class {
|
|
|
2114
2524
|
parameters: this.parameters
|
|
2115
2525
|
};
|
|
2116
2526
|
}
|
|
2527
|
+
/**
|
|
2528
|
+
* Read file contents with optional line range selection
|
|
2529
|
+
*
|
|
2530
|
+
* @param params - File path and optional line range (lineStart, lineEnd)
|
|
2531
|
+
* @param context - Execution context with optional workspace directory
|
|
2532
|
+
* @returns File content as text with metadata including path, size, and line range
|
|
2533
|
+
*
|
|
2534
|
+
* @example
|
|
2535
|
+
* ```typescript
|
|
2536
|
+
* const result = await fileReadTool.execute({ path: 'package.json' });
|
|
2537
|
+
* if (result.status === 'success' && result.type === 'text') {
|
|
2538
|
+
* console.log(result.result); // file contents
|
|
2539
|
+
* console.log(result.metadata?.path); // resolved file path
|
|
2540
|
+
* console.log(result.metadata?.size); // file size in bytes
|
|
2541
|
+
* }
|
|
2542
|
+
* ```
|
|
2543
|
+
*/
|
|
2117
2544
|
async execute(params, context) {
|
|
2118
2545
|
try {
|
|
2119
2546
|
if (!params.path || typeof params.path !== "string") {
|
|
2120
|
-
return err('Parameter "path" must be a non-empty string');
|
|
2547
|
+
return err('Parameter "path" must be a non-empty string', void 0, "invalid_input" /* InvalidInput */);
|
|
2121
2548
|
}
|
|
2122
2549
|
const abs = this.resolveSafePath(params.path, context);
|
|
2123
2550
|
const st = await fs3.stat(abs).catch(() => null);
|
|
2124
|
-
if (!st || !st.isFile()) return err(`File not found: ${params.path}
|
|
2551
|
+
if (!st || !st.isFile()) return err(`File not found: ${params.path}`, { path: params.path }, "not_found" /* NotFound */);
|
|
2125
2552
|
if (st.size > this.maxBytesHard) {
|
|
2126
|
-
return err(`File too large (${st.size} bytes). Hard cap is ${this.maxBytesHard} bytes
|
|
2553
|
+
return err(`File too large (${st.size} bytes). Hard cap is ${this.maxBytesHard} bytes.`, { path: params.path }, "invalid_input" /* InvalidInput */);
|
|
2127
2554
|
}
|
|
2128
2555
|
const payload = await fs3.readFile(abs);
|
|
2129
2556
|
let text = payload.toString("utf8");
|
|
2557
|
+
const bomStripped = text.charCodeAt(0) === 65279;
|
|
2130
2558
|
text = stripUtfBom(text);
|
|
2131
2559
|
const metadata = {
|
|
2132
2560
|
path: params.path,
|
|
2133
2561
|
created: st.birthtime.toISOString(),
|
|
2134
|
-
modified: st.mtime.toISOString()
|
|
2562
|
+
modified: st.mtime.toISOString(),
|
|
2563
|
+
size: st.size,
|
|
2564
|
+
encoding: "utf8",
|
|
2565
|
+
bomStripped
|
|
2135
2566
|
};
|
|
2136
2567
|
if (params.lineStart || params.lineEnd) {
|
|
2137
2568
|
const lines = text.split(/\r?\n/);
|
|
@@ -2144,17 +2575,19 @@ var FileReadTool = class {
|
|
|
2144
2575
|
return `${lineNum}\u2502${line}`;
|
|
2145
2576
|
});
|
|
2146
2577
|
const slice = numberedLines.join("\n");
|
|
2147
|
-
return
|
|
2578
|
+
return okText(slice, {
|
|
2148
2579
|
...metadata,
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2580
|
+
lineRange: {
|
|
2581
|
+
lineStart: lo,
|
|
2582
|
+
lineEnd: hi,
|
|
2583
|
+
linesTotal: totalLines
|
|
2584
|
+
}
|
|
2152
2585
|
});
|
|
2153
2586
|
}
|
|
2154
|
-
return
|
|
2587
|
+
return okText(text, metadata);
|
|
2155
2588
|
} catch (e) {
|
|
2156
2589
|
const message = e instanceof Error ? e.message : String(e);
|
|
2157
|
-
return err(message);
|
|
2590
|
+
return err(message, { path: params.path }, "unknown" /* Unknown */);
|
|
2158
2591
|
}
|
|
2159
2592
|
}
|
|
2160
2593
|
// ---------- helpers ----------
|
|
@@ -2209,16 +2642,22 @@ var FileNewTool = class {
|
|
|
2209
2642
|
}
|
|
2210
2643
|
async execute(p, ctx) {
|
|
2211
2644
|
try {
|
|
2212
|
-
if (!p.file_path?.trim()) return err('Parameter "file_path" is required.');
|
|
2213
|
-
if (typeof p.content !== "string") return err('"content" must be a string.');
|
|
2645
|
+
if (!p.file_path?.trim()) return err('Parameter "file_path" is required.', void 0, "invalid_input" /* InvalidInput */);
|
|
2646
|
+
if (typeof p.content !== "string") return err('"content" must be a string.', void 0, "invalid_input" /* InvalidInput */);
|
|
2214
2647
|
const abs = this.resolveSafePath(p.file_path, ctx);
|
|
2648
|
+
const existsBefore = await fs4.stat(abs).then(() => true).catch(() => false);
|
|
2215
2649
|
await fs4.mkdir(path4.dirname(abs), { recursive: true });
|
|
2216
2650
|
const bytes = Buffer.from(p.content, "utf8");
|
|
2217
2651
|
await this.writeAtomic(abs, bytes);
|
|
2218
|
-
return
|
|
2652
|
+
return okText(`File written at ${p.file_path}.`, {
|
|
2653
|
+
file_path: p.file_path,
|
|
2654
|
+
bytes: bytes.length,
|
|
2655
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2656
|
+
overwritten: existsBefore
|
|
2657
|
+
});
|
|
2219
2658
|
} catch (e) {
|
|
2220
2659
|
const message = e instanceof Error ? e.message : String(e);
|
|
2221
|
-
return err(message);
|
|
2660
|
+
return err(message, void 0, "unknown" /* Unknown */);
|
|
2222
2661
|
}
|
|
2223
2662
|
}
|
|
2224
2663
|
// helpers
|
|
@@ -2295,21 +2734,21 @@ var FileEditTool = class {
|
|
|
2295
2734
|
}
|
|
2296
2735
|
async execute(p, ctx) {
|
|
2297
2736
|
try {
|
|
2298
|
-
if (!p.file_path?.trim()) return err('Parameter "file_path" is required.');
|
|
2737
|
+
if (!p.file_path?.trim()) return err('Parameter "file_path" is required.', void 0, "invalid_input" /* InvalidInput */);
|
|
2299
2738
|
const abs = resolveAbsoluteWithinRoot(p.file_path, ctx, this.rootDir);
|
|
2300
2739
|
if (typeof p.old_text !== "string") {
|
|
2301
|
-
return err("old_text must be a string.");
|
|
2740
|
+
return err("old_text must be a string.", void 0, "invalid_input" /* InvalidInput */);
|
|
2302
2741
|
}
|
|
2303
2742
|
if (typeof p.new_text !== "string") {
|
|
2304
|
-
return err("new_text must be a string.");
|
|
2743
|
+
return err("new_text must be a string.", void 0, "invalid_input" /* InvalidInput */);
|
|
2305
2744
|
}
|
|
2306
2745
|
const st = await fs5.stat(abs).catch(() => null);
|
|
2307
2746
|
const exists = !!st && st.isFile();
|
|
2308
2747
|
if (!exists || !st) {
|
|
2309
|
-
return err("File does not exist. Use a file creation tool to create new files.");
|
|
2748
|
+
return err("File does not exist. Use a file creation tool to create new files.", void 0, "not_found" /* NotFound */);
|
|
2310
2749
|
}
|
|
2311
2750
|
if (st.size > this.maxBytes) {
|
|
2312
|
-
return err(`File too large (${st.size} bytes). Cap is ${this.maxBytes}
|
|
2751
|
+
return err(`File too large (${st.size} bytes). Cap is ${this.maxBytes}.`, void 0, "invalid_input" /* InvalidInput */);
|
|
2313
2752
|
}
|
|
2314
2753
|
const originalBytes = await fs5.readFile(abs);
|
|
2315
2754
|
const originalEol = detectEol(originalBytes) ?? "lf";
|
|
@@ -2322,14 +2761,16 @@ var FileEditTool = class {
|
|
|
2322
2761
|
const preview = oldTextLF.slice(0, 100).replace(/\n/g, "\\n");
|
|
2323
2762
|
return err(
|
|
2324
2763
|
`old_text not found in file. Make sure it matches exactly including whitespace.
|
|
2325
|
-
Searching for: "${preview}${oldTextLF.length > 100 ? "..." : ""}"
|
|
2764
|
+
Searching for: "${preview}${oldTextLF.length > 100 ? "..." : ""}"`,
|
|
2765
|
+
void 0,
|
|
2766
|
+
"not_found" /* NotFound */
|
|
2326
2767
|
);
|
|
2327
2768
|
}
|
|
2328
2769
|
const resultLF = originalLF.slice(0, idx) + newTextLF + originalLF.slice(idx + oldTextLF.length);
|
|
2329
2770
|
const finalText = convertEol(resultLF, originalEol);
|
|
2330
2771
|
const finalBytes = Buffer.from(finalText, "utf8");
|
|
2331
2772
|
if (finalBytes.length > this.maxBytes) {
|
|
2332
|
-
return err(`Resulting file too large (${finalBytes.length} bytes). Cap is ${this.maxBytes}
|
|
2773
|
+
return err(`Resulting file too large (${finalBytes.length} bytes). Cap is ${this.maxBytes}.`, void 0, "invalid_input" /* InvalidInput */);
|
|
2333
2774
|
}
|
|
2334
2775
|
const beforeSha = sha256(originalBytes);
|
|
2335
2776
|
const afterSha = sha256(finalBytes);
|
|
@@ -2338,10 +2779,13 @@ Searching for: "${preview}${oldTextLF.length > 100 ? "..." : ""}"`
|
|
|
2338
2779
|
await atomicWrite(abs, finalBytes);
|
|
2339
2780
|
}
|
|
2340
2781
|
const lineNumbers = this.calculateLineNumbers(originalLF, oldTextLF, newTextLF, idx);
|
|
2341
|
-
return
|
|
2782
|
+
return okText(
|
|
2342
2783
|
noChange ? "No changes (content identical)." : p.dry_run ? "Validated (dry run: no write)." : "Edit applied successfully.",
|
|
2343
2784
|
{
|
|
2344
2785
|
path: showPath(abs, this.rootDir),
|
|
2786
|
+
created: st.birthtime.toISOString(),
|
|
2787
|
+
modified: st.mtime.toISOString(),
|
|
2788
|
+
size: st.size,
|
|
2345
2789
|
eol: originalEol,
|
|
2346
2790
|
oldTextLength: oldTextLF.length,
|
|
2347
2791
|
newTextLength: newTextLF.length,
|
|
@@ -2349,11 +2793,12 @@ Searching for: "${preview}${oldTextLF.length > 100 ? "..." : ""}"`
|
|
|
2349
2793
|
beforeSha,
|
|
2350
2794
|
afterSha,
|
|
2351
2795
|
dryRun: !!p.dry_run,
|
|
2352
|
-
lineNumbers
|
|
2796
|
+
lineNumbers,
|
|
2797
|
+
noChange
|
|
2353
2798
|
}
|
|
2354
2799
|
);
|
|
2355
2800
|
} catch (e) {
|
|
2356
|
-
return err(e instanceof Error ? e.message : String(e));
|
|
2801
|
+
return err(e instanceof Error ? e.message : String(e), void 0, "unknown" /* Unknown */);
|
|
2357
2802
|
}
|
|
2358
2803
|
}
|
|
2359
2804
|
calculateLineNumbers(originalText, oldText, newText, matchIndex) {
|
|
@@ -2500,6 +2945,23 @@ var BashTool = class {
|
|
|
2500
2945
|
parameters: this.parameters
|
|
2501
2946
|
};
|
|
2502
2947
|
}
|
|
2948
|
+
/**
|
|
2949
|
+
* Execute bash command with timeout protection
|
|
2950
|
+
*
|
|
2951
|
+
* @param p - Command parameters including cmd, cwd, and optional timeout
|
|
2952
|
+
* @param ctx - Execution context with optional abort signal
|
|
2953
|
+
* @returns Structured result with command output and execution metadata
|
|
2954
|
+
*
|
|
2955
|
+
* @example
|
|
2956
|
+
* ```typescript
|
|
2957
|
+
* const result = await bashTool.execute({ cmd: 'ls -la' });
|
|
2958
|
+
* if (result.status === 'success' && result.type === 'text') {
|
|
2959
|
+
* console.log(result.result); // command output
|
|
2960
|
+
* console.log(result.metadata?.code); // exit code
|
|
2961
|
+
* console.log(result.metadata?.cwd); // working directory
|
|
2962
|
+
* }
|
|
2963
|
+
* ```
|
|
2964
|
+
*/
|
|
2503
2965
|
async execute(p, ctx) {
|
|
2504
2966
|
try {
|
|
2505
2967
|
return await this.execOnce(p, ctx?.signal);
|
|
@@ -2618,7 +3080,7 @@ ${output}` : "";
|
|
|
2618
3080
|
}
|
|
2619
3081
|
return err(output, metadata);
|
|
2620
3082
|
}
|
|
2621
|
-
return
|
|
3083
|
+
return okText(output, { code, signal: exitSignal, cwd, stripped: stripAnsi });
|
|
2622
3084
|
} catch (e) {
|
|
2623
3085
|
if (timer) clearTimeout(timer);
|
|
2624
3086
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -2701,7 +3163,7 @@ var DirLsTool = class {
|
|
|
2701
3163
|
name: this.name,
|
|
2702
3164
|
description: [
|
|
2703
3165
|
"List files and directories in a specified directory.",
|
|
2704
|
-
"Returns entries sorted alphabetically by name
|
|
3166
|
+
"Returns entries sorted alphabetically by name as structured JSON.",
|
|
2705
3167
|
"",
|
|
2706
3168
|
"Typical uses:",
|
|
2707
3169
|
"1) List all files in current directory",
|
|
@@ -2733,6 +3195,25 @@ var DirLsTool = class {
|
|
|
2733
3195
|
return 0;
|
|
2734
3196
|
}
|
|
2735
3197
|
}
|
|
3198
|
+
/**
|
|
3199
|
+
* List directory contents as structured JSON
|
|
3200
|
+
*
|
|
3201
|
+
* @param params - Directory path and optional limit
|
|
3202
|
+
* @param context - Execution context with optional workspace directory
|
|
3203
|
+
* @returns Structured JSON with directory entries including name, type, size, and metadata
|
|
3204
|
+
*
|
|
3205
|
+
* @example
|
|
3206
|
+
* ```typescript
|
|
3207
|
+
* const result = await dirLsTool.execute({ path: 'src/tools', limit: 50 });
|
|
3208
|
+
* if (result.status === 'success' && result.type === 'json') {
|
|
3209
|
+
* console.log(result.result.path); // 'src/tools'
|
|
3210
|
+
* console.log(result.result.total); // number of entries
|
|
3211
|
+
* result.result.entries.forEach(entry => {
|
|
3212
|
+
* console.log(`${entry.name} (${entry.type}): ${entry.size} bytes`);
|
|
3213
|
+
* });
|
|
3214
|
+
* }
|
|
3215
|
+
* ```
|
|
3216
|
+
*/
|
|
2736
3217
|
async execute(params, context) {
|
|
2737
3218
|
try {
|
|
2738
3219
|
const targetPath = params.path ?? ".";
|
|
@@ -2741,10 +3222,10 @@ var DirLsTool = class {
|
|
|
2741
3222
|
const abs = this.resolveSafePath(targetPath, context);
|
|
2742
3223
|
const st = await fs7.stat(abs).catch(() => null);
|
|
2743
3224
|
if (!st) {
|
|
2744
|
-
return err(`Directory not found: ${targetPath}
|
|
3225
|
+
return err(`Directory not found: ${targetPath}`, void 0, "not_found" /* NotFound */);
|
|
2745
3226
|
}
|
|
2746
3227
|
if (!st.isDirectory()) {
|
|
2747
|
-
return err(`Path is not a directory: ${targetPath}
|
|
3228
|
+
return err(`Path is not a directory: ${targetPath}`, void 0, "invalid_input" /* InvalidInput */);
|
|
2748
3229
|
}
|
|
2749
3230
|
const entries = await fs7.readdir(abs);
|
|
2750
3231
|
const results = [];
|
|
@@ -2781,40 +3262,23 @@ var DirLsTool = class {
|
|
|
2781
3262
|
results.push(dirEntry);
|
|
2782
3263
|
}
|
|
2783
3264
|
results.sort((a, b) => a.name.localeCompare(b.name));
|
|
2784
|
-
const
|
|
2785
|
-
|
|
2786
|
-
|
|
3265
|
+
const result = okJson(
|
|
3266
|
+
{
|
|
3267
|
+
path: targetPath,
|
|
3268
|
+
entries: results,
|
|
3269
|
+
truncated: entries.length > limit,
|
|
3270
|
+
total: results.length
|
|
3271
|
+
},
|
|
3272
|
+
{
|
|
3273
|
+
limit,
|
|
3274
|
+
includeHidden
|
|
3275
|
+
}
|
|
3276
|
+
);
|
|
3277
|
+
return result;
|
|
2787
3278
|
} catch (e) {
|
|
2788
3279
|
const message = e instanceof Error ? e.message : String(e);
|
|
2789
|
-
return err(message);
|
|
2790
|
-
}
|
|
2791
|
-
}
|
|
2792
|
-
formatAsLsLine(entry) {
|
|
2793
|
-
const mode = entry.mode ? this.formatMode(entry.mode) : "----------";
|
|
2794
|
-
const size = entry.size !== void 0 ? entry.size.toString().padStart(10) : " 0";
|
|
2795
|
-
const date = entry.mtime ? new Date(entry.mtime) : /* @__PURE__ */ new Date();
|
|
2796
|
-
const month = date.toLocaleString("en-US", { month: "short" });
|
|
2797
|
-
const day = date.getDate().toString().padStart(2);
|
|
2798
|
-
const time = `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
|
|
2799
|
-
const dateStr = `${month} ${day} ${time}`;
|
|
2800
|
-
const typeIndicator = entry.type === "directory" ? "/" : entry.type === "symlink" ? "@" : "";
|
|
2801
|
-
const name = `${entry.name}${typeIndicator}`;
|
|
2802
|
-
return `${mode} ${size} ${dateStr} ${name}`;
|
|
2803
|
-
}
|
|
2804
|
-
formatMode(mode) {
|
|
2805
|
-
const fileType = (mode & 61440) === 16384 ? "d" : (mode & 61440) === 40960 ? "l" : "-";
|
|
2806
|
-
const perms = [
|
|
2807
|
-
mode & 256 ? "r" : "-",
|
|
2808
|
-
mode & 128 ? "w" : "-",
|
|
2809
|
-
mode & 64 ? "x" : "-",
|
|
2810
|
-
mode & 32 ? "r" : "-",
|
|
2811
|
-
mode & 16 ? "w" : "-",
|
|
2812
|
-
mode & 8 ? "x" : "-",
|
|
2813
|
-
mode & 4 ? "r" : "-",
|
|
2814
|
-
mode & 2 ? "w" : "-",
|
|
2815
|
-
mode & 1 ? "x" : "-"
|
|
2816
|
-
];
|
|
2817
|
-
return fileType + perms.join("");
|
|
3280
|
+
return err(message, void 0, "unknown" /* Unknown */);
|
|
3281
|
+
}
|
|
2818
3282
|
}
|
|
2819
3283
|
resolveSafePath(target, context) {
|
|
2820
3284
|
const baseFromCtx = context?.workspaceRoot || context?.cwd || this.rootDir;
|
|
@@ -2892,7 +3356,7 @@ var AgentRegistry = class {
|
|
|
2892
3356
|
systemPrompt: partial.systemPrompt,
|
|
2893
3357
|
tools,
|
|
2894
3358
|
temperature: partial.temperature ?? 0.7,
|
|
2895
|
-
maxTokens: partial.maxTokens ??
|
|
3359
|
+
maxTokens: partial.maxTokens ?? 64e3,
|
|
2896
3360
|
provider: partial.provider,
|
|
2897
3361
|
model: partial.model,
|
|
2898
3362
|
topP: partial.topP,
|
|
@@ -3084,20 +3548,55 @@ ${agentList}`,
|
|
|
3084
3548
|
};
|
|
3085
3549
|
}
|
|
3086
3550
|
/**
|
|
3087
|
-
*
|
|
3551
|
+
* Delegate a task to a specialist agent for focused execution
|
|
3552
|
+
*
|
|
3553
|
+
* @param params - Agent ID and task description to delegate
|
|
3554
|
+
* @param context - Execution context including delegation depth tracking
|
|
3555
|
+
* @returns Delegation result with comprehensive metrics including cost breakdown
|
|
3556
|
+
*
|
|
3557
|
+
* @example
|
|
3558
|
+
* ```typescript
|
|
3559
|
+
* const result = await assignTool.execute({
|
|
3560
|
+
* agent: 'code-reviewer',
|
|
3561
|
+
* task: 'Review the changes in src/tools/*.ts',
|
|
3562
|
+
* description: 'Code review of tool implementations'
|
|
3563
|
+
* });
|
|
3564
|
+
* if (result.status === 'success' && result.type === 'text') {
|
|
3565
|
+
* console.log(result.result); // Agent's response
|
|
3566
|
+
* console.log(result.metadata.metrics?.totalCost); // Cost in USD
|
|
3567
|
+
* console.log(result.metadata.executionTimeMs); // Duration
|
|
3568
|
+
* console.log(result.metadata.toolCallsExecuted); // Number of tool calls
|
|
3569
|
+
* }
|
|
3570
|
+
* ```
|
|
3088
3571
|
*/
|
|
3089
3572
|
async execute(params, context) {
|
|
3090
3573
|
if (!params.agent || typeof params.agent !== "string") {
|
|
3091
|
-
return err('Parameter "agent" is required and must be a string');
|
|
3574
|
+
return err('Parameter "agent" is required and must be a string', void 0, "invalid_input" /* InvalidInput */);
|
|
3092
3575
|
}
|
|
3093
3576
|
if (!params.task || typeof params.task !== "string") {
|
|
3094
|
-
return err('Parameter "task" is required and must be a string');
|
|
3577
|
+
return err('Parameter "task" is required and must be a string', void 0, "invalid_input" /* InvalidInput */);
|
|
3095
3578
|
}
|
|
3096
3579
|
const outcome = await this.delegationService.delegate(params, context);
|
|
3097
3580
|
if (!outcome.success || !outcome.summary) {
|
|
3098
|
-
|
|
3581
|
+
const isNotFound = outcome.error?.includes("not found");
|
|
3582
|
+
const isPolicyDenied = outcome.error?.includes("policy") || outcome.error?.includes("denied");
|
|
3583
|
+
return err(
|
|
3584
|
+
outcome.error ?? "Failed to delegate task.",
|
|
3585
|
+
{
|
|
3586
|
+
agentId: params.agent,
|
|
3587
|
+
agentNotFound: isNotFound,
|
|
3588
|
+
policyDenied: isPolicyDenied,
|
|
3589
|
+
delegationDepth: context?.delegationDepth
|
|
3590
|
+
},
|
|
3591
|
+
"unknown" /* Unknown */
|
|
3592
|
+
);
|
|
3099
3593
|
}
|
|
3100
|
-
|
|
3594
|
+
const metadata = outcome.metadata;
|
|
3595
|
+
return okText(outcome.summary, {
|
|
3596
|
+
...metadata,
|
|
3597
|
+
taskDescription: params.task,
|
|
3598
|
+
delegationDepth: (context?.delegationDepth ?? 0) + 1
|
|
3599
|
+
});
|
|
3101
3600
|
}
|
|
3102
3601
|
};
|
|
3103
3602
|
|
|
@@ -3224,6 +3723,7 @@ var AgentManager = class {
|
|
|
3224
3723
|
result: "Sub-agent execution aborted by user",
|
|
3225
3724
|
metadata: {
|
|
3226
3725
|
agentId,
|
|
3726
|
+
agentName: config.agentName,
|
|
3227
3727
|
toolCallsExecuted: 0,
|
|
3228
3728
|
executionTimeMs: 0,
|
|
3229
3729
|
errorMessage: "Aborted before execution"
|
|
@@ -3237,13 +3737,14 @@ var AgentManager = class {
|
|
|
3237
3737
|
result: `Maximum delegation depth (${MAX_DELEGATION_DEPTH}) exceeded`,
|
|
3238
3738
|
metadata: {
|
|
3239
3739
|
agentId,
|
|
3740
|
+
agentName: config.agentName,
|
|
3240
3741
|
toolCallsExecuted: 0,
|
|
3241
3742
|
executionTimeMs: Date.now() - startTime,
|
|
3242
3743
|
errorMessage: "Max delegation depth exceeded"
|
|
3243
3744
|
}
|
|
3244
3745
|
};
|
|
3245
3746
|
}
|
|
3246
|
-
this.eventCallback?.({
|
|
3747
|
+
await this.eventCallback?.({
|
|
3247
3748
|
type: AgentEventTypes.SubAgentStarted,
|
|
3248
3749
|
conversationId: config.conversationId ?? "default",
|
|
3249
3750
|
messageId: config.messageId ?? "",
|
|
@@ -3262,7 +3763,7 @@ var AgentManager = class {
|
|
|
3262
3763
|
events.push(event);
|
|
3263
3764
|
if (event.type === AgentEventTypes.ToolCalls) {
|
|
3264
3765
|
for (const toolCall of event.toolCalls) {
|
|
3265
|
-
this.eventCallback?.({
|
|
3766
|
+
await this.eventCallback?.({
|
|
3266
3767
|
type: AgentEventTypes.SubAgentToolCall,
|
|
3267
3768
|
conversationId: config.conversationId ?? "default",
|
|
3268
3769
|
messageId: config.messageId ?? "",
|
|
@@ -3273,7 +3774,7 @@ var AgentManager = class {
|
|
|
3273
3774
|
});
|
|
3274
3775
|
}
|
|
3275
3776
|
} else if (event.type === AgentEventTypes.ToolResult) {
|
|
3276
|
-
this.eventCallback?.({
|
|
3777
|
+
await this.eventCallback?.({
|
|
3277
3778
|
type: AgentEventTypes.SubAgentToolResult,
|
|
3278
3779
|
conversationId: config.conversationId ?? "default",
|
|
3279
3780
|
messageId: config.messageId ?? "",
|
|
@@ -3300,6 +3801,16 @@ var AgentManager = class {
|
|
|
3300
3801
|
// Specialists run autonomously
|
|
3301
3802
|
reasoningEffort: freshConfig.reasoningEffort ?? this.delegatingConfig.reasoningEffort
|
|
3302
3803
|
};
|
|
3804
|
+
const metricsPort = new InMemoryMetricsPort((snapshot) => {
|
|
3805
|
+
this.eventCallback?.({
|
|
3806
|
+
type: AgentEventTypes.SubAgentMetrics,
|
|
3807
|
+
conversationId: config.conversationId ?? "default",
|
|
3808
|
+
messageId: config.messageId ?? "",
|
|
3809
|
+
agentId: config.agentId,
|
|
3810
|
+
toolCallId: config.toolCallId ?? "",
|
|
3811
|
+
metrics: snapshot
|
|
3812
|
+
});
|
|
3813
|
+
});
|
|
3303
3814
|
const llm = this.resolveLLM(config);
|
|
3304
3815
|
const specialistOrchestrator = new AgentOrchestrator(specialistConfig, {
|
|
3305
3816
|
memory,
|
|
@@ -3310,7 +3821,8 @@ var AgentManager = class {
|
|
|
3310
3821
|
clock: new SystemClock(),
|
|
3311
3822
|
cost: new SimpleCost(),
|
|
3312
3823
|
reminders: new NoopReminders(),
|
|
3313
|
-
events: eventPort
|
|
3824
|
+
events: eventPort,
|
|
3825
|
+
metrics: metricsPort
|
|
3314
3826
|
});
|
|
3315
3827
|
this.activeAgents.set(agentId, specialistOrchestrator);
|
|
3316
3828
|
try {
|
|
@@ -3325,7 +3837,8 @@ var AgentManager = class {
|
|
|
3325
3837
|
totalTokens += event.usage.total_tokens;
|
|
3326
3838
|
}
|
|
3327
3839
|
}
|
|
3328
|
-
|
|
3840
|
+
const snapshot = metricsPort.getSnapshot();
|
|
3841
|
+
await this.eventCallback?.({
|
|
3329
3842
|
type: AgentEventTypes.SubAgentCompleted,
|
|
3330
3843
|
conversationId: config.conversationId ?? "default",
|
|
3331
3844
|
messageId: config.messageId ?? "",
|
|
@@ -3340,11 +3853,13 @@ var AgentManager = class {
|
|
|
3340
3853
|
result: response.content || "",
|
|
3341
3854
|
metadata: {
|
|
3342
3855
|
agentId,
|
|
3856
|
+
agentName: config.agentName,
|
|
3343
3857
|
tokensUsed: totalTokens || response.metadata?.totalTokens,
|
|
3344
3858
|
toolCallsExecuted,
|
|
3345
3859
|
executionTimeMs,
|
|
3346
3860
|
conversationHistory,
|
|
3347
|
-
events
|
|
3861
|
+
events,
|
|
3862
|
+
metrics: snapshot
|
|
3348
3863
|
}
|
|
3349
3864
|
};
|
|
3350
3865
|
} catch (error) {
|
|
@@ -3353,7 +3868,7 @@ var AgentManager = class {
|
|
|
3353
3868
|
const isTimeout = error instanceof Error && error.message.includes("timeout");
|
|
3354
3869
|
const isAborted = error instanceof Error && (error.message.includes("aborted") || error.name === "AbortError");
|
|
3355
3870
|
const status = isTimeout ? "timeout" : isAborted ? "error" : "error";
|
|
3356
|
-
this.eventCallback?.({
|
|
3871
|
+
await this.eventCallback?.({
|
|
3357
3872
|
type: AgentEventTypes.SubAgentCompleted,
|
|
3358
3873
|
conversationId: config.conversationId ?? "default",
|
|
3359
3874
|
messageId: config.messageId ?? "",
|
|
@@ -3368,6 +3883,7 @@ var AgentManager = class {
|
|
|
3368
3883
|
result: errorMessage,
|
|
3369
3884
|
metadata: {
|
|
3370
3885
|
agentId,
|
|
3886
|
+
agentName: config.agentName,
|
|
3371
3887
|
toolCallsExecuted: events.filter((e) => e.type === "tool_calls").length,
|
|
3372
3888
|
executionTimeMs,
|
|
3373
3889
|
errorMessage,
|
|
@@ -3541,10 +4057,12 @@ var DefaultDelegationResultFormatter = class {
|
|
|
3541
4057
|
summary: result.result,
|
|
3542
4058
|
metadata: {
|
|
3543
4059
|
agentId,
|
|
4060
|
+
agentName: result.metadata.agentName,
|
|
3544
4061
|
status: result.status,
|
|
3545
4062
|
executionTimeMs: result.metadata.executionTimeMs,
|
|
3546
4063
|
toolCallsExecuted: result.metadata.toolCallsExecuted,
|
|
3547
|
-
tokensUsed: result.metadata.tokensUsed
|
|
4064
|
+
tokensUsed: result.metadata.tokensUsed,
|
|
4065
|
+
metrics: result.metadata.metrics
|
|
3548
4066
|
}
|
|
3549
4067
|
};
|
|
3550
4068
|
}
|
|
@@ -3803,6 +4321,121 @@ var CompositeToolPort = class {
|
|
|
3803
4321
|
}
|
|
3804
4322
|
};
|
|
3805
4323
|
|
|
4324
|
+
// src/tools/tool-params.ts
|
|
4325
|
+
function parseToolArguments(args) {
|
|
4326
|
+
if (typeof args === "string") {
|
|
4327
|
+
try {
|
|
4328
|
+
return JSON.parse(args);
|
|
4329
|
+
} catch {
|
|
4330
|
+
return {};
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
return args;
|
|
4334
|
+
}
|
|
4335
|
+
function isBashToolArgs(args) {
|
|
4336
|
+
return "cmd" in args && typeof args.cmd === "string";
|
|
4337
|
+
}
|
|
4338
|
+
function isFileReadArgs(args) {
|
|
4339
|
+
return "path" in args && typeof args.path === "string";
|
|
4340
|
+
}
|
|
4341
|
+
function isFileEditArgs(args) {
|
|
4342
|
+
return "file_path" in args && "old_text" in args && "new_text" in args;
|
|
4343
|
+
}
|
|
4344
|
+
function isFileNewArgs(args) {
|
|
4345
|
+
return "file_path" in args && "content" in args;
|
|
4346
|
+
}
|
|
4347
|
+
function isTodoWriteArgs(args) {
|
|
4348
|
+
return "todos" in args && Array.isArray(args.todos);
|
|
4349
|
+
}
|
|
4350
|
+
function isAssignTaskArgs(args) {
|
|
4351
|
+
return "agent" in args && "task" in args && "description" in args;
|
|
4352
|
+
}
|
|
4353
|
+
function isWebSearchArgs(args) {
|
|
4354
|
+
return "query" in args && typeof args.query === "string";
|
|
4355
|
+
}
|
|
4356
|
+
function isWebFetchArgs(args) {
|
|
4357
|
+
return "url" in args && typeof args.url === "string";
|
|
4358
|
+
}
|
|
4359
|
+
function isDirLsArgs(args) {
|
|
4360
|
+
return !("cmd" in args) && !("url" in args) && !("query" in args) && !("todos" in args) && !("agent" in args) && !("file_path" in args) && !("content" in args);
|
|
4361
|
+
}
|
|
4362
|
+
|
|
4363
|
+
// src/tools/type-guards.ts
|
|
4364
|
+
function isSuccess(result) {
|
|
4365
|
+
return result.status === "success";
|
|
4366
|
+
}
|
|
4367
|
+
function isError(result) {
|
|
4368
|
+
return result.status === "error";
|
|
4369
|
+
}
|
|
4370
|
+
function isTextResult(result) {
|
|
4371
|
+
return result.type === "text";
|
|
4372
|
+
}
|
|
4373
|
+
function isJsonResult(result) {
|
|
4374
|
+
return result.type === "json";
|
|
4375
|
+
}
|
|
4376
|
+
function isSuccessText(result) {
|
|
4377
|
+
return result.status === "success" && result.type === "text";
|
|
4378
|
+
}
|
|
4379
|
+
function isSuccessJson(result) {
|
|
4380
|
+
return result.status === "success" && result.type === "json";
|
|
4381
|
+
}
|
|
4382
|
+
|
|
4383
|
+
// src/tools/tool-type-guards.ts
|
|
4384
|
+
function isBashResult(result) {
|
|
4385
|
+
return result.name === "bash_tool";
|
|
4386
|
+
}
|
|
4387
|
+
function isBashSuccess(result) {
|
|
4388
|
+
return result.name === "bash_tool" && result.status === "success" && result.type === "text";
|
|
4389
|
+
}
|
|
4390
|
+
function isFileReadResult(result) {
|
|
4391
|
+
return result.name === "file_read";
|
|
4392
|
+
}
|
|
4393
|
+
function isFileReadSuccess(result) {
|
|
4394
|
+
return result.name === "file_read" && result.status === "success" && result.type === "text";
|
|
4395
|
+
}
|
|
4396
|
+
function isFileEditResult(result) {
|
|
4397
|
+
return result.name === "file_edit";
|
|
4398
|
+
}
|
|
4399
|
+
function isFileEditSuccess(result) {
|
|
4400
|
+
return result.name === "file_edit" && result.status === "success" && result.type === "text";
|
|
4401
|
+
}
|
|
4402
|
+
function isFileNewResult(result) {
|
|
4403
|
+
return result.name === "file_new";
|
|
4404
|
+
}
|
|
4405
|
+
function isFileNewSuccess(result) {
|
|
4406
|
+
return result.name === "file_new" && result.status === "success" && result.type === "text";
|
|
4407
|
+
}
|
|
4408
|
+
function isDirLsResult(result) {
|
|
4409
|
+
return result.name === "dir_ls";
|
|
4410
|
+
}
|
|
4411
|
+
function isDirLsSuccess(result) {
|
|
4412
|
+
return result.name === "dir_ls" && result.status === "success" && result.type === "json";
|
|
4413
|
+
}
|
|
4414
|
+
function isWebSearchResult(result) {
|
|
4415
|
+
return result.name === "web_search";
|
|
4416
|
+
}
|
|
4417
|
+
function isWebSearchSuccess(result) {
|
|
4418
|
+
return result.name === "web_search" && result.status === "success" && result.type === "json";
|
|
4419
|
+
}
|
|
4420
|
+
function isWebFetchResult(result) {
|
|
4421
|
+
return result.name === "web_fetch";
|
|
4422
|
+
}
|
|
4423
|
+
function isWebFetchSuccess(result) {
|
|
4424
|
+
return result.name === "web_fetch" && result.status === "success" && result.type === "text";
|
|
4425
|
+
}
|
|
4426
|
+
function isTodoWriteResult(result) {
|
|
4427
|
+
return result.name === "todo_write";
|
|
4428
|
+
}
|
|
4429
|
+
function isTodoWriteSuccess(result) {
|
|
4430
|
+
return result.name === "todo_write" && result.status === "success" && result.type === "text";
|
|
4431
|
+
}
|
|
4432
|
+
function isAssignResult(result) {
|
|
4433
|
+
return result.name === "assign_task";
|
|
4434
|
+
}
|
|
4435
|
+
function isAssignSuccess(result) {
|
|
4436
|
+
return result.name === "assign_task" && result.status === "success" && result.type === "text";
|
|
4437
|
+
}
|
|
4438
|
+
|
|
3806
4439
|
// src/agent-file-persistence.ts
|
|
3807
4440
|
import * as fs8 from "fs";
|
|
3808
4441
|
import * as path7 from "path";
|
|
@@ -3927,6 +4560,16 @@ var AgentFilePersistence = class {
|
|
|
3927
4560
|
}
|
|
3928
4561
|
};
|
|
3929
4562
|
|
|
4563
|
+
// src/sub-agent-types.ts
|
|
4564
|
+
function parseSubAgentToolCallArguments(argsString) {
|
|
4565
|
+
if (!argsString) return {};
|
|
4566
|
+
try {
|
|
4567
|
+
return JSON.parse(argsString);
|
|
4568
|
+
} catch {
|
|
4569
|
+
return {};
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
|
|
3930
4573
|
// src/llm-providers/llm-utils.ts
|
|
3931
4574
|
function mergeChoices(choices) {
|
|
3932
4575
|
const contentParts = [];
|
|
@@ -3984,9 +4627,11 @@ var BaseLLM = class {
|
|
|
3984
4627
|
transport = null;
|
|
3985
4628
|
apiUrl;
|
|
3986
4629
|
enablePromptCaching = false;
|
|
4630
|
+
retryConfig;
|
|
3987
4631
|
constructor(apiUrl, options) {
|
|
3988
4632
|
this.apiUrl = apiUrl;
|
|
3989
4633
|
this.enablePromptCaching = options?.enablePromptCaching ?? false;
|
|
4634
|
+
this.retryConfig = options?.retry;
|
|
3990
4635
|
}
|
|
3991
4636
|
transformUsage(rawUsage) {
|
|
3992
4637
|
if (!rawUsage) return void 0;
|
|
@@ -4649,6 +5294,206 @@ function createTransport(inner, defaultBaseUrl, apiKey, baseUrl, version, custom
|
|
|
4649
5294
|
return new SimpleBearerAuthTransport(inner, defaultBaseUrl, apiKey, baseUrl, version, customHeaders);
|
|
4650
5295
|
}
|
|
4651
5296
|
|
|
5297
|
+
// src/transports/backoff.ts
|
|
5298
|
+
function calculateBackoff(attempt, baseDelayMs, maxDelayMs, multiplier, jitterFactor) {
|
|
5299
|
+
const exponentialDelay = baseDelayMs * multiplier ** attempt;
|
|
5300
|
+
const cappedDelay = Math.min(exponentialDelay, maxDelayMs);
|
|
5301
|
+
const jitterRange = cappedDelay * jitterFactor;
|
|
5302
|
+
const jitter = jitterRange * (Math.random() * 2 - 1);
|
|
5303
|
+
return Math.max(0, Math.round(cappedDelay + jitter));
|
|
5304
|
+
}
|
|
5305
|
+
function parseRetryAfterHeader(header) {
|
|
5306
|
+
if (!header) return null;
|
|
5307
|
+
const seconds = parseInt(header, 10);
|
|
5308
|
+
if (!Number.isNaN(seconds) && seconds >= 0) {
|
|
5309
|
+
return seconds * 1e3;
|
|
5310
|
+
}
|
|
5311
|
+
const date = Date.parse(header);
|
|
5312
|
+
if (!Number.isNaN(date)) {
|
|
5313
|
+
const delayMs = date - Date.now();
|
|
5314
|
+
return delayMs > 0 ? delayMs : null;
|
|
5315
|
+
}
|
|
5316
|
+
return null;
|
|
5317
|
+
}
|
|
5318
|
+
|
|
5319
|
+
// src/transports/error-classification.ts
|
|
5320
|
+
var DEFAULT_RETRYABLE_STATUS_CODES = [429, 500, 502, 503, 504];
|
|
5321
|
+
var RETRYABLE_NETWORK_ERRORS = [
|
|
5322
|
+
"econnrefused",
|
|
5323
|
+
"enotfound",
|
|
5324
|
+
"etimedout",
|
|
5325
|
+
"econnreset",
|
|
5326
|
+
"epipe",
|
|
5327
|
+
"network",
|
|
5328
|
+
"fetch failed",
|
|
5329
|
+
"socket hang up"
|
|
5330
|
+
];
|
|
5331
|
+
var NON_RETRYABLE_PATTERNS = [
|
|
5332
|
+
"invalid",
|
|
5333
|
+
"unauthorized",
|
|
5334
|
+
"forbidden",
|
|
5335
|
+
"not found",
|
|
5336
|
+
"bad request",
|
|
5337
|
+
"api key",
|
|
5338
|
+
"authentication",
|
|
5339
|
+
"permission",
|
|
5340
|
+
"invalid_api_key",
|
|
5341
|
+
"insufficient_quota"
|
|
5342
|
+
];
|
|
5343
|
+
function isRetryableStatusCode(status, retryableStatusCodes = DEFAULT_RETRYABLE_STATUS_CODES) {
|
|
5344
|
+
return retryableStatusCodes.includes(status);
|
|
5345
|
+
}
|
|
5346
|
+
function isRetryableError(error, retryableStatusCodes = DEFAULT_RETRYABLE_STATUS_CODES) {
|
|
5347
|
+
if (!error) return false;
|
|
5348
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
5349
|
+
return false;
|
|
5350
|
+
}
|
|
5351
|
+
if (error instanceof LLMError) {
|
|
5352
|
+
if (error.statusCode) {
|
|
5353
|
+
return isRetryableStatusCode(error.statusCode, retryableStatusCodes);
|
|
5354
|
+
}
|
|
5355
|
+
return error.isRetryable;
|
|
5356
|
+
}
|
|
5357
|
+
const err2 = error;
|
|
5358
|
+
const statusCode = err2.statusCode ?? err2.status;
|
|
5359
|
+
if (statusCode) {
|
|
5360
|
+
return isRetryableStatusCode(statusCode, retryableStatusCodes);
|
|
5361
|
+
}
|
|
5362
|
+
const message = err2.message?.toLowerCase() || "";
|
|
5363
|
+
const code = err2.code?.toLowerCase() || "";
|
|
5364
|
+
for (const pattern of NON_RETRYABLE_PATTERNS) {
|
|
5365
|
+
if (message.includes(pattern) || code.includes(pattern)) {
|
|
5366
|
+
return false;
|
|
5367
|
+
}
|
|
5368
|
+
}
|
|
5369
|
+
for (const networkError of RETRYABLE_NETWORK_ERRORS) {
|
|
5370
|
+
if (message.includes(networkError) || code.includes(networkError)) {
|
|
5371
|
+
return true;
|
|
5372
|
+
}
|
|
5373
|
+
}
|
|
5374
|
+
return false;
|
|
5375
|
+
}
|
|
5376
|
+
|
|
5377
|
+
// src/transports/retry-transport.ts
|
|
5378
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
5379
|
+
maxRetries: 3,
|
|
5380
|
+
baseDelayMs: 1e3,
|
|
5381
|
+
maxDelayMs: 6e4,
|
|
5382
|
+
backoffMultiplier: 2,
|
|
5383
|
+
jitterFactor: 0.2,
|
|
5384
|
+
retryableStatusCodes: [429, 500, 502, 503, 504]
|
|
5385
|
+
};
|
|
5386
|
+
var AbortError = class _AbortError extends Error {
|
|
5387
|
+
constructor(message = "Operation aborted") {
|
|
5388
|
+
super(message);
|
|
5389
|
+
this.name = "AbortError";
|
|
5390
|
+
if (Error.captureStackTrace) {
|
|
5391
|
+
Error.captureStackTrace(this, _AbortError);
|
|
5392
|
+
}
|
|
5393
|
+
}
|
|
5394
|
+
};
|
|
5395
|
+
var sleep = (ms, signal) => {
|
|
5396
|
+
return new Promise((resolve6, reject) => {
|
|
5397
|
+
if (signal?.aborted) {
|
|
5398
|
+
reject(new AbortError("Operation aborted"));
|
|
5399
|
+
return;
|
|
5400
|
+
}
|
|
5401
|
+
const timeout = setTimeout(resolve6, ms);
|
|
5402
|
+
signal?.addEventListener(
|
|
5403
|
+
"abort",
|
|
5404
|
+
() => {
|
|
5405
|
+
clearTimeout(timeout);
|
|
5406
|
+
reject(new AbortError("Operation aborted during retry delay"));
|
|
5407
|
+
},
|
|
5408
|
+
{ once: true }
|
|
5409
|
+
);
|
|
5410
|
+
});
|
|
5411
|
+
};
|
|
5412
|
+
var RetryTransport = class {
|
|
5413
|
+
constructor(inner, config = {}) {
|
|
5414
|
+
this.inner = inner;
|
|
5415
|
+
this.config = { ...DEFAULT_RETRY_CONFIG, ...config };
|
|
5416
|
+
}
|
|
5417
|
+
config;
|
|
5418
|
+
async get(url, headers, signal) {
|
|
5419
|
+
return this.executeWithRetry(() => this.inner.get(url, headers, signal), signal);
|
|
5420
|
+
}
|
|
5421
|
+
async post(url, body, headers, signal) {
|
|
5422
|
+
return this.executeWithRetry(() => this.inner.post(url, body, headers, signal), signal);
|
|
5423
|
+
}
|
|
5424
|
+
async executeWithRetry(fn, signal) {
|
|
5425
|
+
let lastError;
|
|
5426
|
+
let attempt = 0;
|
|
5427
|
+
while (attempt <= this.config.maxRetries) {
|
|
5428
|
+
if (signal?.aborted) {
|
|
5429
|
+
throw new AbortError("Operation aborted before execution");
|
|
5430
|
+
}
|
|
5431
|
+
try {
|
|
5432
|
+
const response = await fn();
|
|
5433
|
+
if (this.isRetryableResponse(response)) {
|
|
5434
|
+
const error = new Error(`HTTP ${response.status}`);
|
|
5435
|
+
error.status = response.status;
|
|
5436
|
+
if (attempt < this.config.maxRetries) {
|
|
5437
|
+
const delayMs = this.getDelayForResponse(response, attempt);
|
|
5438
|
+
this.config.onRetry?.(attempt + 1, error, delayMs);
|
|
5439
|
+
await sleep(delayMs, signal);
|
|
5440
|
+
attempt++;
|
|
5441
|
+
continue;
|
|
5442
|
+
}
|
|
5443
|
+
lastError = error;
|
|
5444
|
+
break;
|
|
5445
|
+
}
|
|
5446
|
+
return response;
|
|
5447
|
+
} catch (error) {
|
|
5448
|
+
if (error instanceof AbortError || error instanceof Error && error.name === "AbortError") {
|
|
5449
|
+
throw error;
|
|
5450
|
+
}
|
|
5451
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
5452
|
+
if (!isRetryableError(lastError, this.config.retryableStatusCodes)) {
|
|
5453
|
+
throw lastError;
|
|
5454
|
+
}
|
|
5455
|
+
if (attempt < this.config.maxRetries) {
|
|
5456
|
+
const delayMs = calculateBackoff(
|
|
5457
|
+
attempt,
|
|
5458
|
+
this.config.baseDelayMs,
|
|
5459
|
+
this.config.maxDelayMs,
|
|
5460
|
+
this.config.backoffMultiplier,
|
|
5461
|
+
this.config.jitterFactor
|
|
5462
|
+
);
|
|
5463
|
+
this.config.onRetry?.(attempt + 1, lastError, delayMs);
|
|
5464
|
+
await sleep(delayMs, signal);
|
|
5465
|
+
attempt++;
|
|
5466
|
+
} else {
|
|
5467
|
+
break;
|
|
5468
|
+
}
|
|
5469
|
+
}
|
|
5470
|
+
}
|
|
5471
|
+
if (lastError) {
|
|
5472
|
+
this.config.onExhausted?.(lastError, attempt + 1);
|
|
5473
|
+
throw lastError;
|
|
5474
|
+
}
|
|
5475
|
+
throw new Error("Retry exhausted without error");
|
|
5476
|
+
}
|
|
5477
|
+
isRetryableResponse(response) {
|
|
5478
|
+
return isRetryableStatusCode(response.status, this.config.retryableStatusCodes);
|
|
5479
|
+
}
|
|
5480
|
+
getDelayForResponse(response, attempt) {
|
|
5481
|
+
const headers = "headers" in response && response.headers instanceof Headers ? response.headers : null;
|
|
5482
|
+
const retryAfter = headers?.get("retry-after") ?? null;
|
|
5483
|
+
const retryAfterMs = parseRetryAfterHeader(retryAfter);
|
|
5484
|
+
if (retryAfterMs !== null) {
|
|
5485
|
+
return Math.min(retryAfterMs, this.config.maxDelayMs);
|
|
5486
|
+
}
|
|
5487
|
+
return calculateBackoff(
|
|
5488
|
+
attempt,
|
|
5489
|
+
this.config.baseDelayMs,
|
|
5490
|
+
this.config.maxDelayMs,
|
|
5491
|
+
this.config.backoffMultiplier,
|
|
5492
|
+
this.config.jitterFactor
|
|
5493
|
+
);
|
|
5494
|
+
}
|
|
5495
|
+
};
|
|
5496
|
+
|
|
4652
5497
|
// src/llm-providers/model-limits.ts
|
|
4653
5498
|
function normalizeModelLimits(provider, model) {
|
|
4654
5499
|
switch (provider.toLowerCase()) {
|
|
@@ -4766,7 +5611,7 @@ function normalizeModelInfo(provider, model) {
|
|
|
4766
5611
|
var GithubLLM = class extends BaseLLM {
|
|
4767
5612
|
opts;
|
|
4768
5613
|
constructor(opts = {}) {
|
|
4769
|
-
super(opts.apiUrl ?? "https://api.individual.githubcopilot.com");
|
|
5614
|
+
super(opts.apiUrl ?? "https://api.individual.githubcopilot.com", { retry: opts.retry });
|
|
4770
5615
|
this.opts = opts;
|
|
4771
5616
|
}
|
|
4772
5617
|
createTransport() {
|
|
@@ -4777,11 +5622,15 @@ var GithubLLM = class extends BaseLLM {
|
|
|
4777
5622
|
maxFileSize: 5 * 1024 * 1024,
|
|
4778
5623
|
captureResponseBody: true
|
|
4779
5624
|
});
|
|
4780
|
-
|
|
5625
|
+
const authTransport = new GithubAuthTransport(base, {
|
|
4781
5626
|
baseUrl: this.opts.apiUrl,
|
|
4782
5627
|
apiKey: this.opts.apiKey,
|
|
4783
5628
|
accessToken: this.opts.accessToken
|
|
4784
5629
|
});
|
|
5630
|
+
if (this.retryConfig) {
|
|
5631
|
+
return new RetryTransport(authTransport, this.retryConfig);
|
|
5632
|
+
}
|
|
5633
|
+
return authTransport;
|
|
4785
5634
|
}
|
|
4786
5635
|
transformUsage(rawUsage) {
|
|
4787
5636
|
if (!rawUsage) return void 0;
|
|
@@ -5400,8 +6249,8 @@ var GenericLLM = class extends BaseLLM {
|
|
|
5400
6249
|
providerName;
|
|
5401
6250
|
customHeaders;
|
|
5402
6251
|
constructor(baseUrl, modelConfig, opts = {}, customHeaders) {
|
|
5403
|
-
const { enablePromptCaching = false, includeUsage = false, providerName = "unknown", ...restOpts } = opts;
|
|
5404
|
-
super(opts.apiUrl || baseUrl, { enablePromptCaching });
|
|
6252
|
+
const { enablePromptCaching = false, includeUsage = false, providerName = "unknown", retry, ...restOpts } = opts;
|
|
6253
|
+
super(opts.apiUrl || baseUrl, { enablePromptCaching, retry });
|
|
5405
6254
|
this.includeUsage = includeUsage;
|
|
5406
6255
|
this.modelConfig = modelConfig;
|
|
5407
6256
|
this.providerName = providerName;
|
|
@@ -5416,7 +6265,7 @@ var GenericLLM = class extends BaseLLM {
|
|
|
5416
6265
|
maxFileSize: 5 * 1024 * 1024,
|
|
5417
6266
|
captureResponseBody: true
|
|
5418
6267
|
});
|
|
5419
|
-
|
|
6268
|
+
const authTransport = createTransport(
|
|
5420
6269
|
base,
|
|
5421
6270
|
this.apiUrl,
|
|
5422
6271
|
this.opts.apiKey,
|
|
@@ -5424,6 +6273,10 @@ var GenericLLM = class extends BaseLLM {
|
|
|
5424
6273
|
this.opts.version,
|
|
5425
6274
|
this.customHeaders
|
|
5426
6275
|
);
|
|
6276
|
+
if (this.retryConfig) {
|
|
6277
|
+
return new RetryTransport(authTransport, this.retryConfig);
|
|
6278
|
+
}
|
|
6279
|
+
return authTransport;
|
|
5427
6280
|
}
|
|
5428
6281
|
async getModels(signal) {
|
|
5429
6282
|
if (this.modelConfig === false) {
|
|
@@ -5731,7 +6584,11 @@ var MCPToolPort = class {
|
|
|
5731
6584
|
try {
|
|
5732
6585
|
const res = await this.client.callTool({ name: original, arguments: c.parameters || {} });
|
|
5733
6586
|
const flat = flattenMcpContent(res.content);
|
|
5734
|
-
|
|
6587
|
+
if (flat.type === "text") {
|
|
6588
|
+
return { id: c.id, name: c.name, status: "success", type: "text", result: flat.value };
|
|
6589
|
+
} else {
|
|
6590
|
+
return { id: c.id, name: c.name, status: "success", type: "json", result: flat.value };
|
|
6591
|
+
}
|
|
5735
6592
|
} catch (err2) {
|
|
5736
6593
|
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
5737
6594
|
return { id: c.id, name: c.name, status: "error", type: "text", result: message };
|
|
@@ -5810,6 +6667,7 @@ function isValidConfig(value) {
|
|
|
5810
6667
|
}
|
|
5811
6668
|
export {
|
|
5812
6669
|
AGENT_CREATOR_SYSTEM_PROMPT,
|
|
6670
|
+
AbortError,
|
|
5813
6671
|
AgentEventTypes,
|
|
5814
6672
|
AgentFilePersistence,
|
|
5815
6673
|
AgentManager,
|
|
@@ -5822,6 +6680,7 @@ export {
|
|
|
5822
6680
|
ConversationContext,
|
|
5823
6681
|
ConversationStore,
|
|
5824
6682
|
CoreMCPClient,
|
|
6683
|
+
DEFAULT_RETRY_CONFIG,
|
|
5825
6684
|
DefaultDelegationPolicy,
|
|
5826
6685
|
DefaultDelegationResultFormatter,
|
|
5827
6686
|
DefaultDelegationService,
|
|
@@ -5841,6 +6700,7 @@ export {
|
|
|
5841
6700
|
NoopReminders,
|
|
5842
6701
|
PersistedMemory,
|
|
5843
6702
|
PersistingConsoleEventPort,
|
|
6703
|
+
RetryTransport,
|
|
5844
6704
|
RuntimeEnv,
|
|
5845
6705
|
SimpleContextBuilder,
|
|
5846
6706
|
SimpleCost,
|
|
@@ -5850,19 +6710,63 @@ export {
|
|
|
5850
6710
|
buildAgentCreationPrompt,
|
|
5851
6711
|
buildInjectedSystem,
|
|
5852
6712
|
canonicalizeTerminalPaste,
|
|
6713
|
+
convertToolCall,
|
|
6714
|
+
convertToolCalls,
|
|
5853
6715
|
createEmptySnapshot,
|
|
5854
6716
|
createLLM,
|
|
6717
|
+
err,
|
|
5855
6718
|
generateFolderTree,
|
|
5856
6719
|
getAvailableProviders,
|
|
5857
6720
|
getFallbackLimits,
|
|
5858
6721
|
getProviderLabel,
|
|
6722
|
+
isAssignResult,
|
|
6723
|
+
isAssignSuccess,
|
|
6724
|
+
isAssignTaskArgs,
|
|
6725
|
+
isBashResult,
|
|
6726
|
+
isBashSuccess,
|
|
6727
|
+
isBashToolArgs,
|
|
6728
|
+
isDirLsArgs,
|
|
6729
|
+
isDirLsResult,
|
|
6730
|
+
isDirLsSuccess,
|
|
6731
|
+
isError,
|
|
6732
|
+
isFileEditArgs,
|
|
6733
|
+
isFileEditResult,
|
|
6734
|
+
isFileEditSuccess,
|
|
6735
|
+
isFileNewArgs,
|
|
6736
|
+
isFileNewResult,
|
|
6737
|
+
isFileNewSuccess,
|
|
6738
|
+
isFileReadArgs,
|
|
6739
|
+
isFileReadResult,
|
|
6740
|
+
isFileReadSuccess,
|
|
6741
|
+
isJsonResult,
|
|
6742
|
+
isRetryableError,
|
|
6743
|
+
isRetryableStatusCode,
|
|
6744
|
+
isSuccess,
|
|
6745
|
+
isSuccessJson,
|
|
6746
|
+
isSuccessText,
|
|
6747
|
+
isTextResult,
|
|
6748
|
+
isTodoWriteArgs,
|
|
6749
|
+
isTodoWriteResult,
|
|
6750
|
+
isTodoWriteSuccess,
|
|
6751
|
+
isWebFetchArgs,
|
|
6752
|
+
isWebFetchResult,
|
|
6753
|
+
isWebFetchSuccess,
|
|
6754
|
+
isWebSearchArgs,
|
|
6755
|
+
isWebSearchResult,
|
|
6756
|
+
isWebSearchSuccess,
|
|
5859
6757
|
loadMCPConfig,
|
|
5860
6758
|
normalizeModelInfo,
|
|
5861
6759
|
normalizeModelLimits,
|
|
5862
6760
|
normalizeNewlines,
|
|
6761
|
+
okJson,
|
|
6762
|
+
okText,
|
|
6763
|
+
parseJSON,
|
|
6764
|
+
parseSubAgentToolCallArguments,
|
|
6765
|
+
parseToolArguments,
|
|
5863
6766
|
renderTemplate,
|
|
5864
6767
|
resolveBackspaces,
|
|
5865
6768
|
resolveCarriageReturns,
|
|
5866
6769
|
stripAnsiAndControls,
|
|
5867
|
-
supportsGetModels
|
|
6770
|
+
supportsGetModels,
|
|
6771
|
+
toolValidators
|
|
5868
6772
|
};
|