@townco/ui 0.1.77 → 0.1.79

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 (49) hide show
  1. package/dist/core/hooks/use-chat-messages.d.ts +6 -4
  2. package/dist/core/hooks/use-chat-messages.js +4 -1
  3. package/dist/core/hooks/use-chat-session.d.ts +1 -1
  4. package/dist/core/hooks/use-chat-session.js +5 -1
  5. package/dist/core/hooks/use-subagent-stream.js +6 -6
  6. package/dist/core/hooks/use-tool-calls.d.ts +5 -3
  7. package/dist/core/hooks/use-tool-calls.js +1 -1
  8. package/dist/core/schemas/chat.d.ts +14 -10
  9. package/dist/core/schemas/tool-call.d.ts +21 -8
  10. package/dist/core/schemas/tool-call.js +15 -0
  11. package/dist/core/store/chat-store.js +1 -0
  12. package/dist/core/utils/tool-summary.js +8 -3
  13. package/dist/core/utils/tool-verbiage.js +1 -1
  14. package/dist/gui/components/AppSidebar.d.ts +1 -1
  15. package/dist/gui/components/AppSidebar.js +4 -3
  16. package/dist/gui/components/ChatEmptyState.js +1 -1
  17. package/dist/gui/components/ChatHeader.d.ts +1 -28
  18. package/dist/gui/components/ChatHeader.js +4 -71
  19. package/dist/gui/components/ChatLayout.d.ts +6 -2
  20. package/dist/gui/components/ChatLayout.js +82 -33
  21. package/dist/gui/components/ChatView.js +28 -45
  22. package/dist/gui/components/ContextUsageButton.d.ts +0 -1
  23. package/dist/gui/components/ContextUsageButton.js +10 -3
  24. package/dist/gui/components/HookNotification.js +2 -1
  25. package/dist/gui/components/MessageContent.js +24 -160
  26. package/dist/gui/components/SessionHistory.js +1 -2
  27. package/dist/gui/components/SessionHistoryItem.js +1 -1
  28. package/dist/gui/components/Sidebar.js +27 -42
  29. package/dist/gui/components/SubAgentDetails.js +10 -14
  30. package/dist/gui/components/TodoSubline.js +1 -0
  31. package/dist/gui/components/ToolOperation.js +117 -81
  32. package/dist/gui/components/WorkProgress.js +5 -3
  33. package/dist/gui/components/index.d.ts +0 -1
  34. package/dist/gui/components/resizable.d.ts +1 -1
  35. package/dist/gui/constants.d.ts +6 -0
  36. package/dist/gui/constants.js +8 -0
  37. package/dist/gui/hooks/index.d.ts +1 -0
  38. package/dist/gui/hooks/index.js +1 -0
  39. package/dist/gui/hooks/use-lock-body-scroll.d.ts +7 -0
  40. package/dist/gui/hooks/use-lock-body-scroll.js +29 -0
  41. package/dist/gui/lib/motion.d.ts +12 -0
  42. package/dist/gui/lib/motion.js +69 -0
  43. package/dist/sdk/schemas/session.d.ts +37 -24
  44. package/dist/sdk/transports/http.d.ts +1 -1
  45. package/dist/sdk/transports/http.js +99 -1
  46. package/dist/sdk/transports/stdio.js +2 -2
  47. package/dist/sdk/transports/types.d.ts +11 -0
  48. package/dist/sdk/transports/types.js +28 -1
  49. package/package.json +3 -5
@@ -3,13 +3,13 @@ import { z } from "zod";
3
3
  * Session status
4
4
  */
5
5
  export declare const SessionStatus: z.ZodEnum<{
6
- error: "error";
7
6
  active: "active";
8
- disconnected: "disconnected";
7
+ error: "error";
8
+ idle: "idle";
9
9
  connecting: "connecting";
10
10
  connected: "connected";
11
- idle: "idle";
12
11
  streaming: "streaming";
12
+ disconnected: "disconnected";
13
13
  }>;
14
14
  export type SessionStatus = z.infer<typeof SessionStatus>;
