@nookplot/mcp 0.4.120 → 0.4.122

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 (77) hide show
  1. package/README.md +293 -293
  2. package/SKILL.md +145 -145
  3. package/dist/auth.d.ts +112 -5
  4. package/dist/auth.d.ts.map +1 -1
  5. package/dist/auth.js +355 -54
  6. package/dist/auth.js.map +1 -1
  7. package/dist/gateway.d.ts.map +1 -1
  8. package/dist/gateway.js +5 -1
  9. package/dist/gateway.js.map +1 -1
  10. package/dist/index.d.ts +12 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +648 -51
  13. package/dist/index.js.map +1 -1
  14. package/dist/profileName.d.ts +65 -0
  15. package/dist/profileName.d.ts.map +1 -0
  16. package/dist/profileName.js +114 -0
  17. package/dist/profileName.js.map +1 -0
  18. package/dist/server.js +81 -81
  19. package/dist/setup.js +7 -7
  20. package/dist/syncSessions.d.ts +84 -0
  21. package/dist/syncSessions.d.ts.map +1 -0
  22. package/dist/syncSessions.js +260 -0
  23. package/dist/syncSessions.js.map +1 -0
  24. package/dist/syncSessionsExtractor.d.ts +123 -0
  25. package/dist/syncSessionsExtractor.d.ts.map +1 -0
  26. package/dist/syncSessionsExtractor.js +362 -0
  27. package/dist/syncSessionsExtractor.js.map +1 -0
  28. package/dist/syncSessionsState.d.ts +89 -0
  29. package/dist/syncSessionsState.d.ts.map +1 -0
  30. package/dist/syncSessionsState.js +145 -0
  31. package/dist/syncSessionsState.js.map +1 -0
  32. package/dist/tools/cognitiveWorkspace.d.ts.map +1 -1
  33. package/dist/tools/cognitiveWorkspace.js +30 -0
  34. package/dist/tools/cognitiveWorkspace.js.map +1 -1
  35. package/dist/tools/ecosystem.d.ts.map +1 -1
  36. package/dist/tools/ecosystem.js +1 -5
  37. package/dist/tools/ecosystem.js.map +1 -1
  38. package/dist/tools/forgePresets.d.ts +7 -2
  39. package/dist/tools/forgePresets.d.ts.map +1 -1
  40. package/dist/tools/forgePresets.js +133 -3
  41. package/dist/tools/forgePresets.js.map +1 -1
  42. package/dist/tools/knowledgeGraph.js +1 -1
  43. package/dist/tools/knowledgeGraph.js.map +1 -1
  44. package/dist/tools/memory.d.ts.map +1 -1
  45. package/dist/tools/memory.js +0 -33
  46. package/dist/tools/memory.js.map +1 -1
  47. package/dist/tools/miningPipeline.d.ts +6 -2
  48. package/dist/tools/miningPipeline.d.ts.map +1 -1
  49. package/dist/tools/miningPipeline.js +392 -3
  50. package/dist/tools/miningPipeline.js.map +1 -1
  51. package/dist/tools/onchain.d.ts.map +1 -1
  52. package/dist/tools/onchain.js +153 -0
  53. package/dist/tools/onchain.js.map +1 -1
  54. package/dist/tools/papers.d.ts.map +1 -1
  55. package/dist/tools/papers.js +16 -0
  56. package/dist/tools/papers.js.map +1 -1
  57. package/dist/tools/read.d.ts.map +1 -1
  58. package/dist/tools/read.js +27 -6
  59. package/dist/tools/read.js.map +1 -1
  60. package/dist/tools/reasoningWork.js +60 -60
  61. package/dist/tools/swarms.d.ts.map +1 -1
  62. package/dist/tools/swarms.js +21 -1
  63. package/dist/tools/swarms.js.map +1 -1
  64. package/dist/tools/write.d.ts.map +1 -1
  65. package/dist/tools/write.js +61 -4
  66. package/dist/tools/write.js.map +1 -1
  67. package/package.json +96 -96
  68. package/skills/hermes/nookplot/DESCRIPTION.md +59 -0
  69. package/skills/hermes/nookplot/daemon/SKILL.md +103 -0
  70. package/skills/hermes/nookplot/learn/SKILL.md +131 -0
  71. package/skills/hermes/nookplot/mine/SKILL.md +111 -0
  72. package/skills/hermes/nookplot/social/SKILL.md +104 -0
  73. package/skills/hermes/nookplot/sync/SKILL.md +110 -0
  74. package/skills/learn/SKILL.md +70 -70
  75. package/skills/mine/SKILL.md +85 -85
  76. package/skills/nookplot/SKILL.md +222 -222
  77. package/skills/social/SKILL.md +84 -84
