otterly 0.3.0 → 0.3.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/dist/cli.js CHANGED
@@ -12,9 +12,14 @@ const { values, positionals } = parseArgs({
12
12
  "max-queue": { type: "string", default: "50" },
13
13
  "rate-limit": { type: "string", default: "60" },
14
14
  help: { type: "boolean", short: "h", default: false },
15
+ version: { type: "boolean", short: "v", default: false },
15
16
  },
16
17
  });
17
18
  const command = positionals[0] || "serve";
19
+ if (values.version) {
20
+ console.log("0.3.1");
21
+ process.exit(0);
22
+ }
18
23
  if (values.help || command === "help") {
19
24
  console.log(`
20
25
  otterly — local inference server for Claude Code
@@ -29,6 +34,7 @@ if (values.help || command === "help") {
29
34
  --max-concurrent <number> Max concurrent requests (default: 5)
30
35
  --max-queue <number> Max queued requests (default: 50)
31
36
  --rate-limit <number> Requests per minute per client (default: 60)
37
+ -v, --version Print version
32
38
  -h, --help Show this help
33
39
 
34
40
  Environment:
@@ -39,6 +45,7 @@ if (values.help || command === "help") {
39
45
  POST /api/run Native one-shot execution
40
46
  POST /api/stream Native NDJSON streaming
41
47
  GET /api/status Health check + queue/circuit stats
48
+ GET /playground Interactive API playground
42
49
  WS /ws Multi-turn WebSocket sessions
43
50
  `);
44
51
  process.exit(0);
@@ -12,6 +12,7 @@ import { checkAuth, RateLimiter, sendAuthError, sendRateLimitError } from "./mid
12
12
  import { generateRequestId, logRequest, logResponse, logError } from "./logger.js";
13
13
  import { CircuitBreaker } from "./circuit-breaker.js";
14
14
  import { openApiSpec } from "./swagger.js";
15
+ import { getPlaygroundHtml } from "./playground.js";
15
16
  /**
16
17
  * Parse JSON body from an incoming request. Returns parsed object or null on failure.
17
18
  */
@@ -104,6 +105,18 @@ export async function startApiServer(opts = {}) {
104
105
  jsonResponse(res, 200, openApiSpec);
105
106
  return;
106
107
  }
108
+ // GET /playground — interactive API playground
109
+ if (req.method === "GET" && path === "/playground") {
110
+ const html = getPlaygroundHtml(port);
111
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
112
+ res.end(html);
113
+ return;
114
+ }
115
+ // GET / — server info
116
+ if (req.method === "GET" && path === "/") {
117
+ jsonResponse(res, 200, { name: "otterly", version: "0.3.1", playground: "/playground" });
118
+ return;
119
+ }
107
120
  // ── POST routes: auth → rate limit → circuit breaker → queue ──
108
121
  if (req.method !== "POST") {
109
122
  jsonResponse(res, 404, { error: "Not found" });
@@ -243,6 +256,7 @@ export async function startApiServer(opts = {}) {
243
256
  console.log(` Streaming : http://localhost:${port}/api/stream`);
244
257
  console.log(` WebSocket : ws://localhost:${port}/ws`);
245
258
  console.log(` Health : http://localhost:${port}/api/status`);
259
+ console.log(` Playground : http://localhost:${port}/playground`);
246
260
  console.log(` Working dir : ${workingDir}`);
247
261
  if (apiKey) {
248
262
  console.log(` Auth : API key required (OTTERLY_API_KEY)`);
@@ -0,0 +1 @@
1
+ export declare function getPlaygroundHtml(port: number): string;