agentgui 1.0.45 → 1.0.47
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/.prd +45 -0
- package/acp-launcher.js +36 -163
- package/conversation-importer.js +70 -0
- package/database.js +145 -0
- package/package.json +2 -2
package/.prd
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# agentgui Work Items
|
|
2
|
+
|
|
3
|
+
## ACTIVE 🔄
|
|
4
|
+
|
|
5
|
+
### Phase 2: OpenCode Integration (PRIORITY 2)
|
|
6
|
+
**User Request:** Import all OpenCode conversations and keep them in sync
|
|
7
|
+
|
|
8
|
+
**Blockers:**
|
|
9
|
+
- [ ] Determine OpenCode conversation storage location
|
|
10
|
+
|
|
11
|
+
**Tasks:**
|
|
12
|
+
- [ ] Implement OpenCode history loader
|
|
13
|
+
- [ ] Merge both sources in database
|
|
14
|
+
- [ ] Display merged history in sidebar
|
|
15
|
+
- [ ] Support agent type filtering
|
|
16
|
+
|
|
17
|
+
### Phase 3: Sync & Consistency (PRIORITY 3)
|
|
18
|
+
- [ ] File watchers for history changes
|
|
19
|
+
- [ ] Auto-import new conversations from CLI
|
|
20
|
+
- [ ] Keep GUI database in sync with filesystem
|
|
21
|
+
- [ ] Handle conflicts (same conversation in both systems)
|
|
22
|
+
- [ ] Implement read-only mode for imported conversations
|
|
23
|
+
|
|
24
|
+
## ISSUES TO FIX ⚠️
|
|
25
|
+
|
|
26
|
+
**Issue #1: Timeout on Conversation Selection**
|
|
27
|
+
- Clicking conversations causes code execution timeout
|
|
28
|
+
- Needs investigation into click handlers
|
|
29
|
+
|
|
30
|
+
**Issue #2: Message Input Field**
|
|
31
|
+
- Message submission behavior unclear
|
|
32
|
+
- May not be properly wired to agent communication
|
|
33
|
+
|
|
34
|
+
## Test Categories Remaining (10 of 12)
|
|
35
|
+
- [ ] Category 2: Real-Time Streaming with Persistence
|
|
36
|
+
- [ ] Category 3: HTML Rendering Without Text Mixing
|
|
37
|
+
- [ ] Category 4: Theme Compliance (Light/Dark)
|
|
38
|
+
- [ ] Category 5: Advanced RippleUI Components
|
|
39
|
+
- [ ] Category 6: Interactive Forms & Input Validation
|
|
40
|
+
- [ ] Category 7: Database Persistence & Recovery
|
|
41
|
+
- [ ] Category 8: State Consistency & Validation
|
|
42
|
+
- [ ] Category 9: Reconnection & Recovery
|
|
43
|
+
- [ ] Category 10: Error Handling & Edge Cases
|
|
44
|
+
- [ ] Category 11: Performance & Latency
|
|
45
|
+
- [ ] Category 12: Multi-Agent & Configuration
|
package/acp-launcher.js
CHANGED
|
@@ -1,202 +1,75 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import os from 'os';
|
|
1
|
+
import { query } from '@anthropic-ai/claude-code';
|
|
5
2
|
import { default as SYSTEM_PROMPT } from './system-prompt.js';
|
|
6
3
|
|
|
7
|
-
/**
|
|
8
|
-
* Load CLI configuration to ensure identical behavior
|
|
9
|
-
* Supports both Claude Code and OpenCode
|
|
10
|
-
*/
|
|
11
|
-
function loadCLIConfig(agentType) {
|
|
12
|
-
const configPaths = [
|
|
13
|
-
// Claude Code paths
|
|
14
|
-
path.join(os.homedir(), '.claude', 'config.json'),
|
|
15
|
-
path.join(os.homedir(), '.claude-code', 'config.json'),
|
|
16
|
-
path.join(process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), 'claude', 'config.json'),
|
|
17
|
-
// OpenCode paths
|
|
18
|
-
path.join(os.homedir(), '.opencode', 'config.json'),
|
|
19
|
-
path.join(os.homedir(), '.config', 'opencode', 'config.json'),
|
|
20
|
-
path.join(process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), 'opencode', 'config.json')
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
for (const configPath of configPaths) {
|
|
24
|
-
try {
|
|
25
|
-
if (fs.existsSync(configPath)) {
|
|
26
|
-
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
27
|
-
console.log(`[ACP] Loaded ${agentType} CLI config from ${configPath}`);
|
|
28
|
-
return config;
|
|
29
|
-
}
|
|
30
|
-
} catch (e) {
|
|
31
|
-
// Config file doesn't exist or is invalid, continue
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
console.log(`[ACP] No ${agentType} config found, using defaults`);
|
|
36
|
-
return {};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
4
|
export default class ACPConnection {
|
|
40
5
|
constructor() {
|
|
41
|
-
this.client = null;
|
|
42
6
|
this.sessionId = null;
|
|
43
7
|
this.onUpdate = null;
|
|
44
8
|
}
|
|
45
9
|
|
|
46
|
-
/**
|
|
47
|
-
* Connect to ACP bridge and create session
|
|
48
|
-
* Uses identical configuration to CLI version
|
|
49
|
-
*/
|
|
50
10
|
async connect(agentType, cwd) {
|
|
51
|
-
|
|
52
|
-
console.log(`[ACP] Connecting to ${agentType}...`);
|
|
53
|
-
|
|
54
|
-
// Load CLI configuration for identical behavior
|
|
55
|
-
const cliConfig = loadCLIConfig(agentType);
|
|
56
|
-
|
|
57
|
-
// Create client with CLI-identical configuration
|
|
58
|
-
// Pass through all environment for OAuth and plugin support
|
|
59
|
-
const clientConfig = {
|
|
60
|
-
agent: agentType === 'opencode' ? 'opencode' : 'claude-code',
|
|
61
|
-
cwd,
|
|
62
|
-
// Use same environment as CLI (HOME, PATH, etc.)
|
|
63
|
-
env: process.env,
|
|
64
|
-
// Load plugins just like CLI does
|
|
65
|
-
plugins: true,
|
|
66
|
-
// Use OAuth for authentication (same as CLI)
|
|
67
|
-
oauth: true,
|
|
68
|
-
// Use model preferences from CLI config
|
|
69
|
-
modelPreferences: cliConfig.modelPreferences || undefined,
|
|
70
|
-
// Enable all capabilities that CLI enables
|
|
71
|
-
capabilities: {
|
|
72
|
-
fs: true,
|
|
73
|
-
mcp: true,
|
|
74
|
-
web: true,
|
|
75
|
-
terminal: true
|
|
76
|
-
},
|
|
77
|
-
// Pass through any other CLI settings
|
|
78
|
-
...cliConfig
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// Remove potential conflicting fields
|
|
82
|
-
delete clientConfig.agent; // Re-add below
|
|
83
|
-
delete clientConfig.cwd; // Re-add below
|
|
84
|
-
|
|
85
|
-
this.client = await createClient({
|
|
86
|
-
agent: clientConfig.agent || (agentType === 'opencode' ? 'opencode' : 'claude-code'),
|
|
87
|
-
cwd,
|
|
88
|
-
...clientConfig
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
console.log(`[ACP] ✅ Connected to ${agentType} (CLI-identical mode)`);
|
|
92
|
-
} catch (err) {
|
|
93
|
-
console.error(`[ACP] ❌ FATAL: Connection failed: ${err.message}`);
|
|
94
|
-
throw new Error(`ACP connection failed for ${agentType}: ${err.message}`);
|
|
95
|
-
}
|
|
11
|
+
console.log(`[ACP] Using Claude Code SDK (${agentType})`);
|
|
96
12
|
}
|
|
97
13
|
|
|
98
|
-
/**
|
|
99
|
-
* Initialize ACP session
|
|
100
|
-
*/
|
|
101
14
|
async initialize() {
|
|
102
|
-
|
|
103
|
-
return this.client.request('initialize', {
|
|
104
|
-
protocolVersion: 1,
|
|
105
|
-
clientCapabilities: { fs: { readTextFile: true, writeTextFile: true } }
|
|
106
|
-
});
|
|
15
|
+
return { ready: true };
|
|
107
16
|
}
|
|
108
17
|
|
|
109
|
-
/**
|
|
110
|
-
* Create new session
|
|
111
|
-
*/
|
|
112
18
|
async newSession(cwd) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
this.sessionId = result.sessionId;
|
|
116
|
-
return result;
|
|
19
|
+
this.sessionId = Math.random().toString(36).substring(7);
|
|
20
|
+
return { sessionId: this.sessionId };
|
|
117
21
|
}
|
|
118
22
|
|
|
119
|
-
/**
|
|
120
|
-
* Set session mode
|
|
121
|
-
*/
|
|
122
23
|
async setSessionMode(modeId) {
|
|
123
|
-
|
|
124
|
-
return this.client.request('session/set_mode', { sessionId: this.sessionId, modeId });
|
|
24
|
+
return { modeId };
|
|
125
25
|
}
|
|
126
26
|
|
|
127
|
-
/**
|
|
128
|
-
* Inject unified HTML enforcement system prompt
|
|
129
|
-
*/
|
|
130
27
|
async injectSkills(additionalContext = '') {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const systemPrompt = additionalContext
|
|
134
|
-
? `${SYSTEM_PROMPT}\n\n---\n\n${additionalContext}`
|
|
135
|
-
: SYSTEM_PROMPT;
|
|
136
|
-
|
|
137
|
-
return this.client.request('session/skill_inject', {
|
|
138
|
-
sessionId: this.sessionId,
|
|
139
|
-
skills: [],
|
|
140
|
-
notification: [{ type: 'text', text: systemPrompt }]
|
|
141
|
-
});
|
|
28
|
+
return { skills: [] };
|
|
142
29
|
}
|
|
143
30
|
|
|
144
|
-
/**
|
|
145
|
-
* Inject system context with unified HTML enforcement
|
|
146
|
-
*/
|
|
147
31
|
async injectSystemContext() {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return this.client.request('session/context', {
|
|
151
|
-
sessionId: this.sessionId,
|
|
152
|
-
context: SYSTEM_PROMPT,
|
|
153
|
-
role: 'system'
|
|
154
|
-
});
|
|
32
|
+
return { context: SYSTEM_PROMPT };
|
|
155
33
|
}
|
|
156
34
|
|
|
157
|
-
/**
|
|
158
|
-
* Send prompt and stream updates
|
|
159
|
-
*/
|
|
160
35
|
async sendPrompt(prompt) {
|
|
161
|
-
|
|
36
|
+
const messages = [];
|
|
37
|
+
let fullResponse = '';
|
|
162
38
|
|
|
163
|
-
|
|
39
|
+
try {
|
|
40
|
+
const promptText = typeof prompt === 'string' ? prompt : prompt.map(p => p.text).join('\n');
|
|
41
|
+
const systemMessage = `${SYSTEM_PROMPT}\n\nUser Request: ${promptText}`;
|
|
164
42
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// Forward updates immediately with no delay
|
|
169
|
-
this.onUpdate({ update });
|
|
43
|
+
const response = query({
|
|
44
|
+
prompt: systemMessage,
|
|
45
|
+
options: {}
|
|
170
46
|
});
|
|
171
|
-
}
|
|
172
47
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
48
|
+
for await (const message of response) {
|
|
49
|
+
fullResponse += message.content?.map(c => c.text || '').join('') || '';
|
|
50
|
+
|
|
51
|
+
if (this.onUpdate) {
|
|
52
|
+
this.onUpdate({
|
|
53
|
+
update: {
|
|
54
|
+
sessionUpdate: 'agent_message_chunk',
|
|
55
|
+
content: { text: message.content?.map(c => c.text || '').join('') || '' }
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { content: fullResponse };
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.error(`[ACP] Query error: ${err.message}`);
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
178
66
|
}
|
|
179
67
|
|
|
180
|
-
/**
|
|
181
|
-
* Check if connection is running
|
|
182
|
-
*/
|
|
183
68
|
isRunning() {
|
|
184
|
-
return
|
|
69
|
+
return true;
|
|
185
70
|
}
|
|
186
71
|
|
|
187
|
-
/**
|
|
188
|
-
* Terminate connection
|
|
189
|
-
*/
|
|
190
72
|
async terminate() {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
try {
|
|
194
|
-
await this.client.close();
|
|
195
|
-
} catch (err) {
|
|
196
|
-
console.error(`[ACP] Error during terminate: ${err.message}`);
|
|
197
|
-
} finally {
|
|
198
|
-
this.client = null;
|
|
199
|
-
this.sessionId = null;
|
|
200
|
-
}
|
|
73
|
+
return;
|
|
201
74
|
}
|
|
202
75
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import { queries } from './database.js';
|
|
5
|
+
|
|
6
|
+
export class ConversationImporter {
|
|
7
|
+
static async importClaudeCodeSessions() {
|
|
8
|
+
const projectsDir = path.join(os.homedir(), '.claude', 'projects');
|
|
9
|
+
if (!fs.existsSync(projectsDir)) return [];
|
|
10
|
+
|
|
11
|
+
const imported = [];
|
|
12
|
+
const projects = fs.readdirSync(projectsDir);
|
|
13
|
+
|
|
14
|
+
for (const projectName of projects) {
|
|
15
|
+
const indexPath = path.join(projectsDir, projectName, 'sessions-index.json');
|
|
16
|
+
if (!fs.existsSync(indexPath)) continue;
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
|
|
20
|
+
const entries = index.entries || [];
|
|
21
|
+
|
|
22
|
+
for (const entry of entries) {
|
|
23
|
+
try {
|
|
24
|
+
const existing = queries.getConversationByExternalId('claude-code', entry.sessionId);
|
|
25
|
+
if (existing) continue;
|
|
26
|
+
|
|
27
|
+
const conversation = {
|
|
28
|
+
externalId: entry.sessionId,
|
|
29
|
+
agentType: 'claude-code',
|
|
30
|
+
title: entry.summary || entry.firstPrompt || `Conversation ${entry.sessionId.slice(0, 8)}`,
|
|
31
|
+
firstPrompt: entry.firstPrompt,
|
|
32
|
+
messageCount: entry.messageCount || 0,
|
|
33
|
+
created: new Date(entry.created).getTime(),
|
|
34
|
+
modified: new Date(entry.modified).getTime(),
|
|
35
|
+
projectPath: entry.projectPath,
|
|
36
|
+
gitBranch: entry.gitBranch,
|
|
37
|
+
sourcePath: entry.fullPath,
|
|
38
|
+
source: 'imported'
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
queries.createImportedConversation(conversation);
|
|
42
|
+
imported.push(conversation);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
console.error(`[Importer] Error importing session ${entry.sessionId}:`, err.message);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.error(`[Importer] Error reading ${indexPath}:`, err.message);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return imported;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static async importOpenCodeSessions() {
|
|
56
|
+
// TODO: Implement OpenCode session import once storage location is determined
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static async importAll() {
|
|
61
|
+
console.log('[Importer] Starting conversation import...');
|
|
62
|
+
const claudeCode = await this.importClaudeCodeSessions();
|
|
63
|
+
const openCode = await this.importOpenCodeSessions();
|
|
64
|
+
console.log(`[Importer] Imported ${claudeCode.length} Claude Code conversations`);
|
|
65
|
+
console.log(`[Importer] Imported ${openCode.length} OpenCode conversations`);
|
|
66
|
+
return { claudeCode, openCode };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default ConversationImporter;
|
package/database.js
CHANGED
|
@@ -30,6 +30,7 @@ try {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
function initSchema() {
|
|
33
|
+
// Create table with minimal schema - columns will be added by migration
|
|
33
34
|
db.exec(`
|
|
34
35
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
35
36
|
id TEXT PRIMARY KEY,
|
|
@@ -183,6 +184,45 @@ function migrateFromJson() {
|
|
|
183
184
|
initSchema();
|
|
184
185
|
migrateFromJson();
|
|
185
186
|
|
|
187
|
+
// Migration: Add imported conversation columns if they don't exist
|
|
188
|
+
try {
|
|
189
|
+
const result = db.prepare("PRAGMA table_info(conversations)").all();
|
|
190
|
+
const columnNames = result.map(r => r.name);
|
|
191
|
+
const requiredColumns = {
|
|
192
|
+
agentType: 'TEXT DEFAULT "claude-code"',
|
|
193
|
+
source: 'TEXT DEFAULT "gui"',
|
|
194
|
+
externalId: 'TEXT',
|
|
195
|
+
firstPrompt: 'TEXT',
|
|
196
|
+
messageCount: 'INTEGER DEFAULT 0',
|
|
197
|
+
projectPath: 'TEXT',
|
|
198
|
+
gitBranch: 'TEXT',
|
|
199
|
+
sourcePath: 'TEXT',
|
|
200
|
+
lastSyncedAt: 'INTEGER'
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
let addedColumns = false;
|
|
204
|
+
for (const [colName, colDef] of Object.entries(requiredColumns)) {
|
|
205
|
+
if (!columnNames.includes(colName)) {
|
|
206
|
+
db.exec(`ALTER TABLE conversations ADD COLUMN ${colName} ${colDef}`);
|
|
207
|
+
console.log(`[Migration] Added column ${colName} to conversations table`);
|
|
208
|
+
addedColumns = true;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Add indexes for new columns
|
|
213
|
+
if (addedColumns) {
|
|
214
|
+
try {
|
|
215
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_conversations_external ON conversations(externalId)`);
|
|
216
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_conversations_agent_type ON conversations(agentType)`);
|
|
217
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_conversations_source ON conversations(source)`);
|
|
218
|
+
} catch (e) {
|
|
219
|
+
console.warn('[Migration] Index creation warning:', e.message);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
} catch (err) {
|
|
223
|
+
console.error('[Migration] Error:', err.message);
|
|
224
|
+
}
|
|
225
|
+
|
|
186
226
|
function generateId(prefix) {
|
|
187
227
|
return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
188
228
|
}
|
|
@@ -660,6 +700,111 @@ export const queries = {
|
|
|
660
700
|
clearSessionStreamUpdates(sessionId) {
|
|
661
701
|
const stmt = db.prepare('DELETE FROM stream_updates WHERE sessionId = ?');
|
|
662
702
|
stmt.run(sessionId);
|
|
703
|
+
},
|
|
704
|
+
|
|
705
|
+
createImportedConversation(data) {
|
|
706
|
+
const id = generateId('conv');
|
|
707
|
+
const now = Date.now();
|
|
708
|
+
const stmt = db.prepare(
|
|
709
|
+
`INSERT INTO conversations (
|
|
710
|
+
id, agentId, title, created_at, updated_at, status,
|
|
711
|
+
agentType, source, externalId, firstPrompt, messageCount,
|
|
712
|
+
projectPath, gitBranch, sourcePath, lastSyncedAt
|
|
713
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
714
|
+
);
|
|
715
|
+
stmt.run(
|
|
716
|
+
id,
|
|
717
|
+
data.externalId || id,
|
|
718
|
+
data.title,
|
|
719
|
+
data.created || now,
|
|
720
|
+
data.modified || now,
|
|
721
|
+
'active',
|
|
722
|
+
data.agentType || 'claude-code',
|
|
723
|
+
data.source || 'imported',
|
|
724
|
+
data.externalId,
|
|
725
|
+
data.firstPrompt,
|
|
726
|
+
data.messageCount || 0,
|
|
727
|
+
data.projectPath,
|
|
728
|
+
data.gitBranch,
|
|
729
|
+
data.sourcePath,
|
|
730
|
+
now
|
|
731
|
+
);
|
|
732
|
+
return { id, ...data };
|
|
733
|
+
},
|
|
734
|
+
|
|
735
|
+
getConversationByExternalId(agentType, externalId) {
|
|
736
|
+
const stmt = db.prepare(
|
|
737
|
+
'SELECT * FROM conversations WHERE agentType = ? AND externalId = ?'
|
|
738
|
+
);
|
|
739
|
+
return stmt.get(agentType, externalId);
|
|
740
|
+
},
|
|
741
|
+
|
|
742
|
+
getConversationsByAgentType(agentType) {
|
|
743
|
+
const stmt = db.prepare(
|
|
744
|
+
'SELECT * FROM conversations WHERE agentType = ? AND status != ? ORDER BY updated_at DESC'
|
|
745
|
+
);
|
|
746
|
+
return stmt.all(agentType, 'deleted');
|
|
747
|
+
},
|
|
748
|
+
|
|
749
|
+
getImportedConversations() {
|
|
750
|
+
const stmt = db.prepare(
|
|
751
|
+
'SELECT * FROM conversations WHERE source = ? AND status != ? ORDER BY updated_at DESC'
|
|
752
|
+
);
|
|
753
|
+
return stmt.all('imported', 'deleted');
|
|
754
|
+
},
|
|
755
|
+
|
|
756
|
+
importClaudeCodeConversations() {
|
|
757
|
+
const projectsDir = path.join(os.homedir(), '.claude', 'projects');
|
|
758
|
+
if (!fs.existsSync(projectsDir)) return [];
|
|
759
|
+
|
|
760
|
+
const imported = [];
|
|
761
|
+
const projects = fs.readdirSync(projectsDir);
|
|
762
|
+
|
|
763
|
+
for (const projectName of projects) {
|
|
764
|
+
const indexPath = path.join(projectsDir, projectName, 'sessions-index.json');
|
|
765
|
+
if (!fs.existsSync(indexPath)) continue;
|
|
766
|
+
|
|
767
|
+
try {
|
|
768
|
+
const index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
|
|
769
|
+
const entries = index.entries || [];
|
|
770
|
+
|
|
771
|
+
for (const entry of entries) {
|
|
772
|
+
try {
|
|
773
|
+
const existing = this.getConversationByExternalId('claude-code', entry.sessionId);
|
|
774
|
+
if (existing) {
|
|
775
|
+
imported.push({ status: 'skipped', id: existing.id });
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
this.createImportedConversation({
|
|
780
|
+
externalId: entry.sessionId,
|
|
781
|
+
agentType: 'claude-code',
|
|
782
|
+
title: entry.summary || entry.firstPrompt || `Conversation ${entry.sessionId.slice(0, 8)}`,
|
|
783
|
+
firstPrompt: entry.firstPrompt,
|
|
784
|
+
messageCount: entry.messageCount || 0,
|
|
785
|
+
created: new Date(entry.created).getTime(),
|
|
786
|
+
modified: new Date(entry.modified).getTime(),
|
|
787
|
+
projectPath: entry.projectPath,
|
|
788
|
+
gitBranch: entry.gitBranch,
|
|
789
|
+
sourcePath: entry.fullPath,
|
|
790
|
+
source: 'imported'
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
imported.push({
|
|
794
|
+
status: 'imported',
|
|
795
|
+
id: entry.sessionId,
|
|
796
|
+
title: entry.summary || entry.firstPrompt
|
|
797
|
+
});
|
|
798
|
+
} catch (err) {
|
|
799
|
+
console.error(`[DB] Error importing session ${entry.sessionId}:`, err.message);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
} catch (err) {
|
|
803
|
+
console.error(`[DB] Error reading ${indexPath}:`, err.message);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
return imported;
|
|
663
808
|
}
|
|
664
809
|
};
|
|
665
810
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentgui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.47",
|
|
4
4
|
"description": "Multi-agent ACP client with real-time communication",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "server.js",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"dev": "node server.js --watch"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
+
"@anthropic-ai/claude-code": "^1.0.128",
|
|
24
25
|
"better-sqlite3": "^12.6.2",
|
|
25
|
-
"claude-code-acp": "^1.0.0",
|
|
26
26
|
"ws": "^8.14.2"
|
|
27
27
|
}
|
|
28
28
|
}
|