@machina.ai/cell-cli-core 1.40.1-rc1 → 1.41.1-rc1

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 (176) hide show
  1. package/dist/docs/AFTER_MERGE_PROMPT.md +1 -1
  2. package/dist/docs/changelogs/index.md +18 -0
  3. package/dist/docs/changelogs/latest.md +243 -255
  4. package/dist/docs/changelogs/preview.md +168 -18
  5. package/dist/docs/cli/sandbox.md +162 -45
  6. package/dist/docs/cli/settings.md +19 -13
  7. package/dist/docs/reference/configuration.md +77 -0
  8. package/dist/docs/reference/keyboard-shortcuts.md +1 -0
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/package.json +2 -1
  13. package/dist/src/agents/browser/browser-tools-manifest.json +20 -20
  14. package/dist/src/agents/local-executor.js +8 -0
  15. package/dist/src/agents/local-executor.js.map +1 -1
  16. package/dist/src/agents/skill-extraction-agent.js +5 -4
  17. package/dist/src/agents/skill-extraction-agent.js.map +1 -1
  18. package/dist/src/agents/skill-extraction-agent.test.js +4 -2
  19. package/dist/src/agents/skill-extraction-agent.test.js.map +1 -1
  20. package/dist/src/agents/types.d.ts +2 -0
  21. package/dist/src/agents/types.js.map +1 -1
  22. package/dist/src/code_assist/server.js +16 -0
  23. package/dist/src/code_assist/server.js.map +1 -1
  24. package/dist/src/code_assist/server.test.js +18 -0
  25. package/dist/src/code_assist/server.test.js.map +1 -1
  26. package/dist/src/config/config.d.ts +6 -0
  27. package/dist/src/config/config.js +26 -8
  28. package/dist/src/config/config.js.map +1 -1
  29. package/dist/src/config/config.test.js +39 -1
  30. package/dist/src/config/config.test.js.map +1 -1
  31. package/dist/src/config/defaultModelConfigs.js +34 -0
  32. package/dist/src/config/defaultModelConfigs.js.map +1 -1
  33. package/dist/src/config/models.d.ts +3 -1
  34. package/dist/src/config/models.js +21 -4
  35. package/dist/src/config/models.js.map +1 -1
  36. package/dist/src/config/models.test.js +23 -1
  37. package/dist/src/config/models.test.js.map +1 -1
  38. package/dist/src/context/config/configLoader.d.ts +1 -2
  39. package/dist/src/context/config/configLoader.js +12 -7
  40. package/dist/src/context/config/configLoader.js.map +1 -1
  41. package/dist/src/context/config/configLoader.test.js +8 -12
  42. package/dist/src/context/config/configLoader.test.js.map +1 -1
  43. package/dist/src/context/config/profiles.d.ts +7 -1
  44. package/dist/src/context/config/profiles.js +46 -5
  45. package/dist/src/context/config/profiles.js.map +1 -1
  46. package/dist/src/context/contextManager.js +5 -3
  47. package/dist/src/context/contextManager.js.map +1 -1
  48. package/dist/src/context/eventBus.d.ts +7 -0
  49. package/dist/src/context/eventBus.js +6 -0
  50. package/dist/src/context/eventBus.js.map +1 -1
  51. package/dist/src/context/graph/builtinBehaviors.js +3 -3
  52. package/dist/src/context/graph/builtinBehaviors.js.map +1 -1
  53. package/dist/src/context/graph/mapper.d.ts +4 -2
  54. package/dist/src/context/graph/mapper.js +15 -3
  55. package/dist/src/context/graph/mapper.js.map +1 -1
  56. package/dist/src/context/graph/toGraph.d.ts +13 -2
  57. package/dist/src/context/graph/toGraph.js +88 -32
  58. package/dist/src/context/graph/toGraph.js.map +1 -1
  59. package/dist/src/context/historyObserver.d.ts +1 -0
  60. package/dist/src/context/historyObserver.js +25 -26
  61. package/dist/src/context/historyObserver.js.map +1 -1
  62. package/dist/src/context/initializer.d.ts +9 -0
  63. package/dist/src/context/initializer.js +75 -0
  64. package/dist/src/context/initializer.js.map +1 -0
  65. package/dist/src/context/pipeline/contextWorkingBuffer.js +12 -6
  66. package/dist/src/context/pipeline/contextWorkingBuffer.js.map +1 -1
  67. package/dist/src/context/pipeline/contextWorkingBuffer.test.js +1 -1
  68. package/dist/src/context/pipeline/environmentImpl.d.ts +3 -2
  69. package/dist/src/context/pipeline/environmentImpl.js +6 -3
  70. package/dist/src/context/pipeline/environmentImpl.js.map +1 -1
  71. package/dist/src/context/pipeline/environmentImpl.test.js +1 -1
  72. package/dist/src/context/pipeline/environmentImpl.test.js.map +1 -1
  73. package/dist/src/context/pipeline/orchestrator.js +5 -0
  74. package/dist/src/context/pipeline/orchestrator.js.map +1 -1
  75. package/dist/src/context/processors/toolMaskingProcessor.js +21 -5
  76. package/dist/src/context/processors/toolMaskingProcessor.js.map +1 -1
  77. package/dist/src/context/processors/toolMaskingProcessor.test.js +22 -0
  78. package/dist/src/context/processors/toolMaskingProcessor.test.js.map +1 -1
  79. package/dist/src/context/system-tests/lifecycle.golden.test.js +5 -0
  80. package/dist/src/context/system-tests/lifecycle.golden.test.js.map +1 -1
  81. package/dist/src/context/system-tests/simulationHarness.js +1 -1
  82. package/dist/src/context/system-tests/simulationHarness.js.map +1 -1
  83. package/dist/src/context/testing/contextTestUtils.js +7 -3
  84. package/dist/src/context/testing/contextTestUtils.js.map +1 -1
  85. package/dist/src/context/tracer.js +3 -1
  86. package/dist/src/context/tracer.js.map +1 -1
  87. package/dist/src/context/tracer.test.js +4 -2
  88. package/dist/src/context/tracer.test.js.map +1 -1
  89. package/dist/src/context/utils/contextTokenCalculator.d.ts +2 -1
  90. package/dist/src/context/utils/contextTokenCalculator.js +13 -11
  91. package/dist/src/context/utils/contextTokenCalculator.js.map +1 -1
  92. package/dist/src/core/client.d.ts +1 -0
  93. package/dist/src/core/client.js +9 -8
  94. package/dist/src/core/client.js.map +1 -1
  95. package/dist/src/core/client.test.js +0 -3
  96. package/dist/src/core/client.test.js.map +1 -1
  97. package/dist/src/core/geminiChat.d.ts +2 -1
  98. package/dist/src/core/geminiChat.js +72 -20
  99. package/dist/src/core/geminiChat.js.map +1 -1
  100. package/dist/src/core/geminiChat.test.js +1 -0
  101. package/dist/src/core/geminiChat.test.js.map +1 -1
  102. package/dist/src/core/geminiChat_network_retry.test.js +1 -0
  103. package/dist/src/core/geminiChat_network_retry.test.js.map +1 -1
  104. package/dist/src/core/tokenLimits.d.ts +1 -0
  105. package/dist/src/core/tokenLimits.js +5 -1
  106. package/dist/src/core/tokenLimits.js.map +1 -1
  107. package/dist/src/generated/git-commit.d.ts +2 -2
  108. package/dist/src/generated/git-commit.js +2 -2
  109. package/dist/src/index.d.ts +9 -1
  110. package/dist/src/index.js +10 -1
  111. package/dist/src/index.js.map +1 -1
  112. package/dist/src/policy/policy-engine.js +12 -7
  113. package/dist/src/policy/policy-engine.js.map +1 -1
  114. package/dist/src/policy/policy-engine.test.js +69 -1
  115. package/dist/src/policy/policy-engine.test.js.map +1 -1
  116. package/dist/src/prompts/snippets.js +2 -1
  117. package/dist/src/prompts/snippets.js.map +1 -1
  118. package/dist/src/prompts/snippets.legacy.js +2 -1
  119. package/dist/src/prompts/snippets.legacy.js.map +1 -1
  120. package/dist/src/services/chatRecordingService.d.ts +1 -0
  121. package/dist/src/services/chatRecordingService.js +23 -0
  122. package/dist/src/services/chatRecordingService.js.map +1 -1
  123. package/dist/src/services/chatRecordingTypes.d.ts +13 -0
  124. package/dist/src/services/memoryService.d.ts +5 -0
  125. package/dist/src/services/memoryService.js +76 -53
  126. package/dist/src/services/memoryService.js.map +1 -1
  127. package/dist/src/services/memoryService.test.js +256 -12
  128. package/dist/src/services/memoryService.test.js.map +1 -1
  129. package/dist/src/services/sessionScratchpadUtils.d.ts +7 -0
  130. package/dist/src/services/sessionScratchpadUtils.js +121 -0
  131. package/dist/src/services/sessionScratchpadUtils.js.map +1 -0
  132. package/dist/src/services/sessionScratchpadUtils.test.d.ts +6 -0
  133. package/dist/src/services/sessionScratchpadUtils.test.js +27 -0
  134. package/dist/src/services/sessionScratchpadUtils.test.js.map +1 -0
  135. package/dist/src/services/sessionSummaryUtils.d.ts +3 -3
  136. package/dist/src/services/sessionSummaryUtils.js +232 -27
  137. package/dist/src/services/sessionSummaryUtils.js.map +1 -1
  138. package/dist/src/services/sessionSummaryUtils.test.js +449 -10
  139. package/dist/src/services/sessionSummaryUtils.test.js.map +1 -1
  140. package/dist/src/services/test-data/resolved-aliases-retry.golden.json +283 -259
  141. package/dist/src/services/test-data/resolved-aliases.golden.json +283 -259
  142. package/dist/src/tools/trackerTools.test.js +7 -2
  143. package/dist/src/tools/trackerTools.test.js.map +1 -1
  144. package/dist/src/utils/binaryCheck.d.ts +9 -0
  145. package/dist/src/utils/binaryCheck.js +13 -0
  146. package/dist/src/utils/binaryCheck.js.map +1 -0
  147. package/dist/src/utils/fsErrorMessages.js +4 -0
  148. package/dist/src/utils/fsErrorMessages.js.map +1 -1
  149. package/dist/src/utils/fsErrorMessages.test.js +21 -0
  150. package/dist/src/utils/fsErrorMessages.test.js.map +1 -1
  151. package/dist/src/utils/tokenCalculation.d.ts +2 -2
  152. package/dist/src/utils/tokenCalculation.js +15 -14
  153. package/dist/src/utils/tokenCalculation.js.map +1 -1
  154. package/dist/src/voice/audioRecorder.d.ts +27 -0
  155. package/dist/src/voice/audioRecorder.js +95 -0
  156. package/dist/src/voice/audioRecorder.js.map +1 -0
  157. package/dist/src/voice/geminiLiveTranscriptionProvider.d.ts +20 -0
  158. package/dist/src/voice/geminiLiveTranscriptionProvider.js +140 -0
  159. package/dist/src/voice/geminiLiveTranscriptionProvider.js.map +1 -0
  160. package/dist/src/voice/transcriptionFactory.d.ts +12 -0
  161. package/dist/src/voice/transcriptionFactory.js +32 -0
  162. package/dist/src/voice/transcriptionFactory.js.map +1 -0
  163. package/dist/src/voice/transcriptionProvider.d.ts +29 -0
  164. package/dist/src/voice/transcriptionProvider.js +7 -0
  165. package/dist/src/voice/transcriptionProvider.js.map +1 -0
  166. package/dist/src/voice/whisperModelManager.d.ts +26 -0
  167. package/dist/src/voice/whisperModelManager.js +79 -0
  168. package/dist/src/voice/whisperModelManager.js.map +1 -0
  169. package/dist/src/voice/whisperTranscriptionProvider.d.ts +34 -0
  170. package/dist/src/voice/whisperTranscriptionProvider.js +151 -0
  171. package/dist/src/voice/whisperTranscriptionProvider.js.map +1 -0
  172. package/dist/src/voice/whisperTranscriptionProvider.test.d.ts +6 -0
  173. package/dist/src/voice/whisperTranscriptionProvider.test.js +24 -0
  174. package/dist/src/voice/whisperTranscriptionProvider.test.js.map +1 -0
  175. package/dist/tsconfig.tsbuildinfo +1 -1
  176. package/package.json +2 -1
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import * as path from 'node:path';
7
+ import * as fs from 'node:fs';
8
+ import { EventEmitter } from 'node:events';
9
+ import { homedir, CELL_DIR } from '../utils/paths.js';
10
+ import { debugLogger } from '../utils/debugLogger.js';
11
+ const ALLOWED_MODELS = [
12
+ 'ggml-tiny.en.bin',
13
+ 'ggml-base.en.bin',
14
+ 'ggml-large-v3-turbo-q5_0.bin',
15
+ 'ggml-large-v3-turbo-q8_0.bin',
16
+ ];
17
+ /**
18
+ * Manages Whisper models (checking existence, downloading).
19
+ */
20
+ export class WhisperModelManager extends EventEmitter {
21
+ modelsDir;
22
+ constructor() {
23
+ super();
24
+ this.modelsDir = path.join(homedir(), CELL_DIR, 'whisper_models');
25
+ }
26
+ isModelInstalled(modelName) {
27
+ this.validateModelName(modelName);
28
+ return fs.existsSync(path.join(this.modelsDir, modelName));
29
+ }
30
+ getModelPath(modelName) {
31
+ this.validateModelName(modelName);
32
+ return path.join(this.modelsDir, modelName);
33
+ }
34
+ async downloadModel(modelName) {
35
+ this.validateModelName(modelName);
36
+ if (!fs.existsSync(this.modelsDir)) {
37
+ fs.mkdirSync(this.modelsDir, { recursive: true });
38
+ }
39
+ const destination = path.join(this.modelsDir, modelName);
40
+ const url = `https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${modelName}`;
41
+ debugLogger.debug(`[WhisperModelManager] Downloading ${modelName} from ${url}`);
42
+ const response = await fetch(url);
43
+ if (!response.ok) {
44
+ throw new Error(`Failed to download model: ${response.statusText}`);
45
+ }
46
+ const total = parseInt(response.headers.get('content-length') || '0', 10);
47
+ let transferred = 0;
48
+ const reader = response.body?.getReader();
49
+ if (!reader) {
50
+ throw new Error('Response body is not readable');
51
+ }
52
+ const writer = fs.createWriteStream(destination);
53
+ try {
54
+ while (true) {
55
+ const { done, value } = await reader.read();
56
+ if (done)
57
+ break;
58
+ transferred += value.length;
59
+ writer.write(value);
60
+ const percentage = total > 0 ? transferred / total : 0;
61
+ this.emit('progress', {
62
+ modelName,
63
+ transferred,
64
+ total,
65
+ percentage,
66
+ });
67
+ }
68
+ }
69
+ finally {
70
+ writer.end();
71
+ }
72
+ }
73
+ validateModelName(modelName) {
74
+ if (!ALLOWED_MODELS.includes(modelName)) {
75
+ throw new Error(`Unauthorized model name: ${modelName}`);
76
+ }
77
+ }
78
+ }
79
+ //# sourceMappingURL=whisperModelManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whisperModelManager.js","sourceRoot":"","sources":["../../../src/voice/whisperModelManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { EventEmitter } from 'node:events';
7
+ import type { TranscriptionProvider, TranscriptionEvents } from './transcriptionProvider.js';
8
+ export interface WhisperProviderOptions {
9
+ modelPath: string;
10
+ threads?: number;
11
+ step?: number;
12
+ length?: number;
13
+ }
14
+ /**
15
+ * Local transcription provider using `whisper-stream` from whisper.cpp.
16
+ *
17
+ * Uses the Sliding Window Mode with VAD (--step 0) for stable,
18
+ * non-overlapping transcription blocks that can be appended directly.
19
+ */
20
+ export declare class WhisperTranscriptionProvider extends EventEmitter<TranscriptionEvents> implements TranscriptionProvider {
21
+ private readonly options;
22
+ private process;
23
+ private currentTranscription;
24
+ constructor(options: WhisperProviderOptions);
25
+ /**
26
+ * Checks if `whisper-stream` is available on the system.
27
+ */
28
+ static isAvailable(): Promise<boolean>;
29
+ connect(): Promise<void>;
30
+ private parseOutput;
31
+ sendAudioChunk(_chunk: Buffer): void;
32
+ getTranscription(): string;
33
+ disconnect(): void;
34
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { spawn } from 'node:child_process';
7
+ import { EventEmitter } from 'node:events';
8
+ import commandExists from 'command-exists';
9
+ import { debugLogger } from '../utils/debugLogger.js';
10
+ /**
11
+ * Local transcription provider using `whisper-stream` from whisper.cpp.
12
+ *
13
+ * Uses the Sliding Window Mode with VAD (--step 0) for stable,
14
+ * non-overlapping transcription blocks that can be appended directly.
15
+ */
16
+ export class WhisperTranscriptionProvider extends EventEmitter {
17
+ options;
18
+ process = null;
19
+ currentTranscription = '';
20
+ constructor(options) {
21
+ super();
22
+ this.options = options;
23
+ }
24
+ /**
25
+ * Checks if `whisper-stream` is available on the system.
26
+ */
27
+ static async isAvailable() {
28
+ try {
29
+ await commandExists('whisper-stream');
30
+ return true;
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ async connect() {
37
+ const { modelPath, threads = 4, step = 0, length = 5000 } = this.options;
38
+ this.currentTranscription = '';
39
+ const available = await WhisperTranscriptionProvider.isAvailable();
40
+ if (!available) {
41
+ return Promise.reject(new Error('The `whisper-stream` command is required for local voice mode. Please install it (e.g., `brew install whisper-cpp` on macOS).'));
42
+ }
43
+ debugLogger.debug(`[WhisperTranscription] Starting whisper-stream with model: ${modelPath} (VAD mode: step=${step}, length=${length})`);
44
+ return new Promise((resolve, reject) => {
45
+ let isResolved = false;
46
+ try {
47
+ // whisper-stream -m <model_path> -t <threads> --step 0 --length <length> -vth 0.6
48
+ // Setting step == 0 enables sliding window mode with VAD, which outputs
49
+ // non-overlapping transcription blocks suitable for appending.
50
+ this.process = spawn('whisper-stream', [
51
+ '-m',
52
+ modelPath,
53
+ '-t',
54
+ threads.toString(),
55
+ '--step',
56
+ step.toString(),
57
+ '--length',
58
+ length.toString(),
59
+ '-vth',
60
+ '0.6',
61
+ ]);
62
+ this.process.stdout.on('data', (data) => {
63
+ const output = data.toString();
64
+ this.parseOutput(output);
65
+ });
66
+ this.process.stderr.on('data', (data) => {
67
+ const msg = data.toString();
68
+ if (msg.includes('error')) {
69
+ debugLogger.error(`[WhisperTranscription] stderr: ${msg}`);
70
+ if (!isResolved) {
71
+ isResolved = true;
72
+ reject(new Error(msg));
73
+ }
74
+ }
75
+ // whisper-stream prints "whisper_init_from_file_with_params_no_state: loading model from..."
76
+ // and finally "main: processing, press Ctrl+C to stop" when ready.
77
+ if (!isResolved && msg.includes('main: processing')) {
78
+ debugLogger.debug('[WhisperTranscription] whisper-stream is ready');
79
+ isResolved = true;
80
+ resolve();
81
+ }
82
+ });
83
+ this.process.on('error', (err) => {
84
+ debugLogger.error('[WhisperTranscription] Process error:', err);
85
+ this.emit('error', err);
86
+ if (!isResolved) {
87
+ isResolved = true;
88
+ reject(err);
89
+ }
90
+ });
91
+ this.process.on('close', (code) => {
92
+ debugLogger.debug(`[WhisperTranscription] Process closed with code ${code}`);
93
+ this.emit('close');
94
+ this.process = null;
95
+ });
96
+ // Fallback timeout in case "main: processing" is never seen
97
+ setTimeout(() => {
98
+ if (!isResolved) {
99
+ debugLogger.warn('[WhisperTranscription] Connection timeout (fallback resolve)');
100
+ isResolved = true;
101
+ resolve();
102
+ }
103
+ }, 10000);
104
+ }
105
+ catch (err) {
106
+ debugLogger.error('[WhisperTranscription] Failed to spawn process:', err);
107
+ if (!isResolved) {
108
+ isResolved = true;
109
+ reject(err);
110
+ }
111
+ }
112
+ });
113
+ }
114
+ parseOutput(output) {
115
+ // whisper-stream output format: "[00:00:00.000 --> 00:00:02.000] Hello world."
116
+ const lines = output.split('\n');
117
+ for (const line of lines) {
118
+ const match = line.match(/\[.* --> .*\]\s+(.*)/);
119
+ if (match && match[1]) {
120
+ let text = match[1].trim();
121
+ // Filter out [Silence], [music], (laughter), etc.
122
+ text = text
123
+ .replace(/\[[^\]]*\]/g, '')
124
+ .replace(/\([^)]*\)/g, '')
125
+ .trim();
126
+ if (text) {
127
+ // In VAD mode (step=0), each line is a completed speech block.
128
+ // Append it to the buffer to ensure it doesn't disappear.
129
+ this.currentTranscription = this.currentTranscription
130
+ ? `${this.currentTranscription} ${text}`
131
+ : text;
132
+ debugLogger.debug(`[WhisperTranscription] Transcription updated (Local-VAD): "${this.currentTranscription}"`);
133
+ this.emit('transcription', this.currentTranscription);
134
+ }
135
+ }
136
+ }
137
+ }
138
+ sendAudioChunk(_chunk) {
139
+ // whisper-stream handles its own audio capture.
140
+ }
141
+ getTranscription() {
142
+ return this.currentTranscription;
143
+ }
144
+ disconnect() {
145
+ if (this.process) {
146
+ this.process.kill('SIGTERM');
147
+ this.process = null;
148
+ }
149
+ }
150
+ }
151
+ //# sourceMappingURL=whisperTranscriptionProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whisperTranscriptionProvider.js","sourceRoot":"","sources":["../../../src/voice/whisperTranscriptionProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
7
+ import { WhisperTranscriptionProvider } from './whisperTranscriptionProvider.js';
8
+ import commandExists from 'command-exists';
9
+ vi.mock('command-exists', () => ({
10
+ default: vi.fn(),
11
+ }));
12
+ describe('WhisperTranscriptionProvider', () => {
13
+ beforeEach(() => {
14
+ vi.clearAllMocks();
15
+ });
16
+ it('should throw a friendly error if whisper-stream is not available', async () => {
17
+ vi.mocked(commandExists).mockRejectedValue(new Error('not found'));
18
+ const provider = new WhisperTranscriptionProvider({
19
+ modelPath: 'test-model.bin',
20
+ });
21
+ await expect(provider.connect()).rejects.toThrow('The `whisper-stream` command is required for local voice mode. Please install it (e.g., `brew install whisper-cpp` on macOS).');
22
+ });
23
+ });
24
+ //# sourceMappingURL=whisperTranscriptionProvider.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whisperTranscriptionProvider.test.js","sourceRoot":"","sources":["../../../src/voice/whisperTranscriptionProvider.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAE3C,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/B,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;CACjB,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;QAEnE,MAAM,QAAQ,GAAG,IAAI,4BAA4B,CAAC;YAChD,SAAS,EAAE,gBAAgB;SAC5B,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAC9C,+HAA+H,CAChI,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}