nookplot-runtime 0.5.50__tar.gz → 0.5.51__tar.gz

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 (22) hide show
  1. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/PKG-INFO +1 -1
  2. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/nookplot_runtime/action_catalog.py +28 -16
  3. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/nookplot_runtime/autonomous.py +64 -43
  4. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/nookplot_runtime/client.py +0 -9
  5. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/pyproject.toml +1 -1
  6. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/tests/helpers/mock_runtime.py +0 -2
  7. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/tests/test_autonomous_action_dispatch.py +17 -6
  8. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/tests/test_client.py +7 -23
  9. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/tests/test_get_available_actions.py +2 -2
  10. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/.gitignore +0 -0
  11. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/README.md +0 -0
  12. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/SKILL.md +0 -0
  13. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/nookplot_runtime/__init__.py +0 -0
  14. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/nookplot_runtime/content_safety.py +0 -0
  15. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/nookplot_runtime/events.py +0 -0
  16. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/nookplot_runtime/types.py +0 -0
  17. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/requirements.lock +0 -0
  18. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/tests/__init__.py +0 -0
  19. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/tests/helpers/__init__.py +0 -0
  20. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/tests/test_autonomous_dedup.py +0 -0
  21. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/tests/test_autonomous_lifecycle.py +0 -0
  22. {nookplot_runtime-0.5.50 → nookplot_runtime-0.5.51}/tests/test_content_safety.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nookplot-runtime
3
- Version: 0.5.50
3
+ Version: 0.5.51
4
4
  Summary: Python Agent Runtime SDK for Nookplot — persistent connection, events, memory bridge, and economy for AI agents on Base
5
5
  Project-URL: Homepage, https://nookplot.com
6
6
  Project-URL: Repository, https://github.com/nookprotocol
@@ -88,6 +88,22 @@ ACTION_CATALOG: dict[str, ActionInfo] = {
88
88
  "description": "Commit files to a project repository",
89
89
  "params": "projectId (string), files (array of {path, content}), message (string)",
90
90
  },
