@townco/ui 0.1.72 → 0.1.74
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 +23 -0
- package/dist/core/hooks/use-chat-messages.js +8 -0
- package/dist/core/schemas/chat.d.ts +93 -0
- package/dist/core/schemas/chat.js +38 -0
- package/dist/core/store/chat-store.d.ts +3 -0
- package/dist/core/store/chat-store.js +133 -0
- package/dist/gui/components/ChatLayout.js +12 -50
- package/dist/gui/components/ChatView.js +3 -4
- package/dist/gui/components/ContextUsageButton.d.ts +1 -1
- package/dist/gui/components/ContextUsageButton.js +6 -2
- package/dist/gui/components/HookNotification.d.ts +9 -0
- package/dist/gui/components/HookNotification.js +97 -0
- package/dist/gui/components/MessageContent.js +130 -29
- package/dist/gui/components/index.d.ts +1 -0
- package/dist/gui/components/index.js +1 -0
- package/dist/gui/hooks/index.d.ts +1 -0
- package/dist/gui/hooks/index.js +1 -0
- package/dist/gui/hooks/use-scroll-to-bottom.d.ts +18 -0
- package/dist/gui/hooks/use-scroll-to-bottom.js +120 -0
- package/dist/sdk/schemas/message.d.ts +173 -2
- package/dist/sdk/schemas/message.js +60 -0
- package/dist/sdk/schemas/session.d.ts +6 -6
- package/dist/sdk/transports/http.js +28 -0
- package/package.json +3 -3
|
@@ -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";
|
|
17
16
|
text: "text";
|
|
18
17
|
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";
|
|
29
28
|
text: "text";
|
|
30
29
|
image: "image";
|
|
30
|
+
file: "file";
|
|
31
31
|
tool_call: "tool_call";
|
|
32
32
|
tool_result: "tool_result";
|
|
33
33
|
}>;
|
|
@@ -263,6 +263,140 @@ export declare const ToolCallUpdateChunk: z.ZodObject<{
|
|
|
263
263
|
messageId: z.ZodOptional<z.ZodString>;
|
|
264
264
|
}, z.core.$strip>;
|
|
265
265
|
export type ToolCallUpdateChunk = z.infer<typeof ToolCallUpdateChunk>;
|
|
266
|
+
/**
|
|
267
|
+
* Hook type enum
|
|
268
|
+
*/
|
|
269
|
+
export declare const HookType: z.ZodEnum<{
|
|
270
|
+
context_size: "context_size";
|
|
271
|
+
tool_response: "tool_response";
|
|
272
|
+
}>;
|
|
273
|
+
export type HookType = z.infer<typeof HookType>;
|
|
274
|
+
/**
|
|
275
|
+
* Hook triggered notification
|
|
276
|
+
*/
|
|
277
|
+
export declare const HookTriggeredNotification: z.ZodObject<{
|
|
278
|
+
type: z.ZodLiteral<"hook_triggered">;
|
|
279
|
+
hookType: z.ZodEnum<{
|
|
280
|
+
context_size: "context_size";
|
|
281
|
+
tool_response: "tool_response";
|
|
282
|
+
}>;
|
|
283
|
+
threshold: z.ZodNumber;
|
|
284
|
+
currentPercentage: z.ZodNumber;
|
|
285
|
+
callback: z.ZodString;
|
|
286
|
+
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
287
|
+
}, z.core.$strip>;
|
|
288
|
+
export type HookTriggeredNotification = z.infer<typeof HookTriggeredNotification>;
|
|
289
|
+
/**
|
|
290
|
+
* Hook completed notification
|
|
291
|
+
*/
|
|
292
|
+
export declare const HookCompletedNotification: z.ZodObject<{
|
|
293
|
+
type: z.ZodLiteral<"hook_completed">;
|
|
294
|
+
hookType: z.ZodEnum<{
|
|
295
|
+
context_size: "context_size";
|
|
296
|
+
tool_response: "tool_response";
|
|
297
|
+
}>;
|
|
298
|
+
callback: z.ZodString;
|
|
299
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
300
|
+
action: z.ZodOptional<z.ZodString>;
|
|
301
|
+
messagesRemoved: z.ZodOptional<z.ZodNumber>;
|
|
302
|
+
tokensSaved: z.ZodOptional<z.ZodNumber>;
|
|
303
|
+
}, z.core.$loose>>;
|
|
304
|
+
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
305
|
+
}, z.core.$strip>;
|
|
306
|
+
export type HookCompletedNotification = z.infer<typeof HookCompletedNotification>;
|
|
307
|
+
/**
|
|
308
|
+
* Hook error notification
|
|
309
|
+
*/
|
|
310
|
+
export declare const HookErrorNotification: z.ZodObject<{
|
|
311
|
+
type: z.ZodLiteral<"hook_error">;
|
|
312
|
+
hookType: z.ZodEnum<{
|
|
313
|
+
context_size: "context_size";
|
|
314
|
+
tool_response: "tool_response";
|
|
315
|
+
}>;
|
|
316
|
+
callback: z.ZodString;
|
|
317
|
+
error: z.ZodString;
|
|
318
|
+
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
319
|
+
}, z.core.$strip>;
|
|
320
|
+
export type HookErrorNotification = z.infer<typeof HookErrorNotification>;
|
|
321
|
+
/**
|
|
322
|
+
* Union of all hook notification types
|
|
323
|
+
*/
|
|
324
|
+
export declare const HookNotification: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
325
|
+
type: z.ZodLiteral<"hook_triggered">;
|
|
326
|
+
hookType: z.ZodEnum<{
|
|
327
|
+
context_size: "context_size";
|
|
328
|
+
tool_response: "tool_response";
|
|
329
|
+
}>;
|
|
330
|
+
threshold: z.ZodNumber;
|
|
331
|
+
currentPercentage: z.ZodNumber;
|
|
332
|
+
callback: z.ZodString;
|
|
333
|
+
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
334
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
335
|
+
type: z.ZodLiteral<"hook_completed">;
|
|
336
|
+
hookType: z.ZodEnum<{
|
|
337
|
+
context_size: "context_size";
|
|
338
|
+
tool_response: "tool_response";
|
|
339
|
+
}>;
|
|
340
|
+
callback: z.ZodString;
|
|
341
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
342
|
+
action: z.ZodOptional<z.ZodString>;
|
|
343
|
+
messagesRemoved: z.ZodOptional<z.ZodNumber>;
|
|
344
|
+
tokensSaved: z.ZodOptional<z.ZodNumber>;
|
|
345
|
+
}, z.core.$loose>>;
|
|
346
|
+
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
347
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
348
|
+
type: z.ZodLiteral<"hook_error">;
|
|
349
|
+
hookType: z.ZodEnum<{
|
|
350
|
+
context_size: "context_size";
|
|
351
|
+
tool_response: "tool_response";
|
|
352
|
+
}>;
|
|
353
|
+
callback: z.ZodString;
|
|
354
|
+
error: z.ZodString;
|
|
355
|
+
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
356
|
+
}, z.core.$strip>], "type">;
|
|
357
|
+
export type HookNotification = z.infer<typeof HookNotification>;
|
|
358
|
+
/**
|
|
359
|
+
* Hook notification chunk - for streaming hook events
|
|
360
|
+
*/
|
|
361
|
+
export declare const HookNotificationChunk: z.ZodObject<{
|
|
362
|
+
type: z.ZodLiteral<"hook_notification">;
|
|
363
|
+
id: z.ZodString;
|
|
364
|
+
notification: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
365
|
+
type: z.ZodLiteral<"hook_triggered">;
|
|
366
|
+
hookType: z.ZodEnum<{
|
|
367
|
+
context_size: "context_size";
|
|
368
|
+
tool_response: "tool_response";
|
|
369
|
+
}>;
|
|
370
|
+
threshold: z.ZodNumber;
|
|
371
|
+
currentPercentage: z.ZodNumber;
|
|
372
|
+
callback: z.ZodString;
|
|
373
|
+
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
374
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
375
|
+
type: z.ZodLiteral<"hook_completed">;
|
|
376
|
+
hookType: z.ZodEnum<{
|
|
377
|
+
context_size: "context_size";
|
|
378
|
+
tool_response: "tool_response";
|
|
379
|
+
}>;
|
|
380
|
+
callback: z.ZodString;
|
|
381
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
382
|
+
action: z.ZodOptional<z.ZodString>;
|
|
383
|
+
messagesRemoved: z.ZodOptional<z.ZodNumber>;
|
|
384
|
+
tokensSaved: z.ZodOptional<z.ZodNumber>;
|
|
385
|
+
}, z.core.$loose>>;
|
|
386
|
+
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
387
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
388
|
+
type: z.ZodLiteral<"hook_error">;
|
|
389
|
+
hookType: z.ZodEnum<{
|
|
390
|
+
context_size: "context_size";
|
|
391
|
+
tool_response: "tool_response";
|
|
392
|
+
}>;
|
|
393
|
+
callback: z.ZodString;
|
|
394
|
+
error: z.ZodString;
|
|
395
|
+
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
396
|
+
}, z.core.$strip>], "type">;
|
|
397
|
+
messageId: z.ZodOptional<z.ZodString>;
|
|
398
|
+
}, z.core.$strip>;
|
|
399
|
+
export type HookNotificationChunk = z.infer<typeof HookNotificationChunk>;
|
|
266
400
|
/**
|
|
267
401
|
* Message chunk - discriminated union of all chunk types
|
|
268
402
|
*/
|
|
@@ -337,5 +471,42 @@ export declare const MessageChunk: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
337
471
|
id: z.ZodString;
|
|
338
472
|
toolCallUpdate: z.ZodAny;
|
|
339
473
|
messageId: z.ZodOptional<z.ZodString>;
|
|
474
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
475
|
+
type: z.ZodLiteral<"hook_notification">;
|
|
476
|
+
id: z.ZodString;
|
|
477
|
+
notification: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
478
|
+
type: z.ZodLiteral<"hook_triggered">;
|
|
479
|
+
hookType: z.ZodEnum<{
|
|
480
|
+
context_size: "context_size";
|
|
481
|
+
tool_response: "tool_response";
|
|
482
|
+
}>;
|
|
483
|
+
threshold: z.ZodNumber;
|
|
484
|
+
currentPercentage: z.ZodNumber;
|
|
485
|
+
callback: z.ZodString;
|
|
486
|
+
triggeredAt: z.ZodOptional<z.ZodNumber>;
|
|
487
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
488
|
+
type: z.ZodLiteral<"hook_completed">;
|
|
489
|
+
hookType: z.ZodEnum<{
|
|
490
|
+
context_size: "context_size";
|
|
491
|
+
tool_response: "tool_response";
|
|
492
|
+
}>;
|
|
493
|
+
callback: z.ZodString;
|
|
494
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
495
|
+
action: z.ZodOptional<z.ZodString>;
|
|
496
|
+
messagesRemoved: z.ZodOptional<z.ZodNumber>;
|
|
497
|
+
tokensSaved: z.ZodOptional<z.ZodNumber>;
|
|
498
|
+
}, z.core.$loose>>;
|
|
499
|
+
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
500
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
501
|
+
type: z.ZodLiteral<"hook_error">;
|
|
502
|
+
hookType: z.ZodEnum<{
|
|
503
|
+
context_size: "context_size";
|
|
504
|
+
tool_response: "tool_response";
|
|
505
|
+
}>;
|
|
506
|
+
callback: z.ZodString;
|
|
507
|
+
error: z.ZodString;
|
|
508
|
+
completedAt: z.ZodOptional<z.ZodNumber>;
|
|
509
|
+
}, z.core.$strip>], "type">;
|
|
510
|
+
messageId: z.ZodOptional<z.ZodString>;
|
|
340
511
|
}, z.core.$strip>], "type">;
|
|
341
512
|
export type MessageChunk = z.infer<typeof MessageChunk>;
|
|
@@ -147,6 +147,65 @@ export const ToolCallUpdateChunk = z.object({
|
|
|
147
147
|
toolCallUpdate: z.any(), // Will be typed properly by importing ToolCallUpdate
|
|
148
148
|
messageId: z.string().optional(),
|
|
149
149
|
});
|
|
150
|
+
/**
|
|
151
|
+
* Hook type enum
|
|
152
|
+
*/
|
|
153
|
+
export const HookType = z.enum(["context_size", "tool_response"]);
|
|
154
|
+
/**
|
|
155
|
+
* Hook triggered notification
|
|
156
|
+
*/
|
|
157
|
+
export const HookTriggeredNotification = z.object({
|
|
158
|
+
type: z.literal("hook_triggered"),
|
|
159
|
+
hookType: HookType,
|
|
160
|
+
threshold: z.number(),
|
|
161
|
+
currentPercentage: z.number(),
|
|
162
|
+
callback: z.string(),
|
|
163
|
+
triggeredAt: z.number().optional(), // Unix timestamp (ms) from backend
|
|
164
|
+
});
|
|
165
|
+
/**
|
|
166
|
+
* Hook completed notification
|
|
167
|
+
*/
|
|
168
|
+
export const HookCompletedNotification = z.object({
|
|
169
|
+
type: z.literal("hook_completed"),
|
|
170
|
+
hookType: HookType,
|
|
171
|
+
callback: z.string(),
|
|
172
|
+
metadata: z
|
|
173
|
+
.object({
|
|
174
|
+
action: z.string().optional(),
|
|
175
|
+
messagesRemoved: z.number().optional(),
|
|
176
|
+
tokensSaved: z.number().optional(),
|
|
177
|
+
})
|
|
178
|
+
.passthrough()
|
|
179
|
+
.optional(),
|
|
180
|
+
completedAt: z.number().optional(), // Unix timestamp (ms) from backend
|
|
181
|
+
});
|
|
182
|
+
/**
|
|
183
|
+
* Hook error notification
|
|
184
|
+
*/
|
|
185
|
+
export const HookErrorNotification = z.object({
|
|
186
|
+
type: z.literal("hook_error"),
|
|
187
|
+
hookType: HookType,
|
|
188
|
+
callback: z.string(),
|
|
189
|
+
error: z.string(),
|
|
190
|
+
completedAt: z.number().optional(), // Unix timestamp (ms) from backend
|
|
191
|
+
});
|
|
192
|
+
/**
|
|
193
|
+
* Union of all hook notification types
|
|
194
|
+
*/
|
|
195
|
+
export const HookNotification = z.discriminatedUnion("type", [
|
|
196
|
+
HookTriggeredNotification,
|
|
197
|
+
HookCompletedNotification,
|
|
198
|
+
HookErrorNotification,
|
|
199
|
+
]);
|
|
200
|
+
/**
|
|
201
|
+
* Hook notification chunk - for streaming hook events
|
|
202
|
+
*/
|
|
203
|
+
export const HookNotificationChunk = z.object({
|
|
204
|
+
type: z.literal("hook_notification"),
|
|
205
|
+
id: z.string(),
|
|
206
|
+
notification: HookNotification,
|
|
207
|
+
messageId: z.string().optional(),
|
|
208
|
+
});
|
|
150
209
|
/**
|
|
151
210
|
* Message chunk - discriminated union of all chunk types
|
|
152
211
|
*/
|
|
@@ -154,4 +213,5 @@ export const MessageChunk = z.discriminatedUnion("type", [
|
|
|
154
213
|
ContentChunk,
|
|
155
214
|
ToolCallChunk,
|
|
156
215
|
ToolCallUpdateChunk,
|
|
216
|
+
HookNotificationChunk,
|
|
157
217
|
]);
|
|
@@ -4,10 +4,10 @@ import { z } from "zod";
|
|
|
4
4
|
*/
|
|
5
5
|
export declare const SessionStatus: z.ZodEnum<{
|
|
6
6
|
error: "error";
|
|
7
|
-
active: "active";
|
|
8
7
|
idle: "idle";
|
|
9
8
|
connecting: "connecting";
|
|
10
9
|
connected: "connected";
|
|
10
|
+
active: "active";
|
|
11
11
|
streaming: "streaming";
|
|
12
12
|
disconnected: "disconnected";
|
|
13
13
|
}>;
|
|
@@ -41,10 +41,10 @@ export declare const Session: z.ZodObject<{
|
|
|
41
41
|
id: z.ZodString;
|
|
42
42
|
status: z.ZodEnum<{
|
|
43
43
|
error: "error";
|
|
44
|
-
active: "active";
|
|
45
44
|
idle: "idle";
|
|
46
45
|
connecting: "connecting";
|
|
47
46
|
connected: "connected";
|
|
47
|
+
active: "active";
|
|
48
48
|
streaming: "streaming";
|
|
49
49
|
disconnected: "disconnected";
|
|
50
50
|
}>;
|
|
@@ -117,10 +117,10 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
117
117
|
sessionId: z.ZodString;
|
|
118
118
|
status: z.ZodOptional<z.ZodEnum<{
|
|
119
119
|
error: "error";
|
|
120
|
-
active: "active";
|
|
121
120
|
idle: "idle";
|
|
122
121
|
connecting: "connecting";
|
|
123
122
|
connected: "connected";
|
|
123
|
+
active: "active";
|
|
124
124
|
streaming: "streaming";
|
|
125
125
|
disconnected: "disconnected";
|
|
126
126
|
}>>;
|
|
@@ -354,10 +354,10 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
354
354
|
sessionId: z.ZodString;
|
|
355
355
|
status: z.ZodOptional<z.ZodEnum<{
|
|
356
356
|
error: "error";
|
|
357
|
-
active: "active";
|
|
358
357
|
idle: "idle";
|
|
359
358
|
connecting: "connecting";
|
|
360
359
|
connected: "connected";
|
|
360
|
+
active: "active";
|
|
361
361
|
streaming: "streaming";
|
|
362
362
|
disconnected: "disconnected";
|
|
363
363
|
}>>;
|
|
@@ -561,10 +561,10 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
561
561
|
sessionId: z.ZodString;
|
|
562
562
|
status: z.ZodOptional<z.ZodEnum<{
|
|
563
563
|
error: "error";
|
|
564
|
-
active: "active";
|
|
565
564
|
idle: "idle";
|
|
566
565
|
connecting: "connecting";
|
|
567
566
|
connected: "connected";
|
|
567
|
+
active: "active";
|
|
568
568
|
streaming: "streaming";
|
|
569
569
|
disconnected: "disconnected";
|
|
570
570
|
}>>;
|
|
@@ -626,10 +626,10 @@ export declare const SessionUpdate: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
626
626
|
sessionId: z.ZodString;
|
|
627
627
|
status: z.ZodOptional<z.ZodEnum<{
|
|
628
628
|
error: "error";
|
|
629
|
-
active: "active";
|
|
630
629
|
idle: "idle";
|
|
631
630
|
connecting: "connecting";
|
|
632
631
|
connected: "connected";
|
|
632
|
+
active: "active";
|
|
633
633
|
streaming: "streaming";
|
|
634
634
|
disconnected: "disconnected";
|
|
635
635
|
}>>;
|
|
@@ -978,6 +978,34 @@ export class HttpTransport {
|
|
|
978
978
|
isReplay: this.isInReplayMode,
|
|
979
979
|
});
|
|
980
980
|
}
|
|
981
|
+
else if (update &&
|
|
982
|
+
"sessionUpdate" in update &&
|
|
983
|
+
update.sessionUpdate ===
|
|
984
|
+
"hook_notification") {
|
|
985
|
+
// Hook notification - forward to message queue for processing
|
|
986
|
+
const hookNotificationUpdate = update;
|
|
987
|
+
logger.debug("Received hook_notification", {
|
|
988
|
+
id: hookNotificationUpdate.id,
|
|
989
|
+
notificationType: hookNotificationUpdate.notification.type,
|
|
990
|
+
hookType: hookNotificationUpdate.notification.hookType,
|
|
991
|
+
});
|
|
992
|
+
// Create a hook_notification chunk for the message queue
|
|
993
|
+
// Use type assertion since we know the shape matches HookNotificationChunk
|
|
994
|
+
const hookNotificationChunk = {
|
|
995
|
+
type: "hook_notification",
|
|
996
|
+
id: hookNotificationUpdate.id,
|
|
997
|
+
notification: hookNotificationUpdate.notification,
|
|
998
|
+
messageId: hookNotificationUpdate.messageId,
|
|
999
|
+
};
|
|
1000
|
+
// Queue for ordered processing
|
|
1001
|
+
const resolver = this.chunkResolvers.shift();
|
|
1002
|
+
if (resolver) {
|
|
1003
|
+
resolver(hookNotificationChunk);
|
|
1004
|
+
}
|
|
1005
|
+
else {
|
|
1006
|
+
this.messageQueue.push(hookNotificationChunk);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
981
1009
|
else if (update &&
|
|
982
1010
|
"sessionUpdate" in update &&
|
|
983
1011
|
update.sessionUpdate === "tool_output") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@townco/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.74",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -49,7 +49,7 @@
|
|
|
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.
|
|
52
|
+
"@townco/core": "0.0.52",
|
|
53
53
|
"@uiw/react-json-view": "^2.0.0-alpha.39",
|
|
54
54
|
"bun": "^1.3.1",
|
|
55
55
|
"class-variance-authority": "^0.7.1",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@tailwindcss/postcss": "^4.1.17",
|
|
70
|
-
"@townco/tsconfig": "0.1.
|
|
70
|
+
"@townco/tsconfig": "0.1.71",
|
|
71
71
|
"@types/node": "^24.10.0",
|
|
72
72
|
"@types/react": "^19.2.2",
|
|
73
73
|
"ink": "^6.4.0",
|