@agentshouse/skills 0.1.0-cbac35d4f59f1 → 0.1.0-cbd84a558d68d
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/agent-instructions.json +1 -1
- package/guide/apps/data.md +1 -1
- package/guide/apps/design.md +1 -1
- package/guide/apps/runtime-api.md +3 -2
- package/guide/apps/runtime-files.md +14 -14
- package/guide/apps/search.md +5 -4
- package/guide/get-started.md +2 -4
- package/guide/reference/access-level.md +1 -1
- package/guide/reference/agent-function.md +1 -1
- package/guide/reference/schema.md +1 -1
- package/guide/sites/build.md +3 -3
- package/guide/sites/counter.md +12 -6
- package/guide/sites/entry-data-contract.md +2 -2
- package/guide/sites/first-load.md +4 -5
- package/guide/sites/runtime.md +5 -2
- package/guide/sites/tags.md +9 -0
- package/guide/skills/build-app.md +9 -9
- package/guide/skills/house-onboarding.md +1 -1
- package/guide/skills/prototype-app.md +14 -27
- package/guide/skills/wizard.md +1 -1
- package/package.json +1 -1
package/agent-instructions.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"Work with House through the `house` CLI, `house <tool> '<arguments as JSON>'`: `house --help` lists the Tools and `house help <tool>` names a Tool's arguments."
|
|
5
5
|
],
|
|
6
6
|
"routing": [
|
|
7
|
-
"Read with `shell` and `
|
|
7
|
+
"Read with `shell` and `info`. Write with `files_batch`; `records_append` adds a record from one of your Sources.",
|
|
8
8
|
"For anything else, `find_command`, then `run_command`.",
|
|
9
9
|
"Optional per-Room instructions: `/rooms/private/rooms/<handle>/AGENTS.md`."
|
|
10
10
|
],
|
package/guide/apps/data.md
CHANGED
|
@@ -6,7 +6,7 @@ How an App keeps what it shows as typed documents in the Rooms bound to it.
|
|
|
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` over bound Rooms none of which declares them, and answers `{ pending }` instead while the App reaches no bound Room yet; an observed query that has already answered answers `{ pending }` while its bound Rooms refuse it, and answers again once they declare what it names.
|
|
7
7
|
- Link types with `reference` fields instead of copying values; a query follows them with `hop` and `backlinks`.
|
|
8
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 `apps/bindings/set`; 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
|
-
- A bound Room must hold each slot type identically in its own `settings/schema.yaml`, beside any other types, or its binding warns the User who bound it, and `apps/bindings/list` names that release and slot in its `
|
|
9
|
+
- A bound Room must hold each slot type identically in its own `settings/schema.yaml`, beside any other types, or its binding warns the User who bound it, and `apps/bindings/list` names that release and slot in a line of its `mismatches`, to the App's owner too. Only `indexed`, rule keywords and `title`s may differ, and a type whose `indexed` leaves out a field the App's names still fits, with a warning there naming the fields to index. Write it with `files_batch` before binding; `rooms/create` makes a new Room.
|
|
10
10
|
- A slot may hold a Space instead (`apps/bindings/set` with `space_ref`): every Room of it your User holds, now and later. An App its owner puts into a Space (`apps/space/set`) uses that Space's schema instead of its own `schema.yaml`, and every member of the Space uses it, each slot holding the Space's Rooms.
|
|
11
11
|
- 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.
|
|
12
12
|
- House's own facts, such as your User's Rooms and the Space each is in, come from House acts: name each in `app.json` `house_acts` and call it with `runtime.call('<act>', input)`, such as `runtime.call('rooms/list', {})`. A call needs a connection, so offline show what the bound Rooms hold. A slot holding the Private Room brings its Triggers and none of the other documents House writes under its `house/`.
|
package/guide/apps/design.md
CHANGED
|
@@ -7,6 +7,6 @@ What an App's design settles before its code, one page per question House answer
|
|
|
7
7
|
- [Designs that load House](apps/design-load): what its saves, Triggers and functions cost, and the designs that cost less.
|
|
8
8
|
- [An App's look](apps/design-look): what House draws around its page, and what the App sets.
|
|
9
9
|
|
|
10
|
-
Keep a Room for the App where you write how it is developed: its decisions, its
|
|
10
|
+
Keep a Room for the App where you write how it is developed: its decisions, its plan and tickets, and what its Triggers and functions do. Name that Room in the App's README, so the next agent working on the App finds it. House reads nothing there.
|
|
11
11
|
|
|
12
12
|
[Example: tasks](apps/example-tasks) follows these pages.
|
|
@@ -27,8 +27,9 @@ not, each with its `cli` and `environment` `{ identity, name, state }`, `state`
|
|
|
27
27
|
`offline`; offline every Agent a conversation names. Each conversation the Provider lists is held
|
|
28
28
|
complete in the browser. `conversation.list()` and `observe('conversations')` answer each
|
|
29
29
|
with its Agent's identity and name, its name, created and finished times, last outcome,
|
|
30
|
-
live `state` (`asking` while a question waits, `working` while a turn runs, else `idle`)
|
|
31
|
-
|
|
30
|
+
live `state` (`asking` while a question waits, `working` while a turn runs, else `idle`),
|
|
31
|
+
`started`, when the running turn began, or `null`, `jobs`, the kinds and counts of what a turn
|
|
32
|
+
left running, and `deliveryWaiting`, the messages no turn has taken yet. `observe('conversation', id, {
|
|
32
33
|
limit, total: true })` holds its latest `limit` messages, at most 1,000, oldest first,
|
|
33
34
|
`total` their count, and `next` while older ones exist, which `after` takes, there or in
|
|
34
35
|
`conversation.read(id, { limit, after })`, for the window before; its chat draft; and,
|
|
@@ -6,16 +6,17 @@ Presentation State is one value per App, kept in the browser and shared by its t
|
|
|
6
6
|
`presentation.read()` answers it, `null` before anything is kept,
|
|
7
7
|
`observe('presentation')` hears it whole, `presentation.write(value)` replaces it whole,
|
|
8
8
|
and `presentation.edit(members)` sets each member named, or removes one named `null`, in
|
|
9
|
-
the state as it stands, so tabs
|
|
9
|
+
the state as it stands, so tabs editing different members keep each other's change:
|
|
10
10
|
never write back a value read before. Each rejects when the browser does not keep the
|
|
11
11
|
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
|
-
|
|
15
|
+
revision, path, byteLength, mediaType, sha256, width, height }`, or with `state: 'pending'`
|
|
16
|
+
and a `localId` for `revision` while an upload the panel saved waits for the Provider.
|
|
17
|
+
House's own pages keep an image's proportions by them, an Entry Page `srcset` and
|
|
18
|
+
`picture`. Text names a file only by a link to its Path, a field by a `reference:
|
|
19
|
+
attachment`. Move or remove one as a Document, its bytes following.
|
|
19
20
|
|
|
20
21
|
- `binaryFile.attach(room, file)` writes the `File` into the Room at
|
|
21
22
|
`attachments/<YYYY-MM-DD>/<name>`, a free name, and answers `{ kind: 'attached', path }`,
|
|
@@ -27,26 +28,25 @@ or remove one as a Document, its bytes following.
|
|
|
27
28
|
answers `{ kind: 'started' }`, `blocked` where the browser refused the tab an `.html`
|
|
28
29
|
page opens in, or a refusal or failure.
|
|
29
30
|
- `<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
|
|
31
|
+
Room. It reserves the box `width` and `height` set, in the file's pixels, or a 16:9
|
|
31
32
|
one, before any byte; asks for the file only as it nears the view; draws a file the
|
|
32
33
|
browser keeps from its bytes, offline too, and reads and keeps an image; shows a video's
|
|
33
34
|
first frame with a play mark and plays it only in House's full-screen viewer, which a
|
|
34
35
|
press on it opens, and plays an audio file, loading only either's metadata from the
|
|
35
|
-
Provider's address; asks again when a shown file's address lapses
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
good; and shows its children where the file cannot be read.
|
|
36
|
+
Provider's address; asks again when a shown file's address lapses, and while the file
|
|
37
|
+
cannot be shown yet, such as while the Room does not hold it or House did not answer,
|
|
38
|
+
until House refuses it for good; and shows its children where the file cannot be read.
|
|
39
39
|
- `binaryFile.read(room, path, revision?)` answers `{ kind: 'binary', stream, byteLength,
|
|
40
|
-
mediaType }`, the bytes a `ReadableStream` of parts of at most
|
|
40
|
+
mediaType }`, the bytes a `ReadableStream` of parts of at most 1 MiB, which the
|
|
41
41
|
browser keeps for later reads, offline too.
|
|
42
42
|
|
|
43
|
-
Rooms, Query, Observe, Types, Room Draft, Save
|
|
44
|
-
Search, History, a
|
|
43
|
+
Rooms, Query, Observe, Types, Room Draft, Save and Reached never touch the network;
|
|
44
|
+
Search, History, a file's attach and download, a file shown or read that the
|
|
45
45
|
browser does not keep, and Call go to the Provider through the Adapter.
|
|
46
46
|
Call takes the Action names the Adapter declares, any other answering `undeclared`. A Call
|
|
47
47
|
result whose effect the Provider places in a Room carries `at`, that Room and Room
|
|
48
48
|
Version: `reached(room, roomVersion)` answers whether the Room's confirmed state has
|
|
49
|
-
reached it,
|
|
49
|
+
reached it, and `reached(room, roomVersion, path)`
|
|
50
50
|
whether the held copy of that document was written later. A History revision names its
|
|
51
51
|
author, `{ kind: 'user', id }` or `{ kind: 'inbox', id, name }`; History of a Path no
|
|
52
52
|
document holds answers the removed document's revisions, newest first, with `deleted:
|
package/guide/apps/search.md
CHANGED
|
@@ -5,11 +5,12 @@ How `search` finds Documents by words through House, and how a page finds them o
|
|
|
5
5
|
`search({ text, rooms })` asks House's search once and online: there
|
|
6
6
|
is no observed search and the device keeps no full-text index. `rooms` names Room locators
|
|
7
7
|
and defaults to every Room the page binds; the search never leaves those Rooms, and finds
|
|
8
|
-
words in every Document
|
|
8
|
+
the words, as written and ignoring case, in every Document of each Room your User holds at
|
|
9
|
+
the Keep or Open level. A Room held at the Search level is not searched.
|
|
9
10
|
|
|
10
|
-
- **Results.** `{ kind: 'found', documents }`,
|
|
11
|
-
its `room
|
|
12
|
-
hit's Document with `query` naming its `paths`.
|
|
11
|
+
- **Results.** `{ kind: 'found', documents }`, in path order and unranked, at most 20 hits.
|
|
12
|
+
A hit names its `room`, its `path`, the first `line` holding the words and a short
|
|
13
|
+
`snippet` of that line. Read a hit's Document with `query` naming its `paths`.
|
|
13
14
|
- **Offline.** Without a connection `search` answers `{ kind: 'offline' }`, and where no
|
|
14
15
|
House search is reached, `{ kind: 'undeclared' }`. Find Documents then with a
|
|
15
16
|
[Local Query](apps/local-query): by Path, name, field values and `text`, a phrase its text
|
package/guide/get-started.md
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
# Get started
|
|
2
2
|
|
|
3
|
-
What House is, where your User signs up and how
|
|
3
|
+
What House is, where your User signs up and where to read how to connect.
|
|
4
4
|
|
|
5
5
|
House keeps Markdown files in Rooms, which your User shares with other people and their agents.
|
|
6
6
|
|
|
7
7
|
Sign-up page: <origin>/sign-up
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Your User signs up on that page; then add the MCP address to this client as a remote MCP server, and your User signs in when it asks.
|
|
9
|
+
How to connect: <origin>/connect
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
How much of a Room a grant or a Share lets its holder do with its text, and where.
|
|
4
4
|
|
|
5
|
-
Access level, `level` on a Room grant or a Share’s Room item, each level including the one before it: `search`, the Search level, reaches the Room through `shell` and `
|
|
5
|
+
Access level, `level` on a Room grant or a Share’s Room item, each level including the one before it: `search`, the Search level, reaches the Room through `shell` and `info`, each reply at most <mcp-read-size> of the Room’s text, and for App code only through the pages of rows [`queryHouse`](apps/query-house) asks House for, which no agent reaches, with no copy anywhere; `open`, the Open level, also opens the Room in browser Apps while the browser is online, and acts as `search` everywhere else; `keep`, the Keep level, also copies the Room to the devices that keep it, offline included, and is the one `export` needs. An App that reads the Room on the device, through `query` and `observe`, needs `open` or `keep`.
|
|
6
6
|
|
|
7
7
|
```json
|
|
8
8
|
{ "room_ref": "r_ab12.1", "level": "open", "operations": ["write"] }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
How an Agent function document in the Private Room is written, one for each Room it serves.
|
|
4
4
|
|
|
5
|
-
Agent function, `/rooms/private/rooms/<room-handle>/agent-functions/<name>.md`, serving the Room `<room-handle>` names: `description`; `input`, a text saying what to send, empty if nothing; `agent`, the identifier of the one of your User's current Agents it starts; and `afk`, `true` for a run nobody watches, off when absent, under which Kit answers every question and permission prompt of the conversation a request starts by itself, for that conversation's life. The body is the instruction, which never leaves the Private Room. Writing it needs your User's write in that Room. House writes its card, the description, input, Agent and `answer`, at `/rooms/<room-handle>/house/agent-functions/<name>.md`, where every member reads it, and refuses a name a card there already holds as `name_taken`. An Agent function a second Room needs is a copy under that Room's handle. While its document is not written in this form, every request for it is refused `agent_function_unreadable`. Anyone who writes that Room asks it with `agent-functions/send` naming the card, or names the `agent` with their own words, as the Standing answer there allows: the card's `answer`, or the Agent's for own words. `at_once`, the default, starts it; `ask_me` waits for the owner's approval; `off` refuses it, `agent_function_not_admitted` or `own_text_not_admitted`. Only the owner sets an answer, on the Room's House page; no field of this document holds one. The owner, their agents and their Private Room's Triggers start at once under every answer, a Trigger of another Room asks as its writers do, and `
|
|
5
|
+
Agent function, `/rooms/private/rooms/<room-handle>/agent-functions/<name>.md`, serving the Room `<room-handle>` names: `description`; `input`, a text saying what to send, empty if nothing; `agent`, the identifier of the one of your User's current Agents it starts; and `afk`, `true` for a run nobody watches, off when absent, under which Kit answers every question and permission prompt of the conversation a request starts by itself, for that conversation's life. The body is the instruction, which never leaves the Private Room. Writing it needs your User's write in that Room. House writes its card, the description, input, Agent and `answer`, at `/rooms/<room-handle>/house/agent-functions/<name>.md`, where every member reads it, and refuses a name a card there already holds as `name_taken`. An Agent function a second Room needs is a copy under that Room's handle. While its document is not written in this form, every request for it is refused `agent_function_unreadable`. Anyone who writes that Room asks it with `agent-functions/send` naming the card, or names the `agent` with their own words, as the Standing answer there allows: the card's `answer`, or the Agent's for own words. `at_once`, the default, starts it; `ask_me` waits for the owner's approval; `off` refuses it, `agent_function_not_admitted` or `own_text_not_admitted`. Only the owner sets an answer, on the Room's House page; no field of this document holds one. The owner, their agents and their Private Room's Triggers start at once under every answer, a Trigger of another Room asks as its writers do, and `info` on a Room root names the Agents you may ask there with their answers. An Agent function request's input is text the Agent reads, and House checks no shape. Mail your conversation sends with `agent-functions/mail/send` and a request it sent reaches the conversation that request started at once where that Agent's own-words answer there is `at_once`; otherwise `agent-functions/mail/send` answers `waiting: true` and the mail waits for that Agent's owner, and a declined one comes back to you as House's message saying so. That conversation's mail always comes back to yours. A request's run is the first turn of the conversation it starts: during that turn the Agent names the document it wrote in the request's Room as the request's result with `agent-functions/result/set`, and the turn's end finishes the request. The conversation stays active until it is Done, which `conversations/mark-done` sets at the end of a turn and which nothing undoes, so mail reaches it after its run.
|
|
6
6
|
|
|
7
7
|
A Trigger's `message` action puts its `text`, a link to what matched and its files into the active conversation, one not Done, its Agent function started from that Room for what the Event is about: the chat of a customer's `chat-message`, the matched document or item, or the Trigger for a `cron` clock. Its Event shows `continued` with that `request`; with none, it starts the Agent function as a `agent_function` action does, `requested`. A conversation waiting for approval refuses it, `refused` with `conversation_waiting`. The Agent reads a customer's message as a customer's words, one from a Trigger of its owner's Private Room as the owner's instruction, and any other as what matched, never an instruction. A `agent_function` action starts a new request on every Event. A `done` action marks Done every active conversation a request of its Trigger's Room started for the Event's document, whoever owns its Agent, but one waiting for approval, which stays for its owner to approve or decline; its Event shows `marked` with their number, `conversations`, 0 when there are none, as on a `cron` clock, whose Event names no document.
|
|
8
8
|
|
|
@@ -4,7 +4,7 @@ How a Room's `settings/schema.yaml` declares its document types.
|
|
|
4
4
|
|
|
5
5
|
Schema, `/rooms/<room>/settings/schema.yaml`: one JSON Schema in YAML. Each top-level key is an MD type holding the schema of its documents' values; `$defs` holds shapes reused through `$ref: '#/$defs/<name>'`. An object setting neither `additionalProperties` nor `unevaluatedProperties` refuses other keys. House adds `reference` on a string at any depth, naming the types, or `attachment`, its value links to, and `cross_room: true` beside it, letting that be another Room's document of those types; a link or reference written as its `/rooms/<room>/` path is stored relative to the document; `title` on a field, the label a document shows for it, its key when it has none; `contentMediaType: text/markdown` on a string, Markdown text under its own heading; and `member_document: true` on one type, whose documents name their member with `member`, a User Identifier from `rooms/members/list`. On a type, `create_roles` lists the Schema Roles that may create its documents and `delete_roles` those that may delete them, and changing a document's `type` needs both; on a field of a type's own `properties`, `change_roles` lists those that may change it, `initial_roles` those that may set it on a new document, and `transitions` the `{from, to, roles}` changes it may make, `null` standing for absent; `owner` and `member` are built in, `[]` allows nobody, and only someone who manages the Room's access changes them. `files_batch` creates, patches or replaces it, House checks the whole text it leaves, and the same call may rewrite the documents a change breaks.
|
|
6
6
|
|
|
7
|
-
A Room in a Space shows its Space's schema at that path and keeps none of its own: its owner and a member who can write in the Space change it there, a rule keyword only someone who manages the Space, in an edit
|
|
7
|
+
A Room in a Space shows its Space's schema at that path and keeps none of its own: its owner and a member who can write in the Space change it there, a rule keyword only someone who manages the Space, in an edit that may also change that Room's documents and no other Room's, checked against every document of every Room of the Space as the edit leaves them; a change that would break a document of another Room is refused naming it, so change that document in its own edit first. A Room taken out of its Space keeps the last version as its own. Every Room also knows the [Inbox types](reference/inbox-types) and the [Wayfinding types](reference/wayfinding-types) without declaring them.
|
|
8
8
|
|
|
9
9
|
A typed document keeps only `type`, `member`, `submitted` and House's other keys in its frontmatter and writes its values in its body: `name` as its `#` line; under it each short value as one `- **Label**: value` line, yes or no as `- [x] Label` or `- [ ] Label`, a reference as a link, a group of short values as an indented list under its label and a list of plain values as indented bullets; a Markdown text, or a value holding a line break, under its own `##` heading, one level deeper per level of nesting; rows of short values as a table whose column headings are labels; any other list as one heading per item, named by the item's `name`; and a value of no single JSON type as one fenced `json` block under its heading. Values come in any order and in any spelling GitHub Markdown reads alike. The list directly under the `#` line is the value list; a heading naming no field, the text around the values and everything after a `---` line is free text. A refusal names the line: `repeated-value` for a value written twice, `unknown-label` for a value line naming no field, `malformed-value` for a value its type's form does not read. Changing a `title` relabels every document of the type.
|
|
10
10
|
|
package/guide/sites/build.md
CHANGED
|
@@ -4,7 +4,7 @@ How to build a Site, an App at a public address anyone opens without signing in.
|
|
|
4
4
|
|
|
5
5
|
Build it as [Build an App](apps/build) says, with what follows. Anything private is an App.
|
|
6
6
|
|
|
7
|
-
- A Site starts with `sites/create`: `name` is its address name, and the answer's `source_url` is its App's `.git` address to clone the same way. With `app_ref` it gives one of your User's Apps that address instead
|
|
7
|
+
- A Site starts with `sites/create`: `name` is its address name, and the answer's `source_url` is its App's `.git` address to clone the same way. With `app_ref` it gives one of your User's Apps that address instead, such as `prototype-app`'s prototype: that App keeps its holders, each still opens it at its App address, and each release reaches them and the Site's visitors together. An App has one Site at most.
|
|
8
8
|
- `sites/delete` ends the address and keeps the App; `apps/delete` deletes the App and its Site.
|
|
9
9
|
- A Site shows the Rooms it published, as `published` names them: creating it publishes its bound Rooms, a release keeps the published data, and later Room edits stay private until `sites/publish`. A publication whose `state` is `preparing` replaces the shown one once its screenshot is taken; `sites/list` names each Site's newest publication and its `state`, and `sites/publish` with nothing changed since answers that publication. `sites/unpublish` stops serving a Site and keeps it; `sites/republish` or `sites/publish` serves it again.
|
|
10
10
|
- Bind a Site's Rooms with `sites/bindings/set`.
|
|
@@ -14,8 +14,8 @@ Build it as [Build an App](apps/build) says, with what follows. Anything private
|
|
|
14
14
|
- To receive messages from visitors, name an Intake Room with `sites/intake-room/set` and send each with `runtime.call('sites/submissions/create', { content })`, online only. `content` is one Markdown document the Intake Room's `settings/schema.yaml` accepts, and House adds its `site` and `submitted` fields. The call answers `{ kind: 'action', result: { submitted: true } }` once House stored it. Anything else stored nothing: `{ kind: 'rejected', code }` says why, such as `bot_check_failed` for a browser that failed the bot check, as automated test browsers do, `site_intake_room_absent`, `invalid_documents` with the `path`, `rule` and `field` it broke, `submission_reserved_key`, `submission_too_large`, `limit_reached` or `cap_reached`. So thank the visitor only for `submitted`, and otherwise show that nothing was sent.
|
|
15
15
|
- A Site loads House's servers when it is bound to a Room that changes often, or when it writes once per visitor, such as a Submission sent on every visit: send one only when a visitor asks to.
|
|
16
16
|
- Code that holds a key, such as one opening a checkout, runs in one of the App's functions, which the page calls: [A Site's function calls](sites/functions). [A Site's payments](sites/payments) takes payments with them.
|
|
17
|
-
- `sites/describe` sets
|
|
17
|
+
- `sites/describe` sets the title and description search engines show, and Google Analytics, the Meta Pixel and the TikTok Pixel by their IDs alone, `google_analytics_id`, `meta_pixel_id` and `tiktok_pixel_id`; one banner asks for all of them: [A Site's tags](sites/tags). Any other vendor's: [A Site's own counter](sites/counter).
|
|
18
18
|
- A Site moved from another builder keeps its old links with `redirects` in `app.json`, `[{ "from": "/old", "to": "/new" }]`: each old path, as a browser asks for it, answers a permanent redirect to its new path, query included. No old path is under `/_house/`, a root file such as `/robots.txt` or an entry route's; none repeats or is a new path. A document published at an old path takes it over.
|
|
19
|
-
- See it yourself:
|
|
19
|
+
- See it yourself: its url needs no sign-in.
|
|
20
20
|
|
|
21
21
|
Build its first screen as [A Site's first load](sites/first-load) says. House serves a route as HTML only where the [Entry Data Contract](sites/entry-data-contract) declares it, and [The App runtime on a Site](sites/runtime) says what the runtime does differently there.
|
package/guide/sites/counter.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# A Site's own counter
|
|
2
2
|
|
|
3
|
-
How a Site counts its visitors in a counter of its own,
|
|
3
|
+
How a Site counts its visitors in a counter of its own, any web analytics counter or ad pixel but Google Analytics, the Meta Pixel and the TikTok Pixel, which [A Site's tags](sites/tags) loads by ID, beside them or instead of them.
|
|
4
4
|
|
|
5
|
-
- **Its
|
|
6
|
-
- **Its
|
|
5
|
+
- **Its origins.** List in `app.json`'s `external_origins` every https origin the counter loads its script from or sends to. At the Site's address a page loads scripts from those origins, so the counter loads its script from its server as its snippet does. The browser console names each origin the page refused.
|
|
6
|
+
- **Its snippet in your code.** A page runs no inline script, so put the snippet's code, without its `<script>` tags, in your source and run it once the visitor accepts.
|
|
7
|
+
- **At the App's address** a page loads no script from outside its release, so the counter's script is refused there: treat a refused script as no counter, never wait for it to load, and let what the snippet queued go unsent. The page around your frame is another origin there, so `countPages` below reads nothing of it and counts nothing.
|
|
7
8
|
- **The page's address and referrer.** Your page runs in a frame of the Site's page at the Site's own origin, so the counter sees the frame's address and no referrer of the visitor's. Turn off its own page view and send each through `countPages` below, which gives the page's address and where the visitor came from: first the Site page's referrer, then the page they left.
|
|
8
|
-
- **Consent, as for
|
|
9
|
-
- **Hits arrive.** Publish, open the Site's url in a browser, accept and open a second page: the network log shows a request to the counter for each page, answered, and the counter's real-time report, which your User reads, shows both pages at the Site's address, the second with the first as its referrer.
|
|
9
|
+
- **Consent, as for the Site's tags.** Start the counter only after the visitor accepts, never after Decline. Ask on the Site unless their answer is kept. While `bridge.onStatus` reports `analytics.measures`, the answer is the tags' `analytics.choice`, kept with `bridge.analyticsConsent`, so one banner asks once for the tags and the counter; otherwise keep it in local storage, and a browser that keeps none is never counted. Keep a way on every page to decline later, which reloads the page without the counter: `bridge.analyticsConsent('decline')` does that while `analytics.measures` holds, `parent.location.reload()` otherwise.
|
|
10
|
+
- **Hits arrive.** Publish, open the Site's url in a browser, accept and open a second page: the network log shows the counter's script from its server and a request to the counter for each page, answered, and the counter's real-time report, which your User reads, shows both pages at the Site's address, the second with the first as its referrer.
|
|
10
11
|
|
|
11
12
|
`src/counter.ts`, which your entry script calls once the visitor accepted, with the counter's call that sends one page view:
|
|
12
13
|
|
|
@@ -14,7 +15,12 @@ How a Site counts its visitors in a counter of its own, such as a web analytics
|
|
|
14
15
|
import { houseBridge } from '@agentshouse/app-bridge';
|
|
15
16
|
|
|
16
17
|
export function countPages(pageView: (page: string, referrer: string) => void): void {
|
|
17
|
-
let referrer
|
|
18
|
+
let referrer: string;
|
|
19
|
+
try {
|
|
20
|
+
referrer = parent.document.referrer;
|
|
21
|
+
} catch {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
18
24
|
let counted = '';
|
|
19
25
|
houseBridge().onAddress((address) => {
|
|
20
26
|
const page = location.origin + address;
|
|
@@ -4,11 +4,11 @@ How a Site App's `entry_data` has House serve each route as HTML before the App
|
|
|
4
4
|
|
|
5
5
|
Entry Data Contract, `entry_data` in a Site App’s `app.json`: House serves each route in its `routes` list as HTML before the App starts, running none of your code. A Site has an Entry Page only for a route you list; any other address starts the App as usual.
|
|
6
6
|
|
|
7
|
-
A static route, one with no `queries` and no parameter, names only its `path`. Its Entry Page is your release's own HTML for that path: the `entry` document for `/`, `about/index.html` for `/about`. Write the route's first screen into that HTML. The push reads it without running it: it keeps the body's text and its plain elements (headings, paragraphs, lists, tables, links, images and the like), drops scripts, `on…` attributes and every other element (`button`, `form`, `svg
|
|
7
|
+
A static route, one with no `queries` and no parameter, names only its `path`. Its Entry Page is your release's own HTML for that path: the `entry` document for `/`, `about/index.html` for `/about`. Write the route's first screen into that HTML. The push reads it without running it: it keeps the body's text and its plain elements (headings, paragraphs, lists, tables, links, images and the like), drops scripts, `on…` attributes and every other element (`button`, `form`, `svg` among them) with its content, resolves relative addresses, drops an image the release lacks, and takes the head's `<title>`, `<meta name="description">` and each release stylesheet it links for every screen (no `media` but `all` or `screen`, not `alternate`). A static route that declares `body`, `title`, `description` or `styles`, whose HTML the release lacks, that links more than 8 stylesheets, or whose body passes 2000 nodes, 24 levels or, with every other route, 64 kB, refuses the push.
|
|
8
8
|
|
|
9
9
|
A route that reads Rooms or takes a parameter declares its Entry Page: 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` or `fileIds`; `{"$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`, `styles` (release CSS files) 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}`.
|
|
10
10
|
|
|
11
|
-
On every Entry Page an `img` keeps the `loading` and `fetchpriority` it names and loads lazily where it names no `loading`; a document's images always load lazily. Each takes the box its `width` and `height` name, 16:9 without them, and an `img` whose `src` is relative (`images/hero.webp`) shows that file of your release. House puts each stylesheet into the page itself, its relative `url()`s pointing into your release, so the page draws in your fonts and styles from its first byte. A route that fails starts the App as usual, and the Site document names why.
|
|
11
|
+
On every Entry Page an `img` keeps the `loading` and `fetchpriority` it names and loads lazily where it names no `loading`; a document's images always load lazily. Each takes the box its `width` and `height` name, 16:9 without them, and an `img` whose `src` is relative (`images/hero.webp`) shows that file of your release. A Room image House knows the size of keeps its own proportions and offers its smaller copies in `srcset`, unless your `img` names its own, across the page's width or the `sizes` your `img` names. A `picture`, its `source`s and their `srcset`, `sizes`, `media` and `type` stay; each `srcset` address is kept or dropped as a `src` is. House puts each stylesheet into the page itself, its relative `url()`s pointing into your release, so the page draws in your fonts and styles from its first byte. A route that fails starts the App as usual, and the Site document names why.
|
|
12
12
|
|
|
13
13
|
```json
|
|
14
14
|
{
|
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
How to build a Site whose first screen reaches a visitor's phone within about a second, and how to see that it does.
|
|
4
4
|
|
|
5
|
-
A phone on a slow link pays for every byte before the first screen
|
|
5
|
+
A phone on a slow link pays for every byte before the first screen. Build every Site this way by default:
|
|
6
6
|
|
|
7
|
-
- **An Entry Page for every entry route.** House draws a route as HTML before the App starts only where the release declares it in `entry_data` ([Entry Data Contract](sites/entry-data-contract)); any other route shows once the App has run. A route with no queries and no parameter names only its `path`, and its Entry Page is the release's own HTML for that path: the entry document for `/`, and `about/index.html` in the release for `/about`. House reads that HTML and never runs it, keeping its text and plain elements and taking its title, description and stylesheets from its head, so prerender each such route's first screen into it at build, its main image
|
|
7
|
+
- **An Entry Page for every entry route.** House draws a route as HTML before the App starts only where the release declares it in `entry_data` ([Entry Data Contract](sites/entry-data-contract)); any other route shows once the App has run. A route with no queries and no parameter names only its `path`, and its Entry Page is the release's own HTML for that path: the entry document for `/`, and `about/index.html` in the release for `/about`. House reads that HTML and never runs it, keeping its text and plain elements and taking its title, description and stylesheets from its head, so prerender each such route's first screen into it at build, its main image an `img` or a `picture`, since an `svg` and a script are dropped. A route that reads Rooms or takes a parameter declares its queries and its body. An Entry Page draws in the Site's own fonts, styles and images, so nothing moves when the App takes over.
|
|
8
8
|
- **Images at the size the App draws them**, each with its `width` and `height`: a larger file costs bytes nobody sees, and the box stays still while it loads.
|
|
9
9
|
- **The first image at once**: the first screen's main image names `loading="eager"` and `fetchpriority="high"`, in the release's HTML and in the App, since an Entry image that names no `loading` loads lazily. Every image below the first screen loads lazily.
|
|
10
10
|
- **No entrance animation on the first screen**: draw it in its final place, since content that fades or slides in counts as shown only once it stops.
|
|
11
11
|
- **Heavy libraries after the first draw**, behind a poster: load a 3D scene, a map or a video player with `import()` once the first screen has drawn, and show a still image of it until it runs.
|
|
12
12
|
- **Built minified and split**: minification on, and each route and heavy part a chunk of its own loaded by `import()`, so the first screen loads only its own code.
|
|
13
|
-
- **At most two font families**, the Site's own, their files in the release.
|
|
13
|
+
- **At most two font families**, the Site's own, their small files in the release, each with `font-display: block`: House shows an Entry Page once the fonts it draws in have arrived, so nothing on it moves when they do.
|
|
14
14
|
- **The first view within the bound** the publish warns at. The first view is the entry document, its scripts and stylesheets and what they import statically, compressed as House stores them. A first view past the bound, or no Entry Page for `/`, never stops a publish: its answer and `sites/list` name each in `warnings` by its `code`, `first_view_heavy` with its `bytes` and `bound`, and `entry_page_missing`. Fix them before the next publish.
|
|
15
|
-
- **Read `first_load` in `sites/list` after each publish.** House loads the Site once more, cold, as a phone on a slow link, and answers `{ first_content_ms, largest_content_ms, at }` for the release or publication it serves: `null` before that figure, when that load failed or where the Building times no Site.
|
|
16
|
-
- **A common Site from a Site Template**, built this way, where `templates/list` answers them: `site-landing`, one page whose form sends each lead as a Submission; `site-services`, a page that lists each document of its Room's `services/` folder as one service; and `site-shop`, a shop on the recipe of [Payments with Stripe](sites/payments-stripe). Make the Site with one `templates/use` of it, at the address `templates/list` answers, with a `site_name` and a `room_name`: the Site gets its own App and a new Room holding the Template's schema and Starter content, keeps no link to the Template, and you change its App as any other. It binds that Room in every slot but one that declares `intake: true`, which publishes it. `site-landing`'s one slot declares it, so the Room is the Site's Intake Room and none is published: turn on Notify me with `sites/notifications/set` and each lead reaches your User on the channels they chose. `site-shop`'s `orders` slot declares it: set up its Intake Room as that recipe says.
|
|
15
|
+
- **Read `first_load` in `sites/list` after each publish.** House loads the Site once more, cold, as a phone on a slow link, and answers `{ first_content_ms, largest_content_ms, at }` for the release or publication it serves: `null` before that figure, when that load failed or where the Building times no Site.
|
package/guide/sites/runtime.md
CHANGED
|
@@ -6,8 +6,11 @@ A Room the Site binds for queries only never reaches a visitor's browser: `rooms
|
|
|
6
6
|
with `queriesOnly: true` and nothing held, and its rows come a page at a time through
|
|
7
7
|
`queryHouse`, as [House query rules](apps/query-house) say, except that a query of more than
|
|
8
8
|
about 9,000 bytes, too long for the Site's address, answers `query_too_large` with no `cap`
|
|
9
|
-
before it is sent.
|
|
10
|
-
|
|
9
|
+
before it is sent. The Site's page orders that Room by a field its types index, totals it and
|
|
10
|
+
groups it by such a field, as a shop's products by price, how many match and each brand with its
|
|
11
|
+
count, under those rules' refusals and count cap. Every visitor asking the same query gets the
|
|
12
|
+
same answer, rows, a total or groups, which the edge keeps for a few minutes, so a change to the
|
|
13
|
+
Room shows within them.
|
|
11
14
|
|
|
12
15
|
A History revision or a Document's `change` written by a Site gives its `author` as `{ kind: 'site', id, name }`. `observe('member')` answers `null` on a Site, and a Document's `change` is `null` there, since the Provider delivers no time.
|
|
13
16
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# A Site's tags
|
|
2
|
+
|
|
3
|
+
How a Site loads its owner's Google Analytics, Meta Pixel and TikTok Pixel, each set by its ID alone.
|
|
4
|
+
|
|
5
|
+
- **The IDs.** `sites/describe` sets `google_analytics_id`, a `G-` measurement ID, `meta_pixel_id`, the Meta Pixel ID, and `tiktok_pixel_id`, the TikTok Pixel ID, and `null` clears one. An ID of another form is refused, a Universal Analytics `UA-` ID among them.
|
|
6
|
+
- **One banner asks for all of them.** House loads every tag the Site sets, on every page, only after the visitor accepts. While `bridge.onStatus` reports `analytics.measures`, ask the visitor on the Site unless `analytics.choice` holds their answer, with one banner reading "Accept cookies" with two buttons, Accept and Decline, the same words whichever IDs are set; report the answer with `bridge.analyticsConsent('accept')` or `'decline'`, and keep a way on every page to decline later, which reloads the page without the tags.
|
|
7
|
+
- **House counts each page.** Every tag gets one page view for each page the visitor reaches, at its own address, and Google Analytics with the title `bridge.setTab({ title })` gave it, so set the title as you draw the page; Google's page left untitled is counted a second after it shows, or as you move on. Send no page view of your own.
|
|
8
|
+
- **Google Analytics counts history changes itself** until its web stream's setting "Page changes based on browser history events" is off, which no code can turn off; ask your User to turn it off, so each page counts once.
|
|
9
|
+
- **Any other vendor's tag** comes from your Site's own code: [A Site's own counter](sites/counter).
|
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: build-app
|
|
3
|
-
description: Build an App properly from its prototype and publish it into the same App
|
|
3
|
+
description: Build an App properly from the variant picked in its prototype and publish it into the same App.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Build an App
|
|
7
7
|
|
|
8
|
-
Build
|
|
8
|
+
Build an App properly from the variant picked in its prototype, and publish it into the same App.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Start
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Whoever asks names the App, by its address or `a_` reference, and the variant picked in its prototype, with any edits. Ask them for what they leave out; never pick for them. An App with no prototype starts with [`prototype-app`](skills/prototype-app).
|
|
13
13
|
|
|
14
14
|
## Design
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Read [Design an App](apps/design) and each page it links, then draft from the picked variant:
|
|
17
17
|
|
|
18
18
|
- the App's types and fields, as its `schema.yaml` will declare them;
|
|
19
19
|
- each piece of work no page does, the function that does it and the Trigger that starts it;
|
|
20
20
|
- for each design on [Designs that load House](apps/design-load) the App comes near, how it keeps that load down;
|
|
21
|
-
- its top colours, light and dark, from the
|
|
21
|
+
- its top colours, light and dark, from the picked variant, and its icon.
|
|
22
22
|
|
|
23
23
|
The draft is no document of its own: the grilling takes it in.
|
|
24
24
|
|
|
25
25
|
## Build
|
|
26
26
|
|
|
27
|
-
Run `grill-with-docs` on that draft, then `to-spec`, then `to-tickets`, then `implement` for each ticket in order. Keep what they write
|
|
27
|
+
Run `grill-with-docs` on that draft, then `to-spec`, then `to-tickets`, then `implement` for each ticket in order. Keep what they write where the Owner rules, `/rooms/private/owner-rules.md`, say, in the Room where the App is developed: the one its README or whoever asks names, or else one you make with `rooms/create`, named in the App's README. Each Skill named here is also a Command of its name, or the Guide page it links, for a client that has not installed it.
|
|
28
28
|
|
|
29
29
|
## Publish into the same App
|
|
30
30
|
|
|
31
31
|
Publish into the App the prototype made, never a new one, so its address and bindings stay:
|
|
32
32
|
|
|
33
33
|
- where you run Git, from a clone of its `.git` address, with `npm run publish` and never `--name`, as [Start an App](apps/start) says;
|
|
34
|
-
- otherwise zip the project folder after its build, `dist/` included and `.env` and `node_modules/` left out, `upload` the ZIP to
|
|
34
|
+
- otherwise zip the project folder after its build, `dist/` included and `.env` and `node_modules/` left out, `upload` the ZIP to that Room and publish it with `apps/publish-zip`, naming the App by its `a_` reference.
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Give your User the App's address.
|
|
@@ -16,7 +16,7 @@ Run `wayfinder` to chart the map; this page adds only what is House's. `wayfinde
|
|
|
16
16
|
|
|
17
17
|
## Keep the plan
|
|
18
18
|
|
|
19
|
-
- Make the plan's
|
|
19
|
+
- Make the plan's Room with `rooms/create`, named for what your User wants.
|
|
20
20
|
- Keep the map as one `wayfinding-map` and its tickets as `wayfinding-ticket` documents in that Room, each declaring `type: wayfinding-map` or `type: wayfinding-ticket` in its frontmatter: a field named for the type makes no map. Chart the map even when the way looks clear.
|
|
21
21
|
- Keep decisions about the account, billing, runtime or credentials in the Private Room, `/rooms/private`.
|
|
22
22
|
- Make the App for your User's goal a ticket.
|
|
@@ -1,42 +1,29 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: prototype-app
|
|
3
|
-
description: Make a new App by publishing a prototype
|
|
3
|
+
description: Make a new App by publishing a prototype of its design, in as many variants as asked, 3 by default, for a person to pick one.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Prototype an App
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Make a new App whose first release is a prototype of its design, in variants a person picks from.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Run `prototype` on its UI branch for the variants; this page adds only what is House's. `prototype` is also a Command of its name for a client that has not installed it.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
- **How many.** Make as many variants as whoever runs this asks for, 3 when they name none.
|
|
13
|
+
- **The App is the prototype.** Build the variants in a new App's project, cloned as [Start an App](apps/start) says: they are the App's own pages on its main branch, in place of a throwaway route and branch, and each draws the App's main pages. Settle only their look ([An App's look](apps/design-look)); the App's types and functions wait for [`build-app`](skills/build-app).
|
|
14
|
+
- **The switcher stays.** Keep the switcher visible in every published release, production builds included, so the person flips between variants at its address. With one variant there is no switcher.
|
|
15
|
+
- **The first screen.** Write the App's first screen as static HTML in its entry document, which its script takes over once it runs, so the screen shows before any script has loaded; every release keeps it so.
|
|
16
|
+
- **Phone and desktop.** Before giving the address, look at every variant 390 and 1440 pixels wide and redo any that looks generic or broken.
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
## Publish
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
- **Notes:** this map's tickets do the work they name; the App's address and `a_` reference once the prototype is published.
|
|
18
|
-
- **Tickets**, each blocked by the one before:
|
|
19
|
-
1. Prototype, `kind: task`: three design variants in one prototype, published as the App's first release.
|
|
20
|
-
2. Design decision, `kind: grilling`: the variant the User picks, with their edits.
|
|
21
|
-
3. Build, `kind: task`: run [`build-app`](skills/build-app).
|
|
22
|
-
|
|
23
|
-
## 2. Publish the prototype
|
|
24
|
-
|
|
25
|
-
Claim the first ticket. Build three variants as [Build an App](apps/build) says, each a distinct visual direction (type, colour, layout, tone), not three shades of one. Each draws every main page with real-looking content, and a switcher on the page moves between them. Build only pages, their look and their flow: no tests, no data model, no reviews. Before publishing, look at each variant at phone and desktop width and redo any that looks generic or broken.
|
|
26
|
-
|
|
27
|
-
Write the App's first screen as static HTML in its entry document, which its script takes over once it runs, so the screen shows before any script has loaded; every release keeps it so.
|
|
28
|
-
|
|
29
|
-
Publish it as a new App, which creates it:
|
|
20
|
+
Publish the first round as a new App, which creates it:
|
|
30
21
|
|
|
31
22
|
- where you run Git, with `npm run publish -- --name "<display name>"`;
|
|
32
|
-
- otherwise zip the project folder after its build, `dist/` included and `.env` and `node_modules/` left out, `upload` the ZIP to the Room and publish it with `apps/publish-zip`, naming the display name and no App.
|
|
33
|
-
|
|
34
|
-
Write the App's address and reference into the map's Notes, resolve the ticket with them, and give the User the address.
|
|
35
|
-
|
|
36
|
-
## 3. Record the User's decision
|
|
23
|
+
- otherwise zip the project folder after its build, `dist/` included and `.env` and `node_modules/` left out, `upload` the ZIP to the Room whoever runs this names, or else one you make with `rooms/create`, and publish it with `apps/publish-zip`, naming the display name and no App.
|
|
37
24
|
|
|
38
|
-
|
|
25
|
+
Give the person the prototype's address. Publish each later round into the same App: `npm run publish` without `--name`, or `apps/publish-zip` naming the App.
|
|
39
26
|
|
|
40
|
-
##
|
|
27
|
+
## The pick
|
|
41
28
|
|
|
42
|
-
|
|
29
|
+
Ask the person to open the address and pick one variant, naming any edits or pieces to take from the others; never pick for them. Publish their pick as the next round, until they keep it. Record what they picked, in their words, where whoever ran this keeps its work.
|
package/guide/skills/wizard.md
CHANGED
|
@@ -13,7 +13,7 @@ Create it with `wizards/create`, for the Environment you work through or another
|
|
|
13
13
|
|
|
14
14
|
## As a function
|
|
15
15
|
|
|
16
|
-
For a script the User may want to keep, propose a name when you create the Web Wizard. Only the User keeps a script: they tick Keep as a function on its page, may change the name, and press Keep, which runs nothing and makes the script one of their Environment functions. The document then reads kept with the function's name; keeping under a name they already use replaces that function's script. `
|
|
16
|
+
For a script the User may want to keep, propose a name when you create the Web Wizard. Only the User keeps a script: they tick Keep as a function on its page, may change the name, and press Keep, which runs nothing and makes the script one of their Environment functions. The document then reads kept with the function's name; keeping under a name they already use replaces that function's script. `info` on the Environment lists its functions, and `environments/functions/delete` deletes one. On a function's page the User can also press Run now, which runs it in a terminal they type into, so a kept script may ask them for a password there; nothing of that run reaches you.
|
|
17
17
|
|
|
18
18
|
`environments/functions/run` runs a function on its Environment, whose Kit must be connected, and answers when the run ends. Your input reaches the script as JSON in the file `HOUSE_INPUT` names. The run has no terminal, so a script that asks for typing fails at once; such a step stays a Web Wizard. The answer's ending is exited with its exit_code, timed_out at the run's time limit, not_started with its cause, or interrupted when House lost the run; output is the end of what the script printed, cut when its start was dropped.
|
|
19
19
|
|
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-cbd84a558d68d",
|
|
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",
|