@betterlu/agentlu 1.7.1 → 1.8.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 +120 -2
- package/dist/generated.d.ts +878 -0
- package/dist/generated.js +11 -0
- package/dist/index.d.ts +181 -49
- package/dist/index.js +205 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ const client = new OpenAI({ baseURL: "http://localhost:8912/v1", apiKey });
|
|
|
10
10
|
const r = await client.responses.create({ model: "fast", input: "hi" });
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
This client adds get-or-create registration, typed `runJson` / `runText`, use-case catalogs, background `wait`, client-side `timeoutMs`, and auto-retry on `409 thread_busy`.
|
|
13
|
+
This client adds get-or-create registration, typed `runJson` / `runText`, use-case catalogs, the two `/v1` tiers (`llm.*` / `agent.*`), error classification (`err.kind`, `isUnavailable`), background `wait`, bulk uploads, client-side `timeoutMs`, and auto-retry on `409 thread_busy`.
|
|
14
14
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
@@ -33,6 +33,76 @@ const { data, response } = await alu.run({
|
|
|
33
33
|
console.log(response.output_text);
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
## Two tiers
|
|
37
|
+
|
|
38
|
+
`/v1` has two documented tiers, and 1.8 exposes both as namespaces. Pick one and
|
|
39
|
+
stay there (see the `agentlu-api` skill for the full contract):
|
|
40
|
+
|
|
41
|
+
| | `alu.llm.*` (direct) | `alu.agent.*` (agent) |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| What runs | one profile-free provider call | profile + tool families + agent loop |
|
|
44
|
+
| Session | none (`store: false`) | a real thread you can continue |
|
|
45
|
+
| Tools | none | the closed family set (+ MCP for `api`) |
|
|
46
|
+
| Use it for | extraction, classification, short answers | research, phone/browser work, context |
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
// Direct tier.
|
|
50
|
+
const { text } = await alu.llm.text("Name three colours.");
|
|
51
|
+
const { data } = await alu.llm.json<{ items: string[] }>(
|
|
52
|
+
{ type: "object", properties: { items: { type: "array", items: { type: "string" } } }, required: ["items"] },
|
|
53
|
+
"two milk, one bread",
|
|
54
|
+
);
|
|
55
|
+
for await (const event of alu.llm.stream("Count to three")) console.log(event.type);
|
|
56
|
+
|
|
57
|
+
// Agent tier (default agent `api`; pin fast/research/… or "<app>/<name>").
|
|
58
|
+
const run = await alu.agent.run({ agent: "fast", input: "what changed in node 24?" });
|
|
59
|
+
const done = await alu.agent.background({ input: "research this deeply" }, { timeoutMs: 600_000 });
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`alu.run` / `runJson` / `runText` / `stream` remain the agent-tier aliases they
|
|
63
|
+
always were - nothing breaks by upgrading.
|
|
64
|
+
|
|
65
|
+
## Errors: `kind` and fail-open
|
|
66
|
+
|
|
67
|
+
Every `AgentLuError` carries a coarse `kind`, and `isUnavailable(err)` is the
|
|
68
|
+
predicate for "the service could not answer right now" (offline, 5xx,
|
|
69
|
+
saturation, timeout, rate limit):
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { isUnavailable } from "@betterlu/agentlu";
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
await alu.llm.text(input);
|
|
76
|
+
} catch (err) {
|
|
77
|
+
if (isUnavailable(err)) return fallbackAnswer(); // degrade gracefully
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
| `err.kind` | Meaning |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `unavailable` | offline / upstream 5xx / saturated - retry or degrade |
|
|
85
|
+
| `timeout` | the run or request hit its deadline |
|
|
86
|
+
| `rate_limited` | HTTP 429 or a retryable 409 (`thread_busy`) - back off (the SDK already retries with jitter) |
|
|
87
|
+
| `invalid_request` | the caller must fix the request (4xx) |
|
|
88
|
+
| `schema` | structured output failed or never validated |
|
|
89
|
+
| `incomplete` | the run finished without a complete answer |
|
|
90
|
+
| `internal` | anything else, including a cancelled run and the `systemone_unconfigured` config boundary (never retried, so it surfaces instead of degrading) |
|
|
91
|
+
|
|
92
|
+
## Bulk uploads and background runs
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
const files = await alu.uploadMany(photos, { concurrency: 4 });
|
|
96
|
+
await alu.agent.run({ input: "catalog these", fileIds: files.map((f) => f.id) });
|
|
97
|
+
|
|
98
|
+
const finished = await alu.useCase("myapp-long").runBackground({ input }, { intervalMs: 2_000 });
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`uploadMany` preserves input order and bounds parallelism (default 3).
|
|
102
|
+
`runBackground` = enqueue (`background: true`) + `responses.wait`; it resolves
|
|
103
|
+
with the terminal Response row (check `status`; a failed run is not an
|
|
104
|
+
exception there).
|
|
105
|
+
|
|
36
106
|
## JSON results
|
|
37
107
|
|
|
38
108
|
`runJson` returns only a completed response with the server-provided `output_parsed` value. It preserves JSON `null`, `false`, `0`, and empty arrays. A missing parsed value, failed response, incomplete response, cancellation, or queued response throws an SDK error instead of parsing `output_text`. `background: true` is rejected by this helper; use raw `run` when polling is intended.
|
|
@@ -75,7 +145,55 @@ const { data } = await mealEnricher.runJson<{ meal: string }>({ input: "two eggs
|
|
|
75
145
|
|
|
76
146
|
Set a field on `run` or `runJson` to override its registered default. `strict: false` still requires parsed JSON but does not require that value to match the schema.
|
|
77
147
|
|
|
78
|
-
|
|
148
|
+
`priority` declares the use-case tier and opts the client into its defaults
|
|
149
|
+
(`instant` = fast models/45s/2k/1 attempt, `standard` = 3 min/2 attempts, `deep`
|
|
150
|
+
= strongest/10 min/8k/3 attempts). A client with no declared priority keeps the
|
|
151
|
+
pre-tier envelope, so adding it is always a deliberate change:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const parse = alu.useCase("myapp-parse", {
|
|
155
|
+
app: "myapp",
|
|
156
|
+
priority: "instant",
|
|
157
|
+
use_case_profile: { outputKind: "json_schema" },
|
|
158
|
+
defaults: { agent: "api", store: false, tools: [] },
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`maxOutputTokens` on client defaults is honored for defaults written from this
|
|
163
|
+
release on: a value stored earlier stays inert until the client re-declares its
|
|
164
|
+
defaults (or the console edits them). Prefer a request-level `maxOutputTokens`
|
|
165
|
+
when you only need it for one call.
|
|
166
|
+
|
|
167
|
+
### App-owned agents
|
|
168
|
+
|
|
169
|
+
An app can declare its own agents at registration and call them as
|
|
170
|
+
`agent: "<app>/<name>"` from any client of the same app. The declaration's
|
|
171
|
+
instructions become the agent's profile body (caller `instructions` are
|
|
172
|
+
appended below them), and `tools` limits the families it may use.
|
|
173
|
+
|
|
174
|
+
`app` is slugified to the address grammar (`NestLu` → `nestlu`, `my app` →
|
|
175
|
+
`my-app`), and the server enforces the naming convention that keeps apps from
|
|
176
|
+
overwriting each other: the declaring client's name must own the app (`nestlu`
|
|
177
|
+
or `nestlu-...`). Any other declaration - or an address that can never parse -
|
|
178
|
+
is refused with a `warnings` entry on the registration response; the
|
|
179
|
+
registration itself still succeeds and the stored agents stay untouched. An
|
|
180
|
+
explicit request `agent`/`model` always wins over a client-default app agent:
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
const chat = alu.useCase("nestlu-chat", {
|
|
184
|
+
app: "nestlu",
|
|
185
|
+
agents: [
|
|
186
|
+
{
|
|
187
|
+
name: "chat",
|
|
188
|
+
instructions: "You are the NestLu baby shopping-list assistant …", // the old pi/agents/nestlu.md body
|
|
189
|
+
tools: ["hublu", "web_search", "fetch_content"],
|
|
190
|
+
model: "MiniMax-M3",
|
|
191
|
+
temperature: 0.3,
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
});
|
|
195
|
+
await chat.run({ agent: "nestlu/chat", input: "还缺什么?" });
|
|
196
|
+
```
|
|
79
197
|
|
|
80
198
|
Several use-cases sharing one client:
|
|
81
199
|
|