534bb94eea
Build Dev Image / build-dev-image (push) Waiting to run
Check i18n Keys / Check i18n Key Consistency (push) Waiting to run
Lint / Ruff Lint & Format (push) Waiting to run
Lint / Frontend Lint (push) Waiting to run
Test Migrations / Migrations (SQLite) (push) Waiting to run
Test Migrations / Migrations (PostgreSQL) (push) Waiting to run
199 lines
7.9 KiB
JSON
199 lines
7.9 KiB
JSON
{
|
|
"openapi": "3.0.3",
|
|
"info": {
|
|
"title": "LangBot HTTP Bot Adapter",
|
|
"version": "1.0.0",
|
|
"description": "Server-to-server HTTP integration for a LangBot pipeline. Inbound messages are POSTed to the unified webhook route; replies are delivered to a configured callback URL (one POST per reply part). All requests are HMAC-SHA256 signed. See docs/platforms/http-bot.md."
|
|
},
|
|
"paths": {
|
|
"/bots/{bot_uuid}": {
|
|
"post": {
|
|
"summary": "Push a message into the pipeline (fire-and-collect)",
|
|
"description": "Returns 202 immediately. Replies arrive asynchronously on the configured callback URL. Reuse the same session_id within the aggregation window to merge multiple messages into one turn (N->1).",
|
|
"parameters": [
|
|
{ "$ref": "#/components/parameters/BotUuid" },
|
|
{ "$ref": "#/components/parameters/Timestamp" },
|
|
{ "$ref": "#/components/parameters/Signature" },
|
|
{ "$ref": "#/components/parameters/Idempotency" }
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/InboundMessage" } } }
|
|
},
|
|
"responses": {
|
|
"202": {
|
|
"description": "Accepted (queued for the pipeline)",
|
|
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/AcceptedResponse" } } }
|
|
},
|
|
"400": { "$ref": "#/components/responses/Error" },
|
|
"401": { "$ref": "#/components/responses/Error" },
|
|
"409": { "$ref": "#/components/responses/Error" },
|
|
"413": { "$ref": "#/components/responses/Error" }
|
|
}
|
|
}
|
|
},
|
|
"/bots/{bot_uuid}/sync": {
|
|
"post": {
|
|
"summary": "Push a message and wait for the collapsed reply",
|
|
"description": "Blocking convenience mode. Waits for is_final and returns all reply parts collapsed into one array. Lossy (no sequence/streaming). One in-flight sync per session_id.",
|
|
"parameters": [
|
|
{ "$ref": "#/components/parameters/BotUuid" },
|
|
{ "$ref": "#/components/parameters/Timestamp" },
|
|
{ "$ref": "#/components/parameters/Signature" }
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/InboundMessage" } } }
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "The collapsed reply",
|
|
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/SyncResponse" } } }
|
|
},
|
|
"400": { "$ref": "#/components/responses/Error" },
|
|
"401": { "$ref": "#/components/responses/Error" }
|
|
}
|
|
}
|
|
},
|
|
"/bots/{bot_uuid}/reset": {
|
|
"post": {
|
|
"summary": "Reset a session's conversation",
|
|
"parameters": [
|
|
{ "$ref": "#/components/parameters/BotUuid" },
|
|
{ "$ref": "#/components/parameters/Timestamp" },
|
|
{ "$ref": "#/components/parameters/Signature" }
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"required": ["session_id"],
|
|
"properties": {
|
|
"session_id": { "type": "string" },
|
|
"session_type": { "type": "string", "enum": ["person", "group"] }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": { "description": "Reset done" },
|
|
"400": { "$ref": "#/components/responses/Error" },
|
|
"401": { "$ref": "#/components/responses/Error" }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"parameters": {
|
|
"BotUuid": {
|
|
"name": "bot_uuid", "in": "path", "required": true,
|
|
"schema": { "type": "string", "format": "uuid" }
|
|
},
|
|
"Timestamp": {
|
|
"name": "X-LB-Timestamp", "in": "header", "required": true,
|
|
"description": "Unix seconds; rejected if more than +/-300s from server time.",
|
|
"schema": { "type": "string" }
|
|
},
|
|
"Signature": {
|
|
"name": "X-LB-Signature", "in": "header", "required": true,
|
|
"description": "sha256=<hex> of HMAC-SHA256(secret, \"{timestamp}.\" + raw_body).",
|
|
"schema": { "type": "string" }
|
|
},
|
|
"Idempotency": {
|
|
"name": "X-LB-Idempotency-Key", "in": "header", "required": false,
|
|
"description": "Dedup key; a repeat within the dedup window returns 409.",
|
|
"schema": { "type": "string" }
|
|
}
|
|
},
|
|
"schemas": {
|
|
"Segment": {
|
|
"type": "object",
|
|
"required": ["type"],
|
|
"properties": {
|
|
"type": { "type": "string", "enum": ["Plain", "Image", "Voice", "File", "At", "Quote"] },
|
|
"text": { "type": "string", "description": "For type=Plain." },
|
|
"url": { "type": "string", "description": "For media types." },
|
|
"base64": { "type": "string", "description": "For media types (data URI or raw base64)." }
|
|
}
|
|
},
|
|
"InboundMessage": {
|
|
"type": "object",
|
|
"required": ["session_id", "message"],
|
|
"properties": {
|
|
"session_id": { "type": "string", "description": "Caller-defined; maps 1:1 to a LangBot session." },
|
|
"session_type": { "type": "string", "enum": ["person", "group"], "default": "person" },
|
|
"sender": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": { "type": "string" },
|
|
"name": { "type": "string" },
|
|
"group_name": { "type": "string", "description": "For session_type=group." }
|
|
}
|
|
},
|
|
"message": { "type": "array", "items": { "$ref": "#/components/schemas/Segment" } }
|
|
}
|
|
},
|
|
"AcceptedResponse": {
|
|
"type": "object",
|
|
"properties": {
|
|
"code": { "type": "integer", "example": 0 },
|
|
"msg": { "type": "string", "example": "accepted" },
|
|
"data": {
|
|
"type": "object",
|
|
"properties": {
|
|
"session_id": { "type": "string" },
|
|
"accepted_message_id": { "type": "string", "example": "in_01H..." },
|
|
"aggregating": { "type": "boolean" }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"SyncResponse": {
|
|
"type": "object",
|
|
"properties": {
|
|
"code": { "type": "integer", "example": 0 },
|
|
"msg": { "type": "string", "example": "ok" },
|
|
"data": {
|
|
"type": "object",
|
|
"properties": {
|
|
"session_id": { "type": "string" },
|
|
"reply_to": { "type": "string" },
|
|
"message": { "type": "array", "items": { "$ref": "#/components/schemas/Segment" } }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"Callback": {
|
|
"type": "object",
|
|
"description": "Delivered by LangBot to your callback_url, one POST per reply part. Signed with the outbound secret.",
|
|
"properties": {
|
|
"session_id": { "type": "string" },
|
|
"reply_to": { "type": "string", "description": "The accepted_message_id this answers." },
|
|
"sequence": { "type": "integer", "description": "1-based ordinal within the turn." },
|
|
"is_final": { "type": "boolean", "description": "True on the last part of the turn." },
|
|
"stream": { "type": "boolean" },
|
|
"message": { "type": "array", "items": { "$ref": "#/components/schemas/Segment" } },
|
|
"timestamp": { "type": "string", "format": "date-time" }
|
|
}
|
|
},
|
|
"ErrorEnvelope": {
|
|
"type": "object",
|
|
"properties": {
|
|
"code": { "type": "integer", "example": 40101 },
|
|
"msg": { "type": "string", "example": "invalid signature: signature_mismatch" },
|
|
"data": { "nullable": true }
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"Error": {
|
|
"description": "Error envelope",
|
|
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEnvelope" } } }
|
|
}
|
|
}
|
|
}
|
|
}
|