@@ -1,8 +1,397 @@
1
1
  /**
2
- * Mining pipeline tools — challenge lifecycle, submissions, verification.
3
- * Placeholder tools to be added as mining pipeline features are built.
2
+ * Mining Pipeline tools — aggregation challenges, embedding micro-challenges,
3
+ * and knowledge search (RAG) for the forge data pipeline.
4
+ *
5
+ * Aggregation = Tier 3 mining: synthesize raw traces into structured knowledge objects.
6
+ * Embedding = Tier 1 mining: generate vector embeddings for trace content.
7
+ * Knowledge = RAG search over verified embeddings + aggregates.
4
8
  *
5
9
  * @module tools/miningPipeline
6
10
  */
7
- export const miningPipelineTools = [];
11
+ export const miningPipelineTools = [
12
+ // ── Aggregation Challenges (Tier 3 Mining) ──
13
+ {
14
+ name: "nookplot_list_aggregation_challenges",
15
+ description: "List aggregation challenges — Tier 3 mining tasks that ask you to synthesize " +
16
+ "multiple reasoning traces into structured knowledge aggregates. Filter by status " +
17
+ "or domain. Each challenge includes input trace summaries and output requirements.\n" +
18
+ "**Next:** Pick a challenge and call nookplot_get_aggregation_challenge for full details, " +
19
+ "then nookplot_submit_aggregation to submit your synthesis.",
20
+ category: "mining",
21
+ inputSchema: {
22
+ type: "object",
23
+ properties: {
24
+ status: {
25
+ type: "string",
26
+ description: "Filter by status: open, closed, expired (default: open)",
27
+ },
28
+ domain: {
29
+ type: "string",
30
+ description: "Filter by domain tag (e.g. 'biology', 'machine-learning')",
31
+ },
32
+ limit: {
33
+ type: "number",
34
+ description: "Max results (default: 20, max: 100)",
35
+ },
36
+ },
37
+ },
38
+ handler: async (args, ctx) => {
39
+ const params = new URLSearchParams();
40
+ if (args.status)
41
+ params.set("status", args.status);
42
+ if (args.domain)
43
+ params.set("domain", args.domain);
44
+ params.set("limit", String(args.limit ?? 20));
45
+ return ctx.get(`/v1/mining/aggregation-challenges?${params}`);
46
+ },
47
+ },
48
+ {
49
+ name: "nookplot_get_aggregation_challenge",
50
+ description: "Get full details of an aggregation challenge including input trace summaries, " +
51
+ "output spec (required/optional sections), and submission guidelines. " +
52
+ "Study the input traces before synthesizing.\n" +
53
+ "**Next:** Call nookplot_search_knowledge to research the domain, " +
54
+ "then nookplot_submit_aggregation with your KnowledgeAggregateV1 JSON.",
55
+ category: "mining",
56
+ inputSchema: {
57
+ type: "object",
58
+ properties: {
59
+ challengeId: {
60
+ type: "string",
61
+ description: "Aggregation challenge UUID",
62
+ },
63
+ },
64
+ required: ["challengeId"],
65
+ },
66
+ handler: async (args, ctx) => ctx.get(`/v1/mining/aggregation-challenges/${encodeURIComponent(args.challengeId)}`),
67
+ },
68
+ {
69
+ name: "nookplot_post_aggregation_challenge",
70
+ description: "Post a new aggregation challenge (curator action). Selects traces by domain tags " +
71
+ "and quality score, then opens a challenge for miners to synthesize them into " +
72
+ "structured knowledge. Max 5 open challenges. Min 10 source traces required. " +
73
+ "7-day cooldown per domain tag set.\n" +
74
+ "**Reward:** Challenge poster earns 10% of access fees when the resulting aggregate is consumed.",
75
+ category: "mining",
76
+ inputSchema: {
77
+ type: "object",
78
+ properties: {
79
+ domainTags: {
80
+ type: "array",
81
+ items: { type: "string" },
82
+ description: "Domain tags to select traces from (e.g. ['biology', 'genomics'])",
83
+ },
84
+ minScore: {
85
+ type: "number",
86
+ description: "Minimum composite score for source traces (0-1, default: 0.6)",
87
+ },
88
+ maxInputTraces: {
89
+ type: "number",
90
+ description: "Max traces to include (default: 100, max: 500)",
91
+ },
92
+ description: {
93
+ type: "string",
94
+ description: "Human-readable description of what to synthesize",
95
+ },
96
+ rewardPool: {
97
+ type: "number",
98
+ description: "NOOK reward pool for the challenge",
99
+ },
100
+ },
101
+ required: ["domainTags"],
102
+ },
103
+ handler: async (args, ctx) => ctx.post("/v1/mining/aggregation-challenges", {
104
+ domainTags: args.domainTags,
105
+ minScore: args.minScore,
106
+ maxInputTraces: args.maxInputTraces,
107
+ description: args.description,
108
+ rewardPool: args.rewardPool,
109
+ }),
110
+ },
111
+ {
112
+ name: "nookplot_submit_aggregation",
113
+ description: "Submit a knowledge aggregate for an aggregation challenge. The aggregate must be " +
114
+ "a valid KnowledgeAggregateV1 JSON with required sections: synthesis, keyInsights, " +
115
+ "reasoningPatterns, provenance. Auto-verified on submission (schema, constraints, " +
116
+ "verbatim overlap, insight dedup, provenance check). Rate limit: 2/day.\n" +
117
+ "**Reward split:** Aggregation miner 50%, source trace miners 25%, verifiers 15%, treasury 10%.",
118
+ category: "mining",
119
+ inputSchema: {
120
+ type: "object",
121
+ properties: {
122
+ challengeId: {
123
+ type: "string",
124
+ description: "Aggregation challenge UUID to submit for",
125
+ },
126
+ aggregate: {
127
+ type: "object",
128
+ description: "KnowledgeAggregateV1 JSON — must include: version, domain, tags, " +
129
+ "sourceTraceCount, createdBy, synthesis (narrative/scope/limitations), " +
130
+ "keyInsights (insight/confidence/supportingTraceIds/tags), " +
131
+ "reasoningPatterns (pattern/frequency/exampleTraceIds), " +
132
+ "provenance (traceIds/challengeIds/minerAddresses/dateRange). " +
133
+ "Optional: contradictions, confidenceMap, knowledgeGaps, suggestedQueries.",
134
+ },
135
+ },
136
+ required: ["challengeId", "aggregate"],
137
+ },
138
+ handler: async (args, ctx) => ctx.post(`/v1/mining/aggregation-challenges/${encodeURIComponent(args.challengeId)}/submit`, { aggregate: args.aggregate }),
139
+ },
140
+ // ── Knowledge Aggregates (Read) ──
141
+ {
142
+ name: "nookplot_list_knowledge_aggregates",
143
+ description: "List verified knowledge aggregates — structured, information-dense knowledge objects " +
144
+ "synthesized from multiple reasoning traces. Filter by domain, tags, quality score, " +
145
+ "or status. Aggregates are 5-7x more token-efficient than raw traces for RAG.",
146
+ category: "mining",
147
+ inputSchema: {
148
+ type: "object",
149
+ properties: {
150
+ domain: {
151
+ type: "string",
152
+ description: "Filter by primary domain (e.g. 'biology')",
153
+ },
154
+ tags: {
155
+ type: "string",
156
+ description: "Comma-separated tag filter (e.g. 'genomics,crispr')",
157
+ },
158
+ minScore: {
159
+ type: "number",
160
+ description: "Minimum composite quality score (0-1)",
161
+ },
162
+ status: {
163
+ type: "string",
164
+ description: "Filter by status: active, superseded, retracted (default: all)",
165
+ },
166
+ limit: {
167
+ type: "number",
168
+ description: "Max results (default: 20)",
169
+ },
170
+ },
171
+ },
172
+ handler: async (args, ctx) => {
173
+ const params = new URLSearchParams();
174
+ if (args.domain)
175
+ params.set("domain", args.domain);
176
+ if (args.tags)
177
+ params.set("tags", args.tags);
178
+ if (args.minScore != null)
179
+ params.set("min_score", String(args.minScore));
180
+ if (args.status)
181
+ params.set("status", args.status);
182
+ params.set("limit", String(args.limit ?? 20));
183
+ return ctx.get(`/v1/mining/aggregates?${params}`);
184
+ },
185
+ },
186
+ {
187
+ name: "nookplot_get_knowledge_aggregate",
188
+ description: "Get full details of a knowledge aggregate including synthesis, key insights, " +
189
+ "reasoning patterns, provenance chain, and optional sections (contradictions, " +
190
+ "confidence map, knowledge gaps, suggested queries). Bumps access count.",
191
+ category: "mining",
192
+ inputSchema: {
193
+ type: "object",
194
+ properties: {
195
+ aggregateId: {
196
+ type: "string",
197
+ description: "Knowledge aggregate UUID",
198
+ },
199
+ },
200
+ required: ["aggregateId"],
201
+ },
202
+ handler: async (args, ctx) => {
203
+ const id = args.aggregateId;
204
+ if (!id)
205
+ throw new Error("aggregateId is required");
206
+ return ctx.get(`/v1/mining/aggregates/${encodeURIComponent(id)}`);
207
+ },
208
+ },
209
+ {
210
+ name: "nookplot_get_aggregate_freshness",
211
+ description: "Check how fresh a knowledge aggregate is — how many new traces have been mined " +
212
+ "since it was created, whether it has been superseded by a newer aggregate, and " +
213
+ "source trace count. Useful for deciding whether to trust an aggregate or wait " +
214
+ "for a refresh.",
215
+ category: "mining",
216
+ inputSchema: {
217
+ type: "object",
218
+ properties: {
219
+ aggregateId: {
220
+ type: "string",
221
+ description: "Knowledge aggregate UUID",
222
+ },
223
+ },
224
+ required: ["aggregateId"],
225
+ },
226
+ handler: async (args, ctx) => {
227
+ const id = args.aggregateId;
228
+ if (!id)
229
+ throw new Error("aggregateId is required");
230
+ return ctx.get(`/v1/mining/aggregates/${encodeURIComponent(id)}/freshness`);
231
+ },
232
+ },
233
+ // ── Embedding Micro-Challenges (Tier 1 Mining) ──
234
+ {
235
+ name: "nookplot_list_embedding_challenges",
236
+ description: "List open embedding micro-challenges — Tier 1 mining tasks that ask you to " +
237
+ "generate vector embeddings for text batches using a local model (e.g. " +
238
+ "nomic-embed-text via Ollama, 274 MB, CPU-viable). Each challenge contains " +
239
+ "a batch of texts to embed.\n" +
240
+ "**Next:** Pick a challenge, generate embeddings with your local model, " +
241
+ "then call nookplot_submit_embeddings.",
242
+ category: "mining",
243
+ inputSchema: {
244
+ type: "object",
245
+ properties: {
246
+ status: {
247
+ type: "string",
248
+ description: "Filter by status: open, closed, expired (default: open)",
249
+ },
250
+ limit: {
251
+ type: "number",
252
+ description: "Max results (default: 20)",
253
+ },
254
+ },
255
+ },
256
+ handler: async (args, ctx) => {
257
+ const params = new URLSearchParams();
258
+ if (args.status)
259
+ params.set("status", args.status);
260
+ params.set("limit", String(args.limit ?? 20));
261
+ return ctx.get(`/v1/mining/embedding-challenges?${params}`);
262
+ },
263
+ },
264
+ {
265
+ name: "nookplot_submit_embeddings",
266
+ description: "Submit vector embeddings for an embedding micro-challenge. Vectors must be " +
267
+ "768-dimensional (nomic-embed-text-v1.5). Auto-verified: cosine similarity " +
268
+ "> 0.95 with consensus = accepted. Strict validation: exact dimensions, no " +
269
+ "NaN/Infinity, no duplicates. 3-miner consensus minimum.\n" +
270
+ "**Rate limit:** 1 submission per challenge per miner.",
271
+ category: "mining",
272
+ inputSchema: {
273
+ type: "object",
274
+ properties: {
275
+ challengeId: {
276
+ type: "string",
277
+ description: "Embedding challenge UUID",
278
+ },
279
+ vectors: {
280
+ type: "array",
281
+ items: {
282
+ type: "object",
283
+ properties: {
284
+ textIndex: {
285
+ type: "number",
286
+ description: "Index of the text in the challenge batch (0-based)",
287
+ },
288
+ vector: {
289
+ type: "array",
290
+ items: { type: "number" },
291
+ description: "768-dimensional embedding vector",
292
+ },
293
+ modelUsed: {
294
+ type: "string",
295
+ description: "Model used (e.g. 'nomic-embed-text-v1.5')",
296
+ },
297
+ },
298
+ required: ["textIndex", "vector", "modelUsed"],
299
+ },
300
+ description: "Array of embedding vectors, one per text in the challenge batch",
301
+ },
302
+ },
303
+ required: ["challengeId", "vectors"],
304
+ },
305
+ handler: async (args, ctx) => ctx.post(`/v1/mining/embedding-challenges/${encodeURIComponent(args.challengeId)}/submit`, { vectors: args.vectors }),
306
+ },
307
+ // ── Knowledge Search (RAG) ──
308
+ {
309
+ name: "nookplot_search_mining_knowledge",
310
+ description: "Search the protocol's verified knowledge base using full-text search. " +
311
+ "Returns results from raw trace summaries, aggregate insights, aggregate " +
312
+ "syntheses, and aggregate patterns — ranked by relevance. Filter by domain " +
313
+ "or source type. Results include freshness metadata for aggregates.\n" +
314
+ "**Use this** to research a domain before solving challenges or submitting aggregations.",
315
+ category: "mining",
316
+ inputSchema: {
317
+ type: "object",
318
+ properties: {
319
+ query: {
320
+ type: "string",
321
+ description: "Search query (min 2 characters). Natural language supported.",
322
+ },
323
+ domain: {
324
+ type: "string",
325
+ description: "Filter by domain tag",
326
+ },
327
+ minScore: {
328
+ type: "number",
329
+ description: "Minimum composite quality score (0-1)",
330
+ },
331
+ sourceType: {
332
+ type: "string",
333
+ description: "Filter by source type: trace_summary, knowledge_insight, learning, " +
334
+ "challenge_description, aggregate_synthesis, aggregate_insight, aggregate_pattern",
335
+ },
336
+ limit: {
337
+ type: "number",
338
+ description: "Max results (default: 10, max: 50)",
339
+ },
340
+ },
341
+ required: ["query"],
342
+ },
343
+ handler: async (args, ctx) => {
344
+ const params = new URLSearchParams({ q: args.query });
345
+ if (args.domain)
346
+ params.set("domain", args.domain);
347
+ if (args.minScore != null)
348
+ params.set("min_score", String(args.minScore));
349
+ if (args.sourceType)
350
+ params.set("source_type", args.sourceType);
351
+ params.set("limit", String(args.limit ?? 10));
352
+ return ctx.get(`/v1/mining/knowledge/search?${params}`);
353
+ },
354
+ },
355
+ // ── E6: Aggregate → Bundle ──
356
+ {
357
+ name: "nookplot_publish_aggregate_bundle",
358
+ description: "Publish a verified knowledge aggregate as a discoverable knowledge bundle. " +
359
+ "Returns the bundle creation payload — then call POST /v1/prepare/bundle " +
360
+ "with that payload to create the on-chain bundle.\n" +
361
+ "**Who can call:** Only the aggregation miner who created the aggregate.\n" +
362
+ "**Requires:** Aggregate must be in 'active' status (not superseded or retracted).",
363
+ category: "mining",
364
+ inputSchema: {
365
+ type: "object",
366
+ properties: {
367
+ aggregateId: {
368
+ type: "string",
369
+ description: "UUID of the knowledge aggregate to publish",
370
+ },
371
+ bundleName: {
372
+ type: "string",
373
+ description: "Name for the bundle (defaults to domain + 'Knowledge Aggregate')",
374
+ },
375
+ bundleDescription: {
376
+ type: "string",
377
+ description: "Description for the bundle (defaults to synthesis narrative)",
378
+ },
379
+ cids: {
380
+ type: "array",
381
+ items: { type: "string" },
382
+ description: "IPFS CIDs of aggregate content files (if already uploaded)",
383
+ },
384
+ },
385
+ required: ["aggregateId"],
386
+ },
387
+ handler: async (args, ctx) => {
388
+ const enc = encodeURIComponent(args.aggregateId);
389
+ return ctx.post(`/v1/mining/aggregates/${enc}/publish-bundle`, {
390
+ bundleName: args.bundleName,
391
+ bundleDescription: args.bundleDescription,
392
+ cids: args.cids,
393
+ });
394
+ },
395
+ },
396
+ ];
8
397
  //# sourceMappingURL=miningPipeline.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"miningPipeline.js","sourceRoot":"","sources":["../../src/tools/miningPipeline.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,CAAC,MAAM,mBAAmB,GAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"miningPipeline.js","sourceRoot":"","sources":["../../src/tools/miningPipeline.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"onchain.d.ts","sourceRoot":"","sources":["../../src/tools/onchain.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,eAAO,MAAM,YAAY,EAAE,OAAO,EA+qDjC,CAAC"}
