@mrpatronz/nexusflow 0.2.12 → 0.2.17

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 (233) hide show
  1. package/.github/dependabot.yml +52 -52
  2. package/.github/workflows/dependabot-merge.yml +53 -0
  3. package/.github/workflows/release.yml +112 -100
  4. package/.vscode/launch.json +17 -17
  5. package/.vscode/tasks.json +17 -17
  6. package/GETTING_STARTED.md +114 -109
  7. package/README.md +336 -311
  8. package/desktop/build-installer.js +228 -0
  9. package/desktop/build.js +118 -0
  10. package/desktop/installer/nexusflow.iss +35 -0
  11. package/desktop/neutralino.config.json +39 -0
  12. package/desktop/package-lock.json +1060 -0
  13. package/desktop/package.json +14 -0
  14. package/dist/commands/add-repo.d.ts.map +1 -1
  15. package/dist/commands/add-repo.js +24 -14
  16. package/dist/commands/add-repo.js.map +1 -1
  17. package/dist/commands/commit.js +1 -1
  18. package/dist/commands/commit.js.map +1 -1
  19. package/dist/commands/desktop.d.ts +12 -0
  20. package/dist/commands/desktop.d.ts.map +1 -0
  21. package/dist/commands/desktop.js +119 -0
  22. package/dist/commands/desktop.js.map +1 -0
  23. package/dist/commands/diff.js +1 -1
  24. package/dist/commands/diff.js.map +1 -1
  25. package/dist/commands/doctor.js +1 -1
  26. package/dist/commands/doctor.js.map +1 -1
  27. package/dist/commands/handoff.js +1 -1
  28. package/dist/commands/handoff.js.map +1 -1
  29. package/dist/commands/logs.js +1 -1
  30. package/dist/commands/logs.js.map +1 -1
  31. package/dist/commands/open.d.ts.map +1 -1
  32. package/dist/commands/open.js +12 -7
  33. package/dist/commands/open.js.map +1 -1
  34. package/dist/commands/pack.js +1 -1
  35. package/dist/commands/pack.js.map +1 -1
  36. package/dist/commands/refresh.js +13 -8
  37. package/dist/commands/refresh.js.map +1 -1
  38. package/dist/commands/remove.d.ts.map +1 -1
  39. package/dist/commands/remove.js +12 -7
  40. package/dist/commands/remove.js.map +1 -1
  41. package/dist/commands/start.js +1 -1
  42. package/dist/commands/start.js.map +1 -1
  43. package/dist/commands/status.js +1 -1
  44. package/dist/commands/status.js.map +1 -1
  45. package/dist/commands/stop.js +1 -1
  46. package/dist/commands/stop.js.map +1 -1
  47. package/dist/commands/sync.d.ts.map +1 -1
  48. package/dist/commands/sync.js +14 -11
  49. package/dist/commands/sync.js.map +1 -1
  50. package/dist/commands/tui.d.ts +8 -0
  51. package/dist/commands/tui.d.ts.map +1 -0
  52. package/dist/commands/tui.js +386 -0
  53. package/dist/commands/tui.js.map +1 -0
  54. package/dist/commands/ui.d.ts +3 -1
  55. package/dist/commands/ui.d.ts.map +1 -1
  56. package/dist/commands/ui.js +76 -19
  57. package/dist/commands/ui.js.map +1 -1
  58. package/dist/core/workspace.d.ts +7 -0
  59. package/dist/core/workspace.d.ts.map +1 -1
  60. package/dist/core/workspace.js +45 -1
  61. package/dist/core/workspace.js.map +1 -1
  62. package/dist/generators/base.d.ts.map +1 -1
  63. package/dist/generators/base.js +78 -66
  64. package/dist/generators/base.js.map +1 -1
  65. package/dist/generators/codex.js +11 -11
  66. package/dist/generators/copilot.js +17 -17
  67. package/dist/generators/cursor.js +5 -5
  68. package/dist/generators/index.d.ts.map +1 -1
  69. package/dist/generators/index.js +64 -50
  70. package/dist/generators/index.js.map +1 -1
  71. package/dist/generators/map-generator.js +14 -14
  72. package/dist/generators/skills-generator.js +28 -28
  73. package/dist/gui/app_logo.png +0 -0
  74. package/dist/gui/assets/index-Ct3qq-X4.js +25 -0
  75. package/dist/gui/assets/index-P_ZrgHXg.css +1 -0
  76. package/dist/gui/icons.svg +24 -24
  77. package/dist/gui/index.html +18 -18
  78. package/dist/index.js +43 -0
  79. package/dist/index.js.map +1 -1
  80. package/dist/orchestration/runner.d.ts +5 -6
  81. package/dist/orchestration/runner.d.ts.map +1 -1
  82. package/dist/orchestration/runner.js +105 -102
  83. package/dist/orchestration/runner.js.map +1 -1
  84. package/dist/server.d.ts.map +1 -1
  85. package/dist/server.js +235 -2
  86. package/dist/server.js.map +1 -1
  87. package/dist/server.test.js +78 -0
  88. package/dist/server.test.js.map +1 -1
  89. package/dist/types.d.ts +4 -0
  90. package/dist/types.d.ts.map +1 -1
  91. package/dist/utils/detect-editors.js +1 -1
  92. package/dist/utils/detect-editors.js.map +1 -1
  93. package/dist/utils/detect-editors.test.js +3 -3
  94. package/dist/utils/detect-editors.test.js.map +1 -1
  95. package/dist/utils/git.d.ts +16 -0
  96. package/dist/utils/git.d.ts.map +1 -1
  97. package/dist/utils/git.js +52 -0
  98. package/dist/utils/git.js.map +1 -1
  99. package/dist/utils/multi-git.d.ts +2 -0
  100. package/dist/utils/multi-git.d.ts.map +1 -1
  101. package/dist/utils/multi-git.js +5 -2
  102. package/dist/utils/multi-git.js.map +1 -1
  103. package/dist/utils/prompts.d.ts +1 -0
  104. package/dist/utils/prompts.d.ts.map +1 -1
  105. package/dist/utils/prompts.js +77 -15
  106. package/dist/utils/prompts.js.map +1 -1
  107. package/dist/utils/update-check.d.ts +3 -1
  108. package/dist/utils/update-check.d.ts.map +1 -1
  109. package/dist/utils/update-check.js +23 -6
  110. package/dist/utils/update-check.js.map +1 -1
  111. package/dist/utils/workflows.d.ts +11 -0
  112. package/dist/utils/workflows.d.ts.map +1 -0
  113. package/dist/utils/workflows.js +156 -0
  114. package/dist/utils/workflows.js.map +1 -0
  115. package/dist/utils/workflows.test.d.ts +2 -0
  116. package/dist/utils/workflows.test.d.ts.map +1 -0
  117. package/dist/utils/workflows.test.js +86 -0
  118. package/dist/utils/workflows.test.js.map +1 -0
  119. package/extension/media/icon.svg +1 -0
  120. package/extension/package-lock.json +2673 -2811
  121. package/extension/package.json +108 -61
  122. package/extension/src/extension.ts +631 -168
  123. package/extension/tsconfig.json +21 -19
  124. package/gui/README.md +73 -73
  125. package/gui/e2e/wizard.spec.ts +346 -327
  126. package/gui/eslint.config.js +26 -22
  127. package/gui/index.html +17 -17
  128. package/gui/package-lock.json +3079 -3118
  129. package/gui/package.json +36 -36
  130. package/gui/playwright.config.ts +41 -41
  131. package/gui/public/app_logo.png +0 -0
  132. package/gui/public/icons.svg +24 -24
  133. package/gui/src/App.css +1 -1
  134. package/gui/src/App.tsx +3407 -2498
  135. package/gui/src/assets/vite.svg +1 -1
  136. package/gui/src/features/changes/ChangesViewer.tsx +388 -212
  137. package/gui/src/features/knowledge/KnowledgeBase.tsx +84 -84
  138. package/gui/src/features/onboarding/OnboardingWizard.tsx +230 -230
  139. package/gui/src/features/plan/ImplementationPlan.tsx +32 -32
  140. package/gui/src/features/services/ServiceConsole.tsx +250 -159
  141. package/gui/src/features/sessions/SessionHistory.tsx +195 -195
  142. package/gui/src/features/workspace/WorkspaceList.tsx +666 -514
  143. package/gui/src/index.css +152 -17
  144. package/gui/src/main.tsx +94 -10
  145. package/gui/src/types.ts +62 -62
  146. package/gui/tsconfig.app.json +25 -25
  147. package/gui/tsconfig.json +7 -7
  148. package/gui/tsconfig.node.json +24 -24
  149. package/gui/vite.config.ts +12 -12
  150. package/package.json +56 -55
  151. package/resources/workflows/plan-implement-review.md +8 -0
  152. package/resources/workflows/research-verify.md +6 -0
  153. package/resources/workflows/solo-developer.md +3 -0
  154. package/scripts/simulate-workspaces.ts +55 -55
  155. package/src/analyzers/detect-apis.ts +290 -290
  156. package/src/analyzers/detect-deps.ts +315 -315
  157. package/src/analyzers/detect-existing.ts +74 -74
  158. package/src/analyzers/detect-ports.ts +110 -110
  159. package/src/analyzers/index.ts +97 -97
  160. package/src/analyzers/messaging-analyzer.ts +254 -254
  161. package/src/analyzers/readme-summarizer.ts +102 -102
  162. package/src/analyzers/run-analyzer.ts +269 -269
  163. package/src/analyzers/tech-stack.ts +283 -283
  164. package/src/commands/add-repo.ts +157 -141
  165. package/src/commands/commands.test.ts +155 -155
  166. package/src/commands/commit.ts +131 -131
  167. package/src/commands/create.ts +207 -207
  168. package/src/commands/desktop.ts +128 -0
  169. package/src/commands/diff.ts +125 -125
  170. package/src/commands/doctor.ts +357 -357
  171. package/src/commands/handoff.ts +266 -266
  172. package/src/commands/init.ts +134 -134
  173. package/src/commands/list.ts +46 -46
  174. package/src/commands/logs.ts +63 -63
  175. package/src/commands/mcp.ts +92 -92
  176. package/src/commands/open.ts +129 -121
  177. package/src/commands/pack.ts +73 -73
  178. package/src/commands/refresh.ts +147 -139
  179. package/src/commands/remove.ts +98 -90
  180. package/src/commands/start.ts +117 -117
  181. package/src/commands/status.ts +54 -54
  182. package/src/commands/stop.ts +55 -55
  183. package/src/commands/sync.ts +151 -145
  184. package/src/commands/tui.ts +424 -0
  185. package/src/commands/ui.ts +111 -47
  186. package/src/core/config.test.ts +96 -96
  187. package/src/core/config.ts +115 -115
  188. package/src/core/graph.ts +344 -344
  189. package/src/core/packer.test.ts +99 -99
  190. package/src/core/packer.ts +107 -107
  191. package/src/core/scanner.test.ts +61 -61
  192. package/src/core/scanner.ts +91 -91
  193. package/src/core/workspace.ts +380 -333
  194. package/src/core/worktree.ts +120 -120
  195. package/src/generators/antigravity.ts +32 -32
  196. package/src/generators/base.ts +240 -227
  197. package/src/generators/claude.ts +34 -34
  198. package/src/generators/codex.ts +48 -48
  199. package/src/generators/copilot.ts +56 -56
  200. package/src/generators/cursor.ts +44 -44
  201. package/src/generators/index.ts +250 -230
  202. package/src/generators/map-generator.test.ts +159 -159
  203. package/src/generators/map-generator.ts +542 -542
  204. package/src/generators/plan-generator.ts +481 -481
  205. package/src/generators/skills-generator.ts +259 -259
  206. package/src/index.ts +426 -382
  207. package/src/mcp/server.ts +294 -294
  208. package/src/orchestration/detect.ts +313 -313
  209. package/src/orchestration/index.ts +7 -7
  210. package/src/orchestration/runner.ts +283 -279
  211. package/src/server.test.ts +555 -464
  212. package/src/server.ts +1308 -1047
  213. package/src/types.ts +408 -403
  214. package/src/utils/detect-ai.test.ts +44 -44
  215. package/src/utils/detect-ai.ts +84 -84
  216. package/src/utils/detect-editors.test.ts +48 -48
  217. package/src/utils/detect-editors.ts +57 -57
  218. package/src/utils/git.test.ts +74 -74
  219. package/src/utils/git.ts +117 -61
  220. package/src/utils/local-ai.test.ts +130 -130
  221. package/src/utils/local-ai.ts +111 -111
  222. package/src/utils/multi-git.ts +313 -306
  223. package/src/utils/prompts.ts +209 -135
  224. package/src/utils/session-finder.ts +483 -483
  225. package/src/utils/system-scanner.test.ts +89 -89
  226. package/src/utils/system-scanner.ts +96 -96
  227. package/src/utils/update-check.ts +309 -275
  228. package/src/utils/workflows.test.ts +114 -0
  229. package/src/utils/workflows.ts +178 -0
  230. package/tsconfig.json +19 -19
  231. package/vitest.config.ts +14 -14
  232. package/dist/gui/assets/index-Ca2VRMrQ.js +0 -22
  233. package/dist/gui/assets/index-fj0RJiOb.css +0 -2
