@adhdev/daemon-core 0.8.98 → 0.8.100
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/chat-history.d.ts +1 -0
- package/dist/index.js +253 -43
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +253 -43
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +1 -1
- package/node_modules/@adhdev/session-host-core/dist/defaults.d.mts +1 -1
- package/node_modules/@adhdev/session-host-core/dist/defaults.d.ts +1 -1
- package/node_modules/@adhdev/session-host-core/dist/defaults.js +1 -1
- package/node_modules/@adhdev/session-host-core/dist/defaults.js.map +1 -1
- package/node_modules/@adhdev/session-host-core/dist/defaults.mjs +1 -1
- package/node_modules/@adhdev/session-host-core/dist/defaults.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/dist/index.js +1 -1
- package/node_modules/@adhdev/session-host-core/dist/index.js.map +1 -1
- package/node_modules/@adhdev/session-host-core/dist/index.mjs +1 -1
- package/node_modules/@adhdev/session-host-core/dist/index.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/chat/subscription-updates.ts +6 -2
- package/src/config/chat-history.ts +207 -14
- package/src/providers/cli-provider-instance.ts +54 -27
- package/src/providers/provider-session-id.ts +4 -0
|
@@ -1295,9 +1295,17 @@ function extractCanonicalHermesMessageTimestamp(message: Record<string, unknown>
|
|
|
1295
1295
|
return fallbackTs;
|
|
1296
1296
|
}
|
|
1297
1297
|
|
|
1298
|
-
function
|
|
1298
|
+
function extractTimestampValue(value: unknown): number {
|
|
1299
|
+
const numericTimestamp = Number(value || 0);
|
|
1300
|
+
if (Number.isFinite(numericTimestamp) && numericTimestamp > 0) return numericTimestamp;
|
|
1301
|
+
const stringTimestamp = typeof value === 'string' ? Date.parse(value) : NaN;
|
|
1302
|
+
if (Number.isFinite(stringTimestamp) && stringTimestamp > 0) return stringTimestamp;
|
|
1303
|
+
return 0;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
function readExistingSessionStartRecord(agentType: string, historySessionId: string): HistoryMessage | null {
|
|
1299
1307
|
try {
|
|
1300
|
-
const dir = path.join(HISTORY_DIR,
|
|
1308
|
+
const dir = path.join(HISTORY_DIR, agentType);
|
|
1301
1309
|
if (!fs.existsSync(dir)) return null;
|
|
1302
1310
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
1303
1311
|
for (const file of files) {
|
|
@@ -1320,6 +1328,28 @@ function readExistingHermesSessionStartRecord(historySessionId: string): History
|
|
|
1320
1328
|
}
|
|
1321
1329
|
}
|
|
1322
1330
|
|
|
1331
|
+
function rewriteCanonicalSavedHistory(agentType: string, historySessionId: string, records: HistoryMessage[]): boolean {
|
|
1332
|
+
if (records.length === 0) return false;
|
|
1333
|
+
try {
|
|
1334
|
+
const dir = path.join(HISTORY_DIR, agentType);
|
|
1335
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
1336
|
+
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, '_')}_`;
|
|
1337
|
+
for (const file of fs.readdirSync(dir)) {
|
|
1338
|
+
if (file.startsWith(prefix) && file.endsWith('.jsonl')) {
|
|
1339
|
+
fs.unlinkSync(path.join(dir, file));
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
1343
|
+
const filePath = path.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
1344
|
+
fs.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join('\n')}\n`, 'utf-8');
|
|
1345
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
1346
|
+
savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, '_'));
|
|
1347
|
+
return true;
|
|
1348
|
+
} catch {
|
|
1349
|
+
return false;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1323
1353
|
export function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId: string): boolean {
|
|
1324
1354
|
const normalizedSessionId = normalizeSavedHistorySessionId('hermes-cli', historySessionId);
|
|
1325
1355
|
if (!normalizedSessionId) return false;
|
|
@@ -1335,7 +1365,7 @@ export function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId:
|
|
|
1335
1365
|
const canonicalMessages = Array.isArray(raw.messages) ? raw.messages : [];
|
|
1336
1366
|
const dir = path.join(HISTORY_DIR, 'hermes-cli');
|
|
1337
1367
|
fs.mkdirSync(dir, { recursive: true });
|
|
1338
|
-
const existingSessionStart =
|
|
1368
|
+
const existingSessionStart = readExistingSessionStartRecord('hermes-cli', normalizedSessionId);
|
|
1339
1369
|
const records: HistoryMessage[] = [];
|
|
1340
1370
|
if (existingSessionStart) {
|
|
1341
1371
|
records.push({
|
|
@@ -1392,21 +1422,184 @@ export function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId:
|
|
|
1392
1422
|
}
|
|
1393
1423
|
}
|
|
1394
1424
|
|
|
1395
|
-
|
|
1425
|
+
return rewriteCanonicalSavedHistory('hermes-cli', normalizedSessionId, records);
|
|
1426
|
+
} catch {
|
|
1427
|
+
return false;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1396
1430
|
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1431
|
+
function resolveClaudeProjectTranscriptPath(historySessionId: string, workspace?: string): string | null {
|
|
1432
|
+
const claudeProjectsDir = path.join(os.homedir(), '.claude', 'projects');
|
|
1433
|
+
if (!fs.existsSync(claudeProjectsDir)) return null;
|
|
1434
|
+
const normalizedWorkspace = typeof workspace === 'string' ? workspace.trim() : '';
|
|
1435
|
+
if (normalizedWorkspace) {
|
|
1436
|
+
const directPath = path.join(claudeProjectsDir, normalizedWorkspace.replace(/[\\/]/g, '-'), `${historySessionId}.jsonl`);
|
|
1437
|
+
if (fs.existsSync(directPath)) return directPath;
|
|
1438
|
+
}
|
|
1439
|
+
const stack = [claudeProjectsDir];
|
|
1440
|
+
while (stack.length > 0) {
|
|
1441
|
+
const current = stack.pop();
|
|
1442
|
+
if (!current) continue;
|
|
1443
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
1444
|
+
const entryPath = path.join(current, entry.name);
|
|
1445
|
+
if (entry.isDirectory()) {
|
|
1446
|
+
stack.push(entryPath);
|
|
1447
|
+
continue;
|
|
1448
|
+
}
|
|
1449
|
+
if (entry.isFile() && entry.name === `${historySessionId}.jsonl`) {
|
|
1450
|
+
return entryPath;
|
|
1401
1451
|
}
|
|
1402
1452
|
}
|
|
1453
|
+
}
|
|
1454
|
+
return null;
|
|
1455
|
+
}
|
|
1403
1456
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1457
|
+
function extractClaudeAssistantContentParts(content: unknown): Array<{ content: string; kind: 'standard' | 'tool'; senderName?: string; role?: 'assistant' }> {
|
|
1458
|
+
if (typeof content === 'string') {
|
|
1459
|
+
const trimmed = content.trim();
|
|
1460
|
+
return trimmed ? [{ content: trimmed, kind: 'standard', role: 'assistant' }] : [];
|
|
1461
|
+
}
|
|
1462
|
+
if (!Array.isArray(content)) return [];
|
|
1463
|
+
const parts: Array<{ content: string; kind: 'standard' | 'tool'; senderName?: string; role?: 'assistant' }> = [];
|
|
1464
|
+
for (const block of content) {
|
|
1465
|
+
if (!block || typeof block !== 'object') continue;
|
|
1466
|
+
const record = block as Record<string, unknown>;
|
|
1467
|
+
const type = String(record.type || '').trim();
|
|
1468
|
+
if (type === 'text') {
|
|
1469
|
+
const text = String(record.text || '').trim();
|
|
1470
|
+
if (text) parts.push({ content: text, kind: 'standard', role: 'assistant' });
|
|
1471
|
+
continue;
|
|
1472
|
+
}
|
|
1473
|
+
if (type === 'tool_use') {
|
|
1474
|
+
const name = String(record.name || '').trim() || 'Tool';
|
|
1475
|
+
const input = record.input && typeof record.input === 'object'
|
|
1476
|
+
? record.input as Record<string, unknown>
|
|
1477
|
+
: null;
|
|
1478
|
+
const command = input ? String(input.command || '').trim() : '';
|
|
1479
|
+
const summary = command ? `${name}: ${command}` : name;
|
|
1480
|
+
if (summary) parts.push({ content: summary, kind: 'tool', senderName: 'Tool', role: 'assistant' });
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
return parts;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
function extractClaudeUserContentParts(content: unknown): Array<{ role: 'user' | 'assistant'; content: string; kind: 'standard' | 'tool'; senderName?: string }> {
|
|
1487
|
+
if (typeof content === 'string') {
|
|
1488
|
+
const trimmed = content.trim();
|
|
1489
|
+
return trimmed ? [{ role: 'user', content: trimmed, kind: 'standard' }] : [];
|
|
1490
|
+
}
|
|
1491
|
+
if (!Array.isArray(content)) return [];
|
|
1492
|
+
const parts: Array<{ role: 'user' | 'assistant'; content: string; kind: 'standard' | 'tool'; senderName?: string }> = [];
|
|
1493
|
+
for (const block of content) {
|
|
1494
|
+
if (!block || typeof block !== 'object') continue;
|
|
1495
|
+
const record = block as Record<string, unknown>;
|
|
1496
|
+
const type = String(record.type || '').trim();
|
|
1497
|
+
if (type === 'text') {
|
|
1498
|
+
const text = String(record.text || '').trim();
|
|
1499
|
+
if (text) parts.push({ role: 'user', content: text, kind: 'standard' });
|
|
1500
|
+
continue;
|
|
1501
|
+
}
|
|
1502
|
+
if (type === 'tool_result') {
|
|
1503
|
+
const rawContent = record.content;
|
|
1504
|
+
const text = typeof rawContent === 'string'
|
|
1505
|
+
? rawContent.trim()
|
|
1506
|
+
: Array.isArray(rawContent)
|
|
1507
|
+
? rawContent
|
|
1508
|
+
.map((entry) => {
|
|
1509
|
+
if (typeof entry === 'string') return entry.trim();
|
|
1510
|
+
if (!entry || typeof entry !== 'object') return '';
|
|
1511
|
+
const nested = entry as Record<string, unknown>;
|
|
1512
|
+
if (typeof nested.text === 'string') return nested.text.trim();
|
|
1513
|
+
if (typeof nested.content === 'string') return nested.content.trim();
|
|
1514
|
+
return '';
|
|
1515
|
+
})
|
|
1516
|
+
.filter(Boolean)
|
|
1517
|
+
.join('\n')
|
|
1518
|
+
: '';
|
|
1519
|
+
if (text) parts.push({ role: 'assistant', content: text, kind: 'tool', senderName: 'Tool' });
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
return parts;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
export function rebuildClaudeSavedHistoryFromNativeProject(historySessionId: string, workspace?: string): boolean {
|
|
1526
|
+
const normalizedSessionId = normalizeSavedHistorySessionId('claude-cli', historySessionId);
|
|
1527
|
+
if (!normalizedSessionId) return false;
|
|
1528
|
+
|
|
1529
|
+
try {
|
|
1530
|
+
const transcriptPath = resolveClaudeProjectTranscriptPath(normalizedSessionId, workspace);
|
|
1531
|
+
if (!transcriptPath) return false;
|
|
1532
|
+
const lines = fs.readFileSync(transcriptPath, 'utf-8').split('\n').filter(Boolean);
|
|
1533
|
+
const records: HistoryMessage[] = [];
|
|
1534
|
+
const existingSessionStart = readExistingSessionStartRecord('claude-cli', normalizedSessionId);
|
|
1535
|
+
if (existingSessionStart) {
|
|
1536
|
+
records.push({
|
|
1537
|
+
...existingSessionStart,
|
|
1538
|
+
historySessionId: normalizedSessionId,
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
let fallbackTs = Date.now();
|
|
1542
|
+
for (const line of lines) {
|
|
1543
|
+
let parsed: Record<string, unknown> | null = null;
|
|
1544
|
+
try {
|
|
1545
|
+
parsed = JSON.parse(line) as Record<string, unknown>;
|
|
1546
|
+
} catch {
|
|
1547
|
+
parsed = null;
|
|
1548
|
+
}
|
|
1549
|
+
if (!parsed) continue;
|
|
1550
|
+
const parsedSessionId = String(parsed.sessionId || '').trim();
|
|
1551
|
+
if (parsedSessionId && parsedSessionId !== normalizedSessionId) continue;
|
|
1552
|
+
const receivedAt = extractTimestampValue(parsed.timestamp) || fallbackTs;
|
|
1553
|
+
fallbackTs = receivedAt + 1;
|
|
1554
|
+
const parsedWorkspace = String(parsed.cwd || workspace || '').trim();
|
|
1555
|
+
if (records.length === 0 && parsedWorkspace) {
|
|
1556
|
+
records.push({
|
|
1557
|
+
ts: new Date(receivedAt).toISOString(),
|
|
1558
|
+
receivedAt,
|
|
1559
|
+
role: 'system',
|
|
1560
|
+
kind: 'session_start',
|
|
1561
|
+
content: parsedWorkspace,
|
|
1562
|
+
agent: 'claude-cli',
|
|
1563
|
+
historySessionId: normalizedSessionId,
|
|
1564
|
+
workspace: parsedWorkspace,
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
const type = String(parsed.type || '').trim();
|
|
1568
|
+
const message = parsed.message && typeof parsed.message === 'object'
|
|
1569
|
+
? parsed.message as Record<string, unknown>
|
|
1570
|
+
: null;
|
|
1571
|
+
if (type === 'user' && message) {
|
|
1572
|
+
for (const part of extractClaudeUserContentParts(message.content)) {
|
|
1573
|
+
records.push({
|
|
1574
|
+
ts: new Date(receivedAt).toISOString(),
|
|
1575
|
+
receivedAt,
|
|
1576
|
+
role: part.role,
|
|
1577
|
+
content: part.content,
|
|
1578
|
+
kind: part.kind,
|
|
1579
|
+
senderName: part.senderName,
|
|
1580
|
+
agent: 'claude-cli',
|
|
1581
|
+
historySessionId: normalizedSessionId,
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1584
|
+
continue;
|
|
1585
|
+
}
|
|
1586
|
+
if (type === 'assistant' && message) {
|
|
1587
|
+
for (const part of extractClaudeAssistantContentParts(message.content)) {
|
|
1588
|
+
records.push({
|
|
1589
|
+
ts: new Date(receivedAt).toISOString(),
|
|
1590
|
+
receivedAt,
|
|
1591
|
+
role: 'assistant',
|
|
1592
|
+
content: part.content,
|
|
1593
|
+
kind: part.kind,
|
|
1594
|
+
senderName: part.senderName,
|
|
1595
|
+
agent: 'claude-cli',
|
|
1596
|
+
historySessionId: normalizedSessionId,
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
return rewriteCanonicalSavedHistory('claude-cli', normalizedSessionId, records);
|
|
1410
1603
|
} catch {
|
|
1411
1604
|
return false;
|
|
1412
1605
|
}
|
|
@@ -17,7 +17,7 @@ import { ProviderCliAdapter } from '../cli-adapters/provider-cli-adapter.js';
|
|
|
17
17
|
import type { CliProviderModule } from '../cli-adapters/provider-cli-adapter.js';
|
|
18
18
|
import type { PtyRuntimeMetadata, PtyTransportFactory } from '../cli-adapters/pty-transport.js';
|
|
19
19
|
import { StatusMonitor } from './status-monitor.js';
|
|
20
|
-
import { ChatHistoryWriter, readChatHistory, rebuildHermesSavedHistoryFromCanonicalSession } from '../config/chat-history.js';
|
|
20
|
+
import { ChatHistoryWriter, readChatHistory, rebuildClaudeSavedHistoryFromNativeProject, rebuildHermesSavedHistoryFromCanonicalSession } from '../config/chat-history.js';
|
|
21
21
|
import { LOG } from '../logging/logger.js';
|
|
22
22
|
import type { ChatMessage } from '../types.js';
|
|
23
23
|
import { buildPersistedProviderEffectMessage, normalizeProviderEffects } from './control-effects.js';
|
|
@@ -377,7 +377,7 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
377
377
|
: [];
|
|
378
378
|
}
|
|
379
379
|
const mergedMessages = this.mergeConversationMessages(parsedMessages);
|
|
380
|
-
const
|
|
380
|
+
const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
|
|
381
381
|
|
|
382
382
|
const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
|
|
383
383
|
|
|
@@ -400,7 +400,7 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
400
400
|
senderName: typeof message.senderName === 'string' ? message.senderName : undefined,
|
|
401
401
|
receivedAt: typeof message.receivedAt === 'number' ? message.receivedAt : message.timestamp,
|
|
402
402
|
}));
|
|
403
|
-
if (!
|
|
403
|
+
if (!canonicalBackedHistory && !shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
|
|
404
404
|
const incrementalMessages = buildIncrementalHistoryAppendMessages(this.lastPersistedHistoryMessages, normalizedMessagesToSave);
|
|
405
405
|
this.historyWriter.appendNewMessages(
|
|
406
406
|
this.type,
|
|
@@ -410,7 +410,7 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
410
410
|
this.providerSessionId,
|
|
411
411
|
);
|
|
412
412
|
}
|
|
413
|
-
if (!
|
|
413
|
+
if (!canonicalBackedHistory) {
|
|
414
414
|
this.lastPersistedHistoryMessages = normalizedMessagesToSave;
|
|
415
415
|
}
|
|
416
416
|
}
|
|
@@ -807,7 +807,14 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
807
807
|
get cliName(): string { return this.provider.name; }
|
|
808
808
|
|
|
809
809
|
private shouldAutoApprove(): boolean {
|
|
810
|
-
|
|
810
|
+
if (typeof this.settings.autoApprove === 'boolean') {
|
|
811
|
+
return this.settings.autoApprove;
|
|
812
|
+
}
|
|
813
|
+
const providerDefault = this.provider.settings?.autoApprove?.default;
|
|
814
|
+
if (typeof providerDefault === 'boolean') {
|
|
815
|
+
return providerDefault;
|
|
816
|
+
}
|
|
817
|
+
return false;
|
|
811
818
|
}
|
|
812
819
|
|
|
813
820
|
private recordAutoApproval(modalMessage?: string, buttonLabel?: string, now = Date.now()): void {
|
|
@@ -951,33 +958,53 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
951
958
|
LOG.info('CLI', `[${this.type}] discovered provider session id: ${nextSessionId}`);
|
|
952
959
|
}
|
|
953
960
|
|
|
954
|
-
private
|
|
955
|
-
if (
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
961
|
+
private syncCanonicalSavedHistoryIfNeeded(): boolean {
|
|
962
|
+
if (!this.providerSessionId) return false;
|
|
963
|
+
if (this.type === 'hermes-cli') {
|
|
964
|
+
try {
|
|
965
|
+
const canonicalPath = path.join(os.homedir(), '.hermes', 'sessions', `session_${this.providerSessionId}.json`);
|
|
966
|
+
if (!fs.existsSync(canonicalPath)) return false;
|
|
967
|
+
const stat = fs.statSync(canonicalPath);
|
|
968
|
+
if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
|
|
969
|
+
const rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
|
|
970
|
+
if (!rebuilt) return false;
|
|
971
|
+
this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
|
|
972
|
+
const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
|
|
973
|
+
this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
|
|
974
|
+
role: message.role,
|
|
975
|
+
content: message.content,
|
|
976
|
+
kind: message.kind,
|
|
977
|
+
senderName: message.senderName,
|
|
978
|
+
receivedAt: message.receivedAt,
|
|
979
|
+
}));
|
|
980
|
+
return true;
|
|
981
|
+
} catch {
|
|
982
|
+
return false;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
if (this.type === 'claude-cli') {
|
|
986
|
+
try {
|
|
987
|
+
const rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
|
|
988
|
+
if (!rebuilt) return false;
|
|
989
|
+
const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
|
|
990
|
+
this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
|
|
991
|
+
role: message.role,
|
|
992
|
+
content: message.content,
|
|
993
|
+
kind: message.kind,
|
|
994
|
+
senderName: message.senderName,
|
|
995
|
+
receivedAt: message.receivedAt,
|
|
996
|
+
}));
|
|
997
|
+
return true;
|
|
998
|
+
} catch {
|
|
999
|
+
return false;
|
|
1000
|
+
}
|
|
975
1001
|
}
|
|
1002
|
+
return false;
|
|
976
1003
|
}
|
|
977
1004
|
|
|
978
1005
|
private restorePersistedHistoryFromCurrentSession(): void {
|
|
979
1006
|
if (!this.providerSessionId) return;
|
|
980
|
-
this.
|
|
1007
|
+
this.syncCanonicalSavedHistoryIfNeeded();
|
|
981
1008
|
this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
|
|
982
1009
|
const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
|
|
983
1010
|
this.historyWriter.seedSessionHistory(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const HERMES_SESSION_ID_RE = /^\d{8}_\d{6}_[a-z0-9]+$/i
|
|
2
|
+
const CLAUDE_SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
2
3
|
|
|
3
4
|
export function normalizeProviderSessionId(providerType: string | undefined, providerSessionId: string | null | undefined): string {
|
|
4
5
|
const normalizedProviderType = typeof providerType === 'string' ? providerType.trim() : ''
|
|
@@ -11,6 +12,9 @@ export function normalizeProviderSessionId(providerType: string | undefined, pro
|
|
|
11
12
|
if (normalizedProviderType === 'hermes-cli' && !HERMES_SESSION_ID_RE.test(normalizedId)) {
|
|
12
13
|
return ''
|
|
13
14
|
}
|
|
15
|
+
if (normalizedProviderType === 'claude-cli' && !CLAUDE_SESSION_ID_RE.test(normalizedId)) {
|
|
16
|
+
return ''
|
|
17
|
+
}
|
|
14
18
|
|
|
15
19
|
return normalizedId
|
|
16
20
|
}
|