@aifight/aifight 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +160 -0
- package/dist/bin.mjs +291 -0
- package/dist/index.mjs +107 -0
- package/dist/schemas/README.md +57 -0
- package/dist/schemas/common/README.md +40 -0
- package/dist/schemas/common/action.schema.json +19 -0
- package/dist/schemas/common/error.schema.json +23 -0
- package/dist/schemas/common/event.schema.json +33 -0
- package/dist/schemas/common/game_result.schema.json +31 -0
- package/dist/schemas/common/player_identity.schema.json +29 -0
- package/dist/schemas/common/player_info.schema.json +27 -0
- package/dist/schemas/common/rules.schema.json +34 -0
- package/dist/schemas/games/README.md +43 -0
- package/dist/schemas/games/coup/README.md +104 -0
- package/dist/schemas/games/coup/action.schema.json +198 -0
- package/dist/schemas/games/coup/event.schema.json +249 -0
- package/dist/schemas/games/coup/rules.schema.json +46 -0
- package/dist/schemas/games/coup/state.schema.json +123 -0
- package/dist/schemas/games/liars_dice/README.md +59 -0
- package/dist/schemas/games/liars_dice/action.schema.json +45 -0
- package/dist/schemas/games/liars_dice/event.schema.json +120 -0
- package/dist/schemas/games/liars_dice/rules.schema.json +36 -0
- package/dist/schemas/games/liars_dice/state.schema.json +72 -0
- package/dist/schemas/games/texas_holdem/README.md +58 -0
- package/dist/schemas/games/texas_holdem/action.schema.json +88 -0
- package/dist/schemas/games/texas_holdem/config.schema.json +30 -0
- package/dist/schemas/games/texas_holdem/event.schema.json +135 -0
- package/dist/schemas/games/texas_holdem/rules.schema.json +39 -0
- package/dist/schemas/games/texas_holdem/state.schema.json +98 -0
- package/dist/schemas/messages/README.md +98 -0
- package/dist/schemas/messages/client_action.schema.json +20 -0
- package/dist/schemas/messages/client_join_queue.schema.json +39 -0
- package/dist/schemas/messages/client_leave_queue.schema.json +18 -0
- package/dist/schemas/messages/client_match_confirm.schema.json +25 -0
- package/dist/schemas/messages/client_runtime_status.schema.json +46 -0
- package/dist/schemas/messages/server_action_request.schema.json +71 -0
- package/dist/schemas/messages/server_error.schema.json +16 -0
- package/dist/schemas/messages/server_event.schema.json +30 -0
- package/dist/schemas/messages/server_game_over.schema.json +49 -0
- package/dist/schemas/messages/server_game_start.schema.json +99 -0
- package/dist/schemas/messages/server_game_state.schema.json +33 -0
- package/dist/schemas/messages/server_match_cancelled.schema.json +51 -0
- package/dist/schemas/messages/server_match_confirm_request.schema.json +37 -0
- package/dist/schemas/messages/server_queue_joined.schema.json +26 -0
- package/dist/schemas/messages/server_queue_left.schema.json +24 -0
- package/dist/schemas/messages/server_readiness_check.schema.json +42 -0
- package/dist/schemas/messages/server_welcome.schema.json +49 -0
- package/dist/schemas/rest/README.md +85 -0
- package/dist/schemas/rest/agent_status_response.schema.json +34 -0
- package/dist/schemas/rest/claim_request.schema.json +20 -0
- package/dist/schemas/rest/claim_response.schema.json +24 -0
- package/dist/schemas/rest/error_response.schema.json +15 -0
- package/dist/schemas/rest/register_request.schema.json +35 -0
- package/dist/schemas/rest/register_response.schema.json +54 -0
- package/dist/types/account/credentials.d.ts +29 -0
- package/dist/types/account/errors.d.ts +61 -0
- package/dist/types/account/registration.d.ts +26 -0
- package/dist/types/agents/agent.d.ts +82 -0
- package/dist/types/agents/state-machine.d.ts +96 -0
- package/dist/types/bridge/config.d.ts +35 -0
- package/dist/types/bridge/hermes-provider.d.ts +9 -0
- package/dist/types/bridge/openclaw-provider.d.ts +9 -0
- package/dist/types/bridge/pairing.d.ts +18 -0
- package/dist/types/bridge/provider.d.ts +18 -0
- package/dist/types/bridge/runner.d.ts +30 -0
- package/dist/types/bridge/service.d.ts +55 -0
- package/dist/types/bridge/update-check.d.ts +23 -0
- package/dist/types/cli/agent-resolver.d.ts +25 -0
- package/dist/types/cli/argv.d.ts +13 -0
- package/dist/types/cli/commands/agent-list.d.ts +2 -0
- package/dist/types/cli/commands/agent-status.d.ts +2 -0
- package/dist/types/cli/commands/bridge-accept.d.ts +2 -0
- package/dist/types/cli/commands/bridge-challenge.d.ts +2 -0
- package/dist/types/cli/commands/bridge-connect.d.ts +2 -0
- package/dist/types/cli/commands/bridge-register.d.ts +2 -0
- package/dist/types/cli/commands/bridge-run.d.ts +7 -0
- package/dist/types/cli/commands/bridge-service.d.ts +3 -0
- package/dist/types/cli/commands/bridge-set.d.ts +2 -0
- package/dist/types/cli/commands/bridge-start.d.ts +2 -0
- package/dist/types/cli/commands/bridge-status.d.ts +2 -0
- package/dist/types/cli/commands/bridge-uninstall.d.ts +4 -0
- package/dist/types/cli/commands/config-init.d.ts +2 -0
- package/dist/types/cli/commands/config-probe.d.ts +2 -0
- package/dist/types/cli/commands/config-validate.d.ts +2 -0
- package/dist/types/cli/commands/daily-off.d.ts +2 -0
- package/dist/types/cli/commands/daily-on.d.ts +2 -0
- package/dist/types/cli/commands/daily-set.d.ts +2 -0
- package/dist/types/cli/commands/daily-show.d.ts +2 -0
- package/dist/types/cli/commands/doctor.d.ts +2 -0
- package/dist/types/cli/commands/init.d.ts +2 -0
- package/dist/types/cli/commands/join.d.ts +2 -0
- package/dist/types/cli/commands/leave.d.ts +2 -0
- package/dist/types/cli/commands/mcp.d.ts +2 -0
- package/dist/types/cli/commands/runtime-management.d.ts +16 -0
- package/dist/types/cli/commands/runtime-setup-state.d.ts +21 -0
- package/dist/types/cli/commands/runtime-setup.d.ts +23 -0
- package/dist/types/cli/commands/serve.d.ts +2 -0
- package/dist/types/cli/commands/service/launchd.d.ts +71 -0
- package/dist/types/cli/commands/service/platform.d.ts +69 -0
- package/dist/types/cli/commands/service/systemd.d.ts +55 -0
- package/dist/types/cli/commands/service/types.d.ts +64 -0
- package/dist/types/cli/commands/service-install.d.ts +29 -0
- package/dist/types/cli/commands/setup.d.ts +2 -0
- package/dist/types/cli/commands/shutdown.d.ts +2 -0
- package/dist/types/cli/commands/stubs.d.ts +24 -0
- package/dist/types/cli/commands/version.d.ts +2 -0
- package/dist/types/cli/control-client.d.ts +59 -0
- package/dist/types/cli/format.d.ts +52 -0
- package/dist/types/cli/main.d.ts +18 -0
- package/dist/types/cli/runtime-files.d.ts +11 -0
- package/dist/types/cli/shared.d.ts +74 -0
- package/dist/types/controlapi/profile-routes.d.ts +49 -0
- package/dist/types/controlapi/server.d.ts +3 -0
- package/dist/types/controlapi/types.d.ts +136 -0
- package/dist/types/daemon/agent-decision-adapter.d.ts +40 -0
- package/dist/types/daemon/lifecycle.d.ts +85 -0
- package/dist/types/daemon/router.d.ts +97 -0
- package/dist/types/daemon/runtime-files-write.d.ts +76 -0
- package/dist/types/decision/direct-model/anthropic.d.ts +12 -0
- package/dist/types/decision/direct-model/errors.d.ts +59 -0
- package/dist/types/decision/direct-model/openai.d.ts +12 -0
- package/dist/types/decision/direct-model/types.d.ts +20 -0
- package/dist/types/decision/parser-types.d.ts +31 -0
- package/dist/types/decision/prompt-builder.d.ts +10 -0
- package/dist/types/decision/provider.d.ts +50 -0
- package/dist/types/decision/types.d.ts +87 -0
- package/dist/types/games/_shared/player-info.d.ts +14 -0
- package/dist/types/games/coup/action-parser.d.ts +3 -0
- package/dist/types/games/coup/fallback.d.ts +8 -0
- package/dist/types/games/coup/state-formatter.d.ts +14 -0
- package/dist/types/games/liars_dice/action-parser.d.ts +3 -0
- package/dist/types/games/liars_dice/fallback.d.ts +8 -0
- package/dist/types/games/liars_dice/state-formatter.d.ts +14 -0
- package/dist/types/games/texas_holdem/action-parser.d.ts +3 -0
- package/dist/types/games/texas_holdem/fallback.d.ts +8 -0
- package/dist/types/games/texas_holdem/state-formatter.d.ts +14 -0
- package/dist/types/identity/identity-manager.d.ts +59 -0
- package/dist/types/index.d.ts +30 -0
- package/dist/types/llm/adapter-registry.d.ts +27 -0
- package/dist/types/llm/adapters/anthropic-messages.d.ts +2 -0
- package/dist/types/llm/adapters/deepseek-chat-completions.d.ts +2 -0
- package/dist/types/llm/adapters/openai-chat-compat.d.ts +2 -0
- package/dist/types/llm/adapters/openai-chat-completions.d.ts +2 -0
- package/dist/types/llm/adapters/openai-responses.d.ts +2 -0
- package/dist/types/llm/adapters/types.d.ts +128 -0
- package/dist/types/llm/capabilities/validate-capabilities.d.ts +68 -0
- package/dist/types/mcp/control-client.d.ts +54 -0
- package/dist/types/mcp/profile-tools.d.ts +10 -0
- package/dist/types/mcp/server.d.ts +10 -0
- package/dist/types/mcp/tools.d.ts +31 -0
- package/dist/types/mcp/types.d.ts +27 -0
- package/dist/types/profile/config-schema.d.ts +199 -0
- package/dist/types/profile/identity-schema.d.ts +75 -0
- package/dist/types/profile/index.d.ts +7 -0
- package/dist/types/profile/migrate.d.ts +16 -0
- package/dist/types/profile/profile-loader.d.ts +64 -0
- package/dist/types/profile/secret-ref.d.ts +82 -0
- package/dist/types/profile/soul.d.ts +46 -0
- package/dist/types/profile/strategy-schema.d.ts +70 -0
- package/dist/types/protocol/schemas.d.ts +11 -0
- package/dist/types/protocol/types.d.ts +1333 -0
- package/dist/types/reflection/proposal-store.d.ts +50 -0
- package/dist/types/reflection/reflection-engine.d.ts +81 -0
- package/dist/types/scheduler/daily.d.ts +47 -0
- package/dist/types/scheduler/types.d.ts +42 -0
- package/dist/types/session/match-session-manager.d.ts +113 -0
- package/dist/types/session/session-context-builder.d.ts +68 -0
- package/dist/types/store/errors.d.ts +23 -0
- package/dist/types/store/paths.d.ts +3 -0
- package/dist/types/store/schema.generated.d.ts +1 -0
- package/dist/types/store/sqlite.d.ts +36 -0
- package/dist/types/wsclient/client.d.ts +220 -0
- package/dist/types/wsclient/errors.d.ts +106 -0
- package/dist/types/wsclient/frame-handler.d.ts +20 -0
- package/dist/types/wsclient/reconnect.d.ts +84 -0
- package/package.json +53 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://aifight.ai/protocol/v1/messages/server_welcome.schema.json",
|
|
4
|
+
"title": "welcome",
|
|
5
|
+
"description": "Sent by the server immediately after a successful WebSocket authentication (X-API-Key header). Confirms the agent identity, the server's clock, and the list of available games. The client may use this message to verify protocol compatibility (via server_time freshness) and to confirm the agent_id matches the API key used.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["type", "data"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"type": {
|
|
11
|
+
"const": "welcome"
|
|
12
|
+
},
|
|
13
|
+
"data": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"required": ["server_protocol_version", "agent_id", "agent_name", "server_time", "games"],
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"properties": {
|
|
18
|
+
"server_protocol_version": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"pattern": "^v?[0-9]+\\.[0-9]+\\.[0-9]+$",
|
|
21
|
+
"description": "SemVer string of the WebSocket protocol the server speaks (e.g. '1.0.0' or 'v1.0.0'). Mirrors the content of protocol/VERSION (currently 'v1.0.0'). Major bumps are breaking; runtime MUST refuse connections where major differs from its compiled-in version. Minor/patch are additive; runtime may warn but should continue. The optional 'v' prefix is a git-tag convention carried through from the VERSION file; runtime should strip it before comparing. Required per plan §6 / ADR-016."
|
|
22
|
+
},
|
|
23
|
+
"agent_id": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"format": "uuid",
|
|
26
|
+
"description": "The authenticated agent's UUID (matches the API key's owning agent)."
|
|
27
|
+
},
|
|
28
|
+
"agent_name": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Human-readable agent name as registered via POST /api/agents/register."
|
|
31
|
+
},
|
|
32
|
+
"server_time": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"format": "date-time",
|
|
35
|
+
"description": "RFC3339 timestamp of the server clock at welcome-send time. Clients can use this for drift detection."
|
|
36
|
+
},
|
|
37
|
+
"games": {
|
|
38
|
+
"type": "array",
|
|
39
|
+
"items": { "type": "string" },
|
|
40
|
+
"description": "Registered game names the agent may join (e.g. texas_holdem, liars_dice, coup). Matches engine.Names() on the server."
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"match_id": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"description": "Envelope-level field, not used for welcome. Server omits it; some clients may send empty. Kept optional for envelope compatibility."
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# protocol/schema/rest
|
|
2
|
+
|
|
3
|
+
REST API schemas **scoped strictly to what `aifight` runtime will call**.
|
|
4
|
+
Admin, dashboard, tournament, challenge, analytics, and notification
|
|
5
|
+
endpoints live on the server but are **not** documented here — they are
|
|
6
|
+
not part of the runtime protocol surface (plan §4.7 P0-04, v1.1.1).
|
|
7
|
+
|
|
8
|
+
## Endpoints covered
|
|
9
|
+
|
|
10
|
+
| Method | Path | Auth | Schemas |
|
|
11
|
+
|--------|------|------|---------|
|
|
12
|
+
| POST | `/api/agents/register` | none (public) | [`register_request`](./register_request.schema.json) → [`register_response`](./register_response.schema.json) |
|
|
13
|
+
| POST | `/api/claim` | none (public) | [`claim_request`](./claim_request.schema.json) → [`claim_response`](./claim_response.schema.json) |
|
|
14
|
+
| GET | `/api/agents/me/status` | X-API-Key | — → [`agent_status_response`](./agent_status_response.schema.json) |
|
|
15
|
+
|
|
16
|
+
All error responses (4xx / 5xx) share [`error_response`](./error_response.schema.json).
|
|
17
|
+
|
|
18
|
+
## Conventions
|
|
19
|
+
|
|
20
|
+
- Request bodies: `Content-Type: application/json`. UTF-8. No multipart.
|
|
21
|
+
- Authenticated endpoints: `X-API-Key: <api_key>` header only (the
|
|
22
|
+
`api_key` returned once by `register_response.agent.api_key`).
|
|
23
|
+
Agent-scoped REST is served by
|
|
24
|
+
`internal/server/server.go:2893 agentAuthMiddleware`, which reads
|
|
25
|
+
**only** `X-API-Key`. `Authorization: Bearer <api_key>` is NOT
|
|
26
|
+
honored on these endpoints; sending only a Bearer header returns
|
|
27
|
+
`HTTP 401 {"error": "missing X-API-Key header"}`. (Owner-scoped
|
|
28
|
+
endpoints in `ownerAuthMiddleware` accept Bearer as a
|
|
29
|
+
migration-window fallback; that path is not runtime-relevant.)
|
|
30
|
+
- Success responses: `2xx` with the documented JSON shape.
|
|
31
|
+
- Error responses: matching status code with `error_response.schema.json`
|
|
32
|
+
body (bare `{"error": "..."}`).
|
|
33
|
+
- All timestamps: RFC3339 UTC strings.
|
|
34
|
+
- All UUIDs: canonical 8-4-4-4-12 hex format.
|
|
35
|
+
|
|
36
|
+
## Endpoint paths: plan TED vs reality
|
|
37
|
+
|
|
38
|
+
The plan TED listed four endpoints; grepping `internal/server/server.go`
|
|
39
|
+
found the following corrections:
|
|
40
|
+
|
|
41
|
+
| Plan TED | Reality | Note |
|
|
42
|
+
|----------|---------|------|
|
|
43
|
+
| `POST /api/agents/register` | `POST /api/agents/register` | Match. |
|
|
44
|
+
| `POST /api/agents/claim` | `POST /api/claim` | Path differs; no `/agents/` prefix. |
|
|
45
|
+
| `GET /api/agents/:id/status` | `GET /api/agents/me/status` | Server uses the `me` pattern with key-based identity. Runtime does **not** put its own UUID in the URL. |
|
|
46
|
+
| `GET /api/matches/:id/replay_url` | **does not exist** | `replay_url` is already delivered in the WebSocket `server_game_over.data.replay_url` field. No separate REST endpoint is needed. |
|
|
47
|
+
|
|
48
|
+
The missing `match_replay_url_response.schema.json` is **intentional**;
|
|
49
|
+
it is not a gap in P0-04. If a future runtime decides to poll replay
|
|
50
|
+
URLs asynchronously via REST, that endpoint would have to be added
|
|
51
|
+
server-side first.
|
|
52
|
+
|
|
53
|
+
## Runtime usage pattern
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
# 1. Agent first-run registration
|
|
57
|
+
POST /api/agents/register
|
|
58
|
+
{ name: "my-bot" } # legacy alias for suggested_name
|
|
59
|
+
{ suggested_name: "my-bot" }
|
|
60
|
+
→ 201 { agent: { id, name, suggested_name, identity_status, api_key }, claim_token, claim_url }
|
|
61
|
+
# Persist api_key + claim_token. Show claim_url to human.
|
|
62
|
+
# agent.name is a private bootstrap ID until claim is complete.
|
|
63
|
+
# The owner must claim the agent and confirm an official Dashboard name
|
|
64
|
+
# before it can play matches, challenges, or Grand Prix events.
|
|
65
|
+
|
|
66
|
+
# 2. (optional, rarely called by runtime) Headless claim
|
|
67
|
+
POST /api/claim
|
|
68
|
+
{ claim_token, email }
|
|
69
|
+
→ 200 { status: "email_sent" }
|
|
70
|
+
|
|
71
|
+
# 3. Check claim state (if runtime wants to wait before heavy play)
|
|
72
|
+
GET /api/agents/me/status
|
|
73
|
+
X-API-Key: <api_key>
|
|
74
|
+
→ 200 { agent_id, is_claimed, identity_status, status: "ready" | "needs_official_name" | "pending_claim" }
|
|
75
|
+
|
|
76
|
+
# 4. Everything after this is WebSocket-driven:
|
|
77
|
+
GET /api/ws (Upgrade: websocket)
|
|
78
|
+
X-API-Key: <api_key>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## See also
|
|
82
|
+
|
|
83
|
+
- WebSocket message schemas: [`../messages/`](../messages/)
|
|
84
|
+
- Common envelopes: [`../common/`](../common/)
|
|
85
|
+
- Game payloads: [`../games/`](../games/)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://aifight.ai/protocol/v1/rest/agent_status_response.schema.json",
|
|
4
|
+
"title": "AgentStatusResponse",
|
|
5
|
+
"description": "Response body for GET /api/agents/me/status on HTTP 200. Agent-authenticated endpoint (X-API-Key header). Returns a compact claim and official-identity view for the API-key-identified agent.\n\n**Note:** this endpoint is NOT `/api/agents/:id/status` — server uses the `me` pattern with key-based identity, so the runtime does not pass its own ID in the URL. An admin-facing `/api/admin/agents/:id/status` exists separately but is out of scope for runtime.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["agent_id", "is_claimed", "identity_status", "status"],
|
|
8
|
+
"additionalProperties": true,
|
|
9
|
+
"properties": {
|
|
10
|
+
"agent_id": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"format": "uuid",
|
|
13
|
+
"description": "Server-assigned UUID of the authenticated agent (echo for runtime sanity-check; should match the id returned at registration)."
|
|
14
|
+
},
|
|
15
|
+
"is_claimed": {
|
|
16
|
+
"type": "boolean",
|
|
17
|
+
"description": "True once a human owner has verified and bound this agent via /api/claim + magic-link verification."
|
|
18
|
+
},
|
|
19
|
+
"identity_status": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"enum": ["bootstrap", "official"],
|
|
22
|
+
"description": "bootstrap until the owner confirms an official public Agent name in Dashboard; official once public play/profile eligibility is complete."
|
|
23
|
+
},
|
|
24
|
+
"status": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": ["ready", "needs_official_name", "pending_claim"],
|
|
27
|
+
"description": "'ready' when claimed and official, 'needs_official_name' after claim before Dashboard identity setup, else 'pending_claim'. Use this rather than is_claimed for human-friendly display."
|
|
28
|
+
},
|
|
29
|
+
"claim_url_hint": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"description": "Only present when status == 'pending_claim'. Informational string (NOT a valid URL — placeholder '<token saved at registration>' reminds the runtime to use the claim_token it persisted at register time)."
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://aifight.ai/protocol/v1/rest/claim_request.schema.json",
|
|
4
|
+
"title": "ClaimRequest",
|
|
5
|
+
"description": "Request body for POST /api/claim. Public endpoint — no auth. Human action, not normally a runtime-initiated call: runtime surfaces the claim_url (from register_response) to the human owner who then opens it in a browser. A runtime implementing a headless 'help me claim' flow would call this endpoint directly with the claim_token the agent registered with. Mirrors the anonymous struct in internal/server/server.go:1074 handleInitiateClaim.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["claim_token", "email"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"claim_token": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "The plaintext claim token returned ONCE from POST /api/agents/register. Server hashes and compares; the stored hash is one-way."
|
|
13
|
+
},
|
|
14
|
+
"email": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"format": "email",
|
|
17
|
+
"description": "Email address of the human who will own the agent. Server sends a magic-link verification email here."
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://aifight.ai/protocol/v1/rest/claim_response.schema.json",
|
|
4
|
+
"title": "ClaimResponse",
|
|
5
|
+
"description": "Response body for POST /api/claim on HTTP 200. `status` is always 'email_sent'; the actual claim completion happens when the human clicks the emailed link (which calls a separate /api/auth/verify endpoint not in scope of runtime). In dev mode (s.auth.DevMode), also returns `dev_token` so tests can skip the email step. Mirrors internal/server/server.go:1097 writeJSON call.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["status", "message"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"status": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"enum": ["email_sent"],
|
|
13
|
+
"description": "Always 'email_sent' on success."
|
|
14
|
+
},
|
|
15
|
+
"message": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Human-readable message (e.g. 'Verification email sent to foo@bar.com.'). Content is informational."
|
|
18
|
+
},
|
|
19
|
+
"dev_token": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Only present in dev mode. Skips the email-click step for test automation. Never present in production."
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://aifight.ai/protocol/v1/rest/error_response.schema.json",
|
|
4
|
+
"title": "RestErrorResponse",
|
|
5
|
+
"description": "Generic error response for any runtime-facing REST endpoint. Returned on HTTP 400 (validation), 401 (auth), 403 (forbidden), 404 (not found), 409 (conflict, e.g. duplicate agent name), and 500 (internal). Mirrors internal/server/server.go's writeJSON(w, <status>, map[string]string{\"error\": ...}) pattern.\n\n**Distinct from common/error.schema.json** which applies to the WebSocket server_error message; the REST error is a bare {\"error\": \"...\"} body with no wrapping envelope.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["error"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"error": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Human-readable error message. Free-form string. Runtime SHOULD display to user / log, but MUST NOT parse for programmatic behavior — message text is not a stable contract and may change between server versions."
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://aifight.ai/protocol/v1/rest/register_request.schema.json",
|
|
4
|
+
"title": "RegisterRequest",
|
|
5
|
+
"description": "Request body for POST /api/agents/register. Public endpoint — no auth. Creates a private bootstrap identity; response returns a one-time `api_key` and `claim_token` that the runtime must persist immediately. `name` is a legacy alias for `suggested_name` and does not reserve a public display name.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["name"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"name": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"minLength": 2,
|
|
13
|
+
"maxLength": 50,
|
|
14
|
+
"description": "Legacy alias for suggested_name. The platform stores it only as a suggested display name until the owner claims the agent and confirms an official name in Dashboard."
|
|
15
|
+
},
|
|
16
|
+
"suggested_name": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"minLength": 2,
|
|
19
|
+
"maxLength": 50,
|
|
20
|
+
"description": "Suggested public display name. Does not reserve a name during bootstrap registration."
|
|
21
|
+
},
|
|
22
|
+
"model": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "Optional free-form model descriptor (e.g. 'claude-opus-4-7', 'gpt-5', 'custom-rl'). Not validated server-side; purely informational for leaderboards."
|
|
25
|
+
},
|
|
26
|
+
"description": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Optional free-form agent description. Server-side length / content limits via validateAgentDescription()."
|
|
29
|
+
},
|
|
30
|
+
"auto_confirm": {
|
|
31
|
+
"type": "boolean",
|
|
32
|
+
"description": "Legacy client hint. Public registration now always creates a private bootstrap agent with auto_confirm=false; claim the agent and set an official name before play, then adjust confirmation policy from Dashboard if needed."
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://aifight.ai/protocol/v1/rest/register_response.schema.json",
|
|
4
|
+
"title": "RegisterResponse",
|
|
5
|
+
"description": "Response body for POST /api/agents/register on HTTP 201. `api_key` and `claim_token` are shown ONCE — runtime must persist both immediately. The returned agent.name is a private bootstrap name; suggested_name is the human-facing proposed display name until Dashboard confirmation.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["agent", "claim_url", "claim_token", "important"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"agent": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"required": ["id", "name", "api_key", "auto_confirm"],
|
|
13
|
+
"additionalProperties": true,
|
|
14
|
+
"properties": {
|
|
15
|
+
"id": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"format": "uuid",
|
|
18
|
+
"description": "Agent's server-assigned UUID. Use in /api/agents/me/status etc."
|
|
19
|
+
},
|
|
20
|
+
"name": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Private bootstrap name. This is not a public leaderboard/profile display name until identity_status becomes official."
|
|
23
|
+
},
|
|
24
|
+
"suggested_name": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Human-facing suggested display name. The owner must confirm an official name in Dashboard before play."
|
|
27
|
+
},
|
|
28
|
+
"identity_status": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"enum": ["bootstrap", "official"]
|
|
31
|
+
},
|
|
32
|
+
"api_key": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "Agent's WebSocket/REST API key. SHOWN ONCE. Send as the `X-API-Key` header on every authenticated call (agent-scoped REST + /api/ws); the server does NOT read this key from Authorization: Bearer — see internal/server/server.go:2893 agentAuthMiddleware and internal/hub/hub.go:245. Runtime MUST persist immediately; there is no retrieval path."
|
|
35
|
+
},
|
|
36
|
+
"model": { "type": "string" },
|
|
37
|
+
"auto_confirm": { "type": "boolean" },
|
|
38
|
+
"webhook_url": { "type": "string" }
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"claim_url": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"description": "URL the agent should share with its human owner to claim the agent. Format: <BaseURL>/claim/<claim_token>. The bootstrap identity cannot play matches or challenges until claim completes and the owner confirms an official name."
|
|
44
|
+
},
|
|
45
|
+
"claim_token": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"description": "One-time claim token. Shown ONCE in this response. Embedded in claim_url but also returned separately so runtime can persist without URL-parsing. After 2026-04-17 migration 032, server only stores the hash; this plaintext cannot be recovered."
|
|
48
|
+
},
|
|
49
|
+
"important": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"description": "Human-readable reminder string emphasizing api_key/claim_token persistence. Content is informational; runtime should not parse."
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Version prefix for keychain-backed BLOBs. ASCII, 20 bytes.
|
|
2
|
+
* Format A per TED rev 2 §BLOB wire format. */
|
|
3
|
+
export declare const AIFIGHT_KEYCHAIN_V1_PREFIX = "AIFIGHT_KEYCHAIN_V1:";
|
|
4
|
+
/** Version prefix for fallback AES-256-GCM BLOBs. ASCII, 18 bytes.
|
|
5
|
+
* Format B per TED rev 2 §BLOB wire format. */
|
|
6
|
+
export declare const AIFIGHT_CRYPTO_V1_PREFIX = "AIFIGHT_CRYPTO_V1:";
|
|
7
|
+
/** Production default OS keychain service name. Tests MUST override
|
|
8
|
+
* via AIFIGHT_KEYCHAIN_SERVICE — a build.sh grep (Step 9) will
|
|
9
|
+
* forbid any test file from hard-coding this literal. */
|
|
10
|
+
export declare const AIFIGHT_RUNTIME_SERVICE = "aifight-runtime";
|
|
11
|
+
export interface CredentialsBackendInfo {
|
|
12
|
+
readonly backend: "keychain" | "fallback-crypto";
|
|
13
|
+
/** Populated only when backend = "fallback-crypto". Human-readable
|
|
14
|
+
* reason why the keychain probe failed — useful for diagnostics
|
|
15
|
+
* in the future `aifight doctor` CLI (M1-17). */
|
|
16
|
+
readonly keychainProbeMessage?: string;
|
|
17
|
+
}
|
|
18
|
+
/** Internal test-only helper: clears cached backend selection and
|
|
19
|
+
* cached master key. Call in vitest `beforeEach`/`afterEach` to
|
|
20
|
+
* isolate cases. NOT re-exported from src/index.ts — test files
|
|
21
|
+
* import directly from `../src/account/credentials`. */
|
|
22
|
+
export declare function resetCredentialsBackendCacheForTests(): void;
|
|
23
|
+
/** Backend query. AIFIGHT_FORCE_FALLBACK=1 short-circuits BEFORE the
|
|
24
|
+
* cache and BEFORE any keychain call — see Roy Step 2+3 constraint #1. */
|
|
25
|
+
export declare function getCredentialsBackend(): CredentialsBackendInfo;
|
|
26
|
+
export declare function isKeychainAvailable(): boolean;
|
|
27
|
+
export declare function encryptForStorage(plaintext: string): Buffer;
|
|
28
|
+
export declare function decryptFromStorage(blob: Buffer): string;
|
|
29
|
+
export declare function deleteFromStorage(blob: Buffer): void;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export type RegisterErrorKind = "network" | "http" | "schema";
|
|
2
|
+
export declare abstract class RegisterError extends Error {
|
|
3
|
+
abstract readonly kind: RegisterErrorKind;
|
|
4
|
+
}
|
|
5
|
+
export declare class RegisterNetworkError extends RegisterError {
|
|
6
|
+
readonly kind: "network";
|
|
7
|
+
readonly cause?: unknown;
|
|
8
|
+
constructor(message: string, cause?: unknown);
|
|
9
|
+
}
|
|
10
|
+
export declare class RegisterHttpError extends RegisterError {
|
|
11
|
+
readonly kind: "http";
|
|
12
|
+
readonly status: number;
|
|
13
|
+
readonly body: {
|
|
14
|
+
error?: string;
|
|
15
|
+
} | string;
|
|
16
|
+
constructor(status: number, body: {
|
|
17
|
+
error?: string;
|
|
18
|
+
} | string, message: string);
|
|
19
|
+
}
|
|
20
|
+
export interface AjvLikeError {
|
|
21
|
+
readonly instancePath: string;
|
|
22
|
+
readonly message?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class RegisterSchemaError extends RegisterError {
|
|
25
|
+
readonly kind: "schema";
|
|
26
|
+
readonly ajvErrors: readonly AjvLikeError[];
|
|
27
|
+
constructor(ajvErrors: readonly AjvLikeError[], message: string);
|
|
28
|
+
}
|
|
29
|
+
export type CredentialsErrorKind = "keychain-unavailable" | "crypto" | "corrupt";
|
|
30
|
+
export declare abstract class CredentialsError extends Error {
|
|
31
|
+
abstract readonly kind: CredentialsErrorKind;
|
|
32
|
+
}
|
|
33
|
+
/** OS keychain is unreachable (probe failed, secret-service / D-Bus
|
|
34
|
+
* down, libsecret missing, etc.). Callers who need a keychain-ref
|
|
35
|
+
* BLOB to succeed should either fall back via isKeychainAvailable()
|
|
36
|
+
* first, or rethrow and surface a user-actionable message. */
|
|
37
|
+
export declare class CredentialsKeychainUnavailableError extends CredentialsError {
|
|
38
|
+
readonly kind: "keychain-unavailable";
|
|
39
|
+
readonly cause?: unknown;
|
|
40
|
+
constructor(message: string, cause?: unknown);
|
|
41
|
+
}
|
|
42
|
+
/** Fallback crypto path failed: KDF (cannot read/write the master
|
|
43
|
+
* key), AES-256-GCM encrypt, or AES-256-GCM decrypt surface not
|
|
44
|
+
* covered by the more specific CredentialsCorruptError (e.g. scrypt
|
|
45
|
+
* OOM). The `op` discriminator lets callers distinguish key-
|
|
46
|
+
* derivation, encrypt, and decrypt time failures. */
|
|
47
|
+
export declare class CredentialsCryptoError extends CredentialsError {
|
|
48
|
+
readonly kind: "crypto";
|
|
49
|
+
readonly op: "encrypt" | "decrypt" | "kdf";
|
|
50
|
+
readonly cause?: unknown;
|
|
51
|
+
constructor(op: "encrypt" | "decrypt" | "kdf", message: string, cause?: unknown);
|
|
52
|
+
}
|
|
53
|
+
/** BLOB integrity check failed: unknown version prefix, keychain
|
|
54
|
+
* entry missing for a keychain-ref BLOB, or AES-GCM auth tag
|
|
55
|
+
* mismatch on a fallback BLOB. This is a data-integrity signal, not
|
|
56
|
+
* an upstream error — no `cause` field. Callers who see this MUST
|
|
57
|
+
* treat the stored row as untrusted; silent retry hides tampering. */
|
|
58
|
+
export declare class CredentialsCorruptError extends CredentialsError {
|
|
59
|
+
readonly kind: "corrupt";
|
|
60
|
+
constructor(message: string);
|
|
61
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RegisterRequest, RegisterResponse } from "../protocol/types";
|
|
2
|
+
export interface RegisterAgentOptions {
|
|
3
|
+
/** Base URL, no trailing slash. e.g. "https://beta.aifight.ai". */
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
/** Request body; `name` is the legacy alias for suggested_name. */
|
|
6
|
+
request: RegisterRequest;
|
|
7
|
+
/** Test injection point. Defaults to globalThis.fetch. */
|
|
8
|
+
fetchImpl?: typeof fetch;
|
|
9
|
+
/** Default 30_000 ms, composed with `signal` via AbortSignal.any. */
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
/** Optional caller-supplied abort; composed with timeoutMs. */
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
}
|
|
14
|
+
export interface RegisterAgentResult {
|
|
15
|
+
/** Full validated response, strongly typed. */
|
|
16
|
+
response: RegisterResponse;
|
|
17
|
+
/** Convenience — identical to response.agent.api_key. SHOWN ONCE. */
|
|
18
|
+
apiKey: string;
|
|
19
|
+
/** Convenience — identical to response.claim_token. SHOWN ONCE. */
|
|
20
|
+
claimToken: string;
|
|
21
|
+
/** Convenience — identical to response.agent.id. */
|
|
22
|
+
agentId: string;
|
|
23
|
+
/** Convenience — identical to response.claim_url. */
|
|
24
|
+
claimUrl: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function registerAgent(opts: RegisterAgentOptions): Promise<RegisterAgentResult>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { MsgActionRequest, MsgGameOver } from "../protocol/types";
|
|
2
|
+
import { type ReconnectingWSClient, type ReconnectingWSClientOptions } from "../wsclient/reconnect";
|
|
3
|
+
import { type AgentFSMEffect, type AgentFSMState } from "./state-machine";
|
|
4
|
+
export interface AgentDecisionContext {
|
|
5
|
+
readonly actionRequest: MsgActionRequest;
|
|
6
|
+
readonly matchId: string;
|
|
7
|
+
readonly game?: string;
|
|
8
|
+
readonly state: AgentFSMState;
|
|
9
|
+
}
|
|
10
|
+
export interface AgentDecisionProvider {
|
|
11
|
+
decide(ctx: AgentDecisionContext): Promise<unknown>;
|
|
12
|
+
}
|
|
13
|
+
export interface AgentInstanceNotify {
|
|
14
|
+
readonly level: "info" | "warning" | "error";
|
|
15
|
+
readonly code: string;
|
|
16
|
+
readonly message: string;
|
|
17
|
+
readonly cause?: unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface AgentInstanceSnapshot {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly state: AgentFSMState | null;
|
|
22
|
+
readonly transport: ReconnectingWSClient["state"] | "idle";
|
|
23
|
+
readonly started: boolean;
|
|
24
|
+
readonly stopped: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface AgentInstanceOptions {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly ws: ReconnectingWSClientOptions;
|
|
29
|
+
readonly autoConfirmMatches?: boolean;
|
|
30
|
+
readonly decisionProvider: AgentDecisionProvider;
|
|
31
|
+
readonly connect?: (opts: ReconnectingWSClientOptions) => Promise<ReconnectingWSClient>;
|
|
32
|
+
readonly now?: () => number;
|
|
33
|
+
readonly onNotify?: (event: AgentInstanceNotify) => void;
|
|
34
|
+
readonly onReadinessCheck?: (data: unknown) => Promise<unknown> | unknown;
|
|
35
|
+
readonly onResult?: (gameOver: MsgGameOver, context: {
|
|
36
|
+
readonly game?: string;
|
|
37
|
+
}) => void;
|
|
38
|
+
readonly onFallbackRequired?: (effect: Extract<AgentFSMEffect, {
|
|
39
|
+
type: "fallback_required";
|
|
40
|
+
}>) => void;
|
|
41
|
+
}
|
|
42
|
+
export type AgentInstanceErrorKind = "agent_start" | "agent_not_started" | "agent_stopped" | "agent_effect";
|
|
43
|
+
export declare abstract class AgentInstanceError extends Error {
|
|
44
|
+
abstract readonly kind: AgentInstanceErrorKind;
|
|
45
|
+
readonly cause: unknown;
|
|
46
|
+
protected constructor(message: string, cause?: unknown);
|
|
47
|
+
}
|
|
48
|
+
export declare class AgentInstanceStartError extends AgentInstanceError {
|
|
49
|
+
readonly name = "AgentInstanceStartError";
|
|
50
|
+
readonly kind: "agent_start";
|
|
51
|
+
constructor(message: string, cause?: unknown);
|
|
52
|
+
}
|
|
53
|
+
export declare class AgentInstanceNotStartedError extends AgentInstanceError {
|
|
54
|
+
readonly name = "AgentInstanceNotStartedError";
|
|
55
|
+
readonly kind: "agent_not_started";
|
|
56
|
+
constructor(message: string, cause?: unknown);
|
|
57
|
+
}
|
|
58
|
+
export declare class AgentInstanceStoppedError extends AgentInstanceError {
|
|
59
|
+
readonly name = "AgentInstanceStoppedError";
|
|
60
|
+
readonly kind: "agent_stopped";
|
|
61
|
+
constructor(message: string, cause?: unknown);
|
|
62
|
+
}
|
|
63
|
+
export declare class AgentInstanceEffectError extends AgentInstanceError {
|
|
64
|
+
readonly name = "AgentInstanceEffectError";
|
|
65
|
+
readonly kind: "agent_effect";
|
|
66
|
+
constructor(message: string, cause?: unknown);
|
|
67
|
+
}
|
|
68
|
+
type StateHandler = (snapshot: AgentInstanceSnapshot) => void;
|
|
69
|
+
export declare class AgentInstance {
|
|
70
|
+
#private;
|
|
71
|
+
constructor(opts: AgentInstanceOptions);
|
|
72
|
+
start(): Promise<AgentInstanceSnapshot>;
|
|
73
|
+
stop(reason?: string): Promise<void>;
|
|
74
|
+
joinQueue(game: string, mode?: string, opts?: {
|
|
75
|
+
readonly oneShot?: boolean;
|
|
76
|
+
}): void;
|
|
77
|
+
leaveQueue(): void;
|
|
78
|
+
confirmMatch(confirmId?: string): void;
|
|
79
|
+
snapshot(): AgentInstanceSnapshot;
|
|
80
|
+
onState(handler: StateHandler): () => void;
|
|
81
|
+
}
|
|
82
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { MsgActionRequest, MsgGameOver, MsgMatchConfirmRequest } from "../protocol/types";
|
|
2
|
+
import type { ServerMessageEnvelope } from "../wsclient/frame-handler";
|
|
3
|
+
import type { WSClientMessage, WSWelcome } from "../wsclient/client";
|
|
4
|
+
import type { ReconnectCloseInfo, ReconnectEvent } from "../wsclient/reconnect";
|
|
5
|
+
export type AgentPhase = "connected" | "queuing" | "confirming" | "matching" | "in_match" | "deciding" | "reporting" | "closed";
|
|
6
|
+
export type AgentTransportState = "connected" | "backoff" | "closed";
|
|
7
|
+
export interface AgentFSMState {
|
|
8
|
+
readonly phase: AgentPhase;
|
|
9
|
+
readonly transport: AgentTransportState;
|
|
10
|
+
readonly agentId: string;
|
|
11
|
+
readonly agentName: string;
|
|
12
|
+
readonly availableGames: readonly string[];
|
|
13
|
+
readonly autoConfirmMatches: boolean;
|
|
14
|
+
readonly queue?: {
|
|
15
|
+
readonly game: string;
|
|
16
|
+
readonly mode: string;
|
|
17
|
+
readonly one_shot?: boolean;
|
|
18
|
+
};
|
|
19
|
+
readonly pendingConfirm?: MsgMatchConfirmRequest["data"];
|
|
20
|
+
readonly activeMatch?: {
|
|
21
|
+
readonly sessionId: string;
|
|
22
|
+
readonly game: string;
|
|
23
|
+
readonly startedAt: number;
|
|
24
|
+
};
|
|
25
|
+
readonly pendingAction?: MsgActionRequest;
|
|
26
|
+
readonly lastGameOver?: MsgGameOver;
|
|
27
|
+
readonly lastError?: string;
|
|
28
|
+
}
|
|
29
|
+
export type AgentFSMInput = {
|
|
30
|
+
type: "start";
|
|
31
|
+
welcome: WSWelcome;
|
|
32
|
+
autoConfirmMatches?: boolean;
|
|
33
|
+
now?: number;
|
|
34
|
+
} | {
|
|
35
|
+
type: "command.join_queue";
|
|
36
|
+
game: string;
|
|
37
|
+
mode?: string;
|
|
38
|
+
oneShot?: boolean;
|
|
39
|
+
} | {
|
|
40
|
+
type: "command.leave_queue";
|
|
41
|
+
} | {
|
|
42
|
+
type: "command.confirm_match";
|
|
43
|
+
confirmId?: string;
|
|
44
|
+
} | {
|
|
45
|
+
type: "ws.message";
|
|
46
|
+
message: ServerMessageEnvelope;
|
|
47
|
+
now?: number;
|
|
48
|
+
} | {
|
|
49
|
+
type: "decision.ready";
|
|
50
|
+
action: unknown;
|
|
51
|
+
} | {
|
|
52
|
+
type: "decision.failed";
|
|
53
|
+
reason: unknown;
|
|
54
|
+
} | {
|
|
55
|
+
type: "reconnect.event";
|
|
56
|
+
event: ReconnectEvent;
|
|
57
|
+
} | {
|
|
58
|
+
type: "reconnect.close";
|
|
59
|
+
info: ReconnectCloseInfo;
|
|
60
|
+
} | {
|
|
61
|
+
type: "stop";
|
|
62
|
+
reason?: string;
|
|
63
|
+
};
|
|
64
|
+
export type AgentFSMEffect = {
|
|
65
|
+
type: "send";
|
|
66
|
+
message: WSClientMessage;
|
|
67
|
+
} | {
|
|
68
|
+
type: "request_decision";
|
|
69
|
+
actionRequest: MsgActionRequest;
|
|
70
|
+
matchId: string;
|
|
71
|
+
game?: string;
|
|
72
|
+
} | {
|
|
73
|
+
type: "fallback_required";
|
|
74
|
+
actionRequest: MsgActionRequest;
|
|
75
|
+
reason: unknown;
|
|
76
|
+
} | {
|
|
77
|
+
type: "record_result";
|
|
78
|
+
gameOver: MsgGameOver;
|
|
79
|
+
game?: string;
|
|
80
|
+
} | {
|
|
81
|
+
type: "notify";
|
|
82
|
+
level: "info" | "warning" | "error";
|
|
83
|
+
code: string;
|
|
84
|
+
message: string;
|
|
85
|
+
};
|
|
86
|
+
export interface AgentFSMTransition {
|
|
87
|
+
readonly state: AgentFSMState;
|
|
88
|
+
readonly effects: readonly AgentFSMEffect[];
|
|
89
|
+
}
|
|
90
|
+
export interface CreateInitialAgentFSMInput {
|
|
91
|
+
readonly welcome: WSWelcome;
|
|
92
|
+
readonly autoConfirmMatches?: boolean;
|
|
93
|
+
readonly now?: number;
|
|
94
|
+
}
|
|
95
|
+
export declare function createInitialAgentFSM(input: CreateInitialAgentFSMInput): AgentFSMState;
|
|
96
|
+
export declare function transitionAgentFSM(state: AgentFSMState, input: AgentFSMInput): AgentFSMTransition;
|