@nookplot/runtime 0.5.30 → 0.5.32

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 (31) hide show
  1. package/dist/__tests__/autonomous.actionDispatch.test.d.ts +2 -0
  2. package/dist/__tests__/autonomous.actionDispatch.test.d.ts.map +1 -0
  3. package/dist/__tests__/autonomous.actionDispatch.test.js +570 -0
  4. package/dist/__tests__/autonomous.actionDispatch.test.js.map +1 -0
  5. package/dist/__tests__/autonomous.dedup.test.d.ts +2 -0
  6. package/dist/__tests__/autonomous.dedup.test.d.ts.map +1 -0
  7. package/dist/__tests__/autonomous.dedup.test.js +125 -0
  8. package/dist/__tests__/autonomous.dedup.test.js.map +1 -0
  9. package/dist/__tests__/autonomous.getAvailableActions.test.d.ts +2 -0
  10. package/dist/__tests__/autonomous.getAvailableActions.test.d.ts.map +1 -0
  11. package/dist/__tests__/autonomous.getAvailableActions.test.js +110 -0
  12. package/dist/__tests__/autonomous.getAvailableActions.test.js.map +1 -0
  13. package/dist/__tests__/autonomous.lifecycle.test.d.ts +2 -0
  14. package/dist/__tests__/autonomous.lifecycle.test.d.ts.map +1 -0
  15. package/dist/__tests__/autonomous.lifecycle.test.js +144 -0
  16. package/dist/__tests__/autonomous.lifecycle.test.js.map +1 -0
  17. package/dist/__tests__/contentSafety.test.d.ts +2 -0
  18. package/dist/__tests__/contentSafety.test.d.ts.map +1 -0
  19. package/dist/__tests__/contentSafety.test.js +90 -0
  20. package/dist/__tests__/contentSafety.test.js.map +1 -0
  21. package/dist/__tests__/helpers/mockRuntime.d.ts +11 -0
  22. package/dist/__tests__/helpers/mockRuntime.d.ts.map +1 -0
  23. package/dist/__tests__/helpers/mockRuntime.js +146 -0
  24. package/dist/__tests__/helpers/mockRuntime.js.map +1 -0
  25. package/dist/actionCatalog.d.ts.map +1 -1
  26. package/dist/actionCatalog.js +5 -0
  27. package/dist/actionCatalog.js.map +1 -1
  28. package/dist/autonomous.d.ts.map +1 -1
  29. package/dist/autonomous.js +122 -2
  30. package/dist/autonomous.js.map +1 -1
  31. package/package.json +5 -3
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=autonomous.actionDispatch.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autonomous.actionDispatch.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/autonomous.actionDispatch.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,570 @@
1
+ /**
2
+ * Action dispatch tests for AutonomousAgent.handleActionRequest.
3
+ *
4
+ * Tests that each action type calls the correct runtime manager method
5
+ * with the right arguments. Uses mock runtime + mock prepareSignRelay.
6
+ */
7
+ import { describe, it, expect, vi, beforeEach } from "vitest";
8
+ import { createMockRuntime } from "./helpers/mockRuntime.js";
9
+ import { AutonomousAgent } from "../autonomous.js";
10
+ // Mock prepareSignRelay at module level
11
+ vi.mock("../signing.js", () => ({
12
+ prepareSignRelay: vi.fn().mockResolvedValue({ txHash: "0xRELAY_TX" }),
13
+ signForwardRequest: vi.fn(),
14
+ }));
15
+ import { prepareSignRelay } from "../signing.js";
16
+ const mockPrepareSignRelay = vi.mocked(prepareSignRelay);
17
+ let runtime;
18
+ let callbacks;
19
+ let agent;
20
+ beforeEach(() => {
21
+ vi.clearAllMocks();
22
+ const mock = createMockRuntime();
23
+ runtime = mock.runtime;
24
+ callbacks = mock.callbacks;
25
+ agent = new AutonomousAgent(runtime, { verbose: false });
26
+ agent.start();
27
+ });
28
+ /** Helper: dispatch an action request and wait for processing */
29
+ async function dispatchAction(actionType, payload, suggestedContent, actionId) {
30
+ const event = { agentId: "agent_1", actionType, payload, suggestedContent, actionId };
31
+ callbacks.actionCb(event);
32
+ // Allow async handler to settle
33
+ await new Promise((r) => setTimeout(r, 10));
34
+ }
35
+ // ── On-chain via runtime managers ──────────────────────────────
36
+ describe("on-chain actions via runtime managers", () => {
37
+ it("create_post / publish calls memory.publishKnowledge", async () => {
38
+ await dispatchAction("create_post", { community: "general", title: "Test" }, "Post body");
39
+ expect(runtime.memory.publishKnowledge).toHaveBeenCalledWith(expect.objectContaining({ title: "Test", body: "Post body", community: "general" }));
40
+ });
41
+ it("publish is alias for create_post", async () => {
42
+ await dispatchAction("publish", { community: "sci" }, "My insight");
43
+ expect(runtime.memory.publishKnowledge).toHaveBeenCalled();
44
+ });
45
+ it("post_reply calls memory.publishComment", async () => {
46
+ await dispatchAction("post_reply", { parentCid: "Qm_parent", community: "general" }, "Nice post!");
47
+ expect(runtime.memory.publishComment).toHaveBeenCalledWith(expect.objectContaining({ parentCid: "Qm_parent", body: "Nice post!", community: "general" }));
48
+ });
49
+ it("vote calls memory.vote", async () => {
50
+ await dispatchAction("vote", { cid: "Qm_cid", voteType: "up" });
51
+ expect(runtime.memory.vote).toHaveBeenCalledWith(expect.objectContaining({ cid: "Qm_cid", type: "up" }));
52
+ });
53
+ it("follow_agent calls social.follow", async () => {
54
+ await dispatchAction("follow_agent", { targetAddress: "0xTARGET" });
55
+ expect(runtime.social.follow).toHaveBeenCalledWith("0xTARGET");
56
+ });
57
+ it("attest_agent calls social.attest", async () => {
58
+ await dispatchAction("attest_agent", { targetAddress: "0xTARGET" }, "Great work!");
59
+ expect(runtime.social.attest).toHaveBeenCalledWith("0xTARGET", "Great work!");
60
+ });
61
+ it("list_service calls marketplace.createListing", async () => {
62
+ await dispatchAction("list_service", { category: "dev" }, "Build APIs");
63
+ expect(runtime.marketplace.createListing).toHaveBeenCalledWith(expect.objectContaining({ title: "Build APIs", category: "dev" }));
64
+ });
65
+ it("create_agreement calls marketplace.createAgreement", async () => {
66
+ await dispatchAction("create_agreement", { listingId: 42 }, "Build me an API");
67
+ expect(runtime.marketplace.createAgreement).toHaveBeenCalledWith(expect.objectContaining({ listingId: 42, terms: "Build me an API" }));
68
+ });
69
+ it("deliver_work calls marketplace.deliver", async () => {
70
+ await dispatchAction("deliver_work", { agreementId: 5 }, "Qm_delivery_cid");
71
+ expect(runtime.marketplace.deliver).toHaveBeenCalledWith(5, "Qm_delivery_cid");
72
+ });
73
+ it("settle_agreement calls marketplace.settle", async () => {
74
+ await dispatchAction("settle_agreement", { agreementId: 5 });
75
+ expect(runtime.marketplace.settle).toHaveBeenCalledWith(5);
76
+ });
77
+ it("dispute_agreement calls marketplace.dispute", async () => {
78
+ await dispatchAction("dispute_agreement", { agreementId: 5 });
79
+ expect(runtime.marketplace.dispute).toHaveBeenCalledWith(5);
80
+ });
81
+ it("cancel_agreement calls marketplace.cancel", async () => {
82
+ await dispatchAction("cancel_agreement", { agreementId: 5 });
83
+ expect(runtime.marketplace.cancel).toHaveBeenCalledWith(5);
84
+ });
85
+ it("expire_dispute calls marketplace.expireDispute", async () => {
86
+ await dispatchAction("expire_dispute", { agreementId: 5 });
87
+ expect(runtime.marketplace.expireDispute).toHaveBeenCalledWith(5);
88
+ });
89
+ it("expire_delivered calls marketplace.expireDelivered", async () => {
90
+ await dispatchAction("expire_delivered", { agreementId: 5 });
91
+ expect(runtime.marketplace.expireDelivered).toHaveBeenCalledWith(5);
92
+ });
93
+ });
94
+ // ── On-chain via prepareSignRelay ────────────────────────────
95
+ describe("on-chain actions via prepareSignRelay", () => {
96
+ it("create_community calls prepareSignRelay with /v1/prepare/community", async () => {
97
+ await dispatchAction("create_community", { slug: "ai", name: "AI Agents" }, "An AI community");
98
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/community", expect.objectContaining({ slug: "ai", name: "AI Agents" }));
99
+ });
100
+ it("propose_guild calls prepareSignRelay with /v1/prepare/guild", async () => {
101
+ await dispatchAction("propose_guild", { name: "BuilderGuild", members: ["0xA", "0xB", "0xC"] }, "A builder guild");
102
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/guild", expect.objectContaining({ name: "BuilderGuild", members: ["0xA", "0xB", "0xC"] }));
103
+ });
104
+ it("propose_clique is alias for propose_guild", async () => {
105
+ await dispatchAction("propose_clique", { name: "Clique", members: ["0xA", "0xB"] }, "desc");
106
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/guild", expect.anything());
107
+ });
108
+ it("create_project does 2-step discover + prepare", async () => {
109
+ vi.mocked(runtime.connection.request).mockResolvedValueOnce({ discoveryId: "disc_1" });
110
+ await dispatchAction("create_project", { projectId: "proj_1", name: "My Project" }, "Project desc");
111
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/projects/discover", expect.anything());
112
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/project", expect.objectContaining({ discoveryId: "disc_1", projectId: "proj_1" }));
113
+ });
114
+ it("claim_bounty calls prepareSignRelay with /v1/prepare/bounty/:id/claim", async () => {
115
+ await dispatchAction("claim_bounty", { bountyId: "42" });
116
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/bounty/42/claim", {});
117
+ });
118
+ it("claim is alias for claim_bounty", async () => {
119
+ await dispatchAction("claim", { bountyId: "99" });
120
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/bounty/99/claim", {});
121
+ });
122
+ it("create_bounty calls prepareSignRelay with /v1/prepare/bounty", async () => {
123
+ await dispatchAction("create_bounty", { tokenRewardAmount: "100" }, "Fix the bug");
124
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/bounty", expect.objectContaining({ title: "Fix the bug", tokenRewardAmount: "100" }));
125
+ });
126
+ it("create_bundle calls prepareSignRelay with /v1/prepare/bundle", async () => {
127
+ await dispatchAction("create_bundle", { name: "Research Bundle" });
128
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/bundle", expect.objectContaining({ name: "Research Bundle" }));
129
+ });
130
+ it("approve_bounty_claimer calls prepareSignRelay with /v1/prepare/bounty/:id/approve-claimer", async () => {
131
+ await dispatchAction("approve_bounty_claimer", { bountyId: "10", claimer: "0xCLAIMER" });
132
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/bounty/10/approve-claimer", { claimer: "0xCLAIMER" });
133
+ });
134
+ it("approve_bounty_work calls prepareSignRelay with /v1/prepare/bounty/:id/approve", async () => {
135
+ await dispatchAction("approve_bounty_work", { bountyId: "10" });
136
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/bounty/10/approve", {});
137
+ });
138
+ it("dispute_bounty_work calls prepareSignRelay with /v1/prepare/bounty/:id/dispute", async () => {
139
+ await dispatchAction("dispute_bounty_work", { bountyId: "10" });
140
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/bounty/10/dispute", {});
141
+ });
142
+ it("cancel_bounty calls prepareSignRelay with /v1/prepare/bounty/:id/cancel", async () => {
143
+ await dispatchAction("cancel_bounty", { bountyId: "10" });
144
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/bounty/10/cancel", {});
145
+ });
146
+ it("unclaim_bounty calls prepareSignRelay with /v1/prepare/bounty/:id/unclaim", async () => {
147
+ await dispatchAction("unclaim_bounty", { bountyId: "10" });
148
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/bounty/10/unclaim", {});
149
+ });
150
+ it("deploy_preview calls prepareSignRelay with /v1/prepare/project/:id/deployment", async () => {
151
+ await dispatchAction("deploy_preview", { projectId: "proj_1" });
152
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/project/proj_1/deployment", expect.objectContaining({ prepaidHours: 2 }));
153
+ });
154
+ it("join_guild / approve_guild calls prepareSignRelay with /v1/prepare/guild/:id/approve", async () => {
155
+ await dispatchAction("join_guild", { guildId: 5 });
156
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/guild/5/approve", {});
157
+ });
158
+ it("reject_guild calls prepareSignRelay with /v1/prepare/guild/:id/reject", async () => {
159
+ await dispatchAction("reject_guild", { guildId: 5 });
160
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/guild/5/reject", {});
161
+ });
162
+ it("leave_guild calls prepareSignRelay with /v1/prepare/guild/:id/leave", async () => {
163
+ await dispatchAction("leave_guild", { guildId: 5 });
164
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/guild/5/leave", {});
165
+ });
166
+ it("update_service calls prepareSignRelay with /v1/prepare/service/update", async () => {
167
+ await dispatchAction("update_service", { listingId: "list_1", title: "Updated" });
168
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/service/update", expect.objectContaining({ listingId: "list_1" }));
169
+ });
170
+ it("create_listing calls prepareSignRelay with /v1/prepare/service/list", async () => {
171
+ await dispatchAction("create_listing", { title: "Service", category: "dev" });
172
+ expect(mockPrepareSignRelay).toHaveBeenCalledWith(runtime.connection, "/v1/prepare/service/list", expect.anything());
173
+ });
174
+ });
175
+ // ── Off-chain messaging ──────────────────────────────────────
176
+ describe("off-chain messaging actions", () => {
177
+ it("reply with channelId sends to channel", async () => {
178
+ await dispatchAction("reply", { channelId: "ch_1" }, "Hello channel!");
179
+ expect(runtime.channels.send).toHaveBeenCalledWith("ch_1", "Hello channel!");
180
+ });
181
+ it("reply with to sends DM", async () => {
182
+ await dispatchAction("reply", { to: "0xTARGET" }, "Hello DM!");
183
+ expect(runtime.inbox.send).toHaveBeenCalledWith(expect.objectContaining({ to: "0xTARGET", content: "Hello DM!" }));
184
+ });
185
+ it("send_dm calls inbox.send", async () => {
186
+ await dispatchAction("send_dm", { recipientAddress: "0xTARGET" }, "Hey!");
187
+ expect(runtime.inbox.send).toHaveBeenCalledWith(expect.objectContaining({ to: "0xTARGET", content: "Hey!" }));
188
+ });
189
+ it("send_message with to sends DM", async () => {
190
+ await dispatchAction("send_message", { to: "0xTARGET" }, "Collaboration time!");
191
+ expect(runtime.inbox.send).toHaveBeenCalled();
192
+ });
193
+ it("send_message with channelId sends to channel", async () => {
194
+ await dispatchAction("send_message", { channelId: "ch_2" }, "Hi team!");
195
+ expect(runtime.channels.send).toHaveBeenCalledWith("ch_2", "Hi team!");
196
+ });
197
+ it("acknowledge sends to project channel", async () => {
198
+ await dispatchAction("acknowledge", { projectId: "proj_1" });
199
+ expect(runtime.channels.sendToProject).toHaveBeenCalledWith("proj_1", expect.any(String));
200
+ });
201
+ it("accept sends to project channel", async () => {
202
+ await dispatchAction("accept", { projectId: "proj_1" });
203
+ expect(runtime.channels.sendToProject).toHaveBeenCalledWith("proj_1", expect.any(String));
204
+ });
205
+ it("execute with channelId sends to channel", async () => {
206
+ await dispatchAction("execute", { channelId: "ch_1" }, "Executing task...");
207
+ expect(runtime.channels.send).toHaveBeenCalledWith("ch_1", "Executing task...");
208
+ });
209
+ it("execute with to sends DM", async () => {
210
+ await dispatchAction("execute", { to: "0xTARGET" }, "Done!");
211
+ expect(runtime.inbox.send).toHaveBeenCalled();
212
+ });
213
+ it("propose_collab sends DM", async () => {
214
+ await dispatchAction("propose_collab", { targetAddress: "0xTARGET" }, "Let's work together!");
215
+ expect(runtime.inbox.send).toHaveBeenCalledWith(expect.objectContaining({ to: "0xTARGET", content: "Let's work together!" }));
216
+ });
217
+ });
218
+ // ── Off-chain social ─────────────────────────────────────────
219
+ describe("off-chain social actions", () => {
220
+ it("follow calls social.follow", async () => {
221
+ await dispatchAction("follow", { targetAddress: "0xTARGET" });
222
+ expect(runtime.social.follow).toHaveBeenCalledWith("0xTARGET");
223
+ });
224
+ it("follow_back calls social.follow", async () => {
225
+ await dispatchAction("follow_back", { senderAddress: "0xFOLLOWER" });
226
+ expect(runtime.social.follow).toHaveBeenCalledWith("0xFOLLOWER");
227
+ });
228
+ it("attest calls social.attest", async () => {
229
+ await dispatchAction("attest", { targetAddress: "0xTARGET" }, "Excellent contributor");
230
+ expect(runtime.social.attest).toHaveBeenCalledWith("0xTARGET", "Excellent contributor");
231
+ });
232
+ it("attest_back calls social.attest", async () => {
233
+ await dispatchAction("attest_back", { senderAddress: "0xATTESTER" });
234
+ expect(runtime.social.attest).toHaveBeenCalledWith("0xATTESTER", "Valued collaborator");
235
+ });
236
+ });
237
+ // ── Off-chain project actions ────────────────────────────────
238
+ describe("off-chain project actions", () => {
239
+ it("review calls projects.submitReview", async () => {
240
+ await dispatchAction("review", { projectId: "proj_1", commitId: "abc", verdict: "approve" }, "LGTM");
241
+ expect(runtime.projects.submitReview).toHaveBeenCalledWith("proj_1", "abc", "approve", "LGTM");
242
+ });
243
+ it("comment calls projects.submitReview with verdict=comment", async () => {
244
+ await dispatchAction("comment", { projectId: "proj_1", commitId: "abc" }, "Looks fine");
245
+ expect(runtime.projects.submitReview).toHaveBeenCalledWith("proj_1", "abc", "comment", "Looks fine");
246
+ });
247
+ it("request_ai_review calls projects.requestAIReview", async () => {
248
+ await dispatchAction("request_ai_review", { projectId: "proj_1", commitId: "abc" });
249
+ expect(runtime.projects.requestAIReview).toHaveBeenCalledWith("proj_1", "abc");
250
+ });
251
+ it("commit_files calls projects.commitFiles", async () => {
252
+ const files = [{ path: "src/main.ts", content: "console.log('hi')" }];
253
+ await dispatchAction("commit_files", { projectId: "proj_1", files }, "Initial commit");
254
+ expect(runtime.projects.commitFiles).toHaveBeenCalledWith("proj_1", files, "Initial commit");
255
+ });
256
+ it("gateway_commit is alias for commit_files", async () => {
257
+ const files = [{ path: "index.ts", content: "export {}" }];
258
+ await dispatchAction("gateway_commit", { projectId: "proj_1", files });
259
+ expect(runtime.projects.commitFiles).toHaveBeenCalled();
260
+ });
261
+ it("add_collaborator calls projects.addCollaborator", async () => {
262
+ await dispatchAction("add_collaborator", { projectId: "proj_1", collaboratorAddress: "0xCOLLAB", role: "editor" });
263
+ expect(runtime.projects.addCollaborator).toHaveBeenCalledWith("proj_1", "0xCOLLAB", "editor");
264
+ });
265
+ it("create_task calls projects.createTask", async () => {
266
+ await dispatchAction("create_task", { projectId: "proj_1" }, "Implement feature X");
267
+ expect(runtime.projects.createTask).toHaveBeenCalledWith("proj_1", expect.objectContaining({ title: "Implement feature X" }));
268
+ });
269
+ it("assign_task calls projects.assignTask", async () => {
270
+ await dispatchAction("assign_task", { projectId: "proj_1", taskId: "task_1", assigneeAddress: "0xWORKER" });
271
+ expect(runtime.projects.assignTask).toHaveBeenCalledWith("proj_1", "task_1", "0xWORKER");
272
+ });
273
+ it("complete_task calls projects.updateTask with status=completed", async () => {
274
+ await dispatchAction("complete_task", { projectId: "proj_1", taskId: "task_1" });
275
+ expect(runtime.projects.updateTask).toHaveBeenCalledWith("proj_1", "task_1", expect.objectContaining({ status: "completed" }));
276
+ });
277
+ it("update_task calls projects.updateTask with provided updates", async () => {
278
+ await dispatchAction("update_task", { projectId: "proj_1", taskId: "task_1", status: "in_progress", priority: "high" });
279
+ expect(runtime.projects.updateTask).toHaveBeenCalledWith("proj_1", "task_1", expect.objectContaining({ status: "in_progress", priority: "high" }));
280
+ });
281
+ it("link_project_to_guild performs 3-step linking", async () => {
282
+ vi.mocked(runtime.guilds.get).mockResolvedValueOnce({ members: [{ address: "0xMEMBER", status: 2 }] });
283
+ await dispatchAction("link_project_to_guild", { projectId: "proj_1", guildId: 5 });
284
+ expect(runtime.guilds.linkProject).toHaveBeenCalledWith(5, "proj_1");
285
+ expect(runtime.projects.setGuildAttribution).toHaveBeenCalledWith("proj_1", "5");
286
+ expect(runtime.projects.addCollaborator).toHaveBeenCalledWith("proj_1", "0xMEMBER", "editor");
287
+ });
288
+ });
289
+ // ── Off-chain HTTP actions ───────────────────────────────────
290
+ describe("off-chain HTTP actions", () => {
291
+ it("apply_bounty calls connection.request POST", async () => {
292
+ await dispatchAction("apply_bounty", { bountyId: "42" }, "I can do this!");
293
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/bounties/42/apply", expect.objectContaining({ message: "I can do this!" }));
294
+ });
295
+ it("submit_bounty_work calls connection.request POST", async () => {
296
+ await dispatchAction("submit_bounty_work", { bountyId: "42" }, "Here is my work");
297
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/bounties/42/submissions", expect.anything());
298
+ });
299
+ it("approve_bounty_application calls connection.request POST", async () => {
300
+ await dispatchAction("approve_bounty_application", { bountyId: "42", applicationId: "app_1" });
301
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/bounties/42/applications/app_1/approve", {});
302
+ });
303
+ it("reject_bounty_application calls connection.request POST", async () => {
304
+ await dispatchAction("reject_bounty_application", { bountyId: "42", applicationId: "app_1" });
305
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/bounties/42/applications/app_1/reject", {});
306
+ });
307
+ it("select_bounty_submission calls connection.request POST", async () => {
308
+ await dispatchAction("select_bounty_submission", { bountyId: "42", submissionId: "sub_1" });
309
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/bounties/42/submissions/sub_1/select", {});
310
+ });
311
+ it("accept_invitation calls connection.request POST", async () => {
312
+ await dispatchAction("accept_invitation", { invitationId: "inv_1" });
313
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/teams/invitations/inv_1/accept", {});
314
+ });
315
+ it("decline_invitation calls connection.request POST", async () => {
316
+ await dispatchAction("decline_invitation", { invitationId: "inv_1" });
317
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/teams/invitations/inv_1/decline", {});
318
+ });
319
+ it("grant calls connection.request POST with grant-access", async () => {
320
+ await dispatchAction("grant", { projectId: "proj_1", bountyId: "42", requestId: "req_1" });
321
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/projects/proj_1/bounties/42/grant-access", { requestId: "req_1" });
322
+ });
323
+ it("deny calls connection.request POST with deny-access", async () => {
324
+ await dispatchAction("deny", { projectId: "proj_1", bountyId: "42", requestId: "req_1" });
325
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/projects/proj_1/bounties/42/deny-access", { requestId: "req_1" });
326
+ });
327
+ });
328
+ // ── Real-world actions ───────────────────────────────────────
329
+ describe("real-world actions", () => {
330
+ it("egress_request calls tools.httpRequest", async () => {
331
+ await dispatchAction("egress_request", { url: "https://api.example.com/data", method: "GET" });
332
+ expect(runtime.tools.httpRequest).toHaveBeenCalledWith("https://api.example.com/data", "GET", expect.anything());
333
+ });
334
+ it("http_request is alias for egress_request", async () => {
335
+ await dispatchAction("http_request", { url: "https://example.com", method: "POST" });
336
+ expect(runtime.tools.httpRequest).toHaveBeenCalled();
337
+ });
338
+ it("execute_tool calls tools.executeTool", async () => {
339
+ await dispatchAction("execute_tool", { toolName: "my_tool", args: { key: "val" } });
340
+ expect(runtime.tools.executeTool).toHaveBeenCalledWith("my_tool", { key: "val" });
341
+ });
342
+ it("connect_mcp_server calls tools.connectMcpServer", async () => {
343
+ await dispatchAction("connect_mcp_server", { serverUrl: "https://mcp.example.com", serverName: "test" });
344
+ expect(runtime.tools.connectMcpServer).toHaveBeenCalledWith("https://mcp.example.com", "test");
345
+ });
346
+ it("disconnect_mcp_server calls tools.disconnectMcpServer", async () => {
347
+ await dispatchAction("disconnect_mcp_server", { serverId: "mcp_1" });
348
+ expect(runtime.tools.disconnectMcpServer).toHaveBeenCalledWith("mcp_1");
349
+ });
350
+ it("call_mcp_tool calls tools.executeTool", async () => {
351
+ await dispatchAction("call_mcp_tool", { toolName: "mcp_tool_1", args: { x: 1 } });
352
+ expect(runtime.tools.executeTool).toHaveBeenCalledWith("mcp_tool_1", { x: 1 });
353
+ });
354
+ it("register_webhook calls tools.registerWebhook", async () => {
355
+ await dispatchAction("register_webhook", { source: "github" });
356
+ expect(runtime.tools.registerWebhook).toHaveBeenCalledWith("github", expect.anything());
357
+ });
358
+ });
359
+ // ── Strategy / knowledge actions ─────────────────────────────
360
+ describe("strategy and knowledge actions", () => {
361
+ it("publish_insight calls insights.publish", async () => {
362
+ await dispatchAction("publish_insight", { title: "Insight", body: "Content" });
363
+ expect(runtime.insights.publish).toHaveBeenCalledWith(expect.objectContaining({ title: "Insight", body: "Content" }));
364
+ });
365
+ it("cite_insight calls insights.cite", async () => {
366
+ await dispatchAction("cite_insight", { insightId: "ins_1" });
367
+ expect(runtime.insights.cite).toHaveBeenCalledWith("ins_1", undefined, undefined);
368
+ });
369
+ it("apply_insight calls insights.apply", async () => {
370
+ await dispatchAction("apply_insight", { insightId: "ins_1" });
371
+ expect(runtime.insights.apply).toHaveBeenCalledWith("ins_1", undefined, undefined);
372
+ });
373
+ it("workspace_create calls workspaces.create", async () => {
374
+ await dispatchAction("workspace_create", { name: "My Workspace" });
375
+ expect(runtime.workspaces.create).toHaveBeenCalledWith(expect.objectContaining({ name: "My Workspace" }));
376
+ });
377
+ it("workspace_set calls workspaces.setState", async () => {
378
+ await dispatchAction("workspace_set", { workspaceId: "ws_1", key: "status", value: "active" });
379
+ expect(runtime.workspaces.setState).toHaveBeenCalledWith("ws_1", "status", "active");
380
+ });
381
+ it("workspace_snapshot calls workspaces.createSnapshot", async () => {
382
+ await dispatchAction("workspace_snapshot", { workspaceId: "ws_1" });
383
+ expect(runtime.workspaces.createSnapshot).toHaveBeenCalledWith("ws_1", undefined);
384
+ });
385
+ it("propose_action calls workspaces.createProposal", async () => {
386
+ await dispatchAction("propose_action", { workspaceId: "ws_1", title: "Upgrade deps" });
387
+ expect(runtime.workspaces.createProposal).toHaveBeenCalledWith("ws_1", expect.objectContaining({ title: "Upgrade deps" }));
388
+ });
389
+ it("vote_proposal calls workspaces.vote", async () => {
390
+ await dispatchAction("vote_proposal", { workspaceId: "ws_1", proposalId: "prop_1", vote: true });
391
+ expect(runtime.workspaces.vote).toHaveBeenCalledWith("ws_1", "prop_1", true, undefined);
392
+ });
393
+ it("cancel_proposal calls workspaces.cancelProposal", async () => {
394
+ await dispatchAction("cancel_proposal", { workspaceId: "ws_1", proposalId: "prop_1" });
395
+ expect(runtime.workspaces.cancelProposal).toHaveBeenCalledWith("ws_1", "prop_1");
396
+ });
397
+ });
398
+ // ── Treasury actions ─────────────────────────────────────────
399
+ describe("treasury actions", () => {
400
+ it("deposit_treasury calls guilds.depositTreasury", async () => {
401
+ await dispatchAction("deposit_treasury", { guildId: "5", amount: 100 });
402
+ expect(runtime.guilds.depositTreasury).toHaveBeenCalledWith("5", 100, undefined);
403
+ });
404
+ it("withdraw_treasury calls guilds.withdrawTreasury", async () => {
405
+ await dispatchAction("withdraw_treasury", { guildId: "5", amount: 50 });
406
+ expect(runtime.guilds.withdrawTreasury).toHaveBeenCalledWith("5", 50, undefined);
407
+ });
408
+ it("fund_bounty_from_treasury calls guilds.fundBountyFromTreasury", async () => {
409
+ await dispatchAction("fund_bounty_from_treasury", { guildId: "5", bountyId: "10", amount: 25 });
410
+ expect(runtime.guilds.fundBountyFromTreasury).toHaveBeenCalledWith("5", "10", 25, undefined);
411
+ });
412
+ it("distribute_revenue calls guilds.distributeRevenue", async () => {
413
+ await dispatchAction("distribute_revenue", { guildId: "5" });
414
+ expect(runtime.guilds.distributeRevenue).toHaveBeenCalledWith("5", undefined);
415
+ });
416
+ });
417
+ // ── Swarm actions ────────────────────────────────────────────
418
+ describe("swarm actions", () => {
419
+ it("create_swarm calls swarms.create", async () => {
420
+ await dispatchAction("create_swarm", { title: "Data Collection", subtasks: [{ title: "Collect A" }] });
421
+ expect(runtime.swarms.create).toHaveBeenCalledWith(expect.objectContaining({ title: "Data Collection" }));
422
+ });
423
+ it("claim_subtask calls swarms.claimSubtask", async () => {
424
+ await dispatchAction("claim_subtask", { subtaskId: "st_1" });
425
+ expect(runtime.swarms.claimSubtask).toHaveBeenCalledWith("st_1");
426
+ });
427
+ it("submit_swarm_result calls swarms.submitResult", async () => {
428
+ await dispatchAction("submit_swarm_result", { subtaskId: "st_1" });
429
+ expect(runtime.swarms.submitResult).toHaveBeenCalledWith("st_1", undefined, undefined);
430
+ });
431
+ it("aggregate_swarm calls swarms.aggregate", async () => {
432
+ await dispatchAction("aggregate_swarm", { swarmId: "swarm_1" });
433
+ expect(runtime.swarms.aggregate).toHaveBeenCalledWith("swarm_1", undefined);
434
+ });
435
+ });
436
+ // ── Specialization actions ───────────────────────────────────
437
+ describe("specialization actions", () => {
438
+ it("record_gap calls specialization.recordGap", async () => {
439
+ await dispatchAction("record_gap", { queryText: "How to deploy to k8s?" });
440
+ expect(runtime.specialization.recordGap).toHaveBeenCalledWith(expect.objectContaining({ queryText: "How to deploy to k8s?" }));
441
+ });
442
+ it("update_proficiency calls specialization.updateProficiency", async () => {
443
+ await dispatchAction("update_proficiency", { skillDomain: "typescript", proficiency: 85 });
444
+ expect(runtime.specialization.updateProficiency).toHaveBeenCalledWith("typescript", 85);
445
+ });
446
+ it("generate_recommendations calls specialization.generateRecommendations", async () => {
447
+ await dispatchAction("generate_recommendations", {});
448
+ expect(runtime.specialization.generateRecommendations).toHaveBeenCalled();
449
+ });
450
+ it("dismiss_recommendation calls specialization.dismissRecommendation", async () => {
451
+ await dispatchAction("dismiss_recommendation", { recommendationId: "rec_1" });
452
+ expect(runtime.specialization.dismissRecommendation).toHaveBeenCalledWith("rec_1");
453
+ });
454
+ });
455
+ // ── Intent actions ───────────────────────────────────────────
456
+ describe("intent actions", () => {
457
+ it("create_intent calls intents.create", async () => {
458
+ await dispatchAction("create_intent", { title: "Need a logo" });
459
+ expect(runtime.intents.create).toHaveBeenCalledWith(expect.objectContaining({ title: "Need a logo" }));
460
+ });
461
+ it("browse_intents calls intents.list", async () => {
462
+ await dispatchAction("browse_intents", { status: "open" });
463
+ expect(runtime.intents.list).toHaveBeenCalledWith(expect.objectContaining({ status: "open", limit: 20 }));
464
+ });
465
+ it("submit_proposal calls intents.submitProposal", async () => {
466
+ await dispatchAction("submit_proposal", { intentId: "intent_1" }, "I can help");
467
+ expect(runtime.intents.submitProposal).toHaveBeenCalledWith("intent_1", expect.objectContaining({ description: "I can help" }));
468
+ });
469
+ it("accept_proposal calls intents.acceptProposal", async () => {
470
+ await dispatchAction("accept_proposal", { intentId: "intent_1", proposalId: "prop_1" });
471
+ expect(runtime.intents.acceptProposal).toHaveBeenCalledWith("intent_1", "prop_1");
472
+ });
473
+ it("cancel_intent calls intents.cancel", async () => {
474
+ await dispatchAction("cancel_intent", { intentId: "intent_1" });
475
+ expect(runtime.intents.cancel).toHaveBeenCalledWith("intent_1");
476
+ });
477
+ it("complete_intent calls intents.complete", async () => {
478
+ await dispatchAction("complete_intent", { intentId: "intent_1" });
479
+ expect(runtime.intents.complete).toHaveBeenCalledWith("intent_1");
480
+ });
481
+ it("withdraw_proposal calls intents.withdrawProposal", async () => {
482
+ await dispatchAction("withdraw_proposal", { intentId: "intent_1", proposalId: "prop_1" });
483
+ expect(runtime.intents.withdrawProposal).toHaveBeenCalledWith("intent_1", "prop_1");
484
+ });
485
+ });
486
+ // ── Token launch actions ─────────────────────────────────────
487
+ describe("token launch actions", () => {
488
+ it("preview_token_launch calls connection.request POST", async () => {
489
+ await dispatchAction("preview_token_launch", { tokenName: "MyCoin", tokenTicker: "MYC" });
490
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/clawnch/preview", expect.objectContaining({ tokenName: "MyCoin", tokenTicker: "MYC" }));
491
+ });
492
+ it("launch_token calls connection.request POST", async () => {
493
+ await dispatchAction("launch_token", { tokenName: "MyCoin", tokenTicker: "MYC" });
494
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/clawnch/launch", expect.objectContaining({ tokenName: "MyCoin", tokenTicker: "MYC" }));
495
+ });
496
+ it("claim_clawnch_fees calls connection.request POST", async () => {
497
+ await dispatchAction("claim_clawnch_fees", { tokenAddress: "0xTOKEN" });
498
+ expect(runtime.connection.request).toHaveBeenCalledWith("POST", "/v1/clawnch/claim-fees", { tokenAddress: "0xTOKEN" });
499
+ });
500
+ it("get_token_analytics calls connection.request GET", async () => {
501
+ await dispatchAction("get_token_analytics", { tokenAddress: "0xTOKEN" });
502
+ expect(runtime.connection.request).toHaveBeenCalledWith("GET", "/v1/clawnch/analytics/token/0xTOKEN");
503
+ });
504
+ });
505
+ // ── Oracle actions ───────────────────────────────────────────
506
+ describe("oracle actions", () => {
507
+ it("query_oracle project calls oracle.getProjectSignals", async () => {
508
+ await dispatchAction("query_oracle", { entityType: "project", entityId: "proj_1" });
509
+ expect(runtime.oracle.getProjectSignals).toHaveBeenCalledWith("proj_1");
510
+ });
511
+ it("query_oracle agent calls oracle.getAgentSignals", async () => {
512
+ await dispatchAction("query_oracle", { entityType: "agent", entityId: "0xAGENT" });
513
+ expect(runtime.oracle.getAgentSignals).toHaveBeenCalledWith("0xAGENT");
514
+ });
515
+ it("query_oracle intent calls oracle.getIntentSignals", async () => {
516
+ await dispatchAction("query_oracle", { entityType: "intent", entityId: "intent_1" });
517
+ expect(runtime.oracle.getIntentSignals).toHaveBeenCalledWith("intent_1");
518
+ });
519
+ it("query_oracle guild calls oracle.getGuildSignals", async () => {
520
+ await dispatchAction("query_oracle", { entityType: "guild", entityId: "guild_1" });
521
+ expect(runtime.oracle.getGuildSignals).toHaveBeenCalledWith("guild_1");
522
+ });
523
+ });
524
+ // ── Marketplace review + messages ────────────────────────────
525
+ describe("marketplace review and messages", () => {
526
+ it("submit_review calls marketplace.submitReview", async () => {
527
+ await dispatchAction("submit_review", { agreementId: 5, rating: 4 }, "Good work!");
528
+ expect(runtime.marketplace.submitReview).toHaveBeenCalledWith(5, 4, "Good work!");
529
+ });
530
+ it("send_agreement_message calls marketplace.sendAgreementMessage", async () => {
531
+ await dispatchAction("send_agreement_message", { agreementId: 5, messageType: "revision_request" }, "Please fix X");
532
+ expect(runtime.marketplace.sendAgreementMessage).toHaveBeenCalledWith(5, "revision_request", "Please fix X", undefined);
533
+ });
534
+ });
535
+ // ── Matching actions ─────────────────────────────────────────
536
+ describe("matching actions", () => {
537
+ it("find_agents calls matching.findAgents", async () => {
538
+ await dispatchAction("find_agents", { skills: ["typescript", "react"] });
539
+ expect(runtime.matching.findAgents).toHaveBeenCalledWith(["typescript", "react"], expect.anything());
540
+ });
541
+ it("assemble_team calls matching.assembleTeam", async () => {
542
+ await dispatchAction("assemble_team", {}, "Build a web3 dashboard");
543
+ expect(runtime.matching.assembleTeam).toHaveBeenCalledWith(expect.objectContaining({ description: "Build a web3 dashboard" }));
544
+ });
545
+ });
546
+ // ── Error cases and lifecycle ────────────────────────────────
547
+ describe("error cases and action lifecycle", () => {
548
+ it("unknown action rejects delegated action", async () => {
549
+ await dispatchAction("totally_unknown_action", {}, undefined, "action_42");
550
+ expect(runtime.proactive.rejectDelegatedAction).toHaveBeenCalledWith("action_42", expect.stringContaining("Unknown"));
551
+ });
552
+ it("actionId triggers proactive.completeAction on success", async () => {
553
+ await dispatchAction("follow", { targetAddress: "0xTARGET" }, undefined, "action_99");
554
+ expect(runtime.proactive.completeAction).toHaveBeenCalledWith("action_99", "0xMOCK_TX", expect.anything());
555
+ });
556
+ it("missing required field throws and rejects delegated action", async () => {
557
+ await dispatchAction("send_dm", {}, undefined, "action_fail");
558
+ expect(runtime.proactive.rejectDelegatedAction).toHaveBeenCalledWith("action_fail", expect.stringContaining("requires"));
559
+ });
560
+ it("custom onAction handler bypasses default dispatch", async () => {
561
+ const customHandler = vi.fn().mockResolvedValue(undefined);
562
+ const customAgent = new AutonomousAgent(runtime, { onAction: customHandler, verbose: false });
563
+ customAgent.start();
564
+ callbacks.actionCb({ agentId: "a1", actionType: "follow", payload: { targetAddress: "0x1" } });
565
+ await new Promise((r) => setTimeout(r, 10));
566
+ expect(customHandler).toHaveBeenCalled();
567
+ expect(runtime.social.follow).not.toHaveBeenCalled();
568
+ });
569
+ });
570
+ //# sourceMappingURL=autonomous.actionDispatch.test.js.map