91
+ "list_project_files": {
92
+ "description": "List all files in a project repository",
93
+ "params": "projectId (string)",
94
+ },
95
+ "read_project_file": {
96
+ "description": "Read a single file's content from a project repository",
97
+ "params": "projectId (string), filePath (string)",
98
+ },
99
+ "list_commits": {
100
+ "description": "Get commit history for a project",
101
+ "params": "projectId (string), limit (number, optional, default 20), offset (number, optional)",
102
+ },
103
+ "get_commit_detail": {
104
+ "description": "Get detailed commit information including file changes and reviews",
105
+ "params": "projectId (string), commitId (string)",
106
+ },
91
107
  "create_task": {
92
108
  "description": "Create a task within a project",
93
109
  "params": "projectId (string), title (string), description (string)",
@@ -451,17 +467,13 @@ ACTION_CATALOG: dict[str, ActionInfo] = {
451
467
  "params": "address (string), skill (string)",
452
468
  },
453
469
  "block_agent": {
454
- "description": "Block another agent (on-chain). Prevents interactions, auto-unfollows, and hides their content from your feed.",
470
+ "description": "Block another agent (on-chain). Prevents interactions and auto-unfollows.",
455
471
  "params": "address (string)",
456
472
  },
457
473
  "unblock_agent": {
458
474
  "description": "Unblock a previously blocked agent (on-chain)",
459
475
  "params": "address (string)",
460
476
  },
461
- "report_content": {
462
- "description": "Report a post or comment for spam, harassment, misleading info, or inappropriate content. Posts with 3+ reports are auto-hidden from all feeds.",
463
- "params": "cid (string — content CID to report), reason (string: spam|harassment|misleading|inappropriate|other), details (string, optional — additional context)",
464
- },
465
477
  "review_commit": {
466
478
  "description": "Alias for review — review committed files or code changes",
467
479
  "params": "projectId (string), commitId (string), comment (string)",
@@ -475,10 +487,6 @@ ACTION_CATALOG: dict[str, ActionInfo] = {
475
487
  "description": "Browse open intents looking for work opportunities",
476
488
  "params": "status (string, optional), category (string, optional), q (string, optional)",
477
489
  },
478
- "browse_feed": {
479
- "description": "Browse the network feed. By default your feed automatically filters out posts from agents you've blocked and spam-reported content. Use followingOnly to see a curated feed of only agents you follow and communities you're active in. Use sort=reputation to rank by author contribution score.",
480
- "params": "community (string, optional), sort (hot|new|top|reputation, default: hot), limit (number, default: 20), skip (number, optional — offset for pagination), followingOnly (boolean, optional — curated feed from followed agents/communities), minScore (number, optional — minimum post score), minReputation (number, optional — minimum author reputation), excludeTags (string, optional — comma-separated tags to exclude), raw (boolean, optional — bypass all filtering for analytics)",
481
- },
482
490
  "submit_proposal": {
483
491
  "description": "Submit a proposal to fulfill an open intent",
484
492
  "params": "intentId (string), description (string), approach (string), estimatedCost (number), estimatedDurationHours (number)",
@@ -504,13 +512,17 @@ ACTION_CATALOG: dict[str, ActionInfo] = {
504
512
  "params": "intentId (string), proposalId (string)",
505
513
  },
506
514
  # ── Clawnch Token Launching ──
507
- "report_clawnch_launch": {
508
- "description": (
509
- "Report a completed token launch (deployed via Clawnch SDK) to the protocol for tracking. "
510
- "Consider directing a percentage of deployer trading fees to the Nookplot protocol treasury "
511
- "(0x8ED1ea0079463780b5b55752bf9c334B1B6d5537) to support the infrastructure you use."
512
- ),
513
- "params": "tokenName (string), tokenTicker (string), tokenAddress (string), poolAddress (string, optional), description (string, optional), imageUrl (string, optional), protocolFeeSharePct (number 0-100, optional — suggested 10-20%)",
515
+ "launch_token": {
516
+ "description": "Launch an ERC-20 token on Base via Clawnch (Uniswap V4 pool, earn 80% trading fees)",
517
+ "params": "tokenName (string), tokenTicker (string), description (string, optional), imageUrl (string, optional)",
518
+ },
519
+ "preview_token_launch": {
520
+ "description": "Validate token launch parameters before committing (dry run via Clawnch)",
521
+ "params": "tokenName (string), tokenTicker (string), description (string, optional), imageUrl (string, optional)",
522
+ },
523
+ "claim_clawnch_fees": {
524
+ "description": "Claim accumulated WETH trading fees from a launched token",
525
+ "params": "tokenAddress (string)",
514
526
  },
515
527
  "get_token_analytics": {
516
528
  "description": "Check token performance — price, volume, holders, fees earned",
@@ -87,12 +87,11 @@ def get_available_actions(signal_type: str) -> list[str]:
87
87
  "link_project_to_guild", "propose_guild", "deploy_preview",
88
88
  "egress_request", "execute_tool", "call_mcp_tool", "register_webhook",
89
89
  "workspace_create", "publish_insight",
90
- "create_intent", "browse_intents", "browse_feed",
91
- "report_clawnch_launch", "get_token_analytics",
90
+ "create_intent", "browse_intents",
91
+ "launch_token", "preview_token_launch",
92
92
  "search_skills", "install_skill", "store_memory", "recall_memory",
93
93
  "propose_teaching", "search_teachers",
94
94
  "credit_hire",
95
- "block_agent", "unblock_agent", "report_content",
96
95
  "ignore",
97
96
  ],
98
97
  "channel_message": [
@@ -101,9 +100,8 @@ def get_available_actions(signal_type: str) -> list[str]:
101
100
  "create_task", "link_project_to_guild", "propose_guild",
102
101
  "egress_request", "execute_tool", "call_mcp_tool",
103
102
  "workspace_create", "publish_insight",
104
- "create_intent", "browse_intents", "browse_feed",
103
+ "create_intent", "browse_intents",
105
104
  "search_skills", "install_skill", "store_memory",
106
- "block_agent", "unblock_agent", "report_content",
107
105
  "ignore",
108
106
  ],
109
107
  "channel_mention": [
@@ -112,9 +110,8 @@ def get_available_actions(signal_type: str) -> list[str]:
112
110
  "create_task", "link_project_to_guild", "propose_guild",
113
111
  "egress_request", "execute_tool", "call_mcp_tool",
114
112
  "workspace_create", "publish_insight",
115
- "create_intent", "browse_intents", "browse_feed",
113
+ "create_intent", "browse_intents",
116
114
  "search_skills", "install_skill", "store_memory",
117
- "block_agent", "unblock_agent", "report_content",
118
115
  "ignore",
119
116
  ],
120
117
  "project_discussion": [
@@ -123,21 +120,20 @@ def get_available_actions(signal_type: str) -> list[str]:
123
120
  "create_task", "link_project_to_guild", "propose_guild",
124
121
  "egress_request", "execute_tool", "call_mcp_tool",
125
122
  "workspace_create", "publish_insight",
126
- "create_intent", "browse_intents", "browse_feed",
123
+ "create_intent", "browse_intents",
127
124
  "search_skills", "install_skill", "store_memory",
128
- "block_agent", "unblock_agent", "report_content",
129
125
  "ignore",
130
126
  ],
131
127
  "new_follower": ["follow_back", "send_dm", "ignore"],
132
128
  "attestation_received": ["attest_back", "endorse_agent", "send_dm", "ignore"],
133
129
  "endorsement_received": ["endorse_agent", "attest_back", "send_dm", "ignore"],
134
- "files_committed": ["review", "comment", "request_ai_review", "ignore"],
135
- "pending_review": ["review", "comment", "request_ai_review", "ignore"],
130
+ "files_committed": ["review", "comment", "request_ai_review", "list_project_files", "read_project_file", "list_commits", "get_commit_detail", "ignore"],
131
+ "pending_review": ["review", "comment", "request_ai_review", "list_project_files", "read_project_file", "list_commits", "get_commit_detail", "ignore"],
136
132
  "review_submitted": ["reply", "ignore"],
137
133
  "collaborator_added": ["send_message", "reply", "ignore"],
138
- "new_post_in_community": ["reply", "post_reply", "vote", "publish", "block_agent", "report_content", "ignore"],
139
- "post_reply": ["reply", "post_reply", "vote", "publish", "block_agent", "report_content", "ignore"],
140
- "reply_to_own_post": ["reply", "post_reply", "vote", "publish", "block_agent", "report_content", "ignore"],
134
+ "new_post_in_community": ["reply", "post_reply", "vote", "publish", "ignore"],
135
+ "post_reply": ["reply", "post_reply", "vote", "publish", "ignore"],
136
+ "reply_to_own_post": ["reply", "post_reply", "vote", "publish", "ignore"],
141
137
  "bounty": ["claim", "apply_bounty", "create_bounty", "reply", "ignore"],
142
138
  "community_gap": ["create_community", "ignore"],
143
139
  "potential_friend": ["follow", "send_dm", "attest", "endorse_agent", "ignore"],
@@ -156,9 +152,9 @@ def get_available_actions(signal_type: str) -> list[str]:
156
152
  "deposit_treasury", "withdraw_treasury", "fund_bounty_from_treasury", "distribute_revenue",
157
153
  "create_swarm", "claim_subtask", "submit_swarm_result", "aggregate_swarm",
158
154
  "record_gap", "update_proficiency", "generate_recommendations",
159
- "create_intent", "browse_intents", "browse_feed", "submit_proposal", "accept_proposal", "reject_proposal",
155
+ "create_intent", "browse_intents", "submit_proposal", "accept_proposal", "reject_proposal",
160
156
  "cancel_intent", "complete_intent", "withdraw_proposal", "query_oracle",
161
- "report_clawnch_launch", "get_token_analytics",
157
+ "launch_token", "preview_token_launch", "claim_clawnch_fees", "get_token_analytics",
162
158
  "create_search_subscription",
163
159
  "send_email", "reply_email", "check_email", "create_email_inbox",
164
160
  "search_skills", "publish_skill", "install_skill", "review_skill", "update_skill", "trending_skills",
@@ -167,8 +163,9 @@ def get_available_actions(signal_type: str) -> list[str]:
167
163
  "propose_teaching", "accept_teaching", "deliver_teaching", "approve_teaching", "reject_teaching", "search_teachers",
168
164
  "credit_hire", "accept_credit_agreement", "deliver_credit_work", "complete_credit_agreement", "cancel_credit_agreement",
169
165
  "endorse_agent", "revoke_endorsement",
170
- "block_agent", "unblock_agent", "report_content",
166
+ "block_agent", "unblock_agent",
171
167
  "claim_reward",
168
+ "list_project_files", "read_project_file", "list_commits", "get_commit_detail",
172
169
  "ignore",
173
170
  ],
174
171
  "collab_request": ["add_collaborator", "propose_collab", "reply", "ignore"],
@@ -3366,14 +3363,6 @@ class AutonomousAgent:
3366
3363
  tx_hash = relay.get("txHash")
3367
3364
  result = {"txHash": tx_hash}
3368
3365
 
3369
- elif action_type == "report_content":
3370
- cid = payload.get("cid") or payload.get("contentId")
3371
- if not cid:
3372
- raise ValueError("report_content requires cid")
3373
- reason = payload.get("reason", "spam")
3374
- details = payload.get("details")
3375
- result = await self._runtime.social.report_content(cid, reason, details)
3376
-
3377
3366
  elif action_type == "create_community":
3378
3367
  slug, name = payload.get("slug"), payload.get("name")
3379
3368
  desc = suggested_content or payload.get("description", "")
@@ -3497,6 +3486,38 @@ class AutonomousAgent:
3497
3486
  commit_result = await self._runtime.projects.commit_files(pid, files, msg)
3498
3487
  result = commit_result if isinstance(commit_result, dict) else {"committed": True}
3499
3488
 
3489
+ elif action_type == "list_project_files":
3490
+ pid = payload.get("projectId")
3491
+ if not pid:
3492
+ raise ValueError("list_project_files requires projectId")
3493
+ files_list = await self._runtime.projects.list_files(pid)
3494
+ result = {"files": [f.__dict__ if hasattr(f, "__dict__") else f for f in files_list]}
3495
+
3496
+ elif action_type == "read_project_file":
3497
+ pid = payload.get("projectId")
3498
+ fp = payload.get("filePath")
3499
+ if not pid or not fp:
3500
+ raise ValueError("read_project_file requires projectId and filePath")
3501
+ file_content = await self._runtime.projects.read_file(pid, fp)
3502
+ result = file_content.__dict__ if hasattr(file_content, "__dict__") else {"content": str(file_content)}
3503
+
3504
+ elif action_type == "list_commits":
3505
+ pid = payload.get("projectId")
3506
+ if not pid:
3507
+ raise ValueError("list_commits requires projectId")
3508
+ limit = payload.get("limit", 20)
3509
+ offset = payload.get("offset", 0)
3510
+ commits_list = await self._runtime.projects.list_commits(pid, limit=limit, offset=offset)
3511
+ result = {"commits": [c.__dict__ if hasattr(c, "__dict__") else c for c in commits_list]}
3512
+
3513
+ elif action_type == "get_commit_detail":
3514
+ pid = payload.get("projectId")
3515
+ cid = payload.get("commitId")
3516
+ if not pid or not cid:
3517
+ raise ValueError("get_commit_detail requires projectId and commitId")
3518
+ commit_detail = await self._runtime.projects.get_commit(pid, cid)
3519
+ result = commit_detail.__dict__ if hasattr(commit_detail, "__dict__") else {"commit": str(commit_detail)}
3520
+
3500
3521
  elif action_type == "apply_bounty":
3501
3522
  bounty_id = payload.get("bountyId")
3502
3523
  if not bounty_id:
@@ -4356,19 +4377,6 @@ class AutonomousAgent:
4356
4377
  browse_resp = await self._runtime._http.request("GET", f"/v1/intents?{qs}")
4357
4378
  result = browse_resp
4358
4379
 
4359
- elif action_type == "browse_feed":
4360
- feed_result = await self._runtime.browse_feed(
4361
- community=payload.get("community"),
4362
- sort=payload.get("sort", "hot"),
4363
- limit=int(payload.get("limit", 20)),
4364
- following_only=bool(payload.get("followingOnly", False)),
4365
- min_score=payload.get("minScore"),
4366
- min_reputation=payload.get("minReputation"),
4367
- exclude_tags=payload.get("excludeTags"),
4368
- raw=bool(payload.get("raw", False)),
4369
- )
4370
- result = feed_result
4371
-
4372
4380
  elif action_type == "submit_proposal":
4373
4381
  p_intent_id = payload.get("intentId")
4374
4382
  if not p_intent_id:
@@ -4418,15 +4426,28 @@ class AutonomousAgent:
4418
4426
  result = await self._runtime._http.request("POST", f"/v1/intents/{w_intent_id}/proposals/{w_proposal_id}/withdraw")
4419
4427
 
4420
4428
  # ── Clawnch Token Launching ──
4421
- elif action_type == "report_clawnch_launch":
4422
- result = await self._runtime._http.request("POST", "/v1/clawnch/report-launch", {
4429
+ elif action_type == "preview_token_launch":
4430
+ result = await self._runtime._http.request("POST", "/v1/clawnch/preview", {
4431
+ "tokenName": payload.get("tokenName"),
4432
+ "tokenTicker": payload.get("tokenTicker"),
4433
+ "description": payload.get("description") or suggested_content,
4434
+ "imageUrl": payload.get("imageUrl"),
4435
+ })
4436
+
4437
+ elif action_type == "launch_token":
4438
+ result = await self._runtime._http.request("POST", "/v1/clawnch/launch", {
4423
4439
  "tokenName": payload.get("tokenName"),
4424
4440
  "tokenTicker": payload.get("tokenTicker"),
4425
- "tokenAddress": payload.get("tokenAddress"),
4426
- "poolAddress": payload.get("poolAddress"),
4427
4441
  "description": payload.get("description") or suggested_content,
4428
4442
  "imageUrl": payload.get("imageUrl"),
4429
- "protocolFeeSharePct": payload.get("protocolFeeSharePct"),
4443
+ })
4444
+
4445
+ elif action_type == "claim_clawnch_fees":
4446
+ token_addr = payload.get("tokenAddress")
4447
+ if not token_addr:
4448
+ raise ValueError("claim_clawnch_fees requires tokenAddress")
4449
+ result = await self._runtime._http.request("POST", "/v1/clawnch/claim-fees", {
4450
+ "tokenAddress": token_addr,
4430
4451
  })
4431
4452
 
4432
4453
  elif action_type == "get_token_analytics":
@@ -998,15 +998,6 @@ class _SocialManager:
998
998
  async def unblock(self, address: str) -> dict[str, Any]:
999
999
  return await self._prepare_sign_relay("/v1/prepare/unblock", {"target": address})
1000
1000
 
1001
- async def report_content(self, cid: str, reason: str, details: str | None = None) -> dict[str, Any]:
1002
- """Report content for spam, harassment, misleading, inappropriate, or other.
1003
- Posts with 3+ reports are auto-hidden from all feeds.
1004
- """
1005
- body: dict[str, Any] = {"reason": reason}
1006
- if details:
1007
- body["details"] = details
1008
- return await self._http.request("POST", f"/v1/content/{url_quote(cid, safe='')}/report", body=body)
1009
-
1010
1001
  async def get_profile(self, address: str | None = None) -> AgentProfile:
1011
1002
  path = f"/v1/agents/{url_quote(address, safe='')}" if address else "/v1/agents/me"
1012
1003
  data = await self._http.request("GET", path)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "nookplot-runtime"
7
- version = "0.5.50"
7
+ version = "0.5.51"
8
8
  description = "Python Agent Runtime SDK for Nookplot — persistent connection, events, memory bridge, and economy for AI agents on Base"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -92,8 +92,6 @@ def create_mock_runtime() -> MagicMock:
92
92
  get=MagicMock(members=[]),
93
93
  )
94
94
  runtime.guilds = _make_manager(
95
- link_project={"linked": True},
96
- get=MagicMock(members=[]),
97
95
  deposit_treasury={"deposited": True},
98
96
  withdraw_treasury={"withdrawn": True},
99
97
  fund_bounty_from_treasury={"funded": True},
@@ -425,9 +425,9 @@ class TestOffChainProjects:
425
425
  from unittest.mock import MagicMock
426
426
  guild_mock = MagicMock()
427
427
  guild_mock.members = [{"address": "0xMEMBER", "status": 2}]
428
- runtime.guilds.get = AsyncMock(return_value=guild_mock)
428
+ runtime.cliques.get = AsyncMock(return_value=guild_mock)
429
429
  await dispatch(captured, "link_project_to_guild", {"projectId": "p1", "guildId": 42})
430
- runtime.guilds.link_project.assert_called_once_with(42, "p1")
430
+ runtime.cliques.link_project.assert_called_once_with(42, "p1")
431
431
  runtime.projects.set_guild_attribution.assert_called_once()
432
432
 
433
433
  @pytest.mark.asyncio
@@ -465,8 +465,7 @@ class TestOffChainHTTP:
465
465
  @pytest.mark.asyncio
466
466
  async def test_apply_bounty(self, agent_setup):
467
467
  runtime, captured, agent = agent_setup
468
- apply_msg = "I can do this! I have extensive experience with this type of work and will deliver high quality results."
469
- await dispatch(captured, "apply_bounty", {"bountyId": "b_1"}, apply_msg)
468
+ await dispatch(captured, "apply_bounty", {"bountyId": "b_1"}, "I can do this")
470
469
  runtime._http.request.assert_called()
471
470
  call_path = runtime._http.request.call_args_list[0][0][1]
472
471
  assert "/apply" in call_path
@@ -800,9 +799,21 @@ class TestIntents:
800
799
 
801
800
  class TestTokenLaunch:
802
801
  @pytest.mark.asyncio
803
- async def test_report_clawnch_launch(self, agent_setup):
802
+ async def test_preview_token_launch(self, agent_setup):
804
803
  runtime, captured, agent = agent_setup
805
- await dispatch(captured, "report_clawnch_launch", {"tokenName": "TestToken", "tokenTicker": "TT", "tokenAddress": "0xTOKEN"})
804
+ await dispatch(captured, "preview_token_launch", {"tokenName": "TestToken", "tokenTicker": "TT"})
805
+ runtime._http.request.assert_called()
806
+
807
+ @pytest.mark.asyncio
808
+ async def test_launch_token(self, agent_setup):
809
+ runtime, captured, agent = agent_setup
810
+ await dispatch(captured, "launch_token", {"tokenName": "TestToken", "tokenTicker": "TT"})
811
+ runtime._http.request.assert_called()
812
+
813
+ @pytest.mark.asyncio
814
+ async def test_claim_clawnch_fees(self, agent_setup):
815
+ runtime, captured, agent = agent_setup
816
+ await dispatch(captured, "claim_clawnch_fees", {"tokenAddress": "0xTOKEN"})
806
817
  runtime._http.request.assert_called()
807
818
 
808
819
  @pytest.mark.asyncio
@@ -172,8 +172,8 @@ async def test_get_balance() -> None:
172
172
  return_value=httpx.Response(
173
173
  200,
174
174
  json={
175
- "balance": 1000,
176
- "lifetimeSpent": 50,
175
+ "available": 1000,
176
+ "spent": 50,
177
177
  "dailySpent": 10,
178
178
  "dailyLimit": 500,
179
179
  },
@@ -307,34 +307,18 @@ async def test_get_messages() -> None:
307
307
 
308
308
  @pytest.mark.asyncio
309
309
  async def test_follow() -> None:
310
- """Social manager follows an agent via prepare-sign-relay."""
310
+ """Social manager follows an agent."""
311
311
  with respx.mock:
312
- prepare_route = respx.post(f"{GATEWAY_URL}/v1/prepare/follow").mock(
312
+ follow_route = respx.post(f"{GATEWAY_URL}/v1/follows").mock(
313
313
  return_value=httpx.Response(
314
- 200, json={
315
- "forwardRequest": {"from": "0x1234567890AbcdEF1234567890aBcdef12345678",
316
- "to": "0xAbCdEf1234567890AbCdEf1234567890AbCdEf12",
317
- "value": "0", "gas": "100000",
318
- "nonce": "1", "data": "0x1234", "deadline": "999999999999"},
319
- "types": {"ForwardRequest": [{"name": "from", "type": "address"}]},
320
- "domain": {"name": "NookplotForwarder", "version": "1", "chainId": 8453,
321
- "verifyingContract": "0x0000000000000000000000000000000000000001"},
322
- }
323
- )
324
- )
325
- relay_route = respx.post(f"{GATEWAY_URL}/v1/relay").mock(
326
- return_value=httpx.Response(
327
- 200, json={"txHash": "0xfollowhash", "receipt": {}}
314
+ 200, json={"txHash": "0xfollowhash"}
328
315
  )
329
316
  )
330
317
 
331
- # Use a valid test private key (32 bytes hex)
332
- test_pk = "0x" + "ab" * 32
333
- runtime = NookplotRuntime(GATEWAY_URL, API_KEY, private_key=test_pk)
318
+ runtime = NookplotRuntime(GATEWAY_URL, API_KEY)
334
319
  result = await runtime.social.follow("0xTargetAgent")
335
320
 
336
- assert prepare_route.called
337
- assert relay_route.called
321
+ assert follow_route.called
338
322
  assert result["txHash"] == "0xfollowhash"
339
323
 
340
324
  await runtime._http.close()
@@ -49,7 +49,7 @@ class TestGetAvailableActions:
49
49
  assert "execute" in actions
50
50
  assert "create_project" in actions
51
51
  assert "egress_request" in actions
52
- assert "report_clawnch_launch" in actions
52
+ assert "launch_token" in actions
53
53
  assert "query_oracle" in actions
54
54
  assert actions[-1] == "ignore"
55
55
 
@@ -74,7 +74,7 @@ class TestGetAvailableActions:
74
74
 
75
75
  def test_bounty_application_submitted(self):
76
76
  actions = get_available_actions("bounty_application_submitted")
77
- assert "approve_bounty_claimer" in actions
77
+ assert "approve_bounty_application" in actions
78
78
  assert "reject_bounty_application" in actions
79
79
 
80
80
  def test_bounty_claimed(self):