@townco/ui 0.1.32 → 0.1.34

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 (50) hide show
  1. package/dist/core/hooks/use-chat-session.d.ts +1 -1
  2. package/dist/core/hooks/use-chat-session.js +33 -15
  3. package/dist/core/schemas/chat.d.ts +1 -1
  4. package/dist/core/store/chat-store.js +17 -2
  5. package/dist/gui/components/Button.js +1 -1
  6. package/dist/gui/components/ChatEmptyState.js +1 -1
  7. package/dist/gui/components/ChatHeader.js +2 -2
  8. package/dist/gui/components/ChatInput.js +1 -1
  9. package/dist/gui/components/ChatInputCommandMenu.js +1 -1
  10. package/dist/gui/components/ChatLayout.js +1 -1
  11. package/dist/gui/components/ChatPanelTabContent.d.ts +3 -0
  12. package/dist/gui/components/ChatPanelTabContent.js +24 -5
  13. package/dist/gui/components/ChatSecondaryPanel.js +3 -3
  14. package/dist/gui/components/ChatView.js +28 -9
  15. package/dist/gui/components/Dialog.js +2 -2
  16. package/dist/gui/components/DropdownMenu.js +7 -7
  17. package/dist/gui/components/FileSystemItem.d.ts +17 -0
  18. package/dist/gui/components/FileSystemItem.js +81 -0
  19. package/dist/gui/components/FileSystemView.d.ts +14 -0
  20. package/dist/gui/components/FileSystemView.js +46 -0
  21. package/dist/gui/components/Input.js +1 -1
  22. package/dist/gui/components/Label.js +1 -1
  23. package/dist/gui/components/MarkdownRenderer.js +5 -5
  24. package/dist/gui/components/Message.d.ts +1 -1
  25. package/dist/gui/components/MessageContent.js +8 -8
  26. package/dist/gui/components/PanelTabsHeader.js +1 -1
  27. package/dist/gui/components/Reasoning.js +2 -2
  28. package/dist/gui/components/Response.js +13 -11
  29. package/dist/gui/components/Select.js +3 -3
  30. package/dist/gui/components/SourceListItem.js +1 -1
  31. package/dist/gui/components/Tabs.js +1 -1
  32. package/dist/gui/components/Task.js +2 -2
  33. package/dist/gui/components/Textarea.js +1 -1
  34. package/dist/gui/components/ThinkingBlock.js +2 -2
  35. package/dist/gui/components/TodoList.js +1 -1
  36. package/dist/gui/components/ToolCall.js +67 -70
  37. package/dist/gui/components/ToolCallList.js +1 -1
  38. package/dist/gui/components/index.d.ts +4 -0
  39. package/dist/gui/components/index.js +4 -0
  40. package/dist/gui/data/mockFileSystemData.d.ts +21 -0
  41. package/dist/gui/data/mockFileSystemData.js +127 -0
  42. package/dist/gui/types/filesystem.d.ts +27 -0
  43. package/dist/gui/types/filesystem.js +5 -0
  44. package/dist/sdk/schemas/session.d.ts +12 -12
  45. package/package.json +3 -3
  46. package/src/styles/global.css +108 -0
  47. package/dist/core/lib/logger.d.ts +0 -59
  48. package/dist/core/lib/logger.js +0 -191
  49. package/dist/tui/components/LogsPanel.d.ts +0 -5
  50. package/dist/tui/components/LogsPanel.js +0 -29
