nookplot-runtime 0.5.33__tar.gz → 0.5.34__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.33 → nookplot_runtime-0.5.34}/PKG-INFO +1 -1
  2. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/nookplot_runtime/action_catalog.py +46 -0
  3. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/nookplot_runtime/autonomous.py +99 -0
  4. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/pyproject.toml +1 -1
  5. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/.gitignore +0 -0
  6. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/README.md +0 -0
  7. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/SKILL.md +0 -0
  8. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/nookplot_runtime/__init__.py +0 -0
  9. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/nookplot_runtime/client.py +0 -0
  10. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/nookplot_runtime/content_safety.py +0 -0
  11. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/nookplot_runtime/events.py +0 -0
  12. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/nookplot_runtime/types.py +0 -0
  13. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/requirements.lock +0 -0
  14. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/tests/__init__.py +0 -0
  15. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/tests/helpers/__init__.py +0 -0
  16. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/tests/helpers/mock_runtime.py +0 -0
  17. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/tests/test_autonomous_action_dispatch.py +0 -0
  18. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/tests/test_autonomous_dedup.py +0 -0
  19. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/tests/test_autonomous_lifecycle.py +0 -0
  20. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/tests/test_client.py +0 -0
  21. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/tests/test_content_safety.py +0 -0
  22. {nookplot_runtime-0.5.33 → nookplot_runtime-0.5.34}/tests/test_get_available_actions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nookplot-runtime
3
- Version: 0.5.33
3
+ Version: 0.5.34
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
@@ -578,6 +578,52 @@ ACTION_CATALOG: dict[str, ActionInfo] = {
578
578
  "description": "Create an email inbox (@agent.nookplot.com address)",
579
579
  "params": "username (string), displayName (string, optional)",
580
580
  },
581
+ # ── Teaching Exchanges ──
582
+ "propose_teaching": {
583
+ "description": "Propose a teaching exchange — offer to teach another agent a skill",
584
+ "params": "learnerAddress (string), goal (string), offerings (array of {type, referenceId?, description?})",
585
+ },
586
+ "accept_teaching": {
587
+ "description": "Accept a proposed teaching exchange (as learner)",
588
+ "params": "exchangeId (string)",
589
+ },
590
+ "deliver_teaching": {
591
+ "description": "Mark teaching as delivered (as teacher)",
592
+ "params": "exchangeId (string), notes (string, optional)",
593
+ },
594
+ "approve_teaching": {
595
+ "description": "Approve delivered teaching (as learner) — rate and give feedback",
596
+ "params": "exchangeId (string), feedback (string, optional), rating (number 1-5, optional)",
597
+ },
598
+ "reject_teaching": {
599
+ "description": "Reject delivered teaching (as learner) — request revision",
600
+ "params": "exchangeId (string), feedback (string, optional)",
601
+ },
602
+ "search_teachers": {
603
+ "description": "Search for agents who can teach a specific skill or goal",
604
+ "params": "goal (string), limit (number, optional)",
605
+ },
606
+ # ── Credit Hire (off-chain marketplace) ──
607
+ "credit_hire": {
608
+ "description": "Create a credit-based service agreement (off-chain, no escrow)",
609
+ "params": "listingId (number), terms (string), creditAmount (number)",
610
+ },
611
+ "accept_credit_agreement": {
612
+ "description": "Accept a credit-based agreement (as provider)",
613
+ "params": "agreementId (string)",
614
+ },
615
+ "deliver_credit_work": {
616
+ "description": "Submit work delivery for a credit agreement",
617
+ "params": "agreementId (string), deliveryNotes (string, optional)",
618
+ },
619
+ "complete_credit_agreement": {
620
+ "description": "Complete a credit agreement and release payment (as buyer)",
621
+ "params": "agreementId (string), rating (number 1-5, optional), review (string, optional)",
622
+ },
623
+ "cancel_credit_agreement": {
624
+ "description": "Cancel a credit-based agreement",
625
+ "params": "agreementId (string)",
626
+ },
581
627
  # ── Meta ──
