@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.js
CHANGED
|
@@ -444,6 +444,10 @@ var AgentChatTransport = class {
|
|
|
444
444
|
});
|
|
445
445
|
}
|
|
446
446
|
break;
|
|
447
|
+
case "approval-settled":
|
|
448
|
+
ensureStep();
|
|
449
|
+
forwardAsData(event, false);
|
|
450
|
+
break;
|
|
447
451
|
case "ui":
|
|
448
452
|
ensureStep();
|
|
449
453
|
closeRuns();
|
|
@@ -679,6 +683,15 @@ var AgentClient = class {
|
|
|
679
683
|
const query = threadId === void 0 ? "" : `?threadId=${encodeURIComponent(threadId)}`;
|
|
680
684
|
return this.request("GET", `/agent/skills${query}`);
|
|
681
685
|
}
|
|
686
|
+
/**
|
|
687
|
+
* The tools this caller can reach through `agent` (the default agent when omitted), each with the
|
|
688
|
+
* server-declared `presentation` a chat narrates it by — the same list the model is offered.
|
|
689
|
+
* Prefer {@link useToolCatalog}, which fetches it once and shares it.
|
|
690
|
+
*/
|
|
691
|
+
listTools(agent) {
|
|
692
|
+
const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
|
|
693
|
+
return this.request("GET", `/agent/tools${query}`);
|
|
694
|
+
}
|
|
682
695
|
getThread(id) {
|
|
683
696
|
return this.request("GET", `/agent/threads/${encodeURIComponent(id)}`);
|
|
684
697
|
}
|
|
@@ -734,6 +747,10 @@ var AgentClient = class {
|
|
|
734
747
|
cancelStream(runId) {
|
|
735
748
|
return this.request("POST", `/agent/chat/${encodeURIComponent(runId)}/cancel`);
|
|
736
749
|
}
|
|
750
|
+
/**
|
|
751
|
+
* `remember` approves later calls of the same tool in the same thread; `via` names the surface
|
|
752
|
+
* the decision came through (the server records `'web'` when omitted).
|
|
753
|
+
*/
|
|
737
754
|
approveToolCall(input) {
|
|
738
755
|
return this.request("POST", "/agent/tool-call/approve", input);
|
|
739
756
|
}
|
|
@@ -961,7 +978,280 @@ import React3 from "react";
|
|
|
961
978
|
import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "react";
|
|
962
979
|
|
|
963
980
|
// src/transcript/model.ts
|
|
964
|
-
import { getToolName, isDataUIPart, isFileUIPart, isReasoningUIPart, isTextUIPart, isToolUIPart } from "ai";
|
|
981
|
+
import { getToolName as getToolName2, isDataUIPart, isFileUIPart, isReasoningUIPart, isTextUIPart, isToolUIPart } from "ai";
|
|
982
|
+
|
|
983
|
+
// src/presentation/tool-activity.ts
|
|
984
|
+
import { getToolName } from "ai";
|
|
985
|
+
|
|
986
|
+
// src/presentation/phrasing.ts
|
|
987
|
+
function toolCatalogFrom(entries) {
|
|
988
|
+
const catalog = {};
|
|
989
|
+
for (const entry of entries) {
|
|
990
|
+
if (entry.presentation !== void 0) catalog[entry.name] = entry.presentation;
|
|
991
|
+
}
|
|
992
|
+
return catalog;
|
|
993
|
+
}
|
|
994
|
+
__name(toolCatalogFrom, "toolCatalogFrom");
|
|
995
|
+
function readPath(value, path) {
|
|
996
|
+
return path.split(".").reduce((current, key) => {
|
|
997
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
998
|
+
return current[key];
|
|
999
|
+
}, value);
|
|
1000
|
+
}
|
|
1001
|
+
__name(readPath, "readPath");
|
|
1002
|
+
function renderValue(value) {
|
|
1003
|
+
if (value === null || value === void 0) return "";
|
|
1004
|
+
if (typeof value === "string") return value;
|
|
1005
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
1006
|
+
if (Array.isArray(value)) return value.map(renderValue).filter(Boolean).join(", ");
|
|
1007
|
+
return "";
|
|
1008
|
+
}
|
|
1009
|
+
__name(renderValue, "renderValue");
|
|
1010
|
+
function fillTemplate(template, context) {
|
|
1011
|
+
return template.replace(/(\s*)\{([\w.]+)\}/g, (_match, space, path) => {
|
|
1012
|
+
const rendered = renderValue(readPath(context, path));
|
|
1013
|
+
return rendered === "" ? "" : `${space}${rendered}`;
|
|
1014
|
+
}).replace(/\s{2,}/g, " ").trim();
|
|
1015
|
+
}
|
|
1016
|
+
__name(fillTemplate, "fillTemplate");
|
|
1017
|
+
function phraseFor(presentation, input, isSettled2, fallback = {
|
|
1018
|
+
running: "Working",
|
|
1019
|
+
done: "Done"
|
|
1020
|
+
}) {
|
|
1021
|
+
if (presentation === void 0) return isSettled2 ? fallback.done : fallback.running;
|
|
1022
|
+
const filled = fillTemplate(isSettled2 ? presentation.done : presentation.running, input);
|
|
1023
|
+
return filled === "" ? presentation.label : filled;
|
|
1024
|
+
}
|
|
1025
|
+
__name(phraseFor, "phraseFor");
|
|
1026
|
+
|
|
1027
|
+
// src/presentation/result-view.ts
|
|
1028
|
+
function isRecord(value) {
|
|
1029
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1030
|
+
}
|
|
1031
|
+
__name(isRecord, "isRecord");
|
|
1032
|
+
function toText(value) {
|
|
1033
|
+
if (value === null || value === void 0) return "\u2014";
|
|
1034
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1035
|
+
return String(value);
|
|
1036
|
+
}
|
|
1037
|
+
if (Array.isArray(value)) return value.map(toText).join(", ");
|
|
1038
|
+
return "\u2014";
|
|
1039
|
+
}
|
|
1040
|
+
__name(toText, "toText");
|
|
1041
|
+
function inferResultView(output) {
|
|
1042
|
+
if (!isRecord(output)) return void 0;
|
|
1043
|
+
for (const [key, value] of Object.entries(output)) {
|
|
1044
|
+
if (!Array.isArray(value) || value.length === 0) continue;
|
|
1045
|
+
if (value.every((entry) => typeof entry === "string")) {
|
|
1046
|
+
return {
|
|
1047
|
+
kind: "log",
|
|
1048
|
+
lines: key
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
if (value.every(isRecord)) {
|
|
1052
|
+
const first = value[0];
|
|
1053
|
+
return {
|
|
1054
|
+
kind: "table",
|
|
1055
|
+
rows: key,
|
|
1056
|
+
columns: Object.keys(first).filter((column) => !isRecord(first[column])).map((column) => ({
|
|
1057
|
+
path: column,
|
|
1058
|
+
label: column
|
|
1059
|
+
}))
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
const fields = Object.entries(output).filter(([, value]) => [
|
|
1064
|
+
"string",
|
|
1065
|
+
"number",
|
|
1066
|
+
"boolean"
|
|
1067
|
+
].includes(typeof value)).map(([key]) => ({
|
|
1068
|
+
path: key,
|
|
1069
|
+
label: key
|
|
1070
|
+
}));
|
|
1071
|
+
return fields.length > 0 ? {
|
|
1072
|
+
kind: "metrics",
|
|
1073
|
+
fields
|
|
1074
|
+
} : void 0;
|
|
1075
|
+
}
|
|
1076
|
+
__name(inferResultView, "inferResultView");
|
|
1077
|
+
function resolveResultView(output, view, options = {}) {
|
|
1078
|
+
const resolved = view ?? (options.infer === true ? inferResultView(output) : void 0);
|
|
1079
|
+
if (resolved === void 0 || resolved.kind === "elsewhere") return null;
|
|
1080
|
+
switch (resolved.kind) {
|
|
1081
|
+
case "note": {
|
|
1082
|
+
const text = fillTemplate(resolved.text, output);
|
|
1083
|
+
return text === "" ? null : {
|
|
1084
|
+
kind: "note",
|
|
1085
|
+
text
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
case "metrics": {
|
|
1089
|
+
const readings = resolved.fields.map((field) => ({
|
|
1090
|
+
field,
|
|
1091
|
+
value: readPath(output, field.path)
|
|
1092
|
+
})).filter((entry) => entry.value !== void 0 && entry.value !== null).map(({ field, value }) => ({
|
|
1093
|
+
label: field.label,
|
|
1094
|
+
value: toText(value),
|
|
1095
|
+
unit: field.unit ?? null
|
|
1096
|
+
}));
|
|
1097
|
+
return readings.length === 0 ? null : {
|
|
1098
|
+
kind: "metrics",
|
|
1099
|
+
readings
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
case "log": {
|
|
1103
|
+
const lines = readPath(output, resolved.lines);
|
|
1104
|
+
if (!Array.isArray(lines) || lines.length === 0) return null;
|
|
1105
|
+
return {
|
|
1106
|
+
kind: "log",
|
|
1107
|
+
lines: lines.map(toText)
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
case "table": {
|
|
1111
|
+
const rows = readPath(output, resolved.rows);
|
|
1112
|
+
if (!Array.isArray(rows)) return null;
|
|
1113
|
+
return {
|
|
1114
|
+
kind: "table",
|
|
1115
|
+
columns: resolved.columns,
|
|
1116
|
+
rows: rows.map((row) => resolved.columns.map((column) => toText(readPath(row, column.path)))),
|
|
1117
|
+
empty: rows.length === 0 ? resolved.empty ?? null : null
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
__name(resolveResultView, "resolveResultView");
|
|
1123
|
+
|
|
1124
|
+
// src/presentation/tool-activity.ts
|
|
1125
|
+
function isActionCall(part) {
|
|
1126
|
+
const metadata = part.toolMetadata;
|
|
1127
|
+
return typeof metadata === "object" && metadata !== null && metadata.toolKind === "action";
|
|
1128
|
+
}
|
|
1129
|
+
__name(isActionCall, "isActionCall");
|
|
1130
|
+
function toolCallState(part) {
|
|
1131
|
+
const output = "output" in part ? part.output : void 0;
|
|
1132
|
+
const errorText = "errorText" in part ? part.errorText : void 0;
|
|
1133
|
+
const outputError = output !== null && typeof output === "object" && "error" in output ? String(output.error) : void 0;
|
|
1134
|
+
const isDenied = part.state === "output-denied";
|
|
1135
|
+
const isFailed = part.state === "output-error" || outputError !== void 0 && !isDenied;
|
|
1136
|
+
const isSettled2 = part.state === "output-available" || part.state === "output-error" || isDenied;
|
|
1137
|
+
const isAwaiting = part.state === "approval-requested" || part.state === "input-available" && isActionCall(part);
|
|
1138
|
+
const status = isDenied ? "denied" : isFailed ? "failed" : isSettled2 ? "done" : isAwaiting ? "awaiting-approval" : "running";
|
|
1139
|
+
return {
|
|
1140
|
+
status,
|
|
1141
|
+
isSettled: isSettled2,
|
|
1142
|
+
isFailed,
|
|
1143
|
+
isDenied,
|
|
1144
|
+
output,
|
|
1145
|
+
error: errorText ?? outputError ?? null
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
__name(toolCallState, "toolCallState");
|
|
1149
|
+
function correctedCallIds(parts) {
|
|
1150
|
+
const corrected = /* @__PURE__ */ new Set();
|
|
1151
|
+
const lastSuccessByTool = /* @__PURE__ */ new Map();
|
|
1152
|
+
parts.forEach((part, index) => {
|
|
1153
|
+
if (part.state === "output-available" && !toolCallState(part).isFailed) {
|
|
1154
|
+
lastSuccessByTool.set(getToolName(part), index);
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1157
|
+
parts.forEach((part, index) => {
|
|
1158
|
+
const successAt = lastSuccessByTool.get(getToolName(part));
|
|
1159
|
+
if (successAt !== void 0 && index < successAt && toolCallState(part).isFailed) {
|
|
1160
|
+
corrected.add(part.toolCallId);
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1163
|
+
return corrected;
|
|
1164
|
+
}
|
|
1165
|
+
__name(correctedCallIds, "correctedCallIds");
|
|
1166
|
+
function describeToolCall(part, catalog, options = {}) {
|
|
1167
|
+
const presentation = catalog?.[getToolName(part)];
|
|
1168
|
+
const state = toolCallState(part);
|
|
1169
|
+
const input = part.input;
|
|
1170
|
+
const confirm = presentation?.confirm;
|
|
1171
|
+
return {
|
|
1172
|
+
status: state.status,
|
|
1173
|
+
phrase: phraseFor(presentation, input, state.isSettled, options.fallback),
|
|
1174
|
+
label: presentation?.label ?? null,
|
|
1175
|
+
icon: presentation?.icon ?? null,
|
|
1176
|
+
tone: presentation?.tone ?? "neutral",
|
|
1177
|
+
detail: presentation?.detail ?? null,
|
|
1178
|
+
confirm: confirm === void 0 ? null : {
|
|
1179
|
+
title: fillTemplate(confirm.title, input),
|
|
1180
|
+
verb: confirm.verb,
|
|
1181
|
+
detail: confirm.detail !== void 0 ? fillTemplate(confirm.detail, input) : null
|
|
1182
|
+
},
|
|
1183
|
+
result: state.status === "done" ? resolveResultView(state.output, presentation?.result, {
|
|
1184
|
+
...options.inferResult !== void 0 ? {
|
|
1185
|
+
infer: options.inferResult
|
|
1186
|
+
} : {}
|
|
1187
|
+
}) : null,
|
|
1188
|
+
error: state.error,
|
|
1189
|
+
presentation: presentation ?? null
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
__name(describeToolCall, "describeToolCall");
|
|
1193
|
+
var STATUS_WEIGHT = {
|
|
1194
|
+
running: 4,
|
|
1195
|
+
"awaiting-approval": 3,
|
|
1196
|
+
failed: 2,
|
|
1197
|
+
denied: 1,
|
|
1198
|
+
done: 0
|
|
1199
|
+
};
|
|
1200
|
+
function descendants(call) {
|
|
1201
|
+
return call.children.flatMap((child) => [
|
|
1202
|
+
child,
|
|
1203
|
+
...descendants(child)
|
|
1204
|
+
]);
|
|
1205
|
+
}
|
|
1206
|
+
__name(descendants, "descendants");
|
|
1207
|
+
function leaves(call) {
|
|
1208
|
+
return call.children.length === 0 ? [
|
|
1209
|
+
call
|
|
1210
|
+
] : call.children.flatMap(leaves);
|
|
1211
|
+
}
|
|
1212
|
+
__name(leaves, "leaves");
|
|
1213
|
+
function groupToolActivity(calls, options = {}) {
|
|
1214
|
+
const expanded = options.expandNested === true ? calls.flatMap(leaves) : [
|
|
1215
|
+
...calls
|
|
1216
|
+
];
|
|
1217
|
+
const corrected = options.hideCorrected === true ? correctedCallIds(expanded.map((call) => call.part)) : /* @__PURE__ */ new Set();
|
|
1218
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1219
|
+
for (const call of expanded) {
|
|
1220
|
+
if (corrected.has(call.toolCallId)) continue;
|
|
1221
|
+
const presentation = options.catalog?.[call.name];
|
|
1222
|
+
const key = options.keyOf?.(call, presentation) ?? presentation?.label ?? call.name;
|
|
1223
|
+
const status = toolCallState(call.part).status;
|
|
1224
|
+
const phrase = phraseFor(presentation, call.part.input, status !== "running" && status !== "awaiting-approval", options.fallback);
|
|
1225
|
+
const inner = options.expandNested === true ? 0 : descendants(call).length;
|
|
1226
|
+
const existing = groups.get(key);
|
|
1227
|
+
if (existing === void 0) {
|
|
1228
|
+
groups.set(key, {
|
|
1229
|
+
key,
|
|
1230
|
+
label: presentation?.label ?? null,
|
|
1231
|
+
icon: presentation?.icon ?? null,
|
|
1232
|
+
status,
|
|
1233
|
+
count: 1,
|
|
1234
|
+
phrase,
|
|
1235
|
+
calls: [
|
|
1236
|
+
call
|
|
1237
|
+
],
|
|
1238
|
+
innerCount: inner
|
|
1239
|
+
});
|
|
1240
|
+
continue;
|
|
1241
|
+
}
|
|
1242
|
+
existing.count += 1;
|
|
1243
|
+
existing.calls.push(call);
|
|
1244
|
+
existing.phrase = phrase;
|
|
1245
|
+
existing.innerCount += inner;
|
|
1246
|
+
if (STATUS_WEIGHT[status] > STATUS_WEIGHT[existing.status]) existing.status = status;
|
|
1247
|
+
}
|
|
1248
|
+
return [
|
|
1249
|
+
...groups.values()
|
|
1250
|
+
];
|
|
1251
|
+
}
|
|
1252
|
+
__name(groupToolActivity, "groupToolActivity");
|
|
1253
|
+
|
|
1254
|
+
// src/transcript/model.ts
|
|
965
1255
|
function buildTranscriptBlocks(message, options) {
|
|
966
1256
|
const blocks = [];
|
|
967
1257
|
let toolBuffer = [];
|
|
@@ -978,13 +1268,19 @@ function buildTranscriptBlocks(message, options) {
|
|
|
978
1268
|
if (toolBuffer.length === 0) {
|
|
979
1269
|
return;
|
|
980
1270
|
}
|
|
981
|
-
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId)
|
|
1271
|
+
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvalOf(approvals.get(part.toolCallId), part), options.toolCatalog));
|
|
1272
|
+
const roots = nestToolCalls(calls);
|
|
982
1273
|
blocks.push({
|
|
983
1274
|
kind: "tools",
|
|
984
1275
|
key: `${message.id}-tools-${toolCounter++}`,
|
|
985
1276
|
parts: toolBuffer,
|
|
986
1277
|
calls,
|
|
987
|
-
roots
|
|
1278
|
+
roots,
|
|
1279
|
+
activity: groupToolActivity(roots, {
|
|
1280
|
+
...options.toolCatalog !== void 0 ? {
|
|
1281
|
+
catalog: options.toolCatalog
|
|
1282
|
+
} : {}
|
|
1283
|
+
})
|
|
988
1284
|
});
|
|
989
1285
|
toolBuffer = [];
|
|
990
1286
|
}
|
|
@@ -1047,7 +1343,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1047
1343
|
fileBuffer.push(part);
|
|
1048
1344
|
continue;
|
|
1049
1345
|
}
|
|
1050
|
-
if (part.type === APPROVAL_PART) {
|
|
1346
|
+
if (part.type === APPROVAL_PART || part.type === SETTLED_PART) {
|
|
1051
1347
|
continue;
|
|
1052
1348
|
}
|
|
1053
1349
|
flushAll();
|
|
@@ -1133,7 +1429,7 @@ function isSettled(state) {
|
|
|
1133
1429
|
__name(isSettled, "isSettled");
|
|
1134
1430
|
function toolKind(part) {
|
|
1135
1431
|
const metadata = part.toolMetadata;
|
|
1136
|
-
return
|
|
1432
|
+
return isRecord2(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
|
|
1137
1433
|
}
|
|
1138
1434
|
__name(toolKind, "toolKind");
|
|
1139
1435
|
function isAwaitingApproval(part) {
|
|
@@ -1148,7 +1444,7 @@ function isAwaitingApproval(part) {
|
|
|
1148
1444
|
__name(isAwaitingApproval, "isAwaitingApproval");
|
|
1149
1445
|
function toolParentId(part) {
|
|
1150
1446
|
const metadata = part.toolMetadata;
|
|
1151
|
-
return
|
|
1447
|
+
return isRecord2(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
|
|
1152
1448
|
}
|
|
1153
1449
|
__name(toolParentId, "toolParentId");
|
|
1154
1450
|
function nestToolCalls(calls) {
|
|
@@ -1181,23 +1477,28 @@ function isAncestor(call, candidate, byId) {
|
|
|
1181
1477
|
return false;
|
|
1182
1478
|
}
|
|
1183
1479
|
__name(isAncestor, "isAncestor");
|
|
1184
|
-
function buildToolCall(part, options, approval) {
|
|
1480
|
+
function buildToolCall(part, options, approval, catalog) {
|
|
1185
1481
|
const toolCallId = part.toolCallId;
|
|
1186
1482
|
const awaiting = isAwaitingApproval(part);
|
|
1187
1483
|
const sending = awaiting ? options?.submitting(toolCallId) ?? null : null;
|
|
1188
1484
|
return {
|
|
1189
1485
|
part,
|
|
1190
1486
|
toolCallId,
|
|
1191
|
-
name:
|
|
1487
|
+
name: getToolName2(part),
|
|
1192
1488
|
toolKind: toolKind(part) ?? null,
|
|
1193
1489
|
parentId: toolParentId(part),
|
|
1194
1490
|
children: [],
|
|
1195
1491
|
approval,
|
|
1492
|
+
description: describeToolCall(part, catalog),
|
|
1196
1493
|
isAwaitingApproval: awaiting,
|
|
1197
1494
|
approve: {
|
|
1198
1495
|
available: awaiting && options?.canApprove === true,
|
|
1199
1496
|
isSubmitting: sending === "approve",
|
|
1200
|
-
|
|
1497
|
+
// Read by field, not passed through: `onClick={call.approve.run}` hands this a click event,
|
|
1498
|
+
// and a host's handler must not receive that as its options.
|
|
1499
|
+
run: /* @__PURE__ */ __name((approveOptions) => approveOptions?.remember === true ? options?.approve(toolCallId, {
|
|
1500
|
+
remember: true
|
|
1501
|
+
}) : options?.approve(toolCallId), "run")
|
|
1201
1502
|
},
|
|
1202
1503
|
reject: {
|
|
1203
1504
|
available: awaiting && options?.canReject === true,
|
|
@@ -1210,17 +1511,17 @@ function buildToolCall(part, options, approval) {
|
|
|
1210
1511
|
__name(buildToolCall, "buildToolCall");
|
|
1211
1512
|
function readElicitationRequest(part) {
|
|
1212
1513
|
const input = part.input;
|
|
1213
|
-
if (!
|
|
1514
|
+
if (!isRecord2(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
|
|
1214
1515
|
return null;
|
|
1215
1516
|
}
|
|
1216
1517
|
const questions = [];
|
|
1217
1518
|
for (const candidate of input.questions) {
|
|
1218
|
-
if (!
|
|
1519
|
+
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string" || !Array.isArray(candidate.options) || candidate.options.length === 0) {
|
|
1219
1520
|
return null;
|
|
1220
1521
|
}
|
|
1221
1522
|
const options = [];
|
|
1222
1523
|
for (const option of candidate.options) {
|
|
1223
|
-
if (!
|
|
1524
|
+
if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
|
|
1224
1525
|
return null;
|
|
1225
1526
|
}
|
|
1226
1527
|
options.push({
|
|
@@ -1245,7 +1546,7 @@ function readElicitationRequest(part) {
|
|
|
1245
1546
|
__name(readElicitationRequest, "readElicitationRequest");
|
|
1246
1547
|
function readElicitationOutcome(part) {
|
|
1247
1548
|
const output = part.output;
|
|
1248
|
-
if (!
|
|
1549
|
+
if (!isRecord2(output) || !isRecord2(output.answers) || typeof output.skipped !== "boolean") {
|
|
1249
1550
|
return null;
|
|
1250
1551
|
}
|
|
1251
1552
|
const answers = {};
|
|
@@ -1325,28 +1626,93 @@ function buildElicitationBlock(key, part, request, options) {
|
|
|
1325
1626
|
__name(buildElicitationBlock, "buildElicitationBlock");
|
|
1326
1627
|
var UI_PART = "data-ui";
|
|
1327
1628
|
var APPROVAL_PART = "data-approval-requested";
|
|
1629
|
+
var SETTLED_PART = "data-approval-settled";
|
|
1630
|
+
var SETTLED_STATUSES = [
|
|
1631
|
+
"approved",
|
|
1632
|
+
"rejected",
|
|
1633
|
+
"expired"
|
|
1634
|
+
];
|
|
1328
1635
|
function readApprovals(parts) {
|
|
1329
1636
|
const out = /* @__PURE__ */ new Map();
|
|
1637
|
+
const entry = /* @__PURE__ */ __name((id) => {
|
|
1638
|
+
let found = out.get(id);
|
|
1639
|
+
if (found === void 0) {
|
|
1640
|
+
found = {
|
|
1641
|
+
approver: null,
|
|
1642
|
+
expiresAt: null,
|
|
1643
|
+
reason: null,
|
|
1644
|
+
status: null,
|
|
1645
|
+
remember: false,
|
|
1646
|
+
decidedBy: null,
|
|
1647
|
+
decidedVia: null,
|
|
1648
|
+
decisionReason: null
|
|
1649
|
+
};
|
|
1650
|
+
out.set(id, found);
|
|
1651
|
+
}
|
|
1652
|
+
return found;
|
|
1653
|
+
}, "entry");
|
|
1330
1654
|
for (const part of parts) {
|
|
1331
|
-
if (part.type !== APPROVAL_PART) {
|
|
1655
|
+
if (part.type !== APPROVAL_PART && part.type !== SETTLED_PART) {
|
|
1332
1656
|
continue;
|
|
1333
1657
|
}
|
|
1334
1658
|
const data = part.data;
|
|
1335
|
-
if (!
|
|
1659
|
+
if (!isRecord2(data) || typeof data.id !== "string") {
|
|
1336
1660
|
continue;
|
|
1337
1661
|
}
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1662
|
+
const approval = entry(data.id);
|
|
1663
|
+
if (part.type === APPROVAL_PART) {
|
|
1664
|
+
if (typeof data.approver !== "string") {
|
|
1665
|
+
continue;
|
|
1666
|
+
}
|
|
1667
|
+
approval.approver = data.approver;
|
|
1668
|
+
approval.expiresAt = typeof data.expiresAt === "string" ? data.expiresAt : null;
|
|
1669
|
+
approval.reason = typeof data.reason === "string" ? data.reason : null;
|
|
1670
|
+
continue;
|
|
1671
|
+
}
|
|
1672
|
+
if (typeof data.status !== "string" || !SETTLED_STATUSES.includes(data.status)) {
|
|
1673
|
+
continue;
|
|
1674
|
+
}
|
|
1675
|
+
approval.status = data.status;
|
|
1676
|
+
if (approval.approver === null && typeof data.approver === "string") {
|
|
1677
|
+
approval.approver = data.approver;
|
|
1678
|
+
}
|
|
1679
|
+
approval.remember = data.remember === true;
|
|
1680
|
+
approval.decidedBy = typeof data.decidedBy === "string" ? data.decidedBy : null;
|
|
1681
|
+
approval.decidedVia = typeof data.decidedVia === "string" ? data.decidedVia : null;
|
|
1682
|
+
approval.decisionReason = typeof data.reason === "string" ? data.reason : null;
|
|
1343
1683
|
}
|
|
1344
1684
|
return out;
|
|
1345
1685
|
}
|
|
1346
1686
|
__name(readApprovals, "readApprovals");
|
|
1687
|
+
function approvalOf(parts, call) {
|
|
1688
|
+
if (parts === void 0 || parts.approver === null) {
|
|
1689
|
+
return null;
|
|
1690
|
+
}
|
|
1691
|
+
return {
|
|
1692
|
+
approver: parts.approver,
|
|
1693
|
+
expiresAt: parts.expiresAt,
|
|
1694
|
+
reason: parts.reason,
|
|
1695
|
+
status: parts.status ?? statusFromPart(call),
|
|
1696
|
+
remember: parts.remember,
|
|
1697
|
+
decidedBy: parts.decidedBy,
|
|
1698
|
+
decidedVia: parts.decidedVia,
|
|
1699
|
+
decisionReason: parts.decisionReason
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
__name(approvalOf, "approvalOf");
|
|
1703
|
+
function statusFromPart(call) {
|
|
1704
|
+
if (call.state === "output-denied") {
|
|
1705
|
+
return "rejected";
|
|
1706
|
+
}
|
|
1707
|
+
if (call.state === "output-available" || call.state === "output-error") {
|
|
1708
|
+
return "approved";
|
|
1709
|
+
}
|
|
1710
|
+
return "pending";
|
|
1711
|
+
}
|
|
1712
|
+
__name(statusFromPart, "statusFromPart");
|
|
1347
1713
|
function readUiComponent(part) {
|
|
1348
1714
|
const data = part.data;
|
|
1349
|
-
if (!
|
|
1715
|
+
if (!isRecord2(data) || typeof data.component !== "string") {
|
|
1350
1716
|
return null;
|
|
1351
1717
|
}
|
|
1352
1718
|
const id = typeof data.id === "string" ? data.id : part.id;
|
|
@@ -1356,18 +1722,18 @@ function readUiComponent(part) {
|
|
|
1356
1722
|
return {
|
|
1357
1723
|
id,
|
|
1358
1724
|
component: data.component,
|
|
1359
|
-
props:
|
|
1725
|
+
props: isRecord2(data.props) ? data.props : {},
|
|
1360
1726
|
version: typeof data.version === "number" ? data.version : null
|
|
1361
1727
|
};
|
|
1362
1728
|
}
|
|
1363
1729
|
__name(readUiComponent, "readUiComponent");
|
|
1364
|
-
function
|
|
1730
|
+
function isRecord2(value) {
|
|
1365
1731
|
return typeof value === "object" && value !== null;
|
|
1366
1732
|
}
|
|
1367
|
-
__name(
|
|
1733
|
+
__name(isRecord2, "isRecord");
|
|
1368
1734
|
function readQuery(part) {
|
|
1369
1735
|
const input = part.input;
|
|
1370
|
-
if (!
|
|
1736
|
+
if (!isRecord2(input) || typeof input.query !== "string") {
|
|
1371
1737
|
return null;
|
|
1372
1738
|
}
|
|
1373
1739
|
return input.query;
|
|
@@ -1375,12 +1741,12 @@ function readQuery(part) {
|
|
|
1375
1741
|
__name(readQuery, "readQuery");
|
|
1376
1742
|
function readPassages(part) {
|
|
1377
1743
|
const output = part.output;
|
|
1378
|
-
if (!
|
|
1744
|
+
if (!isRecord2(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
|
|
1379
1745
|
return null;
|
|
1380
1746
|
}
|
|
1381
1747
|
const passages = [];
|
|
1382
1748
|
for (const candidate of output.passages) {
|
|
1383
|
-
if (!
|
|
1749
|
+
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
|
|
1384
1750
|
return null;
|
|
1385
1751
|
}
|
|
1386
1752
|
passages.push({
|
|
@@ -1390,7 +1756,7 @@ function readPassages(part) {
|
|
|
1390
1756
|
...typeof candidate.source === "string" ? {
|
|
1391
1757
|
source: candidate.source
|
|
1392
1758
|
} : {},
|
|
1393
|
-
...
|
|
1759
|
+
...isRecord2(candidate.metadata) ? {
|
|
1394
1760
|
metadata: candidate.metadata
|
|
1395
1761
|
} : {}
|
|
1396
1762
|
});
|
|
@@ -1729,10 +2095,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1729
2095
|
}, [
|
|
1730
2096
|
settle
|
|
1731
2097
|
]);
|
|
1732
|
-
const approve = useCallback3((toolCallId) => {
|
|
2098
|
+
const approve = useCallback3((toolCallId, options2) => {
|
|
1733
2099
|
const onApprove = latest.current.options.onApprove;
|
|
1734
2100
|
if (onApprove) {
|
|
1735
|
-
settle(toolCallId, "approve", () => onApprove(toolCallId));
|
|
2101
|
+
settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
|
|
1736
2102
|
}
|
|
1737
2103
|
}, [
|
|
1738
2104
|
settle
|
|
@@ -1857,6 +2223,9 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
1857
2223
|
...options.sources !== void 0 ? {
|
|
1858
2224
|
sources: options.sources
|
|
1859
2225
|
} : {},
|
|
2226
|
+
...options.toolCatalog !== void 0 ? {
|
|
2227
|
+
toolCatalog: options.toolCatalog
|
|
2228
|
+
} : {},
|
|
1860
2229
|
...options.onAnswer !== void 0 ? {
|
|
1861
2230
|
elicitation: {
|
|
1862
2231
|
picked: /* @__PURE__ */ __name((toolCallId, questionId) => picks.get(pickKey(toolCallId, questionId)), "picked"),
|
|
@@ -2632,6 +3001,121 @@ function isPromise(value) {
|
|
|
2632
3001
|
}
|
|
2633
3002
|
__name(isPromise, "isPromise");
|
|
2634
3003
|
|
|
3004
|
+
// src/presentation/use-tool-catalog.ts
|
|
3005
|
+
import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo3, useState as useState7 } from "react";
|
|
3006
|
+
var shared = /* @__PURE__ */ new WeakMap();
|
|
3007
|
+
function load(client, agent) {
|
|
3008
|
+
let byAgent = shared.get(client);
|
|
3009
|
+
if (byAgent === void 0) {
|
|
3010
|
+
byAgent = /* @__PURE__ */ new Map();
|
|
3011
|
+
shared.set(client, byAgent);
|
|
3012
|
+
}
|
|
3013
|
+
const key = agent ?? "";
|
|
3014
|
+
const cached = byAgent.get(key);
|
|
3015
|
+
if (cached !== void 0) return cached;
|
|
3016
|
+
const request = client.listTools(agent).catch((error) => {
|
|
3017
|
+
byAgent.delete(key);
|
|
3018
|
+
throw error;
|
|
3019
|
+
});
|
|
3020
|
+
byAgent.set(key, request);
|
|
3021
|
+
return request;
|
|
3022
|
+
}
|
|
3023
|
+
__name(load, "load");
|
|
3024
|
+
function useToolCatalog(options) {
|
|
3025
|
+
const { client, agent, enabled = true } = options;
|
|
3026
|
+
const [entries, setEntries] = useState7([]);
|
|
3027
|
+
const [isLoading, setLoading] = useState7(enabled);
|
|
3028
|
+
const [error, setError] = useState7(null);
|
|
3029
|
+
const [generation, setGeneration] = useState7(0);
|
|
3030
|
+
useEffect7(() => {
|
|
3031
|
+
if (!enabled) {
|
|
3032
|
+
setLoading(false);
|
|
3033
|
+
return;
|
|
3034
|
+
}
|
|
3035
|
+
let cancelled = false;
|
|
3036
|
+
setLoading(true);
|
|
3037
|
+
load(client, agent).then((loaded) => {
|
|
3038
|
+
if (cancelled) return;
|
|
3039
|
+
setEntries(loaded);
|
|
3040
|
+
setError(null);
|
|
3041
|
+
setLoading(false);
|
|
3042
|
+
}, (failure) => {
|
|
3043
|
+
if (cancelled) return;
|
|
3044
|
+
setError(failure instanceof Error ? failure : new Error(String(failure)));
|
|
3045
|
+
setLoading(false);
|
|
3046
|
+
});
|
|
3047
|
+
return () => {
|
|
3048
|
+
cancelled = true;
|
|
3049
|
+
};
|
|
3050
|
+
}, [
|
|
3051
|
+
client,
|
|
3052
|
+
agent,
|
|
3053
|
+
enabled,
|
|
3054
|
+
generation
|
|
3055
|
+
]);
|
|
3056
|
+
const refresh = useCallback5(() => {
|
|
3057
|
+
shared.get(client)?.delete(agent ?? "");
|
|
3058
|
+
setGeneration((current) => current + 1);
|
|
3059
|
+
}, [
|
|
3060
|
+
client,
|
|
3061
|
+
agent
|
|
3062
|
+
]);
|
|
3063
|
+
const catalog = useMemo3(() => toolCatalogFrom(entries), [
|
|
3064
|
+
entries
|
|
3065
|
+
]);
|
|
3066
|
+
return {
|
|
3067
|
+
catalog,
|
|
3068
|
+
entries,
|
|
3069
|
+
isLoading,
|
|
3070
|
+
error,
|
|
3071
|
+
refresh
|
|
3072
|
+
};
|
|
3073
|
+
}
|
|
3074
|
+
__name(useToolCatalog, "useToolCatalog");
|
|
3075
|
+
|
|
3076
|
+
// src/approvals/countdown.ts
|
|
3077
|
+
import { useEffect as useEffect8, useRef as useRef6, useState as useState8 } from "react";
|
|
3078
|
+
function approvalCountdown(expiresAt, now = Date.now()) {
|
|
3079
|
+
const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
|
|
3080
|
+
if (!Number.isFinite(deadline)) {
|
|
3081
|
+
return {
|
|
3082
|
+
remainingMs: null,
|
|
3083
|
+
isExpired: false
|
|
3084
|
+
};
|
|
3085
|
+
}
|
|
3086
|
+
const remainingMs = Math.max(0, deadline - now);
|
|
3087
|
+
return {
|
|
3088
|
+
remainingMs,
|
|
3089
|
+
isExpired: remainingMs === 0
|
|
3090
|
+
};
|
|
3091
|
+
}
|
|
3092
|
+
__name(approvalCountdown, "approvalCountdown");
|
|
3093
|
+
function useApprovalCountdown(expiresAt, options = {}) {
|
|
3094
|
+
const { intervalMs = 1e3 } = options;
|
|
3095
|
+
const nowRef = useRef6(options.now ?? Date.now);
|
|
3096
|
+
nowRef.current = options.now ?? Date.now;
|
|
3097
|
+
const [state, setState] = useState8(() => approvalCountdown(expiresAt, nowRef.current()));
|
|
3098
|
+
useEffect8(() => {
|
|
3099
|
+
const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
|
|
3100
|
+
const first = read();
|
|
3101
|
+
setState(first);
|
|
3102
|
+
if (first.remainingMs === null || first.isExpired) {
|
|
3103
|
+
return;
|
|
3104
|
+
}
|
|
3105
|
+
const timer = setInterval(() => {
|
|
3106
|
+
const next = read();
|
|
3107
|
+
setState(next);
|
|
3108
|
+
if (next.isExpired) clearInterval(timer);
|
|
3109
|
+
}, intervalMs);
|
|
3110
|
+
return () => clearInterval(timer);
|
|
3111
|
+
}, [
|
|
3112
|
+
expiresAt,
|
|
3113
|
+
intervalMs
|
|
3114
|
+
]);
|
|
3115
|
+
return state;
|
|
3116
|
+
}
|
|
3117
|
+
__name(useApprovalCountdown, "useApprovalCountdown");
|
|
3118
|
+
|
|
2635
3119
|
// src/stored-message-to-ui-message.ts
|
|
2636
3120
|
import { DEFAULT_REFUSAL_REASON } from "@dudousxd/nestjs-agent-core";
|
|
2637
3121
|
function isRefusal(result) {
|
|
@@ -2691,6 +3175,41 @@ function storedMessageToUiMessage(message) {
|
|
|
2691
3175
|
}
|
|
2692
3176
|
});
|
|
2693
3177
|
}
|
|
3178
|
+
for (const approval of message.approvals ?? []) {
|
|
3179
|
+
parts.push({
|
|
3180
|
+
type: "data-approval-requested",
|
|
3181
|
+
id: approval.toolCallId,
|
|
3182
|
+
data: {
|
|
3183
|
+
id: approval.toolCallId,
|
|
3184
|
+
approver: approval.approver,
|
|
3185
|
+
...approval.expiresAt !== void 0 ? {
|
|
3186
|
+
expiresAt: approval.expiresAt
|
|
3187
|
+
} : {}
|
|
3188
|
+
}
|
|
3189
|
+
});
|
|
3190
|
+
if (approval.status !== "pending") {
|
|
3191
|
+
parts.push({
|
|
3192
|
+
type: "data-approval-settled",
|
|
3193
|
+
id: approval.toolCallId,
|
|
3194
|
+
data: {
|
|
3195
|
+
id: approval.toolCallId,
|
|
3196
|
+
status: approval.status,
|
|
3197
|
+
...approval.decidedBy !== void 0 ? {
|
|
3198
|
+
decidedBy: approval.decidedBy
|
|
3199
|
+
} : {},
|
|
3200
|
+
...approval.decidedVia !== void 0 ? {
|
|
3201
|
+
decidedVia: approval.decidedVia
|
|
3202
|
+
} : {},
|
|
3203
|
+
...approval.remember === true ? {
|
|
3204
|
+
remember: true
|
|
3205
|
+
} : {},
|
|
3206
|
+
...approval.reason !== void 0 ? {
|
|
3207
|
+
reason: approval.reason
|
|
3208
|
+
} : {}
|
|
3209
|
+
}
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3212
|
+
}
|
|
2694
3213
|
for (const call of message.toolCalls ?? []) {
|
|
2695
3214
|
const result = message.toolResults?.find((candidate) => candidate.id === call.id);
|
|
2696
3215
|
const toolKind2 = call.kind;
|
|
@@ -2793,20 +3312,20 @@ __name(sumUsage, "sumUsage");
|
|
|
2793
3312
|
|
|
2794
3313
|
// src/use-agent-chat.ts
|
|
2795
3314
|
import { useChat } from "@ai-sdk/react";
|
|
2796
|
-
import { useCallback as
|
|
3315
|
+
import { useCallback as useCallback6, useEffect as useEffect9, useMemo as useMemo4, useRef as useRef7, useState as useState9 } from "react";
|
|
2797
3316
|
function useAgentChat(options) {
|
|
2798
|
-
const latest =
|
|
3317
|
+
const latest = useRef7(options);
|
|
2799
3318
|
latest.current = options;
|
|
2800
|
-
const [runId, setRunId] =
|
|
2801
|
-
const runIdRef =
|
|
3319
|
+
const [runId, setRunId] = useState9(options.resumeRunId);
|
|
3320
|
+
const runIdRef = useRef7(runId);
|
|
2802
3321
|
runIdRef.current = runId;
|
|
2803
|
-
const settlingRunIdRef =
|
|
2804
|
-
const autoResumeRunIdRef =
|
|
2805
|
-
const [autoResume, setAutoResume] =
|
|
2806
|
-
const [activeRunId, setActiveRunId] =
|
|
2807
|
-
const regenerateNext =
|
|
2808
|
-
const createdThreadId =
|
|
2809
|
-
const client =
|
|
3322
|
+
const settlingRunIdRef = useRef7(void 0);
|
|
3323
|
+
const autoResumeRunIdRef = useRef7(void 0);
|
|
3324
|
+
const [autoResume, setAutoResume] = useState9(false);
|
|
3325
|
+
const [activeRunId, setActiveRunId] = useState9(null);
|
|
3326
|
+
const regenerateNext = useRef7(false);
|
|
3327
|
+
const createdThreadId = useRef7(void 0);
|
|
3328
|
+
const client = useMemo4(() => {
|
|
2810
3329
|
if (options.client) return options.client;
|
|
2811
3330
|
return new AgentClient({
|
|
2812
3331
|
...options.baseUrl !== void 0 ? {
|
|
@@ -2821,7 +3340,7 @@ function useAgentChat(options) {
|
|
|
2821
3340
|
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
2822
3341
|
});
|
|
2823
3342
|
}, []);
|
|
2824
|
-
|
|
3343
|
+
useEffect9(() => {
|
|
2825
3344
|
if (!options.resume || options.threadId === void 0) return;
|
|
2826
3345
|
let cancelled = false;
|
|
2827
3346
|
const threadId = options.threadId;
|
|
@@ -2841,7 +3360,7 @@ function useAgentChat(options) {
|
|
|
2841
3360
|
options.resume,
|
|
2842
3361
|
options.threadId
|
|
2843
3362
|
]);
|
|
2844
|
-
const transport =
|
|
3363
|
+
const transport = useMemo4(() => {
|
|
2845
3364
|
function onMeta(meta) {
|
|
2846
3365
|
settlingRunIdRef.current = meta.runId;
|
|
2847
3366
|
setRunId(meta.runId);
|
|
@@ -2890,7 +3409,7 @@ function useAgentChat(options) {
|
|
|
2890
3409
|
}, "onAttemptStart")
|
|
2891
3410
|
});
|
|
2892
3411
|
}, []);
|
|
2893
|
-
const backgroundRef =
|
|
3412
|
+
const backgroundRef = useRef7(() => Promise.resolve());
|
|
2894
3413
|
const chat = useChat({
|
|
2895
3414
|
transport,
|
|
2896
3415
|
resume: options.resumeRunId !== void 0 || autoResume,
|
|
@@ -2921,13 +3440,13 @@ function useAgentChat(options) {
|
|
|
2921
3440
|
}
|
|
2922
3441
|
}, "onFinish")
|
|
2923
3442
|
});
|
|
2924
|
-
const chatRef =
|
|
3443
|
+
const chatRef = useRef7(chat);
|
|
2925
3444
|
chatRef.current = chat;
|
|
2926
|
-
const turnInFlight =
|
|
2927
|
-
const isTurnInFlight =
|
|
3445
|
+
const turnInFlight = useRef7(false);
|
|
3446
|
+
const isTurnInFlight = useCallback6(() => turnInFlight.current || transport.isAttemptLive, [
|
|
2928
3447
|
transport
|
|
2929
3448
|
]);
|
|
2930
|
-
const sendMessage =
|
|
3449
|
+
const sendMessage = useCallback6(async (...args) => {
|
|
2931
3450
|
if (isTurnInFlight()) return;
|
|
2932
3451
|
turnInFlight.current = true;
|
|
2933
3452
|
try {
|
|
@@ -2938,15 +3457,15 @@ function useAgentChat(options) {
|
|
|
2938
3457
|
}, [
|
|
2939
3458
|
isTurnInFlight
|
|
2940
3459
|
]);
|
|
2941
|
-
const addToolResult =
|
|
3460
|
+
const addToolResult = useCallback6(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
|
|
2942
3461
|
tool,
|
|
2943
3462
|
toolCallId,
|
|
2944
3463
|
output
|
|
2945
3464
|
}), []);
|
|
2946
|
-
const [threads, setThreads] =
|
|
2947
|
-
const [quota, setQuota] =
|
|
2948
|
-
const [backgroundRuns, setBackgroundRuns] =
|
|
2949
|
-
const refreshBackground =
|
|
3465
|
+
const [threads, setThreads] = useState9([]);
|
|
3466
|
+
const [quota, setQuota] = useState9(null);
|
|
3467
|
+
const [backgroundRuns, setBackgroundRuns] = useState9([]);
|
|
3468
|
+
const refreshBackground = useCallback6(async () => {
|
|
2950
3469
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
2951
3470
|
if (threadId === void 0) {
|
|
2952
3471
|
return;
|
|
@@ -2971,7 +3490,7 @@ function useAgentChat(options) {
|
|
|
2971
3490
|
]);
|
|
2972
3491
|
backgroundRef.current = refreshBackground;
|
|
2973
3492
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
2974
|
-
|
|
3493
|
+
useEffect9(() => {
|
|
2975
3494
|
if (options.background !== true || options.threadId === void 0) {
|
|
2976
3495
|
return;
|
|
2977
3496
|
}
|
|
@@ -2981,7 +3500,7 @@ function useAgentChat(options) {
|
|
|
2981
3500
|
options.threadId,
|
|
2982
3501
|
refreshBackground
|
|
2983
3502
|
]);
|
|
2984
|
-
|
|
3503
|
+
useEffect9(() => {
|
|
2985
3504
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
2986
3505
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
2987
3506
|
return;
|
|
@@ -2992,26 +3511,26 @@ function useAgentChat(options) {
|
|
|
2992
3511
|
isWorking,
|
|
2993
3512
|
refreshBackground
|
|
2994
3513
|
]);
|
|
2995
|
-
const loadThreads =
|
|
3514
|
+
const loadThreads = useCallback6(async () => {
|
|
2996
3515
|
const list = await client.listThreads();
|
|
2997
3516
|
setThreads(list);
|
|
2998
3517
|
return list;
|
|
2999
3518
|
}, [
|
|
3000
3519
|
client
|
|
3001
3520
|
]);
|
|
3002
|
-
const loadThread =
|
|
3521
|
+
const loadThread = useCallback6((id) => client.getThread(id), [
|
|
3003
3522
|
client
|
|
3004
3523
|
]);
|
|
3005
|
-
const deleteThread =
|
|
3524
|
+
const deleteThread = useCallback6(async (id) => {
|
|
3006
3525
|
await client.deleteThread(id);
|
|
3007
3526
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
3008
3527
|
}, [
|
|
3009
3528
|
client
|
|
3010
3529
|
]);
|
|
3011
|
-
const forkThread =
|
|
3530
|
+
const forkThread = useCallback6((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
|
|
3012
3531
|
client
|
|
3013
3532
|
]);
|
|
3014
|
-
const renameThread =
|
|
3533
|
+
const renameThread = useCallback6(async (id, title) => {
|
|
3015
3534
|
await client.renameThread(id, title);
|
|
3016
3535
|
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
3017
3536
|
...thread,
|
|
@@ -3020,24 +3539,24 @@ function useAgentChat(options) {
|
|
|
3020
3539
|
}, [
|
|
3021
3540
|
client
|
|
3022
3541
|
]);
|
|
3023
|
-
const promoteThread =
|
|
3542
|
+
const promoteThread = useCallback6(async (id) => {
|
|
3024
3543
|
await client.promoteThread(id);
|
|
3025
3544
|
await loadThreads();
|
|
3026
3545
|
}, [
|
|
3027
3546
|
client,
|
|
3028
3547
|
loadThreads
|
|
3029
3548
|
]);
|
|
3030
|
-
const truncateFromMessage =
|
|
3549
|
+
const truncateFromMessage = useCallback6((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
|
|
3031
3550
|
client
|
|
3032
3551
|
]);
|
|
3033
|
-
const loadQuota =
|
|
3552
|
+
const loadQuota = useCallback6(async () => {
|
|
3034
3553
|
const today = await client.getQuotaToday();
|
|
3035
3554
|
setQuota(today);
|
|
3036
3555
|
return today;
|
|
3037
3556
|
}, [
|
|
3038
3557
|
client
|
|
3039
3558
|
]);
|
|
3040
|
-
const cancel =
|
|
3559
|
+
const cancel = useCallback6(async () => {
|
|
3041
3560
|
chatRef.current.stop();
|
|
3042
3561
|
const activeRunId2 = runIdRef.current;
|
|
3043
3562
|
if (activeRunId2) {
|
|
@@ -3049,24 +3568,33 @@ function useAgentChat(options) {
|
|
|
3049
3568
|
}, [
|
|
3050
3569
|
client
|
|
3051
3570
|
]);
|
|
3052
|
-
const approve =
|
|
3571
|
+
const approve = useCallback6(async ({ toolCallId, remember, via }) => {
|
|
3053
3572
|
await client.approveToolCall({
|
|
3054
|
-
toolCallId
|
|
3573
|
+
toolCallId,
|
|
3574
|
+
...remember === true ? {
|
|
3575
|
+
remember: true
|
|
3576
|
+
} : {},
|
|
3577
|
+
...via !== void 0 ? {
|
|
3578
|
+
via
|
|
3579
|
+
} : {}
|
|
3055
3580
|
});
|
|
3056
3581
|
}, [
|
|
3057
3582
|
client
|
|
3058
3583
|
]);
|
|
3059
|
-
const reject =
|
|
3584
|
+
const reject = useCallback6(async ({ toolCallId, reason, via }) => {
|
|
3060
3585
|
await client.rejectToolCall({
|
|
3061
3586
|
toolCallId,
|
|
3062
3587
|
...reason !== void 0 ? {
|
|
3063
3588
|
reason
|
|
3589
|
+
} : {},
|
|
3590
|
+
...via !== void 0 ? {
|
|
3591
|
+
via
|
|
3064
3592
|
} : {}
|
|
3065
3593
|
});
|
|
3066
3594
|
}, [
|
|
3067
3595
|
client
|
|
3068
3596
|
]);
|
|
3069
|
-
const answer =
|
|
3597
|
+
const answer = useCallback6(async ({ toolCallId, answers }) => {
|
|
3070
3598
|
await client.answerToolCall({
|
|
3071
3599
|
toolCallId,
|
|
3072
3600
|
...answers !== void 0 ? {
|
|
@@ -3076,14 +3604,14 @@ function useAgentChat(options) {
|
|
|
3076
3604
|
}, [
|
|
3077
3605
|
client
|
|
3078
3606
|
]);
|
|
3079
|
-
const skip =
|
|
3607
|
+
const skip = useCallback6(async ({ toolCallId }) => {
|
|
3080
3608
|
await client.skipToolCall({
|
|
3081
3609
|
toolCallId
|
|
3082
3610
|
});
|
|
3083
3611
|
}, [
|
|
3084
3612
|
client
|
|
3085
3613
|
]);
|
|
3086
|
-
const regenerate =
|
|
3614
|
+
const regenerate = useCallback6(() => {
|
|
3087
3615
|
if (isTurnInFlight()) return;
|
|
3088
3616
|
regenerateNext.current = true;
|
|
3089
3617
|
turnInFlight.current = true;
|
|
@@ -3146,27 +3674,41 @@ export {
|
|
|
3146
3674
|
MessageList,
|
|
3147
3675
|
SPEECH_LANGUAGES,
|
|
3148
3676
|
applyCompletion,
|
|
3677
|
+
approvalCountdown,
|
|
3149
3678
|
backgroundRunsFromThread,
|
|
3150
3679
|
buildTranscriptBlocks,
|
|
3680
|
+
correctedCallIds,
|
|
3151
3681
|
createSkillsSource,
|
|
3152
3682
|
describeTimestamp,
|
|
3683
|
+
describeToolCall,
|
|
3153
3684
|
describeUsage,
|
|
3154
3685
|
extractMessageText,
|
|
3686
|
+
fillTemplate,
|
|
3155
3687
|
filterAutocompleteItems,
|
|
3156
3688
|
findActiveTrigger,
|
|
3157
3689
|
formatElapsed,
|
|
3158
3690
|
formatRelativeTime,
|
|
3691
|
+
groupToolActivity,
|
|
3692
|
+
inferResultView,
|
|
3693
|
+
isActionCall,
|
|
3159
3694
|
loadStoredSpeechLang,
|
|
3160
3695
|
persistSpeechLang,
|
|
3696
|
+
phraseFor,
|
|
3697
|
+
readPath,
|
|
3161
3698
|
readReasoningMs,
|
|
3699
|
+
resolveResultView,
|
|
3162
3700
|
storedMessageToUiMessage,
|
|
3163
3701
|
storedThreadToUiMessages,
|
|
3702
|
+
toolCallState,
|
|
3703
|
+
toolCatalogFrom,
|
|
3164
3704
|
useAgentChat,
|
|
3705
|
+
useApprovalCountdown,
|
|
3165
3706
|
useChatTranscript,
|
|
3166
3707
|
useComposerAutocomplete,
|
|
3167
3708
|
useElapsed,
|
|
3168
3709
|
useSpeechRecognition,
|
|
3169
3710
|
useStickToBottom,
|
|
3711
|
+
useToolCatalog,
|
|
3170
3712
|
useTranscriptItem
|
|
3171
3713
|
};
|
|
3172
3714
|
//# sourceMappingURL=index.js.map
|