📦 SDKs — AI Gateway TH

Native client libraries สำหรับ https://gateway.kiatdamrong.shop — ครอบทุก endpoint รวม Wizard / Grounding / Knowledge / read_file. API surface เดียวกันทุกภาษา.

⚠️ Honest status (2026-06-11): ทั้ง 4 SDKs v0.6.0 — เพิ่ม Document Intelligence ครบ (corpus / longform+resume / export / schedules). Python live-verified · Node tsc clean · .NET build clean · Java mvn compile clean (2026-06-11) — added auto-Idempotency-Key (derived from request body; identical concurrent requests collapse to ONE LLM call on the gateway, crash-safe replay in ms). Build + dry-run publish PASS for every registry. Not yet uploaded to PyPI / npm / NuGet / Maven Central — credentials being set up. ตอนนี้ install จาก source / git ได้เลย — column "planned" คือ identifier ตอน publish. Release tooling: tools/release_sdks.py + .github/workflows/release-sdks.yml.
LanguageInstall (วันนี้, from source)Install (planned)TestsLive verified
Pythonpip install -e ./sdks/pythonpip install ai-gateway-thmanual✅
Node / TScd sdks/node && npm i && npm run buildnpm i @ai-gateway-th/sdk25/25 ✅✅
.NET (net8/net9)dotnet add reference sdks/dotnet/AiGatewayTh/AiGatewayTh.csprojdotnet add package AiGatewayThbuilds clean—
Java + Springmvn -f sdks/java/pom.xml installMaven shop.kiatdamrong:ai-gateway-th-sdk6/6 ✅—

Shared API surface (ทุก SDK)

เปลี่ยนแค่ naming convention ของภาษา — snake_case (Python), camelCase (Node/Java), PascalCaseAsync (.NET).

Per-call backend tier (NEW 2026-06-01): ทุก wizard + smart endpoint รองรับ tier="standard"|"premium"|"frontier" opt-in. premium = Gemini Flash judge (เร็ว, ~$0.075/M tokens), frontier = Claude Haiku judge (เร็วสุด, ~$0.80/M tokens). PII auto-pin LOCAL via X-Gateway-Tier-Downgraded-Reason: pdpa_pinned. Per-step usage.per_step[] ใน response สำหรับลูกค้าคำนวณค่าใช้จ่าย client-side. Paid judges ยังเข้าถึง Smart Engine tools (lookup_knowledge / web_search / read_url) ได้ครบ. ดู INTEGRATION_GUIDE_TH.md §12.10

Not in SDK (intentional): admin endpoints (web UI ที่ /admin/tenants) · demo endpoints (/v1/analyze-csv, /v1/cohorts/analyze, /v1/exam). ดู INTEGRATION_GUIDE_TH.md §12.9

Quick start

Install

pip install -e ./sdks/python      # from source (today)
# pip install ai-gateway-th       # when published

Use

from ai_gateway_th import GatewayClient, GatewayError

c = GatewayClient(
    base_url="https://gateway.kiatdamrong.shop",
    token="<YOUR_TOKEN>",
    tenant_id="<YOUR_TENANT_ID>",
)

# Chat (OpenAI-compat)
r = c.chat("gateway-th",
    [{"role": "user", "content": "อธิบาย scaffolding"}],
    idempotency_key="msg-001")

# Wizard polish (Typhoon SAFE — ลบ translationese)
p = c.wizard_polish("ที่ซึ่งผู้เรียนถูกทำให้มีส่วนร่วม",
                    style="neutral")

# Grounded summarize (reads real sources)
s = c.wizard_grounded_summarize(
    "สรุปแนวทาง active learning ป.4 จากแหล่งจริง")

# read_file — PDF / DOCX / XLSX / CSV / TXT
with open("plan.pdf", "rb") as f:
    doc = c.read_file(f, max_chars=30000)

# Compose pipeline (writer → judge → revise)
r = c.compose(
    messages=[{"role":"user","content":"เขียนบทความ active learning"}],
    max_revisions=2, editor_score_threshold=80)

# Charts (deterministic, no LLM)
img = c.charts_render(
    chart={"type":"bar","title":"Q1","categories":{"A":3,"B":5,"C":2}},
    format="svg", width=400, height=300)

