@zhixuan92/multi-model-agent-mcp 2.7.5 → 2.8.1

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 (54) hide show
  1. package/README.md +11 -133
  2. package/dist/cli.js +6 -584
  3. package/package.json +8 -48
  4. package/dist/cli.d.ts +0 -58
  5. package/dist/cli.d.ts.map +0 -1
  6. package/dist/cli.js.map +0 -1
  7. package/dist/headline.d.ts +0 -25
  8. package/dist/headline.d.ts.map +0 -1
  9. package/dist/headline.js +0 -58
  10. package/dist/headline.js.map +0 -1
  11. package/dist/index.d.ts +0 -4
  12. package/dist/index.d.ts.map +0 -1
  13. package/dist/index.js +0 -3
  14. package/dist/index.js.map +0 -1
  15. package/dist/routing/render-provider-routing-matrix.d.ts +0 -7
  16. package/dist/routing/render-provider-routing-matrix.d.ts.map +0 -1
  17. package/dist/routing/render-provider-routing-matrix.js +0 -153
  18. package/dist/routing/render-provider-routing-matrix.js.map +0 -1
  19. package/dist/tools/audit-document.d.ts +0 -23
  20. package/dist/tools/audit-document.d.ts.map +0 -1
  21. package/dist/tools/audit-document.js +0 -123
  22. package/dist/tools/audit-document.js.map +0 -1
  23. package/dist/tools/batch-response.d.ts +0 -14
  24. package/dist/tools/batch-response.d.ts.map +0 -1
  25. package/dist/tools/batch-response.js +0 -42
  26. package/dist/tools/batch-response.js.map +0 -1
  27. package/dist/tools/confirm-clarifications.d.ts +0 -15
  28. package/dist/tools/confirm-clarifications.d.ts.map +0 -1
  29. package/dist/tools/confirm-clarifications.js +0 -95
  30. package/dist/tools/confirm-clarifications.js.map +0 -1
  31. package/dist/tools/debug-task.d.ts +0 -13
  32. package/dist/tools/debug-task.d.ts.map +0 -1
  33. package/dist/tools/debug-task.js +0 -63
  34. package/dist/tools/debug-task.js.map +0 -1
  35. package/dist/tools/execute-plan.d.ts +0 -12
  36. package/dist/tools/execute-plan.d.ts.map +0 -1
  37. package/dist/tools/execute-plan.js +0 -123
  38. package/dist/tools/execute-plan.js.map +0 -1
  39. package/dist/tools/review-code.d.ts +0 -17
  40. package/dist/tools/review-code.d.ts.map +0 -1
  41. package/dist/tools/review-code.js +0 -108
  42. package/dist/tools/review-code.js.map +0 -1
  43. package/dist/tools/shared.d.ts +0 -72
  44. package/dist/tools/shared.d.ts.map +0 -1
  45. package/dist/tools/shared.js +0 -160
  46. package/dist/tools/shared.js.map +0 -1
  47. package/dist/tools/truncation.d.ts +0 -18
  48. package/dist/tools/truncation.d.ts.map +0 -1
  49. package/dist/tools/truncation.js +0 -62
  50. package/dist/tools/truncation.js.map +0 -1
  51. package/dist/tools/verify-work.d.ts +0 -12
  52. package/dist/tools/verify-work.d.ts.map +0 -1
  53. package/dist/tools/verify-work.js +0 -85
  54. package/dist/tools/verify-work.js.map +0 -1
