@cloudflare/ai-chat 0.0.5 → 0.0.7
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/CHANGELOG.md +19 -0
- package/dist/index.d.ts +12 -2
- package/dist/index.js +79 -1
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +19 -19
- package/dist/react.js +22 -0
- package/dist/react.js.map +1 -1
- package/dist/types.d.ts +24 -17
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -1
- package/package.json +7 -10
- package/scripts/build.ts +2 -2
- package/src/index.ts +150 -3
- package/src/react-tests/vitest.config.ts +1 -0
- package/src/react.tsx +65 -4
- package/src/tests/client-tool-duplicate-message.test.ts +313 -0
- package/src/tests/vitest.config.ts +1 -0
- package/src/tests/wrangler.jsonc +1 -1
- package/src/types.ts +11 -1
- package/vitest.config.ts +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @cloudflare/ai-chat
|
|
2
2
|
|
|
3
|
+
## 0.0.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#859](https://github.com/cloudflare/agents/pull/859) [`3de98a3`](https://github.com/cloudflare/agents/commit/3de98a398d55aeca51c7b845ed4c5d6051887d6d) Thanks [@threepointone](https://github.com/threepointone)! - broaden peer deps
|
|
8
|
+
|
|
9
|
+
- [#865](https://github.com/cloudflare/agents/pull/865) [`c3211d0`](https://github.com/cloudflare/agents/commit/c3211d0b0cc36aa294c15569ae650d3afeab9926) Thanks [@threepointone](https://github.com/threepointone)! - update dependencies
|
|
10
|
+
|
|
11
|
+
## 0.0.6
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#829](https://github.com/cloudflare/agents/pull/829) [`83f137f`](https://github.com/cloudflare/agents/commit/83f137f7046aeafc3b480b5aa4518f6290b14406) Thanks [@Muhammad-Bin-Ali](https://github.com/Muhammad-Bin-Ali)! - Fix duplicate assistant messages when using needsApproval tools
|
|
16
|
+
|
|
17
|
+
When calling `addToolApprovalResponse`, the original assistant message is now updated in place instead of creating a duplicate with a new ID.
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [[`68916bf`](https://github.com/cloudflare/agents/commit/68916bfa08358d4bb5d61aff37acd8dc4ffc950e), [`3f490d0`](https://github.com/cloudflare/agents/commit/3f490d045844e4884db741afbb66ca1fe65d4093)]:
|
|
20
|
+
- agents@0.3.10
|
|
21
|
+
|
|
3
22
|
## 0.0.5
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -20,8 +20,8 @@ import { Agent, AgentContext } from "agents";
|
|
|
20
20
|
* and handle them via the `onToolCall` callback in `useAgentChat`.
|
|
21
21
|
*/
|
|
22
22
|
type ClientToolSchema = {
|
|
23
|
-
/** Unique name for the tool */ name: string
|
|
24
|
-
description?: Tool["description"]
|
|
23
|
+
/** Unique name for the tool */ name: string /** Human-readable description of what the tool does */;
|
|
24
|
+
description?: Tool["description"] /** JSON Schema defining the tool's input parameters */;
|
|
25
25
|
parameters?: JSONSchema7;
|
|
26
26
|
};
|
|
27
27
|
/**
|
|
@@ -296,6 +296,16 @@ declare class AIChatAgent<
|
|
|
296
296
|
private updateDynamicToolPart;
|
|
297
297
|
private updateToolPart;
|
|
298
298
|
private updateMessageMetadata;
|
|
299
|
+
/**
|
|
300
|
+
* Applies a tool approval response from the client, updating the persisted message.
|
|
301
|
+
* This is called when the client sends CF_AGENT_TOOL_APPROVAL for tools with needsApproval.
|
|
302
|
+
* Updates the tool part state from input-available/approval-requested to approval-responded.
|
|
303
|
+
*
|
|
304
|
+
* @param toolCallId - The tool call ID this approval is for
|
|
305
|
+
* @param approved - Whether the tool execution was approved
|
|
306
|
+
* @returns true if the approval was applied, false if the message was not found
|
|
307
|
+
*/
|
|
308
|
+
private _applyToolApproval;
|
|
299
309
|
private _reply;
|
|
300
310
|
/**
|
|
301
311
|
* Mark a stream as errored and clean up state.
|
package/dist/index.js
CHANGED
|
@@ -238,6 +238,11 @@ var AIChatAgent = class extends Agent {
|
|
|
238
238
|
});
|
|
239
239
|
return;
|
|
240
240
|
}
|
|
241
|
+
if (data.type === MessageType.CF_AGENT_TOOL_APPROVAL) {
|
|
242
|
+
const { toolCallId, approved } = data;
|
|
243
|
+
this._applyToolApproval(toolCallId, approved);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
241
246
|
}
|
|
242
247
|
return _onMessage(connection, message);
|
|
243
248
|
};
|
|
@@ -542,7 +547,7 @@ var AIChatAgent = class extends Agent {
|
|
|
542
547
|
*/
|
|
543
548
|
_resolveMessageForToolMerge(message) {
|
|
544
549
|
if (message.role !== "assistant") return message;
|
|
545
|
-
for (const part of message.parts) if ("toolCallId" in part && "state" in part && part.state === "output-available") {
|
|
550
|
+
for (const part of message.parts) if ("toolCallId" in part && "state" in part && (part.state === "output-available" || part.state === "approval-responded" || part.state === "approval-requested")) {
|
|
546
551
|
const toolCallId = part.toolCallId;
|
|
547
552
|
const existingMessage = this._findMessageByToolCallId(toolCallId);
|
|
548
553
|
if (existingMessage && existingMessage.id !== message.id) return {
|
|
@@ -1068,6 +1073,79 @@ var AIChatAgent = class extends Agent {
|
|
|
1068
1073
|
...metadata
|
|
1069
1074
|
} : metadata;
|
|
1070
1075
|
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Applies a tool approval response from the client, updating the persisted message.
|
|
1078
|
+
* This is called when the client sends CF_AGENT_TOOL_APPROVAL for tools with needsApproval.
|
|
1079
|
+
* Updates the tool part state from input-available/approval-requested to approval-responded.
|
|
1080
|
+
*
|
|
1081
|
+
* @param toolCallId - The tool call ID this approval is for
|
|
1082
|
+
* @param approved - Whether the tool execution was approved
|
|
1083
|
+
* @returns true if the approval was applied, false if the message was not found
|
|
1084
|
+
*/
|
|
1085
|
+
async _applyToolApproval(toolCallId, approved) {
|
|
1086
|
+
let message;
|
|
1087
|
+
if (this._streamingMessage) {
|
|
1088
|
+
for (const part of this._streamingMessage.parts) if ("toolCallId" in part && part.toolCallId === toolCallId) {
|
|
1089
|
+
message = this._streamingMessage;
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
if (!message) for (let attempt = 0; attempt < 10; attempt++) {
|
|
1094
|
+
message = this._findMessageByToolCallId(toolCallId);
|
|
1095
|
+
if (message) break;
|
|
1096
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1097
|
+
}
|
|
1098
|
+
if (!message) {
|
|
1099
|
+
console.warn(`[AIChatAgent] _applyToolApproval: Could not find message with toolCallId ${toolCallId} after retries`);
|
|
1100
|
+
return false;
|
|
1101
|
+
}
|
|
1102
|
+
const isStreamingMessage = message === this._streamingMessage;
|
|
1103
|
+
let updated = false;
|
|
1104
|
+
if (isStreamingMessage) {
|
|
1105
|
+
for (const part of message.parts) if ("toolCallId" in part && part.toolCallId === toolCallId && "state" in part && (part.state === "input-available" || part.state === "approval-requested")) {
|
|
1106
|
+
part.state = "approval-responded";
|
|
1107
|
+
part.approval = { approved };
|
|
1108
|
+
updated = true;
|
|
1109
|
+
break;
|
|
1110
|
+
}
|
|
1111
|
+
} else {
|
|
1112
|
+
const updatedParts = message.parts.map((part) => {
|
|
1113
|
+
if ("toolCallId" in part && part.toolCallId === toolCallId && "state" in part && (part.state === "input-available" || part.state === "approval-requested")) {
|
|
1114
|
+
updated = true;
|
|
1115
|
+
return {
|
|
1116
|
+
...part,
|
|
1117
|
+
state: "approval-responded",
|
|
1118
|
+
approval: { approved }
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
return part;
|
|
1122
|
+
});
|
|
1123
|
+
if (updated) {
|
|
1124
|
+
const updatedMessage = this._sanitizeMessageForPersistence({
|
|
1125
|
+
...message,
|
|
1126
|
+
parts: updatedParts
|
|
1127
|
+
});
|
|
1128
|
+
this.sql`
|
|
1129
|
+
update cf_ai_chat_agent_messages
|
|
1130
|
+
set message = ${JSON.stringify(updatedMessage)}
|
|
1131
|
+
where id = ${message.id}
|
|
1132
|
+
`;
|
|
1133
|
+
this.messages = autoTransformMessages(this._loadMessagesFromDb());
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
if (!updated) {
|
|
1137
|
+
console.warn(`[AIChatAgent] _applyToolApproval: Tool part with toolCallId ${toolCallId} not in input-available or approval-requested state`);
|
|
1138
|
+
return false;
|
|
1139
|
+
}
|
|
1140
|
+
if (!isStreamingMessage) {
|
|
1141
|
+
const broadcastMessage = this._findMessageByToolCallId(toolCallId);
|
|
1142
|
+
if (broadcastMessage) this._broadcastChatMessage({
|
|
1143
|
+
type: MessageType.CF_AGENT_MESSAGE_UPDATED,
|
|
1144
|
+
message: broadcastMessage
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
return true;
|
|
1148
|
+
}
|
|
1071
1149
|
async _reply(id, response, excludeBroadcastIds = [], options = {}) {
|
|
1072
1150
|
const { continuation = false } = options;
|
|
1073
1151
|
return this._tryCatchChat(async () => {
|