# Knowledge packs (list + query)
packs = c.list_knowledge_packs()
hits = c.knowledge_query(packs["data"][0]["pack_id"], "binary search")

# Tier opt-in (Phase 1 — 2026-06-01). Customer pays for faster/nicer judge.
# Same call shape, just add tier=. Per-step usage in response for billing.
r = httpx.post(BASE+"/v1/wizard/polish",
    headers=hdr,
    json={"text":"...", "tier":"premium"})   # or "frontier" / "standard"
# r.json()["usage"]["per_step"] -> tokens per backend (compute cost client-side)
# r.headers["X-Gateway-Tier-Used"] -> what tier actually ran (PDPA may downgrade)
# r.headers["X-Gateway-Compose-Judge-Tools"] == "on" -> paid judge used our tools

# Smart streaming (long compose >100s)
for ev in c.smart_stream(messages=[
        {"role": "user", "content": "ออกแบบบทเรียน ป.4"}]):
    if ev["event"] == "smart.complete":
        print(ev["data"]["choices"][0]["message"]["content"])
        break

# Error handling
try:
    c.chat("bad-model", [{"role": "user", "content": "x"}])
except GatewayError as e:
    print(e.status_code, e.error_type, e.request_id)

Install

cd sdks/node && npm install && npm run build
# npm i @ai-gateway-th/sdk      # when published

Use

import { GatewayClient, GatewayError } from "@ai-gateway-th/sdk";

const c = new GatewayClient({
  baseUrl: "https://gateway.kiatdamrong.shop",
  token: process.env.GATEWAY_TOKEN!,
  tenantId: process.env.GATEWAY_TENANT_ID,
});

// Chat
const r = await c.chat({
  model: "gateway-th",
  messages: [{ role: "user", content: "อธิบาย scaffolding" }],
}, { idempotencyKey: "msg-001" });

// Wizard polish
const p = await c.wizardPolish(
  "ที่ซึ่งผู้เรียนถูกทำให้มีส่วนร่วม",
  { style: "neutral" });

// read_file (Blob / Uint8Array / ArrayBuffer)
import { readFileSync } from "node:fs";
const bytes = readFileSync("plan.pdf");
const doc = await c.readFile(bytes, {
  filename: "plan.pdf",
  contentType: "application/pdf",
  maxChars: 30000,
});

// Smart streaming with cancel
const ctrl = new AbortController();
for await (const ev of c.smartStream(
  { messages: [{ role: "user", content: "ออกแบบบทเรียน" }] },
  { signal: ctrl.signal },
)) {
  if (ev.event === "smart.complete") {
    console.log((ev.data as any).choices[0].message.content);
  }
}

// Error handling
try { await c.chat({ model: "bad", messages: [] }); }
catch (e) {
  if (e instanceof GatewayError) console.error(e.statusCode, e.errorType);
}

// Tier opt-in (Phase 1, 2026-06-01)
const r = await c.wizardPolish("...", { tier: "premium" });
// r.usage.per_step has token counts per backend; compute cost client-side
// Headers: X-Gateway-Tier-Used + X-Gateway-Tier-Downgraded-Reason (if PII)

Install

dotnet add reference sdks/dotnet/AiGatewayTh/AiGatewayTh.csproj
# dotnet add package AiGatewayTh    # when published

Use

using AiGatewayTh;

using var client = new GatewayClient(new GatewayClientOptions
{
    Token = Environment.GetEnvironmentVariable("GATEWAY_TOKEN")!,
    TenantId = "your-tenant",
    BaseUrl = "https://gateway.kiatdamrong.shop",
});

// Chat
var r = await client.ChatAsync(new ChatCompletionRequest
{
    Model = "gateway-th",
    Messages = new() {
        new() { Role = "user", Content = "อธิบาย scaffolding" }
    },
}, idempotencyKey: "msg-001");

// Wizard polish
var p = await client.WizardPolishAsync(
    "ที่ซึ่งผู้เรียนถูกทำให้มีส่วนร่วม", style: "neutral");

