Skip to content

Commit e460a76

Browse files
committed
Fixing linting issues, unit tests, and integration tests.
1 parent dd39920 commit e460a76

29 files changed

Lines changed: 639 additions & 528 deletions

.husky/pre-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
npm run format:check && npm run lint && npm run build && npm run test:unit
1+
npm run format:check && npm run lint && npm run build && npm run test

src/agents/DeveloperAgent.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ export class DeveloperAgent {
7171
// Optional: Git Commit
7272
if (this.git) {
7373
try {
74+
this.host.log('debug', `[DEBUG DeveloperAgent] Attempting git commit in ${this.project.paths.root}`);
7475
this.git.add('.');
7576
this.git.commit(`[nexical] Completed task: ${task.id} - ${task.message}`);
7677
} catch (e) {
77-
this.host.log('warn', `Git commit failed for task ${task.id}: ${e instanceof Error ? e.message : String(e)}`);
78+
this.host.log('warn', `Git commit failed for task ${task.id}: ${(e as Error).message}`);
7879
// We don't fail the whole workflow just because git failed
7980
}
8081
}

src/agents/PlannerAgent.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,10 @@ export class PlannerAgent {
6767
try {
6868
const plan = Plan.fromYaml(planStr);
6969
await this.workspace.savePlan(plan);
70-
} catch (e: any) {
71-
this.host.log('error', `Failed to parse plan YAML: ${e.message}\nContent: ${planStr}`);
72-
throw e;
70+
} catch (e) {
71+
const error = e instanceof Error ? e : new Error(String(e));
72+
this.host.log('error', `Failed to parse plan YAML: ${error.message}\nContent: ${planStr}`);
73+
throw error;
7374
}
7475

7576
// Reload plan

src/domain/Plan.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ export class Plan {
3232
static fromYaml(yamlString: string): Plan {
3333
const data = yaml.load(yamlString);
3434
const validated = PlanSchema.parse(data);
35-
const tasks = validated.tasks.map((t: unknown) => Task.fromData(t));
36-
return new Plan(validated.plan_name, tasks);
35+
return new Plan(
36+
validated.plan_name,
37+
validated.tasks.map((t: unknown) => Task.fromData(t)),
38+
);
3739
}
3840
}

src/domain/Project.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export class Project implements IProject {
8484
}
8585

8686
class ProjectPaths {
87+
public readonly root: string;
8788
public readonly ai: string;
8889
public readonly config: string;
8990
public readonly state: string;
@@ -109,6 +110,7 @@ class ProjectPaths {
109110
public readonly archive: string;
110111

111112
constructor(root: string) {
113+
this.root = root;
112114
this.ai = path.join(root, '.ai');
113115
this.config = path.join(this.ai, 'config.yml');
114116
this.state = path.join(this.ai, 'state.yml');

src/domain/State.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export class EngineState {
2626
public user_prompt: string = '';
2727
public interactive: boolean = false;
2828
public context: Record<string, unknown> = {};
29+
public error?: string;
2930

3031
constructor(session_id: string) {
3132
this.session_id = session_id;
@@ -105,6 +106,7 @@ export class EngineState {
105106
state.user_prompt = (data.user_prompt as string) || '';
106107
state.interactive = (data.interactive as boolean) || false;
107108
state.context = (data.context as Record<string, unknown>) || {};
109+
state.error = data.error as string | undefined;
108110

109111
return state;
110112
}

src/services/GitService.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ export class GitService {
1212
}
1313

1414
runCommand(args: string[], cwd?: string): string {
15+
const finalCwd = cwd || this.rootDirectory;
16+
this.host.log('debug', `[DEBUG GitService] Executing: git ${args.join(' ')} in ${finalCwd}`);
1517
const result = this.shell.executeSync('git', args, {
16-
cwd: cwd || this.rootDirectory,
18+
cwd: finalCwd,
1719
});
1820

1921
if (result.code !== 0) {

src/services/SkillRunner.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,28 @@ export class SkillRunner implements ISkillRunner {
7979
continue;
8080
}
8181

82-
if (!(await driver.validateSkill(skill))) {
83-
errors.push(`Skill '${name}' failed validation for driver '${driver.name}'.`);
82+
// Start of the change
83+
if (driver) {
84+
const valid = await driver.validateSkill(skill);
85+
this.host.log('debug', `[DEBUG SkillRunner] Validating ${skill.name} with ${driver.name}: ${valid}`);
86+
if (!valid) {
87+
errors.push(
88+
`Skill '${name}' failed validation for driver '${driver.name}': Driver reported incompatibility.`,
89+
);
90+
}
91+
} else {
92+
this.host.log('debug', `[DEBUG SkillRunner] No driver found for provider ${skill.provider}`);
8493
}
94+
// End of the change
8595
} catch (_e) {
8696
errors.push(`Error validating skill '${name}': ${(_e as Error).message}`);
8797
}
8898
}
8999

90100
if (errors.length > 0) {
91-
throw new Error(`Skill validation failed:\n${errors.map((e) => `- ${e}`).join('\n')}`);
101+
const msg = `Skill validation failed:\n${errors.map((e) => `- ${e}`).join('\n')}`;
102+
this.host.log('error', `[DEBUG SkillRunner] Throwing: ${msg}`);
103+
throw new Error(msg);
92104
}
93105

94106
this.host.log('debug', `Validated ${Object.keys(this.skills).length} skills successfully.`);

src/workflow/Workflow.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export class Workflow {
112112
if (signal.type === SignalType.FAIL) {
113113
this.host.log('error', `Workflow Failed: ${signal.reason}`);
114114
state.updateStatus('FAILED');
115+
state.error = signal.reason;
115116
await this.workspace.saveState(state);
116117
break;
117118
}

src/workflow/states/ExecutingState.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { EngineState } from '../../domain/State.js';
22
import { SignalDetectedError } from '../../errors/SignalDetectedError.js';
3-
import { Signal } from '../Signal.js';
3+
import { Signal, SignalType } from '../Signal.js';
44
import { State } from './State.js';
55

66
export class ExecutingState extends State {
@@ -17,6 +17,29 @@ export class ExecutingState extends State {
1717
if (error instanceof SignalDetectedError) {
1818
return error.signal;
1919
}
20+
21+
// Fallback for cases where instanceof might fail (ESM/Jest quirks)
22+
const errObj = error as Record<string, unknown>;
23+
24+
if (errObj && typeof errObj === 'object') {
25+
if (errObj.code === 'SIGNAL_DETECTED' && errObj.signal) {
26+
return errObj.signal as Signal;
27+
}
28+
}
29+
30+
const metadata = (errObj?.metadata || {}) as Record<string, unknown>;
31+
const rawSignal = (errObj?.signal || metadata.signal) as Record<string, unknown> | undefined;
32+
33+
if (errObj && typeof errObj === 'object' && (errObj.code === 'SIGNAL_DETECTED' || rawSignal)) {
34+
if (rawSignal && typeof rawSignal.type === 'string') {
35+
return new Signal(
36+
rawSignal.type as SignalType,
37+
(rawSignal.reason as string) || '',
38+
(rawSignal.metadata as Record<string, unknown>) || {},
39+
);
40+
}
41+
return Signal.fail('Signal detected but missing signal object or type');
42+
}
2043
return Signal.fail(`Execution failed: ${(error as Error).message}`);
2144
}
2245
}

0 commit comments

Comments
 (0)