@wowok/agent-mcp 2.5.4 → 2.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.
Files changed (76) hide show
  1. package/README.md +33 -26
  2. package/dist/config/runtime.js +3 -6
  3. package/dist/harness/checkpoint.js +2 -2
  4. package/dist/knowledge/flywheel-loop.js +2 -5
  5. package/dist/knowledge/overrides-loader.js +2 -4
  6. package/dist/knowledge/progress-ledger.js +3 -0
  7. package/dist/knowledge/progress-translation.js +5 -1
  8. package/dist/knowledge/reward-confirm.d.ts +3 -0
  9. package/dist/knowledge/reward-confirm.js +30 -0
  10. package/dist/knowledge/reward-puzzle.d.ts +1 -0
  11. package/dist/knowledge/reward-puzzle.js +12 -0
  12. package/dist/knowledge/reward-risk.d.ts +4 -1
  13. package/dist/knowledge/reward-risk.js +85 -3
  14. package/dist/knowledge/tools-reference.js +5 -4
  15. package/dist/loop-engineering/improve.js +2 -4
  16. package/dist/project/deployment-bridge.d.ts +5 -0
  17. package/dist/project/deployment-bridge.js +96 -0
  18. package/dist/project/evaluation.d.ts +53 -0
  19. package/dist/project/evaluation.js +860 -0
  20. package/dist/project/graph-builder.d.ts +43 -0
  21. package/dist/project/graph-builder.js +585 -0
  22. package/dist/project/handlers.d.ts +154 -0
  23. package/dist/project/handlers.js +567 -0
  24. package/dist/project/index.d.ts +1 -0
  25. package/dist/project/index.js +26 -7
  26. package/dist/project/project-store.js +2 -5
  27. package/dist/project/query.d.ts +1 -0
  28. package/dist/project/query.js +2 -0
  29. package/dist/project/semantic-assembler.d.ts +93 -0
  30. package/dist/project/semantic-assembler.js +345 -0
  31. package/dist/schema/call/base.js +1 -1
  32. package/dist/schema/config/index.d.ts +12 -12
  33. package/dist/schema/local/index.d.ts +108 -108
  34. package/dist/schema/local/index.js +21 -18
  35. package/dist/schema/messenger/index.d.ts +16 -16
  36. package/dist/schema/messenger/index.js +2 -2
  37. package/dist/schema/operations.d.ts +0 -6
  38. package/dist/schema/project/index.d.ts +1840 -3903
  39. package/dist/schema/project/index.js +403 -955
  40. package/dist/schema/query/index.d.ts +10 -5
  41. package/dist/schema/trust/index.d.ts +6 -6
  42. package/dist/schemas/account_operation.output.json +7 -21
  43. package/dist/schemas/account_operation.schema.json +9 -23
  44. package/dist/schemas/bridge_operation.schema.json +1 -1
  45. package/dist/schemas/guard2file.schema.json +1 -1
  46. package/dist/schemas/index.json +2 -2
  47. package/dist/schemas/machineNode2file.schema.json +1 -1
  48. package/dist/schemas/messenger_operation.schema.json +6 -6
  49. package/dist/schemas/onchain_operations.schema.json +5 -5
  50. package/dist/schemas/onchain_operations_allocation.schema.json +1 -1
  51. package/dist/schemas/onchain_operations_arbitration.schema.json +1 -1
  52. package/dist/schemas/onchain_operations_contact.schema.json +1 -1
  53. package/dist/schemas/onchain_operations_demand.schema.json +1 -1
  54. package/dist/schemas/onchain_operations_gen_passport.schema.json +2 -2
  55. package/dist/schemas/onchain_operations_gen_proof.schema.json +2 -2
  56. package/dist/schemas/onchain_operations_guard.schema.json +1 -1
  57. package/dist/schemas/onchain_operations_machine.schema.json +1 -1
  58. package/dist/schemas/onchain_operations_order.schema.json +1 -1
  59. package/dist/schemas/onchain_operations_payment.schema.json +1 -1
  60. package/dist/schemas/onchain_operations_permission.schema.json +1 -1
  61. package/dist/schemas/onchain_operations_personal.schema.json +1 -1
  62. package/dist/schemas/onchain_operations_progress.schema.json +1 -1
  63. package/dist/schemas/onchain_operations_proof.schema.json +1 -1
  64. package/dist/schemas/onchain_operations_repository.schema.json +1 -1
  65. package/dist/schemas/onchain_operations_reward.schema.json +1 -1
  66. package/dist/schemas/onchain_operations_service.schema.json +1 -1
  67. package/dist/schemas/onchain_operations_treasury.schema.json +1 -1
  68. package/dist/schemas/project_operation.output.json +1178 -2494
  69. package/dist/schemas/project_operation.schema.json +216 -530
  70. package/dist/schemas/query_toolkit.output.json +7 -6
  71. package/dist/schemas/query_toolkit.schema.json +0 -4
  72. package/dist/telemetry/storage.js +2 -2
  73. package/dist/tools/handlers/onchain.js +110 -19
  74. package/dist/tools/handlers/project.js +56 -1046
  75. package/dist/tools/index.js +85 -56
  76. package/package.json +2 -2