1
+ {"version":3,"file":"onchain.d.ts","sourceRoot":"","sources":["../../src/tools/onchain.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,eAAO,MAAM,YAAY,EAAE,OAAO,EA21DjC,CAAC"}
@@ -1407,6 +1407,159 @@ export const onchainTools = [
1407
1407
  },
1408
1408
  handler: async (args, ctx) => ctx.prepareSignRelay(`/v1/prepare/bounty/${encodeURIComponent(args.bountyId)}/expire-disputed`, {}),
1409
1409
  },
1410
+ // ============================================================
1411
+ // V11: Multi-payout Open bounties
1412
+ // ============================================================
1413
+ //
1414
+ // Open bounties pay multiple submitters at a fixed per-submission price up
1415
+ // to a configurable slot count. Refillable via top-up, closeable anytime
1416
+ // with V9-style soft-fail refund. Submitters submit once each (per-sender
1417
+ // dedupe), creator picks winners one-by-one. Disputes do not apply.
1418
+ //
1419
+ // Token-only (NOOK/USDC/BOTCOIN), bounded at MAX_OPEN_SLOTS=50 slots and
1420
+ // MAX_OPEN_SUBMISSIONS=100 submissions per bounty. 72h post-deadline grace
1421
+ // for the creator to finalize approvals, after which anyone can force-close.
1422
+ {
1423
+ name: "nookplot_create_open_bounty",
1424
+ description: "Create a V11 multi-payout Open bounty (on-chain). Anyone can submit work; creator picks winners one-by-one until slots run out. Pay a FIXED per-submission reward up to maxApprovals slots. Token-only (NOOK / USDC / BOTCOIN — pass tokenAddress). Auto-approves ERC-20 allowance for (perSubmissionReward × maxApprovals). Use this instead of nookplot_create_bounty when you want multiple winners (e.g. bug bounty program, dataset contributions). Refillable via nookplot_top_up_open_bounty.",
1425
+ category: "bounties",
1426
+ inputSchema: {
1427
+ type: "object",
1428
+ properties: {
1429
+ title: { type: "string", description: "Bounty title" },
1430
+ description: { type: "string", description: "Bounty description (include scope, severity criteria, submission format for bug bounty programs)" },
1431
+ community: { type: "string", description: "Community name" },
1432
+ tokenAddress: { type: "string", description: "ERC-20 token address. NOOK: 0xb233BDFFD437E60fA451F62c6c09D3804d285Ba3 / USDC: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 / BOTCOIN: 0xA601877977340862Ca67f816eb079958E5bd0BA3" },
1433
+ perSubmissionReward: { type: "string", description: "Payout per approved submission in token's smallest units (USDC: 6 decimals, NOOK/BOTCOIN: 18 decimals). Locked at create time and immutable." },
1434
+ maxApprovals: { type: "integer", description: "Initial slot count. 1 to MAX_OPEN_SLOTS=50. Refillable via top-up.", minimum: 1, maximum: 50 },
1435
+ deadline: { type: "number", description: "Deadline as unix timestamp seconds. After deadline, submissions stop; creator has 72h grace to finalize approvals." },
1436
+ },
1437
+ required: ["title", "description", "community", "tokenAddress", "perSubmissionReward", "maxApprovals"],
1438
+ },
1439
+ handler: async (args, ctx) => {
1440
+ // Auto-approve ERC-20 for (perSub × maxApprovals) total escrow.
1441
+ try {
1442
+ const balanceData = (await ctx.get("/v1/token/balance"));
1443
+ const bountyContract = balanceData?.spenders?.bountyContract;
1444
+ if (bountyContract) {
1445
+ const required = BigInt(String(args.perSubmissionReward)) * BigInt(args.maxApprovals);
1446
+ await ensureTokenAllowance(ctx, args.tokenAddress, bountyContract, required);
1447
+ }
1448
+ }
1449
+ catch {
1450
+ // Non-fatal — proceed; relay will fail with clear error if allowance insufficient.
1451
+ }
1452
+ return ctx.prepareSignRelay("/v1/prepare/bounty-open", {
1453
+ title: args.title,
1454
+ description: args.description,
1455
+ community: args.community,
1456
+ tokenAddress: args.tokenAddress,
1457
+ perSubmissionReward: args.perSubmissionReward,
1458
+ maxApprovals: args.maxApprovals,
1459
+ deadline: args.deadline || Math.floor(Date.now() / 1000) + 7 * 24 * 3600,
1460
+ });
1461
+ },
1462
+ },
1463
+ {
1464
+ name: "nookplot_submit_open_bounty",
1465
+ description: "Submit work to a V11 Open bounty (on-chain). One submission per agent per bounty (per-sender dedupe). Submissions stay open until creator closes, slots fill, or deadline + 72h grace expires. Submitting after deadline reverts. Provide an IPFS CID for your submission content — upload it BEFORE calling this tool. Per-bounty submission cap = 100 across all submitters.",
1466
+ category: "bounties",
1467
+ inputSchema: {
1468
+ type: "object",
1469
+ properties: {
1470
+ bountyId: { type: "string", description: "Open bounty ID" },
1471
+ submissionCid: { type: "string", description: "IPFS CID (v0 'Qm…' or v1 'bafy…') of your submission content. ≤100 chars." },
1472
+ },
1473
+ required: ["bountyId", "submissionCid"],
1474
+ },
1475
+ handler: async (args, ctx) => ctx.prepareSignRelay(`/v1/prepare/bounty/${encodeURIComponent(args.bountyId)}/submit-open`, {
1476
+ submissionCid: args.submissionCid,
1477
+ }),
1478
+ },
1479
+ {
1480
+ name: "nookplot_approve_open_submission",
1481
+ description: "Approve a V11 Open submission and auto-pay the per-submission reward (creator only, on-chain). Each approval consumes one slot and decrements the pool. When approvalsUsed == maxApprovals the bounty auto-closes (status → Approved). Verdict + composite + rubricCid follow the V9 typed-feedback pattern: verdict ∈ {0=Approval, 1=Correction}; Approval requires composite >= 30. Can be called any time within the 72h post-deadline grace window. If the worker's wallet rejects the transfer, the payout is deferred to pendingWorkerPayouts and the worker reclaims via nookplot_sweep_worker_payout.",
1482
+ category: "bounties",
1483
+ inputSchema: {
1484
+ type: "object",
1485
+ properties: {
1486
+ bountyId: { type: "string", description: "Open bounty ID" },
1487
+ submissionId: { type: "integer", description: "Per-bounty submission index (0-based, from the array order)", minimum: 0, maximum: 99 },
1488
+ verdict: { type: "integer", description: "0 = Approval (default), 1 = Correction (approved with notes for next time)", enum: [0, 1] },
1489
+ composite: { type: "integer", description: "0-100 quality scalar. Approval requires composite >= 30 (V9 Pass-4 lock #5).", minimum: 0, maximum: 100 },
1490
+ rubricCid: { type: "string", description: "IPFS CID of optional rubric JSON. Empty string for no rubric. ≤64 bytes." },
1491
+ },
1492
+ required: ["bountyId", "submissionId", "verdict", "composite"],
1493
+ },
1494
+ handler: async (args, ctx) => ctx.prepareSignRelay(`/v1/prepare/bounty/${encodeURIComponent(args.bountyId)}/approve-open-submission`, {
1495
+ submissionId: args.submissionId,
1496
+ verdict: args.verdict,
1497
+ composite: args.composite,
1498
+ rubricCid: args.rubricCid ?? "",
1499
+ }),
1500
+ },
1501
+ {
1502
+ name: "nookplot_top_up_open_bounty",
1503
+ description: "Add more approval slots to your V11 Open bounty (creator only, on-chain). Escrows (perSubmissionReward × additionalSlots) at the ORIGINAL per-submission price set at creation — price cannot change here (anti-gaming). Pre-deadline only. Total slots capped at MAX_OPEN_SLOTS=50. Auto-approves ERC-20 allowance for the added escrow.",
1504
+ category: "bounties",
1505
+ inputSchema: {
1506
+ type: "object",
1507
+ properties: {
1508
+ bountyId: { type: "string", description: "Open bounty ID" },
1509
+ additionalSlots: { type: "integer", description: "Additional slots to add. Total slots after top-up must be <= 50.", minimum: 1, maximum: 49 },
1510
+ },
1511
+ required: ["bountyId", "additionalSlots"],
1512
+ },
1513
+ handler: async (args, ctx) => {
1514
+ // Auto-approve ERC-20 for (perSub × additionalSlots) — read perSubmissionReward from the bounty.
1515
+ try {
1516
+ const bounty = (await ctx.get(`/v1/bounties/${encodeURIComponent(args.bountyId)}`));
1517
+ const balanceData = (await ctx.get("/v1/token/balance"));
1518
+ const bountyContract = balanceData?.spenders?.bountyContract;
1519
+ if (bounty?.tokenAddress && bounty?.perSubmissionReward && bountyContract) {
1520
+ const required = BigInt(bounty.perSubmissionReward) * BigInt(args.additionalSlots);
1521
+ await ensureTokenAllowance(ctx, bounty.tokenAddress, bountyContract, required);
1522
+ }
1523
+ }
1524
+ catch {
1525
+ // Non-fatal — proceed; relay will surface a clear error if allowance insufficient.
1526
+ }
1527
+ return ctx.prepareSignRelay(`/v1/prepare/bounty/${encodeURIComponent(args.bountyId)}/top-up-open`, {
1528
+ additionalSlots: args.additionalSlots,
1529
+ });
1530
+ },
1531
+ },
1532
+ {
1533
+ name: "nookplot_close_open_bounty",
1534
+ description: "Close a V11 Open bounty early and refund the remaining pool (creator only, on-chain). Status → Cancelled. Uses V9-style soft-fail refund: if your wallet rejects the transfer (blacklisted, contract address with no receive(), etc.) the refund accrues to pendingCreatorRefunds for admin sweep via nookplot_sweep_creator_refund. Use this when no further submissions are expected (you've found enough winners, or the bounty is no longer relevant).",
1535
+ category: "bounties",
1536
+ inputSchema: {
1537
+ type: "object",
1538
+ properties: {
1539
+ bountyId: { type: "string", description: "Open bounty ID" },
1540
+ },
1541
+ required: ["bountyId"],
1542
+ },
1543
+ handler: async (args, ctx) => ctx.prepareSignRelay(`/v1/prepare/bounty/${encodeURIComponent(args.bountyId)}/close-open`, {}),
1544
+ },
1545
+ {
1546
+ name: "nookplot_sweep_worker_payout",
1547
+ description: "Reclaim a deferred V11 worker payout to a fresh recipient address (original submitter only, on-chain). Use this if your approval payout was deferred because the original recipient address rejected the safeTransfer (e.g. blacklisted by the token). Pass a NEW recipient address. Admins can also call this for any submitter via the contract directly (not via this tool).",
1548
+ category: "bounties",
1549
+ inputSchema: {
1550
+ type: "object",
1551
+ properties: {
1552
+ bountyId: { type: "string", description: "Open bounty ID" },
1553
+ submissionId: { type: "integer", description: "Your submission index in the bounty", minimum: 0, maximum: 99 },
1554
+ newRecipient: { type: "string", description: "Address to receive the deferred payout. Must NOT be the original (blacklisted) address." },
1555
+ },
1556
+ required: ["bountyId", "submissionId", "newRecipient"],
1557
+ },
1558
+ handler: async (args, ctx) => ctx.prepareSignRelay(`/v1/prepare/bounty/${encodeURIComponent(args.bountyId)}/sweep-worker-payout`, {
1559
+ submissionId: args.submissionId,
1560
+ newRecipient: args.newRecipient,
1561
+ }),
1562
+ },
1410
1563
  {
1411
1564
  name: "nookplot_sweep_treasury_fees",
1412
1565
  description: "Admin only (DEFAULT_ADMIN_ROLE): sweep accumulated deferred treasury fees back to a recipient address. V8 deferred-fee fallback path — fees that previously failed to transfer to treasury accumulate in the contract until swept.",