nuabase 2.3.4 → 2.3.7

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.
Files changed (66) hide show
  1. package/README.md +53 -2
  2. package/dist/cjs/chunks/logger-Co5uZG0A.cjs +90 -0
  3. package/dist/cjs/index.cjs +1516 -1380
  4. package/dist/cjs/local-agent.cjs +1043 -0
  5. package/dist/esm/chunks/logger-DnkHzkX_.mjs +88 -0
  6. package/dist/esm/index.mjs +1516 -1380
  7. package/dist/esm/local-agent.mjs +1041 -0
  8. package/dist/types/__tests__/helpers/client-factory.d.ts +33 -11
  9. package/dist/types/__tests__/helpers/index.d.ts +2 -1
  10. package/dist/types/backend/direct.d.ts +19 -7
  11. package/dist/types/backend/types.d.ts +7 -3
  12. package/dist/types/index.d.cts +3 -2
  13. package/dist/types/index.d.mts +3 -2
  14. package/dist/types/local-agent.d.cts +2 -0
  15. package/dist/types/local-agent.d.mts +2 -0
  16. package/dist/types/nua-llm-core/index.d.ts +23 -0
  17. package/dist/types/nua-llm-core/lib/error-utils.d.ts +6 -0
  18. package/dist/types/nua-llm-core/lib/logger.d.ts +44 -0
  19. package/dist/types/nua-llm-core/lib/nua-errors.d.ts +12 -0
  20. package/dist/types/nua-llm-core/lib/prompt-template-utils.d.ts +2 -0
  21. package/dist/types/nua-llm-core/lib/schema-utils.d.ts +1 -0
  22. package/dist/types/nua-llm-core/lib/stable-stringify.d.ts +1 -0
  23. package/dist/types/nua-llm-core/lib/strict-json-schema.d.ts +7 -0
  24. package/dist/types/nua-llm-core/lib/types.d.ts +8 -0
  25. package/dist/types/nua-llm-core/lib/validate-mappable-input-data.d.ts +4 -0
  26. package/dist/types/nua-llm-core/local-agent.d.ts +7 -0
  27. package/dist/types/nua-llm-core/modules/agent/agent-loop.d.ts +10 -0
  28. package/dist/types/nua-llm-core/modules/agent/agent-turn.d.ts +17 -0
  29. package/dist/types/nua-llm-core/modules/agent/provider-formatters.d.ts +22 -0
  30. package/dist/types/nua-llm-core/modules/agent/run-agent.d.ts +7 -0
  31. package/dist/types/nua-llm-core/modules/agent/types.d.ts +90 -0
  32. package/dist/types/nua-llm-core/modules/cast/cast-request.d.ts +32 -0
  33. package/dist/types/nua-llm-core/modules/cast/envelope.d.ts +9 -0
  34. package/dist/types/nua-llm-core/modules/cast/list-schema.d.ts +32 -0
  35. package/dist/types/nua-llm-core/modules/cast/prompts/list-prompt.d.ts +3 -0
  36. package/dist/types/nua-llm-core/modules/cast/prompts/render-prompt.d.ts +7 -0
  37. package/dist/types/nua-llm-core/modules/cast/prompts/value-prompt.d.ts +3 -0
  38. package/dist/types/nua-llm-core/modules/cast/run-cast.d.ts +44 -0
  39. package/dist/types/nua-llm-core/modules/engine/engine-router.d.ts +23 -0
  40. package/dist/types/nua-llm-core/modules/engine/http/http-engine.d.ts +12 -0
  41. package/dist/types/nua-llm-core/modules/engine/http/provider-call.d.ts +33 -0
  42. package/dist/types/nua-llm-core/modules/engine/http/provider-config.d.ts +65 -0
  43. package/dist/types/nua-llm-core/modules/engine/http/provider-engines.d.ts +35 -0
  44. package/dist/types/nua-llm-core/modules/engine/llm-engine.d.ts +73 -0
  45. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/claude-code.d.ts +2 -0
  46. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/codex.d.ts +2 -0
  47. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/failure-classification.d.ts +4 -0
  48. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/index.d.ts +3 -0
  49. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/pi.d.ts +2 -0
  50. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/types.d.ts +61 -0
  51. package/dist/types/nua-llm-core/modules/engine/local-agent/agent-id.d.ts +4 -0
  52. package/dist/types/nua-llm-core/modules/engine/local-agent/create-local-agent.d.ts +36 -0
  53. package/dist/types/nua-llm-core/modules/engine/local-agent/detect.d.ts +20 -0
  54. package/dist/types/nua-llm-core/modules/engine/local-agent/local-agent-engine.d.ts +32 -0
  55. package/dist/types/nua-llm-core/modules/engine/local-agent/local-agent.d.ts +25 -0
  56. package/dist/types/nua-llm-core/modules/engine/local-agent/process-runner.d.ts +16 -0
  57. package/dist/types/nua-llm-core/modules/engine/local-agent/semaphore.d.ts +8 -0
  58. package/dist/types/nua-llm-core/modules/execution/llm-response-extraction.d.ts +5 -0
  59. package/dist/types/nua-llm-core/modules/json-schema-validation/ajv-instances.d.ts +12 -0
  60. package/dist/types/nua-llm-core/modules/json-schema-validation/nua-json-schema-value-validation.d.ts +10 -0
  61. package/dist/types/nua-llm-core/modules/json-schema-validation/validate-json-schema.d.ts +2 -0
  62. package/dist/types/nua-llm-core/modules/model-info/index.d.ts +15 -0
  63. package/dist/types/nua-llm-core/modules/streaming/sse-parser.d.ts +7 -0
  64. package/dist/types/nua-llm-core/nua-llm-client.d.ts +37 -0
  65. package/dist/types/nua.d.ts +6 -1
  66. package/package.json +19 -2
