pot-api 0.1.0

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 ADDED
@@ -0,0 +1,102 @@
1
+ # pot-api
2
+
3
+ REST API server for [pot-sdk](https://npmjs.com/package/pot-sdk) — sync and async AI output verification with webhook callbacks.
4
+
5
+ ## What it does
6
+
7
+ pot-api wraps pot-sdk as an HTTP server. Fire a verification request and get the result synchronously, or use async mode to get a `jobId` immediately while verification runs in the background — with optional webhook push on completion.
8
+
9
+ ## Install & Run
10
+
11
+ ```bash
12
+ # Run directly
13
+ ANTHROPIC_API_KEY=... XAI_API_KEY=... npx pot-api
14
+
15
+ # Or install globally
16
+ npm install -g pot-api
17
+ pot-api
18
+ ```
19
+
20
+ Default port: `3141`. Override with `PORT=8080`.
21
+
22
+ ## Endpoints
23
+
24
+ ### `POST /verify` — Sync
25
+ Blocks until verification is complete (~5–30s depending on tier).
26
+
27
+ ```bash
28
+ curl -X POST http://localhost:3141/verify \
29
+ -H "Content-Type: application/json" \
30
+ -d '{
31
+ "output": "The Eiffel Tower is 330m tall.",
32
+ "question": "How tall is the Eiffel Tower?",
33
+ "tier": "basic"
34
+ }'
35
+ ```
36
+
37
+ Returns: `VerificationResult` (confidence, flags, mdi, sas, dissent, synthesis)
38
+
39
+ ### `POST /verify/async` — Async + Webhook
40
+ Returns `{jobId}` immediately. Verification runs in background.
41
+
42
+ ```bash
43
+ curl -X POST http://localhost:3141/verify/async \
44
+ -H "Content-Type: application/json" \
45
+ -d '{
46
+ "output": "The Eiffel Tower is 330m tall.",
47
+ "question": "How tall is the Eiffel Tower?",
48
+ "tier": "basic",
49
+ "callbackUrl": "https://your-agent.example.com/webhook"
50
+ }'
51
+
52
+ # → {"jobId":"abc-123","status":"pending","pollUrl":"/jobs/abc-123"}
53
+ ```
54
+
55
+ When done, pot-api POSTs to your `callbackUrl`:
56
+ ```json
57
+ {
58
+ "jobId": "abc-123",
59
+ "status": "done",
60
+ "result": { "verified": true, "confidence": 0.91, ... }
61
+ }
62
+ ```
63
+
64
+ ### `GET /jobs/:id` — Poll Status
65
+ ```bash
66
+ curl http://localhost:3141/jobs/abc-123
67
+ # → {"id":"abc-123","status":"running","input":{...}}
68
+ # → {"id":"abc-123","status":"done","result":{...}}
69
+ ```
70
+
71
+ Status values: `pending` → `running` → `done` | `error`
72
+
73
+ ## Environment Variables
74
+
75
+ | Variable | Description |
76
+ |----------|-------------|
77
+ | `ANTHROPIC_API_KEY` | ✅ Required |
78
+ | `XAI_API_KEY` | Optional extra generator |
79
+ | `DEEPSEEK_API_KEY` | Optional extra generator |
80
+ | `MOONSHOT_API_KEY` | Optional extra generator |
81
+ | `PORT` | Server port (default: 3141) |
82
+
83
+ ## Per-request API keys (BYOK)
84
+
85
+ Override keys per request:
86
+ ```json
87
+ {
88
+ "output": "...",
89
+ "question": "...",
90
+ "apiKeys": {
91
+ "anthropic": "sk-ant-...",
92
+ "xai": "xai-..."
93
+ }
94
+ }
95
+ ```
96
+
97
+ ## Links
98
+
99
+ - pot-sdk: https://npmjs.com/package/pot-sdk
100
+ - pot-mcp: https://npmjs.com/package/pot-mcp
101
+ - Protocol spec: https://thoughtproof.ai
102
+ - GitHub: https://github.com/ThoughtProof/pot-api
@@ -0,0 +1,9 @@
1
+ export interface ApiKeys {
2
+ anthropic?: string;
3
+ xai?: string;
4
+ deepseek?: string;
5
+ moonshot?: string;
6
+ }
7
+ export declare function resolveKeys(override?: ApiKeys): ApiKeys;
8
+ export declare function buildApiKeyRecord(keys: ApiKeys): Record<string, string>;
9
+ export declare function validateConfig(keys: ApiKeys): string | null;
package/dist/config.js ADDED
@@ -0,0 +1,26 @@
1
+ export function resolveKeys(override) {
2
+ return {
3
+ anthropic: override?.anthropic ?? process.env.ANTHROPIC_API_KEY,
4
+ xai: override?.xai ?? process.env.XAI_API_KEY,
5
+ deepseek: override?.deepseek ?? process.env.DEEPSEEK_API_KEY,
6
+ moonshot: override?.moonshot ?? process.env.MOONSHOT_API_KEY,
7
+ };
8
+ }
9
+ export function buildApiKeyRecord(keys) {
10
+ const record = {};
11
+ if (keys.anthropic)
12
+ record['anthropic'] = keys.anthropic;
13
+ if (keys.xai)
14
+ record['xai'] = keys.xai;
15
+ if (keys.deepseek)
16
+ record['deepseek'] = keys.deepseek;
17
+ if (keys.moonshot)
18
+ record['moonshot'] = keys.moonshot;
19
+ return record;
20
+ }
21
+ export function validateConfig(keys) {
22
+ if (!keys.anthropic) {
23
+ return 'ANTHROPIC_API_KEY is required.';
24
+ }
25
+ return null;
26
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ import express from 'express';
3
+ import { verify } from 'pot-sdk';
4
+ import { resolveKeys, buildApiKeyRecord, validateConfig } from './config.js';
5
+ import { createJob, getJob, updateJob } from './jobs.js';
6
+ const app = express();
7
+ app.use(express.json({ limit: '1mb' }));
8
+ const PORT = parseInt(process.env.PORT ?? '3141', 10);
9
+ // ─── Health ───────────────────────────────────────────────
10
+ app.get('/', (_req, res) => {
11
+ res.json({ name: 'pot-api', version: '0.1.0', status: 'ok' });
12
+ });
13
+ // ─── Sync verify ──────────────────────────────────────────
14
+ app.post('/verify', async (req, res) => {
15
+ const { output, question, tier = 'basic', apiKeys } = req.body;
16
+ if (!output || !question) {
17
+ res.status(400).json({ error: 'output and question are required' });
18
+ return;
19
+ }
20
+ const keys = resolveKeys(apiKeys);
21
+ const configError = validateConfig(keys);
22
+ if (configError) {
23
+ res.status(400).json({ error: configError });
24
+ return;
25
+ }
26
+ try {
27
+ const result = await verify(output, {
28
+ tier,
29
+ apiKeys: buildApiKeyRecord(keys),
30
+ question,
31
+ });
32
+ res.json(result);
33
+ }
34
+ catch (err) {
35
+ res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
36
+ }
37
+ });
38
+ // ─── Async verify ─────────────────────────────────────────
39
+ app.post('/verify/async', (req, res) => {
40
+ const { output, question, tier = 'basic', callbackUrl, apiKeys } = req.body;
41
+ if (!output || !question) {
42
+ res.status(400).json({ error: 'output and question are required' });
43
+ return;
44
+ }
45
+ const keys = resolveKeys(apiKeys);
46
+ const configError = validateConfig(keys);
47
+ if (configError) {
48
+ res.status(400).json({ error: configError });
49
+ return;
50
+ }
51
+ const job = createJob({ output, question, tier, callbackUrl });
52
+ res.status(202).json({ jobId: job.id, status: 'pending', pollUrl: `/jobs/${job.id}` });
53
+ // Run in background
54
+ runJob(job.id, output, question, tier, buildApiKeyRecord(keys), callbackUrl);
55
+ });
56
+ // ─── Poll job status ───────────────────────────────────────
57
+ app.get('/jobs/:id', (req, res) => {
58
+ const job = getJob(req.params.id);
59
+ if (!job) {
60
+ res.status(404).json({ error: 'Job not found' });
61
+ return;
62
+ }
63
+ res.json(job);
64
+ });
65
+ // ─── Background runner + webhook push ────────────────────
66
+ async function runJob(jobId, output, question, tier, apiKeys, callbackUrl) {
67
+ updateJob(jobId, { status: 'running' });
68
+ try {
69
+ const result = await verify(output, { tier, apiKeys, question });
70
+ updateJob(jobId, { status: 'done', result });
71
+ if (callbackUrl) {
72
+ await pushWebhook(callbackUrl, { jobId, status: 'done', result });
73
+ }
74
+ }
75
+ catch (err) {
76
+ const error = err instanceof Error ? err.message : String(err);
77
+ updateJob(jobId, { status: 'error', error });
78
+ if (callbackUrl) {
79
+ await pushWebhook(callbackUrl, { jobId, status: 'error', error });
80
+ }
81
+ }
82
+ }
83
+ async function pushWebhook(url, payload) {
84
+ try {
85
+ await fetch(url, {
86
+ method: 'POST',
87
+ headers: { 'Content-Type': 'application/json' },
88
+ body: JSON.stringify(payload),
89
+ signal: AbortSignal.timeout(10_000),
90
+ });
91
+ }
92
+ catch (err) {
93
+ console.warn(`[pot-api] Webhook delivery failed for ${url}:`, err);
94
+ }
95
+ }
96
+ // ─── Start ────────────────────────────────────────────────
97
+ app.listen(PORT, () => {
98
+ console.log(`🔍 pot-api running on http://localhost:${PORT}`);
99
+ console.log(` POST /verify — sync verification`);
100
+ console.log(` POST /verify/async — async + webhook`);
101
+ console.log(` GET /jobs/:id — poll status`);
102
+ });
package/dist/jobs.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export type JobStatus = 'pending' | 'running' | 'done' | 'error';
2
+ export interface Job {
3
+ id: string;
4
+ status: JobStatus;
5
+ createdAt: string;
6
+ updatedAt: string;
7
+ input: {
8
+ output: string;
9
+ question: string;
10
+ tier: 'basic' | 'pro';
11
+ callbackUrl?: string;
12
+ };
13
+ result?: unknown;
14
+ error?: string;
15
+ }
16
+ export declare function createJob(input: Job['input']): Job;
17
+ export declare function getJob(id: string): Job | undefined;
18
+ export declare function updateJob(id: string, patch: Partial<Job>): void;
package/dist/jobs.js ADDED
@@ -0,0 +1,31 @@
1
+ import { randomUUID } from 'crypto';
2
+ const store = new Map();
3
+ // Auto-cleanup jobs older than 1h
4
+ setInterval(() => {
5
+ const cutoff = Date.now() - 60 * 60 * 1000;
6
+ for (const [id, job] of store.entries()) {
7
+ if (new Date(job.createdAt).getTime() < cutoff) {
8
+ store.delete(id);
9
+ }
10
+ }
11
+ }, 10 * 60 * 1000);
12
+ export function createJob(input) {
13
+ const job = {
14
+ id: randomUUID(),
15
+ status: 'pending',
16
+ createdAt: new Date().toISOString(),
17
+ updatedAt: new Date().toISOString(),
18
+ input,
19
+ };
20
+ store.set(job.id, job);
21
+ return job;
22
+ }
23
+ export function getJob(id) {
24
+ return store.get(id);
25
+ }
26
+ export function updateJob(id, patch) {
27
+ const job = store.get(id);
28
+ if (job) {
29
+ Object.assign(job, patch, { updatedAt: new Date().toISOString() });
30
+ }
31
+ }
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "pot-api",
3
+ "version": "0.1.0",
4
+ "description": "REST API server for pot-sdk — sync and async AI output verification with webhook callbacks",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "bin": {
8
+ "pot-api": "dist/index.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "files": ["dist", "README.md"],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "prepare": "npm run build && chmod +x dist/index.js",
15
+ "dev": "tsc --watch",
16
+ "start": "node dist/index.js"
17
+ },
18
+ "dependencies": {
19
+ "express": "^4.18.0",
20
+ "pot-sdk": "^0.1.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/express": "^4.17.0",
24
+ "@types/node": "^25.3.0",
25
+ "typescript": "^5.3.0"
26
+ }
27
+ }