nexus-prime 7.9.23 → 7.9.25
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.
|
@@ -280,9 +280,10 @@ export function buildMcpToolDefinitions() {
|
|
|
280
280
|
specialists: { type: 'array', items: { type: 'string' }, description: 'Optional hard specialist selectors' },
|
|
281
281
|
optimizationProfile: { type: 'string', enum: ['standard', 'max'], description: 'Planner optimization profile override' },
|
|
282
282
|
executionPreset: { type: 'string', enum: ['fast', 'balanced', 'deep', 'release'], description: 'Optional execution preset that maps orchestration depth, verification strictness, and backend routing' },
|
|
283
|
-
background: { type: 'boolean', description: '
|
|
283
|
+
background: { type: 'boolean', description: 'Compatibility flag; nexus_orchestrate already returns a queued hiring preflight by default and continues in the async gate.' },
|
|
284
284
|
async: { type: 'boolean', description: 'Alias for background; useful for clients that prefer explicit async orchestration.' },
|
|
285
|
-
waitMs: { type: 'number', description: '
|
|
285
|
+
waitMs: { type: 'number', description: 'Advanced/debug bounded wait for inline execution. Clamped to 45 seconds; normal orchestrate calls return a queued preflight immediately.' },
|
|
286
|
+
inline: { type: 'boolean', description: 'Advanced/debug only: wait for inline orchestrate output instead of the default fast queued preflight.' }
|
|
286
287
|
},
|
|
287
288
|
required: ['prompt'],
|
|
288
289
|
},
|
|
@@ -19,6 +19,7 @@ import { recordToolInvocation } from './tool-health.js';
|
|
|
19
19
|
import { getAsyncGate, withAsyncGate } from './async-gate.js';
|
|
20
20
|
import { getCircuitManager, checkBackpressure } from './circuit.js';
|
|
21
21
|
import { completeRun, createRun, failRun, updateStage } from '../../../engines/orchestrator/store.js';
|
|
22
|
+
import { buildSelectionPlan } from '../../../engines/orchestrator/decision-spine.js';
|
|
22
23
|
function summarizeAsyncMcpResult(toolName, result) {
|
|
23
24
|
const text = result?.content
|
|
24
25
|
?.map((part) => part?.type === 'text' ? String(part.text ?? '') : '')
|
|
@@ -99,6 +100,9 @@ function coerceBoundedWaitMs(value) {
|
|
|
99
100
|
function shouldReturnQueuedReceipt(toolName, args) {
|
|
100
101
|
if (!SLOW_TOOLS.has(toolName))
|
|
101
102
|
return false;
|
|
103
|
+
if (toolName === 'nexus_orchestrate') {
|
|
104
|
+
return !isTruthyFlag(args.inline) && !isTruthyFlag(args.sync) && !isTruthyFlag(args.blocking);
|
|
105
|
+
}
|
|
102
106
|
return isTruthyFlag(args.background)
|
|
103
107
|
|| isTruthyFlag(args.async)
|
|
104
108
|
|| isTruthyFlag(args.queue)
|
|
@@ -109,6 +113,158 @@ function resolveMaxSyncMs(toolName, args) {
|
|
|
109
113
|
?? coerceBoundedWaitMs(args.maxSyncMs)
|
|
110
114
|
?? (toolName === 'nexus_orchestrate' ? ORCHESTRATE_DEFAULT_MAX_SYNC_MS : DEFAULT_MAX_SYNC_MS);
|
|
111
115
|
}
|
|
116
|
+
function asStringList(value) {
|
|
117
|
+
if (Array.isArray(value)) {
|
|
118
|
+
return value
|
|
119
|
+
.map((item) => typeof item === 'string' ? item : (item && typeof item === 'object' ? String(item.name ?? item.id ?? '') : String(item ?? '')))
|
|
120
|
+
.map((item) => item.trim())
|
|
121
|
+
.filter(Boolean);
|
|
122
|
+
}
|
|
123
|
+
if (typeof value === 'string') {
|
|
124
|
+
return value.split(',')
|
|
125
|
+
.map((item) => item.trim())
|
|
126
|
+
.filter(Boolean);
|
|
127
|
+
}
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
function uniqueList(items, max = 8) {
|
|
131
|
+
const seen = new Set();
|
|
132
|
+
const out = [];
|
|
133
|
+
for (const item of items) {
|
|
134
|
+
const value = String(item ?? '').trim();
|
|
135
|
+
if (!value || seen.has(value))
|
|
136
|
+
continue;
|
|
137
|
+
seen.add(value);
|
|
138
|
+
out.push(value);
|
|
139
|
+
if (out.length >= max)
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
function extractLinkedSelectors(prompt, prefix) {
|
|
145
|
+
const escaped = prefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
146
|
+
const pattern = new RegExp(`\\[${escaped}([^\\]\\s]+)\\]`, 'g');
|
|
147
|
+
return Array.from(prompt.matchAll(pattern))
|
|
148
|
+
.map((match) => match[1]?.trim())
|
|
149
|
+
.filter(Boolean);
|
|
150
|
+
}
|
|
151
|
+
function inferQueuedOrchestratePreview(args, runId) {
|
|
152
|
+
const prompt = String(args.prompt ?? args.goal ?? '');
|
|
153
|
+
const lower = prompt.toLowerCase();
|
|
154
|
+
const files = uniqueList([
|
|
155
|
+
...asStringList(args.files),
|
|
156
|
+
...asStringList(args.filePaths),
|
|
157
|
+
], 20);
|
|
158
|
+
const skills = uniqueList([
|
|
159
|
+
...asStringList(args.skills),
|
|
160
|
+
...asStringList(args.skillNames),
|
|
161
|
+
...extractLinkedSelectors(prompt, '$'),
|
|
162
|
+
], 20);
|
|
163
|
+
const isRuntimeControlPlane = /orchestrat|synapse|architect|runtime|mcp|dispatch|route|routing|queue|queued|scheduler|model routing|worker|hiring|workflow selection|token|budget|memory|lifecycle/.test(lower);
|
|
164
|
+
const wantsResearch = /research|paper|literature|deep-research|source-grounded|cited/.test(lower);
|
|
165
|
+
const wantsMemory = /memory|recall|learning|decay|graph|mcp/.test(lower);
|
|
166
|
+
const wantsPerf = /fast|faster|millisecond|latency|performance|budget|token|optim/i.test(lower);
|
|
167
|
+
const workflows = uniqueList([
|
|
168
|
+
...asStringList(args.workflows),
|
|
169
|
+
...asStringList(args.workflowSelectors),
|
|
170
|
+
isRuntimeControlPlane ? 'orchestration-execution-loop' : undefined,
|
|
171
|
+
isRuntimeControlPlane ? 'backend-execution-loop' : undefined,
|
|
172
|
+
isRuntimeControlPlane ? 'testing-execution-loop' : undefined,
|
|
173
|
+
isRuntimeControlPlane && !wantsResearch ? 'typescript-execution-loop' : undefined,
|
|
174
|
+
wantsResearch ? 'research-and-implement' : undefined,
|
|
175
|
+
lower.match(/dashboard|board|ui|ux/) && !isRuntimeControlPlane ? 'frontend-execution-loop' : undefined,
|
|
176
|
+
], 8);
|
|
177
|
+
const specialists = uniqueList([
|
|
178
|
+
...asStringList(args.specialists),
|
|
179
|
+
isRuntimeControlPlane ? 'Agents Orchestrator' : undefined,
|
|
180
|
+
isRuntimeControlPlane ? 'Backend Architect' : undefined,
|
|
181
|
+
isRuntimeControlPlane ? 'Workflow Optimizer' : undefined,
|
|
182
|
+
wantsPerf ? 'Performance Benchmarker' : undefined,
|
|
183
|
+
wantsMemory && !wantsPerf ? 'Backend Architect' : undefined,
|
|
184
|
+
lower.match(/dashboard|board|ui|ux/) && !isRuntimeControlPlane ? 'Frontend Developer' : undefined,
|
|
185
|
+
lower.match(/test|verify|qa|release|publish/) ? 'Verification Engineer' : undefined,
|
|
186
|
+
], 8);
|
|
187
|
+
const crew = String(args.crew ?? args.selectedCrew ?? (lower.match(/orchestrat|synapse|runtime|mcp|dispatch|queue|queued/)
|
|
188
|
+
? 'Implementation Crew'
|
|
189
|
+
: lower.match(/research|paper|literature/)
|
|
190
|
+
? 'Research Crew'
|
|
191
|
+
: 'Implementation Crew'));
|
|
192
|
+
const risk = lower.match(/fix|broken|bug|doesn.?t|failed|queued|runtime|synapse|orchestrat/) ? 'high' : 'medium';
|
|
193
|
+
const task = {
|
|
194
|
+
goal: prompt,
|
|
195
|
+
intent: lower.match(/fix|bug|broken|doesn.?t|failed/) ? 'bugfix' : 'feature',
|
|
196
|
+
files,
|
|
197
|
+
skillNames: skills,
|
|
198
|
+
workflowSelectors: workflows,
|
|
199
|
+
};
|
|
200
|
+
const workerManifests = uniqueList([
|
|
201
|
+
specialists.length > 0 ? 'worker_coder' : undefined,
|
|
202
|
+
'worker_verifier',
|
|
203
|
+
]).map((workerId, index) => ({
|
|
204
|
+
workerId,
|
|
205
|
+
role: index === 0 ? 'coder' : 'verifier',
|
|
206
|
+
specialistName: index === 0 ? specialists[0] : 'Verification Engineer',
|
|
207
|
+
actions: index === 0 ? ['inspect', 'patch'] : ['verify'],
|
|
208
|
+
verifyCommands: index === 1 ? ['npm run lint', 'targeted tests'] : [],
|
|
209
|
+
}));
|
|
210
|
+
const run = {
|
|
211
|
+
runId,
|
|
212
|
+
requestBrief: {
|
|
213
|
+
id: `brief_${runId}`,
|
|
214
|
+
intent: task.intent,
|
|
215
|
+
risk,
|
|
216
|
+
confidence: 0.68,
|
|
217
|
+
},
|
|
218
|
+
plannerResult: {
|
|
219
|
+
selectedFiles: files,
|
|
220
|
+
selectedSkills: skills,
|
|
221
|
+
selectedWorkflows: workflows,
|
|
222
|
+
selectedSpecialists: specialists.map((name) => ({ name })),
|
|
223
|
+
selectedCrew: { name: crew },
|
|
224
|
+
},
|
|
225
|
+
workerManifests,
|
|
226
|
+
};
|
|
227
|
+
const plan = buildSelectionPlan({ run, task });
|
|
228
|
+
return { plan, crew, specialists, workflows };
|
|
229
|
+
}
|
|
230
|
+
function formatBudgetRoute(plan) {
|
|
231
|
+
const total = Number(plan.budgets?.total ?? 0);
|
|
232
|
+
const code = Number(plan.budgets?.codeBlocks ?? plan.budgets?.codeBlockPolicy?.reservedTokens ?? 0);
|
|
233
|
+
const cap = Number(plan.executionPolicy?.agentFlow?.maxTaskCostUsd ?? plan.executionPolicy?.budgetCapUsd ?? 0);
|
|
234
|
+
return `${total.toLocaleString()} tokens · ${code.toLocaleString()} code-block tokens · $${cap.toFixed(2)} task cap`;
|
|
235
|
+
}
|
|
236
|
+
function formatQueuedOrchestrateReceipt(args, receipt) {
|
|
237
|
+
const preview = inferQueuedOrchestratePreview(args, receipt.runId);
|
|
238
|
+
const plan = preview.plan;
|
|
239
|
+
const stages = Array.isArray(plan.executionPolicy?.agentFlow?.stages)
|
|
240
|
+
? plan.executionPolicy.agentFlow.stages
|
|
241
|
+
: [];
|
|
242
|
+
const selected = plan.selected ?? {};
|
|
243
|
+
const specialists = uniqueList([...(selected.specialists ?? []), ...preview.specialists], 8);
|
|
244
|
+
const workflows = uniqueList([...(selected.workflows ?? []), ...preview.workflows], 8);
|
|
245
|
+
const skills = uniqueList(selected.skills ?? [], 8);
|
|
246
|
+
const receiptJson = JSON.stringify({ queued: true, runId: receipt.runId, etaMs: receipt.etaMs }, null, 2);
|
|
247
|
+
const hiredLine = [
|
|
248
|
+
`crew ${preview.crew}`,
|
|
249
|
+
specialists.length ? `specialists ${specialists.join(', ')}` : '',
|
|
250
|
+
workflows.length ? `workflows ${workflows.join(', ')}` : '',
|
|
251
|
+
skills.length ? `skills ${skills.join(', ')}` : '',
|
|
252
|
+
].filter(Boolean).join(' · ');
|
|
253
|
+
return [
|
|
254
|
+
'Nexus orchestration queued with hiring preflight.',
|
|
255
|
+
`Run: ${receipt.runId}`,
|
|
256
|
+
`ETA: ${receipt.etaMs ? `~${Math.ceil(receipt.etaMs / 1000)}s` : 'background'}`,
|
|
257
|
+
`Hired/selected: ${hiredLine}`,
|
|
258
|
+
`Model route: ${plan.modelRoute?.workerTier ?? 'T1'}${plan.modelRoute?.reviewerTier ? ` + reviewer ${plan.modelRoute.reviewerTier}` : ''}`,
|
|
259
|
+
`Budget route: ${formatBudgetRoute(plan)}`,
|
|
260
|
+
stages.length ? `AgentFlow gates: ${stages.map((stage) => `${stage.stage}:${stage.ownerRole}`).join(' -> ')}` : '',
|
|
261
|
+
'Poll progress with nexus_run_status(runId).',
|
|
262
|
+
'',
|
|
263
|
+
'```json',
|
|
264
|
+
receiptJson,
|
|
265
|
+
'```',
|
|
266
|
+
].filter((line) => line !== '').join('\n');
|
|
267
|
+
}
|
|
112
268
|
/**
|
|
113
269
|
* Route a tool call to the appropriate handler group.
|
|
114
270
|
*
|
|
@@ -232,8 +388,10 @@ export async function dispatchMcpToolCall(hctx, request, args, ctx) {
|
|
|
232
388
|
rawResult = {
|
|
233
389
|
content: [{
|
|
234
390
|
type: 'text',
|
|
235
|
-
text:
|
|
236
|
-
|
|
391
|
+
text: toolName === 'nexus_orchestrate'
|
|
392
|
+
? formatQueuedOrchestrateReceipt(args, gated)
|
|
393
|
+
: JSON.stringify({ queued: true, runId: gated.runId, etaMs: gated.etaMs }, null, 2)
|
|
394
|
+
+ '\n\nCall nexus_run_status(runId) to check progress.',
|
|
237
395
|
}],
|
|
238
396
|
};
|
|
239
397
|
}
|
|
@@ -183,6 +183,8 @@ export declare class OrchestratorEngine {
|
|
|
183
183
|
private searchIndexedRepoCandidates;
|
|
184
184
|
private toFileRef;
|
|
185
185
|
private resolveSelections;
|
|
186
|
+
private inferRuntimeCatalogHints;
|
|
187
|
+
private filterExistingCatalogSelectors;
|
|
186
188
|
private getSkillCatalogItems;
|
|
187
189
|
private getWorkflowCatalogItems;
|
|
188
190
|
private getHookCatalogItems;
|
|
@@ -2382,10 +2382,16 @@ export class OrchestratorEngine {
|
|
|
2382
2382
|
limit: 5,
|
|
2383
2383
|
selector: 'name',
|
|
2384
2384
|
});
|
|
2385
|
-
const
|
|
2385
|
+
const runtimeCatalogHints = this.inferRuntimeCatalogHints(task, intent, {
|
|
2386
|
+
workflows: allWorkflowItems,
|
|
2387
|
+
specialists: allSpecialistItems,
|
|
2388
|
+
crews: allCrewItems,
|
|
2389
|
+
});
|
|
2390
|
+
const workflowSelection = this.resolveCatalogVotes('workflow', task, intent, options.workflowSelectors?.length || runtimeCatalogHints.workflows.length ? allWorkflowItems : workflowItems, {
|
|
2386
2391
|
explicit: options.workflowSelectors,
|
|
2387
2392
|
planner: planner.selectedWorkflows,
|
|
2388
2393
|
knowledge: knowledgeFabric.recommendations.workflows,
|
|
2394
|
+
runtime: runtimeCatalogHints.workflows,
|
|
2389
2395
|
scorerLimit: 4,
|
|
2390
2396
|
limit: 4,
|
|
2391
2397
|
selector: 'name',
|
|
@@ -2423,18 +2429,20 @@ export class OrchestratorEngine {
|
|
|
2423
2429
|
limit: intent.taskType === 'release' || this.sessionState.repeatedFailures > 0 ? 3 : 2,
|
|
2424
2430
|
selector: 'name',
|
|
2425
2431
|
});
|
|
2426
|
-
const specialistSelection = this.resolveCatalogVotes('specialist', task, intent, options.specialistSelectors?.length ? allSpecialistItems : specialistItems, {
|
|
2432
|
+
const specialistSelection = this.resolveCatalogVotes('specialist', task, intent, options.specialistSelectors?.length || runtimeCatalogHints.specialists.length ? allSpecialistItems : specialistItems, {
|
|
2427
2433
|
explicit: options.specialistSelectors,
|
|
2428
2434
|
planner: planner.selectedSpecialists.map((specialist) => specialist.specialistId),
|
|
2429
2435
|
knowledge: knowledgeFabric.recommendations.specialists,
|
|
2436
|
+
runtime: runtimeCatalogHints.specialists,
|
|
2430
2437
|
scorerLimit: 4,
|
|
2431
2438
|
limit: 4,
|
|
2432
2439
|
selector: 'id',
|
|
2433
2440
|
});
|
|
2434
|
-
const crewSelection = this.resolveCatalogVotes('crew', task, intent, options.crewSelectors?.length ? allCrewItems : crewItems, {
|
|
2441
|
+
const crewSelection = this.resolveCatalogVotes('crew', task, intent, options.crewSelectors?.length || runtimeCatalogHints.crews.length ? allCrewItems : crewItems, {
|
|
2435
2442
|
explicit: options.crewSelectors,
|
|
2436
2443
|
planner: planner.selectedCrew ? [planner.selectedCrew.crewId] : [],
|
|
2437
2444
|
knowledge: knowledgeFabric.recommendations.crews,
|
|
2445
|
+
runtime: runtimeCatalogHints.crews,
|
|
2438
2446
|
scorerLimit: 2,
|
|
2439
2447
|
limit: 1,
|
|
2440
2448
|
selector: 'id',
|
|
@@ -2504,6 +2512,47 @@ export class OrchestratorEngine {
|
|
|
2504
2512
|
},
|
|
2505
2513
|
};
|
|
2506
2514
|
}
|
|
2515
|
+
inferRuntimeCatalogHints(task, intent, catalog) {
|
|
2516
|
+
const lower = task.toLowerCase();
|
|
2517
|
+
const isControlPlane = /\b(orchestrat(?:e|or|ion)|synapse|architects?|mcp|dispatch|routing|route|queued?|queue|scheduler|runtime|control plane|agentflow|worker|hiring|specialist|crew|workflow selection|model routing|token budget|memory hook|memory graph|lifecycle)\b/.test(lower);
|
|
2518
|
+
if (!isControlPlane) {
|
|
2519
|
+
return { workflows: [], specialists: [], crews: [] };
|
|
2520
|
+
}
|
|
2521
|
+
const wantsResearch = /\b(research|papers?|literature|source-grounded|cited|deep-research)\b/.test(lower);
|
|
2522
|
+
const wantsMemory = /\b(memory|recall|learning|decay|graph|mcp)\b/.test(lower);
|
|
2523
|
+
const wantsPerf = /\b(fast|faster|milliseconds?|latency|performance|budget|token|optim(?:i|is|iz))\b/.test(lower);
|
|
2524
|
+
const readOnlyResearch = intent.taskType === 'research'
|
|
2525
|
+
&& !/\b(fix|patch|implement|refactor|change|add|wire|ship|deploy|release|mutate|improve)\b/.test(lower);
|
|
2526
|
+
const workflowSelectors = [
|
|
2527
|
+
'orchestration-execution-loop',
|
|
2528
|
+
'backend-execution-loop',
|
|
2529
|
+
'testing-execution-loop',
|
|
2530
|
+
wantsResearch ? 'research-and-implement' : 'typescript-execution-loop',
|
|
2531
|
+
];
|
|
2532
|
+
const specialistSelectors = [
|
|
2533
|
+
'specialist_specialized-agents-orchestrator',
|
|
2534
|
+
'specialist_engineering-engineering-backend-architect',
|
|
2535
|
+
'specialist_testing-testing-workflow-optimizer',
|
|
2536
|
+
wantsPerf
|
|
2537
|
+
? 'specialist_testing-testing-performance-benchmarker'
|
|
2538
|
+
: wantsMemory
|
|
2539
|
+
? 'specialist_integrations-mcp-memory-backend-architect-with-memory'
|
|
2540
|
+
: undefined,
|
|
2541
|
+
];
|
|
2542
|
+
const crewSelectors = [
|
|
2543
|
+
readOnlyResearch ? 'crew_research' : 'crew_implementation',
|
|
2544
|
+
];
|
|
2545
|
+
return {
|
|
2546
|
+
workflows: this.filterExistingCatalogSelectors(catalog.workflows, workflowSelectors, 'name'),
|
|
2547
|
+
specialists: this.filterExistingCatalogSelectors(catalog.specialists, specialistSelectors, 'id'),
|
|
2548
|
+
crews: this.filterExistingCatalogSelectors(catalog.crews, crewSelectors, 'id'),
|
|
2549
|
+
};
|
|
2550
|
+
}
|
|
2551
|
+
filterExistingCatalogSelectors(items, selectors, selector) {
|
|
2552
|
+
const existing = new Set(items.map((item) => selector === 'id' ? item.id : item.name));
|
|
2553
|
+
return dedupeStrings(selectors.filter((value) => Boolean(value)))
|
|
2554
|
+
.filter((value) => existing.has(value));
|
|
2555
|
+
}
|
|
2507
2556
|
getSkillCatalogItems() {
|
|
2508
2557
|
const skills = this.runtime.listSkillsForSelection();
|
|
2509
2558
|
const signature = skills
|
|
@@ -2657,7 +2706,7 @@ export class OrchestratorEngine {
|
|
|
2657
2706
|
applyVote(value, 'knowledge-fabric', 0.76, 'medium', 'Knowledge Fabric recommended this artifact from cross-source evidence.');
|
|
2658
2707
|
});
|
|
2659
2708
|
(input.runtime ?? []).forEach((value) => {
|
|
2660
|
-
applyVote(value, 'runtime-resolver', 0
|
|
2709
|
+
applyVote(value, 'runtime-resolver', 2.0, 'high', 'Runtime resolver matched this artifact against the registered catalog for the active goal.');
|
|
2661
2710
|
});
|
|
2662
2711
|
this.pickCatalogEntries(task, intent, items, input.scorerLimit).forEach((entry) => {
|
|
2663
2712
|
applyVote(input.selector === 'id' ? entry.item.id : entry.item.name, 'scorer', Math.min(0.7, entry.score / 10), entry.score >= 9 ? 'medium' : 'low', `Keyword scorer matched the task with score ${entry.score}.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexus-prime",
|
|
3
|
-
"version": "7.9.
|
|
3
|
+
"version": "7.9.25",
|
|
4
4
|
"description": "Local-first MCP control plane for coding agents with bootstrap-orchestrate execution, memory fabric, token budgeting, and worktree-backed swarms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|