@vybestack/llxprt-code 0.1.18-nightly.250808.f9b79d74 → 0.1.18-nightly.250811.b0db22c6

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 (194) hide show
  1. package/dist/package.json +5 -3
  2. package/dist/src/auth/gemini-oauth-provider.d.ts +15 -0
  3. package/dist/src/auth/gemini-oauth-provider.js +33 -0
  4. package/dist/src/auth/gemini-oauth-provider.js.map +1 -0
  5. package/dist/src/auth/oauth-manager.d.ts +103 -0
  6. package/dist/src/auth/oauth-manager.js +326 -0
  7. package/dist/src/auth/oauth-manager.js.map +1 -0
  8. package/dist/src/auth/oauth-manager.spec.d.ts +6 -0
  9. package/dist/src/auth/oauth-manager.spec.js +523 -0
  10. package/dist/src/auth/oauth-manager.spec.js.map +1 -0
  11. package/dist/src/auth/qwen-oauth-provider.d.ts +14 -0
  12. package/dist/src/auth/qwen-oauth-provider.js +75 -0
  13. package/dist/src/auth/qwen-oauth-provider.js.map +1 -0
  14. package/dist/src/auth/types.d.ts +7 -0
  15. package/dist/src/auth/types.js +7 -0
  16. package/dist/src/auth/types.js.map +1 -0
  17. package/dist/src/config/auth.js +9 -0
  18. package/dist/src/config/auth.js.map +1 -1
  19. package/dist/src/config/config.js +93 -43
  20. package/dist/src/config/config.js.map +1 -1
  21. package/dist/src/config/keyBindings.d.ts +66 -0
  22. package/dist/src/config/keyBindings.js +136 -0
  23. package/dist/src/config/keyBindings.js.map +1 -0
  24. package/dist/src/config/settings.d.ts +3 -59
  25. package/dist/src/config/settings.js +17 -1
  26. package/dist/src/config/settings.js.map +1 -1
  27. package/dist/src/config/settingsSchema.d.ts +587 -0
  28. package/dist/src/config/settingsSchema.js +565 -0
  29. package/dist/src/config/settingsSchema.js.map +1 -0
  30. package/dist/src/gemini.js +12 -109
  31. package/dist/src/gemini.js.map +1 -1
  32. package/dist/src/generated/git-commit.d.ts +1 -1
  33. package/dist/src/generated/git-commit.js +1 -1
  34. package/dist/src/nonInteractiveCli.js +0 -1
  35. package/dist/src/nonInteractiveCli.js.map +1 -1
  36. package/dist/src/providers/logging/git-stats-service-impl.d.ts +19 -0
  37. package/dist/src/providers/logging/git-stats-service-impl.js +25 -0
  38. package/dist/src/providers/logging/git-stats-service-impl.js.map +1 -0
  39. package/dist/src/providers/logging/git-stats.d.ts +43 -0
  40. package/dist/src/providers/logging/git-stats.js +137 -0
  41. package/dist/src/providers/logging/git-stats.js.map +1 -0
  42. package/dist/src/providers/providerManagerInstance.js +39 -4
  43. package/dist/src/providers/providerManagerInstance.js.map +1 -1
  44. package/dist/src/services/BuiltinCommandLoader.js +4 -0
  45. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  46. package/dist/src/services/todo-continuation/todoContinuationService.d.ts +172 -0
  47. package/dist/src/services/todo-continuation/todoContinuationService.js +387 -0
  48. package/dist/src/services/todo-continuation/todoContinuationService.js.map +1 -0
  49. package/dist/src/services/todo-continuation/todoContinuationService.spec.d.ts +6 -0
  50. package/dist/src/services/todo-continuation/todoContinuationService.spec.js +385 -0
  51. package/dist/src/services/todo-continuation/todoContinuationService.spec.js.map +1 -0
  52. package/dist/src/ui/App.js +76 -26
  53. package/dist/src/ui/App.js.map +1 -1
  54. package/dist/src/ui/colors.d.ts +5 -0
  55. package/dist/src/ui/colors.js +51 -0
  56. package/dist/src/ui/colors.js.map +1 -1
  57. package/dist/src/ui/commands/authCommand.d.ts +11 -1
  58. package/dist/src/ui/commands/authCommand.js +143 -48
  59. package/dist/src/ui/commands/authCommand.js.map +1 -1
  60. package/dist/src/ui/commands/chatCommand.js +16 -0
  61. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  62. package/dist/src/ui/commands/ideCommand.js +67 -31
  63. package/dist/src/ui/commands/ideCommand.js.map +1 -1
  64. package/dist/src/ui/commands/keyfileCommand.js +15 -12
  65. package/dist/src/ui/commands/keyfileCommand.js.map +1 -1
  66. package/dist/src/ui/commands/loggingCommand.d.ts +15 -0
  67. package/dist/src/ui/commands/loggingCommand.js +421 -0
  68. package/dist/src/ui/commands/loggingCommand.js.map +1 -0
  69. package/dist/src/ui/commands/privacyCommand.d.ts +3 -0
  70. package/dist/src/ui/commands/privacyCommand.js +6 -3
  71. package/dist/src/ui/commands/privacyCommand.js.map +1 -1
  72. package/dist/src/ui/commands/settingsCommand.d.ts +7 -0
  73. package/dist/src/ui/commands/settingsCommand.js +16 -0
  74. package/dist/src/ui/commands/settingsCommand.js.map +1 -0
  75. package/dist/src/ui/commands/setupGithubCommand.js +21 -2
  76. package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
  77. package/dist/src/ui/commands/types.d.ts +14 -2
  78. package/dist/src/ui/commands/types.js.map +1 -1
  79. package/dist/src/ui/components/AuthDialog.js +13 -56
  80. package/dist/src/ui/components/AuthDialog.js.map +1 -1
  81. package/dist/src/ui/components/AuthInProgress.js +3 -3
  82. package/dist/src/ui/components/AuthInProgress.js.map +1 -1
  83. package/dist/src/ui/components/ContextUsageDisplay.d.ts +10 -0
  84. package/dist/src/ui/components/ContextUsageDisplay.js +27 -0
  85. package/dist/src/ui/components/ContextUsageDisplay.js.map +1 -0
  86. package/dist/src/ui/components/FolderTrustDialog.d.ts +16 -0
  87. package/dist/src/ui/components/FolderTrustDialog.js +38 -0
  88. package/dist/src/ui/components/FolderTrustDialog.js.map +1 -0
  89. package/dist/src/ui/components/Footer.js +132 -15
  90. package/dist/src/ui/components/Footer.js.map +1 -1
  91. package/dist/src/ui/components/InputPrompt.d.ts +1 -0
  92. package/dist/src/ui/components/InputPrompt.js +87 -31
  93. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  94. package/dist/src/ui/components/LoggingDialog.d.ts +37 -0
  95. package/dist/src/ui/components/LoggingDialog.js +155 -0
  96. package/dist/src/ui/components/LoggingDialog.js.map +1 -0
  97. package/dist/src/ui/components/MemoryUsageDisplay.js +6 -4
  98. package/dist/src/ui/components/MemoryUsageDisplay.js.map +1 -1
  99. package/dist/src/ui/components/ProviderDialog.js +100 -26
  100. package/dist/src/ui/components/ProviderDialog.js.map +1 -1
  101. package/dist/src/ui/components/ProviderModelDialog.js +99 -27
  102. package/dist/src/ui/components/ProviderModelDialog.js.map +1 -1
  103. package/dist/src/ui/components/SettingsDialog.d.ts +14 -0
  104. package/dist/src/ui/components/SettingsDialog.js +247 -0
  105. package/dist/src/ui/components/SettingsDialog.js.map +1 -0
  106. package/dist/src/ui/components/ThemeDialog.js +4 -15
  107. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  108. package/dist/src/ui/components/TodoPanel.js +93 -18
  109. package/dist/src/ui/components/TodoPanel.js.map +1 -1
  110. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +85 -7
  111. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  112. package/dist/src/ui/contexts/SettingsContext.d.ts +9 -0
  113. package/dist/src/ui/contexts/SettingsContext.js +15 -0
  114. package/dist/src/ui/contexts/SettingsContext.js.map +1 -0
  115. package/dist/src/ui/hooks/atCommandProcessor.js +21 -0
  116. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  117. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +6 -2
  118. package/dist/src/ui/hooks/slashCommandProcessor.js +142 -113
  119. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  120. package/dist/src/ui/hooks/useAtCompletion.js +1 -1
  121. package/dist/src/ui/hooks/useAuthCommand.js +14 -0
  122. package/dist/src/ui/hooks/useAuthCommand.js.map +1 -1
  123. package/dist/src/ui/hooks/useConsoleMessages.js +7 -0
  124. package/dist/src/ui/hooks/useConsoleMessages.js.map +1 -1
  125. package/dist/src/ui/hooks/useFolderTrust.d.ts +11 -0
  126. package/dist/src/ui/hooks/useFolderTrust.js +22 -0
  127. package/dist/src/ui/hooks/useFolderTrust.js.map +1 -0
  128. package/dist/src/ui/hooks/useGeminiStream.js +14 -3
  129. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  130. package/dist/src/ui/hooks/useResponsive.d.ts +14 -0
  131. package/dist/src/ui/hooks/useResponsive.js +19 -0
  132. package/dist/src/ui/hooks/useResponsive.js.map +1 -0
  133. package/dist/src/ui/hooks/useSettingsCommand.d.ts +10 -0
  134. package/dist/src/ui/hooks/useSettingsCommand.js +21 -0
  135. package/dist/src/ui/hooks/useSettingsCommand.js.map +1 -0
  136. package/dist/src/ui/hooks/useTodoContinuation.d.ts +31 -0
  137. package/dist/src/ui/hooks/useTodoContinuation.js +148 -0
  138. package/dist/src/ui/hooks/useTodoContinuation.js.map +1 -0
  139. package/dist/src/ui/hooks/useTodoContinuation.spec.d.ts +6 -0
  140. package/dist/src/ui/hooks/useTodoContinuation.spec.js +378 -0
  141. package/dist/src/ui/hooks/useTodoContinuation.spec.js.map +1 -0
  142. package/dist/src/ui/keyMatchers.d.ts +26 -0
  143. package/dist/src/ui/keyMatchers.js +68 -0
  144. package/dist/src/ui/keyMatchers.js.map +1 -0
  145. package/dist/src/ui/privacy/PrivacyNotice.js +10 -4
  146. package/dist/src/ui/privacy/PrivacyNotice.js.map +1 -1
  147. package/dist/src/ui/themes/semantic-resolver.d.ts +12 -0
  148. package/dist/src/ui/themes/semantic-resolver.js +32 -0
  149. package/dist/src/ui/themes/semantic-resolver.js.map +1 -0
  150. package/dist/src/ui/themes/semantic-tokens.d.ts +52 -0
  151. package/dist/src/ui/themes/semantic-tokens.js +7 -0
  152. package/dist/src/ui/themes/semantic-tokens.js.map +1 -0
  153. package/dist/src/ui/themes/theme-compat.d.ts +34 -0
  154. package/dist/src/ui/themes/theme-compat.js +65 -0
  155. package/dist/src/ui/themes/theme-compat.js.map +1 -0
  156. package/dist/src/ui/themes/theme-manager.d.ts +8 -0
  157. package/dist/src/ui/themes/theme-manager.js +18 -0
  158. package/dist/src/ui/themes/theme-manager.js.map +1 -1
  159. package/dist/src/ui/utils/CodeColorizer.d.ts +2 -1
  160. package/dist/src/ui/utils/CodeColorizer.js +4 -3
  161. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  162. package/dist/src/ui/utils/MarkdownDisplay.js +4 -2
  163. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  164. package/dist/src/ui/utils/commandUtils.d.ts +1 -0
  165. package/dist/src/ui/utils/commandUtils.js +22 -1
  166. package/dist/src/ui/utils/commandUtils.js.map +1 -1
  167. package/dist/src/ui/utils/responsive.d.ts +16 -0
  168. package/dist/src/ui/utils/responsive.js +111 -0
  169. package/dist/src/ui/utils/responsive.js.map +1 -0
  170. package/dist/src/utils/cleanup.d.ts +2 -2
  171. package/dist/src/utils/cleanup.js +2 -2
  172. package/dist/src/utils/cleanup.js.map +1 -1
  173. package/dist/src/utils/dialogScopeUtils.d.ts +31 -0
  174. package/dist/src/utils/dialogScopeUtils.js +48 -0
  175. package/dist/src/utils/dialogScopeUtils.js.map +1 -0
  176. package/dist/src/utils/gitUtils.d.ts +9 -0
  177. package/dist/src/utils/gitUtils.js +17 -0
  178. package/dist/src/utils/gitUtils.js.map +1 -1
  179. package/dist/src/utils/privacy/ConversationDataRedactor.d.ts +75 -0
  180. package/dist/src/utils/privacy/ConversationDataRedactor.js +412 -0
  181. package/dist/src/utils/privacy/ConversationDataRedactor.js.map +1 -0
  182. package/dist/src/utils/privacy/PrivacyManager.d.ts +58 -0
  183. package/dist/src/utils/privacy/PrivacyManager.js +133 -0
  184. package/dist/src/utils/privacy/PrivacyManager.js.map +1 -0
  185. package/dist/src/utils/sandbox.js +10 -0
  186. package/dist/src/utils/sandbox.js.map +1 -1
  187. package/dist/src/utils/settingsUtils.d.ts +126 -0
  188. package/dist/src/utils/settingsUtils.js +327 -0
  189. package/dist/src/utils/settingsUtils.js.map +1 -0
  190. package/dist/tsconfig.tsbuildinfo +1 -1
  191. package/package.json +5 -3
  192. package/dist/src/ui/components/IDEContextDetailDisplay.d.ts +0 -12
  193. package/dist/src/ui/components/IDEContextDetailDisplay.js +0 -17
  194. package/dist/src/ui/components/IDEContextDetailDisplay.js.map +0 -1
