@lotics/cli 0.284.2 → 0.285.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/AGENTS.md +2 -2
- package/README.md +1 -0
- package/dist/src/cli.js +1644 -1505
- package/docs/building_an_app.md +2 -2
- package/docs/cli_reference.md +1 -1
- package/docs/design.md +10 -3
- package/docs/document_templates.md +1 -1
- package/docs/field_values.md +2 -0
- package/docs/migration.md +1 -1
- package/package.json +1 -1
package/docs/building_an_app.md
CHANGED
|
@@ -6,8 +6,7 @@ reach for the area doc (`lotics docs`) whenever you need the detail.
|
|
|
6
6
|
|
|
7
7
|
**The live app is the only edit surface.** Every change to an app — applying a model, deploying a
|
|
8
8
|
build, setting one query or workflow — mints a new version of it, and rolling back to an earlier
|
|
9
|
-
version is the undo. Nothing about an app lives in a local directory the platform reads back
|
|
10
|
-
there is no project to keep in sync and no deploy to find out whether something works.
|
|
9
|
+
version is the undo. Nothing about an app lives in a local directory the platform reads back.
|
|
11
10
|
|
|
12
11
|
**Rolling back restores the app, not the data.** A table change the model made, and every row a
|
|
13
12
|
workflow wrote while you tried it, stay where they are. Try a write on a throwaway record.
|
|
@@ -115,6 +114,7 @@ cd <dir>
|
|
|
115
114
|
# edit src/App.tsx — node_modules/@lotics/app-sdk/AGENTS.md is the reference
|
|
116
115
|
npm run typecheck && npm run lint && npm test
|
|
117
116
|
lotics app deploy -m "<what changed>" # build, upload, a new version live
|
|
117
|
+
lotics app pull <app_id> # the live version's source, on a machine without the project or after another deploy
|
|
118
118
|
```
|
|
119
119
|
|
|
120
120
|
What the app reads and writes is bound on the app, never in the project: `lotics run
|
package/docs/cli_reference.md
CHANGED
|
@@ -43,7 +43,7 @@ Per-command syntax, flags, contracts, and gotchas for the public `lotics` CLI. S
|
|
|
43
43
|
| `lotics knowledge hide <id...>` / `lotics knowledge unhide <id...>` | `PATCH /v1/knowledge_docs` with `{ knowledge_doc_ids, hidden }`. Hiding takes docs out of every **listing** — the Library's list, `list_knowledge`, and the corpus `grep_knowledge` searches — while leaving IAM untouched and keeping them readable **by id** (`read_knowledge` with an id, a code run staging one, an app agent's declared set). So it can never silently break an app that depends on a doc, and unhiding costs nothing. Refuses the no-argument form rather than reading it as "everything". |
|
|
44
44
|
| `lotics knowledge rm <id>` | Archive the doc via `delete_knowledge` (`{ knowledge_doc_id }`). The REST execute path does not gate `needsApproval`, so this runs unattended. |
|
|
45
45
|
| `lotics setup <model.json> [--email <addr>] [--json]` | **The whole first run, in one command.** Creates an account when this machine has no credential (the same call `auth signup` makes — `--name` and `--timezone` apply), then applies the model to its workspace, then prints the one-time sign-in link. **When that email already has an account it hands over to the `lotics auth login` flow** — it prints the sign-in page to open and the code it must show, and **exits 1 having created nothing**; the person presses Confirm and runs the same command again, which collects the key and carries on into the model. (`--wait` holds the terminal through the Confirm instead, finishing in one command.) The re-run is not refused for naming an `--email` it is now signed in as — that address IS the account it holds, not a second one. The file is a workspace MODEL, and it is read and checked before an account is created — the design decisions an apply would refuse it for too (`lotics docs design`), since a new workspace holds no rows to change them — because a file with a typo in it must not leave an organization behind. Then it is `lotics model apply` run on the new workspace: its tables, rows and apps; the sign-in link lands on its app when it has one, else on the workspace's app list. It exists because the two-command form has a seam where the FIRST command exists only to produce a credential for the second, and a caller pasting a prompt has to get both right. **`--email` is only for creating an account**: with a credential already resolvable it is REFUSED rather than obeyed, because the two can name different organizations and preferring either one silently writes into an org the caller did not name — the message says how to do each thing on purpose. Without it, `setup` applies the model to the account you already have. A path positional after the file is accepted and IGNORED with a warning — `setup` writes nothing to disk — so a prompt that passes one still runs. **`--json` prints one object on stdout and nothing else** — what `lotics model apply --json` does (`tables`; `apps`, each with `alias`, `app_id`, `version_id`, `origin`, `address` and `findings`; and `findings`) plus `organization_id`, `workspace_id` and `signin_url`, and a `warnings` array carrying everything the prose form would have said out of band, such as a sign-in link that could not be minted. A warning is never merely silenced: when the command fails with an error before it can emit, the ones it had collected go to stderr alongside it. Reachable with no install: `npx -y @lotics/cli setup …`. |
|
|
46
|
-
| `lotics model apply <model.json> [--app <alias> ...] [--plan] [--json]` | **The model, applied to this workspace, through the `apply_model` tool.** The file is read and checked against the model's own rules with the validator the server runs, every problem in one run, before anything is uploaded. **The apply refuses an app leaving out a treatment its rows call for** (`lotics docs design`) — judged by the server beside the workspace's rows, before it writes anything — until the app adopts it or states why not under the `declines` key the refusal names; the refusal carries each refused app's patch adopting its decisions, to merge in the order printed. Documents a row attaches by a path beside the file are uploaded first and the rows sent with their `fil_` ids; a path this workspace already recorded keeps its id, so a re-apply uploads nothing twice. **Where the file was pulled (`-o`) or applied in this workspace before, only what it changed since is sent**, as a `patch`: what changed in the workspace since and the file does not touch stays. What the file takes out is sent as a removal: it goes where an apply rebuilds it (an app's acts and columns, a write rule) and is refused, naming the tool that deletes it, where an apply never deletes it (a table, a field, an option, an app). A file that reorders items named by their `alias` sends the whole model, said on stderr. The copy each change is read against is kept per workspace and file under `~/.lotics/model_bases`: an apply narrowed by `--app` leaves in it the other apps as they were, so the next apply sends their edits again, and an apply that fails — refused, or cut off — leaves none, so the next sends the whole model. Then the tool adopts or creates every table (the table this workspace bound the entity to, else an existing table of the same label, is ADOPTED and given the fields, options and views it lacks; no stored value changes), writes first rows only where every bound table is empty, and mints a new version of each app the model declares — `--app` (repeatable, comma-separated) narrows which apps, while the tables are applied whole. Prints one line per app — alias, `app_id`, `created`/`updated` with the version minted or `unchanged`, and the address it is served at — then the model's notes once, as the server states them. **`--plan` writes nothing and uploads nothing**: it prints what the apply would do to the tables (what it would create, what it leaves as the workspace has it, what the two disagree about), which apps it would create or update, and what it would refuse an app for — the decisions among its findings, read beside the workspace's rows, with each refused app's patch — exiting 1 when it would refuse one; workflow bodies are checked only at apply, since they name fields a plan has not created. **A rollback restores an app's earlier version** (`lotics run rollback_app`); table changes and data writes stay. Resolves and ANNOUNCES its workspace first. `--json` prints `{workspace_id, tables, apps, findings}` on stdout (with `--plan`, each table and app is what the apply would do, an app the patches change carrying its body as they leave it as `draft`, and `designs` each refused app's patch in merge order), or `{ok: false, findings}` when the file does not check. |
|
|
46
|
+
| `lotics model apply <model.json> [--app <alias> ...] [--plan] [--json]` | **The model, applied to this workspace, through the `apply_model` tool.** The file is read and checked against the model's own rules with the validator the server runs, every problem in one run, before anything is uploaded. **The apply refuses an app leaving out a treatment its rows call for** (`lotics docs design`) — judged by the server beside the workspace's rows, before it writes anything — until the app adopts it or states why not under the `declines` key the refusal names; the refusal carries each refused app's patch adopting its decisions, to merge in the order printed. Documents a row attaches by a path beside the file are uploaded first and the rows sent with their `fil_` ids; a path this workspace already recorded keeps its id, so a re-apply uploads nothing twice. **Where the file was pulled (`-o`) or applied in this workspace before, only what it changed since is sent**, as a `patch`: what changed in the workspace since and the file does not touch stays. What the file takes out is sent as a removal: it goes where an apply rebuilds it (an app's acts and columns, a write rule) and is refused, naming the tool that deletes it, where an apply never deletes it (a table, a field, an option, an app). A file that reorders items named by their `alias`, or states a `null` a patch would read as a removal, sends the whole model, said on stderr. The copy each change is read against is kept per workspace and file under `~/.lotics/model_bases`: an apply narrowed by `--app` leaves in it the other apps as they were, so the next apply sends their edits again, and an apply that fails — refused, or cut off — leaves none, so the next sends the whole model. Then the tool adopts or creates every table (the table this workspace bound the entity to, else an existing table of the same label, is ADOPTED and given the fields, options and views it lacks; no stored value changes), writes first rows only where every bound table is empty, and mints a new version of each app the model declares — `--app` (repeatable, comma-separated) narrows which apps, while the tables are applied whole. Prints one line per app — alias, `app_id`, `created`/`updated` with the version minted or `unchanged`, and the address it is served at — then the model's notes once, as the server states them. **`--plan` writes nothing and uploads nothing**: it prints what the apply would do to the tables (what it would create, what it leaves as the workspace has it, what the two disagree about), which apps it would create or update, and what it would refuse an app for — the decisions among its findings, read beside the workspace's rows, with each refused app's patch — exiting 1 when it would refuse one; workflow bodies are checked only at apply, since they name fields a plan has not created. **A rollback restores an app's earlier version** (`lotics run rollback_app`); table changes and data writes stay. Resolves and ANNOUNCES its workspace first. `--json` prints `{workspace_id, tables, apps, findings}` on stdout (with `--plan`, each table and app is what the apply would do, an app the patches change carrying its body as they leave it as `draft`, and `designs` each refused app's patch in merge order), or `{ok: false, findings}` when the file does not check. |
|
|
47
47
|
| `lotics model pull [-o <model.json>]` | **This workspace's model, rebuilt from what owns each part** — the tables, fields, options, templates and roles the workspace holds, how rows are recognised, and each app's body from its current version — through the `get_model` tool, as the file `model apply` reads: to stdout, or to the file `-o` names. What the workspace holds that a model cannot state is printed on stderr, never written into the file. Applying what it wrote changes nothing. With `-o`, what it wrote is the copy the next `model apply` of that file reads its changes against. |
|
|
48
48
|
| `lotics app create <name> --custom [path]` | **A custom-code app**: creates the app (`POST /v1/apps`), scaffolds a Vite + React + TypeScript project into `[path]` (default `./<name>`, refused when not empty — before the app row exists) that depends on `@lotics/app-sdk` alone and draws with plain React, and installs it (`npm install --ignore-scripts`), then writes the declarations of the app's live bindings (`get_app_types`) into `.lotics/`, which the project's `tsconfig.json` includes. `package.json#lotics` names the app and its workspace, which is how `app deploy` in that directory finds both. The app has no version until the first `lotics app deploy`. `--custom` is required: an app the runtime draws from a model is made by `lotics model apply`. The SDK's reference is `node_modules/@lotics/app-sdk/AGENTS.md` inside the project. |
|
|
49
49
|
| `lotics app pull [app_id] [path]` | **A custom-code app's live source, as a project ready to deploy on it.** The target is `[path]`, else this directory when it is the app's project (or no app is named), else `./<name>`. **The app's own project is brought up to date in place** — but only when it holds no edit since the version `package.json#lotics.current_version_id` names: its source (packed as a deploy packs it) is compared with that version's archive, ignoring `.lotics/` and `package.json#lotics`, and any difference refuses the pull, naming the changed files; a pull never merges, so local work is never lost. Already at the live version is a no-op that says so. **An empty or new directory receives the source whole**; any other directory is refused. Downloads come from `GET /v1/apps/{id}/versions/{version_id}/source`. `package.json#lotics` is then set to exactly the app, its workspace and the pulled version, dropping every other key an older CLI wrote there, so the next `lotics app deploy` builds on the live version; then `.lotics/` is written (`get_app_types`) and dependencies installed (`npm ci` with a lockfile, else `npm install`, both `--ignore-scripts`). A JSON app has no source tree: the server's refusal names `get_model`, and `lotics model pull` is its pull. |
|
package/docs/design.md
CHANGED
|
@@ -64,6 +64,7 @@ then check again. A note refuses nothing.
|
|
|
64
64
|
| Papers to read | an act's `intake` with `fills` | `model/acts` |
|
|
65
65
|
| Calls and visits | an act's `record` | `model/acts` |
|
|
66
66
|
| Documents covering lines | a rows block with `under` | `model/blocks` |
|
|
67
|
+
| Rows on file a record takes in | a rows block with `pick` | `model/blocks` |
|
|
67
68
|
| One owner's question across jobs | a dashboard app | `model/dashboards` |
|
|
68
69
|
|
|
69
70
|
### Faces and pictures
|
|
@@ -167,7 +168,9 @@ default record: every field a person writes.
|
|
|
167
168
|
|
|
168
169
|
Rows that each belong to one row of another entity (a one-row link to it) are drawn under that row: a `rows` block on
|
|
169
170
|
its record, a `timeline` where they are a log, an `agenda` where they are planned on a day and within it, a roster of
|
|
170
|
-
them, or lanes of them by that link. Which children a record lists is the author's — one of them at least.
|
|
171
|
+
them, or lanes of them by that link. Which children a record lists is the author's — one of them at least. Rows on
|
|
172
|
+
file before the row they come to belong to — a job's cost lines before the supplier bill over them — are picked into
|
|
173
|
+
it: a rows block with `pick`, often with `create: false` and `remove: false`.
|
|
171
174
|
|
|
172
175
|
### Papers
|
|
173
176
|
|
|
@@ -188,12 +191,16 @@ placeholder, the reader ticking which to make. A template no act names is made b
|
|
|
188
191
|
|
|
189
192
|
A paper the business is brought and reads is an act's `intake`: the press takes the papers, an agent reads
|
|
190
193
|
them, and each is filed as the line of its kind in the child the record `expect`s, while `fills` writes what
|
|
191
|
-
they state into the record's fields —
|
|
194
|
+
they state into the record's fields — a single link as a row the agent finds among those the app reads of its
|
|
195
|
+
entity — shown before it is saved. Worked: `examples/case`.
|
|
192
196
|
|
|
193
197
|
#### Under
|
|
194
198
|
|
|
195
199
|
A rows block with `under`: the documents that cover lines (an invoice over its fee lines) stand as headings
|
|
196
|
-
over the lines they cover, and a line no document covers offers to make one.
|
|
200
|
+
over the lines they cover, and a line no document covers offers to make one. A document entered as it arrives,
|
|
201
|
+
over lines already on file (a supplier bill), picks them from its own record instead: a rows block with `pick`.
|
|
202
|
+
Choose one per document: a document a make covers lines by is never also picked into, since a pick does not check
|
|
203
|
+
what the make does.
|
|
197
204
|
|
|
198
205
|
### Calls
|
|
199
206
|
|
|
@@ -130,7 +130,7 @@ lotics download <file_id> -o ./out/
|
|
|
130
130
|
`table`/`list`/loop variables. `filename` excludes the extension (the type sets it).
|
|
131
131
|
- `generate_document` renders the template's own type and returns a generated file object; take
|
|
132
132
|
its `file_id` onward.
|
|
133
|
-
- In a workflow, a **generate step** calls the same
|
|
133
|
+
- In a workflow, a **generate step** calls the same tool and hands the `file_id` to the next
|
|
134
134
|
step (attach to a record, send as an attachment, etc.).
|
|
135
135
|
|
|
136
136
|
## Discovering and managing templates
|
package/docs/field_values.md
CHANGED
|
@@ -27,6 +27,8 @@ one value.
|
|
|
27
27
|
- A single-select is a ONE-element array; a bare `"opt_…"` is accepted and wrapped. A single
|
|
28
28
|
`select_member` takes a bare `"mbr_…"` the same way.
|
|
29
29
|
- `select_record_link` and `files` take an array only.
|
|
30
|
+
- A `files` id the write adds must name a live file of this workspace, or the whole write is refused;
|
|
31
|
+
an id that cell already holds stays, though its file was archived since.
|
|
30
32
|
- Two options on a single-select, or two members on a single `select_member`, are refused.
|
|
31
33
|
- `update_records`' `add_to`, `remove_from` and `replace` take arrays of the same items: `opt_` keys
|
|
32
34
|
for a select, member ids for a `select_member`, record ids for a `select_record_link`, file ids for
|
package/docs/migration.md
CHANGED
|
@@ -20,7 +20,7 @@ templates and roles are the workspace's own.
|
|
|
20
20
|
| `lotics app regenerate` | change the model file, then `lotics model apply` |
|
|
21
21
|
| `lotics scaffold diff` | `lotics model apply <model.json> --plan` — what the apply would change, writing nothing |
|
|
22
22
|
| `lotics scaffold export` | `lotics model pull [-o <model.json>]` — the workspace's model, rebuilt from what owns each part |
|
|
23
|
-
| `lotics app
|
|
23
|
+
| `lotics app codegen`, `app check`, `app dev`, `app preview` | nothing local: read an app with `lotics run get_app`, and change it through its tools |
|
|
24
24
|
| `lotics app workflow set` / `app query set` / `app agent set` | `lotics run set_app_workflow` / `set_app_queries` / `set_app_agent` — each mints a version |
|
|
25
25
|
| `lotics app versions` + a redeploy of an old tree | `lotics run query_app_versions`, then `lotics run rollback_app` — restores the app's earlier version; table changes and data writes stay |
|
|
26
26
|
| `lotics app rename`, `app subdomain`, `package.json#lotics.capabilities` | `lotics run update_app` (`name`, `public_subdomain`, `capabilities`) |
|