@tinycloud/cli 1.5.0-beta.26 → 1.5.0-beta.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -103,6 +103,150 @@ tc space create
103
103
  tc delegation create --to did:pkh:eip155:1:0x...
104
104
  ```
105
105
 
106
+ ## Home feed
107
+
108
+ `tc feed` uses separate owner-provisioned SQLite databases for each agent's
109
+ cards/handling and the owner's append-only responses. Owner registry and view
110
+ state live separately. SDK consumers use the same contract from
111
+ `@tinycloud/sdk-services/feed` with existing SQL database handles; see the
112
+ [canonical types](../sdk-services/src/feed/types.ts).
113
+
114
+ Use an authenticated **owner-openkey or local-owner-key** profile for `connect`.
115
+ That owner needs SQL read/write/schema authority for
116
+ `xyz.tinycloud.tinychat/home_feed` and the `xyz.tinycloud.tinychat/feed/`
117
+ namespace, plus authority to delegate the exact agent grants below. The trailing
118
+ slash denotes a database namespace, not an individual database.
119
+
120
+ Create a separate agent profile and set `AGENT_DID` to its printed DID. Use the
121
+ same node as the owner:
122
+
123
+ ```bash
124
+ tc profile create feed-agent --posture delegate-session --operator agent
125
+ tc --profile owner feed connect --agent writer --to "$AGENT_DID" --label Writer \
126
+ --space applications > feed-grant.json
127
+ tc --profile feed-agent auth import feed-grant.json
128
+ ```
129
+
130
+ `connect` reserves a stable token/DID/resource binding, provisions both schemas,
131
+ and activates one bundled delegation through the existing SDK. It registers
132
+ actual grant provenance only after activation; a failed activation may be
133
+ retried with the same DID and resources. The agent receives read/write on
134
+ `xyz.tinycloud.tinychat/feed/feed_output_writer`, read on
135
+ `xyz.tinycloud.tinychat/feed/feed_responses_writer`, and hook subscription on
136
+ `sql/xyz.tinycloud.tinychat/feed/feed_responses_writer`. Agents do not receive
137
+ response-write or schema authority. Display labels and tokens select resources;
138
+ the signed grants determine access.
139
+
140
+ Publish `card.json` from the agent profile:
141
+
142
+ ```json
143
+ {"cardId":"card-draft-01","revision":1,"issuanceId":"issuance-draft-01","kind":"decision","needsResponse":true,"title":"Create draft?","body":"Create a reversible draft only.","choices":[{"id":"create","label":"Create draft"}],"urgency":1,"createdAt":"2026-10-29T00:00:00Z"}
144
+ ```
145
+
146
+ ```bash
147
+ tc --profile feed-agent feed publish --agent writer --file card.json
148
+ tc --profile feed-agent feed watch --agent writer --recipient agent-runtime \
149
+ --runner '["node","agent-handler.js"]'
150
+ ```
151
+
152
+ Run `watch` in the agent terminal, then save `response.json` from the owner
153
+ profile in another terminal, or answer the card through Home:
154
+
155
+ ```json
156
+ {"responseId":"response-draft-01","cardId":"card-draft-01","revision":1,"issuanceId":"issuance-draft-01","kind":"answer","choiceId":"create","createdAt":"2026-10-29T00:01:00Z"}
157
+ ```
158
+
159
+ ```bash
160
+ tc --profile owner feed respond --agent writer --file response.json
161
+ tc --profile feed-agent feed responses --agent writer --after 0
162
+ tc --profile feed-agent feed handling --agent writer --file handling.json
163
+ tc --profile owner feed show card-draft-01 --agent writer
164
+ ```
165
+
166
+ For an explicit outbound note to that agent, save a separate `message.json`:
167
+
168
+ ```json
169
+ {"responseId":"message-draft-01","cardId":"card-draft-01","revision":1,"issuanceId":"issuance-draft-01","kind":"message","text":"Please explain the draft before I answer.","createdAt":"2026-10-29T00:02:00Z"}
170
+ ```
171
+
172
+ ```bash
173
+ tc --profile owner feed message --agent writer --file message.json
174
+ ```
175
+
176
+ Messages also work on information cards with `needsResponse: false`. They do not
177
+ answer a card, clear Needs action, or replace its current answer or handling.
178
+ `choiceId` and `supersedesResponseId` are refused on messages. Agent response pages
179
+ and watch include messages, with acknowledgements/outcomes tied to their own full
180
+ response IDs. Private owner notes, task ticks, and seen state remain owner-only
181
+ registry data; they are not outbound messages.
182
+
183
+ For a new response with private structured data, `payload.json` is a versioned
184
+ JSON envelope, for example:
185
+
186
+ ```json
187
+ {"type":"example.private-action","version":1,"data":{"code":"SYNTHETIC-ONLY"}}
188
+ ```
189
+
190
+ Include it on the **first** save, instead of the plain `respond` command above:
191
+
192
+ ```bash
193
+ tc --profile owner feed respond --agent writer --file response.json --payload-file payload.json
194
+ tc --profile feed-agent feed payload --agent writer --response response-draft-01 \
195
+ --card card-draft-01 --revision 1 --issuance issuance-draft-01
196
+ ```
197
+
198
+ The header and payload commit atomically in the same owner-response database.
199
+ Retries of the same response ID must include the same header and payload; a
200
+ changed, omitted, or later-added payload is refused. `feed payload` verifies the
201
+ full response/card/revision/issuance identity, returning its envelope, or `null`
202
+ for a known response without a payload. Unknown or mismatched identities fail.
203
+ Keep approval codes in `payload.data`, never the normal response text.
204
+
205
+ Default `list`, `show`, `responses`, and `watch` output contains only response
206
+ headers and optional `payloadType`/`payloadVersion` metadata, not payload data.
207
+ The SDK equivalents are the optional fourth `appendFeedResponse` or
208
+ `appendFeedMessage` argument and the explicit `readFeedResponsePayload` method.
209
+ `feed message` accepts the same `--payload-file` option on its first save.
210
+ Owner schema initialization adds `feed_response_payloads`; existing response-read
211
+ authority also authorizes an explicit payload read. “Private” here means excluded
212
+ from notification copies, not a new authorization boundary against an agent already
213
+ granted database read.
214
+
215
+ `readFeedResponseHandling(output, identity)` reads acknowledgement and outcome for
216
+ one full response/card/revision/issuance identity, including historical answers or
217
+ messages after later arrivals. Unknown or mismatched handling returns `NOT_FOUND`,
218
+ not a synthetic empty receipt. Known acknowledgement-only or outcome-only history
219
+ retains the other slot as `null`. `getFeedCardState` selects only the current
220
+ answer/follow-up; a saved answer without handling still has `null` receipt slots.
221
+
222
+ Retain the full response ID on a retry. Reusing it with different content is
223
+ refused. Responses bind the full card ID, revision, and issuance; corrections
224
+ are new follow-up records, optionally naming `supersedesResponseId`. Short card
225
+ references work only when unambiguous. Handling records carry their own
226
+ `handlingId`, the response/card identities, `createdAt`, and `phase`:
227
+ `acknowledged`, `succeeded`, or `failed`, with optional structured `detail`.
228
+ Acknowledgement history and the terminal outcome are retained independently.
229
+
230
+ **Saved, delivered, acknowledged, and completed are different states.**
231
+ The runner receives allowlisted response-header JSON and optional payload
232
+ type/version metadata on stdin through an argv array, never shell interpolation.
233
+ Exit zero must mean durable acceptance of that response ID, not completion of
234
+ its action. The agent publishes acknowledgement and outcome through `handling`.
235
+
236
+ `watch` requires **Bun or Node.js 22.13+** for its durable local SQLite ledger;
237
+ other commands keep the CLI's Node.js 20 requirement. By default the ledger is
238
+ stored under the selected profile; `--handoff` selects another durable file.
239
+ The listener subscribes before draining and reconciles on readiness, writes,
240
+ reconnects, and five-minute renewal, without a rapid idle query loop.
241
+
242
+ Before attempting a send, the ledger records `unconfirmed`. A crash, uncertain
243
+ runtime result, or interruption leaves that identity unconfirmed rather than
244
+ automatically sending again. A `prepared` record can resume only before an
245
+ attempt began. Ctrl-C/SIGTERM stops the watcher and forcibly terminates its
246
+ current runner; an already-started action may still have happened. Keep response
247
+ IDs as downstream idempotency keys where supported. Exactly-once external
248
+ execution is not promised.
249
+
106
250
  ## Commands
107
251
 
108
252
  | Command | Description |
@@ -125,6 +269,7 @@ tc delegation create --to did:pkh:eip155:1:0x...
125
269
  | `tc sql query <sql>` | Run a SQLite SELECT query |
126
270
  | `tc sql execute <sql>` | Run a SQLite write or schema statement |
127
271
  | `tc sql export` | Export a SQLite database file |
272
+ | `tc feed` | Connect an agent, publish cards, save responses, record handling, and watch for runtime handoff; see [Home feed](#home-feed) |
128
273
  | `tc space list` | List your spaces |
129
274
  | `tc space create` | Create a new space |
130
275
  | `tc delegation create` | Grant access to another user |
@@ -248,21 +393,20 @@ it, network sign-in and KV reads still work, but local replica reads stay gated
248
393
  until a new verified sign-in. A gated root prefix does not imply `kv-sync-root`
249
394
  support.
250
395
 
251
- Replica-enabled OpenKey login uses the SDK-prepared SIWE approval URL, not the
252
- older browser-created session. Specify `--owner did:pkh:eip155:CHAIN:ADDRESS`
253
- unless this profile already has a verified owner session. The CLI verifies the
254
- signed result before saving its new key, session and replica stamp. Safari, and
255
- Chromium browsers that enforce Local Network Access without granting it (headless
256
- Chromium cannot show the prompt), may block the HTTPS page's plain-HTTP loopback
257
- callback: use an interactive CLI terminal and paste the same one-line code shown
258
- by OpenKey, or start with
259
- `tc auth login --method openkey --replication-prefix notes/ --owner DID --paste`
260
- for a headless terminal. Non-TTY `--no-popup` cannot accept a paste; if that
261
- callback fails, it exits nonzero at the five-minute expiry with a `--paste`
262
- retry hint and discards the candidate key. Restarting requires a new approval
263
- and cannot reuse the old signed code. Ctrl-C, SIGINT or SIGTERM before approval
264
- arrives cancels the OpenKey handoff (best effort) and exits 130 `CANCELLED`
265
- without saving a key or session.
396
+ Replica-enabled OpenKey login uses the SDK-prepared SIWE approval request.
397
+ Specify `--owner did:pkh:eip155:CHAIN:ADDRESS` unless this profile already has a
398
+ verified owner session. The CLI verifies the signed result before saving its new
399
+ key, session and replica stamp.
400
+
401
+ Normal OpenKey login prints a short approval link on stderr and waits. Relay it
402
+ to the owner from a headless or remote CLI; no localhost callback or pasted code
403
+ is needed. `--no-popup` skips opening a local browser, not automatic result
404
+ retrieval. The CLI verifies the encrypted result, durably saves it, then
405
+ acknowledges delivery. Re-run the same command after an interruption to resume.
406
+ The one-hour request expiry is independent of the requested grant lifetime and
407
+ result retention. Normal login keeps its seven-day default; onboarding requests
408
+ 30 days explicitly. `--paste` remains an explicit manual fallback with a
409
+ five-minute, single-use return code, not the automatic short-link transport.
266
410
 
267
411
  Use `tc replica report` for read-only aggregates of persisted replication events
268
412
  and identity partitions. Live replica status is unavailable there. Report