@assertrx/dino 1.0.1 → 1.0.2
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 +48 -6
- package/package.json +1 -1
- package/scripts/api-server.mjs +202 -14
- package/scripts/setup-dino-api.bat +23 -23
package/README.md
CHANGED
|
@@ -321,8 +321,9 @@ npm install -g @earendil-works/pi-coding-agent
|
|
|
321
321
|
# 2. Install Dino via pi
|
|
322
322
|
pi install npm:@assertrx/dino --approve
|
|
323
323
|
|
|
324
|
-
# 3. Set API key
|
|
324
|
+
# 3. Set an API key (any supported provider works)
|
|
325
325
|
export ANTHROPIC_API_KEY=sk-ant-...
|
|
326
|
+
# e.g. for OpenAI instead: export OPENAI_API_KEY=sk-...
|
|
326
327
|
|
|
327
328
|
# 4. Start the server
|
|
328
329
|
node ~/.pi/agent/npm/node_modules/@assertrx/dino/scripts/api-server.mjs
|
|
@@ -333,13 +334,35 @@ node ~/.pi/agent/npm/node_modules/@assertrx/dino/scripts/api-server.mjs
|
|
|
333
334
|
| Method | Path | Description |
|
|
334
335
|
|--------|------|-------------|
|
|
335
336
|
| `GET` | `/api/health` | Health check |
|
|
337
|
+
| `GET` | `/api/providers` | List all providers with auth status and model counts |
|
|
338
|
+
| `GET` | `/api/models` | List models available with current credentials (`?provider=<id>` to filter) |
|
|
339
|
+
| `POST` | `/api/models` | List models for given credentials — body accepts `provider`+`apiKey` or `apiKeys` (validates the key and unlocks that provider's catalog) |
|
|
336
340
|
| `GET` | `/api/prompts` | List all available prompts with parameters |
|
|
337
341
|
| `GET` | `/api/prompts/:name` | Get raw markdown content of a prompt |
|
|
338
342
|
| `POST` | `/api/prompts/:name` | **Execute** a prompt via the pi agent |
|
|
339
343
|
|
|
344
|
+
### Providers, models & API keys
|
|
345
|
+
|
|
346
|
+
The server supports every pi provider (Anthropic, OpenAI, Google, DeepSeek, Groq, Mistral, xAI, OpenRouter, and many more). Credentials can come from three places, in this order of precedence:
|
|
347
|
+
|
|
348
|
+
1. **Per-request keys** — pass `apiKeys` (a map of provider → key) or `apiKey` (+ optional `provider`) in the POST body. These keys are scoped to that single request's session.
|
|
349
|
+
2. **Environment variables** — any provider's standard env var (e.g. `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`).
|
|
350
|
+
3. **Stored credentials** — logins created via `pi /login` in `~/.pi/agent/auth.json`.
|
|
351
|
+
|
|
352
|
+
Use `GET /api/providers` to discover which providers are configured and `GET /api/models` to list models available to the server right now.
|
|
353
|
+
|
|
354
|
+
**Selecting a model:** pass `model` in the POST body as either `"provider/model-id"` (e.g. `"openai/gpt-5.2"`) or `{ "provider": "openai", "id": "gpt-5.2" }`. Without `model`, the session uses the default model resolution (configured provider defaults). Requesting a model whose provider has no credentials returns a clear error.
|
|
355
|
+
|
|
340
356
|
### Prompt execution endpoints
|
|
341
357
|
|
|
342
|
-
All POST bodies accept
|
|
358
|
+
All POST bodies accept auth/model options, `cwd` (workspace directory, defaults to current), and `stream` (default: `true` for SSE):
|
|
359
|
+
|
|
360
|
+
| Body param | Description |
|
|
361
|
+
|------------|-------------|
|
|
362
|
+
| `apiKeys` | Map of provider → API key, e.g. `{"anthropic": "sk-...", "openai": "sk-..."}` |
|
|
363
|
+
| `apiKey` | Single API key. Pair with `provider` to target one explicitly; otherwise applied to the first available provider (anthropic fallback) |
|
|
364
|
+
| `provider` | Provider id (e.g. `"openai"`) to pair with a single `apiKey` |
|
|
365
|
+
| `model` | Model selection: `"provider/model-id"`, `"model-id"`, or `{"provider": ..., "id": ...}` |
|
|
343
366
|
|
|
344
367
|
| Prompt name | Required params |
|
|
345
368
|
|-------------|---------------|
|
|
@@ -357,14 +380,33 @@ All POST bodies accept `apiKey` (optional, falls back to `ANTHROPIC_API_KEY` env
|
|
|
357
380
|
# List all prompts
|
|
358
381
|
curl http://localhost:3000/api/prompts
|
|
359
382
|
|
|
360
|
-
#
|
|
361
|
-
curl http://localhost:3000/api/
|
|
383
|
+
# Discover providers and their auth status
|
|
384
|
+
curl http://localhost:3000/api/providers
|
|
385
|
+
|
|
386
|
+
# List models available to the server (optionally per provider)
|
|
387
|
+
curl http://localhost:3000/api/models
|
|
388
|
+
curl "http://localhost:3000/api/models?provider=anthropic"
|
|
362
389
|
|
|
363
|
-
# Execute a prompt (SSE streaming)
|
|
390
|
+
# Execute a prompt (SSE streaming, auth from env vars)
|
|
364
391
|
curl -X POST http://localhost:3000/api/prompts/setup-playwright \
|
|
365
392
|
-H "Content-Type: application/json" \
|
|
366
393
|
-d '{"cwd": "/path/to/workspace"}'
|
|
367
394
|
|
|
395
|
+
# Execute with a single provider key + model selection
|
|
396
|
+
# (env: export OPENAI_API_KEY=sk-... then:)
|
|
397
|
+
curl -X POST http://localhost:3000/api/prompts/setup-playwright \
|
|
398
|
+
-H "Content-Type: application/json" \
|
|
399
|
+
-d '{"cwd": "/path/to/workspace", "model": "openai/gpt-5.2"}'
|
|
400
|
+
|
|
401
|
+
# Execute with multiple per-request API keys and an explicit model
|
|
402
|
+
curl -X POST http://localhost:3000/api/prompts/setup-playwright \
|
|
403
|
+
-H "Content-Type: application/json" \
|
|
404
|
+
-d '{
|
|
405
|
+
"cwd": "/path/to/workspace",
|
|
406
|
+
"apiKeys": {"anthropic": "sk-ant-...", "openai": "sk-ov-..."},
|
|
407
|
+
"model": "anthropic/claude-sonnet-4-5"
|
|
408
|
+
}'
|
|
409
|
+
|
|
368
410
|
# Execute with URL parameter (non-streaming JSON response)
|
|
369
411
|
curl -X POST http://localhost:3000/api/prompts/generate-pom-from-url-cli \
|
|
370
412
|
-H "Content-Type: application/json" \
|
|
@@ -399,5 +441,5 @@ event: error → {"message": "..."} # error
|
|
|
399
441
|
|----------|---------|-------------|
|
|
400
442
|
| `PORT` | `3000` | Server port |
|
|
401
443
|
| `HOST` | `0.0.0.0` | Server host |
|
|
402
|
-
|
|
|
444
|
+
| Provider env vars | — | Any provider's standard env var (e.g. `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`); per-request `apiKeys`/`apiKey` override these |
|
|
403
445
|
|
package/package.json
CHANGED
package/scripts/api-server.mjs
CHANGED
|
@@ -100,25 +100,119 @@ async function loadPrompt(name, params = {}) {
|
|
|
100
100
|
return content;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
/**
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Create a fresh ModelRuntime.
|
|
105
|
+
*
|
|
106
|
+
* Runtime API keys set on this instance are isolated to the current request.
|
|
107
|
+
*/
|
|
108
|
+
async function createModelRuntime() {
|
|
109
|
+
return ModelRuntime.create({
|
|
106
110
|
allowModelNetwork: false,
|
|
107
111
|
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Resolve runtime API keys from the request body.
|
|
116
|
+
*
|
|
117
|
+
* Supports three styles:
|
|
118
|
+
* - `apiKeys`: { "anthropic": "...", "openai": "..." }
|
|
119
|
+
* - `provider` + `apiKey`: set one key for an explicit provider
|
|
120
|
+
* - `apiKey` only (legacy): set key for the first available provider, falling back to anthropic
|
|
121
|
+
*/
|
|
122
|
+
function resolveApiKeys(body, availableModels) {
|
|
123
|
+
const keys = [];
|
|
124
|
+
|
|
125
|
+
if (body.apiKeys && typeof body.apiKeys === "object") {
|
|
126
|
+
for (const [providerId, key] of Object.entries(body.apiKeys)) {
|
|
127
|
+
if (typeof key === "string" && key.trim().length > 0) {
|
|
128
|
+
keys.push({ provider: providerId, key });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return keys;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (body.apiKey && typeof body.apiKey === "string" && body.apiKey.trim().length > 0) {
|
|
135
|
+
const provider = body.provider && typeof body.provider === "string"
|
|
136
|
+
? body.provider
|
|
137
|
+
: availableModels.length > 0
|
|
138
|
+
? availableModels[0].provider
|
|
139
|
+
: "anthropic";
|
|
140
|
+
keys.push({ provider, key: body.apiKey });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return keys;
|
|
144
|
+
}
|
|
108
145
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
146
|
+
/**
|
|
147
|
+
* Resolve a model object from the request body.
|
|
148
|
+
*
|
|
149
|
+
* Accepts:
|
|
150
|
+
* - string: "anthropic/claude-opus-4-5" or "claude-opus-4-5"
|
|
151
|
+
* - object: { provider: "anthropic", id: "claude-opus-4-5" }
|
|
152
|
+
*
|
|
153
|
+
* If no model is requested, returns undefined so the agent picks a default.
|
|
154
|
+
*/
|
|
155
|
+
function resolveModel(modelRuntime, modelSelector, configuredProviders) {
|
|
156
|
+
if (!modelSelector) return undefined;
|
|
157
|
+
|
|
158
|
+
let providerId;
|
|
159
|
+
let modelId;
|
|
160
|
+
|
|
161
|
+
if (typeof modelSelector === "string") {
|
|
162
|
+
const parts = modelSelector.split("/");
|
|
163
|
+
if (parts.length === 2) {
|
|
164
|
+
[providerId, modelId] = parts;
|
|
116
165
|
} else {
|
|
117
|
-
|
|
118
|
-
|
|
166
|
+
modelId = modelSelector;
|
|
167
|
+
providerId = configuredProviders[0] ?? "anthropic";
|
|
119
168
|
}
|
|
169
|
+
} else if (typeof modelSelector === "object") {
|
|
170
|
+
providerId = modelSelector.provider;
|
|
171
|
+
modelId = modelSelector.id ?? modelSelector.modelId;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (!providerId || !modelId) {
|
|
175
|
+
throw new Error(`Invalid model selector: ${JSON.stringify(modelSelector)}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const model = modelRuntime.getModel(providerId, modelId);
|
|
179
|
+
if (!model) {
|
|
180
|
+
throw new Error(`Model not found: ${providerId}/${modelId}`);
|
|
120
181
|
}
|
|
121
182
|
|
|
183
|
+
if (!modelRuntime.hasConfiguredAuth(providerId)) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
`Provider "${providerId}" is not configured with an API key. ` +
|
|
186
|
+
`Provide an apiKey or apiKeys for this provider.`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return model;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Create a single-use pi agent session. */
|
|
194
|
+
async function createSession({ cwd, apiKey, apiKeys, provider, model: modelSelector }) {
|
|
195
|
+
const modelRuntime = await createModelRuntime();
|
|
196
|
+
|
|
197
|
+
// Resolve keys before selecting a model so we know which providers are configured.
|
|
198
|
+
const availableBeforeKeys = modelRuntime.getAvailableSnapshot();
|
|
199
|
+
const keysToSet = resolveApiKeys({ apiKey, apiKeys, provider }, availableBeforeKeys);
|
|
200
|
+
|
|
201
|
+
// Set all runtime API keys in parallel.
|
|
202
|
+
await Promise.all(
|
|
203
|
+
keysToSet.map(({ provider: providerId, key }) =>
|
|
204
|
+
modelRuntime.setRuntimeApiKey(providerId, key).catch((err) => {
|
|
205
|
+
throw new Error(`Failed to set API key for ${providerId}: ${err.message}`);
|
|
206
|
+
})
|
|
207
|
+
)
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// Refresh availability after keys are set so the model picker sees configured providers.
|
|
211
|
+
await modelRuntime.getAvailable();
|
|
212
|
+
|
|
213
|
+
const configuredProviders = keysToSet.map((entry) => entry.provider);
|
|
214
|
+
const model = resolveModel(modelRuntime, modelSelector, configuredProviders);
|
|
215
|
+
|
|
122
216
|
const agentDir = getAgentDir();
|
|
123
217
|
|
|
124
218
|
const loader = new DefaultResourceLoader({
|
|
@@ -133,6 +227,7 @@ async function createSession({ cwd, apiKey }) {
|
|
|
133
227
|
modelRuntime,
|
|
134
228
|
resourceLoader: loader,
|
|
135
229
|
sessionManager: SessionManager.inMemory(),
|
|
230
|
+
...(model ? { model } : {}),
|
|
136
231
|
});
|
|
137
232
|
|
|
138
233
|
return session;
|
|
@@ -185,6 +280,88 @@ app.get("/api/prompts/:name", async (request, reply) => {
|
|
|
185
280
|
};
|
|
186
281
|
});
|
|
187
282
|
|
|
283
|
+
// List providers and their auth/configuration status
|
|
284
|
+
app.get("/api/providers", async (request, reply) => {
|
|
285
|
+
try {
|
|
286
|
+
const modelRuntime = await createModelRuntime();
|
|
287
|
+
const providers = modelRuntime.getProviders().map((provider) => ({
|
|
288
|
+
id: provider.id,
|
|
289
|
+
name: provider.name ?? provider.id,
|
|
290
|
+
authStatus: modelRuntime.getProviderAuthStatus(provider.id),
|
|
291
|
+
modelCount: modelRuntime.getModels(provider.id).length,
|
|
292
|
+
}));
|
|
293
|
+
return { providers };
|
|
294
|
+
} catch (err) {
|
|
295
|
+
reply.code(500);
|
|
296
|
+
return { error: `Failed to list providers: ${err.message}` };
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// List available models. Optionally filter with ?provider=<id>.
|
|
301
|
+
app.get("/api/models", async (request, reply) => {
|
|
302
|
+
try {
|
|
303
|
+
const { provider } = request.query;
|
|
304
|
+
const modelRuntime = await createModelRuntime();
|
|
305
|
+
await modelRuntime.getAvailable();
|
|
306
|
+
const models = modelRuntime.getAvailableSnapshot();
|
|
307
|
+
const filtered = provider
|
|
308
|
+
? models.filter((model) => model.provider === provider)
|
|
309
|
+
: models;
|
|
310
|
+
return {
|
|
311
|
+
models: filtered.map((model) => ({
|
|
312
|
+
provider: model.provider,
|
|
313
|
+
id: model.id,
|
|
314
|
+
name: model.name ?? model.id,
|
|
315
|
+
thinking: model.thinking,
|
|
316
|
+
})),
|
|
317
|
+
};
|
|
318
|
+
} catch (err) {
|
|
319
|
+
reply.code(500);
|
|
320
|
+
return { error: `Failed to list models: ${err.message}` };
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// List models available for the provided credentials (per-request keys).
|
|
325
|
+
// Accepts provider+apiKey or an apiKeys map; without keys, lists models from
|
|
326
|
+
// env/stored credentials. Used by clients to validate a key and pick a model.
|
|
327
|
+
app.post("/api/models", async (request, reply) => {
|
|
328
|
+
try {
|
|
329
|
+
const { provider, apiKey, apiKeys } = request.body || {};
|
|
330
|
+
const modelRuntime = await createModelRuntime();
|
|
331
|
+
|
|
332
|
+
const availableBeforeKeys = modelRuntime.getAvailableSnapshot();
|
|
333
|
+
const keysToSet = resolveApiKeys({ provider, apiKey, apiKeys }, availableBeforeKeys);
|
|
334
|
+
|
|
335
|
+
await Promise.all(
|
|
336
|
+
keysToSet.map(({ provider: providerId, key }) =>
|
|
337
|
+
modelRuntime.setRuntimeApiKey(providerId, key).catch((err) => {
|
|
338
|
+
throw new Error(`Failed to set API key for ${providerId}: ${err.message}`);
|
|
339
|
+
})
|
|
340
|
+
)
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
await modelRuntime.getAvailable();
|
|
344
|
+
|
|
345
|
+
let models = modelRuntime.getAvailableSnapshot();
|
|
346
|
+
if (provider) {
|
|
347
|
+
models = models.filter((model) => model.provider === provider);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return {
|
|
351
|
+
providers: [...new Set(keysToSet.map((entry) => entry.provider))],
|
|
352
|
+
models: models.map((model) => ({
|
|
353
|
+
provider: model.provider,
|
|
354
|
+
id: model.id,
|
|
355
|
+
name: model.name ?? model.id,
|
|
356
|
+
thinking: model.thinking,
|
|
357
|
+
})),
|
|
358
|
+
};
|
|
359
|
+
} catch (err) {
|
|
360
|
+
reply.code(500);
|
|
361
|
+
return { error: `Failed to list models: ${err.message}` };
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
188
365
|
// Execute a prompt (SSE streaming)
|
|
189
366
|
app.post("/api/prompts/:name", async (request, reply) => {
|
|
190
367
|
const { name } = request.params;
|
|
@@ -196,6 +373,9 @@ app.post("/api/prompts/:name", async (request, reply) => {
|
|
|
196
373
|
|
|
197
374
|
const {
|
|
198
375
|
apiKey,
|
|
376
|
+
apiKeys,
|
|
377
|
+
provider,
|
|
378
|
+
model,
|
|
199
379
|
cwd = process.cwd(),
|
|
200
380
|
stream = true,
|
|
201
381
|
...params
|
|
@@ -221,7 +401,13 @@ app.post("/api/prompts/:name", async (request, reply) => {
|
|
|
221
401
|
// Create session
|
|
222
402
|
let session;
|
|
223
403
|
try {
|
|
224
|
-
session = await createSession({
|
|
404
|
+
session = await createSession({
|
|
405
|
+
cwd: resolve(cwd),
|
|
406
|
+
apiKey,
|
|
407
|
+
apiKeys,
|
|
408
|
+
provider,
|
|
409
|
+
model,
|
|
410
|
+
});
|
|
225
411
|
} catch (err) {
|
|
226
412
|
reply.code(500);
|
|
227
413
|
return { error: `Failed to create agent session: ${err.message}` };
|
|
@@ -313,7 +499,9 @@ try {
|
|
|
313
499
|
await app.listen({ port: PORT, host: HOST });
|
|
314
500
|
console.log(`🦕 Dino API server running at http://${HOST}:${PORT}`);
|
|
315
501
|
console.log(` Prompts: http://${HOST}:${PORT}/api/prompts`);
|
|
502
|
+
console.log(` Providers: http://${HOST}:${PORT}/api/providers`);
|
|
503
|
+
console.log(` Models: http://${HOST}:${PORT}/api/models`);
|
|
316
504
|
} catch (err) {
|
|
317
505
|
app.log.error(err);
|
|
318
506
|
process.exit(1);
|
|
319
|
-
}
|
|
507
|
+
}
|
|
@@ -2,51 +2,51 @@
|
|
|
2
2
|
setlocal enabledelayedexpansion
|
|
3
3
|
|
|
4
4
|
echo ============================================
|
|
5
|
-
echo
|
|
5
|
+
echo Dino API Server - Setup ^& Start
|
|
6
6
|
echo ============================================
|
|
7
7
|
echo.
|
|
8
8
|
|
|
9
9
|
:: ── 1. Check Node.js ──────────────────────────────────────────────────
|
|
10
10
|
echo [1/4] Checking Node.js...
|
|
11
11
|
where node >nul 2>&1
|
|
12
|
-
if
|
|
12
|
+
if !ERRORLEVEL! NEQ 0 (
|
|
13
13
|
echo ERROR: Node.js is not installed.
|
|
14
14
|
echo Please install Node.js from https://nodejs.org/ and re-run this script.
|
|
15
15
|
pause
|
|
16
16
|
exit /b 1
|
|
17
17
|
)
|
|
18
|
-
for /f "tokens=*" %%v in ('node -v') do echo
|
|
18
|
+
for /f "tokens=*" %%v in ('node -v') do echo Found Node.js %%v
|
|
19
19
|
|
|
20
20
|
:: ── 2. Install pi (if missing) ────────────────────────────────────────
|
|
21
21
|
echo [2/4] Checking pi CLI...
|
|
22
22
|
where pi >nul 2>&1
|
|
23
|
-
if
|
|
24
|
-
for /f "tokens=*" %%v in ('pi --version 2^>^&1') do echo
|
|
23
|
+
if !ERRORLEVEL! EQU 0 (
|
|
24
|
+
for /f "tokens=*" %%v in ('pi --version 2^>^&1') do echo Found pi %%v
|
|
25
25
|
) else (
|
|
26
|
-
echo
|
|
26
|
+
echo Installing pi...
|
|
27
27
|
call npm install -g @earendil-works/pi-coding-agent
|
|
28
|
-
if
|
|
28
|
+
if !ERRORLEVEL! NEQ 0 (
|
|
29
29
|
echo ERROR: Failed to install pi.
|
|
30
30
|
pause
|
|
31
31
|
exit /b 1
|
|
32
32
|
)
|
|
33
|
-
echo
|
|
33
|
+
echo pi installed successfully.
|
|
34
34
|
)
|
|
35
35
|
|
|
36
36
|
:: ── 3. Install Dino via pi (if missing) ───────────────────────────────
|
|
37
37
|
echo [3/4] Checking Dino package...
|
|
38
38
|
set "DINO_DIR=%USERPROFILE%\.pi\agent\npm\node_modules\@assertrx\dino"
|
|
39
39
|
if not exist "%DINO_DIR%" (
|
|
40
|
-
echo
|
|
40
|
+
echo Installing @assertrx/dino via pi...
|
|
41
41
|
call pi install npm:@assertrx/dino --approve
|
|
42
|
-
if
|
|
42
|
+
if !ERRORLEVEL! NEQ 0 (
|
|
43
43
|
echo ERROR: Failed to install Dino package.
|
|
44
44
|
pause
|
|
45
45
|
exit /b 1
|
|
46
46
|
)
|
|
47
|
-
echo
|
|
47
|
+
echo Dino package installed.
|
|
48
48
|
) else (
|
|
49
|
-
echo
|
|
49
|
+
echo Dino already installed at %DINO_DIR%
|
|
50
50
|
)
|
|
51
51
|
|
|
52
52
|
:: ── 4. Start server ───────────────────────────────────────────────────
|
|
@@ -57,22 +57,22 @@ echo.
|
|
|
57
57
|
if "%PORT%"=="" set PORT=3000
|
|
58
58
|
if "%HOST%"=="" set HOST=0.0.0.0
|
|
59
59
|
|
|
60
|
-
echo
|
|
61
|
-
echo
|
|
60
|
+
echo Port: %PORT%
|
|
61
|
+
echo Host: %HOST%
|
|
62
62
|
echo.
|
|
63
63
|
|
|
64
64
|
:: Use ANTHROPIC_API_KEY from env if set
|
|
65
65
|
if defined ANTHROPIC_API_KEY (
|
|
66
|
-
echo
|
|
66
|
+
echo API key: loaded from ANTHROPIC_API_KEY
|
|
67
67
|
) else (
|
|
68
|
-
echo
|
|
68
|
+
echo WARNING: No ANTHROPIC_API_KEY set. Set it or pass apiKey in request body.
|
|
69
69
|
)
|
|
70
70
|
|
|
71
71
|
echo.
|
|
72
|
-
echo
|
|
73
|
-
echo
|
|
74
|
-
echo
|
|
75
|
-
echo
|
|
72
|
+
echo Endpoints:
|
|
73
|
+
echo GET http://%HOST%:%PORT%/api/health
|
|
74
|
+
echo GET http://%HOST%:%PORT%/api/prompts
|
|
75
|
+
echo POST http://%HOST%:%PORT%/api/prompts/:name
|
|
76
76
|
echo.
|
|
77
77
|
echo ============================================
|
|
78
78
|
echo.
|
|
@@ -83,11 +83,11 @@ set "LOCAL_API=%~dp0..\scripts\api-server.mjs"
|
|
|
83
83
|
set "INSTALLED_API=%DINO_DIR%\scripts\api-server.mjs"
|
|
84
84
|
|
|
85
85
|
if exist "%INSTALLED_API%" (
|
|
86
|
-
echo
|
|
86
|
+
echo Using installed api-server.mjs
|
|
87
87
|
node "%INSTALLED_API%"
|
|
88
88
|
) else if exist "%LOCAL_API%" (
|
|
89
|
-
echo
|
|
90
|
-
echo
|
|
89
|
+
echo Installed api-server.mjs not found.
|
|
90
|
+
echo Falling back to local source: %LOCAL_API%
|
|
91
91
|
node "%LOCAL_API%"
|
|
92
92
|
) else (
|
|
93
93
|
echo ERROR: api-server.mjs not found at either of the following locations:
|