@@ -0,0 +1,567 @@
1
+ import { LocalProject, LocalMark, query_objects, } from "@wowok/wowok";
2
+ import { GraphBuilder } from "./graph-builder.js";
3
+ import { SemanticAssembler } from "./semantic-assembler.js";
4
+ import { runEvaluation, compareProjects, } from "./evaluation.js";
5
+ const localProject = LocalProject.Instance();
6
+ function requireField(value, name) {
7
+ if (value === undefined || value === null) {
8
+ throw new Error(`'${name}' is required for this action`);
9
+ }
10
+ return value;
11
+ }
12
+ async function resolveProjectId(v) {
13
+ if (v.project_id)
14
+ return v.project_id;
15
+ if (v.project) {
16
+ const p = await localProject.getProjectByPrefix(v.project);
17
+ if (!p)
18
+ throw new Error(`Project not found by prefix: ${v.project}`);
19
+ return p.id;
20
+ }
21
+ throw new Error("Either 'project_id' or 'project' (prefix) is required for this action");
22
+ }
23
+ async function resolveObjectAddress(v) {
24
+ if (v.object_address)
25
+ return v.object_address;
26
+ if (v.object_name_add) {
27
+ const mark = await LocalMark.Instance().get(v.object_name_add);
28
+ if (mark?.address)
29
+ return mark.address;
30
+ throw new Error(`LocalMark name not found: ${v.object_name_add}`);
31
+ }
32
+ throw new Error("Either 'object_address' or 'object_name_add' is required for add_object");
33
+ }
34
+ export async function handleListProjects(v) {
35
+ const filter = {};
36
+ if (v.filter_status)
37
+ filter.status = v.filter_status;
38
+ if (v.filter_perspective)
39
+ filter.perspective = v.filter_perspective;
40
+ if (v.filter_network)
41
+ filter.network = v.filter_network;
42
+ const projects = await localProject.listProjects(Object.keys(filter).length > 0 ? filter : undefined);
43
+ const items = await Promise.all(projects.map(async (p) => {
44
+ const [objs, evals] = await Promise.all([
45
+ localProject.listObjects(p.id),
46
+ localProject.listEvaluations(p.id),
47
+ ]);
48
+ const types = new Set();
49
+ for (const o of objs) {
50
+ if (o.objectType)
51
+ types.add(o.objectType);
52
+ }
53
+ if (p.status === "draft" && objs.length > 0) {
54
+ const updated = await localProject.updateProject(p.id, { status: "active" });
55
+ if (updated) {
56
+ return {
57
+ ...updated,
58
+ objectCount: objs.length,
59
+ evaluationCount: evals.length,
60
+ objectTypes: Array.from(types),
61
+ };
62
+ }
63
+ }
64
+ return {
65
+ ...p,
66
+ objectCount: objs.length,
67
+ evaluationCount: evals.length,
68
+ objectTypes: Array.from(types),
69
+ };
70
+ }));
71
+ return {
72
+ action: "list_projects",
73
+ items,
74
+ total: items.length,
75
+ };
76
+ }
77
+ export async function handleCreateProject(v) {
78
+ const prefix = requireField(v.project, "project (prefix)");
79
+ const name = requireField(v.project_name, "project_name");
80
+ const existing = await localProject.getProjectByPrefix(prefix);
81
+ if (existing) {
82
+ throw new Error(`Project prefix '${prefix}' already exists (project: '${existing.name}', id: '${existing.id}'). ` +
83
+ `Use a different prefix or update the existing project.`);
84
+ }
85
+ const create = {
86
+ prefix,
87
+ name,
88
+ description: v.project_description,
89
+ industry: v.project_industry,
90
+ perspective: v.project_perspective ?? "producer",
91
+ labels: v.project_labels,
92
+ serviceAddress: v.service_address,
93
+ network: v.project_network ?? "testnet",
94
+ };
95
+ const project = await localProject.createProject(create);
96
+ return { action: "create_project", project };
97
+ }
98
+ export async function handleCreateProjectFromOnchain(v) {
99
+ const serviceAddress = requireField(v.service_address, "service_address");
100
+ const network = (v.project_network ?? "testnet");
101
+ let prefix = v.project ?? `svc_${serviceAddress.slice(2, 8)}`;
102
+ const name = v.project_name ?? `Consumer Project ${serviceAddress.slice(2, 8)}`;
103
+ const existing = await localProject.getProjectByPrefix(prefix);
104
+ if (existing) {
105
+ if (v.project) {
106
+ throw new Error(`Project prefix '${prefix}' already exists (project: '${existing.name}', id: '${existing.id}'). ` +
107
+ `Use a different prefix.`);
108
+ }
109
+ let suffix = 2;
110
+ while (await localProject.getProjectByPrefix(`${prefix}_${suffix}`)) {
111
+ suffix++;
112
+ }
113
+ prefix = `${prefix}_${suffix}`;
114
+ }
115
+ const project = await localProject.createProject({
116
+ prefix,
117
+ name,
118
+ description: v.project_description ?? `Auto-discovered from Service ${serviceAddress}`,
119
+ industry: v.project_industry,
120
+ perspective: "consumer",
121
+ labels: v.project_labels,
122
+ serviceAddress,
123
+ network: network,
124
+ });
125
+ const builder = new GraphBuilder({
126
+ maxDepth: v.max_depth ?? 3,
127
+ enableRegistrar: v.enable_registrar ?? true,
128
+ enablePotential: v.enable_potential ?? false,
129
+ projectId: project.id,
130
+ network: network,
131
+ });
132
+ const graphResult = await builder.buildRelationshipGraph(serviceAddress);
133
+ const objects = [];
134
+ for (const node of graphResult.graph.nodes) {
135
+ const isCore = node.address === serviceAddress;
136
+ const obj = await localProject.addObject(project.id, {
137
+ objectAddress: node.address,
138
+ objectType: node.objectType ?? undefined,
139
+ objectName: node.objectName ?? undefined,
140
+ role: (isCore ? "core" : "dependency"),
141
+ });
142
+ objects.push(obj);
143
+ }
144
+ const updatedProject = await localProject.updateProject(project.id, { status: "active" });
145
+ return {
146
+ action: "create_project_from_onchain",
147
+ project: updatedProject ?? project,
148
+ objects,
149
+ graphEdgeCount: graphResult.graph.edges.length,
150
+ };
151
+ }
152
+ export async function handleUpdateProject(v) {
153
+ const id = await resolveProjectId(v);
154
+ const update = {
155
+ name: v.project_name,
156
+ description: v.project_description,
157
+ industry: v.project_industry,
158
+ perspective: v.project_perspective,
159
+ status: v.project_status,
160
+ labels: v.project_labels,
161
+ serviceAddress: v.service_address,
162
+ };
163
+ const project = await localProject.updateProject(id, update);
164
+ return { action: "update_project", project };
165
+ }
166
+ export async function handleGetProjectDetail(v) {
167
+ const id = await resolveProjectId(v);
168
+ const project = await localProject.getProject(id);
169
+ if (!project)
170
+ throw new Error(`Project not found: ${id}`);
171
+ const objects = await localProject.listObjects(id);
172
+ const edges = await localProject.getGraph(id);
173
+ const evaluations = await localProject.listEvaluations(id);
174
+ const versions = await localProject.listVersions(id);
175
+ let effectiveProject = project;
176
+ if (project.status === "draft" && objects.length > 0) {
177
+ const updated = await localProject.updateProject(id, { status: "active" });
178
+ if (updated)
179
+ effectiveProject = updated;
180
+ }
181
+ const needsNameFix = objects.some(o => !o.objectName);
182
+ const needsRoleFix = objects.some(o => o.role === "reference");
183
+ if (needsNameFix || needsRoleFix) {
184
+ const allMarks = await LocalMark.Instance().list(null);
185
+ const addressToName = new Map();
186
+ for (const m of allMarks) {
187
+ if (m.name && m.address) {
188
+ addressToName.set(m.address.toLowerCase(), m.name);
189
+ }
190
+ }
191
+ for (const obj of objects) {
192
+ const updates = {};
193
+ if (!obj.objectName) {
194
+ const name = addressToName.get(obj.objectAddress.toLowerCase());
195
+ if (name) {
196
+ updates.objectName = name;
197
+ obj.objectName = name;
198
+ }
199
+ }
200
+ if (obj.role === "reference" && obj.objectType) {
201
+ const t = obj.objectType;
202
+ if (t.includes("service::Service")) {
203
+ updates.role = "core";
204
+ obj.role = "core";
205
+ }
206
+ else if (t.includes("permission::Permission") ||
207
+ t.includes("machine::Machine") ||
208
+ t.includes("guard::Guard") ||
209
+ t.includes("reward::Reward") ||
210
+ t.includes("treasury::Treasury") ||
211
+ t.includes("allocation::Allocation") ||
212
+ t.includes("progress::Progress") ||
213
+ t.includes("arbitration::Arbitration") ||
214
+ t.includes("demand::Demand") ||
215
+ t.includes("order::Order") ||
216
+ t.includes("repository::Repository")) {
217
+ updates.role = "dependency";
218
+ obj.role = "dependency";
219
+ }
220
+ }
221
+ if (effectiveProject.serviceAddress &&
222
+ obj.objectAddress === effectiveProject.serviceAddress &&
223
+ obj.role !== "core") {
224
+ updates.role = "core";
225
+ obj.role = "core";
226
+ }
227
+ if (Object.keys(updates).length > 0) {
228
+ await localProject.updateObject(obj.id, updates).catch(() => { });
229
+ }
230
+ }
231
+ }
232
+ return {
233
+ action: "get_project_detail",
234
+ project: effectiveProject,
235
+ objects,
236
+ graphEdgeCount: edges.length,
237
+ evaluations: evaluations.map(e => ({
238
+ id: e.id,
239
+ evalType: e.evalType,
240
+ score: e.score,
241
+ summary: e.summary,
242
+ details: e.details,
243
+ evaluatedAt: e.evaluatedAt,
244
+ })),
245
+ versions: versions.map(v => ({
246
+ version: v.version,
247
+ description: v.description,
248
+ createdAt: v.createdAt,
249
+ })),
250
+ };
251
+ }
252
+ export async function handleAddObject(v) {
253
+ const projectId = await resolveProjectId(v);
254
+ const objectAddress = await resolveObjectAddress(v);
255
+ let objectName = v.object_name_add;
256
+ let role = v.object_role;
257
+ if (!objectName) {
258
+ const marks = await LocalMark.Instance().list({ address: objectAddress });
259
+ if (marks.length > 0 && marks[0].name) {
260
+ objectName = marks[0].name;
261
+ }
262
+ }
263
+ if (!role) {
264
+ const objType = v.object_type_add ?? "";
265
+ if (objType.includes("service::Service")) {
266
+ role = "core";
267
+ }
268
+ else if (objType.includes("::") && (objType.includes("permission::") ||
269
+ objType.includes("machine::") ||
270
+ objType.includes("guard::") ||
271
+ objType.includes("reward::") ||
272
+ objType.includes("treasury::") ||
273
+ objType.includes("allocation::") ||
274
+ objType.includes("progress::") ||
275
+ objType.includes("arbitration::") ||
276
+ objType.includes("demand::") ||
277
+ objType.includes("order::") ||
278
+ objType.includes("repository::"))) {
279
+ role = "dependency";
280
+ }
281
+ else {
282
+ role = "reference";
283
+ }
284
+ }
285
+ const obj = await localProject.addObject(projectId, {
286
+ objectAddress,
287
+ objectType: v.object_type_add,
288
+ objectName,
289
+ role,
290
+ tags: v.object_tags_add,
291
+ });
292
+ const project = await localProject.getProject(projectId);
293
+ if (project && project.status === "draft") {
294
+ await localProject.updateProject(projectId, { status: "active" });
295
+ }
296
+ return { action: "add_object", object: obj };
297
+ }
298
+ export async function handleRemoveObject(v) {
299
+ const objectId = requireField(v.object_id_remove, "object_id_remove");
300
+ await localProject.removeObject(objectId);
301
+ return { action: "remove_object", removed: true };
302
+ }
303
+ export async function handleUpdateObject(v) {
304
+ const objectId = requireField(v.object_id_update, "object_id_update");
305
+ const updates = {};
306
+ if (v.object_name_update !== undefined)
307
+ updates.objectName = v.object_name_update;
308
+ if (v.object_type_update !== undefined)
309
+ updates.objectType = v.object_type_update;
310
+ if (v.object_role_update !== undefined)
311
+ updates.role = v.object_role_update;
312
+ if (v.object_tags_update !== undefined)
313
+ updates.tags = v.object_tags_update;
314
+ const obj = await localProject.updateObject(objectId, updates);
315
+ return { action: "update_object", object: obj };
316
+ }
317
+ export async function handleCreateVersion(v) {
318
+ const projectId = await resolveProjectId(v);
319
+ const version = requireField(v.version, "version");
320
+ const project = await localProject.getProject(projectId);
321
+ if (!project)
322
+ throw new Error(`Project not found: ${projectId}`);
323
+ const created = await localProject.createVersion(projectId, version, v.version_description);
324
+ return {
325
+ action: "create_version",
326
+ version: {
327
+ version: created.version,
328
+ description: created.description,
329
+ createdAt: created.createdAt,
330
+ },
331
+ };
332
+ }
333
+ export async function handleBuildGraph(v) {
334
+ const projectId = await resolveProjectId(v);
335
+ const project = await localProject.getProject(projectId);
336
+ if (!project)
337
+ throw new Error(`Project not found: ${projectId}`);
338
+ let rootAddress = project.serviceAddress;
339
+ if (!rootAddress) {
340
+ const objects = await localProject.listObjects(projectId);
341
+ if (objects.length === 0) {
342
+ throw new Error("Cannot build graph: project has no objects and no service_address");
343
+ }
344
+ const coreObj = objects.find(o => o.role === "core");
345
+ rootAddress = (coreObj ?? objects[0]).objectAddress;
346
+ }
347
+ const builder = new GraphBuilder({
348
+ maxDepth: v.max_depth ?? 3,
349
+ enableRegistrar: v.enable_registrar ?? true,
350
+ enablePotential: v.enable_potential ?? false,
351
+ projectId,
352
+ network: project.network,
353
+ });
354
+ const result = await builder.buildRelationshipGraph(rootAddress);
355
+ const edgesBySource = {};
356
+ for (const edge of result.graph.edges) {
357
+ const src = edge.edgeSource ?? "unknown";
358
+ edgesBySource[src] = (edgesBySource[src] ?? 0) + 1;
359
+ }
360
+ return {
361
+ action: "build_graph",
362
+ nodeCount: result.graph.nodes.length,
363
+ edgeCount: result.graph.edges.length,
364
+ edgesBySource,
365
+ reputationCount: result.reputation.size,
366
+ builtAt: result.graph.builtAt,
367
+ };
368
+ }
369
+ export async function handleGetGraph(v) {
370
+ const projectId = await resolveProjectId(v);
371
+ const edges = await localProject.getGraph(projectId);
372
+ return {
373
+ action: "get_graph",
374
+ edges: edges.map(e => ({
375
+ sourceObject: e.sourceObject,
376
+ targetObject: e.targetObject,
377
+ edgeSource: e.edgeSource,
378
+ relationshipType: e.relationshipType,
379
+ fieldName: e.fieldName,
380
+ depth: e.depth,
381
+ verified: e.verified,
382
+ weight: e.weight,
383
+ direction: e.direction,
384
+ })),
385
+ };
386
+ }
387
+ export async function handleEvaluateProject(v) {
388
+ const projectId = await resolveProjectId(v);
389
+ const evalType = requireField(v.evaluation_type, "evaluation_type");
390
+ const project = await localProject.getProject(projectId);
391
+ if (!project)
392
+ throw new Error(`Project not found: ${projectId}`);
393
+ if (v.refresh_before_eval) {
394
+ await refreshProjectObjects(projectId, project.network);
395
+ }
396
+ const objects = await localProject.listObjects(projectId);
397
+ const edges = await localProject.getGraph(projectId);
398
+ const addresses = objects.map(o => o.objectAddress);
399
+ const cacheEntries = await localProject.getCachedObjects(addresses);
400
+ const objectCache = new Map();
401
+ for (const [addr, entry] of cacheEntries)
402
+ objectCache.set(addr, entry);
403
+ let llmPrompt;
404
+ if (evalType === "worth_buying" || evalType === "value") {
405
+ const assembler = new SemanticAssembler();
406
+ const reputation = new Map();
407
+ for (const edge of edges) {
408
+ if (edge.edgeSource === "registrar" && edge.relationshipType === "affiliation") {
409
+ }
410
+ }
411
+ const context = await assembler.assemble(project, objects, edges, reputation);
412
+ const promptResult = assembler.buildEvaluationPrompt(evalType, context);
413
+ llmPrompt = promptResult.prompt;
414
+ }
415
+ const evalInput = {
416
+ project,
417
+ objects,
418
+ edges: edges,
419
+ objectCache: objectCache,
420
+ reputation: undefined,
421
+ };
422
+ const result = runEvaluation(evalInput, evalType, llmPrompt);
423
+ let evaluationId = "";
424
+ if (!result.needsLlm) {
425
+ const evalInput2 = {
426
+ projectId,
427
+ evalType,
428
+ score: result.score,
429
+ summary: result.summary,
430
+ details: {
431
+ criterionScores: result.criterionScores,
432
+ findings: result.findings,
433
+ strengths: result.strengths,
434
+ },
435
+ };
436
+ const saved = await localProject.saveEvaluation(evalInput2);
437
+ evaluationId = saved.id;
438
+ }
439
+ return {
440
+ action: "evaluate_project",
441
+ evaluationType: result.evaluationType,
442
+ score: result.score,
443
+ summary: result.summary,
444
+ criterionScores: result.criterionScores,
445
+ findings: result.findings,
446
+ strengths: result.strengths,
447
+ needsLlm: result.needsLlm,
448
+ llmPrompt: result.llmPrompt,
449
+ evaluationId,
450
+ };
451
+ }
452
+ export async function handleSaveEvaluation(v) {
453
+ const projectId = await resolveProjectId(v);
454
+ const evalType = requireField(v.evaluation_type, "evaluation_type");
455
+ const score = requireField(v.eval_score, "eval_score");
456
+ const summary = v.eval_summary ?? "";
457
+ const details = v.eval_details ?? {};
458
+ const saved = await localProject.saveEvaluation({
459
+ projectId,
460
+ evalType,
461
+ score,
462
+ summary,
463
+ details,
464
+ });
465
+ return {
466
+ action: "save_evaluation",
467
+ evaluation: {
468
+ id: saved.id,
469
+ evalType: saved.evalType,
470
+ score: saved.score,
471
+ summary: saved.summary,
472
+ evaluatedAt: saved.evaluatedAt,
473
+ },
474
+ };
475
+ }
476
+ export async function handleCompareProjects(v) {
477
+ const projectIds = requireField(v.compare_project_ids, "compare_project_ids");
478
+ const evalType = (v.evaluation_type ?? "worth_buying");
479
+ const entries = [];
480
+ for (const pid of projectIds) {
481
+ const project = await localProject.getProject(pid);
482
+ if (!project)
483
+ continue;
484
+ const evals = await localProject.listEvaluations(pid, { evalType });
485
+ const latest = evals[0];
486
+ entries.push({
487
+ projectId: pid,
488
+ projectName: project.name,
489
+ score: latest?.score ?? null,
490
+ summary: latest?.summary ?? null,
491
+ evaluatedAt: latest?.evaluatedAt ?? null,
492
+ });
493
+ }
494
+ const comparison = compareProjects(entries, evalType);
495
+ return {
496
+ action: "compare_projects",
497
+ evaluationType: comparison.evaluationType,
498
+ ranking: comparison.ranking,
499
+ bestProjectId: comparison.bestProjectId,
500
+ };
501
+ }
502
+ async function refreshProjectObjects(projectId, network) {
503
+ const objects = await localProject.listObjects(projectId);
504
+ const addresses = objects.map(o => o.objectAddress);
505
+ if (addresses.length === 0)
506
+ return { refreshedCount: 0, failedCount: 0 };
507
+ let refreshedCount = 0;
508
+ let failedCount = 0;
509
+ const BATCH_SIZE = 50;
510
+ for (let i = 0; i < addresses.length; i += BATCH_SIZE) {
511
+ const batch = addresses.slice(i, i + BATCH_SIZE);
512
+ try {
513
+ const response = await query_objects({
514
+ objects: batch,
515
+ no_cache: true,
516
+ network,
517
+ });
518
+ for (const obj of response?.objects ?? []) {
519
+ if (obj?.object) {
520
+ await localProject.cacheObject(obj.object, obj.type ?? null, JSON.stringify(obj), network);
521
+ refreshedCount++;
522
+ }
523
+ }
524
+ }
525
+ catch {
526
+ failedCount += batch.length;
527
+ }
528
+ }
529
+ return { refreshedCount, failedCount };
530
+ }
531
+ export async function handleRefreshObjects(v) {
532
+ const projectId = await resolveProjectId(v);
533
+ const project = await localProject.getProject(projectId);
534
+ if (!project)
535
+ throw new Error(`Project not found: ${projectId}`);
536
+ const network = project.network;
537
+ const { refreshedCount, failedCount } = await refreshProjectObjects(projectId, network);
538
+ return {
539
+ action: "refresh_objects",
540
+ refreshedCount,
541
+ failedCount,
542
+ refreshedAt: Date.now(),
543
+ };
544
+ }
545
+ export async function handleDeleteProject(v) {
546
+ const id = await resolveProjectId(v);
547
+ await localProject.deleteProject(id);
548
+ return { action: "delete_project", deleted: true };
549
+ }
550
+ export async function handleGetObjectDiff(v) {
551
+ const address = requireField(v.diff_address, "diff_address");
552
+ const fromTime = requireField(v.diff_from_time, "diff_from_time");
553
+ const toTime = requireField(v.diff_to_time, "diff_to_time");
554
+ const diff = await localProject.getObjectDiff(address, fromTime, toTime);
555
+ return {
556
+ action: "get_object_diff",
557
+ address: diff.address,
558
+ fromTime: diff.fromTime,
559
+ toTime: diff.toTime,
560
+ changedFields: diff.changedFields.map(f => ({
561
+ fieldPath: f.fieldPath,
562
+ oldValue: f.oldValue,
563
+ newValue: f.newValue,
564
+ changeType: f.changeType,
565
+ })),
566
+ };
567
+ }
@@ -58,6 +58,7 @@ export declare function queryProjectObjects(prefix: string): Promise<{
58
58
  address?: string;
59
59
  type?: string;
60
60
  version?: string;
61
+ tags?: string[];
61
62
  }[]>;
