@dudousxd/nestjs-agent-react 0.10.0 → 0.12.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 +38 -4
- package/dist/index.cjs +327 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +118 -10
- package/dist/index.d.ts +118 -10
- package/dist/index.js +299 -37
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -41,8 +41,10 @@ __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
|
+
coerceAnswer: () => coerceAnswer,
|
|
46
48
|
correctedCallIds: () => correctedCallIds,
|
|
47
49
|
createSkillsSource: () => createSkillsSource,
|
|
48
50
|
describeTimestamp: () => describeTimestamp,
|
|
@@ -68,13 +70,16 @@ __export(src_exports, {
|
|
|
68
70
|
toolCallState: () => toolCallState,
|
|
69
71
|
toolCatalogFrom: () => toolCatalogFrom,
|
|
70
72
|
useAgentChat: () => useAgentChat,
|
|
73
|
+
useApprovalCountdown: () => useApprovalCountdown,
|
|
71
74
|
useChatTranscript: () => useChatTranscript,
|
|
72
75
|
useComposerAutocomplete: () => useComposerAutocomplete,
|
|
73
76
|
useElapsed: () => useElapsed,
|
|
74
77
|
useSpeechRecognition: () => useSpeechRecognition,
|
|
75
78
|
useStickToBottom: () => useStickToBottom,
|
|
76
79
|
useToolCatalog: () => useToolCatalog,
|
|
77
|
-
useTranscriptItem: () => useTranscriptItem
|
|
80
|
+
useTranscriptItem: () => useTranscriptItem,
|
|
81
|
+
validateAnswer: () => import_nestjs_agent_core.validateElicitationAnswer,
|
|
82
|
+
validateAnswerValue: () => import_nestjs_agent_core.validateElicitationValue
|
|
78
83
|
});
|
|
79
84
|
module.exports = __toCommonJS(src_exports);
|
|
80
85
|
|
|
@@ -521,6 +526,10 @@ var AgentChatTransport = class {
|
|
|
521
526
|
});
|
|
522
527
|
}
|
|
523
528
|
break;
|
|
529
|
+
case "approval-settled":
|
|
530
|
+
ensureStep();
|
|
531
|
+
forwardAsData(event, false);
|
|
532
|
+
break;
|
|
524
533
|
case "ui":
|
|
525
534
|
ensureStep();
|
|
526
535
|
closeRuns();
|
|
@@ -820,6 +829,10 @@ var AgentClient = class {
|
|
|
820
829
|
cancelStream(runId) {
|
|
821
830
|
return this.request("POST", `/agent/chat/${encodeURIComponent(runId)}/cancel`);
|
|
822
831
|
}
|
|
832
|
+
/**
|
|
833
|
+
* `remember` approves later calls of the same tool in the same thread; `via` names the surface
|
|
834
|
+
* the decision came through (the server records `'web'` when omitted).
|
|
835
|
+
*/
|
|
823
836
|
approveToolCall(input) {
|
|
824
837
|
return this.request("POST", "/agent/tool-call/approve", input);
|
|
825
838
|
}
|
|
@@ -1047,8 +1060,66 @@ var import_react6 = __toESM(require("react"), 1);
|
|
|
1047
1060
|
var import_react5 = require("react");
|
|
1048
1061
|
|
|
1049
1062
|
// src/transcript/model.ts
|
|
1063
|
+
var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
|
|
1050
1064
|
var import_ai2 = require("ai");
|
|
1051
1065
|
|
|
1066
|
+
// src/elicitation/answers.ts
|
|
1067
|
+
var import_nestjs_agent_core = require("@dudousxd/nestjs-agent-core");
|
|
1068
|
+
function pad(value) {
|
|
1069
|
+
return String(value).padStart(2, "0");
|
|
1070
|
+
}
|
|
1071
|
+
__name(pad, "pad");
|
|
1072
|
+
function toDay(date) {
|
|
1073
|
+
if (Number.isNaN(date.getTime())) {
|
|
1074
|
+
return null;
|
|
1075
|
+
}
|
|
1076
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
1077
|
+
}
|
|
1078
|
+
__name(toDay, "toDay");
|
|
1079
|
+
function coerceOne(type, raw) {
|
|
1080
|
+
if (raw === null || raw === void 0) {
|
|
1081
|
+
return null;
|
|
1082
|
+
}
|
|
1083
|
+
if (Array.isArray(raw)) {
|
|
1084
|
+
return null;
|
|
1085
|
+
}
|
|
1086
|
+
if (raw instanceof Date) {
|
|
1087
|
+
return type === "date" || type === void 0 ? toDay(raw) : raw.toISOString();
|
|
1088
|
+
}
|
|
1089
|
+
if (typeof raw === "boolean") {
|
|
1090
|
+
return raw ? "true" : "false";
|
|
1091
|
+
}
|
|
1092
|
+
if (typeof raw === "number") {
|
|
1093
|
+
return Number.isFinite(raw) ? String(raw) : null;
|
|
1094
|
+
}
|
|
1095
|
+
const text = raw;
|
|
1096
|
+
switch (type) {
|
|
1097
|
+
case "number":
|
|
1098
|
+
case "email":
|
|
1099
|
+
case "url":
|
|
1100
|
+
case "date":
|
|
1101
|
+
return text.trim() === "" ? null : text.trim();
|
|
1102
|
+
case "boolean": {
|
|
1103
|
+
const lowered = text.trim().toLowerCase();
|
|
1104
|
+
if (lowered === "true" || lowered === "on" || lowered === "yes") return "true";
|
|
1105
|
+
if (lowered === "false" || lowered === "off" || lowered === "no") return "false";
|
|
1106
|
+
return lowered === "" ? null : text;
|
|
1107
|
+
}
|
|
1108
|
+
default:
|
|
1109
|
+
return text === "" ? null : text;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
__name(coerceOne, "coerceOne");
|
|
1113
|
+
function coerceAnswer(question, raw) {
|
|
1114
|
+
const type = question.input?.type;
|
|
1115
|
+
const items = Array.isArray(raw) ? raw : [
|
|
1116
|
+
raw
|
|
1117
|
+
];
|
|
1118
|
+
const values = items.map((item) => coerceOne(type, item)).filter((value) => value !== null);
|
|
1119
|
+
return question.multiple === true ? values : values.slice(0, 1);
|
|
1120
|
+
}
|
|
1121
|
+
__name(coerceAnswer, "coerceAnswer");
|
|
1122
|
+
|
|
1052
1123
|
// src/presentation/tool-activity.ts
|
|
1053
1124
|
var import_ai = require("ai");
|
|
1054
1125
|
|
|
@@ -1337,7 +1408,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1337
1408
|
if (toolBuffer.length === 0) {
|
|
1338
1409
|
return;
|
|
1339
1410
|
}
|
|
1340
|
-
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvals.get(part.toolCallId)
|
|
1411
|
+
const calls = toolBuffer.map((part) => buildToolCall(part, options.approval, approvalOf(approvals.get(part.toolCallId), part), options.toolCatalog));
|
|
1341
1412
|
const roots = nestToolCalls(calls);
|
|
1342
1413
|
blocks.push({
|
|
1343
1414
|
kind: "tools",
|
|
@@ -1412,7 +1483,7 @@ function buildTranscriptBlocks(message, options) {
|
|
|
1412
1483
|
fileBuffer.push(part);
|
|
1413
1484
|
continue;
|
|
1414
1485
|
}
|
|
1415
|
-
if (part.type === APPROVAL_PART) {
|
|
1486
|
+
if (part.type === APPROVAL_PART || part.type === SETTLED_PART) {
|
|
1416
1487
|
continue;
|
|
1417
1488
|
}
|
|
1418
1489
|
flushAll();
|
|
@@ -1563,7 +1634,11 @@ function buildToolCall(part, options, approval, catalog) {
|
|
|
1563
1634
|
approve: {
|
|
1564
1635
|
available: awaiting && options?.canApprove === true,
|
|
1565
1636
|
isSubmitting: sending === "approve",
|
|
1566
|
-
|
|
1637
|
+
// Read by field, not passed through: `onClick={call.approve.run}` hands this a click event,
|
|
1638
|
+
// and a host's handler must not receive that as its options.
|
|
1639
|
+
run: /* @__PURE__ */ __name((approveOptions) => approveOptions?.remember === true ? options?.approve(toolCallId, {
|
|
1640
|
+
remember: true
|
|
1641
|
+
}) : options?.approve(toolCallId), "run")
|
|
1567
1642
|
},
|
|
1568
1643
|
reject: {
|
|
1569
1644
|
available: awaiting && options?.canReject === true,
|
|
@@ -1581,11 +1656,16 @@ function readElicitationRequest(part) {
|
|
|
1581
1656
|
}
|
|
1582
1657
|
const questions = [];
|
|
1583
1658
|
for (const candidate of input.questions) {
|
|
1584
|
-
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string"
|
|
1659
|
+
if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string") {
|
|
1660
|
+
return null;
|
|
1661
|
+
}
|
|
1662
|
+
const input2 = (0, import_nestjs_agent_core2.readElicitationInput)(candidate.input) ?? null;
|
|
1663
|
+
const rawOptions = Array.isArray(candidate.options) ? candidate.options : [];
|
|
1664
|
+
if (rawOptions.length === 0 && (input2 === null || input2.type === "select")) {
|
|
1585
1665
|
return null;
|
|
1586
1666
|
}
|
|
1587
1667
|
const options = [];
|
|
1588
|
-
for (const option of
|
|
1668
|
+
for (const option of rawOptions) {
|
|
1589
1669
|
if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
|
|
1590
1670
|
return null;
|
|
1591
1671
|
}
|
|
@@ -1598,7 +1678,10 @@ function readElicitationRequest(part) {
|
|
|
1598
1678
|
questions.push({
|
|
1599
1679
|
id: candidate.id,
|
|
1600
1680
|
prompt: candidate.prompt,
|
|
1681
|
+
description: typeof candidate.description === "string" ? candidate.description : null,
|
|
1682
|
+
input: input2,
|
|
1601
1683
|
multiple: candidate.multiple === true,
|
|
1684
|
+
allowFreeText: candidate.allowFreeText === true,
|
|
1602
1685
|
defaults: Array.isArray(candidate.defaults) ? candidate.defaults.filter((value) => typeof value === "string") : [],
|
|
1603
1686
|
options
|
|
1604
1687
|
});
|
|
@@ -1634,12 +1717,38 @@ function buildElicitationBlock(key, part, request, options) {
|
|
|
1634
1717
|
const picked = isPending ? options.picked(toolCallId, question.id) : void 0;
|
|
1635
1718
|
const selected = picked ?? outcome?.answers[question.id] ?? question.defaults;
|
|
1636
1719
|
const pick = /* @__PURE__ */ __name((values) => options.pick(toolCallId, question.id, values), "pick");
|
|
1720
|
+
const error = isPending ? (0, import_nestjs_agent_core2.validateElicitationAnswer)({
|
|
1721
|
+
id: question.id,
|
|
1722
|
+
prompt: question.prompt,
|
|
1723
|
+
options: question.options.map(({ value, label }) => ({
|
|
1724
|
+
value,
|
|
1725
|
+
label
|
|
1726
|
+
})),
|
|
1727
|
+
...question.input !== null ? {
|
|
1728
|
+
input: question.input
|
|
1729
|
+
} : {},
|
|
1730
|
+
...question.multiple ? {
|
|
1731
|
+
multiple: true
|
|
1732
|
+
} : {},
|
|
1733
|
+
...question.allowFreeText ? {
|
|
1734
|
+
allowFreeText: true
|
|
1735
|
+
} : {}
|
|
1736
|
+
}, selected) : null;
|
|
1637
1737
|
return {
|
|
1638
1738
|
id: question.id,
|
|
1639
1739
|
prompt: question.prompt,
|
|
1740
|
+
description: question.description,
|
|
1741
|
+
input: question.input,
|
|
1640
1742
|
multiple: question.multiple,
|
|
1641
1743
|
position: index + 1,
|
|
1642
1744
|
selected,
|
|
1745
|
+
value: selected[0] ?? "",
|
|
1746
|
+
error,
|
|
1747
|
+
setValue: /* @__PURE__ */ __name((raw) => {
|
|
1748
|
+
if (isPending) {
|
|
1749
|
+
pick(coerceAnswer(question, raw));
|
|
1750
|
+
}
|
|
1751
|
+
}, "setValue"),
|
|
1643
1752
|
isPristine: isPending ? picked === void 0 : outcome?.defaulted.includes(question.id) ?? true,
|
|
1644
1753
|
options: question.options.map((option) => ({
|
|
1645
1754
|
value: option.value,
|
|
@@ -1674,6 +1783,7 @@ function buildElicitationBlock(key, part, request, options) {
|
|
|
1674
1783
|
questions,
|
|
1675
1784
|
questionCount: questions.length,
|
|
1676
1785
|
isPending,
|
|
1786
|
+
isValid: questions.every((question) => question.error === null),
|
|
1677
1787
|
outcome,
|
|
1678
1788
|
error: options.errorOf(toolCallId),
|
|
1679
1789
|
answer: {
|
|
@@ -1691,25 +1801,90 @@ function buildElicitationBlock(key, part, request, options) {
|
|
|
1691
1801
|
__name(buildElicitationBlock, "buildElicitationBlock");
|
|
1692
1802
|
var UI_PART = "data-ui";
|
|
1693
1803
|
var APPROVAL_PART = "data-approval-requested";
|
|
1804
|
+
var SETTLED_PART = "data-approval-settled";
|
|
1805
|
+
var SETTLED_STATUSES = [
|
|
1806
|
+
"approved",
|
|
1807
|
+
"rejected",
|
|
1808
|
+
"expired"
|
|
1809
|
+
];
|
|
1694
1810
|
function readApprovals(parts) {
|
|
1695
1811
|
const out = /* @__PURE__ */ new Map();
|
|
1812
|
+
const entry = /* @__PURE__ */ __name((id) => {
|
|
1813
|
+
let found = out.get(id);
|
|
1814
|
+
if (found === void 0) {
|
|
1815
|
+
found = {
|
|
1816
|
+
approver: null,
|
|
1817
|
+
expiresAt: null,
|
|
1818
|
+
reason: null,
|
|
1819
|
+
status: null,
|
|
1820
|
+
remember: false,
|
|
1821
|
+
decidedBy: null,
|
|
1822
|
+
decidedVia: null,
|
|
1823
|
+
decisionReason: null
|
|
1824
|
+
};
|
|
1825
|
+
out.set(id, found);
|
|
1826
|
+
}
|
|
1827
|
+
return found;
|
|
1828
|
+
}, "entry");
|
|
1696
1829
|
for (const part of parts) {
|
|
1697
|
-
if (part.type !== APPROVAL_PART) {
|
|
1830
|
+
if (part.type !== APPROVAL_PART && part.type !== SETTLED_PART) {
|
|
1698
1831
|
continue;
|
|
1699
1832
|
}
|
|
1700
1833
|
const data = part.data;
|
|
1701
|
-
if (!isRecord2(data) || typeof data.id !== "string"
|
|
1834
|
+
if (!isRecord2(data) || typeof data.id !== "string") {
|
|
1702
1835
|
continue;
|
|
1703
1836
|
}
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1837
|
+
const approval = entry(data.id);
|
|
1838
|
+
if (part.type === APPROVAL_PART) {
|
|
1839
|
+
if (typeof data.approver !== "string") {
|
|
1840
|
+
continue;
|
|
1841
|
+
}
|
|
1842
|
+
approval.approver = data.approver;
|
|
1843
|
+
approval.expiresAt = typeof data.expiresAt === "string" ? data.expiresAt : null;
|
|
1844
|
+
approval.reason = typeof data.reason === "string" ? data.reason : null;
|
|
1845
|
+
continue;
|
|
1846
|
+
}
|
|
1847
|
+
if (typeof data.status !== "string" || !SETTLED_STATUSES.includes(data.status)) {
|
|
1848
|
+
continue;
|
|
1849
|
+
}
|
|
1850
|
+
approval.status = data.status;
|
|
1851
|
+
if (approval.approver === null && typeof data.approver === "string") {
|
|
1852
|
+
approval.approver = data.approver;
|
|
1853
|
+
}
|
|
1854
|
+
approval.remember = data.remember === true;
|
|
1855
|
+
approval.decidedBy = typeof data.decidedBy === "string" ? data.decidedBy : null;
|
|
1856
|
+
approval.decidedVia = typeof data.decidedVia === "string" ? data.decidedVia : null;
|
|
1857
|
+
approval.decisionReason = typeof data.reason === "string" ? data.reason : null;
|
|
1709
1858
|
}
|
|
1710
1859
|
return out;
|
|
1711
1860
|
}
|
|
1712
1861
|
__name(readApprovals, "readApprovals");
|
|
1862
|
+
function approvalOf(parts, call) {
|
|
1863
|
+
if (parts === void 0 || parts.approver === null) {
|
|
1864
|
+
return null;
|
|
1865
|
+
}
|
|
1866
|
+
return {
|
|
1867
|
+
approver: parts.approver,
|
|
1868
|
+
expiresAt: parts.expiresAt,
|
|
1869
|
+
reason: parts.reason,
|
|
1870
|
+
status: parts.status ?? statusFromPart(call),
|
|
1871
|
+
remember: parts.remember,
|
|
1872
|
+
decidedBy: parts.decidedBy,
|
|
1873
|
+
decidedVia: parts.decidedVia,
|
|
1874
|
+
decisionReason: parts.decisionReason
|
|
1875
|
+
};
|
|
1876
|
+
}
|
|
1877
|
+
__name(approvalOf, "approvalOf");
|
|
1878
|
+
function statusFromPart(call) {
|
|
1879
|
+
if (call.state === "output-denied") {
|
|
1880
|
+
return "rejected";
|
|
1881
|
+
}
|
|
1882
|
+
if (call.state === "output-available" || call.state === "output-error") {
|
|
1883
|
+
return "approved";
|
|
1884
|
+
}
|
|
1885
|
+
return "pending";
|
|
1886
|
+
}
|
|
1887
|
+
__name(statusFromPart, "statusFromPart");
|
|
1713
1888
|
function readUiComponent(part) {
|
|
1714
1889
|
const data = part.data;
|
|
1715
1890
|
if (!isRecord2(data) || typeof data.component !== "string") {
|
|
@@ -2095,10 +2270,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2095
2270
|
}, [
|
|
2096
2271
|
settle
|
|
2097
2272
|
]);
|
|
2098
|
-
const approve = (0, import_react5.useCallback)((toolCallId) => {
|
|
2273
|
+
const approve = (0, import_react5.useCallback)((toolCallId, options2) => {
|
|
2099
2274
|
const onApprove = latest.current.options.onApprove;
|
|
2100
2275
|
if (onApprove) {
|
|
2101
|
-
settle(toolCallId, "approve", () => onApprove(toolCallId));
|
|
2276
|
+
settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
|
|
2102
2277
|
}
|
|
2103
2278
|
}, [
|
|
2104
2279
|
settle
|
|
@@ -3073,8 +3248,51 @@ function useToolCatalog(options) {
|
|
|
3073
3248
|
}
|
|
3074
3249
|
__name(useToolCatalog, "useToolCatalog");
|
|
3075
3250
|
|
|
3251
|
+
// src/approvals/countdown.ts
|
|
3252
|
+
var import_react9 = require("react");
|
|
3253
|
+
function approvalCountdown(expiresAt, now = Date.now()) {
|
|
3254
|
+
const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
|
|
3255
|
+
if (!Number.isFinite(deadline)) {
|
|
3256
|
+
return {
|
|
3257
|
+
remainingMs: null,
|
|
3258
|
+
isExpired: false
|
|
3259
|
+
};
|
|
3260
|
+
}
|
|
3261
|
+
const remainingMs = Math.max(0, deadline - now);
|
|
3262
|
+
return {
|
|
3263
|
+
remainingMs,
|
|
3264
|
+
isExpired: remainingMs === 0
|
|
3265
|
+
};
|
|
3266
|
+
}
|
|
3267
|
+
__name(approvalCountdown, "approvalCountdown");
|
|
3268
|
+
function useApprovalCountdown(expiresAt, options = {}) {
|
|
3269
|
+
const { intervalMs = 1e3 } = options;
|
|
3270
|
+
const nowRef = (0, import_react9.useRef)(options.now ?? Date.now);
|
|
3271
|
+
nowRef.current = options.now ?? Date.now;
|
|
3272
|
+
const [state, setState] = (0, import_react9.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
|
|
3273
|
+
(0, import_react9.useEffect)(() => {
|
|
3274
|
+
const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
|
|
3275
|
+
const first = read();
|
|
3276
|
+
setState(first);
|
|
3277
|
+
if (first.remainingMs === null || first.isExpired) {
|
|
3278
|
+
return;
|
|
3279
|
+
}
|
|
3280
|
+
const timer = setInterval(() => {
|
|
3281
|
+
const next = read();
|
|
3282
|
+
setState(next);
|
|
3283
|
+
if (next.isExpired) clearInterval(timer);
|
|
3284
|
+
}, intervalMs);
|
|
3285
|
+
return () => clearInterval(timer);
|
|
3286
|
+
}, [
|
|
3287
|
+
expiresAt,
|
|
3288
|
+
intervalMs
|
|
3289
|
+
]);
|
|
3290
|
+
return state;
|
|
3291
|
+
}
|
|
3292
|
+
__name(useApprovalCountdown, "useApprovalCountdown");
|
|
3293
|
+
|
|
3076
3294
|
// src/stored-message-to-ui-message.ts
|
|
3077
|
-
var
|
|
3295
|
+
var import_nestjs_agent_core3 = require("@dudousxd/nestjs-agent-core");
|
|
3078
3296
|
function isRefusal(result) {
|
|
3079
3297
|
if (result.denied === true) {
|
|
3080
3298
|
return true;
|
|
@@ -3087,7 +3305,7 @@ function refusalReason(result) {
|
|
|
3087
3305
|
const { output } = result;
|
|
3088
3306
|
if (output !== null && typeof output === "object" && "reason" in output) {
|
|
3089
3307
|
const reason = output.reason;
|
|
3090
|
-
return typeof reason === "string" && reason !==
|
|
3308
|
+
return typeof reason === "string" && reason !== import_nestjs_agent_core3.DEFAULT_REFUSAL_REASON ? reason : void 0;
|
|
3091
3309
|
}
|
|
3092
3310
|
return void 0;
|
|
3093
3311
|
}
|
|
@@ -3132,6 +3350,41 @@ function storedMessageToUiMessage(message) {
|
|
|
3132
3350
|
}
|
|
3133
3351
|
});
|
|
3134
3352
|
}
|
|
3353
|
+
for (const approval of message.approvals ?? []) {
|
|
3354
|
+
parts.push({
|
|
3355
|
+
type: "data-approval-requested",
|
|
3356
|
+
id: approval.toolCallId,
|
|
3357
|
+
data: {
|
|
3358
|
+
id: approval.toolCallId,
|
|
3359
|
+
approver: approval.approver,
|
|
3360
|
+
...approval.expiresAt !== void 0 ? {
|
|
3361
|
+
expiresAt: approval.expiresAt
|
|
3362
|
+
} : {}
|
|
3363
|
+
}
|
|
3364
|
+
});
|
|
3365
|
+
if (approval.status !== "pending") {
|
|
3366
|
+
parts.push({
|
|
3367
|
+
type: "data-approval-settled",
|
|
3368
|
+
id: approval.toolCallId,
|
|
3369
|
+
data: {
|
|
3370
|
+
id: approval.toolCallId,
|
|
3371
|
+
status: approval.status,
|
|
3372
|
+
...approval.decidedBy !== void 0 ? {
|
|
3373
|
+
decidedBy: approval.decidedBy
|
|
3374
|
+
} : {},
|
|
3375
|
+
...approval.decidedVia !== void 0 ? {
|
|
3376
|
+
decidedVia: approval.decidedVia
|
|
3377
|
+
} : {},
|
|
3378
|
+
...approval.remember === true ? {
|
|
3379
|
+
remember: true
|
|
3380
|
+
} : {},
|
|
3381
|
+
...approval.reason !== void 0 ? {
|
|
3382
|
+
reason: approval.reason
|
|
3383
|
+
} : {}
|
|
3384
|
+
}
|
|
3385
|
+
});
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3135
3388
|
for (const call of message.toolCalls ?? []) {
|
|
3136
3389
|
const result = message.toolResults?.find((candidate) => candidate.id === call.id);
|
|
3137
3390
|
const toolKind2 = call.kind;
|
|
@@ -3233,21 +3486,21 @@ function sumUsage(rows) {
|
|
|
3233
3486
|
__name(sumUsage, "sumUsage");
|
|
3234
3487
|
|
|
3235
3488
|
// src/use-agent-chat.ts
|
|
3236
|
-
var
|
|
3237
|
-
var
|
|
3489
|
+
var import_react10 = require("@ai-sdk/react");
|
|
3490
|
+
var import_react11 = require("react");
|
|
3238
3491
|
function useAgentChat(options) {
|
|
3239
|
-
const latest = (0,
|
|
3492
|
+
const latest = (0, import_react11.useRef)(options);
|
|
3240
3493
|
latest.current = options;
|
|
3241
|
-
const [runId, setRunId] = (0,
|
|
3242
|
-
const runIdRef = (0,
|
|
3494
|
+
const [runId, setRunId] = (0, import_react11.useState)(options.resumeRunId);
|
|
3495
|
+
const runIdRef = (0, import_react11.useRef)(runId);
|
|
3243
3496
|
runIdRef.current = runId;
|
|
3244
|
-
const settlingRunIdRef = (0,
|
|
3245
|
-
const autoResumeRunIdRef = (0,
|
|
3246
|
-
const [autoResume, setAutoResume] = (0,
|
|
3247
|
-
const [activeRunId, setActiveRunId] = (0,
|
|
3248
|
-
const regenerateNext = (0,
|
|
3249
|
-
const createdThreadId = (0,
|
|
3250
|
-
const client = (0,
|
|
3497
|
+
const settlingRunIdRef = (0, import_react11.useRef)(void 0);
|
|
3498
|
+
const autoResumeRunIdRef = (0, import_react11.useRef)(void 0);
|
|
3499
|
+
const [autoResume, setAutoResume] = (0, import_react11.useState)(false);
|
|
3500
|
+
const [activeRunId, setActiveRunId] = (0, import_react11.useState)(null);
|
|
3501
|
+
const regenerateNext = (0, import_react11.useRef)(false);
|
|
3502
|
+
const createdThreadId = (0, import_react11.useRef)(void 0);
|
|
3503
|
+
const client = (0, import_react11.useMemo)(() => {
|
|
3251
3504
|
if (options.client) return options.client;
|
|
3252
3505
|
return new AgentClient({
|
|
3253
3506
|
...options.baseUrl !== void 0 ? {
|
|
@@ -3262,7 +3515,7 @@ function useAgentChat(options) {
|
|
|
3262
3515
|
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
3263
3516
|
});
|
|
3264
3517
|
}, []);
|
|
3265
|
-
(0,
|
|
3518
|
+
(0, import_react11.useEffect)(() => {
|
|
3266
3519
|
if (!options.resume || options.threadId === void 0) return;
|
|
3267
3520
|
let cancelled = false;
|
|
3268
3521
|
const threadId = options.threadId;
|
|
@@ -3282,7 +3535,7 @@ function useAgentChat(options) {
|
|
|
3282
3535
|
options.resume,
|
|
3283
3536
|
options.threadId
|
|
3284
3537
|
]);
|
|
3285
|
-
const transport = (0,
|
|
3538
|
+
const transport = (0, import_react11.useMemo)(() => {
|
|
3286
3539
|
function onMeta(meta) {
|
|
3287
3540
|
settlingRunIdRef.current = meta.runId;
|
|
3288
3541
|
setRunId(meta.runId);
|
|
@@ -3331,8 +3584,8 @@ function useAgentChat(options) {
|
|
|
3331
3584
|
}, "onAttemptStart")
|
|
3332
3585
|
});
|
|
3333
3586
|
}, []);
|
|
3334
|
-
const backgroundRef = (0,
|
|
3335
|
-
const chat = (0,
|
|
3587
|
+
const backgroundRef = (0, import_react11.useRef)(() => Promise.resolve());
|
|
3588
|
+
const chat = (0, import_react10.useChat)({
|
|
3336
3589
|
transport,
|
|
3337
3590
|
resume: options.resumeRunId !== void 0 || autoResume,
|
|
3338
3591
|
...options.threadId !== void 0 ? {
|
|
@@ -3362,13 +3615,13 @@ function useAgentChat(options) {
|
|
|
3362
3615
|
}
|
|
3363
3616
|
}, "onFinish")
|
|
3364
3617
|
});
|
|
3365
|
-
const chatRef = (0,
|
|
3618
|
+
const chatRef = (0, import_react11.useRef)(chat);
|
|
3366
3619
|
chatRef.current = chat;
|
|
3367
|
-
const turnInFlight = (0,
|
|
3368
|
-
const isTurnInFlight = (0,
|
|
3620
|
+
const turnInFlight = (0, import_react11.useRef)(false);
|
|
3621
|
+
const isTurnInFlight = (0, import_react11.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
|
|
3369
3622
|
transport
|
|
3370
3623
|
]);
|
|
3371
|
-
const sendMessage = (0,
|
|
3624
|
+
const sendMessage = (0, import_react11.useCallback)(async (...args) => {
|
|
3372
3625
|
if (isTurnInFlight()) return;
|
|
3373
3626
|
turnInFlight.current = true;
|
|
3374
3627
|
try {
|
|
@@ -3379,15 +3632,15 @@ function useAgentChat(options) {
|
|
|
3379
3632
|
}, [
|
|
3380
3633
|
isTurnInFlight
|
|
3381
3634
|
]);
|
|
3382
|
-
const addToolResult = (0,
|
|
3635
|
+
const addToolResult = (0, import_react11.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
|
|
3383
3636
|
tool,
|
|
3384
3637
|
toolCallId,
|
|
3385
3638
|
output
|
|
3386
3639
|
}), []);
|
|
3387
|
-
const [threads, setThreads] = (0,
|
|
3388
|
-
const [quota, setQuota] = (0,
|
|
3389
|
-
const [backgroundRuns, setBackgroundRuns] = (0,
|
|
3390
|
-
const refreshBackground = (0,
|
|
3640
|
+
const [threads, setThreads] = (0, import_react11.useState)([]);
|
|
3641
|
+
const [quota, setQuota] = (0, import_react11.useState)(null);
|
|
3642
|
+
const [backgroundRuns, setBackgroundRuns] = (0, import_react11.useState)([]);
|
|
3643
|
+
const refreshBackground = (0, import_react11.useCallback)(async () => {
|
|
3391
3644
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
3392
3645
|
if (threadId === void 0) {
|
|
3393
3646
|
return;
|
|
@@ -3412,7 +3665,7 @@ function useAgentChat(options) {
|
|
|
3412
3665
|
]);
|
|
3413
3666
|
backgroundRef.current = refreshBackground;
|
|
3414
3667
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
3415
|
-
(0,
|
|
3668
|
+
(0, import_react11.useEffect)(() => {
|
|
3416
3669
|
if (options.background !== true || options.threadId === void 0) {
|
|
3417
3670
|
return;
|
|
3418
3671
|
}
|
|
@@ -3422,7 +3675,7 @@ function useAgentChat(options) {
|
|
|
3422
3675
|
options.threadId,
|
|
3423
3676
|
refreshBackground
|
|
3424
3677
|
]);
|
|
3425
|
-
(0,
|
|
3678
|
+
(0, import_react11.useEffect)(() => {
|
|
3426
3679
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
3427
3680
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
3428
3681
|
return;
|
|
@@ -3433,26 +3686,26 @@ function useAgentChat(options) {
|
|
|
3433
3686
|
isWorking,
|
|
3434
3687
|
refreshBackground
|
|
3435
3688
|
]);
|
|
3436
|
-
const loadThreads = (0,
|
|
3689
|
+
const loadThreads = (0, import_react11.useCallback)(async () => {
|
|
3437
3690
|
const list = await client.listThreads();
|
|
3438
3691
|
setThreads(list);
|
|
3439
3692
|
return list;
|
|
3440
3693
|
}, [
|
|
3441
3694
|
client
|
|
3442
3695
|
]);
|
|
3443
|
-
const loadThread = (0,
|
|
3696
|
+
const loadThread = (0, import_react11.useCallback)((id) => client.getThread(id), [
|
|
3444
3697
|
client
|
|
3445
3698
|
]);
|
|
3446
|
-
const deleteThread = (0,
|
|
3699
|
+
const deleteThread = (0, import_react11.useCallback)(async (id) => {
|
|
3447
3700
|
await client.deleteThread(id);
|
|
3448
3701
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
3449
3702
|
}, [
|
|
3450
3703
|
client
|
|
3451
3704
|
]);
|
|
3452
|
-
const forkThread = (0,
|
|
3705
|
+
const forkThread = (0, import_react11.useCallback)((threadId, messageId) => client.forkFromMessage(threadId, messageId), [
|
|
3453
3706
|
client
|
|
3454
3707
|
]);
|
|
3455
|
-
const renameThread = (0,
|
|
3708
|
+
const renameThread = (0, import_react11.useCallback)(async (id, title) => {
|
|
3456
3709
|
await client.renameThread(id, title);
|
|
3457
3710
|
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
3458
3711
|
...thread,
|
|
@@ -3461,24 +3714,24 @@ function useAgentChat(options) {
|
|
|
3461
3714
|
}, [
|
|
3462
3715
|
client
|
|
3463
3716
|
]);
|
|
3464
|
-
const promoteThread = (0,
|
|
3717
|
+
const promoteThread = (0, import_react11.useCallback)(async (id) => {
|
|
3465
3718
|
await client.promoteThread(id);
|
|
3466
3719
|
await loadThreads();
|
|
3467
3720
|
}, [
|
|
3468
3721
|
client,
|
|
3469
3722
|
loadThreads
|
|
3470
3723
|
]);
|
|
3471
|
-
const truncateFromMessage = (0,
|
|
3724
|
+
const truncateFromMessage = (0, import_react11.useCallback)((threadId, messageId) => client.truncateFromMessage(threadId, messageId).then(() => void 0), [
|
|
3472
3725
|
client
|
|
3473
3726
|
]);
|
|
3474
|
-
const loadQuota = (0,
|
|
3727
|
+
const loadQuota = (0, import_react11.useCallback)(async () => {
|
|
3475
3728
|
const today = await client.getQuotaToday();
|
|
3476
3729
|
setQuota(today);
|
|
3477
3730
|
return today;
|
|
3478
3731
|
}, [
|
|
3479
3732
|
client
|
|
3480
3733
|
]);
|
|
3481
|
-
const cancel = (0,
|
|
3734
|
+
const cancel = (0, import_react11.useCallback)(async () => {
|
|
3482
3735
|
chatRef.current.stop();
|
|
3483
3736
|
const activeRunId2 = runIdRef.current;
|
|
3484
3737
|
if (activeRunId2) {
|
|
@@ -3490,24 +3743,33 @@ function useAgentChat(options) {
|
|
|
3490
3743
|
}, [
|
|
3491
3744
|
client
|
|
3492
3745
|
]);
|
|
3493
|
-
const approve = (0,
|
|
3746
|
+
const approve = (0, import_react11.useCallback)(async ({ toolCallId, remember, via }) => {
|
|
3494
3747
|
await client.approveToolCall({
|
|
3495
|
-
toolCallId
|
|
3748
|
+
toolCallId,
|
|
3749
|
+
...remember === true ? {
|
|
3750
|
+
remember: true
|
|
3751
|
+
} : {},
|
|
3752
|
+
...via !== void 0 ? {
|
|
3753
|
+
via
|
|
3754
|
+
} : {}
|
|
3496
3755
|
});
|
|
3497
3756
|
}, [
|
|
3498
3757
|
client
|
|
3499
3758
|
]);
|
|
3500
|
-
const reject = (0,
|
|
3759
|
+
const reject = (0, import_react11.useCallback)(async ({ toolCallId, reason, via }) => {
|
|
3501
3760
|
await client.rejectToolCall({
|
|
3502
3761
|
toolCallId,
|
|
3503
3762
|
...reason !== void 0 ? {
|
|
3504
3763
|
reason
|
|
3764
|
+
} : {},
|
|
3765
|
+
...via !== void 0 ? {
|
|
3766
|
+
via
|
|
3505
3767
|
} : {}
|
|
3506
3768
|
});
|
|
3507
3769
|
}, [
|
|
3508
3770
|
client
|
|
3509
3771
|
]);
|
|
3510
|
-
const answer = (0,
|
|
3772
|
+
const answer = (0, import_react11.useCallback)(async ({ toolCallId, answers }) => {
|
|
3511
3773
|
await client.answerToolCall({
|
|
3512
3774
|
toolCallId,
|
|
3513
3775
|
...answers !== void 0 ? {
|
|
@@ -3517,14 +3779,14 @@ function useAgentChat(options) {
|
|
|
3517
3779
|
}, [
|
|
3518
3780
|
client
|
|
3519
3781
|
]);
|
|
3520
|
-
const skip = (0,
|
|
3782
|
+
const skip = (0, import_react11.useCallback)(async ({ toolCallId }) => {
|
|
3521
3783
|
await client.skipToolCall({
|
|
3522
3784
|
toolCallId
|
|
3523
3785
|
});
|
|
3524
3786
|
}, [
|
|
3525
3787
|
client
|
|
3526
3788
|
]);
|
|
3527
|
-
const regenerate = (0,
|
|
3789
|
+
const regenerate = (0, import_react11.useCallback)(() => {
|
|
3528
3790
|
if (isTurnInFlight()) return;
|
|
3529
3791
|
regenerateNext.current = true;
|
|
3530
3792
|
turnInFlight.current = true;
|
|
@@ -3588,8 +3850,10 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
3588
3850
|
MessageList,
|
|
3589
3851
|
SPEECH_LANGUAGES,
|
|
3590
3852
|
applyCompletion,
|
|
3853
|
+
approvalCountdown,
|
|
3591
3854
|
backgroundRunsFromThread,
|
|
3592
3855
|
buildTranscriptBlocks,
|
|
3856
|
+
coerceAnswer,
|
|
3593
3857
|
correctedCallIds,
|
|
3594
3858
|
createSkillsSource,
|
|
3595
3859
|
describeTimestamp,
|
|
@@ -3615,12 +3879,15 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
3615
3879
|
toolCallState,
|
|
3616
3880
|
toolCatalogFrom,
|
|
3617
3881
|
useAgentChat,
|
|
3882
|
+
useApprovalCountdown,
|
|
3618
3883
|
useChatTranscript,
|
|
3619
3884
|
useComposerAutocomplete,
|
|
3620
3885
|
useElapsed,
|
|
3621
3886
|
useSpeechRecognition,
|
|
3622
3887
|
useStickToBottom,
|
|
3623
3888
|
useToolCatalog,
|
|
3624
|
-
useTranscriptItem
|
|
3889
|
+
useTranscriptItem,
|
|
3890
|
+
validateAnswer,
|
|
3891
|
+
validateAnswerValue
|
|
3625
3892
|
});
|
|
3626
3893
|
//# sourceMappingURL=index.cjs.map
|