@shepai/cli 1.24.0 → 1.25.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/packages/core/src/application/use-cases/features/create/metadata-generator.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/metadata-generator.js +3 -0
- package/dist/packages/core/src/infrastructure/di/populate-use-cases-bridge.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/populate-use-cases-bridge.js +2 -0
- package/dist/packages/core/src/infrastructure/di/use-cases-bridge.d.ts +9 -1
- package/dist/packages/core/src/infrastructure/di/use-cases-bridge.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/use-cases-bridge.js +17 -1
- package/dist/src/presentation/web/app/api/features/create/route.d.ts +5 -0
- package/dist/src/presentation/web/app/api/features/create/route.d.ts.map +1 -0
- package/dist/src/presentation/web/app/api/features/create/route.js +32 -0
- package/dist/src/presentation/web/app/layout.d.ts.map +1 -1
- package/dist/src/presentation/web/app/layout.js +2 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +2 -2
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +1 -0
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +45 -9
- package/dist/src/presentation/web/dev-server.js +17 -4
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/app-path-routes-manifest.json +1 -0
- 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/.tsbuildinfo +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/routes-manifest.json +6 -0
- 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/page.js +1 -1
- package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_not-found.html +2 -2
- package/web/.next/server/app/_not-found.rsc +13 -12
- package/web/.next/server/app/_not-found.segments/_full.segment.rsc +13 -12
- package/web/.next/server/app/_not-found.segments/_head.segment.rsc +3 -3
- package/web/.next/server/app/_not-found.segments/_index.segment.rsc +5 -4
- package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/api/dialog/pick-files/route.js +2 -2
- package/web/.next/server/app/api/dialog/pick-files/route.js.nft.json +1 -1
- package/web/.next/server/app/api/dialog/pick-folder/route.js +2 -2
- package/web/.next/server/app/api/dialog/pick-folder/route.js.nft.json +1 -1
- package/web/.next/server/app/api/features/create/route/app-paths-manifest.json +3 -0
- package/web/.next/server/app/api/features/create/route/build-manifest.json +11 -0
- package/web/.next/server/app/api/features/create/route/server-reference-manifest.json +4 -0
- package/web/.next/server/app/api/features/create/route.js +6 -0
- package/web/.next/server/app/api/features/create/route.js.map +5 -0
- package/web/.next/server/app/api/features/create/route.js.nft.json +1 -0
- package/web/.next/server/app/api/features/create/route_client-reference-manifest.js +2 -0
- package/web/.next/server/app/page.js +1 -1
- package/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page.js +1 -1
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version.html +2 -2
- package/web/.next/server/app/version.rsc +12 -11
- package/web/.next/server/app/version.segments/_full.segment.rsc +12 -11
- package/web/.next/server/app/version.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/_index.segment.rsc +3 -2
- package/web/.next/server/app/version.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/version/__PAGE__.segment.rsc +2 -2
- package/web/.next/server/app/version.segments/version.segment.rsc +1 -1
- package/web/.next/server/app-paths-manifest.json +1 -0
- package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_features_create_route_actions_de49a114.js +3 -0
- package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_features_create_route_actions_de49a114.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__4e987cf3._.js +8 -0
- package/web/.next/server/chunks/[root-of-the-server]__4e987cf3._.js.map +1 -0
- package/web/.next/server/chunks/{[root-of-the-server]__22cabd43._.js → [root-of-the-server]__a6bf88cc._.js} +3 -3
- package/web/.next/server/chunks/{[root-of-the-server]__22cabd43._.js.map → [root-of-the-server]__a6bf88cc._.js.map} +1 -1
- package/web/.next/server/chunks/{[root-of-the-server]__00833626._.js → [root-of-the-server]__ba6c5641._.js} +2 -2
- package/web/.next/server/chunks/{[root-of-the-server]__00833626._.js.map → [root-of-the-server]__ba6c5641._.js.map} +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__ec87d735._.js +3 -0
- package/web/.next/server/chunks/{[root-of-the-server]__95785ac7._.js.map → [root-of-the-server]__ec87d735._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a21ef212._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a21ef212._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f12b60be._.js +1 -1
- package/web/.next/server/chunks/ssr/_09afa42a._.js +1 -1
- package/web/.next/server/chunks/ssr/_09afa42a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_1c3962d7._.js +10 -0
- package/web/.next/server/chunks/ssr/_1c3962d7._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_67178b88._.js +13 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_67178b88._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js.map +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/static/chunks/{f6b5484377f4e78e.js → 1c236dcc303f3033.js} +1 -1
- package/web/.next/static/chunks/78ef4acb26e4d6ea.js +1 -0
- package/web/.next/static/chunks/79009d1ca0d944d2.js +5 -0
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/web/.next/types/link.d.ts +1 -0
- package/web/.next/types/routes.d.ts +2 -1
- package/web/.next/types/validator.ts +9 -0
- package/web/.next/server/chunks/[root-of-the-server]__95785ac7._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7c64f85c._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7c64f85c._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_1f9347c8._.js +0 -7
- package/web/.next/server/chunks/ssr/_1f9347c8._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_a0c04017._.js +0 -6
- package/web/.next/server/chunks/ssr/_a0c04017._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_372075f9._.js +0 -13
- package/web/.next/server/chunks/ssr/src_presentation_web_372075f9._.js.map +0 -1
- package/web/.next/static/chunks/8bc34062bc0f4ddc.js +0 -1
- package/web/.next/static/chunks/f5099c5888ef9a74.js +0 -5
- /package/web/.next/static/{LOfelu4nKYgB7PB1XlRqc → -dFLqLT3RMg1ueqbAhsJk}/_buildManifest.js +0 -0
- /package/web/.next/static/{LOfelu4nKYgB7PB1XlRqc → -dFLqLT3RMg1ueqbAhsJk}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{LOfelu4nKYgB7PB1XlRqc → -dFLqLT3RMg1ueqbAhsJk}/_ssgManifest.js +0 -0
package/dist/packages/core/src/application/use-cases/features/create/metadata-generator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata-generator.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/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;
|
|
1
|
+
{"version":3,"file":"metadata-generator.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/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;IA4CnE;;OAEG;IACH,OAAO,CAAC,cAAc;IAgBtB;;;OAGG;IACH,OAAO,CAAC,MAAM;CAgBf"}
|
|
@@ -53,6 +53,9 @@ JSON only, no markdown fences.`;
|
|
|
53
53
|
silent: true,
|
|
54
54
|
});
|
|
55
55
|
const cleaned = this.stripCodeFence(result.result);
|
|
56
|
+
if (!cleaned) {
|
|
57
|
+
throw new Error('AI returned empty response for metadata generation');
|
|
58
|
+
}
|
|
56
59
|
const parsed = JSON.parse(cleaned);
|
|
57
60
|
if (!parsed.slug || !parsed.name || !parsed.description) {
|
|
58
61
|
throw new Error('Missing required fields in AI response');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"populate-use-cases-bridge.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/di/populate-use-cases-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"populate-use-cases-bridge.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/di/populate-use-cases-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAMpD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAQnE"}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* @see use-cases-bridge.ts for the reader side (web-safe).
|
|
13
13
|
*/
|
|
14
14
|
import { ListFeaturesUseCase } from '../../application/use-cases/features/list-features.use-case.js';
|
|
15
|
+
import { CreateFeatureUseCase } from '../../application/use-cases/features/create/create-feature.use-case.js';
|
|
15
16
|
import { SHEP_USE_CASES_KEY } from './use-cases-bridge.js';
|
|
16
17
|
/**
|
|
17
18
|
* Populate the globalThis bridge with resolved use cases from the DI container.
|
|
@@ -21,6 +22,7 @@ export function populateUseCasesBridge(c) {
|
|
|
21
22
|
const bridge = {
|
|
22
23
|
listFeatures: c.resolve(ListFeaturesUseCase),
|
|
23
24
|
agentRunRepo: c.resolve('IAgentRunRepository'),
|
|
25
|
+
createFeature: c.resolve(CreateFeatureUseCase),
|
|
24
26
|
};
|
|
25
27
|
globalThis[SHEP_USE_CASES_KEY] = bridge;
|
|
26
28
|
process[SHEP_USE_CASES_KEY] = bridge;
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import type { Feature, AgentRun } from '../../domain/generated/output.js';
|
|
19
19
|
import type { FeatureListFilters } from '../../application/ports/output/repositories/feature-repository.interface.js';
|
|
20
|
-
|
|
20
|
+
import type { CreateFeatureInput, CreateFeatureResult } from '../../application/use-cases/features/create/types.js';
|
|
21
|
+
export type { FeatureListFilters, CreateFeatureInput, CreateFeatureResult };
|
|
21
22
|
/** The globalThis key shared between writer and reader. */
|
|
22
23
|
export declare const SHEP_USE_CASES_KEY = "__shepUseCases";
|
|
23
24
|
/**
|
|
@@ -31,4 +32,11 @@ export declare function getFeatures(filters?: FeatureListFilters): Promise<Featu
|
|
|
31
32
|
* Returns null if the DI bridge is not initialized or the run is not found.
|
|
32
33
|
*/
|
|
33
34
|
export declare function getAgentRun(id: string): Promise<AgentRun | null>;
|
|
35
|
+
/**
|
|
36
|
+
* Create a new feature via the DI-managed use case.
|
|
37
|
+
* Unlike getFeatures/getAgentRun, this function propagates errors so callers
|
|
38
|
+
* (API routes) can return proper HTTP error responses and surface messages to the user.
|
|
39
|
+
* Throws if the bridge is not initialized or the use case fails.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createFeature(input: CreateFeatureInput): Promise<CreateFeatureResult>;
|
|
34
42
|
//# sourceMappingURL=use-cases-bridge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-cases-bridge.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/di/use-cases-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6EAA6E,CAAC;
|
|
1
|
+
{"version":3,"file":"use-cases-bridge.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/di/use-cases-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6EAA6E,CAAC;AACtH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,sDAAsD,CAAC;AAE9D,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,CAAC;AAE5E,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAqCnD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAWlF;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAStE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAO3F"}
|
|
@@ -23,10 +23,13 @@ function isShepUseCases(value) {
|
|
|
23
23
|
const maybe = value;
|
|
24
24
|
const listFeatures = maybe.listFeatures;
|
|
25
25
|
const agentRunRepo = maybe.agentRunRepo;
|
|
26
|
+
const createFeature = maybe.createFeature;
|
|
26
27
|
return (!!listFeatures &&
|
|
27
28
|
typeof listFeatures.execute === 'function' &&
|
|
28
29
|
!!agentRunRepo &&
|
|
29
|
-
typeof agentRunRepo.findById === 'function'
|
|
30
|
+
typeof agentRunRepo.findById === 'function' &&
|
|
31
|
+
!!createFeature &&
|
|
32
|
+
typeof createFeature.execute === 'function');
|
|
30
33
|
}
|
|
31
34
|
function getUseCases() {
|
|
32
35
|
const globalBridge = globalThis[SHEP_USE_CASES_KEY];
|
|
@@ -70,3 +73,16 @@ export async function getAgentRun(id) {
|
|
|
70
73
|
return null;
|
|
71
74
|
}
|
|
72
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Create a new feature via the DI-managed use case.
|
|
78
|
+
* Unlike getFeatures/getAgentRun, this function propagates errors so callers
|
|
79
|
+
* (API routes) can return proper HTTP error responses and surface messages to the user.
|
|
80
|
+
* Throws if the bridge is not initialized or the use case fails.
|
|
81
|
+
*/
|
|
82
|
+
export async function createFeature(input) {
|
|
83
|
+
const useCases = getUseCases();
|
|
84
|
+
if (!useCases?.createFeature) {
|
|
85
|
+
throw new Error('Use-cases bridge is not initialized. Ensure the CLI process is running.');
|
|
86
|
+
}
|
|
87
|
+
return useCases.createFeature.execute(input);
|
|
88
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
export declare function POST(request: Request): Promise<NextResponse<{
|
|
3
|
+
error: string;
|
|
4
|
+
}> | NextResponse<import("../../../../../../../packages/core/src/infrastructure/di/use-cases-bridge.js").CreateFeatureResult>>;
|
|
5
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../../src/presentation/web/app/api/features/create/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA2B3C,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO;;kGA0B1C"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { createFeature } from '../../../../../../../packages/core/src/infrastructure/di/use-cases-bridge.js';
|
|
3
|
+
function composeUserInput(name, description, attachments) {
|
|
4
|
+
let userInput = `Feature: ${name}`;
|
|
5
|
+
if (description) {
|
|
6
|
+
userInput += `\n\n${description}`;
|
|
7
|
+
}
|
|
8
|
+
if (attachments && attachments.length > 0) {
|
|
9
|
+
const paths = attachments.map((a) => `- ${a.path}`).join('\n');
|
|
10
|
+
userInput += `\n\nAttached files:\n${paths}`;
|
|
11
|
+
}
|
|
12
|
+
return userInput;
|
|
13
|
+
}
|
|
14
|
+
export async function POST(request) {
|
|
15
|
+
const body = await request.json();
|
|
16
|
+
const { name, description, repositoryPath, attachments } = body;
|
|
17
|
+
if (!name?.trim()) {
|
|
18
|
+
return NextResponse.json({ error: 'name is required' }, { status: 400 });
|
|
19
|
+
}
|
|
20
|
+
if (!repositoryPath?.trim()) {
|
|
21
|
+
return NextResponse.json({ error: 'repositoryPath is required' }, { status: 400 });
|
|
22
|
+
}
|
|
23
|
+
const userInput = composeUserInput(name, description, attachments);
|
|
24
|
+
try {
|
|
25
|
+
const result = await createFeature({ userInput, repositoryPath });
|
|
26
|
+
return NextResponse.json(result);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
const message = error instanceof Error ? error.message : 'Failed to create feature';
|
|
30
|
+
return NextResponse.json({ error: message }, { status: 500 });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/layout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,6BAA6B,CAAC;AACrC,OAAO,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/app/layout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,6BAA6B,CAAC;AACrC,OAAO,eAAe,CAAC;AAIvB,eAAO,MAAM,QAAQ,EAAE,QAItB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EACjC,QAAQ,GACT,EAAE,QAAQ,CAAC;IACV,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC,2CA0BD"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import '@xyflow/react/dist/base.css';
|
|
3
3
|
import './globals.css';
|
|
4
4
|
import { AppShell } from '../components/layouts/app-shell/index.js';
|
|
5
|
+
import { Toaster } from '../components/ui/sonner.js';
|
|
5
6
|
export const metadata = {
|
|
6
7
|
title: 'Shep AI',
|
|
7
8
|
description: 'Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy',
|
|
@@ -19,5 +20,5 @@ export default function RootLayout({ children, }) {
|
|
|
19
20
|
} catch (e) {}
|
|
20
21
|
})();
|
|
21
22
|
`,
|
|
22
|
-
} }) }),
|
|
23
|
+
} }) }), _jsxs("body", { className: "min-h-screen antialiased", children: [_jsx(AppShell, { children: children }), _jsx(Toaster, {})] })] }));
|
|
23
24
|
}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAK5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAK5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CAkDzF"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -6,12 +6,12 @@ import { FeatureDrawer, FeatureCreateDrawer } from '../../common/index.js';
|
|
|
6
6
|
import { ControlCenterEmptyState } from './control-center-empty-state.js';
|
|
7
7
|
import { useControlCenterState } from './use-control-center-state.js';
|
|
8
8
|
export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
9
|
-
const { nodes, edges, selectedNode, isCreateDrawerOpen, onNodesChange, handleConnect, handleAddFeature, handleAddFeatureToRepo, handleAddFeatureToFeature, handleAddRepository, handleNodeClick, clearSelection, handleCreateFeatureSubmit, closeCreateDrawer, } = useControlCenterState(initialNodes, initialEdges);
|
|
9
|
+
const { nodes, edges, selectedNode, isCreateDrawerOpen, isSubmitting, onNodesChange, handleConnect, handleAddFeature, handleAddFeatureToRepo, handleAddFeatureToFeature, handleAddRepository, handleNodeClick, clearSelection, handleCreateFeatureSubmit, closeCreateDrawer, } = useControlCenterState(initialNodes, initialEdges);
|
|
10
10
|
// Listen for global "open create drawer" events from the sidebar
|
|
11
11
|
useEffect(() => {
|
|
12
12
|
const handler = () => handleAddFeature();
|
|
13
13
|
window.addEventListener('shep:open-create-drawer', handler);
|
|
14
14
|
return () => window.removeEventListener('shep:open-create-drawer', handler);
|
|
15
15
|
}, [handleAddFeature]);
|
|
16
|
-
return (_jsxs(_Fragment, { children: [_jsx(FeaturesCanvas, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeAction: handleAddFeatureToFeature, onNodeClick: handleNodeClick, onPaneClick: clearSelection, onRepositoryAdd: handleAddFeatureToRepo, onRepositorySelect: handleAddRepository, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: handleAddRepository }) }), _jsx(FeatureDrawer, { selectedNode: selectedNode, onClose: clearSelection }), _jsx(FeatureCreateDrawer, { open: isCreateDrawerOpen, onClose: closeCreateDrawer, onSubmit: handleCreateFeatureSubmit })] }));
|
|
16
|
+
return (_jsxs(_Fragment, { children: [_jsx(FeaturesCanvas, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeAction: handleAddFeatureToFeature, onNodeClick: handleNodeClick, onPaneClick: clearSelection, onRepositoryAdd: handleAddFeatureToRepo, onRepositorySelect: handleAddRepository, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: handleAddRepository }) }), _jsx(FeatureDrawer, { selectedNode: selectedNode, onClose: clearSelection }), _jsx(FeatureCreateDrawer, { open: isCreateDrawerOpen, onClose: closeCreateDrawer, onSubmit: handleCreateFeatureSubmit, isSubmitting: isSubmitting })] }));
|
|
17
17
|
}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface ControlCenterState {
|
|
|
8
8
|
edges: Edge[];
|
|
9
9
|
selectedNode: FeatureNodeData | null;
|
|
10
10
|
isCreateDrawerOpen: boolean;
|
|
11
|
+
isSubmitting: boolean;
|
|
11
12
|
onNodesChange: (changes: NodeChange<CanvasNodeType>[]) => void;
|
|
12
13
|
handleConnect: (connection: Connection) => void;
|
|
13
14
|
clearSelection: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEhF,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,eAAe,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACzE,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,sBAAsB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,yBAAyB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,yBAAyB,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACjE,iBAAiB,EAAE,MAAM,IAAI,CAAC;CAC/B;AAID,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAmTpB"}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useState, useCallback, useEffect } from 'react';
|
|
3
|
+
import { useRouter } from 'next/navigation';
|
|
4
|
+
import { toast } from 'sonner';
|
|
3
5
|
import { applyNodeChanges } from '@xyflow/react';
|
|
4
6
|
import { layoutWithDagre } from '../../../lib/layout-with-dagre.js';
|
|
5
7
|
let nextFeatureId = 0;
|
|
6
8
|
export function useControlCenterState(initialNodes, initialEdges) {
|
|
9
|
+
const router = useRouter();
|
|
7
10
|
const [nodes, setNodes] = useState(initialNodes);
|
|
8
11
|
const [edges, setEdges] = useState(initialEdges);
|
|
9
12
|
const [selectedNode, setSelectedNode] = useState(null);
|
|
10
13
|
const [isCreateDrawerOpen, setIsCreateDrawerOpen] = useState(false);
|
|
14
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
15
|
+
const [pendingRepoNodeId, setPendingRepoNodeId] = useState(null);
|
|
11
16
|
const onNodesChange = useCallback((changes) => {
|
|
12
17
|
setNodes((ns) => applyNodeChanges(changes, ns));
|
|
13
18
|
}, []);
|
|
@@ -161,19 +166,49 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
161
166
|
setSelectedNode(null);
|
|
162
167
|
setIsCreateDrawerOpen(true);
|
|
163
168
|
}, []);
|
|
164
|
-
const handleCreateFeatureSubmit = useCallback((data) => {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
const handleCreateFeatureSubmit = useCallback(async (data) => {
|
|
170
|
+
if (!pendingRepoNodeId) {
|
|
171
|
+
toast.error('Please create the feature from a repository node.');
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const repositoryPath = pendingRepoNodeId.replace(/^repo-/, '');
|
|
175
|
+
setIsSubmitting(true);
|
|
176
|
+
try {
|
|
177
|
+
const response = await fetch('/api/features/create', {
|
|
178
|
+
method: 'POST',
|
|
179
|
+
headers: { 'Content-Type': 'application/json' },
|
|
180
|
+
body: JSON.stringify({
|
|
181
|
+
name: data.name,
|
|
182
|
+
description: data.description || '',
|
|
183
|
+
repositoryPath,
|
|
184
|
+
attachments: data.attachments,
|
|
185
|
+
}),
|
|
186
|
+
});
|
|
187
|
+
if (!response.ok) {
|
|
188
|
+
const body = await response.json();
|
|
189
|
+
toast.error(body.error ?? 'Failed to create feature');
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
setIsCreateDrawerOpen(false);
|
|
193
|
+
setPendingRepoNodeId(null);
|
|
194
|
+
toast.success('Feature created successfully');
|
|
195
|
+
router.refresh();
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
toast.error('Failed to create feature');
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
setIsSubmitting(false);
|
|
202
|
+
}
|
|
203
|
+
}, [pendingRepoNodeId, router]);
|
|
171
204
|
const closeCreateDrawer = useCallback(() => {
|
|
172
205
|
setIsCreateDrawerOpen(false);
|
|
173
206
|
}, []);
|
|
174
207
|
const handleAddFeatureToRepo = useCallback((repoNodeId) => {
|
|
175
|
-
|
|
176
|
-
|
|
208
|
+
setSelectedNode(null);
|
|
209
|
+
setPendingRepoNodeId(repoNodeId);
|
|
210
|
+
setIsCreateDrawerOpen(true);
|
|
211
|
+
}, []);
|
|
177
212
|
const handleAddFeatureToFeature = useCallback((featureNodeId) => {
|
|
178
213
|
createFeatureNode(featureNodeId);
|
|
179
214
|
}, [createFeatureNode]);
|
|
@@ -220,6 +255,7 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
220
255
|
edges,
|
|
221
256
|
selectedNode,
|
|
222
257
|
isCreateDrawerOpen,
|
|
258
|
+
isSubmitting,
|
|
223
259
|
onNodesChange,
|
|
224
260
|
handleConnect,
|
|
225
261
|
clearSelection,
|
|
@@ -39,21 +39,34 @@ async function main() {
|
|
|
39
39
|
const server = http.createServer((req, res) => {
|
|
40
40
|
handle(req, res);
|
|
41
41
|
});
|
|
42
|
+
// Forward WebSocket upgrades to Next.js for HMR/Fast Refresh
|
|
43
|
+
server.on('upgrade', (req, socket, head) => {
|
|
44
|
+
app.getUpgradeHandler()(req, socket, head);
|
|
45
|
+
});
|
|
42
46
|
await new Promise((resolve, reject) => {
|
|
43
47
|
server.on('error', reject);
|
|
44
48
|
server.listen(port, 'localhost', resolve);
|
|
45
49
|
});
|
|
46
50
|
console.log(`[dev-server] Ready at http://localhost:${port}`);
|
|
47
|
-
// Graceful shutdown
|
|
51
|
+
// Graceful shutdown with timeout to avoid hanging on open connections
|
|
48
52
|
let isShuttingDown = false;
|
|
49
53
|
const shutdown = async () => {
|
|
50
54
|
if (isShuttingDown)
|
|
51
55
|
return;
|
|
52
56
|
isShuttingDown = true;
|
|
53
57
|
console.log('\n[dev-server] Shutting down...');
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
const forceExit = setTimeout(() => process.exit(0), 2000);
|
|
59
|
+
try {
|
|
60
|
+
server.closeAllConnections();
|
|
61
|
+
await Promise.all([
|
|
62
|
+
new Promise((resolve) => server.close(() => resolve())),
|
|
63
|
+
app.close(),
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
clearTimeout(forceExit);
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
57
70
|
};
|
|
58
71
|
process.on('SIGINT', shutdown);
|
|
59
72
|
process.on('SIGTERM', shutdown);
|