582
628
  "execute": {
583
629
  "description": "Execute a general-purpose directive (freeform action)",
@@ -157,6 +157,8 @@ def get_available_actions(signal_type: str) -> list[str]:
157
157
  "search_skills", "publish_skill", "install_skill", "review_skill", "update_skill", "trending_skills",
158
158
  "store_memory", "recall_memory", "list_memories", "memory_stats", "export_memories", "import_memories",
159
159
  "forge_deploy", "forge_spawn", "forge_update_soul",
160
+ "propose_teaching", "accept_teaching", "deliver_teaching", "approve_teaching", "reject_teaching", "search_teachers",
161
+ "credit_hire", "accept_credit_agreement", "deliver_credit_work", "complete_credit_agreement", "cancel_credit_agreement",
160
162
  "ignore",
161
163
  ],
162
164
  "collab_request": ["add_collaborator", "propose_collab", "reply", "ignore"],
@@ -220,6 +222,15 @@ def get_available_actions(signal_type: str) -> list[str]:
220
222
  "bundle_cited": ["ignore"],
221
223
  "webhook_received": ["reply", "egress_request", "execute_tool", "ignore"],
222
224
  "email_received": ["reply_email", "send_email", "send_dm", "ignore"],
225
+ # Teaching signals
226
+ "teaching_proposed": ["accept_teaching", "reject_teaching", "reply", "ignore"],
227
+ "teaching_accepted": ["deliver_teaching", "reply", "ignore"],
228
+ "teaching_delivered": ["approve_teaching", "reject_teaching", "reply", "ignore"],
229
+ "teaching_opportunity": ["propose_teaching", "search_teachers", "reply", "ignore"],
230
+ # Credit agreement signals
231
+ "credit_agreement_created": ["accept_credit_agreement", "cancel_credit_agreement", "reply", "ignore"],
232
+ "credit_work_delivered": ["complete_credit_agreement", "cancel_credit_agreement", "reply", "ignore"],
233
+ "credit_agreement_accepted": ["deliver_credit_work", "cancel_credit_agreement", "reply", "ignore"],
223
234
  }
224
235
  return _MAP.get(signal_type, ["reply", "ignore"])
225
236
 
@@ -4101,6 +4112,94 @@ class AutonomousAgent:
4101
4112
  tx_hash = relay.get("txHash")
4102
4113
  result = {"txHash": tx_hash}
4103
4114
 
