genbox-agent 0.0.2 → 1.0.1
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/dist/configure-hooks.d.ts +17 -0
- package/dist/configure-hooks.d.ts.map +1 -0
- package/dist/configure-hooks.js +235 -0
- package/dist/configure-hooks.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +41 -1
- package/dist/index.js.map +1 -1
- package/dist/providers/base-provider.d.ts +125 -0
- package/dist/providers/base-provider.d.ts.map +1 -0
- package/dist/providers/base-provider.js +217 -0
- package/dist/providers/base-provider.js.map +1 -0
- package/dist/providers/claude-provider.d.ts +35 -0
- package/dist/providers/claude-provider.d.ts.map +1 -0
- package/dist/providers/claude-provider.js +298 -0
- package/dist/providers/claude-provider.js.map +1 -0
- package/dist/providers/codex-provider.d.ts +73 -0
- package/dist/providers/codex-provider.d.ts.map +1 -0
- package/dist/providers/codex-provider.js +426 -0
- package/dist/providers/codex-provider.js.map +1 -0
- package/dist/providers/gemini-provider.d.ts +37 -0
- package/dist/providers/gemini-provider.d.ts.map +1 -0
- package/dist/providers/gemini-provider.js +352 -0
- package/dist/providers/gemini-provider.js.map +1 -0
- package/dist/providers/index.d.ts +128 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +293 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/types/index.d.ts +123 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/unified-daemon.d.ts +18 -0
- package/dist/unified-daemon.d.ts.map +1 -0
- package/dist/unified-daemon.js +309 -0
- package/dist/unified-daemon.js.map +1 -0
- package/dist/unified-hook.d.ts +24 -0
- package/dist/unified-hook.d.ts.map +1 -0
- package/dist/unified-hook.js +173 -0
- package/dist/unified-hook.js.map +1 -0
- package/package.json +34 -8
- package/src/daemon.ts +0 -329
- package/src/hook.ts +0 -200
- package/src/index.ts +0 -1
- package/src/session-manager.ts +0 -270
- package/tsconfig.json +0 -19
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gemini CLI Provider
|
|
4
|
+
*
|
|
5
|
+
* Provider implementation for Google's Gemini CLI
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.GeminiProvider = void 0;
|
|
42
|
+
const child_process_1 = require("child_process");
|
|
43
|
+
const crypto = __importStar(require("crypto"));
|
|
44
|
+
const base_provider_1 = require("./base-provider");
|
|
45
|
+
/**
|
|
46
|
+
* Event mapping from Gemini CLI events to unified events
|
|
47
|
+
*
|
|
48
|
+
* Gemini CLI supports:
|
|
49
|
+
* - SessionStart, SessionEnd
|
|
50
|
+
* - BeforeAgent (after user submits prompt)
|
|
51
|
+
* - AfterAgent (when agent loop ends)
|
|
52
|
+
* - BeforeModel, AfterModel (LLM request/response)
|
|
53
|
+
* - BeforeToolSelection
|
|
54
|
+
* - BeforeTool, AfterTool
|
|
55
|
+
* - PreCompress
|
|
56
|
+
* - Notification
|
|
57
|
+
*/
|
|
58
|
+
const GEMINI_EVENT_MAPPING = {
|
|
59
|
+
SessionStart: 'session_start',
|
|
60
|
+
SessionEnd: 'session_end',
|
|
61
|
+
BeforeAgent: 'before_prompt',
|
|
62
|
+
AfterAgent: 'after_prompt',
|
|
63
|
+
BeforeModel: 'before_model',
|
|
64
|
+
AfterModel: 'after_model',
|
|
65
|
+
BeforeToolSelection: 'before_tool',
|
|
66
|
+
BeforeTool: 'before_tool',
|
|
67
|
+
AfterTool: 'after_tool',
|
|
68
|
+
PreCompress: 'notification',
|
|
69
|
+
Notification: 'notification',
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Gemini CLI provider configuration
|
|
73
|
+
*/
|
|
74
|
+
const GEMINI_CONFIG = {
|
|
75
|
+
provider: 'gemini',
|
|
76
|
+
displayName: 'Gemini CLI',
|
|
77
|
+
cliCommand: 'gemini',
|
|
78
|
+
settingsPath: '~/.gemini/settings.json',
|
|
79
|
+
tmuxPrefix: 'gemini-',
|
|
80
|
+
supportedEvents: [
|
|
81
|
+
'SessionStart',
|
|
82
|
+
'SessionEnd',
|
|
83
|
+
'BeforeAgent',
|
|
84
|
+
'AfterAgent',
|
|
85
|
+
'BeforeModel',
|
|
86
|
+
'AfterModel',
|
|
87
|
+
'BeforeToolSelection',
|
|
88
|
+
'BeforeTool',
|
|
89
|
+
'AfterTool',
|
|
90
|
+
'PreCompress',
|
|
91
|
+
'Notification',
|
|
92
|
+
],
|
|
93
|
+
eventMapping: GEMINI_EVENT_MAPPING,
|
|
94
|
+
};
|
|
95
|
+
class GeminiProvider extends base_provider_1.BaseProvider {
|
|
96
|
+
config = GEMINI_CONFIG;
|
|
97
|
+
sessions = new Map();
|
|
98
|
+
constructor(genboxId) {
|
|
99
|
+
super(genboxId);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Detect if Gemini CLI is installed
|
|
103
|
+
*/
|
|
104
|
+
detect() {
|
|
105
|
+
try {
|
|
106
|
+
const result = (0, child_process_1.execSync)('gemini --version 2>/dev/null', {
|
|
107
|
+
encoding: 'utf-8',
|
|
108
|
+
timeout: 5000,
|
|
109
|
+
});
|
|
110
|
+
const versionMatch = result.match(/(\d+\.\d+\.\d+)/);
|
|
111
|
+
const version = versionMatch ? versionMatch[1] : undefined;
|
|
112
|
+
return {
|
|
113
|
+
detected: true,
|
|
114
|
+
provider: 'gemini',
|
|
115
|
+
version,
|
|
116
|
+
configPath: this.config.settingsPath.replace('~', process.env.HOME || ''),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return { detected: false };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Create a new Gemini CLI session
|
|
125
|
+
*/
|
|
126
|
+
createSession(projectPath = '/home/dev') {
|
|
127
|
+
const sessionId = this.generateSessionId();
|
|
128
|
+
const sessionName = this.getSessionName(sessionId);
|
|
129
|
+
// Create detached tmux session
|
|
130
|
+
const result = this.runTmux([
|
|
131
|
+
'new-session',
|
|
132
|
+
'-d',
|
|
133
|
+
'-s', sessionName,
|
|
134
|
+
'-c', projectPath,
|
|
135
|
+
]);
|
|
136
|
+
if (!result.success) {
|
|
137
|
+
console.error(`Failed to create tmux session: ${result.stderr}`);
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
// Wait for tmux to initialize
|
|
141
|
+
(0, child_process_1.execSync)('sleep 0.5');
|
|
142
|
+
// Start Gemini CLI
|
|
143
|
+
this.runTmux([
|
|
144
|
+
'send-keys',
|
|
145
|
+
'-t', sessionName,
|
|
146
|
+
'gemini',
|
|
147
|
+
'Enter',
|
|
148
|
+
]);
|
|
149
|
+
const session = {
|
|
150
|
+
sessionId,
|
|
151
|
+
sessionName,
|
|
152
|
+
provider: 'gemini',
|
|
153
|
+
projectPath,
|
|
154
|
+
createdAt: Date.now(),
|
|
155
|
+
status: 'starting',
|
|
156
|
+
};
|
|
157
|
+
this.sessions.set(sessionId, session);
|
|
158
|
+
return session;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Parse Gemini CLI hook input
|
|
162
|
+
*
|
|
163
|
+
* Gemini CLI sends JSON to stdin with different structure than Claude
|
|
164
|
+
*/
|
|
165
|
+
parseHookInput(eventType, rawInput) {
|
|
166
|
+
let hookData = {};
|
|
167
|
+
try {
|
|
168
|
+
if (rawInput.trim()) {
|
|
169
|
+
hookData = JSON.parse(rawInput);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
hookData = { raw_input: rawInput };
|
|
174
|
+
}
|
|
175
|
+
const sessionId = this.getOrCreateSessionId();
|
|
176
|
+
const baseEvent = this.createBaseHookEvent(eventType, sessionId);
|
|
177
|
+
const event = {
|
|
178
|
+
...baseEvent,
|
|
179
|
+
eventType: this.mapEventType(eventType),
|
|
180
|
+
provider: 'gemini',
|
|
181
|
+
providerEventType: eventType,
|
|
182
|
+
sessionId,
|
|
183
|
+
genboxId: this.genboxId,
|
|
184
|
+
timestamp: new Date().toISOString(),
|
|
185
|
+
projectPath: process.cwd(),
|
|
186
|
+
rawData: hookData,
|
|
187
|
+
};
|
|
188
|
+
// Parse event-specific data (Gemini uses slightly different field names)
|
|
189
|
+
switch (eventType) {
|
|
190
|
+
case 'BeforeTool':
|
|
191
|
+
event.toolName = hookData.toolName || hookData.tool_name || '';
|
|
192
|
+
event.toolInput = hookData.input || hookData.tool_input || {};
|
|
193
|
+
break;
|
|
194
|
+
case 'AfterTool':
|
|
195
|
+
event.toolName = hookData.toolName || hookData.tool_name || '';
|
|
196
|
+
event.toolInput = hookData.input || hookData.tool_input || {};
|
|
197
|
+
event.toolResponse = hookData.output || hookData.tool_response || {};
|
|
198
|
+
event.toolSuccess = !hookData.error;
|
|
199
|
+
break;
|
|
200
|
+
case 'BeforeAgent':
|
|
201
|
+
// BeforeAgent fires after user submits prompt
|
|
202
|
+
event.prompt = hookData.prompt || hookData.userInput || '';
|
|
203
|
+
event.promptLength = (event.prompt || '').length;
|
|
204
|
+
break;
|
|
205
|
+
case 'AfterAgent':
|
|
206
|
+
event.stopReason = hookData.reason || '';
|
|
207
|
+
break;
|
|
208
|
+
case 'BeforeModel':
|
|
209
|
+
event.modelName = hookData.model || '';
|
|
210
|
+
event.modelRequest = hookData.request || {};
|
|
211
|
+
event.tokenCount = hookData.tokenCount || 0;
|
|
212
|
+
break;
|
|
213
|
+
case 'AfterModel':
|
|
214
|
+
event.modelName = hookData.model || '';
|
|
215
|
+
event.modelResponse = hookData.response || {};
|
|
216
|
+
event.tokenCount = hookData.tokenCount || 0;
|
|
217
|
+
break;
|
|
218
|
+
case 'Notification':
|
|
219
|
+
event.notification = hookData.message || hookData.notification || '';
|
|
220
|
+
event.notificationType = hookData.type || '';
|
|
221
|
+
break;
|
|
222
|
+
case 'SessionStart':
|
|
223
|
+
event.cliVersion = hookData.version || '';
|
|
224
|
+
break;
|
|
225
|
+
case 'SessionEnd':
|
|
226
|
+
event.sessionDuration = hookData.durationMs || hookData.duration_ms || 0;
|
|
227
|
+
break;
|
|
228
|
+
case 'PreCompress':
|
|
229
|
+
event.notification = 'Context compression starting';
|
|
230
|
+
event.tokenCount = hookData.tokenCount || 0;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
return event;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Generate Gemini CLI hook configuration
|
|
237
|
+
*/
|
|
238
|
+
generateHookConfig(hookScriptPath) {
|
|
239
|
+
return {
|
|
240
|
+
provider: 'gemini',
|
|
241
|
+
settingsJson: {
|
|
242
|
+
hooks: {
|
|
243
|
+
SessionStart: [{
|
|
244
|
+
hooks: [{
|
|
245
|
+
type: 'command',
|
|
246
|
+
command: `${hookScriptPath} gemini SessionStart`,
|
|
247
|
+
}],
|
|
248
|
+
}],
|
|
249
|
+
SessionEnd: [{
|
|
250
|
+
hooks: [{
|
|
251
|
+
type: 'command',
|
|
252
|
+
command: `${hookScriptPath} gemini SessionEnd`,
|
|
253
|
+
}],
|
|
254
|
+
}],
|
|
255
|
+
BeforeAgent: [{
|
|
256
|
+
hooks: [{
|
|
257
|
+
type: 'command',
|
|
258
|
+
command: `${hookScriptPath} gemini BeforeAgent`,
|
|
259
|
+
}],
|
|
260
|
+
}],
|
|
261
|
+
AfterAgent: [{
|
|
262
|
+
hooks: [{
|
|
263
|
+
type: 'command',
|
|
264
|
+
command: `${hookScriptPath} gemini AfterAgent`,
|
|
265
|
+
}],
|
|
266
|
+
}],
|
|
267
|
+
BeforeTool: [{
|
|
268
|
+
matcher: '.*',
|
|
269
|
+
hooks: [{
|
|
270
|
+
type: 'command',
|
|
271
|
+
command: `${hookScriptPath} gemini BeforeTool`,
|
|
272
|
+
}],
|
|
273
|
+
}],
|
|
274
|
+
AfterTool: [{
|
|
275
|
+
matcher: '.*',
|
|
276
|
+
hooks: [{
|
|
277
|
+
type: 'command',
|
|
278
|
+
command: `${hookScriptPath} gemini AfterTool`,
|
|
279
|
+
}],
|
|
280
|
+
}],
|
|
281
|
+
BeforeModel: [{
|
|
282
|
+
hooks: [{
|
|
283
|
+
type: 'command',
|
|
284
|
+
command: `${hookScriptPath} gemini BeforeModel`,
|
|
285
|
+
}],
|
|
286
|
+
}],
|
|
287
|
+
AfterModel: [{
|
|
288
|
+
hooks: [{
|
|
289
|
+
type: 'command',
|
|
290
|
+
command: `${hookScriptPath} gemini AfterModel`,
|
|
291
|
+
}],
|
|
292
|
+
}],
|
|
293
|
+
Notification: [{
|
|
294
|
+
hooks: [{
|
|
295
|
+
type: 'command',
|
|
296
|
+
command: `${hookScriptPath} gemini Notification`,
|
|
297
|
+
}],
|
|
298
|
+
}],
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Analyze output for Gemini-specific status indicators
|
|
305
|
+
*/
|
|
306
|
+
analyzeOutputForStatus(output) {
|
|
307
|
+
const lowerOutput = output.toLowerCase();
|
|
308
|
+
const lines = output.split('\n');
|
|
309
|
+
const lastNonEmptyLine = lines.filter(l => l.trim()).pop() || '';
|
|
310
|
+
// Gemini-specific patterns
|
|
311
|
+
if (lastNonEmptyLine.includes('❯') || lastNonEmptyLine.includes('gemini>')) {
|
|
312
|
+
return 'waiting_input';
|
|
313
|
+
}
|
|
314
|
+
if (lowerOutput.includes('thinking') || lowerOutput.includes('generating')) {
|
|
315
|
+
return 'active';
|
|
316
|
+
}
|
|
317
|
+
if (lowerOutput.includes('error') || lowerOutput.includes('failed')) {
|
|
318
|
+
return 'error';
|
|
319
|
+
}
|
|
320
|
+
return 'idle';
|
|
321
|
+
}
|
|
322
|
+
generateSessionId() {
|
|
323
|
+
return crypto
|
|
324
|
+
.createHash('sha256')
|
|
325
|
+
.update(`${this.genboxId}-gemini-${Date.now()}-${process.pid}`)
|
|
326
|
+
.digest('hex')
|
|
327
|
+
.slice(0, 16);
|
|
328
|
+
}
|
|
329
|
+
getOrCreateSessionId() {
|
|
330
|
+
const fs = require('fs');
|
|
331
|
+
const path = require('path');
|
|
332
|
+
const sessionFile = path.join(process.env.HOME || '/tmp', '.gemini-session-id');
|
|
333
|
+
try {
|
|
334
|
+
if (fs.existsSync(sessionFile)) {
|
|
335
|
+
return fs.readFileSync(sessionFile, 'utf-8').trim();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
// Ignore read errors
|
|
340
|
+
}
|
|
341
|
+
const sessionId = this.generateSessionId();
|
|
342
|
+
try {
|
|
343
|
+
fs.writeFileSync(sessionFile, sessionId);
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
// Ignore write errors
|
|
347
|
+
}
|
|
348
|
+
return sessionId;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
exports.GeminiProvider = GeminiProvider;
|
|
352
|
+
//# sourceMappingURL=gemini-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-provider.js","sourceRoot":"","sources":["../../src/providers/gemini-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Registry
|
|
3
|
+
*
|
|
4
|
+
* Central registry for all AI CLI providers. Provides:
|
|
5
|
+
* - Provider registration and discovery
|
|
6
|
+
* - Auto-detection of installed providers
|
|
7
|
+
* - Unified interface for provider operations
|
|
8
|
+
*/
|
|
9
|
+
import { AIProvider, AISession, ProviderConfig, ProviderDetectionResult, HookConfig } from '../types';
|
|
10
|
+
import { IAIProvider } from './base-provider';
|
|
11
|
+
export { BaseProvider, IAIProvider } from './base-provider';
|
|
12
|
+
export { ClaudeProvider } from './claude-provider';
|
|
13
|
+
export { GeminiProvider } from './gemini-provider';
|
|
14
|
+
export { CodexProvider } from './codex-provider';
|
|
15
|
+
/**
|
|
16
|
+
* Provider factory function type
|
|
17
|
+
*/
|
|
18
|
+
type ProviderFactory = (genboxId: string) => IAIProvider;
|
|
19
|
+
/**
|
|
20
|
+
* Provider Registry
|
|
21
|
+
*
|
|
22
|
+
* Manages all registered AI CLI providers and provides a unified interface
|
|
23
|
+
* for creating and working with them.
|
|
24
|
+
*/
|
|
25
|
+
export declare class ProviderRegistry {
|
|
26
|
+
private static instance;
|
|
27
|
+
private providers;
|
|
28
|
+
private instances;
|
|
29
|
+
private constructor();
|
|
30
|
+
/**
|
|
31
|
+
* Get singleton instance
|
|
32
|
+
*/
|
|
33
|
+
static getInstance(): ProviderRegistry;
|
|
34
|
+
/**
|
|
35
|
+
* Register a new provider
|
|
36
|
+
*/
|
|
37
|
+
register(provider: AIProvider, factory: ProviderFactory, priority?: number): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get a provider instance
|
|
40
|
+
*/
|
|
41
|
+
getProvider(provider: AIProvider, genboxId: string): IAIProvider | null;
|
|
42
|
+
/**
|
|
43
|
+
* Get all registered providers
|
|
44
|
+
*/
|
|
45
|
+
getRegisteredProviders(): AIProvider[];
|
|
46
|
+
/**
|
|
47
|
+
* Detect all installed providers
|
|
48
|
+
*/
|
|
49
|
+
detectInstalledProviders(genboxId: string): Map<AIProvider, ProviderDetectionResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Get the first available (installed) provider
|
|
52
|
+
*/
|
|
53
|
+
getDefaultProvider(genboxId: string): IAIProvider | null;
|
|
54
|
+
/**
|
|
55
|
+
* Get provider configuration
|
|
56
|
+
*/
|
|
57
|
+
getProviderConfig(provider: AIProvider, genboxId: string): ProviderConfig | null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Unified Session Manager
|
|
61
|
+
*
|
|
62
|
+
* High-level interface for managing sessions across all providers
|
|
63
|
+
*/
|
|
64
|
+
export declare class UnifiedSessionManager {
|
|
65
|
+
private readonly genboxId;
|
|
66
|
+
private registry;
|
|
67
|
+
private sessions;
|
|
68
|
+
constructor(genboxId: string);
|
|
69
|
+
/**
|
|
70
|
+
* Create a new session with the specified or default provider
|
|
71
|
+
*/
|
|
72
|
+
createSession(projectPath?: string, provider?: AIProvider): AISession | null;
|
|
73
|
+
/**
|
|
74
|
+
* Send a prompt to a session
|
|
75
|
+
*/
|
|
76
|
+
sendPrompt(sessionId: string, prompt: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Send a keystroke to a session
|
|
79
|
+
*/
|
|
80
|
+
sendKeystroke(sessionId: string, key: string): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Get terminal output from a session
|
|
83
|
+
*/
|
|
84
|
+
getOutput(sessionId: string, lines?: number): string | null;
|
|
85
|
+
/**
|
|
86
|
+
* Get session status
|
|
87
|
+
*/
|
|
88
|
+
getSessionStatus(sessionId: string): AISession['status'];
|
|
89
|
+
/**
|
|
90
|
+
* Kill a session
|
|
91
|
+
*/
|
|
92
|
+
killSession(sessionId: string): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* List all sessions across all providers
|
|
95
|
+
*/
|
|
96
|
+
listAllSessions(): AISession[];
|
|
97
|
+
/**
|
|
98
|
+
* Find a session across all providers
|
|
99
|
+
*/
|
|
100
|
+
private findSession;
|
|
101
|
+
/**
|
|
102
|
+
* Get detected providers
|
|
103
|
+
*/
|
|
104
|
+
getDetectedProviders(): Map<AIProvider, ProviderDetectionResult>;
|
|
105
|
+
/**
|
|
106
|
+
* Get a specific provider instance
|
|
107
|
+
*/
|
|
108
|
+
getProvider(provider: AIProvider): IAIProvider | null;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Hook Configuration Generator
|
|
112
|
+
*
|
|
113
|
+
* Generates hook configurations for all providers
|
|
114
|
+
*/
|
|
115
|
+
export declare class HookConfigGenerator {
|
|
116
|
+
private readonly genboxId;
|
|
117
|
+
private registry;
|
|
118
|
+
constructor(genboxId: string);
|
|
119
|
+
/**
|
|
120
|
+
* Generate hook configuration for a specific provider
|
|
121
|
+
*/
|
|
122
|
+
generateForProvider(provider: AIProvider, hookScriptPath: string): HookConfig | null;
|
|
123
|
+
/**
|
|
124
|
+
* Generate hook configurations for all detected providers
|
|
125
|
+
*/
|
|
126
|
+
generateForAllDetected(hookScriptPath: string): Map<AIProvider, HookConfig>;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"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"}
|