@townco/ui 0.1.32 → 0.1.33

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.
@@ -3,7 +3,7 @@ import type { AcpClient } from "../../sdk/client/index.js";
3
3
  * Hook for managing chat session lifecycle
4
4
  */
5
5
  export declare function useChatSession(client: AcpClient | null, initialSessionId?: string | null): {
6
- connectionStatus: "error" | "disconnected" | "connecting" | "connected";
6
+ connectionStatus: "disconnected" | "connecting" | "connected" | "error";
7
7
  sessionId: string | null;
8
8
  connect: () => Promise<void>;
9
9
  loadSession: (sessionIdToLoad: string) => Promise<void>;
@@ -27,21 +27,39 @@ export function useChatSession(client, initialSessionId) {
27
27
  // Convert SDK message to DisplayMessage
28
28
  // Filter out tool messages as they're not displayed in the chat
29
29
  if (update.message.role !== "tool") {
30
- const displayMessage = {
31
- id: update.message.id,
32
- role: update.message.role,
33
- content: update.message.content
34
- .map((c) => {
35
- if (c.type === "text") {
36
- return c.text;
37
- }
38
- return "";
39
- })
40
- .join(""),
41
- timestamp: update.message.timestamp,
42
- isStreaming: false,
43
- };
44
- addMessage(displayMessage);
30
+ const textContent = update.message.content
31
+ .map((c) => {
32
+ if (c.type === "text") {
33
+ return c.text;
34
+ }
35
+ return "";
36
+ })
37
+ .join("");
38
+ // During session replay, chunks for the same message arrive separately
39
+ // Check if we should append to the last assistant message or create a new one
40
+ const messages = useChatStore.getState().messages;
41
+ const lastMessage = messages[messages.length - 1];
42
+ if (update.message.role === "assistant" &&
43
+ lastMessage?.role === "assistant" &&
44
+ lastMessage.content === "" &&
45
+ textContent) {
46
+ // Append text to existing empty assistant message (created by tool call)
47
+ logger.debug("Appending text to existing assistant message");
48
+ useChatStore.getState().updateMessage(lastMessage.id, {
49
+ content: lastMessage.content + textContent,
50
+ });
51
+ }
52
+ else {
53
+ // Create new message
54
+ const displayMessage = {
55
+ id: update.message.id,
56
+ role: update.message.role,
57
+ content: textContent,
58
+ timestamp: update.message.timestamp,
59
+ isStreaming: false,
60
+ };
61
+ addMessage(displayMessage);
62
+ }
45
63
  }
46
64
  }
47
65
  });
@@ -155,8 +155,23 @@ export const useChatStore = create((set) => ({
155
155
  // Find the most recent assistant message (which should be streaming)
156
156
  const lastAssistantIndex = state.messages.findLastIndex((msg) => msg.role === "assistant");
157
157
  if (lastAssistantIndex === -1) {
158
- logger.warn("No assistant message found to add tool call to");
159
- return state;
158
+ // No assistant message exists yet - create one with the tool call
159
+ // This happens during session replay when a tool call comes before any text
160
+ logger.debug("No assistant message found, creating one for tool call at position 0");
161
+ const newMessage = {
162
+ id: `msg_${Date.now()}_assistant`,
163
+ role: "assistant",
164
+ content: "",
165
+ timestamp: new Date().toISOString(),
166
+ isStreaming: false,
167
+ toolCalls: [
168
+ {
169
+ ...toolCall,
170
+ contentPosition: 0, // Tool call at the start
171
+ },
172
+ ],
173
+ };
174
+ return { messages: [...state.messages, newMessage] };
160
175
  }
161
176
  const messages = [...state.messages];
162
177
  const lastAssistantMsg = messages[lastAssistantIndex];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@townco/ui",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@agentclientprotocol/sdk": "^0.5.1",
43
- "@townco/core": "0.0.10",
43
+ "@townco/core": "0.0.11",
44
44
  "@radix-ui/react-dialog": "^1.1.15",
45
45
  "@radix-ui/react-dropdown-menu": "^2.1.16",
46
46
  "@radix-ui/react-label": "^2.1.8",
@@ -62,7 +62,7 @@
62
62
  },
63
63
  "devDependencies": {
64
64
  "@tailwindcss/postcss": "^4.1.17",
65
- "@townco/tsconfig": "0.1.29",
65
+ "@townco/tsconfig": "0.1.30",
66
66
  "@types/node": "^24.10.0",
67
67
  "@types/react": "^19.2.2",
68
68
  "ink": "^6.4.0",