package/README.md CHANGED
@@ -165,6 +165,16 @@ Every call returns a discriminated union. When `success` is `false`, you get an
165
165
  | `llmUsage` | `object` | Token usage from LLM calls. |
166
166
  | `cacheUsage` | `object` | Token usage served from cache. |
167
167
 
168
+ **Direct-specific metadata** (`meta` when `source` is `'direct'`):
169
+
170
+ | Field | Type | Description |
171
+ | ------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------- |
172
+ | `engine` | `'http'` \| `'local-agent'` | Whether an LLM provider's API or a coding agent on this machine answered. |
173
+ | `schemaEnforcement` | `'in-prompt'` \| `'native'` | Whether the schema was described in the prompt or enforced by the engine. Output is validated either way. |
174
+ | `provider` | `string` | `engine: 'http'` only. The LLM provider. |
175
+ | `agent` | `'claude-code'` \| `'codex'` \| `'pi'` | `engine: 'local-agent'` only. Which coding agent answered. |
176
+ | `costUsdEstimate` | `number \| undefined` | `engine: 'local-agent'` only. The agent's own estimate. On a subscription this is not what you pay. |
177
+
168
178
  **Error**
169
179
 
170
180
  | Field | Type | Description |
@@ -185,10 +195,12 @@ Creates a client that connects to the Nuabase API gateway. Use this for producti
185
195
  - `baseUrl?: string` – Override the API host. Defaults to `https://api.nuabase.com`.
186
196
 
187
197
  **`Nua.direct(config)`**
188
- Creates a client that calls LLM providers directly (in-process). Use this for serverless, edge functions, or CLI tools where you don't need the gateway infrastructure.
198
+ Creates a client that runs casts in this process instead of through the gateway. Use this for serverless, edge functions, or CLI tools where you don't need the gateway infrastructure. It runs on one of two kinds of engine, chosen by the config.
199
+
200
+ With API keys for LLM providers:
189
201
 
190
- - `model?: ModelInput` – Optional default model. Omit it to use `{ alias: 'fast' }`.
191
202
  - `providers: { groq?: { apiKey: string }, cerebras?: { apiKey: string }, gemini?: { apiKey: string }, openrouter?: { apiKey: string } }` – Provider credentials.