@@ -0,0 +1,378 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Vybestack LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach, } from 'vitest';
7
+ import { renderHook, act } from '@testing-library/react';
8
+ import { useTodoContinuation } from './useTodoContinuation.js';
9
+ import { useTodoContext } from '../contexts/TodoContext.js';
10
+ import { Config, GeminiClient, ApprovalMode, } from '@vybestack/llxprt-code-core';
11
+ // Mock dependencies
12
+ vi.mock('../contexts/TodoContext.js');
13
+ vi.mock('@vybestack/llxprt-code-core', async () => {
14
+ const actual = (await vi.importActual('@vybestack/llxprt-code-core'));
15
+ return {
16
+ ...actual,
17
+ Config: vi.fn(),
18
+ GeminiClient: vi.fn(),
19
+ };
20
+ });
21
+ describe('useTodoContinuation - Behavioral Tests', () => {
22
+ let mockConfig;
23
+ let mockGeminiClient;
24
+ let mockTodoContext;
25
+ let mockOnDebugMessage;
26
+ const createTodo = (id, content, status = 'pending') => ({
27
+ id,
28
+ content,
29
+ status,
30
+ priority: 'medium',
31
+ });
32
+ beforeEach(() => {
33
+ vi.resetAllMocks();
34
+ // Mock Config
35
+ mockConfig = {
36
+ getEphemeralSettings: vi.fn().mockReturnValue({}),
37
+ getApprovalMode: vi.fn().mockReturnValue(ApprovalMode.DEFAULT),
38
+ };
39
+ Config.mockImplementation(() => mockConfig);
40
+ // Mock GeminiClient
41
+ mockGeminiClient = {
42
+ sendMessageStream: vi.fn().mockResolvedValue(undefined),
43
+ };
44
+ GeminiClient.mockImplementation(() => mockGeminiClient);
45
+ // Mock TodoContext
46
+ mockTodoContext = {
47
+ todos: [],
48
+ updateTodos: vi.fn(),
49
+ refreshTodos: vi.fn(),
50
+ };
51
+ useTodoContext.mockReturnValue(mockTodoContext);
52
+ // Mock debug message handler
53
+ mockOnDebugMessage = vi.fn();
54
+ });
55
+ describe('Stream Completion Detection', () => {
56
+ it('@requirement REQ-001.1 should trigger continuation when stream completes without tool calls and has active todos', () => {
57
+ // Given: Active todos exist and todo-continuation is enabled
58
+ mockTodoContext.todos = [
59
+ createTodo('1', 'Complete feature implementation', 'in_progress'),
60
+ createTodo('2', 'Write tests', 'pending'),
61
+ ];
62
+ mockConfig.getEphemeralSettings.mockReturnValue({
63
+ 'todo-continuation': true,
64
+ });
65
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, // not responding
66
+ mockOnDebugMessage));
67
+ // When: Stream completes without tool calls
68
+ act(() => {
69
+ result.current.handleStreamCompleted(false);
70
+ });
71
+ // Then: Continuation should be triggered
72
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith(expect.stringContaining('Complete feature implementation'), { ephemeral: true });
73
+ });
74
+ it('@requirement REQ-001.2 should NOT trigger when no active todos exist', () => {
75
+ // Given: No active todos
76
+ mockTodoContext.todos = [createTodo('1', 'Completed task', 'completed')];
77
+ mockConfig.getEphemeralSettings.mockReturnValue({
78
+ 'todo-continuation': true,
79
+ });
80
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
81
+ // When: Stream completes without tool calls
82
+ act(() => {
83
+ result.current.handleStreamCompleted(false);
84
+ });
85
+ // Then: No continuation should be triggered
86
+ expect(mockGeminiClient.sendMessageStream).not.toHaveBeenCalled();
87
+ });
88
+ it('@requirement REQ-001.2 should NOT trigger when tool calls were present', () => {
89
+ // Given: Active todos exist and continuation is enabled
90
+ mockTodoContext.todos = [createTodo('1', 'Active task', 'in_progress')];
91
+ mockConfig.getEphemeralSettings.mockReturnValue({
92
+ 'todo-continuation': true,
93
+ });
94
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
95
+ // When: Stream completes WITH tool calls
96
+ act(() => {
97
+ result.current.handleStreamCompleted(true);
98
+ });
99
+ // Then: No continuation should be triggered
100
+ expect(mockGeminiClient.sendMessageStream).not.toHaveBeenCalled();
101
+ });
102
+ it('@requirement REQ-001.4 should NOT trigger when todo-continuation setting is disabled', () => {
103
+ // Given: Active todos exist but continuation is disabled
104
+ mockTodoContext.todos = [createTodo('1', 'Active task', 'in_progress')];
105
+ mockConfig.getEphemeralSettings.mockReturnValue({
106
+ 'todo-continuation': false,
107
+ });
108
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
109
+ // When: Stream completes without tool calls
110
+ act(() => {
111
+ result.current.handleStreamCompleted(false);
112
+ });
113
+ // Then: No continuation should be triggered
114
+ expect(mockGeminiClient.sendMessageStream).not.toHaveBeenCalled();
115
+ });
116
+ it('@requirement REQ-001.3 should NOT trigger when AI is currently responding', () => {
117
+ // Given: Active todos and continuation enabled
118
+ mockTodoContext.todos = [createTodo('1', 'Active task', 'in_progress')];
119
+ mockConfig.getEphemeralSettings.mockReturnValue({
120
+ 'todo-continuation': true,
121
+ });
122
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, true, // currently responding
123
+ mockOnDebugMessage));
124
+ // When: Stream completes without tool calls
125
+ act(() => {
126
+ result.current.handleStreamCompleted(false);
127
+ });
128
+ // Then: No continuation should be triggered
129
+ expect(mockGeminiClient.sendMessageStream).not.toHaveBeenCalled();
130
+ });
131
+ });
132
+ describe('Prompt Generation', () => {
133
+ it('@requirement REQ-002.1 should send ephemeral prompt with most relevant active task', () => {
134
+ // Given: Multiple active todos with priorities
135
+ mockTodoContext.todos = [
136
+ createTodo('1', 'Fix critical bug', 'in_progress'),
137
+ createTodo('2', 'Update documentation', 'pending'),
138
+ createTodo('3', 'Add new feature', 'pending'),
139
+ ];
140
+ mockConfig.getEphemeralSettings.mockReturnValue({
141
+ 'todo-continuation': true,
142
+ });
143
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
144
+ // When: Stream completes without tool calls
145
+ act(() => {
146
+ result.current.handleStreamCompleted(false);
147
+ });
148
+ // Then: Should send prompt with in_progress task (most relevant)
149
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith(expect.stringContaining('Fix critical bug'), { ephemeral: true });
150
+ });
151
+ it('@requirement REQ-002.2 should use different prompt for YOLO mode', () => {
152
+ // Given: YOLO mode is active
153
+ mockTodoContext.todos = [
154
+ createTodo('1', 'Complete implementation', 'in_progress'),
155
+ ];
156
+ mockConfig.getEphemeralSettings.mockReturnValue({
157
+ 'todo-continuation': true,
158
+ });
159
+ mockConfig.getApprovalMode.mockReturnValue(ApprovalMode.YOLO);
160
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
161
+ // When: Stream completes without tool calls
162
+ act(() => {
163
+ result.current.handleStreamCompleted(false);
164
+ });
165
+ // Then: Should use YOLO-specific prompt
166
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith(expect.stringMatching(/(continue|proceed).*without.*confirmation/i), { ephemeral: true });
167
+ });
168
+ it('@requirement REQ-002.1 should NOT store prompt in conversation history', () => {
169
+ // Given: Active todos and continuation enabled
170
+ mockTodoContext.todos = [createTodo('1', 'Active task', 'in_progress')];
171
+ mockConfig.getEphemeralSettings.mockReturnValue({
172
+ 'todo-continuation': true,
173
+ });
174
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
175
+ // When: Stream completes without tool calls
176
+ act(() => {
177
+ result.current.handleStreamCompleted(false);
178
+ });
179
+ // Then: Should send with ephemeral flag
180
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith(expect.any(String), { ephemeral: true });
181
+ });
182
+ });
183
+ describe('Integration with TodoContext', () => {
184
+ it('@requirement REQ-003.1 should respond to todo state changes', () => {
185
+ const { result, rerender } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
186
+ // Given: Initially no todos
187
+ mockTodoContext.todos = [];
188
+ mockConfig.getEphemeralSettings.mockReturnValue({
189
+ 'todo-continuation': true,
190
+ });
191
+ // When: Stream completes (should not trigger)
192
+ act(() => {
193
+ result.current.handleStreamCompleted(false);
194
+ });
195
+ expect(mockGeminiClient.sendMessageStream).not.toHaveBeenCalled();
196
+ // When: Todos are updated with active task
197
+ mockTodoContext.todos = [
198
+ createTodo('1', 'New active task', 'in_progress'),
199
+ ];
200
+ rerender();
201
+ // Then: Next completion should trigger continuation
202
+ act(() => {
203
+ result.current.handleStreamCompleted(false);
204
+ });
205
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith(expect.stringContaining('New active task'), { ephemeral: true });
206
+ });
207
+ it('@requirement REQ-003.2 should handle todo_pause events', () => {
208
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
209
+ // When: Todo pause is requested
210
+ const pauseResult = result.current.handleTodoPause('User requested pause');
211
+ // Then: Should return pause event structure
212
+ expect(pauseResult).toEqual({
213
+ type: 'pause',
214
+ reason: 'User requested pause',
215
+ message: expect.stringContaining('paused'),
216
+ });
217
+ });
218
+ });
219
+ describe('State Management', () => {
220
+ it('@requirement REQ-004.1 should track continuation state', () => {
221
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
222
+ // Initially not active
223
+ expect(result.current.continuationState.isActive).toBe(false);
224
+ expect(result.current.continuationState.attemptCount).toBe(0);
225
+ // Given: Active todos and continuation enabled
226
+ mockTodoContext.todos = [createTodo('1', 'Active task', 'in_progress')];
227
+ mockConfig.getEphemeralSettings.mockReturnValue({
228
+ 'todo-continuation': true,
229
+ });
230
+ // When: Continuation is triggered
231
+ act(() => {
232
+ result.current.handleStreamCompleted(false);
233
+ });
234
+ // Then: State should be updated
235
+ expect(result.current.continuationState.taskDescription).toContain('Active task');
236
+ });
237
+ it('@requirement REQ-004.2 should reset state appropriately', () => {
238
+ // Given: Active continuation state
239
+ mockTodoContext.todos = [createTodo('1', 'Task 1', 'in_progress')];
240
+ mockConfig.getEphemeralSettings.mockReturnValue({
241
+ 'todo-continuation': true,
242
+ });
243
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
244
+ // Trigger continuation
245
+ act(() => {
246
+ result.current.handleStreamCompleted(false);
247
+ });
248
+ // When: Stream completes with tool calls (should reset)
249
+ act(() => {
250
+ result.current.handleStreamCompleted(true);
251
+ });
252
+ // Then: State should be reset
253
+ expect(result.current.continuationState.isActive).toBe(false);
254
+ });
255
+ });
256
+ describe('Edge Cases', () => {
257
+ it('@requirement REQ-005.1 should handle multiple rapid completions', () => {
258
+ // Given: Continuation enabled with active todo
259
+ mockTodoContext.todos = [createTodo('1', 'Active task', 'in_progress')];
260
+ mockConfig.getEphemeralSettings.mockReturnValue({
261
+ 'todo-continuation': true,
262
+ });
263
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
264
+ // When: Multiple rapid completions occur
265
+ act(() => {
266
+ result.current.handleStreamCompleted(false);
267
+ result.current.handleStreamCompleted(false);
268
+ result.current.handleStreamCompleted(false);
269
+ });
270
+ // Then: Should not trigger multiple continuations simultaneously
271
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(1);
272
+ });
273
+ it('@requirement REQ-005.2 should handle changing settings mid-stream', () => {
274
+ // Given: Initially enabled
275
+ mockTodoContext.todos = [createTodo('1', 'Active task', 'in_progress')];
276
+ mockConfig.getEphemeralSettings.mockReturnValue({
277
+ 'todo-continuation': true,
278
+ });
279
+ const { result, rerender } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
280
+ // When: Setting is changed during hook lifecycle
281
+ mockConfig.getEphemeralSettings.mockReturnValue({
282
+ 'todo-continuation': false,
283
+ });
284
+ rerender();
285
+ // Then: Should respect new setting
286
+ act(() => {
287
+ result.current.handleStreamCompleted(false);
288
+ });
289
+ expect(mockGeminiClient.sendMessageStream).not.toHaveBeenCalled();
290
+ });
291
+ it('@requirement REQ-005.3 should handle malformed todos gracefully', () => {
292
+ // Given: Malformed todos (missing required fields)
293
+ mockTodoContext.todos = [
294
+ {
295
+ id: '1',
296
+ content: '',
297
+ status: 'in_progress',
298
+ priority: 'medium',
299
+ },
300
+ // @ts-expect-error Testing malformed data
301
+ {
302
+ id: '2',
303
+ status: 'pending',
304
+ priority: 'high',
305
+ },
306
+ ];
307
+ mockConfig.getEphemeralSettings.mockReturnValue({
308
+ 'todo-continuation': true,
309
+ });
310
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
311
+ // When: Stream completes
312
+ act(() => {
313
+ result.current.handleStreamCompleted(false);
314
+ });
315
+ // Then: Should handle gracefully without crashing
316
+ expect(() => {
317
+ result.current.handleStreamCompleted(false);
318
+ }).not.toThrow();
319
+ // Should either skip malformed todos or handle them safely
320
+ if (mockGeminiClient.sendMessageStream.mock.calls.length > 0) {
321
+ const callArgs = mockGeminiClient.sendMessageStream.mock.calls[0];
322
+ expect(callArgs[0]).toBeTypeOf('string');
323
+ expect(callArgs[1]).toEqual({ ephemeral: true });
324
+ }
325
+ });
326
+ it('@requirement REQ-005.4 should prevent continuation loops', () => {
327
+ // Given: Continuation enabled
328
+ mockTodoContext.todos = [createTodo('1', 'Active task', 'in_progress')];
329
+ mockConfig.getEphemeralSettings.mockReturnValue({
330
+ 'todo-continuation': true,
331
+ });
332
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
333
+ // When: Continuation is triggered multiple times in sequence
334
+ act(() => {
335
+ result.current.handleStreamCompleted(false);
336
+ });
337
+ const firstCallCount = mockGeminiClient.sendMessageStream.mock.calls.length;
338
+ act(() => {
339
+ result.current.handleStreamCompleted(false);
340
+ });
341
+ // Then: Should not trigger additional continuations if already active
342
+ expect(mockGeminiClient.sendMessageStream.mock.calls.length).toBe(firstCallCount);
343
+ });
344
+ });
345
+ describe('Configuration Integration', () => {
346
+ it('@requirement REQ-006.1 should respect default settings when todo-continuation is undefined', () => {
347
+ // Given: Settings don't specify todo-continuation
348
+ mockTodoContext.todos = [createTodo('1', 'Active task', 'in_progress')];
349
+ mockConfig.getEphemeralSettings.mockReturnValue({});
350
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
351
+ // When: Stream completes without tool calls
352
+ act(() => {
353
+ result.current.handleStreamCompleted(false);
354
+ });
355
+ // Then: Should use default behavior (disabled)
356
+ expect(mockGeminiClient.sendMessageStream).not.toHaveBeenCalled();
357
+ });
358
+ it('@requirement REQ-006.2 should prioritize in_progress todos over pending ones', () => {
359
+ // Given: Mix of pending and in_progress todos
360
+ mockTodoContext.todos = [
361
+ createTodo('1', 'Pending task', 'pending'),
362
+ createTodo('2', 'Active task', 'in_progress'),
363
+ createTodo('3', 'Another pending', 'pending'),
364
+ ];
365
+ mockConfig.getEphemeralSettings.mockReturnValue({
366
+ 'todo-continuation': true,
367
+ });
368
+ const { result } = renderHook(() => useTodoContinuation(mockGeminiClient, mockConfig, false, mockOnDebugMessage));
369
+ // When: Stream completes
370
+ act(() => {
371
+ result.current.handleStreamCompleted(false);
372
+ });
373
+ // Then: Should select in_progress task
374
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith(expect.stringContaining('Active task'), { ephemeral: true });
375
+ });
376
+ });
377
+ });
378
+ //# sourceMappingURL=useTodoContinuation.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTodoContinuation.spec.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useTodoContinuation.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { Key } from './hooks/useKeypress.js';
7
+ import { Command, KeyBindingConfig } from '../config/keyBindings.js';
8
+ /**
9
+ * Key matcher function type
10
+ */
11
+ type KeyMatcher = (key: Key) => boolean;
12
+ /**
13
+ * Type for key matchers mapped to Command enum
14
+ */
15
+ export type KeyMatchers = {
16
+ readonly [C in Command]: KeyMatcher;
17
+ };
18
+ /**
19
+ * Creates key matchers from a key binding configuration
20
+ */
21
+ export declare function createKeyMatchers(config?: KeyBindingConfig): KeyMatchers;
22
+ /**
23
+ * Default key binding matchers using the default configuration
24
+ */
25
+ export declare const keyMatchers: KeyMatchers;
26
+ export { Command };
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Command, defaultKeyBindings, } from '../config/keyBindings.js';
7
+ /**
8
+ * Matches a KeyBinding against an actual Key press
9
+ * Pure data-driven matching logic
10
+ */
11
+ function matchKeyBinding(keyBinding, key) {
12
+ // Either key name or sequence must match (but not both should be defined)
13
+ let keyMatches = false;
14
+ if (keyBinding.key !== undefined) {
15
+ keyMatches = keyBinding.key === key.name;
16
+ }
17
+ else if (keyBinding.sequence !== undefined) {
18
+ keyMatches = keyBinding.sequence === key.sequence;
19
+ }
20
+ else {
21
+ // Neither key nor sequence defined - invalid binding
22
+ return false;
23
+ }
24
+ if (!keyMatches) {
25
+ return false;
26
+ }
27
+ // Check modifiers - follow original logic:
28
+ // undefined = ignore this modifier (original behavior)
29
+ // true = modifier must be pressed
30
+ // false = modifier must NOT be pressed
31
+ if (keyBinding.ctrl !== undefined && key.ctrl !== keyBinding.ctrl) {
32
+ return false;
33
+ }
34
+ if (keyBinding.shift !== undefined && key.shift !== keyBinding.shift) {
35
+ return false;
36
+ }
37
+ if (keyBinding.command !== undefined && key.meta !== keyBinding.command) {
38
+ return false;
39
+ }
40
+ if (keyBinding.paste !== undefined && key.paste !== keyBinding.paste) {
41
+ return false;
42
+ }
43
+ return true;
44
+ }
45
+ /**
46
+ * Checks if a key matches any of the bindings for a command
47
+ */
48
+ function matchCommand(command, key, config = defaultKeyBindings) {
49
+ const bindings = config[command];
50
+ return bindings.some((binding) => matchKeyBinding(binding, key));
51
+ }
52
+ /**
53
+ * Creates key matchers from a key binding configuration
54
+ */
55
+ export function createKeyMatchers(config = defaultKeyBindings) {
56
+ const matchers = {};
57
+ for (const command of Object.values(Command)) {
58
+ matchers[command] = (key) => matchCommand(command, key, config);
59
+ }
60
+ return matchers;
61
+ }
62
+ /**
63
+ * Default key binding matchers using the default configuration
64
+ */
65
+ export const keyMatchers = createKeyMatchers(defaultKeyBindings);
66
+ // Re-export Command for convenience
67
+ export { Command };
68
+ //# sourceMappingURL=keyMatchers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyMatchers.js","sourceRoot":"","sources":["../../../src/ui/keyMatchers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,OAAO,EAGP,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAElC;;;GAGG;AACH,SAAS,eAAe,CAAC,UAAsB,EAAE,GAAQ;IACvD,0EAA0E;IAC1E,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,IAAI,UAAU,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QACjC,UAAU,GAAG,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC;IAC3C,CAAC;SAAM,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC7C,UAAU,GAAG,UAAU,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,qDAAqD;QACrD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2CAA2C;IAC3C,uDAAuD;IACvD,kCAAkC;IAClC,uCAAuC;IAEvC,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;QAClE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,UAAU,CAAC,OAAO,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CACnB,OAAgB,EAChB,GAAQ,EACR,SAA2B,kBAAkB;IAE7C,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;AACnE,CAAC;AAcD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAA2B,kBAAkB;IAE7C,MAAM,QAAQ,GAAG,EAAoC,CAAC;IAEtD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,QAAuB,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAgB,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;AAE9E,oCAAoC;AACpC,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -17,13 +17,19 @@ const NonGeminiProviderNotice = ({ providerName, onExit, }) => {
17
17
  };
