nookplot-runtime 0.5.89__tar.gz → 0.5.91__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 (33) hide show
  1. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/PKG-INFO +1 -1
  2. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/action_catalog_generated.py +2 -2
  3. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/autonomous.py +45 -0
  4. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/client.py +80 -0
  5. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/pyproject.toml +1 -1
  6. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/.gitignore +0 -0
  7. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/README.md +0 -0
  8. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/SKILL.md +0 -0
  9. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/__init__.py +0 -0
  10. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/action_catalog.py +0 -0
  11. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/artifact_embeddings.py +0 -0
  12. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/cognitive_workspace.py +0 -0
  13. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/content_safety.py +0 -0
  14. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/cro.py +0 -0
  15. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/embedding_exchange.py +0 -0
  16. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/evaluator.py +0 -0
  17. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/events.py +0 -0
  18. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/formatters.py +0 -0
  19. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/knowledge_context.py +0 -0
  20. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/manifest.py +0 -0
  21. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/signal_action_map.py +0 -0
  22. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/nookplot_runtime/types.py +0 -0
  23. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/requirements.lock +0 -0
  24. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/__init__.py +0 -0
  25. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/helpers/__init__.py +0 -0
  26. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/helpers/mock_runtime.py +0 -0
  27. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/test_autonomous_action_dispatch.py +0 -0
  28. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/test_autonomous_dedup.py +0 -0
  29. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/test_autonomous_lifecycle.py +0 -0
  30. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/test_client.py +0 -0
  31. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/test_content_safety.py +0 -0
  32. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/test_get_available_actions.py +0 -0
  33. {nookplot_runtime-0.5.89 → nookplot_runtime-0.5.91}/tests/test_latent_space.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nookplot-runtime
3
- Version: 0.5.89
3
+ Version: 0.5.91
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
@@ -1914,7 +1914,7 @@ GENERATED_CATALOG: dict[str, ActionInfo] = {
1914
1914
  },
1915
1915
  "store_knowledge_item": {
1916
1916
  "description": "Store a knowledge item in your personal graph. Use this after completing tasks, learning something new, or gaining insights.\n**Free** — no credits charged.\n**Important:** Always include a domain and tags — items without domains can't be consolidated or cross-linked by the compiler.\n**Next:** Link related items with nookplot_add_knowledge_citation.",
1917
- "params": "contentText (string), knowledgeType (string, optional), sourceType (string, optional), domain (string, optional), tags (array, optional), importance (number, optional), confidence (number, optional)",
1917
+ "params": "contentText (string), knowledgeType (string, optional), sourceType (string, optional), domain (string, optional), tags (array, optional), importance (number, optional), confidence (number, optional), sourceItemIds (array, optional), title (string, optional)",
1918
1918
  "category": "knowledge",
1919
1919
  },
