@north-light/cli 0.3.491 → 0.3.493

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.
Files changed (33) hide show
  1. package/dist/api/command-manifest/index.d.ts +1 -0
  2. package/dist/api/command-manifest/index.js +1 -1
  3. package/dist/api/command-manifest/object-kinds.d.ts +20 -0
  4. package/dist/api/command-manifest/object-kinds.js +1 -0
  5. package/dist/api/contract.d.ts +1 -1
  6. package/dist/api/contract.js +1 -1
  7. package/dist/api/dto/lifecycle.d.ts +8 -0
  8. package/dist/builtin-memory/crouter-plugin/deploying.md +22 -0
  9. package/dist/builtin-memory/crouter-sdk/client.md +1 -1
  10. package/dist/builtin-memory/crouter-sdk/release-notes.md +35 -1
  11. package/dist/builtin-memory/crouter-sdk/resources.md +2 -2
  12. package/dist/builtin-memory/northlight-apps/concepts/connections.md +17 -0
  13. package/dist/builtin-memory/northlight-apps/errors.md +2 -0
  14. package/dist/clients/attach/viewer.js +429 -429
  15. package/dist/commands/node-lifecycle-revive.js +1 -1
  16. package/dist/core/graph/access.d.ts +3 -0
  17. package/dist/core/graph/access.js +3 -3
  18. package/dist/core/plugin-objects-manifest.d.ts +2 -16
  19. package/dist/core/plugin-objects-manifest.js +1 -1
  20. package/dist/core/runtime/view-socket.d.ts +3 -4
  21. package/dist/core/runtime/view-socket.js +1 -1
  22. package/dist/daemon/api/handlers/nodes.js +1 -1
  23. package/dist/daemon/api/map.d.ts +1 -1
  24. package/dist/daemon/api/map.js +1 -1
  25. package/docs/apps/concepts/connections.md +17 -0
  26. package/docs/apps/errors.md +2 -0
  27. package/docs/plugin/deploying.md +22 -0
  28. package/docs/sdk/client.md +1 -1
  29. package/docs/sdk/release-notes.md +35 -1
  30. package/docs/sdk/resources.md +2 -2
  31. package/package.json +2 -2
  32. package/packages/crouter-identity/package.json +1 -1
  33. package/runtime.lock.json +12 -12
@@ -7,6 +7,40 @@ description: Behavior changes in @north-light/sdk that an app must act on, newes
7
7
 
8
8
  Changes to `@north-light/sdk` that can change what an existing app sees. Newest first.
9
9
 
