agents 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-tool-types-VPsjVYL0.d.ts → agent-tool-types-NofdbL9X.d.ts} +57 -4
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-BGpgfpJT.d.ts → agent-tools-DLquv-dp.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/browser/ai.d.ts +126 -7
- package/dist/browser/ai.js +73 -29
- package/dist/browser/ai.js.map +1 -1
- package/dist/browser/index.d.ts +81 -69
- package/dist/browser/index.js +3 -2
- package/dist/browser/tanstack-ai.d.ts +13 -7
- package/dist/browser/tanstack-ai.js +18 -19
- package/dist/browser/tanstack-ai.js.map +1 -1
- package/dist/chat/index.d.ts +111 -5
- package/dist/chat/index.js +207 -35
- package/dist/chat/index.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +1 -1
- package/dist/{classPrivateFieldGet2-Beqsfu2Z.js → classPrivateFieldGet2-CZ7QjTXN.js} +5 -5
- package/dist/{classPrivateMethodInitSpec-B5ko1s2R.js → classPrivateMethodInitSpec-D-0__zd9.js} +2 -2
- package/dist/client.d.ts +19 -2
- package/dist/client.js +31 -11
- package/dist/client.js.map +1 -1
- package/dist/{compaction-helpers-BEUILPss.d.ts → compaction-helpers-DVcu5lPN.d.ts} +91 -12
- package/dist/connector-D6yYzYHg.js +1080 -0
- package/dist/connector-D6yYzYHg.js.map +1 -0
- package/dist/connector-DXursxV5.d.ts +340 -0
- package/dist/experimental/memory/session/index.d.ts +75 -12
- package/dist/experimental/memory/session/index.js +226 -21
- package/dist/experimental/memory/session/index.js.map +1 -1
- package/dist/experimental/memory/utils/index.d.ts +2 -2
- package/dist/{index-CPe1OtI0.d.ts → index-B7IbEeze.d.ts} +32 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +116 -45
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/observability/index.d.ts +1 -1
- package/dist/react.d.ts +12 -1
- package/dist/react.js +101 -30
- package/dist/react.js.map +1 -1
- package/dist/{retries-CF_HKSlJ.d.ts → retries-CwlpAGet.d.ts} +35 -5
- package/dist/retries.d.ts +9 -5
- package/dist/retries.js +87 -1
- package/dist/retries.js.map +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/skills/index.js +2 -2
- package/dist/sub-routing.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/package.json +10 -10
- package/dist/shared-4CAYLCTO.d.ts +0 -34
- package/dist/shared-wyII629d.js +0 -432
- package/dist/shared-wyII629d.js.map +0 -1
package/dist/chat/index.js
CHANGED
|
@@ -456,7 +456,8 @@ function transition(state, event) {
|
|
|
456
456
|
}
|
|
457
457
|
case "response": {
|
|
458
458
|
let accumulator;
|
|
459
|
-
|
|
459
|
+
const isReplayedStart = event.replay === true && event.chunkData?.type === "start";
|
|
460
|
+
if (state.status === "idle" || state.streamId !== event.streamId || isReplayedStart) {
|
|
460
461
|
let messageId = event.messageId;
|
|
461
462
|
let existingParts;
|
|
462
463
|
let existingMetadata;
|
|
@@ -550,8 +551,28 @@ const CHUNK_BUFFER_MAX_SIZE = 100;
|
|
|
550
551
|
const SEGMENT_MAX_BYTES = 512e3;
|
|
551
552
|
/** Default cleanup interval for old streams (ms) - every 10 minutes */
|
|
552
553
|
const CLEANUP_INTERVAL_MS = 600 * 1e3;
|
|
553
|
-
/**
|
|
554
|
-
|
|
554
|
+
/**
|
|
555
|
+
* Retention for completed/errored stream buffers, measured from completion.
|
|
556
|
+
*
|
|
557
|
+
* The assistant message is persisted separately (`cf_ai_chat_agent_messages`),
|
|
558
|
+
* so once a stream completes its buffer is no longer the source of truth — it
|
|
559
|
+
* is only a brief reconnect-and-replay grace window: long enough to cover a
|
|
560
|
+
* client that dropped at the completion boundary and reconnects to replay the
|
|
561
|
+
* just-finished stream, and to deliver a pending terminal error frame on a
|
|
562
|
+
* resumed stream (#1645). It is deliberately short (not the chat's lifetime)
|
|
563
|
+
* so idle/one-off chat DOs don't accumulate stale buffers (#1706).
|
|
564
|
+
*/
|
|
565
|
+
const COMPLETED_RETENTION_MS = 600 * 1e3;
|
|
566
|
+
/**
|
|
567
|
+
* Retention for abandoned `streaming` rows, measured from LAST chunk activity.
|
|
568
|
+
*
|
|
569
|
+
* Generous relative to {@link COMPLETED_RETENTION_MS}: an interrupted turn must
|
|
570
|
+
* have ample time to be resumed by a reconnecting client or healed by fiber
|
|
571
|
+
* recovery before its buffer is reaped. Only a stream that has produced no
|
|
572
|
+
* chunk for this long is treated as truly dead. Keyed off last activity (not
|
|
573
|
+
* start time) so a long but still-active stream is never swept mid-flight.
|
|
574
|
+
*/
|
|
575
|
+
const ABANDONED_STREAM_RETENTION_MS = 3600 * 1e3;
|
|
555
576
|
/** Shared encoder for UTF-8 byte length measurement */
|
|
556
577
|
const textEncoder = new TextEncoder();
|
|
557
578
|
/**
|
|
@@ -588,6 +609,7 @@ var ResumableStream = class ResumableStream {
|
|
|
588
609
|
this._activeRequestId = null;
|
|
589
610
|
this._segmentIndex = 0;
|
|
590
611
|
this._isLive = false;
|
|
612
|
+
this._activeIsContinuation = false;
|
|
591
613
|
this._chunkBuffer = [];
|
|
592
614
|
this._chunkBufferBytes = 0;
|
|
593
615
|
this._isFlushingChunks = false;
|
|
@@ -618,9 +640,11 @@ var ResumableStream = class ResumableStream {
|
|
|
618
640
|
* error-driven control flow.
|
|
619
641
|
*/
|
|
620
642
|
_migrateMetadataColumns() {
|
|
621
|
-
|
|
643
|
+
const columns = this.sql`
|
|
622
644
|
select name from pragma_table_info('cf_ai_chat_stream_metadata')
|
|
623
|
-
` ?? []
|
|
645
|
+
` ?? [];
|
|
646
|
+
if (!columns.some((column) => column.name === "message_id")) this.sql`alter table cf_ai_chat_stream_metadata add column message_id text`;
|
|
647
|
+
if (!columns.some((column) => column.name === "is_continuation")) this.sql`alter table cf_ai_chat_stream_metadata add column is_continuation integer`;
|
|
624
648
|
}
|
|
625
649
|
get activeStreamId() {
|
|
626
650
|
return this._activeStreamId;
|
|
@@ -651,10 +675,11 @@ var ResumableStream = class ResumableStream {
|
|
|
651
675
|
this._activeRequestId = requestId;
|
|
652
676
|
this._segmentIndex = 0;
|
|
653
677
|
this._isLive = true;
|
|
678
|
+
this._activeIsContinuation = options.continuation ?? false;
|
|
654
679
|
const messageId = options.messageId ?? null;
|
|
655
680
|
this.sql`
|
|
656
|
-
insert into cf_ai_chat_stream_metadata (id, request_id, status, created_at, message_id)
|
|
657
|
-
values (${streamId}, ${requestId}, 'streaming', ${Date.now()}, ${messageId})
|
|
681
|
+
insert into cf_ai_chat_stream_metadata (id, request_id, status, created_at, message_id, is_continuation)
|
|
682
|
+
values (${streamId}, ${requestId}, 'streaming', ${Date.now()}, ${messageId}, ${this._activeIsContinuation ? 1 : 0})
|
|
658
683
|
`;
|
|
659
684
|
return streamId;
|
|
660
685
|
}
|
|
@@ -687,6 +712,7 @@ var ResumableStream = class ResumableStream {
|
|
|
687
712
|
this._activeRequestId = null;
|
|
688
713
|
this._segmentIndex = 0;
|
|
689
714
|
this._isLive = false;
|
|
715
|
+
this._activeIsContinuation = false;
|
|
690
716
|
this._maybeCleanupOldStreams();
|
|
691
717
|
}
|
|
692
718
|
/**
|
|
@@ -704,6 +730,7 @@ var ResumableStream = class ResumableStream {
|
|
|
704
730
|
this._activeRequestId = null;
|
|
705
731
|
this._segmentIndex = 0;
|
|
706
732
|
this._isLive = false;
|
|
733
|
+
this._activeIsContinuation = false;
|
|
707
734
|
}
|
|
708
735
|
/**
|
|
709
736
|
* Buffer a stream chunk for batch write to SQLite.
|
|
@@ -780,6 +807,7 @@ var ResumableStream = class ResumableStream {
|
|
|
780
807
|
const streamId = this._activeStreamId;
|
|
781
808
|
if (!streamId) return null;
|
|
782
809
|
this.flushBuffer();
|
|
810
|
+
const continuation = this._activeIsContinuation;
|
|
783
811
|
const chunks = this.sql`
|
|
784
812
|
select * from cf_ai_chat_stream_chunks
|
|
785
813
|
where stream_id = ${streamId}
|
|
@@ -790,7 +818,8 @@ var ResumableStream = class ResumableStream {
|
|
|
790
818
|
done: false,
|
|
791
819
|
id: requestId,
|
|
792
820
|
type: CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE,
|
|
793
|
-
replay: true
|
|
821
|
+
replay: true,
|
|
822
|
+
...continuation && { continuation: true }
|
|
794
823
|
}))) return null;
|
|
795
824
|
if (this._activeStreamId !== streamId) {
|
|
796
825
|
sendIfOpen$1(connection, JSON.stringify({
|
|
@@ -798,7 +827,8 @@ var ResumableStream = class ResumableStream {
|
|
|
798
827
|
done: true,
|
|
799
828
|
id: requestId,
|
|
800
829
|
type: CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE,
|
|
801
|
-
replay: true
|
|
830
|
+
replay: true,
|
|
831
|
+
...continuation && { continuation: true }
|
|
802
832
|
}));
|
|
803
833
|
return null;
|
|
804
834
|
}
|
|
@@ -808,7 +838,8 @@ var ResumableStream = class ResumableStream {
|
|
|
808
838
|
done: true,
|
|
809
839
|
id: requestId,
|
|
810
840
|
type: CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE,
|
|
811
|
-
replay: true
|
|
841
|
+
replay: true,
|
|
842
|
+
...continuation && { continuation: true }
|
|
812
843
|
}));
|
|
813
844
|
this.complete(streamId);
|
|
814
845
|
return streamId;
|
|
@@ -819,23 +850,65 @@ var ResumableStream = class ResumableStream {
|
|
|
819
850
|
id: requestId,
|
|
820
851
|
type: CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE,
|
|
821
852
|
replay: true,
|
|
822
|
-
replayComplete: true
|
|
853
|
+
replayComplete: true,
|
|
854
|
+
...continuation && { continuation: true }
|
|
823
855
|
}));
|
|
824
856
|
return null;
|
|
825
857
|
}
|
|
826
858
|
replayCompletedChunksByRequestId(connection, requestId) {
|
|
859
|
+
const stream = this._latestStreamForRequest(requestId, "completed");
|
|
860
|
+
if (!stream) return false;
|
|
861
|
+
const continuation = stream.is_continuation === 1;
|
|
862
|
+
if (!this._replayStoredChunks(connection, stream.id, requestId, continuation)) return false;
|
|
863
|
+
return sendIfOpen$1(connection, JSON.stringify({
|
|
864
|
+
body: "",
|
|
865
|
+
done: true,
|
|
866
|
+
id: requestId,
|
|
867
|
+
type: CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE,
|
|
868
|
+
replay: true,
|
|
869
|
+
...continuation && { continuation: true }
|
|
870
|
+
}));
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Replay the stored chunks of an errored stream for a request, WITHOUT a
|
|
874
|
+
* terminal frame — the caller follows up with the `done: true, error: true`
|
|
875
|
+
* frame carrying the durable terminal record's error text, mirroring what a
|
|
876
|
+
* live client observed (content chunks, then the error). Without this, a
|
|
877
|
+
* client that missed broadcast frames while disconnected has no other
|
|
878
|
+
* channel to the pre-error partial content: the server does not push
|
|
879
|
+
* messages on connect, and {@link replayCompletedChunksByRequestId} only
|
|
880
|
+
* serves `completed` streams (#1575).
|
|
881
|
+
*
|
|
882
|
+
* Returns true when the caller should proceed to send its terminal frame:
|
|
883
|
+
* either no errored stream existed (nothing to replay) or its chunks were
|
|
884
|
+
* replayed successfully. Returns false only when a send failed mid-replay,
|
|
885
|
+
* signalling the caller to skip the terminal frame — the connection is gone
|
|
886
|
+
* and the next reconnect retries the whole sequence.
|
|
887
|
+
*/
|
|
888
|
+
replayErroredChunksByRequestId(connection, requestId) {
|
|
889
|
+
const stream = this._latestStreamForRequest(requestId, "error");
|
|
890
|
+
if (!stream) return true;
|
|
891
|
+
return this._replayStoredChunks(connection, stream.id, requestId, stream.is_continuation === 1);
|
|
892
|
+
}
|
|
893
|
+
/** Latest stream row for a request with the given terminal status. */
|
|
894
|
+
_latestStreamForRequest(requestId, status) {
|
|
827
895
|
this.flushBuffer();
|
|
828
|
-
|
|
896
|
+
return this.sql`
|
|
829
897
|
select * from cf_ai_chat_stream_metadata
|
|
830
898
|
where request_id = ${requestId}
|
|
831
|
-
and status =
|
|
899
|
+
and status = ${status}
|
|
832
900
|
order by created_at desc
|
|
833
901
|
limit 1
|
|
834
902
|
`[0];
|
|
835
|
-
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Send a finished stream's stored chunks to a connection as replay frames.
|
|
906
|
+
* Returns false if the connection closed mid-replay.
|
|
907
|
+
*/
|
|
908
|
+
_replayStoredChunks(connection, streamId, requestId, continuation = false) {
|
|
836
909
|
const chunks = this.sql`
|
|
837
910
|
select * from cf_ai_chat_stream_chunks
|
|
838
|
-
where stream_id = ${
|
|
911
|
+
where stream_id = ${streamId}
|
|
839
912
|
order by chunk_index asc
|
|
840
913
|
`;
|
|
841
914
|
for (const chunk of chunks || []) for (const body of unpackSegmentBody(chunk.body)) if (!sendIfOpen$1(connection, JSON.stringify({
|
|
@@ -843,15 +916,10 @@ var ResumableStream = class ResumableStream {
|
|
|
843
916
|
done: false,
|
|
844
917
|
id: requestId,
|
|
845
918
|
type: CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE,
|
|
846
|
-
replay: true
|
|
919
|
+
replay: true,
|
|
920
|
+
...continuation && { continuation: true }
|
|
847
921
|
}))) return false;
|
|
848
|
-
return
|
|
849
|
-
body: "",
|
|
850
|
-
done: true,
|
|
851
|
-
id: requestId,
|
|
852
|
-
type: CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE,
|
|
853
|
-
replay: true
|
|
854
|
-
}));
|
|
922
|
+
return true;
|
|
855
923
|
}
|
|
856
924
|
/**
|
|
857
925
|
* Restore active stream state if the agent was restarted during streaming.
|
|
@@ -869,6 +937,7 @@ var ResumableStream = class ResumableStream {
|
|
|
869
937
|
const stream = activeStreams[0];
|
|
870
938
|
this._activeStreamId = stream.id;
|
|
871
939
|
this._activeRequestId = stream.request_id;
|
|
940
|
+
this._activeIsContinuation = stream.is_continuation === 1;
|
|
872
941
|
const lastChunk = this.sql`
|
|
873
942
|
select max(chunk_index) as max_index
|
|
874
943
|
from cf_ai_chat_stream_chunks
|
|
@@ -888,6 +957,7 @@ var ResumableStream = class ResumableStream {
|
|
|
888
957
|
this._activeStreamId = null;
|
|
889
958
|
this._activeRequestId = null;
|
|
890
959
|
this._segmentIndex = 0;
|
|
960
|
+
this._activeIsContinuation = false;
|
|
891
961
|
}
|
|
892
962
|
/**
|
|
893
963
|
* Drop all stream tables (called on destroy).
|
|
@@ -898,33 +968,76 @@ var ResumableStream = class ResumableStream {
|
|
|
898
968
|
this.sql`drop table if exists cf_ai_chat_stream_metadata`;
|
|
899
969
|
this._activeStreamId = null;
|
|
900
970
|
this._activeRequestId = null;
|
|
971
|
+
this._activeIsContinuation = false;
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Force a sweep of aged stream buffers now, bypassing the lazy interval
|
|
975
|
+
* gate used by {@link _maybeCleanupOldStreams}. Intended to be driven by an
|
|
976
|
+
* alarm so idle/hibernated chat DOs still reclaim buffers even when no
|
|
977
|
+
* further stream ever completes to trigger the lazy path.
|
|
978
|
+
*/
|
|
979
|
+
cleanup(now = Date.now()) {
|
|
980
|
+
this._lastCleanupTime = now;
|
|
981
|
+
this._sweepOldStreams(now);
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* True if any stream rows remain at all. Used by alarm-driven cleanup to
|
|
985
|
+
* decide whether to re-arm: once no rows remain there is nothing left to
|
|
986
|
+
* sweep, so the DO can stop waking itself.
|
|
987
|
+
*/
|
|
988
|
+
hasReclaimableStreams() {
|
|
989
|
+
return (this.sql`
|
|
990
|
+
select count(*) as n from cf_ai_chat_stream_metadata
|
|
991
|
+
`?.[0]?.n ?? 0) > 0;
|
|
901
992
|
}
|
|
902
993
|
_maybeCleanupOldStreams() {
|
|
903
994
|
const now = Date.now();
|
|
904
995
|
if (now - this._lastCleanupTime < CLEANUP_INTERVAL_MS) return;
|
|
905
996
|
this._lastCleanupTime = now;
|
|
906
|
-
|
|
997
|
+
this._sweepOldStreams(now);
|
|
998
|
+
}
|
|
999
|
+
/** Delete completed/errored buffers past the completion grace window, plus
|
|
1000
|
+
* abandoned "streaming" rows past the stale-in-flight window. The two use
|
|
1001
|
+
* different retentions: a completed buffer is redundant with the persisted
|
|
1002
|
+
* message and needs only a brief replay grace, whereas an in-flight buffer
|
|
1003
|
+
* must outlive resume/recovery before it is presumed dead. */
|
|
1004
|
+
_sweepOldStreams(now) {
|
|
1005
|
+
const completedCutoff = now - COMPLETED_RETENTION_MS;
|
|
907
1006
|
this.sql`
|
|
908
1007
|
delete from cf_ai_chat_stream_chunks
|
|
909
1008
|
where stream_id in (
|
|
910
1009
|
select id from cf_ai_chat_stream_metadata
|
|
911
|
-
where status in ('completed', 'error') and completed_at < ${
|
|
1010
|
+
where status in ('completed', 'error') and completed_at < ${completedCutoff}
|
|
912
1011
|
)
|
|
913
1012
|
`;
|
|
914
1013
|
this.sql`
|
|
915
1014
|
delete from cf_ai_chat_stream_metadata
|
|
916
|
-
where status in ('completed', 'error') and completed_at < ${
|
|
1015
|
+
where status in ('completed', 'error') and completed_at < ${completedCutoff}
|
|
917
1016
|
`;
|
|
1017
|
+
const abandonedCutoff = now - ABANDONED_STREAM_RETENTION_MS;
|
|
918
1018
|
this.sql`
|
|
919
1019
|
delete from cf_ai_chat_stream_chunks
|
|
920
1020
|
where stream_id in (
|
|
921
|
-
select id from cf_ai_chat_stream_metadata
|
|
922
|
-
where status = 'streaming'
|
|
1021
|
+
select m.id from cf_ai_chat_stream_metadata m
|
|
1022
|
+
where m.status = 'streaming'
|
|
1023
|
+
and coalesce(
|
|
1024
|
+
(select max(c.created_at) from cf_ai_chat_stream_chunks c
|
|
1025
|
+
where c.stream_id = m.id),
|
|
1026
|
+
m.created_at
|
|
1027
|
+
) < ${abandonedCutoff}
|
|
923
1028
|
)
|
|
924
1029
|
`;
|
|
925
1030
|
this.sql`
|
|
926
1031
|
delete from cf_ai_chat_stream_metadata
|
|
927
|
-
where
|
|
1032
|
+
where id in (
|
|
1033
|
+
select m.id from cf_ai_chat_stream_metadata m
|
|
1034
|
+
where m.status = 'streaming'
|
|
1035
|
+
and coalesce(
|
|
1036
|
+
(select max(c.created_at) from cf_ai_chat_stream_chunks c
|
|
1037
|
+
where c.stream_id = m.id),
|
|
1038
|
+
m.created_at
|
|
1039
|
+
) < ${abandonedCutoff}
|
|
1040
|
+
)
|
|
928
1041
|
`;
|
|
929
1042
|
}
|
|
930
1043
|
/**
|
|
@@ -970,6 +1083,19 @@ var ResumableStream = class ResumableStream {
|
|
|
970
1083
|
values (${streamId}, ${requestId}, 'streaming', ${createdAt})
|
|
971
1084
|
`;
|
|
972
1085
|
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Append a chunk to a stream dated `ageMs` in the past. Used to exercise the
|
|
1088
|
+
* last-activity sweep threshold: a long-running streaming row with a *recent*
|
|
1089
|
+
* chunk must survive even when its start time is older than the cutoff.
|
|
1090
|
+
* @internal For testing only
|
|
1091
|
+
*/
|
|
1092
|
+
insertChunkAt(streamId, body, ageMs) {
|
|
1093
|
+
const createdAt = Date.now() - ageMs;
|
|
1094
|
+
this.sql`
|
|
1095
|
+
insert into cf_ai_chat_stream_chunks (id, stream_id, body, chunk_index, created_at)
|
|
1096
|
+
values (${nanoid()}, ${streamId}, ${body}, 0, ${createdAt})
|
|
1097
|
+
`;
|
|
1098
|
+
}
|
|
973
1099
|
};
|
|
974
1100
|
ResumableStream.CHUNK_MAX_BYTES = 18e5;
|
|
975
1101
|
//#endregion
|
|
@@ -1015,22 +1141,35 @@ function buildInClauseStrings(prefix, count) {
|
|
|
1015
1141
|
/**
|
|
1016
1142
|
* Converts client tool schemas to AI SDK tool format.
|
|
1017
1143
|
*
|
|
1018
|
-
*
|
|
1019
|
-
* the tool call is sent back to the client for execution.
|
|
1144
|
+
* By default these tools have no `execute` function — when the AI model calls
|
|
1145
|
+
* them, the tool call is sent back to the client for execution.
|
|
1146
|
+
*
|
|
1147
|
+
* When `options.execute` is provided, each tool is built WITH an `execute` that
|
|
1148
|
+
* delegates to it. This is used by the RPC path (e.g. a parent agent driving a
|
|
1149
|
+
* Think sub-agent) so the model's client-tool call is resolved inline within
|
|
1150
|
+
* the same turn.
|
|
1020
1151
|
*
|
|
1021
1152
|
* @param clientTools - Array of tool schemas from the client
|
|
1153
|
+
* @param options - Optional `execute` delegate to run the tools inline
|
|
1022
1154
|
* @returns Record of AI SDK tools that can be spread into your tools object
|
|
1023
1155
|
*/
|
|
1024
|
-
function createToolsFromClientSchemas(clientTools) {
|
|
1156
|
+
function createToolsFromClientSchemas(clientTools, options) {
|
|
1025
1157
|
if (!clientTools || clientTools.length === 0) return {};
|
|
1026
1158
|
const seenNames = /* @__PURE__ */ new Set();
|
|
1027
1159
|
for (const t of clientTools) {
|
|
1028
1160
|
if (seenNames.has(t.name)) console.warn(`[createToolsFromClientSchemas] Duplicate tool name "${t.name}" found. Later definitions will override earlier ones.`);
|
|
1029
1161
|
seenNames.add(t.name);
|
|
1030
1162
|
}
|
|
1031
|
-
|
|
1163
|
+
const execute = options?.execute;
|
|
1164
|
+
const createTool = tool;
|
|
1165
|
+
return Object.fromEntries(clientTools.map((t) => [t.name, createTool({
|
|
1032
1166
|
description: t.description ?? "",
|
|
1033
|
-
inputSchema: jsonSchema(t.parameters ?? { type: "object" })
|
|
1167
|
+
inputSchema: jsonSchema(t.parameters ?? { type: "object" }),
|
|
1168
|
+
...execute ? { execute: (input, executeOptions) => execute({
|
|
1169
|
+
toolName: t.name,
|
|
1170
|
+
input,
|
|
1171
|
+
toolCallId: executeOptions?.toolCallId ?? ""
|
|
1172
|
+
}) } : {}
|
|
1034
1173
|
})]));
|
|
1035
1174
|
}
|
|
1036
1175
|
//#endregion
|
|
@@ -1359,6 +1498,39 @@ function crossMessageToolResultUpdate(toolCallId, updateType, output, errorText,
|
|
|
1359
1498
|
};
|
|
1360
1499
|
}
|
|
1361
1500
|
/**
|
|
1501
|
+
* Build an update descriptor that replaces the output of a *paused durable
|
|
1502
|
+
* execution* tool part (e.g. a codemode runtime tool that paused for
|
|
1503
|
+
* approval).
|
|
1504
|
+
*
|
|
1505
|
+
* A paused execution completes its tool call normally — the part is already
|
|
1506
|
+
* `output-available` with an output of `{ status: "paused", executionId }`.
|
|
1507
|
+
* When the host later approves/rejects the execution, the new outcome
|
|
1508
|
+
* (completed / rejected / paused-again) must replace that output in place.
|
|
1509
|
+
*
|
|
1510
|
+
* Matching is deliberately narrow and idempotent:
|
|
1511
|
+
*
|
|
1512
|
+
* - only `output-available` parts are considered;
|
|
1513
|
+
* - the existing output must be a paused-execution object carrying the same
|
|
1514
|
+
* `executionId` — anything else (already replaced, different execution)
|
|
1515
|
+
* returns the *same part reference*, which callers treat as a no-op signal
|
|
1516
|
+
* (skip persist + broadcast), mirroring {@link crossMessageToolResultUpdate}.
|
|
1517
|
+
*/
|
|
1518
|
+
function pausedExecutionUpdate(toolCallId, executionId, output) {
|
|
1519
|
+
return {
|
|
1520
|
+
toolCallId,
|
|
1521
|
+
matchStates: ["output-available"],
|
|
1522
|
+
apply: (part) => {
|
|
1523
|
+
const current = part.output;
|
|
1524
|
+
if (current == null || typeof current !== "object" || current.status !== "paused" || current.executionId !== executionId) return part;
|
|
1525
|
+
return {
|
|
1526
|
+
...part,
|
|
1527
|
+
output,
|
|
1528
|
+
preliminary: false
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
/**
|
|
1362
1534
|
* Build an update descriptor for applying a tool approval.
|
|
1363
1535
|
*
|
|
1364
1536
|
* Matches parts in `input-available` or `approval-requested` state.
|
|
@@ -1627,6 +1799,6 @@ function unwrapChatFiberSnapshot(key, value, expectedKind) {
|
|
|
1627
1799
|
};
|
|
1628
1800
|
}
|
|
1629
1801
|
//#endregion
|
|
1630
|
-
export { AbortRegistry, CHAT_MESSAGE_TYPES, ContinuationState, MAX_BOUND_PARAMS, ROW_MAX_BYTES, ResumableStream, StreamAccumulator, SubmitConcurrencyController, TurnQueue, applyAgentToolEvent, applyChunkToParts, applyToolUpdate, assistantContentKey, transition as broadcastTransition, buildInClauseStrings, byteLength, createAgentToolEventState, createChatFiberSnapshot, createToolsFromClientSchemas, crossMessageToolResultUpdate, enforceRowSizeLimit, isReplayChunk, normalizeToolInput, parseProtocolMessage, reconcileMessages, resolveToolMergeId, sanitizeMessage, toolApprovalUpdate, toolResultUpdate, unwrapChatFiberSnapshot, wrapChatFiberSnapshot };
|
|
1802
|
+
export { AbortRegistry, CHAT_MESSAGE_TYPES, ContinuationState, MAX_BOUND_PARAMS, ROW_MAX_BYTES, ResumableStream, StreamAccumulator, SubmitConcurrencyController, TurnQueue, applyAgentToolEvent, applyChunkToParts, applyToolUpdate, assistantContentKey, transition as broadcastTransition, buildInClauseStrings, byteLength, createAgentToolEventState, createChatFiberSnapshot, createToolsFromClientSchemas, crossMessageToolResultUpdate, enforceRowSizeLimit, isReplayChunk, normalizeToolInput, parseProtocolMessage, pausedExecutionUpdate, reconcileMessages, resolveToolMergeId, sanitizeMessage, toolApprovalUpdate, toolResultUpdate, unwrapChatFiberSnapshot, wrapChatFiberSnapshot };
|
|
1631
1803
|
|
|
1632
1804
|
//# sourceMappingURL=index.js.map
|