// read_file
byte[] bytes = File.ReadAllBytes("plan.pdf");
var doc = await client.ReadFileAsync(
    bytes, filename: "plan.pdf",
    contentType: "application/pdf", maxChars: 30000);

// Error handling
try { await client.ChatAsync(req); }
catch (GatewayException ex) when (ex.ErrorType == GatewayErrorType.RateLimitError)
{ /* exponential backoff already ran 3x */ }

// ASP.NET Core DI
// builder.Services.AddHttpClient("ai-gateway", c => {
//     c.BaseAddress = new Uri("https://gateway.kiatdamrong.shop");
// });
// builder.Services.AddSingleton(sp => new GatewayClient(new()
// {
//     Token = builder.Configuration["AiGateway:Token"]!,
//     HttpClient = sp.GetRequiredService<IHttpClientFactory>()
//                    .CreateClient("ai-gateway"),
// }));

// Tier opt-in (Phase 1, 2026-06-01)
var r = await client.WizardPolishAsync("...", tier: "premium");
// r["usage"]["per_step"] has token counts per backend
// Response headers: X-Gateway-Tier-Used + X-Gateway-Tier-Downgraded-Reason

Install (Maven)

cd sdks/java && mvn clean install
<!-- pom.xml -->
<dependency>
    <groupId>shop.kiatdamrong</groupId>
    <artifactId>ai-gateway-th-sdk</artifactId>
    <version>0.5.0</version>
</dependency>

Use

import shop.kiatdamrong.aigateway.*;

GatewayClient client = new GatewayClient(
    GatewayClientOptions.builder()
        .token(System.getenv("GATEWAY_TOKEN"))
        .tenantId("your-tenant")
        .baseUrl("https://gateway.kiatdamrong.shop")
        .build());

// Chat
Types.ChatCompletionRequest req = new Types.ChatCompletionRequest();
req.model = "gateway-th";
req.messages = List.of(
    new Types.ChatMessage("user", "อธิบาย scaffolding"));
Types.ChatCompletionResponse r = client.chat(req, "msg-001");

// Wizard polish
Map<String,Object> p = client.wizardPolish(
    "ที่ซึ่งผู้เรียนถูกทำให้มีส่วนร่วม", "neutral", null, null);

// read_file
byte[] bytes = Files.readAllBytes(Path.of("plan.pdf"));
Map<String,Object> doc = client.readFile(
    bytes, "plan.pdf", "application/pdf", 30000);

// Error handling
try { client.chat(req); }
catch (GatewayException ex) {
    log.warn("gateway error {} {}: {}",
        ex.getStatusCode(), ex.getErrorType(), ex.getMessage());
}

// Spring Boot auto-config (application.yml):
//   ai-gateway:
//     token: ${GATEWAY_TOKEN}
//     base-url: https://gateway.kiatdamrong.shop
// then @Autowired GatewayClient ใน service

// Tier opt-in (Phase 1, 2026-06-01)
Map<String,Object> r = client.wizardPolish(
    "...", "neutral", null, "premium", null);
// r["usage"]["per_step"] has token counts per backend
// Headers: X-Gateway-Tier-Used + X-Gateway-Tier-Downgraded-Reason

Common patterns (ทุก SDK)

PatternPythonNode.NETJava
Idempotencyidempotency_key={idempotencyKey}idempotencyKey:chat(req, "key")
CancelKeyboardInterruptAbortSignalCancellationTokenthread interrupt
Streamingsmart_stream()smartStream()SmartStreamAsync()smartStream()
Retry3 attempts on 5xx + network errors, exponential backoff 1s→2s→4s (configurable)
Tier opt-intier="premium"{tier:"premium"}tier:"premium"5th positional arg

Streaming methods ส่ง SSE keepalive (: ping) อัตโนมัติ — กัน Cloudflare tunnel idle-timeout ที่ 100s. Tier rates ดูที่ /pricing.

Full integration guide

ทุก endpoint + Wizard / Grounding / Knowledge / Admin + auth + PDPA + audit + bench numbers อยู่ในไฟล์ Markdown ใน repo:

ติดต่อ [email protected] เพื่อรับไฟล์ + Bearer token + tenant_id.

🪄 ลองใน Playground 📚 OpenAPI / Swagger