vignette/apps/api/engine_gateway/golden/engine_gateway_schema.v1.json
Yun Chan 4b45d33142
Some checks failed
API contract / OpenAPI type drift (push) Failing after 12m57s
관리자 AI 제공자 연결 기능 추가 (claude·codex·agy·openrouter 토큰 붙여넣기 연결)
관리자 /admin/ai 화면에서 provider 토큰(OAuth 액세스 토큰 또는 API 키)을
발급받아 붙여넣으면 DB에 암호화 저장되고, shared-secret으로 보호되는
게이트웨이 내부 엔드포인트로 push되어 실행 중인 엔진 컨테이너에 즉시
적용된다. NAS처럼 게이트웨이가 컨테이너로 도는 환경에서 CLI·로컬 PC
의존 없이 claude_api·openai·openrouter를 연결할 수 있다.

- 게이트웨이: openrouter 어댑터 신설(chat/completions), OAuth 토큰이면
  Anthropic Bearer 헤더, /internal/provider-credentials GET/POST와
  boot_id 기반 재동기화
- API: app.admin_provider_credential 테이블(idempotent DDL), stdlib
  HMAC-CTR+MAC 암호화 서비스(PROVIDER_CREDENTIAL_SECRET, 폴백
  SESSION_SECRET), /admin/providers CRUD·검증 라우트
- 웹: 제공자 연결 패널(저장·검증·해제, 토큰 힌트만 표시), 엔진 선택에
  OpenRouter 추가, api.gen.ts 재생성
- compose: api 서비스에 PROVIDER_CREDENTIAL_SECRET 전달(로컬·NAS)
2026-09-11 14:06:15 +09:00

375 lines
7.8 KiB
JSON

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://vignette.local/schemas/engine_gateway_contract.v1.json",
"title": "EngineGatewayGoldenContract",
"type": "object",
"additionalProperties": false,
"required": [
"version",
"generate_request",
"generate_response",
"stream_frames",
"stream_packets",
"compatibility_lines"
],
"properties": {
"version": {
"const": 1
},
"generate_request": {
"$ref": "#/$defs/GenerateRequest"
},
"generate_response": {
"$ref": "#/$defs/GenerateResponse"
},
"stream_frames": {
"type": "array",
"items": {
"type": "string"
}
},
"stream_packets": {
"type": "array",
"items": {
"$ref": "#/$defs/StreamPacket"
}
},
"compatibility_lines": {
"type": "array",
"items": {
"type": "string"
}
}
},
"$defs": {
"EngineMessage": {
"properties": {
"role": {
"enum": [
"system",
"user",
"assistant"
],
"title": "Role",
"type": "string"
},
"content": {
"title": "Content",
"type": "string"
},
"cache": {
"default": false,
"title": "Cache",
"type": "boolean"
}
},
"required": [
"role",
"content"
],
"title": "EngineMessage",
"type": "object"
},
"GenerateRequest": {
"properties": {
"ai_role": {
"default": "client",
"enum": [
"client",
"counselor",
"evaluator"
],
"title": "Ai Role",
"type": "string"
},
"messages": {
"items": {
"$ref": "#/$defs/EngineMessage"
},
"title": "Messages",
"type": "array"
},
"provider": {
"anyOf": [
{
"enum": [
"claude_cli",
"claude_api",
"codex_cli",
"agy_cli",
"openai",
"openrouter",
"solar"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Provider"
},
"model": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Model"
},
"reasoning_effort": {
"anyOf": [
{
"enum": [
"low",
"medium",
"high",
"xhigh",
"max",
"ultra"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Reasoning Effort"
},
"max_tokens": {
"default": 1024,
"title": "Max Tokens",
"type": "integer"
},
"temperature": {
"default": 0.7,
"title": "Temperature",
"type": "number"
},
"structured_schema": {
"anyOf": [
{
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Structured Schema"
},
"session_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Session Id"
},
"metadata": {
"title": "Metadata",
"type": "object"
}
},
"required": [
"messages"
],
"title": "GenerateRequest",
"type": "object"
},
"GenerateResponse": {
"properties": {
"text": {
"title": "Text",
"type": "string"
},
"model": {
"title": "Model",
"type": "string"
},
"provider": {
"title": "Provider",
"type": "string"
},
"tokens_in": {
"default": 0,
"title": "Tokens In",
"type": "integer"
},
"tokens_out": {
"default": 0,
"title": "Tokens Out",
"type": "integer"
},
"cost_usd": {
"default": 0.0,
"title": "Cost Usd",
"type": "number"
},
"inference_geo": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Inference Geo"
},
"structured": {
"anyOf": [
{
"type": "object"
},
{
"type": "null"
}
],
"default": null,
"title": "Structured"
}
},
"required": [
"text",
"model",
"provider"
],
"title": "GenerateResponse",
"type": "object"
},
"StreamTokenEvent": {
"properties": {
"text": {
"title": "Text",
"type": "string"
}
},
"required": [
"text"
],
"title": "StreamTokenEvent",
"type": "object"
},
"StreamDoneEvent": {
"properties": {
"provider": {
"title": "Provider",
"type": "string"
},
"model": {
"title": "Model",
"type": "string"
},
"tokens_in": {
"default": 0,
"title": "Tokens In",
"type": "integer"
},
"tokens_out": {
"default": 0,
"title": "Tokens Out",
"type": "integer"
},
"cost_usd": {
"default": 0.0,
"title": "Cost Usd",
"type": "number"
},
"turns": {
"default": 0,
"title": "Turns",
"type": "integer"
}
},
"required": [
"provider",
"model"
],
"title": "StreamDoneEvent",
"type": "object"
},
"StreamErrorEvent": {
"properties": {
"detail": {
"title": "Detail",
"type": "string"
}
},
"required": [
"detail"
],
"title": "StreamErrorEvent",
"type": "object"
},
"StreamPacket": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"event",
"payload"
],
"properties": {
"event": {
"const": "token"
},
"payload": {
"$ref": "#/$defs/StreamTokenEvent"
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"event",
"payload"
],
"properties": {
"event": {
"const": "done"
},
"payload": {
"$ref": "#/$defs/StreamDoneEvent"
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"event",
"payload"
],
"properties": {
"event": {
"const": "error"
},
"payload": {
"$ref": "#/$defs/StreamErrorEvent"
}
}
}
]
}
},
"x-engine-gateway-sse-events": [
"token",
"done",
"error"
],
"x-engine-gateway-default-model-sentinel": "gateway-default"
}