62
63
  export declare function queryShareableObjects(): Promise<{
63
64
  name?: string;
@@ -2,10 +2,9 @@ import { normalizeForProject, extractProjectPrefix, extractAllProjectVersions, T
2
2
  import { ProjectGraph, extractReferences, nodeIdOf, } from "./graph.js";
3
3
  import { listProjects, listProjectObjects, listShareableObjects, traceDependencies, traceReferencedBy, prePublishCheck, findCrossProjectReferences, } from "./query.js";
4
4
  import { isEnabled as isRuntimeEnabled } from "../config/index.js";
5
- import { LocalMark } from "@wowok/wowok";
5
+ import { LocalMark, getWowMcpDir } from "@wowok/wowok";
6
6
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
7
7
  import { dirname, join } from "path";
8
- import { homedir } from "os";
9
8
  import * as ProjectStore from "./project-store.js";
10
9
  export * from "./namespace.js";
11
10
  export * from "./graph.js";
@@ -217,7 +216,30 @@ function extractAddressFromResult(result) {
217
216
  return undefined;
218
217
  }
219
218
  export async function queryProjects() {
220
- return listProjects();
219
+ const tagProjects = await listProjects();
220
+ try {
221
+ const { LocalProject } = await import("@wowok/wowok");
222
+ const sqliteProjects = await LocalProject.Instance().listProjects();
223
+ const sqliteInfos = sqliteProjects.map(p => ({
224
+ prefix: p.prefix,
225
+ objectCount: 0,
226
+ types: [],
227
+ versions: p.currentVersion ? [p.currentVersion] : [],
228
+ objects: [],
229
+ ...p,
230
+ }));
231
+ const merged = new Map();
232
+ for (const p of tagProjects)
233
+ merged.set(p.prefix, p);
234
+ for (const p of sqliteInfos) {
235
+ if (!merged.has(p.prefix))
236
+ merged.set(p.prefix, p);
237
+ }
238
+ return Array.from(merged.values());
239
+ }
240
+ catch {
241
+ return tagProjects;
242
+ }
221
243
  }
222
244
  export async function queryProjectObjects(prefix) {
223
245
  return listProjectObjects(prefix);
@@ -247,10 +269,7 @@ export function queryGraphStats() {
247
269
  };
248
270
  }
249
271
  function graphFilePath() {
250
- const dir = process.env.WOWOK_CONFIG_DIR
251
- ? process.env.WOWOK_CONFIG_DIR
252
- : join(homedir(), ".wowok");
253
- return join(dir, "project-graph.json");
272
+ return join(getWowMcpDir(), "project-graph.json");
254
273
  }
255
274
  export function saveGraph() {
256
275
  const path = graphFilePath();
@@ -1,12 +1,9 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, copyFileSync, statSync, appendFileSync, } from "fs";
2
2
  import { dirname, join } from "path";
3
- import { homedir } from "os";
3
+ import { getWowMcpDir } from "@wowok/wowok";
4
4
  export const CURRENT_SCHEMA_VERSION = "1.0.0";
5
5
  export function projectsRootDir() {
6
- const base = process.env.WOWOK_CONFIG_DIR
7
- ? process.env.WOWOK_CONFIG_DIR
8
- : join(homedir(), ".wowok");
9
- return join(base, "projects");
6
+ return join(getWowMcpDir(), "projects");
10
7
  }
11
8
  export function projectDir(prefix, version) {
12
9
  return join(projectsRootDir(), `${prefix}_${version}`);
@@ -9,6 +9,7 @@ export interface ProjectInfo {
9
9
  address?: string;
10
10
  type?: string;
11
11
  version?: string;
12
+ tags?: string[];
12
13
  }>;
13
14
  }
14
15
  export interface DependencyTrace {
@@ -42,6 +42,7 @@ export async function listProjects() {
42
42
  address: m.address,
43
43
  type,
44
44
  version: v,
45
+ tags: m.tags,
45
46
  });
46
47
  }
47
48
  }
@@ -68,6 +69,7 @@ export async function listProjectObjects(prefix) {
68
69
  address: m.address,
69
70
  type: typeTag?.slice(TAG_PREFIX.type.length),
70
71
  version: matched.version,
72
+ tags: m.tags,
71
73
  });
72
74
  }
73
75
  return results;