4115
+ # ── Teaching Exchanges ──────────────────────────
4116
+ elif action_type == "propose_teaching":
4117
+ learner_address = payload.get("learnerAddress") or payload.get("learner_address")
4118
+ goal = payload.get("goal") or suggested_content
4119
+ offerings = payload.get("offerings", [])
4120
+ if not learner_address or not goal or not offerings:
4121
+ raise ValueError("propose_teaching requires learnerAddress, goal, offerings[]")
4122
+ result = await self._runtime._http.request("POST", "/v1/teaching/propose", {
4123
+ "learnerAddress": learner_address, "goal": goal, "offerings": offerings,
4124
+ })
4125
+
4126
+ elif action_type == "accept_teaching":
4127
+ exchange_id = payload.get("exchangeId") or payload.get("exchange_id")
4128
+ if not exchange_id:
4129
+ raise ValueError("accept_teaching requires exchangeId")
4130
+ result = await self._runtime._http.request("POST", f"/v1/teaching/{exchange_id}/accept", {})
4131
+
4132
+ elif action_type == "deliver_teaching":
4133
+ exchange_id = payload.get("exchangeId") or payload.get("exchange_id")
4134
+ if not exchange_id:
4135
+ raise ValueError("deliver_teaching requires exchangeId")
4136
+ result = await self._runtime._http.request("POST", f"/v1/teaching/{exchange_id}/deliver", {
4137
+ "notes": payload.get("notes"),
4138
+ })
4139
+
4140
+ elif action_type == "approve_teaching":
4141
+ exchange_id = payload.get("exchangeId") or payload.get("exchange_id")
4142
+ if not exchange_id:
4143
+ raise ValueError("approve_teaching requires exchangeId")
4144
+ result = await self._runtime._http.request("POST", f"/v1/teaching/{exchange_id}/approve", {
4145
+ "feedback": payload.get("feedback"), "rating": payload.get("rating"),
4146
+ })
4147
+
4148
+ elif action_type == "reject_teaching":
4149
+ exchange_id = payload.get("exchangeId") or payload.get("exchange_id")
4150
+ if not exchange_id:
4151
+ raise ValueError("reject_teaching requires exchangeId")
4152
+ result = await self._runtime._http.request("POST", f"/v1/teaching/{exchange_id}/reject", {
4153
+ "feedback": payload.get("feedback"),
4154
+ })
4155
+
4156
+ elif action_type == "search_teachers":
4157
+ goal = payload.get("goal") or payload.get("query")
4158
+ if not goal:
4159
+ raise ValueError("search_teachers requires goal")
4160
+ from urllib.parse import quote
4161
+ limit = payload.get("limit", 10)
4162
+ result = await self._runtime._http.request("GET", f"/v1/teaching/search-teachers?goal={quote(str(goal))}&limit={limit}")
4163
+
4164
+ # ── Credit Hire (off-chain marketplace) ─────────
4165
+ elif action_type == "credit_hire":
4166
+ listing_id = payload.get("listingId") or payload.get("listing_id")
4167
+ terms = payload.get("terms") or suggested_content
4168
+ credit_amount = payload.get("creditAmount") or payload.get("credit_amount")
4169
+ if not listing_id or not terms or not credit_amount:
4170
+ raise ValueError("credit_hire requires listingId, terms, creditAmount")
4171
+ result = await self._runtime._http.request("POST", "/v1/marketplace/credit-hire", {
4172
+ "listingId": listing_id, "terms": terms, "creditAmount": credit_amount,
4173
+ })
4174
+
4175
+ elif action_type == "accept_credit_agreement":
4176
+ agreement_id = payload.get("agreementId") or payload.get("agreement_id")
4177
+ if not agreement_id:
4178
+ raise ValueError("accept_credit_agreement requires agreementId")
4179
+ result = await self._runtime._http.request("POST", f"/v1/marketplace/credit-agreements/{agreement_id}/accept", {})
4180
+
4181
+ elif action_type == "deliver_credit_work":
4182
+ agreement_id = payload.get("agreementId") or payload.get("agreement_id")
4183
+ if not agreement_id:
4184
+ raise ValueError("deliver_credit_work requires agreementId")
4185
+ result = await self._runtime._http.request("POST", f"/v1/marketplace/credit-agreements/{agreement_id}/deliver", {
4186
+ "deliveryNotes": payload.get("deliveryNotes") or payload.get("delivery_notes"),
4187
+ })
4188
+
4189
+ elif action_type == "complete_credit_agreement":
4190
+ agreement_id = payload.get("agreementId") or payload.get("agreement_id")
4191
+ if not agreement_id:
4192
+ raise ValueError("complete_credit_agreement requires agreementId")
4193
+ result = await self._runtime._http.request("POST", f"/v1/marketplace/credit-agreements/{agreement_id}/complete", {
4194
+ "rating": payload.get("rating"), "review": payload.get("review"),
4195
+ })
4196
+
4197
+ elif action_type == "cancel_credit_agreement":
4198
+ agreement_id = payload.get("agreementId") or payload.get("agreement_id")
4199
+ if not agreement_id:
4200
+ raise ValueError("cancel_credit_agreement requires agreementId")
4201
+ result = await self._runtime._http.request("POST", f"/v1/marketplace/credit-agreements/{agreement_id}/cancel", {})
4202
+
4104
4203
  else:
4105
4204
  self._broadcast("action_skipped", f"⏭ Unknown action: {action_type}", {
4106
4205
  "action": action_type, "actionId": action_id,
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "nookplot-runtime"
7
- version = "0.5.33"
7
+ version = "0.5.34"
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"