10
+ ## 0.3.493
11
+
12
+ An app can act on a person's hosted runtime with no sign-in of theirs, and `@north-light/plugin` can declare canvas object kinds. Everything below is additive: no request or response an existing app sends or reads changes.
13
+
14
+ ### `oauth.appClient(userId)`: the app acts on a person's hosted runtime (additive)
15
+
16
+ `await oauth.appClient('user:<id>')` returns a client on that person's hosted runtime without a stored connection or refresh token. The SDK signs a `client_credentials` request with the `OAuth2Client`'s key (`private_key_jwt`) for `sub=user:<id>`, and the directory answers a token and the person's `runtimeUrl`. The app must be registered with the `app_token_for_user` operation, and the person must hold an active grant for it. Tokens are cached per person until a minute before they expire, and one mint is in flight per person however many callers ask. The client mints again on expiry and once after a `401`. A `userId` that is not `user:<id>` throws `CrouterError`.
17
+
18
+ - `NoHostedRuntimeError` (`no_hosted_runtime`, status 409, not retryable): the person has no hosted runtime to act on.
19
+ - `NotGrantedError` (`not_granted`, status 409, not retryable): the person has no active grant for the app, so they have not signed in to it.
20
+ - A runtime still provisioning (503), a directory 5xx and a 429 throw an error with `retryable: true`. `invalid_client` is a `401` `unauthorized` that names the signing key.
21
+
22
+ `no_hosted_runtime` and `not_granted` are appended to `sdkErrorCodes`, so the codes already in the list keep their positions. `NoHostedRuntimeError` and `NotGrantedError` are exported from `@north-light/sdk`. See [Errors](/docs/errors) and [Connections](/docs/concepts/connections#acting-without-a-sign-in).
23
+
24
+ ### `customObjects` and `canvas` on `AppClient` (additive, type change)
25
+
26
+ `AppClient` (the type of `oauth.client(userId)` and `oauth.appClient(userId)`) now offers two namespaces the app listener already served to an app grant token:
27
+
28
+ - `customObjects.register`, `publish` and `unregister` act on the custom objects your app owns. `receive` and `ack` stay owner-daemon only.
29
+ - `canvas.watch` and `canvas.unwatch` link a node to an object your app owns, under `crtr:objects:link:node`. Pass `watcher` (a node id) and, for a node of another of the account's machines, `watcher_machine`. `unwatch` takes the same `watcher` and `watcher_machine` to remove that node's watch; without `watcher` it removes the app's own watch.
30
+
31
+ Every other `canvas` method and `customObjects.receive`/`ack` remain absent from the type and throw `CrouterError` if reached. `Crouter` is still assignable to `AppClient`.
32
+
33
+ ### `@north-light/plugin`: `objectKinds` and `LeafCaller.crtr` (additive)
34
+
35
+ - `definePlugin({objectKinds})` declares canvas object kinds by name relative to the plugin (`repo`), each `{ description, events: { <name>: { level: 1-10, supersedes? } }, read?: { command: [...] } }`. The bundle the kit serves carries them in `bundle.json` `object_kinds`, keyed `<providerId>.<name>`: `providerId` is the `auth.providerId` the handler was given, else the plugin name. `definePlugin` throws `PluginDefinitionError` for a relative name that is not lowercase letters, digits and `-`, a blank description, more than 64 events, a level outside 1-10, and a `read.command` that is not a non-streaming leaf of the plugin. Building the bundle throws if the prefixed kind is not one crouter accepts (a provider id with capitals or `_`, or one of crouter's reserved roots such as `repo` or `report`).
36
+ - `ctx.caller.crtr` carries the calling node: `{ node?, machine?, profile?, run? }`, parsed by the exported `parseCrtrCaller(header)` from the request's `Crtr-Caller`. It is absent when the header names no field. The runtime asserts that header and the bearer token does not cover it, so use it to tell which of the verified `sub`'s nodes called, never to authorize; authorize on `sub`.
37
+
38
+ See [Local plugins](https://crouter.docs.northlight.ai/docs/plugin/deploying#local-plugins) and [Object kinds and the calling node](https://crouter.docs.northlight.ai/docs/plugin/deploying#object-kinds-and-the-calling-node).
39
+
40
+ ### `nodes.revive` reports `ready` (additive)
41
+
42
+ `ReviveResultDTO` gains an optional `ready`. The daemon checks, in its own namespace, whether the revived node's `view.sock` accepts a connection (up to 10 s, ending early if the launched broker exits) and returns the answer. `true` means the node is attachable; it does not show the task was delivered or the model is making progress. `false` means no connection yet, including `outcome: 'frozen'`. A daemon that predates the field sends none, so treat an absent `ready` as unknown.
43
+
10
44
  ## 0.3.488
11
45
 
12
46
  ### Developer CLI: `--help` exits 0, `login` is safe to re-run (CLI only, no app change)
@@ -58,7 +92,7 @@ Plugins can now declare canvas object kinds and act on the canvas, and an app to
58
92
  - `app:<x>`: nodes and custom objects of another app `x`. An app never needs a scope for its own objects, and a plugin may not declare its own `app:<plugin>` space.
59
93
  - `node`: any node, including the stub of a node on another of the account's machines.
60
94
 
61
- `read` lets the holder read objects of the target, `write` change them, and `link` (below) make a node watch an object the holder owns. `watch` lets a custom object that watches an object of the target read it. Holding a scope never lifts run confinement inside the owning app, and a revoked grant holds nothing. A public custom object is readable by any app that may use the owning app's tools, with no scope. The app listener now serves the canvas operations (`objects.*`, `custom-objects.*`, `docs.*`) to an app grant token under its resolved scopes; those rows answered `unknown operation` there before.
95
+ `read` lets the holder read objects of the target, `write` change them, and `link` (below) make a node watch an object the holder owns. `watch` lets a custom object that watches an object of the target read it. Holding a scope never lifts run confinement inside the owning app, and a revoked grant holds nothing. A public custom object is readable by any app that may use the owning app's tools, with no scope. A `friends` or `private` instance is readable, with no read scope, only by a run (a node, or a node of another machine) that holds one of the owning app's provider-group scopes `<app>:<group>`, the scopes a call to that app's provider commands needs; another app's server reads it only through a held `crtr:objects:read:app:<app>` scope. The app listener now serves the canvas operations (`objects.*`, `custom-objects.*`, `docs.*`) to an app grant token under its resolved scopes; those rows answered `unknown operation` there before.
62
96
 
63
97
  ### The `crtr_app_` credential and its socket fetch (additive)
64
98
 
@@ -38,13 +38,13 @@ Every namespace exported by the client. Namespaces are camelCase. Verbs are `cre
38
38
  | `grant` | `get` (`wait`, `since`: hold until `version` changes) | `GET /v1/grant` |
39
39
  | `health` | `get` | `GET /v1/health` |
40
40
 
41
- `runs`, `uploads`, `attachments`, `shares`, `questions`, `docs` and the app side of `grant` and `providers` are the application-facing API an app reaches through the app listener; `oauth.client(userId)` returns a client typed to exactly that set (`AppClient`); `nodes`, `bash`, `canvas`, `crons`, `human`, `models`, `customObjects`, `structuredRequests`, `system`, `auth`, `files.read/write/list` and `profiles.ensure/retrieve` are the owner's own daemon and are not served to an app. An app schedules work with its own timer calling `runs.start`, or a run's agent runs `crtr cron add` under `crtr:schedule`. See [Apps on Northlight](./guides/apps-on-northlight.md) and [Apps with many users](./guides/apps-with-many-users.md). `memory` is the person's `public` documents ([Memory](./memory.md)). `docs` writes, reads and edits documents the calling app owns: `docs.write({name, body, preview, kind?, rules?})` returns the canonical `name`; `docs.get(name)` returns `body`, `revision`, `rules` and the edit `base`; `docs.edit(name, {body, rationale, base?})` changes it in place and refuses a stale `base` with `ConflictError` (`stale_revision`). To keep one document current, `get` it (catch `NotFoundError` on first run to `write`), compare `body` to your text, and `edit` only when they differ. `system.health` (`/healthz`) is the daemon's liveness check; `health.get` is the app listener's.
41
+ `runs`, `uploads`, `attachments`, `shares`, `questions`, `docs` and the app side of `grant` and `providers` are the application-facing API an app reaches through the app listener; `oauth.client(userId)` returns a client typed to exactly that set (`AppClient`); `customObjects` (`register`, `publish`, `unregister`) and `canvas` (`watch`, `unwatch`) are served too, for the custom objects your app owns; `oauth.appClient(userId)` returns the same `AppClient` type without a stored sign-in ([Connections](../apps/concepts/connections.md#acting-without-a-sign-in)). `nodes`, `bash`, `crons`, `human`, `models`, `structuredRequests`, `system`, `auth`, the rest of `canvas` and `customObjects` (`receive`, `ack`), `files.read/write/list` and `profiles.ensure/retrieve` are the owner's own daemon and are not served to an app. An app schedules work with its own timer calling `runs.start`, or a run's agent runs `crtr cron add` under `crtr:schedule`. See [Apps on Northlight](./guides/apps-on-northlight.md) and [Apps with many users](./guides/apps-with-many-users.md). `memory` is the person's `public` documents ([Memory](./memory.md)). `docs` writes, reads and edits documents the calling app owns: `docs.write({name, body, preview, kind?, rules?})` returns the canonical `name`; `docs.get(name)` returns `body`, `revision`, `rules` and the edit `base`; `docs.edit(name, {body, rationale, base?})` changes it in place and refuses a stale `base` with `ConflictError` (`stale_revision`). To keep one document current, `get` it (catch `NotFoundError` on first run to `write`), compare `body` to your text, and `edit` only when they differ. `system.health` (`/healthz`) is the daemon's liveness check; `health.get` is the app listener's.
42
42
 
43
43
  Action methods keep the product's literal name (`fork`, `revive`, `promote`, `yield`) rather than being renamed into a generic verb. Every request-capable method takes `RequestOptions` as its final argument after its path, body, or query arguments. `RequestOptions` is `{ headers?, signal?, timeout?, maxRetries? }`; stream event options exclude `timeout` and add `after`.
44
44
 
45
45
  ## Custom objects
46
46
 
47
- `client.customObjects` registers an external service or script as an object on the canvas, with a declared event catalog and a queue, URL or argv receiver, and publishes its events to the objects watching it. `register(body)` returns the object and, once, its publish token; `publish(ref, body)` sends one declared event (a custom object may publish with that token alone); `receive(ref, { after?, signal? })` is an async iterator over a queue receiver's deliveries and replays every unacknowledged delivery on each connect; `ack(ref, deliveryIds)` acknowledges them; `unregister(ref)` deletes the object. The same objects are managed from a terminal with `crtr custom-object` and watched with `crtr canvas watch`.
47
+ `client.customObjects` registers an external service or script as an object on the canvas, with a declared event catalog and a queue, URL or argv receiver, and publishes its events to the objects watching it. `register(body)` returns the object and, once, its publish token; `publish(ref, body)` sends one declared event (a custom object may publish with that token alone); `receive(ref, { after?, signal? })` is an async iterator over a queue receiver's deliveries and replays every unacknowledged delivery on each connect; `ack(ref, deliveryIds)` acknowledges them; `unregister(ref)` deletes the object. An app reaches `register`, `publish` and `unregister` on its own objects through `oauth.client(userId)` or `oauth.appClient(userId)`, and links a node to one with `client.canvas.watch(ref, { watcher, watcher_machine? })` and `client.canvas.unwatch(ref, { watcher, watcher_machine? })` under `crtr:objects:link:node` (without `watcher`, `unwatch` removes the app's own watch). The same objects are managed from a terminal with `crtr custom-object` and watched with `crtr canvas watch`.
48
48
 
49
49
  ## Files and bash
50
50
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.491",
3
+ "version": "0.3.493",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -138,7 +138,7 @@
138
138
  },
139
139
  "license": "UNLICENSED",
140
140
  "dependencies": {
141
- "@north-light/identity": "0.3.491",
141
+ "@north-light/identity": "0.3.493",
142
142
  "@earendil-works/pi-agent-core": "1.1.0",
143
143
  "@earendil-works/pi-ai": "1.1.0",
144
144
  "@earendil-works/pi-coding-agent": "1.1.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/identity",
3
- "version": "0.3.491",
3
+ "version": "0.3.493",
4
4
  "description": "Northlight access-token verification and scope rules",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/runtime.lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.491",
3
+ "version": "0.3.493",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@north-light/cli",
9
- "version": "0.3.491",
9
+ "version": "0.3.493",
10
10
  "hasInstallScript": true,
11
11
  "license": "UNLICENSED",
12
12
  "workspaces": [
@@ -18,7 +18,7 @@
18
18
  "@earendil-works/pi-ai": "1.1.0",
19
19
  "@earendil-works/pi-coding-agent": "1.1.0",
20
20
  "@earendil-works/pi-tui": "1.1.0",
21
- "@north-light/identity": "0.3.491",
21
+ "@north-light/identity": "0.3.493",
22
22
  "cron-parser": "^5.6.0",
23
23
  "esbuild": "^0.27.7",
24
24
  "jose": "^6.2.12",
@@ -12116,17 +12116,17 @@
12116
12116
  },
12117
12117
  "packages/crouter-api": {
12118
12118
  "name": "@north-light/api",
12119
- "version": "0.3.491",
12119
+ "version": "0.3.493",
12120
12120
  "license": "UNLICENSED"
12121
12121
  },
12122
12122
  "packages/crouter-env-docker": {
12123
12123
  "name": "@north-light/env-docker",
12124
- "version": "0.3.491",
12124
+ "version": "0.3.493",
12125
12125
  "license": "UNLICENSED"
12126
12126
  },
12127
12127
  "packages/crouter-identity": {
12128
12128
  "name": "@north-light/identity",
12129
- "version": "0.3.491",
12129
+ "version": "0.3.493",
12130
12130
  "license": "UNLICENSED",
12131
12131
  "dependencies": {
12132
12132
  "jose": "^6.2.1"
@@ -12134,20 +12134,20 @@
12134
12134
  },
12135
12135
  "packages/crouter-plugin": {
12136
12136
  "name": "@north-light/plugin",
12137
- "version": "0.3.491",
12137
+ "version": "0.3.493",
12138
12138
  "license": "UNLICENSED",
12139
12139
  "dependencies": {
12140
- "@north-light/api": "0.3.491",
12141
- "@north-light/identity": "0.3.491"
12140
+ "@north-light/api": "0.3.493",
12141
+ "@north-light/identity": "0.3.493"
12142
12142
  }
12143
12143
  },
12144
12144
  "packages/crouter-sdk": {
12145
12145
  "name": "@north-light/sdk",
12146
- "version": "0.3.491",
12146
+ "version": "0.3.493",
12147
12147
  "license": "UNLICENSED",
12148
12148
  "dependencies": {
12149
- "@north-light/api": "0.3.491",
12150
- "@north-light/identity": "0.3.491",
12149
+ "@north-light/api": "0.3.493",
12150
+ "@north-light/identity": "0.3.493",
12151
12151
  "jose": "^6.2.1"
12152
12152
  },
12153
12153
  "bin": {