1920
1920
  "get_knowledge_item": {
@@ -1933,7 +1933,7 @@ GENERATED_CATALOG: dict[str, ActionInfo] = {
1933
1933
  "category": "knowledge",
1934
1934
  },
1935
1935
  "compile_knowledge": {
1936
- "description": "Organize your knowledge — consolidates domain clusters, cross-links items, regenerates your index, and runs quality checks.\n**Free** — no credits charged.\n**When to use:** After storing 5+ items.\n**Response includes:** `lint.totalActive` (issue count), `lint.byType` (breakdown), and `lintFindings` (top 10 issues with itemId, lintType, description).\n**Act on findings:**\n- metadata_gap → `nookplot_update_knowledge_item(itemId, domain/tags/title)`\n- stale or low_quality → `nookplot_archive_knowledge_item(itemId)`\n- near_duplicate → archive the lower-importance item\n- contradiction → archive the outdated item, or leave both if valid",
1936
+ "description": "Synthesize your knowledge — returns items that need real synthesis, grouped by domain.\n**YOUR JOB:** Read the items, find patterns/insights/connections across them, then store each synthesis via `nookplot_store_knowledge_item` with `knowledgeType: 'synthesis'`.\n**Output format:** Write rich markdown — headers, bullet points, code blocks, tables. Find patterns, contradictions, key takeaways, and actionable insights.\n**Free** — no credits charged.\n**When to use:** After storing 5+ items, or periodically to maintain your knowledge.\n**Mechanical work done for you:** Cross-linking, embedding backfill, and linting run automatically.\n**Act on lint findings:**\n- metadata_gap → `nookplot_update_knowledge_item(itemId, domain/tags/title)`\n- stale or low_quality → `nookplot_archive_knowledge_item(itemId)`\n- near_duplicate → archive the lower-importance item\n- contradiction → archive the outdated item, or leave both if valid",
1937
1937
  "category": "knowledge",
1938
1938
  },
1939
1939
  "update_knowledge_item": {
@@ -602,6 +602,9 @@ class AutonomousAgent:
602
602
  # ── File sharing signals ──
603
603
  elif signal_type == "file_shared":
604
604
  await self._handle_file_shared(data)
605
+ # ── Knowledge dream prompts ──
606
+ elif signal_type == "dream_prompt":
607
+ await self._handle_dream_prompt(data)
605
608
  else:
606
609
  self._broadcast("action_skipped", f"⏭ Unhandled signal type: {signal_type}", {
607
610
  "signalType": signal_type,
@@ -2034,6 +2037,48 @@ class AutonomousAgent:
2034
2037
  "action": "file_shared", "error": str(exc),
2035
2038
  })
2036
2039
 
2040
+ # ── Knowledge dream prompt handler ──
2041
+
2042
+ async def _handle_dream_prompt(self, data: dict[str, Any]) -> None:
2043
+ """Handle idle-time knowledge exploration — search domains, find connections, store insights."""
2044
+ dream_type = data.get("dreamType", "gap_bridge")
2045
+ prompt_text = data.get("prompt", data.get("message", ""))
2046
+ domains = data.get("domains", [])
2047
+
2048
+ if not prompt_text:
2049
+ return
2050
+
2051
+ try:
2052
+ domain_ctx = f"Domains involved: {', '.join(domains)}\n" if domains else ""
2053
+
2054
+ prompt = (
2055
+ "KNOWLEDGE DREAM — Idle-time exploration\n\n"
2056
+ f"{wrap_untrusted(str(prompt_text)[:500], 'dream prompt')}\n\n"
2057
+ f"{domain_ctx}"
2058
+ "Your task:\n"
2059
+ "1. Search your knowledge for the domains mentioned above (use search_knowledge)\n"
2060
+ "2. Think about connections, patterns, or gaps\n"
2061
+ "3. If you discover an insight, store it (use store_knowledge_item with rich markdown)\n"
2062
+ "4. Optionally run compile_knowledge to organize everything\n\n"
2063
+ "Available actions:\n"
2064
+ "- search_knowledge: Search your knowledge graph\n"
2065
+ "- store_knowledge_item: Store a new insight\n"
2066
+ "- compile_knowledge: Run full knowledge synthesis\n"
2067
+ "- get_knowledge_stats: Check your knowledge overview\n"
2068
+ "- ignore: Take no action\n\n"
2069
+ "Format:\nACTION: <action_type>\nPARAMS: <json params>"
2070
+ )
2071
+
2072
+ assert self._generate_response is not None
2073
+ response = await self._generate_response(prompt)
2074
+ text = (response or "").strip()
2075
+ if text:
2076
+ await self._parse_and_execute_action(text)
2077
+ except Exception as exc:
2078
+ self._broadcast("error", f"Dream prompt handling failed: {exc}", {
2079
+ "action": "dream_prompt", "error": str(exc),
2080
+ })
2081
+
2037
2082
  # ── Bounty application/submission signal handlers ──
2038
2083
 
2039
2084
  async def _handle_bounty_application_submitted(self, data: dict[str, Any]) -> None:
@@ -5452,8 +5452,88 @@ class NookplotRuntime:
5452
5452
  self._agent_id,
5453
5453
  self._address,
5454
5454
  )
5455
+
5456
+ # CLI-1 fix: auto-load forge knowledge after connect (same as CLI agentLoop).
5457
+ # Non-fatal — agent works without preset knowledge if this fails.
5458
+ try:
5459
+ await self.load_forge_knowledge()
5460
+ except Exception:
5461
+ pass # load_forge_knowledge already handles its own error logging
5462
+
5455
5463
  return result
5456
5464
 
5465
+ async def load_forge_knowledge(self) -> dict[str, Any] | None:
5466
+ """Load forge preset knowledge into the agent's personal KG.
5467
+
5468
+ If this agent has a forge deployment with a linked preset,
5469
+ fetches the preset data and ingests it server-side into the
5470
+ personal knowledge graph. Idempotent — safe to call on every boot.
5471
+
5472
+ Returns the KG result dict or None if no preset is linked.
5473
+ Raises no exceptions — failures are logged and silently skipped.
5474
+ """
5475
+ if not self._address:
5476
+ return None
5477
+ try:
5478
+ # Find agent's deployments
5479
+ dep_data = await self._http.request(
5480
+ "GET",
5481
+ f"/v1/forge?first=1&skip=0&creator={self._address}",
5482
+ )
5483
+ deployments = dep_data.get("deployments", [])
5484
+ if not deployments:
5485
+ return None
5486
+
5487
+ # Find linked preset
5488
+ presets_data = await self._http.request(
5489
+ "GET",
5490
+ f"/v1/forge/presets?creator={self._address}&first=1",
5491
+ )
5492
+ presets = presets_data.get("presets", [])
5493
+ if not presets:
5494
+ return None
5495
+
5496
+ preset = presets[0]
5497
+ preset_id = preset.get("preset_id")
5498
+ if not preset_id:
5499
+ return None
5500
+
5501
+ # Build sources from preset config
5502
+ ds_config = preset.get("dataset_config") or {}
5503
+ raw_sources = ds_config.get("sources", [])
5504
+ if raw_sources:
5505
+ sources = [{"type": s["type"], "config": s.get("config", {})} for s in raw_sources]
5506
+ else:
5507
+ sources = [{"type": preset.get("source_type", "mining"), "config": {}}]
5508
+
5509
+ # Fetch + ingest in one call
5510
+ result = await self._http.request("POST", "/v1/forge/data/fetch", {
5511
+ "presetId": preset_id,
5512
+ "sources": sources,
5513
+ "ingestToKg": True,
5514
+ })
5515
+
5516
+ kg_result = result.get("kgResult")
5517
+ if kg_result:
5518
+ ingested = kg_result.get("ingested", 0)
5519
+ blocked = kg_result.get("blocked", 0)
5520
+ if ingested > 0:
5521
+ logger.info("[knowledge] Loaded %d items into personal KG", ingested)
5522
+ if blocked > 0:
5523
+ logger.warning("[knowledge] %d items blocked by safety scanner", blocked)
5524
+ return kg_result
5525
+ except Exception as exc:
5526
+ # Non-fatal — agent still works without preset knowledge
5527
+ msg = str(exc)
5528
+ if "not found" in msg:
5529
+ pass # Expected: no deployment
5530
+ elif "402" in msg:
5531
+ # CLI-2 fix: surface insufficient balance so user knows why knowledge is missing
5532
+ logger.warning("[knowledge] Insufficient NOOK balance to load forge data. Agent will operate without preset knowledge.")
5533
+ else:
5534
+ logger.debug("[knowledge] Forge knowledge load skipped: %s", msg)
5535
+ return None
5536
+
5457
5537
  async def disconnect(self) -> None:
5458
5538
  """Disconnect from the Nookplot gateway."""
5459
5539
  # Stop heartbeat
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "nookplot-runtime"
7
- version = "0.5.89"
7
+ version = "0.5.91"
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"