15
15
  /**
@@ -40,13 +40,13 @@ export type SessionMetadata = z.infer<typeof SessionMetadata>;
40
40
  export declare const Session: z.ZodObject<{
41
41
  id: z.ZodString;
42
42
  status: z.ZodEnum<{
43
- error: "error";
44
43
  active: "active";
45
- disconnected: "disconnected";
44
+ error: "error";
45
+ idle: "idle";
46
46
  connecting: "connecting";
47
47
  connected: "connected";
48
- idle: "idle";
49
48
  streaming: "streaming";
49
+ disconnected: "disconnected";
50
50
  }>;
51
51
  config: z.ZodObject<{
52
52
  agentPath: z.ZodString;
@@ -116,13 +116,13 @@ export type Session = z.infer<typeof Session>;
116
116
  export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
117
117
  sessionId: z.ZodString;
118
118
  status: z.ZodOptional<z.ZodEnum<{
119
- error: "error";
120
119
  active: "active";
121
- disconnected: "disconnected";
120
+ error: "error";
121
+ idle: "idle";
122
122
  connecting: "connecting";
123
123
  connected: "connected";
124
- idle: "idle";
125
124
  streaming: "streaming";
125
+ disconnected: "disconnected";
126
126
  }>>;
127
127
  message: z.ZodOptional<z.ZodObject<{
128
128
  id: z.ZodString;
@@ -197,9 +197,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
197
197
  other: "other";
198
198
  }>;
199
199
  status: z.ZodEnum<{
200
- completed: "completed";
201
200
  pending: "pending";
202
201
  in_progress: "in_progress";
202
+ completed: "completed";
203
203
  failed: "failed";
204
204
  }>;
205
205
  contentPosition: z.ZodOptional<z.ZodNumber>;
@@ -253,6 +253,8 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
253
253
  }>>;
254
254
  originalTokens: z.ZodOptional<z.ZodNumber>;
255
255
  finalTokens: z.ZodOptional<z.ZodNumber>;
256
+ originalContentPreview: z.ZodOptional<z.ZodString>;
257
+ originalContentPath: z.ZodOptional<z.ZodString>;
256
258
  }, z.core.$strip>>;
257
259
  subagentPort: z.ZodOptional<z.ZodNumber>;
258
260
  subagentSessionId: z.ZodOptional<z.ZodString>;
@@ -265,9 +267,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
265
267
  prettyName: z.ZodOptional<z.ZodString>;
266
268
  icon: z.ZodOptional<z.ZodString>;
267
269
  status: z.ZodEnum<{
268
- completed: "completed";
269
270
  pending: "pending";
270
271
  in_progress: "in_progress";
272
+ completed: "completed";
271
273
  failed: "failed";
272
274
  }>;
273
275
  content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -310,9 +312,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
310
312
  prettyName: z.ZodOptional<z.ZodString>;
311
313
  icon: z.ZodOptional<z.ZodString>;
312
314
  status: z.ZodEnum<{
313
- completed: "completed";
314
315
  pending: "pending";
315
316
  in_progress: "in_progress";
317
+ completed: "completed";
316
318
  failed: "failed";
317
319
  }>;
318
320
  content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -353,13 +355,13 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
353
355
  }, z.core.$strip>, z.ZodObject<{
354
356
  sessionId: z.ZodString;
355
357
  status: z.ZodOptional<z.ZodEnum<{
356
- error: "error";
357
358
  active: "active";
358
- disconnected: "disconnected";
359
+ error: "error";
360
+ idle: "idle";
359
361
  connecting: "connecting";
360
362
  connected: "connected";
361
- idle: "idle";
362
363
  streaming: "streaming";
364
+ disconnected: "disconnected";
363
365
  }>>;
364
366
  message: z.ZodOptional<z.ZodObject<{
365
367
  id: z.ZodString;
@@ -412,9 +414,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
412
414
  toolCallUpdate: z.ZodObject<{
413
415
  id: z.ZodString;
414
416
  status: z.ZodOptional<z.ZodEnum<{
415
- completed: "completed";
416
417
  pending: "pending";
417
418
  in_progress: "in_progress";
419
+ completed: "completed";
418
420
  failed: "failed";
419
421
  }>>;
420
422
  title: z.ZodOptional<z.ZodString>;
@@ -473,9 +475,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
473
475
  prettyName: z.ZodOptional<z.ZodString>;
474
476
  icon: z.ZodOptional<z.ZodString>;
475
477
  status: z.ZodEnum<{
476
- completed: "completed";
477
478
  pending: "pending";
478
479
  in_progress: "in_progress";
480
+ completed: "completed";
479
481
  failed: "failed";
480
482
  }>;
481
483
  content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -518,9 +520,9 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
518
520
  prettyName: z.ZodOptional<z.ZodString>;
519
521
  icon: z.ZodOptional<z.ZodString>;
520
522
  status: z.ZodEnum<{
521
- completed: "completed";
522
523
  pending: "pending";
523
524
  in_progress: "in_progress";
525
+ completed: "completed";
524
526
  failed: "failed";
525
527
  }>;
526
528
  content: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -555,18 +557,29 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
555
557
  }, z.core.$strip>], "type">>>;
556
558
  isStreaming: z.ZodOptional<z.ZodBoolean>;
557
559
  }, z.core.$strip>>>;
560
+ _meta: z.ZodOptional<z.ZodObject<{
561
+ truncationWarning: z.ZodOptional<z.ZodString>;
562
+ compactionAction: z.ZodOptional<z.ZodEnum<{
563
+ compacted: "compacted";
564
+ truncated: "truncated";
565
+ }>>;
566
+ originalTokens: z.ZodOptional<z.ZodNumber>;
567
+ finalTokens: z.ZodOptional<z.ZodNumber>;
568
+ originalContentPreview: z.ZodOptional<z.ZodString>;
569
+ originalContentPath: z.ZodOptional<z.ZodString>;
570
+ }, z.core.$strip>>;
558
571
  }, z.core.$strip>;
559
572
  messageId: z.ZodOptional<z.ZodString>;
560
573
  }, z.core.$strip>, z.ZodObject<{
561
574
  sessionId: z.ZodString;
562
575
  status: z.ZodOptional<z.ZodEnum<{
563
- error: "error";
564
576
  active: "active";
565
- disconnected: "disconnected";
577
+ error: "error";
578
+ idle: "idle";
566
579
  connecting: "connecting";
567
580
  connected: "connected";
568
- idle: "idle";
569
581
  streaming: "streaming";
582
+ disconnected: "disconnected";
570
583
  }>>;
571
584
  message: z.ZodOptional<z.ZodObject<{
572
585
  id: z.ZodString;
@@ -625,13 +638,13 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
625
638
  }, z.core.$strip>, z.ZodObject<{
626
639
  sessionId: z.ZodString;
627
640
  status: z.ZodOptional<z.ZodEnum<{
628
- error: "error";
629
641
  active: "active";
630
- disconnected: "disconnected";
642
+ error: "error";
643
+ idle: "idle";
631
644
  connecting: "connecting";
632
645
  connected: "connected";
633
- idle: "idle";
634
646
  streaming: "streaming";
647
+ disconnected: "disconnected";
635
648
  }>>;
636
649
  message: z.ZodOptional<z.ZodObject<{
637
650
  id: z.ZodString;
@@ -1,5 +1,5 @@
1
1
  import type { Message, MessageChunk, SessionUpdate } from "../schemas/index.js";
2
- import type { HttpTransportOptions, SessionSummary, Transport } from "./types.js";
2
+ import { type HttpTransportOptions, type SessionSummary, type 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
@@ -1,5 +1,6 @@
1
1
  import * as acp from "@agentclientprotocol/sdk";
2
2
  import { createLogger } from "@townco/core";
3
+ import { httpTransportOptionsSchema, } from "./types.js";
3
4
  const logger = createLogger("http-transport");
4
5
  /**
5
6
  * HTTP transport implementation using ACP over HTTP + SSE
@@ -24,6 +25,14 @@ export class HttpTransport {
24
25
  isInReplayMode = false; // True during session replay, ignores non-replay streaming
25
26
  agentInfo;
26
27
  constructor(options) {
28
+ // Validate options at the boundary using Zod
29
+ const validationResult = httpTransportOptionsSchema.safeParse(options);
30
+ if (!validationResult.success) {
31
+ const errorMessages = validationResult.error.issues
32
+ .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
33
+ .join("; ");
34
+ throw new Error(`Invalid HTTP transport configuration: ${errorMessages}`);
35
+ }
27
36
  // Ensure baseUrl doesn't end with a slash
28
37
  this.options = { ...options, baseUrl: options.baseUrl.replace(/\/$/, "") };
29
38
  }
@@ -714,6 +723,37 @@ export class HttpTransport {
714
723
  Array.isArray(update._meta.subagentMessages)
715
724
  ? update._meta.subagentMessages
716
725
  : undefined;
726
+ // Extract compaction metadata from _meta (for initial tool call during replay)
727
+ const compactionActionInitial = update._meta &&
728
+ typeof update._meta === "object" &&
729
+ "compactionAction" in update._meta &&
730
+ typeof update._meta.compactionAction === "string"
731
+ ? update._meta.compactionAction
732
+ : undefined;
733
+ const originalTokensInitial = update._meta &&
734
+ typeof update._meta === "object" &&
735
+ "originalTokens" in update._meta &&
736
+ typeof update._meta.originalTokens === "number"
737
+ ? update._meta.originalTokens
738
+ : undefined;
739
+ const finalTokensInitial = update._meta &&
740
+ typeof update._meta === "object" &&
741
+ "finalTokens" in update._meta &&
742
+ typeof update._meta.finalTokens === "number"
743
+ ? update._meta.finalTokens
744
+ : undefined;
745
+ const originalContentPreviewInitial = update._meta &&
746
+ typeof update._meta === "object" &&
747
+ "originalContentPreview" in update._meta &&
748
+ typeof update._meta.originalContentPreview === "string"
749
+ ? update._meta.originalContentPreview
750
+ : undefined;
751
+ const originalContentPathInitial = update._meta &&
752
+ typeof update._meta === "object" &&
753
+ "originalContentPath" in update._meta &&
754
+ typeof update._meta.originalContentPath === "string"
755
+ ? update._meta.originalContentPath
756
+ : undefined;
717
757
  // Initial tool call notification
718
758
  const toolCall = {
719
759
  id: update.toolCallId ?? "",
@@ -778,6 +818,20 @@ export class HttpTransport {
778
818
  subagentPort,
779
819
  subagentSessionId,
780
820
  subagentMessages,
821
+ // Compaction metadata
822
+ _meta: compactionActionInitial ||
823
+ originalTokensInitial ||
824
+ finalTokensInitial ||
825
+ originalContentPreviewInitial ||
826
+ originalContentPathInitial
827
+ ? {
828
+ compactionAction: compactionActionInitial,
829
+ originalTokens: originalTokensInitial,
830
+ finalTokens: finalTokensInitial,
831
+ originalContentPreview: originalContentPreviewInitial,
832
+ originalContentPath: originalContentPathInitial,
833
+ }
834
+ : undefined,
781
835
  };
782
836
  const sessionUpdate = {
783
837
  type: "tool_call",
@@ -791,7 +845,6 @@ export class HttpTransport {
791
845
  typeof update._meta === "object" &&
792
846
  "isReplay" in update._meta &&
793
847
  update._meta.isReplay === true;
794
- // Debug: log tool call creation
795
848
  logger.info("Creating tool_call session update", {
796
849
  toolCallId: toolCall.id,
797
850
  title: toolCall.title,
@@ -876,6 +929,37 @@ export class HttpTransport {
876
929
  subagentMessagesCount: subagentMessages?.length,
877
930
  });
878
931
  }
932
+ // Extract compaction metadata from _meta
933
+ const compactionAction = update._meta &&
934
+ typeof update._meta === "object" &&
935
+ "compactionAction" in update._meta &&
936
+ typeof update._meta.compactionAction === "string"
937
+ ? update._meta.compactionAction
938
+ : undefined;
939
+ const originalTokens = update._meta &&
940
+ typeof update._meta === "object" &&
941
+ "originalTokens" in update._meta &&
942
+ typeof update._meta.originalTokens === "number"
943
+ ? update._meta.originalTokens
944
+ : undefined;
945
+ const finalTokens = update._meta &&
946
+ typeof update._meta === "object" &&
947
+ "finalTokens" in update._meta &&
948
+ typeof update._meta.finalTokens === "number"
949
+ ? update._meta.finalTokens
950
+ : undefined;
951
+ const originalContentPreview = update._meta &&
952
+ typeof update._meta === "object" &&
953
+ "originalContentPreview" in update._meta &&
954
+ typeof update._meta.originalContentPreview === "string"
955
+ ? update._meta.originalContentPreview
956
+ : undefined;
957
+ const originalContentPath = update._meta &&
958
+ typeof update._meta === "object" &&
959
+ "originalContentPath" in update._meta &&
960
+ typeof update._meta.originalContentPath === "string"
961
+ ? update._meta.originalContentPath
962
+ : undefined;
879
963
  // Tool call update notification
880
964
  const toolCallUpdate = {
881
965
  id: update.toolCallId ?? "",
@@ -943,6 +1027,20 @@ export class HttpTransport {
943
1027
  subagentSessionId,
944
1028
  // Sub-agent messages for replay
945
1029
  subagentMessages,
1030
+ // Compaction metadata
1031
+ _meta: compactionAction ||
1032
+ originalTokens ||
1033
+ finalTokens ||
1034
+ originalContentPreview ||
1035
+ originalContentPath
1036
+ ? {
1037
+ compactionAction,
1038
+ originalTokens,
1039
+ finalTokens,
1040
+ originalContentPreview,
1041
+ originalContentPath,
1042
+ }
1043
+ : undefined,
946
1044
  };
947
1045
  const sessionUpdate = {
948
1046
  type: "tool_call_update",
@@ -180,7 +180,7 @@ export class StdioTransport {
180
180
  }),
181
181
  startedAt: Date.now(),
182
182
  };
183
- const sessionUpdate = {
183
+ const _sessionUpdate = {
184
184
  type: "tool_call",
185
185
  sessionId,
186
186
  status: "active",
@@ -265,7 +265,7 @@ export class StdioTransport {
265
265
  ? Date.now()
266
266
  : undefined,
267
267
  };
268
- const sessionUpdate = {
268
+ const _sessionUpdate = {
269
269
  type: "tool_call_update",
270
270
  sessionId,
271
271
  status: "active",
@@ -1,3 +1,4 @@
1
+ import { z } from "zod";
1
2
  import type { Message, MessageChunk, SessionUpdate } from "../schemas/index.js";
2
3
  /**
3
4
  * Agent tool information exposed via initialize response
@@ -127,6 +128,16 @@ export interface StdioTransportOptions {
127
128
  workingDirectory?: string;
128
129
  timeout?: number;
129
130
  }
131
+ /**
132
+ * Zod schema for validating HTTP transport options
133
+ * Validates that baseUrl is a valid URL at the boundary
134
+ */
135
+ export declare const httpTransportOptionsSchema: z.ZodObject<{
136
+ baseUrl: z.ZodString;
137
+ apiKey: z.ZodOptional<z.ZodString>;
138
+ timeout: z.ZodOptional<z.ZodNumber>;
139
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
140
+ }, z.core.$strip>;
130
141
  /**
131
142
  * HTTP transport options
132
143
  */
