gencode-ai 0.1.1 → 0.1.3
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/.gencode/settings.local.json +7 -0
- package/CLAUDE.md +86 -0
- package/README.md +13 -16
- package/dist/agent/agent.d.ts +50 -1
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +96 -16
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/types.d.ts +14 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/cli/components/App.d.ts +8 -1
- package/dist/cli/components/App.d.ts.map +1 -1
- package/dist/cli/components/App.js +266 -29
- package/dist/cli/components/App.js.map +1 -1
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
- package/dist/cli/components/CommandSuggestions.js +2 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -1
- package/dist/cli/components/Header.d.ts +1 -1
- package/dist/cli/components/Header.d.ts.map +1 -1
- package/dist/cli/components/Header.js +4 -6
- package/dist/cli/components/Header.js.map +1 -1
- package/dist/cli/components/Logo.d.ts +1 -0
- package/dist/cli/components/Logo.d.ts.map +1 -1
- package/dist/cli/components/Logo.js +16 -3
- package/dist/cli/components/Logo.js.map +1 -1
- package/dist/cli/components/Messages.d.ts +4 -4
- package/dist/cli/components/Messages.d.ts.map +1 -1
- package/dist/cli/components/Messages.js +66 -23
- package/dist/cli/components/Messages.js.map +1 -1
- package/dist/cli/components/PermissionPrompt.d.ts +60 -0
- package/dist/cli/components/PermissionPrompt.d.ts.map +1 -0
- package/dist/cli/components/PermissionPrompt.js +192 -0
- package/dist/cli/components/PermissionPrompt.js.map +1 -0
- package/dist/cli/components/ProviderManager.js +3 -3
- package/dist/cli/components/ProviderManager.js.map +1 -1
- package/dist/cli/components/QuestionPrompt.d.ts +23 -0
- package/dist/cli/components/QuestionPrompt.d.ts.map +1 -0
- package/dist/cli/components/QuestionPrompt.js +231 -0
- package/dist/cli/components/QuestionPrompt.js.map +1 -0
- package/dist/cli/components/Spinner.d.ts +7 -2
- package/dist/cli/components/Spinner.d.ts.map +1 -1
- package/dist/cli/components/Spinner.js +116 -25
- package/dist/cli/components/Spinner.js.map +1 -1
- package/dist/cli/components/TodoList.d.ts +7 -0
- package/dist/cli/components/TodoList.d.ts.map +1 -0
- package/dist/cli/components/TodoList.js +34 -0
- package/dist/cli/components/TodoList.js.map +1 -0
- package/dist/cli/components/index.d.ts +2 -0
- package/dist/cli/components/index.d.ts.map +1 -1
- package/dist/cli/components/index.js +2 -0
- package/dist/cli/components/index.js.map +1 -1
- package/dist/cli/components/theme.d.ts +7 -0
- package/dist/cli/components/theme.d.ts.map +1 -1
- package/dist/cli/components/theme.js +11 -1
- package/dist/cli/components/theme.js.map +1 -1
- package/dist/cli/index.js +47 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +13 -4
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +18 -3
- package/dist/config/index.js.map +1 -1
- package/dist/config/levels.d.ts +49 -0
- package/dist/config/levels.d.ts.map +1 -0
- package/dist/config/levels.js +222 -0
- package/dist/config/levels.js.map +1 -0
- package/dist/config/loader.d.ts +46 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +153 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/manager.d.ts +115 -15
- package/dist/config/manager.d.ts.map +1 -1
- package/dist/config/manager.js +260 -34
- package/dist/config/manager.js.map +1 -1
- package/dist/config/manager.test.d.ts +5 -0
- package/dist/config/manager.test.d.ts.map +1 -0
- package/dist/config/manager.test.js +192 -0
- package/dist/config/manager.test.js.map +1 -0
- package/dist/config/merger.d.ts +56 -0
- package/dist/config/merger.d.ts.map +1 -0
- package/dist/config/merger.js +177 -0
- package/dist/config/merger.js.map +1 -0
- package/dist/config/test-utils.d.ts +24 -0
- package/dist/config/test-utils.d.ts.map +1 -0
- package/dist/config/test-utils.js +55 -0
- package/dist/config/test-utils.js.map +1 -0
- package/dist/config/types.d.ts +78 -9
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +52 -2
- package/dist/config/types.js.map +1 -1
- package/dist/memory/import-resolver.d.ts +46 -0
- package/dist/memory/import-resolver.d.ts.map +1 -0
- package/dist/memory/import-resolver.js +117 -0
- package/dist/memory/import-resolver.js.map +1 -0
- package/dist/memory/index.d.ts +7 -6
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +7 -5
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/init-prompt.d.ts +22 -0
- package/dist/memory/init-prompt.d.ts.map +1 -0
- package/dist/memory/init-prompt.js +103 -0
- package/dist/memory/init-prompt.js.map +1 -0
- package/dist/memory/memory-manager.d.ts +119 -0
- package/dist/memory/memory-manager.d.ts.map +1 -0
- package/dist/memory/memory-manager.js +587 -0
- package/dist/memory/memory-manager.js.map +1 -0
- package/dist/memory/rules-parser.d.ts +38 -0
- package/dist/memory/rules-parser.d.ts.map +1 -0
- package/dist/memory/rules-parser.js +69 -0
- package/dist/memory/rules-parser.js.map +1 -0
- package/dist/memory/test-utils.d.ts +20 -0
- package/dist/memory/test-utils.d.ts.map +1 -0
- package/dist/memory/test-utils.js +44 -0
- package/dist/memory/test-utils.js.map +1 -0
- package/dist/memory/types.d.ts +70 -63
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/memory/types.js +42 -2
- package/dist/memory/types.js.map +1 -1
- package/dist/permissions/audit.d.ts +82 -0
- package/dist/permissions/audit.d.ts.map +1 -0
- package/dist/permissions/audit.js +229 -0
- package/dist/permissions/audit.js.map +1 -0
- package/dist/permissions/index.d.ts +11 -1
- package/dist/permissions/index.d.ts.map +1 -1
- package/dist/permissions/index.js +15 -0
- package/dist/permissions/index.js.map +1 -1
- package/dist/permissions/manager.d.ts +149 -13
- package/dist/permissions/manager.d.ts.map +1 -1
- package/dist/permissions/manager.js +480 -35
- package/dist/permissions/manager.js.map +1 -1
- package/dist/permissions/manager.test.d.ts +5 -0
- package/dist/permissions/manager.test.d.ts.map +1 -0
- package/dist/permissions/manager.test.js +213 -0
- package/dist/permissions/manager.test.js.map +1 -0
- package/dist/permissions/persistence.d.ts +74 -0
- package/dist/permissions/persistence.d.ts.map +1 -0
- package/dist/permissions/persistence.js +248 -0
- package/dist/permissions/persistence.js.map +1 -0
- package/dist/permissions/persistence.test.d.ts +5 -0
- package/dist/permissions/persistence.test.d.ts.map +1 -0
- package/dist/permissions/persistence.test.js +171 -0
- package/dist/permissions/persistence.test.js.map +1 -0
- package/dist/permissions/prompt-matcher.d.ts +64 -0
- package/dist/permissions/prompt-matcher.d.ts.map +1 -0
- package/dist/permissions/prompt-matcher.js +415 -0
- package/dist/permissions/prompt-matcher.js.map +1 -0
- package/dist/permissions/prompt-matcher.test.d.ts +5 -0
- package/dist/permissions/prompt-matcher.test.d.ts.map +1 -0
- package/dist/permissions/prompt-matcher.test.js +107 -0
- package/dist/permissions/prompt-matcher.test.js.map +1 -0
- package/dist/permissions/types.d.ts +157 -0
- package/dist/permissions/types.d.ts.map +1 -1
- package/dist/permissions/types.js +45 -8
- package/dist/permissions/types.js.map +1 -1
- package/dist/prompts/index.d.ts +92 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +241 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/tools/builtin/ask-user.d.ts +64 -0
- package/dist/tools/builtin/ask-user.d.ts.map +1 -0
- package/dist/tools/builtin/ask-user.js +148 -0
- package/dist/tools/builtin/ask-user.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -1
- package/dist/tools/builtin/bash.js +2 -1
- package/dist/tools/builtin/bash.js.map +1 -1
- package/dist/tools/builtin/edit.d.ts.map +1 -1
- package/dist/tools/builtin/edit.js +2 -1
- package/dist/tools/builtin/edit.js.map +1 -1
- package/dist/tools/builtin/glob.d.ts.map +1 -1
- package/dist/tools/builtin/glob.js +2 -1
- package/dist/tools/builtin/glob.js.map +1 -1
- package/dist/tools/builtin/grep.d.ts.map +1 -1
- package/dist/tools/builtin/grep.js +2 -1
- package/dist/tools/builtin/grep.js.map +1 -1
- package/dist/tools/builtin/read.d.ts.map +1 -1
- package/dist/tools/builtin/read.js +2 -1
- package/dist/tools/builtin/read.js.map +1 -1
- package/dist/tools/builtin/todowrite.d.ts +15 -0
- package/dist/tools/builtin/todowrite.d.ts.map +1 -0
- package/dist/tools/builtin/todowrite.js +88 -0
- package/dist/tools/builtin/todowrite.js.map +1 -0
- package/dist/tools/builtin/webfetch.d.ts.map +1 -1
- package/dist/tools/builtin/webfetch.js +2 -5
- package/dist/tools/builtin/webfetch.js.map +1 -1
- package/dist/tools/builtin/websearch.d.ts.map +1 -1
- package/dist/tools/builtin/websearch.js +2 -16
- package/dist/tools/builtin/websearch.js.map +1 -1
- package/dist/tools/builtin/write.d.ts.map +1 -1
- package/dist/tools/builtin/write.js +2 -1
- package/dist/tools/builtin/write.js.map +1 -1
- package/dist/tools/index.d.ts +19 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +8 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/types.d.ts +39 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +8 -0
- package/dist/tools/types.js.map +1 -1
- package/docs/config-system-comparison.md +707 -0
- package/docs/memory-system.md +238 -0
- package/docs/permissions.md +368 -0
- package/docs/proposals/0005-todo-system.md +350 -85
- package/docs/proposals/0006-memory-system.md +11 -10
- package/docs/proposals/0012-ask-user-question.md +1007 -207
- package/docs/proposals/0023-permission-enhancements.md +61 -2
- package/docs/proposals/0041-configuration-system.md +33 -2
- package/docs/proposals/0042-prompt-optimization.md +866 -0
- package/docs/proposals/README.md +7 -6
- package/examples/test-ask-user.ts +167 -0
- package/jest.config.js +26 -0
- package/package.json +8 -2
- package/src/agent/agent.ts +130 -16
- package/src/agent/index.ts +1 -0
- package/src/agent/types.ts +13 -1
- package/src/cli/components/App.tsx +362 -37
- package/src/cli/components/CommandSuggestions.tsx +2 -0
- package/src/cli/components/Header.tsx +11 -17
- package/src/cli/components/Logo.tsx +76 -9
- package/src/cli/components/Messages.tsx +104 -41
- package/src/cli/components/PermissionPrompt.tsx +388 -0
- package/src/cli/components/ProviderManager.tsx +5 -5
- package/src/cli/components/QuestionPrompt.tsx +462 -0
- package/src/cli/components/Spinner.tsx +138 -25
- package/src/cli/components/TodoList.tsx +54 -0
- package/src/cli/components/index.ts +7 -0
- package/src/cli/components/theme.ts +11 -1
- package/src/cli/index.tsx +54 -6
- package/src/config/index.ts +78 -4
- package/src/config/levels.test.ts +163 -0
- package/src/config/levels.ts +285 -0
- package/src/config/loader.test.ts +120 -0
- package/src/config/loader.ts +178 -0
- package/src/config/manager.test.ts +215 -0
- package/src/config/manager.ts +328 -40
- package/src/config/merger.test.ts +360 -0
- package/src/config/merger.ts +221 -0
- package/src/config/test-utils.ts +79 -0
- package/src/config/types.ts +152 -9
- package/src/memory/import-resolver.test.ts +117 -0
- package/src/memory/import-resolver.ts +149 -0
- package/src/memory/index.ts +11 -0
- package/src/memory/init-prompt.ts +113 -0
- package/src/memory/memory-manager.test.ts +198 -0
- package/src/memory/memory-manager.ts +716 -0
- package/src/memory/rules-parser.test.ts +182 -0
- package/src/memory/rules-parser.ts +82 -0
- package/src/memory/test-utils.ts +60 -0
- package/src/memory/types.ts +119 -0
- package/src/permissions/audit.ts +284 -0
- package/src/permissions/index.ts +20 -1
- package/src/permissions/manager.test.ts +260 -0
- package/src/permissions/manager.ts +592 -40
- package/src/permissions/persistence.test.ts +220 -0
- package/src/permissions/persistence.ts +301 -0
- package/src/permissions/prompt-matcher.test.ts +213 -0
- package/src/permissions/prompt-matcher.ts +472 -0
- package/src/permissions/types.ts +238 -8
- package/src/prompts/index.test.ts +279 -0
- package/src/prompts/index.ts +306 -0
- package/src/prompts/system/anthropic.txt +29 -0
- package/src/prompts/system/base.txt +166 -0
- package/src/prompts/system/gemini.txt +35 -0
- package/src/prompts/system/generic.txt +128 -0
- package/src/prompts/system/openai.txt +29 -0
- package/src/prompts/tools/ask-user.txt +110 -0
- package/src/prompts/tools/bash.txt +60 -0
- package/src/prompts/tools/edit.txt +29 -0
- package/src/prompts/tools/glob.txt +35 -0
- package/src/prompts/tools/grep.txt +43 -0
- package/src/prompts/tools/read.txt +22 -0
- package/src/prompts/tools/todowrite.txt +71 -0
- package/src/prompts/tools/webfetch.txt +34 -0
- package/src/prompts/tools/websearch.txt +41 -0
- package/src/prompts/tools/write.txt +23 -0
- package/src/tools/builtin/ask-user.ts +185 -0
- package/src/tools/builtin/bash.ts +2 -1
- package/src/tools/builtin/edit.ts +2 -1
- package/src/tools/builtin/glob.ts +2 -1
- package/src/tools/builtin/grep.ts +2 -1
- package/src/tools/builtin/read.ts +2 -1
- package/src/tools/builtin/todowrite.ts +102 -0
- package/src/tools/builtin/webfetch.ts +2 -5
- package/src/tools/builtin/websearch.ts +2 -16
- package/src/tools/builtin/write.ts +2 -1
- package/src/tools/index.ts +19 -0
- package/src/tools/types.ts +30 -0
- package/tsconfig.json +1 -1
|
@@ -22,13 +22,24 @@ import { PromptInput, ConfirmPrompt } from './Input.js';
|
|
|
22
22
|
import { ModelSelector } from './ModelSelector.js';
|
|
23
23
|
import { ProviderManager } from './ProviderManager.js';
|
|
24
24
|
import { CommandSuggestions, getFilteredCommands } from './CommandSuggestions.js';
|
|
25
|
+
import {
|
|
26
|
+
PermissionPrompt,
|
|
27
|
+
PermissionRulesDisplay,
|
|
28
|
+
PermissionAuditDisplay,
|
|
29
|
+
} from './PermissionPrompt.js';
|
|
30
|
+
import { TodoList } from './TodoList.js';
|
|
31
|
+
import { QuestionPrompt, AnswerDisplay } from './QuestionPrompt.js';
|
|
25
32
|
import { colors, icons } from './theme.js';
|
|
33
|
+
import { getTodos, formatAnswersForDisplay } from '../../tools/index.js';
|
|
34
|
+
import type { Question, QuestionAnswer } from '../../tools/types.js';
|
|
26
35
|
import type { ProviderName } from '../../providers/index.js';
|
|
36
|
+
import type { ApprovalAction, ApprovalSuggestion } from '../../permissions/types.js';
|
|
37
|
+
import { gatherContextFiles, buildInitPrompt, getContextSummary } from '../../memory/index.js';
|
|
27
38
|
|
|
28
39
|
// Types
|
|
29
40
|
interface HistoryItem {
|
|
30
41
|
id: string;
|
|
31
|
-
type: 'header' | 'welcome' | 'user' | 'assistant' | 'tool_call' | 'tool_result' | 'info' | 'completion';
|
|
42
|
+
type: 'header' | 'welcome' | 'user' | 'assistant' | 'tool_call' | 'tool_result' | 'info' | 'completion' | 'todos';
|
|
32
43
|
content: string;
|
|
33
44
|
meta?: Record<string, unknown>;
|
|
34
45
|
}
|
|
@@ -36,11 +47,19 @@ interface HistoryItem {
|
|
|
36
47
|
interface ConfirmState {
|
|
37
48
|
tool: string;
|
|
38
49
|
input: Record<string, unknown>;
|
|
39
|
-
|
|
50
|
+
suggestions: ApprovalSuggestion[];
|
|
51
|
+
resolve: (action: ApprovalAction) => void;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface QuestionState {
|
|
55
|
+
questions: Question[];
|
|
56
|
+
resolve: (answers: QuestionAnswer[]) => void;
|
|
40
57
|
}
|
|
41
58
|
|
|
42
59
|
interface SettingsManager {
|
|
43
60
|
save: (settings: { model?: string }) => Promise<void>;
|
|
61
|
+
getCwd?: () => string;
|
|
62
|
+
addPermissionRule?: (pattern: string, type: 'allow' | 'deny', level?: 'global' | 'project' | 'local') => Promise<void>;
|
|
44
63
|
}
|
|
45
64
|
|
|
46
65
|
interface Session {
|
|
@@ -49,10 +68,16 @@ interface Session {
|
|
|
49
68
|
updatedAt: string;
|
|
50
69
|
}
|
|
51
70
|
|
|
71
|
+
interface PermissionSettings {
|
|
72
|
+
allow?: string[];
|
|
73
|
+
deny?: string[];
|
|
74
|
+
}
|
|
75
|
+
|
|
52
76
|
interface AppProps {
|
|
53
77
|
config: AgentConfig;
|
|
54
78
|
settingsManager?: SettingsManager;
|
|
55
79
|
resumeLatest?: boolean;
|
|
80
|
+
permissionSettings?: PermissionSettings;
|
|
56
81
|
}
|
|
57
82
|
|
|
58
83
|
// ============================================================================
|
|
@@ -125,10 +150,64 @@ function SessionsTable({ sessions }: SessionsTableProps) {
|
|
|
125
150
|
);
|
|
126
151
|
}
|
|
127
152
|
|
|
153
|
+
// ============================================================================
|
|
154
|
+
// Memory Files Display Component
|
|
155
|
+
// ============================================================================
|
|
156
|
+
interface MemoryFileInfo {
|
|
157
|
+
path: string;
|
|
158
|
+
level: string;
|
|
159
|
+
size: number;
|
|
160
|
+
type: 'file' | 'rule';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function MemoryFilesDisplay({ files }: { files: MemoryFileInfo[] }) {
|
|
164
|
+
const formatSize = (bytes: number): string => {
|
|
165
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
166
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const memoryFiles = files.filter((f) => f.type === 'file');
|
|
170
|
+
const ruleFiles = files.filter((f) => f.type === 'rule');
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<Box flexDirection="column">
|
|
174
|
+
{memoryFiles.length > 0 && (
|
|
175
|
+
<>
|
|
176
|
+
<Text color={colors.info}>Loaded Memory Files:</Text>
|
|
177
|
+
{memoryFiles.map((f, i) => (
|
|
178
|
+
<Text key={f.path}>
|
|
179
|
+
<Text color={colors.textMuted}> [{i + 1}] </Text>
|
|
180
|
+
<Text color={colors.primary}>{f.path} </Text>
|
|
181
|
+
<Text color={colors.textMuted}>({f.level}, {formatSize(f.size)})</Text>
|
|
182
|
+
</Text>
|
|
183
|
+
))}
|
|
184
|
+
</>
|
|
185
|
+
)}
|
|
186
|
+
{ruleFiles.length > 0 && (
|
|
187
|
+
<Box flexDirection="column" marginTop={memoryFiles.length > 0 ? 1 : 0}>
|
|
188
|
+
<Text color={colors.info}>
|
|
189
|
+
Loaded Rules:
|
|
190
|
+
</Text>
|
|
191
|
+
{ruleFiles.map((f, i) => (
|
|
192
|
+
<Text key={f.path}>
|
|
193
|
+
<Text color={colors.textMuted}> [{i + 1}] </Text>
|
|
194
|
+
<Text color={colors.warning}>{f.path} </Text>
|
|
195
|
+
<Text color={colors.textMuted}>({f.level}, {formatSize(f.size)})</Text>
|
|
196
|
+
</Text>
|
|
197
|
+
))}
|
|
198
|
+
</Box>
|
|
199
|
+
)}
|
|
200
|
+
{files.length === 0 && (
|
|
201
|
+
<Text color={colors.textMuted}>No memory files loaded</Text>
|
|
202
|
+
)}
|
|
203
|
+
</Box>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
128
207
|
// ============================================================================
|
|
129
208
|
// Main App
|
|
130
209
|
// ============================================================================
|
|
131
|
-
export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
210
|
+
export function App({ config, settingsManager, resumeLatest, permissionSettings }: AppProps) {
|
|
132
211
|
const { exit } = useApp();
|
|
133
212
|
const agent = useAgent(config);
|
|
134
213
|
|
|
@@ -160,7 +239,10 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
160
239
|
const [isThinking, setIsThinking] = useState(false);
|
|
161
240
|
const [streamingText, setStreamingText] = useState('');
|
|
162
241
|
const streamingTextRef = useRef(''); // Track current streaming text for closure
|
|
242
|
+
const [processingStartTime, setProcessingStartTime] = useState<number | undefined>(undefined);
|
|
243
|
+
const [tokenCount, setTokenCount] = useState(0);
|
|
163
244
|
const [confirmState, setConfirmState] = useState<ConfirmState | null>(null);
|
|
245
|
+
const [questionState, setQuestionState] = useState<QuestionState | null>(null);
|
|
164
246
|
const [showModelSelector, setShowModelSelector] = useState(false);
|
|
165
247
|
const [showProviderManager, setShowProviderManager] = useState(false);
|
|
166
248
|
const [currentModel, setCurrentModel] = useState(config.model);
|
|
@@ -168,6 +250,7 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
168
250
|
const [inputKey, setInputKey] = useState(0); // Force cursor to end after autocomplete
|
|
169
251
|
const [pendingTool, setPendingTool] = useState<{ name: string; input: Record<string, unknown> } | null>(null);
|
|
170
252
|
const pendingToolRef = useRef<{ name: string; input: Record<string, unknown> } | null>(null);
|
|
253
|
+
const [todos, setTodos] = useState<ReturnType<typeof getTodos>>([]);
|
|
171
254
|
|
|
172
255
|
// Check if showing command suggestions
|
|
173
256
|
const showCmdSuggestions = input.startsWith('/') && !isProcessing;
|
|
@@ -186,12 +269,37 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
186
269
|
// Initialize
|
|
187
270
|
useEffect(() => {
|
|
188
271
|
const init = async () => {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
272
|
+
// Initialize permission system with settings
|
|
273
|
+
await agent.initializePermissions(permissionSettings);
|
|
274
|
+
|
|
275
|
+
// Set enhanced confirm callback with approval options
|
|
276
|
+
agent.setEnhancedConfirmCallback(async (tool, toolInput, suggestions) => {
|
|
277
|
+
return new Promise<ApprovalAction>((resolve) => {
|
|
278
|
+
setConfirmState({
|
|
279
|
+
tool,
|
|
280
|
+
input: toolInput as Record<string, unknown>,
|
|
281
|
+
suggestions,
|
|
282
|
+
resolve,
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// Set askUser callback for AskUserQuestion tool
|
|
288
|
+
agent.setAskUserCallback(async (questions) => {
|
|
289
|
+
return new Promise<QuestionAnswer[]>((resolve) => {
|
|
290
|
+
setQuestionState({ questions, resolve });
|
|
192
291
|
});
|
|
193
292
|
});
|
|
194
293
|
|
|
294
|
+
// Set callback to save permission rules to settings.local.json
|
|
295
|
+
if (settingsManager?.addPermissionRule) {
|
|
296
|
+
agent.setSaveRuleCallback(async (tool, pattern) => {
|
|
297
|
+
// Format as Claude Code style pattern: Tool(pattern) or just Tool
|
|
298
|
+
const rulePattern = pattern ? `${tool}(${pattern})` : tool;
|
|
299
|
+
await settingsManager.addPermissionRule!(rulePattern, 'allow', 'local');
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
195
303
|
if (resumeLatest) {
|
|
196
304
|
const resumed = await agent.resumeLatest();
|
|
197
305
|
if (resumed) {
|
|
@@ -200,12 +308,38 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
200
308
|
}
|
|
201
309
|
};
|
|
202
310
|
init();
|
|
203
|
-
}, [agent, resumeLatest, addHistory]);
|
|
311
|
+
}, [agent, resumeLatest, addHistory, permissionSettings, settingsManager]);
|
|
204
312
|
|
|
205
|
-
// Handle
|
|
206
|
-
const
|
|
313
|
+
// Handle question answers (AskUserQuestion)
|
|
314
|
+
const handleQuestionComplete = useCallback((answers: QuestionAnswer[]) => {
|
|
315
|
+
if (questionState) {
|
|
316
|
+
// Show confirmation in history
|
|
317
|
+
addHistory({
|
|
318
|
+
type: 'info',
|
|
319
|
+
content: formatAnswersForDisplay(answers),
|
|
320
|
+
});
|
|
321
|
+
questionState.resolve(answers);
|
|
322
|
+
setQuestionState(null);
|
|
323
|
+
}
|
|
324
|
+
}, [questionState, addHistory]);
|
|
325
|
+
|
|
326
|
+
// Handle question cancel
|
|
327
|
+
const handleQuestionCancel = useCallback(() => {
|
|
328
|
+
if (questionState) {
|
|
329
|
+
// Clear pending tool display (no more spinner)
|
|
330
|
+
pendingToolRef.current = null;
|
|
331
|
+
setPendingTool(null);
|
|
332
|
+
// Add canceled message to history
|
|
333
|
+
addHistory({ type: 'info', content: 'Question canceled' });
|
|
334
|
+
questionState.resolve([]); // Return empty answers on cancel
|
|
335
|
+
setQuestionState(null);
|
|
336
|
+
}
|
|
337
|
+
}, [questionState, addHistory]);
|
|
338
|
+
|
|
339
|
+
// Handle permission decision
|
|
340
|
+
const handlePermissionDecision = (action: ApprovalAction) => {
|
|
207
341
|
if (confirmState) {
|
|
208
|
-
confirmState.resolve(
|
|
342
|
+
confirmState.resolve(action);
|
|
209
343
|
setConfirmState(null);
|
|
210
344
|
}
|
|
211
345
|
};
|
|
@@ -321,13 +455,113 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
321
455
|
return true;
|
|
322
456
|
}
|
|
323
457
|
|
|
458
|
+
case 'permissions': {
|
|
459
|
+
const permManager = agent.getPermissionManager();
|
|
460
|
+
|
|
461
|
+
if (arg === 'audit') {
|
|
462
|
+
// Show audit log
|
|
463
|
+
const auditLog = permManager.getAuditLog(20);
|
|
464
|
+
if (auditLog.length === 0) {
|
|
465
|
+
addHistory({ type: 'info', content: 'No permission decisions recorded yet' });
|
|
466
|
+
} else {
|
|
467
|
+
const entries = auditLog.map((e) => ({
|
|
468
|
+
time: e.timestamp.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }),
|
|
469
|
+
tool: e.tool,
|
|
470
|
+
input: e.inputSummary,
|
|
471
|
+
decision: e.decision,
|
|
472
|
+
rule: e.matchedRule,
|
|
473
|
+
}));
|
|
474
|
+
addHistory({
|
|
475
|
+
type: 'info',
|
|
476
|
+
content: '__PERMISSION_AUDIT__',
|
|
477
|
+
meta: { entries },
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
} else if (arg === 'stats') {
|
|
481
|
+
// Show statistics
|
|
482
|
+
const stats = permManager.getAuditStats();
|
|
483
|
+
addHistory({
|
|
484
|
+
type: 'info',
|
|
485
|
+
content: `Permissions: ${stats.allowed + stats.confirmed} allowed, ${stats.denied + stats.rejected} denied`,
|
|
486
|
+
});
|
|
487
|
+
} else {
|
|
488
|
+
// Show rules
|
|
489
|
+
const rules = permManager.getRules();
|
|
490
|
+
const prompts = permManager.getAllowedPrompts();
|
|
491
|
+
const displayRules = rules.map((r) => ({
|
|
492
|
+
type: r.scope === 'session' ? 'Session' : r.description?.startsWith('Settings') ? 'Settings' : 'Built-in',
|
|
493
|
+
tool: typeof r.tool === 'string' ? r.tool : r.tool.toString(),
|
|
494
|
+
pattern: typeof r.pattern === 'string' ? r.pattern : r.pattern?.toString(),
|
|
495
|
+
scope: r.scope ?? 'session',
|
|
496
|
+
mode: r.mode,
|
|
497
|
+
}));
|
|
498
|
+
addHistory({
|
|
499
|
+
type: 'info',
|
|
500
|
+
content: '__PERMISSIONS__',
|
|
501
|
+
meta: { rules: displayRules, prompts },
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
|
|
324
507
|
case 'init': {
|
|
325
|
-
|
|
508
|
+
// Gather context files and generate AGENT.md
|
|
509
|
+
addHistory({ type: 'info', content: 'Analyzing codebase...' });
|
|
510
|
+
|
|
511
|
+
const contextFiles = await gatherContextFiles(cwd);
|
|
512
|
+
addHistory({ type: 'info', content: getContextSummary(contextFiles) });
|
|
513
|
+
|
|
514
|
+
// Check if AGENT.md already exists
|
|
515
|
+
const memoryManager = agent.getMemoryManager();
|
|
516
|
+
const existingPath = await memoryManager.getExistingProjectMemoryPath(cwd);
|
|
517
|
+
let existingContent: string | undefined;
|
|
518
|
+
|
|
519
|
+
if (existingPath) {
|
|
520
|
+
try {
|
|
521
|
+
const fs = await import('fs/promises');
|
|
522
|
+
existingContent = await fs.readFile(existingPath, 'utf-8');
|
|
523
|
+
addHistory({
|
|
524
|
+
type: 'info',
|
|
525
|
+
content: `Found existing: ${existingPath.replace(cwd, '.')}`,
|
|
526
|
+
});
|
|
527
|
+
} catch {
|
|
528
|
+
// File doesn't exist or can't be read
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Build init prompt and run through agent
|
|
533
|
+
const initPrompt = buildInitPrompt(contextFiles, existingContent);
|
|
534
|
+
addHistory({ type: 'info', content: 'Generating AGENT.md...' });
|
|
535
|
+
addHistory({ type: 'user', content: '/init' });
|
|
536
|
+
await runAgent(initPrompt);
|
|
326
537
|
return true;
|
|
327
538
|
}
|
|
328
539
|
|
|
329
540
|
case 'memory': {
|
|
330
|
-
|
|
541
|
+
// Show loaded memory files
|
|
542
|
+
const memoryManager = agent.getMemoryManager();
|
|
543
|
+
const loadedFiles = memoryManager.getLoadedFileList();
|
|
544
|
+
|
|
545
|
+
if (loadedFiles.length === 0) {
|
|
546
|
+
// Try to load memory first
|
|
547
|
+
await agent.loadMemory();
|
|
548
|
+
const filesAfterLoad = memoryManager.getLoadedFileList();
|
|
549
|
+
if (filesAfterLoad.length === 0) {
|
|
550
|
+
addHistory({ type: 'info', content: 'No memory files found' });
|
|
551
|
+
} else {
|
|
552
|
+
addHistory({
|
|
553
|
+
type: 'info',
|
|
554
|
+
content: '__MEMORY__',
|
|
555
|
+
meta: { files: filesAfterLoad },
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
} else {
|
|
559
|
+
addHistory({
|
|
560
|
+
type: 'info',
|
|
561
|
+
content: '__MEMORY__',
|
|
562
|
+
meta: { files: loadedFiles },
|
|
563
|
+
});
|
|
564
|
+
}
|
|
331
565
|
return true;
|
|
332
566
|
}
|
|
333
567
|
|
|
@@ -347,6 +581,8 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
347
581
|
streamingTextRef.current = '';
|
|
348
582
|
interruptFlagRef.current = false;
|
|
349
583
|
const startTime = Date.now();
|
|
584
|
+
setProcessingStartTime(startTime);
|
|
585
|
+
setTokenCount(0);
|
|
350
586
|
|
|
351
587
|
try {
|
|
352
588
|
for await (const event of agent.run(prompt)) {
|
|
@@ -360,6 +596,8 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
360
596
|
setIsThinking(false);
|
|
361
597
|
streamingTextRef.current += event.text;
|
|
362
598
|
setStreamingText(streamingTextRef.current);
|
|
599
|
+
// Estimate token count (roughly 4 chars per token)
|
|
600
|
+
setTokenCount((prev) => prev + Math.max(1, Math.ceil(event.text.length / 4)));
|
|
363
601
|
break;
|
|
364
602
|
|
|
365
603
|
case 'tool_start':
|
|
@@ -376,24 +614,37 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
376
614
|
break;
|
|
377
615
|
|
|
378
616
|
case 'tool_result':
|
|
379
|
-
//
|
|
380
|
-
if (
|
|
617
|
+
// For TodoWrite: add todos first, then hide tool_call/tool_result
|
|
618
|
+
if (event.name === 'TodoWrite') {
|
|
619
|
+
const currentTodos = getTodos();
|
|
620
|
+
setTodos(currentTodos);
|
|
621
|
+
if (currentTodos.length > 0) {
|
|
622
|
+
addHistory({
|
|
623
|
+
type: 'todos',
|
|
624
|
+
content: '',
|
|
625
|
+
meta: { todos: currentTodos },
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
} else {
|
|
629
|
+
// Add tool_call to history (now completed) - use ref for correct value
|
|
630
|
+
if (pendingToolRef.current) {
|
|
631
|
+
addHistory({
|
|
632
|
+
type: 'tool_call',
|
|
633
|
+
content: pendingToolRef.current.name,
|
|
634
|
+
meta: { toolName: pendingToolRef.current.name, input: pendingToolRef.current.input },
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
// Add tool_result to history
|
|
381
638
|
addHistory({
|
|
382
|
-
type: '
|
|
383
|
-
content:
|
|
384
|
-
meta: {
|
|
639
|
+
type: 'tool_result',
|
|
640
|
+
content: event.result.output,
|
|
641
|
+
meta: {
|
|
642
|
+
toolName: event.name,
|
|
643
|
+
success: event.result.success,
|
|
644
|
+
metadata: event.result.metadata,
|
|
645
|
+
},
|
|
385
646
|
});
|
|
386
647
|
}
|
|
387
|
-
// Add tool_result to history
|
|
388
|
-
addHistory({
|
|
389
|
-
type: 'tool_result',
|
|
390
|
-
content: event.result.output,
|
|
391
|
-
meta: {
|
|
392
|
-
toolName: event.name,
|
|
393
|
-
success: event.result.success,
|
|
394
|
-
metadata: event.result.metadata,
|
|
395
|
-
},
|
|
396
|
-
});
|
|
397
648
|
pendingToolRef.current = null;
|
|
398
649
|
setPendingTool(null);
|
|
399
650
|
setIsThinking(true);
|
|
@@ -413,6 +664,7 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
413
664
|
// Add completion message with duration
|
|
414
665
|
const durationMs = Date.now() - startTime;
|
|
415
666
|
addHistory({ type: 'completion', content: '', meta: { durationMs } });
|
|
667
|
+
setProcessingStartTime(undefined);
|
|
416
668
|
break;
|
|
417
669
|
}
|
|
418
670
|
}
|
|
@@ -454,6 +706,47 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
454
706
|
return;
|
|
455
707
|
}
|
|
456
708
|
|
|
709
|
+
// Handle # prefix for quick memory adds
|
|
710
|
+
// ## note -> user memory (~/.gencode/AGENT.md)
|
|
711
|
+
// # note -> project memory (./AGENT.md)
|
|
712
|
+
if (trimmed.startsWith('#') && !trimmed.startsWith('#!/')) {
|
|
713
|
+
const memoryManager = agent.getMemoryManager();
|
|
714
|
+
let level: 'user' | 'project';
|
|
715
|
+
let content: string;
|
|
716
|
+
|
|
717
|
+
if (trimmed.startsWith('## ')) {
|
|
718
|
+
level = 'user';
|
|
719
|
+
content = trimmed.slice(3).trim();
|
|
720
|
+
} else if (trimmed.startsWith('# ')) {
|
|
721
|
+
level = 'project';
|
|
722
|
+
content = trimmed.slice(2).trim();
|
|
723
|
+
} else {
|
|
724
|
+
// Just # with no space, treat as project
|
|
725
|
+
level = 'project';
|
|
726
|
+
content = trimmed.slice(1).trim();
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
if (!content) {
|
|
730
|
+
addHistory({ type: 'info', content: 'Empty memory entry ignored' });
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
try {
|
|
735
|
+
const savedPath = await memoryManager.quickAdd(content, level, cwd);
|
|
736
|
+
const displayPath = savedPath.replace(process.env.HOME || '', '~');
|
|
737
|
+
addHistory({
|
|
738
|
+
type: 'info',
|
|
739
|
+
content: `Added to ${level} memory: ${displayPath}`,
|
|
740
|
+
});
|
|
741
|
+
} catch (error) {
|
|
742
|
+
addHistory({
|
|
743
|
+
type: 'info',
|
|
744
|
+
content: `Failed to add to memory: ${error instanceof Error ? error.message : String(error)}`,
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
|
|
457
750
|
if (trimmed.startsWith('/')) {
|
|
458
751
|
const handled = await handleCommand(trimmed);
|
|
459
752
|
if (!handled) {
|
|
@@ -478,6 +771,9 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
478
771
|
setIsProcessing(false);
|
|
479
772
|
setStreamingText('');
|
|
480
773
|
streamingTextRef.current = '';
|
|
774
|
+
// Clear pending tool (stop spinner)
|
|
775
|
+
pendingToolRef.current = null;
|
|
776
|
+
setPendingTool(null);
|
|
481
777
|
addHistory({ type: 'info', content: 'Interrupted' });
|
|
482
778
|
}
|
|
483
779
|
|
|
@@ -537,9 +833,29 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
537
833
|
if (item.content === '__SESSIONS__' && item.meta?.input) {
|
|
538
834
|
return <SessionsTable sessions={item.meta.input as Session[]} />;
|
|
539
835
|
}
|
|
836
|
+
if (item.content === '__PERMISSIONS__' && item.meta?.rules) {
|
|
837
|
+
return (
|
|
838
|
+
<PermissionRulesDisplay
|
|
839
|
+
rules={item.meta.rules as { type: string; tool: string; pattern?: string; scope: string; mode: string }[]}
|
|
840
|
+
allowedPrompts={item.meta.prompts as { tool: string; prompt: string }[] | undefined}
|
|
841
|
+
/>
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
if (item.content === '__PERMISSION_AUDIT__' && item.meta?.entries) {
|
|
845
|
+
return (
|
|
846
|
+
<PermissionAuditDisplay
|
|
847
|
+
entries={item.meta.entries as { time: string; tool: string; input: string; decision: string; rule?: string }[]}
|
|
848
|
+
/>
|
|
849
|
+
);
|
|
850
|
+
}
|
|
851
|
+
if (item.content === '__MEMORY__' && item.meta?.files) {
|
|
852
|
+
return <MemoryFilesDisplay files={item.meta.files as MemoryFileInfo[]} />;
|
|
853
|
+
}
|
|
540
854
|
return <InfoMessage text={item.content} />;
|
|
541
855
|
case 'completion':
|
|
542
856
|
return <CompletionMessage durationMs={(item.meta?.durationMs as number) || 0} />;
|
|
857
|
+
case 'todos':
|
|
858
|
+
return <TodoList todos={item.meta?.todos as ReturnType<typeof getTodos>} />;
|
|
543
859
|
default:
|
|
544
860
|
return null;
|
|
545
861
|
}
|
|
@@ -551,17 +867,26 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
551
867
|
{(item) => <Box key={item.id}>{renderHistoryItem(item)}</Box>}
|
|
552
868
|
</Static>
|
|
553
869
|
|
|
554
|
-
{pendingTool && <PendingToolCall name={pendingTool.name} input={pendingTool.input} />}
|
|
870
|
+
{pendingTool && !confirmState && <PendingToolCall name={pendingTool.name} input={pendingTool.input} />}
|
|
555
871
|
|
|
556
872
|
{streamingText && <AssistantMessage text={streamingText} streaming />}
|
|
557
873
|
|
|
558
874
|
{confirmState && (
|
|
559
|
-
<
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
875
|
+
<PermissionPrompt
|
|
876
|
+
tool={confirmState.tool}
|
|
877
|
+
input={confirmState.input}
|
|
878
|
+
suggestions={confirmState.suggestions}
|
|
879
|
+
onDecision={handlePermissionDecision}
|
|
880
|
+
projectPath={settingsManager?.getCwd?.() ?? process.cwd()}
|
|
881
|
+
/>
|
|
882
|
+
)}
|
|
883
|
+
|
|
884
|
+
{questionState && (
|
|
885
|
+
<QuestionPrompt
|
|
886
|
+
questions={questionState.questions}
|
|
887
|
+
onComplete={handleQuestionComplete}
|
|
888
|
+
onCancel={handleQuestionCancel}
|
|
889
|
+
/>
|
|
565
890
|
)}
|
|
566
891
|
|
|
567
892
|
{showModelSelector && (
|
|
@@ -588,7 +913,7 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
588
913
|
</Box>
|
|
589
914
|
)}
|
|
590
915
|
|
|
591
|
-
{!confirmState && !showModelSelector && !showProviderManager && (
|
|
916
|
+
{!confirmState && !questionState && !showModelSelector && !showProviderManager && (
|
|
592
917
|
<Box flexDirection="column" marginTop={1}>
|
|
593
918
|
<PromptInput
|
|
594
919
|
key={inputKey}
|
|
@@ -602,8 +927,8 @@ export function App({ config, settingsManager, resumeLatest }: AppProps) {
|
|
|
602
927
|
</Box>
|
|
603
928
|
)}
|
|
604
929
|
|
|
605
|
-
{isProcessing ? (
|
|
606
|
-
<ProgressBar />
|
|
930
|
+
{isProcessing && !confirmState && !questionState ? (
|
|
931
|
+
<ProgressBar startTime={processingStartTime} tokenCount={tokenCount} isThinking={isThinking} />
|
|
607
932
|
) : showCmdSuggestions && cmdSuggestions.length > 0 ? (
|
|
608
933
|
<Box marginTop={1}>
|
|
609
934
|
<Text color={colors.textMuted}> Tab to complete · ↑↓ navigate</Text>
|
|
@@ -9,6 +9,8 @@ interface Command {
|
|
|
9
9
|
export const COMMANDS: Command[] = [
|
|
10
10
|
{ name: '/model', description: 'Switch model' },
|
|
11
11
|
{ name: '/provider', description: 'Manage providers' },
|
|
12
|
+
{ name: '/permissions', description: 'View permission rules' },
|
|
13
|
+
{ name: '/permissions audit', description: 'View permission audit log' },
|
|
12
14
|
{ name: '/sessions', description: 'List sessions' },
|
|
13
15
|
{ name: '/resume', description: 'Resume session' },
|
|
14
16
|
{ name: '/new', description: 'New session' },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box, Text } from 'ink';
|
|
2
2
|
import { colors } from './theme.js';
|
|
3
|
-
import {
|
|
3
|
+
import { BigLogo } from './Logo.js';
|
|
4
4
|
|
|
5
5
|
interface HeaderProps {
|
|
6
6
|
provider: string;
|
|
@@ -8,20 +8,14 @@ interface HeaderProps {
|
|
|
8
8
|
cwd: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export function Header({
|
|
12
|
-
const home = process.env.HOME || '';
|
|
13
|
-
const cwdDisplay = cwd.startsWith(home) ? '~' + cwd.slice(home.length) : cwd;
|
|
14
|
-
|
|
11
|
+
export function Header({ model, cwd }: HeaderProps) {
|
|
15
12
|
return (
|
|
16
|
-
<Box flexDirection="
|
|
17
|
-
<
|
|
18
|
-
<Box
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
</Box>
|
|
23
|
-
<Text color={colors.textMuted}>{model} · API Usage Billing</Text>
|
|
24
|
-
<Text color={colors.textMuted}>{cwdDisplay}</Text>
|
|
13
|
+
<Box flexDirection="column" marginTop={1}>
|
|
14
|
+
<BigLogo />
|
|
15
|
+
<Box marginTop={1}>
|
|
16
|
+
<Text color={colors.textSecondary}>{model}</Text>
|
|
17
|
+
<Text color={colors.textMuted}> · </Text>
|
|
18
|
+
<Text color={colors.textMuted}>{cwd}</Text>
|
|
25
19
|
</Box>
|
|
26
20
|
</Box>
|
|
27
21
|
);
|
|
@@ -29,8 +23,8 @@ export function Header({ provider, model, cwd }: HeaderProps) {
|
|
|
29
23
|
|
|
30
24
|
export function Welcome() {
|
|
31
25
|
return (
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
</
|
|
26
|
+
<Box marginTop={1}>
|
|
27
|
+
<Text color={colors.textMuted}>? for help · Ctrl+C to exit</Text>
|
|
28
|
+
</Box>
|
|
35
29
|
);
|
|
36
30
|
}
|