203
+ - `model?: ModelInput` – Optional default model. Omit it to use `{ alias: 'fast' }`.
192
204
 
193
205
  Model inputs are objects, not provider-prefixed strings:
194
206
 
@@ -204,6 +216,45 @@ await nua.get('Extract the company name', {
204
216
  });
205
217
  ```
206
218
 
219
+ With a coding agent on this machine (Node.js only):
220
+
221
+ - `localAgent: LocalAgent` – Created with `localAgent()` or `findLocalAgent()` from `nuabase/local-agent`.
222
+
223
+ ```ts
224
+ import { Nua } from 'nuabase';
225
+ import { detectLocalAgents, findLocalAgent, localAgent } from 'nuabase/local-agent';
226
+
227
+ const nua = Nua.direct({ localAgent: localAgent({ agent: 'claude-code', model: 'haiku' }) });
228
+
229
+ // Or use the first agent that is installed and logged in:
230
+ const auto = Nua.direct({ localAgent: await findLocalAgent() });
231
+
232
+ const agents = await detectLocalAgents();
233
+ // [{ agent: 'claude-code', installed: true, loggedIn: true, version: '...', binaryPath: '...' }, ...]
234
+ ```
235
+
236
+ This runs a coding-agent CLI already installed and logged in on this machine, in its headless mode (`claude -p`, `codex exec`, or `pi --mode json`). Calls use the user's own logged-in subscription or provider login, so no API key is needed. `get()` and `list()` behave as with providers: the output is validated against your schema and typed the same way. Queue operations are not supported. `nuabase/local-agent` is a separate entry point so that browser bundles of `nuabase` never include it.
237
+
238
+ The agent is set up once, when you create it. If you install an agent or log in after that, create a new one.
239
+
240
+ **`localAgent(config)`** sets up a named agent. It throws right away if the agent's executable cannot be found; if the agent is not logged in, the first call fails with that error.
241
+
242
+ - `agent: 'claude-code' | 'codex' | 'pi'`
243
+ - `binaryPath?: string` – Path to the agent executable. Defaults to looking it up on `PATH`. On Windows, point this at a native executable; `.cmd` shims are not supported.
244
+ - and the options below.
245
+
246
+ **`findLocalAgent(options?)`** returns a promise of the first agent that is installed and logged in, trying Claude Code first. It rejects when there is none. Checking runs each CLI's version and login-status commands, which make no model calls.
247
+
248
+ Options for both:
249
+
250
+ - `model?: string` – The agent's own model name, e.g. `'haiku'` for Claude Code, for calls that name no model. Defaults to the agent's default. Per-call `model: { alias }` works for aliases the agent understands (`haiku`, `sonnet`, `opus` for Claude Code). Codex and Pi have no aliases: pass one of their own model names, and for Pi a `provider/id` name such as `'openrouter/z-ai/glm-5.2'`.
251
+ - `timeoutMs?: number` – Per-call limit. Defaults to `180000`.
252
+ - `concurrency?: number` – Maximum agent processes at once. Defaults to `2`.
253
+ - `auth?: 'subscription' | 'inherit'` – `subscription` (default) hides `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` and similar variables from the agent so it bills the logged-in plan rather than an API key.
254
+ - `logger?` – An object with `debug`, `info`, `warn` and `error` methods, where calls and retries are logged. Defaults to the console.
255
+
256
+ How it works: each call runs the agent in a fresh, empty temporary directory with its tools, project settings and MCP servers turned off. The schema is wrapped as `{ value: ... }` (the agents require an object at the top level) and passed to the agent's own schema option. Codex only accepts OpenAI strict-mode schemas, so a schema with optional properties or open-ended objects is instead described in the prompt, and the output is validated as usual. Pi has no schema flag at all, so its schemas are always described in the prompt. If an agent rejects a schema, the call is retried with the schema in the prompt. `maxTokens` has no CLI equivalent and is ignored. Calls count against the user's plan limits; check each vendor's terms before offering this to other users.
257
+
207
258
  ### Methods
208
259
 
209
260
  **`nua.get(prompt)`**
@@ -0,0 +1,90 @@
1
+ 'use strict';
2
+
3
+ var logger = {};
4
+
5
+ var hasRequiredLogger;
6
+ function requireLogger() {
7
+ if (hasRequiredLogger) return logger;
8
+ hasRequiredLogger = 1;
9
+ Object.defineProperty(logger, "__esModule", { value: true });
10
+ logger.logLlmCallError = logger.logLlmCallComplete = logger.logLlmCallStart = logger.generateSpanId = logger.ConsoleLogger = void 0;
11
+ logger.pickHeaders = pickHeaders;
12
+ logger.normalizeError = normalizeError;
13
+ class ConsoleLogger {
14
+ debug(message, context) {
15
+ console.debug(`[DEBUG] ${message}`, context || "");
16
+ }
17
+ info(message, context) {
18
+ console.info(`[INFO] ${message}`, context || "");
19
+ }
20
+ warn(message, context) {
21
+ console.warn(`[WARN] ${message}`, context || "");
22
+ }
23
+ error(message, context) {
24
+ console.error(`[ERROR] ${message}`, context || "");
25
+ }
26
+ }
27
+ logger.ConsoleLogger = ConsoleLogger;
28
+ const generateSpanId = () => crypto.randomUUID();
29
+ logger.generateSpanId = generateSpanId;
30
+ function pickHeaders(headers, allowlist, redactSet) {
31
+ const result = {};
32
+ for (const [key, value] of Object.entries(headers)) {
33
+ const lowerKey = key.toLowerCase();
34
+ if (redactSet?.has(lowerKey)) {
35
+ result[key] = "[REDACTED]";
36
+ } else if (allowlist.has(lowerKey)) {
37
+ result[key] = Array.isArray(value) ? value.join(", ") : value ?? "";
38
+ }
39
+ }
40
+ return result;
41
+ }
42
+ function normalizeError(error) {
43
+ return error instanceof Error ? { message: error.message, stack: error.stack } : String(error);
44
+ }
45
+ const LLM_RESPONSE_HEADER_ALLOWLIST = /* @__PURE__ */ new Set([
46
+ "x-request-id",
47
+ "x-ratelimit-limit-requests",
48
+ "x-ratelimit-limit-tokens",
49
+ "x-ratelimit-remaining-requests",
50
+ "x-ratelimit-remaining-tokens",
51
+ "x-groq-region"
52
+ ]);
53
+ const logLlmCallStart = (logger2, spanId, service, method, request) => {
54
+ logger2.info("LLM call started", {
55
+ type: "llm_call_start",
56
+ span_id: spanId,
57
+ service,
58
+ method,
59
+ ...request
60
+ });
61
+ };
62
+ logger.logLlmCallStart = logLlmCallStart;
63
+ const logLlmCallComplete = (logger2, spanId, service, method, response, duration) => {
64
+ const { headers, ...rest } = response;
65
+ logger2.info("LLM call completed", {
66
+ type: "llm_call_complete",
67
+ span_id: spanId,
68
+ service,
69
+ method,
70
+ ...rest,
71
+ ...pickHeaders(headers, LLM_RESPONSE_HEADER_ALLOWLIST),
72
+ duration_ms: duration
73
+ });
74
+ };
75
+ logger.logLlmCallComplete = logLlmCallComplete;
76
+ const logLlmCallError = (logger2, spanId, service, method, error, duration) => {
77
+ logger2.error("LLM call failed", {
78
+ type: "llm_call_error",
79
+ span_id: spanId,
80
+ service,
81
+ method,
82
+ error: normalizeError(error),
83
+ duration_ms: duration
84
+ });
85
+ };
86
+ logger.logLlmCallError = logLlmCallError;
87
+ return logger;
88
+ }
89
+
90
+ exports.requireLogger = requireLogger;