@shepai/cli 1.20.0 → 1.21.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 +1 -0
- package/dist/src/application/ports/output/services/index.d.ts +1 -0
- package/dist/src/application/ports/output/services/index.d.ts.map +1 -1
- package/dist/src/application/ports/output/services/tool-installer.service.d.ts +35 -0
- package/dist/src/application/ports/output/services/tool-installer.service.d.ts.map +1 -0
- package/dist/src/application/ports/output/services/tool-installer.service.js +7 -0
- package/dist/src/application/use-cases/features/create/create-feature.use-case.d.ts +37 -0
- package/dist/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -0
- package/dist/src/application/use-cases/features/{create-feature.use-case.js → create/create-feature.use-case.js} +17 -100
- package/dist/src/application/use-cases/features/create/metadata-generator.d.ts +28 -0
- package/dist/src/application/use-cases/features/create/metadata-generator.d.ts.map +1 -0
- package/dist/src/application/use-cases/features/create/metadata-generator.js +109 -0
- package/dist/src/application/use-cases/features/create/slug-resolver.d.ts +24 -0
- package/dist/src/application/use-cases/features/create/slug-resolver.d.ts.map +1 -0
- package/dist/src/application/use-cases/features/create/slug-resolver.js +66 -0
- package/dist/src/application/use-cases/features/create/types.d.ts +16 -0
- package/dist/src/application/use-cases/features/create/types.d.ts.map +1 -0
- package/dist/src/application/use-cases/features/create/types.js +1 -0
- package/dist/src/application/use-cases/tools/install-tool.use-case.d.ts +21 -0
- package/dist/src/application/use-cases/tools/install-tool.use-case.d.ts.map +1 -0
- package/dist/src/application/use-cases/tools/install-tool.use-case.js +41 -0
- package/dist/src/application/use-cases/tools/validate-tool-availability.use-case.d.ts +20 -0
- package/dist/src/application/use-cases/tools/validate-tool-availability.use-case.d.ts.map +1 -0
- package/dist/src/application/use-cases/tools/validate-tool-availability.use-case.js +40 -0
- package/dist/src/domain/generated/output.d.ts +97 -0
- package/dist/src/domain/generated/output.d.ts.map +1 -1
- package/dist/src/domain/generated/output.js +10 -0
- package/dist/src/domain/value-objects/index.d.ts +2 -0
- package/dist/src/domain/value-objects/index.d.ts.map +1 -1
- package/dist/src/domain/value-objects/index.js +1 -0
- package/dist/src/domain/value-objects/tool-installation-status.d.ts +70 -0
- package/dist/src/domain/value-objects/tool-installation-status.d.ts.map +1 -0
- package/dist/src/domain/value-objects/tool-installation-status.js +111 -0
- package/dist/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/src/infrastructure/di/container.js +11 -1
- package/dist/src/infrastructure/services/agents/common/executors/mock-executor.service.js +2 -2
- package/dist/src/infrastructure/services/tool-installer/tool-installer.service.d.ts +36 -0
- package/dist/src/infrastructure/services/tool-installer/tool-installer.service.d.ts.map +1 -0
- package/dist/src/infrastructure/services/tool-installer/tool-installer.service.js +179 -0
- package/dist/src/infrastructure/services/tool-installer/tool-metadata.d.ts +37 -0
- package/dist/src/infrastructure/services/tool-installer/tool-metadata.d.ts.map +1 -0
- package/dist/src/infrastructure/services/tool-installer/tool-metadata.js +52 -0
- package/dist/src/infrastructure/services/tool-installer/tools/antigravity.json +20 -0
- package/dist/src/infrastructure/services/tool-installer/tools/claude-code.json +16 -0
- package/dist/src/infrastructure/services/tool-installer/tools/cursor-cli.json +16 -0
- package/dist/src/infrastructure/services/tool-installer/tools/cursor.json +17 -0
- package/dist/src/infrastructure/services/tool-installer/tools/vscode.json +17 -0
- package/dist/src/infrastructure/services/tool-installer/tools/windsurf.json +17 -0
- package/dist/src/infrastructure/services/tool-installer/tools/zed.json +17 -0
- package/dist/src/presentation/cli/commands/feat/new.command.js +1 -1
- package/dist/src/presentation/cli/commands/install.command.d.ts +14 -0
- package/dist/src/presentation/cli/commands/install.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/install.command.js +134 -0
- package/dist/src/presentation/cli/index.js +2 -0
- package/dist/src/presentation/cli/ui/index.d.ts +1 -0
- package/dist/src/presentation/cli/ui/index.d.ts.map +1 -1
- package/dist/src/presentation/cli/ui/index.js +1 -0
- package/dist/src/presentation/cli/ui/install-messages.d.ts +23 -0
- package/dist/src/presentation/cli/ui/install-messages.d.ts.map +1 -0
- package/dist/src/presentation/cli/ui/install-messages.js +36 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -2
- 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/dist/src/application/use-cases/features/create-feature.use-case.d.ts +0 -53
- package/dist/src/application/use-cases/features/create-feature.use-case.d.ts.map +0 -1
- /package/web/.next/static/{u-tyZUMnsIne6K_0rPmPO → 64iQn2RbdM-TFYWmABhXw}/_buildManifest.js +0 -0
- /package/web/.next/static/{u-tyZUMnsIne6K_0rPmPO → 64iQn2RbdM-TFYWmABhXw}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{u-tyZUMnsIne6K_0rPmPO → 64iQn2RbdM-TFYWmABhXw}/_ssgManifest.js +0 -0
package/dist/eslint.config.mjs
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
export type { IExternalIssueFetcher, ExternalIssue } from './external-issue-fetcher.interface.js';
|
|
7
7
|
export { IssueFetcherError, IssueNotFoundError, IssueAuthenticationError, IssueServiceUnavailableError, } from './external-issue-fetcher.interface.js';
|
|
8
8
|
export type { ISpecInitializerService, SpecInitializerResult, } from './spec-initializer.interface.js';
|
|
9
|
+
export type { IToolInstallerService } from './tool-installer.service.js';
|
|
9
10
|
export type { IVersionService } from './version-service.interface.js';
|
|
10
11
|
export type { IWebServerService } from './web-server-service.interface.js';
|
|
11
12
|
export type { IWorktreeService, WorktreeInfo } from './worktree-service.interface.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/application/ports/output/services/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAClG,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,iCAAiC,CAAC;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/application/ports/output/services/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAClG,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,iCAAiC,CAAC;AACzC,YAAY,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,YAAY,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Installer Service Interface
|
|
3
|
+
*
|
|
4
|
+
* Output port for tool installation operations.
|
|
5
|
+
* Implementations check tool availability and execute installations.
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolInstallationStatus, ToolInstallCommand } from '../../../../domain/generated/output.js';
|
|
8
|
+
/**
|
|
9
|
+
* Service interface for tool installation management.
|
|
10
|
+
*/
|
|
11
|
+
export interface IToolInstallerService {
|
|
12
|
+
/**
|
|
13
|
+
* Check if a tool is available on the system (PATH check).
|
|
14
|
+
*
|
|
15
|
+
* @param toolName - Name of the tool to check
|
|
16
|
+
* @returns ToolInstallationStatus with availability information
|
|
17
|
+
*/
|
|
18
|
+
checkAvailability(toolName: string): Promise<ToolInstallationStatus>;
|
|
19
|
+
/**
|
|
20
|
+
* Get the install command metadata for a tool on the current platform.
|
|
21
|
+
*
|
|
22
|
+
* @param toolName - Name of the tool to get install command for
|
|
23
|
+
* @returns ToolInstallCommand with installation details, or null if not available
|
|
24
|
+
*/
|
|
25
|
+
getInstallCommand(toolName: string): ToolInstallCommand | null;
|
|
26
|
+
/**
|
|
27
|
+
* Execute installation of a tool with live output streaming.
|
|
28
|
+
*
|
|
29
|
+
* @param toolName - Name of the tool to install
|
|
30
|
+
* @param onOutput - Optional callback for streaming installation output
|
|
31
|
+
* @returns ToolInstallationStatus with result of installation
|
|
32
|
+
*/
|
|
33
|
+
executeInstall(toolName: string, onOutput?: (data: string) => void): Promise<ToolInstallationStatus>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=tool-installer.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-installer.service.d.ts","sourceRoot":"","sources":["../../../../../../src/application/ports/output/services/tool-installer.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,wCAAwC,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAErE;;;;;OAKG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAAC;IAE/D;;;;;;OAMG;IACH,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAChC,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACpC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create Feature Use Case
|
|
3
|
+
*
|
|
4
|
+
* Creates a new feature entity with a git worktree for isolated development,
|
|
5
|
+
* initializes the spec directory with YAML templates, then spawns the
|
|
6
|
+
* feature agent to begin autonomous SDLC processing.
|
|
7
|
+
*
|
|
8
|
+
* Business Rules:
|
|
9
|
+
* - Metadata generation delegated to MetadataGenerator service
|
|
10
|
+
* - Slug uniqueness delegated to SlugResolver service
|
|
11
|
+
* - Full user input is preserved as-is in spec.yaml
|
|
12
|
+
* - A git worktree is created at ~/.shep/repos/HASH/wt/SLUG/
|
|
13
|
+
* - Spec YAML files are scaffolded at WORKTREE/specs/NNN-SLUG/
|
|
14
|
+
* - Feature agent is spawned with the spec dir path
|
|
15
|
+
* - specPath is persisted on the Feature record
|
|
16
|
+
* - Initial lifecycle is Requirements
|
|
17
|
+
*/
|
|
18
|
+
import type { IFeatureRepository } from '../../../ports/output/repositories/feature-repository.interface.js';
|
|
19
|
+
import type { IWorktreeService } from '../../../ports/output/services/worktree-service.interface.js';
|
|
20
|
+
import type { IFeatureAgentProcessService } from '../../../ports/output/agents/feature-agent-process.interface.js';
|
|
21
|
+
import type { IAgentRunRepository } from '../../../ports/output/agents/agent-run-repository.interface.js';
|
|
22
|
+
import type { ISpecInitializerService } from '../../../ports/output/services/spec-initializer.interface.js';
|
|
23
|
+
import { MetadataGenerator } from './metadata-generator.js';
|
|
24
|
+
import { SlugResolver } from './slug-resolver.js';
|
|
25
|
+
import type { CreateFeatureInput, CreateFeatureResult } from './types.js';
|
|
26
|
+
export declare class CreateFeatureUseCase {
|
|
27
|
+
private readonly featureRepo;
|
|
28
|
+
private readonly worktreeService;
|
|
29
|
+
private readonly agentProcess;
|
|
30
|
+
private readonly runRepository;
|
|
31
|
+
private readonly specInitializer;
|
|
32
|
+
private readonly metadataGenerator;
|
|
33
|
+
private readonly slugResolver;
|
|
34
|
+
constructor(featureRepo: IFeatureRepository, worktreeService: IWorktreeService, agentProcess: IFeatureAgentProcessService, runRepository: IAgentRunRepository, specInitializer: ISpecInitializerService, metadataGenerator: MetadataGenerator, slugResolver: SlugResolver);
|
|
35
|
+
execute(input: CreateFeatureInput): Promise<CreateFeatureResult>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=create-feature.use-case.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-feature.use-case.d.ts","sourceRoot":"","sources":["../../../../../../src/application/use-cases/features/create/create-feature.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oEAAoE,CAAC;AAC7G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8DAA8D,CAAC;AACrG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iEAAiE,CAAC;AACnH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gEAAgE,CAAC;AAC1G,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8DAA8D,CAAC;AAE5G,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1E,qBACa,oBAAoB;IAG7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAEhC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAE7B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAEhC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAZZ,WAAW,EAAE,kBAAkB,EAE/B,eAAe,EAAE,gBAAgB,EAEjC,YAAY,EAAE,2BAA2B,EAEzC,aAAa,EAAE,mBAAmB,EAElC,eAAe,EAAE,uBAAuB,EAExC,iBAAiB,EAAE,iBAAiB,EAEpC,YAAY,EAAE,YAAY;IAGvC,OAAO,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAyEvE"}
|
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
* feature agent to begin autonomous SDLC processing.
|
|
7
7
|
*
|
|
8
8
|
* Business Rules:
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
9
|
+
* - Metadata generation delegated to MetadataGenerator service
|
|
10
|
+
* - Slug uniqueness delegated to SlugResolver service
|
|
11
11
|
* - Full user input is preserved as-is in spec.yaml
|
|
12
|
-
* - Slug must be unique within the repository
|
|
13
12
|
* - A git worktree is created at ~/.shep/repos/HASH/wt/SLUG/
|
|
14
13
|
* - Spec YAML files are scaffolded at WORKTREE/specs/NNN-SLUG/
|
|
15
14
|
* - Feature agent is spawned with the spec dir path
|
|
@@ -30,31 +29,32 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
30
29
|
};
|
|
31
30
|
import { injectable, inject } from 'tsyringe';
|
|
32
31
|
import { randomUUID } from 'node:crypto';
|
|
33
|
-
import { SdlcLifecycle } from '
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
|
|
37
|
-
const MAX_INPUT_FOR_AI = 500;
|
|
32
|
+
import { SdlcLifecycle, AgentRunStatus } from '../../../../domain/generated/output.js';
|
|
33
|
+
import { getSettings } from '../../../../infrastructure/services/settings.service.js';
|
|
34
|
+
import { MetadataGenerator } from './metadata-generator.js';
|
|
35
|
+
import { SlugResolver } from './slug-resolver.js';
|
|
38
36
|
let CreateFeatureUseCase = class CreateFeatureUseCase {
|
|
39
37
|
featureRepo;
|
|
40
38
|
worktreeService;
|
|
41
39
|
agentProcess;
|
|
42
40
|
runRepository;
|
|
43
41
|
specInitializer;
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
metadataGenerator;
|
|
43
|
+
slugResolver;
|
|
44
|
+
constructor(featureRepo, worktreeService, agentProcess, runRepository, specInitializer, metadataGenerator, slugResolver) {
|
|
46
45
|
this.featureRepo = featureRepo;
|
|
47
46
|
this.worktreeService = worktreeService;
|
|
48
47
|
this.agentProcess = agentProcess;
|
|
49
48
|
this.runRepository = runRepository;
|
|
50
49
|
this.specInitializer = specInitializer;
|
|
51
|
-
this.
|
|
50
|
+
this.metadataGenerator = metadataGenerator;
|
|
51
|
+
this.slugResolver = slugResolver;
|
|
52
52
|
}
|
|
53
53
|
async execute(input) {
|
|
54
|
-
const metadata = await this.generateMetadata(input.userInput);
|
|
54
|
+
const metadata = await this.metadataGenerator.generateMetadata(input.userInput);
|
|
55
55
|
const originalSlug = metadata.slug;
|
|
56
56
|
// Find a unique slug — the branch may exist from a previous (deleted) feature
|
|
57
|
-
const { slug, branch, warning } = await this.resolveUniqueSlug(originalSlug, input.repositoryPath);
|
|
57
|
+
const { slug, branch, warning } = await this.slugResolver.resolveUniqueSlug(originalSlug, input.repositoryPath);
|
|
58
58
|
// Determine next feature number for this repo
|
|
59
59
|
const existingFeatures = await this.featureRepo.list({
|
|
60
60
|
repositoryPath: input.repositoryPath,
|
|
@@ -105,91 +105,6 @@ let CreateFeatureUseCase = class CreateFeatureUseCase {
|
|
|
105
105
|
});
|
|
106
106
|
return { feature, warning };
|
|
107
107
|
}
|
|
108
|
-
/**
|
|
109
|
-
* Find a unique slug by checking both the feature DB and git branches.
|
|
110
|
-
* If the original slug conflicts, appends -2, -3, etc. until a free one is found.
|
|
111
|
-
*/
|
|
112
|
-
async resolveUniqueSlug(originalSlug, repositoryPath) {
|
|
113
|
-
const MAX_SUFFIX = 10;
|
|
114
|
-
for (let suffix = 0; suffix <= MAX_SUFFIX; suffix++) {
|
|
115
|
-
const slug = suffix === 0 ? originalSlug : `${originalSlug}-${suffix + 1}`;
|
|
116
|
-
const branch = `feat/${slug}`;
|
|
117
|
-
// Check if a feature with this slug already exists in the DB
|
|
118
|
-
const existing = await this.featureRepo.findBySlug(slug, repositoryPath);
|
|
119
|
-
if (existing) {
|
|
120
|
-
if (suffix === 0)
|
|
121
|
-
continue; // try suffixed version
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
// Check if the git branch already exists (leftover from deleted feature)
|
|
125
|
-
const branchInUse = await this.worktreeService.exists(repositoryPath, branch);
|
|
126
|
-
if (branchInUse)
|
|
127
|
-
continue;
|
|
128
|
-
if (suffix > 0) {
|
|
129
|
-
return {
|
|
130
|
-
slug,
|
|
131
|
-
branch,
|
|
132
|
-
warning: `Branch "feat/${originalSlug}" already exists, using "${branch}" instead`,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
return { slug, branch };
|
|
136
|
-
}
|
|
137
|
-
throw new Error(`Could not find a unique slug for "${originalSlug}" after ${MAX_SUFFIX} attempts`);
|
|
138
|
-
}
|
|
139
|
-
async generateMetadata(userInput) {
|
|
140
|
-
try {
|
|
141
|
-
const executor = this.executorProvider.getExecutor();
|
|
142
|
-
const truncated = userInput.length > MAX_INPUT_FOR_AI
|
|
143
|
-
? `${userInput.slice(0, MAX_INPUT_FOR_AI)}...`
|
|
144
|
-
: userInput;
|
|
145
|
-
const prompt = `Generate feature metadata from this user request:
|
|
146
|
-
"${truncated}"
|
|
147
|
-
|
|
148
|
-
Return ONLY a JSON object with these fields:
|
|
149
|
-
- slug: kebab-case identifier, 2-4 words max (e.g., "github-oauth-login")
|
|
150
|
-
- name: short human-readable title (e.g., "GitHub OAuth Login")
|
|
151
|
-
- description: refined 1-2 sentence description
|
|
152
|
-
|
|
153
|
-
JSON only, no markdown fences.`;
|
|
154
|
-
const result = await executor.execute(prompt, {
|
|
155
|
-
maxTurns: 1,
|
|
156
|
-
allowedTools: [],
|
|
157
|
-
silent: true,
|
|
158
|
-
});
|
|
159
|
-
const parsed = JSON.parse(result.result);
|
|
160
|
-
if (!parsed.slug || !parsed.name || !parsed.description) {
|
|
161
|
-
throw new Error('Missing required fields in AI response');
|
|
162
|
-
}
|
|
163
|
-
return {
|
|
164
|
-
slug: this.toSlug(parsed.slug),
|
|
165
|
-
name: parsed.name,
|
|
166
|
-
description: parsed.description,
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
// Fallback to regex-based slug generation
|
|
171
|
-
return {
|
|
172
|
-
slug: this.toSlug(userInput),
|
|
173
|
-
name: userInput,
|
|
174
|
-
description: userInput,
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
toSlug(text) {
|
|
179
|
-
const slug = text
|
|
180
|
-
.toLowerCase()
|
|
181
|
-
.replace(/[^a-z0-9\s-]/g, '')
|
|
182
|
-
.replace(/\s+/g, '-')
|
|
183
|
-
.replace(/-+/g, '-')
|
|
184
|
-
.replace(/^-|-$/g, '');
|
|
185
|
-
// Limit to ~50 chars, cutting at a word boundary
|
|
186
|
-
if (slug.length <= 50) {
|
|
187
|
-
return slug;
|
|
188
|
-
}
|
|
189
|
-
const truncated = slug.slice(0, 50);
|
|
190
|
-
const lastDash = truncated.lastIndexOf('-');
|
|
191
|
-
return lastDash > 10 ? truncated.slice(0, lastDash) : truncated;
|
|
192
|
-
}
|
|
193
108
|
};
|
|
194
109
|
CreateFeatureUseCase = __decorate([
|
|
195
110
|
injectable(),
|
|
@@ -198,7 +113,9 @@ CreateFeatureUseCase = __decorate([
|
|
|
198
113
|
__param(2, inject('IFeatureAgentProcessService')),
|
|
199
114
|
__param(3, inject('IAgentRunRepository')),
|
|
200
115
|
__param(4, inject('ISpecInitializerService')),
|
|
201
|
-
__param(5, inject(
|
|
202
|
-
|
|
116
|
+
__param(5, inject(MetadataGenerator)),
|
|
117
|
+
__param(6, inject(SlugResolver)),
|
|
118
|
+
__metadata("design:paramtypes", [Object, Object, Object, Object, Object, MetadataGenerator,
|
|
119
|
+
SlugResolver])
|
|
203
120
|
], CreateFeatureUseCase);
|
|
204
121
|
export { CreateFeatureUseCase };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetadataGenerator
|
|
3
|
+
*
|
|
4
|
+
* Generates feature metadata (slug, name, description) from user input
|
|
5
|
+
* via AI call through IAgentExecutorProvider.
|
|
6
|
+
* Errors are propagated to the caller.
|
|
7
|
+
*/
|
|
8
|
+
import type { IAgentExecutorProvider } from '../../../ports/output/agents/agent-executor-provider.interface.js';
|
|
9
|
+
import type { FeatureMetadata } from './types.js';
|
|
10
|
+
export declare class MetadataGenerator {
|
|
11
|
+
private readonly executorProvider;
|
|
12
|
+
constructor(executorProvider: IAgentExecutorProvider);
|
|
13
|
+
/**
|
|
14
|
+
* Generate feature metadata from user input via AI.
|
|
15
|
+
* Errors are propagated to the caller.
|
|
16
|
+
*/
|
|
17
|
+
generateMetadata(userInput: string): Promise<FeatureMetadata>;
|
|
18
|
+
/**
|
|
19
|
+
* Strip markdown code fence wrappers (```lang ... ```) if present at start/end.
|
|
20
|
+
*/
|
|
21
|
+
private stripCodeFence;
|
|
22
|
+
/**
|
|
23
|
+
* Convert text to kebab-case slug with 50-char limit.
|
|
24
|
+
* Removes special characters, collapses spaces, limits length.
|
|
25
|
+
*/
|
|
26
|
+
private toSlug;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=metadata-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata-generator.d.ts","sourceRoot":"","sources":["../../../../../../src/application/use-cases/features/create/metadata-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mEAAmE,CAAC;AAChH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAKlD,qBACa,iBAAiB;IAG1B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;gBAAhB,gBAAgB,EAAE,sBAAsB;IAG3D;;;OAGG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAyCnE;;OAEG;IACH,OAAO,CAAC,cAAc;IAgBtB;;;OAGG;IACH,OAAO,CAAC,MAAM;CAgBf"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetadataGenerator
|
|
3
|
+
*
|
|
4
|
+
* Generates feature metadata (slug, name, description) from user input
|
|
5
|
+
* via AI call through IAgentExecutorProvider.
|
|
6
|
+
* Errors are propagated to the caller.
|
|
7
|
+
*/
|
|
8
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
9
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
10
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
11
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
12
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
13
|
+
};
|
|
14
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
15
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
16
|
+
};
|
|
17
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
18
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
19
|
+
};
|
|
20
|
+
import { injectable, inject } from 'tsyringe';
|
|
21
|
+
/** Maximum characters of user input sent to the AI for metadata generation. */
|
|
22
|
+
const MAX_INPUT_FOR_AI = 500;
|
|
23
|
+
let MetadataGenerator = class MetadataGenerator {
|
|
24
|
+
executorProvider;
|
|
25
|
+
constructor(executorProvider) {
|
|
26
|
+
this.executorProvider = executorProvider;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generate feature metadata from user input via AI.
|
|
30
|
+
* Errors are propagated to the caller.
|
|
31
|
+
*/
|
|
32
|
+
async generateMetadata(userInput) {
|
|
33
|
+
const executor = this.executorProvider.getExecutor();
|
|
34
|
+
const truncated = userInput.length > MAX_INPUT_FOR_AI
|
|
35
|
+
? `${userInput.slice(0, MAX_INPUT_FOR_AI)}...`
|
|
36
|
+
: userInput;
|
|
37
|
+
const prompt = `Analyze this user request and extract the CORE feature intent. Condense to essential concepts.
|
|
38
|
+
|
|
39
|
+
User request:
|
|
40
|
+
"${truncated}"
|
|
41
|
+
|
|
42
|
+
IMPORTANT: Don't use the request as-is. Extract the key feature being requested and improve the wording.
|
|
43
|
+
|
|
44
|
+
Return ONLY a JSON object with these fields:
|
|
45
|
+
- slug: kebab-case identifier, 2-4 words MAX. Extract the core feature name (e.g., "github-oauth-login" from "add github oauth")
|
|
46
|
+
- name: polished, professional title (improve upon user's wording)
|
|
47
|
+
- description: refined 1-2 sentence description that captures the feature essence (not the request verbatim)
|
|
48
|
+
|
|
49
|
+
JSON only, no markdown fences.`;
|
|
50
|
+
const result = await executor.execute(prompt, {
|
|
51
|
+
maxTurns: 1,
|
|
52
|
+
allowedTools: [],
|
|
53
|
+
silent: true,
|
|
54
|
+
});
|
|
55
|
+
const cleaned = this.stripCodeFence(result.result);
|
|
56
|
+
const parsed = JSON.parse(cleaned);
|
|
57
|
+
if (!parsed.slug || !parsed.name || !parsed.description) {
|
|
58
|
+
throw new Error('Missing required fields in AI response');
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
slug: this.toSlug(parsed.slug),
|
|
62
|
+
name: parsed.name,
|
|
63
|
+
description: parsed.description,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Strip markdown code fence wrappers (```lang ... ```) if present at start/end.
|
|
68
|
+
*/
|
|
69
|
+
stripCodeFence(text) {
|
|
70
|
+
const trimmed = text.trim();
|
|
71
|
+
if (!trimmed.startsWith('```')) {
|
|
72
|
+
return trimmed;
|
|
73
|
+
}
|
|
74
|
+
// Find end of first line (```json or ```anything)
|
|
75
|
+
const firstNewline = trimmed.indexOf('\n');
|
|
76
|
+
if (firstNewline === -1) {
|
|
77
|
+
return trimmed;
|
|
78
|
+
}
|
|
79
|
+
if (!trimmed.endsWith('```')) {
|
|
80
|
+
return trimmed;
|
|
81
|
+
}
|
|
82
|
+
return trimmed.slice(firstNewline + 1, trimmed.length - 3).trim();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Convert text to kebab-case slug with 50-char limit.
|
|
86
|
+
* Removes special characters, collapses spaces, limits length.
|
|
87
|
+
*/
|
|
88
|
+
toSlug(text) {
|
|
89
|
+
const slug = text
|
|
90
|
+
.toLowerCase()
|
|
91
|
+
.replace(/[^a-z0-9\s-]/g, '')
|
|
92
|
+
.replace(/\s+/g, '-')
|
|
93
|
+
.replace(/-+/g, '-')
|
|
94
|
+
.replace(/^-|-$/g, '');
|
|
95
|
+
// Limit to ~50 chars, cutting at a word boundary
|
|
96
|
+
if (slug.length <= 50) {
|
|
97
|
+
return slug;
|
|
98
|
+
}
|
|
99
|
+
const truncated = slug.slice(0, 50);
|
|
100
|
+
const lastDash = truncated.lastIndexOf('-');
|
|
101
|
+
return lastDash > 10 ? truncated.slice(0, lastDash) : truncated;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
MetadataGenerator = __decorate([
|
|
105
|
+
injectable(),
|
|
106
|
+
__param(0, inject('IAgentExecutorProvider')),
|
|
107
|
+
__metadata("design:paramtypes", [Object])
|
|
108
|
+
], MetadataGenerator);
|
|
109
|
+
export { MetadataGenerator };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SlugResolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves unique slugs by checking against database and git branches.
|
|
5
|
+
* Ensures no slug collision by appending numeric suffixes (-2, -3, etc.)
|
|
6
|
+
*/
|
|
7
|
+
import type { IFeatureRepository } from '../../../ports/output/repositories/feature-repository.interface.js';
|
|
8
|
+
import type { IWorktreeService } from '../../../ports/output/services/worktree-service.interface.js';
|
|
9
|
+
export interface SlugResolutionResult {
|
|
10
|
+
slug: string;
|
|
11
|
+
branch: string;
|
|
12
|
+
warning?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class SlugResolver {
|
|
15
|
+
private readonly featureRepo;
|
|
16
|
+
private readonly worktreeService;
|
|
17
|
+
constructor(featureRepo: IFeatureRepository, worktreeService: IWorktreeService);
|
|
18
|
+
/**
|
|
19
|
+
* Find a unique slug by checking both the feature DB and git branches.
|
|
20
|
+
* If the original slug conflicts, appends -2, -3, etc. until a free one is found.
|
|
21
|
+
*/
|
|
22
|
+
resolveUniqueSlug(originalSlug: string, repositoryPath: string): Promise<SlugResolutionResult>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=slug-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug-resolver.d.ts","sourceRoot":"","sources":["../../../../../../src/application/use-cases/features/create/slug-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oEAAoE,CAAC;AAC7G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8DAA8D,CAAC;AAKrG,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBACa,YAAY;IAGrB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,eAAe;gBAFf,WAAW,EAAE,kBAAkB,EAE/B,eAAe,EAAE,gBAAgB;IAGpD;;;OAGG;IACG,iBAAiB,CACrB,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,oBAAoB,CAAC;CA+BjC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SlugResolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves unique slugs by checking against database and git branches.
|
|
5
|
+
* Ensures no slug collision by appending numeric suffixes (-2, -3, etc.)
|
|
6
|
+
*/
|
|
7
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
8
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
11
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
12
|
+
};
|
|
13
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
14
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
15
|
+
};
|
|
16
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
17
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
18
|
+
};
|
|
19
|
+
import { injectable, inject } from 'tsyringe';
|
|
20
|
+
/** Maximum number of suffix attempts before giving up */
|
|
21
|
+
const MAX_SUFFIX = 10;
|
|
22
|
+
let SlugResolver = class SlugResolver {
|
|
23
|
+
featureRepo;
|
|
24
|
+
worktreeService;
|
|
25
|
+
constructor(featureRepo, worktreeService) {
|
|
26
|
+
this.featureRepo = featureRepo;
|
|
27
|
+
this.worktreeService = worktreeService;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Find a unique slug by checking both the feature DB and git branches.
|
|
31
|
+
* If the original slug conflicts, appends -2, -3, etc. until a free one is found.
|
|
32
|
+
*/
|
|
33
|
+
async resolveUniqueSlug(originalSlug, repositoryPath) {
|
|
34
|
+
for (let suffix = 0; suffix <= MAX_SUFFIX; suffix++) {
|
|
35
|
+
const slug = suffix === 0 ? originalSlug : `${originalSlug}-${suffix + 1}`;
|
|
36
|
+
const branch = `feat/${slug}`;
|
|
37
|
+
// Check if a feature with this slug already exists in the DB
|
|
38
|
+
const existing = await this.featureRepo.findBySlug(slug, repositoryPath);
|
|
39
|
+
if (existing) {
|
|
40
|
+
if (suffix === 0)
|
|
41
|
+
continue; // try suffixed version
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
// Check if the git branch already exists (leftover from deleted feature)
|
|
45
|
+
const branchInUse = await this.worktreeService.exists(repositoryPath, branch);
|
|
46
|
+
if (branchInUse)
|
|
47
|
+
continue;
|
|
48
|
+
if (suffix > 0) {
|
|
49
|
+
return {
|
|
50
|
+
slug,
|
|
51
|
+
branch,
|
|
52
|
+
warning: `Branch "feat/${originalSlug}" already exists, using "${branch}" instead`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return { slug, branch };
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`Could not find a unique slug for "${originalSlug}" after ${MAX_SUFFIX} attempts`);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
SlugResolver = __decorate([
|
|
61
|
+
injectable(),
|
|
62
|
+
__param(0, inject('IFeatureRepository')),
|
|
63
|
+
__param(1, inject('IWorktreeService')),
|
|
64
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
65
|
+
], SlugResolver);
|
|
66
|
+
export { SlugResolver };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ApprovalGates, Feature } from '../../../../domain/generated/output.js';
|
|
2
|
+
export interface CreateFeatureInput {
|
|
3
|
+
userInput: string;
|
|
4
|
+
repositoryPath: string;
|
|
5
|
+
approvalGates?: ApprovalGates;
|
|
6
|
+
}
|
|
7
|
+
export interface CreateFeatureResult {
|
|
8
|
+
feature: Feature;
|
|
9
|
+
warning?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface FeatureMetadata {
|
|
12
|
+
slug: string;
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/application/use-cases/features/create/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AAErF,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InstallToolUseCase
|
|
3
|
+
*
|
|
4
|
+
* Executes the installation of a tool with live output streaming support.
|
|
5
|
+
* Returns detailed status information about the installation result.
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolInstallationStatus } from '../../../domain/generated/output.js';
|
|
8
|
+
import type { IToolInstallerService } from '../../ports/output/services/index.js';
|
|
9
|
+
export declare class InstallToolUseCase {
|
|
10
|
+
private readonly toolInstallerService;
|
|
11
|
+
constructor(toolInstallerService: IToolInstallerService);
|
|
12
|
+
/**
|
|
13
|
+
* Executes installation of a tool with optional output streaming.
|
|
14
|
+
*
|
|
15
|
+
* @param toolName - Name of the tool to install
|
|
16
|
+
* @param onOutput - Optional callback for streaming installation output
|
|
17
|
+
* @returns Status information about the installation result
|
|
18
|
+
*/
|
|
19
|
+
execute(toolName: string, onOutput?: (data: string) => void): Promise<ToolInstallationStatus>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=install-tool.use-case.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-tool.use-case.d.ts","sourceRoot":"","sources":["../../../../../src/application/use-cases/tools/install-tool.use-case.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAElF,qBACa,kBAAkB;IAG3B,OAAO,CAAC,QAAQ,CAAC,oBAAoB;gBAApB,oBAAoB,EAAE,qBAAqB;IAG9D;;;;;;OAMG;IACG,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAChC,OAAO,CAAC,sBAAsB,CAAC;CAGnC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* InstallToolUseCase
|
|
3
|
+
*
|
|
4
|
+
* Executes the installation of a tool with live output streaming support.
|
|
5
|
+
* Returns detailed status information about the installation result.
|
|
6
|
+
*/
|
|
7
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
8
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
11
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
12
|
+
};
|
|
13
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
14
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
15
|
+
};
|
|
16
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
17
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
18
|
+
};
|
|
19
|
+
import { injectable, inject } from 'tsyringe';
|
|
20
|
+
let InstallToolUseCase = class InstallToolUseCase {
|
|
21
|
+
toolInstallerService;
|
|
22
|
+
constructor(toolInstallerService) {
|
|
23
|
+
this.toolInstallerService = toolInstallerService;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Executes installation of a tool with optional output streaming.
|
|
27
|
+
*
|
|
28
|
+
* @param toolName - Name of the tool to install
|
|
29
|
+
* @param onOutput - Optional callback for streaming installation output
|
|
30
|
+
* @returns Status information about the installation result
|
|
31
|
+
*/
|
|
32
|
+
async execute(toolName, onOutput) {
|
|
33
|
+
return this.toolInstallerService.executeInstall(toolName, onOutput);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
InstallToolUseCase = __decorate([
|
|
37
|
+
injectable(),
|
|
38
|
+
__param(0, inject('IToolInstallerService')),
|
|
39
|
+
__metadata("design:paramtypes", [Object])
|
|
40
|
+
], InstallToolUseCase);
|
|
41
|
+
export { InstallToolUseCase };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ValidateToolAvailabilityUseCase
|
|
3
|
+
*
|
|
4
|
+
* Validates if a tool is available on the system by checking its presence in PATH.
|
|
5
|
+
* Returns detailed status information including installation suggestions if missing.
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolInstallationStatus } from '../../../domain/generated/output.js';
|
|
8
|
+
import type { IToolInstallerService } from '../../ports/output/services/index.js';
|
|
9
|
+
export declare class ValidateToolAvailabilityUseCase {
|
|
10
|
+
private readonly toolInstallerService;
|
|
11
|
+
constructor(toolInstallerService: IToolInstallerService);
|
|
12
|
+
/**
|
|
13
|
+
* Validates if a tool is available on the system.
|
|
14
|
+
*
|
|
15
|
+
* @param toolName - Name of the tool to validate
|
|
16
|
+
* @returns Status information about the tool's availability
|
|
17
|
+
*/
|
|
18
|
+
execute(toolName: string): Promise<ToolInstallationStatus>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=validate-tool-availability.use-case.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-tool-availability.use-case.d.ts","sourceRoot":"","sources":["../../../../../src/application/use-cases/tools/validate-tool-availability.use-case.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAElF,qBACa,+BAA+B;IAGxC,OAAO,CAAC,QAAQ,CAAC,oBAAoB;gBAApB,oBAAoB,EAAE,qBAAqB;IAG9D;;;;;OAKG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;CAGjE"}
|