# Kura agent guide

Audience: **agents**, not humans. Humans use the browser UI.

This document is the AI-friendly entry for Kura (仓). Product package name remains `assetsSrcAPI`.

## Start here

1. Read the machine descriptor: `GET {base}/api/query`  
   Response has `kind: "descriptor"`, `audience: "agent"`, protocol `kura.query/v1`.
2. Discover packs with that protocol (or the thin GET helpers below).
3. Resolve a download plan with `GET {base}/api/fetch?...`. Prefer **origin** URLs. Do not download through Kura's CDN when origin works.
4. Download bytes from the origin zip/archive yourself (or via `import-to-headless.mjs` on the user machine).

**Base URL:** `https://kuroneko.chat/assets`  
All paths below are relative to this base (for example `GET https://kuroneko.chat/assets/api/query`).

## What is in the catalog (mini-game direction)

Current sources:

| Provider | Id | Content |
|----------|----|---------|
| KayKit | `kaykit` | CC0 stylized character / prop / level **kits** (whole GitHub pack) |
| Kenney | `kenney` | CC0 game **packs** from kenney.nl (includes Hexagon Kit) |

Not for mini-games in this catalog: Poly Haven HDRIs / photogrammetry, ambientCG scans.

Search for **what the pack is for** (`dungeon`, `hexagon`, `character`), not for smaller file sizes.

## Protocol: `kura.query/v1`

One query document for every source. Rejected field: `native` (provider-specific filters).

| | |
|--|--|
| Describe | `GET /api/query` |
| Execute GET | `GET /api/query?text=hexagon&providerIds=kenney&kinds=model` |
| Execute POST | `POST /api/query` with JSON body |

Body / query fields: `scope` (`discover` \| `search`), `text`, `kinds`, `tags`, `facets`, `providerIds`, `rights.*`, `target.*`, `constraints.*`, `limit` (default 20, max 100), `offset`.

- `discover`: federated provider search (use this first).
- `search`: assets already ingested into the pool.
- `text`: case-insensitive; every whitespace-separated term must match.

Example:

```http
GET /api/query?scope=discover&text=hexagon&providerIds=kenney&limit=10
```

```http
POST /api/query
Content-Type: application/json

{
  "protocol": "kura.query/v1",
  "scope": "discover",
  "query": {
    "text": "dungeon",
    "providerIds": ["kaykit"],
    "kinds": ["model"],
    "limit": 10
  }
}
```

## Fetch: `kura.fetch/v1`

```http
GET /api/fetch?providerId=kenney&externalId=hexagon-kit
```

Order is always `origin` then `vault`. Use `files[].url` (origin) when present. Vault is only a fallback if a local copy already exists.

Thin helpers (same pool, older clients):

| | |
|--|--|
| Providers | `GET /api/providers` |
| Discover | `GET /api/discover?providerId=kenney&text=hexagon` |
| Resolve | `GET /api/resolve?providerId=kenney&externalId=hexagon-kit` |
| Package | `GET /api/package?providerId=kenney&externalId=hexagon-kit` |

## Typical agent loop

```text
GET /api/query  →  learn fields
GET/POST /api/query?…  →  pick externalId
GET /api/fetch?providerId=…&externalId=…  →  origin zip URL
download origin zip on the caller machine
(optional) node tools/import-to-headless.mjs --project $GAME --id <externalId>
```

Do **not**:

- Put main-account cloud API keys in prompts
- Proxy large packs through Kura when origin works
- Filter by “small file” as a stand-in for mini-games
- Pass `native` filters

## Related docs

- Headless Cocos import: [`HEADLESS-IMPORT.md`](HEADLESS-IMPORT.md)
- Catalog ops: [`../deploy/kuroneko/README.md`](../deploy/kuroneko/README.md)