@@ -1,160 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { z } from 'zod';
3
- import { composeHeadline } from '../headline.js';
4
- import { computeTimings, computeBatchProgress, computeAggregateCost } from './batch-response.js';
5
- export const commonToolFields = {
6
- filePaths: z.array(z.string()).optional()
7
- .describe('Files the sub-agent should focus on. Multiple files are processed in parallel.'),
8
- contextBlockIds: z.array(z.string()).optional()
9
- .describe('IDs from register_context_block to prepend to prompt. Use for delta audits, diff-scoped reviews, or shared specs.'),
10
- };
11
- function hasContent(value) {
12
- return value !== undefined && value.trim().length > 0;
13
- }
14
- function hasValidPaths(paths) {
15
- return Array.isArray(paths) && paths.some(p => p.trim().length > 0);
16
- }
17
- export function validateInput(inlineContent, filePaths) {
18
- if (hasContent(inlineContent) || hasValidPaths(filePaths)) {
19
- return { valid: true };
20
- }
21
- return { valid: false, message: 'Provide content or filePaths (or both)' };
22
- }
23
- export function resolveDispatchMode(inlineContent, filePaths) {
24
- if (hasContent(inlineContent))
25
- return 'single';
26
- const validPaths = (filePaths ?? []).filter(p => p.trim().length > 0);
27
- if (validPaths.length >= 2)
28
- return 'fan_out';
29
- return 'single';
30
- }
31
- /**
32
- * Auto-register task output(s) as a context block so callers can reference
33
- * the result in follow-up calls (e.g. round 2 of an audit) without manually
34
- * calling register_context_block. Diagnostic outputs are excluded.
35
- */
36
- export function autoRegisterContextBlock(results, store) {
37
- if (!store)
38
- return undefined;
39
- const usable = results.filter(r => !r.outputIsDiagnostic && r.output.trim().length > 0);
40
- if (usable.length === 0)
41
- return undefined;
42
- const combined = usable.map(r => r.output).join('\n\n---\n\n');
43
- const { id } = store.register(combined);
44
- return id;
45
- }
46
- export function resolveParentModel(config) {
47
- return process.env.PARENT_MODEL_NAME || config.defaults?.parentModel || undefined;
48
- }
49
- export function buildFilePathsPrompt(filePaths) {
50
- if (!filePaths || filePaths.length === 0)
51
- return '';
52
- return `Read and analyze these files:\n${filePaths.map(p => `- ${p}`).join('\n')}`;
53
- }
54
- export function buildPerFilePrompt(filePath, promptTemplate) {
55
- return `${promptTemplate}\n\nRead and analyze this file:\n- ${filePath}`;
56
- }
57
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
- export function buildRunTasksOptions(extra) {
59
- if (!extra)
60
- return {};
61
- const rawToken = extra._meta?.progressToken;
62
- const progressToken = typeof rawToken === 'string' || typeof rawToken === 'number'
63
- ? rawToken
64
- : undefined;
65
- let progressCounter = 0;
66
- if (progressToken === undefined)
67
- return {};
68
- return {
69
- onProgress: (_taskIndex, event) => {
70
- progressCounter += 1;
71
- const headline = `[task ${_taskIndex}] ${event.headline}`;
72
- void extra.sendNotification({
73
- method: 'notifications/progress',
74
- params: {
75
- progressToken,
76
- progress: progressCounter,
77
- message: headline,
78
- },
79
- });
80
- },
81
- };
82
- }
83
- function coerceRequestId(v) {
84
- if (typeof v === 'string' && v.length > 0)
85
- return v;
86
- if (typeof v === 'number')
87
- return String(v);
88
- return undefined;
89
- }
90
- /**
91
- * Wrap an MCP tool handler so every call is recorded as request_start and
92
- * request_complete in the DiagnosticLogger. The start event is emitted before
93
- * the tool handler runs. The completion event is emitted on both success and
94
- * throw; thrown handlers record status:"error" with responseBytes:0.
95
- */
96
- export function withDiagnostics(tool, logger, handler) {
97
- return async (...args) => {
98
- const rawExtra = args[args.length - 1];
99
- const extra = (rawExtra && typeof rawExtra === 'object') ? rawExtra : undefined;
100
- const requestId = coerceRequestId(extra?.requestId) ?? randomUUID();
101
- const startedAt = Date.now();
102
- logger.requestStart({ requestId, tool });
103
- try {
104
- const result = await handler(...args);
105
- let responseBytes = 0;
106
- try {
107
- responseBytes = Buffer.byteLength(JSON.stringify(result));
108
- }
109
- catch {
110
- responseBytes = 0;
111
- }
112
- logger.requestComplete({
113
- tool,
114
- requestId,
115
- durationMs: Date.now() - startedAt,
116
- responseBytes,
117
- status: 'ok',
118
- });
119
- return result;
120
- }
121
- catch (err) {
122
- logger.requestComplete({
123
- tool,
124
- requestId,
125
- durationMs: Date.now() - startedAt,
126
- responseBytes: 0,
127
- status: 'error',
128
- });
129
- throw err;
130
- }
131
- };
132
- }
133
- /**
134
- * Build a unified MCP response envelope for delegate_tasks / clarification flows.
135
- * Strips noisy internal fields (escalationLog, usage, turns, agents, models).
136
- */
137
- export function buildUnifiedResponse(input) {
138
- const { batchId, results, tasks, wallClockMs, parentModel, contextBlockId, clarificationId, clarifications, } = input;
139
- const timings = computeTimings(wallClockMs, results);
140
- const batchProgress = computeBatchProgress(results);
141
- const aggregateCost = computeAggregateCost(results);
142
- const headline = composeHeadline({ timings, batchProgress, aggregateCost, parentModel });
143
- const response = {
144
- headline,
145
- batchId,
146
- ...(contextBlockId && { contextBlockId }),
147
- ...(clarificationId && { clarificationId }),
148
- ...(clarifications && clarifications.length > 0 && { clarifications }),
149
- results: results.map((r) => ({
150
- status: r.status,
151
- output: r.output,
152
- filesWritten: r.filesWritten,
153
- ...(r.status === 'error' && r.error !== undefined && { error: r.error }),
154
- })),
155
- };
156
- return {
157
- content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
158
- };
159
- }
160
- //# sourceMappingURL=shared.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/tools/shared.ts"],"names":[],"mappings":"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"}
@@ -1,18 +0,0 @@
1
- interface TruncatableResult {
2
- status: string;
3
- output: string;
4
- filesWritten: string[];
5
- error?: string;
6
- }
7
- /**
8
- * Truncate result outputs to stay within a combined character budget.
9
- *
10
- * When combined output exceeds the threshold, the budget is allocated equally
11
- * across all tasks. Short tasks are left intact and their surplus is
12
- * redistributed proportionally to oversized ones. Oversized outputs are
13
- * truncated at valid Unicode codepoint boundaries and annotated with a
14
- * get_batch_slice suffix.
15
- */
16
- export declare function truncateResults<T extends TruncatableResult>(results: T[], batchId: string, threshold: number): T[];
17
- export {};
18
- //# sourceMappingURL=truncation.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"truncation.d.ts","sourceRoot":"","sources":["../../src/tools/truncation.ts"],"names":[],"mappings":"AAAA,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,iBAAiB,EACzD,OAAO,EAAE,CAAC,EAAE,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,CAAC,EAAE,CAuDL"}
@@ -1,62 +0,0 @@
1
- function buildSuffix(batchId, taskIndex, originalLength, truncatedLength) {
2
- return `\n\n[Output truncated at ${truncatedLength}/${originalLength} chars. Use get_batch_slice({ batchId: "${batchId}", taskIndex: ${taskIndex} }) to fetch full output.]`;
3
- }
4
- /**
5
- * Truncate result outputs to stay within a combined character budget.
6
- *
7
- * When combined output exceeds the threshold, the budget is allocated equally
8
- * across all tasks. Short tasks are left intact and their surplus is
9
- * redistributed proportionally to oversized ones. Oversized outputs are
10
- * truncated at valid Unicode codepoint boundaries and annotated with a
11
- * get_batch_slice suffix.
12
- */
13
- export function truncateResults(results, batchId, threshold) {
14
- const totalChars = results.reduce((sum, r) => sum + r.output.length, 0);
15
- if (totalChars <= threshold)
16
- return results;
17
- // Compute actual suffix lengths per result (not a fixed estimate)
18
- const suffixLengths = results.map((_, i) => buildSuffix(batchId, i, 999999, 999999).length);
19
- const suffixReserve = suffixLengths.reduce((sum, l) => sum + l, 0);
20
- // Content budget is threshold minus suffix overhead, clamped to [0, threshold]
21
- const contentBudget = Math.max(0, threshold - suffixReserve);
22
- const perTaskShare = Math.floor(contentBudget / results.length);
23
- // First pass: identify short (fits in share) vs oversized
24
- const shortIndices = [];
25
- const oversizedIndices = [];
26
- let surplusBudget = 0;
27
- for (let i = 0; i < results.length; i++) {
28
- if (results[i].output.length <= perTaskShare) {
29
- shortIndices.push(i);
30
- surplusBudget += perTaskShare - results[i].output.length;
31
- }
32
- else {
33
- oversizedIndices.push(i);
34
- }
35
- }
36
- // Redistribute surplus proportionally to oversized outputs
37
- const totalOversized = oversizedIndices.reduce((sum, i) => sum + results[i].output.length, 0);
38
- return results.map((r, i) => {
39
- if (shortIndices.includes(i))
40
- return r; // fits, no truncation
41
- let budget = perTaskShare;
42
- if (totalOversized > 0 && surplusBudget > 0) {
43
- budget += Math.floor(surplusBudget * (r.output.length / totalOversized));
44
- }
45
- // Truncate at valid Unicode boundary (avoid splitting surrogate pairs)
46
- let truncPoint = Math.min(budget, r.output.length);
47
- if (truncPoint > 0 && truncPoint < r.output.length) {
48
- const code = r.output.charCodeAt(truncPoint - 1);
49
- // Don't split after a high surrogate (would orphan it)
50
- if (code >= 0xD800 && code <= 0xDBFF)
51
- truncPoint--;
52
- // Don't split on a low surrogate (would orphan the preceding high)
53
- const codeAt = r.output.charCodeAt(truncPoint);
54
- if (codeAt >= 0xDC00 && codeAt <= 0xDFFF && truncPoint > 0)
55
- truncPoint--;
56
- }
57
- const truncatedOutput = r.output.slice(0, truncPoint) +
58
- buildSuffix(batchId, i, r.output.length, truncPoint);
59
- return { ...r, output: truncatedOutput };
60
- });
61
- }
62
- //# sourceMappingURL=truncation.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"truncation.js","sourceRoot":"","sources":["../../src/tools/truncation.ts"],"names":[],"mappings":"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"}
@@ -1,12 +0,0 @@
1
- import { z } from 'zod';
2
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
- import type { MultiModelConfig, ContextBlockStore, DiagnosticLogger } from '@zhixuan92/multi-model-agent-core';
4
- export declare const verifyWorkSchema: z.ZodObject<{
5
- filePaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
- contextBlockIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
7
- work: z.ZodOptional<z.ZodString>;
8
- checklist: z.ZodArray<z.ZodString>;
9
- }, z.core.$strip>;
10
- export type VerifyWorkParams = z.infer<typeof verifyWorkSchema>;
11
- export declare function registerVerifyWork(server: McpServer, config: MultiModelConfig, logger: DiagnosticLogger, contextBlockStore?: ContextBlockStore): void;
12
- //# sourceMappingURL=verify-work.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify-work.d.ts","sourceRoot":"","sources":["../../src/tools/verify-work.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAY,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAezH,eAAO,MAAM,gBAAgB;;;;;iBAI3B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAiBhE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,EAAE,iBAAiB,QAuE9I"}
@@ -1,85 +0,0 @@
1
- import { z } from 'zod';
2
- import { randomUUID } from 'node:crypto';
3
- import { runTasks } from '@zhixuan92/multi-model-agent-core/run-tasks';
4
- import { commonToolFields, validateInput, resolveDispatchMode, buildUnifiedResponse, buildFilePathsPrompt, buildPerFilePrompt, buildRunTasksOptions, resolveParentModel, autoRegisterContextBlock, withDiagnostics, } from './shared.js';
5
- export const verifyWorkSchema = z.object({
6
- work: z.string().optional().describe('Inline work product to verify'),
7
- checklist: z.array(z.string()).min(1).describe('Verification checklist items (at least 1)'),
8
- ...commonToolFields,
9
- });
10
- function buildVerifyPrompt(work, filePaths, checklist) {
11
- const parts = ['Verify this work:'];
12
- if (work)
13
- parts.push(work);
14
- const fileSection = buildFilePathsPrompt(filePaths);
15
- if (fileSection)
16
- parts.push(fileSection);
17
- const checklistText = checklist.map((item, i) => `${i + 1}. ${item}`).join('\n');
18
- parts.push(`Checklist:\n${checklistText}`);
19
- parts.push('For each checklist item, indicate pass/fail and provide evidence.');
20
- return parts.join('\n\n');
21
- }
22
- export function registerVerifyWork(server, config, logger, contextBlockStore) {
23
- server.tool('verify_work', 'Verify work against a checklist with pass/fail evidence. Accepts inline description or file paths (multiple files verified in parallel). Preset: standard agent, spec review only.', verifyWorkSchema.shape, withDiagnostics('verify_work', logger, (async (params, extra) => {
24
- const runOptions = buildRunTasksOptions(extra);
25
- const validation = validateInput(params.work, params.filePaths);
26
- if (!validation.valid) {
27
- return { content: [{ type: 'text', text: `Error: ${validation.message}` }], isError: true };
28
- }
29
- const baseTaskSpec = {
30
- agentType: 'standard',
31
- reviewPolicy: 'spec_only',
32
- briefQualityPolicy: 'off',
33
- done: `Every checklist item (${params.checklist.length} total) has a pass/fail verdict with supporting evidence from the code.`,
34
- tools: config.defaults?.tools ?? 'full',
35
- timeoutMs: config.defaults?.timeoutMs ?? 1_800_000,
36
- maxCostUSD: config.defaults?.maxCostUSD ?? 10,
37
- sandboxPolicy: config.defaults?.sandboxPolicy ?? 'cwd-only',
38
- cwd: process.cwd(),
39
- contextBlockIds: params.contextBlockIds,
40
- parentModel: resolveParentModel(config),
41
- };
42
- const runtime = contextBlockStore ? { contextBlockStore } : undefined;
43
- const parentModel = baseTaskSpec.parentModel;
44
- try {
45
- const mode = resolveDispatchMode(params.work, params.filePaths);
46
- if (mode === 'fan_out') {
47
- const validPaths = params.filePaths.filter(p => p.trim().length > 0);
48
- const promptTemplate = buildVerifyPrompt(undefined, undefined, params.checklist);
49
- const tasks = validPaths.map(fp => ({
50
- ...baseTaskSpec,
51
- prompt: buildPerFilePrompt(fp, promptTemplate),
52
- }));
53
- const startMs = Date.now();
54
- const results = await runTasks(tasks, config, { ...runOptions, runtime });
55
- const ctxId = autoRegisterContextBlock(results, contextBlockStore);
56
- return buildUnifiedResponse({
57
- batchId: randomUUID(),
58
- results,
59
- tasks,
60
- wallClockMs: Date.now() - startMs,
61
- parentModel,
62
- contextBlockId: ctxId,
63
- });
64
- }
65
- const prompt = buildVerifyPrompt(params.work, params.filePaths, params.checklist);
66
- const results = await runTasks([{ ...baseTaskSpec, prompt }], config, { ...runOptions, runtime });
67
- const ctxId = autoRegisterContextBlock(results, contextBlockStore);
68
- return buildUnifiedResponse({
69
- batchId: randomUUID(),
70
- results,
71
- tasks: [{ ...baseTaskSpec, prompt }],
72
- wallClockMs: 0,
73
- parentModel,
74
- contextBlockId: ctxId,
75
- });
76
- }
77
- catch (err) {
78
- return {
79
- content: [{ type: 'text', text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
80
- isError: true,
81
- };
82
- }
83
- })));
84
- }
85
- //# sourceMappingURL=verify-work.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify-work.js","sourceRoot":"","sources":["../../src/tools/verify-work.ts"],"names":[],"mappings":"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"}