@townco/ui 0.1.50 → 0.1.52

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.
Files changed (33) hide show
  1. package/dist/core/hooks/index.d.ts +1 -0
  2. package/dist/core/hooks/index.js +1 -0
  3. package/dist/core/hooks/use-chat-messages.d.ts +84 -0
  4. package/dist/core/hooks/use-chat-session.js +20 -3
  5. package/dist/core/hooks/use-subagent-stream.d.ts +28 -0
  6. package/dist/core/hooks/use-subagent-stream.js +254 -0
  7. package/dist/core/hooks/use-tool-calls.d.ts +84 -0
  8. package/dist/core/schemas/chat.d.ts +188 -0
  9. package/dist/core/schemas/tool-call.d.ts +286 -0
  10. package/dist/core/schemas/tool-call.js +53 -0
  11. package/dist/gui/components/ChatEmptyState.d.ts +2 -0
  12. package/dist/gui/components/ChatEmptyState.js +2 -2
  13. package/dist/gui/components/ChatLayout.d.ts +2 -0
  14. package/dist/gui/components/ChatLayout.js +70 -1
  15. package/dist/gui/components/ChatPanelTabContent.js +2 -2
  16. package/dist/gui/components/ChatSecondaryPanel.js +1 -1
  17. package/dist/gui/components/ChatView.js +85 -12
  18. package/dist/gui/components/PanelTabsHeader.js +1 -1
  19. package/dist/gui/components/SubAgentDetails.d.ts +27 -0
  20. package/dist/gui/components/SubAgentDetails.js +121 -0
  21. package/dist/gui/components/TodoList.js +12 -2
  22. package/dist/gui/components/ToolCall.js +41 -8
  23. package/dist/gui/components/index.d.ts +1 -0
  24. package/dist/gui/components/index.js +1 -0
  25. package/dist/sdk/client/acp-client.d.ts +9 -1
  26. package/dist/sdk/client/acp-client.js +10 -0
  27. package/dist/sdk/schemas/message.d.ts +2 -2
  28. package/dist/sdk/schemas/session.d.ts +96 -0
  29. package/dist/sdk/transports/http.d.ts +12 -1
  30. package/dist/sdk/transports/http.js +77 -1
  31. package/dist/sdk/transports/stdio.d.ts +3 -0
  32. package/dist/sdk/transports/types.d.ts +34 -0
  33. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  import type { MessageChunk, Session, SessionConfig, SessionUpdate } from "../schemas/index.js";
2
- import type { HttpTransportOptions, StdioTransportOptions, WebSocketTransportOptions } from "../transports/index.js";
2
+ import type { HttpTransportOptions, SessionSummary, StdioTransportOptions, WebSocketTransportOptions } from "../transports/index.js";
3
3
  /**
4
4
  * Client configuration with explicit transport selection
5
5
  */
