Skip to content

Commit a8fed47

Browse files
committed
fix: address remaining CodeRabbit and Devin review feedback
- doctor.ts: Use getAdapter() per AgentType instead of getAllAdapters() spread (which destroys prototype methods like isDetected) - doctor.ts: Use getGlobalSkillsDir() from AGENT_CONFIG instead of hardcoded path formula - session-explainer.ts: Defensively default state.history and state.decisions to empty arrays - session-explainer.ts: Use loadConfig().agent with skillSource fallback instead of always using skillSource as agent name - observation-store.ts: Add static readAll() that reads observations without sessionId mismatch clearing - session.ts: Use ObservationStore.readAll() for snapshot save to avoid empty observations due to sessionId mismatch
1 parent 097af03 commit a8fed47

File tree

4 files changed

+42
-16
lines changed

4 files changed

+42
-16
lines changed

packages/cli/src/commands/doctor.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { execFileSync } from 'node:child_process';
33
import { existsSync, lstatSync, readlinkSync, readdirSync, mkdirSync, unlinkSync } from 'node:fs';
44
import { resolve, join } from 'node:path';
55
import { homedir } from 'node:os';
6-
import { detectAgent, getAllAdapters, getAdapter } from '@skillkit/agents';
7-
import type { AgentType } from '@skillkit/core';
8-
import { findAllSkills, validateSkill, loadConfig, getProjectConfigPath } from '@skillkit/core';
6+
import { detectAgent, getAdapter } from '@skillkit/agents';
7+
import { AgentType, findAllSkills, validateSkill, loadConfig, getProjectConfigPath, getGlobalSkillsDir } from '@skillkit/core';
8+
import type { AgentType as AgentTypeT } from '@skillkit/core';
99
import { getSearchDirs } from '../helpers.js';
1010
import { colors, symbols } from '../onboarding/index.js';
1111

@@ -82,7 +82,7 @@ export class DoctorCommand extends Command {
8282
}
8383

8484
// --- Agent Detection ---
85-
let detectedAgent: AgentType = 'universal';
85+
let detectedAgent: AgentTypeT = 'universal';
8686
try {
8787
detectedAgent = await detectAgent();
8888
results.push({ name: 'Detected agent', status: 'pass', message: `Detected: ${detectedAgent}` });
@@ -92,12 +92,12 @@ export class DoctorCommand extends Command {
9292

9393
const otherDetected: string[] = [];
9494
try {
95-
const allAdapters = getAllAdapters();
96-
for (const adapter of allAdapters) {
97-
if (adapter.agentType === detectedAgent || adapter.agentType === 'universal') continue;
95+
for (const agentType of AgentType.options) {
96+
if (agentType === detectedAgent || agentType === 'universal') continue;
9897
try {
99-
if (await adapter.isDetected()) {
100-
otherDetected.push(adapter.agentType);
98+
const agentAdapter = getAdapter(agentType);
99+
if (await agentAdapter.isDetected()) {
100+
otherDetected.push(agentType);
101101
}
102102
} catch {
103103
// skip
@@ -132,8 +132,9 @@ export class DoctorCommand extends Command {
132132
}
133133
}
134134

135-
const globalSkillsDir = join(homedir(), `.${detectedAgent === 'claude-code' ? 'claude' : detectedAgent}`, 'skills');
136-
if (existsSync(globalSkillsDir)) {
135+
const globalSkillsDirRaw = getGlobalSkillsDir(detectedAgent);
136+
const globalSkillsDir = globalSkillsDirRaw ? globalSkillsDirRaw.replace(/^~/, homedir()) : null;
137+
if (globalSkillsDir && existsSync(globalSkillsDir)) {
137138
const entries = readdirSync(globalSkillsDir).filter(e => !e.startsWith('.'));
138139
results.push({ name: 'Global skills dir', status: 'pass', message: `${globalSkillsDir} (${entries.length} entries)` });
139140
} else {

packages/cli/src/commands/session.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ export class SessionSnapshotSaveCommand extends Command {
360360

361361
let observations: SessionSnapshot['observations'] = [];
362362
try {
363-
const raw = new ObservationStore(projectPath).getAll();
363+
const raw = ObservationStore.readAll(projectPath);
364364
observations = raw.map((o) => ({
365365
id: o.id,
366366
timestamp: o.timestamp,

packages/core/src/memory/observation-store.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,18 @@ export class ObservationStore {
181181
return this.load().observations;
182182
}
183183

184+
static readAll(projectPath: string): Observation[] {
185+
const filePath = join(projectPath, '.skillkit', 'memory', 'observations.yaml');
186+
if (!existsSync(filePath)) return [];
187+
try {
188+
const content = readFileSync(filePath, 'utf-8');
189+
const data = parseYaml(content) as ObservationStoreData;
190+
return data?.observations ?? [];
191+
} catch {
192+
return [];
193+
}
194+
}
195+
184196
getByType(type: ObservationType): Observation[] {
185197
return this.load().observations.filter((o) => o.type === type);
186198
}

packages/core/src/session/session-explainer.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { SessionExplanation } from './types.js';
22
import { SessionManager } from './manager.js';
33
import { ObservationStore } from '../memory/observation-store.js';
44
import { getGitCommits } from '../learning/git-analyzer.js';
5+
import { loadConfig } from '../config.js';
56

67
function formatDuration(ms: number): string {
78
const seconds = Math.floor(ms / 1000);
@@ -46,9 +47,21 @@ export class SessionExplainer {
4647
return explanation;
4748
}
4849

50+
try {
51+
const configAgent = loadConfig().agent;
52+
if (configAgent && configAgent !== 'universal') {
53+
explanation.agent = configAgent;
54+
} else if (state.currentExecution?.skillSource) {
55+
explanation.agent = state.currentExecution.skillSource;
56+
}
57+
} catch {
58+
if (state.currentExecution?.skillSource) {
59+
explanation.agent = state.currentExecution.skillSource;
60+
}
61+
}
62+
4963
if (state.currentExecution) {
5064
const exec = state.currentExecution;
51-
explanation.agent = exec.skillSource || 'unknown';
5265

5366
const startTime = new Date(exec.startedAt).getTime();
5467
explanation.duration = formatDuration(Date.now() - startTime);
@@ -79,7 +92,7 @@ export class SessionExplainer {
7992
}
8093
}
8194

82-
for (const hist of state.history) {
95+
for (const hist of state.history ?? []) {
8396
const alreadyListed = explanation.skillsUsed.some(
8497
(s) => s.name === hist.skillName
8598
);
@@ -96,10 +109,10 @@ export class SessionExplainer {
96109

97110
explanation.filesModified = [...new Set(explanation.filesModified)];
98111

99-
explanation.decisions = state.decisions.map(({ key, value }) => ({ key, value }));
112+
explanation.decisions = (state.decisions ?? []).map(({ key, value }) => ({ key, value }));
100113

101114
try {
102-
const observations = new ObservationStore(this.projectPath).getAll();
115+
const observations = ObservationStore.readAll(this.projectPath);
103116
const countByType = (type: string) => observations.filter((o) => o.type === type).length;
104117
explanation.observationCounts = {
105118
total: observations.length,

0 commit comments

Comments
 (0)