anbaric 1.56.8 → 1.57.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/docs/api/cli.md
CHANGED
|
@@ -46,7 +46,7 @@ anbaric app status link-media-brief # a different app, from anywhere
|
|
|
46
46
|
| --- | --- |
|
|
47
47
|
| `anbaric state-machines` | List registered state machines. |
|
|
48
48
|
| `anbaric jobs create <sm-id> <start-state> [k=v …]` | Create a job and queue it for processing. |
|
|
49
|
-
| `anbaric jobs list [state-machine-id]` | List jobs,
|
|
49
|
+
| `anbaric jobs list [state-machine-id]` | List jobs, newest first, a page at a time (100 by default — `--page 1` for the next). Narrow with `--state`, `--status`, `--app`; `--oldest` flips the order. Filters apply on the platform, across every job, before paging. |
|
|
50
50
|
| `anbaric jobs stats` | Job counts per state and the queue size. |
|
|
51
51
|
| `anbaric jobs watch <job-id>` | Follow a job's state and property changes live. |
|
|
52
52
|
| `anbaric jobs set-state <job-id> <state>` | Move a job to a state and re-queue it. |
|
|
@@ -67,6 +67,9 @@ ask for, so the CLI runs unattended in scripts and CI.
|
|
|
67
67
|
| `--name <name>` | `app configure`/`deploy`/`update` | App name; prompts if omitted (suggested from `package.json`). |
|
|
68
68
|
| `--port <port>` | `app configure`/`deploy`/`update` | Internal port (1–65535); prompts if omitted. |
|
|
69
69
|
| `--yes` | `app deploy`, `app tear-down`, `jobs kill-old` | Skip confirmation. (`app update` implies it.) |
|
|
70
|
+
| `--state <state>`, `--status <status>`, `--app <app>` | `jobs list` | Only jobs in that state / with that status (`active`, `Awaiting input`, `Failed`) / belonging to that app. |
|
|
71
|
+
| `--page <n>`, `--page-size <n>` | `jobs list` | Which page (from 0) and how many per page (default 100). |
|
|
72
|
+
| `--oldest` | `jobs list` | Oldest first instead of newest. |
|
|
70
73
|
| `--help`, `-h` | all | Print usage. |
|
|
71
74
|
|
|
72
75
|
## Configuration and storage
|
|
@@ -136,20 +136,46 @@ actor : Actor
|
|
|
136
136
|
constructor(name : string, actor : Actor, description : string = "", id? : string)
|
|
137
137
|
|
|
138
138
|
// Replaceable function fields — assign your own:
|
|
139
|
+
reads : Reads // default: Reads.everything
|
|
139
140
|
predicate : (job : Job) => boolean // default: () => true
|
|
140
141
|
run : (job : Job) => Promise<Map<string, any>> // default: async () => new Map()
|
|
141
142
|
```
|
|
142
143
|
|
|
143
|
-
You configure an action by assigning `predicate` and `run
|
|
144
|
+
You configure an action by assigning `predicate` and `run`, and `reads` when
|
|
145
|
+
the job holds more than the action needs:
|
|
144
146
|
|
|
145
147
|
```ts
|
|
146
148
|
const sendWelcome = new Action("Send welcome email", new Code("welcome"));
|
|
149
|
+
sendWelcome.reads = Reads.only("email", "name");
|
|
147
150
|
sendWelcome.run = async (job) => new Map([["welcomeSent", true]]);
|
|
148
151
|
```
|
|
149
152
|
|
|
153
|
+
- **`reads`** — which properties are loaded for the job before `predicate` and
|
|
154
|
+
`run` see it. Given the machine's property definitions, so it can be written
|
|
155
|
+
once and follow the schema. See [`Reads`](#reads).
|
|
150
156
|
- **`predicate`** — return `false` to skip this action for a given job.
|
|
151
157
|
- **`run`** — return a `Map` of the properties to change. Only properties in the
|
|
152
|
-
machine's schema are applied; others are ignored with a warning.
|
|
158
|
+
machine's schema are applied; others are ignored with a warning. Only the
|
|
159
|
+
properties that actually changed are written back.
|
|
160
|
+
|
|
161
|
+
### `Reads`
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
type Reads = (definitions : Array<PropertyDefinition>) => Array<string>
|
|
165
|
+
|
|
166
|
+
Reads.everything // every property (the default)
|
|
167
|
+
Reads.nothing // none
|
|
168
|
+
Reads.only("summary", "articles") // a fixed few
|
|
169
|
+
Reads.where(definition => definition.id.startsWith("article")) // whatever matches
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
A job is loaded with the union of what the current state's actions, awaits and
|
|
173
|
+
transitions read, and nothing else: a property that wasn't declared is simply
|
|
174
|
+
absent from `job.properties`. A step that reads everything loads everything, so
|
|
175
|
+
nothing changes until you declare. Declaring matters for jobs that carry a lot
|
|
176
|
+
— a workflow holding hundreds of article summaries stops moving all of them
|
|
177
|
+
for a step that scores one — and for [agentic actions](../features/ai-agents.md),
|
|
178
|
+
whose prompt carries the loaded properties and nothing more.
|
|
153
179
|
|
|
154
180
|
See [Actions and actors](../features/actions-and-actors.md).
|
|
155
181
|
|
|
@@ -172,6 +198,7 @@ waitingFor? : AwaitParty
|
|
|
172
198
|
fields : Array<string> = []
|
|
173
199
|
resolveUrl : string | ((job : Job) => string) = ""
|
|
174
200
|
metadata : (job : Job) => Map<string, any> // default: () => new Map()
|
|
201
|
+
reads : Reads // what resolveUrl and metadata read; default: Reads.everything
|
|
175
202
|
|
|
176
203
|
constructor(name : string, waitingFor? : AwaitParty, description : string = "", id? : string)
|
|
177
204
|
|
|
@@ -218,18 +245,20 @@ transition whose predicate holds moves the job to `to`.
|
|
|
218
245
|
```ts
|
|
219
246
|
to : string
|
|
220
247
|
predicate : (job : Job) => boolean // default: () => true
|
|
248
|
+
reads : Reads // default: everything if guarded, nothing if not
|
|
221
249
|
|
|
222
|
-
constructor(to : string, predicate? : (job : Job) => boolean)
|
|
250
|
+
constructor(to : string, predicate? : (job : Job) => boolean, reads? : Reads)
|
|
223
251
|
```
|
|
224
252
|
|
|
225
253
|
```ts
|
|
226
|
-
new Transition("active", (job) => job.properties.get("welcomeSent") === true)
|
|
254
|
+
new Transition("active", (job) => job.properties.get("welcomeSent") === true, Reads.only("welcomeSent"))
|
|
227
255
|
new Transition("scoring") // unguarded: the actions run, then the job moves on
|
|
228
256
|
```
|
|
229
257
|
|
|
230
258
|
The predicate is optional. Omit it when a state's actions simply run and the job
|
|
231
259
|
should move on, rather than inventing a sentinel property for the transition to
|
|
232
|
-
read. Guard a transition only when the move is conditional
|
|
260
|
+
read. Guard a transition only when the move is conditional, and say what the
|
|
261
|
+
guard reads so the job is loaded with only that.
|
|
233
262
|
|
|
234
263
|
---
|
|
235
264
|
|
|
@@ -268,6 +297,45 @@ A job whose action threw is `FAILED`, with the reason in its audit trail. It
|
|
|
268
297
|
stays in its state rather than transitioning, and an update that moves it on
|
|
269
298
|
returns it to `ACTIVE` — so a failure is recoverable, not terminal.
|
|
270
299
|
|
|
300
|
+
### Reading a job
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
persistence.retrieve(id, actor) : Promise<Job> // every property
|
|
304
|
+
persistence.retrieve(id, actor, ["summary", "score"]) : Promise<Job> // only those
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Properties are stored one by one, so a job can be read with only the keys
|
|
308
|
+
wanted — that's what the machine does for every step, from what the step
|
|
309
|
+
[declares it reads](#reads) — and a save writes only the properties that
|
|
310
|
+
changed. A property absent from a partial read is never touched by a save of
|
|
311
|
+
that job, and no save ever removes a property. Over HTTP the same read is
|
|
312
|
+
`GET /api/v2/jobs/<id>?keys=summary,score`, and the properties in a `PUT` body
|
|
313
|
+
are the ones written.
|
|
314
|
+
|
|
315
|
+
### Listing jobs
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
const persistence = JobPersistenceFactory.instance();
|
|
319
|
+
|
|
320
|
+
persistence.list(actor) : Promise<Array<Job>> // first 100, oldest first
|
|
321
|
+
persistence.list(actor, pageSize, page, query?) : Promise<Array<Job>>
|
|
322
|
+
|
|
323
|
+
type JobPersistence.Query = {
|
|
324
|
+
workflowId? : string,
|
|
325
|
+
appId? : string,
|
|
326
|
+
state? : string,
|
|
327
|
+
status? : string, // "active", "Awaiting input", "Failed"
|
|
328
|
+
killed? : boolean,
|
|
329
|
+
order? : "oldest" | "newest" // by when the job was started; oldest by default
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
A listing is a **page**, never a cap: `pageSize` jobs (default 100) at `page`
|
|
334
|
+
(from 0), and every job the store holds is reachable by asking for the next
|
|
335
|
+
page until one comes back short. The query narrows the set on the store before
|
|
336
|
+
paging — a filter sees every job, and page numbers count matching jobs only.
|
|
337
|
+
Deployed, the store holds every job on the tenant across all apps and machines.
|
|
338
|
+
|
|
271
339
|
---
|
|
272
340
|
|
|
273
341
|
## `PropertyDefinition`
|
package/docs/api/web.md
CHANGED
|
@@ -94,10 +94,43 @@ GET /api/v2/whoami → { "id": "user-123", "roles": ["admin"] }
|
|
|
94
94
|
|
|
95
95
|
Returns the authenticated user for the current request.
|
|
96
96
|
|
|
97
|
+
### Jobs
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
GET /api/v2/jobs?page=0&pageSize=100&order=newest&workflowId=…&appId=…&state=…&status=…&killed=false
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Every job on the tenant, across all apps and state machines, **paged**: the
|
|
104
|
+
response is one page of at most `pageSize` jobs (default 100) at page `page`
|
|
105
|
+
(from 0). The page size is not a cap — keep asking for the next page until one
|
|
106
|
+
comes back shorter than `pageSize`, which is the last. `order` is by when the
|
|
107
|
+
job was started: `oldest` (the default, for compatibility) or `newest`.
|
|
108
|
+
|
|
109
|
+
The other parameters are filters, applied on the platform **before** paging, so
|
|
110
|
+
a filter sees every job and page numbers count matching jobs only. All are
|
|
111
|
+
optional and combine with AND: `workflowId` (the state machine), `appId`,
|
|
112
|
+
`state`, `status` (`active`, `Awaiting input`, `Failed`) and `killed`
|
|
113
|
+
(`true`/`false`).
|
|
114
|
+
|
|
115
|
+
In code the same listing is `JobPersistenceFactory.instance().list(actor,
|
|
116
|
+
pageSize, page, query)`; the CLI's `anbaric jobs list` and the MCP tool
|
|
117
|
+
`anbaric_jobs_list` take the same filters.
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
GET /api/v2/jobs/<id> every property
|
|
121
|
+
GET /api/v2/jobs/<id>?keys=summary,score only those
|
|
122
|
+
PUT /api/v2/jobs/<id> body: a serialised job
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
A job's properties are stored one by one. A `GET` with `keys` returns only
|
|
126
|
+
those; the properties in a `PUT` body are **upserted** — written if given,
|
|
127
|
+
left alone if not — so a caller that read a few keys can write a few keys
|
|
128
|
+
without disturbing the rest, and no `PUT` ever removes a property.
|
|
129
|
+
|
|
97
130
|
### Other resources
|
|
98
131
|
|
|
99
132
|
Also under `/api/v2`, reached through the cloud clients rather than raw HTTP:
|
|
100
|
-
`
|
|
133
|
+
`state-machines`, `queue`, `consumers`, and (when enabled) `documents`,
|
|
101
134
|
`secrets`, `audits`. Prefer the typed clients and factories over calling these by
|
|
102
135
|
hand.
|
|
103
136
|
|
|
@@ -32,6 +32,32 @@ Actions in a state run **in order** each time a job is processed. An action that
|
|
|
32
32
|
returns an unchanged value doesn't churn the job — the machine only advances (or
|
|
33
33
|
schedules a re-check) when something actually changes.
|
|
34
34
|
|
|
35
|
+
### Declare what an action reads
|
|
36
|
+
|
|
37
|
+
A job can hold a lot — hundreds of article summaries, say — while a given
|
|
38
|
+
action needs one property of it. Declare that, and only that is loaded:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import {Reads} from "anbaric";
|
|
42
|
+
|
|
43
|
+
chargeCard.reads = Reads.only("total", "paid");
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`reads` is a function of the machine's property definitions, so a mapping can
|
|
47
|
+
be written once and keep up as the schema grows: `Reads.everything` (the
|
|
48
|
+
default — nothing changes until you declare), `Reads.nothing`,
|
|
49
|
+
`Reads.only(...keys)`, or `Reads.where(definition => …)` to pick by name. A
|
|
50
|
+
transition's guard takes a `reads` too, and an `Await`'s `resolveUrl` and
|
|
51
|
+
`metadata` have one.
|
|
52
|
+
|
|
53
|
+
Before a job is processed in a state, the machine loads the union of what that
|
|
54
|
+
state's actions, awaits and transitions read; a property that wasn't declared
|
|
55
|
+
is simply absent from `job.properties`, so declare honestly. Afterwards it
|
|
56
|
+
writes back only the properties that changed — never the ones it read, and
|
|
57
|
+
never the ones it didn't load. For an [agentic action](ai-agents.md) the
|
|
58
|
+
declaration also decides what reaches the model: the prompt carries the loaded
|
|
59
|
+
properties and nothing more.
|
|
60
|
+
|
|
35
61
|
## Actors: who does the work
|
|
36
62
|
|
|
37
63
|
An actor is a small identity object — `type`, `id`, and `roles`. There are four
|
|
@@ -45,7 +45,11 @@ constrained to the schema; the result is applied to the job, and the transition
|
|
|
45
45
|
advances it. The decision is recorded against `triager`.
|
|
46
46
|
|
|
47
47
|
The job's current properties are appended to the prompt automatically, so the
|
|
48
|
-
model sees the data it's reasoning about
|
|
48
|
+
model sees the data it's reasoning about — the properties the action
|
|
49
|
+
[declares it reads](actions-and-actors.md#declare-what-an-action-reads), which
|
|
50
|
+
is all of them until you say otherwise. On a job that holds a lot, declare
|
|
51
|
+
them: `triage.reads = Reads.only("subject")` keeps a ticket's attachments,
|
|
52
|
+
history and everything else out of every call.
|
|
49
53
|
|
|
50
54
|
## The output schema
|
|
51
55
|
|
|
@@ -43,6 +43,12 @@ against your schema before applying them. Every property a job holds must have a
|
|
|
43
43
|
`PropertyDefinition`, or the change is rejected. This is what keeps a job's data
|
|
44
44
|
trustworthy no matter who or what wrote it.
|
|
45
45
|
|
|
46
|
+
Properties are stored one by one, and a step is given only the ones it
|
|
47
|
+
[declares it reads](actions-and-actors.md#declare-what-an-action-reads) — by
|
|
48
|
+
default all of them. So a job can carry a great deal of data without every
|
|
49
|
+
step paying for all of it: a step that scores one summary loads one summary,
|
|
50
|
+
and writes back only what it changed.
|
|
51
|
+
|
|
46
52
|
## Nothing is hard-wired
|
|
47
53
|
|
|
48
54
|
Persistence, queueing, document/secret/SQL stores — all of them come from
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anbaric",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.57.0",
|
|
4
4
|
"description": "Everything needed to write an Anbaric app: state machines, jobs, document and secret stores, local in-memory implementations and the Anbaric Cloud clients",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"prepublishOnly": "npm run build"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"anbaric-impl-cloud": "^1.
|
|
28
|
-
"anbaric-data-store": "^1.
|
|
29
|
-
"anbaric-state-machine": "^1.
|
|
30
|
-
"anbaric-tsapi": "^1.
|
|
27
|
+
"anbaric-impl-cloud": "^1.57.0",
|
|
28
|
+
"anbaric-data-store": "^1.57.0",
|
|
29
|
+
"anbaric-state-machine": "^1.57.0",
|
|
30
|
+
"anbaric-tsapi": "^1.57.0"
|
|
31
31
|
}
|
|
32
32
|
}
|