@@ -48,6 +48,10 @@ export declare class AcpClient {
48
48
  * Load an existing session
49
49
  */
50
50
  loadSession(sessionId: string, config?: Partial<SessionConfig>): Promise<string>;
51
+ /**
52
+ * List available sessions
53
+ */
54
+ listSessions(): Promise<SessionSummary[]>;
51
55
  /**
52
56
  * Send a message in the current session
53
57
  */
@@ -89,6 +93,7 @@ export declare class AcpClient {
89
93
  * - tools: List of tools available to the agent
90
94
  * - mcps: List of MCP servers connected to the agent
91
95
  * - subagents: List of subagents available via Task tool
96
+ * - uiConfig: UI configuration for interface appearance
92
97
  */
93
98
  getAgentInfo(): {
94
99
  name?: string;
@@ -96,6 +101,9 @@ export declare class AcpClient {
96
101
  version?: string;
97
102
  description?: string;
98
103
  suggestedPrompts?: string[];
104
+ uiConfig?: {
105
+ hideTopBar?: boolean;
106
+ };
99
107
  tools?: Array<{
100
108
  name: string;
101
109
  description?: string;
@@ -131,6 +131,15 @@ export class AcpClient {
131
131
  this.updateSessionStatus(sessionId, "connected");
132
132
  return sessionId;
133
133
  }
134
+ /**
135
+ * List available sessions
136
+ */
137
+ async listSessions() {
138
+ if (!this.transport.listSessions) {
139
+ return [];
140
+ }
141
+ return this.transport.listSessions();
142
+ }
134
143
  /**
135
144
  * Send a message in the current session
136
145
  */
@@ -236,6 +245,7 @@ export class AcpClient {
236
245
  * - tools: List of tools available to the agent
237
246
  * - mcps: List of MCP servers connected to the agent
238
247
  * - subagents: List of subagents available via Task tool
248
+ * - uiConfig: UI configuration for interface appearance
239
249
  */
240
250
  getAgentInfo() {
241
251
  return this.transport.getAgentInfo?.() || {};
@@ -13,9 +13,9 @@ export type MessageRole = z.infer<typeof MessageRole>;
13
13
  * Content type for messages
14
14
  */
15
15
  export declare const ContentType: z.ZodEnum<{
16
+ file: "file";
16
17
  text: "text";
17
18
  image: "image";
18
- file: "file";
19
19
  tool_call: "tool_call";
20
20
  tool_result: "tool_result";
21
21
  }>;
@@ -25,9 +25,9 @@ export type ContentType = z.infer<typeof ContentType>;
25
25
  */
26
26
  export declare const BaseContent: z.ZodObject<{
27
27
  type: z.ZodEnum<{
28
+ file: "file";
28
29
  text: "text";
29
30
  image: "image";
30
- file: "file";
31
31
  tool_call: "tool_call";
32
32
  tool_result: "tool_result";
33
33
  }>;
@@ -249,6 +249,100 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
249
249
  originalTokens: z.ZodOptional<z.ZodNumber>;
250
250
  finalTokens: z.ZodOptional<z.ZodNumber>;
251
251
  }, z.core.$strip>>;
252
+ subagentPort: z.ZodOptional<z.ZodNumber>;
253
+ subagentSessionId: z.ZodOptional<z.ZodString>;
254
+ subagentMessages: z.ZodOptional<z.ZodArray<z.ZodObject<{
255
+ id: z.ZodString;
256
+ content: z.ZodString;
257
+ toolCalls: z.ZodOptional<z.ZodArray<z.ZodObject<{
258
+ id: z.ZodString;
259
+ title: z.ZodString;
260
+ prettyName: z.ZodOptional<z.ZodString>;
261
+ icon: z.ZodOptional<z.ZodString>;
262
+ status: z.ZodEnum<{
263
+ pending: "pending";
264
+ in_progress: "in_progress";
265
+ completed: "completed";
266
+ failed: "failed";
267
+ }>;
268
+ content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
269
+ type: z.ZodLiteral<"content">;
270
+ content: z.ZodObject<{
271
+ type: z.ZodLiteral<"text">;
272
+ text: z.ZodString;
273
+ }, z.core.$strip>;
274
+ }, z.core.$strip>, z.ZodObject<{
275
+ type: z.ZodLiteral<"text">;
276
+ text: z.ZodString;
277
+ }, z.core.$strip>, z.ZodObject<{
278
+ type: z.ZodLiteral<"image">;
279
+ data: z.ZodString;
280
+ mimeType: z.ZodOptional<z.ZodString>;
281
+ alt: z.ZodOptional<z.ZodString>;
282
+ }, z.core.$strip>, z.ZodObject<{
283
+ type: z.ZodLiteral<"image">;
284
+ url: z.ZodString;
285
+ alt: z.ZodOptional<z.ZodString>;
286
+ }, z.core.$strip>, z.ZodObject<{
287
+ type: z.ZodLiteral<"diff">;
288
+ path: z.ZodString;
289
+ oldText: z.ZodString;
290
+ newText: z.ZodString;
291
+ line: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
292
+ }, z.core.$strip>, z.ZodObject<{
293
+ type: z.ZodLiteral<"terminal">;
294
+ terminalId: z.ZodString;
295
+ }, z.core.$strip>], "type">>>;
296
+ }, z.core.$strip>>>;
297
+ contentBlocks: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
298
+ type: z.ZodLiteral<"text">;
299
+ text: z.ZodString;
300
+ }, z.core.$strip>, z.ZodObject<{
301
+ type: z.ZodLiteral<"tool_call">;
302
+ toolCall: z.ZodObject<{
303
+ id: z.ZodString;
304
+ title: z.ZodString;
305
+ prettyName: z.ZodOptional<z.ZodString>;
306
+ icon: z.ZodOptional<z.ZodString>;
307
+ status: z.ZodEnum<{
308
+ pending: "pending";
309
+ in_progress: "in_progress";
310
+ completed: "completed";
311
+ failed: "failed";
312
+ }>;
313
+ content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
314
+ type: z.ZodLiteral<"content">;
315
+ content: z.ZodObject<{
316
+ type: z.ZodLiteral<"text">;
317
+ text: z.ZodString;
318
+ }, z.core.$strip>;
319
+ }, z.core.$strip>, z.ZodObject<{
320
+ type: z.ZodLiteral<"text">;
321
+ text: z.ZodString;
322
+ }, z.core.$strip>, z.ZodObject<{
323
+ type: z.ZodLiteral<"image">;
324
+ data: z.ZodString;
325
+ mimeType: z.ZodOptional<z.ZodString>;
326
+ alt: z.ZodOptional<z.ZodString>;
327
+ }, z.core.$strip>, z.ZodObject<{
328
+ type: z.ZodLiteral<"image">;
329
+ url: z.ZodString;
330
+ alt: z.ZodOptional<z.ZodString>;
331
+ }, z.core.$strip>, z.ZodObject<{
332
+ type: z.ZodLiteral<"diff">;
333
+ path: z.ZodString;
334
+ oldText: z.ZodString;
335
+ newText: z.ZodString;
336
+ line: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
337
+ }, z.core.$strip>, z.ZodObject<{
338
+ type: z.ZodLiteral<"terminal">;
339
+ terminalId: z.ZodString;
340
+ }, z.core.$strip>], "type">>>;
341
+ }, z.core.$strip>;
342
+ }, z.core.$strip>], "type">>>;
343
+ isStreaming: z.ZodOptional<z.ZodBoolean>;
344
+ }, z.core.$strip>>>;
345
+ subagentStreaming: z.ZodOptional<z.ZodBoolean>;
252
346
  }, z.core.$strip>;
