feat: OpenPlanter Crowd — local Nostr-compatible task market (REPL/TUI + Tauri) - #35
Open
erkinalp wants to merge 20 commits into
Open
feat: OpenPlanter Crowd — local Nostr-compatible task market (REPL/TUI + Tauri)#35erkinalp wants to merge 20 commits into
erkinalp wants to merge 20 commits into
Conversation
- agent/crowd.py: identity, Nostr-style event model, task store, in-memory relay, strfry wrapper, DP embeddings, high-level client - SessionStore now exposes .crowd (CrowdStore) - add /crowd, /claim, /trust slash commands - add persistent settings: crowd_relays, crowd_nsec, crowd_worker_tags, crowd_epsilon - add --crowd*, OPENPLANTER_CROWD* config flags Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- CrowdIdentity now signs Nostr events with coincurve.sign_schnorr. - 32-byte x-only public keys and 64-byte signatures (hex) for real relay compatibility. - Fallback to HMAC placeholder only when coincurve is unavailable. - Add coincurve>=21.0.0 to project dependencies. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Add CROWD.md with quick start, CLI/env config, event kinds, signing, storage layout, relay federation, and programmatic API. - Surface crowd flags and env vars in README.md. - Update project structure and dependency list in README.md. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Add CrowdStore.cancel_task() (sets status to 'canceled' if not finished). - Add CrowdClient.cancel_task() that publishes a signed kind:31006 event. - Add /cancel <hash-or-prefix> to the REPL/Textual TUI. - Update CROWD.md and README help text. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Add the same /crowd, /claim, /cancel, and /trust slash commands from the Python REPL to the Tauri desktop chat. - New agent/crowd_cli.py headless CLI wrapper around agent/crowd.py - New Tauri IPC commands in crates/op-tauri/src/commands/crowd.rs that invoke the Python CLI - Frontend API wrappers and slash dispatch in openplanter-desktop/frontend - Update CROWD.md and README.md with desktop usage instructions Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Use compact JSON separators for event id to match NIP-01.\n- Simplify strfry root to store.root so absolute session dirs work. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- PersistentSettings.normalized() now preserves crowd_relays, crowd_nsec, crowd_worker_tags and crowd_epsilon. - --crowd-relay-port only overrides env when explicitly provided. - A single CrowdClient is created at startup, stored in ChatContext, and stopped on exit. - Generated crowd_nsec is persisted in SettingsStore from REPL, TUI and CLI. - CrowdIdentity only falls back to HMAC placeholder when coincurve is missing. - MemoryRelay invokes subscriber callbacks outside the non-reentrant lock. - CLI claim/cancel resolve tasks against open status only, matching the TUI. - _crowd_client caches the built client in ChatContext. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…eration - Persist every signed Nostr event to events/<task_hash>/<event_id>.json. - Add CrowdStore.append_event/list_events/iter_all_events and hydrate MemoryRelay from disk. - Use filelock + threading.Lock for atomic cross-process claim/cancel/result writes. - Start the strfry router when upstream_relays are configured and --crowd-strfry is set. - Update CROWD.md and README for durable events, locking, and federation. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…mand, noisy embedding docs Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Add a real WebSocket Nostr relay adapter in agent/relay.py and a small relay_server.py for local integration tests. - Wire RelayPool into CrowdClient so two processes can exchange tasks, claims, results, and cancellations over ws://. - Complete marketplace lifecycle: publish, discover, claim, result, accept/reject/expire/reopen. - Add private-task support: encrypted briefs (AES-GCM + ECDH per allowed private identity), sanitized context bundles, scoped relay access, and separate public/private identities persisted in settings. - Rename the placeholder differential-privacy class to NoisyEmbedding and document it as randomized matching. - Add automated integration tests covering event verification, public lifecycle, encrypted task exchange, cancel propagation, and atomic simultaneous claims. - Fix x-only ECDH parity for odd-y private keys so encrypted briefs can be decrypted by any BIP-340 identity. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…tings keys, restrictive perms Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…ngs plaintext fallback, private relay fallback, REPL client config, event ordering, strfry sync window, publish-private allowed default, TUI epsilon Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…ay flush, encrypted settings overwrite guard Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…de claim limit Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
… OK response - Only the task publisher can cancel/accept/reject/expire/reopen (enforced in CrowdClient.cancel_task, CrowdStore lifecycle methods, and _ingest_event for remote events). - Split task identity into brief_hash (deduplication/provenance) and task_id = H(publisher || nonce || brief_hash) so identical briefs from the same or different publishers no longer collide. - Publish task events with task_id, brief_hash, publisher, and nonce in content and use task_id as the NIP-33 d-tag/local store key. - Fix bundled relay OK response to use a boolean third element and a separate reason string per NIP-01. Validation: py_compile, pytest tests/test_crowd.py (5), cargo check -p op-tauri, npm test (200), npm run build. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces OpenPlanter Crowd: a local, nostr-compatible task market with durable signed event storage, cross-process atomic claims, and optional strfry relay/router federation. Agents can publish leaf tasks, claim work from peers, return results, cancel tasks, advertise availability, and maintain a trust list — from the Python REPL/TUI and the Tauri desktop chat.
Key changes
agent/crowd.pyCrowdStorepersists every signed event toevents/<task_hash>/<event_id>.jsonand hydratesMemoryRelayfrom disk onCrowdClientcreation, so new processes see all prior events.CrowdStoreusesthreading.Lockplus an optionalfilelockon.openplanter/crowd/.crowd.lock, makingclaim,cancel, andresultwrites safe across separate Python processes.CrowdClient.start_local_relay()starts a localstrfryrelay when--crowd-strfryis set and, whencrowd_relaysare configured, also spawns astrfry routerto relay31001–31005events up/down those upstreams.CrowdClientno longer publishes orphaned events: it signs, persists to the store atomically, then publishes to the in-memory relay.agent/__main__.pynow passesauto_spawn_strfrytoCrowdClientand shows the active upstream federation in the startup banner.agent/crowd_cli.pyandagent/tui.pycontinue to reuse the samecrowd_client_from_configpath, so desktop and REPL share the same durable store and identity.pyproject.tomladdsfilelockas a dependency.CROWD.mdandREADME.mdupdated for durable events, locking, and federation.Design choices
python3 -m agent.crowd_clito keep BIP-340 signing and storage in one place and identical between CLI and desktop.strfryis still optional; the out-of-the-box mode is in-memory local-only, but events now survive process restarts because they are written to disk.filelockdependency is optional at import time: if it is not installed, the store falls back to a thread lock only.Usage
Python:
or with
strfryfederation:openplanter-agent --workspace ./my-project --crowd --crowd-strfry # after setting crowd_relays in .openplanter/settings.jsonTesting
python3 -m py_compile agent/crowd.py agent/__main__.py agent/crowd_cli.py agent/tui.pypublish → list → claim → list → cancel → trustpassescrowd_cli claimprocesses, only one succeedscargo check -p op-tauripassesnpm run buildandnpm testpass (200/200)