@agentshouse/skills 0.1.0-cddf1d04a5650 → 0.1.0-cdf317eaa8570
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/guide/apps/data.md +1 -1
- package/guide/apps/local-first.md +2 -2
- package/guide/apps/page.md +2 -1
- package/guide/apps/runtime-api.md +1 -1
- package/guide/apps/runtime-files.md +27 -16
- package/guide/reference/app-manifest.md +1 -1
- package/guide/reference/triggers.md +1 -1
- package/guide/sites/entry-data-contract.md +1 -1
- package/package.json +1 -1
package/guide/apps/data.md
CHANGED
|
@@ -5,7 +5,7 @@ How an App keeps what it shows as typed documents in the Rooms bound to it.
|
|
|
5
5
|
- Design the Room schema first. Each thing the App shows is one Markdown document in a Room: its frontmatter `type` names its MD type, the rest of its frontmatter holds the fields, and long text goes in `##` sections. `schema.yaml` declares the types ([Schema](reference/schema)).
|
|
6
6
|
- Keep each type in its own folder, such as `tasks/`, and read it by `pathPrefix`: a query naming `types` fails with `unknown-type` while no bound Room declares them.
|
|
7
7
|
- Link types with `reference` fields instead of copying values; a query follows them with `hop` and `backlinks`.
|
|
8
|
-
- `app.json` `room_slots` names the Rooms the App needs, each with `access` `read` or `write` and the `types` it uses ([App manifest](reference/app-manifest)). Bind Rooms with `set_app_bindings`; App code cannot bind and reaches only bound Rooms, so it opens `bridge.ceremony('/bind/<app_ref>?slot=<name>')`, the House page where your User binds Rooms
|
|
8
|
+
- `app.json` `room_slots` names the Rooms the App needs, each with `access` `read` or `write` and the `types` it uses ([App manifest](reference/app-manifest)). Bind Rooms with `set_app_bindings`; App code cannot bind and reaches only bound Rooms, so it opens `bridge.ceremony('/bind/<app_ref>?slot=<name>')`, the House page where your User binds Rooms, which returns to the App.
|
|
9
9
|
- A bound Room must hold each slot type identically in its own `settings/schema.yaml`, beside any other types, or your User is warned. Write it with `edit` before binding; `create_room` makes a new Room.
|
|
10
10
|
- Read an existing Room's `settings/schema.yaml` before inventing types. Two Apps over one schema are two interfaces over the same data, and your User's Agents read and write those documents too.
|
|
11
11
|
- What no browser can do, such as acting when documents change or at a set time, is a Trigger (`create_trigger`) that notifies or starts a Routine on an Agent; what it writes reaches the App at once.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
How an App reads and writes its Rooms on the device, offline included.
|
|
4
4
|
|
|
5
5
|
- The runtime holds every bound Room on the device and streams in every change, from any device, App or Agent. `query`, `search` and `observe` answer from the device and never wait on the network.
|
|
6
|
-
- Draw from `observe` at once, with no loading spinner for Room data and no request of your own; an observation hears each later change by itself, so never poll, refetch or subscribe to House. An answer is `{ pending }` while a Room it reads has not reached this device or been prepared on it, or the search index has not: draw the page without those documents, and keep the empty state for a complete answer that has none.
|
|
6
|
+
- Draw from `observe` at once, with no loading spinner for Room data and no request of your own; an observation hears each later change by itself, so never poll, refetch or subscribe to House. An answer is `{ pending }` while a Room it reads has not reached this device or been prepared on it, or the search index has not: draw the page without those documents, and keep the empty state for a complete answer that has none. `rooms` answers once the runtime knows the Rooms the page reaches. Offer binding a Room when it is empty while the sync status names House reachable (`providerUnreachable` false) and `observe('connection-refusal')` answers `null`; an empty list at any other moment says only that nothing can be listed yet.
|
|
7
7
|
- Write optimistically: write a Room Draft, then `save`. The change shows in every query at once as a Pending Change and reaches House when it can. `save` refuses at once, with its `code`, a change that is `stale`, `changed-underneath` or against the schema: say so and keep the form.
|
|
8
8
|
- Show what the runtime reports: `observe('queue', room)` lists changes House has not confirmed yet, and `observe('sync-status')`'s `attentionRequired` lists each change House refused, returned as a Room Draft with why, to save again or discard.
|
|
9
9
|
- Keep what the User types in the Room Draft (`roomDraft.write`) as they type; it survives a new release replacing the page, a reload and another tab. Draw a form again only when its page changes, never on a streamed change.
|
|
@@ -11,6 +11,6 @@ How an App reads and writes its Rooms on the device, offline included.
|
|
|
11
11
|
- Save a change the User does not type, such as a checkbox, with `saveParts(room, [{ path, parts }])`: it writes no Room Draft, so the one another tab holds stays.
|
|
12
12
|
- Offline, all of this works and saves wait. `bridge.onStatus` reports `offline`; say so quietly.
|
|
13
13
|
- A Room your User reads by Online Read locks once the browser has been offline 2 minutes, and from the moment it opens until House confirms the access. While it is locked, `rooms` lists it `locked: true`, a query or search that does not name it leaves it out, one naming it answers `{ pending }` with `awaits: 'unlock'`, and every other read and write naming it, `save` included, answers the code `room-locked` and keeps nothing. Draw it as locked until it unlocks and keep what the User types in the page; what was saved before stays and is sent then.
|
|
14
|
-
- An outside service is reached only at the origins `app.json` lists in `external_origins
|
|
14
|
+
- An outside service is reached only at the origins `app.json` lists in `external_origins`, directly or through `bridge.callExternal`, which House's server sends; neither carries a key.
|
|
15
15
|
- The page's own storage is a disposable cache, the Room the only durable home of the App's data; handle any code or value you do not know through `code` and `retryable`, which every refusal and failure carries.
|
|
16
16
|
- React: `useObserve` and `useSave` from `@agentshouse/mdruntime/react`. react-admin and Refine: the data providers of `@agentshouse/mdruntime-families`. The whole client is described in [The App runtime](apps/runtime).
|
package/guide/apps/page.md
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
What an App's page draws and how it behaves in the browser.
|
|
4
4
|
|
|
5
5
|
- The App draws everything; House draws nothing around it. Set the tab's title with `bridge.setTab({ title })`.
|
|
6
|
-
- The address bar is the shell's, not your page's: read your place from `bridge.address()` and `bridge.onAddress`, and move with `bridge.push` or `bridge.replace`, so Back, Forward, reload and a shared link keep it; a push to the address already shown replaces it, so a double click adds no history entry. Keep the open item, tab, filter and search in the address. Addresses under `/render`, `/info` and `/tab-icon` are House's.
|
|
6
|
+
- The address bar is the shell's, not your page's: read your place from `bridge.address()` and `bridge.onAddress`, and move with `bridge.push` or `bridge.replace`, so Back, Forward, reload and a shared link keep it; a push to the address already shown replaces it, so a double click adds no history entry. After an act that ends what the page shows, and when a dialog closes, `bridge.replace` the next address; a replace with the address this page was opened from goes back to it, so Back returns to where the person came from. Keep the open item, tab, filter and search in the address. Addresses under `/render`, `/info` and `/tab-icon` are House's.
|
|
7
|
+
- Files: take one in with `binaryFile.attach` the moment it is chosen and keep the Path it answers, hand one out with `binaryFile.download`, and show an image or video in `<room-media>` naming its width and height, so nothing waits for media and nothing moves when it arrives; never read a file whole to show or download it ([files](apps/runtime-files)).
|
|
7
8
|
- Mobile first: lay out from 360 pixels wide up, with no action behind hover alone.
|
|
8
9
|
- Every control works from the keyboard, with visible focus and a label.
|
|
9
10
|
- An empty list says what it will hold and invites the first document.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
What App code reaches through the runtime's client: its surfaces, its reach, observations, Agents and conversations.
|
|
4
4
|
|
|
5
5
|
App code reaches the MD Runtime through the remote client. The surfaces are Rooms, Query,
|
|
6
|
-
Search, Observe, Types, Room Draft, Save, History, Resolve,
|
|
6
|
+
Search, Observe, Types, Room Draft, Save, History, Resolve, binary files, Call,
|
|
7
7
|
Reached, Log, the reported persistence answer, reauthorization, conversation, the chat
|
|
8
8
|
draft, and Presentation State. Sync Status, readiness, the Service Mode, the storage-loss
|
|
9
9
|
statement, the deployment facts and the signed-in member are observations only.
|
|
@@ -12,24 +12,35 @@ change, and no tab sees it then.
|
|
|
12
12
|
|
|
13
13
|
A binary file at a Path is a binary Path entry. Query lists it by `path`, and History each
|
|
14
14
|
of its revisions, with its `binaryFile` record and never its bytes: `{ state: 'accepted',
|
|
15
|
-
revision, path, byteLength, mediaType, sha256 }`, or
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
15
|
+
revision, path, byteLength, mediaType, sha256 }`, or `{ state: 'pending', localId, path,
|
|
16
|
+
byteLength, mediaType, sha256 }` while an upload the panel saved waits for the Provider.
|
|
17
|
+
Text names a file only by a link to its Path, and a field by a `reference: attachment`. Move
|
|
18
|
+
or remove one as a Document, its bytes following.
|
|
19
|
+
|
|
20
|
+
- `binaryFile.attach(room, file)` writes the `File` into the Room at
|
|
21
|
+
`attachments/<YYYY-MM-DD>/<name>`, a free name, and answers `{ kind: 'attached', path }`,
|
|
22
|
+
the Room Path to link, download, show and read at once, `{ kind: 'offline' }`, or a
|
|
23
|
+
refusal or failure. A Room Draft write
|
|
24
|
+
or Save carrying a `file` part is refused as `attach-required`.
|
|
25
|
+
- `binaryFile.download(room, path, revision?)`, called from a click, hands the browser its
|
|
26
|
+
own download of the Provider's address at once, or of a pending file's saved bytes, and
|
|
27
|
+
answers `{ kind: 'started' }`, `blocked` where the browser refused the tab an `.html`
|
|
28
|
+
page opens in, or a refusal or failure.
|
|
29
|
+
- `<room-media room path width height alt>` draws an image, video or audio file of the
|
|
30
|
+
Room. It reserves the box `width` and `height` set, in the file's own pixels, or a 16:9
|
|
31
|
+
one, before any byte; asks for the file only as it nears the view; draws a file the
|
|
32
|
+
browser keeps from its bytes, offline too, and reads and keeps an image; plays a video
|
|
33
|
+
or audio file from the Provider's address loading only its metadata; asks again when a
|
|
34
|
+
shown file's address lapses; asks again while the file cannot be shown yet, such as
|
|
35
|
+
while the Room does not hold it or House did not answer, until House refuses it for
|
|
36
|
+
good; and shows its children where the file cannot be read.
|
|
37
|
+
- `binaryFile.read(room, path, revision?)` answers `{ kind: 'binary', stream, byteLength,
|
|
38
|
+
mediaType }`, the bytes a `ReadableStream` of parts of at most a mebibyte, which the
|
|
39
|
+
browser keeps for later reads, offline too.
|
|
29
40
|
|
|
30
41
|
Rooms, Query, Search, Observe, Types, Room Draft, Save, and Reached never touch the
|
|
31
|
-
network; History, a binary file
|
|
32
|
-
Provider through the Adapter.
|
|
42
|
+
network; History, a binary file's attach and download, a file shown or read that the
|
|
43
|
+
browser does not keep, and Call go to the Provider through the Adapter.
|
|
33
44
|
Call takes the Action names the Adapter declares, any other answering `undeclared`. A Call
|
|
34
45
|
result whose effect the Provider places in a Room carries `at`, that Room and Room
|
|
35
46
|
Version: `reached(room, roomVersion)` answers whether the Room's confirmed state has
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
What an App's `app.json` declares.
|
|
4
4
|
|
|
5
|
-
App manifest, `app.json` at an App’s root: `entry`, its HTML page, and `room_slots`, each with a `name`, `access` `read` or `write`, and `types` from the `schema.yaml` beside it, written like a Room schema; `set_app_bindings` fills a slot with Rooms. Where needed it adds `external_origins`, the https origins its page may reach; `
|
|
5
|
+
App manifest, `app.json` at an App’s root: `entry`, its HTML page, and `room_slots`, each with a `name`, `access` `read` or `write`, and `types` from the `schema.yaml` beside it, written like a Room schema; `set_app_bindings` fills a slot with Rooms. Where needed it adds `external_origins`, the https origins its page may reach; `conversations: true` to read your User’s conversations; `local_search: true` to call `search`; `inboxes: true` to show and answer customer chats, naming `inbox-chat` and `inbox-message` in `room_slots`; `house_model`, the House model types it shows, which it reads from your User’s Private Room under `house/` without binding that Room; `house_acts`, the House acts it calls by their act names, such as `rooms/rename`, never one only a person takes or one that changes what an App reaches; and `theme_colour`, `#rrggbb`. A User who does not own the App is asked once to allow the House model types and House acts it declares, and again only for those a later release adds; a declined one reads nothing and is refused. [Build an App](apps/build) shows how its page works.
|
|
6
6
|
|
|
7
7
|
```json
|
|
8
8
|
{
|
|
@@ -4,6 +4,6 @@ How a Trigger's `condition` and `actions` are written for `create_trigger` and `
|
|
|
4
4
|
|
|
5
5
|
A Room's Triggers are its read-only `house-trigger` documents, one at `house/triggers/<trigger>.md` for each, which House writes as the Trigger's acts left it.
|
|
6
6
|
|
|
7
|
-
`condition`: When it fires, e.g. `{on: "documents", scope: {type: "task"}, mode: "starts_matching", new_documents: false, match: {all: [{path: "/fields/status", eq: "review"}, {path: "/members/assignee", eq: "<User id>"}]}}`; for a new document in a folder, `{on: "documents", scope: {folder: "/answers"}, mode: "starts_matching", new_documents: true, match: {all: []}}`; on documents, `moved_between_rooms: true` fires only on a document moved in from or out to another Room, `false` only on any other change; for arriving items, `{on: "items", address: "<push address>", match: {path: "/json/ref", eq: "refs/heads/main"}}`. A clock is `{on: "clock", cron: "0 9 * * 1", time_zone: "Europe/Berlin"}`, or a day before each task is due: `{on: "clock", scope: {type: "task"}, date: "/fields/due", days: -1, at: "09:00", time_zone: "Europe/Berlin", match: <test>}`.
|
|
7
|
+
`condition`: When it fires, e.g. `{on: "documents", scope: {type: "task"}, mode: "starts_matching", new_documents: false, match: {all: [{path: "/fields/status", eq: "review"}, {path: "/members/assignee", eq: "<User id>"}]}}`; for a new document in a folder, `{on: "documents", scope: {folder: "/answers"}, mode: "starts_matching", new_documents: true, match: {all: []}}`; for any edit of one document, typed or plain, `{on: "documents", scope: {document: "/notes/plan.md"}, mode: "field_changes", field: "/text"}`; on documents, `moved_between_rooms: true` fires only on a document moved in from or out to another Room, `false` only on any other change; for arriving items, `{on: "items", address: "<push address>", match: {path: "/json/ref", eq: "refs/heads/main"}}`. A clock is `{on: "clock", cron: "0 9 * * 1", time_zone: "Europe/Berlin"}`, or a day before each task is due: `{on: "clock", scope: {type: "task"}, date: "/fields/due", days: -1, at: "09:00", time_zone: "Europe/Berlin", match: <test>}`.
|
|
8
8
|
|
|
9
9
|
`actions`: What it does; a `notify` action names whom it reaches, e.g. `{kind: "notify", title: "Ready to test", text: "A task waits.", to: {users: ["<User id>"], fields: ["/members/assignee"], roles: ["owner"]}}`, Users by id, the member a field of the matched document names, and every holder of a Schema Role; a `routine` action names a Routine Access.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
How a Site App's `entry_data` has House serve each route as HTML from Rooms.
|
|
4
4
|
|
|
5
|
-
Entry Data Contract, `entry_data` in a Site App’s `app.json`: House serves each route as HTML from your Rooms before the App starts, running none of your code. Each of `routes` has a `path` (`/`, `/posts/:slug`), optional `query` (functional `?name` parameters with defaults), `queries` (Local Query objects with `types` and a `pathPrefix` at each scope, no `rooms`; `{"$param": "slug"}` takes an argument, `"as": "integer"` converts it; `boundQuery` from `@agentshouse/mdruntime/entry` fills the same query in your page), `interaction` (the queries its first interaction needs), `title`, `description` and `body`. A body node is text, `{text: v}`, `{markdown: v}` of a document, `{tag, attrs, children}`, `{each: v, as, children}` or `{if: v, then, else}`; a value `v` is a literal, `{param}`, `{at, pointer}` into a query result or `each` item, `{join: [v]}`, `{count: v}` or `{stem: v}`. `styles` lists release CSS files. A route that fails starts the App as usual, and the Site document names why.
|
|
5
|
+
Entry Data Contract, `entry_data` in a Site App’s `app.json`: House serves each route as HTML from your Rooms before the App starts, running none of your code. Each of `routes` has a `path` (`/`, `/posts/:slug`), optional `query` (functional `?name` parameters with defaults), `queries` (Local Query objects with `types` and a `pathPrefix` at each scope, no `rooms`; `{"$param": "slug"}` takes an argument, `"as": "integer"` converts it; `boundQuery` from `@agentshouse/mdruntime/entry` fills the same query in your page), `interaction` (the queries its first interaction needs), `title`, `description` and `body`. A body node is text, `{text: v}`, `{markdown: v}` of a document, `{tag, attrs, children}`, `{each: v, as, children}` or `{if: v, then, else}`; a value `v` is a literal, `{param}`, `{at, pointer}` into a query result or `each` item, `{join: [v]}`, `{count: v}` or `{stem: v}`. An `img`, a document's images among them, loads lazily in the box its `width` and `height` name, 16:9 without them. `styles` lists release CSS files. A route that fails starts the App as usual, and the Site document names why.
|
|
6
6
|
|
|
7
7
|
```json
|
|
8
8
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentshouse/skills",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-cdf317eaa8570",
|
|
4
4
|
"description": "The upstream Skills agents.house serves its agents, verbatim, and the texts it writes for them: the Guide, its own Skills among the pages, and the Agent instructions",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|