ai-code-connect 1.0.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/dist/config.js ADDED
@@ -0,0 +1,104 @@
1
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
2
+ import { homedir } from 'os';
3
+ import { join } from 'path';
4
+ const DEFAULT_CONFIG = {
5
+ defaultTool: 'claude',
6
+ tools: {
7
+ claude: {
8
+ command: 'claude',
9
+ defaultFlags: ['-p', '--output-format', 'text'],
10
+ },
11
+ gemini: {
12
+ command: 'gemini',
13
+ defaultFlags: ['-o', 'text'],
14
+ },
15
+ },
16
+ };
17
+ /**
18
+ * Get the config directory path
19
+ */
20
+ export function getConfigDir() {
21
+ return join(homedir(), '.aic');
22
+ }
23
+ /**
24
+ * Get the config file path
25
+ */
26
+ export function getConfigPath() {
27
+ return join(getConfigDir(), 'config.json');
28
+ }
29
+ /**
30
+ * Ensure the config directory exists
31
+ */
32
+ export function ensureConfigDir() {
33
+ const dir = getConfigDir();
34
+ if (!existsSync(dir)) {
35
+ mkdirSync(dir, { recursive: true });
36
+ }
37
+ }
38
+ /**
39
+ * Load configuration from disk, or return defaults
40
+ */
41
+ export function loadConfig() {
42
+ const configPath = getConfigPath();
43
+ if (!existsSync(configPath)) {
44
+ return { ...DEFAULT_CONFIG };
45
+ }
46
+ try {
47
+ const content = readFileSync(configPath, 'utf-8');
48
+ const loaded = JSON.parse(content);
49
+ return {
50
+ ...DEFAULT_CONFIG,
51
+ ...loaded,
52
+ tools: {
53
+ ...DEFAULT_CONFIG.tools,
54
+ ...loaded.tools,
55
+ },
56
+ };
57
+ }
58
+ catch {
59
+ console.warn('Failed to load config, using defaults');
60
+ return { ...DEFAULT_CONFIG };
61
+ }
62
+ }
63
+ /**
64
+ * Save configuration to disk
65
+ */
66
+ export function saveConfig(config) {
67
+ ensureConfigDir();
68
+ const configPath = getConfigPath();
69
+ writeFileSync(configPath, JSON.stringify(config, null, 2));
70
+ }
71
+ /**
72
+ * Get the default tool (checks env var first, then config)
73
+ */
74
+ export function getDefaultTool() {
75
+ // Environment variable takes priority
76
+ const envTool = process.env.AIC_DEFAULT_TOOL;
77
+ if (envTool && ['claude', 'gemini'].includes(envTool.toLowerCase())) {
78
+ return envTool.toLowerCase();
79
+ }
80
+ // Fall back to config file
81
+ const config = loadConfig();
82
+ return config.defaultTool || 'claude';
83
+ }
84
+ /**
85
+ * Set the default tool and save to config
86
+ */
87
+ export function setDefaultTool(tool) {
88
+ const validTools = ['claude', 'gemini'];
89
+ const normalizedTool = tool.toLowerCase();
90
+ if (!validTools.includes(normalizedTool)) {
91
+ return {
92
+ success: false,
93
+ message: `Invalid tool "${tool}". Valid options: ${validTools.join(', ')}`
94
+ };
95
+ }
96
+ const config = loadConfig();
97
+ config.defaultTool = normalizedTool;
98
+ saveConfig(config);
99
+ return {
100
+ success: true,
101
+ message: `Default tool set to "${normalizedTool}". Will be used on next launch.`
102
+ };
103
+ }
104
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { AdapterRegistry, ClaudeAdapter, GeminiAdapter } from './adapters/index.js';
4
+ import { loadConfig, getDefaultTool, setDefaultTool, getConfigPath } from './config.js';
5
+ import { startSDKSession } from './sdk-session.js';
6
+ const program = new Command();
7
+ // Initialize adapters
8
+ const registry = new AdapterRegistry();
9
+ registry.register(new ClaudeAdapter());
10
+ registry.register(new GeminiAdapter());
11
+ // Load config
12
+ const config = loadConfig();
13
+ const HELP_TEXT = `
14
+ AIC² - AI Code Connect
15
+ Bridge Claude Code and Gemini CLI in a single session.
16
+
17
+ Session Commands:
18
+ /claude Switch to Claude Code
19
+ /gemini Switch to Gemini CLI
20
+ /i Enter interactive mode (Ctrl+] to detach)
21
+ /forward [tool] [msg] Forward last response to another tool
22
+ /history Show conversation history
23
+ /status Show running processes
24
+ /default <tool> Set default tool (saved permanently)
25
+ /clear Clear sessions and history
26
+ /quit, /cya Exit
27
+
28
+ Tool Commands:
29
+ //command Run /command in interactive mode (e.g., //status, //cost)
30
+
31
+ Configuration:
32
+ aic config default [tool] Get or set default tool
33
+ AIC_DEFAULT_TOOL=gemini Override via environment variable
34
+
35
+ Forward Behavior:
36
+ With 2 tools: /forward Auto-selects the other tool
37
+ With 3+ tools: /forward <tool> Target tool required
38
+
39
+ Examples:
40
+ aic Launch interactive session
41
+ aic tools List available AI tools
42
+ aic config default gemini Set Gemini as default tool
43
+ `;
44
+ program
45
+ .name('aic')
46
+ .description('AIC² - AI Code Connect\nBridge Claude Code and Gemini CLI')
47
+ .version('1.0.0')
48
+ .addHelpText('after', HELP_TEXT);
49
+ // Tools command - list available tools
50
+ program
51
+ .command('tools')
52
+ .description('List available AI tools and their status')
53
+ .action(async () => {
54
+ console.log('Available tools:\n');
55
+ for (const adapter of registry.getAll()) {
56
+ const available = await adapter.isAvailable();
57
+ const status = available ? '✓ available' : '✗ not found';
58
+ console.log(` ${adapter.name.padEnd(10)} ${adapter.displayName.padEnd(15)} ${status}`);
59
+ }
60
+ });
61
+ // Config command
62
+ const configCmd = program
63
+ .command('config')
64
+ .description('Manage AIC² configuration');
65
+ configCmd
66
+ .command('default [tool]')
67
+ .description('Get or set the default tool (claude, gemini)')
68
+ .action((tool) => {
69
+ if (tool) {
70
+ // Set default tool
71
+ const result = setDefaultTool(tool);
72
+ if (result.success) {
73
+ console.log(`✓ ${result.message}`);
74
+ }
75
+ else {
76
+ console.error(`✗ ${result.message}`);
77
+ process.exit(1);
78
+ }
79
+ }
80
+ else {
81
+ // Show current default
82
+ const currentDefault = getDefaultTool();
83
+ const configPath = getConfigPath();
84
+ console.log(`Default tool: ${currentDefault}`);
85
+ console.log(`Config file: ${configPath}`);
86
+ // Check if env var is overriding
87
+ if (process.env.AIC_DEFAULT_TOOL) {
88
+ console.log(`(Overridden by AIC_DEFAULT_TOOL environment variable)`);
89
+ }
90
+ }
91
+ });
92
+ // Default action - start interactive session
93
+ program
94
+ .action(async () => {
95
+ await startSDKSession();
96
+ });
97
+ program.parse();
98
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Session with persistent interactive mode support
3
+ * - Regular messages: uses -p (print mode) with --continue/--resume
4
+ * - Interactive mode: persistent PTY process, detach with Ctrl+]
5
+ */
6
+ export declare class SDKSession {
7
+ private isRunning;
8
+ private activeTool;
9
+ private conversationHistory;
10
+ private claudeHasSession;
11
+ private geminiHasSession;
12
+ private runningProcesses;
13
+ private interactiveOutputBuffer;
14
+ private cwd;
15
+ private rl;
16
+ private inputHistory;
17
+ constructor(cwd?: string);
18
+ start(): Promise<void>;
19
+ private getPrompt;
20
+ /**
21
+ * Tab completion for / commands
22
+ */
23
+ private completer;
24
+ private setupReadline;
25
+ private runLoop;
26
+ private promptLoop;
27
+ private readInput;
28
+ private handleMetaCommand;
29
+ private showHelp;
30
+ private sendToTool;
31
+ private sendToClaude;
32
+ private sendToGemini;
33
+ /**
34
+ * Enter full interactive mode with the active tool.
35
+ * - If a process is already running, re-attach to it
36
+ * - If not, spawn a new one
37
+ * - Press Ctrl+] to detach (process keeps running)
38
+ * - Use /exit in the tool to terminate the process
39
+ */
40
+ private enterInteractiveMode;
41
+ /**
42
+ * Enter interactive mode and automatically send a slash command
43
+ * User stays in interactive mode to see output and interact, then Ctrl+] to return
44
+ */
45
+ private enterInteractiveModeWithCommand;
46
+ private showStatus;
47
+ private handleForward;
48
+ private showHistory;
49
+ private cleanup;
50
+ }
51
+ export declare function startSDKSession(): Promise<void>;
52
+ //# sourceMappingURL=sdk-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-session.d.ts","sourceRoot":"","sources":["../src/sdk-session.ts"],"names":[],"mappings":"AA6RA;;;;GAIG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,mBAAmB,CAAiB;IAG5C,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,gBAAgB,CAAS;IAGjC,OAAO,CAAC,gBAAgB,CAAgC;IAGxD,OAAO,CAAC,uBAAuB,CAAkC;IAGjE,OAAO,CAAC,GAAG,CAAS;IAGpB,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,YAAY,CAAgB;gBAExB,GAAG,CAAC,EAAE,MAAM;IAMlB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0I5B,OAAO,CAAC,SAAS;IAMjB;;OAEG;IACH,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,aAAa;YAqBP,OAAO;YAKP,UAAU;IA2CxB,OAAO,CAAC,SAAS;YAwCH,iBAAiB;IAiF/B,OAAO,CAAC,QAAQ;YA4BF,UAAU;IA8BxB,OAAO,CAAC,YAAY;IA0DpB,OAAO,CAAC,YAAY;IAyDpB;;;;;;OAMG;YACW,oBAAoB;IAmRlC;;;OAGG;YACW,+BAA+B;IAwT7C,OAAO,CAAC,UAAU;YAcJ,aAAa;IAoE3B,OAAO,CAAC,WAAW;YA8BL,OAAO;CAQtB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAGrD"}