18
18
  const PrivacyNoticeText = ({ config, onExit, }) => {
19
19
  const authType = config.getContentGeneratorConfig()?.authType;
20
- // Check if we're using a non-Gemini provider
20
+ // Check if we're using a non-Gemini provider or llxprt multi-provider
21
21
  const providerManager = config.getProviderManager?.();
22
22
  const activeProvider = providerManager?.getActiveProvider?.();
23
23
  const isNonGeminiProvider = activeProvider && activeProvider.name !== 'gemini';
24
- // Don't show Gemini-specific privacy notices for non-Gemini providers
25
- if (authType === AuthType.USE_PROVIDER && isNonGeminiProvider) {
26
- return (_jsx(NonGeminiProviderNotice, { providerName: activeProvider.name, onExit: onExit }));
24
+ // For llxprt multi-provider or when content generator is not initialized,
25
+ // show the basic Gemini privacy notice
26
+ if (!authType || authType === AuthType.USE_PROVIDER || isNonGeminiProvider) {
27
+ // If we have a specific non-Gemini provider, show its notice
28
+ if (isNonGeminiProvider) {
29
+ return (_jsx(NonGeminiProviderNotice, { providerName: activeProvider.name, onExit: onExit }));
30
+ }
31
+ // Otherwise show basic Gemini API terms
32
+ return _jsx(GeminiPrivacyNotice, { onExit: onExit });
27
33
  }
28
34
  switch (authType) {
29
35
  case AuthType.USE_GEMINI:
@@ -1 +1 @@
1
- {"version":3,"file":"PrivacyNotice.js","sourceRoot":"","sources":["../../../../src/ui/privacy/PrivacyNotice.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAe,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAOrE,MAAM,uBAAuB,GAAG,CAAC,EAC/B,YAAY,EACZ,MAAM,GAIP,EAAE,EAAE;IACH,QAAQ,CAAC,GAAG,EAAE;QACZ,MAAM,EAAE,CAAC;IACX,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,aACpC,MAAC,IAAI,yBAAQ,YAAY,kBAAkB,EAC3C,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,2CAAkC,IAChD,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,EACzB,MAAM,EACN,MAAM,GAIP,EAAE,EAAE;IACH,MAAM,QAAQ,GAAG,MAAM,CAAC,yBAAyB,EAAE,EAAE,QAAQ,CAAC;IAE9D,6CAA6C;IAC7C,MAAM,eAAe,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,CAAC;IACtD,MAAM,cAAc,GAAG,eAAe,EAAE,iBAAiB,EAAE,EAAE,CAAC;IAC9D,MAAM,mBAAmB,GACvB,cAAc,IAAI,cAAc,CAAC,IAAI,KAAK,QAAQ,CAAC;IAErD,sEAAsE;IACtE,IAAI,QAAQ,KAAK,QAAQ,CAAC,YAAY,IAAI,mBAAmB,EAAE,CAAC;QAC9D,OAAO,CACL,KAAC,uBAAuB,IACtB,YAAY,EAAE,cAAc,CAAC,IAAI,EACjC,MAAM,EAAE,MAAM,GACd,CACH,CAAC;IACJ,CAAC;IAED,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,UAAU;YACtB,OAAO,KAAC,mBAAmB,IAAC,MAAM,EAAE,MAAM,GAAI,CAAC;QACjD,KAAK,QAAQ,CAAC,aAAa;YACzB,OAAO,KAAC,sBAAsB,IAAC,MAAM,EAAE,MAAM,GAAI,CAAC;QACpD,KAAK,QAAQ,CAAC,iBAAiB,CAAC;QAChC;YACE,OAAO,KAAC,sBAAsB,IAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAI,CAAC;IACtE,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAsB,EAAE,EAAE,CAAC,CACvE,KAAC,GAAG,IAAC,WAAW,EAAC,OAAO,EAAC,OAAO,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,YACzD,KAAC,iBAAiB,IAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAI,GACjD,CACP,CAAC"}
1
+ {"version":3,"file":"PrivacyNotice.js","sourceRoot":"","sources":["../../../../src/ui/privacy/PrivacyNotice.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAe,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAOrE,MAAM,uBAAuB,GAAG,CAAC,EAC/B,YAAY,EACZ,MAAM,GAIP,EAAE,EAAE;IACH,QAAQ,CAAC,GAAG,EAAE;QACZ,MAAM,EAAE,CAAC;IACX,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,aACpC,MAAC,IAAI,yBAAQ,YAAY,kBAAkB,EAC3C,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,2CAAkC,IAChD,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,EACzB,MAAM,EACN,MAAM,GAIP,EAAE,EAAE;IACH,MAAM,QAAQ,GAAG,MAAM,CAAC,yBAAyB,EAAE,EAAE,QAAQ,CAAC;IAE9D,sEAAsE;IACtE,MAAM,eAAe,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,CAAC;IACtD,MAAM,cAAc,GAAG,eAAe,EAAE,iBAAiB,EAAE,EAAE,CAAC;IAC9D,MAAM,mBAAmB,GACvB,cAAc,IAAI,cAAc,CAAC,IAAI,KAAK,QAAQ,CAAC;IAErD,0EAA0E;IAC1E,uCAAuC;IACvC,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,QAAQ,CAAC,YAAY,IAAI,mBAAmB,EAAE,CAAC;QAC3E,6DAA6D;QAC7D,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,CACL,KAAC,uBAAuB,IACtB,YAAY,EAAE,cAAc,CAAC,IAAI,EACjC,MAAM,EAAE,MAAM,GACd,CACH,CAAC;QACJ,CAAC;QACD,wCAAwC;QACxC,OAAO,KAAC,mBAAmB,IAAC,MAAM,EAAE,MAAM,GAAI,CAAC;IACjD,CAAC;IAED,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,UAAU;YACtB,OAAO,KAAC,mBAAmB,IAAC,MAAM,EAAE,MAAM,GAAI,CAAC;QACjD,KAAK,QAAQ,CAAC,aAAa;YACzB,OAAO,KAAC,sBAAsB,IAAC,MAAM,EAAE,MAAM,GAAI,CAAC;QACpD,KAAK,QAAQ,CAAC,iBAAiB,CAAC;QAChC;YACE,OAAO,KAAC,sBAAsB,IAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAI,CAAC;IACtE,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAsB,EAAE,EAAE,CAAC,CACvE,KAAC,GAAG,IAAC,WAAW,EAAC,OAAO,EAAC,OAAO,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,YACzD,KAAC,iBAAiB,IAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAI,GACjD,CACP,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ColorsTheme } from './theme.js';
7
+ import { SemanticColors } from './semantic-tokens.js';
8
+ /**
9
+ * Resolves a theme's colors to semantic color tokens.
10
+ * Maps theme-specific colors to meaningful semantic purposes.
11
+ */
12
+ export declare function resolveSemanticColors(theme: ColorsTheme): SemanticColors;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Resolves a theme's colors to semantic color tokens.
8
+ * Maps theme-specific colors to meaningful semantic purposes.
9
+ */
10
+ export function resolveSemanticColors(theme) {
11
+ return {
12
+ text: {
13
+ primary: theme.Foreground,
14
+ secondary: theme.Gray,
15
+ accent: theme.AccentBlue,
16
+ },
17
+ status: {
18
+ success: theme.AccentGreen,
19
+ warning: theme.AccentYellow,
20
+ error: theme.AccentRed,
21
+ },
22
+ background: {
23
+ primary: theme.Background,
24
+ secondary: theme.DiffAdded ?? theme.AccentGreen,
25
+ },
26
+ border: {
27
+ default: theme.Gray,
28
+ focused: theme.AccentBlue,
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=semantic-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-resolver.js","sourceRoot":"","sources":["../../../../src/ui/themes/semantic-resolver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO;QACL,IAAI,EAAE;YACJ,OAAO,EAAE,KAAK,CAAC,UAAU;YACzB,SAAS,EAAE,KAAK,CAAC,IAAI;YACrB,MAAM,EAAE,KAAK,CAAC,UAAU;SACzB;QACD,MAAM,EAAE;YACN,OAAO,EAAE,KAAK,CAAC,WAAW;YAC1B,OAAO,EAAE,KAAK,CAAC,YAAY;YAC3B,KAAK,EAAE,KAAK,CAAC,SAAS;SACvB;QACD,UAAU,EAAE;YACV,OAAO,EAAE,KAAK,CAAC,UAAU;YACzB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,WAAW;SAChD;QACD,MAAM,EAAE;YACN,OAAO,EAAE,KAAK,CAAC,IAAI;YACnB,OAAO,EAAE,KAAK,CAAC,UAAU;SAC1B;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Semantic color tokens that provide meaningful color abstractions
8
+ * for different UI purposes. These tokens map to actual colors
9
+ * based on the active theme.
10
+ */
11
+ export interface SemanticColors {
12
+ /**
13
+ * Colors for text content at different hierarchy levels
14
+ */
15
+ text: {
16
+ /** Primary text color for main content */
17
+ primary: string;
18
+ /** Secondary text color for less important content */
19
+ secondary: string;
20
+ /** Accent text color for highlighted or interactive content */
21
+ accent: string;
22
+ };
23
+ /**
24
+ * Colors for status indicators and feedback
25
+ */
26
+ status: {
27
+ /** Color for successful states and positive feedback */
28
+ success: string;
29
+ /** Color for warning states and cautionary messages */
30
+ warning: string;
31
+ /** Color for error states and critical issues */
32
+ error: string;
33
+ };
34
+ /**
35
+ * Colors for background surfaces
36
+ */
37
+ background: {
38
+ /** Primary background color for main surfaces */
39
+ primary: string;
40
+ /** Secondary background color for secondary surfaces */
41
+ secondary: string;
42
+ };
43
+ /**
44
+ * Colors for borders and dividers
45
+ */
46
+ border: {
47
+ /** Default border color for general use */
48
+ default: string;
49
+ /** Border color for focused or active elements */
50
+ focused: string;
51
+ };
52
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=semantic-tokens.js.map