@dudousxd/nestjs-agent-react 0.9.0 → 0.10.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 +28 -0
- package/dist/index.cjs +454 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +219 -2
- package/dist/index.d.ts +219 -2
- package/dist/index.js +426 -50
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -679,6 +679,15 @@ var AgentClient = class {
|
|
|
679
679
|
const query = threadId === void 0 ? "" : `?threadId=${encodeURIComponent(threadId)}`;
|
|
680
680
|
return this.request("GET", `/agent/skills${query}`);
|
|
681
681
|
}
|
|
682
|
+
/**
|
|
683
|
+
* The tools this caller can reach through `agent` (the default agent when omitted), each with the
|
|
684
|
+
* server-declared `presentation` a chat narrates it by — the same list the model is offered.
|
|
685
|
+
* Prefer {@link useToolCatalog}, which fetches it once and shares it.
|
|
686
|
+
*/
|
|
687
|
+
listTools(agent) {
|
|
688
|
+
const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
|
|
689
|
+
return this.request("GET", `/agent/tools${query}`);
|
|
690
|
+
}
|
|
682
691
|
getThread(id) {
|
|
683
692
|
return this.request("GET", `/agent/threads/${encodeURIComponent(id)}`);
|
|
684
693
|
}
|
|
@@ -961,7 +970,280 @@ import React3 from "react";
|
|
|
961
970
|
import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "react";
|
|
962
971
|
|
|
963
972
|
// src/transcript/model.ts
|
|
964
|
-
import { getToolName, isDataUIPart, isFileUIPart, isReasoningUIPart, isTextUIPart, isToolUIPart } from "ai";
|
|
973
|
+
import { getToolName as getToolName2, isDataUIPart, isFileUIPart, isReasoningUIPart, isTextUIPart, isToolUIPart } from "ai";
|
|
974
|
+
|
|
975
|
+
// src/presentation/tool-activity.ts
|
|
976
|
+
import { getToolName } from "ai";
|
|
977
|
+
|
|
978
|
+
// src/presentation/phrasing.ts
|
|
979
|
+
function toolCatalogFrom(entries) {
|
|
980
|
+
const catalog = {};
|
|
981
|
+
for (const entry of entries) {
|
|
982
|
+
if (entry.presentation !== void 0) catalog[entry.name] = entry.presentation;
|
|
983
|
+
}
|
|
984
|
+
return catalog;
|
|
985
|
+
}
|
|
986
|
+
__name(toolCatalogFrom, "toolCatalogFrom");
|
|
987
|
+
function readPath(value, path) {
|
|
988
|
+
return path.split(".").reduce((current, key) => {
|
|
989
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
990
|
+
return current[key];
|
|
991
|
+
}, value);
|
|
992
|
+
}
|
|
993
|
+
__name(readPath, "readPath");
|
|
994
|
+
function renderValue(value) {
|
|
995
|
+
if (value === null || value === void 0) return "";
|
|
996
|
+
if (typeof value === "string") return value;
|
|
997
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
998
|
+
if (Array.isArray(value)) return value.map(renderValue).filter(Boolean).join(", ");
|
|
999
|
+
return "";
|
|
1000
|
+
}
|
|
1001
|
+
__name(renderValue, "renderValue");
|
|
1002
|
+
function fillTemplate(template, context) {
|
|
1003
|
+
return template.replace(/(\s*)\{([\w.]+)\}/g, (_match, space, path) => {
|
|
1004
|
+
const rendered = renderValue(readPath(context, path));
|
|
1005
|
+
return rendered === "" ? "" : `${space}${rendered}`;
|
|
1006
|
+
}).replace(/\s{2,}/g, " ").trim();
|
|
1007
|
+
}
|
|
1008
|
+
__name(fillTemplate, "fillTemplate");
|
|
1009
|
+
function phraseFor(presentation, input, isSettled2, fallback = {
|
|
1010
|
+
running: "Working",
|
|
1011
|
+
done: "Done"
|
|
1012
|
+
}) {
|
|
1013
|
+
if (presentation === void 0) return isSettled2 ? fallback.done : fallback.running;
|
|
1014
|
+
const filled = fillTemplate(isSettled2 ? presentation.done : presentation.running, input);
|
|
1015
|
+
return filled === "" ? presentation.label : filled;
|
|
1016
|
+
}
|
|
1017
|
+
__name(phraseFor, "phraseFor");
|
|
1018
|
+
|
|
1019
|
+
// src/presentation/result-view.ts
|
|
1020
|
+
function isRecord(value) {
|
|
1021
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1022
|
+
}
|
|
1023
|
+
__name(isRecord, "isRecord");
|
|
1024
|
+
function toText(value) {
|
|
1025
|
+
if (value === null || value === void 0) return "\u2014";
|
|
1026
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1027
|
+
return String(value);
|
|
1028
|
+
}
|
|
1029
|
+
if (Array.isArray(value)) return value.map(toText).join(", ");
|
|
1030
|
+
return "\u2014";
|
|
1031
|
+
}
|
|
1032
|
+
__name(toText, "toText");
|
|
1033
|
+
function inferResultView(output) {
|
|
1034
|
+
if (!isRecord(output)) return void 0;
|
|
1035
|
+
for (const [key, value] of Object.entries(output)) {
|
|
1036
|
+
if (!Array.isArray(value) || value.length === 0) continue;
|
|
1037
|
+
if (value.every((entry) => typeof entry === "string")) {
|
|
1038
|
+
return {
|
|
1039
|
+
kind: "log",
|
|
1040
|
+
lines: key
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
if (value.every(isRecord)) {
|
|
1044
|
+
const first = value[0];
|
|
1045
|
+
return {
|
|
1046
|
+
kind: "table",
|
|
1047
|
+
rows: key,
|
|
1048
|
+
columns: Object.keys(first).filter((column) => !isRecord(first[column])).map((column) => ({
|
|
1049
|
+
path: column,
|
|
1050
|
+
label: column
|
|
1051
|
+
}))
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
const fields = Object.entries(output).filter(([, value]) => [
|
|
1056
|
+
"string",
|
|
1057
|
+
"number",
|
|
1058
|
+
"boolean"
|
|
1059
|
+
].includes(typeof value)).map(([key]) => ({
|
|
1060
|
+
path: key,
|
|
1061
|
+
label: key
|
|
1062
|
+
}));
|
|
1063
|
+
return fields.length > 0 ? {
|
|
1064
|
+
kind: "metrics",
|
|
1065
|
+
fields
|
|
1066
|
+
} : void 0;
|
|
1067
|
+
}
|
|
1068
|
+
__name(inferResultView, "inferResultView");
|
|
1069
|
+
function resolveResultView(output, view, options = {}) {
|
|
1070
|
+
const resolved = view ?? (options.infer === true ? inferResultView(output) : void 0);
|
|
1071
|
+
if (resolved === void 0 || resolved.kind === "elsewhere") return null;
|
|
1072
|
+
switch (resolved.kind) {
|
|
1073
|
+
case "note": {
|
|
1074
|
+
const text = fillTemplate(resolved.text, output);
|
|
1075
|
+
return text === "" ? null : {
|
|
1076
|
+
kind: "note",
|
|
1077
|
+
text
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
case "metrics": {
|
|
1081
|
+
const readings = resolved.fields.map((field) => ({
|
|
1082
|
+
field,
|
|
1083
|
+
value: readPath(output, field.path)
|
|
1084
|
+
})).filter((entry) => entry.value !== void 0 && entry.value !== null).map(({ field, value }) => ({
|
|
1085
|
+
label: field.label,
|
|
1086
|
+
value: toText(value),
|
|
1087
|
+
unit: field.unit ?? null
|
|
1088
|
+
}));
|
|
1089
|
+
return readings.length === 0 ? null : {
|
|
1090
|
+
kind: "metrics",
|
|
1091
|
+
readings
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
case "log": {
|
|
1095
|
+
const lines = readPath(output, resolved.lines);
|
|
1096
|
+
if (!Array.isArray(lines) || lines.length === 0) return null;
|
|
1097
|
+
return {
|
|
1098
|
+
kind: "log",
|
|
1099
|
+
lines: lines.map(toText)
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
case "table": {
|
|
1103
|
+
const rows = readPath(output, resolved.rows);
|
|
1104
|
+
if (!Array.isArray(rows)) return null;
|
|
1105
|
+
return {
|
|
1106
|
+
kind: "table",
|
|
1107
|
+
columns: resolved.columns,
|
|
1108
|
+
rows: rows.map((row) => resolved.columns.map((column) => toText(readPath(row, column.path)))),
|
|
1109
|
+
empty: rows.length === 0 ? resolved.empty ?? null : null
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
__name(resolveResultView, "resolveResultView");
|
|
1115
|
+
|
|
1116
|
+
// src/presentation/tool-activity.ts
|
|
1117
|
+
function isActionCall(part) {
|
|
1118
|
+
const metadata = part.toolMetadata;
|
|
1119
|
+
return typeof metadata === "object" && metadata !== null && metadata.toolKind === "action";
|
|
1120
|
+
}
|
|
1121
|
+
__name(isActionCall, "isActionCall");
|
|
1122
|
+
function toolCallState(part) {
|
|
1123
|
+
const output = "output" in part ? part.output : void 0;
|
|
1124
|
+
const errorText = "errorText" in part ? part.errorText : void 0;
|
|
1125
|
+
const outputError = output !== null && typeof output === "object" && "error" in output ? String(output.error) : void 0;
|
|
1126
|
+
const isDenied = part.state === "output-denied";
|
|
1127
|
+
const isFailed = part.state === "output-error" || outputError !== void 0 && !isDenied;
|
|
1128
|
+
const isSettled2 = part.state === "output-available" || part.state === "output-error" || isDenied;
|
|
1129
|
+
const isAwaiting = part.state === "approval-requested" || part.state === "input-available" && isActionCall(part);
|
|
1130
|
+
const status = isDenied ? "denied" : isFailed ? "failed" : isSettled2 ? "done" : isAwaiting ? "awaiting-approval" : "running";
|
|
1131
|
+
return {
|
|
1132
|
+
status,
|
|
1133
|
+
isSettled: isSettled2,
|
|
1134
|
+
isFailed,
|
|
1135
|
+
isDenied,
|
|
1136
|
+
output,
|
|
1137
|
+
error: errorText ?? outputError ?? null
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
__name(toolCallState, "toolCallState");
|
|
1141
|
+
function correctedCallIds(parts) {
|
|
1142
|
+
const corrected = /* @__PURE__ */ new Set();
|
|
1143
|
+
const lastSuccessByTool = /* @__PURE__ */ new Map();
|
|
1144
|
+
parts.forEach((part, index) => {
|
|
1145
|
+
if (part.state === "output-available" && !toolCallState(part).isFailed) {
|
|
1146
|
+
lastSuccessByTool.set(getToolName(part), index);
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
parts.forEach((part, index) => {
|
|
1150
|
+
const successAt = lastSuccessByTool.get(getToolName(part));
|
|
1151
|
+
if (successAt !== void 0 && index < successAt && toolCallState(part).isFailed) {
|
|
1152
|
+
corrected.add(part.toolCallId);
|
|
1153
|
+
}
|
|
1154
|
+
});
|
|
1155
|
+
return corrected;
|
|
1156
|
+
}
|
|
1157
|
+
__name(correctedCallIds, "correctedCallIds");
|
|
1158
|
+
function describeToolCall(part, catalog, options = {}) {
|
|
1159
|
+
const presentation = catalog?.[getToolName(part)];
|
|
1160
|
+
const state = toolCallState(part);
|
|
1161
|
+
const input = part.input;
|
|
1162
|
+
const confirm = presentation?.confirm;
|
|
1163
|
+
return {
|
|
1164
|
+
status: state.status,
|
|
1165
|
+
phrase: phraseFor(presentation, input, state.isSettled, options.fallback),
|
|
1166
|
+
label: presentation?.label ?? null,
|
|
1167
|
+
icon: presentation?.icon ?? null,
|
|
1168
|
+
tone: presentation?.tone ?? "neutral",
|
|
1169
|
+
detail: presentation?.detail ?? null,
|
|
1170
|
+
confirm: confirm === void 0 ? null : {
|
|
1171
|
+
title: fillTemplate(confirm.title, input),
|
|
1172
|
+
verb: confirm.verb,
|
|
1173
|
+
detail: confirm.detail !== void 0 ? fillTemplate(confirm.detail, input) : null
|
|
1174
|
+
},
|
|
1175
|
+
result: state.status === "done" ? resolveResultView(state.output, presentation?.result, {
|
|
1176
|
+
...options.inferResult !== void 0 ? {
|
|
1177
|
+
infer: options.inferResult
|
|
1178
|
+
} : {}
|
|
1179
|
+
}) : null,
|
|
1180
|
+
error: state.error,
|
|
1181
|
+
presentation: presentation ?? null
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
__name(describeToolCall, "describeToolCall");
|
|
1185
|
+
var STATUS_WEIGHT = {
|
|
1186
|
+
running: 4,
|
|
1187
|
+
"awaiting-approval": 3,
|
|
1188
|
+
failed: 2,
|
|
1189
|
+
denied: 1,
|
|
1190
|
+
done: 0
|
|
1191
|
+
};
|
|
1192
|
+
function descendants(call) {
|
|
1193
|
+
return call.children.flatMap((child) => [
|
|
1194
|
+
child,
|
|
1195
|
+
...descendants(child)
|
|
1196
|
+
]);
|
|
1197
|
+
}
|
|
1198
|
+
__name(descendants, "descendants");
|
|
1199
|
+
function leaves(call) {
|
|
1200
|
+
return call.children.length === 0 ? [
|
|
1201
|
+
call
|
|
1202
|
+
] : call.children.flatMap(leaves);
|
|
1203
|
+
}
|
|
1204
|
+
__name(leaves, "leaves");
|
|
1205
|
+
function groupToolActivity(calls, options = {}) {
|
|
1206
|
+
const expanded = options.expandNested === true ? calls.flatMap(leaves) : [
|
|
1207
|
+
...calls
|
|
1208
|
+
];
|
|
1209
|
+
const corrected = options.hideCorrected === true ? correctedCallIds(expanded.map((call) => call.part)) : /* @__PURE__ */ new Set();
|
|
1210
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1211
|
+
for (const call of expanded) {
|
|
1212
|
+
if (corrected.has(call.toolCallId)) continue;
|
|
1213
|
+
const presentation = options.catalog?.[call.name];
|
|
1214
|
+
const key = options.keyOf?.(call, presentation) ?? presentation?.label ?? call.name;
|
|
1215
|
+
const status = toolCallState(call.part).status;
|
|
1216
|
+
const phrase = phraseFor(presentation, call.part.input, status !== "running" && status !== "awaiting-approval", options.fallback);
|
|
1217
|
+
const inner = options.expandNested === true ? 0 : descendants(call).length;
|
|
1218
|
+
const existing = groups.get(key);
|
|
1219
|
+
if (existing === void 0) {
|
|
1220
|
+
groups.set(key, {
|
|
1221
|
+
key,
|
|
1222
|
+
label: presentation?.label ?? null,
|
|
1223
|
+
icon: presentation?.icon ?? null,
|
|
1224
|
+
status,
|
|
1225
|
+
count: 1,
|
|
1226
|
+
phrase,
|
|
1227
|
+
calls: [
|
|
1228
|
+
call
|
|
1229
|
+
],
|
|
1230
|
+
innerCount: inner
|
|
1231
|
+
});
|
|
1232
|
+
continue;
|
|
1233
|
+
}
|
|
1234
|
+
existing.count += 1;
|
|
1235
|
+
existing.calls.push(call);
|
|
1236
|
+
existing.phrase = phrase;
|
|
1237
|
+
existing.innerCount += inner;
|
|
1238
|
+
if (STATUS_WEIGHT[status] > STATUS_WEIGHT[existing.status]) existing.status = status;
|
|
1239
|
+
}
|
|
1240
|
+
return [
|
|
1241
|
+
...groups.values()
|
|
1242
|
+
];
|
|
1243
|
+
}
|
|
1244
|
+
__name(groupToolActivity, "groupToolActivity");
|
|
1245
|
+
|
|
1246
|
+
// src/transcript/model.ts
|
|
965
1247
|
function buildTranscriptBlocks(message, options) {
|
|
966
1248
|
const blocks = [];
|
|
967
1249
|
let toolBuffer = [];
|
|
@@ -978,13 +1260,19 @@ function buildTranscriptBlocks(message, options) {
|
|
|
978
1260
|
if (toolBuffer.length === 0) {
|
|
979
1261
|
return;
|
|
980
1262
|
}
|
|
981
|
-
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId) ?? null));
|
|
1263
|
+
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId) ?? null, options.toolCatalog));
|
|
1264
|
+
const roots = nestToolCalls(calls);
|
|
982
1265
|
blocks.push({
|
|
983
1266
|
kind: "tools",
|
|
984
1267
|
key: `${message.id}-tools-${toolCounter++}`,
|
|
985
1268
|
parts: toolBuffer,
|
|
986
1269
|
calls,
|
|
987
|
-
roots
|
|
1270
|
+
roots,
|
|
1271
|
+
activity: groupToolActivity(roots, {
|
|
1272
|
+
...options.toolCatalog !== void 0 ? {
|
|
1273
|
+
catalog: options.toolCatalog
|
|
1274
|
+
} : {}
|
|
1275
|
+
})
|
|
988
1276
|
});
|
|
989
1277
|
toolBuffer = [];
|
|
990
1278
|
}
|
|
@@ -1133,7 +1421,7 @@ function isSettled(state) {
|
|
|
1133
1421
|
__name(isSettled, "isSettled");
|
|
1134
1422
|
function toolKind(part) {
|
|
1135
1423
|
const metadata = part.toolMetadata;
|
|
1136
|
-
return
|
|
1424
|
+
return isRecord2(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
|
|
1137
1425
|
}
|
|
1138
1426
|
__name(toolKind, "toolKind");
|
|
1139
1427
|
function isAwaitingApproval(part) {
|
|
@@ -1148,7 +1436,7 @@ function isAwaitingApproval(part) {
|
|
|
1148
1436
|
__name(isAwaitingApproval, "isAwaitingApproval");
|
|
1149
1437
|
function toolParentId(part) {
|
|
1150
1438
|
const metadata = part.toolMetadata;
|
|
1151
|
-
return
|
|
1439
|
+
return isRecord2(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
|
|
1152
1440
|
}
|
|
1153
1441
|
__name(toolParentId, "toolParentId");
|
|
1154
1442
|
function nestToolCalls(calls) {
|
|
@@ -1181,18 +1469,19 @@ function isAncestor(call, candidate, byId) {
|
|
|
1181
1469
|
return false;
|
|
1182
1470
|
}
|
|
1183
1471
|
__name(isAncestor, "isAncestor");
|
|
1184
|
-
function buildToolCall(part, options, approval) {
|
|
1472
|
+
function buildToolCall(part, options, approval, catalog) {
|
|
1185
1473
|
const toolCallId = part.toolCallId;
|
|
1186
1474
|
const awaiting = isAwaitingApproval(part);
|
|
1187
1475
|
const sending = awaiting ? options?.submitting(toolCallId) ?? null : null;
|
|
1188
1476
|
return {
|
|
1189
1477
|
part,
|
|
1190
1478
|
toolCallId,
|
|
1191
|
-
name:
|
|
1479
|
+
name: getToolName2(part),
|
|
1192
1480
|
toolKind: toolKind(part) ?? null,
|
|
1193
1481
|
parentId: toolParentId(part),
|
|
1194
1482
|
children: [],
|
|
1195
1483
|
approval,
|
|
1484
|
+
description: describeToolCall(part, catalog),
|
|
1196
1485
|
isAwaitingApproval: awaiting,
|
|
1197
1486
|
approve: {
|
|
1198
1487
|
available: awaiting && options?.canApprove === true,
|
|
@@ -1210,17 +1499,17 @@ function buildToolCall(part, options, approval) {
|
|
|
1210
1499
|
__name(buildToolCall, "buildToolCall");
|
|
1211
1500
|
function readElicitationRequest(part) {
|
|
1212
1501
|
const input = part.input;
|
|
1213
|
-
if (!
|
|
1502
|
+
if (!isRecord2(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
|
|
1214
1503
|
return null;
|
|
1215
1504
|
}
|
|
1216
1505
|
const questions = [];
|
|
1217
1506
|
for (const candidate of input.questions) {
|
|
1218
|
-
if (!
|
|
1507
|
+
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string" || !Array.isArray(candidate.options) || candidate.options.length === 0) {
|
|
1219
1508
|
return null;
|
|
1220
1509
|
}
|
|
1221
1510
|
const options = [];
|
|
1222
1511
|
for (const option of candidate.options) {
|
|
1223
|
-
if (!
|
|
1512
|
+
if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
|
|
1224
1513
|
return null;
|
|
1225
1514
|
}
|
|
1226
1515
|
options.push({
|
|
@@ -1245,7 +1534,7 @@ function readElicitationRequest(part) {
|
|
|
1245
1534
|
__name(readElicitationRequest, "readElicitationRequest");
|
|
1246
1535
|
function readElicitationOutcome(part) {
|
|
1247
1536
|
const output = part.output;
|
|
1248
|
-
if (!
|
|
1537
|
+
if (!isRecord2(output) || !isRecord2(output.answers) || typeof output.skipped !== "boolean") {
|
|
1249
1538
|
return null;
|
|
1250
1539
|
}
|
|
1251
1540
|
const answers = {};
|
|
@@ -1332,7 +1621,7 @@ function readApprovals(parts) {
|
|
|
1332
1621
|
continue;
|
|
1333
1622
|
}
|
|
1334
1623
|
const data = part.data;
|
|
1335
|
-
if (!
|
|
1624
|
+
if (!isRecord2(data) || typeof data.id !== "string" || typeof data.approver !== "string") {
|
|
1336
1625
|
continue;
|
|
1337
1626
|
}
|
|
1338
1627
|
out.set(data.id, {
|
|
@@ -1346,7 +1635,7 @@ function readApprovals(parts) {
|
|
|
1346
1635
|
__name(readApprovals, "readApprovals");
|
|
1347
1636
|
function readUiComponent(part) {
|
|
1348
1637
|
const data = part.data;
|
|
1349
|
-
if (!
|
|
1638
|
+
if (!isRecord2(data) || typeof data.component !== "string") {
|
|
1350
1639
|
return null;
|
|
1351
1640
|
}
|
|
1352
1641
|
const id = typeof data.id === "string" ? data.id : part.id;
|
|
@@ -1356,18 +1645,18 @@ function readUiComponent(part) {
|
|
|
1356
1645
|
return {
|
|
1357
1646
|
id,
|
|
1358
1647
|
component: data.component,
|
|
1359
|
-
props:
|
|
1648
|
+
props: isRecord2(data.props) ? data.props : {},
|
|
1360
1649
|
version: typeof data.version === "number" ? data.version : null
|
|
1361
1650
|
};
|
|
1362
1651
|
}
|
|
1363
1652
|
__name(readUiComponent, "readUiComponent");
|
|
1364
|
-
function
|
|
1653
|
+
function isRecord2(value) {
|
|
1365
1654
|
return typeof value === "object" && value !== null;
|
|
1366
1655
|
}
|
|
1367
|
-
__name(
|
|
1656
|
+
__name(isRecord2, "isRecord");
|
|
1368
1657
|
function readQuery(part) {
|
|
1369
1658
|
const input = part.input;
|
|
1370
|
-
if (!
|
|
1659
|
+
if (!isRecord2(input) || typeof input.query !== "string") {
|
|
1371
1660
|
return null;
|
|
1372
1661
|
}
|
|
1373
1662
|
return input.query;
|
|
@@ -1375,12 +1664,12 @@ function readQuery(part) {
|
|
|
1375
1664
|
__name(readQuery, "readQuery");
|
|
1376
1665
|
function readPassages(part) {
|
|
1377
1666
|
const output = part.output;
|
|
1378
|
-
if (!
|
|
1667
|
+
if (!isRecord2(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
|
|
1379
1668
|
return null;
|
|
1380
1669
|
}
|
|
1381
1670
|
const passages = [];
|
|
1382
1671
|
for (const candidate of output.passages) {
|
|
1383
|
-
if (!
|
|
1672
|
+
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
|
|
1384
1673
|
return null;
|
|
1385
1674
|
}
|
|
1386
1675
|
passages.push({
|
|
@@ -1390,7 +1679,7 @@ function readPassages(part) {
|
|
|
1390
1679
|
...typeof candidate.source === "string" ? {
|
|
1391
1680
|
source: candidate.source
|
|
1392
1681
|
} : {},
|
|
1393
|
-
...
|
|
1682
|
+
...isRecord2(candidate.metadata) ? {
|
|
1394
1683
|
metadata: candidate.metadata
|
|
1395
1684
|
} : {}
|
|
1396
1685
|
});
|
|
@@ -1857,6 +2146,9 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1857
2146
|
...options.sources !== void 0 ? {
|
|
1858
2147
|
sources: options.sources
|
|
1859
2148
|
} : {},
|
|
2149
|
+
...options.toolCatalog !== void 0 ? {
|
|
2150
|
+
toolCatalog: options.toolCatalog
|
|
2151
|
+
} : {},
|
|
1860
2152
|
...options.onAnswer !== void 0 ? {
|
|
1861
2153
|
elicitation: {
|
|
1862
2154
|
picked: /* @__PURE__ */ __name((toolCallId, questionId) => picks.get(pickKey(toolCallId, questionId)), "picked"),
|
|
@@ -2632,6 +2924,78 @@ function isPromise(value) {
|
|
|
2632
2924
|
}
|
|
2633
2925
|
__name(isPromise, "isPromise");
|
|
2634
2926
|
|
|
2927
|
+
// src/presentation/use-tool-catalog.ts
|
|
2928
|
+
import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo3, useState as useState7 } from "react";
|
|
2929
|
+
var shared = /* @__PURE__ */ new WeakMap();
|
|
2930
|
+
function load(client, agent) {
|
|
2931
|
+
let byAgent = shared.get(client);
|
|
2932
|
+
if (byAgent === void 0) {
|
|
2933
|
+
byAgent = /* @__PURE__ */ new Map();
|
|
2934
|
+
shared.set(client, byAgent);
|
|
2935
|
+
}
|
|
2936
|
+
const key = agent ?? "";
|
|
2937
|
+
const cached = byAgent.get(key);
|
|
2938
|
+
if (cached !== void 0) return cached;
|
|
2939
|
+
const request = client.listTools(agent).catch((error) => {
|
|
2940
|
+
byAgent.delete(key);
|
|
2941
|
+
throw error;
|
|
2942
|
+
});
|
|
2943
|
+
byAgent.set(key, request);
|
|
2944
|
+
return request;
|
|
2945
|
+
}
|
|
2946
|
+
__name(load, "load");
|
|
2947
|
+
function useToolCatalog(options) {
|
|
2948
|
+
const { client, agent, enabled = true } = options;
|
|
2949
|
+
const [entries, setEntries] = useState7([]);
|
|
2950
|
+
const [isLoading, setLoading] = useState7(enabled);
|
|
2951
|
+
const [error, setError] = useState7(null);
|
|
2952
|
+
const [generation, setGeneration] = useState7(0);
|
|
2953
|
+
useEffect7(() => {
|
|
2954
|
+
if (!enabled) {
|
|
2955
|
+
setLoading(false);
|
|
2956
|
+
return;
|
|
2957
|
+
}
|
|
2958
|
+
let cancelled = false;
|
|
2959
|
+
setLoading(true);
|
|
2960
|
+
load(client, agent).then((loaded) => {
|
|
2961
|
+
if (cancelled) return;
|
|
2962
|
+
setEntries(loaded);
|
|
2963
|
+
setError(null);
|
|
2964
|
+
setLoading(false);
|
|
2965
|
+
}, (failure) => {
|
|
2966
|
+
if (cancelled) return;
|
|
2967
|
+
setError(failure instanceof Error ? failure : new Error(String(failure)));
|
|
2968
|
+
setLoading(false);
|
|
2969
|
+
});
|
|
2970
|
+
return () => {
|
|
2971
|
+
cancelled = true;
|
|
2972
|
+
};
|
|
2973
|
+
}, [
|
|
2974
|
+
client,
|
|
2975
|
+
agent,
|
|
2976
|
+
enabled,
|
|
2977
|
+
generation
|
|
2978
|
+
]);
|
|
2979
|
+
const refresh = useCallback5(() => {
|
|
2980
|
+
shared.get(client)?.delete(agent ?? "");
|
|
2981
|
+
setGeneration((current) => current + 1);
|
|
2982
|
+
}, [
|
|
2983
|
+
client,
|
|
2984
|
+
agent
|
|
2985
|
+
]);
|
|
2986
|
+
const catalog = useMemo3(() => toolCatalogFrom(entries), [
|
|
2987
|
+
entries
|
|
2988
|
+
]);
|
|
2989
|
+
return {
|
|
2990
|
+
catalog,
|
|
2991
|
+
entries,
|
|
2992
|
+
isLoading,
|
|
2993
|
+
error,
|
|
2994
|
+
refresh
|
|
2995
|
+
};
|
|
2996
|
+
}
|
|
2997
|
+
__name(useToolCatalog, "useToolCatalog");
|
|
2998
|
+
|
|
2635
2999
|
// src/stored-message-to-ui-message.ts
|
|
2636
3000
|
import { DEFAULT_REFUSAL_REASON } from "@dudousxd/nestjs-agent-core";
|
|
2637
3001
|
function isRefusal(result) {
|
|
@@ -2793,20 +3157,20 @@ __name(sumUsage, "sumUsage");
|
|
|
2793
3157
|
|
|
2794
3158
|
// src/use-agent-chat.ts
|
|
2795
3159
|
import { useChat } from "@ai-sdk/react";
|
|
2796
|
-
import { useCallback as
|
|
3160
|
+
import { useCallback as useCallback6, useEffect as useEffect8, useMemo as useMemo4, useRef as useRef6, useState as useState8 } from "react";
|
|
2797
3161
|
function useAgentChat(options) {
|
|
2798
3162
|
const latest = useRef6(options);
|
|
2799
3163
|
latest.current = options;
|
|
2800
|
-
const [runId, setRunId] =
|
|
3164
|
+
const [runId, setRunId] = useState8(options.resumeRunId);
|
|
2801
3165
|
const runIdRef = useRef6(runId);
|
|
2802
3166
|
runIdRef.current = runId;
|
|
2803
3167
|
const settlingRunIdRef = useRef6(void 0);
|
|
2804
3168
|
const autoResumeRunIdRef = useRef6(void 0);
|
|
2805
|
-
const [autoResume, setAutoResume] =
|
|
2806
|
-
const [activeRunId, setActiveRunId] =
|
|
3169
|
+
const [autoResume, setAutoResume] = useState8(false);
|
|
3170
|
+
const [activeRunId, setActiveRunId] = useState8(null);
|
|
2807
3171
|
const regenerateNext = useRef6(false);
|
|
2808
3172
|
const createdThreadId = useRef6(void 0);
|
|
2809
|
-
const client =
|
|
3173
|
+
const client = useMemo4(() => {
|
|
2810
3174
|
if (options.client) return options.client;
|
|
2811
3175
|
return new AgentClient({
|
|
2812
3176
|
...options.baseUrl !== void 0 ? {
|
|
@@ -2821,7 +3185,7 @@ function useAgentChat(options) {
|
|
|
2821
3185
|
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
2822
3186
|
});
|
|
2823
3187
|
}, []);
|
|
2824
|
-
|
|
3188
|
+
useEffect8(() => {
|
|
2825
3189
|
if (!options.resume || options.threadId === void 0) return;
|
|
2826
3190
|
let cancelled = false;
|
|
2827
3191
|
const threadId = options.threadId;
|
|
@@ -2841,7 +3205,7 @@ function useAgentChat(options) {
|
|
|
2841
3205
|
options.resume,
|
|
2842
3206
|
options.threadId
|
|
2843
3207
|
]);
|
|
2844
|
-
const transport =
|
|
3208
|
+
const transport = useMemo4(() => {
|
|
2845
3209
|
function onMeta(meta) {
|
|
2846
3210
|
settlingRunIdRef.current = meta.runId;
|
|
2847
3211
|
setRunId(meta.runId);
|
|
@@ -2924,10 +3288,10 @@ function useAgentChat(options) {
|
|
|
2924
3288
|
const chatRef = useRef6(chat);
|
|
2925
3289
|
chatRef.current = chat;
|
|
2926
3290
|
const turnInFlight = useRef6(false);
|
|
2927
|
-
const isTurnInFlight =
|
|
3291
|
+
const isTurnInFlight = useCallback6(() => turnInFlight.current || transport.isAttemptLive, [
|
|
2928
3292
|
transport
|
|
2929
3293
|
]);
|
|
2930
|
-
const sendMessage =
|
|
3294
|
+
const sendMessage = useCallback6(async (...args) => {
|
|
2931
3295
|
if (isTurnInFlight()) return;
|
|
2932
3296
|
turnInFlight.current = true;
|
|
2933
3297
|
try {
|
|
@@ -2938,15 +3302,15 @@ function useAgentChat(options) {
|
|
|
2938
3302
|
}, [
|
|
2939
3303
|
isTurnInFlight
|
|
2940
3304
|
]);
|
|
2941
|
-
const addToolResult =
|
|
3305
|
+
const addToolResult = useCallback6(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
|
|
2942
3306
|
tool,
|
|
2943
3307
|
toolCallId,
|
|
2944
3308
|
output
|
|
2945
3309
|
}), []);
|
|
2946
|
-
const [threads, setThreads] =
|
|
2947
|
-
const [quota, setQuota] =
|
|
2948
|
-
const [backgroundRuns, setBackgroundRuns] =
|
|
2949
|
-
const refreshBackground =
|
|
3310
|
+
const [threads, setThreads] = useState8([]);
|
|
3311
|
+
const [quota, setQuota] = useState8(null);
|
|
3312
|
+
const [backgroundRuns, setBackgroundRuns] = useState8([]);
|
|
3313
|
+
const refreshBackground = useCallback6(async () => {
|
|
2950
3314
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
2951
3315
|
if (threadId === void 0) {
|
|
2952
3316
|
return;
|
|
@@ -2971,7 +3335,7 @@ function useAgentChat(options) {
|
|
|
2971
3335
|
]);
|
|
2972
3336
|
backgroundRef.current = refreshBackground;
|
|
2973
3337
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
2974
|
-
|
|
3338
|
+
useEffect8(() => {
|
|
2975
3339
|
if (options.background !== true || options.threadId === void 0) {
|
|
2976
3340
|
return;
|
|
2977
3341
|
}
|
|
@@ -2981,7 +3345,7 @@ function useAgentChat(options) {
|
|
|
2981
3345
|
options.threadId,
|
|
2982
3346
|
refreshBackground
|
|
2983
3347
|
]);
|
|
2984
|
-
|
|
3348
|
+
useEffect8(() => {
|
|
2985
3349
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
2986
3350
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
2987
3351
|
return;
|
|
@@ -2992,26 +3356,26 @@ function useAgentChat(options) {
|
|
|
2992
3356
|
isWorking,
|
|
2993
3357
|
refreshBackground
|
|
2994
3358
|
]);
|
|
2995
|
-
const loadThreads =
|
|
3359
|
+
const loadThreads = useCallback6(async () => {
|
|
2996
3360
|
const list = await client.listThreads();
|
|
2997
3361
|
setThreads(list);
|
|
2998
3362
|
return list;
|
|
2999
3363
|
}, [
|
|
3000
3364
|
client
|
|
3001
3365
|
]);
|
|
3002
|
-
const loadThread =
|
|
3366
|
+
const loadThread = useCallback6((id) => client.getThread(id), [
|
|
3003
3367
|
client
|
|
3004
3368
|
]);
|
|
3005
|
-
const deleteThread =
|
|
3369
|
+
const deleteThread = useCallback6(async (id) => {
|
|
3006
3370
|
await client.deleteThread(id);
|
|
3007
3371
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
3008
3372
|
}, [
|
|
3009
3373
|
client
|
|
3010
3374
|
]);
|
|
3011
|
-
const forkThread =
|
|
3375
|
+
const forkThread = useCallback6((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
|
|
3012
3376
|
client
|
|
3013
3377
|
]);
|
|
3014
|
-
const renameThread =
|
|
3378
|
+
const renameThread = useCallback6(async (id, title) => {
|
|
3015
3379
|
await client.renameThread(id, title);
|
|
3016
3380
|
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
3017
3381
|
...thread,
|
|
@@ -3020,24 +3384,24 @@ function useAgentChat(options) {
|
|
|
3020
3384
|
}, [
|
|
3021
3385
|
client
|
|
3022
3386
|
]);
|
|
3023
|
-
const promoteThread =
|
|
3387
|
+
const promoteThread = useCallback6(async (id) => {
|
|
3024
3388
|
await client.promoteThread(id);
|
|
3025
3389
|
await loadThreads();
|
|
3026
3390
|
}, [
|
|
3027
3391
|
client,
|
|
3028
3392
|
loadThreads
|
|
3029
3393
|
]);
|
|
3030
|
-
const truncateFromMessage =
|
|
3394
|
+
const truncateFromMessage = useCallback6((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
|
|
3031
3395
|
client
|
|
3032
3396
|
]);
|
|
3033
|
-
const loadQuota =
|
|
3397
|
+
const loadQuota = useCallback6(async () => {
|
|
3034
3398
|
const today = await client.getQuotaToday();
|
|
3035
3399
|
setQuota(today);
|
|
3036
3400
|
return today;
|
|
3037
3401
|
}, [
|
|
3038
3402
|
client
|
|
3039
3403
|
]);
|
|
3040
|
-
const cancel =
|
|
3404
|
+
const cancel = useCallback6(async () => {
|
|
3041
3405
|
chatRef.current.stop();
|
|
3042
3406
|
const activeRunId2 = runIdRef.current;
|
|
3043
3407
|
if (activeRunId2) {
|
|
@@ -3049,14 +3413,14 @@ function useAgentChat(options) {
|
|
|
3049
3413
|
}, [
|
|
3050
3414
|
client
|
|
3051
3415
|
]);
|
|
3052
|
-
const approve =
|
|
3416
|
+
const approve = useCallback6(async ({ toolCallId }) => {
|
|
3053
3417
|
await client.approveToolCall({
|
|
3054
3418
|
toolCallId
|
|
3055
3419
|
});
|
|
3056
3420
|
}, [
|
|
3057
3421
|
client
|
|
3058
3422
|
]);
|
|
3059
|
-
const reject =
|
|
3423
|
+
const reject = useCallback6(async ({ toolCallId, reason }) => {
|
|
3060
3424
|
await client.rejectToolCall({
|
|
3061
3425
|
toolCallId,
|
|
3062
3426
|
...reason !== void 0 ? {
|
|
@@ -3066,7 +3430,7 @@ function useAgentChat(options) {
|
|
|
3066
3430
|
}, [
|
|
3067
3431
|
client
|
|
3068
3432
|
]);
|
|
3069
|
-
const answer =
|
|
3433
|
+
const answer = useCallback6(async ({ toolCallId, answers }) => {
|
|
3070
3434
|
await client.answerToolCall({
|
|
3071
3435
|
toolCallId,
|
|
3072
3436
|
...answers !== void 0 ? {
|
|
@@ -3076,14 +3440,14 @@ function useAgentChat(options) {
|
|
|
3076
3440
|
}, [
|
|
3077
3441
|
client
|
|
3078
3442
|
]);
|
|
3079
|
-
const skip =
|
|
3443
|
+
const skip = useCallback6(async ({ toolCallId }) => {
|
|
3080
3444
|
await client.skipToolCall({
|
|
3081
3445
|
toolCallId
|
|
3082
3446
|
});
|
|
3083
3447
|
}, [
|
|
3084
3448
|
client
|
|
3085
3449
|
]);
|
|
3086
|
-
const regenerate =
|
|
3450
|
+
const regenerate = useCallback6(() => {
|
|
3087
3451
|
if (isTurnInFlight()) return;
|
|
3088
3452
|
regenerateNext.current = true;
|
|
3089
3453
|
turnInFlight.current = true;
|
|
@@ -3148,25 +3512,37 @@ export {
|
|
|
3148
3512
|
applyCompletion,
|
|
3149
3513
|
backgroundRunsFromThread,
|
|
3150
3514
|
buildTranscriptBlocks,
|
|
3515
|
+
correctedCallIds,
|
|
3151
3516
|
createSkillsSource,
|
|
3152
3517
|
describeTimestamp,
|
|
3518
|
+
describeToolCall,
|
|
3153
3519
|
describeUsage,
|
|
3154
3520
|
extractMessageText,
|
|
3521
|
+
fillTemplate,
|
|
3155
3522
|
filterAutocompleteItems,
|
|
3156
3523
|
findActiveTrigger,
|
|
3157
3524
|
formatElapsed,
|
|
3158
3525
|
formatRelativeTime,
|
|
3526
|
+
groupToolActivity,
|
|
3527
|
+
inferResultView,
|
|
3528
|
+
isActionCall,
|
|
3159
3529
|
loadStoredSpeechLang,
|
|
3160
3530
|
persistSpeechLang,
|
|
3531
|
+
phraseFor,
|
|
3532
|
+
readPath,
|
|
3161
3533
|
readReasoningMs,
|
|
3534
|
+
resolveResultView,
|
|
3162
3535
|
storedMessageToUiMessage,
|
|
3163
3536
|
storedThreadToUiMessages,
|
|
3537
|
+
toolCallState,
|
|
3538
|
+
toolCatalogFrom,
|
|
3164
3539
|
useAgentChat,
|
|
3165
3540
|
useChatTranscript,
|
|
3166
3541
|
useComposerAutocomplete,
|
|
3167
3542
|
useElapsed,
|
|
3168
3543
|
useSpeechRecognition,
|
|
3169
3544
|
useStickToBottom,
|
|
3545
|
+
useToolCatalog,
|
|
3170
3546
|
useTranscriptItem
|
|
3171
3547
|
};
|
|
3172
3548
|
//# sourceMappingURL=index.js.map
|