253
347
  messageId: z.ZodOptional<z.ZodString>;
254
348
  }, z.core.$strip>, z.ZodObject<{
@@ -363,6 +457,8 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
363
457
  outputTokens: z.ZodOptional<z.ZodNumber>;
364
458
  totalTokens: z.ZodOptional<z.ZodNumber>;
365
459
  }, z.core.$strip>>;
460
+ subagentPort: z.ZodOptional<z.ZodNumber>;
461
+ subagentSessionId: z.ZodOptional<z.ZodString>;
366
462
  }, z.core.$strip>;
367
463
  messageId: z.ZodOptional<z.ZodString>;
368
464
  }, z.core.$strip>, z.ZodObject<{
@@ -1,5 +1,5 @@
1
1
  import type { Message, MessageChunk, SessionUpdate } from "../schemas/index.js";
2
- import type { HttpTransportOptions, Transport } from "./types.js";
2
+ import type { HttpTransportOptions, SessionSummary, Transport } from "./types.js";
3
3
  /**
4
4
  * HTTP transport implementation using ACP over HTTP + SSE
5
5
  * Uses POST /rpc for client->agent messages and GET /events (SSE) for agent->client
@@ -29,6 +29,10 @@ export declare class HttpTransport implements Transport {
29
29
  * @param sessionId - The session ID to load
30
30
  */
31
31
  loadSession(sessionId: string): Promise<void>;
32
+ /**
33
+ * List available sessions from the server
34
+ */
35
+ listSessions(): Promise<SessionSummary[]>;
32
36
  disconnect(): Promise<void>;
33
37
  send(message: Message): Promise<void>;
34
38
  receive(): AsyncIterableIterator<MessageChunk>;
@@ -41,6 +45,13 @@ export declare class HttpTransport implements Transport {
41
45
  version?: string;
42
46
  description?: string;
43
47
  suggestedPrompts?: string[];
48
+ initialMessage?: {
49
+ enabled: boolean;
50
+ content: string;
51
+ };
52
+ uiConfig?: {
53
+ hideTopBar?: boolean;
54
+ };
44
55
  tools?: Array<{
45
56
  name: string;
46
57
  description?: string;
@@ -65,6 +65,18 @@ export class HttpTransport {
65
65
  const subagents = metaIsObject && "subagents" in meta && Array.isArray(meta.subagents)
66
66
  ? meta.subagents
67
67
  : undefined;
68
+ const initialMessage = metaIsObject &&
69
+ "initialMessage" in meta &&
70
+ meta.initialMessage &&
71
+ typeof meta.initialMessage === "object"
72
+ ? meta.initialMessage
73
+ : undefined;
74
+ const uiConfig = metaIsObject &&
75
+ "uiConfig" in meta &&
76
+ meta.uiConfig &&
77
+ typeof meta.uiConfig === "object"
78
+ ? meta.uiConfig
79
+ : undefined;
68
80
  this.agentInfo = {
69
81
  name: initResponse.agentInfo.name,
70
82
  // title is the ACP field for human-readable display name
@@ -74,6 +86,8 @@ export class HttpTransport {
74
86
  version: initResponse.agentInfo.version,
75
87
  ...(description ? { description } : {}),
76
88
  ...(suggestedPrompts ? { suggestedPrompts } : {}),
89
+ ...(initialMessage ? { initialMessage } : {}),
90
+ ...(uiConfig ? { uiConfig } : {}),
77
91
  ...(tools ? { tools } : {}),
78
92
  ...(mcps ? { mcps } : {}),
79
93
  ...(subagents ? { subagents } : {}),
@@ -146,6 +160,18 @@ export class HttpTransport {
146
160
  const subagents = metaIsObject && "subagents" in meta && Array.isArray(meta.subagents)
147
161
  ? meta.subagents
148
162
  : undefined;
163
+ const initialMessage = metaIsObject &&
164
+ "initialMessage" in meta &&
165
+ meta.initialMessage &&
166
+ typeof meta.initialMessage === "object"
167
+ ? meta.initialMessage
168
+ : undefined;
169
+ const uiConfig = metaIsObject &&
170
+ "uiConfig" in meta &&
171
+ meta.uiConfig &&
172
+ typeof meta.uiConfig === "object"
173
+ ? meta.uiConfig
174
+ : undefined;
149
175
  this.agentInfo = {
150
176
  name: initResponse.agentInfo.name,
151
177
  // title is the ACP field for human-readable display name
@@ -155,6 +181,8 @@ export class HttpTransport {
155
181
  version: initResponse.agentInfo.version,
156
182
  ...(description ? { description } : {}),
157
183
  ...(suggestedPrompts ? { suggestedPrompts } : {}),
184
+ ...(initialMessage ? { initialMessage } : {}),
185
+ ...(uiConfig ? { uiConfig } : {}),
158
186
  ...(tools ? { tools } : {}),
159
187
  ...(mcps ? { mcps } : {}),
160
188
  ...(subagents ? { subagents } : {}),
@@ -204,6 +232,29 @@ export class HttpTransport {
204
232
  throw err;
205
233
  }
206
234
  }
235
+ /**
236
+ * List available sessions from the server
237
+ */
238
+ async listSessions() {
239
+ try {
240
+ const fetchOptions = {
241
+ method: "GET",
242
+ };
243
+ if (this.options.headers) {
244
+ fetchOptions.headers = this.options.headers;
245
+ }
246
+ const response = await fetch(`${this.options.baseUrl}/sessions`, fetchOptions);
247
+ if (!response.ok) {
248
+ throw new Error(`HTTP ${response.status}: ${await response.text()}`);
249
+ }
250
+ const data = await response.json();
251
+ return data.sessions || [];
252
+ }
253
+ catch (error) {
254
+ logger.error("Failed to list sessions", { error });
255
+ return [];
256
+ }
257
+ }
207
258
  async disconnect() {
208
259
  if (!this.connected) {
209
260
  return;
@@ -736,6 +787,28 @@ export class HttpTransport {
736
787
  typeof update._meta.batchId === "string"
737
788
  ? update._meta.batchId
738
789
  : undefined;
790
+ // Extract subagent connection info from _meta
791
+ const subagentPort = update._meta &&
792
+ typeof update._meta === "object" &&
793
+ "subagentPort" in update._meta &&
794
+ typeof update._meta.subagentPort === "number"
795
+ ? update._meta.subagentPort
796
+ : undefined;
797
+ const subagentSessionId = update._meta &&
798
+ typeof update._meta === "object" &&
799
+ "subagentSessionId" in update._meta &&
800
+ typeof update._meta.subagentSessionId === "string"
801
+ ? update._meta.subagentSessionId
802
+ : undefined;
803
+ // Debug logging for subagent connection info
804
+ if (subagentPort || subagentSessionId) {
805
+ logger.info("Extracted subagent connection info from tool_call_update", {
806
+ toolCallId: update.toolCallId,
807
+ subagentPort,
808
+ subagentSessionId,
809
+ _meta: update._meta,
810
+ });
811
+ }
739
812
  // Tool call update notification
740
813
  const toolCallUpdate = {
741
814
  id: update.toolCallId ?? "",
@@ -798,6 +871,9 @@ export class HttpTransport {
798
871
  completedAt: update.status === "completed" || update.status === "failed"
799
872
  ? Date.now()
800
873
  : undefined,
874
+ // Sub-agent connection info for direct SSE streaming
875
+ subagentPort,
876
+ subagentSessionId,
801
877
  };
802
878
  const sessionUpdate = {
803
879
  type: "tool_call_update",
@@ -982,7 +1058,7 @@ export class HttpTransport {
982
1058
  timestamp: new Date().toISOString(),
983
1059
  },
984
1060
  };
985
- // Notify as a complete message (for session replay)
1061
+ // Notify as a complete message (for session replay or initial message)
986
1062
  this.notifySessionUpdate(messageSessionUpdate);
987
1063
  }
988
1064
  }
@@ -31,6 +31,9 @@ export declare class StdioTransport implements Transport {
31
31
  version?: string;
32
32
  description?: string;
33
33
  suggestedPrompts?: string[];
34
+ uiConfig?: {
35
+ hideTopBar?: boolean;
36
+ };
34
37
  tools?: Array<{
35
38
  name: string;
36
39
  description?: string;
@@ -22,6 +22,32 @@ export interface AgentSubagentInfo {
22
22
  name: string;
23
23
  description: string;
24
24
  }
25
+ /**
26
+ * Initial message configuration for agents
27
+ */
28
+ export interface AgentInitialMessage {
29
+ /** Whether the agent should send an initial message when a session starts */
30
+ enabled: boolean;
31
+ /** The content of the initial message */
32
+ content: string;
33
+ }
34
+ /**
35
+ * UI configuration for agents
36
+ */
37
+ export interface AgentUiConfig {
38
+ /** Whether to hide the top bar (session switcher, debugger link, settings) */
39
+ hideTopBar?: boolean;
40
+ }
41
+ /**
42
+ * Session summary for listing
43
+ */
44
+ export interface SessionSummary {
45
+ sessionId: string;
46
+ createdAt: string;
47
+ updatedAt: string;
48
+ messageCount: number;
49
+ firstUserMessage?: string;
50
+ }
25
51
  /**
26
52
  * Transport interface for different communication methods
27
53
  */
@@ -34,6 +60,10 @@ export interface Transport {
34
60
  * Load an existing session (optional, not all transports support this)
35
61
  */
36
62
  loadSession?(sessionId: string): Promise<void>;
63
+ /**
64
+ * List available sessions (optional, not all transports support this)
65
+ */
66
+ listSessions?(): Promise<SessionSummary[]>;
37
67
  /**
38
68
  * Close the transport connection
39
69
  */
@@ -66,6 +96,8 @@ export interface Transport {
66
96
  * - tools: List of tools available to the agent
67
97
  * - mcps: List of MCP servers connected to the agent
68
98
  * - subagents: List of subagents available via Task tool
99
+ * - initialMessage: Configuration for agent's initial message on session start
100
+ * - uiConfig: UI configuration for controlling interface appearance
69
101
  */
70
102
  getAgentInfo?(): {
71
103
  name?: string;
@@ -73,6 +105,8 @@ export interface Transport {
73
105
  version?: string;
74
106
  description?: string;
75
107
  suggestedPrompts?: string[];
108
+ initialMessage?: AgentInitialMessage;
109
+ uiConfig?: AgentUiConfig;
76
110
  tools?: AgentToolInfo[];
77
111
  mcps?: AgentMcpInfo[];
78
112
  subagents?: AgentSubagentInfo[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@townco/ui",
3
- "version": "0.1.50",
3
+ "version": "0.1.52",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@agentclientprotocol/sdk": "^0.5.1",
47
- "@townco/core": "0.0.28",
47
+ "@townco/core": "0.0.30",
48
48
  "@radix-ui/react-dialog": "^1.1.15",
49
49
  "@radix-ui/react-dropdown-menu": "^2.1.16",
50
50
  "@radix-ui/react-label": "^2.1.8",
@@ -67,7 +67,7 @@
67
67
  },
68
68
  "devDependencies": {
69
69
  "@tailwindcss/postcss": "^4.1.17",
70
- "@townco/tsconfig": "0.1.47",
70
+ "@townco/tsconfig": "0.1.49",
71
71
  "@types/node": "^24.10.0",
72
72
  "@types/react": "^19.2.2",
73
73
  "ink": "^6.4.0",