@mrpatronz/nexusflow 1.3.3 → 1.6.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/README.md +50 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +85 -44
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +16 -73
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.d.ts +4 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +58 -318
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/finish.d.ts +17 -0
- package/dist/commands/finish.d.ts.map +1 -0
- package/dist/commands/finish.js +173 -0
- package/dist/commands/finish.js.map +1 -0
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +11 -6
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/knowledge.d.ts +36 -0
- package/dist/commands/knowledge.d.ts.map +1 -0
- package/dist/commands/knowledge.js +184 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/open.d.ts.map +1 -1
- package/dist/commands/open.js +2 -4
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/refresh.d.ts +2 -1
- package/dist/commands/refresh.d.ts.map +1 -1
- package/dist/commands/refresh.js +35 -2
- package/dist/commands/refresh.js.map +1 -1
- package/dist/commands/strategy.d.ts +37 -0
- package/dist/commands/strategy.d.ts.map +1 -0
- package/dist/commands/strategy.js +198 -0
- package/dist/commands/strategy.js.map +1 -0
- package/dist/core/commit.d.ts +41 -0
- package/dist/core/commit.d.ts.map +1 -0
- package/dist/core/commit.js +53 -0
- package/dist/core/commit.js.map +1 -0
- package/dist/core/config.d.ts +3 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +60 -32
- package/dist/core/config.js.map +1 -1
- package/dist/core/config.test.js +24 -0
- package/dist/core/config.test.js.map +1 -1
- package/dist/core/diff.d.ts +27 -0
- package/dist/core/diff.d.ts.map +1 -0
- package/dist/core/diff.js +50 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/doctor.d.ts +34 -0
- package/dist/core/doctor.d.ts.map +1 -0
- package/dist/core/doctor.js +276 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/finish.d.ts +56 -0
- package/dist/core/finish.d.ts.map +1 -0
- package/dist/core/finish.js +121 -0
- package/dist/core/finish.js.map +1 -0
- package/dist/core/finish.test.d.ts +2 -0
- package/dist/core/finish.test.d.ts.map +1 -0
- package/dist/core/finish.test.js +110 -0
- package/dist/core/finish.test.js.map +1 -0
- package/dist/core/knowledge.d.ts +96 -0
- package/dist/core/knowledge.d.ts.map +1 -0
- package/dist/core/knowledge.js +299 -0
- package/dist/core/knowledge.js.map +1 -0
- package/dist/core/knowledge.test.d.ts +2 -0
- package/dist/core/knowledge.test.d.ts.map +1 -0
- package/dist/core/knowledge.test.js +157 -0
- package/dist/core/knowledge.test.js.map +1 -0
- package/dist/core/refresh.test.d.ts +2 -0
- package/dist/core/refresh.test.d.ts.map +1 -0
- package/dist/core/refresh.test.js +67 -0
- package/dist/core/refresh.test.js.map +1 -0
- package/dist/core/status.d.ts +45 -0
- package/dist/core/status.d.ts.map +1 -0
- package/dist/core/status.js +45 -0
- package/dist/core/status.js.map +1 -0
- package/dist/core/sync.test.d.ts +2 -0
- package/dist/core/sync.test.d.ts.map +1 -0
- package/dist/core/sync.test.js +86 -0
- package/dist/core/sync.test.js.map +1 -0
- package/dist/core/workspace.create.test.d.ts +2 -0
- package/dist/core/workspace.create.test.d.ts.map +1 -0
- package/dist/core/workspace.create.test.js +95 -0
- package/dist/core/workspace.create.test.js.map +1 -0
- package/dist/core/workspace.d.ts +9 -3
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +91 -13
- package/dist/core/workspace.js.map +1 -1
- package/dist/core/worktree.d.ts +11 -1
- package/dist/core/worktree.d.ts.map +1 -1
- package/dist/core/worktree.js +2 -0
- package/dist/core/worktree.js.map +1 -1
- package/dist/core/worktree.test.d.ts +2 -0
- package/dist/core/worktree.test.d.ts.map +1 -0
- package/dist/core/worktree.test.js +111 -0
- package/dist/core/worktree.test.js.map +1 -0
- package/dist/generators/base.js +1 -1
- package/dist/generators/index.d.ts +7 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +4 -1
- package/dist/generators/index.js.map +1 -1
- package/dist/index.js +205 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +51 -282
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts +45 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +413 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +43 -26
- package/dist/server.js.map +1 -1
- package/dist/utils/debug.d.ts +17 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +25 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/detect-ai.d.ts +14 -6
- package/dist/utils/detect-ai.d.ts.map +1 -1
- package/dist/utils/detect-ai.js +22 -9
- package/dist/utils/detect-ai.js.map +1 -1
- package/dist/utils/detect-ai.test.js +33 -0
- package/dist/utils/detect-ai.test.js.map +1 -1
- package/dist/utils/git.d.ts +13 -2
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +64 -5
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/git.test.js +46 -8
- package/dist/utils/git.test.js.map +1 -1
- package/dist/utils/multi-git.d.ts +40 -0
- package/dist/utils/multi-git.d.ts.map +1 -1
- package/dist/utils/multi-git.js +80 -0
- package/dist/utils/multi-git.js.map +1 -1
- package/dist/utils/multi-git.test.js +54 -1
- package/dist/utils/multi-git.test.js.map +1 -1
- package/dist/utils/open-editor.d.ts +20 -0
- package/dist/utils/open-editor.d.ts.map +1 -0
- package/dist/utils/open-editor.js +44 -0
- package/dist/utils/open-editor.js.map +1 -0
- package/dist/utils/pr.d.ts +50 -0
- package/dist/utils/pr.d.ts.map +1 -0
- package/dist/utils/pr.js +144 -0
- package/dist/utils/pr.js.map +1 -0
- package/dist/utils/pr.test.d.ts +2 -0
- package/dist/utils/pr.test.d.ts.map +1 -0
- package/dist/utils/pr.test.js +47 -0
- package/dist/utils/pr.test.js.map +1 -0
- package/dist/utils/prompts.d.ts +22 -1
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +145 -24
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/resolve-workspace.d.ts +30 -0
- package/dist/utils/resolve-workspace.d.ts.map +1 -0
- package/dist/utils/resolve-workspace.js +77 -0
- package/dist/utils/resolve-workspace.js.map +1 -0
- package/dist/utils/workflow-advisor.d.ts +2 -0
- package/dist/utils/workflow-advisor.d.ts.map +1 -1
- package/dist/utils/workflow-advisor.js +27 -4
- package/dist/utils/workflow-advisor.js.map +1 -1
- package/package.json +11 -11
package/dist/utils/pr.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module utils/pr
|
|
3
|
+
* Pull-request helpers: detect the GitHub CLI, parse a git remote URL into its
|
|
4
|
+
* host/owner/repo, and construct a "create PR / MR" compare URL for the common
|
|
5
|
+
* forges. Pure functions (`parseRemoteUrl`, `buildCompareUrl`) are unit-tested;
|
|
6
|
+
* `detectGh`/`createPrWithGh` shell out to `gh`.
|
|
7
|
+
*/
|
|
8
|
+
import { execa } from 'execa';
|
|
9
|
+
/** Determines the forge kind from a hostname. */
|
|
10
|
+
function forgeKind(host) {
|
|
11
|
+
const h = host.toLowerCase();
|
|
12
|
+
if (h.includes('github'))
|
|
13
|
+
return 'github';
|
|
14
|
+
if (h.includes('gitlab'))
|
|
15
|
+
return 'gitlab';
|
|
16
|
+
if (h.includes('dev.azure.com') || h.includes('visualstudio.com') || h.includes('azure'))
|
|
17
|
+
return 'azure';
|
|
18
|
+
if (h.includes('bitbucket'))
|
|
19
|
+
return 'bitbucket';
|
|
20
|
+
return 'unknown';
|
|
21
|
+
}
|
|
22
|
+
function stripGitSuffix(s) {
|
|
23
|
+
return s.replace(/\.git$/, '');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parses a git remote URL (https, ssh://, scp-style `git@host:path`, and Azure
|
|
27
|
+
* DevOps variants) into structured parts, or `null` when it cannot be parsed.
|
|
28
|
+
*/
|
|
29
|
+
export function parseRemoteUrl(url) {
|
|
30
|
+
if (!url)
|
|
31
|
+
return null;
|
|
32
|
+
const raw = url.trim();
|
|
33
|
+
// Azure DevOps SSH: git@ssh.dev.azure.com:v3/{org}/{project}/{repo}
|
|
34
|
+
// or: {org}@vs-ssh.visualstudio.com:v3/{org}/{project}/{repo}
|
|
35
|
+
const azureSsh = raw.match(/@(?:ssh\.dev\.azure\.com|[^:@]*vs-ssh\.visualstudio\.com):v3\/([^/]+)\/([^/]+)\/([^/]+)/i);
|
|
36
|
+
if (azureSsh) {
|
|
37
|
+
return {
|
|
38
|
+
host: 'dev.azure.com',
|
|
39
|
+
owner: azureSsh[1],
|
|
40
|
+
project: azureSsh[2],
|
|
41
|
+
repo: stripGitSuffix(azureSsh[3]),
|
|
42
|
+
kind: 'azure',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// Normalize into a URL we can parse with the WHATWG URL class.
|
|
46
|
+
let normalized = raw;
|
|
47
|
+
const scp = raw.match(/^([^@]+)@([^:]+):(.+)$/); // git@host:owner/repo(.git)
|
|
48
|
+
if (scp && !raw.includes('://')) {
|
|
49
|
+
normalized = `ssh://${scp[1]}@${scp[2]}/${scp[3]}`;
|
|
50
|
+
}
|
|
51
|
+
let parsed;
|
|
52
|
+
try {
|
|
53
|
+
parsed = new URL(normalized);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const host = parsed.hostname;
|
|
59
|
+
const kind = forgeKind(host);
|
|
60
|
+
const segments = parsed.pathname.split('/').filter(Boolean).map((s) => decodeURIComponent(s));
|
|
61
|
+
if (segments.length < 2)
|
|
62
|
+
return null;
|
|
63
|
+
// Azure HTTPS: /{org}/{project}/_git/{repo} (org may be a leading path segment)
|
|
64
|
+
const gitIdx = segments.indexOf('_git');
|
|
65
|
+
if (kind === 'azure' && gitIdx >= 1) {
|
|
66
|
+
const repo = segments[gitIdx + 1];
|
|
67
|
+
const project = segments[gitIdx - 1];
|
|
68
|
+
// The org is whatever precedes the project (Azure hosts it at /{org}/...).
|
|
69
|
+
const org = segments.slice(0, gitIdx - 1).join('/') || project;
|
|
70
|
+
if (repo) {
|
|
71
|
+
return { host: 'dev.azure.com', owner: org, project, repo: stripGitSuffix(repo), kind: 'azure' };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Generic: owner(/subgroups)/repo — repo is the last segment.
|
|
75
|
+
const repo = stripGitSuffix(segments[segments.length - 1]);
|
|
76
|
+
const owner = segments.slice(0, segments.length - 1).join('/');
|
|
77
|
+
if (!owner || !repo)
|
|
78
|
+
return null;
|
|
79
|
+
return { host, owner, repo, kind };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Builds a "create a PR/MR" URL for a base←head comparison, or `null` for an
|
|
83
|
+
* unknown forge (the caller should then print the remote URL + branch instead).
|
|
84
|
+
*/
|
|
85
|
+
export function buildCompareUrl(remote, baseBranch, headBranch) {
|
|
86
|
+
const enc = encodeURIComponent;
|
|
87
|
+
switch (remote.kind) {
|
|
88
|
+
case 'github':
|
|
89
|
+
// GitHub accepts raw slashes in the compare segment (feature/x is fine).
|
|
90
|
+
return `https://${remote.host}/${remote.owner}/${remote.repo}/compare/${baseBranch}...${headBranch}?expand=1`;
|
|
91
|
+
case 'gitlab':
|
|
92
|
+
return (`https://${remote.host}/${remote.owner}/${remote.repo}/-/merge_requests/new` +
|
|
93
|
+
`?merge_request%5Bsource_branch%5D=${enc(headBranch)}` +
|
|
94
|
+
`&merge_request%5Btarget_branch%5D=${enc(baseBranch)}`);
|
|
95
|
+
case 'azure':
|
|
96
|
+
return (`https://dev.azure.com/${remote.owner}/${remote.project ?? ''}/_git/${remote.repo}/pullrequestcreate` +
|
|
97
|
+
`?sourceRef=${enc(headBranch)}&targetRef=${enc(baseBranch)}`);
|
|
98
|
+
case 'bitbucket':
|
|
99
|
+
return `https://${remote.host}/${remote.owner}/${remote.repo}/pull-requests/new?source=${enc(headBranch)}&dest=${enc(baseBranch)}`;
|
|
100
|
+
default:
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Detects whether the GitHub CLI is installed and authenticated. */
|
|
105
|
+
export async function detectGh() {
|
|
106
|
+
let installed = false;
|
|
107
|
+
try {
|
|
108
|
+
const v = await execa('gh', ['--version'], { reject: false });
|
|
109
|
+
installed = v.exitCode === 0;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
installed = false;
|
|
113
|
+
}
|
|
114
|
+
if (!installed)
|
|
115
|
+
return { installed: false, authenticated: false };
|
|
116
|
+
let authenticated = false;
|
|
117
|
+
try {
|
|
118
|
+
const a = await execa('gh', ['auth', 'status'], { reject: false });
|
|
119
|
+
authenticated = a.exitCode === 0;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
authenticated = false;
|
|
123
|
+
}
|
|
124
|
+
return { installed, authenticated };
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Creates a PR with the GitHub CLI. Never throws — returns `{ url }` on success
|
|
128
|
+
* or `{ url: null, error }` so the caller can fall back to a compare URL.
|
|
129
|
+
*/
|
|
130
|
+
export async function createPrWithGh(repoPath, opts) {
|
|
131
|
+
try {
|
|
132
|
+
const result = await execa('gh', ['pr', 'create', '--base', opts.base, '--head', opts.head, '--title', opts.title, '--body', opts.body], { cwd: repoPath, reject: false });
|
|
133
|
+
if (result.exitCode === 0) {
|
|
134
|
+
const lines = result.stdout.split('\n').map((l) => l.trim()).filter(Boolean);
|
|
135
|
+
const url = lines.reverse().find((l) => l.startsWith('http')) ?? null;
|
|
136
|
+
return { url };
|
|
137
|
+
}
|
|
138
|
+
return { url: null, error: (result.stderr || result.stdout || 'gh pr create failed').split('\n')[0] };
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
return { url: null, error: error instanceof Error ? error.message : String(error) };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=pr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr.js","sourceRoot":"","sources":["../../src/utils/pr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr.test.d.ts","sourceRoot":"","sources":["../../src/utils/pr.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { parseRemoteUrl, buildCompareUrl } from './pr.js';
|
|
3
|
+
describe('parseRemoteUrl', () => {
|
|
4
|
+
const cases = [
|
|
5
|
+
['https://github.com/owner/repo.git', { host: 'github.com', owner: 'owner', repo: 'repo', kind: 'github' }],
|
|
6
|
+
['https://github.com/owner/repo', { host: 'github.com', owner: 'owner', repo: 'repo', kind: 'github' }],
|
|
7
|
+
['git@github.com:owner/repo.git', { host: 'github.com', owner: 'owner', repo: 'repo', kind: 'github' }],
|
|
8
|
+
['ssh://git@github.com/owner/repo.git', { host: 'github.com', owner: 'owner', repo: 'repo', kind: 'github' }],
|
|
9
|
+
['https://gitlab.com/group/subgroup/repo.git', { host: 'gitlab.com', owner: 'group/subgroup', repo: 'repo', kind: 'gitlab' }],
|
|
10
|
+
['git@bitbucket.org:team/repo.git', { host: 'bitbucket.org', owner: 'team', repo: 'repo', kind: 'bitbucket' }],
|
|
11
|
+
['https://dev.azure.com/myorg/myproject/_git/myrepo', { host: 'dev.azure.com', owner: 'myorg', project: 'myproject', repo: 'myrepo', kind: 'azure' }],
|
|
12
|
+
['git@ssh.dev.azure.com:v3/myorg/myproject/myrepo', { host: 'dev.azure.com', owner: 'myorg', project: 'myproject', repo: 'myrepo', kind: 'azure' }],
|
|
13
|
+
];
|
|
14
|
+
it.each(cases)('parses %s', (url, expected) => {
|
|
15
|
+
expect(parseRemoteUrl(url)).toMatchObject(expected);
|
|
16
|
+
});
|
|
17
|
+
it('returns null for junk', () => {
|
|
18
|
+
expect(parseRemoteUrl('not a url')).toBeNull();
|
|
19
|
+
expect(parseRemoteUrl('')).toBeNull();
|
|
20
|
+
});
|
|
21
|
+
it('classifies an unknown self-hosted host', () => {
|
|
22
|
+
const r = parseRemoteUrl('https://git.internal.corp/team/repo.git');
|
|
23
|
+
expect(r).toMatchObject({ host: 'git.internal.corp', owner: 'team', repo: 'repo', kind: 'unknown' });
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe('buildCompareUrl', () => {
|
|
27
|
+
it('builds a GitHub compare URL preserving slashes in branch names', () => {
|
|
28
|
+
const r = parseRemoteUrl('https://github.com/owner/repo.git');
|
|
29
|
+
expect(buildCompareUrl(r, 'main', 'feature/x')).toBe('https://github.com/owner/repo/compare/main...feature/x?expand=1');
|
|
30
|
+
});
|
|
31
|
+
it('builds a GitLab MR URL with encoded branch params', () => {
|
|
32
|
+
const r = parseRemoteUrl('https://gitlab.com/group/sub/repo.git');
|
|
33
|
+
const url = buildCompareUrl(r, 'main', 'feature/x');
|
|
34
|
+
expect(url).toContain('/group/sub/repo/-/merge_requests/new');
|
|
35
|
+
expect(url).toContain('source_branch%5D=feature%2Fx');
|
|
36
|
+
expect(url).toContain('target_branch%5D=main');
|
|
37
|
+
});
|
|
38
|
+
it('builds an Azure DevOps PR-create URL', () => {
|
|
39
|
+
const r = parseRemoteUrl('https://dev.azure.com/myorg/myproject/_git/myrepo');
|
|
40
|
+
expect(buildCompareUrl(r, 'main', 'feature/x')).toBe('https://dev.azure.com/myorg/myproject/_git/myrepo/pullrequestcreate?sourceRef=feature%2Fx&targetRef=main');
|
|
41
|
+
});
|
|
42
|
+
it('returns null for an unknown forge', () => {
|
|
43
|
+
const r = parseRemoteUrl('https://git.internal.corp/team/repo.git');
|
|
44
|
+
expect(buildCompareUrl(r, 'main', 'feature/x')).toBeNull();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=pr.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr.test.js","sourceRoot":"","sources":["../../src/utils/pr.test.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/prompts.d.ts
CHANGED
|
@@ -3,13 +3,21 @@
|
|
|
3
3
|
* Interactive CLI prompts for NexusFlow using @inquirer/prompts.
|
|
4
4
|
*/
|
|
5
5
|
import type { AIAssistant, DetectedAI, DetectedEditor, RepoInfo } from '../types.js';
|
|
6
|
+
import type { WorkflowTemplate } from './workflows.js';
|
|
6
7
|
/**
|
|
7
8
|
* Prompts the user for a feature branch name.
|
|
8
9
|
*/
|
|
9
10
|
export declare function promptBranchName(): Promise<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Generic prompt for multi-line text input.
|
|
13
|
+
* Offers short inline typing, multi-line editor (safe for pasting), or loading from file.
|
|
14
|
+
*
|
|
15
|
+
* @param entityName e.g., 'feature description', 'commit message'
|
|
16
|
+
* @param emptyFallback Default text to return if left empty in editor mode
|
|
17
|
+
*/
|
|
18
|
+
export declare function promptMultiLineInput(entityName: string, emptyFallback?: string): Promise<string>;
|
|
10
19
|
/**
|
|
11
20
|
* Prompts the user for a feature description.
|
|
12
|
-
* Accepts plain text or a path to a file.
|
|
13
21
|
*/
|
|
14
22
|
export declare function promptDescription(): Promise<string>;
|
|
15
23
|
/**
|
|
@@ -25,4 +33,17 @@ export declare function promptSelectAI(detected: DetectedAI[]): Promise<AIAssist
|
|
|
25
33
|
* Prompts the user to select an editor to open the workspace in.
|
|
26
34
|
*/
|
|
27
35
|
export declare function promptSelectEditor(detected: DetectedEditor[]): Promise<DetectedEditor | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Prompts the user to select a teamwork collaboration strategy.
|
|
38
|
+
* Shows a preview of the selected template before confirming.
|
|
39
|
+
*/
|
|
40
|
+
export declare function promptSelectStrategy(templates: WorkflowTemplate[]): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Prompts the user for a new strategy name and content.
|
|
43
|
+
* Offers two input modes: open $EDITOR for multi-line authoring, or load from a file.
|
|
44
|
+
*/
|
|
45
|
+
export declare function promptNewStrategy(): Promise<{
|
|
46
|
+
name: string;
|
|
47
|
+
content: string;
|
|
48
|
+
}>;
|
|
28
49
|
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAErF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAcxD;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAkDlG;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEzD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA4F9E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,UAAU,EAAE,GACrB,OAAO,CAAC,WAAW,EAAE,CAAC,CAexB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,cAAc,EAAE,GACzB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAwBhC;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,gBAAgB,EAAE,GAC5B,OAAO,CAAC,MAAM,CAAC,CA4CjB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA4CpF"}
|
package/dist/utils/prompts.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @module utils/prompts
|
|
3
3
|
* Interactive CLI prompts for NexusFlow using @inquirer/prompts.
|
|
4
4
|
*/
|
|
5
|
-
import { input, checkbox, confirm, search } from '@inquirer/prompts';
|
|
5
|
+
import { input, checkbox, confirm, select, search, editor } from '@inquirer/prompts';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
import { isValidBranchName } from './git.js';
|
|
8
8
|
/**
|
|
@@ -27,33 +27,66 @@ export async function promptBranchName() {
|
|
|
27
27
|
return branchName.trim();
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
30
|
+
* Generic prompt for multi-line text input.
|
|
31
|
+
* Offers short inline typing, multi-line editor (safe for pasting), or loading from file.
|
|
32
|
+
*
|
|
33
|
+
* @param entityName e.g., 'feature description', 'commit message'
|
|
34
|
+
* @param emptyFallback Default text to return if left empty in editor mode
|
|
32
35
|
*/
|
|
33
|
-
export async function
|
|
36
|
+
export async function promptMultiLineInput(entityName, emptyFallback = '') {
|
|
37
|
+
const mode = await select({
|
|
38
|
+
message: `How do you want to provide the ${entityName}?`,
|
|
39
|
+
choices: [
|
|
40
|
+
{ name: `✍️ Type short ${entityName}`, value: 'short', description: `Type a single-line ${entityName} directly in the terminal` },
|
|
41
|
+
{ name: `📝 Write in editor`, value: 'editor', description: 'Opens your $EDITOR (safest for copy-pasting multi-line text)' },
|
|
42
|
+
{ name: `📂 Load from file`, value: 'file', description: 'Paste a path to a .md or .txt file' },
|
|
43
|
+
],
|
|
44
|
+
});
|
|
45
|
+
if (mode === 'short') {
|
|
46
|
+
const text = await input({
|
|
47
|
+
message: `${entityName.charAt(0).toUpperCase() + entityName.slice(1)}:`,
|
|
48
|
+
validate: (value) => {
|
|
49
|
+
if (!value.trim() && !emptyFallback)
|
|
50
|
+
return `${entityName} cannot be empty`;
|
|
51
|
+
return true;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
return text.trim() || emptyFallback;
|
|
55
|
+
}
|
|
56
|
+
if (mode === 'editor') {
|
|
57
|
+
const text = await editor({
|
|
58
|
+
message: `Write or paste your ${entityName} (save and close the editor when done):`,
|
|
59
|
+
default: '',
|
|
60
|
+
waitForUserInput: false,
|
|
61
|
+
});
|
|
62
|
+
if (!text.trim()) {
|
|
63
|
+
console.log(chalk.yellow(` ⚠ Empty ${entityName} provided.`));
|
|
64
|
+
return emptyFallback;
|
|
65
|
+
}
|
|
66
|
+
return text.trim();
|
|
67
|
+
}
|
|
68
|
+
// File mode
|
|
34
69
|
const { readFile } = await import('node:fs/promises');
|
|
35
70
|
const { existsSync } = await import('node:fs');
|
|
36
|
-
const
|
|
37
|
-
message:
|
|
71
|
+
const filePath = await input({
|
|
72
|
+
message: `Path to ${entityName} file (.md or .txt):`,
|
|
38
73
|
validate: (value) => {
|
|
39
74
|
if (!value.trim())
|
|
40
|
-
return '
|
|
75
|
+
return 'Path cannot be empty';
|
|
76
|
+
if (!existsSync(value.trim()))
|
|
77
|
+
return 'File not found';
|
|
41
78
|
return true;
|
|
42
79
|
},
|
|
43
80
|
});
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// Fall through to use as plain text
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return trimmed;
|
|
81
|
+
const content = await readFile(filePath.trim(), 'utf-8');
|
|
82
|
+
console.log(chalk.dim(` Read ${entityName} from ${filePath.trim()}`));
|
|
83
|
+
return content.trim() || emptyFallback;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Prompts the user for a feature description.
|
|
87
|
+
*/
|
|
88
|
+
export async function promptDescription() {
|
|
89
|
+
return promptMultiLineInput('feature description', 'No description provided.');
|
|
57
90
|
}
|
|
58
91
|
/**
|
|
59
92
|
* Prompts the user to select repos from a list of discovered repos.
|
|
@@ -173,15 +206,103 @@ export async function promptSelectEditor(detected) {
|
|
|
173
206
|
console.log(chalk.yellow(' No editors detected in PATH.'));
|
|
174
207
|
return null;
|
|
175
208
|
}
|
|
176
|
-
const
|
|
209
|
+
const selectedCommand = await select({
|
|
177
210
|
message: 'Select editor:',
|
|
178
211
|
choices: available.map((editor) => ({
|
|
179
212
|
name: editor.name,
|
|
180
213
|
value: editor.command,
|
|
181
214
|
})),
|
|
182
215
|
});
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
216
|
+
return available.find((e) => e.command === selectedCommand) ?? null;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Prompts the user to select a teamwork collaboration strategy.
|
|
220
|
+
* Shows a preview of the selected template before confirming.
|
|
221
|
+
*/
|
|
222
|
+
export async function promptSelectStrategy(templates) {
|
|
223
|
+
const choices = [
|
|
224
|
+
{ name: '✨ Auto-suggest using AI', value: 'auto', description: 'Dynamically analyzes the task to recommend a strategy' },
|
|
225
|
+
{ name: '✏️ Create new custom strategy', value: 'create_new', description: 'Write a new strategy or load from a file' },
|
|
226
|
+
...templates.map((t) => ({
|
|
227
|
+
name: `${t.name}${t.custom ? ' (Custom)' : ''}`,
|
|
228
|
+
value: t.id,
|
|
229
|
+
description: t.description,
|
|
230
|
+
})),
|
|
231
|
+
];
|
|
232
|
+
while (true) {
|
|
233
|
+
const selectedId = await select({
|
|
234
|
+
message: 'Select a teamwork collaboration strategy:',
|
|
235
|
+
choices,
|
|
236
|
+
});
|
|
237
|
+
// Auto and create_new don't need a preview
|
|
238
|
+
if (selectedId === 'auto' || selectedId === 'create_new') {
|
|
239
|
+
return selectedId;
|
|
240
|
+
}
|
|
241
|
+
// Show preview for template-based strategies
|
|
242
|
+
const template = templates.find((t) => t.id === selectedId);
|
|
243
|
+
if (template) {
|
|
244
|
+
console.log(chalk.bold(`\n📄 Preview: ${template.name}\n`));
|
|
245
|
+
console.log(chalk.dim('─'.repeat(60)));
|
|
246
|
+
console.log(template.content);
|
|
247
|
+
console.log(chalk.dim('─'.repeat(60)));
|
|
248
|
+
const confirmed = await confirm({
|
|
249
|
+
message: 'Use this strategy?',
|
|
250
|
+
default: true,
|
|
251
|
+
});
|
|
252
|
+
if (confirmed) {
|
|
253
|
+
return selectedId;
|
|
254
|
+
}
|
|
255
|
+
// Loop back to selection if not confirmed
|
|
256
|
+
console.log();
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
return selectedId;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Prompts the user for a new strategy name and content.
|
|
265
|
+
* Offers two input modes: open $EDITOR for multi-line authoring, or load from a file.
|
|
266
|
+
*/
|
|
267
|
+
export async function promptNewStrategy() {
|
|
268
|
+
const name = await input({
|
|
269
|
+
message: 'New Strategy Name:',
|
|
270
|
+
validate: (value) => value.trim().length > 0 || 'Name cannot be empty',
|
|
271
|
+
});
|
|
272
|
+
const mode = await select({
|
|
273
|
+
message: 'How do you want to provide the strategy content?',
|
|
274
|
+
choices: [
|
|
275
|
+
{ name: '📝 Write in editor', value: 'editor', description: 'Opens your $EDITOR for multi-line content' },
|
|
276
|
+
{ name: '📂 Load from file', value: 'file', description: 'Paste a path to a .md or .txt file' },
|
|
277
|
+
],
|
|
278
|
+
});
|
|
279
|
+
let content;
|
|
280
|
+
if (mode === 'file') {
|
|
281
|
+
const { readFile } = await import('node:fs/promises');
|
|
282
|
+
const { existsSync } = await import('node:fs');
|
|
283
|
+
const filePath = await input({
|
|
284
|
+
message: 'Path to strategy file (.md or .txt):',
|
|
285
|
+
validate: (value) => {
|
|
286
|
+
if (!value.trim())
|
|
287
|
+
return 'Path cannot be empty';
|
|
288
|
+
if (!existsSync(value.trim()))
|
|
289
|
+
return 'File not found';
|
|
290
|
+
return true;
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
content = await readFile(filePath.trim(), 'utf-8');
|
|
294
|
+
console.log(chalk.dim(` Read strategy from ${filePath.trim()}`));
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
content = await editor({
|
|
298
|
+
message: 'Write your strategy content (save and close the editor when done):',
|
|
299
|
+
default: `# ${name.trim()}\n\nDescribe your teamwork cooperation guidelines here.\n\n## Guidelines\n\n- \n`,
|
|
300
|
+
waitForUserInput: false,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
if (!content.trim()) {
|
|
304
|
+
content = `# ${name.trim()}\n\nCustom strategy template.`;
|
|
305
|
+
}
|
|
306
|
+
return { name: name.trim(), content: content.trim() };
|
|
186
307
|
}
|
|
187
308
|
//# sourceMappingURL=prompts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module utils/resolve-workspace
|
|
3
|
+
* Shared workspace-path resolution used by commands. Replaces the near-identical
|
|
4
|
+
* private `resolveWorkspace` helpers previously copied across commit/diff/finish
|
|
5
|
+
* and other commands.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Resolves a workspace path without any interactive prompts.
|
|
9
|
+
*
|
|
10
|
+
* Resolution order: explicit argument → workspace detected from the current
|
|
11
|
+
* working directory → `null`.
|
|
12
|
+
*
|
|
13
|
+
* @param workspaceArg - Optional explicit workspace path.
|
|
14
|
+
* @returns Absolute workspace path, or `null` when none can be determined.
|
|
15
|
+
* @throws If an explicit `workspaceArg` is given but has no `nexusflow.json`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveWorkspaceQuiet(workspaceArg?: string): Promise<string | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Resolves a workspace path, falling back to an interactive picker when it
|
|
20
|
+
* cannot be determined from the argument or the current directory.
|
|
21
|
+
*
|
|
22
|
+
* Prints friendly errors (and returns `null`) rather than throwing, so callers
|
|
23
|
+
* can simply `return` when the result is `null`.
|
|
24
|
+
*
|
|
25
|
+
* @param workspaceArg - Optional explicit workspace path.
|
|
26
|
+
* @param promptMessage - Prompt shown when picking from the workspace list.
|
|
27
|
+
* @returns Absolute workspace path, or `null` when unavailable/none selected.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveWorkspaceInteractive(workspaceArg: string | undefined, promptMessage: string): Promise<string | null>;
|
|
30
|
+
//# sourceMappingURL=resolve-workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-workspace.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-workspace.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiBzF;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,2BAA2B,CAC/C,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4BxB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module utils/resolve-workspace
|
|
3
|
+
* Shared workspace-path resolution used by commands. Replaces the near-identical
|
|
4
|
+
* private `resolveWorkspace` helpers previously copied across commit/diff/finish
|
|
5
|
+
* and other commands.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { select } from '@inquirer/prompts';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import * as fs from 'node:fs/promises';
|
|
11
|
+
import { loadConfig } from '../core/config.js';
|
|
12
|
+
import { listWorkspaces, loadFeatureConfig } from '../core/workspace.js';
|
|
13
|
+
/**
|
|
14
|
+
* Resolves a workspace path without any interactive prompts.
|
|
15
|
+
*
|
|
16
|
+
* Resolution order: explicit argument → workspace detected from the current
|
|
17
|
+
* working directory → `null`.
|
|
18
|
+
*
|
|
19
|
+
* @param workspaceArg - Optional explicit workspace path.
|
|
20
|
+
* @returns Absolute workspace path, or `null` when none can be determined.
|
|
21
|
+
* @throws If an explicit `workspaceArg` is given but has no `nexusflow.json`.
|
|
22
|
+
*/
|
|
23
|
+
export async function resolveWorkspaceQuiet(workspaceArg) {
|
|
24
|
+
if (workspaceArg) {
|
|
25
|
+
const absolutePath = path.resolve(workspaceArg);
|
|
26
|
+
try {
|
|
27
|
+
await fs.access(path.join(absolutePath, 'nexusflow.json'));
|
|
28
|
+
return absolutePath;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error(`Invalid workspace: No nexusflow.json found at ${absolutePath}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const cwdFeature = await loadFeatureConfig(process.cwd());
|
|
35
|
+
if (cwdFeature) {
|
|
36
|
+
return cwdFeature.workspacePath;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolves a workspace path, falling back to an interactive picker when it
|
|
42
|
+
* cannot be determined from the argument or the current directory.
|
|
43
|
+
*
|
|
44
|
+
* Prints friendly errors (and returns `null`) rather than throwing, so callers
|
|
45
|
+
* can simply `return` when the result is `null`.
|
|
46
|
+
*
|
|
47
|
+
* @param workspaceArg - Optional explicit workspace path.
|
|
48
|
+
* @param promptMessage - Prompt shown when picking from the workspace list.
|
|
49
|
+
* @returns Absolute workspace path, or `null` when unavailable/none selected.
|
|
50
|
+
*/
|
|
51
|
+
export async function resolveWorkspaceInteractive(workspaceArg, promptMessage) {
|
|
52
|
+
try {
|
|
53
|
+
const quiet = await resolveWorkspaceQuiet(workspaceArg);
|
|
54
|
+
if (quiet) {
|
|
55
|
+
return quiet;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error(chalk.red(`✖ ${error instanceof Error ? error.message : String(error)}`));
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const config = await loadConfig();
|
|
63
|
+
const workspaces = await listWorkspaces(config.workspacesDir);
|
|
64
|
+
if (workspaces.length === 0) {
|
|
65
|
+
console.log(chalk.yellow('No workspaces found.\n'));
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const selected = await select({
|
|
69
|
+
message: promptMessage,
|
|
70
|
+
choices: workspaces.map((ws) => ({
|
|
71
|
+
name: `${ws.branchName} ${chalk.dim(`(${ws.repos.length} repos)`)}`,
|
|
72
|
+
value: ws.workspacePath,
|
|
73
|
+
})),
|
|
74
|
+
});
|
|
75
|
+
return selected;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=resolve-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-workspace.js","sourceRoot":"","sources":["../../src/utils/resolve-workspace.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzE;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,YAAqB;IAC/D,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC,CAAC;YAC3D,OAAO,YAAY,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,iDAAiD,YAAY,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1D,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC,aAAa,CAAC;IAClC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,YAAgC,EAChC,aAAqB;IAErB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC,YAAY,CAAC,CAAC;QACxD,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QACxF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAE9D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC;QAC5B,OAAO,EAAE,aAAa;QACtB,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC/B,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,SAAS,CAAC,EAAE;YACnE,KAAK,EAAE,EAAE,CAAC,aAAa;SACxB,CAAC,CAAC;KACJ,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module utils/workflow-advisor
|
|
3
3
|
* Dynamically suggests task difficulty and teamwork strategy guidelines.
|
|
4
|
+
* Uses the canonical template files from resources/workflows/ as the source
|
|
5
|
+
* of truth, falling back to inline defaults only when templates are unavailable.
|
|
4
6
|
*/
|
|
5
7
|
import type { LocalLlmConfig, RepoInfo } from '../types.js';
|
|
6
8
|
export interface WorkflowSuggestion {
|