@mastra/client-js 1.56.0-alpha.1 → 1.56.0-alpha.10
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/client.d.ts +3 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/docs/SKILL.md +2 -2
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-harness-agent-controller.md +11 -14
- package/dist/docs/references/docs-harness-schedules.md +8 -6
- package/dist/docs/references/docs-harness-signals.md +3 -1
- package/dist/docs/references/reference-client-js-agent-controller.md +15 -3
- package/dist/docs/references/reference-client-js-agents.md +20 -0
- package/dist/docs/references/reference-client-js-mastra-client.md +1 -1
- package/dist/docs/references/reference-client-js-observability.md +124 -9
- package/dist/docs/references/{reference-observability-tracing-trace-query.md → reference-observability-tracing-advanced-queries.md} +486 -158
- package/dist/index.cjs +780 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +774 -80
- package/dist/index.js.map +1 -1
- package/dist/resources/agent-controller.d.ts +36 -26
- package/dist/resources/agent-controller.d.ts.map +1 -1
- package/dist/resources/agent.d.ts +46 -6
- package/dist/resources/agent.d.ts.map +1 -1
- package/dist/resources/base.d.ts.map +1 -1
- package/dist/resources/observability.d.ts +9 -7
- package/dist/resources/observability.d.ts.map +1 -1
- package/dist/route-types.generated.d.ts +711 -596
- package/dist/route-types.generated.d.ts.map +1 -1
- package/dist/types.d.ts +9 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/ai-sdk-v4/data-stream-parts.d.ts +89 -0
- package/dist/utils/ai-sdk-v4/data-stream-parts.d.ts.map +1 -0
- package/dist/utils/ai-sdk-v4/fix-json.d.ts +2 -0
- package/dist/utils/ai-sdk-v4/fix-json.d.ts.map +1 -0
- package/dist/utils/ai-sdk-v4/index.d.ts +5 -0
- package/dist/utils/ai-sdk-v4/index.d.ts.map +1 -0
- package/dist/utils/ai-sdk-v4/parse-partial-json.d.ts +6 -0
- package/dist/utils/ai-sdk-v4/parse-partial-json.d.ts.map +1 -0
- package/dist/utils/ai-sdk-v4/process-data-stream.d.ts +53 -0
- package/dist/utils/ai-sdk-v4/process-data-stream.d.ts.map +1 -0
- package/dist/utils/ai-sdk-v4/types.d.ts +93 -0
- package/dist/utils/ai-sdk-v4/types.d.ts.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +8 -10
- package/dist/_types/@ai-sdk_provider/dist/index.d.ts +0 -1587
- package/dist/_types/@ai-sdk_provider/package.json +0 -1
- package/dist/_types/@ai-sdk_provider-utils/dist/index.d.ts +0 -379
- package/dist/_types/@ai-sdk_provider-utils/package.json +0 -1
- package/dist/_types/@ai-sdk_ui-utils/dist/index.d.ts +0 -820
- package/dist/_types/@ai-sdk_ui-utils/package.json +0 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { parsePartialJson, processDataStream } from "@ai-sdk/ui-utils";
|
|
2
1
|
import { v4 } from "@lukeed/uuid";
|
|
3
2
|
import { getErrorFromUnknown } from "@mastra/core/error";
|
|
4
|
-
import { standardSchemaToJSONSchema, toStandardSchema } from "@mastra/schema-compat/schema";
|
|
5
3
|
import { RequestContext, RequestContext as RequestContext$1 } from "@mastra/core/request-context";
|
|
4
|
+
import { standardSchemaToJSONSchema, toStandardSchema } from "@mastra/schema-compat/schema";
|
|
6
5
|
import { zodToJsonSchema } from "@mastra/schema-compat/zod-to-json";
|
|
7
6
|
import { MastraA2AError } from "@mastra/core/a2a/client";
|
|
8
7
|
import { AgentCard, CancelTaskRequest, DeleteTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, GetTaskRequest, ListTaskPushNotificationConfigsRequest, ListTaskPushNotificationConfigsResponse, ListTasksRequest, ListTasksResponse, SendMessageRequest, SendMessageResponse, StreamResponse, SubscribeToTaskRequest, Task, TaskPushNotificationConfig } from "@mastra/core/a2a/v1";
|
|
@@ -377,6 +376,16 @@ function isTerminalHttpError(error) {
|
|
|
377
376
|
return typeof status === "number" && (status >= 400 && status < 500 || status === 501);
|
|
378
377
|
}
|
|
379
378
|
/**
|
|
379
|
+
* Whether an error is the server's trace query execution timeout (504 with code
|
|
380
|
+
* `TRACE_QUERY_EXECUTION_TIMEOUT`). Re-sending the same query hits the same
|
|
381
|
+
* timeout budget, so retrying only repeats an expensive database query.
|
|
382
|
+
* Plain 504s from proxies or gateways do not carry this code and stay retryable.
|
|
383
|
+
*/
|
|
384
|
+
function isTraceQueryTimeoutError(error) {
|
|
385
|
+
const { status, body } = error ?? {};
|
|
386
|
+
return status === 504 && body?.code === "TRACE_QUERY_EXECUTION_TIMEOUT";
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
380
389
|
* Whether a failed resubscribe should end a long-lived subscription instead of
|
|
381
390
|
* retrying. Like {@link isTerminalHttpError}, but 408 Request Timeout and
|
|
382
391
|
* 429 Too Many Requests stay retryable because they mean "try again later".
|
|
@@ -386,6 +395,583 @@ function isTerminalReconnectError(error) {
|
|
|
386
395
|
return isTerminalHttpError(error) && status !== 408 && status !== 429;
|
|
387
396
|
}
|
|
388
397
|
//#endregion
|
|
398
|
+
//#region src/utils/ai-sdk-v4/data-stream-parts.ts
|
|
399
|
+
const dataStreamParts = [
|
|
400
|
+
{
|
|
401
|
+
code: "0",
|
|
402
|
+
name: "text",
|
|
403
|
+
parse: (value) => {
|
|
404
|
+
if (typeof value !== "string") throw new Error("\"text\" parts expect a string value.");
|
|
405
|
+
return {
|
|
406
|
+
type: "text",
|
|
407
|
+
value
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
code: "2",
|
|
413
|
+
name: "data",
|
|
414
|
+
parse: (value) => {
|
|
415
|
+
if (!Array.isArray(value)) throw new Error("\"data\" parts expect an array value.");
|
|
416
|
+
return {
|
|
417
|
+
type: "data",
|
|
418
|
+
value
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
code: "3",
|
|
424
|
+
name: "error",
|
|
425
|
+
parse: (value) => {
|
|
426
|
+
if (typeof value !== "string") throw new Error("\"error\" parts expect a string value.");
|
|
427
|
+
return {
|
|
428
|
+
type: "error",
|
|
429
|
+
value
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
code: "8",
|
|
435
|
+
name: "message_annotations",
|
|
436
|
+
parse: (value) => {
|
|
437
|
+
if (!Array.isArray(value)) throw new Error("\"message_annotations\" parts expect an array value.");
|
|
438
|
+
return {
|
|
439
|
+
type: "message_annotations",
|
|
440
|
+
value
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
code: "9",
|
|
446
|
+
name: "tool_call",
|
|
447
|
+
parse: (value) => {
|
|
448
|
+
if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("toolName" in value) || typeof value.toolName !== "string" || !("args" in value) || typeof value.args !== "object") throw new Error("\"tool_call\" parts expect an object with a \"toolCallId\", \"toolName\", and \"args\" property.");
|
|
449
|
+
return {
|
|
450
|
+
type: "tool_call",
|
|
451
|
+
value
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
code: "a",
|
|
457
|
+
name: "tool_result",
|
|
458
|
+
parse: (value) => {
|
|
459
|
+
if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("result" in value)) throw new Error("\"tool_result\" parts expect an object with a \"toolCallId\" and a \"result\" property.");
|
|
460
|
+
return {
|
|
461
|
+
type: "tool_result",
|
|
462
|
+
value
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
code: "b",
|
|
468
|
+
name: "tool_call_streaming_start",
|
|
469
|
+
parse: (value) => {
|
|
470
|
+
if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("toolName" in value) || typeof value.toolName !== "string") throw new Error("\"tool_call_streaming_start\" parts expect an object with a \"toolCallId\" and \"toolName\" property.");
|
|
471
|
+
return {
|
|
472
|
+
type: "tool_call_streaming_start",
|
|
473
|
+
value
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
code: "c",
|
|
479
|
+
name: "tool_call_delta",
|
|
480
|
+
parse: (value) => {
|
|
481
|
+
if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("argsTextDelta" in value) || typeof value.argsTextDelta !== "string") throw new Error("\"tool_call_delta\" parts expect an object with a \"toolCallId\" and \"argsTextDelta\" property.");
|
|
482
|
+
return {
|
|
483
|
+
type: "tool_call_delta",
|
|
484
|
+
value
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
code: "d",
|
|
490
|
+
name: "finish_message",
|
|
491
|
+
parse: (value) => {
|
|
492
|
+
if (value == null || typeof value !== "object" || !("finishReason" in value) || typeof value.finishReason !== "string") throw new Error("\"finish_message\" parts expect an object with a \"finishReason\" property.");
|
|
493
|
+
const result = { finishReason: value.finishReason };
|
|
494
|
+
if ("usage" in value && value.usage != null && typeof value.usage === "object" && "promptTokens" in value.usage && "completionTokens" in value.usage) result.usage = {
|
|
495
|
+
promptTokens: typeof value.usage.promptTokens === "number" ? value.usage.promptTokens : NaN,
|
|
496
|
+
completionTokens: typeof value.usage.completionTokens === "number" ? value.usage.completionTokens : NaN
|
|
497
|
+
};
|
|
498
|
+
return {
|
|
499
|
+
type: "finish_message",
|
|
500
|
+
value: result
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
code: "e",
|
|
506
|
+
name: "finish_step",
|
|
507
|
+
parse: (value) => {
|
|
508
|
+
if (value == null || typeof value !== "object" || !("finishReason" in value) || typeof value.finishReason !== "string") throw new Error("\"finish_step\" parts expect an object with a \"finishReason\" property.");
|
|
509
|
+
const result = {
|
|
510
|
+
finishReason: value.finishReason,
|
|
511
|
+
isContinued: false
|
|
512
|
+
};
|
|
513
|
+
if ("usage" in value && value.usage != null && typeof value.usage === "object" && "promptTokens" in value.usage && "completionTokens" in value.usage) result.usage = {
|
|
514
|
+
promptTokens: typeof value.usage.promptTokens === "number" ? value.usage.promptTokens : NaN,
|
|
515
|
+
completionTokens: typeof value.usage.completionTokens === "number" ? value.usage.completionTokens : NaN
|
|
516
|
+
};
|
|
517
|
+
if ("isContinued" in value && typeof value.isContinued === "boolean") result.isContinued = value.isContinued;
|
|
518
|
+
return {
|
|
519
|
+
type: "finish_step",
|
|
520
|
+
value: result
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
code: "f",
|
|
526
|
+
name: "start_step",
|
|
527
|
+
parse: (value) => {
|
|
528
|
+
if (value == null || typeof value !== "object" || !("messageId" in value) || typeof value.messageId !== "string") throw new Error("\"start_step\" parts expect an object with an \"id\" property.");
|
|
529
|
+
return {
|
|
530
|
+
type: "start_step",
|
|
531
|
+
value: { messageId: value.messageId }
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
code: "g",
|
|
537
|
+
name: "reasoning",
|
|
538
|
+
parse: (value) => {
|
|
539
|
+
if (typeof value !== "string") throw new Error("\"reasoning\" parts expect a string value.");
|
|
540
|
+
return {
|
|
541
|
+
type: "reasoning",
|
|
542
|
+
value
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
code: "h",
|
|
548
|
+
name: "source",
|
|
549
|
+
parse: (value) => {
|
|
550
|
+
if (value == null || typeof value !== "object") throw new Error("\"source\" parts expect a Source object.");
|
|
551
|
+
return {
|
|
552
|
+
type: "source",
|
|
553
|
+
value
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
code: "i",
|
|
559
|
+
name: "redacted_reasoning",
|
|
560
|
+
parse: (value) => {
|
|
561
|
+
if (value == null || typeof value !== "object" || !("data" in value) || typeof value.data !== "string") throw new Error("\"redacted_reasoning\" parts expect an object with a \"data\" property.");
|
|
562
|
+
return {
|
|
563
|
+
type: "redacted_reasoning",
|
|
564
|
+
value: { data: value.data }
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
code: "j",
|
|
570
|
+
name: "reasoning_signature",
|
|
571
|
+
parse: (value) => {
|
|
572
|
+
if (value == null || typeof value !== "object" || !("signature" in value) || typeof value.signature !== "string") throw new Error("\"reasoning_signature\" parts expect an object with a \"signature\" property.");
|
|
573
|
+
return {
|
|
574
|
+
type: "reasoning_signature",
|
|
575
|
+
value: { signature: value.signature }
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
code: "k",
|
|
581
|
+
name: "file",
|
|
582
|
+
parse: (value) => {
|
|
583
|
+
if (value == null || typeof value !== "object" || !("data" in value) || typeof value.data !== "string" || !("mimeType" in value) || typeof value.mimeType !== "string") throw new Error("\"file\" parts expect an object with a \"data\" and \"mimeType\" property.");
|
|
584
|
+
return {
|
|
585
|
+
type: "file",
|
|
586
|
+
value
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
];
|
|
591
|
+
const dataStreamPartsByCode = Object.fromEntries(dataStreamParts.map((part) => [part.code, part]));
|
|
592
|
+
Object.fromEntries(dataStreamParts.map((part) => [part.name, part.code]));
|
|
593
|
+
const validCodes = dataStreamParts.map((part) => part.code);
|
|
594
|
+
/**
|
|
595
|
+
Parses a stream part from a string.
|
|
596
|
+
|
|
597
|
+
@param line The string to parse.
|
|
598
|
+
@returns The parsed stream part.
|
|
599
|
+
@throws An error if the string cannot be parsed.
|
|
600
|
+
*/
|
|
601
|
+
const parseDataStreamPart = (line) => {
|
|
602
|
+
const firstSeparatorIndex = line.indexOf(":");
|
|
603
|
+
if (firstSeparatorIndex === -1) throw new Error("Failed to parse stream string. No separator found.");
|
|
604
|
+
const prefix = line.slice(0, firstSeparatorIndex);
|
|
605
|
+
if (!validCodes.includes(prefix)) throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`);
|
|
606
|
+
const code = prefix;
|
|
607
|
+
const textValue = line.slice(firstSeparatorIndex + 1);
|
|
608
|
+
const jsonValue = JSON.parse(textValue);
|
|
609
|
+
return dataStreamPartsByCode[code].parse(jsonValue);
|
|
610
|
+
};
|
|
611
|
+
//#endregion
|
|
612
|
+
//#region src/utils/ai-sdk-v4/fix-json.ts
|
|
613
|
+
function fixJson(input) {
|
|
614
|
+
const stack = ["ROOT"];
|
|
615
|
+
let lastValidIndex = -1;
|
|
616
|
+
let literalStart = null;
|
|
617
|
+
function processValueStart(char, i, swapState) {
|
|
618
|
+
switch (char) {
|
|
619
|
+
case "\"":
|
|
620
|
+
lastValidIndex = i;
|
|
621
|
+
stack.pop();
|
|
622
|
+
stack.push(swapState);
|
|
623
|
+
stack.push("INSIDE_STRING");
|
|
624
|
+
break;
|
|
625
|
+
case "f":
|
|
626
|
+
case "t":
|
|
627
|
+
case "n":
|
|
628
|
+
lastValidIndex = i;
|
|
629
|
+
literalStart = i;
|
|
630
|
+
stack.pop();
|
|
631
|
+
stack.push(swapState);
|
|
632
|
+
stack.push("INSIDE_LITERAL");
|
|
633
|
+
break;
|
|
634
|
+
case "-":
|
|
635
|
+
stack.pop();
|
|
636
|
+
stack.push(swapState);
|
|
637
|
+
stack.push("INSIDE_NUMBER");
|
|
638
|
+
break;
|
|
639
|
+
case "0":
|
|
640
|
+
case "1":
|
|
641
|
+
case "2":
|
|
642
|
+
case "3":
|
|
643
|
+
case "4":
|
|
644
|
+
case "5":
|
|
645
|
+
case "6":
|
|
646
|
+
case "7":
|
|
647
|
+
case "8":
|
|
648
|
+
case "9":
|
|
649
|
+
lastValidIndex = i;
|
|
650
|
+
stack.pop();
|
|
651
|
+
stack.push(swapState);
|
|
652
|
+
stack.push("INSIDE_NUMBER");
|
|
653
|
+
break;
|
|
654
|
+
case "{":
|
|
655
|
+
lastValidIndex = i;
|
|
656
|
+
stack.pop();
|
|
657
|
+
stack.push(swapState);
|
|
658
|
+
stack.push("INSIDE_OBJECT_START");
|
|
659
|
+
break;
|
|
660
|
+
case "[":
|
|
661
|
+
lastValidIndex = i;
|
|
662
|
+
stack.pop();
|
|
663
|
+
stack.push(swapState);
|
|
664
|
+
stack.push("INSIDE_ARRAY_START");
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
function processAfterObjectValue(char, i) {
|
|
669
|
+
switch (char) {
|
|
670
|
+
case ",":
|
|
671
|
+
stack.pop();
|
|
672
|
+
stack.push("INSIDE_OBJECT_AFTER_COMMA");
|
|
673
|
+
break;
|
|
674
|
+
case "}":
|
|
675
|
+
lastValidIndex = i;
|
|
676
|
+
stack.pop();
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
function processAfterArrayValue(char, i) {
|
|
681
|
+
switch (char) {
|
|
682
|
+
case ",":
|
|
683
|
+
stack.pop();
|
|
684
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
|
685
|
+
break;
|
|
686
|
+
case "]":
|
|
687
|
+
lastValidIndex = i;
|
|
688
|
+
stack.pop();
|
|
689
|
+
break;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
for (let i = 0; i < input.length; i++) {
|
|
693
|
+
const char = input[i];
|
|
694
|
+
switch (stack[stack.length - 1]) {
|
|
695
|
+
case "ROOT":
|
|
696
|
+
processValueStart(char, i, "FINISH");
|
|
697
|
+
break;
|
|
698
|
+
case "INSIDE_OBJECT_START":
|
|
699
|
+
switch (char) {
|
|
700
|
+
case "\"":
|
|
701
|
+
stack.pop();
|
|
702
|
+
stack.push("INSIDE_OBJECT_KEY");
|
|
703
|
+
break;
|
|
704
|
+
case "}":
|
|
705
|
+
lastValidIndex = i;
|
|
706
|
+
stack.pop();
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
break;
|
|
710
|
+
case "INSIDE_OBJECT_AFTER_COMMA":
|
|
711
|
+
switch (char) {
|
|
712
|
+
case "\"":
|
|
713
|
+
stack.pop();
|
|
714
|
+
stack.push("INSIDE_OBJECT_KEY");
|
|
715
|
+
break;
|
|
716
|
+
}
|
|
717
|
+
break;
|
|
718
|
+
case "INSIDE_OBJECT_KEY":
|
|
719
|
+
switch (char) {
|
|
720
|
+
case "\"":
|
|
721
|
+
stack.pop();
|
|
722
|
+
stack.push("INSIDE_OBJECT_AFTER_KEY");
|
|
723
|
+
break;
|
|
724
|
+
}
|
|
725
|
+
break;
|
|
726
|
+
case "INSIDE_OBJECT_AFTER_KEY":
|
|
727
|
+
switch (char) {
|
|
728
|
+
case ":":
|
|
729
|
+
stack.pop();
|
|
730
|
+
stack.push("INSIDE_OBJECT_BEFORE_VALUE");
|
|
731
|
+
break;
|
|
732
|
+
}
|
|
733
|
+
break;
|
|
734
|
+
case "INSIDE_OBJECT_BEFORE_VALUE":
|
|
735
|
+
processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE");
|
|
736
|
+
break;
|
|
737
|
+
case "INSIDE_OBJECT_AFTER_VALUE":
|
|
738
|
+
processAfterObjectValue(char, i);
|
|
739
|
+
break;
|
|
740
|
+
case "INSIDE_STRING":
|
|
741
|
+
switch (char) {
|
|
742
|
+
case "\"":
|
|
743
|
+
stack.pop();
|
|
744
|
+
lastValidIndex = i;
|
|
745
|
+
break;
|
|
746
|
+
case "\\":
|
|
747
|
+
stack.push("INSIDE_STRING_ESCAPE");
|
|
748
|
+
break;
|
|
749
|
+
default: lastValidIndex = i;
|
|
750
|
+
}
|
|
751
|
+
break;
|
|
752
|
+
case "INSIDE_ARRAY_START":
|
|
753
|
+
switch (char) {
|
|
754
|
+
case "]":
|
|
755
|
+
lastValidIndex = i;
|
|
756
|
+
stack.pop();
|
|
757
|
+
break;
|
|
758
|
+
default:
|
|
759
|
+
lastValidIndex = i;
|
|
760
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
|
761
|
+
break;
|
|
762
|
+
}
|
|
763
|
+
break;
|
|
764
|
+
case "INSIDE_ARRAY_AFTER_VALUE":
|
|
765
|
+
switch (char) {
|
|
766
|
+
case ",":
|
|
767
|
+
stack.pop();
|
|
768
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
|
769
|
+
break;
|
|
770
|
+
case "]":
|
|
771
|
+
lastValidIndex = i;
|
|
772
|
+
stack.pop();
|
|
773
|
+
break;
|
|
774
|
+
default:
|
|
775
|
+
lastValidIndex = i;
|
|
776
|
+
break;
|
|
777
|
+
}
|
|
778
|
+
break;
|
|
779
|
+
case "INSIDE_ARRAY_AFTER_COMMA":
|
|
780
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
|
781
|
+
break;
|
|
782
|
+
case "INSIDE_STRING_ESCAPE":
|
|
783
|
+
stack.pop();
|
|
784
|
+
lastValidIndex = i;
|
|
785
|
+
break;
|
|
786
|
+
case "INSIDE_NUMBER":
|
|
787
|
+
switch (char) {
|
|
788
|
+
case "0":
|
|
789
|
+
case "1":
|
|
790
|
+
case "2":
|
|
791
|
+
case "3":
|
|
792
|
+
case "4":
|
|
793
|
+
case "5":
|
|
794
|
+
case "6":
|
|
795
|
+
case "7":
|
|
796
|
+
case "8":
|
|
797
|
+
case "9":
|
|
798
|
+
lastValidIndex = i;
|
|
799
|
+
break;
|
|
800
|
+
case "e":
|
|
801
|
+
case "E":
|
|
802
|
+
case "-":
|
|
803
|
+
case ".": break;
|
|
804
|
+
case ",":
|
|
805
|
+
stack.pop();
|
|
806
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") processAfterArrayValue(char, i);
|
|
807
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") processAfterObjectValue(char, i);
|
|
808
|
+
break;
|
|
809
|
+
case "}":
|
|
810
|
+
stack.pop();
|
|
811
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") processAfterObjectValue(char, i);
|
|
812
|
+
break;
|
|
813
|
+
case "]":
|
|
814
|
+
stack.pop();
|
|
815
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") processAfterArrayValue(char, i);
|
|
816
|
+
break;
|
|
817
|
+
default:
|
|
818
|
+
stack.pop();
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
821
|
+
break;
|
|
822
|
+
case "INSIDE_LITERAL": {
|
|
823
|
+
const partialLiteral = input.substring(literalStart, i + 1);
|
|
824
|
+
if (!"false".startsWith(partialLiteral) && !"true".startsWith(partialLiteral) && !"null".startsWith(partialLiteral)) {
|
|
825
|
+
stack.pop();
|
|
826
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") processAfterObjectValue(char, i);
|
|
827
|
+
else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") processAfterArrayValue(char, i);
|
|
828
|
+
} else lastValidIndex = i;
|
|
829
|
+
break;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
let result = input.slice(0, lastValidIndex + 1);
|
|
834
|
+
for (let i = stack.length - 1; i >= 0; i--) switch (stack[i]) {
|
|
835
|
+
case "INSIDE_STRING":
|
|
836
|
+
result += "\"";
|
|
837
|
+
break;
|
|
838
|
+
case "INSIDE_OBJECT_KEY":
|
|
839
|
+
case "INSIDE_OBJECT_AFTER_KEY":
|
|
840
|
+
case "INSIDE_OBJECT_AFTER_COMMA":
|
|
841
|
+
case "INSIDE_OBJECT_START":
|
|
842
|
+
case "INSIDE_OBJECT_BEFORE_VALUE":
|
|
843
|
+
case "INSIDE_OBJECT_AFTER_VALUE":
|
|
844
|
+
result += "}";
|
|
845
|
+
break;
|
|
846
|
+
case "INSIDE_ARRAY_START":
|
|
847
|
+
case "INSIDE_ARRAY_AFTER_COMMA":
|
|
848
|
+
case "INSIDE_ARRAY_AFTER_VALUE":
|
|
849
|
+
result += "]";
|
|
850
|
+
break;
|
|
851
|
+
case "INSIDE_LITERAL": {
|
|
852
|
+
const partialLiteral = input.substring(literalStart, input.length);
|
|
853
|
+
if ("true".startsWith(partialLiteral)) result += "true".slice(partialLiteral.length);
|
|
854
|
+
else if ("false".startsWith(partialLiteral)) result += "false".slice(partialLiteral.length);
|
|
855
|
+
else if ("null".startsWith(partialLiteral)) result += "null".slice(partialLiteral.length);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
return result;
|
|
859
|
+
}
|
|
860
|
+
//#endregion
|
|
861
|
+
//#region src/utils/ai-sdk-v4/parse-partial-json.ts
|
|
862
|
+
function tryParse(text) {
|
|
863
|
+
try {
|
|
864
|
+
return {
|
|
865
|
+
success: true,
|
|
866
|
+
value: JSON.parse(text)
|
|
867
|
+
};
|
|
868
|
+
} catch {
|
|
869
|
+
return { success: false };
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
function parsePartialJson(jsonText) {
|
|
873
|
+
if (jsonText === void 0) return {
|
|
874
|
+
value: void 0,
|
|
875
|
+
state: "undefined-input"
|
|
876
|
+
};
|
|
877
|
+
let result = tryParse(jsonText);
|
|
878
|
+
if (result.success) return {
|
|
879
|
+
value: result.value,
|
|
880
|
+
state: "successful-parse"
|
|
881
|
+
};
|
|
882
|
+
result = tryParse(fixJson(jsonText));
|
|
883
|
+
if (result.success) return {
|
|
884
|
+
value: result.value,
|
|
885
|
+
state: "repaired-parse"
|
|
886
|
+
};
|
|
887
|
+
return {
|
|
888
|
+
value: void 0,
|
|
889
|
+
state: "failed-parse"
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
//#endregion
|
|
893
|
+
//#region src/utils/ai-sdk-v4/process-data-stream.ts
|
|
894
|
+
const NEWLINE = "\n".charCodeAt(0);
|
|
895
|
+
function concatChunks(chunks, totalLength) {
|
|
896
|
+
const concatenatedChunks = new Uint8Array(totalLength);
|
|
897
|
+
let offset = 0;
|
|
898
|
+
for (const chunk of chunks) {
|
|
899
|
+
concatenatedChunks.set(chunk, offset);
|
|
900
|
+
offset += chunk.length;
|
|
901
|
+
}
|
|
902
|
+
chunks.length = 0;
|
|
903
|
+
return concatenatedChunks;
|
|
904
|
+
}
|
|
905
|
+
async function processDataStream({ stream, onTextPart, onReasoningPart, onReasoningSignaturePart, onRedactedReasoningPart, onSourcePart, onFilePart, onDataPart, onErrorPart, onToolCallStreamingStartPart, onToolCallDeltaPart, onToolCallPart, onToolResultPart, onMessageAnnotationsPart, onFinishMessagePart, onFinishStepPart, onStartStepPart }) {
|
|
906
|
+
const reader = stream.getReader();
|
|
907
|
+
const decoder = new TextDecoder();
|
|
908
|
+
const chunks = [];
|
|
909
|
+
let totalLength = 0;
|
|
910
|
+
while (true) {
|
|
911
|
+
const { value } = await reader.read();
|
|
912
|
+
if (value) {
|
|
913
|
+
chunks.push(value);
|
|
914
|
+
totalLength += value.length;
|
|
915
|
+
if (value[value.length - 1] !== NEWLINE) continue;
|
|
916
|
+
}
|
|
917
|
+
if (chunks.length === 0) break;
|
|
918
|
+
const concatenatedChunks = concatChunks(chunks, totalLength);
|
|
919
|
+
totalLength = 0;
|
|
920
|
+
const streamParts = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseDataStreamPart);
|
|
921
|
+
for (const { type, value } of streamParts) switch (type) {
|
|
922
|
+
case "text":
|
|
923
|
+
await onTextPart?.(value);
|
|
924
|
+
break;
|
|
925
|
+
case "reasoning":
|
|
926
|
+
await onReasoningPart?.(value);
|
|
927
|
+
break;
|
|
928
|
+
case "reasoning_signature":
|
|
929
|
+
await onReasoningSignaturePart?.(value);
|
|
930
|
+
break;
|
|
931
|
+
case "redacted_reasoning":
|
|
932
|
+
await onRedactedReasoningPart?.(value);
|
|
933
|
+
break;
|
|
934
|
+
case "file":
|
|
935
|
+
await onFilePart?.(value);
|
|
936
|
+
break;
|
|
937
|
+
case "source":
|
|
938
|
+
await onSourcePart?.(value);
|
|
939
|
+
break;
|
|
940
|
+
case "data":
|
|
941
|
+
await onDataPart?.(value);
|
|
942
|
+
break;
|
|
943
|
+
case "error":
|
|
944
|
+
await onErrorPart?.(value);
|
|
945
|
+
break;
|
|
946
|
+
case "message_annotations":
|
|
947
|
+
await onMessageAnnotationsPart?.(value);
|
|
948
|
+
break;
|
|
949
|
+
case "tool_call_streaming_start":
|
|
950
|
+
await onToolCallStreamingStartPart?.(value);
|
|
951
|
+
break;
|
|
952
|
+
case "tool_call_delta":
|
|
953
|
+
await onToolCallDeltaPart?.(value);
|
|
954
|
+
break;
|
|
955
|
+
case "tool_call":
|
|
956
|
+
await onToolCallPart?.(value);
|
|
957
|
+
break;
|
|
958
|
+
case "tool_result":
|
|
959
|
+
await onToolResultPart?.(value);
|
|
960
|
+
break;
|
|
961
|
+
case "finish_message":
|
|
962
|
+
await onFinishMessagePart?.(value);
|
|
963
|
+
break;
|
|
964
|
+
case "finish_step":
|
|
965
|
+
await onFinishStepPart?.(value);
|
|
966
|
+
break;
|
|
967
|
+
case "start_step":
|
|
968
|
+
await onStartStepPart?.(value);
|
|
969
|
+
break;
|
|
970
|
+
default: throw new Error(`Unknown stream part type: ${type}`);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
//#endregion
|
|
389
975
|
//#region src/utils/client-tool-model-output.ts
|
|
390
976
|
/**
|
|
391
977
|
* Normalize modelOutput from toModelOutput() to the AI SDK V2 tool result
|
|
@@ -618,7 +1204,7 @@ var BaseResource = class {
|
|
|
618
1204
|
} catch (error) {
|
|
619
1205
|
lastError = error;
|
|
620
1206
|
if (signal?.aborted || error?.name === "AbortError") throw error;
|
|
621
|
-
if (isTerminalHttpError(error)) throw error;
|
|
1207
|
+
if (isTerminalHttpError(error) || isTraceQueryTimeoutError(error)) throw error;
|
|
622
1208
|
if (attempt === retries) break;
|
|
623
1209
|
await new Promise((resolve, reject) => {
|
|
624
1210
|
const timer = setTimeout(() => {
|
|
@@ -2034,6 +2620,7 @@ var Agent = class extends BaseResource {
|
|
|
2034
2620
|
try {
|
|
2035
2621
|
let messages = [];
|
|
2036
2622
|
let streamRunId = processedParams.runId;
|
|
2623
|
+
let finishedHistory;
|
|
2037
2624
|
const [streamForController, streamForProcessing] = response.body.tee();
|
|
2038
2625
|
const decoder = new TextDecoder();
|
|
2039
2626
|
let pendingText = "";
|
|
@@ -2041,6 +2628,13 @@ var Agent = class extends BaseResource {
|
|
|
2041
2628
|
pendingText += text;
|
|
2042
2629
|
const lines = pendingText.split("\n\n");
|
|
2043
2630
|
pendingText = isFinal ? "" : lines.pop() ?? "";
|
|
2631
|
+
for (const line of lines) {
|
|
2632
|
+
if (!line.startsWith("data: ") || !line.includes("\"type\":\"finish\"")) continue;
|
|
2633
|
+
try {
|
|
2634
|
+
const all = JSON.parse(line.slice(6))?.payload?.messages?.all;
|
|
2635
|
+
if (Array.isArray(all)) finishedHistory = all;
|
|
2636
|
+
} catch {}
|
|
2637
|
+
}
|
|
2044
2638
|
const readableLines = lines.filter((line) => line.trim() !== "[DONE]" && line.trim() !== "data: [DONE]").join("\n\n");
|
|
2045
2639
|
if (readableLines) safeEnqueue(new TextEncoder().encode(`${readableLines}\n\n`));
|
|
2046
2640
|
};
|
|
@@ -2194,12 +2788,12 @@ var Agent = class extends BaseResource {
|
|
|
2194
2788
|
role: "tool",
|
|
2195
2789
|
content: toolResultContents
|
|
2196
2790
|
};
|
|
2197
|
-
const updatedMessages = threadId ? [toolResultMessage] : [
|
|
2791
|
+
const updatedMessages = threadId ? [toolResultMessage] : (route === "resume-stream" || route === "approve-tool-call" || route === "decline-tool-call") && finishedHistory ? [...finishedHistory, toolResultMessage] : [
|
|
2198
2792
|
...Array.isArray(processedParams.messages) ? processedParams.messages : [],
|
|
2199
2793
|
...messages,
|
|
2200
2794
|
toolResultMessage
|
|
2201
2795
|
];
|
|
2202
|
-
const recursionRoute = route === "resume-stream" ? "stream" : route === "resume-stream-until-idle" ? "stream-until-idle" : route;
|
|
2796
|
+
const recursionRoute = route === "resume-stream" || route === "approve-tool-call" || route === "decline-tool-call" ? "stream" : route === "resume-stream-until-idle" ? "stream-until-idle" : route;
|
|
2203
2797
|
if (isAborted()) return;
|
|
2204
2798
|
try {
|
|
2205
2799
|
await this.processStreamResponse({
|
|
@@ -2400,7 +2994,8 @@ var Agent = class extends BaseResource {
|
|
|
2400
2994
|
const { requestContext, ...rest } = params;
|
|
2401
2995
|
const processedParams = {
|
|
2402
2996
|
...rest,
|
|
2403
|
-
requestContext: parseClientRequestContext(requestContext)
|
|
2997
|
+
requestContext: parseClientRequestContext(requestContext),
|
|
2998
|
+
clientTools: processClientTools(params.clientToolsResolver?.() ?? params.clientTools)
|
|
2404
2999
|
};
|
|
2405
3000
|
const { readable, controller: readableController, signal } = this.createCancellableStream(params.abortSignal);
|
|
2406
3001
|
const response = await this.processStreamResponse(processedParams, readableController, "approve-tool-call", signal);
|
|
@@ -2431,7 +3026,8 @@ var Agent = class extends BaseResource {
|
|
|
2431
3026
|
const { requestContext, ...rest } = params;
|
|
2432
3027
|
const processedParams = {
|
|
2433
3028
|
...rest,
|
|
2434
|
-
requestContext: parseClientRequestContext(requestContext)
|
|
3029
|
+
requestContext: parseClientRequestContext(requestContext),
|
|
3030
|
+
clientTools: processClientTools(params.clientToolsResolver?.() ?? params.clientTools)
|
|
2435
3031
|
};
|
|
2436
3032
|
const { readable, controller: readableController, signal } = this.createCancellableStream(params.abortSignal);
|
|
2437
3033
|
const response = await this.processStreamResponse(processedParams, readableController, "decline-tool-call", signal);
|
|
@@ -2588,28 +3184,70 @@ var Agent = class extends BaseResource {
|
|
|
2588
3184
|
* Used when `requireToolApproval` is enabled with generate() to allow the agent to proceed.
|
|
2589
3185
|
*/
|
|
2590
3186
|
async approveToolCallGenerate(params) {
|
|
2591
|
-
const { requestContext, ...rest } = params;
|
|
2592
|
-
|
|
3187
|
+
const { requestContext, clientTools, clientToolsResolver, memory, ...rest } = params;
|
|
3188
|
+
const response = await this.request(`/agents/${this.agentId}/approve-tool-call-generate`, {
|
|
2593
3189
|
method: "POST",
|
|
2594
3190
|
body: {
|
|
2595
3191
|
...rest,
|
|
2596
|
-
requestContext: parseClientRequestContext(requestContext)
|
|
3192
|
+
requestContext: parseClientRequestContext(requestContext),
|
|
3193
|
+
clientTools: processClientTools(clientToolsResolver?.() ?? clientTools)
|
|
2597
3194
|
}
|
|
2598
3195
|
});
|
|
3196
|
+
return this.continueResumedGenerate(response, {
|
|
3197
|
+
requestContext,
|
|
3198
|
+
clientTools,
|
|
3199
|
+
clientToolsResolver,
|
|
3200
|
+
memory
|
|
3201
|
+
});
|
|
2599
3202
|
}
|
|
2600
3203
|
/**
|
|
2601
3204
|
* Declines a pending tool call and returns the complete response (non-streaming).
|
|
2602
3205
|
* Used when `requireToolApproval` is enabled with generate() to prevent tool execution.
|
|
2603
3206
|
*/
|
|
2604
3207
|
async declineToolCallGenerate(params) {
|
|
2605
|
-
const { requestContext, ...rest } = params;
|
|
2606
|
-
|
|
3208
|
+
const { requestContext, clientTools, clientToolsResolver, memory, ...rest } = params;
|
|
3209
|
+
const response = await this.request(`/agents/${this.agentId}/decline-tool-call-generate`, {
|
|
2607
3210
|
method: "POST",
|
|
2608
3211
|
body: {
|
|
2609
3212
|
...rest,
|
|
2610
|
-
requestContext: parseClientRequestContext(requestContext)
|
|
3213
|
+
requestContext: parseClientRequestContext(requestContext),
|
|
3214
|
+
clientTools: processClientTools(clientToolsResolver?.() ?? clientTools)
|
|
2611
3215
|
}
|
|
2612
3216
|
});
|
|
3217
|
+
return this.continueResumedGenerate(response, {
|
|
3218
|
+
requestContext,
|
|
3219
|
+
clientTools,
|
|
3220
|
+
clientToolsResolver,
|
|
3221
|
+
memory
|
|
3222
|
+
});
|
|
3223
|
+
}
|
|
3224
|
+
/**
|
|
3225
|
+
* Runs executable client tools the model called after an approval decision and continues on
|
|
3226
|
+
* /generate, like generate() does. With memory the continuation sends only the new messages to the
|
|
3227
|
+
* thread. Without memory it re-sends the conversation up to the last user turn, because the resume
|
|
3228
|
+
* routes keep the earlier history server-side and drop it once the run finishes.
|
|
3229
|
+
*/
|
|
3230
|
+
async continueResumedGenerate(response, { requestContext, clientTools, clientToolsResolver, memory }) {
|
|
3231
|
+
if (response.finishReason !== "tool-calls") return response;
|
|
3232
|
+
const context = requestContext === void 0 || requestContext instanceof RequestContext$1 ? requestContext : new RequestContext$1(Object.entries(requestContext));
|
|
3233
|
+
const threadId = typeof memory?.thread === "string" ? memory.thread : memory?.thread?.id;
|
|
3234
|
+
const history = response.messages ?? [];
|
|
3235
|
+
const priorTurns = history.slice(0, history.findLastIndex((message) => message.role === "user") + 1);
|
|
3236
|
+
return executeToolCallAndRespond({
|
|
3237
|
+
response,
|
|
3238
|
+
params: {
|
|
3239
|
+
messages: threadId ? [] : priorTurns,
|
|
3240
|
+
clientTools: clientToolsResolver?.() ?? clientTools,
|
|
3241
|
+
clientToolsResolver,
|
|
3242
|
+
requestContext: context,
|
|
3243
|
+
memory
|
|
3244
|
+
},
|
|
3245
|
+
agentId: this.agentId,
|
|
3246
|
+
resourceId: memory?.resource,
|
|
3247
|
+
threadId,
|
|
3248
|
+
requestContext: context,
|
|
3249
|
+
respondFn: (messages, options) => this.generate(messages, options)
|
|
3250
|
+
});
|
|
2613
3251
|
}
|
|
2614
3252
|
/**
|
|
2615
3253
|
* Processes the stream response and handles tool calls
|
|
@@ -4550,10 +5188,10 @@ var Observability = class extends BaseResource {
|
|
|
4550
5188
|
});
|
|
4551
5189
|
}
|
|
4552
5190
|
/**
|
|
4553
|
-
* Queries thread
|
|
5191
|
+
* Queries full-history thread rows using a trace or thread activity window.
|
|
4554
5192
|
*
|
|
4555
|
-
* @param params - Thread query with its
|
|
4556
|
-
* @returns Matching thread
|
|
5193
|
+
* @param params - Thread query with its qualification window, filters and pagination
|
|
5194
|
+
* @returns Matching thread rows. Legacy requests retain their identity-only response.
|
|
4557
5195
|
*/
|
|
4558
5196
|
queryTraceThreads(params) {
|
|
4559
5197
|
return this.request("/observability/threads/query", {
|
|
@@ -6138,48 +6776,40 @@ function hydrateEventTimestamps(event) {
|
|
|
6138
6776
|
return isKnownParsedEvent(event) ? hydrateKnownEvent(event) : event;
|
|
6139
6777
|
}
|
|
6140
6778
|
/**
|
|
6141
|
-
* A session
|
|
6142
|
-
* get-or-create on the server, so re-creating the same
|
|
6143
|
-
*
|
|
6144
|
-
*
|
|
6145
|
-
*
|
|
6146
|
-
* two sessions with the same resourceId but different scopes have their own
|
|
6147
|
-
* run loop, thread binding, and mode/model/state (e.g. one session per git
|
|
6148
|
-
* worktree, with the worktree path as the scope). The scope travels on every
|
|
6149
|
-
* request as a `sessionScope` query param.
|
|
6779
|
+
* A session addressed by its `sessionId` within one agent controller. Sessions
|
|
6780
|
+
* are get-or-create on the server, so re-creating the same sessionId resumes
|
|
6781
|
+
* the existing conversation rather than forking it. Many sessions can work on
|
|
6782
|
+
* one `resourceId` (whose threads and memory they use); each has its own run
|
|
6783
|
+
* loop, thread binding, and mode/model/state.
|
|
6150
6784
|
*/
|
|
6151
6785
|
var AgentControllerSession = class extends BaseResource {
|
|
6152
6786
|
controllerId;
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
constructor(options, controllerId, resourceId, scope) {
|
|
6787
|
+
sessionId;
|
|
6788
|
+
constructor(options, controllerId, sessionId) {
|
|
6156
6789
|
super(options);
|
|
6157
6790
|
this.controllerId = controllerId;
|
|
6158
|
-
this.
|
|
6159
|
-
this.scope = scope;
|
|
6791
|
+
this.sessionId = sessionId;
|
|
6160
6792
|
}
|
|
6161
6793
|
base() {
|
|
6162
|
-
return `/agent-controller/${encodeURIComponent(this.controllerId)}/sessions/${encodeURIComponent(this.
|
|
6163
|
-
}
|
|
6164
|
-
/** Append this session's scope (if any) as a `sessionScope` query param. */
|
|
6165
|
-
url(path) {
|
|
6166
|
-
if (this.scope === void 0) return path;
|
|
6167
|
-
return `${path}${path.includes("?") ? "&" : "?"}sessionScope=${encodeURIComponent(this.scope)}`;
|
|
6794
|
+
return `/agent-controller/${encodeURIComponent(this.controllerId)}/sessions/${encodeURIComponent(this.sessionId)}`;
|
|
6168
6795
|
}
|
|
6169
6796
|
/**
|
|
6170
|
-
* Create or resume this session.
|
|
6171
|
-
*
|
|
6172
|
-
*
|
|
6173
|
-
*
|
|
6797
|
+
* Create or resume this session. `resourceId` names whose threads and memory
|
|
6798
|
+
* the session works on. Without it the server resumes the session on the
|
|
6799
|
+
* resource it already has (the live session's, or the resource of the thread
|
|
6800
|
+
* with the session's id), falling back to the sessionId. Pass `tags` to scope
|
|
6801
|
+
* initial thread selection — a thread is a resume candidate only when its
|
|
6802
|
+
* metadata matches every tag. Pass `threadId` to bind the session to one
|
|
6803
|
+
* exact thread, creating it with that id when it does not exist.
|
|
6174
6804
|
*/
|
|
6175
6805
|
create(options) {
|
|
6176
6806
|
return this.request(`/agent-controller/${encodeURIComponent(this.controllerId)}/sessions`, {
|
|
6177
6807
|
method: "POST",
|
|
6178
6808
|
body: {
|
|
6179
|
-
resourceId:
|
|
6809
|
+
resourceId: options?.resourceId,
|
|
6810
|
+
sessionId: this.sessionId,
|
|
6180
6811
|
tags: options?.tags,
|
|
6181
|
-
threadId: options?.threadId
|
|
6182
|
-
sessionScope: this.scope
|
|
6812
|
+
threadId: options?.threadId
|
|
6183
6813
|
}
|
|
6184
6814
|
});
|
|
6185
6815
|
}
|
|
@@ -6205,10 +6835,12 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6205
6835
|
delayMs: finiteOr(options.reconnect.delayMs, 1e3),
|
|
6206
6836
|
maxDelayMs: finiteOr(options.reconnect.maxDelayMs, 3e4)
|
|
6207
6837
|
} : null;
|
|
6838
|
+
const idleTimeoutMs = finiteOr(options.idleTimeoutMs, 6e4);
|
|
6208
6839
|
/** Exponential backoff for the Nth (1-based) retry of an outage streak. */
|
|
6209
6840
|
const backoffDelay = (attempt) => reconnectOptions ? Math.min(reconnectOptions.delayMs * 2 ** (attempt - 1), reconnectOptions.maxDelayMs) : 0;
|
|
6210
6841
|
let cancelled = false;
|
|
6211
6842
|
let currentReader = null;
|
|
6843
|
+
let currentAbort = null;
|
|
6212
6844
|
let reconnectTimer;
|
|
6213
6845
|
let delayResolve;
|
|
6214
6846
|
const settleDelay = () => {
|
|
@@ -6224,8 +6856,39 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6224
6856
|
delayResolve = resolve;
|
|
6225
6857
|
reconnectTimer = setTimeout(settleDelay, ms);
|
|
6226
6858
|
});
|
|
6859
|
+
const idleTimeoutError = () => {
|
|
6860
|
+
const error = /* @__PURE__ */ new Error(`Agent controller session stream received no data for ${idleTimeoutMs}ms`);
|
|
6861
|
+
error.name = "AgentControllerStreamIdleError";
|
|
6862
|
+
return error;
|
|
6863
|
+
};
|
|
6227
6864
|
const requestStream = async () => {
|
|
6228
|
-
const
|
|
6865
|
+
const abort = new AbortController();
|
|
6866
|
+
currentAbort = abort;
|
|
6867
|
+
let openTimer;
|
|
6868
|
+
const request = this.request(`${this.base()}/stream`, {
|
|
6869
|
+
stream: true,
|
|
6870
|
+
signal: abort.signal
|
|
6871
|
+
});
|
|
6872
|
+
request.then((response) => {
|
|
6873
|
+
if (abort.signal.aborted) response.body?.cancel().catch(() => {});
|
|
6874
|
+
}).catch(() => {});
|
|
6875
|
+
let response;
|
|
6876
|
+
try {
|
|
6877
|
+
if (idleTimeoutMs > 0) response = await Promise.race([request, new Promise((_resolve, reject) => {
|
|
6878
|
+
openTimer = setTimeout(() => {
|
|
6879
|
+
const error = idleTimeoutError();
|
|
6880
|
+
abort.abort(error);
|
|
6881
|
+
reject(error);
|
|
6882
|
+
}, idleTimeoutMs);
|
|
6883
|
+
})]);
|
|
6884
|
+
else response = await request;
|
|
6885
|
+
} finally {
|
|
6886
|
+
clearTimeout(openTimer);
|
|
6887
|
+
}
|
|
6888
|
+
if (abort.signal.aborted) {
|
|
6889
|
+
response.body?.cancel().catch(() => {});
|
|
6890
|
+
throw abort.signal.reason;
|
|
6891
|
+
}
|
|
6229
6892
|
if (!response.body) throw new Error("No response body for agent controller session stream");
|
|
6230
6893
|
return response;
|
|
6231
6894
|
};
|
|
@@ -6251,12 +6914,40 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6251
6914
|
const pump = async (response) => {
|
|
6252
6915
|
const reader = response.body.getReader();
|
|
6253
6916
|
currentReader = reader;
|
|
6917
|
+
const abort = currentAbort;
|
|
6254
6918
|
const decoder = new TextDecoder();
|
|
6255
6919
|
let buffer = "";
|
|
6920
|
+
let idleTimer;
|
|
6921
|
+
let timedOut = false;
|
|
6922
|
+
const armIdleTimer = () => {
|
|
6923
|
+
if (idleTimeoutMs <= 0) return;
|
|
6924
|
+
clearTimeout(idleTimer);
|
|
6925
|
+
idleTimer = setTimeout(() => {
|
|
6926
|
+
timedOut = true;
|
|
6927
|
+
reader.cancel(idleTimeoutError()).catch(() => {});
|
|
6928
|
+
abort?.abort(idleTimeoutError());
|
|
6929
|
+
}, idleTimeoutMs);
|
|
6930
|
+
};
|
|
6256
6931
|
try {
|
|
6932
|
+
armIdleTimer();
|
|
6257
6933
|
while (!cancelled) {
|
|
6258
|
-
|
|
6934
|
+
let chunk;
|
|
6935
|
+
try {
|
|
6936
|
+
chunk = await reader.read();
|
|
6937
|
+
} catch (error) {
|
|
6938
|
+
if (timedOut && !cancelled) return {
|
|
6939
|
+
kind: "transport_error",
|
|
6940
|
+
error: idleTimeoutError()
|
|
6941
|
+
};
|
|
6942
|
+
throw error;
|
|
6943
|
+
}
|
|
6944
|
+
if (timedOut && !cancelled) return {
|
|
6945
|
+
kind: "transport_error",
|
|
6946
|
+
error: idleTimeoutError()
|
|
6947
|
+
};
|
|
6948
|
+
const { done, value } = chunk;
|
|
6259
6949
|
if (done) return cancelled ? { kind: "cancelled" } : { kind: "done" };
|
|
6950
|
+
armIdleTimer();
|
|
6260
6951
|
if (cancelled) return { kind: "cancelled" };
|
|
6261
6952
|
buffer += decoder.decode(value, { stream: true });
|
|
6262
6953
|
let separator;
|
|
@@ -6290,7 +6981,9 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6290
6981
|
error
|
|
6291
6982
|
};
|
|
6292
6983
|
} finally {
|
|
6984
|
+
clearTimeout(idleTimer);
|
|
6293
6985
|
if (currentReader === reader) currentReader = null;
|
|
6986
|
+
if (currentAbort === abort) currentAbort = null;
|
|
6294
6987
|
reader.cancel().catch(() => {});
|
|
6295
6988
|
}
|
|
6296
6989
|
};
|
|
@@ -6367,6 +7060,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6367
7060
|
cancelled = true;
|
|
6368
7061
|
settleDelay();
|
|
6369
7062
|
currentReader?.cancel().catch(() => {});
|
|
7063
|
+
currentAbort?.abort();
|
|
6370
7064
|
} };
|
|
6371
7065
|
}
|
|
6372
7066
|
/**
|
|
@@ -6381,7 +7075,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6381
7075
|
files: void 0
|
|
6382
7076
|
} : message;
|
|
6383
7077
|
const requestContext = parseClientRequestContext(options?.requestContext);
|
|
6384
|
-
await this.request(
|
|
7078
|
+
await this.request(`${this.base()}/messages`, {
|
|
6385
7079
|
method: "POST",
|
|
6386
7080
|
body: {
|
|
6387
7081
|
message: content,
|
|
@@ -6392,7 +7086,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6392
7086
|
}
|
|
6393
7087
|
/** Abort the in-flight run for this session. */
|
|
6394
7088
|
async abort() {
|
|
6395
|
-
await this.request(
|
|
7089
|
+
await this.request(`${this.base()}/abort`, { method: "POST" });
|
|
6396
7090
|
}
|
|
6397
7091
|
/**
|
|
6398
7092
|
* Approve or decline a pending tool call (`tool_approval_required`). Resolves
|
|
@@ -6400,12 +7094,13 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6400
7094
|
*/
|
|
6401
7095
|
async approveTool(toolCallId, approved, options) {
|
|
6402
7096
|
const requestContext = parseClientRequestContext(options?.requestContext);
|
|
6403
|
-
return this.request(
|
|
7097
|
+
return this.request(`${this.base()}/tool-approval`, {
|
|
6404
7098
|
method: "POST",
|
|
6405
7099
|
retries: 0,
|
|
6406
7100
|
body: {
|
|
6407
7101
|
toolCallId,
|
|
6408
7102
|
approved,
|
|
7103
|
+
...options?.alwaysAllowCategory ? { alwaysAllowCategory: true } : {},
|
|
6409
7104
|
...requestContext ? { requestContext } : {}
|
|
6410
7105
|
}
|
|
6411
7106
|
});
|
|
@@ -6417,7 +7112,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6417
7112
|
*/
|
|
6418
7113
|
async respondToToolSuspension(toolCallId, resumeData, options) {
|
|
6419
7114
|
const requestContext = parseClientRequestContext(options?.requestContext);
|
|
6420
|
-
return this.request(
|
|
7115
|
+
return this.request(`${this.base()}/tool-suspension`, {
|
|
6421
7116
|
method: "POST",
|
|
6422
7117
|
retries: 0,
|
|
6423
7118
|
body: {
|
|
@@ -6437,7 +7132,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6437
7132
|
files: void 0
|
|
6438
7133
|
} : message;
|
|
6439
7134
|
const requestContext = parseClientRequestContext(options?.requestContext);
|
|
6440
|
-
await this.request(
|
|
7135
|
+
await this.request(`${this.base()}/steer`, {
|
|
6441
7136
|
method: "POST",
|
|
6442
7137
|
body: {
|
|
6443
7138
|
message: content,
|
|
@@ -6449,18 +7144,18 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6449
7144
|
/** Get the current mode, model, and thread (for initial UI hydration). */
|
|
6450
7145
|
state(options) {
|
|
6451
7146
|
const path = options?.threadId ? `${this.base()}?threadId=${encodeURIComponent(options.threadId)}` : this.base();
|
|
6452
|
-
return this.request(
|
|
7147
|
+
return this.request(path);
|
|
6453
7148
|
}
|
|
6454
7149
|
/** Merge key-value pairs into the session state. Existing keys not in the payload are preserved. */
|
|
6455
7150
|
async setState(updates) {
|
|
6456
|
-
await this.request(
|
|
7151
|
+
await this.request(`${this.base()}/state`, {
|
|
6457
7152
|
method: "PUT",
|
|
6458
7153
|
body: { state: updates }
|
|
6459
7154
|
});
|
|
6460
7155
|
}
|
|
6461
7156
|
/** Switch the active mode (e.g. `build`, `plan`). */
|
|
6462
7157
|
async switchMode(modeId) {
|
|
6463
|
-
await this.request(
|
|
7158
|
+
await this.request(`${this.base()}/mode`, {
|
|
6464
7159
|
method: "POST",
|
|
6465
7160
|
body: { modeId }
|
|
6466
7161
|
});
|
|
@@ -6470,7 +7165,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6470
7165
|
* `thinkingLevel` is provided it is applied and persisted with the model.
|
|
6471
7166
|
*/
|
|
6472
7167
|
async switchModel(modelId, { thinkingLevel } = {}) {
|
|
6473
|
-
await this.request(
|
|
7168
|
+
await this.request(`${this.base()}/model`, {
|
|
6474
7169
|
method: "POST",
|
|
6475
7170
|
body: thinkingLevel !== void 0 ? {
|
|
6476
7171
|
modelId,
|
|
@@ -6491,36 +7186,36 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6491
7186
|
if (opts.limit != null) params.set("limit", String(opts.limit));
|
|
6492
7187
|
if (opts.tags && Object.keys(opts.tags).length > 0) params.set("tags", JSON.stringify(opts.tags));
|
|
6493
7188
|
const query = params.toString() ? `?${params.toString()}` : "";
|
|
6494
|
-
return (await this.request(
|
|
7189
|
+
return (await this.request(`${this.base()}/threads${query}`)).threads;
|
|
6495
7190
|
}
|
|
6496
7191
|
/** Switch the session to an existing thread (rebinds stream + state). */
|
|
6497
7192
|
async switchThread(threadId) {
|
|
6498
|
-
await this.request(
|
|
7193
|
+
await this.request(`${this.base()}/thread`, {
|
|
6499
7194
|
method: "POST",
|
|
6500
7195
|
body: { threadId }
|
|
6501
7196
|
});
|
|
6502
7197
|
}
|
|
6503
7198
|
/** Create a new thread (unbinds previous, binds the new one). */
|
|
6504
7199
|
async createThread(title) {
|
|
6505
|
-
return this.request(
|
|
7200
|
+
return this.request(`${this.base()}/threads`, {
|
|
6506
7201
|
method: "POST",
|
|
6507
7202
|
body: { title }
|
|
6508
7203
|
});
|
|
6509
7204
|
}
|
|
6510
7205
|
/** Delete a thread. If it's the active thread the session unbinds. */
|
|
6511
7206
|
async deleteThread(threadId) {
|
|
6512
|
-
await this.request(
|
|
7207
|
+
await this.request(`${this.base()}/threads/${encodeURIComponent(threadId)}`, { method: "DELETE" });
|
|
6513
7208
|
}
|
|
6514
7209
|
/** Rename a thread. */
|
|
6515
7210
|
async renameThread(threadId, title) {
|
|
6516
|
-
await this.request(
|
|
7211
|
+
await this.request(`${this.base()}/threads/${encodeURIComponent(threadId)}`, {
|
|
6517
7212
|
method: "PUT",
|
|
6518
7213
|
body: { title }
|
|
6519
7214
|
});
|
|
6520
7215
|
}
|
|
6521
7216
|
/** Clone a thread (and its messages). The session binds to the clone. */
|
|
6522
7217
|
async cloneThread(options) {
|
|
6523
|
-
return this.request(
|
|
7218
|
+
return this.request(`${this.base()}/threads/clone`, {
|
|
6524
7219
|
method: "POST",
|
|
6525
7220
|
body: options ?? {}
|
|
6526
7221
|
});
|
|
@@ -6541,7 +7236,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6541
7236
|
if (include) queryParams.set("include", JSON.stringify(include));
|
|
6542
7237
|
}
|
|
6543
7238
|
const query = queryParams.toString();
|
|
6544
|
-
const body = await this.request(
|
|
7239
|
+
const body = await this.request(`${this.base()}/threads/${encodeURIComponent(threadId)}/messages${query ? `?${query}` : ""}`);
|
|
6545
7240
|
const messages = body.messages.map(hydrateMessage);
|
|
6546
7241
|
if (legacy) return messages;
|
|
6547
7242
|
return {
|
|
@@ -6560,7 +7255,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6560
7255
|
files: void 0
|
|
6561
7256
|
} : message;
|
|
6562
7257
|
const requestContext = parseClientRequestContext(options?.requestContext);
|
|
6563
|
-
await this.request(
|
|
7258
|
+
await this.request(`${this.base()}/follow-up`, {
|
|
6564
7259
|
method: "POST",
|
|
6565
7260
|
body: {
|
|
6566
7261
|
message: content,
|
|
@@ -6571,26 +7266,26 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6571
7266
|
}
|
|
6572
7267
|
/** Get the observational memory record for this session's thread. */
|
|
6573
7268
|
async getOMRecord() {
|
|
6574
|
-
return (await this.request(
|
|
7269
|
+
return (await this.request(`${this.base()}/om`)).record;
|
|
6575
7270
|
}
|
|
6576
7271
|
/** Change the session's resource identity. */
|
|
6577
7272
|
async setResourceId(newResourceId) {
|
|
6578
|
-
await this.request(
|
|
7273
|
+
await this.request(`${this.base()}/resource`, {
|
|
6579
7274
|
method: "POST",
|
|
6580
7275
|
body: { newResourceId }
|
|
6581
7276
|
});
|
|
6582
7277
|
}
|
|
6583
7278
|
/** Get known resource IDs for this session. */
|
|
6584
7279
|
async getResourceIds() {
|
|
6585
|
-
return (await this.request(
|
|
7280
|
+
return (await this.request(`${this.base()}/resources`)).resourceIds;
|
|
6586
7281
|
}
|
|
6587
7282
|
/** Get the current goal for this session's thread. */
|
|
6588
7283
|
async getGoal() {
|
|
6589
|
-
return (await this.request(
|
|
7284
|
+
return (await this.request(`${this.base()}/goal`)).goal;
|
|
6590
7285
|
}
|
|
6591
7286
|
/** Set a new goal objective. The agent's in-loop judge evaluates progress after each turn. */
|
|
6592
7287
|
async setGoal(objective, options) {
|
|
6593
|
-
return (await this.request(
|
|
7288
|
+
return (await this.request(`${this.base()}/goal`, {
|
|
6594
7289
|
method: "POST",
|
|
6595
7290
|
body: {
|
|
6596
7291
|
objective,
|
|
@@ -6600,22 +7295,22 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6600
7295
|
}
|
|
6601
7296
|
/** Update goal options (judge model, max runs, status). */
|
|
6602
7297
|
async updateGoal(options) {
|
|
6603
|
-
return (await this.request(
|
|
7298
|
+
return (await this.request(`${this.base()}/goal`, {
|
|
6604
7299
|
method: "PUT",
|
|
6605
7300
|
body: options
|
|
6606
7301
|
})).goal;
|
|
6607
7302
|
}
|
|
6608
7303
|
/** Clear the current goal. */
|
|
6609
7304
|
async clearGoal() {
|
|
6610
|
-
await this.request(
|
|
7305
|
+
await this.request(`${this.base()}/goal`, { method: "DELETE" });
|
|
6611
7306
|
}
|
|
6612
7307
|
/** Get the current permission rules (per-category and per-tool policies). */
|
|
6613
7308
|
async getPermissions() {
|
|
6614
|
-
return this.request(
|
|
7309
|
+
return this.request(`${this.base()}/permissions`);
|
|
6615
7310
|
}
|
|
6616
7311
|
/** Set the approval policy for a tool category. */
|
|
6617
7312
|
async setPermissionForCategory(category, policy) {
|
|
6618
|
-
await this.request(
|
|
7313
|
+
await this.request(`${this.base()}/permissions/category`, {
|
|
6619
7314
|
method: "PUT",
|
|
6620
7315
|
body: {
|
|
6621
7316
|
category,
|
|
@@ -6625,7 +7320,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6625
7320
|
}
|
|
6626
7321
|
/** Set the approval policy for a specific tool. */
|
|
6627
7322
|
async setPermissionForTool(toolName, policy) {
|
|
6628
|
-
await this.request(
|
|
7323
|
+
await this.request(`${this.base()}/permissions/tool`, {
|
|
6629
7324
|
method: "PUT",
|
|
6630
7325
|
body: {
|
|
6631
7326
|
toolName,
|
|
@@ -6639,7 +7334,7 @@ var AgentControllerSession = class extends BaseResource {
|
|
|
6639
7334
|
* or is persisted for later.
|
|
6640
7335
|
*/
|
|
6641
7336
|
async sendNotification(input) {
|
|
6642
|
-
return this.request(
|
|
7337
|
+
return this.request(`${this.base()}/notifications`, {
|
|
6643
7338
|
method: "POST",
|
|
6644
7339
|
body: input
|
|
6645
7340
|
});
|
|
@@ -6672,12 +7367,11 @@ var AgentController = class extends BaseResource {
|
|
|
6672
7367
|
return this.request(`${this.basePath()}/workspace`);
|
|
6673
7368
|
}
|
|
6674
7369
|
/**
|
|
6675
|
-
*
|
|
6676
|
-
*
|
|
6677
|
-
* (e.g. one session per git worktree, with the worktree path as the scope).
|
|
7370
|
+
* Address the session with this `sessionId`. Sessions created without an
|
|
7371
|
+
* explicit id are addressed by their `resourceId`.
|
|
6678
7372
|
*/
|
|
6679
|
-
session(
|
|
6680
|
-
return new AgentControllerSession(this.options, this.controllerId,
|
|
7373
|
+
session(sessionId) {
|
|
7374
|
+
return new AgentControllerSession(this.options, this.controllerId, sessionId);
|
|
6681
7375
|
}
|
|
6682
7376
|
};
|
|
6683
7377
|
/** Pull the plain text out of an assistant message's nested content parts. */
|
|
@@ -6751,7 +7445,7 @@ var MastraClient = class extends BaseResource {
|
|
|
6751
7445
|
}
|
|
6752
7446
|
/**
|
|
6753
7447
|
* Scopes to an agent controller hosted on the connected Mastra instance. Use
|
|
6754
|
-
* `getAgentController(id).session(
|
|
7448
|
+
* `getAgentController(id).session(sessionId)` to create/resume a session,
|
|
6755
7449
|
* stream its events, and send messages.
|
|
6756
7450
|
* @param controllerId - The id the agent controller is registered under on Mastra
|
|
6757
7451
|
*/
|
|
@@ -7272,7 +7966,7 @@ var MastraClient = class extends BaseResource {
|
|
|
7272
7966
|
getTraceQueryValues(params, options) {
|
|
7273
7967
|
return this.observability.getTraceQueryValues(params, options);
|
|
7274
7968
|
}
|
|
7275
|
-
/** Queries thread
|
|
7969
|
+
/** Queries full-history thread rows using a trace or thread activity window. */
|
|
7276
7970
|
queryTraceThreads(params) {
|
|
7277
7971
|
return this.observability.queryTraceThreads(params);
|
|
7278
7972
|
}
|