@mrpatronz/nexusflow 1.3.2 → 1.5.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 +54 -37
- 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 +172 -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/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 +110 -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/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/package.json +11 -11
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module mcp/tools
|
|
3
|
+
* Registry of MCP tools NexusFlow exposes to AI assistants. Each tool declares
|
|
4
|
+
* its schema, MCP annotations, an optional `enabled` predicate, and a handler.
|
|
5
|
+
* `server.ts` lists the enabled tools and dispatches calls to their handlers,
|
|
6
|
+
* so adding a tool means adding one entry here.
|
|
7
|
+
*/
|
|
8
|
+
import { execa } from 'execa';
|
|
9
|
+
import * as fs from 'node:fs/promises';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
import { loadFeatureConfig } from '../core/workspace.js';
|
|
12
|
+
import { syncWorkspace } from '../core/sync.js';
|
|
13
|
+
import { getWorkspaceStatusReport } from '../core/status.js';
|
|
14
|
+
import { getWorkspaceDiffReport } from '../core/diff.js';
|
|
15
|
+
import { commitWorkspace } from '../core/commit.js';
|
|
16
|
+
import { refreshWorkspace } from '../core/refresh.js';
|
|
17
|
+
import { runDoctor } from '../core/doctor.js';
|
|
18
|
+
import { finishWorkspace } from '../core/finish.js';
|
|
19
|
+
import { addWorkspaceKnowledge, addBaseKnowledge, promoteKnowledge, } from '../core/knowledge.js';
|
|
20
|
+
import { callLocalLlm } from '../utils/local-ai.js';
|
|
21
|
+
// ─── Result helpers ─────────────────────────────────────────────────────────
|
|
22
|
+
function text(t) {
|
|
23
|
+
return { content: [{ type: 'text', text: t }] };
|
|
24
|
+
}
|
|
25
|
+
function json(value) {
|
|
26
|
+
return text(JSON.stringify(value, null, 2));
|
|
27
|
+
}
|
|
28
|
+
function errorResult(message) {
|
|
29
|
+
return { content: [{ type: 'text', text: message }], isError: true };
|
|
30
|
+
}
|
|
31
|
+
/** Shared `workspaceId` schema property. */
|
|
32
|
+
const workspaceIdProp = {
|
|
33
|
+
workspaceId: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
description: 'Optional ID/branchName of the workspace. If omitted, uses the currently active workspace.',
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
async function requireWorkspace(ctx) {
|
|
39
|
+
const feature = await loadFeatureConfig(ctx.workspacePath);
|
|
40
|
+
if (!feature) {
|
|
41
|
+
throw new Error(`Workspace not found at ${ctx.workspacePath}. Make sure you are in a NexusFlow workspace or provide a valid workspaceId.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// ─── Tools ──────────────────────────────────────────────────────────────────
|
|
45
|
+
export const tools = [
|
|
46
|
+
{
|
|
47
|
+
name: 'search_workspace',
|
|
48
|
+
description: 'Search for a string or regex across all repositories in the NexusFlow workspace. Extremely fast and useful for finding where a specific variable, function, or concept is used across microservices.',
|
|
49
|
+
annotations: { readOnlyHint: true },
|
|
50
|
+
inputSchema: {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
query: { type: 'string', description: 'The search query or regular expression' },
|
|
54
|
+
...workspaceIdProp,
|
|
55
|
+
},
|
|
56
|
+
required: ['query'],
|
|
57
|
+
},
|
|
58
|
+
handler: async (args, ctx) => {
|
|
59
|
+
const query = args.query;
|
|
60
|
+
try {
|
|
61
|
+
const feature = await loadFeatureConfig(ctx.workspacePath);
|
|
62
|
+
if (!feature) {
|
|
63
|
+
throw new Error(`Workspace not found at ${ctx.workspacePath}. Make sure you are in a NexusFlow workspace or provide a valid workspaceId.`);
|
|
64
|
+
}
|
|
65
|
+
let allResults = '';
|
|
66
|
+
for (const repoPath of feature.repos) {
|
|
67
|
+
const repoName = path.basename(repoPath);
|
|
68
|
+
const worktreePath = path.join(ctx.workspacePath, repoName);
|
|
69
|
+
try {
|
|
70
|
+
await fs.access(worktreePath);
|
|
71
|
+
const { stdout } = await execa('git', ['grep', '-n', '-I', query], { cwd: worktreePath, reject: false });
|
|
72
|
+
if (stdout) {
|
|
73
|
+
allResults += stdout.split('\n').map((line) => `[${repoName}] ${line}`).join('\n') + '\n';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// No match or repo missing — skip.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return text(allResults || 'No results found across the workspace repositories.');
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return errorResult(`Error searching workspace: ${error.message}`);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'workspace_status',
|
|
89
|
+
description: 'Report the git status of every repo in the workspace: current branch, whether it matches the feature branch, dirty files, commits ahead/behind origin, and remote URL. Read-only; use this before committing or finishing.',
|
|
90
|
+
annotations: { readOnlyHint: true },
|
|
91
|
+
inputSchema: { type: 'object', properties: { ...workspaceIdProp } },
|
|
92
|
+
handler: async (_args, ctx) => {
|
|
93
|
+
try {
|
|
94
|
+
await requireWorkspace(ctx);
|
|
95
|
+
return json(await getWorkspaceStatusReport(ctx.workspacePath));
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return errorResult(`Error getting workspace status: ${error.message}`);
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'get_workspace_diff',
|
|
104
|
+
description: 'Summarize uncommitted changes and unpushed commits across the workspace repos (files changed, insertions/deletions, commits ahead of origin). Read-only.',
|
|
105
|
+
annotations: { readOnlyHint: true },
|
|
106
|
+
inputSchema: {
|
|
107
|
+
type: 'object',
|
|
108
|
+
properties: {
|
|
109
|
+
repos: { type: 'array', items: { type: 'string' }, description: 'Optional list of repo names to restrict the diff to.' },
|
|
110
|
+
...workspaceIdProp,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
handler: async (args, ctx) => {
|
|
114
|
+
try {
|
|
115
|
+
await requireWorkspace(ctx);
|
|
116
|
+
const repos = Array.isArray(args.repos) ? args.repos : undefined;
|
|
117
|
+
return json(await getWorkspaceDiffReport(ctx.workspacePath, repos));
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
return errorResult(`Error getting workspace diff: ${error.message}`);
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'commit_workspace',
|
|
126
|
+
description: 'Stage, commit, and (unless noPush) push all repos that have changes, using one commit message. Returns a per-repo report. This writes to git history and pushes to the remote.',
|
|
127
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
|
|
128
|
+
inputSchema: {
|
|
129
|
+
type: 'object',
|
|
130
|
+
properties: {
|
|
131
|
+
message: { type: 'string', description: 'Commit message applied to every changed repo.' },
|
|
132
|
+
noPush: { type: 'boolean', description: 'Commit but do not push. Default false.' },
|
|
133
|
+
repos: { type: 'array', items: { type: 'string' }, description: 'Optional list of repo names to restrict the commit to.' },
|
|
134
|
+
...workspaceIdProp,
|
|
135
|
+
},
|
|
136
|
+
required: ['message'],
|
|
137
|
+
},
|
|
138
|
+
handler: async (args, ctx) => {
|
|
139
|
+
try {
|
|
140
|
+
await requireWorkspace(ctx);
|
|
141
|
+
const message = String(args.message ?? '').trim();
|
|
142
|
+
if (!message)
|
|
143
|
+
return errorResult('A commit message is required.');
|
|
144
|
+
const repos = Array.isArray(args.repos) ? args.repos : undefined;
|
|
145
|
+
return json(await commitWorkspace(ctx.workspacePath, message, { noPush: Boolean(args.noPush), repos }));
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
return errorResult(`Error committing workspace: ${error.message}`);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: 'sync_workspace',
|
|
154
|
+
description: 'Rebase every repository in the NexusFlow workspace onto its base branch. Safe to call non-interactively: dirty working trees are auto-stashed and restored, so a dirty tree is never mis-reported as a conflict. Returns structured per-repo results (status: up-to-date | rebased | conflict | stash-conflict | error) and records them to the workspace state file.',
|
|
155
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
156
|
+
inputSchema: { type: 'object', properties: { ...workspaceIdProp } },
|
|
157
|
+
handler: async (_args, ctx) => {
|
|
158
|
+
try {
|
|
159
|
+
await requireWorkspace(ctx);
|
|
160
|
+
return json(await syncWorkspace(ctx.workspacePath));
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
return errorResult(`Error syncing workspace: ${error.message}`);
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'refresh_context',
|
|
169
|
+
description: 'Regenerate the workspace context files, architecture maps, and plan. Only re-analyzes repos whose content changed (unchanged maps stay byte-identical to preserve prompt caches). Run this after code changes so the AI context stays current.',
|
|
170
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: 'object',
|
|
173
|
+
properties: {
|
|
174
|
+
repo: { type: 'string', description: 'Only refresh a single repo (by directory name).' },
|
|
175
|
+
baseOnly: { type: 'boolean', description: 'Only refresh base-layer maps and knowledge.' },
|
|
176
|
+
force: { type: 'boolean', description: 'Ignore the analysis cache and re-analyze every repo.' },
|
|
177
|
+
...workspaceIdProp,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
handler: async (args, ctx) => {
|
|
181
|
+
try {
|
|
182
|
+
await requireWorkspace(ctx);
|
|
183
|
+
return json(await refreshWorkspace(ctx.workspacePath, {
|
|
184
|
+
onlyRepo: args.repo ? String(args.repo) : undefined,
|
|
185
|
+
baseOnly: Boolean(args.baseOnly),
|
|
186
|
+
force: Boolean(args.force),
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
return errorResult(`Error refreshing context: ${error.message}`);
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
name: 'run_doctor',
|
|
196
|
+
description: 'Run workspace health diagnostics: worktree paths, branch alignment, uncommitted changes, local package setup, test commands, core artifacts, and local-AI connectivity. Returns a structured report. Read-only.',
|
|
197
|
+
annotations: { readOnlyHint: true },
|
|
198
|
+
inputSchema: { type: 'object', properties: { ...workspaceIdProp } },
|
|
199
|
+
handler: async (_args, ctx) => {
|
|
200
|
+
try {
|
|
201
|
+
await requireWorkspace(ctx);
|
|
202
|
+
return json(await runDoctor(ctx.workspacePath));
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
return errorResult(`Error running doctor: ${error.message}`);
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: 'add_knowledge',
|
|
211
|
+
description: 'Record a learning in the workspace knowledge file (or a repo base file with `repo`). Use this whenever you make an architecture decision, discover a gotcha, complete a milestone, or note an assumption — it is the preferred way to persist learnings instead of editing nexusflow-knowledge.md directly.',
|
|
212
|
+
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
213
|
+
inputSchema: {
|
|
214
|
+
type: 'object',
|
|
215
|
+
properties: {
|
|
216
|
+
type: { type: 'string', enum: ['decision', 'gotcha', 'progress', 'assumption', 'question'], description: 'The kind of learning.' },
|
|
217
|
+
message: { type: 'string', description: 'The learning to record.' },
|
|
218
|
+
title: { type: 'string', description: 'Short title (used for decision headings).' },
|
|
219
|
+
repo: { type: 'string', description: "Write to this repo's persistent base knowledge instead of the workspace file (decision/gotcha/assumption only)." },
|
|
220
|
+
...workspaceIdProp,
|
|
221
|
+
},
|
|
222
|
+
required: ['type', 'message'],
|
|
223
|
+
},
|
|
224
|
+
handler: async (args, ctx) => {
|
|
225
|
+
try {
|
|
226
|
+
await requireWorkspace(ctx);
|
|
227
|
+
const type = args.type;
|
|
228
|
+
const message = String(args.message ?? '').trim();
|
|
229
|
+
if (!message)
|
|
230
|
+
return errorResult('A knowledge message is required.');
|
|
231
|
+
const entry = { type, message, title: args.title ? String(args.title) : undefined };
|
|
232
|
+
const result = args.repo
|
|
233
|
+
? await addBaseKnowledge(ctx.workspacePath, String(args.repo), entry)
|
|
234
|
+
: await addWorkspaceKnowledge(ctx.workspacePath, entry);
|
|
235
|
+
return json(result);
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
return errorResult(`Error adding knowledge: ${error.message}`);
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: 'promote_knowledge',
|
|
244
|
+
description: "Promote a reusable learning into a repo's persistent base knowledge so it survives across features. Provide the repo, the entry type (decision | gotcha | assumption), and the text.",
|
|
245
|
+
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
246
|
+
inputSchema: {
|
|
247
|
+
type: 'object',
|
|
248
|
+
properties: {
|
|
249
|
+
repo: { type: 'string', description: 'Target repository (by directory name).' },
|
|
250
|
+
type: { type: 'string', enum: ['decision', 'gotcha', 'assumption'], description: 'The kind of learning to promote.' },
|
|
251
|
+
text: { type: 'string', description: 'The learning text to store in base knowledge.' },
|
|
252
|
+
move: { type: 'boolean', description: 'Reserved; base promotion is additive. Default false.' },
|
|
253
|
+
...workspaceIdProp,
|
|
254
|
+
},
|
|
255
|
+
required: ['repo', 'type', 'text'],
|
|
256
|
+
},
|
|
257
|
+
handler: async (args, ctx) => {
|
|
258
|
+
try {
|
|
259
|
+
await requireWorkspace(ctx);
|
|
260
|
+
const type = args.type;
|
|
261
|
+
const textValue = String(args.text ?? '').trim();
|
|
262
|
+
if (!textValue)
|
|
263
|
+
return errorResult('The learning text is required.');
|
|
264
|
+
// Store the supplied text verbatim under the base section for its type.
|
|
265
|
+
const entry = { section: '', type, text: textValue };
|
|
266
|
+
const result = await promoteKnowledge(ctx.workspacePath, {
|
|
267
|
+
repoName: String(args.repo),
|
|
268
|
+
entries: [entry],
|
|
269
|
+
mode: 'copy',
|
|
270
|
+
});
|
|
271
|
+
return json(result);
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
return errorResult(`Error promoting knowledge: ${error.message}`);
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'finish_workspace',
|
|
280
|
+
description: 'Finish the feature: commit any remaining changes (with the given message), push every repo, and return per-repo PR/compare links. Does NOT delete anything — to remove the workspace, the user runs `nexusflow finish --cleanup` from outside it.',
|
|
281
|
+
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
|
|
282
|
+
inputSchema: {
|
|
283
|
+
type: 'object',
|
|
284
|
+
properties: {
|
|
285
|
+
message: { type: 'string', description: 'Commit message for any remaining changes.' },
|
|
286
|
+
skipPush: { type: 'boolean', description: 'Commit but do not push. Default false.' },
|
|
287
|
+
...workspaceIdProp,
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
handler: async (args, ctx) => {
|
|
291
|
+
try {
|
|
292
|
+
await requireWorkspace(ctx);
|
|
293
|
+
const report = await finishWorkspace(ctx.workspacePath, {
|
|
294
|
+
message: args.message ? String(args.message) : undefined,
|
|
295
|
+
skipPush: Boolean(args.skipPush),
|
|
296
|
+
createPrs: true,
|
|
297
|
+
});
|
|
298
|
+
// MCP never deletes worktrees (an agent's CWD is usually inside the
|
|
299
|
+
// workspace). Point the user at the CLI for cleanup instead.
|
|
300
|
+
return json({
|
|
301
|
+
...report,
|
|
302
|
+
note: report.safeToCleanup
|
|
303
|
+
? 'Workspace is fully pushed. To remove it, run `nexusflow finish --cleanup` from outside the workspace.'
|
|
304
|
+
: 'Some repos are still dirty or unpushed — see the per-repo report.',
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
return errorResult(`Error finishing workspace: ${error.message}`);
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
name: 'get_service_logs',
|
|
314
|
+
description: 'Get the recent logs for a specific running service in the workspace to debug runtime issues.',
|
|
315
|
+
annotations: { readOnlyHint: true },
|
|
316
|
+
inputSchema: {
|
|
317
|
+
type: 'object',
|
|
318
|
+
properties: {
|
|
319
|
+
serviceName: { type: 'string', description: 'The name of the service to fetch logs for (e.g. "frontend", "backend-api")' },
|
|
320
|
+
lines: { type: 'number', description: 'Number of lines to fetch. Default 50.' },
|
|
321
|
+
...workspaceIdProp,
|
|
322
|
+
},
|
|
323
|
+
required: ['serviceName'],
|
|
324
|
+
},
|
|
325
|
+
handler: async (args, ctx) => {
|
|
326
|
+
const serviceName = args.serviceName;
|
|
327
|
+
const lines = args.lines || 50;
|
|
328
|
+
try {
|
|
329
|
+
const logFilePath = path.join(ctx.workspacePath, '.nexusflow-logs', `${serviceName}.log`);
|
|
330
|
+
try {
|
|
331
|
+
await fs.access(logFilePath);
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
return errorResult(`Log file for service "${serviceName}" not found. Ensure the service is running via "nexusflow start".`);
|
|
335
|
+
}
|
|
336
|
+
const content = await fs.readFile(logFilePath, 'utf8');
|
|
337
|
+
const tail = content.split('\n').slice(-lines).join('\n');
|
|
338
|
+
return text(tail || '(empty log)');
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
return errorResult(`Error reading logs: ${error.message}`);
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
name: 'delegate_to_local_agent',
|
|
347
|
+
description: "Delegate simple, high-volume, or repetitive tasks (like searching code, parsing raw service logs, or generating boilerplate) to the local Small Language Model (SLM) running on the user's machine to save remote tokens.",
|
|
348
|
+
enabled: (config) => Boolean(config.localLlm?.enabled),
|
|
349
|
+
annotations: { readOnlyHint: true },
|
|
350
|
+
inputSchema: {
|
|
351
|
+
type: 'object',
|
|
352
|
+
properties: {
|
|
353
|
+
instruction: { type: 'string', description: 'The specific instruction for the local agent.' },
|
|
354
|
+
filesToRead: { type: 'array', items: { type: 'string' }, description: 'Optional workspace-relative file paths the local agent should read as context.' },
|
|
355
|
+
},
|
|
356
|
+
required: ['instruction'],
|
|
357
|
+
},
|
|
358
|
+
handler: async (args, ctx) => {
|
|
359
|
+
const instruction = args.instruction;
|
|
360
|
+
const filesToRead = args.filesToRead || [];
|
|
361
|
+
try {
|
|
362
|
+
if (!ctx.config.localLlm || !ctx.config.localLlm.enabled) {
|
|
363
|
+
throw new Error('Local AI agent delegation is disabled. Enable it in ~/.nexusflow/config.json or settings.');
|
|
364
|
+
}
|
|
365
|
+
const contextFiles = [];
|
|
366
|
+
const normalizedWorkspace = ctx.workspacePath.endsWith(path.sep) ? ctx.workspacePath : ctx.workspacePath + path.sep;
|
|
367
|
+
for (const relativePath of filesToRead) {
|
|
368
|
+
const filePath = path.resolve(ctx.workspacePath, relativePath);
|
|
369
|
+
if (!filePath.startsWith(normalizedWorkspace)) {
|
|
370
|
+
contextFiles.push({ path: relativePath, content: '[Access denied: path is outside workspace boundary]' });
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
375
|
+
const truncatedContent = content.length > 50000
|
|
376
|
+
? content.substring(0, 50000) + '\n\n[Content truncated by NexusFlow to save local context size...]'
|
|
377
|
+
: content;
|
|
378
|
+
contextFiles.push({ path: relativePath, content: truncatedContent });
|
|
379
|
+
}
|
|
380
|
+
catch (e) {
|
|
381
|
+
contextFiles.push({ path: relativePath, content: `[Error reading file: ${e.message || 'unknown error'}]` });
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
const messages = [];
|
|
385
|
+
let systemPrompt = 'You are the NexusFlow local assistant. You are running locally on the user\'s machine to help the remote supervisor agent solve a specific sub-task in a multi-repo workspace.\n';
|
|
386
|
+
systemPrompt += 'Your goal is to be extremely precise, concise, and return only the distilled findings/code to save remote network tokens. Keep your response short, focused, and directly address the instruction.';
|
|
387
|
+
messages.push({ role: 'system', content: systemPrompt });
|
|
388
|
+
let userPrompt = '';
|
|
389
|
+
if (contextFiles.length > 0) {
|
|
390
|
+
userPrompt += 'Here is the local file/log context:\n\n';
|
|
391
|
+
for (const file of contextFiles) {
|
|
392
|
+
userPrompt += `--- FILE: ${file.path} ---\n${file.content}\n\n`;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
userPrompt += `Instruction: ${instruction}`;
|
|
396
|
+
messages.push({ role: 'user', content: userPrompt });
|
|
397
|
+
return text(await callLocalLlm(ctx.config.localLlm, messages));
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
return errorResult(`Error delegating to local agent: ${error.message}`);
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
];
|
|
405
|
+
/** Returns the tools enabled for the given config. */
|
|
406
|
+
export function enabledTools(config) {
|
|
407
|
+
return tools.filter((t) => !t.enabled || t.enabled(config));
|
|
408
|
+
}
|
|
409
|
+
/** Finds a tool by name (regardless of enabled state). */
|
|
410
|
+
export function findTool(name) {
|
|
411
|
+
return tools.find((t) => t.name === name);
|
|
412
|
+
}
|
|
413
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAoE5B,eAAO,MAAM,GAAG,4EAAa,CAAC;AAW9B,yEAAyE;AACzE,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,SAA2B;CAI/C;AAcD,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE/E;AAWD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAc7D;AA46CD,wBAAgB,WAAW,CACzB,IAAI,SAAO,EACX,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,CAwBxC"}
|
package/dist/server.js
CHANGED
|
@@ -27,9 +27,12 @@ import { detectAIAssistants } from './utils/detect-ai.js';
|
|
|
27
27
|
import { detectEditors } from './utils/detect-editors.js';
|
|
28
28
|
import { findSessions, getSessionTranscript } from './utils/session-finder.js';
|
|
29
29
|
import { scanSystemSpecs } from './utils/system-scanner.js';
|
|
30
|
-
import {
|
|
30
|
+
import { getRepoStatus } from './utils/multi-git.js';
|
|
31
31
|
import { syncWorkspace } from './core/sync.js';
|
|
32
|
+
import { commitWorkspace } from './core/commit.js';
|
|
32
33
|
import { refreshWorkspace } from './core/refresh.js';
|
|
34
|
+
import { writeWorkspaceFile } from './core/storage.js';
|
|
35
|
+
import { readWorkspaceKnowledge, addWorkspaceKnowledge, addBaseKnowledge, } from './core/knowledge.js';
|
|
33
36
|
import { addSchedule, loadSchedules, nextDueAt, parseInterval, removeSchedule, runJob, setScheduleEnabled, startScheduler, } from './core/scheduler.js';
|
|
34
37
|
import { detectAllServices, detectOrchestrationTools, startServices, stopServices, loadRunningState, getPm2List, } from './orchestration/index.js';
|
|
35
38
|
import { checkForUpdates, getCurrentVersion, getToolsStatus } from './utils/update-check.js';
|
|
@@ -849,19 +852,15 @@ app.get('/api/workspace/:id/changes/diff', async (c) => {
|
|
|
849
852
|
}
|
|
850
853
|
});
|
|
851
854
|
// 13a. Get workspace knowledge (nexusflow-knowledge.md)
|
|
855
|
+
// Routed through the active storage adapter so the GUI edits the same file the
|
|
856
|
+
// generators write (under the Obsidian/vault adapters this lives outside the
|
|
857
|
+
// workspace directory).
|
|
852
858
|
app.get('/api/workspace/:id/knowledge', async (c) => {
|
|
853
859
|
try {
|
|
854
860
|
const id = c.req.param('id');
|
|
855
861
|
const config = await loadConfig();
|
|
856
862
|
const workspacePath = resolveWorkspacePath(config.workspacesDir, id);
|
|
857
|
-
const
|
|
858
|
-
let content = '';
|
|
859
|
-
try {
|
|
860
|
-
content = await fs.readFile(knowledgeFile, 'utf-8');
|
|
861
|
-
}
|
|
862
|
-
catch {
|
|
863
|
-
content = '# Workspace Knowledge\n\nNo knowledge file yet.';
|
|
864
|
-
}
|
|
863
|
+
const content = (await readWorkspaceKnowledge(workspacePath)) ?? '# Workspace Knowledge\n\nNo knowledge file yet.';
|
|
865
864
|
return c.json({ content });
|
|
866
865
|
}
|
|
867
866
|
catch (error) {
|
|
@@ -875,14 +874,39 @@ app.put('/api/workspace/:id/knowledge', async (c) => {
|
|
|
875
874
|
const { content } = await c.req.json();
|
|
876
875
|
const config = await loadConfig();
|
|
877
876
|
const workspacePath = resolveWorkspacePath(config.workspacesDir, id);
|
|
878
|
-
const
|
|
879
|
-
|
|
877
|
+
const feature = await loadFeatureConfig(workspacePath);
|
|
878
|
+
const featureId = feature?.id ?? path.basename(workspacePath);
|
|
879
|
+
await writeWorkspaceFile(workspacePath, featureId, 'nexusflow-knowledge.md', content);
|
|
880
880
|
return c.json({ success: true });
|
|
881
881
|
}
|
|
882
882
|
catch (error) {
|
|
883
883
|
return errorResponse(c, error);
|
|
884
884
|
}
|
|
885
885
|
});
|
|
886
|
+
// 13b-2. Append a single structured learning (used for a GUI quick-add).
|
|
887
|
+
app.post('/api/workspace/:id/knowledge/entry', async (c) => {
|
|
888
|
+
try {
|
|
889
|
+
const id = c.req.param('id');
|
|
890
|
+
const body = (await c.req.json());
|
|
891
|
+
const config = await loadConfig();
|
|
892
|
+
const workspacePath = resolveWorkspacePath(config.workspacesDir, id);
|
|
893
|
+
const result = body.repo
|
|
894
|
+
? await addBaseKnowledge(workspacePath, body.repo, {
|
|
895
|
+
type: body.type,
|
|
896
|
+
message: body.message,
|
|
897
|
+
title: body.title,
|
|
898
|
+
})
|
|
899
|
+
: await addWorkspaceKnowledge(workspacePath, {
|
|
900
|
+
type: body.type,
|
|
901
|
+
message: body.message,
|
|
902
|
+
title: body.title,
|
|
903
|
+
});
|
|
904
|
+
return c.json({ success: true, ...result });
|
|
905
|
+
}
|
|
906
|
+
catch (error) {
|
|
907
|
+
return errorResponse(c, error);
|
|
908
|
+
}
|
|
909
|
+
});
|
|
886
910
|
// 13c. Get workspace plan (nexusflow-plan.md)
|
|
887
911
|
app.get('/api/workspace/:id/plan', async (c) => {
|
|
888
912
|
try {
|
|
@@ -935,21 +959,14 @@ app.post('/api/workspace/:id/commit', async (c) => {
|
|
|
935
959
|
const { message } = await c.req.json();
|
|
936
960
|
const config = await loadConfig();
|
|
937
961
|
const workspacePath = resolveWorkspacePath(config.workspacesDir, id);
|
|
938
|
-
const
|
|
939
|
-
const results =
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
success: result.success,
|
|
947
|
-
commitHash: result.commitHash,
|
|
948
|
-
filesChanged: result.filesChanged,
|
|
949
|
-
message: result.message,
|
|
950
|
-
});
|
|
951
|
-
}
|
|
952
|
-
}
|
|
962
|
+
const report = await commitWorkspace(workspacePath, message);
|
|
963
|
+
const results = report.repos.map((repo) => ({
|
|
964
|
+
repoName: repo.name,
|
|
965
|
+
success: repo.success,
|
|
966
|
+
commitHash: repo.commitHash,
|
|
967
|
+
filesChanged: repo.filesChanged,
|
|
968
|
+
message: repo.message,
|
|
969
|
+
}));
|
|
953
970
|
return c.json({ results });
|
|
954
971
|
}
|
|
955
972
|
catch (error) {
|