| 124 | } |
| 125 | |
| 126 | function makeHost({ |
| 127 | session, |
| 128 | }: { |
| 129 | readonly session?: Record<string, unknown>; |
| 130 | } = {}) { |
| 131 | const state = { |
| 132 | appState: { |
| 133 | theme: 'dark', |
| 134 | editorCommand: null, |
| 135 | notifications: { enabled: true, condition: 'unfocused' }, |
| 136 | upgrade: { autoInstall: true }, |
| 137 | availableModels: {}, |
| 138 | availableProviders: {}, |
| 139 | }, |
| 140 | editor: { |
| 141 | setDisablePasteBurst: vi.fn(), |
| 142 | }, |
| 143 | theme: { |
| 144 | palette: { |
| 145 | success: '#00ff00', |
| 146 | }, |
| 147 | }, |
| 148 | }; |
| 149 | return { |
| 150 | state, |
| 151 | session, |
| 152 | harness: { |
| 153 | getConfig: vi.fn(async () => ({ |
| 154 | models: { |
| 155 | fresh: { provider: 'test', model: 'fresh-model', maxContextSize: 1000 }, |
| 156 | }, |
| 157 | providers: { |
| 158 | test: { type: 'kimi', apiKey: 'test-key' }, |
| 159 | }, |
| 160 | })), |
| 161 | getExperimentalFeatures: vi.fn(async () => [{ id: 'micro_compaction', enabled: true }]), |
| 162 | }, |
| 163 | setAppState: vi.fn((patch: Record<string, unknown>) => { |
| 164 | Object.assign(state.appState, patch); |
| 165 | }), |
| 166 | applyTheme: vi.fn((theme: string) => { |
| 167 | state.appState.theme = theme; |
| 168 | }), |
| 169 | refreshTerminalThemeTracking: vi.fn(), |
| 170 | refreshSlashCommandAutocomplete: vi.fn(), |
| 171 | reloadCurrentSessionView: vi.fn(async () => {}), |
| 172 | showStatus: vi.fn(), |
| 173 | } as unknown as SlashCommandHost & { |
| 174 | readonly harness: { |
| 175 | readonly getConfig: ReturnType<typeof vi.fn>; |
| 176 | readonly getExperimentalFeatures: ReturnType<typeof vi.fn>; |
| 177 | }; |
| 178 | readonly refreshSlashCommandAutocomplete: ReturnType<typeof vi.fn>; |
| 179 | readonly reloadCurrentSessionView: ReturnType<typeof vi.fn>; |
| 180 | readonly showStatus: ReturnType<typeof vi.fn>; |
| 181 | }; |
| 182 | } |