@shepai/cli 1.18.0 → 1.20.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/eslint.config.mjs +3 -0
- package/dist/src/application/ports/output/agents/feature-agent-process.interface.d.ts +2 -1
- package/dist/src/application/ports/output/agents/feature-agent-process.interface.d.ts.map +1 -1
- package/dist/src/application/ports/output/agents/index.d.ts +1 -0
- package/dist/src/application/ports/output/agents/index.d.ts.map +1 -1
- package/dist/src/application/ports/output/agents/phase-timing-repository.interface.d.ts +44 -0
- package/dist/src/application/ports/output/agents/phase-timing-repository.interface.d.ts.map +1 -0
- package/dist/src/application/ports/output/agents/phase-timing-repository.interface.js +11 -0
- package/dist/src/application/use-cases/agents/approve-agent-run.use-case.d.ts.map +1 -1
- package/dist/src/application/use-cases/agents/approve-agent-run.use-case.js +6 -2
- package/dist/src/application/use-cases/agents/reject-agent-run.use-case.d.ts.map +1 -1
- package/dist/src/application/use-cases/agents/reject-agent-run.use-case.js +0 -1
- package/dist/src/application/use-cases/features/create-feature.use-case.d.ts +12 -2
- package/dist/src/application/use-cases/features/create-feature.use-case.d.ts.map +1 -1
- package/dist/src/application/use-cases/features/create-feature.use-case.js +45 -10
- package/dist/src/application/use-cases/features/resume-feature.use-case.js +2 -2
- package/dist/src/domain/factories/settings-defaults.factory.js +2 -2
- package/dist/src/domain/generated/output.d.ts +48 -7
- package/dist/src/domain/generated/output.d.ts.map +1 -1
- package/dist/src/domain/generated/output.js +8 -0
- package/dist/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/src/infrastructure/di/container.js +7 -0
- package/dist/src/infrastructure/persistence/sqlite/mappers/agent-run.mapper.d.ts +1 -2
- package/dist/src/infrastructure/persistence/sqlite/mappers/agent-run.mapper.d.ts.map +1 -1
- package/dist/src/infrastructure/persistence/sqlite/mappers/agent-run.mapper.js +4 -4
- package/dist/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
- package/dist/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
- package/dist/src/infrastructure/persistence/sqlite/migrations.js +31 -0
- package/dist/src/infrastructure/repositories/agent-run.repository.d.ts.map +1 -1
- package/dist/src/infrastructure/repositories/agent-run.repository.js +5 -9
- package/dist/src/infrastructure/repositories/sqlite-phase-timing.repository.d.ts +21 -0
- package/dist/src/infrastructure/repositories/sqlite-phase-timing.repository.d.ts.map +1 -0
- package/dist/src/infrastructure/repositories/sqlite-phase-timing.repository.js +100 -0
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +305 -13
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js +124 -7
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +2 -1
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +2 -2
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +2 -1
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +19 -7
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/implement.node.js +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +11 -2
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +46 -15
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/repair.node.d.ts +23 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/repair.node.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/repair.node.js +77 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/plan.schema.d.ts +4 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/plan.schema.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/plan.schema.js +54 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/research.schema.d.ts +3 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/research.schema.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/research.schema.js +24 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/spec.schema.d.ts +4 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/spec.schema.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/spec.schema.js +50 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/validation.d.ts +8 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/validation.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/validation.js +36 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/validate.node.d.ts +12 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/validate.node.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/feature-agent/nodes/validate.node.js +58 -0
- package/dist/src/infrastructure/services/agents/feature-agent/phase-timing-context.d.ts +30 -0
- package/dist/src/infrastructure/services/agents/feature-agent/phase-timing-context.d.ts.map +1 -0
- package/dist/src/infrastructure/services/agents/feature-agent/phase-timing-context.js +68 -0
- package/dist/src/infrastructure/services/agents/feature-agent/state.d.ts +5 -1
- package/dist/src/infrastructure/services/agents/feature-agent/state.d.ts.map +1 -1
- package/dist/src/infrastructure/services/agents/feature-agent/state.js +14 -1
- package/dist/src/infrastructure/services/ide-launchers/antigravity.launcher.d.ts +10 -0
- package/dist/src/infrastructure/services/ide-launchers/antigravity.launcher.d.ts.map +1 -0
- package/dist/src/infrastructure/services/ide-launchers/antigravity.launcher.js +21 -0
- package/dist/src/infrastructure/services/ide-launchers/cursor.launcher.d.ts +10 -0
- package/dist/src/infrastructure/services/ide-launchers/cursor.launcher.d.ts.map +1 -0
- package/dist/src/infrastructure/services/ide-launchers/cursor.launcher.js +21 -0
- package/dist/src/infrastructure/services/ide-launchers/ide-launcher.interface.d.ts +31 -0
- package/dist/src/infrastructure/services/ide-launchers/ide-launcher.interface.d.ts.map +1 -0
- package/dist/src/infrastructure/services/ide-launchers/ide-launcher.interface.js +8 -0
- package/dist/src/infrastructure/services/ide-launchers/ide-launcher.registry.d.ts +9 -0
- package/dist/src/infrastructure/services/ide-launchers/ide-launcher.registry.d.ts.map +1 -0
- package/dist/src/infrastructure/services/ide-launchers/ide-launcher.registry.js +24 -0
- package/dist/src/infrastructure/services/ide-launchers/vscode.launcher.d.ts +10 -0
- package/dist/src/infrastructure/services/ide-launchers/vscode.launcher.d.ts.map +1 -0
- package/dist/src/infrastructure/services/ide-launchers/vscode.launcher.js +21 -0
- package/dist/src/infrastructure/services/ide-launchers/windsurf.launcher.d.ts +10 -0
- package/dist/src/infrastructure/services/ide-launchers/windsurf.launcher.d.ts.map +1 -0
- package/dist/src/infrastructure/services/ide-launchers/windsurf.launcher.js +21 -0
- package/dist/src/infrastructure/services/ide-launchers/zed.launcher.d.ts +10 -0
- package/dist/src/infrastructure/services/ide-launchers/zed.launcher.d.ts.map +1 -0
- package/dist/src/infrastructure/services/ide-launchers/zed.launcher.js +21 -0
- package/dist/src/presentation/cli/commands/feat/approve.command.d.ts +12 -0
- package/dist/src/presentation/cli/commands/feat/approve.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/feat/approve.command.js +48 -0
- package/dist/src/presentation/cli/commands/feat/index.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/index.js +7 -1
- package/dist/src/presentation/cli/commands/feat/ls.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/ls.command.js +13 -5
- package/dist/src/presentation/cli/commands/feat/new.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/new.command.js +34 -15
- package/dist/src/presentation/cli/commands/feat/reject.command.d.ts +12 -0
- package/dist/src/presentation/cli/commands/feat/reject.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/feat/reject.command.js +50 -0
- package/dist/src/presentation/cli/commands/feat/resolve-waiting-feature.d.ts +30 -0
- package/dist/src/presentation/cli/commands/feat/resolve-waiting-feature.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/feat/resolve-waiting-feature.js +57 -0
- package/dist/src/presentation/cli/commands/feat/review.command.d.ts +12 -0
- package/dist/src/presentation/cli/commands/feat/review.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/feat/review.command.js +49 -0
- package/dist/src/presentation/cli/commands/feat/show.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/show.command.js +51 -6
- package/dist/src/presentation/cli/commands/ide-open.command.d.ts +10 -0
- package/dist/src/presentation/cli/commands/ide-open.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/ide-open.command.js +77 -0
- package/dist/src/presentation/cli/commands/settings/ide.command.d.ts +15 -0
- package/dist/src/presentation/cli/commands/settings/ide.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/settings/ide.command.js +76 -0
- package/dist/src/presentation/cli/commands/settings/index.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/settings/index.js +3 -1
- package/dist/src/presentation/cli/index.js +2 -0
- package/dist/src/presentation/tui/prompts/ide-select.prompt.d.ts +45 -0
- package/dist/src/presentation/tui/prompts/ide-select.prompt.d.ts.map +1 -0
- package/dist/src/presentation/tui/prompts/ide-select.prompt.js +44 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.html +2 -2
- package/web/.next/server/app/_not-found.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/index.html +2 -2
- package/web/.next/server/app/index.rsc +1 -1
- package/web/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/version.html +2 -2
- package/web/.next/server/app/version.rsc +1 -1
- package/web/.next/server/app/version.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/version/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/version.segment.rsc +1 -1
- package/web/.next/server/chunks/ssr/_19be0743._.js +1 -1
- package/web/.next/server/pages/404.html +2 -2
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- /package/web/.next/static/{iV3kEDpfUq_ttVqv3E57o → u-tyZUMnsIne6K_0rPmPO}/_buildManifest.js +0 -0
- /package/web/.next/static/{iV3kEDpfUq_ttVqv3E57o → u-tyZUMnsIne6K_0rPmPO}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{iV3kEDpfUq_ttVqv3E57o → u-tyZUMnsIne6K_0rPmPO}/_ssgManifest.js +0 -0
package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/research.schema.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { requireString, requireArrayOfShape, requireNonEmptyArray, } from './validation.js';
|
|
2
|
+
export function validateResearch(data) {
|
|
3
|
+
const errors = [];
|
|
4
|
+
if (!data || typeof data !== 'object') {
|
|
5
|
+
errors.push('YAML parsed to null or non-object');
|
|
6
|
+
return { valid: false, errors };
|
|
7
|
+
}
|
|
8
|
+
const d = data;
|
|
9
|
+
requireString(d, 'name', errors);
|
|
10
|
+
requireString(d, 'summary', errors);
|
|
11
|
+
requireString(d, 'content', errors);
|
|
12
|
+
requireArrayOfShape(d, 'decisions', errors, (item, idx, errs) => {
|
|
13
|
+
const decision = item;
|
|
14
|
+
if (!decision || typeof decision !== 'object') {
|
|
15
|
+
errs.push(`decisions[${idx}] must be an object`);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
requireString(decision, 'title', errs, `decisions[${idx}].`);
|
|
19
|
+
requireString(decision, 'chosen', errs, `decisions[${idx}].`);
|
|
20
|
+
requireNonEmptyArray(decision, 'rejected', errs, `decisions[${idx}].`);
|
|
21
|
+
requireString(decision, 'rationale', errs, `decisions[${idx}].`);
|
|
22
|
+
});
|
|
23
|
+
return { valid: errors.length === 0, errors };
|
|
24
|
+
}
|
package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/spec.schema.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.schema.d.ts","sourceRoot":"","sources":["../../../../../../../../src/infrastructure/services/agents/feature-agent/nodes/schemas/spec.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AA4B7F,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAInE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAqBxE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { requireString, requireNonEmptyArray } from './validation.js';
|
|
2
|
+
const VALID_SIZE_ESTIMATES = ['S', 'M', 'L', 'XL'];
|
|
3
|
+
function validateBaseSpec(data, errors) {
|
|
4
|
+
if (!data || typeof data !== 'object') {
|
|
5
|
+
errors.push('YAML parsed to null or non-object');
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const d = data;
|
|
9
|
+
requireString(d, 'name', errors);
|
|
10
|
+
requireString(d, 'oneLiner', errors);
|
|
11
|
+
requireString(d, 'summary', errors);
|
|
12
|
+
requireString(d, 'phase', errors);
|
|
13
|
+
requireString(d, 'content', errors);
|
|
14
|
+
requireNonEmptyArray(d, 'technologies', errors);
|
|
15
|
+
if (typeof d.sizeEstimate === 'string' && !VALID_SIZE_ESTIMATES.includes(d.sizeEstimate)) {
|
|
16
|
+
errors.push(`Field 'sizeEstimate' must be one of ${VALID_SIZE_ESTIMATES.join(', ')}, got '${d.sizeEstimate}'`);
|
|
17
|
+
}
|
|
18
|
+
else if (typeof d.sizeEstimate !== 'string') {
|
|
19
|
+
requireString(d, 'sizeEstimate', errors);
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
export function validateSpecAnalyze(data) {
|
|
24
|
+
const errors = [];
|
|
25
|
+
validateBaseSpec(data, errors);
|
|
26
|
+
return { valid: errors.length === 0, errors };
|
|
27
|
+
}
|
|
28
|
+
export function validateSpecRequirements(data) {
|
|
29
|
+
const errors = [];
|
|
30
|
+
if (!validateBaseSpec(data, errors))
|
|
31
|
+
return { valid: false, errors };
|
|
32
|
+
const d = data;
|
|
33
|
+
if (!('openQuestions' in d)) {
|
|
34
|
+
errors.push("Missing required field 'openQuestions'");
|
|
35
|
+
}
|
|
36
|
+
else if (Array.isArray(d.openQuestions)) {
|
|
37
|
+
for (let i = 0; i < d.openQuestions.length; i++) {
|
|
38
|
+
const q = d.openQuestions[i];
|
|
39
|
+
if (!q || typeof q !== 'object') {
|
|
40
|
+
errors.push(`openQuestions[${i}] must be an object`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
requireString(q, 'question', errors, `openQuestions[${i}].`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
errors.push("Field 'openQuestions' must be an array");
|
|
48
|
+
}
|
|
49
|
+
return { valid: errors.length === 0, errors };
|
|
50
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ValidationResult {
|
|
2
|
+
valid: boolean;
|
|
3
|
+
errors: string[];
|
|
4
|
+
}
|
|
5
|
+
export declare function requireString(data: Record<string, unknown>, field: string, errors: string[], prefix?: string): void;
|
|
6
|
+
export declare function requireNonEmptyArray(data: Record<string, unknown>, field: string, errors: string[], prefix?: string): unknown[] | null;
|
|
7
|
+
export declare function requireArrayOfShape(data: Record<string, unknown>, field: string, errors: string[], itemChecker: (item: unknown, index: number, errors: string[]) => void, prefix?: string): void;
|
|
8
|
+
//# sourceMappingURL=validation.d.ts.map
|
package/dist/src/infrastructure/services/agents/feature-agent/nodes/schemas/validation.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../../../../../../src/infrastructure/services/agents/feature-agent/nodes/schemas/validation.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EAAE,EAChB,MAAM,SAAK,GACV,IAAI,CASN;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EAAE,EAChB,MAAM,SAAK,GACV,OAAO,EAAE,GAAG,IAAI,CAelB;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EAAE,EAChB,WAAW,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,EACrE,MAAM,SAAK,GACV,IAAI,CAMN"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function requireString(data, field, errors, prefix = '') {
|
|
2
|
+
const val = data[field];
|
|
3
|
+
if (val === undefined || val === null) {
|
|
4
|
+
errors.push(`Missing required string field '${prefix}${field}'`);
|
|
5
|
+
}
|
|
6
|
+
else if (typeof val !== 'string') {
|
|
7
|
+
errors.push(`Field '${prefix}${field}' must be a string, got ${typeof val}`);
|
|
8
|
+
}
|
|
9
|
+
else if (val.trim() === '') {
|
|
10
|
+
errors.push(`Field '${prefix}${field}' must not be empty`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function requireNonEmptyArray(data, field, errors, prefix = '') {
|
|
14
|
+
const val = data[field];
|
|
15
|
+
if (val === undefined || val === null) {
|
|
16
|
+
errors.push(`Missing required array field '${prefix}${field}'`);
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
if (!Array.isArray(val)) {
|
|
20
|
+
errors.push(`Field '${prefix}${field}' must be an array, got ${typeof val}`);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
if (val.length === 0) {
|
|
24
|
+
errors.push(`Field '${prefix}${field}' must not be empty`);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return val;
|
|
28
|
+
}
|
|
29
|
+
export function requireArrayOfShape(data, field, errors, itemChecker, prefix = '') {
|
|
30
|
+
const arr = requireNonEmptyArray(data, field, errors, prefix);
|
|
31
|
+
if (!arr)
|
|
32
|
+
return;
|
|
33
|
+
for (let i = 0; i < arr.length; i++) {
|
|
34
|
+
itemChecker(arr[i], i, errors);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FeatureAgentState } from '../state.js';
|
|
2
|
+
import type { ValidationResult } from './schemas/validation.js';
|
|
3
|
+
type SchemaValidator = (data: unknown) => ValidationResult;
|
|
4
|
+
/**
|
|
5
|
+
* Factory that creates a validate node for a specific YAML file.
|
|
6
|
+
*
|
|
7
|
+
* On success: resets validationRetries to 0, clears errors.
|
|
8
|
+
* On failure: increments validationRetries, sets errors for repair node.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createValidateNode(filename: string, schema: SchemaValidator): (state: FeatureAgentState) => Promise<Partial<FeatureAgentState>>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=validate.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.node.d.ts","sourceRoot":"","sources":["../../../../../../../src/infrastructure/services/agents/feature-agent/nodes/validate.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,gBAAgB,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,GACtB,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAsDnE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { readSpecFile, safeYamlLoad, createNodeLogger } from './node-helpers.js';
|
|
2
|
+
/**
|
|
3
|
+
* Factory that creates a validate node for a specific YAML file.
|
|
4
|
+
*
|
|
5
|
+
* On success: resets validationRetries to 0, clears errors.
|
|
6
|
+
* On failure: increments validationRetries, sets errors for repair node.
|
|
7
|
+
*/
|
|
8
|
+
export function createValidateNode(filename, schema) {
|
|
9
|
+
const log = createNodeLogger(`validate:${filename}`);
|
|
10
|
+
return async (state) => {
|
|
11
|
+
log.info(`Validating ${filename}`);
|
|
12
|
+
const content = readSpecFile(state.specDir, filename);
|
|
13
|
+
if (!content) {
|
|
14
|
+
const errors = [`File '${filename}' not found or empty in ${state.specDir}`];
|
|
15
|
+
log.error(errors[0]);
|
|
16
|
+
return {
|
|
17
|
+
lastValidationTarget: filename,
|
|
18
|
+
lastValidationErrors: errors,
|
|
19
|
+
validationRetries: state.validationRetries + 1,
|
|
20
|
+
messages: [`[validate:${filename}] FAIL: ${errors[0]}`],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// Try to parse
|
|
24
|
+
let parsed;
|
|
25
|
+
try {
|
|
26
|
+
parsed = safeYamlLoad(content);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
30
|
+
const errors = [`YAML parse error in ${filename}: ${msg}`];
|
|
31
|
+
log.error(errors[0]);
|
|
32
|
+
return {
|
|
33
|
+
lastValidationTarget: filename,
|
|
34
|
+
lastValidationErrors: errors,
|
|
35
|
+
validationRetries: state.validationRetries + 1,
|
|
36
|
+
messages: [`[validate:${filename}] FAIL: parse error`],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Run schema validation
|
|
40
|
+
const result = schema(parsed);
|
|
41
|
+
if (result.valid) {
|
|
42
|
+
log.info('Validation passed');
|
|
43
|
+
return {
|
|
44
|
+
lastValidationTarget: filename,
|
|
45
|
+
lastValidationErrors: [],
|
|
46
|
+
validationRetries: 0,
|
|
47
|
+
messages: [`[validate:${filename}] PASS`],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
log.error(`Validation failed: ${result.errors.join('; ')}`);
|
|
51
|
+
return {
|
|
52
|
+
lastValidationTarget: filename,
|
|
53
|
+
lastValidationErrors: result.errors,
|
|
54
|
+
validationRetries: state.validationRetries + 1,
|
|
55
|
+
messages: [`[validate:${filename}] FAIL: ${result.errors.length} error(s)`],
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase Timing Context
|
|
3
|
+
*
|
|
4
|
+
* Module-level singleton that provides phase timing recording
|
|
5
|
+
* to executeNode() without changing its public API.
|
|
6
|
+
*
|
|
7
|
+
* The worker calls setPhaseTimingContext() once after DI init.
|
|
8
|
+
* Node helpers call recordPhaseStart/End() during graph execution.
|
|
9
|
+
* Errors are swallowed so timing never blocks graph execution.
|
|
10
|
+
*/
|
|
11
|
+
import type { IPhaseTimingRepository } from '../../../../application/ports/output/agents/phase-timing-repository.interface.js';
|
|
12
|
+
/**
|
|
13
|
+
* Set the phase timing context. Called once by the worker after DI init.
|
|
14
|
+
*/
|
|
15
|
+
export declare function setPhaseTimingContext(runId: string, repository: IPhaseTimingRepository): void;
|
|
16
|
+
/**
|
|
17
|
+
* Clear the phase timing context. Useful for testing.
|
|
18
|
+
*/
|
|
19
|
+
export declare function clearPhaseTimingContext(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Record the start of a phase. Returns the timing record ID (for later update)
|
|
22
|
+
* or null if context is not set or save fails.
|
|
23
|
+
*/
|
|
24
|
+
export declare function recordPhaseStart(phase: string): Promise<string | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Record the end of a phase. Updates the timing record with completedAt and durationMs.
|
|
27
|
+
* No-op if timingId is null (phase start was skipped or failed).
|
|
28
|
+
*/
|
|
29
|
+
export declare function recordPhaseEnd(timingId: string | null, durationMs: number): Promise<void>;
|
|
30
|
+
//# sourceMappingURL=phase-timing-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase-timing-context.d.ts","sourceRoot":"","sources":["../../../../../../src/infrastructure/services/agents/feature-agent/phase-timing-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wEAAwE,CAAC;AAKrH;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,sBAAsB,GAAG,IAAI,CAG7F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmB5E;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/F"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase Timing Context
|
|
3
|
+
*
|
|
4
|
+
* Module-level singleton that provides phase timing recording
|
|
5
|
+
* to executeNode() without changing its public API.
|
|
6
|
+
*
|
|
7
|
+
* The worker calls setPhaseTimingContext() once after DI init.
|
|
8
|
+
* Node helpers call recordPhaseStart/End() during graph execution.
|
|
9
|
+
* Errors are swallowed so timing never blocks graph execution.
|
|
10
|
+
*/
|
|
11
|
+
import { randomUUID } from 'node:crypto';
|
|
12
|
+
let contextRunId;
|
|
13
|
+
let contextRepository;
|
|
14
|
+
/**
|
|
15
|
+
* Set the phase timing context. Called once by the worker after DI init.
|
|
16
|
+
*/
|
|
17
|
+
export function setPhaseTimingContext(runId, repository) {
|
|
18
|
+
contextRunId = runId;
|
|
19
|
+
contextRepository = repository;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Clear the phase timing context. Useful for testing.
|
|
23
|
+
*/
|
|
24
|
+
export function clearPhaseTimingContext() {
|
|
25
|
+
contextRunId = undefined;
|
|
26
|
+
contextRepository = undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Record the start of a phase. Returns the timing record ID (for later update)
|
|
30
|
+
* or null if context is not set or save fails.
|
|
31
|
+
*/
|
|
32
|
+
export async function recordPhaseStart(phase) {
|
|
33
|
+
if (!contextRunId || !contextRepository)
|
|
34
|
+
return null;
|
|
35
|
+
const id = randomUUID();
|
|
36
|
+
const now = new Date();
|
|
37
|
+
try {
|
|
38
|
+
await contextRepository.save({
|
|
39
|
+
id,
|
|
40
|
+
agentRunId: contextRunId,
|
|
41
|
+
phase,
|
|
42
|
+
startedAt: now,
|
|
43
|
+
createdAt: now,
|
|
44
|
+
updatedAt: now,
|
|
45
|
+
});
|
|
46
|
+
return id;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Record the end of a phase. Updates the timing record with completedAt and durationMs.
|
|
54
|
+
* No-op if timingId is null (phase start was skipped or failed).
|
|
55
|
+
*/
|
|
56
|
+
export async function recordPhaseEnd(timingId, durationMs) {
|
|
57
|
+
if (!timingId || !contextRepository)
|
|
58
|
+
return;
|
|
59
|
+
try {
|
|
60
|
+
await contextRepository.update(timingId, {
|
|
61
|
+
completedAt: new Date(),
|
|
62
|
+
durationMs: BigInt(durationMs),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Swallow — timing update failure is non-fatal
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ApprovalGates } from '../../../../domain/generated/output.js';
|
|
1
2
|
/**
|
|
2
3
|
* State annotation for the feature-agent graph.
|
|
3
4
|
*
|
|
@@ -32,8 +33,11 @@ export declare const FeatureAgentAnnotation: import("@langchain/langgraph").Anno
|
|
|
32
33
|
Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
|
|
33
34
|
};
|
|
34
35
|
error: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
35
|
-
|
|
36
|
+
approvalGates: import("@langchain/langgraph").BinaryOperatorAggregate<ApprovalGates | undefined, ApprovalGates | undefined>;
|
|
36
37
|
messages: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
|
|
38
|
+
validationRetries: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
|
|
39
|
+
lastValidationTarget: import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
|
|
40
|
+
lastValidationErrors: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
|
|
37
41
|
}>;
|
|
38
42
|
export type FeatureAgentState = typeof FeatureAgentAnnotation.State;
|
|
39
43
|
//# sourceMappingURL=state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../../../src/infrastructure/services/agents/feature-agent/state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../../../src/infrastructure/services/agents/feature-agent/state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BjC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,OAAO,sBAAsB,CAAC,KAAK,CAAC"}
|
|
@@ -16,7 +16,7 @@ export const FeatureAgentAnnotation = Annotation.Root({
|
|
|
16
16
|
reducer: (prev, next) => (next !== undefined ? next : prev),
|
|
17
17
|
default: () => null,
|
|
18
18
|
}),
|
|
19
|
-
|
|
19
|
+
approvalGates: Annotation({
|
|
20
20
|
reducer: (prev, next) => next ?? prev,
|
|
21
21
|
default: () => undefined,
|
|
22
22
|
}),
|
|
@@ -24,4 +24,17 @@ export const FeatureAgentAnnotation = Annotation.Root({
|
|
|
24
24
|
reducer: (prev, next) => [...prev, ...next],
|
|
25
25
|
default: () => [],
|
|
26
26
|
}),
|
|
27
|
+
// --- Validation state channels (for validate/repair loops) ---
|
|
28
|
+
validationRetries: Annotation({
|
|
29
|
+
reducer: (_prev, next) => next,
|
|
30
|
+
default: () => 0,
|
|
31
|
+
}),
|
|
32
|
+
lastValidationTarget: Annotation({
|
|
33
|
+
reducer: (_prev, next) => next,
|
|
34
|
+
default: () => '',
|
|
35
|
+
}),
|
|
36
|
+
lastValidationErrors: Annotation({
|
|
37
|
+
reducer: (_prev, next) => next,
|
|
38
|
+
default: () => [],
|
|
39
|
+
}),
|
|
27
40
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EditorType } from '../../../domain/generated/output.js';
|
|
2
|
+
import type { IdeLauncher } from './ide-launcher.interface';
|
|
3
|
+
export declare class AntigravityLauncher implements IdeLauncher {
|
|
4
|
+
readonly name = "Antigravity";
|
|
5
|
+
readonly editorId = EditorType.Antigravity;
|
|
6
|
+
readonly binary = "antigravity";
|
|
7
|
+
launch(path: string): Promise<void>;
|
|
8
|
+
checkAvailable(): Promise<boolean>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=antigravity.launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"antigravity.launcher.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/ide-launchers/antigravity.launcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,qBAAa,mBAAoB,YAAW,WAAW;IACrD,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,QAAQ,0BAA0B;IAC3C,QAAQ,CAAC,MAAM,iBAAiB;IAE1B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAOnC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { spawn, execFile } from 'node:child_process';
|
|
2
|
+
import { EditorType } from '../../../domain/generated/output.js';
|
|
3
|
+
export class AntigravityLauncher {
|
|
4
|
+
name = 'Antigravity';
|
|
5
|
+
editorId = EditorType.Antigravity;
|
|
6
|
+
binary = 'antigravity';
|
|
7
|
+
async launch(path) {
|
|
8
|
+
const child = spawn(this.binary, [path], {
|
|
9
|
+
detached: true,
|
|
10
|
+
stdio: 'ignore',
|
|
11
|
+
});
|
|
12
|
+
child.unref();
|
|
13
|
+
}
|
|
14
|
+
checkAvailable() {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
execFile('which', [this.binary], (err) => {
|
|
17
|
+
resolve(!err);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EditorType } from '../../../domain/generated/output.js';
|
|
2
|
+
import type { IdeLauncher } from './ide-launcher.interface';
|
|
3
|
+
export declare class CursorLauncher implements IdeLauncher {
|
|
4
|
+
readonly name = "Cursor";
|
|
5
|
+
readonly editorId = EditorType.Cursor;
|
|
6
|
+
readonly binary = "cursor";
|
|
7
|
+
launch(path: string): Promise<void>;
|
|
8
|
+
checkAvailable(): Promise<boolean>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=cursor.launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.launcher.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/ide-launchers/cursor.launcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,qBAAa,cAAe,YAAW,WAAW;IAChD,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,QAAQ,qBAAqB;IACtC,QAAQ,CAAC,MAAM,YAAY;IAErB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAOnC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { spawn, execFile } from 'node:child_process';
|
|
2
|
+
import { EditorType } from '../../../domain/generated/output.js';
|
|
3
|
+
export class CursorLauncher {
|
|
4
|
+
name = 'Cursor';
|
|
5
|
+
editorId = EditorType.Cursor;
|
|
6
|
+
binary = 'cursor';
|
|
7
|
+
async launch(path) {
|
|
8
|
+
const child = spawn(this.binary, [path], {
|
|
9
|
+
detached: true,
|
|
10
|
+
stdio: 'ignore',
|
|
11
|
+
});
|
|
12
|
+
child.unref();
|
|
13
|
+
}
|
|
14
|
+
checkAvailable() {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
execFile('which', [this.binary], (err) => {
|
|
17
|
+
resolve(!err);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for IDE launcher implementations.
|
|
3
|
+
*
|
|
4
|
+
* Each supported IDE (VS Code, Cursor, Windsurf, Zed, Antigravity) provides
|
|
5
|
+
* its own implementation of this interface. Launchers are responsible for
|
|
6
|
+
* spawning a detached editor process and checking binary availability.
|
|
7
|
+
*/
|
|
8
|
+
import type { EditorType } from '../../../domain/generated/output.js';
|
|
9
|
+
export interface IdeLauncher {
|
|
10
|
+
/** Display name shown to the user (e.g., "VS Code"). */
|
|
11
|
+
readonly name: string;
|
|
12
|
+
/** Editor identifier matching the EditorType enum value. */
|
|
13
|
+
readonly editorId: EditorType;
|
|
14
|
+
/** CLI binary used to launch the editor (e.g., "code"). */
|
|
15
|
+
readonly binary: string;
|
|
16
|
+
/**
|
|
17
|
+
* Open the IDE at the given filesystem path.
|
|
18
|
+
*
|
|
19
|
+
* Spawns a detached process so the CLI does not block.
|
|
20
|
+
*
|
|
21
|
+
* @param path - Absolute path to the file or directory to open.
|
|
22
|
+
*/
|
|
23
|
+
launch(path: string): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Check whether the IDE binary is available on the system PATH.
|
|
26
|
+
*
|
|
27
|
+
* @returns `true` if the binary can be found and executed, `false` otherwise.
|
|
28
|
+
*/
|
|
29
|
+
checkAvailable(): Promise<boolean>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ide-launcher.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ide-launcher.interface.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/ide-launchers/ide-launcher.interface.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAEtE,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAE9B,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpC;;;;OAIG;IACH,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CACpC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for IDE launcher implementations.
|
|
3
|
+
*
|
|
4
|
+
* Each supported IDE (VS Code, Cursor, Windsurf, Zed, Antigravity) provides
|
|
5
|
+
* its own implementation of this interface. Launchers are responsible for
|
|
6
|
+
* spawning a detached editor process and checking binary availability.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { EditorType } from '../../../domain/generated/output.js';
|
|
2
|
+
import type { IdeLauncher } from './ide-launcher.interface.js';
|
|
3
|
+
/**
|
|
4
|
+
* Create a registry of all supported IDE launchers, keyed by EditorType.
|
|
5
|
+
*
|
|
6
|
+
* @returns A Map from EditorType to its IdeLauncher instance.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createLauncherRegistry(): Map<EditorType, IdeLauncher>;
|
|
9
|
+
//# sourceMappingURL=ide-launcher.registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ide-launcher.registry.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/ide-launchers/ide-launcher.registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAO/D;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAcrE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AntigravityLauncher } from './antigravity.launcher.js';
|
|
2
|
+
import { CursorLauncher } from './cursor.launcher.js';
|
|
3
|
+
import { VsCodeLauncher } from './vscode.launcher.js';
|
|
4
|
+
import { WindsurfLauncher } from './windsurf.launcher.js';
|
|
5
|
+
import { ZedLauncher } from './zed.launcher.js';
|
|
6
|
+
/**
|
|
7
|
+
* Create a registry of all supported IDE launchers, keyed by EditorType.
|
|
8
|
+
*
|
|
9
|
+
* @returns A Map from EditorType to its IdeLauncher instance.
|
|
10
|
+
*/
|
|
11
|
+
export function createLauncherRegistry() {
|
|
12
|
+
const launchers = [
|
|
13
|
+
new VsCodeLauncher(),
|
|
14
|
+
new CursorLauncher(),
|
|
15
|
+
new WindsurfLauncher(),
|
|
16
|
+
new ZedLauncher(),
|
|
17
|
+
new AntigravityLauncher(),
|
|
18
|
+
];
|
|
19
|
+
const registry = new Map();
|
|
20
|
+
for (const launcher of launchers) {
|
|
21
|
+
registry.set(launcher.editorId, launcher);
|
|
22
|
+
}
|
|
23
|
+
return registry;
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EditorType } from '../../../domain/generated/output.js';
|
|
2
|
+
import type { IdeLauncher } from './ide-launcher.interface';
|
|
3
|
+
export declare class VsCodeLauncher implements IdeLauncher {
|
|
4
|
+
readonly name = "VS Code";
|
|
5
|
+
readonly editorId = EditorType.VsCode;
|
|
6
|
+
readonly binary = "code";
|
|
7
|
+
launch(path: string): Promise<void>;
|
|
8
|
+
checkAvailable(): Promise<boolean>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=vscode.launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vscode.launcher.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/ide-launchers/vscode.launcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,qBAAa,cAAe,YAAW,WAAW;IAChD,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,QAAQ,qBAAqB;IACtC,QAAQ,CAAC,MAAM,UAAU;IAEnB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAOnC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { spawn, execFile } from 'node:child_process';
|
|
2
|
+
import { EditorType } from '../../../domain/generated/output.js';
|
|
3
|
+
export class VsCodeLauncher {
|
|
4
|
+
name = 'VS Code';
|
|
5
|
+
editorId = EditorType.VsCode;
|
|
6
|
+
binary = 'code';
|
|
7
|
+
async launch(path) {
|
|
8
|
+
const child = spawn(this.binary, [path], {
|
|
9
|
+
detached: true,
|
|
10
|
+
stdio: 'ignore',
|
|
11
|
+
});
|
|
12
|
+
child.unref();
|
|
13
|
+
}
|
|
14
|
+
checkAvailable() {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
execFile('which', [this.binary], (err) => {
|
|
17
|
+
resolve(!err);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EditorType } from '../../../domain/generated/output.js';
|
|
2
|
+
import type { IdeLauncher } from './ide-launcher.interface';
|
|
3
|
+
export declare class WindsurfLauncher implements IdeLauncher {
|
|
4
|
+
readonly name = "Windsurf";
|
|
5
|
+
readonly editorId = EditorType.Windsurf;
|
|
6
|
+
readonly binary = "windsurf";
|
|
7
|
+
launch(path: string): Promise<void>;
|
|
8
|
+
checkAvailable(): Promise<boolean>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=windsurf.launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windsurf.launcher.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/ide-launchers/windsurf.launcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,qBAAa,gBAAiB,YAAW,WAAW;IAClD,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,QAAQ,uBAAuB;IACxC,QAAQ,CAAC,MAAM,cAAc;IAEvB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAOnC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { spawn, execFile } from 'node:child_process';
|
|
2
|
+
import { EditorType } from '../../../domain/generated/output.js';
|
|
3
|
+
export class WindsurfLauncher {
|
|
4
|
+
name = 'Windsurf';
|
|
5
|
+
editorId = EditorType.Windsurf;
|
|
6
|
+
binary = 'windsurf';
|
|
7
|
+
async launch(path) {
|
|
8
|
+
const child = spawn(this.binary, [path], {
|
|
9
|
+
detached: true,
|
|
10
|
+
stdio: 'ignore',
|
|
11
|
+
});
|
|
12
|
+
child.unref();
|
|
13
|
+
}
|
|
14
|
+
checkAvailable() {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
execFile('which', [this.binary], (err) => {
|
|
17
|
+
resolve(!err);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EditorType } from '../../../domain/generated/output.js';
|
|
2
|
+
import type { IdeLauncher } from './ide-launcher.interface';
|
|
3
|
+
export declare class ZedLauncher implements IdeLauncher {
|
|
4
|
+
readonly name = "Zed";
|
|
5
|
+
readonly editorId = EditorType.Zed;
|
|
6
|
+
readonly binary = "zed";
|
|
7
|
+
launch(path: string): Promise<void>;
|
|
8
|
+
checkAvailable(): Promise<boolean>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=zed.launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zed.launcher.d.ts","sourceRoot":"","sources":["../../../../../src/infrastructure/services/ide-launchers/zed.launcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,qBAAa,WAAY,YAAW,WAAW;IAC7C,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,QAAQ,kBAAkB;IACnC,QAAQ,CAAC,MAAM,SAAS;IAElB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;CAOnC"}
|