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.
Files changed (180) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +71 -0
  3. package/.next/app-path-routes-manifest.json +10 -0
  4. package/.next/build-manifest.json +33 -0
  5. package/.next/cache/.previewinfo +1 -0
  6. package/.next/cache/.rscinfo +1 -0
  7. package/.next/cache/webpack/client-production/0.pack +0 -0
  8. package/.next/cache/webpack/client-production/1.pack +0 -0
  9. package/.next/cache/webpack/client-production/10.pack +0 -0
  10. package/.next/cache/webpack/client-production/11.pack +0 -0
  11. package/.next/cache/webpack/client-production/12.pack +0 -0
  12. package/.next/cache/webpack/client-production/13.pack +0 -0
  13. package/.next/cache/webpack/client-production/14.pack +0 -0
  14. package/.next/cache/webpack/client-production/15.pack +0 -0
  15. package/.next/cache/webpack/client-production/16.pack +0 -0
  16. package/.next/cache/webpack/client-production/17.pack +0 -0
  17. package/.next/cache/webpack/client-production/18.pack +0 -0
  18. package/.next/cache/webpack/client-production/19.pack +0 -0
  19. package/.next/cache/webpack/client-production/2.pack +0 -0
  20. package/.next/cache/webpack/client-production/20.pack +0 -0
  21. package/.next/cache/webpack/client-production/21.pack +0 -0
  22. package/.next/cache/webpack/client-production/22.pack +0 -0
  23. package/.next/cache/webpack/client-production/3.pack +0 -0
  24. package/.next/cache/webpack/client-production/4.pack +0 -0
  25. package/.next/cache/webpack/client-production/5.pack +0 -0
  26. package/.next/cache/webpack/client-production/6.pack +0 -0
  27. package/.next/cache/webpack/client-production/7.pack +0 -0
  28. package/.next/cache/webpack/client-production/8.pack +0 -0
  29. package/.next/cache/webpack/client-production/9.pack +0 -0
  30. package/.next/cache/webpack/client-production/index.pack +0 -0
  31. package/.next/cache/webpack/client-production/index.pack.old +0 -0
  32. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  33. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  34. package/.next/cache/webpack/server-production/0.pack +0 -0
  35. package/.next/cache/webpack/server-production/1.pack +0 -0
  36. package/.next/cache/webpack/server-production/10.pack +0 -0
  37. package/.next/cache/webpack/server-production/11.pack +0 -0
  38. package/.next/cache/webpack/server-production/12.pack +0 -0
  39. package/.next/cache/webpack/server-production/13.pack +0 -0
  40. package/.next/cache/webpack/server-production/14.pack +0 -0
  41. package/.next/cache/webpack/server-production/15.pack +0 -0
  42. package/.next/cache/webpack/server-production/16.pack +0 -0
  43. package/.next/cache/webpack/server-production/17.pack +0 -0
  44. package/.next/cache/webpack/server-production/18.pack +0 -0
  45. package/.next/cache/webpack/server-production/19.pack +0 -0
  46. package/.next/cache/webpack/server-production/2.pack +0 -0
  47. package/.next/cache/webpack/server-production/20.pack +0 -0
  48. package/.next/cache/webpack/server-production/3.pack +0 -0
  49. package/.next/cache/webpack/server-production/4.pack +0 -0
  50. package/.next/cache/webpack/server-production/5.pack +0 -0
  51. package/.next/cache/webpack/server-production/6.pack +0 -0
  52. package/.next/cache/webpack/server-production/7.pack +0 -0
  53. package/.next/cache/webpack/server-production/8.pack +0 -0
  54. package/.next/cache/webpack/server-production/9.pack +0 -0
  55. package/.next/cache/webpack/server-production/index.pack +0 -0
  56. package/.next/cache/webpack/server-production/index.pack.old +0 -0
  57. package/.next/diagnostics/build-diagnostics.json +6 -0
  58. package/.next/diagnostics/framework.json +1 -0
  59. package/.next/export-marker.json +6 -0
  60. package/.next/images-manifest.json +58 -0
  61. package/.next/next-minimal-server.js.nft.json +1 -0
  62. package/.next/next-server.js.nft.json +1 -0
  63. package/.next/package.json +1 -0
  64. package/.next/prerender-manifest.json +61 -0
  65. package/.next/react-loadable-manifest.json +1 -0
  66. package/.next/required-server-files.json +320 -0
  67. package/.next/routes-manifest.json +53 -0
  68. package/.next/server/app/_not-found/page.js +2 -0
  69. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  70. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  71. package/.next/server/app/_not-found.html +1 -0
  72. package/.next/server/app/_not-found.meta +8 -0
  73. package/.next/server/app/_not-found.rsc +15 -0
  74. package/.next/server/app/api/feature/route.js +1 -0
  75. package/.next/server/app/api/feature/route.js.nft.json +1 -0
  76. package/.next/server/app/api/feature/route_client-reference-manifest.js +1 -0
  77. package/.next/server/app/api/file/route.js +1 -0
  78. package/.next/server/app/api/file/route.js.nft.json +1 -0
  79. package/.next/server/app/api/file/route_client-reference-manifest.js +1 -0
  80. package/.next/server/app/api/phase/route.js +4 -0
  81. package/.next/server/app/api/phase/route.js.nft.json +1 -0
  82. package/.next/server/app/api/phase/route_client-reference-manifest.js +1 -0
  83. package/.next/server/app/api/state/route.js +1 -0
  84. package/.next/server/app/api/state/route.js.nft.json +1 -0
  85. package/.next/server/app/api/state/route_client-reference-manifest.js +1 -0
  86. package/.next/server/app/api/state/watch/route.js +4 -0
  87. package/.next/server/app/api/state/watch/route.js.nft.json +1 -0
  88. package/.next/server/app/api/state/watch/route_client-reference-manifest.js +1 -0
  89. package/.next/server/app/api/task/route.js +1 -0
  90. package/.next/server/app/api/task/route.js.nft.json +1 -0
  91. package/.next/server/app/api/task/route_client-reference-manifest.js +1 -0
  92. package/.next/server/app/index.html +1 -0
  93. package/.next/server/app/index.meta +7 -0
  94. package/.next/server/app/index.rsc +20 -0
  95. package/.next/server/app/page.js +14 -0
  96. package/.next/server/app/page.js.nft.json +1 -0
  97. package/.next/server/app/page_client-reference-manifest.js +1 -0
  98. package/.next/server/app-paths-manifest.json +10 -0
  99. package/.next/server/chunks/355.js +22 -0
  100. package/.next/server/chunks/6.js +9 -0
  101. package/.next/server/chunks/607.js +6 -0
  102. package/.next/server/chunks/643.js +1 -0
  103. package/.next/server/chunks/897.js +9 -0
  104. package/.next/server/functions-config-manifest.json +4 -0
  105. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  106. package/.next/server/middleware-build-manifest.js +1 -0
  107. package/.next/server/middleware-manifest.json +6 -0
  108. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  109. package/.next/server/next-font-manifest.js +1 -0
  110. package/.next/server/next-font-manifest.json +1 -0
  111. package/.next/server/pages/404.html +1 -0
  112. package/.next/server/pages/500.html +1 -0
  113. package/.next/server/pages/_app.js +1 -0
  114. package/.next/server/pages/_app.js.nft.json +1 -0
  115. package/.next/server/pages/_document.js +1 -0
  116. package/.next/server/pages/_document.js.nft.json +1 -0
  117. package/.next/server/pages/_error.js +19 -0
  118. package/.next/server/pages/_error.js.nft.json +1 -0
  119. package/.next/server/pages-manifest.json +6 -0
  120. package/.next/server/server-reference-manifest.js +1 -0
  121. package/.next/server/server-reference-manifest.json +1 -0
  122. package/.next/server/webpack-runtime.js +1 -0
  123. package/.next/static/chunks/590-a6568595ecd2a994.js +1 -0
  124. package/.next/static/chunks/8381d2c4-9707dccab70b742b.js +1 -0
  125. package/.next/static/chunks/920-f9bfc1b0d0402c3e.js +1 -0
  126. package/.next/static/chunks/acfafb44-8249079a6627ac92.js +1 -0
  127. package/.next/static/chunks/app/_not-found/page-be798b363e27e8c5.js +1 -0
  128. package/.next/static/chunks/app/api/feature/route-bb3c1a82e892ab58.js +1 -0
  129. package/.next/static/chunks/app/api/file/route-bb3c1a82e892ab58.js +1 -0
  130. package/.next/static/chunks/app/api/phase/route-bb3c1a82e892ab58.js +1 -0
  131. package/.next/static/chunks/app/api/state/route-bb3c1a82e892ab58.js +1 -0
  132. package/.next/static/chunks/app/api/state/watch/route-bb3c1a82e892ab58.js +1 -0
  133. package/.next/static/chunks/app/api/task/route-bb3c1a82e892ab58.js +1 -0
  134. package/.next/static/chunks/app/layout-3226c76a5f7f74bc.js +1 -0
  135. package/.next/static/chunks/app/page-8a5248f7704cde29.js +1 -0
  136. package/.next/static/chunks/framework-20dd4f6054cc5446.js +1 -0
  137. package/.next/static/chunks/main-91029f76ac1b7110.js +1 -0
  138. package/.next/static/chunks/main-app-b9ad56d6b1dfa941.js +1 -0
  139. package/.next/static/chunks/pages/_app-aa33dc41c3472021.js +1 -0
  140. package/.next/static/chunks/pages/_error-78b0b3b591df0e73.js +1 -0
  141. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  142. package/.next/static/chunks/webpack-c460f8e58a9e9eff.js +1 -0
  143. package/.next/static/css/008a05b0ad6b854a.css +31 -0
  144. package/.next/static/css/6fd2e11db3a59771.css +3 -0
  145. package/.next/static/fWuQ3yoHovA7Cre6u89W7/_buildManifest.js +1 -0
  146. package/.next/static/fWuQ3yoHovA7Cre6u89W7/_ssgManifest.js +1 -0
  147. package/.next/trace +3 -0
  148. package/.next/types/app/api/feature/route.ts +347 -0
  149. package/.next/types/app/api/file/route.ts +347 -0
  150. package/.next/types/app/api/phase/route.ts +347 -0
  151. package/.next/types/app/api/state/route.ts +347 -0
  152. package/.next/types/app/api/state/watch/route.ts +347 -0
  153. package/.next/types/app/api/task/route.ts +347 -0
  154. package/.next/types/app/layout.ts +84 -0
  155. package/.next/types/app/page.ts +84 -0
  156. package/.next/types/cache-life.d.ts +141 -0
  157. package/.next/types/package.json +1 -0
  158. package/.next/types/routes.d.ts +78 -0
  159. package/.next/types/validator.ts +124 -0
  160. package/LICENSE +21 -0
  161. package/README.md +284 -0
  162. package/bin/adapters/di.js +9 -0
  163. package/bin/adapters/primary/api/utils.js +57 -0
  164. package/bin/adapters/secondary/agent/ProcessAgentRunner.js +161 -0
  165. package/bin/adapters/secondary/fs/FSWorkspaceRepository.js +283 -0
  166. package/bin/app/api/feature/route.js +35 -0
  167. package/bin/app/api/file/route.js +36 -0
  168. package/bin/app/api/phase/route.js +55 -0
  169. package/bin/app/api/state/route.js +28 -0
  170. package/bin/app/api/state/watch/route.js +92 -0
  171. package/bin/app/api/task/route.js +20 -0
  172. package/bin/bin/cli.js +317 -0
  173. package/bin/cli.js +85 -0
  174. package/bin/domain/models/types.js +2 -0
  175. package/bin/domain/ports/in/WorkflowUseCases.js +2 -0
  176. package/bin/domain/ports/out/AgentRunnerPort.js +2 -0
  177. package/bin/domain/ports/out/WorkspaceRepositoryPort.js +2 -0
  178. package/bin/domain/services/WorkflowService.js +174 -0
  179. package/next.config.ts +13 -0
  180. 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
+ });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });