@townco/ui 0.1.29 → 0.1.30
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/dist/core/hooks/use-chat-messages.d.ts +1 -0
- package/dist/core/hooks/use-chat-session.d.ts +1 -1
- package/dist/core/hooks/use-tool-calls.d.ts +1 -0
- package/dist/core/schemas/chat.d.ts +3 -1
- package/dist/core/schemas/tool-call.d.ts +1 -0
- package/dist/core/schemas/tool-call.js +2 -0
- package/dist/core/store/chat-store.js +10 -1
- package/dist/gui/components/Message.d.ts +1 -1
- package/dist/gui/components/MessageContent.js +36 -3
- package/dist/sdk/schemas/session.d.ts +13 -12
- package/package.json +3 -3
|
@@ -16,6 +16,7 @@ export declare function useChatMessages(client: AcpClient | null): {
|
|
|
16
16
|
title: string;
|
|
17
17
|
kind: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "switch_mode" | "other";
|
|
18
18
|
status: "pending" | "in_progress" | "completed" | "failed";
|
|
19
|
+
contentPosition?: number | undefined;
|
|
19
20
|
locations?: {
|
|
20
21
|
path: string;
|
|
21
22
|
line?: number | null | undefined;
|
|
@@ -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" | "
|
|
6
|
+
connectionStatus: "error" | "disconnected" | "connecting" | "connected";
|
|
7
7
|
sessionId: string | null;
|
|
8
8
|
connect: () => Promise<void>;
|
|
9
9
|
loadSession: (sessionIdToLoad: string) => Promise<void>;
|
|
@@ -14,6 +14,7 @@ export declare function useToolCalls(client: AcpClient | null): {
|
|
|
14
14
|
title: string;
|
|
15
15
|
kind: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "switch_mode" | "other";
|
|
16
16
|
status: "pending" | "in_progress" | "completed" | "failed";
|
|
17
|
+
contentPosition?: number | undefined;
|
|
17
18
|
locations?: {
|
|
18
19
|
path: string;
|
|
19
20
|
line?: number | null | undefined;
|
|
@@ -38,6 +38,7 @@ export declare const DisplayMessage: z.ZodObject<{
|
|
|
38
38
|
completed: "completed";
|
|
39
39
|
failed: "failed";
|
|
40
40
|
}>;
|
|
41
|
+
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
41
42
|
locations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
42
43
|
path: z.ZodString;
|
|
43
44
|
line: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -133,6 +134,7 @@ export declare const ChatSessionState: z.ZodObject<{
|
|
|
133
134
|
completed: "completed";
|
|
134
135
|
failed: "failed";
|
|
135
136
|
}>;
|
|
137
|
+
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
136
138
|
locations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
137
139
|
path: z.ZodString;
|
|
138
140
|
line: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -191,8 +193,8 @@ export type ChatSessionState = z.infer<typeof ChatSessionState>;
|
|
|
191
193
|
*/
|
|
192
194
|
export declare const ConnectionStatus: z.ZodEnum<{
|
|
193
195
|
error: "error";
|
|
196
|
+
disconnected: "disconnected";
|
|
194
197
|
connecting: "connecting";
|
|
195
198
|
connected: "connected";
|
|
196
|
-
disconnected: "disconnected";
|
|
197
199
|
}>;
|
|
198
200
|
export type ConnectionStatus = z.infer<typeof ConnectionStatus>;
|
|
@@ -89,6 +89,7 @@ export declare const ToolCallSchema: z.ZodObject<{
|
|
|
89
89
|
completed: "completed";
|
|
90
90
|
failed: "failed";
|
|
91
91
|
}>;
|
|
92
|
+
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
92
93
|
locations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
93
94
|
path: z.ZodString;
|
|
94
95
|
line: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -79,6 +79,8 @@ export const ToolCallSchema = z.object({
|
|
|
79
79
|
kind: ToolCallKindSchema,
|
|
80
80
|
/** Current execution status */
|
|
81
81
|
status: ToolCallStatusSchema,
|
|
82
|
+
/** Position in the message content where this tool call was invoked (character index) */
|
|
83
|
+
contentPosition: z.number().optional(),
|
|
82
84
|
/** Affected file paths with optional line numbers */
|
|
83
85
|
locations: z.array(FileLocationSchema).optional(),
|
|
84
86
|
/** Raw parameters passed to the tool */
|
|
@@ -162,9 +162,18 @@ export const useChatStore = create((set) => ({
|
|
|
162
162
|
const lastAssistantMsg = messages[lastAssistantIndex];
|
|
163
163
|
if (!lastAssistantMsg)
|
|
164
164
|
return state;
|
|
165
|
+
// Track the content position where this tool call was invoked
|
|
166
|
+
const contentPosition = lastAssistantMsg.content.length;
|
|
167
|
+
const toolCallWithPosition = {
|
|
168
|
+
...toolCall,
|
|
169
|
+
contentPosition,
|
|
170
|
+
};
|
|
165
171
|
messages[lastAssistantIndex] = {
|
|
166
172
|
...lastAssistantMsg,
|
|
167
|
-
toolCalls: [
|
|
173
|
+
toolCalls: [
|
|
174
|
+
...(lastAssistantMsg.toolCalls || []),
|
|
175
|
+
toolCallWithPosition,
|
|
176
|
+
],
|
|
168
177
|
};
|
|
169
178
|
return { messages };
|
|
170
179
|
}),
|
|
@@ -7,7 +7,7 @@ import type { DisplayMessage } from "./MessageList.js";
|
|
|
7
7
|
*/
|
|
8
8
|
declare const messageVariants: (props?: ({
|
|
9
9
|
role?: "user" | "assistant" | "system" | null | undefined;
|
|
10
|
-
layout?: "default" | "
|
|
10
|
+
layout?: "default" | "full" | "compact" | null | undefined;
|
|
11
11
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
12
12
|
export interface MessageProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof messageVariants> {
|
|
13
13
|
/**
|
|
@@ -100,9 +100,42 @@ export const MessageContent = React.forwardRef(({ role: roleProp, variant, isStr
|
|
|
100
100
|
const hasThinking = !!thinking;
|
|
101
101
|
// Check if waiting (streaming but no content yet)
|
|
102
102
|
const isWaiting = message.isStreaming && !message.content && message.role === "assistant";
|
|
103
|
-
content = (_jsxs(_Fragment, { children: [message.role === "assistant" && hasThinking && (_jsx(Reasoning, { content: thinking, isStreaming: message.isStreaming, mode: thinkingDisplayStyle, autoCollapse: true })), isWaiting && streamingStartTime && (_jsxs("div", { className: "flex items-center gap-2 opacity-50", children: [_jsx(Loader2Icon, { className: "size-4 animate-spin text-muted-foreground" }), _jsx(WaitingElapsedTime, { startTime: streamingStartTime })] })), message.role === "assistant"
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
content = (_jsxs(_Fragment, { children: [message.role === "assistant" && hasThinking && (_jsx(Reasoning, { content: thinking, isStreaming: message.isStreaming, mode: thinkingDisplayStyle, autoCollapse: true })), isWaiting && streamingStartTime && (_jsxs("div", { className: "flex items-center gap-2 opacity-50", children: [_jsx(Loader2Icon, { className: "size-4 animate-spin text-muted-foreground" }), _jsx(WaitingElapsedTime, { startTime: streamingStartTime })] })), message.role === "assistant" ? ((() => {
|
|
104
|
+
// Sort tool calls by content position
|
|
105
|
+
const sortedToolCalls = (message.toolCalls || [])
|
|
106
|
+
.slice()
|
|
107
|
+
.sort((a, b) => (a.contentPosition ?? Infinity) -
|
|
108
|
+
(b.contentPosition ?? Infinity));
|
|
109
|
+
// If no tool calls or they don't have positions, render old way
|
|
110
|
+
if (sortedToolCalls.length === 0 ||
|
|
111
|
+
!sortedToolCalls.some((tc) => tc.contentPosition !== undefined)) {
|
|
112
|
+
return (_jsxs(_Fragment, { children: [sortedToolCalls.length > 0 && (_jsx("div", { className: "flex flex-col gap-2 mb-3", children: sortedToolCalls.map((toolCall) => (_jsx(ToolCall, { toolCall: toolCall }, toolCall.id))) })), _jsx(Response, { content: message.content, isStreaming: message.isStreaming, showEmpty: false })] }));
|
|
113
|
+
}
|
|
114
|
+
// Render content interleaved with tool calls
|
|
115
|
+
const elements = [];
|
|
116
|
+
let currentPosition = 0;
|
|
117
|
+
sortedToolCalls.forEach((toolCall) => {
|
|
118
|
+
const position = toolCall.contentPosition ?? message.content.length;
|
|
119
|
+
// Add text before this tool call
|
|
120
|
+
if (position > currentPosition) {
|
|
121
|
+
const textChunk = message.content.slice(currentPosition, position);
|
|
122
|
+
if (textChunk) {
|
|
123
|
+
elements.push(_jsx(Response, { content: textChunk, isStreaming: false, showEmpty: false }, `text-before-${toolCall.id}`));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Add the tool call
|
|
127
|
+
elements.push(_jsx("div", { className: "my-2", children: _jsx(ToolCall, { toolCall: toolCall }) }, `tool-${toolCall.id}`));
|
|
128
|
+
currentPosition = position;
|
|
129
|
+
});
|
|
130
|
+
// Add remaining text after the last tool call
|
|
131
|
+
if (currentPosition < message.content.length) {
|
|
132
|
+
const remainingText = message.content.slice(currentPosition);
|
|
133
|
+
if (remainingText) {
|
|
134
|
+
elements.push(_jsx(Response, { content: remainingText, isStreaming: message.isStreaming, showEmpty: false }, "text-end"));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return _jsx(_Fragment, { children: elements });
|
|
138
|
+
})()) : (_jsx("div", { className: "whitespace-pre-wrap", children: message.content })), message.role === "assistant" && message.tokenUsage && (_jsx("div", { className: "mt-3 pt-2 border-t border-border/30 text-xs text-muted-foreground/60", children: _jsxs("span", { children: ["Context:", " ", formatTokenPercentage(message.tokenUsage.totalTokens ?? 0, currentModel ?? undefined), " ", "(", (message.tokenUsage.totalTokens ?? 0).toLocaleString(), " ", "tokens)"] }) }))] }));
|
|
106
139
|
}
|
|
107
140
|
return (_jsx("div", { ref: ref, className: cn(messageContentVariants({ role, variant }), isStreaming && "animate-pulse-subtle", className), ...props, children: content }));
|
|
108
141
|
});
|
|
@@ -4,12 +4,12 @@ import { z } from "zod";
|
|
|
4
4
|
*/
|
|
5
5
|
export declare const SessionStatus: z.ZodEnum<{
|
|
6
6
|
error: "error";
|
|
7
|
-
|
|
7
|
+
disconnected: "disconnected";
|
|
8
8
|
connecting: "connecting";
|
|
9
9
|
connected: "connected";
|
|
10
|
+
idle: "idle";
|
|
10
11
|
active: "active";
|
|
11
12
|
streaming: "streaming";
|
|
12
|
-
disconnected: "disconnected";
|
|
13
13
|
}>;
|
|
14
14
|
export type SessionStatus = z.infer<typeof SessionStatus>;
|
|
15
15
|
/**
|
|
@@ -41,12 +41,12 @@ export declare const Session: z.ZodObject<{
|
|
|
41
41
|
id: z.ZodString;
|
|
42
42
|
status: z.ZodEnum<{
|
|
43
43
|
error: "error";
|
|
44
|
-
|
|
44
|
+
disconnected: "disconnected";
|
|
45
45
|
connecting: "connecting";
|
|
46
46
|
connected: "connected";
|
|
47
|
+
idle: "idle";
|
|
47
48
|
active: "active";
|
|
48
49
|
streaming: "streaming";
|
|
49
|
-
disconnected: "disconnected";
|
|
50
50
|
}>;
|
|
51
51
|
config: z.ZodObject<{
|
|
52
52
|
agentPath: z.ZodString;
|
|
@@ -109,12 +109,12 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
109
109
|
sessionId: z.ZodString;
|
|
110
110
|
status: z.ZodOptional<z.ZodEnum<{
|
|
111
111
|
error: "error";
|
|
112
|
-
|
|
112
|
+
disconnected: "disconnected";
|
|
113
113
|
connecting: "connecting";
|
|
114
114
|
connected: "connected";
|
|
115
|
+
idle: "idle";
|
|
115
116
|
active: "active";
|
|
116
117
|
streaming: "streaming";
|
|
117
|
-
disconnected: "disconnected";
|
|
118
118
|
}>>;
|
|
119
119
|
message: z.ZodOptional<z.ZodObject<{
|
|
120
120
|
id: z.ZodString;
|
|
@@ -176,6 +176,7 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
176
176
|
completed: "completed";
|
|
177
177
|
failed: "failed";
|
|
178
178
|
}>;
|
|
179
|
+
contentPosition: z.ZodOptional<z.ZodNumber>;
|
|
179
180
|
locations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
180
181
|
path: z.ZodString;
|
|
181
182
|
line: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -215,12 +216,12 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
215
216
|
sessionId: z.ZodString;
|
|
216
217
|
status: z.ZodOptional<z.ZodEnum<{
|
|
217
218
|
error: "error";
|
|
218
|
-
|
|
219
|
+
disconnected: "disconnected";
|
|
219
220
|
connecting: "connecting";
|
|
220
221
|
connected: "connected";
|
|
222
|
+
idle: "idle";
|
|
221
223
|
active: "active";
|
|
222
224
|
streaming: "streaming";
|
|
223
|
-
disconnected: "disconnected";
|
|
224
225
|
}>>;
|
|
225
226
|
message: z.ZodOptional<z.ZodObject<{
|
|
226
227
|
id: z.ZodString;
|
|
@@ -306,12 +307,12 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
306
307
|
sessionId: z.ZodString;
|
|
307
308
|
status: z.ZodOptional<z.ZodEnum<{
|
|
308
309
|
error: "error";
|
|
309
|
-
|
|
310
|
+
disconnected: "disconnected";
|
|
310
311
|
connecting: "connecting";
|
|
311
312
|
connected: "connected";
|
|
313
|
+
idle: "idle";
|
|
312
314
|
active: "active";
|
|
313
315
|
streaming: "streaming";
|
|
314
|
-
disconnected: "disconnected";
|
|
315
316
|
}>>;
|
|
316
317
|
message: z.ZodOptional<z.ZodObject<{
|
|
317
318
|
id: z.ZodString;
|
|
@@ -362,12 +363,12 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
362
363
|
sessionId: z.ZodString;
|
|
363
364
|
status: z.ZodOptional<z.ZodEnum<{
|
|
364
365
|
error: "error";
|
|
365
|
-
|
|
366
|
+
disconnected: "disconnected";
|
|
366
367
|
connecting: "connecting";
|
|
367
368
|
connected: "connected";
|
|
369
|
+
idle: "idle";
|
|
368
370
|
active: "active";
|
|
369
371
|
streaming: "streaming";
|
|
370
|
-
disconnected: "disconnected";
|
|
371
372
|
}>>;
|
|
372
373
|
message: z.ZodOptional<z.ZodObject<{
|
|
373
374
|
id: z.ZodString;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@townco/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
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.
|
|
43
|
+
"@townco/core": "0.0.8",
|
|
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.
|
|
65
|
+
"@townco/tsconfig": "0.1.27",
|
|
66
66
|
"@types/node": "^24.10.0",
|
|
67
67
|
"@types/react": "^19.2.2",
|
|
68
68
|
"ink": "^6.4.0",
|