@firstlovecenter/ai-chat 0.2.2 → 0.2.3
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/CHANGELOG.md +13 -0
- package/dist/server/index.cjs +38 -0
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +38 -0
- package/dist/server/index.js.map +1 -1
- package/dist/ui/index.cjs +16 -2
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.js +16 -2
- package/dist/ui/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to `@firstlovecenter/ai-chat` are documented here.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.3] — 2026-05-08
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Empty placeholder boxes when the model produces a content-free `present()`** — when the agent loop forces a model through `SELF_VERIFY_REQUIRED` for a question with no data answer (advisory / strategic prompts), some models satisfy the schema with empty strings (`text: ''`, `key_facts: []`, etc.) instead of refusing. The result was a row of empty cyan callout boxes in the chat. Two fixes:
|
|
13
|
+
- **Agent loop** (`runAgent`) — after `present()` returns, if every block in the payload is functionally empty AND the transcript contains assistant text, replace the payload with a synthetic single-block `paragraph_brief` carrying the model's last text. The user gets the model's actual reasoning instead of empty boxes.
|
|
14
|
+
- **UI** (`AnswerBlocks`) — defensive filter: blocks where `isBlockEmpty()` returns true are hidden at render time. Catches the case where the agent-loop salvage didn't apply (e.g. a partial-empty payload mixed with real content).
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **Live "Thinking… (15s)" counter styling** — the elapsed-time chip now renders one tier smaller (`text-xs`) than the surrounding "Thinking…" copy and gets a wider gap (`ml-2`) so it reads as a secondary annotation rather than running into the main text.
|
|
19
|
+
|
|
8
20
|
## [0.2.2] — 2026-05-08
|
|
9
21
|
|
|
10
22
|
### Added
|
|
@@ -79,6 +91,7 @@ Initial public release on npm under `@firstlovecenter/ai-chat`.
|
|
|
79
91
|
- Dual ESM + CJS output via `tsup` with full `.d.ts` (and `.d.cts`) generation.
|
|
80
92
|
- UI bundle gets a post-build `'use client';` directive injection (tsup otherwise strips module-level directives during bundling, breaking RSC consumers that import the UI from a server file).
|
|
81
93
|
|
|
94
|
+
[0.2.3]: https://github.com/firstlovecenter/flc-ai-chat/compare/v0.2.2...v0.2.3
|
|
82
95
|
[0.2.2]: https://github.com/firstlovecenter/flc-ai-chat/compare/v0.2.1...v0.2.2
|
|
83
96
|
[0.2.1]: https://github.com/firstlovecenter/flc-ai-chat/compare/v0.2.0...v0.2.1
|
|
84
97
|
[0.2.0]: https://github.com/firstlovecenter/flc-ai-chat/compare/v0.1.1...v0.2.0
|
package/dist/server/index.cjs
CHANGED
|
@@ -130,8 +130,46 @@ async function runAgent(input) {
|
|
|
130
130
|
transcript
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
|
+
if (allBlocksEmpty(presentPayload.blocks)) {
|
|
134
|
+
const lastAssistantText = [...transcript].reverse().find((e) => e.kind === "assistant_text");
|
|
135
|
+
const text = lastAssistantText?.text.trim();
|
|
136
|
+
if (text) {
|
|
137
|
+
const topic = input.question.length > 80 ? input.question.slice(0, 77) + "..." : input.question;
|
|
138
|
+
presentPayload = {
|
|
139
|
+
blocks: [
|
|
140
|
+
{
|
|
141
|
+
kind: "paragraph_brief",
|
|
142
|
+
topic,
|
|
143
|
+
key_facts: [text]
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
raw_numbers: presentPayload.raw_numbers ?? {}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
133
150
|
return { ok: true, structured: presentPayload, toolCallCount, transcript };
|
|
134
151
|
}
|
|
152
|
+
function allBlocksEmpty(blocks) {
|
|
153
|
+
if (blocks.length === 0) return true;
|
|
154
|
+
return blocks.every((b) => {
|
|
155
|
+
if (b.kind === "paragraph_brief") {
|
|
156
|
+
return b.key_facts.length === 0 || b.key_facts.every((f) => !f.trim());
|
|
157
|
+
}
|
|
158
|
+
if (b.kind === "list") {
|
|
159
|
+
return b.items.length === 0 || b.items.every((i) => !i.trim());
|
|
160
|
+
}
|
|
161
|
+
if (b.kind === "callout") {
|
|
162
|
+
return !b.text.trim();
|
|
163
|
+
}
|
|
164
|
+
if (b.kind === "chart") {
|
|
165
|
+
return b.data.length === 0;
|
|
166
|
+
}
|
|
167
|
+
if (b.kind === "table") {
|
|
168
|
+
return b.rows.length === 0;
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
135
173
|
var ClaudeToolProvider = class {
|
|
136
174
|
id = "claude";
|
|
137
175
|
client;
|