@@ -1,191 +0,0 @@
1
- /**
2
- * Browser-compatible logger
3
- * Outputs structured JSON logs to console with color-coding
4
- * Also captures logs to a global store for in-app viewing
5
- * In Node.js environment with logsDir option, also writes to .logs/ directory
6
- */
7
- // Check if running in Node.js
8
- const isNode = typeof process !== "undefined" && process.versions?.node;
9
- // Global logs directory configuration (set once at app startup for TUI)
10
- let globalLogsDir;
11
- // Global log store
12
- const globalLogStore = [];
13
- let logIdCounter = 0;
14
- /**
15
- * Get all captured logs
16
- */
17
- export function getCapturedLogs() {
18
- return [...globalLogStore];
19
- }
20
- /**
21
- * Clear all captured logs
22
- */
23
- export function clearCapturedLogs() {
24
- globalLogStore.length = 0;
25
- }
26
- const logSubscribers = new Set();
27
- export function subscribeToLogs(callback) {
28
- logSubscribers.add(callback);
29
- return () => logSubscribers.delete(callback);
30
- }
31
- function notifyLogSubscribers(entry) {
32
- for (const callback of logSubscribers) {
33
- callback(entry);
34
- }
35
- }
36
- /**
37
- * Configure global logs directory for file writing
38
- * Must be called before creating any loggers (typically at TUI startup)
39
- */
40
- export function configureLogsDir(logsDir) {
41
- globalLogsDir = logsDir;
42
- }
43
- const LOG_LEVELS = {
44
- trace: 0,
45
- debug: 1,
46
- info: 2,
47
- warn: 3,
48
- error: 4,
49
- fatal: 5,
50
- };
51
- const _LOG_COLORS = {
52
- trace: "#6B7280", // gray
53
- debug: "#3B82F6", // blue
54
- info: "#10B981", // green
55
- warn: "#F59E0B", // orange
56
- error: "#EF4444", // red
57
- fatal: "#DC2626", // dark red
58
- };
59
- const _LOG_STYLES = {
60
- trace: "color: #6B7280",
61
- debug: "color: #3B82F6; font-weight: bold",
62
- info: "color: #10B981; font-weight: bold",
63
- warn: "color: #F59E0B; font-weight: bold",
64
- error: "color: #EF4444; font-weight: bold",
65
- fatal: "color: #DC2626; font-weight: bold; background: #FEE2E2",
66
- };
67
- export class Logger {
68
- service;
69
- minLevel;
70
- logFilePath;
71
- logsDir;
72
- writeQueue = [];
73
- isWriting = false;
74
- constructor(service, minLevel = "debug") {
75
- this.service = service;
76
- this.minLevel = minLevel;
77
- // In production, suppress trace and debug logs
78
- if (typeof process !== "undefined" &&
79
- process.env?.NODE_ENV === "production") {
80
- this.minLevel = "info";
81
- }
82
- // Note: File logging setup is done lazily in log() method
83
- // This allows loggers created before configureLogsDir() to still write to files
84
- }
85
- setupFileLogging() {
86
- if (!isNode || !globalLogsDir)
87
- return;
88
- try {
89
- // Dynamic import for Node.js modules
90
- const path = require("node:path");
91
- const fs = require("node:fs");
92
- this.logsDir = globalLogsDir;
93
- this.logFilePath = path.join(this.logsDir, `${this.service}.log`);
94
- // Create logs directory if it doesn't exist
95
- if (!fs.existsSync(this.logsDir)) {
96
- fs.mkdirSync(this.logsDir, { recursive: true });
97
- }
98
- }
99
- catch (_error) {
100
- // Silently fail if we can't set up file logging
101
- }
102
- }
103
- async writeToFile(content) {
104
- if (!this.logFilePath || !isNode)
105
- return;
106
- this.writeQueue.push(content);
107
- if (this.isWriting) {
108
- return;
109
- }
110
- this.isWriting = true;
111
- while (this.writeQueue.length > 0) {
112
- const batch = this.writeQueue.splice(0, this.writeQueue.length);
113
- const data = `${batch.join("\n")}\n`;
114
- try {
115
- // Dynamic import for Node.js modules
116
- const fs = require("node:fs");
117
- await fs.promises.appendFile(this.logFilePath, data, "utf-8");
118
- }
119
- catch (_error) {
120
- // Silently fail
121
- }
122
- }
123
- this.isWriting = false;
124
- }
125
- shouldLog(level) {
126
- return LOG_LEVELS[level] >= LOG_LEVELS[this.minLevel];
127
- }
128
- log(level, message, metadata) {
129
- if (!this.shouldLog(level)) {
130
- return;
131
- }
132
- const entry = {
133
- id: `log_${++logIdCounter}`,
134
- timestamp: new Date().toISOString(),
135
- level,
136
- service: this.service,
137
- message,
138
- ...(metadata && { metadata }),
139
- };
140
- // Store in global log store
141
- globalLogStore.push(entry);
142
- // Notify subscribers
143
- notifyLogSubscribers(entry);
144
- // Write to file in Node.js (for logs tab to read)
145
- // Lazily set up file logging if globalLogsDir was configured after this logger was created
146
- if (isNode && !this.logFilePath && globalLogsDir) {
147
- this.setupFileLogging();
148
- }
149
- if (isNode && this.logFilePath) {
150
- // Write as JSON without the id field (to match expected format)
151
- const fileEntry = {
152
- timestamp: entry.timestamp,
153
- level: entry.level,
154
- service: entry.service,
155
- message: entry.message,
156
- ...(entry.metadata && { metadata: entry.metadata }),
157
- };
158
- this.writeToFile(JSON.stringify(fileEntry)).catch(() => {
159
- // Silently fail
160
- });
161
- }
162
- // No console output - logs are only captured and displayed in UI
163
- // This prevents logs from polluting stdout/stderr in TUI mode
164
- }
165
- trace(message, metadata) {
166
- this.log("trace", message, metadata);
167
- }
168
- debug(message, metadata) {
169
- this.log("debug", message, metadata);
170
- }
171
- info(message, metadata) {
172
- this.log("info", message, metadata);
173
- }
174
- warn(message, metadata) {
175
- this.log("warn", message, metadata);
176
- }
177
- error(message, metadata) {
178
- this.log("error", message, metadata);
179
- }
180
- fatal(message, metadata) {
181
- this.log("fatal", message, metadata);
182
- }
183
- }
184
- /**
185
- * Create a logger instance for a service
186
- * @param service - Service name (e.g., "gui", "http-agent", "tui")
187
- * @param minLevel - Minimum log level to display (default: "debug")
188
- */
189
- export function createLogger(service, minLevel = "debug") {
190
- return new Logger(service, minLevel);
191
- }
@@ -1,5 +0,0 @@
1
- import type { LogEntry } from "../../core/lib/logger.js";
2
- export interface LogsPanelProps {
3
- logs: LogEntry[];
4
- }
5
- export declare function LogsPanel({ logs: initialLogs }: LogsPanelProps): import("react/jsx-runtime").JSX.Element;
@@ -1,29 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from "ink";
3
- import { useEffect, useState } from "react";
4
- import { subscribeToLogs } from "../../core/lib/logger.js";
5
- // Color mapping for log levels
6
- const LOG_LEVEL_COLORS = {
7
- trace: "gray",
8
- debug: "blue",
9
- info: "green",
10
- warn: "yellow",
11
- error: "red",
12
- fatal: "red",
13
- };
14
- export function LogsPanel({ logs: initialLogs }) {
15
- const [logs, setLogs] = useState(initialLogs);
16
- // Subscribe to new logs
17
- useEffect(() => {
18
- const unsubscribe = subscribeToLogs((entry) => {
19
- setLogs((prev) => [...prev, entry]);
20
- });
21
- return unsubscribe;
22
- }, []);
23
- if (logs.length === 0) {
24
- return (_jsx(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: _jsx(Text, { dimColor: true, children: "No logs yet..." }) }));
25
- }
26
- // Show last 100 logs
27
- const displayLogs = logs.slice(-100);
28
- return (_jsx(Box, { flexDirection: "column", paddingX: 1, children: displayLogs.map((log) => (_jsxs(Box, { flexDirection: "row", gap: 1, children: [_jsx(Text, { dimColor: true, children: new Date(log.timestamp).toLocaleTimeString() }), _jsxs(Text, { color: LOG_LEVEL_COLORS[log.level], bold: true, children: ["[", log.level.toUpperCase(), "]"] }), _jsxs(Text, { dimColor: true, children: ["[", log.service, "]"] }), _jsx(Text, { children: log.message }), log.metadata && (_jsx(Text, { dimColor: true, children: JSON.stringify(log.metadata) }))] }, log.id))) }));
29
- }