@evomap/evolver-mcp 2.0.19 → 2.0.23

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/dist/primer.js CHANGED
@@ -14,13 +14,16 @@ export function buildEvolverPrimer(opts = {}) {
14
14
  ? 'dry-run validate it (evolver_asset_validate), then publish (evolver_asset_publish).'
15
15
  : 'then publish it (evolver_asset_publish).';
16
16
  const lines = [
17
- 'Evolver gives this agent reusable memory of past solutions (genes and capsules). Use it quietly when prior experience is likely to help:',
17
+ 'Evolver gives this agent reusable memory. A Recipe is ordered Gene/Capsule DNA. Default discovery/execution is Recipe search then express; Gene/Capsule search is fallback when no Recipe matches. Expressing a Recipe is what actually reuses those steps on the hub. Use it quietly when prior experience is likely to help:',
18
18
  '',
19
- '1. PRIME OR SEARCH WHEN USEFUL. For clear error text, repeated workflows, or substantial tasks, look for prior experience:',
20
- ' - call evolver_recall when approved local genes are likely to help;',
21
- ` - call evolver_asset_search with concise key signals or error text to search ${searchWhere};`,
22
- ' - if a candidate fits, call evolver_asset_fetch and reuse only the parts that apply.',
19
+ '1. SEARCH AND EXPRESS RECIPES FIRST. For clear error text, repeated workflows, or substantial tasks:',
23
20
  ];
21
+ if (proxy) {
22
+ lines.push(' - call evolver_recipe_search with the task or error text;', ' - if a recipe fits, call evolver_recipe_express — the hub expands Gene then Capsule steps; do not parse recipe JSON locally;', ' - if no recipe hits, fall back to evolver_asset_search / evolver_asset_fetch on genes and capsules;', ' - call evolver_recall only for approved local genes that are likely to help.');
23
+ }
24
+ else {
25
+ lines.push(' - call evolver_recall when approved local genes are likely to help;', ` - call evolver_asset_search with concise key signals or error text to search ${searchWhere} (Recipe search needs a hub/proxy);`, ' - if a candidate fits, call evolver_asset_fetch and reuse only the parts that apply.');
26
+ }
24
27
  if (proxy) {
25
28
  lines.push('2. REPORT REAL REUSE. After a fetched asset materially affects the solution, call evolver_asset_reuse_result', ' (success / failed / mismatched / stale / unsafe) so the memory learns what is worth keeping.', '3. CAPTURE VERIFIED LEARNING. When you solve something non-trivial and have VERIFIED it, distill it for the next agent:');
26
29
  }
@@ -26,6 +26,18 @@ export interface ProxySearchArgs {
26
26
  limit?: number;
27
27
  expectedHubMode?: 'public' | 'private';
28
28
  }
29
+ export interface ProxyRecipeSearchArgs {
30
+ q?: string;
31
+ limit?: number;
32
+ cursor?: string;
33
+ sort?: string;
34
+ expectedHubMode?: 'public' | 'private';
35
+ }
36
+ export interface ProxyRecipeExpressArgs {
37
+ recipeId: string;
38
+ inputPayload?: Record<string, unknown>;
39
+ expectedHubMode?: 'public' | 'private';
40
+ }
29
41
  export interface ProxyFetchArgs {
30
42
  assetId?: string;
31
43
  assetIds?: string[];
@@ -34,6 +46,7 @@ export interface ProxyFetchArgs {
34
46
  export interface ProxyAssetBundle {
35
47
  assets: unknown[];
36
48
  expected_hub_mode?: 'public' | 'private';
49
+ compose_recipe?: boolean;
37
50
  }
38
51
  export interface ProxyReuseResultArgs {
39
52
  assetId: string;
@@ -71,6 +84,8 @@ export declare class EvolverProxyClient {
71
84
  signal?: AbortSignal;
72
85
  }): Promise<unknown>;
73
86
  search(args: ProxySearchArgs): Promise<unknown>;
87
+ searchRecipes(args: ProxyRecipeSearchArgs): Promise<unknown>;
88
+ expressRecipe(args: ProxyRecipeExpressArgs): Promise<unknown>;
74
89
  fetchAsset(args: ProxyFetchArgs): Promise<unknown>;
75
90
  searchAgents(args: ProxyAgentSearchArgs): Promise<unknown>;
76
91
  getAgentProfile(agentId: string, timeoutMs?: number): Promise<unknown>;
@@ -30,6 +30,24 @@ export class EvolverProxyClient {
30
30
  ...(expectedHubMode ? { expected_hub_mode: expectedHubMode } : {}),
31
31
  });
32
32
  }
33
+ searchRecipes(args) {
34
+ const expectedHubMode = args.expectedHubMode ?? this.expectedHubMode;
35
+ return this.call('POST', '/recipe/search', {
36
+ ...(args.q ? { q: args.q } : {}),
37
+ ...(args.limit !== undefined ? { limit: args.limit } : {}),
38
+ ...(args.cursor ? { cursor: args.cursor } : {}),
39
+ ...(args.sort ? { sort: args.sort } : {}),
40
+ ...(expectedHubMode ? { expected_hub_mode: expectedHubMode } : {}),
41
+ });
42
+ }
43
+ expressRecipe(args) {
44
+ const expectedHubMode = args.expectedHubMode ?? this.expectedHubMode;
45
+ return this.call('POST', '/recipe/express', {
46
+ recipe_id: args.recipeId,
47
+ ...(args.inputPayload ? { input_payload: args.inputPayload } : {}),
48
+ ...(expectedHubMode ? { expected_hub_mode: expectedHubMode } : {}),
49
+ });
50
+ }
33
51
  fetchAsset(args) {
34
52
  const expectedHubMode = args.expectedHubMode ?? this.expectedHubMode;
35
53
  return this.call('POST', '/asset/fetch', {
package/dist/tools.js CHANGED
@@ -155,7 +155,7 @@ export function buildEvolverTools(deps) {
155
155
  // Self-onboarding (#mcp-onboarding): any MCP agent can learn the quiet reuse loop when it needs guidance.
156
156
  // Mirrors the initialize.instructions primer; always present, but no longer asks the agent to narrate routine work.
157
157
  name: 'evolver_guide',
158
- description: '按需说明 evolver 的静默复用机制(search→reuse→capture 循环)与各工具何时调用;不要向用户叙述例行预检、状态或空搜索。',
158
+ description: '按需说明 evolver 的静默复用机制(Recipe search→express, Gene/Capsule 为 fallback;search→reuse→capture 循环)与各工具何时调用;不要向用户叙述例行预检、状态或空搜索。',
159
159
  inputSchema: { type: 'object', properties: {} },
160
160
  handler: async () => ({ guide: buildEvolverPrimer({ proxy: !!deps.proxy }) }),
161
161
  },
@@ -165,7 +165,7 @@ export function buildEvolverTools(deps) {
165
165
  // later observe, from this agent's transcript, which primed genes were used. NOT a hub search (that is
166
166
  // evolver_asset_search): this is the curated, already-approved local memory, ready to reuse quietly.
167
167
  name: 'evolver_recall',
168
- description: '当本机已审核通过的可复用经验 gene 可能有帮助时调用;返回信任+审核双闸后的本地 gene,并记录一条 value.inject。若传入 sessionId(= 本会话 transcript 文件名去掉 .jsonl 后缀),后续 auto-recall 能从该 transcript 观测哪些注入 gene 真正被用,为经 MCP 接入的 AI 闭合自学习环;不传则仅记录归因、无法关联到会话。命中后静默复用,并在结果明确后用 evolver_asset_reuse_result 回报。',
168
+ description: 'Fallback:当本机已审核通过的可复用经验 gene 可能有帮助时调用(不是 Hub Recipe 搜索)。联网默认先 evolver_recipe_search / evolver_recipe_express。返回信任+审核双闸后的本地 gene,并记录一条 value.inject。若传入 sessionId(= 本会话 transcript 文件名去掉 .jsonl 后缀),后续 auto-recall 能从该 transcript 观测哪些注入 gene 真正被用,为经 MCP 接入的 AI 闭合自学习环;不传则仅记录归因、无法关联到会话。命中后静默复用,并在结果明确后用 evolver_asset_reuse_result 回报。',
169
169
  inputSchema: { type: 'object', properties: { limit: { type: 'number' }, sessionId: { type: 'string' } } },
170
170
  handler: async (a) => {
171
171
  const limit = optionalNonNegativeNumberArg(a, 'limit', 'evolver_recall limit must be a non-negative number') ?? 5;
@@ -198,6 +198,59 @@ export function buildEvolverTools(deps) {
198
198
  },
199
199
  },
200
200
  ...(deps.proxy ? [{
201
+ name: 'evolver_recipe_search',
202
+ description: '默认第一步:通过本机 evolver-proxy 搜索 Hub 已发布 Recipe(有序 Gene/Capsule DNA)。命中后调用 evolver_recipe_express。无匹配时再 fallback 到 evolver_asset_search。',
203
+ inputSchema: {
204
+ type: 'object',
205
+ properties: {
206
+ q: { type: 'string' },
207
+ query: { type: 'string' },
208
+ text: { type: 'string' },
209
+ limit: { type: 'number' },
210
+ cursor: { type: 'string' },
211
+ sort: { type: 'string' },
212
+ },
213
+ },
214
+ handler: async (a) => {
215
+ const q = [a['q'], a['query'], a['text']].find((value) => typeof value === 'string' && value.trim().length > 0);
216
+ const receipt = record(await deps.proxy.searchRecipes({
217
+ ...(q ? { q } : {}),
218
+ ...(typeof a['limit'] === 'number' ? { limit: a['limit'] } : {}),
219
+ ...(typeof a['cursor'] === 'string' ? { cursor: a['cursor'] } : {}),
220
+ ...(typeof a['sort'] === 'string' ? { sort: a['sort'] } : {}),
221
+ }));
222
+ if (Array.isArray(receipt['recipes']))
223
+ return receipt['recipes'];
224
+ if (Array.isArray(receipt['results']))
225
+ return receipt['results'];
226
+ if (Array.isArray(receipt['items']))
227
+ return receipt['items'];
228
+ return receipt;
229
+ },
230
+ }, {
231
+ name: 'evolver_recipe_express',
232
+ description: '表达/执行一条 Recipe:只转发 Hub POST /a2a/recipe/{id}/express。Hub 按步骤展开 Gene 再 Capsule,从而产生全网 gene/capsule 调用。不要在本地解析 recipe JSON。',
233
+ inputSchema: {
234
+ type: 'object',
235
+ required: ['recipeId'],
236
+ properties: {
237
+ recipeId: { type: 'string' },
238
+ inputPayload: { type: 'object' },
239
+ },
240
+ },
241
+ handler: async (a) => {
242
+ const recipeId = str(a['recipeId']).trim();
243
+ if (!recipeId)
244
+ throw new Error('evolver_recipe_express requires recipeId');
245
+ const inputPayload = a['inputPayload'];
246
+ return deps.proxy.expressRecipe({
247
+ recipeId,
248
+ ...(inputPayload && typeof inputPayload === 'object' && !Array.isArray(inputPayload)
249
+ ? { inputPayload: inputPayload }
250
+ : {}),
251
+ });
252
+ },
253
+ }, {
201
254
  name: 'evolver_proxy_status',
202
255
  description: '检查本机 evolver-proxy 与 PHub 的连接状态. 需要 EVOLVER_PROXY_URL/EVOLVER_IPC_TOKEN.',
203
256
  inputSchema: { type: 'object', properties: {} },
@@ -206,8 +259,8 @@ export function buildEvolverTools(deps) {
206
259
  {
207
260
  name: 'evolver_asset_search',
208
261
  description: deps.proxy
209
- ? '通过本机 evolver-proxy 搜索 PHub 经验资产(Gene/Capsule/EvolutionEvent); AntiGene 是本地负经验资产, 会直接查本地库供人工 review.'
210
- : '搜索本地经验资产库(Gene/Capsule/EvolutionEvent/AntiGene). 支持 kind/信号/类目/gene 反查/文本.',
262
+ ? 'Fallback:当 evolver_recipe_search 无匹配 Recipe 时,通过本机 evolver-proxy 直搜 PHub 经验资产(Gene/Capsule/EvolutionEvent)AntiGene 是本地负经验资产, 会直接查本地库供人工 review. 真正复用应优先 evolver_recipe_express。'
263
+ : '搜索本地经验资产库(Gene/Capsule/EvolutionEvent/AntiGene). 支持 kind/信号/类目/gene 反查/文本. 联网 Recipe 搜索需要 evolver-proxy。',
211
264
  inputSchema: { type: 'object', properties: { kind: { type: 'string', enum: searchableKinds }, signalsAny: { type: 'array', items: { type: 'string' } }, category: { type: 'string' }, gene: { type: 'string' }, text: { type: 'string' }, limit: { type: 'number' } } },
212
265
  handler: async (a) => {
213
266
  if (deps.proxy && a['kind'] === 'AntiGene') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evomap/evolver-mcp",
3
- "version": "2.0.19",
3
+ "version": "2.0.23",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -23,7 +23,7 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@evomap/evolver-core": "2.0.19",
26
+ "@evomap/evolver-core": "2.0.23",
27
27
  "smol-toml": "^1.6.1"
28
28
  },
29
29
  "repository": {