@shepai/cli 1.119.0 → 1.120.0-pr384.fdb89bb
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/ports/output/services/agent-deployment-service.interface.d.ts +46 -0
- package/dist/packages/core/src/application/ports/output/services/agent-deployment-service.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/agent-deployment-service.interface.js +13 -0
- package/dist/packages/core/src/application/ports/output/services/deployment-service.interface.d.ts +9 -1
- package/dist/packages/core/src/application/ports/output/services/deployment-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/dev-environment-agent.interface.d.ts +65 -0
- package/dist/packages/core/src/application/ports/output/services/dev-environment-agent.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/dev-environment-agent.interface.js +14 -0
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +19 -0
- package/dist/packages/core/src/infrastructure/services/deployment/agent-deployment.service.d.ts +30 -0
- package/dist/packages/core/src/infrastructure/services/deployment/agent-deployment.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/deployment/agent-deployment.service.js +110 -0
- package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.d.ts +6 -2
- package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.js +30 -13
- package/dist/packages/core/src/infrastructure/services/deployment/dev-environment-agent.service.d.ts +35 -0
- package/dist/packages/core/src/infrastructure/services/deployment/dev-environment-agent.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/deployment/dev-environment-agent.service.js +210 -0
- package/dist/src/presentation/web/app/actions/deploy-feature.d.ts +2 -1
- package/dist/src/presentation/web/app/actions/deploy-feature.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/deploy-feature.js +9 -6
- package/dist/src/presentation/web/app/actions/deploy-repository.d.ts +2 -1
- package/dist/src/presentation/web/app/actions/deploy-repository.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/deploy-repository.js +9 -6
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.d.ts.map +1 -1
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +8 -3
- 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/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +21 -21
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +21 -21
- package/web/.next/server/app/(dashboard)/create/page.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +19 -19
- package/web/.next/server/app/(dashboard)/page.js +1 -1
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +19 -19
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +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/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/skills/page.js +1 -2
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/tools/page.js +1 -2
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0534f358._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0534f358._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3b14e5a0._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3b14e5a0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b59c03e._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b59c03e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8c553503._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__994ad9fe._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__994ad9fe._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__997ccfcc._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__997ccfcc._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a6c615b8._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a6c615b8._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c9c1cfee._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c9c1cfee._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_2f6f48b8._.js +1 -1
- package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_aeb74a70._.js → _3b5f25fa._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_aeb74a70._.js.map → _3b5f25fa._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_3c9e300b._.js +3 -0
- package/web/.next/server/chunks/ssr/{_59ae996e._.js.map → _3c9e300b._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_bed4bbb9._.js → _83b11c33._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_bed4bbb9._.js.map → _83b11c33._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_ab069e13._.js +1 -1
- package/web/.next/server/chunks/ssr/_ab069e13._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js.map +1 -1
- 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 +33 -33
- package/web/.next/static/chunks/06702284aedb4e13.js +1 -0
- package/web/.next/static/chunks/{2b35632c1b784fae.js → 2f9dcf87c0a9c513.js} +1 -1
- package/web/.next/static/chunks/{3678617c34576e18.js → 57063722dbce9768.js} +2 -2
- package/web/.next/static/chunks/{ed113fb744f2e4d8.js → 652d07e1b3da6fd3.js} +1 -1
- package/web/.next/static/chunks/{7c57a9143e66868c.js → 6e9701fc52697f2b.js} +1 -1
- package/web/.next/static/chunks/{619af41a8d3232e5.js → 71161130b2462279.js} +1 -1
- package/web/.next/static/chunks/{f3c4a7bb76c69b01.js → 720858e147830a1b.js} +1 -1
- package/web/.next/static/chunks/{c1a6934d2281c088.js → 7da5a2bd92f03feb.js} +1 -1
- package/web/.next/static/chunks/{30097f88cdf8fad8.js → 83e2aac7e244633a.js} +1 -1
- package/web/.next/static/chunks/9e8ebcb706d0ca6f.js +1 -0
- package/web/.next/static/chunks/{69c6d3ba1606e98d.js → f81995913dac5269.js} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b724df9e._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b724df9e._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_59ae996e._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +0 -1
- package/web/.next/static/chunks/1c5310cfde612b81.js +0 -1
- package/web/.next/static/chunks/c4477c532d2081e8.js +0 -1
- /package/web/.next/static/{qmHUdyRBvaVksgjcL6w-m → yAqHoeHdmindXxK6kOd6a}/_buildManifest.js +0 -0
- /package/web/.next/static/{qmHUdyRBvaVksgjcL6w-m → yAqHoeHdmindXxK6kOd6a}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{qmHUdyRBvaVksgjcL6w-m → yAqHoeHdmindXxK6kOd6a}/_ssgManifest.js +0 -0
package/dist/packages/core/src/infrastructure/services/deployment/dev-environment-agent.service.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev Environment Agent Service
|
|
3
|
+
*
|
|
4
|
+
* AI-driven service that analyzes any repository to determine how to start
|
|
5
|
+
* a local dev environment. Language-agnostic — supports Node.js, Python,
|
|
6
|
+
* Go, Rust, Java, Ruby, and more. Uses structured agent calls to get
|
|
7
|
+
* typed analysis results.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - In-memory per-repo caching for fast repeated calls
|
|
11
|
+
* - Reads key config files (package.json, Cargo.toml, etc.) for context
|
|
12
|
+
* - Handles "not deployable" repos gracefully
|
|
13
|
+
* - Truncates large files to prevent prompt overflow
|
|
14
|
+
*/
|
|
15
|
+
import { readdirSync, readFileSync, existsSync } from 'node:fs';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
import { createDeploymentLogger } from './deployment-logger.js';
|
|
18
|
+
const log = createDeploymentLogger('[DevEnvironmentAgent]');
|
|
19
|
+
/** Max characters to include from any single config file. */
|
|
20
|
+
const MAX_FILE_CONTENT_LENGTH = 4000;
|
|
21
|
+
/** Config files to read and include in the prompt, in priority order. */
|
|
22
|
+
const CONFIG_FILES = [
|
|
23
|
+
'package.json',
|
|
24
|
+
'docker-compose.yml',
|
|
25
|
+
'docker-compose.yaml',
|
|
26
|
+
'Dockerfile',
|
|
27
|
+
'Makefile',
|
|
28
|
+
'Cargo.toml',
|
|
29
|
+
'go.mod',
|
|
30
|
+
'requirements.txt',
|
|
31
|
+
'Pipfile',
|
|
32
|
+
'pyproject.toml',
|
|
33
|
+
'setup.py',
|
|
34
|
+
'Gemfile',
|
|
35
|
+
'build.gradle',
|
|
36
|
+
'pom.xml',
|
|
37
|
+
'mix.exs',
|
|
38
|
+
'deno.json',
|
|
39
|
+
'bun.lockb',
|
|
40
|
+
];
|
|
41
|
+
/** JSON schema for the structured agent response. */
|
|
42
|
+
const ANALYSIS_SCHEMA = {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
deployable: {
|
|
46
|
+
type: 'boolean',
|
|
47
|
+
description: 'Whether this repository has a startable dev server or UI. False for libraries, scripts, data repos, etc.',
|
|
48
|
+
},
|
|
49
|
+
reason: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'Brief explanation of what was detected or why the repo is not deployable.',
|
|
52
|
+
},
|
|
53
|
+
command: {
|
|
54
|
+
type: ['string', 'null'],
|
|
55
|
+
description: 'The shell command to start the dev server. Null if not deployable.',
|
|
56
|
+
},
|
|
57
|
+
cwd: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
description: 'Working directory relative to repo root where the command should run. Use "." for repo root.',
|
|
60
|
+
},
|
|
61
|
+
expectedPort: {
|
|
62
|
+
type: ['integer', 'null'],
|
|
63
|
+
description: 'Expected port the dev server will listen on. Null if unknown.',
|
|
64
|
+
},
|
|
65
|
+
language: {
|
|
66
|
+
type: ['string', 'null'],
|
|
67
|
+
description: 'Primary language/runtime (e.g., "node", "python", "go", "rust", "ruby", "java").',
|
|
68
|
+
},
|
|
69
|
+
framework: {
|
|
70
|
+
type: ['string', 'null'],
|
|
71
|
+
description: 'Detected framework if any (e.g., "next.js", "django", "flask", "gin", "rails").',
|
|
72
|
+
},
|
|
73
|
+
setupCommands: {
|
|
74
|
+
type: 'array',
|
|
75
|
+
items: { type: 'string' },
|
|
76
|
+
description: 'Setup commands to run before the dev command (e.g., "npm install", "pip install -r requirements.txt").',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
required: [
|
|
80
|
+
'deployable',
|
|
81
|
+
'reason',
|
|
82
|
+
'command',
|
|
83
|
+
'cwd',
|
|
84
|
+
'expectedPort',
|
|
85
|
+
'language',
|
|
86
|
+
'framework',
|
|
87
|
+
'setupCommands',
|
|
88
|
+
],
|
|
89
|
+
additionalProperties: false,
|
|
90
|
+
};
|
|
91
|
+
const defaultDeps = {
|
|
92
|
+
structuredAgentCaller: null,
|
|
93
|
+
readdir: (path) => readdirSync(path, { encoding: 'utf-8' }),
|
|
94
|
+
readFile: (path) => readFileSync(path, 'utf-8'),
|
|
95
|
+
existsSync,
|
|
96
|
+
};
|
|
97
|
+
export class DevEnvironmentAgentService {
|
|
98
|
+
cache = new Map();
|
|
99
|
+
deps;
|
|
100
|
+
constructor(deps) {
|
|
101
|
+
this.deps = { ...defaultDeps, ...deps };
|
|
102
|
+
}
|
|
103
|
+
async analyze(repositoryPath, options) {
|
|
104
|
+
log.info(`analyze() called — repositoryPath="${repositoryPath}", skipCache=${options?.skipCache ?? false}`);
|
|
105
|
+
if (!this.deps.existsSync(repositoryPath)) {
|
|
106
|
+
throw new Error(`Repository path does not exist: ${repositoryPath}`);
|
|
107
|
+
}
|
|
108
|
+
// Check cache
|
|
109
|
+
if (!options?.skipCache) {
|
|
110
|
+
const cached = this.cache.get(repositoryPath);
|
|
111
|
+
if (cached) {
|
|
112
|
+
log.info(`cache hit for "${repositoryPath}"`);
|
|
113
|
+
return cached;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Build prompt with repo context
|
|
117
|
+
const prompt = this.buildPrompt(repositoryPath);
|
|
118
|
+
log.info(`calling structured agent for "${repositoryPath}"`);
|
|
119
|
+
const result = await this.deps.structuredAgentCaller.call(prompt, ANALYSIS_SCHEMA, {
|
|
120
|
+
silent: true,
|
|
121
|
+
maxTurns: 3,
|
|
122
|
+
cwd: repositoryPath,
|
|
123
|
+
});
|
|
124
|
+
// Cache successful result
|
|
125
|
+
this.cache.set(repositoryPath, result);
|
|
126
|
+
log.info(`analysis complete — deployable=${result.deployable}, command=${result.command}, language=${result.language}`);
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
clearCache(repositoryPath) {
|
|
130
|
+
log.info(`clearCache() — repositoryPath="${repositoryPath}"`);
|
|
131
|
+
this.cache.delete(repositoryPath);
|
|
132
|
+
}
|
|
133
|
+
clearAllCaches() {
|
|
134
|
+
log.info(`clearAllCaches() — clearing ${this.cache.size} entries`);
|
|
135
|
+
this.cache.clear();
|
|
136
|
+
}
|
|
137
|
+
buildPrompt(repositoryPath) {
|
|
138
|
+
const dirListing = this.getDirListing(repositoryPath);
|
|
139
|
+
const configContents = this.readConfigFiles(repositoryPath, dirListing);
|
|
140
|
+
return `You are a dev environment analysis agent. Analyze this repository and determine how to start a local development server.
|
|
141
|
+
|
|
142
|
+
## Repository Directory Listing (root level)
|
|
143
|
+
|
|
144
|
+
${dirListing.join('\n')}
|
|
145
|
+
|
|
146
|
+
## Config File Contents
|
|
147
|
+
|
|
148
|
+
${configContents}
|
|
149
|
+
|
|
150
|
+
## Instructions
|
|
151
|
+
|
|
152
|
+
Analyze the repository structure and config files above to determine:
|
|
153
|
+
|
|
154
|
+
1. **Is this repo deployable?** Does it have a web server, API server, or UI that can be started locally?
|
|
155
|
+
- Libraries (npm packages, Python packages, Go modules meant only for import) are NOT deployable
|
|
156
|
+
- CLI tools that don't serve HTTP are NOT deployable
|
|
157
|
+
- Data repositories, documentation-only repos are NOT deployable
|
|
158
|
+
- Scripts that run once and exit are NOT deployable
|
|
159
|
+
|
|
160
|
+
2. **What command starts the dev server?** Consider:
|
|
161
|
+
- Node.js: \`npm run dev\`, \`pnpm dev\`, \`yarn dev\`, \`npm start\`
|
|
162
|
+
- Python: \`python manage.py runserver\`, \`flask run\`, \`uvicorn main:app --reload\`
|
|
163
|
+
- Go: \`go run .\`, \`air\` (hot reload)
|
|
164
|
+
- Rust: \`cargo run\`, \`cargo watch -x run\`
|
|
165
|
+
- Ruby: \`rails server\`, \`bundle exec rails s\`
|
|
166
|
+
- Java: \`./gradlew bootRun\`, \`mvn spring-boot:run\`
|
|
167
|
+
- Docker: \`docker-compose up\`
|
|
168
|
+
- Generic: \`make dev\`, \`make run\`
|
|
169
|
+
|
|
170
|
+
3. **What port will it listen on?** Check config files for port definitions.
|
|
171
|
+
|
|
172
|
+
4. **What setup is needed first?** (e.g., install dependencies)
|
|
173
|
+
|
|
174
|
+
If the repo has NO server or UI to start, set deployable=false and explain why.
|
|
175
|
+
|
|
176
|
+
Respond with ONLY the JSON object matching the schema.`;
|
|
177
|
+
}
|
|
178
|
+
getDirListing(repositoryPath) {
|
|
179
|
+
try {
|
|
180
|
+
return this.deps.readdir(repositoryPath);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
log.warn(`Failed to read directory listing for "${repositoryPath}"`);
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
readConfigFiles(repositoryPath, dirListing) {
|
|
188
|
+
const sections = [];
|
|
189
|
+
for (const configFile of CONFIG_FILES) {
|
|
190
|
+
if (!dirListing.includes(configFile))
|
|
191
|
+
continue;
|
|
192
|
+
try {
|
|
193
|
+
const filePath = join(repositoryPath, configFile);
|
|
194
|
+
let content = this.deps.readFile(filePath);
|
|
195
|
+
// Truncate large files
|
|
196
|
+
if (content.length > MAX_FILE_CONTENT_LENGTH) {
|
|
197
|
+
content = `${content.slice(0, MAX_FILE_CONTENT_LENGTH)}\n... (truncated)`;
|
|
198
|
+
}
|
|
199
|
+
sections.push(`### ${configFile}\n\`\`\`\n${content}\n\`\`\``);
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
log.warn(`Failed to read config file "${configFile}" in "${repositoryPath}"`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (sections.length === 0) {
|
|
206
|
+
return 'No recognized config files found.';
|
|
207
|
+
}
|
|
208
|
+
return sections.join('\n\n');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { DeploymentState } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
1
|
+
import type { DeploymentState } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
2
2
|
export declare function deployFeature(featureId: string): Promise<{
|
|
3
3
|
success: boolean;
|
|
4
4
|
error?: string;
|
|
5
5
|
state?: DeploymentState;
|
|
6
|
+
reason?: string;
|
|
6
7
|
}>;
|
|
7
8
|
//# sourceMappingURL=deploy-feature.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/deploy-feature.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/deploy-feature.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAI5E,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6CzF"}
|
|
@@ -3,7 +3,6 @@ import { existsSync } from 'node:fs';
|
|
|
3
3
|
import { resolve } from '../../lib/server-container.js';
|
|
4
4
|
import { createDeploymentLogger } from '../../../../../packages/core/src/infrastructure/services/deployment/deployment-logger.js';
|
|
5
5
|
import { computeWorktreePath } from '../../../../../packages/core/src/infrastructure/services/ide-launchers/compute-worktree-path.js';
|
|
6
|
-
import { DeploymentState } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
7
6
|
const log = createDeploymentLogger('[deployFeature]');
|
|
8
7
|
export async function deployFeature(featureId) {
|
|
9
8
|
log.info(`called — featureId="${featureId}"`);
|
|
@@ -25,11 +24,15 @@ export async function deployFeature(featureId) {
|
|
|
25
24
|
log.warn(`worktree path does not exist on disk: "${worktreePath}"`);
|
|
26
25
|
return { success: false, error: `Worktree path does not exist: ${worktreePath}` };
|
|
27
26
|
}
|
|
28
|
-
log.info('worktree path exists, calling
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
log.info('worktree path exists, calling agentDeploymentService.deploy()');
|
|
28
|
+
const agentDeploymentService = resolve('IAgentDeploymentService');
|
|
29
|
+
const result = await agentDeploymentService.deploy(featureId, worktreePath);
|
|
30
|
+
if (!result.success) {
|
|
31
|
+
log.warn(`agent deployment returned not-deployable: ${result.error}`);
|
|
32
|
+
return { success: false, error: result.error, reason: result.analysis?.reason };
|
|
33
|
+
}
|
|
34
|
+
log.info('deploy() returned successfully — state=Booting');
|
|
35
|
+
return { success: true, state: result.state };
|
|
33
36
|
}
|
|
34
37
|
catch (error) {
|
|
35
38
|
const message = error instanceof Error ? error.message : 'Failed to deploy feature';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { DeploymentState } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
1
|
+
import type { DeploymentState } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
2
2
|
export declare function deployRepository(repositoryPath: string): Promise<{
|
|
3
3
|
success: boolean;
|
|
4
4
|
error?: string;
|
|
5
5
|
state?: DeploymentState;
|
|
6
|
+
reason?: string;
|
|
6
7
|
}>;
|
|
7
8
|
//# sourceMappingURL=deploy-repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-repository.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/deploy-repository.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy-repository.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/deploy-repository.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAI5E,wBAAsB,gBAAgB,CACpC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA8BzF"}
|
|
@@ -3,7 +3,6 @@ import { existsSync } from 'node:fs';
|
|
|
3
3
|
import { isAbsolute } from 'node:path';
|
|
4
4
|
import { resolve } from '../../lib/server-container.js';
|
|
5
5
|
import { createDeploymentLogger } from '../../../../../packages/core/src/infrastructure/services/deployment/deployment-logger.js';
|
|
6
|
-
import { DeploymentState } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
7
6
|
const log = createDeploymentLogger('[deployRepository]');
|
|
8
7
|
export async function deployRepository(repositoryPath) {
|
|
9
8
|
log.info(`called — repositoryPath="${repositoryPath}"`);
|
|
@@ -16,11 +15,15 @@ export async function deployRepository(repositoryPath) {
|
|
|
16
15
|
log.warn(`directory does not exist: "${repositoryPath}"`);
|
|
17
16
|
return { success: false, error: `Directory does not exist: ${repositoryPath}` };
|
|
18
17
|
}
|
|
19
|
-
log.info('directory exists, calling
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
log.info('directory exists, calling agentDeploymentService.deploy()');
|
|
19
|
+
const agentDeploymentService = resolve('IAgentDeploymentService');
|
|
20
|
+
const result = await agentDeploymentService.deploy(repositoryPath, repositoryPath);
|
|
21
|
+
if (!result.success) {
|
|
22
|
+
log.warn(`agent deployment returned not-deployable: ${result.error}`);
|
|
23
|
+
return { success: false, error: result.error, reason: result.analysis?.reason };
|
|
24
|
+
}
|
|
25
|
+
log.info('deploy() returned successfully — state=Booting');
|
|
26
|
+
return { success: true, state: result.state };
|
|
24
27
|
}
|
|
25
28
|
catch (error) {
|
|
26
29
|
const message = error instanceof Error ? error.message : 'Failed to deploy repository';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/layouts/app-shell/app-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAsBvE,UAAU,aAAa;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/layouts/app-shell/app-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAsBvE,UAAU,aAAa;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB;AA0FD,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,EAAE,aAAa,2CAUnD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useMemo, useState } from 'react';
|
|
4
|
-
import { useRouter } from 'next/navigation';
|
|
4
|
+
import { useRouter, usePathname } from 'next/navigation';
|
|
5
5
|
import { Plus, FolderPlus } from 'lucide-react';
|
|
6
6
|
import { SidebarProvider, SidebarInset } from '../../ui/sidebar.js';
|
|
7
7
|
import { AppSidebar } from '../../layouts/app-sidebar/index.js';
|
|
@@ -14,9 +14,14 @@ import { DrawerCloseGuardProvider, useDrawerCloseGuard } from '../../../hooks/dr
|
|
|
14
14
|
import { SidebarFeaturesProvider, useSidebarFeaturesContext, } from '../../../hooks/sidebar-features-context.js';
|
|
15
15
|
import { useNotifications } from '../../../hooks/use-notifications.js';
|
|
16
16
|
import { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
|
|
17
|
-
/**
|
|
17
|
+
/** Control center route prefixes where the FAB should be visible. */
|
|
18
|
+
const CONTROL_CENTER_PREFIXES = ['/', '/create', '/feature', '/repository'];
|
|
19
|
+
function isControlCenterRoute(pathname) {
|
|
20
|
+
return CONTROL_CENTER_PREFIXES.some((prefix) => pathname === prefix || (prefix !== '/' && pathname.startsWith(`${prefix}/`)));
|
|
21
|
+
}
|
|
18
22
|
function AppShellInner({ children }) {
|
|
19
23
|
const router = useRouter();
|
|
24
|
+
const pathname = usePathname();
|
|
20
25
|
const { guardedNavigate } = useDrawerCloseGuard();
|
|
21
26
|
const featureFlags = useFeatureFlags();
|
|
22
27
|
// Subscribe to agent lifecycle events and dispatch toast/browser notifications
|
|
@@ -58,7 +63,7 @@ function AppShellInner({ children }) {
|
|
|
58
63
|
loading: addingRepo,
|
|
59
64
|
},
|
|
60
65
|
], [handleNewFeature, handleAddRepository, addingRepo]);
|
|
61
|
-
return (_jsxs(SidebarProvider, { defaultOpen: false, children: [_jsx(AppSidebar, { features: features, featureFlags: featureFlags, onFeatureClick: handleFeatureClick }), _jsx(SidebarInset, { children: _jsxs("div", { className: "relative h-full", children: [_jsxs("div", { className: "absolute top-3 right-3 z-50 flex gap-1", "data-test-id": "canvas-actions-toolbar", children: [_jsx(SoundToggle, {}), _jsx(ThemeToggle, {})] }), _jsx("main", { className: "h-full", children: children }), _jsx(FloatingActionButton, { actions: fabActions })] }) })] }));
|
|
66
|
+
return (_jsxs(SidebarProvider, { defaultOpen: false, children: [_jsx(AppSidebar, { features: features, featureFlags: featureFlags, onFeatureClick: handleFeatureClick }), _jsx(SidebarInset, { children: _jsxs("div", { className: "relative h-full", children: [_jsxs("div", { className: "absolute top-3 right-3 z-50 flex gap-1", "data-test-id": "canvas-actions-toolbar", children: [_jsx(SoundToggle, {}), _jsx(ThemeToggle, {})] }), _jsx("main", { className: "h-full", children: children }), isControlCenterRoute(pathname) && _jsx(FloatingActionButton, { actions: fabActions })] }) })] }));
|
|
62
67
|
}
|
|
63
68
|
export function AppShell({ children }) {
|
|
64
69
|
return (_jsx(AgentEventsProvider, { children: _jsx(DrawerCloseGuardProvider, { children: _jsx(SidebarFeaturesProvider, { children: _jsx(AppShellInner, { children: children }) }) }) }));
|