Skip to content

fix(market): rebase #83 (/market command + agent_talent tool) onto current main#99

Open
Daisuke134 wants to merge 8 commits into
BlockRunAI:mainfrom
Daisuke134:market-rebased
Open

fix(market): rebase #83 (/market command + agent_talent tool) onto current main#99
Daisuke134 wants to merge 8 commits into
BlockRunAI:mainfrom
Daisuke134:market-rebased

Conversation

@Daisuke134

Copy link
Copy Markdown

What

This is a conflict-resolution rebase of #83 (feat(market): /market command + agent_talent tool to hire marketplace skills) by @Zambala108, brought current with main (which has moved 32 commits ahead of #83's base since it was opened, including several security-hardening rounds). #83 has been open 3+ weeks with mergeable_state: dirty and can't be merged as-is.

No new functionality is added here. All credit for the design and implementation (the /market command, the agent_talent tool, src/market/client.ts's x402 payment path, and the regression tests in test/market.local.mjs) belongs to @Zambala108. This PR only makes the existing work mergeable again.

What changed in the rebase

Rebasing #83's 8 commits onto current main produced exactly one textual conflict, in package.json:

Everything else (the new /market command block in src/agent/commands.ts, the agent_talent permission rule in src/agent/permissions.ts, the MARKET_URL config addition, the agentTalentCapability registration in src/tools/index.ts, and the two new files src/market/client.ts / src/tools/agent-talent.ts) auto-merged cleanly with no semantic changes needed.

Compatibility check with main's newer money-safety work

main gained a "Round-4 money audit" (--max-spend ceiling covering all paid tools, generic recordUsage-driven spend accounting) after #83 was opened. Verified that #83's agent_talent tool already calls recordUsage('agent_talent:<slug>', 0, 0, paidUsd, 0) on settlement (the same call signature the audit's recordUsage enhancement expects), so the marketplace hire spend is automatically folded into the --max-spend ceiling via getLiveSpendUsd() with no additional code required.

Testing

  • npm run build — clean, no TypeScript errors.
  • npm test536/536 passing, 0 failures, including all of feat(market): /market command + agent_talent tool to hire marketplace skills #83's original marketplace tests (fetchCatalog, filterCatalog, runMarketSkill, agent_talent list/run, /market command variants) plus the newer spend-accounting regression tests (recordUsage folds positive cost into live spend, agent loop folds concurrent paid-tool spend on the stream-failure path).

Branch

market-rebased in this fork, rebased on top of upstream/main @ d69d243 (3.29.16).

krishna and others added 8 commits July 7, 2026 18:49
… skills

Add a buyer surface for the BlockRun agent marketplace
(business.blockrun.ai): a catalog of paid AI skills, each runnable for ONE
standard single-leg `exact` x402 USDC payment on Base. Two surfaces over one
payment path (src/market/client.ts):

- `/market` slash command — a human browses (`/market`, `/market <keyword>`),
  inspects (`/market info <slug>`), and hires (`/market run <slug> <input>`).
  Browsing is a free GET; run pays one x402 from the wallet.
- `agent_talent` tool — the agent discovers (`action:"list"`) and hires
  (`action:"run"`) talent autonomously mid-task, charged only on success.

The marketplace speaks standard x402, so Franklin pays it with the same EVM
wallet and the same `@blockrun/llm` signer it already uses for the gateway —
the only deltas from the BlockRun gateway primitive are the `x-payment`
header name and the base URL (env BLOCKRUN_MARKET_URL, default
business.blockrun.ai). Base-only: a hire always pays from the EVM wallet.

Regression test (test/market.local.mjs) drives the client against a mock
marketplace and asserts Franklin signs the EXACT advertised price — the
invariant the live route enforces with `signedValueMicro === totalMicro`.
This caught a real bug: a `Run — <skill>` description with an em-dash made
@blockrun/llm's btoa-based payload encoding throw "Invalid character" on any
non-Latin1 skill name; the description is now ASCII-stripped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extend the regression suite from the client-only checks to the two buyer
surfaces: agent_talent (list / list+query / empty / run / missing slug+input
/ failed-hire-no-charge / unknown action / concurrency safety) and the
/market command dispatch (browse / search / info / info-usage / run / run-usage
/ run-failure-no-charge), plus limit clamping and formatSkillCard. 22 market
tests, 470/470 in the full suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rename the user-facing catalog heading from "Agent marketplace" to
"Agent talents" (consistent with the agent_talent tool + the talent panel),
in both the /market command and the tool's list output. Default browse shows
the top 12 by popularity; when more exist the heading now reads
"top 12 of <total>" instead of silently capping.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…search

Broaden the tool description so the model reliably routes a plain-language
"find / search / recommend an agent for <domain>" request to
agent_talent{action:"list", query}, not only the agent's own sub-task needs.
Verified live (Anthropic Haiku 4.5) among Franklin's real toolset: NL requests
in English and Chinese route to agent_talent list with a sensible query, the
model picks it over WebSearch for "find me an agent", and an unrelated question
triggers no marketplace call.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
agent_talent run spends USDC from the wallet with no refund, so it now goes
through the permission prompt (behavior "ask") like the other paid,
irreversible tools (VoiceCall, BuyPhoneNumber) — previously it fell through to
the generic default that dumped raw args. The prompt now reads:

  Hire 'yield-radar' from the agent marketplace — pays from your wallet
  (USDC on Base), charged only on a successful run.

action="list" (browse/search) is a free read, so it auto-allows with no prompt.
In --trust mode both still auto-allow, matching the existing policy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lugs whole

The list rows hard-sliced the description to 40 chars, cutting mid-word
("Live stablecoin yields ranked across cha"). Truncate at the last word
boundary with an ellipsis instead ("...across…"), and stop slicing the slug —
it is the identifier the user types into `/market run <slug>`, so a cut slug
was unusable. Same bug class, fixed in both spots; short descriptions and short
slugs are unaffected and columns still align.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Remove the "N runs" stat from the /market list rows, the /market info card,
and the agent_talent list output. The catalog is still ordered by popularity
(the discovery API sorts by run_count server-side) — the count is just no
longer shown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The catalog's ordering contract on every surface (the /market list, the
agent_talent tool, the future web panel) is most-called-first. The discovery
API already sorts by run_count desc, but the CLI takes a top-N slice, so make
the ordering explicit and self-contained: fetchCatalog stable-sorts by
run_count desc before slicing/filtering. Regression test locks it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant