speckit-assistant 0.1.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/.next/BUILD_ID +1 -0
- package/.next/app-build-manifest.json +71 -0
- package/.next/app-path-routes-manifest.json +10 -0
- package/.next/build-manifest.json +33 -0
- package/.next/cache/.previewinfo +1 -0
- package/.next/cache/.rscinfo +1 -0
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/1.pack +0 -0
- package/.next/cache/webpack/client-production/10.pack +0 -0
- package/.next/cache/webpack/client-production/11.pack +0 -0
- package/.next/cache/webpack/client-production/12.pack +0 -0
- package/.next/cache/webpack/client-production/13.pack +0 -0
- package/.next/cache/webpack/client-production/14.pack +0 -0
- package/.next/cache/webpack/client-production/15.pack +0 -0
- package/.next/cache/webpack/client-production/16.pack +0 -0
- package/.next/cache/webpack/client-production/17.pack +0 -0
- package/.next/cache/webpack/client-production/18.pack +0 -0
- package/.next/cache/webpack/client-production/19.pack +0 -0
- package/.next/cache/webpack/client-production/2.pack +0 -0
- package/.next/cache/webpack/client-production/20.pack +0 -0
- package/.next/cache/webpack/client-production/21.pack +0 -0
- package/.next/cache/webpack/client-production/22.pack +0 -0
- package/.next/cache/webpack/client-production/3.pack +0 -0
- package/.next/cache/webpack/client-production/4.pack +0 -0
- package/.next/cache/webpack/client-production/5.pack +0 -0
- package/.next/cache/webpack/client-production/6.pack +0 -0
- package/.next/cache/webpack/client-production/7.pack +0 -0
- package/.next/cache/webpack/client-production/8.pack +0 -0
- package/.next/cache/webpack/client-production/9.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/1.pack +0 -0
- package/.next/cache/webpack/server-production/10.pack +0 -0
- package/.next/cache/webpack/server-production/11.pack +0 -0
- package/.next/cache/webpack/server-production/12.pack +0 -0
- package/.next/cache/webpack/server-production/13.pack +0 -0
- package/.next/cache/webpack/server-production/14.pack +0 -0
- package/.next/cache/webpack/server-production/15.pack +0 -0
- package/.next/cache/webpack/server-production/16.pack +0 -0
- package/.next/cache/webpack/server-production/17.pack +0 -0
- package/.next/cache/webpack/server-production/18.pack +0 -0
- package/.next/cache/webpack/server-production/19.pack +0 -0
- package/.next/cache/webpack/server-production/2.pack +0 -0
- package/.next/cache/webpack/server-production/20.pack +0 -0
- package/.next/cache/webpack/server-production/3.pack +0 -0
- package/.next/cache/webpack/server-production/4.pack +0 -0
- package/.next/cache/webpack/server-production/5.pack +0 -0
- package/.next/cache/webpack/server-production/6.pack +0 -0
- package/.next/cache/webpack/server-production/7.pack +0 -0
- package/.next/cache/webpack/server-production/8.pack +0 -0
- package/.next/cache/webpack/server-production/9.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/.next/diagnostics/build-diagnostics.json +6 -0
- package/.next/diagnostics/framework.json +1 -0
- package/.next/export-marker.json +6 -0
- package/.next/images-manifest.json +58 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +61 -0
- package/.next/react-loadable-manifest.json +1 -0
- package/.next/required-server-files.json +320 -0
- package/.next/routes-manifest.json +53 -0
- package/.next/server/app/_not-found/page.js +2 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +8 -0
- package/.next/server/app/_not-found.rsc +15 -0
- package/.next/server/app/api/feature/route.js +1 -0
- package/.next/server/app/api/feature/route.js.nft.json +1 -0
- package/.next/server/app/api/feature/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/file/route.js +1 -0
- package/.next/server/app/api/file/route.js.nft.json +1 -0
- package/.next/server/app/api/file/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/phase/route.js +4 -0
- package/.next/server/app/api/phase/route.js.nft.json +1 -0
- package/.next/server/app/api/phase/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/state/route.js +1 -0
- package/.next/server/app/api/state/route.js.nft.json +1 -0
- package/.next/server/app/api/state/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/state/watch/route.js +4 -0
- package/.next/server/app/api/state/watch/route.js.nft.json +1 -0
- package/.next/server/app/api/state/watch/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/task/route.js +1 -0
- package/.next/server/app/api/task/route.js.nft.json +1 -0
- package/.next/server/app/api/task/route_client-reference-manifest.js +1 -0
- package/.next/server/app/index.html +1 -0
- package/.next/server/app/index.meta +7 -0
- package/.next/server/app/index.rsc +20 -0
- package/.next/server/app/page.js +14 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +1 -0
- package/.next/server/app-paths-manifest.json +10 -0
- package/.next/server/chunks/355.js +22 -0
- package/.next/server/chunks/6.js +9 -0
- package/.next/server/chunks/607.js +6 -0
- package/.next/server/chunks/643.js +1 -0
- package/.next/server/chunks/897.js +9 -0
- package/.next/server/functions-config-manifest.json +4 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +1 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +1 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages/_app.js +1 -0
- package/.next/server/pages/_app.js.nft.json +1 -0
- package/.next/server/pages/_document.js +1 -0
- package/.next/server/pages/_document.js.nft.json +1 -0
- package/.next/server/pages/_error.js +19 -0
- package/.next/server/pages/_error.js.nft.json +1 -0
- package/.next/server/pages-manifest.json +6 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +1 -0
- package/.next/server/webpack-runtime.js +1 -0
- package/.next/static/chunks/590-a6568595ecd2a994.js +1 -0
- package/.next/static/chunks/8381d2c4-9707dccab70b742b.js +1 -0
- package/.next/static/chunks/920-f9bfc1b0d0402c3e.js +1 -0
- package/.next/static/chunks/acfafb44-8249079a6627ac92.js +1 -0
- package/.next/static/chunks/app/_not-found/page-be798b363e27e8c5.js +1 -0
- package/.next/static/chunks/app/api/feature/route-bb3c1a82e892ab58.js +1 -0
- package/.next/static/chunks/app/api/file/route-bb3c1a82e892ab58.js +1 -0
- package/.next/static/chunks/app/api/phase/route-bb3c1a82e892ab58.js +1 -0
- package/.next/static/chunks/app/api/state/route-bb3c1a82e892ab58.js +1 -0
- package/.next/static/chunks/app/api/state/watch/route-bb3c1a82e892ab58.js +1 -0
- package/.next/static/chunks/app/api/task/route-bb3c1a82e892ab58.js +1 -0
- package/.next/static/chunks/app/layout-3226c76a5f7f74bc.js +1 -0
- package/.next/static/chunks/app/page-8a5248f7704cde29.js +1 -0
- package/.next/static/chunks/framework-20dd4f6054cc5446.js +1 -0
- package/.next/static/chunks/main-91029f76ac1b7110.js +1 -0
- package/.next/static/chunks/main-app-b9ad56d6b1dfa941.js +1 -0
- package/.next/static/chunks/pages/_app-aa33dc41c3472021.js +1 -0
- package/.next/static/chunks/pages/_error-78b0b3b591df0e73.js +1 -0
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/.next/static/chunks/webpack-c460f8e58a9e9eff.js +1 -0
- package/.next/static/css/008a05b0ad6b854a.css +31 -0
- package/.next/static/css/6fd2e11db3a59771.css +3 -0
- package/.next/static/fWuQ3yoHovA7Cre6u89W7/_buildManifest.js +1 -0
- package/.next/static/fWuQ3yoHovA7Cre6u89W7/_ssgManifest.js +1 -0
- package/.next/trace +3 -0
- package/.next/types/app/api/feature/route.ts +347 -0
- package/.next/types/app/api/file/route.ts +347 -0
- package/.next/types/app/api/phase/route.ts +347 -0
- package/.next/types/app/api/state/route.ts +347 -0
- package/.next/types/app/api/state/watch/route.ts +347 -0
- package/.next/types/app/api/task/route.ts +347 -0
- package/.next/types/app/layout.ts +84 -0
- package/.next/types/app/page.ts +84 -0
- package/.next/types/cache-life.d.ts +141 -0
- package/.next/types/package.json +1 -0
- package/.next/types/routes.d.ts +78 -0
- package/.next/types/validator.ts +124 -0
- package/LICENSE +21 -0
- package/README.md +284 -0
- package/bin/adapters/di.js +9 -0
- package/bin/adapters/primary/api/utils.js +57 -0
- package/bin/adapters/secondary/agent/ProcessAgentRunner.js +161 -0
- package/bin/adapters/secondary/fs/FSWorkspaceRepository.js +283 -0
- package/bin/app/api/feature/route.js +35 -0
- package/bin/app/api/file/route.js +36 -0
- package/bin/app/api/phase/route.js +55 -0
- package/bin/app/api/state/route.js +28 -0
- package/bin/app/api/state/watch/route.js +92 -0
- package/bin/app/api/task/route.js +20 -0
- package/bin/bin/cli.js +317 -0
- package/bin/cli.js +85 -0
- package/bin/domain/models/types.js +2 -0
- package/bin/domain/ports/in/WorkflowUseCases.js +2 -0
- package/bin/domain/ports/out/AgentRunnerPort.js +2 -0
- package/bin/domain/ports/out/WorkspaceRepositoryPort.js +2 -0
- package/bin/domain/services/WorkflowService.js +174 -0
- package/next.config.ts +13 -0
- package/package.json +53 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.dynamic = void 0;
|
|
37
|
+
exports.GET = GET;
|
|
38
|
+
const di_1 = require("../../../../adapters/di");
|
|
39
|
+
const utils_1 = require("../../../../adapters/primary/api/utils");
|
|
40
|
+
const chokidar = __importStar(require("chokidar"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
exports.dynamic = 'force-dynamic';
|
|
43
|
+
async function GET() {
|
|
44
|
+
const workspacePath = (0, utils_1.getWorkspacePath)();
|
|
45
|
+
const encoder = new TextEncoder();
|
|
46
|
+
const watcher = chokidar.watch([
|
|
47
|
+
path.join(workspacePath, 'specs'),
|
|
48
|
+
path.join(workspacePath, '.specify')
|
|
49
|
+
], {
|
|
50
|
+
ignoreInitial: true,
|
|
51
|
+
persistent: true,
|
|
52
|
+
depth: 4
|
|
53
|
+
});
|
|
54
|
+
const customReadableStream = new ReadableStream({
|
|
55
|
+
start(controller) {
|
|
56
|
+
const sendUpdate = async (changedFilePath) => {
|
|
57
|
+
try {
|
|
58
|
+
const state = await di_1.workflowService.getWorkflowState(workspacePath);
|
|
59
|
+
const relativePath = changedFilePath
|
|
60
|
+
? path.relative(workspacePath, changedFilePath)
|
|
61
|
+
: null;
|
|
62
|
+
const payload = {
|
|
63
|
+
state,
|
|
64
|
+
changedFile: relativePath
|
|
65
|
+
};
|
|
66
|
+
controller.enqueue(encoder.encode(`event: update\ndata: ${JSON.stringify(payload)}\n\n`));
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// ignore
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
// Watch all change events (add, change, unlink)
|
|
73
|
+
watcher.on('all', (event, filePath) => {
|
|
74
|
+
// Skip changes inside the internal runtime state directory
|
|
75
|
+
if (filePath.includes('.runtime') || filePath.includes('.git'))
|
|
76
|
+
return;
|
|
77
|
+
sendUpdate(filePath);
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
cancel() {
|
|
81
|
+
watcher.close();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return new Response(customReadableStream, {
|
|
85
|
+
headers: {
|
|
86
|
+
'Content-Type': 'text/event-stream',
|
|
87
|
+
'Cache-Control': 'no-cache, no-transform',
|
|
88
|
+
'Connection': 'keep-alive',
|
|
89
|
+
'X-Accel-Buffering': 'no',
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POST = POST;
|
|
4
|
+
const server_1 = require("next/server");
|
|
5
|
+
const di_1 = require("../../../adapters/di");
|
|
6
|
+
const utils_1 = require("../../../adapters/primary/api/utils");
|
|
7
|
+
async function POST(req) {
|
|
8
|
+
try {
|
|
9
|
+
const { featureName, lineIndex, checked } = await req.json();
|
|
10
|
+
if (!featureName || lineIndex === undefined || checked === undefined) {
|
|
11
|
+
return server_1.NextResponse.json({ error: 'Missing parameters' }, { status: 400 });
|
|
12
|
+
}
|
|
13
|
+
const workspacePath = (0, utils_1.getWorkspacePath)();
|
|
14
|
+
const state = await di_1.workflowService.toggleTask(workspacePath, featureName, lineIndex, checked);
|
|
15
|
+
return server_1.NextResponse.json(state);
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
return server_1.NextResponse.json({ error: err.message }, { status: 500 });
|
|
19
|
+
}
|
|
20
|
+
}
|
package/bin/bin/cli.js
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
const child_process_1 = require("child_process");
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const open_1 = __importDefault(require("open"));
|
|
44
|
+
const os = __importStar(require("os"));
|
|
45
|
+
const di_1 = require("../adapters/di");
|
|
46
|
+
const args = process.argv.slice(2);
|
|
47
|
+
// Resolve workspace path
|
|
48
|
+
function resolveWorkspace(cmdArgs, projectDir) {
|
|
49
|
+
const flagIndex = cmdArgs.findIndex(arg => arg === '-w' || arg === '--workspace');
|
|
50
|
+
if (flagIndex !== -1 && cmdArgs[flagIndex + 1]) {
|
|
51
|
+
const resolved = path.resolve(cmdArgs[flagIndex + 1]);
|
|
52
|
+
saveWorkspacePath(projectDir, resolved);
|
|
53
|
+
return resolved;
|
|
54
|
+
}
|
|
55
|
+
for (let i = 0; i < cmdArgs.length; i++) {
|
|
56
|
+
const arg = cmdArgs[i];
|
|
57
|
+
if (!arg.startsWith('-')) {
|
|
58
|
+
const prev = cmdArgs[i - 1];
|
|
59
|
+
if (prev !== '-p' && prev !== '--port' && prev !== '-w' && prev !== '--workspace' && prev !== '--agent' && prev !== '--prompt') {
|
|
60
|
+
if (fs.existsSync(arg) && fs.statSync(arg).isDirectory()) {
|
|
61
|
+
const resolved = path.resolve(arg);
|
|
62
|
+
saveWorkspacePath(projectDir, resolved);
|
|
63
|
+
return resolved;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const saved = loadWorkspacePath(projectDir);
|
|
69
|
+
if (saved) {
|
|
70
|
+
return saved;
|
|
71
|
+
}
|
|
72
|
+
const fallback = process.cwd();
|
|
73
|
+
saveWorkspacePath(projectDir, fallback);
|
|
74
|
+
return fallback;
|
|
75
|
+
}
|
|
76
|
+
function loadWorkspacePath(projectDir) {
|
|
77
|
+
try {
|
|
78
|
+
const configPath = path.join(os.homedir(), '.speckit-assistant-config.json');
|
|
79
|
+
if (fs.existsSync(configPath)) {
|
|
80
|
+
const data = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
81
|
+
return data.lastWorkspacePath || null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// ignore
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
function saveWorkspacePath(projectDir, resolvedPath) {
|
|
90
|
+
try {
|
|
91
|
+
const configPath = path.join(os.homedir(), '.speckit-assistant-config.json');
|
|
92
|
+
fs.writeFileSync(configPath, JSON.stringify({ lastWorkspacePath: resolvedPath }, null, 2), 'utf-8');
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// ignore
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const appDir = path.resolve(__dirname, '../..');
|
|
99
|
+
const workspacePath = resolveWorkspace(args, appDir);
|
|
100
|
+
process.env.WORKSPACE_PATH = workspacePath;
|
|
101
|
+
const subcommands = ['status', 'approve', 'discard', 'run', 'create', 'delete'];
|
|
102
|
+
const firstArg = args[0];
|
|
103
|
+
// Help menu
|
|
104
|
+
function showHelp() {
|
|
105
|
+
console.log(`
|
|
106
|
+
š± Spec Kit Assistant CLI
|
|
107
|
+
|
|
108
|
+
Usage:
|
|
109
|
+
speckit-assistant Start the Web UI server
|
|
110
|
+
speckit-assistant status Show current SDD workflow status
|
|
111
|
+
speckit-assistant approve <phase> [feature] Approve a phase
|
|
112
|
+
speckit-assistant discard <phase> [feature] Reset/discard a phase
|
|
113
|
+
speckit-assistant create <feature> Create a new feature folder
|
|
114
|
+
speckit-assistant delete <feature> Delete a feature folder
|
|
115
|
+
speckit-assistant run <phase> [feature] [--agent <type>] [--prompt <text>] Run an agent phase
|
|
116
|
+
|
|
117
|
+
Options:
|
|
118
|
+
-w, --workspace <path> Specify target workspace path (default: current directory)
|
|
119
|
+
-p, --port <number> Specify Web UI server port (default: 18080)
|
|
120
|
+
--agent <claude|gemini|copilot> AI agent to use for run command (default: claude)
|
|
121
|
+
--prompt <text> User refinements or prompt additions for the run
|
|
122
|
+
--help Show this help menu
|
|
123
|
+
`);
|
|
124
|
+
}
|
|
125
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
126
|
+
showHelp();
|
|
127
|
+
process.exit(0);
|
|
128
|
+
}
|
|
129
|
+
// 1. Run Subcommands
|
|
130
|
+
if (firstArg && subcommands.includes(firstArg)) {
|
|
131
|
+
handleSubcommand(firstArg, args.slice(1));
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// 2. Start Web Server
|
|
135
|
+
startWebServer();
|
|
136
|
+
}
|
|
137
|
+
// --- Web Server Launcher ---
|
|
138
|
+
function startWebServer() {
|
|
139
|
+
const portFlagIndex = args.findIndex(arg => arg === '-p' || arg === '--port');
|
|
140
|
+
const port = portFlagIndex !== -1 && args[portFlagIndex + 1] ? args[portFlagIndex + 1] : '18080';
|
|
141
|
+
console.log(`\nš± Spec Kit Assistant Web Server`);
|
|
142
|
+
console.log(`š Workspace: ${workspacePath}`);
|
|
143
|
+
console.log(`š Starting server on port ${port}...\n`);
|
|
144
|
+
// Server files are compiled in the same parent directory
|
|
145
|
+
const appDir = path.resolve(__dirname, '../..');
|
|
146
|
+
const nextBin = path.join(appDir, 'node_modules', 'next', 'dist', 'bin', 'next');
|
|
147
|
+
if (!fs.existsSync(nextBin)) {
|
|
148
|
+
console.error(`Error: next binary not found at ${nextBin}`);
|
|
149
|
+
console.error(`Please make sure you ran 'pnpm install' in ${appDir}`);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
const child = (0, child_process_1.spawn)(process.execPath, [nextBin, 'start', '-p', port], {
|
|
153
|
+
cwd: appDir,
|
|
154
|
+
stdio: 'inherit',
|
|
155
|
+
env: {
|
|
156
|
+
...process.env,
|
|
157
|
+
WORKSPACE_PATH: workspacePath
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
const url = `http://localhost:${port}`;
|
|
162
|
+
console.log(`\nš Speckit Assistant available at: ${url}`);
|
|
163
|
+
(0, open_1.default)(url).catch(() => { });
|
|
164
|
+
}, 2500);
|
|
165
|
+
child.on('exit', (code) => {
|
|
166
|
+
process.exit(code || 0);
|
|
167
|
+
});
|
|
168
|
+
process.on('SIGINT', () => {
|
|
169
|
+
child.kill('SIGINT');
|
|
170
|
+
process.exit(0);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
// --- CLI Subcommand Handlers ---
|
|
174
|
+
async function handleSubcommand(command, cmdArgs) {
|
|
175
|
+
try {
|
|
176
|
+
switch (command) {
|
|
177
|
+
case 'status':
|
|
178
|
+
await printStatus();
|
|
179
|
+
break;
|
|
180
|
+
case 'approve':
|
|
181
|
+
await approvePhase(cmdArgs);
|
|
182
|
+
break;
|
|
183
|
+
case 'discard':
|
|
184
|
+
await discardPhase(cmdArgs);
|
|
185
|
+
break;
|
|
186
|
+
case 'create':
|
|
187
|
+
await createFeature(cmdArgs);
|
|
188
|
+
break;
|
|
189
|
+
case 'delete':
|
|
190
|
+
await deleteFeature(cmdArgs);
|
|
191
|
+
break;
|
|
192
|
+
case 'run':
|
|
193
|
+
await runPhase(cmdArgs);
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
process.exit(0);
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
console.error(`\nā Error: ${err.message}`);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async function printStatus() {
|
|
204
|
+
const state = await di_1.workflowService.getWorkflowState(workspacePath);
|
|
205
|
+
console.log(`\nš± SDD WORKFLOW STATUS`);
|
|
206
|
+
console.log(`š Workspace: ${workspacePath}`);
|
|
207
|
+
console.log(`----------------------------------------------------------------------`);
|
|
208
|
+
// Constitution status
|
|
209
|
+
console.log(`š Constitution: [${state.constitutionPhase.status.toUpperCase()}] ${state.constitutionPhase.stale ? '(STALE)' : ''}`);
|
|
210
|
+
console.log(` File: ${state.constitutionPhase.filePath || 'Not created'}`);
|
|
211
|
+
console.log(`----------------------------------------------------------------------`);
|
|
212
|
+
// Features status
|
|
213
|
+
if (state.features.length === 0) {
|
|
214
|
+
console.log(`(No features found in specs/ directory)`);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
state.features.forEach(feat => {
|
|
218
|
+
console.log(`\nš¹ Feature: "${feat.name}"`);
|
|
219
|
+
feat.phases.forEach(p => {
|
|
220
|
+
let progressStr = '';
|
|
221
|
+
if (p.phase === 'tasks' && p.content) {
|
|
222
|
+
const checkboxes = [...p.content.matchAll(/^\s*(?:[-*]|\d+\.)\s+\[( |x|X)\]/gm)];
|
|
223
|
+
if (checkboxes.length > 0) {
|
|
224
|
+
const done = checkboxes.filter(c => c[1].toLowerCase() === 'x').length;
|
|
225
|
+
progressStr = ` (${done}/${checkboxes.length} tasks)`;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const statusLabel = p.status.toUpperCase();
|
|
229
|
+
const staleLabel = p.stale ? ' (STALE)' : '';
|
|
230
|
+
console.log(` - [${p.phase.padEnd(14)}]: ${statusLabel}${staleLabel}${progressStr}`);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
console.log();
|
|
234
|
+
}
|
|
235
|
+
async function approvePhase(cmdArgs) {
|
|
236
|
+
const phase = cmdArgs[0];
|
|
237
|
+
if (!phase)
|
|
238
|
+
throw new Error('Missing phase argument. Usage: approve <phase> [feature]');
|
|
239
|
+
let feature = null;
|
|
240
|
+
if (phase !== 'constitution') {
|
|
241
|
+
feature = cmdArgs[1] || null;
|
|
242
|
+
if (!feature) {
|
|
243
|
+
const state = await di_1.workflowService.getWorkflowState(workspacePath);
|
|
244
|
+
feature = state.activeFeatureName;
|
|
245
|
+
if (!feature)
|
|
246
|
+
throw new Error('No active feature. Please specify feature name.');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
console.log(`Approving phase "${phase}"${feature ? ` for feature "${feature}"` : ''}...`);
|
|
250
|
+
await di_1.workflowService.approvePhase(workspacePath, phase, feature);
|
|
251
|
+
console.log('ā
Approved successfully!');
|
|
252
|
+
}
|
|
253
|
+
async function discardPhase(cmdArgs) {
|
|
254
|
+
const phase = cmdArgs[0];
|
|
255
|
+
if (!phase)
|
|
256
|
+
throw new Error('Missing phase argument. Usage: discard <phase> [feature]');
|
|
257
|
+
let feature = null;
|
|
258
|
+
if (phase !== 'constitution') {
|
|
259
|
+
feature = cmdArgs[1] || null;
|
|
260
|
+
if (!feature) {
|
|
261
|
+
const state = await di_1.workflowService.getWorkflowState(workspacePath);
|
|
262
|
+
feature = state.activeFeatureName;
|
|
263
|
+
if (!feature)
|
|
264
|
+
throw new Error('No active feature. Please specify feature name.');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
console.log(`Discarding/resetting phase "${phase}"${feature ? ` for feature "${feature}"` : ''}...`);
|
|
268
|
+
await di_1.workflowService.discardPhase(workspacePath, phase, feature);
|
|
269
|
+
console.log('ā
Discarded/reset successfully!');
|
|
270
|
+
}
|
|
271
|
+
async function createFeature(cmdArgs) {
|
|
272
|
+
const name = cmdArgs[0];
|
|
273
|
+
if (!name)
|
|
274
|
+
throw new Error('Missing feature name. Usage: create <feature-name>');
|
|
275
|
+
console.log(`Creating feature "${name}"...`);
|
|
276
|
+
await di_1.workflowService.createFeature(workspacePath, name);
|
|
277
|
+
console.log('ā
Feature folder created!');
|
|
278
|
+
}
|
|
279
|
+
async function deleteFeature(cmdArgs) {
|
|
280
|
+
const name = cmdArgs[0];
|
|
281
|
+
if (!name)
|
|
282
|
+
throw new Error('Missing feature name. Usage: delete <feature-name>');
|
|
283
|
+
console.log(`Deleting feature "${name}"...`);
|
|
284
|
+
await di_1.workflowService.deleteFeature(workspacePath, name);
|
|
285
|
+
console.log('ā
Feature folder deleted!');
|
|
286
|
+
}
|
|
287
|
+
async function runPhase(cmdArgs) {
|
|
288
|
+
const phase = cmdArgs[0];
|
|
289
|
+
if (!phase)
|
|
290
|
+
throw new Error('Missing phase argument. Usage: run <phase> [feature] [options]');
|
|
291
|
+
let feature = null;
|
|
292
|
+
let nextArgIndex = 1;
|
|
293
|
+
if (phase !== 'constitution') {
|
|
294
|
+
if (cmdArgs[1] && !cmdArgs[1].startsWith('--')) {
|
|
295
|
+
feature = cmdArgs[1];
|
|
296
|
+
nextArgIndex = 2;
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
const state = await di_1.workflowService.getWorkflowState(workspacePath);
|
|
300
|
+
feature = state.activeFeatureName;
|
|
301
|
+
if (!feature)
|
|
302
|
+
throw new Error('No active feature. Please specify feature name.');
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// Parse options
|
|
306
|
+
const optArgs = cmdArgs.slice(nextArgIndex);
|
|
307
|
+
const agentFlagIndex = optArgs.findIndex(arg => arg === '--agent');
|
|
308
|
+
const agentType = agentFlagIndex !== -1 && optArgs[agentFlagIndex + 1] ? optArgs[agentFlagIndex + 1] : 'claude';
|
|
309
|
+
const promptFlagIndex = optArgs.findIndex(arg => arg === '--prompt');
|
|
310
|
+
const promptText = promptFlagIndex !== -1 && optArgs[promptFlagIndex + 1] ? optArgs[promptFlagIndex + 1] : undefined;
|
|
311
|
+
const agentConfig = { agentType };
|
|
312
|
+
console.log(`Running phase "${phase}"${feature ? ` for feature "${feature}"` : ''} using agent "${agentType}"...\n`);
|
|
313
|
+
await di_1.workflowService.runPhase(workspacePath, phase, feature, agentConfig, promptText, (logData) => {
|
|
314
|
+
process.stdout.write(logData);
|
|
315
|
+
});
|
|
316
|
+
console.log('\nš Phase run completed!');
|
|
317
|
+
}
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
const child_process_1 = require("child_process");
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const open_1 = __importDefault(require("open"));
|
|
43
|
+
const args = process.argv.slice(2);
|
|
44
|
+
// Resolve port
|
|
45
|
+
const portFlagIndex = args.findIndex(arg => arg === '-p' || arg === '--port');
|
|
46
|
+
const port = portFlagIndex !== -1 && args[portFlagIndex + 1] ? args[portFlagIndex + 1] : '18080';
|
|
47
|
+
// Resolve workspace path
|
|
48
|
+
let workspacePath = process.cwd();
|
|
49
|
+
if (args.length > 0) {
|
|
50
|
+
const lastArg = args[args.length - 1];
|
|
51
|
+
if (!lastArg.startsWith('-') && lastArg !== port) {
|
|
52
|
+
workspacePath = lastArg;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const resolvedWorkspace = path.resolve(workspacePath);
|
|
56
|
+
process.env.WORKSPACE_PATH = resolvedWorkspace;
|
|
57
|
+
console.log(`\nš± Spec Kit Assistant`);
|
|
58
|
+
console.log(`š Target Workspace: ${resolvedWorkspace}`);
|
|
59
|
+
console.log(`š Starting server on port ${port}...\n`);
|
|
60
|
+
// The binary runs from the speckit-assistant directory
|
|
61
|
+
const appDir = path.resolve(__dirname, '..');
|
|
62
|
+
const nextBin = path.join(appDir, 'node_modules', 'next', 'dist', 'bin', 'next');
|
|
63
|
+
const child = (0, child_process_1.spawn)(process.execPath, [nextBin, 'start', '-p', port], {
|
|
64
|
+
cwd: appDir,
|
|
65
|
+
stdio: 'inherit',
|
|
66
|
+
env: {
|
|
67
|
+
...process.env,
|
|
68
|
+
WORKSPACE_PATH: resolvedWorkspace
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
// Auto-open browser after the server has warmed up
|
|
72
|
+
setTimeout(() => {
|
|
73
|
+
const url = `http://localhost:${port}`;
|
|
74
|
+
console.log(`\nš Speckit Assistant available at: ${url}`);
|
|
75
|
+
(0, open_1.default)(url).catch(() => {
|
|
76
|
+
// ignore opening failures
|
|
77
|
+
});
|
|
78
|
+
}, 2500);
|
|
79
|
+
child.on('exit', (code) => {
|
|
80
|
+
process.exit(code || 0);
|
|
81
|
+
});
|
|
82
|
+
process.on('SIGINT', () => {
|
|
83
|
+
child.kill('SIGINT');
|
|
84
|
+
process.exit(0);
|
|
85
|
+
});
|