@lunnoa/client 2.0.0 → 2.2.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 +15 -41
- package/dist/cli.js +71 -8
- package/dist/index.cjs +24 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +130 -35
- package/dist/index.d.ts +130 -35
- package/dist/index.js +24 -5
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +24 -5
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +86 -26
- package/dist/react.d.ts +86 -26
- package/dist/react.js +24 -5
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/skills/lunnoa-client/SKILL.md +52 -36
- package/skills/lunnoa-solution-design/SKILL.md +29 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunnoa/client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "TypeScript SDK for building applications on top of Lunnoa Automate — typed client for the Public API (agents, workflows, executions, entities, knowledge, queues), SSE agent chat streaming, and deployment-specific codegen",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
name: lunnoa-client
|
|
3
3
|
description: >-
|
|
4
4
|
Builds custom frontends and backends on top of a Lunnoa Automate deployment
|
|
5
|
-
using the @lunnoa/client TypeScript SDK.
|
|
6
|
-
(
|
|
7
|
-
|
|
8
|
-
browser
|
|
5
|
+
using the @lunnoa/client TypeScript SDK. App login is always a Lunnoa user
|
|
6
|
+
(createBrowserClient + lunnoa.auth.login / refresh / SSO). lna_ API keys are
|
|
7
|
+
for the CLI only (discovery, codegen, deploy), never for the app session and
|
|
8
|
+
never in a browser. Covers discovery of the deployment's agents, workflows, and entity
|
|
9
9
|
types, running the deployment codegen first for typed accessors, querying
|
|
10
10
|
and creating entities, triggering workflows and polling executions,
|
|
11
11
|
resuming NEEDS_INPUT executions from custom forms, streaming agent chat
|
|
@@ -49,19 +49,24 @@ Human docs (detail): Lunnoa Docs → Develop → TypeScript client SDK.
|
|
|
49
49
|
|
|
50
50
|
Run these before inventing resources or shipping UI code:
|
|
51
51
|
|
|
52
|
-
1. **Auth** —
|
|
53
|
-
|
|
54
|
-
browser (SDK throws when `window` exists).
|
|
52
|
+
1. **Auth** — Lunnoa user JWT via `createBrowserClient` + `lunnoa.auth.login`
|
|
53
|
+
(or SSO). **Never** call Lunnoa as the app's users with an `lna_` key, and
|
|
54
|
+
**never** put `lna_` in the browser (SDK throws when `window` exists).
|
|
55
|
+
`lna_` keys are for CLI discovery, codegen, and deploy only.
|
|
55
56
|
2. **Codegen** — When building typed UIs, run
|
|
56
57
|
`npx @lunnoa/client codegen` against the deployment first.
|
|
57
58
|
3. **Discover before inventing** — prefer the CLI (JSON for agents), then
|
|
58
59
|
the SDK: `npx @lunnoa/client tools list --json --for-agent`,
|
|
59
60
|
`tools get <actionId> --json`, `apps list`, `connections list`,
|
|
61
|
+
`ai-connections list --json`,
|
|
60
62
|
`agents|workflows|entity-types|tables list`, `tables get <slugOrId>`,
|
|
61
63
|
`features`.
|
|
62
64
|
SDK equivalents: `workflowApps.list()`, `agents.list`, `workflows.list`,
|
|
63
|
-
`entityTypes.list`, `tables.list`, `
|
|
64
|
-
|
|
65
|
+
`entityTypes.list`, `tables.list`, `aiConnections.list()`,
|
|
66
|
+
`discovery.enabledFeatures()`.
|
|
67
|
+
Do not invent catalogue action ids or model ids. `connections list` is
|
|
68
|
+
app connections (Gmail, HTTP). `ai-connections list` is the model
|
|
69
|
+
provider connection and the `models[].id` values `defineAgent` accepts.
|
|
65
70
|
4. **Run vs deploy** — Ad-hoc: `actions.run` / `runs.start` /
|
|
66
71
|
`workflows.execute`. Durable shared automation: CLI
|
|
67
72
|
`npx @lunnoa/client workflows|agents deploy`. Upsert is by slug
|
|
@@ -70,36 +75,33 @@ Run these before inventing resources or shipping UI code:
|
|
|
70
75
|
|
|
71
76
|
---
|
|
72
77
|
|
|
73
|
-
## 1. Auth:
|
|
78
|
+
## 1. Auth: Lunnoa users only
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
Every person who uses the app is a Lunnoa user. If they are not in the
|
|
81
|
+
workspace yet, they are provisioned there first (invite, SSO, or SCIM). The
|
|
82
|
+
app does not keep its own user directory and does not call Lunnoa with an
|
|
83
|
+
`lna_` key on their behalf.
|
|
84
|
+
|
|
85
|
+
| Caller | Credential |
|
|
86
|
+
|---|---|
|
|
87
|
+
| **Person using the app** | `createBrowserClient({ baseUrl })` + `lunnoa.auth.login` (password, 2FA, or SSO). Permissions, agent shares, and task history are that user's. |
|
|
88
|
+
| **CLI (codegen, discovery, deploy)** | `lna_` API key in `.env` / `--api-key`. Not the app session. |
|
|
79
89
|
|
|
80
90
|
Hard rules:
|
|
81
91
|
|
|
82
92
|
- **NEVER put an `lna_` key in browser code, env vars bundled into the client,
|
|
83
93
|
or anything shipped to the browser.** The SDK throws if an `lna_` key is
|
|
84
94
|
used while `window` exists. A leaked key exposes the whole workspace.
|
|
85
|
-
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
-
|
|
89
|
-
|
|
90
|
-
- Keys are minted by a SuperAdmin in **Adminspace → API keys** (workspace +
|
|
95
|
+
- **NEVER build a backend-for-frontend that holds an `lna_` key so the app
|
|
96
|
+
can have its own users.** Next.js route handlers and server actions count
|
|
97
|
+
as the app: they must forward the signed-in user's JWT, not a service key.
|
|
98
|
+
- The deployment must allow the app's origin via `CORS_ALLOWED_ORIGINS`.
|
|
99
|
+
- CLI keys are minted by a SuperAdmin in **Adminspace → API keys** (workspace +
|
|
91
100
|
RBAC role + optional expiry; secret shown once). Recommend a minimal custom
|
|
92
101
|
role (e.g. `entities:read`, `entities:create`, `agents:use`), not Admin.
|
|
93
102
|
|
|
94
103
|
```typescript
|
|
95
|
-
//
|
|
96
|
-
import { createServerClient } from '@lunnoa/client';
|
|
97
|
-
const lunnoa = createServerClient({
|
|
98
|
-
baseUrl: process.env.LUNNOA_URL!,
|
|
99
|
-
apiKey: process.env.LUNNOA_API_KEY!,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Pattern B (browser) — login + localStorage token store + auto-refresh on 401
|
|
104
|
+
// App session — login + localStorage token store + auto-refresh on 401
|
|
103
105
|
import { createBrowserClient, isLoginRequires2FA } from '@lunnoa/client';
|
|
104
106
|
const lunnoa = createBrowserClient({ baseUrl });
|
|
105
107
|
const result = await lunnoa.auth.login({ email, password });
|
|
@@ -150,7 +152,7 @@ const { data, setPage } = useEntityList({ objectTypeSlug: 'invoice' });
|
|
|
150
152
|
|
|
151
153
|
Peer: `react` ≥ 18 for `/react`. `@ai-sdk/react` ships with the SDK (no extra install).
|
|
152
154
|
Errors are `LunnoaApiError` with `.status`, `.body`, `.isUnauthorized`,
|
|
153
|
-
`.isForbidden`, `.isRateLimited`. A 403 means the
|
|
155
|
+
`.isForbidden`, `.isRateLimited`. A 403 means the user's role or the
|
|
154
156
|
deployment's licence edition does not cover the endpoint.
|
|
155
157
|
|
|
156
158
|
---
|
|
@@ -169,8 +171,9 @@ npx @lunnoa/client codegen --url <deployment-url> --api-key <lna_key> --out ./sr
|
|
|
169
171
|
This emits `src/lunnoa/lunnoa.generated.ts` with `createDeploymentClient`:
|
|
170
172
|
|
|
171
173
|
```typescript
|
|
174
|
+
import { createBrowserClient } from '@lunnoa/client';
|
|
172
175
|
import { createDeploymentClient } from './lunnoa/lunnoa.generated';
|
|
173
|
-
const lunnoa = createDeploymentClient(
|
|
176
|
+
const lunnoa = createDeploymentClient(createBrowserClient({ baseUrl }));
|
|
174
177
|
|
|
175
178
|
await lunnoa.entities.invoice.list({ state: 'pending' }); // typed attributes + states
|
|
176
179
|
await lunnoa.workflows.processInvoice.execute({ invoiceId }); // typed trigger inputs
|
|
@@ -365,7 +368,8 @@ export const ping = defineWorkflow({
|
|
|
365
368
|
|
|
366
369
|
export const triage = defineAgent({
|
|
367
370
|
slug: 'support-triage',
|
|
368
|
-
|
|
371
|
+
// models[].id from `npx @lunnoa/client ai-connections list --json`
|
|
372
|
+
model: 'deepseek-ai/DeepSeek-V4-Pro',
|
|
369
373
|
instructions: 'Triage mail. Be concise.',
|
|
370
374
|
tools: [defineAction({ id: 'http_action_send-request' })],
|
|
371
375
|
});
|
|
@@ -385,11 +389,20 @@ npx @lunnoa/client tools list --json --for-agent
|
|
|
385
389
|
npx @lunnoa/client tools search email --json --for-agent
|
|
386
390
|
npx @lunnoa/client tools get http_action_send-request --json
|
|
387
391
|
npx @lunnoa/client connections list --app gmail --json
|
|
392
|
+
npx @lunnoa/client ai-connections list --json
|
|
388
393
|
```
|
|
389
394
|
|
|
390
395
|
`tools get` returns `inputConfig` / `inputFields` and a `defineAction` sketch.
|
|
391
396
|
`tools list` is compact; use `get` for the schema. `--json` is for coding agents.
|
|
392
397
|
|
|
398
|
+
`ai-connections list` returns the AI connections this key can assign to an
|
|
399
|
+
agent. Set `defineAgent({ model })` to a `models[].id` from that JSON
|
|
400
|
+
(on Lunnoa LLMs that is a catalogue id such as
|
|
401
|
+
`deepseek-ai/DeepSeek-V4-Pro`). Omit `aiConnection` to
|
|
402
|
+
use the connection with `isDefault: true`. Pass
|
|
403
|
+
`defineAiConnection({ id })` only for a different connection. SDK:
|
|
404
|
+
`lunnoa.aiConnections.list()`.
|
|
405
|
+
|
|
393
406
|
Deploy to Automate UI (upsert by slug inside the workspace on the API key; prefer CLI):
|
|
394
407
|
|
|
395
408
|
```bash
|
|
@@ -443,6 +456,8 @@ for await (const chunk of stream) {
|
|
|
443
456
|
}
|
|
444
457
|
```
|
|
445
458
|
|
|
459
|
+
A turn from an app runs in **preview**: 10 model rounds, so the agent can call tools a few times and still send a final reply. The SDK sends `chatMode: 'preview'` for you. Do not pass `chatMode: 'builder'` from an app. That is the agent-editor interview: 4 rounds, and it stops a tool-using agent halfway. The workflow then fails with "Agent did not generate a response" even when a tool already saved the data. A workflow Message Agent step uses the same preview budget. For a job that chains many tool calls (read every record, then write a result), turn on **Long-horizon mode** on that agent in Lunnoa. That raises the budget to 50 rounds. `defineAgent` cannot set the switch, and a later deploy leaves it as you set it.
|
|
460
|
+
|
|
446
461
|
- **React apps:** prefer `useAgentChat` from `@lunnoa/client/react`, which wraps AI SDK `useChat` + `DefaultChatTransport`
|
|
447
462
|
pointed at
|
|
448
463
|
`${baseUrl}/api/agents/${agentId}/tasks/${taskId}/stream-message` with an
|
|
@@ -500,7 +515,7 @@ const { items: work } = await lunnoa.queueItems.listByObject(ticket.id);
|
|
|
500
515
|
`lunnoa.approvals` mirrors Automate **Approvals** (`/approvals`). It uses the
|
|
501
516
|
workspace API (`/api/approvals/...`), not Public API v1. The inbox is filtered
|
|
502
517
|
to requests where the **current user** is eligible and has not decided yet.
|
|
503
|
-
|
|
518
|
+
The caller is the signed-in Lunnoa user. Role needs `approvals:read` / `approvals:decide`.
|
|
504
519
|
|
|
505
520
|
```typescript
|
|
506
521
|
const { items } = await lunnoa.approvals.inbox(); // pending + partially_approved
|
|
@@ -531,14 +546,15 @@ with emails (capped; not Azure object IDs).
|
|
|
531
546
|
|
|
532
547
|
## 10. Ship checklist (after the mandatory checklist)
|
|
533
548
|
|
|
534
|
-
1. Confirm base URL
|
|
535
|
-
|
|
536
|
-
|
|
549
|
+
1. Confirm the base URL. Sign people in with `createBrowserClient` and
|
|
550
|
+
`lunnoa.auth.login` (not an `lna_` key, and not raw localStorage getters
|
|
551
|
+
unless you already hold that user's JWT). Allow the origin in
|
|
552
|
+
`CORS_ALLOWED_ORIGINS`.
|
|
537
553
|
2. Run `npx @lunnoa/client codegen` against the deployment; commit the output.
|
|
538
554
|
3. Call `discovery.enabledFeatures()` and hide unsupported areas.
|
|
539
555
|
4. Build forms/tables from `attributeSchema` / `customInputConfig` (or the generated types).
|
|
540
556
|
5. Render workflow progress from `executionPath`; handle `NEEDS_INPUT` with `submitInput`.
|
|
541
|
-
6. For single-action calls, use `actions.run`; for linear multi-step, use `runs.start` / `defineWorkflow`. Deploy with `npx @lunnoa/client workflows|agents deploy`. Discover catalogue via `npx @lunnoa/client tools list|get|search` (or `workflowApps.list()`).
|
|
557
|
+
6. For single-action calls, use `actions.run`; for linear multi-step, use `runs.start` / `defineWorkflow`. Deploy with `npx @lunnoa/client workflows|agents deploy`. Discover catalogue via `npx @lunnoa/client tools list|get|search` (or `workflowApps.list()`). Discover agent models via `npx @lunnoa/client ai-connections list --json` (or `aiConnections.list()`).
|
|
542
558
|
7. For Request Approval nodes, use `approvals.inbox` / `approvals.decide` (or `executions.submitApproval`).
|
|
543
559
|
8. Chat: stream via SSE, handle resume (reconnects) and stop, load history from the task.
|
|
544
560
|
9. Handle `LunnoaApiError`: 401 → re-auth; 403 → hide the capability; 429 → back off.
|
|
@@ -42,10 +42,11 @@ interrogation.
|
|
|
42
42
|
|
|
43
43
|
### Actors
|
|
44
44
|
|
|
45
|
-
- Who uses the custom UI
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
|
|
45
|
+
- Who uses the custom UI? They sign in as Lunnoa users. If they are not in
|
|
46
|
+
the workspace yet, they are provisioned there first (invite, SSO, or SCIM).
|
|
47
|
+
- The app does not keep its own login and does not call Lunnoa with an `lna_`
|
|
48
|
+
key on their behalf. `lna_` keys are for the CLI only. Never put one in a
|
|
49
|
+
browser.
|
|
49
50
|
|
|
50
51
|
### Data and knowledge
|
|
51
52
|
|
|
@@ -70,10 +71,10 @@ interrogation.
|
|
|
70
71
|
|
|
71
72
|
### Auth for any custom UI
|
|
72
73
|
|
|
73
|
-
| End users |
|
|
74
|
+
| End users | Auth |
|
|
74
75
|
|---|---|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
76
|
+
| People using the app | Lunnoa user JWT: `createBrowserClient` + `lunnoa.auth.login` (or SSO). Provision missing people with invite, SSO, or SCIM first. |
|
|
77
|
+
| Coding agent / CLI | `LUNNOA_API_KEY` for discovery, codegen, and deploy. Not the app session. |
|
|
77
78
|
| Anonymous embed chat (no full login) | Out of scope for v1 client path; scoped embed tokens are a later platform bet |
|
|
78
79
|
|
|
79
80
|
---
|
|
@@ -105,18 +106,28 @@ interrogation.
|
|
|
105
106
|
1. **Agents have no schedules or event triggers.** If something must run on a
|
|
106
107
|
cron or webhook, use a **Workflow** that messages the agent (or runs
|
|
107
108
|
actions). Do not invent an agent trigger.
|
|
108
|
-
2. **
|
|
109
|
+
2. **A tool-using agent gets 10 model rounds per turn** from an app or a
|
|
110
|
+
Message Agent step. That covers a handful of tool calls plus a final reply.
|
|
111
|
+
If the job chains many calls (read every record, then write), the brief must
|
|
112
|
+
say to turn on **Long-horizon mode** for that agent in Lunnoa (50 rounds).
|
|
113
|
+
Do not plan around `chatMode: 'builder'`; that is the editor interview and
|
|
114
|
+
stops after 4 rounds.
|
|
115
|
+
3. **Connections stay on Lunnoa.** Definitions only reference connection ids
|
|
109
116
|
(or omit for sole/default resolution). Never ask the partner to put OAuth
|
|
110
117
|
secrets in their app.
|
|
111
|
-
|
|
118
|
+
4. **Do not invent catalogue actions or model ids.** Discover actions with
|
|
112
119
|
`npx @lunnoa/client tools list|get|search --json` (or `workflowApps.list()`
|
|
113
|
-
/ codegen).
|
|
114
|
-
`
|
|
115
|
-
|
|
120
|
+
/ codegen). Discover models with
|
|
121
|
+
`npx @lunnoa/client ai-connections list --json` and use a returned
|
|
122
|
+
`models[].id` (Lunnoa LLMs uses catalogue ids such as
|
|
123
|
+
`deepseek-ai/DeepSeek-V4-Pro`). Client `defineAction` binds existing
|
|
124
|
+
catalogue actions; toolkit `createAction` is a different product
|
|
125
|
+
(in-platform apps).
|
|
126
|
+
5. **Durable vs ephemeral:** experiments → `runs.start`; shared production
|
|
116
127
|
automation → CLI `workflows deploy` / `agents deploy` by slug.
|
|
117
|
-
|
|
128
|
+
6. **UI is headless.** `@lunnoa/client` has no design system. Optional React
|
|
118
129
|
hooks in `@lunnoa/client/react`. Partners bring their own UI.
|
|
119
|
-
|
|
130
|
+
7. **Reuse before create.** Before proposing any new entity type, table,
|
|
120
131
|
workflow, or agent, run `npx @lunnoa/client entity-types list --json`,
|
|
121
132
|
`tables list --json`, `workflows list --json`, and `agents list --json`.
|
|
122
133
|
The build brief must state explicitly what is **reused** vs **created**.
|
|
@@ -124,11 +135,13 @@ interrogation.
|
|
|
124
135
|
### Common anti-patterns to reject
|
|
125
136
|
|
|
126
137
|
- Putting an agent on a schedule without a workflow wrapper
|
|
138
|
+
- Expecting an agent to loop tools indefinitely, or sending `chatMode: 'builder'` from an app (4 rounds, editor only)
|
|
127
139
|
- Building a fake multi-step “batch” as many unrelated `actions.run` calls
|
|
128
140
|
when the user wanted one Execution (use `runs.start` / workflow)
|
|
129
141
|
- Shipping `lna_` to the browser “just for the demo”
|
|
130
142
|
- Using `@lunnoa/toolkit` to build a customer portal
|
|
131
143
|
- Designing a local LangChain loop instead of Lunnoa-hosted agents
|
|
144
|
+
- Hardcoding `model: 'gpt-4o'` without reading `ai-connections list`
|
|
132
145
|
|
|
133
146
|
---
|
|
134
147
|
|
|
@@ -149,6 +162,7 @@ can execute. Use this shape:
|
|
|
149
162
|
|
|
150
163
|
### Discovery (run first)
|
|
151
164
|
- [ ] `npx @lunnoa/client tools list --json --for-agent` then `tools get <id>`
|
|
165
|
+
- [ ] `npx @lunnoa/client ai-connections list --json` before choosing an agent model
|
|
152
166
|
- [ ] agents / workflows / entity-types / tables list — reuse before create
|
|
153
167
|
- [ ] codegen — if building typed entity/workflow accessors
|
|
154
168
|
|
|
@@ -192,7 +206,7 @@ continue in a coding turn with that skill loaded.
|
|
|
192
206
|
**You ask:** Who chats (customers or staff)? Data source (entities vs ERP
|
|
193
207
|
action)? Need approvals? Existing HTTP/CRM connections?
|
|
194
208
|
|
|
195
|
-
**You conclude (example):**
|
|
209
|
+
**You conclude (example):** Customers are Lunnoa users (SCIM or invite) and sign in with a browser JWT; Agent `order-status` with tools
|
|
196
210
|
`defineAction` for ERP lookup (after `tools list` / `tools get`) + optional
|
|
197
211
|
workflow for staff notifications; UI = chat only; no agent schedule.
|
|
198
212
|
|