@@ -1 +1,28 @@
1
- export {};
1
+ import { z } from "zod";
2
+ /**
3
+ * Zod schema for validating HTTP transport options
4
+ * Validates that baseUrl is a valid URL at the boundary
5
+ */
6
+ export const httpTransportOptionsSchema = z.object({
7
+ baseUrl: z
8
+ .string()
9
+ .url("Invalid base URL. Must be a valid URL (e.g., http://localhost:3000)")
10
+ .refine((url) => {
11
+ try {
12
+ const parsed = new URL(url);
13
+ // Check for common mistakes like double ports (e.g., http://localhost:3102:3100)
14
+ if (parsed.port && parsed.hostname.includes(":")) {
15
+ return false;
16
+ }
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }, {
23
+ message: "Invalid URL format. Check for typos like duplicate ports (e.g., http://localhost:3102:3100)",
24
+ }),
25
+ apiKey: z.string().optional(),
26
+ timeout: z.number().optional(),
27
+ headers: z.record(z.string(), z.string()).optional(),
28
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@townco/ui",
3
- "version": "0.1.77",
3
+ "version": "0.1.79",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -49,9 +49,8 @@
49
49
  "@radix-ui/react-slot": "^1.2.4",
50
50
  "@radix-ui/react-tabs": "^1.1.13",
51
51
  "@radix-ui/react-tooltip": "^1.2.8",
52
- "@townco/core": "0.0.55",
52
+ "@townco/core": "0.0.57",
53
53
  "@uiw/react-json-view": "^2.0.0-alpha.39",
54
- "bun": "^1.3.1",
55
54
  "class-variance-authority": "^0.7.1",
56
55
  "clsx": "^2.1.1",
57
56
  "framer-motion": "^12.23.25",
@@ -66,8 +65,7 @@
66
65
  "zustand": "^5.0.8"
67
66
  },
68
67
  "devDependencies": {
69
- "@tailwindcss/postcss": "^4.1.17",
70
- "@townco/tsconfig": "0.1.74",
68
+ "@townco/tsconfig": "0.1.76",
71
69
  "@types/node": "^24.10.0",
72
70
  "@types/react": "^19.2.2",
73
71
  "ink": "^6.4.0",