@@ -0,0 +1,114 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import * as fs from 'node:fs/promises';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import { getWorkflowTemplates, saveWorkflowTemplate, deleteWorkflowTemplate } from './workflows.js';
6
+
7
+ vi.mock('node:fs/promises');
8
+ vi.mock('node:os', () => ({
9
+ homedir: () => '/mock/home'
10
+ }));
11
+
12
+ describe('Workflows Utility Unit Tests', () => {
13
+ beforeEach(() => {
14
+ vi.clearAllMocks();
15
+ });
16
+
17
+ describe('saveWorkflowTemplate', () => {
18
+ it('should save a template and extract its name from H1 header', async () => {
19
+ vi.spyOn(fs, 'mkdir').mockResolvedValue(undefined);
20
+ vi.spyOn(fs, 'writeFile').mockResolvedValue(undefined);
21
+
22
+ const result = await saveWorkflowTemplate('My Temp Name', '# Final Strategy Name\n\nStrategy Content');
23
+
24
+ expect(fs.mkdir).toHaveBeenCalledWith(path.join('/mock/home', '.nexusflow', 'workflows'), { recursive: true });
25
+ expect(fs.writeFile).toHaveBeenCalledWith(
26
+ path.join('/mock/home', '.nexusflow', 'workflows', 'final-strategy-name.md'),
27
+ '# Final Strategy Name\n\nStrategy Content',
28
+ 'utf-8'
29
+ );
30
+ expect(result).toEqual({
31
+ id: 'final-strategy-name',
32
+ name: 'Final Strategy Name',
33
+ description: 'Strategy Content',
34
+ content: '# Final Strategy Name\n\nStrategy Content',
35
+ custom: true
36
+ });
37
+ });
38
+
39
+ it('should add H1 header if not present', async () => {
40
+ vi.spyOn(fs, 'mkdir').mockResolvedValue(undefined);
41
+ vi.spyOn(fs, 'writeFile').mockResolvedValue(undefined);
42
+
43
+ const result = await saveWorkflowTemplate('My Temp Name', 'Strategy Content');
44
+
45
+ expect(fs.writeFile).toHaveBeenCalledWith(
46
+ path.join('/mock/home', '.nexusflow', 'workflows', 'my-temp-name.md'),
47
+ '# My Temp Name\n\nStrategy Content',
48
+ 'utf-8'
49
+ );
50
+ expect(result.id).toBe('my-temp-name');
51
+ });
52
+
53
+ it('should clean up originalId file if template is renamed', async () => {
54
+ vi.spyOn(fs, 'mkdir').mockResolvedValue(undefined);
55
+ vi.spyOn(fs, 'writeFile').mockResolvedValue(undefined);
56
+ vi.spyOn(fs, 'unlink').mockResolvedValue(undefined);
57
+
58
+ const result = await saveWorkflowTemplate('New Name', '# New Name\n\nContent', 'old-id');
59
+
60
+ expect(fs.unlink).toHaveBeenCalledWith(path.join('/mock/home', '.nexusflow', 'workflows', 'old-id.md'));
61
+ expect(result.id).toBe('new-name');
62
+ });
63
+ });
64
+
65
+ describe('deleteWorkflowTemplate', () => {
66
+ it('should delete template file', async () => {
67
+ vi.spyOn(fs, 'unlink').mockResolvedValue(undefined);
68
+
69
+ await deleteWorkflowTemplate('some-id');
70
+
71
+ expect(fs.unlink).toHaveBeenCalledWith(path.join('/mock/home', '.nexusflow', 'workflows', 'some-id.md'));
72
+ });
73
+
74
+ it('should ignore ENOENT error', async () => {
75
+ const error = new Error('File not found') as any;
76
+ error.code = 'ENOENT';
77
+ vi.spyOn(fs, 'unlink').mockRejectedValue(error);
78
+
79
+ await expect(deleteWorkflowTemplate('some-id')).resolves.toBeUndefined();
80
+ });
81
+ });
82
+
83
+ describe('getWorkflowTemplates', () => {
84
+ it('should load and merge built-in and user templates', async () => {
85
+ vi.spyOn(fs, 'mkdir').mockResolvedValue(undefined);
86
+ // Mock readdir to return files
87
+ vi.spyOn(fs, 'readdir').mockImplementation(async (dirPath) => {
88
+ if (dirPath.toString().includes('.nexusflow')) {
89
+ return ['custom-one.md'] as any;
90
+ }
91
+ return ['solo-developer.md'] as any;
92
+ });
93
+
94
+ // Mock readFile
95
+ vi.spyOn(fs, 'readFile').mockImplementation(async (filePath) => {
96
+ if (filePath.toString().includes('custom-one.md')) {
97
+ return '# Custom One\n\nDescription content.' as any;
98
+ }
99
+ return '# Solo Developer\n\nOverride content.' as any;
100
+ });
101
+
102
+ const templates = await getWorkflowTemplates();
103
+
104
+ expect(templates.length).toBe(2);
105
+ expect(templates.find(t => t.id === 'custom-one')).toEqual({
106
+ id: 'custom-one',
107
+ name: 'Custom One',
108
+ description: 'Description content.',
109
+ content: '# Custom One\n\nDescription content.',
110
+ custom: true
111
+ });
112
+ });
113
+ });
114
+ });
@@ -0,0 +1,178 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import * as os from 'node:os';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ export interface WorkflowTemplate {
10
+ id: string;
11
+ name: string;
12
+ description: string;
13
+ content: string;
14
+ custom: boolean;
15
+ }
16
+
17
+ function parseMarkdownTemplate(id: string, content: string): Omit<WorkflowTemplate, 'id' | 'custom'> {
18
+ const lines = content.split('\n');
19
+ let name = id.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
20
+ let description = '';
21
+
22
+ // Extract name from the first H1 header (# Name)
23
+ for (const line of lines) {
24
+ if (line.startsWith('# ')) {
25
+ name = line.substring(2).trim();
26
+ break;
27
+ }
28
+ }
29
+
30
+ // Extract description from the first non-empty text paragraph below the H1 header
31
+ let foundHeader = false;
32
+ for (const line of lines) {
33
+ const trimmed = line.trim();
34
+ if (trimmed.startsWith('# ')) {
35
+ foundHeader = true;
36
+ continue;
37
+ }
38
+ if (foundHeader && trimmed.length > 0 && !trimmed.startsWith('#') && !trimmed.startsWith('>')) {
39
+ description = trimmed;
40
+ // Truncate to first sentence or 120 chars
41
+ const sentenceEnd = description.indexOf('.');
42
+ if (sentenceEnd !== -1) {
43
+ description = description.substring(0, sentenceEnd + 1);
44
+ }
45
+ if (description.length > 120) {
46
+ description = description.substring(0, 117) + '...';
47
+ }
48
+ break;
49
+ }
50
+ }
51
+
52
+ // Fallbacks for built-in templates if none extracted
53
+ if (!description) {
54
+ if (id === 'plan-implement-review') {
55
+ description = 'Lead planner designs, Code Implementer subagent writes edits, and Code Reviewer subagent tests & reviews in a loop.';
56
+ } else if (id === 'research-verify') {
57
+ description = 'Research specialist subagent analyzes codebase, followed by test-driven developer subagent implementation.';
58
+ } else if (id === 'solo-developer') {
59
+ description = 'Direct coding and verification by the primary agent without subagent delegation overhead.';
60
+ } else {
61
+ description = 'Custom user-defined teamwork strategy.';
62
+ }
63
+ }
64
+
65
+ return { name, description, content };
66
+ }
67
+
68
+ async function loadTemplatesFromDir(dirPath: string, custom: boolean): Promise<WorkflowTemplate[]> {
69
+ const templates: WorkflowTemplate[] = [];
70
+ try {
71
+ const files = await fs.readdir(dirPath);
72
+ for (const file of files) {
73
+ if (!file.endsWith('.md')) continue;
74
+ const id = path.basename(file, '.md');
75
+ const content = await fs.readFile(path.join(dirPath, file), 'utf-8');
76
+ const parsed = parseMarkdownTemplate(id, content);
77
+ templates.push({
78
+ id,
79
+ custom,
80
+ ...parsed,
81
+ });
82
+ }
83
+ } catch (error) {
84
+ // Only log if directory exists (ignoring non-existent custom folder log spam)
85
+ if ((error as any).code !== 'ENOENT') {
86
+ console.error(`Failed to read templates from ${dirPath}:`, error);
87
+ }
88
+ }
89
+ return templates;
90
+ }
91
+
92
+ export async function getWorkflowTemplates(): Promise<WorkflowTemplate[]> {
93
+ const builtInDir = path.resolve(__dirname, '../resources/workflows');
94
+ const userDir = path.join(os.homedir(), '.nexusflow', 'workflows');
95
+
96
+ // Ensure user custom workflows directory exists so they can find it easily
97
+ try {
98
+ await fs.mkdir(userDir, { recursive: true });
99
+ } catch {}
100
+
101
+ const [builtInTemplates, userTemplates] = await Promise.all([
102
+ loadTemplatesFromDir(builtInDir, false),
103
+ loadTemplatesFromDir(userDir, true)
104
+ ]);
105
+
106
+ // Merge templates (user custom templates override built-in if they share the same ID)
107
+ const templateMap = new Map<string, WorkflowTemplate>();
108
+
109
+ for (const t of builtInTemplates) {
110
+ templateMap.set(t.id, t);
111
+ }
112
+ for (const t of userTemplates) {
113
+ templateMap.set(t.id, t);
114
+ }
115
+
116
+ return Array.from(templateMap.values());
117
+ }
118
+
119
+ export async function saveWorkflowTemplate(name: string, content: string, originalId?: string): Promise<WorkflowTemplate> {
120
+ const userDir = path.join(os.homedir(), '.nexusflow', 'workflows');
121
+ await fs.mkdir(userDir, { recursive: true });
122
+
123
+ // Extract name from the first H1 header (# Name) in content if present
124
+ let parsedName = name;
125
+ const lines = content.split('\n');
126
+ for (const line of lines) {
127
+ if (line.trim().startsWith('# ')) {
128
+ parsedName = line.trim().substring(2).trim();
129
+ break;
130
+ }
131
+ }
132
+
133
+ const id = parsedName
134
+ .toLowerCase()
135
+ .replace(/[^a-z0-9]+/g, '-')
136
+ .replace(/(^-|-$)/g, '');
137
+
138
+ if (!id) {
139
+ throw new Error('Invalid template name');
140
+ }
141
+
142
+ // Ensure content starts with "# <Name>" header so it parses correctly next time
143
+ let fileContent = content.trim();
144
+ if (!fileContent.startsWith('# ')) {
145
+ fileContent = `# ${parsedName}\n\n${fileContent}`;
146
+ }
147
+
148
+ const filePath = path.join(userDir, `${id}.md`);
149
+ await fs.writeFile(filePath, fileContent, 'utf-8');
150
+
151
+ // If we are editing an existing custom template and the ID changed, delete the old file
152
+ if (originalId && originalId !== id) {
153
+ const oldPath = path.join(userDir, `${originalId}.md`);
154
+ try {
155
+ await fs.unlink(oldPath);
156
+ } catch {}
157
+ }
158
+
159
+ const parsed = parseMarkdownTemplate(id, fileContent);
160
+ return {
161
+ id,
162
+ custom: true,
163
+ ...parsed,
164
+ };
165
+ }
166
+
167
+ export async function deleteWorkflowTemplate(id: string): Promise<void> {
168
+ const userDir = path.join(os.homedir(), '.nexusflow', 'workflows');
169
+ const filePath = path.join(userDir, `${id}.md`);
170
+
171
+ try {
172
+ await fs.unlink(filePath);
173
+ } catch (error) {
174
+ if ((error as any).code !== 'ENOENT') {
175
+ throw error;
176
+ }
177
+ }
178
+ }
package/tsconfig.json CHANGED
@@ -1,19 +1,19 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "Node16",
5
- "moduleResolution": "Node16",
6
- "outDir": "dist",
7
- "rootDir": "src",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "forceConsistentCasingInFileNames": true,
12
- "resolveJsonModule": true,
13
- "declaration": true,
14
- "declarationMap": true,
15
- "sourceMap": true
16
- },
17
- "include": ["src/**/*"],
18
- "exclude": ["node_modules", "dist", "tests"]
19
- }
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist", "tests"]
19
+ }
package/vitest.config.ts CHANGED
@@ -1,14 +1,14 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- exclude: [
6
- '**/node_modules/**',
7
- '**/dist/**',
8
- '**/cypress/**',
9
- '**/.{idea,git,cache,output,temp}/**',
10
- '**/scratch/**',
11
- '**/gui/**'
12
- ]
13
- }
14
- });
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ exclude: [
6
+ '**/node_modules/**',
7
+ '**/dist/**',
8
+ '**/cypress/**',
9
+ '**/.{idea,git,cache,output,temp}/**',
10
+ '**/scratch/**',
11
+ '**/gui/**'
12
+ ]
13
+ }
14
+ });