@dudousxd/nestjs-agent-react 0.25.0 → 0.26.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 +16 -6
- package/dist/index.cjs +20 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -3
- package/dist/index.d.ts +22 -3
- package/dist/index.js +17 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ handlers passed. On top of the AI SDK chat it returns:
|
|
|
42
42
|
| `quota` / `blocked` | `useQuota`'s state, and the window blocking sends (the `blocked` option overrides it). |
|
|
43
43
|
| `approve` / `reject` / `answer` / `skip` | `({ toolCallId, … })` — the same object shape the transcript's handlers take. |
|
|
44
44
|
| `fork` / `truncateFrom` / `promote` | `({ messageId, threadId? })` / `({ threadId? })`, defaulting to this chat's thread. |
|
|
45
|
-
| `cancel`, `regenerate`, `getThreadId`, `backend`, `runId`, `activeRunId`, `isLoadingHistory`, `connection`, `background` | — |
|
|
45
|
+
| `cancel`, `regenerate`, `getThreadId`, `backend`, `runId`, `activeRunId`, `isLoadingHistory`, `connection`, `background` | — `isLoadingHistory` is already `true` on the first render with a `threadId`, so a page can show a skeleton instead of flashing its empty state |
|
|
46
46
|
|
|
47
47
|
Threads (list, rename, delete) are `useThreads()`; the granular hooks stay the escape hatch.
|
|
48
48
|
|
|
@@ -170,6 +170,8 @@ catalog to the transcript and every tool call carries a `description`, and every
|
|
|
170
170
|
```tsx
|
|
171
171
|
const chat = useAgentChat();
|
|
172
172
|
const { catalog } = useToolCatalog(); // the provider's backend; `{ backend, agent }` to override
|
|
173
|
+
// Several agents on one surface: every tool the actor reaches through any of them.
|
|
174
|
+
const all = useToolCatalog({ agent: ALL_AGENTS }); // GET /agent/tools?agent=*
|
|
173
175
|
const transcript = useChatTranscript({ messages: chat.messages, status: chat.status, toolCatalog: catalog });
|
|
174
176
|
|
|
175
177
|
// in a `tools` block:
|
|
@@ -253,11 +255,19 @@ ones a human actually decided. A settled set keeps its block (`isPending: false`
|
|
|
253
255
|
`selected` showing what was chosen), so one piece of markup renders both states.
|
|
254
256
|
|
|
255
257
|
Detection is structural rather than by tool name — an intake and an `ask` persist under whatever
|
|
256
|
-
name their row holds
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
name their row holds.
|
|
259
|
+
|
|
260
|
+
**Decisions settle through the backend by default.** `onApprove`, `onReject`, `onAnswer` and
|
|
261
|
+
`onSkip` left undefined are NOT "off": each defaults to the in-scope backend's call (the enclosing
|
|
262
|
+
`<AgentProvider>`'s `approveToolCall` / `rejectToolCall` / `answerToolCall` / `skipToolCall`), so a
|
|
263
|
+
parked approval or question set is actionable with no wiring. Pass your own handler to route it
|
|
264
|
+
elsewhere, `null` to drop one affordance (`onAnswer: null` keeps question sets as plain tool
|
|
265
|
+
cards), or `readOnly: true` for a surface nobody acts on — an audit view, a shared or archived
|
|
266
|
+
conversation. `readOnly` keeps parked approvals and question sets rendered (with their outcome)
|
|
267
|
+
but offers no approve / reject / answer / skip, edit, fork, regenerate or stop, whatever is in
|
|
268
|
+
scope; `<MessageList readOnly>` and `useAgentChat({ transcript: { readOnly: true } })` take it too.
|
|
269
|
+
|
|
270
|
+
**A tool call awaiting approval.** Every call in a `tools` block carries its own decision:
|
|
261
271
|
|
|
262
272
|
```tsx
|
|
263
273
|
{block.calls.map((call) => (
|
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/index.ts
|
|
32
32
|
var src_exports = {};
|
|
33
33
|
__export(src_exports, {
|
|
34
|
+
ALL_AGENTS: () => import_nestjs_agent_core4.ALL_AGENTS,
|
|
34
35
|
AgentBackendUnsupportedError: () => AgentBackendUnsupportedError,
|
|
35
36
|
AgentChatTransport: () => AgentChatTransport,
|
|
36
37
|
AgentClient: () => AgentClient,
|
|
@@ -3888,7 +3889,7 @@ function useChatTranscript(options) {
|
|
|
3888
3889
|
},
|
|
3889
3890
|
scroll,
|
|
3890
3891
|
stop: {
|
|
3891
|
-
available: isBusy && options.onStop !== void 0,
|
|
3892
|
+
available: isBusy && options.readOnly !== true && options.onStop !== void 0,
|
|
3892
3893
|
isStopping: stopRequested,
|
|
3893
3894
|
stop
|
|
3894
3895
|
}
|
|
@@ -4158,11 +4159,12 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
4158
4159
|
...options.toolCatalog !== void 0 ? {
|
|
4159
4160
|
toolCatalog: options.toolCatalog
|
|
4160
4161
|
} : {},
|
|
4161
|
-
|
|
4162
|
+
// Read-only still lifts question sets into their block, so the outcome shows.
|
|
4163
|
+
...handlers.onAnswer !== void 0 || options.readOnly === true && options.onAnswer !== null ? {
|
|
4162
4164
|
elicitation: {
|
|
4163
4165
|
picked: /* @__PURE__ */ __name((toolCallId, questionId) => picks.get(pickKey(toolCallId, questionId)), "picked"),
|
|
4164
4166
|
pick,
|
|
4165
|
-
canAnswer:
|
|
4167
|
+
canAnswer: handlers.onAnswer !== void 0,
|
|
4166
4168
|
canSkip: handlers.onSkip !== void 0,
|
|
4167
4169
|
answer,
|
|
4168
4170
|
skip,
|
|
@@ -4190,7 +4192,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
4190
4192
|
copy: callbacks.copy
|
|
4191
4193
|
},
|
|
4192
4194
|
edit: {
|
|
4193
|
-
available: isUser && options.editable === true && options.onEditSubmit !== void 0,
|
|
4195
|
+
available: isUser && options.readOnly !== true && options.editable === true && options.onEditSubmit !== void 0,
|
|
4194
4196
|
isEditing,
|
|
4195
4197
|
draft: draft ?? text,
|
|
4196
4198
|
canSave: (draft ?? "").trim().length > 0,
|
|
@@ -4206,11 +4208,11 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
4206
4208
|
}), "getTextareaProps")
|
|
4207
4209
|
},
|
|
4208
4210
|
fork: {
|
|
4209
|
-
available: options.onFork !== void 0,
|
|
4211
|
+
available: options.readOnly !== true && options.onFork !== void 0,
|
|
4210
4212
|
run: callbacks.fork
|
|
4211
4213
|
},
|
|
4212
4214
|
regenerate: {
|
|
4213
|
-
available: isLastAssistant && options.regeneratable === true && options.onRegenerate !== void 0,
|
|
4215
|
+
available: isLastAssistant && options.readOnly !== true && options.regeneratable === true && options.onRegenerate !== void 0,
|
|
4214
4216
|
run: callbacks.regenerate
|
|
4215
4217
|
}
|
|
4216
4218
|
});
|
|
@@ -4219,7 +4221,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
4219
4221
|
}
|
|
4220
4222
|
__name(useTranscriptItems, "useTranscriptItems");
|
|
4221
4223
|
function settleHandlers(options, backend) {
|
|
4222
|
-
const pick = /* @__PURE__ */ __name((own, fallback2) => own === null ? void 0 : own ?? fallback2, "pick");
|
|
4224
|
+
const pick = /* @__PURE__ */ __name((own, fallback2) => options.readOnly === true || own === null ? void 0 : own ?? fallback2, "pick");
|
|
4223
4225
|
return {
|
|
4224
4226
|
onAnswer: pick(options.onAnswer, backend.answerToolCall ? async (input) => {
|
|
4225
4227
|
await backend.answerToolCall?.(input);
|
|
@@ -4512,10 +4514,13 @@ function joinClasses(...entries) {
|
|
|
4512
4514
|
__name(joinClasses, "joinClasses");
|
|
4513
4515
|
|
|
4514
4516
|
// src/components/message-list.tsx
|
|
4515
|
-
function MessageList({ messages, status, renderToolPart, renderToolGroup, renderText, renderReasoning, renderFiles, renderUi, reasoningLabel, getMeta, onFork, editable, onEditSubmit, regeneratable, onRegenerate, getUsage, getCreatedAt, emptyState, typingIndicator, followUps, onFollowUpClick, error, onRetry, classNames }) {
|
|
4517
|
+
function MessageList({ messages, status, renderToolPart, renderToolGroup, renderText, renderReasoning, renderFiles, renderUi, reasoningLabel, getMeta, readOnly, onFork, editable, onEditSubmit, regeneratable, onRegenerate, getUsage, getCreatedAt, emptyState, typingIndicator, followUps, onFollowUpClick, error, onRetry, classNames }) {
|
|
4516
4518
|
const transcript = useChatTranscript({
|
|
4517
4519
|
messages,
|
|
4518
4520
|
status,
|
|
4521
|
+
...readOnly !== void 0 ? {
|
|
4522
|
+
readOnly
|
|
4523
|
+
} : {},
|
|
4519
4524
|
...onFork ? {
|
|
4520
4525
|
onFork
|
|
4521
4526
|
} : {},
|
|
@@ -4980,6 +4985,7 @@ function isPromise(value) {
|
|
|
4980
4985
|
__name(isPromise, "isPromise");
|
|
4981
4986
|
|
|
4982
4987
|
// src/presentation/use-tool-catalog.ts
|
|
4988
|
+
var import_nestjs_agent_core4 = require("@dudousxd/nestjs-agent-core");
|
|
4983
4989
|
var import_react20 = require("react");
|
|
4984
4990
|
var shared2 = /* @__PURE__ */ new WeakMap();
|
|
4985
4991
|
function load2(client, agent) {
|
|
@@ -5099,7 +5105,7 @@ function useApprovalCountdown(expiresAt, options = {}) {
|
|
|
5099
5105
|
__name(useApprovalCountdown, "useApprovalCountdown");
|
|
5100
5106
|
|
|
5101
5107
|
// src/stored-message-to-ui-message.ts
|
|
5102
|
-
var
|
|
5108
|
+
var import_nestjs_agent_core5 = require("@dudousxd/nestjs-agent-core");
|
|
5103
5109
|
function isRefusal(result) {
|
|
5104
5110
|
if (result.denied === true) {
|
|
5105
5111
|
return true;
|
|
@@ -5112,7 +5118,7 @@ function refusalReason(result) {
|
|
|
5112
5118
|
const { output } = result;
|
|
5113
5119
|
if (output !== null && typeof output === "object" && "reason" in output) {
|
|
5114
5120
|
const reason = output.reason;
|
|
5115
|
-
return typeof reason === "string" && reason !==
|
|
5121
|
+
return typeof reason === "string" && reason !== import_nestjs_agent_core5.DEFAULT_REFUSAL_REASON ? reason : void 0;
|
|
5116
5122
|
}
|
|
5117
5123
|
return void 0;
|
|
5118
5124
|
}
|
|
@@ -5382,7 +5388,7 @@ function useAgentChat(options = {}) {
|
|
|
5382
5388
|
const settlingRunIdRef = (0, import_react23.useRef)(void 0);
|
|
5383
5389
|
const autoResumeRunIdRef = (0, import_react23.useRef)(void 0);
|
|
5384
5390
|
const [activeRunId, setActiveRunId] = (0, import_react23.useState)(null);
|
|
5385
|
-
const [
|
|
5391
|
+
const [historyFor, setHistoryFor] = (0, import_react23.useState)(void 0);
|
|
5386
5392
|
const [historyError, setHistoryError] = (0, import_react23.useState)(null);
|
|
5387
5393
|
const [threadModel, setThreadModel] = (0, import_react23.useState)(null);
|
|
5388
5394
|
const [pickedModel, setPickedModel] = (0, import_react23.useState)(void 0);
|
|
@@ -5547,7 +5553,6 @@ function useAgentChat(options = {}) {
|
|
|
5547
5553
|
const wantResume = current.resume !== false && current.resumeRunId === void 0;
|
|
5548
5554
|
if (!wantHistory && !wantResume) return;
|
|
5549
5555
|
let cancelled = false;
|
|
5550
|
-
if (wantHistory) setIsLoadingHistory(true);
|
|
5551
5556
|
client.getThread(threadId).then((thread) => {
|
|
5552
5557
|
if (cancelled || thread == null) return;
|
|
5553
5558
|
const active = thread.activeRunId ?? null;
|
|
@@ -5568,17 +5573,17 @@ function useAgentChat(options = {}) {
|
|
|
5568
5573
|
if (cancelled) return;
|
|
5569
5574
|
setHistoryError(error instanceof Error ? error : new Error(String(error)));
|
|
5570
5575
|
}).finally(() => {
|
|
5571
|
-
if (!cancelled)
|
|
5576
|
+
if (!cancelled) setHistoryFor(threadId);
|
|
5572
5577
|
});
|
|
5573
5578
|
return () => {
|
|
5574
5579
|
cancelled = true;
|
|
5575
|
-
setIsLoadingHistory(false);
|
|
5576
5580
|
};
|
|
5577
5581
|
}, [
|
|
5578
5582
|
client,
|
|
5579
5583
|
chatId,
|
|
5580
5584
|
options.threadId
|
|
5581
5585
|
]);
|
|
5586
|
+
const isLoadingHistory = options.threadId !== void 0 && options.threadId !== createdThreadId.current && options.history !== false && options.initialMessages === void 0 && historyFor !== options.threadId;
|
|
5582
5587
|
const turnInFlight = (0, import_react23.useRef)(false);
|
|
5583
5588
|
const isTurnInFlight = (0, import_react23.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
|
|
5584
5589
|
transport
|
|
@@ -5989,6 +5994,7 @@ var QuotaBlockedError = class extends Error {
|
|
|
5989
5994
|
};
|
|
5990
5995
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5991
5996
|
0 && (module.exports = {
|
|
5997
|
+
ALL_AGENTS,
|
|
5992
5998
|
AgentBackendUnsupportedError,
|
|
5993
5999
|
AgentChatTransport,
|
|
5994
6000
|
AgentClient,
|