@dudousxd/nestjs-agent-react 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -2
- package/dist/index.cjs +633 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +290 -10
- package/dist/index.d.ts +290 -10
- package/dist/index.js +612 -70
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -41,27 +41,41 @@ __export(src_exports, {
|
|
|
41
41
|
MessageList: () => MessageList,
|
|
42
42
|
SPEECH_LANGUAGES: () => SPEECH_LANGUAGES,
|
|
43
43
|
applyCompletion: () => applyCompletion,
|
|
44
|
+
approvalCountdown: () => approvalCountdown,
|
|
44
45
|
backgroundRunsFromThread: () => backgroundRunsFromThread,
|
|
45
46
|
buildTranscriptBlocks: () => buildTranscriptBlocks,
|
|
47
|
+
correctedCallIds: () => correctedCallIds,
|
|
46
48
|
createSkillsSource: () => createSkillsSource,
|
|
47
49
|
describeTimestamp: () => describeTimestamp,
|
|
50
|
+
describeToolCall: () => describeToolCall,
|
|
48
51
|
describeUsage: () => describeUsage,
|
|
49
52
|
extractMessageText: () => extractMessageText,
|
|
53
|
+
fillTemplate: () => fillTemplate,
|
|
50
54
|
filterAutocompleteItems: () => filterAutocompleteItems,
|
|
51
55
|
findActiveTrigger: () => findActiveTrigger,
|
|
52
56
|
formatElapsed: () => formatElapsed,
|
|
53
57
|
formatRelativeTime: () => formatRelativeTime,
|
|
58
|
+
groupToolActivity: () => groupToolActivity,
|
|
59
|
+
inferResultView: () => inferResultView,
|
|
60
|
+
isActionCall: () => isActionCall,
|
|
54
61
|
loadStoredSpeechLang: () => loadStoredSpeechLang,
|
|
55
62
|
persistSpeechLang: () => persistSpeechLang,
|
|
63
|
+
phraseFor: () => phraseFor,
|
|
64
|
+
readPath: () => readPath,
|
|
56
65
|
readReasoningMs: () => readReasoningMs,
|
|
66
|
+
resolveResultView: () => resolveResultView,
|
|
57
67
|
storedMessageToUiMessage: () => storedMessageToUiMessage,
|
|
58
68
|
storedThreadToUiMessages: () => storedThreadToUiMessages,
|
|
69
|
+
toolCallState: () => toolCallState,
|
|
70
|
+
toolCatalogFrom: () => toolCatalogFrom,
|
|
59
71
|
useAgentChat: () => useAgentChat,
|
|
72
|
+
useApprovalCountdown: () => useApprovalCountdown,
|
|
60
73
|
useChatTranscript: () => useChatTranscript,
|
|
61
74
|
useComposerAutocomplete: () => useComposerAutocomplete,
|
|
62
75
|
useElapsed: () => useElapsed,
|
|
63
76
|
useSpeechRecognition: () => useSpeechRecognition,
|
|
64
77
|
useStickToBottom: () => useStickToBottom,
|
|
78
|
+
useToolCatalog: () => useToolCatalog,
|
|
65
79
|
useTranscriptItem: () => useTranscriptItem
|
|
66
80
|
});
|
|
67
81
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -509,6 +523,10 @@ var AgentChatTransport = class {
|
|
|
509
523
|
});
|
|
510
524
|
}
|
|
511
525
|
break;
|
|
526
|
+
case "approval-settled":
|
|
527
|
+
ensureStep();
|
|
528
|
+
forwardAsData(event, false);
|
|
529
|
+
break;
|
|
512
530
|
case "ui":
|
|
513
531
|
ensureStep();
|
|
514
532
|
closeRuns();
|
|
@@ -744,6 +762,15 @@ var AgentClient = class {
|
|
|
744
762
|
const query = threadId === void 0 ? "" : `?threadId=${encodeURIComponent(threadId)}`;
|
|
745
763
|
return this.request("GET", `/agent/skills${query}`);
|
|
746
764
|
}
|
|
765
|
+
/**
|
|
766
|
+
* The tools this caller can reach through `agent` (the default agent when omitted), each with the
|
|
767
|
+
* server-declared `presentation` a chat narrates it by — the same list the model is offered.
|
|
768
|
+
* Prefer {@link useToolCatalog}, which fetches it once and shares it.
|
|
769
|
+
*/
|
|
770
|
+
listTools(agent) {
|
|
771
|
+
const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
|
|
772
|
+
return this.request("GET", `/agent/tools${query}`);
|
|
773
|
+
}
|
|
747
774
|
getThread(id) {
|
|
748
775
|
return this.request("GET", `/agent/threads/${encodeURIComponent(id)}`);
|
|
749
776
|
}
|
|
@@ -799,6 +826,10 @@ var AgentClient = class {
|
|
|
799
826
|
cancelStream(runId) {
|
|
800
827
|
return this.request("POST", `/agent/chat/${encodeURIComponent(runId)}/cancel`);
|
|
801
828
|
}
|
|
829
|
+
/**
|
|
830
|
+
* `remember` approves later calls of the same tool in the same thread; `via` names the surface
|
|
831
|
+
* the decision came through (the server records `'web'` when omitted).
|
|
832
|
+
*/
|
|
802
833
|
approveToolCall(input) {
|
|
803
834
|
return this.request("POST", "/agent/tool-call/approve", input);
|
|
804
835
|
}
|
|
@@ -1026,7 +1057,280 @@ var import_react6 = __toESM(require("react"), 1);
|
|
|
1026
1057
|
var import_react5 = require("react");
|
|
1027
1058
|
|
|
1028
1059
|
// src/transcript/model.ts
|
|
1060
|
+
var import_ai2 = require("ai");
|
|
1061
|
+
|
|
1062
|
+
// src/presentation/tool-activity.ts
|
|
1029
1063
|
var import_ai = require("ai");
|
|
1064
|
+
|
|
1065
|
+
// src/presentation/phrasing.ts
|
|
1066
|
+
function toolCatalogFrom(entries) {
|
|
1067
|
+
const catalog = {};
|
|
1068
|
+
for (const entry of entries) {
|
|
1069
|
+
if (entry.presentation !== void 0) catalog[entry.name] = entry.presentation;
|
|
1070
|
+
}
|
|
1071
|
+
return catalog;
|
|
1072
|
+
}
|
|
1073
|
+
__name(toolCatalogFrom, "toolCatalogFrom");
|
|
1074
|
+
function readPath(value, path) {
|
|
1075
|
+
return path.split(".").reduce((current, key) => {
|
|
1076
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
1077
|
+
return current[key];
|
|
1078
|
+
}, value);
|
|
1079
|
+
}
|
|
1080
|
+
__name(readPath, "readPath");
|
|
1081
|
+
function renderValue(value) {
|
|
1082
|
+
if (value === null || value === void 0) return "";
|
|
1083
|
+
if (typeof value === "string") return value;
|
|
1084
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
1085
|
+
if (Array.isArray(value)) return value.map(renderValue).filter(Boolean).join(", ");
|
|
1086
|
+
return "";
|
|
1087
|
+
}
|
|
1088
|
+
__name(renderValue, "renderValue");
|
|
1089
|
+
function fillTemplate(template, context) {
|
|
1090
|
+
return template.replace(/(\s*)\{([\w.]+)\}/g, (_match, space, path) => {
|
|
1091
|
+
const rendered = renderValue(readPath(context, path));
|
|
1092
|
+
return rendered === "" ? "" : `${space}${rendered}`;
|
|
1093
|
+
}).replace(/\s{2,}/g, " ").trim();
|
|
1094
|
+
}
|
|
1095
|
+
__name(fillTemplate, "fillTemplate");
|
|
1096
|
+
function phraseFor(presentation, input, isSettled2, fallback = {
|
|
1097
|
+
running: "Working",
|
|
1098
|
+
done: "Done"
|
|
1099
|
+
}) {
|
|
1100
|
+
if (presentation === void 0) return isSettled2 ? fallback.done : fallback.running;
|
|
1101
|
+
const filled = fillTemplate(isSettled2 ? presentation.done : presentation.running, input);
|
|
1102
|
+
return filled === "" ? presentation.label : filled;
|
|
1103
|
+
}
|
|
1104
|
+
__name(phraseFor, "phraseFor");
|
|
1105
|
+
|
|
1106
|
+
// src/presentation/result-view.ts
|
|
1107
|
+
function isRecord(value) {
|
|
1108
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1109
|
+
}
|
|
1110
|
+
__name(isRecord, "isRecord");
|
|
1111
|
+
function toText(value) {
|
|
1112
|
+
if (value === null || value === void 0) return "\u2014";
|
|
1113
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1114
|
+
return String(value);
|
|
1115
|
+
}
|
|
1116
|
+
if (Array.isArray(value)) return value.map(toText).join(", ");
|
|
1117
|
+
return "\u2014";
|
|
1118
|
+
}
|
|
1119
|
+
__name(toText, "toText");
|
|
1120
|
+
function inferResultView(output) {
|
|
1121
|
+
if (!isRecord(output)) return void 0;
|
|
1122
|
+
for (const [key, value] of Object.entries(output)) {
|
|
1123
|
+
if (!Array.isArray(value) || value.length === 0) continue;
|
|
1124
|
+
if (value.every((entry) => typeof entry === "string")) {
|
|
1125
|
+
return {
|
|
1126
|
+
kind: "log",
|
|
1127
|
+
lines: key
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
if (value.every(isRecord)) {
|
|
1131
|
+
const first = value[0];
|
|
1132
|
+
return {
|
|
1133
|
+
kind: "table",
|
|
1134
|
+
rows: key,
|
|
1135
|
+
columns: Object.keys(first).filter((column) => !isRecord(first[column])).map((column) => ({
|
|
1136
|
+
path: column,
|
|
1137
|
+
label: column
|
|
1138
|
+
}))
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
const fields = Object.entries(output).filter(([, value]) => [
|
|
1143
|
+
"string",
|
|
1144
|
+
"number",
|
|
1145
|
+
"boolean"
|
|
1146
|
+
].includes(typeof value)).map(([key]) => ({
|
|
1147
|
+
path: key,
|
|
1148
|
+
label: key
|
|
1149
|
+
}));
|
|
1150
|
+
return fields.length > 0 ? {
|
|
1151
|
+
kind: "metrics",
|
|
1152
|
+
fields
|
|
1153
|
+
} : void 0;
|
|
1154
|
+
}
|
|
1155
|
+
__name(inferResultView, "inferResultView");
|
|
1156
|
+
function resolveResultView(output, view, options = {}) {
|
|
1157
|
+
const resolved = view ?? (options.infer === true ? inferResultView(output) : void 0);
|
|
1158
|
+
if (resolved === void 0 || resolved.kind === "elsewhere") return null;
|
|
1159
|
+
switch (resolved.kind) {
|
|
1160
|
+
case "note": {
|
|
1161
|
+
const text = fillTemplate(resolved.text, output);
|
|
1162
|
+
return text === "" ? null : {
|
|
1163
|
+
kind: "note",
|
|
1164
|
+
text
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
case "metrics": {
|
|
1168
|
+
const readings = resolved.fields.map((field) => ({
|
|
1169
|
+
field,
|
|
1170
|
+
value: readPath(output, field.path)
|
|
1171
|
+
})).filter((entry) => entry.value !== void 0 && entry.value !== null).map(({ field, value }) => ({
|
|
1172
|
+
label: field.label,
|
|
1173
|
+
value: toText(value),
|
|
1174
|
+
unit: field.unit ?? null
|
|
1175
|
+
}));
|
|
1176
|
+
return readings.length === 0 ? null : {
|
|
1177
|
+
kind: "metrics",
|
|
1178
|
+
readings
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
case "log": {
|
|
1182
|
+
const lines = readPath(output, resolved.lines);
|
|
1183
|
+
if (!Array.isArray(lines) || lines.length === 0) return null;
|
|
1184
|
+
return {
|
|
1185
|
+
kind: "log",
|
|
1186
|
+
lines: lines.map(toText)
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
case "table": {
|
|
1190
|
+
const rows = readPath(output, resolved.rows);
|
|
1191
|
+
if (!Array.isArray(rows)) return null;
|
|
1192
|
+
return {
|
|
1193
|
+
kind: "table",
|
|
1194
|
+
columns: resolved.columns,
|
|
1195
|
+
rows: rows.map((row) => resolved.columns.map((column) => toText(readPath(row, column.path)))),
|
|
1196
|
+
empty: rows.length === 0 ? resolved.empty ?? null : null
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
__name(resolveResultView, "resolveResultView");
|
|
1202
|
+
|
|
1203
|
+
// src/presentation/tool-activity.ts
|
|
1204
|
+
function isActionCall(part) {
|
|
1205
|
+
const metadata = part.toolMetadata;
|
|
1206
|
+
return typeof metadata === "object" && metadata !== null && metadata.toolKind === "action";
|
|
1207
|
+
}
|
|
1208
|
+
__name(isActionCall, "isActionCall");
|
|
1209
|
+
function toolCallState(part) {
|
|
1210
|
+
const output = "output" in part ? part.output : void 0;
|
|
1211
|
+
const errorText = "errorText" in part ? part.errorText : void 0;
|
|
1212
|
+
const outputError = output !== null && typeof output === "object" && "error" in output ? String(output.error) : void 0;
|
|
1213
|
+
const isDenied = part.state === "output-denied";
|
|
1214
|
+
const isFailed = part.state === "output-error" || outputError !== void 0 && !isDenied;
|
|
1215
|
+
const isSettled2 = part.state === "output-available" || part.state === "output-error" || isDenied;
|
|
1216
|
+
const isAwaiting = part.state === "approval-requested" || part.state === "input-available" && isActionCall(part);
|
|
1217
|
+
const status = isDenied ? "denied" : isFailed ? "failed" : isSettled2 ? "done" : isAwaiting ? "awaiting-approval" : "running";
|
|
1218
|
+
return {
|
|
1219
|
+
status,
|
|
1220
|
+
isSettled: isSettled2,
|
|
1221
|
+
isFailed,
|
|
1222
|
+
isDenied,
|
|
1223
|
+
output,
|
|
1224
|
+
error: errorText ?? outputError ?? null
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
__name(toolCallState, "toolCallState");
|
|
1228
|
+
function correctedCallIds(parts) {
|
|
1229
|
+
const corrected = /* @__PURE__ */ new Set();
|
|
1230
|
+
const lastSuccessByTool = /* @__PURE__ */ new Map();
|
|
1231
|
+
parts.forEach((part, index) => {
|
|
1232
|
+
if (part.state === "output-available" && !toolCallState(part).isFailed) {
|
|
1233
|
+
lastSuccessByTool.set((0, import_ai.getToolName)(part), index);
|
|
1234
|
+
}
|
|
1235
|
+
});
|
|
1236
|
+
parts.forEach((part, index) => {
|
|
1237
|
+
const successAt = lastSuccessByTool.get((0, import_ai.getToolName)(part));
|
|
1238
|
+
if (successAt !== void 0 && index < successAt && toolCallState(part).isFailed) {
|
|
1239
|
+
corrected.add(part.toolCallId);
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
return corrected;
|
|
1243
|
+
}
|
|
1244
|
+
__name(correctedCallIds, "correctedCallIds");
|
|
1245
|
+
function describeToolCall(part, catalog, options = {}) {
|
|
1246
|
+
const presentation = catalog?.[(0, import_ai.getToolName)(part)];
|
|
1247
|
+
const state = toolCallState(part);
|
|
1248
|
+
const input = part.input;
|
|
1249
|
+
const confirm = presentation?.confirm;
|
|
1250
|
+
return {
|
|
1251
|
+
status: state.status,
|
|
1252
|
+
phrase: phraseFor(presentation, input, state.isSettled, options.fallback),
|
|
1253
|
+
label: presentation?.label ?? null,
|
|
1254
|
+
icon: presentation?.icon ?? null,
|
|
1255
|
+
tone: presentation?.tone ?? "neutral",
|
|
1256
|
+
detail: presentation?.detail ?? null,
|
|
1257
|
+
confirm: confirm === void 0 ? null : {
|
|
1258
|
+
title: fillTemplate(confirm.title, input),
|
|
1259
|
+
verb: confirm.verb,
|
|
1260
|
+
detail: confirm.detail !== void 0 ? fillTemplate(confirm.detail, input) : null
|
|
1261
|
+
},
|
|
1262
|
+
result: state.status === "done" ? resolveResultView(state.output, presentation?.result, {
|
|
1263
|
+
...options.inferResult !== void 0 ? {
|
|
1264
|
+
infer: options.inferResult
|
|
1265
|
+
} : {}
|
|
1266
|
+
}) : null,
|
|
1267
|
+
error: state.error,
|
|
1268
|
+
presentation: presentation ?? null
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
__name(describeToolCall, "describeToolCall");
|
|
1272
|
+
var STATUS_WEIGHT = {
|
|
1273
|
+
running: 4,
|
|
1274
|
+
"awaiting-approval": 3,
|
|
1275
|
+
failed: 2,
|
|
1276
|
+
denied: 1,
|
|
1277
|
+
done: 0
|
|
1278
|
+
};
|
|
1279
|
+
function descendants(call) {
|
|
1280
|
+
return call.children.flatMap((child) => [
|
|
1281
|
+
child,
|
|
1282
|
+
...descendants(child)
|
|
1283
|
+
]);
|
|
1284
|
+
}
|
|
1285
|
+
__name(descendants, "descendants");
|
|
1286
|
+
function leaves(call) {
|
|
1287
|
+
return call.children.length === 0 ? [
|
|
1288
|
+
call
|
|
1289
|
+
] : call.children.flatMap(leaves);
|
|
1290
|
+
}
|
|
1291
|
+
__name(leaves, "leaves");
|
|
1292
|
+
function groupToolActivity(calls, options = {}) {
|
|
1293
|
+
const expanded = options.expandNested === true ? calls.flatMap(leaves) : [
|
|
1294
|
+
...calls
|
|
1295
|
+
];
|
|
1296
|
+
const corrected = options.hideCorrected === true ? correctedCallIds(expanded.map((call) => call.part)) : /* @__PURE__ */ new Set();
|
|
1297
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1298
|
+
for (const call of expanded) {
|
|
1299
|
+
if (corrected.has(call.toolCallId)) continue;
|
|
1300
|
+
const presentation = options.catalog?.[call.name];
|
|
1301
|
+
const key = options.keyOf?.(call, presentation) ?? presentation?.label ?? call.name;
|
|
1302
|
+
const status = toolCallState(call.part).status;
|
|
1303
|
+
const phrase = phraseFor(presentation, call.part.input, status !== "running" && status !== "awaiting-approval", options.fallback);
|
|
1304
|
+
const inner = options.expandNested === true ? 0 : descendants(call).length;
|
|
1305
|
+
const existing = groups.get(key);
|
|
1306
|
+
if (existing === void 0) {
|
|
1307
|
+
groups.set(key, {
|
|
1308
|
+
key,
|
|
1309
|
+
label: presentation?.label ?? null,
|
|
1310
|
+
icon: presentation?.icon ?? null,
|
|
1311
|
+
status,
|
|
1312
|
+
count: 1,
|
|
1313
|
+
phrase,
|
|
1314
|
+
calls: [
|
|
1315
|
+
call
|
|
1316
|
+
],
|
|
1317
|
+
innerCount: inner
|
|
1318
|
+
});
|
|
1319
|
+
continue;
|
|
1320
|
+
}
|
|
1321
|
+
existing.count += 1;
|
|
1322
|
+
existing.calls.push(call);
|
|
1323
|
+
existing.phrase = phrase;
|
|
1324
|
+
existing.innerCount += inner;
|
|
1325
|
+
if (STATUS_WEIGHT[status] > STATUS_WEIGHT[existing.status]) existing.status = status;
|
|
1326
|
+
}
|
|
1327
|
+
return [
|
|
1328
|
+
...groups.values()
|
|
1329
|
+
];
|
|
1330
|
+
}
|
|
1331
|
+
__name(groupToolActivity, "groupToolActivity");
|
|
1332
|
+
|
|
1333
|
+
// src/transcript/model.ts
|
|
1030
1334
|
function buildTranscriptBlocks(message, options) {
|
|
1031
1335
|
const blocks = [];
|
|
1032
1336
|
let toolBuffer = [];
|
|
@@ -1043,13 +1347,19 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1043
1347
|
if (toolBuffer.length === 0) {
|
|
1044
1348
|
return;
|
|
1045
1349
|
}
|
|
1046
|
-
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId)
|
|
1350
|
+
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvalOf(approvals.get(part.toolCallId), part), options.toolCatalog));
|
|
1351
|
+
const roots = nestToolCalls(calls);
|
|
1047
1352
|
blocks.push({
|
|
1048
1353
|
kind: "tools",
|
|
1049
1354
|
key: `${message.id}-tools-${toolCounter++}`,
|
|
1050
1355
|
parts: toolBuffer,
|
|
1051
1356
|
calls,
|
|
1052
|
-
roots
|
|
1357
|
+
roots,
|
|
1358
|
+
activity: groupToolActivity(roots, {
|
|
1359
|
+
...options.toolCatalog !== void 0 ? {
|
|
1360
|
+
catalog: options.toolCatalog
|
|
1361
|
+
} : {}
|
|
1362
|
+
})
|
|
1053
1363
|
});
|
|
1054
1364
|
toolBuffer = [];
|
|
1055
1365
|
}
|
|
@@ -1086,7 +1396,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1086
1396
|
}
|
|
1087
1397
|
__name(flushAll, "flushAll");
|
|
1088
1398
|
for (const part of message.parts ?? []) {
|
|
1089
|
-
if ((0,
|
|
1399
|
+
if ((0, import_ai2.isToolUIPart)(part)) {
|
|
1090
1400
|
const elicitation = options.elicitation;
|
|
1091
1401
|
if (elicitation !== void 0) {
|
|
1092
1402
|
const request = readElicitationRequest(part);
|
|
@@ -1106,17 +1416,17 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1106
1416
|
toolBuffer.push(part);
|
|
1107
1417
|
continue;
|
|
1108
1418
|
}
|
|
1109
|
-
if ((0,
|
|
1419
|
+
if ((0, import_ai2.isFileUIPart)(part)) {
|
|
1110
1420
|
flushTools();
|
|
1111
1421
|
flushSources();
|
|
1112
1422
|
fileBuffer.push(part);
|
|
1113
1423
|
continue;
|
|
1114
1424
|
}
|
|
1115
|
-
if (part.type === APPROVAL_PART) {
|
|
1425
|
+
if (part.type === APPROVAL_PART || part.type === SETTLED_PART) {
|
|
1116
1426
|
continue;
|
|
1117
1427
|
}
|
|
1118
1428
|
flushAll();
|
|
1119
|
-
if ((0,
|
|
1429
|
+
if ((0, import_ai2.isDataUIPart)(part)) {
|
|
1120
1430
|
const ui = part.type === UI_PART ? readUiComponent(part) : null;
|
|
1121
1431
|
if (ui !== null) {
|
|
1122
1432
|
blocks.push({
|
|
@@ -1127,7 +1437,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1127
1437
|
}
|
|
1128
1438
|
continue;
|
|
1129
1439
|
}
|
|
1130
|
-
if ((0,
|
|
1440
|
+
if ((0, import_ai2.isTextUIPart)(part)) {
|
|
1131
1441
|
blocks.push({
|
|
1132
1442
|
kind: "text",
|
|
1133
1443
|
key: `${message.id}-text-${textCounter++}`,
|
|
@@ -1136,7 +1446,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1136
1446
|
});
|
|
1137
1447
|
continue;
|
|
1138
1448
|
}
|
|
1139
|
-
if ((0,
|
|
1449
|
+
if ((0, import_ai2.isReasoningUIPart)(part)) {
|
|
1140
1450
|
const key = `${message.id}-reasoning-${reasoningCounter++}`;
|
|
1141
1451
|
const isStreaming = part.state === "streaming";
|
|
1142
1452
|
blocks.push({
|
|
@@ -1198,7 +1508,7 @@ function isSettled(state) {
|
|
|
1198
1508
|
__name(isSettled, "isSettled");
|
|
1199
1509
|
function toolKind(part) {
|
|
1200
1510
|
const metadata = part.toolMetadata;
|
|
1201
|
-
return
|
|
1511
|
+
return isRecord2(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
|
|
1202
1512
|
}
|
|
1203
1513
|
__name(toolKind, "toolKind");
|
|
1204
1514
|
function isAwaitingApproval(part) {
|
|
@@ -1213,7 +1523,7 @@ function isAwaitingApproval(part) {
|
|
|
1213
1523
|
__name(isAwaitingApproval, "isAwaitingApproval");
|
|
1214
1524
|
function toolParentId(part) {
|
|
1215
1525
|
const metadata = part.toolMetadata;
|
|
1216
|
-
return
|
|
1526
|
+
return isRecord2(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
|
|
1217
1527
|
}
|
|
1218
1528
|
__name(toolParentId, "toolParentId");
|
|
1219
1529
|
function nestToolCalls(calls) {
|
|
@@ -1246,23 +1556,28 @@ function isAncestor(call, candidate, byId) {
|
|
|
1246
1556
|
return false;
|
|
1247
1557
|
}
|
|
1248
1558
|
__name(isAncestor, "isAncestor");
|
|
1249
|
-
function buildToolCall(part, options, approval) {
|
|
1559
|
+
function buildToolCall(part, options, approval, catalog) {
|
|
1250
1560
|
const toolCallId = part.toolCallId;
|
|
1251
1561
|
const awaiting = isAwaitingApproval(part);
|
|
1252
1562
|
const sending = awaiting ? options?.submitting(toolCallId) ?? null : null;
|
|
1253
1563
|
return {
|
|
1254
1564
|
part,
|
|
1255
1565
|
toolCallId,
|
|
1256
|
-
name: (0,
|
|
1566
|
+
name: (0, import_ai2.getToolName)(part),
|
|
1257
1567
|
toolKind: toolKind(part) ?? null,
|
|
1258
1568
|
parentId: toolParentId(part),
|
|
1259
1569
|
children: [],
|
|
1260
1570
|
approval,
|
|
1571
|
+
description: describeToolCall(part, catalog),
|
|
1261
1572
|
isAwaitingApproval: awaiting,
|
|
1262
1573
|
approve: {
|
|
1263
1574
|
available: awaiting && options?.canApprove === true,
|
|
1264
1575
|
isSubmitting: sending === "approve",
|
|
1265
|
-
|
|
1576
|
+
// Read by field, not passed through: `onClick={call.approve.run}` hands this a click event,
|
|
1577
|
+
// and a host's handler must not receive that as its options.
|
|
1578
|
+
run: /* @__PURE__ */ __name((approveOptions) => approveOptions?.remember === true ? options?.approve(toolCallId, {
|
|
1579
|
+
remember: true
|
|
1580
|
+
}) : options?.approve(toolCallId), "run")
|
|
1266
1581
|
},
|
|
1267
1582
|
reject: {
|
|
1268
1583
|
available: awaiting && options?.canReject === true,
|
|
@@ -1275,17 +1590,17 @@ function buildToolCall(part, options, approval) {
|
|
|
1275
1590
|
__name(buildToolCall, "buildToolCall");
|
|
1276
1591
|
function readElicitationRequest(part) {
|
|
1277
1592
|
const input = part.input;
|
|
1278
|
-
if (!
|
|
1593
|
+
if (!isRecord2(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
|
|
1279
1594
|
return null;
|
|
1280
1595
|
}
|
|
1281
1596
|
const questions = [];
|
|
1282
1597
|
for (const candidate of input.questions) {
|
|
1283
|
-
if (!
|
|
1598
|
+
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string" || !Array.isArray(candidate.options) || candidate.options.length === 0) {
|
|
1284
1599
|
return null;
|
|
1285
1600
|
}
|
|
1286
1601
|
const options = [];
|
|
1287
1602
|
for (const option of candidate.options) {
|
|
1288
|
-
if (!
|
|
1603
|
+
if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
|
|
1289
1604
|
return null;
|
|
1290
1605
|
}
|
|
1291
1606
|
options.push({
|
|
@@ -1310,7 +1625,7 @@ function readElicitationRequest(part) {
|
|
|
1310
1625
|
__name(readElicitationRequest, "readElicitationRequest");
|
|
1311
1626
|
function readElicitationOutcome(part) {
|
|
1312
1627
|
const output = part.output;
|
|
1313
|
-
if (!
|
|
1628
|
+
if (!isRecord2(output) || !isRecord2(output.answers) || typeof output.skipped !== "boolean") {
|
|
1314
1629
|
return null;
|
|
1315
1630
|
}
|
|
1316
1631
|
const answers = {};
|
|
@@ -1390,28 +1705,93 @@ function buildElicitationBlock(key, part, request, options) {
|
|
|
1390
1705
|
__name(buildElicitationBlock, "buildElicitationBlock");
|
|
1391
1706
|
var UI_PART = "data-ui";
|
|
1392
1707
|
var APPROVAL_PART = "data-approval-requested";
|
|
1708
|
+
var SETTLED_PART = "data-approval-settled";
|
|
1709
|
+
var SETTLED_STATUSES = [
|
|
1710
|
+
"approved",
|
|
1711
|
+
"rejected",
|
|
1712
|
+
"expired"
|
|
1713
|
+
];
|
|
1393
1714
|
function readApprovals(parts) {
|
|
1394
1715
|
const out = /* @__PURE__ */ new Map();
|
|
1716
|
+
const entry = /* @__PURE__ */ __name((id) => {
|
|
1717
|
+
let found = out.get(id);
|
|
1718
|
+
if (found === void 0) {
|
|
1719
|
+
found = {
|
|
1720
|
+
approver: null,
|
|
1721
|
+
expiresAt: null,
|
|
1722
|
+
reason: null,
|
|
1723
|
+
status: null,
|
|
1724
|
+
remember: false,
|
|
1725
|
+
decidedBy: null,
|
|
1726
|
+
decidedVia: null,
|
|
1727
|
+
decisionReason: null
|
|
1728
|
+
};
|
|
1729
|
+
out.set(id, found);
|
|
1730
|
+
}
|
|
1731
|
+
return found;
|
|
1732
|
+
}, "entry");
|
|
1395
1733
|
for (const part of parts) {
|
|
1396
|
-
if (part.type !== APPROVAL_PART) {
|
|
1734
|
+
if (part.type !== APPROVAL_PART && part.type !== SETTLED_PART) {
|
|
1397
1735
|
continue;
|
|
1398
1736
|
}
|
|
1399
1737
|
const data = part.data;
|
|
1400
|
-
if (!
|
|
1738
|
+
if (!isRecord2(data) || typeof data.id !== "string") {
|
|
1401
1739
|
continue;
|
|
1402
1740
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1741
|
+
const approval = entry(data.id);
|
|
1742
|
+
if (part.type === APPROVAL_PART) {
|
|
1743
|
+
if (typeof data.approver !== "string") {
|
|
1744
|
+
continue;
|
|
1745
|
+
}
|
|
1746
|
+
approval.approver = data.approver;
|
|
1747
|
+
approval.expiresAt = typeof data.expiresAt === "string" ? data.expiresAt : null;
|
|
1748
|
+
approval.reason = typeof data.reason === "string" ? data.reason : null;
|
|
1749
|
+
continue;
|
|
1750
|
+
}
|
|
1751
|
+
if (typeof data.status !== "string" || !SETTLED_STATUSES.includes(data.status)) {
|
|
1752
|
+
continue;
|
|
1753
|
+
}
|
|
1754
|
+
approval.status = data.status;
|
|
1755
|
+
if (approval.approver === null && typeof data.approver === "string") {
|
|
1756
|
+
approval.approver = data.approver;
|
|
1757
|
+
}
|
|
1758
|
+
approval.remember = data.remember === true;
|
|
1759
|
+
approval.decidedBy = typeof data.decidedBy === "string" ? data.decidedBy : null;
|
|
1760
|
+
approval.decidedVia = typeof data.decidedVia === "string" ? data.decidedVia : null;
|
|
1761
|
+
approval.decisionReason = typeof data.reason === "string" ? data.reason : null;
|
|
1408
1762
|
}
|
|
1409
1763
|
return out;
|
|
1410
1764
|
}
|
|
1411
1765
|
__name(readApprovals, "readApprovals");
|
|
1766
|
+
function approvalOf(parts, call) {
|
|
1767
|
+
if (parts === void 0 || parts.approver === null) {
|
|
1768
|
+
return null;
|
|
1769
|
+
}
|
|
1770
|
+
return {
|
|
1771
|
+
approver: parts.approver,
|
|
1772
|
+
expiresAt: parts.expiresAt,
|
|
1773
|
+
reason: parts.reason,
|
|
1774
|
+
status: parts.status ?? statusFromPart(call),
|
|
1775
|
+
remember: parts.remember,
|
|
1776
|
+
decidedBy: parts.decidedBy,
|
|
1777
|
+
decidedVia: parts.decidedVia,
|
|
1778
|
+
decisionReason: parts.decisionReason
|
|
1779
|
+
};
|
|
1780
|
+
}
|
|
1781
|
+
__name(approvalOf, "approvalOf");
|
|
1782
|
+
function statusFromPart(call) {
|
|
1783
|
+
if (call.state === "output-denied") {
|
|
1784
|
+
return "rejected";
|
|
1785
|
+
}
|
|
1786
|
+
if (call.state === "output-available" || call.state === "output-error") {
|
|
1787
|
+
return "approved";
|
|
1788
|
+
}
|
|
1789
|
+
return "pending";
|
|
1790
|
+
}
|
|
1791
|
+
__name(statusFromPart, "statusFromPart");
|
|
1412
1792
|
function readUiComponent(part) {
|
|
1413
1793
|
const data = part.data;
|
|
1414
|
-
if (!
|
|
1794
|
+
if (!isRecord2(data) || typeof data.component !== "string") {
|
|
1415
1795
|
return null;
|
|
1416
1796
|
}
|
|
1417
1797
|
const id = typeof data.id === "string" ? data.id : part.id;
|
|
@@ -1421,18 +1801,18 @@ function readUiComponent(part) {
|
|
|
1421
1801
|
return {
|
|
1422
1802
|
id,
|
|
1423
1803
|
component: data.component,
|
|
1424
|
-
props:
|
|
1804
|
+
props: isRecord2(data.props) ? data.props : {},
|
|
1425
1805
|
version: typeof data.version === "number" ? data.version : null
|
|
1426
1806
|
};
|
|
1427
1807
|
}
|
|
1428
1808
|
__name(readUiComponent, "readUiComponent");
|
|
1429
|
-
function
|
|
1809
|
+
function isRecord2(value) {
|
|
1430
1810
|
return typeof value === "object" && value !== null;
|
|
1431
1811
|
}
|
|
1432
|
-
__name(
|
|
1812
|
+
__name(isRecord2, "isRecord");
|
|
1433
1813
|
function readQuery(part) {
|
|
1434
1814
|
const input = part.input;
|
|
1435
|
-
if (!
|
|
1815
|
+
if (!isRecord2(input) || typeof input.query !== "string") {
|
|
1436
1816
|
return null;
|
|
1437
1817
|
}
|
|
1438
1818
|
return input.query;
|
|
@@ -1440,12 +1820,12 @@ function readQuery(part) {
|
|
|
1440
1820
|
__name(readQuery, "readQuery");
|
|
1441
1821
|
function readPassages(part) {
|
|
1442
1822
|
const output = part.output;
|
|
1443
|
-
if (!
|
|
1823
|
+
if (!isRecord2(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
|
|
1444
1824
|
return null;
|
|
1445
1825
|
}
|
|
1446
1826
|
const passages = [];
|
|
1447
1827
|
for (const candidate of output.passages) {
|
|
1448
|
-
if (!
|
|
1828
|
+
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
|
|
1449
1829
|
return null;
|
|
1450
1830
|
}
|
|
1451
1831
|
passages.push({
|
|
@@ -1455,7 +1835,7 @@ function readPassages(part) {
|
|
|
1455
1835
|
...typeof candidate.source === "string" ? {
|
|
1456
1836
|
source: candidate.source
|
|
1457
1837
|
} : {},
|
|
1458
|
-
...
|
|
1838
|
+
...isRecord2(candidate.metadata) ? {
|
|
1459
1839
|
metadata: candidate.metadata
|
|
1460
1840
|
} : {}
|
|
1461
1841
|
});
|
|
@@ -1466,7 +1846,7 @@ __name(readPassages, "readPassages");
|
|
|
1466
1846
|
function extractMessageText(parts) {
|
|
1467
1847
|
const out = [];
|
|
1468
1848
|
for (const part of parts ?? []) {
|
|
1469
|
-
if ((0,
|
|
1849
|
+
if ((0, import_ai2.isTextUIPart)(part)) {
|
|
1470
1850
|
out.push(part.text);
|
|
1471
1851
|
}
|
|
1472
1852
|
}
|
|
@@ -1794,10 +2174,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1794
2174
|
}, [
|
|
1795
2175
|
settle
|
|
1796
2176
|
]);
|
|
1797
|
-
const approve = (0, import_react5.useCallback)((toolCallId) => {
|
|
2177
|
+
const approve = (0, import_react5.useCallback)((toolCallId, options2) => {
|
|
1798
2178
|
const onApprove = latest.current.options.onApprove;
|
|
1799
2179
|
if (onApprove) {
|
|
1800
|
-
settle(toolCallId, "approve", () => onApprove(toolCallId));
|
|
2180
|
+
settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
|
|
1801
2181
|
}
|
|
1802
2182
|
}, [
|
|
1803
2183
|
settle
|
|
@@ -1922,6 +2302,9 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1922
2302
|
...options.sources !== void 0 ? {
|
|
1923
2303
|
sources: options.sources
|
|
1924
2304
|
} : {},
|
|
2305
|
+
...options.toolCatalog !== void 0 ? {
|
|
2306
|
+
toolCatalog: options.toolCatalog
|
|
2307
|
+
} : {},
|
|
1925
2308
|
...options.onAnswer !== void 0 ? {
|
|
1926
2309
|
elicitation: {
|
|
1927
2310
|
picked: /* @__PURE__ */ __name((toolCallId, questionId) => picks.get(pickKey(toolCallId, questionId)), "picked"),
|
|
@@ -2697,6 +3080,121 @@ function isPromise(value) {
|
|
|
2697
3080
|
}
|
|
2698
3081
|
__name(isPromise, "isPromise");
|
|
2699
3082
|
|
|
3083
|
+
// src/presentation/use-tool-catalog.ts
|
|
3084
|
+
var import_react8 = require("react");
|
|
3085
|
+
var shared = /* @__PURE__ */ new WeakMap();
|
|
3086
|
+
function load(client, agent) {
|
|
3087
|
+
let byAgent = shared.get(client);
|
|
3088
|
+
if (byAgent === void 0) {
|
|
3089
|
+
byAgent = /* @__PURE__ */ new Map();
|
|
3090
|
+
shared.set(client, byAgent);
|
|
3091
|
+
}
|
|
3092
|
+
const key = agent ?? "";
|
|
3093
|
+
const cached = byAgent.get(key);
|
|
3094
|
+
if (cached !== void 0) return cached;
|
|
3095
|
+
const request = client.listTools(agent).catch((error) => {
|
|
3096
|
+
byAgent.delete(key);
|
|
3097
|
+
throw error;
|
|
3098
|
+
});
|
|
3099
|
+
byAgent.set(key, request);
|
|
3100
|
+
return request;
|
|
3101
|
+
}
|
|
3102
|
+
__name(load, "load");
|
|
3103
|
+
function useToolCatalog(options) {
|
|
3104
|
+
const { client, agent, enabled = true } = options;
|
|
3105
|
+
const [entries, setEntries] = (0, import_react8.useState)([]);
|
|
3106
|
+
const [isLoading, setLoading] = (0, import_react8.useState)(enabled);
|
|
3107
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
3108
|
+
const [generation, setGeneration] = (0, import_react8.useState)(0);
|
|
3109
|
+
(0, import_react8.useEffect)(() => {
|
|
3110
|
+
if (!enabled) {
|
|
3111
|
+
setLoading(false);
|
|
3112
|
+
return;
|
|
3113
|
+
}
|
|
3114
|
+
let cancelled = false;
|
|
3115
|
+
setLoading(true);
|
|
3116
|
+
load(client, agent).then((loaded) => {
|
|
3117
|
+
if (cancelled) return;
|
|
3118
|
+
setEntries(loaded);
|
|
3119
|
+
setError(null);
|
|
3120
|
+
setLoading(false);
|
|
3121
|
+
}, (failure) => {
|
|
3122
|
+
if (cancelled) return;
|
|
3123
|
+
setError(failure instanceof Error ? failure : new Error(String(failure)));
|
|
3124
|
+
setLoading(false);
|
|
3125
|
+
});
|
|
3126
|
+
return () => {
|
|
3127
|
+
cancelled = true;
|
|
3128
|
+
};
|
|
3129
|
+
}, [
|
|
3130
|
+
client,
|
|
3131
|
+
agent,
|
|
3132
|
+
enabled,
|
|
3133
|
+
generation
|
|
3134
|
+
]);
|
|
3135
|
+
const refresh = (0, import_react8.useCallback)(() => {
|
|
3136
|
+
shared.get(client)?.delete(agent ?? "");
|
|
3137
|
+
setGeneration((current) => current + 1);
|
|
3138
|
+
}, [
|
|
3139
|
+
client,
|
|
3140
|
+
agent
|
|
3141
|
+
]);
|
|
3142
|
+
const catalog = (0, import_react8.useMemo)(() => toolCatalogFrom(entries), [
|
|
3143
|
+
entries
|
|
3144
|
+
]);
|
|
3145
|
+
return {
|
|
3146
|
+
catalog,
|
|
3147
|
+
entries,
|
|
3148
|
+
isLoading,
|
|
3149
|
+
error,
|
|
3150
|
+
refresh
|
|
3151
|
+
};
|
|
3152
|
+
}
|
|
3153
|
+
__name(useToolCatalog, "useToolCatalog");
|
|
3154
|
+
|
|
3155
|
+
// src/approvals/countdown.ts
|
|
3156
|
+
var import_react9 = require("react");
|
|
3157
|
+
function approvalCountdown(expiresAt, now = Date.now()) {
|
|
3158
|
+
const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
|
|
3159
|
+
if (!Number.isFinite(deadline)) {
|
|
3160
|
+
return {
|
|
3161
|
+
remainingMs: null,
|
|
3162
|
+
isExpired: false
|
|
3163
|
+
};
|
|
3164
|
+
}
|
|
3165
|
+
const remainingMs = Math.max(0, deadline - now);
|
|
3166
|
+
return {
|
|
3167
|
+
remainingMs,
|
|
3168
|
+
isExpired: remainingMs === 0
|
|
3169
|
+
};
|
|
3170
|
+
}
|
|
3171
|
+
__name(approvalCountdown, "approvalCountdown");
|
|
3172
|
+
function useApprovalCountdown(expiresAt, options = {}) {
|
|
3173
|
+
const { intervalMs = 1e3 } = options;
|
|
3174
|
+
const nowRef = (0, import_react9.useRef)(options.now ?? Date.now);
|
|
3175
|
+
nowRef.current = options.now ?? Date.now;
|
|
3176
|
+
const [state, setState] = (0, import_react9.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
|
|
3177
|
+
(0, import_react9.useEffect)(() => {
|
|
3178
|
+
const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
|
|
3179
|
+
const first = read();
|
|
3180
|
+
setState(first);
|
|
3181
|
+
if (first.remainingMs === null || first.isExpired) {
|
|
3182
|
+
return;
|
|
3183
|
+
}
|
|
3184
|
+
const timer = setInterval(() => {
|
|
3185
|
+
const next = read();
|
|
3186
|
+
setState(next);
|
|
3187
|
+
if (next.isExpired) clearInterval(timer);
|
|
3188
|
+
}, intervalMs);
|
|
3189
|
+
return () => clearInterval(timer);
|
|
3190
|
+
}, [
|
|
3191
|
+
expiresAt,
|
|
3192
|
+
intervalMs
|
|
3193
|
+
]);
|
|
3194
|
+
return state;
|
|
3195
|
+
}
|
|
3196
|
+
__name(useApprovalCountdown, "useApprovalCountdown");
|
|
3197
|
+
|
|
2700
3198
|
// src/stored-message-to-ui-message.ts
|
|
2701
3199
|
var import_nestjs_agent_core = require("@dudousxd/nestjs-agent-core");
|
|
2702
3200
|
function isRefusal(result) {
|
|
@@ -2756,6 +3254,41 @@ function storedMessageToUiMessage(message) {
|
|
|
2756
3254
|
}
|
|
2757
3255
|
});
|
|
2758
3256
|
}
|
|
3257
|
+
for (const approval of message.approvals ?? []) {
|
|
3258
|
+
parts.push({
|
|
3259
|
+
type: "data-approval-requested",
|
|
3260
|
+
id: approval.toolCallId,
|
|
3261
|
+
data: {
|
|
3262
|
+
id: approval.toolCallId,
|
|
3263
|
+
approver: approval.approver,
|
|
3264
|
+
...approval.expiresAt !== void 0 ? {
|
|
3265
|
+
expiresAt: approval.expiresAt
|
|
3266
|
+
} : {}
|
|
3267
|
+
}
|
|
3268
|
+
});
|
|
3269
|
+
if (approval.status !== "pending") {
|
|
3270
|
+
parts.push({
|
|
3271
|
+
type: "data-approval-settled",
|
|
3272
|
+
id: approval.toolCallId,
|
|
3273
|
+
data: {
|
|
3274
|
+
id: approval.toolCallId,
|
|
3275
|
+
status: approval.status,
|
|
3276
|
+
...approval.decidedBy !== void 0 ? {
|
|
3277
|
+
decidedBy: approval.decidedBy
|
|
3278
|
+
} : {},
|
|
3279
|
+
...approval.decidedVia !== void 0 ? {
|
|
3280
|
+
decidedVia: approval.decidedVia
|
|
3281
|
+
} : {},
|
|
3282
|
+
...approval.remember === true ? {
|
|
3283
|
+
remember: true
|
|
3284
|
+
} : {},
|
|
3285
|
+
...approval.reason !== void 0 ? {
|
|
3286
|
+
reason: approval.reason
|
|
3287
|
+
} : {}
|
|
3288
|
+
}
|
|
3289
|
+
});
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
2759
3292
|
for (const call of message.toolCalls ?? []) {
|
|
2760
3293
|
const result = message.toolResults?.find((candidate) => candidate.id === call.id);
|
|
2761
3294
|
const toolKind2 = call.kind;
|
|
@@ -2857,21 +3390,21 @@ function sumUsage(rows) {
|
|
|
2857
3390
|
__name(sumUsage, "sumUsage");
|
|
2858
3391
|
|
|
2859
3392
|
// src/use-agent-chat.ts
|
|
2860
|
-
var
|
|
2861
|
-
var
|
|
3393
|
+
var import_react10 = require("@ai-sdk/react");
|
|
3394
|
+
var import_react11 = require("react");
|
|
2862
3395
|
function useAgentChat(options) {
|
|
2863
|
-
const latest = (0,
|
|
3396
|
+
const latest = (0, import_react11.useRef)(options);
|
|
2864
3397
|
latest.current = options;
|
|
2865
|
-
const [runId, setRunId] = (0,
|
|
2866
|
-
const runIdRef = (0,
|
|
3398
|
+
const [runId, setRunId] = (0, import_react11.useState)(options.resumeRunId);
|
|
3399
|
+
const runIdRef = (0, import_react11.useRef)(runId);
|
|
2867
3400
|
runIdRef.current = runId;
|
|
2868
|
-
const settlingRunIdRef = (0,
|
|
2869
|
-
const autoResumeRunIdRef = (0,
|
|
2870
|
-
const [autoResume, setAutoResume] = (0,
|
|
2871
|
-
const [activeRunId, setActiveRunId] = (0,
|
|
2872
|
-
const regenerateNext = (0,
|
|
2873
|
-
const createdThreadId = (0,
|
|
2874
|
-
const client = (0,
|
|
3401
|
+
const settlingRunIdRef = (0, import_react11.useRef)(void 0);
|
|
3402
|
+
const autoResumeRunIdRef = (0, import_react11.useRef)(void 0);
|
|
3403
|
+
const [autoResume, setAutoResume] = (0, import_react11.useState)(false);
|
|
3404
|
+
const [activeRunId, setActiveRunId] = (0, import_react11.useState)(null);
|
|
3405
|
+
const regenerateNext = (0, import_react11.useRef)(false);
|
|
3406
|
+
const createdThreadId = (0, import_react11.useRef)(void 0);
|
|
3407
|
+
const client = (0, import_react11.useMemo)(() => {
|
|
2875
3408
|
if (options.client) return options.client;
|
|
2876
3409
|
return new AgentClient({
|
|
2877
3410
|
...options.baseUrl !== void 0 ? {
|
|
@@ -2886,7 +3419,7 @@ function useAgentChat(options) {
|
|
|
2886
3419
|
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
2887
3420
|
});
|
|
2888
3421
|
}, []);
|
|
2889
|
-
(0,
|
|
3422
|
+
(0, import_react11.useEffect)(() => {
|
|
2890
3423
|
if (!options.resume || options.threadId === void 0) return;
|
|
2891
3424
|
let cancelled = false;
|
|
2892
3425
|
const threadId = options.threadId;
|
|
@@ -2906,7 +3439,7 @@ function useAgentChat(options) {
|
|
|
2906
3439
|
options.resume,
|
|
2907
3440
|
options.threadId
|
|
2908
3441
|
]);
|
|
2909
|
-
const transport = (0,
|
|
3442
|
+
const transport = (0, import_react11.useMemo)(() => {
|
|
2910
3443
|
function onMeta(meta) {
|
|
2911
3444
|
settlingRunIdRef.current = meta.runId;
|
|
2912
3445
|
setRunId(meta.runId);
|
|
@@ -2955,8 +3488,8 @@ function useAgentChat(options) {
|
|
|
2955
3488
|
}, "onAttemptStart")
|
|
2956
3489
|
});
|
|
2957
3490
|
}, []);
|
|
2958
|
-
const backgroundRef = (0,
|
|
2959
|
-
const chat = (0,
|
|
3491
|
+
const backgroundRef = (0, import_react11.useRef)(() => Promise.resolve());
|
|
3492
|
+
const chat = (0, import_react10.useChat)({
|
|
2960
3493
|
transport,
|
|
2961
3494
|
resume: options.resumeRunId !== void 0 || autoResume,
|
|
2962
3495
|
...options.threadId !== void 0 ? {
|
|
@@ -2986,13 +3519,13 @@ function useAgentChat(options) {
|
|
|
2986
3519
|
}
|
|
2987
3520
|
}, "onFinish")
|
|
2988
3521
|
});
|
|
2989
|
-
const chatRef = (0,
|
|
3522
|
+
const chatRef = (0, import_react11.useRef)(chat);
|
|
2990
3523
|
chatRef.current = chat;
|
|
2991
|
-
const turnInFlight = (0,
|
|
2992
|
-
const isTurnInFlight = (0,
|
|
3524
|
+
const turnInFlight = (0, import_react11.useRef)(false);
|
|
3525
|
+
const isTurnInFlight = (0, import_react11.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
|
|
2993
3526
|
transport
|
|
2994
3527
|
]);
|
|
2995
|
-
const sendMessage = (0,
|
|
3528
|
+
const sendMessage = (0, import_react11.useCallback)(async (...args) => {
|
|
2996
3529
|
if (isTurnInFlight()) return;
|
|
2997
3530
|
turnInFlight.current = true;
|
|
2998
3531
|
try {
|
|
@@ -3003,15 +3536,15 @@ function useAgentChat(options) {
|
|
|
3003
3536
|
}, [
|
|
3004
3537
|
isTurnInFlight
|
|
3005
3538
|
]);
|
|
3006
|
-
const addToolResult = (0,
|
|
3539
|
+
const addToolResult = (0, import_react11.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
|
|
3007
3540
|
tool,
|
|
3008
3541
|
toolCallId,
|
|
3009
3542
|
output
|
|
3010
3543
|
}), []);
|
|
3011
|
-
const [threads, setThreads] = (0,
|
|
3012
|
-
const [quota, setQuota] = (0,
|
|
3013
|
-
const [backgroundRuns, setBackgroundRuns] = (0,
|
|
3014
|
-
const refreshBackground = (0,
|
|
3544
|
+
const [threads, setThreads] = (0, import_react11.useState)([]);
|
|
3545
|
+
const [quota, setQuota] = (0, import_react11.useState)(null);
|
|
3546
|
+
const [backgroundRuns, setBackgroundRuns] = (0, import_react11.useState)([]);
|
|
3547
|
+
const refreshBackground = (0, import_react11.useCallback)(async () => {
|
|
3015
3548
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
3016
3549
|
if (threadId === void 0) {
|
|
3017
3550
|
return;
|
|
@@ -3036,7 +3569,7 @@ function useAgentChat(options) {
|
|
|
3036
3569
|
]);
|
|
3037
3570
|
backgroundRef.current = refreshBackground;
|
|
3038
3571
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
3039
|
-
(0,
|
|
3572
|
+
(0, import_react11.useEffect)(() => {
|
|
3040
3573
|
if (options.background !== true || options.threadId === void 0) {
|
|
3041
3574
|
return;
|
|
3042
3575
|
}
|
|
@@ -3046,7 +3579,7 @@ function useAgentChat(options) {
|
|
|
3046
3579
|
options.threadId,
|
|
3047
3580
|
refreshBackground
|
|
3048
3581
|
]);
|
|
3049
|
-
(0,
|
|
3582
|
+
(0, import_react11.useEffect)(() => {
|
|
3050
3583
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
3051
3584
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
3052
3585
|
return;
|
|
@@ -3057,26 +3590,26 @@ function useAgentChat(options) {
|
|
|
3057
3590
|
isWorking,
|
|
3058
3591
|
refreshBackground
|
|
3059
3592
|
]);
|
|
3060
|
-
const loadThreads = (0,
|
|
3593
|
+
const loadThreads = (0, import_react11.useCallback)(async () => {
|
|
3061
3594
|
const list = await client.listThreads();
|
|
3062
3595
|
setThreads(list);
|
|
3063
3596
|
return list;
|
|
3064
3597
|
}, [
|
|
3065
3598
|
client
|
|
3066
3599
|
]);
|
|
3067
|
-
const loadThread = (0,
|
|
3600
|
+
const loadThread = (0, import_react11.useCallback)((id) => client.getThread(id), [
|
|
3068
3601
|
client
|
|
3069
3602
|
]);
|
|
3070
|
-
const deleteThread = (0,
|
|
3603
|
+
const deleteThread = (0, import_react11.useCallback)(async (id) => {
|
|
3071
3604
|
await client.deleteThread(id);
|
|
3072
3605
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
3073
3606
|
}, [
|
|
3074
3607
|
client
|
|
3075
3608
|
]);
|
|
3076
|
-
const forkThread = (0,
|
|
3609
|
+
const forkThread = (0, import_react11.useCallback)((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
|
|
3077
3610
|
client
|
|
3078
3611
|
]);
|
|
3079
|
-
const renameThread = (0,
|
|
3612
|
+
const renameThread = (0, import_react11.useCallback)(async (id, title) => {
|
|
3080
3613
|
await client.renameThread(id, title);
|
|
3081
3614
|
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
3082
3615
|
...thread,
|
|
@@ -3085,24 +3618,24 @@ function useAgentChat(options) {
|
|
|
3085
3618
|
}, [
|
|
3086
3619
|
client
|
|
3087
3620
|
]);
|
|
3088
|
-
const promoteThread = (0,
|
|
3621
|
+
const promoteThread = (0, import_react11.useCallback)(async (id) => {
|
|
3089
3622
|
await client.promoteThread(id);
|
|
3090
3623
|
await loadThreads();
|
|
3091
3624
|
}, [
|
|
3092
3625
|
client,
|
|
3093
3626
|
loadThreads
|
|
3094
3627
|
]);
|
|
3095
|
-
const truncateFromMessage = (0,
|
|
3628
|
+
const truncateFromMessage = (0, import_react11.useCallback)((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
|
|
3096
3629
|
client
|
|
3097
3630
|
]);
|
|
3098
|
-
const loadQuota = (0,
|
|
3631
|
+
const loadQuota = (0, import_react11.useCallback)(async () => {
|
|
3099
3632
|
const today = await client.getQuotaToday();
|
|
3100
3633
|
setQuota(today);
|
|
3101
3634
|
return today;
|
|
3102
3635
|
}, [
|
|
3103
3636
|
client
|
|
3104
3637
|
]);
|
|
3105
|
-
const cancel = (0,
|
|
3638
|
+
const cancel = (0, import_react11.useCallback)(async () => {
|
|
3106
3639
|
chatRef.current.stop();
|
|
3107
3640
|
const activeRunId2 = runIdRef.current;
|
|
3108
3641
|
if (activeRunId2) {
|
|
@@ -3114,24 +3647,33 @@ function useAgentChat(options) {
|
|
|
3114
3647
|
}, [
|
|
3115
3648
|
client
|
|
3116
3649
|
]);
|
|
3117
|
-
const approve = (0,
|
|
3650
|
+
const approve = (0, import_react11.useCallback)(async ({ toolCallId, remember, via }) => {
|
|
3118
3651
|
await client.approveToolCall({
|
|
3119
|
-
toolCallId
|
|
3652
|
+
toolCallId,
|
|
3653
|
+
...remember === true ? {
|
|
3654
|
+
remember: true
|
|
3655
|
+
} : {},
|
|
3656
|
+
...via !== void 0 ? {
|
|
3657
|
+
via
|
|
3658
|
+
} : {}
|
|
3120
3659
|
});
|
|
3121
3660
|
}, [
|
|
3122
3661
|
client
|
|
3123
3662
|
]);
|
|
3124
|
-
const reject = (0,
|
|
3663
|
+
const reject = (0, import_react11.useCallback)(async ({ toolCallId, reason, via }) => {
|
|
3125
3664
|
await client.rejectToolCall({
|
|
3126
3665
|
toolCallId,
|
|
3127
3666
|
...reason !== void 0 ? {
|
|
3128
3667
|
reason
|
|
3668
|
+
} : {},
|
|
3669
|
+
...via !== void 0 ? {
|
|
3670
|
+
via
|
|
3129
3671
|
} : {}
|
|
3130
3672
|
});
|
|
3131
3673
|
}, [
|
|
3132
3674
|
client
|
|
3133
3675
|
]);
|
|
3134
|
-
const answer = (0,
|
|
3676
|
+
const answer = (0, import_react11.useCallback)(async ({ toolCallId, answers }) => {
|
|
3135
3677
|
await client.answerToolCall({
|
|
3136
3678
|
toolCallId,
|
|
3137
3679
|
...answers !== void 0 ? {
|
|
@@ -3141,14 +3683,14 @@ function useAgentChat(options) {
|
|
|
3141
3683
|
}, [
|
|
3142
3684
|
client
|
|
3143
3685
|
]);
|
|
3144
|
-
const skip = (0,
|
|
3686
|
+
const skip = (0, import_react11.useCallback)(async ({ toolCallId }) => {
|
|
3145
3687
|
await client.skipToolCall({
|
|
3146
3688
|
toolCallId
|
|
3147
3689
|
});
|
|
3148
3690
|
}, [
|
|
3149
3691
|
client
|
|
3150
3692
|
]);
|
|
3151
|
-
const regenerate = (0,
|
|
3693
|
+
const regenerate = (0, import_react11.useCallback)(() => {
|
|
3152
3694
|
if (isTurnInFlight()) return;
|
|
3153
3695
|
regenerateNext.current = true;
|
|
3154
3696
|
turnInFlight.current = true;
|
|
@@ -3212,27 +3754,41 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
3212
3754
|
MessageList,
|
|
3213
3755
|
SPEECH_LANGUAGES,
|
|
3214
3756
|
applyCompletion,
|
|
3757
|
+
approvalCountdown,
|
|
3215
3758
|
backgroundRunsFromThread,
|
|
3216
3759
|
buildTranscriptBlocks,
|
|
3760
|
+
correctedCallIds,
|
|
3217
3761
|
createSkillsSource,
|
|
3218
3762
|
describeTimestamp,
|
|
3763
|
+
describeToolCall,
|
|
3219
3764
|
describeUsage,
|
|
3220
3765
|
extractMessageText,
|
|
3766
|
+
fillTemplate,
|
|
3221
3767
|
filterAutocompleteItems,
|
|
3222
3768
|
findActiveTrigger,
|
|
3223
3769
|
formatElapsed,
|
|
3224
3770
|
formatRelativeTime,
|
|
3771
|
+
groupToolActivity,
|
|
3772
|
+
inferResultView,
|
|
3773
|
+
isActionCall,
|
|
3225
3774
|
loadStoredSpeechLang,
|
|
3226
3775
|
persistSpeechLang,
|
|
3776
|
+
phraseFor,
|
|
3777
|
+
readPath,
|
|
3227
3778
|
readReasoningMs,
|
|
3779
|
+
resolveResultView,
|
|
3228
3780
|
storedMessageToUiMessage,
|
|
3229
3781
|
storedThreadToUiMessages,
|
|
3782
|
+
toolCallState,
|
|
3783
|
+
toolCatalogFrom,
|
|
3230
3784
|
useAgentChat,
|
|
3785
|
+
useApprovalCountdown,
|
|
3231
3786
|
useChatTranscript,
|
|
3232
3787
|
useComposerAutocomplete,
|
|
3233
3788
|
useElapsed,
|
|
3234
3789
|
useSpeechRecognition,
|
|
3235
3790
|
useStickToBottom,
|
|
3791
|
+
useToolCatalog,
|
|
3236
3792
|
useTranscriptItem
|
|
3237
3793
|
});
|
|
3238
3794
|
//# sourceMappingURL=index.cjs.map
|