@dudousxd/nestjs-agent-react 0.8.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 +43 -0
- package/dist/index.cjs +668 -187
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +251 -2
- package/dist/index.d.ts +251 -2
- package/dist/index.js +576 -110
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -126,6 +126,34 @@ function Chat() {
|
|
|
126
126
|
itself. `MessageItemView({ item })` is the default markup for one modelled item — drive the model
|
|
127
127
|
yourself and still render the shipped bubble.
|
|
128
128
|
|
|
129
|
+
### Talking about tool calls
|
|
130
|
+
|
|
131
|
+
Tools declare how they are spoken about on the server (`@AiTool({ presentation })`, served by
|
|
132
|
+
`GET /agent/tools`). `useToolCatalog` fetches that once per client + agent and shares it; hand the
|
|
133
|
+
catalog to the transcript and every tool call carries a `description`, and every tool block an
|
|
134
|
+
`activity` grouping:
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
const chat = useAgentChat({ baseUrl: '/agent' });
|
|
138
|
+
const { catalog } = useToolCatalog({ client: chat.client });
|
|
139
|
+
const transcript = useChatTranscript({ messages: chat.messages, status: chat.status, toolCatalog: catalog });
|
|
140
|
+
|
|
141
|
+
// in a `tools` block:
|
|
142
|
+
block.activity.map((group) => (
|
|
143
|
+
<li key={group.key} data-state={group.status}>
|
|
144
|
+
<MyGlyph name={group.icon} /> {group.phrase} {group.count > 1 ? `×${group.count}` : null}
|
|
145
|
+
</li>
|
|
146
|
+
));
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
| Helper | What it gives you |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `call.description` / `describeToolCall(part, catalog)` | `{ status, phrase, label, icon, tone, detail, confirm, result, error }` — `status` is `running` / `awaiting-approval` / `done` / `failed` / `denied`; `confirm` is the approval prompt filled from the input; `result` the output read through the declared view (`metrics` readings, `table` rows as text, `log` lines, `note` text). |
|
|
152
|
+
| `groupToolActivity(block.roots, { catalog, keyOf?, expandNested?, hideCorrected? })` | Calls folded by key ("Database query ×3"), worst status first, latest phrase, `innerCount` of nested calls. `expandNested` replaces a parent (a code-mode `execute`) with the calls it made; `keyOf` groups by anything else (e.g. `github:search`). |
|
|
153
|
+
| `phraseFor` / `fillTemplate` / `readPath` | The template engine: `{dotted.path}` over the input; an empty slot collapses with its leading space; an undescribed tool reads `Working` / `Done`, never its name. |
|
|
154
|
+
| `resolveResultView` / `inferResultView` | A tool output through a view, as plain data — never a serialized payload. |
|
|
155
|
+
| `toolCallState` / `correctedCallIds` / `isActionCall` | Per-call status, and which failures the model later corrected. |
|
|
156
|
+
|
|
129
157
|
### Where the answer came from
|
|
130
158
|
|
|
131
159
|
RAG persists its retrieval as an auto-executed tool call whose output is `{ passages }` — inject
|
|
@@ -417,6 +445,8 @@ const initialMessages = storedThreadToUiMessages(detail.messages);
|
|
|
417
445
|
calls persists as "thinking…" + tool calls, then a separate final-answer row) into ONE `UIMessage` per
|
|
418
446
|
conversational turn, matching how the live stream renders — and stamps `metadata.usage` on any turn it
|
|
419
447
|
merged. For a single already-atomic row, `storedMessageToUiMessage` maps it 1:1 with no merging.
|
|
448
|
+
Persisted reasoning comes back as a `reasoning` part before the text (with its duration), and
|
|
449
|
+
persisted pushed components as `data-ui` parts, so a reloaded thread shows what the live one did.
|
|
420
450
|
|
|
421
451
|
### Attachments and the raw client
|
|
422
452
|
|
|
@@ -452,6 +482,19 @@ Reasoning frames arrive as `reasoning` parts on the message (the transport maps
|
|
|
452
482
|
each run behind a disclosure toggle — open while it streams, folded once the answer lands — with
|
|
453
483
|
`renderReasoning` and `reasoningLabel` slots to override the body and the label.
|
|
454
484
|
|
|
485
|
+
Thinking is timed and persisted: the backend reports each step's `reasoningMs` on `step-finish`, the
|
|
486
|
+
transport stamps it on the reasoning part, and the stored message keeps it, so a reasoning block's
|
|
487
|
+
`durationMs` reads the same live and after a reload. `useElapsed(running)` is the headless ticker
|
|
488
|
+
for while it still streams, and `formatElapsed(ms)` the label:
|
|
489
|
+
|
|
490
|
+
```tsx
|
|
491
|
+
function ThoughtFor({ block }: { block: TranscriptReasoningBlock }) {
|
|
492
|
+
const elapsed = useElapsed(block.isStreaming);
|
|
493
|
+
const ms = block.isStreaming ? elapsed : block.durationMs;
|
|
494
|
+
return ms === null ? null : <span>Thought for {formatElapsed(ms)}</span>;
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
455
498
|
`ChatInput` surfaces cancel next to send:
|
|
456
499
|
|
|
457
500
|
```tsx
|