claudia-orchestrator 0.1.0
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/LICENSE +201 -0
- package/README.md +109 -0
- package/dist/cli-parser.d.ts +11 -0
- package/dist/cli-parser.d.ts.map +1 -0
- package/dist/cli-parser.js +57 -0
- package/dist/cli-parser.js.map +1 -0
- package/dist/cui-server.d.ts +69 -0
- package/dist/cui-server.d.ts.map +1 -0
- package/dist/cui-server.js +705 -0
- package/dist/cui-server.js.map +1 -0
- package/dist/mcp-server/claudia-tools.d.ts +15 -0
- package/dist/mcp-server/claudia-tools.d.ts.map +1 -0
- package/dist/mcp-server/claudia-tools.js +366 -0
- package/dist/mcp-server/claudia-tools.js.map +1 -0
- package/dist/mcp-server/index.d.ts +3 -0
- package/dist/mcp-server/index.d.ts.map +1 -0
- package/dist/mcp-server/index.js +176 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +18 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +136 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/cors-setup.d.ts +7 -0
- package/dist/middleware/cors-setup.d.ts.map +1 -0
- package/dist/middleware/cors-setup.js +8 -0
- package/dist/middleware/cors-setup.js.map +1 -0
- package/dist/middleware/error-handler.d.ts +4 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/error-handler.js +27 -0
- package/dist/middleware/error-handler.js.map +1 -0
- package/dist/middleware/query-parser.d.ts +11 -0
- package/dist/middleware/query-parser.d.ts.map +1 -0
- package/dist/middleware/query-parser.js +68 -0
- package/dist/middleware/query-parser.js.map +1 -0
- package/dist/middleware/request-logger.d.ts +4 -0
- package/dist/middleware/request-logger.d.ts.map +1 -0
- package/dist/middleware/request-logger.js +29 -0
- package/dist/middleware/request-logger.js.map +1 -0
- package/dist/process-daemon/index.d.ts +14 -0
- package/dist/process-daemon/index.d.ts.map +1 -0
- package/dist/process-daemon/index.js +51 -0
- package/dist/process-daemon/index.js.map +1 -0
- package/dist/process-daemon/process-daemon.d.ts +78 -0
- package/dist/process-daemon/process-daemon.d.ts.map +1 -0
- package/dist/process-daemon/process-daemon.js +568 -0
- package/dist/process-daemon/process-daemon.js.map +1 -0
- package/dist/process-daemon/process-manager-client.d.ts +108 -0
- package/dist/process-daemon/process-manager-client.d.ts.map +1 -0
- package/dist/process-daemon/process-manager-client.js +314 -0
- package/dist/process-daemon/process-manager-client.js.map +1 -0
- package/dist/process-daemon/process-manager-interface.d.ts +47 -0
- package/dist/process-daemon/process-manager-interface.d.ts.map +1 -0
- package/dist/process-daemon/process-manager-interface.js +8 -0
- package/dist/process-daemon/process-manager-interface.js.map +1 -0
- package/dist/process-daemon/test-daemon.d.ts +12 -0
- package/dist/process-daemon/test-daemon.d.ts.map +1 -0
- package/dist/process-daemon/test-daemon.js +81 -0
- package/dist/process-daemon/test-daemon.js.map +1 -0
- package/dist/process-daemon/types.d.ts +85 -0
- package/dist/process-daemon/types.d.ts.map +1 -0
- package/dist/process-daemon/types.js +8 -0
- package/dist/process-daemon/types.js.map +1 -0
- package/dist/routes/claudia.routes.d.ts +10 -0
- package/dist/routes/claudia.routes.d.ts.map +1 -0
- package/dist/routes/claudia.routes.js +123 -0
- package/dist/routes/claudia.routes.js.map +1 -0
- package/dist/routes/config.routes.d.ts +4 -0
- package/dist/routes/config.routes.d.ts.map +1 -0
- package/dist/routes/config.routes.js +27 -0
- package/dist/routes/config.routes.js.map +1 -0
- package/dist/routes/conversation.routes.d.ts +8 -0
- package/dist/routes/conversation.routes.d.ts.map +1 -0
- package/dist/routes/conversation.routes.js +870 -0
- package/dist/routes/conversation.routes.js.map +1 -0
- package/dist/routes/filesystem.routes.d.ts +4 -0
- package/dist/routes/filesystem.routes.d.ts.map +1 -0
- package/dist/routes/filesystem.routes.js +86 -0
- package/dist/routes/filesystem.routes.js.map +1 -0
- package/dist/routes/gemini.routes.d.ts +4 -0
- package/dist/routes/gemini.routes.d.ts.map +1 -0
- package/dist/routes/gemini.routes.js +93 -0
- package/dist/routes/gemini.routes.js.map +1 -0
- package/dist/routes/insights.routes.d.ts +17 -0
- package/dist/routes/insights.routes.d.ts.map +1 -0
- package/dist/routes/insights.routes.js +417 -0
- package/dist/routes/insights.routes.js.map +1 -0
- package/dist/routes/license.routes.d.ts +3 -0
- package/dist/routes/license.routes.d.ts.map +1 -0
- package/dist/routes/license.routes.js +111 -0
- package/dist/routes/license.routes.js.map +1 -0
- package/dist/routes/log.routes.d.ts +3 -0
- package/dist/routes/log.routes.d.ts.map +1 -0
- package/dist/routes/log.routes.js +65 -0
- package/dist/routes/log.routes.js.map +1 -0
- package/dist/routes/notifications.routes.d.ts +4 -0
- package/dist/routes/notifications.routes.d.ts.map +1 -0
- package/dist/routes/notifications.routes.js +71 -0
- package/dist/routes/notifications.routes.js.map +1 -0
- package/dist/routes/permission.routes.d.ts +4 -0
- package/dist/routes/permission.routes.d.ts.map +1 -0
- package/dist/routes/permission.routes.js +116 -0
- package/dist/routes/permission.routes.js.map +1 -0
- package/dist/routes/question.routes.d.ts +8 -0
- package/dist/routes/question.routes.d.ts.map +1 -0
- package/dist/routes/question.routes.js +82 -0
- package/dist/routes/question.routes.js.map +1 -0
- package/dist/routes/streaming.routes.d.ts +4 -0
- package/dist/routes/streaming.routes.d.ts.map +1 -0
- package/dist/routes/streaming.routes.js +28 -0
- package/dist/routes/streaming.routes.js.map +1 -0
- package/dist/routes/system.routes.d.ts +5 -0
- package/dist/routes/system.routes.d.ts.map +1 -0
- package/dist/routes/system.routes.js +103 -0
- package/dist/routes/system.routes.js.map +1 -0
- package/dist/routes/working-directories.routes.d.ts +4 -0
- package/dist/routes/working-directories.routes.d.ts.map +1 -0
- package/dist/routes/working-directories.routes.js +25 -0
- package/dist/routes/working-directories.routes.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +34 -0
- package/dist/server.js.map +1 -0
- package/dist/services/ToolMetricsService.d.ts +53 -0
- package/dist/services/ToolMetricsService.d.ts.map +1 -0
- package/dist/services/ToolMetricsService.js +230 -0
- package/dist/services/ToolMetricsService.js.map +1 -0
- package/dist/services/anthropic-service.d.ts +186 -0
- package/dist/services/anthropic-service.d.ts.map +1 -0
- package/dist/services/anthropic-service.js +1132 -0
- package/dist/services/anthropic-service.js.map +1 -0
- package/dist/services/claude-history-reader.d.ts +126 -0
- package/dist/services/claude-history-reader.d.ts.map +1 -0
- package/dist/services/claude-history-reader.js +717 -0
- package/dist/services/claude-history-reader.js.map +1 -0
- package/dist/services/claude-process-manager.d.ts +108 -0
- package/dist/services/claude-process-manager.d.ts.map +1 -0
- package/dist/services/claude-process-manager.js +909 -0
- package/dist/services/claude-process-manager.js.map +1 -0
- package/dist/services/claude-router-service.d.ts +19 -0
- package/dist/services/claude-router-service.d.ts.map +1 -0
- package/dist/services/claude-router-service.js +160 -0
- package/dist/services/claude-router-service.js.map +1 -0
- package/dist/services/claudia-service.d.ts +77 -0
- package/dist/services/claudia-service.d.ts.map +1 -0
- package/dist/services/claudia-service.js +194 -0
- package/dist/services/claudia-service.js.map +1 -0
- package/dist/services/commands-service.d.ts +18 -0
- package/dist/services/commands-service.d.ts.map +1 -0
- package/dist/services/commands-service.js +76 -0
- package/dist/services/commands-service.js.map +1 -0
- package/dist/services/config-service.d.ts +68 -0
- package/dist/services/config-service.d.ts.map +1 -0
- package/dist/services/config-service.js +429 -0
- package/dist/services/config-service.js.map +1 -0
- package/dist/services/conversation-cache.d.ts +86 -0
- package/dist/services/conversation-cache.d.ts.map +1 -0
- package/dist/services/conversation-cache.js +235 -0
- package/dist/services/conversation-cache.js.map +1 -0
- package/dist/services/conversation-status-manager.d.ts +98 -0
- package/dist/services/conversation-status-manager.d.ts.map +1 -0
- package/dist/services/conversation-status-manager.js +295 -0
- package/dist/services/conversation-status-manager.js.map +1 -0
- package/dist/services/cost-tracker.d.ts +87 -0
- package/dist/services/cost-tracker.d.ts.map +1 -0
- package/dist/services/cost-tracker.js +335 -0
- package/dist/services/cost-tracker.js.map +1 -0
- package/dist/services/file-system-service.d.ts +61 -0
- package/dist/services/file-system-service.d.ts.map +1 -0
- package/dist/services/file-system-service.js +348 -0
- package/dist/services/file-system-service.js.map +1 -0
- package/dist/services/gemini-service.d.ts +72 -0
- package/dist/services/gemini-service.d.ts.map +1 -0
- package/dist/services/gemini-service.js +431 -0
- package/dist/services/gemini-service.js.map +1 -0
- package/dist/services/insight-queue.d.ts +99 -0
- package/dist/services/insight-queue.d.ts.map +1 -0
- package/dist/services/insight-queue.js +277 -0
- package/dist/services/insight-queue.js.map +1 -0
- package/dist/services/insights-service.d.ts +102 -0
- package/dist/services/insights-service.d.ts.map +1 -0
- package/dist/services/insights-service.js +1152 -0
- package/dist/services/insights-service.js.map +1 -0
- package/dist/services/json-lines-parser.d.ts +19 -0
- package/dist/services/json-lines-parser.d.ts.map +1 -0
- package/dist/services/json-lines-parser.js +56 -0
- package/dist/services/json-lines-parser.js.map +1 -0
- package/dist/services/license-service.d.ts +69 -0
- package/dist/services/license-service.d.ts.map +1 -0
- package/dist/services/license-service.js +330 -0
- package/dist/services/license-service.js.map +1 -0
- package/dist/services/log-formatter.d.ts +5 -0
- package/dist/services/log-formatter.d.ts.map +1 -0
- package/dist/services/log-formatter.js +77 -0
- package/dist/services/log-formatter.js.map +1 -0
- package/dist/services/log-stream-buffer.d.ts +11 -0
- package/dist/services/log-stream-buffer.d.ts.map +1 -0
- package/dist/services/log-stream-buffer.js +36 -0
- package/dist/services/log-stream-buffer.js.map +1 -0
- package/dist/services/logger.d.ts +71 -0
- package/dist/services/logger.d.ts.map +1 -0
- package/dist/services/logger.js +215 -0
- package/dist/services/logger.js.map +1 -0
- package/dist/services/mcp-config-generator.d.ts +32 -0
- package/dist/services/mcp-config-generator.d.ts.map +1 -0
- package/dist/services/mcp-config-generator.js +126 -0
- package/dist/services/mcp-config-generator.js.map +1 -0
- package/dist/services/message-filter.d.ts +22 -0
- package/dist/services/message-filter.d.ts.map +1 -0
- package/dist/services/message-filter.js +57 -0
- package/dist/services/message-filter.js.map +1 -0
- package/dist/services/notification-service.d.ts +45 -0
- package/dist/services/notification-service.d.ts.map +1 -0
- package/dist/services/notification-service.js +184 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/services/permission-tracker.d.ts +67 -0
- package/dist/services/permission-tracker.d.ts.map +1 -0
- package/dist/services/permission-tracker.js +161 -0
- package/dist/services/permission-tracker.js.map +1 -0
- package/dist/services/process-manager-factory.d.ts +81 -0
- package/dist/services/process-manager-factory.d.ts.map +1 -0
- package/dist/services/process-manager-factory.js +211 -0
- package/dist/services/process-manager-factory.js.map +1 -0
- package/dist/services/question-tracker.d.ts +47 -0
- package/dist/services/question-tracker.d.ts.map +1 -0
- package/dist/services/question-tracker.js +105 -0
- package/dist/services/question-tracker.js.map +1 -0
- package/dist/services/session-activity-watcher.d.ts +33 -0
- package/dist/services/session-activity-watcher.d.ts.map +1 -0
- package/dist/services/session-activity-watcher.js +194 -0
- package/dist/services/session-activity-watcher.js.map +1 -0
- package/dist/services/session-info-service.d.ts +228 -0
- package/dist/services/session-info-service.d.ts.map +1 -0
- package/dist/services/session-info-service.js +920 -0
- package/dist/services/session-info-service.js.map +1 -0
- package/dist/services/session-insights-service.d.ts +119 -0
- package/dist/services/session-insights-service.d.ts.map +1 -0
- package/dist/services/session-insights-service.js +889 -0
- package/dist/services/session-insights-service.js.map +1 -0
- package/dist/services/stream-manager.d.ts +62 -0
- package/dist/services/stream-manager.d.ts.map +1 -0
- package/dist/services/stream-manager.js +239 -0
- package/dist/services/stream-manager.js.map +1 -0
- package/dist/services/web-push-service.d.ts +48 -0
- package/dist/services/web-push-service.d.ts.map +1 -0
- package/dist/services/web-push-service.js +186 -0
- package/dist/services/web-push-service.js.map +1 -0
- package/dist/services/working-directories-service.d.ts +19 -0
- package/dist/services/working-directories-service.d.ts.map +1 -0
- package/dist/services/working-directories-service.js +103 -0
- package/dist/services/working-directories-service.js.map +1 -0
- package/dist/types/config.d.ts +111 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +14 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/express.d.ts +5 -0
- package/dist/types/express.d.ts.map +1 -0
- package/dist/types/express.js +2 -0
- package/dist/types/express.js.map +1 -0
- package/dist/types/index.d.ts +325 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +18 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/insights.d.ts +99 -0
- package/dist/types/insights.d.ts.map +1 -0
- package/dist/types/insights.js +7 -0
- package/dist/types/insights.js.map +1 -0
- package/dist/types/license.d.ts +70 -0
- package/dist/types/license.d.ts.map +1 -0
- package/dist/types/license.js +5 -0
- package/dist/types/license.js.map +1 -0
- package/dist/types/router-config.d.ts +13 -0
- package/dist/types/router-config.d.ts.map +1 -0
- package/dist/types/router-config.js +2 -0
- package/dist/types/router-config.js.map +1 -0
- package/dist/utils/constants.d.ts +26 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +28 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/machine-id.d.ts +7 -0
- package/dist/utils/machine-id.d.ts.map +1 -0
- package/dist/utils/machine-id.js +76 -0
- package/dist/utils/machine-id.js.map +1 -0
- package/dist/utils/server-startup.d.ts +13 -0
- package/dist/utils/server-startup.d.ts.map +1 -0
- package/dist/utils/server-startup.js +20 -0
- package/dist/utils/server-startup.js.map +1 -0
- package/dist/web/assets/main-DAc2rjJ2.css +1 -0
- package/dist/web/assets/main-DvlZ02mT.js +137 -0
- package/dist/web/favicon.png +0 -0
- package/dist/web/favicon.svg +22 -0
- package/dist/web/icon-192x192.png +0 -0
- package/dist/web/icon-512x512.png +0 -0
- package/dist/web/index.html +36 -0
- package/dist/web/manifest.json +61 -0
- package/package.json +174 -0
- package/scripts/postinstall.js +30 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
import { GoogleGenAI, Type } from '@google/genai';
|
|
2
|
+
import { setGlobalDispatcher, ProxyAgent } from 'undici';
|
|
3
|
+
import sharp from 'sharp';
|
|
4
|
+
import { CUIError } from '../types/index.js';
|
|
5
|
+
import { createLogger } from '../services/logger.js';
|
|
6
|
+
import { ConfigService } from './config-service.js';
|
|
7
|
+
// Set up proxy support using environment variables (production only)
|
|
8
|
+
const proxyUrl = process.env.HTTPS_PROXY || process.env.https_proxy;
|
|
9
|
+
if (proxyUrl && process.env.NODE_ENV !== 'test') {
|
|
10
|
+
const dispatcher = new ProxyAgent({ uri: new URL(proxyUrl).toString() });
|
|
11
|
+
setGlobalDispatcher(dispatcher);
|
|
12
|
+
}
|
|
13
|
+
export class GeminiService {
|
|
14
|
+
logger;
|
|
15
|
+
genAI = null;
|
|
16
|
+
model;
|
|
17
|
+
constructor() {
|
|
18
|
+
this.logger = createLogger('GeminiService');
|
|
19
|
+
this.model = 'gemini-2.5-flash';
|
|
20
|
+
}
|
|
21
|
+
async initialize() {
|
|
22
|
+
const config = ConfigService.getInstance().getConfig();
|
|
23
|
+
const apiKey = config.gemini?.apiKey || process.env.GOOGLE_API_KEY;
|
|
24
|
+
if (!apiKey) {
|
|
25
|
+
this.logger.warn('Gemini API key not configured');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
this.genAI = new GoogleGenAI({
|
|
30
|
+
apiKey: apiKey
|
|
31
|
+
});
|
|
32
|
+
if (config.gemini?.model) {
|
|
33
|
+
this.model = config.gemini.model;
|
|
34
|
+
}
|
|
35
|
+
this.logger.info('Gemini service initialized', { model: this.model });
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
this.logger.error('Failed to initialize Gemini service', { error });
|
|
39
|
+
throw new CUIError('GEMINI_INIT_ERROR', 'Failed to initialize Gemini service', 500);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async checkHealth() {
|
|
43
|
+
if (!this.genAI) {
|
|
44
|
+
return {
|
|
45
|
+
status: 'unhealthy',
|
|
46
|
+
message: 'Gemini API key not configured',
|
|
47
|
+
apiKeyValid: false
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
// Test the API with a simple request
|
|
52
|
+
const response = await this.genAI.models.generateContent({
|
|
53
|
+
model: this.model,
|
|
54
|
+
contents: [{
|
|
55
|
+
role: 'user',
|
|
56
|
+
parts: [{
|
|
57
|
+
text: 'Say hello and nothing else'
|
|
58
|
+
}]
|
|
59
|
+
}]
|
|
60
|
+
});
|
|
61
|
+
if (response.text) {
|
|
62
|
+
return {
|
|
63
|
+
status: 'healthy',
|
|
64
|
+
message: 'Gemini API is accessible',
|
|
65
|
+
apiKeyValid: true
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
status: 'unhealthy',
|
|
70
|
+
message: 'Unexpected response from Gemini API',
|
|
71
|
+
apiKeyValid: true
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
this.logger.error('Health check failed', { error });
|
|
76
|
+
return {
|
|
77
|
+
status: 'unhealthy',
|
|
78
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
79
|
+
apiKeyValid: false
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async transcribe(audio, mimeType) {
|
|
84
|
+
if (!this.genAI) {
|
|
85
|
+
throw new CUIError('GEMINI_API_KEY_MISSING', 'Gemini API key not configured', 400);
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const response = await this.genAI.models.generateContent({
|
|
89
|
+
model: this.model,
|
|
90
|
+
contents: [{
|
|
91
|
+
role: 'user',
|
|
92
|
+
parts: [
|
|
93
|
+
{
|
|
94
|
+
inlineData: {
|
|
95
|
+
mimeType: mimeType,
|
|
96
|
+
data: audio
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
text: 'Transcribe the above audio instructions, which are likely related to software development and may include a mix of different languages and technical terms (e.g., code references, file paths, API names). Transcribe verbatim with correct punctuation, do not add explanations or non-verbal cues. Return the raw transcribed text only:'
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
}]
|
|
104
|
+
});
|
|
105
|
+
const text = response.text;
|
|
106
|
+
if (!text) {
|
|
107
|
+
throw new CUIError('GEMINI_TRANSCRIBE_ERROR', 'No transcription returned', 500);
|
|
108
|
+
}
|
|
109
|
+
this.logger.debug('Audio transcribed successfully', { textLength: text.length });
|
|
110
|
+
return { text: text.trim() };
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
if (error instanceof CUIError) {
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
this.logger.error('Transcription failed', { error });
|
|
117
|
+
throw new CUIError('GEMINI_TRANSCRIBE_ERROR', 'Failed to transcribe audio', 500);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async summarize(text) {
|
|
121
|
+
if (!this.genAI) {
|
|
122
|
+
throw new CUIError('GEMINI_API_KEY_MISSING', 'Gemini API key not configured', 400);
|
|
123
|
+
}
|
|
124
|
+
const schema = {
|
|
125
|
+
type: Type.OBJECT,
|
|
126
|
+
properties: {
|
|
127
|
+
title: {
|
|
128
|
+
type: Type.STRING,
|
|
129
|
+
description: 'A concise title summarizing the conversation'
|
|
130
|
+
},
|
|
131
|
+
keypoints: {
|
|
132
|
+
type: Type.ARRAY,
|
|
133
|
+
items: {
|
|
134
|
+
type: Type.STRING
|
|
135
|
+
},
|
|
136
|
+
description: 'List of key points from the text'
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
required: ['title', 'keypoints']
|
|
140
|
+
};
|
|
141
|
+
try {
|
|
142
|
+
const response = await this.genAI.models.generateContent({
|
|
143
|
+
model: this.model,
|
|
144
|
+
contents: [{
|
|
145
|
+
role: 'user',
|
|
146
|
+
parts: [{
|
|
147
|
+
text: `Please summarize the following text into a title and key points:\n\n${text}`
|
|
148
|
+
}]
|
|
149
|
+
}],
|
|
150
|
+
config: {
|
|
151
|
+
responseMimeType: 'application/json',
|
|
152
|
+
responseSchema: schema
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
const responseText = response.text;
|
|
156
|
+
if (!responseText) {
|
|
157
|
+
throw new CUIError('GEMINI_SUMMARIZE_ERROR', 'No response text returned', 500);
|
|
158
|
+
}
|
|
159
|
+
const result = JSON.parse(responseText);
|
|
160
|
+
if (!result.title || !Array.isArray(result.keypoints)) {
|
|
161
|
+
throw new CUIError('GEMINI_SUMMARIZE_ERROR', 'Invalid response format', 500);
|
|
162
|
+
}
|
|
163
|
+
this.logger.debug('Text summarized successfully', {
|
|
164
|
+
titleLength: result.title.length,
|
|
165
|
+
keypointCount: result.keypoints.length
|
|
166
|
+
});
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
if (error instanceof CUIError) {
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
this.logger.error('Summarization failed', { error });
|
|
174
|
+
throw new CUIError('GEMINI_SUMMARIZE_ERROR', 'Failed to summarize text', 500);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
async generateSessionName(conversationText) {
|
|
178
|
+
if (!this.genAI) {
|
|
179
|
+
throw new CUIError('GEMINI_API_KEY_MISSING', 'Gemini API key not configured', 400);
|
|
180
|
+
}
|
|
181
|
+
const schema = {
|
|
182
|
+
type: Type.OBJECT,
|
|
183
|
+
properties: {
|
|
184
|
+
name: {
|
|
185
|
+
type: Type.STRING,
|
|
186
|
+
description: 'A brief, descriptive name for this coding session (3-6 words)'
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
required: ['name']
|
|
190
|
+
};
|
|
191
|
+
try {
|
|
192
|
+
const response = await this.genAI.models.generateContent({
|
|
193
|
+
model: this.model,
|
|
194
|
+
contents: [{
|
|
195
|
+
role: 'user',
|
|
196
|
+
parts: [{
|
|
197
|
+
text: `Generate a brief, descriptive name (3-6 words) for this coding session. Focus on the main task or feature being worked on. Do not include generic words like "session", "conversation", or "chat". Examples of good names: "Fix auth redirect bug", "Add dark mode support", "Refactor user service".
|
|
198
|
+
|
|
199
|
+
Conversation:
|
|
200
|
+
${conversationText}`
|
|
201
|
+
}]
|
|
202
|
+
}],
|
|
203
|
+
config: {
|
|
204
|
+
responseMimeType: 'application/json',
|
|
205
|
+
responseSchema: schema
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
const responseText = response.text;
|
|
209
|
+
if (!responseText) {
|
|
210
|
+
throw new CUIError('GEMINI_SESSION_NAME_ERROR', 'No response text returned', 500);
|
|
211
|
+
}
|
|
212
|
+
const result = JSON.parse(responseText);
|
|
213
|
+
if (!result.name) {
|
|
214
|
+
throw new CUIError('GEMINI_SESSION_NAME_ERROR', 'Invalid response format', 500);
|
|
215
|
+
}
|
|
216
|
+
this.logger.debug('Session name generated successfully', {
|
|
217
|
+
nameLength: result.name.length
|
|
218
|
+
});
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
if (error instanceof CUIError) {
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
this.logger.error('Session name generation failed', { error });
|
|
226
|
+
throw new CUIError('GEMINI_SESSION_NAME_ERROR', 'Failed to generate session name', 500);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Generate structured session insights for display
|
|
231
|
+
*/
|
|
232
|
+
async generateSessionInsights(conversationText) {
|
|
233
|
+
if (!this.genAI) {
|
|
234
|
+
throw new CUIError('GEMINI_API_KEY_MISSING', 'Gemini API key not configured', 400);
|
|
235
|
+
}
|
|
236
|
+
const schema = {
|
|
237
|
+
type: Type.OBJECT,
|
|
238
|
+
properties: {
|
|
239
|
+
purposes: {
|
|
240
|
+
type: Type.ARRAY,
|
|
241
|
+
items: { type: Type.STRING },
|
|
242
|
+
description: 'The main goals/purposes of this session (1-3 items). Each should be a concise phrase like "Implement dark mode" or "Debug auth flow"'
|
|
243
|
+
},
|
|
244
|
+
milestones: {
|
|
245
|
+
type: Type.ARRAY,
|
|
246
|
+
items: {
|
|
247
|
+
type: Type.OBJECT,
|
|
248
|
+
properties: {
|
|
249
|
+
label: { type: Type.STRING, description: 'Short milestone description (3-8 words)' },
|
|
250
|
+
status: { type: Type.STRING, description: 'One of: done, current, pending' }
|
|
251
|
+
},
|
|
252
|
+
required: ['label', 'status']
|
|
253
|
+
},
|
|
254
|
+
description: 'Key chunks of work in this session (2-5 items). Mark completed work as "done", active work as "current", planned work as "pending"'
|
|
255
|
+
},
|
|
256
|
+
recentActions: {
|
|
257
|
+
type: Type.ARRAY,
|
|
258
|
+
items: { type: Type.STRING },
|
|
259
|
+
description: 'The 3-4 most recent concrete actions taken, each as a concise phrase (e.g., "Added migration for new columns", "Fixed JSON parsing bug")'
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
required: ['purposes', 'milestones', 'recentActions']
|
|
263
|
+
};
|
|
264
|
+
try {
|
|
265
|
+
const response = await this.genAI.models.generateContent({
|
|
266
|
+
model: this.model,
|
|
267
|
+
contents: [{
|
|
268
|
+
role: 'user',
|
|
269
|
+
parts: [{
|
|
270
|
+
text: `Analyze this coding session and extract structured information.
|
|
271
|
+
|
|
272
|
+
${conversationText}
|
|
273
|
+
|
|
274
|
+
Extract:
|
|
275
|
+
1. purposes: The main goals of this session (1-3 concise phrases)
|
|
276
|
+
2. milestones: Key chunks of work with status (done/current/pending)
|
|
277
|
+
3. recentActions: The 3-4 most recent concrete actions taken`
|
|
278
|
+
}]
|
|
279
|
+
}],
|
|
280
|
+
config: {
|
|
281
|
+
responseMimeType: 'application/json',
|
|
282
|
+
responseSchema: schema
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
const responseText = response.text;
|
|
286
|
+
if (!responseText) {
|
|
287
|
+
throw new CUIError('GEMINI_INSIGHTS_ERROR', 'No response text returned', 500);
|
|
288
|
+
}
|
|
289
|
+
const result = JSON.parse(responseText);
|
|
290
|
+
if (!result.purposes || !result.milestones || !result.recentActions) {
|
|
291
|
+
throw new CUIError('GEMINI_INSIGHTS_ERROR', 'Invalid response format', 500);
|
|
292
|
+
}
|
|
293
|
+
this.logger.debug('Session insights generated successfully');
|
|
294
|
+
return result;
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
if (error instanceof CUIError) {
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
this.logger.error('Session insights generation failed', { error });
|
|
301
|
+
throw new CUIError('GEMINI_INSIGHTS_ERROR', 'Failed to generate session insights', 500);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Map session theme to a neon glow color for visual differentiation.
|
|
306
|
+
* This creates instant visual grouping - all debugging sessions are amber,
|
|
307
|
+
* all implementing sessions are green, etc.
|
|
308
|
+
*/
|
|
309
|
+
getColorForTheme(theme) {
|
|
310
|
+
const themeColorMap = {
|
|
311
|
+
'debugging': 'warm amber/orange',
|
|
312
|
+
'investigating': 'cool cyan/blue',
|
|
313
|
+
'implementing': 'green/emerald',
|
|
314
|
+
'polishing': 'gold/yellow',
|
|
315
|
+
'exploring': 'purple/violet',
|
|
316
|
+
'refactoring': 'gold/yellow',
|
|
317
|
+
'designing': 'purple/violet',
|
|
318
|
+
'experimenting': 'magenta/pink',
|
|
319
|
+
'research': 'purple/violet',
|
|
320
|
+
'implementation': 'green/emerald',
|
|
321
|
+
};
|
|
322
|
+
if (!theme)
|
|
323
|
+
return 'cyan/blue';
|
|
324
|
+
const themeLower = theme.toLowerCase();
|
|
325
|
+
for (const [key, color] of Object.entries(themeColorMap)) {
|
|
326
|
+
if (themeLower.includes(key)) {
|
|
327
|
+
return color;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return 'cyan/blue'; // default
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Create a black canvas PNG to use as base for image editing.
|
|
334
|
+
* Using inpainting on a black canvas ensures consistent black backgrounds.
|
|
335
|
+
*/
|
|
336
|
+
async createBlackCanvas() {
|
|
337
|
+
// Create at higher resolution for quality, will resize after generation
|
|
338
|
+
return sharp({
|
|
339
|
+
create: {
|
|
340
|
+
width: 512,
|
|
341
|
+
height: 960,
|
|
342
|
+
channels: 3,
|
|
343
|
+
background: { r: 0, g: 0, b: 0 }
|
|
344
|
+
}
|
|
345
|
+
}).png().toBuffer();
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Generate an abstract visual identity image for a session.
|
|
349
|
+
* Uses image editing on a black canvas to ensure consistent black backgrounds,
|
|
350
|
+
* with color-mood mapping for instant visual differentiation between session types.
|
|
351
|
+
*/
|
|
352
|
+
async generateSessionImage(sessionContext) {
|
|
353
|
+
if (!this.genAI) {
|
|
354
|
+
throw new CUIError('GEMINI_API_KEY_MISSING', 'Gemini API key not configured', 400);
|
|
355
|
+
}
|
|
356
|
+
// Get color based on session theme for visual grouping
|
|
357
|
+
const glowColor = this.getColorForTheme(sessionContext.theme);
|
|
358
|
+
// Build the prompt - shorter and more focused than before
|
|
359
|
+
const prompt = `Add a glowing neon icon to this black image.
|
|
360
|
+
|
|
361
|
+
TASK: ${sessionContext.mission}
|
|
362
|
+
COLOR: ${glowColor} glow
|
|
363
|
+
|
|
364
|
+
Requirements:
|
|
365
|
+
- Single bold central symbol
|
|
366
|
+
- Neon glow effect
|
|
367
|
+
- Keep the black background intact
|
|
368
|
+
- No text, no faces
|
|
369
|
+
- Tech/circuit aesthetic optional`;
|
|
370
|
+
this.logger.debug('Session image prompt', {
|
|
371
|
+
theme: sessionContext.theme,
|
|
372
|
+
color: glowColor,
|
|
373
|
+
mission: sessionContext.mission
|
|
374
|
+
});
|
|
375
|
+
try {
|
|
376
|
+
// Create black canvas as base image
|
|
377
|
+
const blackCanvas = await this.createBlackCanvas();
|
|
378
|
+
const blackCanvasBase64 = blackCanvas.toString('base64');
|
|
379
|
+
// Use image editing mode - pass black canvas + prompt
|
|
380
|
+
const response = await this.genAI.models.generateContent({
|
|
381
|
+
model: 'gemini-3-pro-image-preview',
|
|
382
|
+
contents: [
|
|
383
|
+
{
|
|
384
|
+
role: 'user',
|
|
385
|
+
parts: [
|
|
386
|
+
{ inlineData: { mimeType: 'image/png', data: blackCanvasBase64 } },
|
|
387
|
+
{ text: prompt }
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
],
|
|
391
|
+
config: {
|
|
392
|
+
responseModalities: ['TEXT', 'IMAGE'],
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
// Extract image from response parts
|
|
396
|
+
if (response.candidates?.[0]?.content?.parts) {
|
|
397
|
+
for (const part of response.candidates[0].content.parts) {
|
|
398
|
+
if (part.inlineData) {
|
|
399
|
+
this.logger.debug('Raw session image generated, resizing to 80x150');
|
|
400
|
+
const rawImageBuffer = Buffer.from(part.inlineData.data, 'base64');
|
|
401
|
+
// Resize to final dimensions and encode as JPEG
|
|
402
|
+
const resizedBuffer = await sharp(rawImageBuffer)
|
|
403
|
+
.resize(80, 150, { fit: 'cover' })
|
|
404
|
+
.jpeg({ quality: 80 })
|
|
405
|
+
.toBuffer();
|
|
406
|
+
const resizedBase64 = resizedBuffer.toString('base64');
|
|
407
|
+
this.logger.debug('Session image resized successfully', {
|
|
408
|
+
originalSize: rawImageBuffer.length,
|
|
409
|
+
resizedSize: resizedBuffer.length
|
|
410
|
+
});
|
|
411
|
+
return {
|
|
412
|
+
imageData: resizedBase64,
|
|
413
|
+
mimeType: 'image/jpeg'
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
throw new CUIError('GEMINI_IMAGE_ERROR', 'No image was generated in the response', 500);
|
|
419
|
+
}
|
|
420
|
+
catch (error) {
|
|
421
|
+
if (error instanceof CUIError) {
|
|
422
|
+
throw error;
|
|
423
|
+
}
|
|
424
|
+
this.logger.error('Session image generation failed', { error });
|
|
425
|
+
throw new CUIError('GEMINI_IMAGE_ERROR', 'Failed to generate session image', 500);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// Export singleton instance
|
|
430
|
+
export const geminiService = new GeminiService();
|
|
431
|
+
//# sourceMappingURL=gemini-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-service.js","sourceRoot":"","sources":["../../src/services/gemini-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InsightQueue - Serializes insight operations per session to eliminate race conditions.
|
|
3
|
+
*
|
|
4
|
+
* The Problem This Solves:
|
|
5
|
+
* Previously, background regenerations could race with patches:
|
|
6
|
+
* T+0s: Patch starts (Haiku)
|
|
7
|
+
* T+1s: Background regen starts (Opus)
|
|
8
|
+
* T+5s: Patch completes, writes to cache
|
|
9
|
+
* T+8s: Regen completes, merge decision uses stale snapshot, overwrites patch
|
|
10
|
+
*
|
|
11
|
+
* The Solution:
|
|
12
|
+
* All insight operations go through this queue. Operations for the same session
|
|
13
|
+
* are serialized - a REFRESH can't start until the PATCH completes.
|
|
14
|
+
*
|
|
15
|
+
* Key Design Decisions:
|
|
16
|
+
* - One queue per session (different sessions can run in parallel)
|
|
17
|
+
* - Operations coalesce (if PATCH is queued and another PATCH comes in, skip the new one)
|
|
18
|
+
* - Priority ordering: PATCH > GENERATE > REFRESH
|
|
19
|
+
* - In-memory only (operations are idempotent, no need for persistence)
|
|
20
|
+
*/
|
|
21
|
+
import { EventEmitter } from 'events';
|
|
22
|
+
export type InsightOperationType = 'GENERATE' | 'PATCH' | 'REFRESH';
|
|
23
|
+
export type InsightTrigger = 'initial' | 'user_message' | 'completion' | 'tool_use' | 'scheduled' | 'manual' | 'missing_fields';
|
|
24
|
+
export interface InsightOperation {
|
|
25
|
+
type: InsightOperationType;
|
|
26
|
+
sessionId: string;
|
|
27
|
+
priority: 'high' | 'normal' | 'low';
|
|
28
|
+
trigger: InsightTrigger;
|
|
29
|
+
enqueuedAt: number;
|
|
30
|
+
traceId?: string;
|
|
31
|
+
}
|
|
32
|
+
interface QueueStats {
|
|
33
|
+
totalEnqueued: number;
|
|
34
|
+
totalProcessed: number;
|
|
35
|
+
totalSkipped: number;
|
|
36
|
+
byType: Record<InsightOperationType, number>;
|
|
37
|
+
byTrigger: Record<string, number>;
|
|
38
|
+
}
|
|
39
|
+
export declare class InsightQueue extends EventEmitter {
|
|
40
|
+
private logger;
|
|
41
|
+
private queues;
|
|
42
|
+
private processing;
|
|
43
|
+
private processingType;
|
|
44
|
+
private stats;
|
|
45
|
+
private executor;
|
|
46
|
+
constructor();
|
|
47
|
+
/**
|
|
48
|
+
* Set the executor function that processes operations.
|
|
49
|
+
* This is injected to break the circular dependency between queue and handler.
|
|
50
|
+
*/
|
|
51
|
+
setExecutor(executor: (op: InsightOperation) => Promise<void>): void;
|
|
52
|
+
/**
|
|
53
|
+
* Enqueue an insight operation.
|
|
54
|
+
* Operations are coalesced (duplicate type+session skipped) and prioritized.
|
|
55
|
+
*/
|
|
56
|
+
enqueue(op: Omit<InsightOperation, 'enqueuedAt'>): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Process the next operation in a session's queue.
|
|
59
|
+
* This is the serialization point - only one operation per session at a time.
|
|
60
|
+
*/
|
|
61
|
+
private processNext;
|
|
62
|
+
/**
|
|
63
|
+
* Get the current queue for a session (for debugging/UI).
|
|
64
|
+
*/
|
|
65
|
+
getQueue(sessionId: string): InsightOperation[];
|
|
66
|
+
/**
|
|
67
|
+
* Check if a session is currently being processed.
|
|
68
|
+
*/
|
|
69
|
+
isProcessing(sessionId: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Get the operation type currently being processed for a session.
|
|
72
|
+
*/
|
|
73
|
+
getProcessingType(sessionId: string): InsightOperationType | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Get the number of pending operations for a session.
|
|
76
|
+
*/
|
|
77
|
+
getPendingCount(sessionId: string): number;
|
|
78
|
+
/**
|
|
79
|
+
* Get all sessions with pending operations.
|
|
80
|
+
*/
|
|
81
|
+
getActiveSessionIds(): string[];
|
|
82
|
+
/**
|
|
83
|
+
* Get queue statistics.
|
|
84
|
+
*/
|
|
85
|
+
getStats(): QueueStats;
|
|
86
|
+
/**
|
|
87
|
+
* Clear the queue for a session (e.g., when session is archived).
|
|
88
|
+
*/
|
|
89
|
+
clearSession(sessionId: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Shutdown the queue (for graceful server shutdown).
|
|
92
|
+
* Waits for in-flight operations to complete but doesn't process new ones.
|
|
93
|
+
*/
|
|
94
|
+
shutdown(timeoutMs?: number): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
export declare function getInsightQueue(): InsightQueue;
|
|
97
|
+
export declare function resetInsightQueue(): void;
|
|
98
|
+
export {};
|
|
99
|
+
//# sourceMappingURL=insight-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insight-queue.d.ts","sourceRoot":"","sources":["../../src/services/insight-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAEpE,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,cAAc,GACd,YAAY,GACZ,UAAU,GACV,WAAW,GACX,QAAQ,GACR,gBAAgB,CAAC;AAErB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACpC,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,UAAU;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;IAC7C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAiCD,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAA8C;IAC5D,OAAO,CAAC,UAAU,CAA0B;IAE5C,OAAO,CAAC,cAAc,CAAgD;IACtE,OAAO,CAAC,KAAK,CAMX;IAGF,OAAO,CAAC,QAAQ,CAA0D;;IAO1E;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAKpE;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,GAAG,OAAO;IAoD1D;;;OAGG;YACW,WAAW;IA0EzB;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EAAE;IAI/C;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIxC;;OAEG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;IAItE;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI1C;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE;IAM/B;;OAEG;IACH,QAAQ,IAAI,UAAU;IAItB;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAWrC;;;OAGG;IACG,QAAQ,CAAC,SAAS,GAAE,MAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAuBzD;AAKD,wBAAgB,eAAe,IAAI,YAAY,CAK9C;AAGD,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|