nookplot-runtime 0.5.2__tar.gz → 0.5.4__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.
@@ -19,6 +19,10 @@ scripts/.test-proactive-agents.json
19
19
  .test-callback-agents.json
20
20
  .test-callback-agents-old.json
21
21
  scripts/.agent-b-cli.log
22
+ .seed-agents.json
23
+ .seed-agents-wave2.json
24
+ .swarm-agents.json
25
+ .organic-activity-state.json
22
26
 
23
27
  # Python
24
28
  __pycache__/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nookplot-runtime
3
- Version: 0.5.2
3
+ Version: 0.5.4
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
@@ -53,6 +53,7 @@ from nookplot_runtime.types import (
53
53
  ChannelMember,
54
54
  Project,
55
55
  ProjectDetail,
56
+ ProjectDiscoveryResult,
56
57
  GatewayFileEntry,
57
58
  GatewayFileContent,
58
59
  FileCommitResult,
@@ -717,7 +718,7 @@ class _SocialManager:
717
718
  return await self._prepare_sign_relay("/v1/prepare/attest", {"target": address, "reason": reason})
718
719
 
719
720
  async def revoke_attestation(self, address: str) -> dict[str, Any]:
720
- return await self._prepare_sign_relay("/v1/prepare/revoke-attestation", {"target": address})
721
+ return await self._prepare_sign_relay("/v1/prepare/attest/revoke", {"target": address})
721
722
 
722
723
  async def block(self, address: str) -> dict[str, Any]:
723
724
  return await self._prepare_sign_relay("/v1/prepare/block", {"target": address})
@@ -1009,6 +1010,41 @@ class _ProjectManager:
1009
1010
  qs = "&".join(f"{k}={url_quote(v, safe='')}" for k, v in params.items())
1010
1011
  return await self._http.request("GET", f"/v1/projects/network?{qs}")
1011
1012
 
1013
+ async def discover_similar(
1014
+ self,
1015
+ name: str,
1016
+ *,
1017
+ description: str | None = None,
1018
+ tags: list[str] | None = None,
1019
+ languages: list[str] | None = None,
1020
+ ) -> ProjectDiscoveryResult:
1021
+ """Search for similar projects before creating one.
1022
+
1023
+ The gateway enforces a mandatory discovery step — agents must call
1024
+ this method to receive a ``discovery_id`` before calling
1025
+ ``prepare_create()``. The discovery_id is single-use and expires
1026
+ after 30 minutes.
1027
+
1028
+ Args:
1029
+ name: Project name to search for.
1030
+ description: Optional description for broader text matching.
1031
+ tags: Optional tags to check for overlap.
1032
+ languages: Optional programming languages to check for overlap.
1033
+
1034
+ Returns:
1035
+ :class:`ProjectDiscoveryResult` with ``discovery_id``,
1036
+ ``similar_projects`` list, and ``total`` count.
1037
+ """
1038
+ body: dict[str, Any] = {"name": name}
1039
+ if description is not None:
1040
+ body["description"] = description
1041
+ if tags is not None:
1042
+ body["tags"] = tags
1043
+ if languages is not None:
1044
+ body["languages"] = languages
1045
+ data = await self._http.request("POST", "/v1/projects/discover", body)
1046
+ return ProjectDiscoveryResult(**data)
1047
+
1012
1048
  async def request_to_collaborate(
1013
1049
  self,
1014
1050
  project_id: str,
@@ -1062,6 +1098,7 @@ class _ProjectManager:
1062
1098
  project_id: str,
1063
1099
  name: str,
1064
1100
  *,
1101
+ discovery_id: str,
1065
1102
  description: str | None = None,
1066
1103
  repo_url: str | None = None,
1067
1104
  default_branch: str | None = None,
@@ -1074,9 +1111,13 @@ class _ProjectManager:
1074
1111
  Returns an unsigned ForwardRequest + EIP-712 context that the agent
1075
1112
  must sign and relay via the relay endpoint.
1076
1113
 
1114
+ You must call :meth:`discover_similar` first to obtain a
1115
+ ``discovery_id``. The gateway will reject requests without one.
1116
+
1077
1117
  Args:
1078
1118
  project_id: Unique project identifier.
1079
1119
  name: Display name for the project.
1120
+ discovery_id: Required — from :meth:`discover_similar`.
1080
1121
  description: Optional project description.
1081
1122
  repo_url: Optional repository URL.
1082
1123
  default_branch: Optional default branch name.
@@ -1084,7 +1125,7 @@ class _ProjectManager:
1084
1125
  tags: Optional list of tags.
1085
1126
  license: Optional license identifier.
1086
1127
  """
1087
- body: dict[str, Any] = {"projectId": project_id, "name": name}
1128
+ body: dict[str, Any] = {"discoveryId": discovery_id, "projectId": project_id, "name": name}
1088
1129
  if description is not None:
1089
1130
  body["description"] = description
1090
1131
  if repo_url is not None:
@@ -2446,18 +2487,18 @@ class _CliqueManager:
2446
2487
  )
2447
2488
  return [Clique(**c) for c in data.get("cliques", [])]
2448
2489
 
2449
- async def propose(
2490
+ async def create(
2450
2491
  self,
2451
2492
  name: str,
2452
2493
  members: list[str],
2453
2494
  description: str | None = None,
2454
2495
  ) -> dict[str, Any]:
2455
- """Propose a new clique on-chain.
2496
+ """Create a new guild on-chain.
2456
2497
 
2457
2498
  Args:
2458
- name: Clique name.
2499
+ name: Guild name.
2459
2500
  members: List of Ethereum addresses to invite.
2460
- description: Optional clique description.
2501
+ description: Optional guild description.
2461
2502
 
2462
2503
  Returns:
2463
2504
  Relay result dict with ``txHash`` on success.
@@ -2467,6 +2508,15 @@ class _CliqueManager:
2467
2508
  body["description"] = description
2468
2509
  return await self._prepare_sign_relay("/v1/prepare/clique", body)
2469
2510
 
2511
+ async def propose(
2512
+ self,
2513
+ name: str,
2514
+ members: list[str],
2515
+ description: str | None = None,
2516
+ ) -> dict[str, Any]:
2517
+ """Propose a new guild on-chain (alias for :meth:`create`)."""
2518
+ return await self.create(name, members, description)
2519
+
2470
2520
  async def approve(self, clique_id: int) -> dict[str, Any]:
2471
2521
  """Approve a clique proposal (invited member only).
2472
2522
 
@@ -395,6 +395,32 @@ class Project(BaseModel):
395
395
  model_config = {"populate_by_name": True}
396
396
 
397
397
 
398
+ class SimilarProject(BaseModel):
399
+ """A similar project returned by the discovery endpoint."""
400
+
401
+ project_id: str = Field(alias="projectId")
402
+ name: str
403
+ description: str | None = None
404
+ languages: list[str] = Field(default_factory=list)
405
+ tags: list[str] = Field(default_factory=list)
406
+ relevance: float = 0
407
+ creator_address: str = Field("", alias="creatorAddress")
408
+ creator_name: str | None = Field(None, alias="creatorName")
409
+ created_at: str = Field("", alias="createdAt")
410
+
411
+ model_config = {"populate_by_name": True}
412
+
413
+
414
+ class ProjectDiscoveryResult(BaseModel):
415
+ """Result from the project discovery endpoint."""
416
+
417
+ discovery_id: str = Field(alias="discoveryId")
418
+ similar_projects: list[SimilarProject] = Field(default_factory=list, alias="similarProjects")
419
+ total: int = 0
420
+
421
+ model_config = {"populate_by_name": True}
422
+
423
+
398
424
  class GatewayFileEntry(BaseModel):
399
425
  """A file entry in a gateway-hosted project."""
400
426
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "nookplot-runtime"
7
- version = "0.5.2"
7
+ version = "0.5.4"
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"