Repository navigation
Import marketplace - #40
Merged
Merged
Conversation
One pipeline for every way an Agent App arrives: a package (the app's framework files, never credentials, runtime state or data), a marketplace catalogue delivered the way CraftBot already reads it (raw catalogue.json, then the app's folder from the branch archive), and zip, folder, GitHub and git sources. Install acquires into staging, inspects, sanitizes, re-vendors from a locally installed toolkit, customizes, places atomically, registers with a new identity and provenance, installs dependencies, gates and serves. Marketplace apps are catalogued (no walk-verify); every other source is untrusted. inspect, export and --events complete the CLI contract; schemas for the catalogue, the inspect report and manifest provenance.
The starter now targets PocketBase 0.39.7, the version CraftBot and the
marketplace apps run, instead of 0.26.x.
- The adapter needed no API rewrite: nothing it uses in the JSVM API
changed between 0.26.6 and 0.39.7 (type definitions compared, flags
and superuser/migrate commands checked on the real binary).
- Behaviour changes in that range are handled and documented:
- API rules now run before record hooks (0.27), so an app's create
rule must not depend on the owner field the guard fills;
- raw $app.db() writes go to a single write connection (0.28),
audited for deadlocks inside transactions.
- `node pb-serve.mjs --fetch` downloads the pinned release for this
OS/arch, checks its SHA-256 against hashes embedded in the launcher
(taken from the release's checksums.txt), extracts only the binary
through a .partial file, confirms its version and renames it into
place. It does nothing when 0.39.7 is already there, and refuses an
OS/arch the release doesn't ship. pipeline.install runs it, so an
installed app needs no manual download.
- A database created on 0.26.6 keeps its accounts, sessions, ownership
and tasks under 0.39.7.
Rules self-test passes; the PocketBase e2e passes 104/104 (a new check
that install fetches nothing when the binary is present); the
multi-user suite passes 65/65; the starter suite is unchanged at 20/32.
Any HTTP app now runs unchanged behind the framework's sidecar adapter, and agents operate it over A2App with the full 0.2 auth (accounts, delegated credentials, the ceiling, device sign-in, task credentials), inherited from adapter-core. - @a2app/reverse-proxy is now runnable (`a2app-sidecar [<dir>]`). It reads sidecar.json, starts the upstream from an argv (never a shell) with PORT and every A2APP_* variable removed from its environment, waits for its health path, then serves A2App on the app's port under the network policy, with .agent-token as the admin credential, authMode from the manifest, the account page and a durable state store. Declared operations are forwarded (path params escaped, query or JSON body, nothing of the caller forwarded, per-call timeout, 5 MiB response cap, clean error envelopes). The app's exit takes the sidecar down; stopping the sidecar stops the app. - `a2app-sidecar --check` is the gate: every declared operation has a mapping and every mapping a declaration, path params declared and required, no GET with a body, a sound upstream declaration. - blueprint-sidecar: framework files, sidecar.json, the account page, and how an agent adopts an app (source read-only in upstream/, start and health declared, the API mapped into modules and operations). It is operate-only: the app's own UI stays at its own address. - The package is published like adapter-core; the toolkit is in the workspace and the conformance Toolkit class (87/87). Tests: reverse-proxy 45 checks, sidecar 65 checks (stable across repeated Windows runs after ending by draining the event loop instead of process.exit, which aborted Node while the app's handle closed), and an end-to-end adoption of a small foreign app (52 checks).
The CLI side of spec/v0_2/packaging.md: one pipeline for every way an Agent App arrives, so every harness gets the same result. - `agent-app catalogue [--search] [--source]`: the marketplace's apps, each marked compatible, incompatible (with why) or unknown. The default marketplace falls back from agent-app-collection to living-ui-marketplace, as CraftBot does, and says so. - `agent-app inspect <id> | --from <source>`: what a source is (agent-app, living-ui or foreign), whether it installs, what its toolkit will run, what would be stripped, and the route (install, adopt, convert) when it doesn't. - `agent-app install <id> | --from <zip|folder|github:…|git+…>`: acquire → inspect → sanitize → revendor → customize → place → register → dependencies → gate → serve → open, with --events for progress. Marketplace apps arrive the way CraftBot delivers them (catalogue.json, then the app's folder from the branch archive) and are trusted as catalogued; every other source is untrusted and owes a walk-verify. A failure leaves nothing registered or half-placed. - `agent-app <dir> export` writes a package that installs elsewhere; `agent-app <dir> import` is the same pipeline in place. Safety the old import and CraftBot's installer lacked: - credentials (at any depth), runtime state, the data directory and build output are never carried over; - system files come only from a toolkit installed here, never from one the package names or plants, and stray files in system folders are dropped; - extraction refuses zip-slip, absolute and device paths, links, encrypted entries and oversize archives; - downloads are capped while streaming and their sha256 recorded as provenance in the manifest; - placeholder values are escaped per file type, or refused before any file is written; - git runs with no prompts and no hooks. Zip is read and written with Node's zlib (deflate/stored, data descriptors, zip64, UTF-8 names) streaming entry by entry, so no dependency is added. The describe cache is now kept per credential, under a hash of it, so a walk never shows one agent another's reach. Tests (no network; a loopback fake of GitHub): zip 28, package rules 14, install 24, describe cache; every existing CLI test still passes.
The gate's describe-budget and multi-user-access checks need the app
up, so during install they came back unchecked (and printed connection
refused). install now runs them after serve instead: a result whose
gate is {ok:true} has really been checked. An app that fails them —
say a multi-user app with sign-in off — is stopped and reported, and
stays registered so it can be fixed, as a gate failure does.
stop's work is now stopServed(), which returns its outcome without
printing, so install can stop an app and still answer with one JSON
document.
Proven end to end from a local marketplace: a react-node app (65/65
multi-user, 32/32 starter) and a PocketBase app whose install fetched
and verified PocketBase 0.39.7 itself (65/65, 20/32 as on any
PocketBase app).
…ketBase 0.39.7 Records the install pipeline and its commands, adopting with blueprint-sidecar, the PocketBase 0.39.7 upgrade and how existing apps take it, the hardened import, the per-credential describe cache, and corrects the PocketBase starter-suite count (20/32). The conformance Toolkit row for pocketbase-react no longer claims the binary is added by hand.
Every surface calls the same CLI (catalogue, inspect, install, export),
so an app installed from OpenClaw, Hermes, dsh, CraftBot, Claude Code or
Pi arrives exactly as one installed from a terminal; nothing re-runs
the pipeline itself.
- integration-starter (the shared engine): five tools —
agent_app_catalogue, _inspect, _install (its description explains
trust and what `next` owes), _export, _list_apps; runInstall, which
reports each --events step; install jobs and private, capped uploads
for manager UIs; one PackageApi holding the manager routes. Its verb
router now covers every framework verb and is tested against the
built CLI's own commands; all eight toolkits are listed; install,
import and adopt kick off the importer skill.
- Claude Code (MCP): the 22 tools; any non-zero exit is an error that
keeps the CLI's own words.
- OpenClaw, Hermes (dashboard and webui) and dsh: Marketplace and Import
panels beside the build form.
- Marketplace: search, tags, compatibility, a form for customizable
fields, and install with step-by-step progress, polled from a job
so it survives reloads and has no client timeout.
- Import: a zip, folder or git source is inspected before install,
and Living UI or foreign code is handed to an agent to convert or
adopt.
- CraftBot: marketplace_list, marketplace_install, inspect and import
under CraftBot's own action names, so its agents keep working when
CraftBot moves to this framework; find and run_operation declare the
fields they read; the install hint names agent-app-framework.
- Hermes gains the same tools, routes and jobs in its Python engine;
dsh's tools are run by the engine, so each reaches the binary that
owns it.
- The importer skill is rewritten around the real commands: marketplace
(catalogue, confirm, install; no walk-verify), packages (inspect,
show, ask, install, walk-verify by a separate agent), Living UI and
foreign code (convert, or adopt with blueprint-sidecar), export. The
/agent-app prompts and the Claude Code plugin route these to it.
Tests: engine and packages (the real install path through the tools),
MCP, OpenClaw, dsh, Pi, Hermes (48 tests, system Python and the FastAPI
venv), CraftBot (5 tests, which fail on the old schema bugs); the three
manager pages checked in headless Chrome.
Converting a Living UI app or foreign code starts from its source kept read-only in reference/source/, and the importer skill had to tell the agent to fetch a marketplace folder by hand. `agent-app inspect … --keep <dir>` now keeps the inspected source there, from any source, exactly as a package would carry it: no credentials, secrets, runtime state, data, .git/, node_modules/ or build output, and links never followed. The report gains `kept`; the skill's convert steps use it. Test: a Living UI marketplace app kept without its published .superuser, and a non-empty --keep refused (install 26/26).
…efused
Found walking the whole user journey with the real CLIs:
- owner, invite and credential list/mint/revoke printed their result as
plain lines on stdout, against the CLI's contract that stdout carries
one JSON result. They now answer { ok, role, url, expiresAt },
{ ok, credentials }, { ok, token, credential } (the token's only
appearance) and { ok, revoked }; the human lines stay on stderr.
- whoami turned every refusal into "whoami unavailable (adapter
predates IAM, or credential rejected)", and data reported a revoked
credential as "No entity". Both now lead with the app's own code
(credential_revoked, token_expired, principal_inactive,
missing_required, …) and pass on its how-to-recover hint, so an agent
can take the step the operator skill names for that code.
The journey (setup, build, people, operate, connect, credentials, the
bridge, evolve, export and install, teardown) passes 53/53 end to end.
- bridge: a refused heartbeat is read, not assumed. A run that completed its own task is left to exit instead of being killed as claim_lost, and the log names who each run acts as. - Bundled blueprints keep their .gitignore (packed as _gitignore). pb-serve --fetch keeps a binary only when its SHA-256 is the pinned release's, never by running it. - PocketBase's describe root names the app from the manifest, not "Acme". - A remote agent with no credential is pointed at login, not .agent-token. --scopes splits on commas or spaces (PowerShell joins a,b into "a b"). - scaffold needs --blueprint; agent-app blueprints lists them; dev --install. - data create/update take field=value; tasks complete --summary; usage lines for tasks, data, dev, serve, login and remove say what they take. - remove keeps the app's own backups. The harness build tool takes authMode. - The Claude Code MCP server no longer overrides the built-in bridge profile. - Blueprint guides: how the View runs an operation and finds who is signed in. - The CLI reports the version in its own package.json.
All five go out together at 0.2.0 (protocol 0.2), so `npm i -g agent-app-framework` no longer pulls the 0.1 alphas. The react-node and sidecar blueprints depend on ^0.2.0, which the published packages satisfy.
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.
Allow user to import agent app from the marketplace. However, might need revamp we if stop relying on the github repo as the only source.
It will not work now because the living-ui-marketplace (agent-app-marketplace) repo is still using the older framework files.