feat: add Taskmarket tool - #3016
Conversation
Add TaskmarketTool, a chat-native Taskmarket requester tool for Chainlit apps: discover open tasks, track live status, review submissions (read-only), and create funded tasks through the official Taskmarket CLI with a hard spend cap and a mandatory fresh authorization string. - list_tasks/get_task/list_submissions: public REST reads, no wallet - create_task: safety checks (authorization, max_spend, duration) then delegates the funded transfer to the official taskmarket CLI - never stores private keys, seeds, or tokens; never blindly retries - every method surfaces as Step(type='tool') for chat visibility - sample app + 8 tests covering the contract and refunds Co-Authored-By: Hermes Agent <nicolasesanchez50@gmail.com>
There was a problem hiding this comment.
All reported issues were addressed across 4 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…lement Address all 8 findings from cubic-dev-ai review on PR Chainlit#3016. Safety: - authorization gate is now a server-generated, time-limited, single-use token (request_authorization), bound to the exact reward — a caller can no longer construct the gate from the reward parameter - CLI timeout / unrecognized output / failed status lookup now return explicit unknown-settlement results with the task id whenever known, never raise, never blind-retry a payment Async: - HTTP reads via async httpx client (no event-loop block up to 45s) - CLI write via asyncio subprocess with 120s wait_for (no block up to 120s) Quality: - tests now mock _get_json with fixtures (no live network; 13 tests, all offline and deterministic) - sample app guards refusal strings against JSON parse Co-Authored-By: Hermes Agent <nicolasesanchez50@gmail.com>
|
Addressed all 8 findings in commit P1 — authorization gate (nonce): now P1 — event-loop blocking: HTTP reads now run through an async P1 — unknown settlement: CLI timeout, exit-0-with-unrecognized-output, and status-lookup failure all return explicit P2 — tests: live-internet tests replaced with mocked P2 — sample: refusal strings are guarded with |
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…egistry - P1: terminate and reap the subprocess on CLI timeout instead of leaking a hung process after the create command was issued. - P2: bind authorization tokens to the issuing chat session and reject cross-session use. - P2: reject nonpositive TTLs instead of silently falling back to the default 300s window. - P2: prune expired/used tokens and cap the authorization registry. - tests: enter the Chainlit context fixture (repo pattern), patch shutil.which so the settlement path runs on machines/CI without the real CLI binary, and cover the timeout-kill, session-binding and nonpositive-TTL paths. Co-Authored-By: Hermes Agent jobs <hermes@nicosanchez.com.ar>
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
…orking Address cubic review (2 P2): - One conversation can no longer exhaust the shared token cap: add a per-conversation cap (MAX_AUTH_TOKENS_PER_SCOPE) in front of the global backstop, so a single chat holding its max (10) cannot starve the other conversations of the 100-token pool. - Token binding now follows the conversation thread id instead of the raw session id. Thread ids survive across HTTP API requests (where each request gets a fresh session id), so a token issued in one request is usable by create_task in a later request of the same thread, while cross-conversation tokens are still refused. Tests: add per-conversation cap regression test (cap applies to one thread only, another thread still issues) and HTTP-flow regression test (token survives a session id change within the same thread). Co-Authored-By: Hermes Agent jobs <hermes@nicosanchez.com.ar>
Summary
Adds
TaskmarketTool, a chat-native Taskmarket requester tool for Chainlit apps. Taskmarket is an onchain agent labor marketplace on Base; this lets a user run the full requester flow from a Chainlit conversation.What it does
list_tasks— discover open tasks via public REST (no wallet)get_task— live status: reward USDC, phase, expiry, submission windowlist_submissions— read-only review view (never accepts/rejects)create_task— funded requester flow:authorize 5 USDC for taskmarket task)reward > 0andreward <= max_spend(default 5 USDC,TASKMARKET_MAX_SPENDto override)taskmarketCLI (wallet keys, X402 payment, legal acceptance, idempotency all handled by first-party tooling — no private keys, seeds, or tokens touched here)Every method surfaces as
Step(type="tool")so tool activity is visible in the chat UI. Exported ascl.TaskmarketToolvia the lazy__getattr__pattern used by the other integrations.Checklist
backend/chainlit/sample/taskmarket.pybackend/tests/test_taskmarket.py) — contract + live read path + all refundsruff check+ruff format --checkcleanmypycleanverified: true, reasonvalid)Summary by cubic
Adds
TaskmarketTooltochainlitto run the Taskmarket requester flow from chat via the officialtaskmarketCLI. Creation requires a server-generated, single-use authorization token bound to the conversation thread and exact reward; CLI timeouts are killed and return explicit unknown-settlement results.request_authorization(server-generated token; TTL > 0; per-thread cap 10; global cap 100),list_tasks/get_task/list_submissions(async public REST, read-only),create_task(requires token; reward > 0 and <=TASKMARKET_MAX_SPEND[default 5 USDC]; duration > 0; delegates funded transfer totaskmarketCLI; never handles private keys). All surface as Step(type="tool").cl.TaskmarketToolvia lazy import; sample atbackend/chainlit/sample/taskmarket.py; 13 offline tests atbackend/tests/test_taskmarket.py.Written for commit 491db25. Summary will update on new commits.