@north-light/cli 0.3.543 → 0.3.545
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/dist/builtin-memory/crouter-sdk/release-notes.md +6 -0
- package/dist/builtin-memory/northlight-apps/build-on-your-app.md +47 -0
- package/dist/builtin-memory/northlight-apps/cli.md +3 -3
- package/dist/builtin-memory/northlight-apps/coding-agents.md +16 -7
- package/dist/builtin-memory/northlight-apps/concepts/apps-and-sign-in.md +0 -4
- package/dist/builtin-memory/northlight-apps/concepts/connections.md +0 -4
- package/dist/builtin-memory/northlight-apps/concepts/providers.md +0 -4
- package/dist/builtin-memory/northlight-apps/concepts/runs.md +0 -4
- package/dist/builtin-memory/northlight-apps/concepts/scopes-and-grants.md +0 -4
- package/dist/builtin-memory/northlight-apps/concepts/testing-mode.md +0 -4
- package/dist/builtin-memory/northlight-apps/get-started.md +56 -0
- package/dist/builtin-memory/northlight-apps/guides/go-live.md +1 -1
- package/dist/builtin-memory/northlight-apps/guides/manage-your-app.md +4 -4
- package/dist/builtin-memory/northlight-apps/guides/watchable-objects.md +74 -0
- package/dist/builtin-memory/northlight-apps/how-it-fits.md +1 -1
- package/dist/builtin-memory/northlight-apps/know-the-person.md +29 -0
- package/dist/builtin-memory/northlight-apps/let-their-ai-use-your-app.md +67 -0
- package/dist/builtin-memory/northlight-apps/providers/README.md +1 -1
- package/dist/builtin-memory/northlight-apps/providers/context.md +2 -2
- package/dist/builtin-memory/northlight-apps/providers/device.md +3 -3
- package/dist/builtin-memory/northlight-apps/providers/integrations.md +1 -1
- package/dist/builtin-memory/northlight-apps/providers/search.md +1 -1
- package/dist/builtin-memory/northlight-apps/providers/sms.md +3 -3
- package/dist/builtin-memory/northlight-apps/quickstart.md +3 -17
- package/dist/builtin-memory/northlight-apps/reach-people-by-text.md +50 -0
- package/dist/builtin-memory/northlight-apps/use-our-ai.md +55 -0
- package/dist/builtin-memory/northlight-apps/use-our-apps.md +46 -0
- package/dist/core/command-plugins/transport/http-plan.d.ts +2 -0
- package/dist/core/command-plugins/transport/http-plan.js +1 -1
- package/dist/core/providers/call.js +1 -1
- package/dist/daemon/api/app-listener.d.ts +1 -1
- package/dist/daemon/api/app-listener.js +13 -13
- package/dist/daemon/api/handlers/providers.d.ts +3 -1
- package/dist/shared/traceparent.d.ts +6 -0
- package/dist/shared/traceparent.js +1 -0
- package/docs/apps/build-on-your-app.md +44 -0
- package/docs/apps/cli.md +3 -3
- package/docs/apps/coding-agents.md +16 -7
- package/docs/apps/concepts/apps-and-sign-in.md +0 -4
- package/docs/apps/concepts/connections.md +0 -4
- package/docs/apps/concepts/providers.md +0 -4
- package/docs/apps/concepts/runs.md +0 -4
- package/docs/apps/concepts/scopes-and-grants.md +0 -4
- package/docs/apps/concepts/testing-mode.md +0 -4
- package/docs/apps/get-started.md +47 -0
- package/docs/apps/guides/go-live.md +1 -1
- package/docs/apps/guides/manage-your-app.md +4 -4
- package/docs/apps/guides/watchable-objects.md +71 -0
- package/docs/apps/how-it-fits.md +1 -1
- package/docs/apps/know-the-person.md +27 -0
- package/docs/apps/let-their-ai-use-your-app.md +63 -0
- package/docs/apps/providers/README.md +1 -1
- package/docs/apps/providers/context.md +2 -2
- package/docs/apps/providers/device.md +3 -3
- package/docs/apps/providers/integrations.md +1 -1
- package/docs/apps/providers/search.md +1 -1
- package/docs/apps/providers/sms.md +3 -3
- package/docs/apps/quickstart.md +3 -17
- package/docs/apps/reach-people-by-text.md +47 -0
- package/docs/apps/use-our-ai.md +27 -0
- package/docs/apps/use-our-apps.md +32 -0
- package/docs/cli/join-northlight.md +1 -1
- package/docs/release-local.md +2 -2
- package/docs/sdk/release-notes.md +6 -0
- package/package.json +3 -3
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -12
package/docs/apps/quickstart.md
CHANGED
|
@@ -9,19 +9,19 @@ description: From no account to a running app that signs a person in with Northl
|
|
|
9
9
|
npx @north-light/sdk@latest init my-app
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
This command creates a small Node server, a signing key and an env file. About ten minutes later you have an app on your laptop that signs you in with Northlight, starts an agent run on your own Northlight runtime, and texts your phone. The app runs on your machine and talks to Northlight's production directory at `https://account.northlight.ai`. There is no local Northlight stack to run
|
|
12
|
+
This command creates a small Node server, a signing key and an env file. About ten minutes later you have an app on your laptop that signs you in with Northlight, starts an agent run on your own Northlight runtime, and texts your phone. The app runs on your machine and talks to Northlight's production directory at `https://account.northlight.ai`. There is no local Northlight stack to run. To run crouter on your own machine as well, see [Get started](/docs/get-started#run-crtr-cloud-apps-yourself).
|
|
13
13
|
|
|
14
14
|
You need Node.js 20.6 or later (the start command uses `--env-file`) and a phone that can receive iMessage. The server was run on Node 20.6, 20.20, 22.14, 22.22 and 26.12.
|
|
15
15
|
|
|
16
16
|
Using a coding agent? Tell it: *Read https://sdk.docs.northlight.ai/SKILL.md and follow it.* It runs every command below; you sign up, then choose **Allow** twice in your browser. See [Use your coding agent](/docs/coding-agents).
|
|
17
17
|
|
|
18
|
-
Each step below ends with what you should see when it worked.
|
|
18
|
+
Each step below ends with what you should see when it worked.
|
|
19
19
|
|
|
20
20
|
## 1. Create an account
|
|
21
21
|
|
|
22
22
|
Open `https://account.northlight.ai/signup` and create your account. Signup texts a confirmation code to your phone, and that text is sent over iMessage. A number that cannot receive iMessage gets "We couldn't send the text", and retrying does not help. One phone number belongs to one account.
|
|
23
23
|
|
|
24
|
-
You should see: your account's page after you enter the code. Opening `https://account.northlight.ai/console` while signed in shows the console, where your apps are listed.
|
|
24
|
+
You should see: your account's page after you enter the code. Opening `https://account.northlight.ai/console` while signed in shows the console, where your apps are listed.
|
|
25
25
|
|
|
26
26
|
## 2. Scaffold the app
|
|
27
27
|
|
|
@@ -49,8 +49,6 @@ You should see, on the terminal: `Created a Northlight app in my-app:` with the
|
|
|
49
49
|
|
|
50
50
|
Only the browser registration below uses that line: `register` reads the public half from `local/app-key.json` itself. If a file already exists, `init` refuses, names it and exits non-zero without writing anything.
|
|
51
51
|
|
|
52
|
-
Checked on production: `npx @north-light/sdk@latest init my-app` (npm `latest` 0.3.476) in an empty directory with no crtr on `PATH` printed this output and wrote these files, the private key has mode `0600`, and `server.ts` is the one listed at the end of this page. Running it again names the skill file and writes nothing.
|
|
53
|
-
|
|
54
52
|
## 3. Log in
|
|
55
53
|
|
|
56
54
|
```bash
|
|
@@ -89,8 +87,6 @@ and "Done. Go back to your terminal." in the browser. The name, id and dates are
|
|
|
89
87
|
|
|
90
88
|
The login is saved outside your project, in `~/.config/northlight/credentials.json` (mode `0600`). Never commit, paste or print it.
|
|
91
89
|
|
|
92
|
-
Checked on production: this whole step, including the confirm page and its wording. The confirm page reads "Let a coding agent manage your Northlight apps?", shows the code, the computer's name and platform and the address it asked from ("The computer named itself; Northlight did not check it"), and lists what the login can and can't do. After **Allow** the page reads "Done / Go back to your terminal." and the terminal prints the output above.
|
|
93
|
-
|
|
94
90
|
If you run `login` again, it does not start over. While a code is pending it prints "Still waiting for the login started at HH:MM." with the same link and code. Once you are logged in it prints "Already logged in as …" and exits 0. If the code expired unapproved it exits 1 and says so: run it again for a new code. See [the CLI reference](/docs/cli#login-logout-whoami).
|
|
95
91
|
|
|
96
92
|
If `login` cannot reach `account.northlight.ai`, or you would rather use the browser, skip to [Register in the browser instead](#register-in-the-browser-instead).
|
|
@@ -118,8 +114,6 @@ Next: npm i && npm start, then open http://localhost:3000/auth/login
|
|
|
118
114
|
|
|
119
115
|
`local/app.env` now has all four settings. The name, client ID and key ID are examples. Change the defaults with `--name`, `--logo`, `--justification` and `--redirect-uri`; the default logo is a placeholder, `https://sdk.docs.northlight.ai/app-logo.png`. `register` refuses when `CROUTER_CLIENT_ID` is already set. A login can register at most 10 apps a day.
|
|
120
116
|
|
|
121
|
-
Checked on production: this step, including that the directory accepts the default logo.
|
|
122
|
-
|
|
123
117
|
## 5. Run it
|
|
124
118
|
|
|
125
119
|
```bash
|
|
@@ -131,8 +125,6 @@ node --env-file=local/app.env --import tsx server.ts
|
|
|
131
125
|
|
|
132
126
|
Open `http://localhost:3000/auth/login`. Your browser goes to `account.northlight.ai`. Sign in if asked, read the consent page, and choose Allow. You land back on `http://localhost:3000/` with "Signed in" and your Northlight user id. Press **Start a run and send me a text**. The page answers "Done", shows the run's status `idle`, the run's reply (`pong`) and the text's `message_id`, and your phone receives "Hello from my first Northlight app." from Northlight's number.
|
|
133
127
|
|
|
134
|
-
Checked on production, as the account that owns the app: the server starts (with `npm start` too), `/` shows the sign-in link, and `/auth/login` answers `303` to `https://account.northlight.ai/authorize?client_id=…&scope=openid+profile+crtr%3Allm+crtr%3Aact+sms%3Asend…&code_challenge_method=S256…`. The consent page listed the four permissions and the monthly cap, **Allow** returned to `http://localhost:3000/` with "Signed in" and the user id, and the button page answered "Done" with status `idle` and a `message_id` for the text. In the console the key then read "Last used just now". Not yet checked on production: that the text reached the phone (the `message_id` is the provider's answer, not a delivery receipt), and the `426` case. The `pong` reply is read through `runs.reply` and has not been run on production since this example changed. Signing in as a second person needs a second account and is not covered here.
|
|
135
|
-
|
|
136
128
|
If `/` shows "One step left", `CROUTER_CLIENT_ID` is empty: run `npx @north-light/sdk register` (or, for an app you registered in the browser, `env --client-id`) and restart. If a call fails with `426 runtime_version_unsupported`, your SDK is newer than the Northlight runtimes. Install the previous version with `npm i --save-exact @north-light/sdk@<version>` and tell support@northlight.ai.
|
|
137
129
|
|
|
138
130
|
## 6. What next
|
|
@@ -163,16 +155,12 @@ Choose **Register app**.
|
|
|
163
155
|
|
|
164
156
|
You should see: a page titled "*your app's name* is registered" with a **Client ID** and, under it, the key ID of the key you pasted. Copy the client ID, then choose **Continue to *your app's name***. If it says "Next: add your app's public key on the Sign-in tab", the key was left out: open the app's **Sign-in** tab and choose **Add key**. The app starts asking for `crtr:llm` and `crtr:act`.
|
|
165
157
|
|
|
166
|
-
Checked on production: these field labels, registering with a pasted key, and the app page opening in testing with that key active and `crtr:llm` and `crtr:act` listed. The "Next: add your app's public key" message, which shows when the key is left out, is not yet checked on production.
|
|
167
|
-
|
|
168
158
|
### Add the permission to text
|
|
169
159
|
|
|
170
160
|
On the app's page, open the **What it asks for** tab and choose **Add permissions**. Choose **Texting**, tick `sms:send` ("Send you text messages from Northlight's number"), and choose **Done**. Then choose **Save** under the list: **Done** only closes the dialog, and the change is not stored until you save.
|
|
171
161
|
|
|
172
162
|
You should see: `sms:send` under what your app asks for after **Save** says "Saved", next to `crtr:llm` and `crtr:act`. The server in this guide asks for all three, so without `sms:send` the consent page does not offer it and the text in step 5 is refused. Take scope strings from this list. Do not invent them. See [Scopes and grants](/docs/concepts/scopes-and-grants).
|
|
173
163
|
|
|
174
|
-
Checked on production: after **Save** and a reload, the tab lists `crtr:llm` and `crtr:act` under Agents and `sms:send` under Texting, and the consent page in step 5 offered the text permission.
|
|
175
|
-
|
|
176
164
|
### Write the client ID into the env file
|
|
177
165
|
|
|
178
166
|
```bash
|
|
@@ -191,8 +179,6 @@ Key file: local/app-key.json (set CROUTER_KEY_FILE to change it).
|
|
|
191
179
|
|
|
192
180
|
`local/app.env` now has all four settings. The command makes no network call and keeps every other line in the file. Add `--origin <url>` if your app does not run on `http://localhost:3000`.
|
|
193
181
|
|
|
194
|
-
Checked on production: this output, and that the command works in a directory with no `local/` yet. `--origin` is not yet checked on production.
|
|
195
|
-
|
|
196
182
|
## The server `init` writes
|
|
197
183
|
|
|
198
184
|
This is `examples/apps/quickstart-server.ts`. The SDK reads no environment: the server passes the values in.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Reach people by text
|
|
3
|
+
description: Give your app its own iMessage number with Comms. People text it, your server answers with an agent run on their runtime, and you can text them again later.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Reach people by text
|
|
7
|
+
|
|
8
|
+
Comms gives your app its own iMessage number, under your app's name and avatar. People text that number, Comms sends each text to your server as a signed webhook, and your server answers with an agent run on the person's own runtime. Once a person has texted you, your app can text them again later, for example from a timer.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import {continueInRuntime, formatReply, verifyWebhook} from '@north-light/comms';
|
|
12
|
+
|
|
13
|
+
const event = verifyWebhook(req.headers, rawBody, [process.env.COMMS_WEBHOOK_SECRET!]);
|
|
14
|
+
if (event.type === 'message.received' && event.data.content.type === 'text') {
|
|
15
|
+
const {contact, content} = event.data;
|
|
16
|
+
if (!contact.user) return; // only a sender texting from an Apple ID email has no user
|
|
17
|
+
const client = await oauth.client(contact.user.id); // their Northlight user id, the same as Connection.userId
|
|
18
|
+
const {runId, reply} = await continueInRuntime({client, message: content.text, runId: runs.get(contact.id), idempotencyKey: event.id});
|
|
19
|
+
runs.set(contact.id, runId); // later texts continue the same run
|
|
20
|
+
const {text} = await reply.collect();
|
|
21
|
+
for (const part of formatReply(text)) {
|
|
22
|
+
await comms.sendMessage({environment: event.environment, to: {contact_id: contact.id}, text: part, idempotency_key: `reply:${event.id}:${part.length}`});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`oauth.client` throws `CrouterError` with code `not_connected` when the person has not signed in to your app yet. Answer that with `sendSignInLink(comms, contact, {environment: event.environment})`: Comms texts them a link that signs them in to your app, which lands on your **Sign-in start URL** (console → **Profile** → **Marketplace**).
|
|
28
|
+
|
|
29
|
+
## The steps
|
|
30
|
+
|
|
31
|
+
The [Comms guide for coding agents](https://comms.northlight.ai/llms.txt) is the whole reference: the webhook events, the send API, its errors, STOP and HELP handling, and the `crtr comms` commands. In short:
|
|
32
|
+
|
|
33
|
+
1. **Build in fake mode.** `npx @north-light/comms fake --webhook http://localhost:3000/hook` runs a local Comms with no account. `npx @north-light/comms fake send --from +15550001 --text "hi"` plays a person texting you.
|
|
34
|
+
2. **Register your app on Northlight.** [Quick setup](/docs/quickstart) steps 1 to 4: sign up, `npx @north-light/sdk login`, `npx @north-light/sdk register`. Comms signs in with the same app key.
|
|
35
|
+
3. **Connect the app to Comms.** At `https://comms.northlight.ai`, sign in and choose **Connect an app**. This is done in a browser only.
|
|
36
|
+
4. **Turn Texting on.** On the app's page there, or with `crtr comms turn-on`: a display name, a square avatar, the HELP text and your test webhook URL. The page shows the test webhook signing secret.
|
|
37
|
+
5. **Text it from your own phone, in test mode.** Add yourself as a tester (`crtr comms testers add --app-id <id> --phone <number> --label <name>`, or the site), then text `JOIN <code>` to the test number. Test mode is free; the [Comms guide](https://comms.northlight.ai/llms.txt) has the tester limit.
|
|
38
|
+
6. **Go to production** when you want your app's own number and anyone to text it. Production is paid: add a card on the billing account, and Comms gets your app its own number.
|
|
39
|
+
|
|
40
|
+
Comms is priced per person your app texts with in production each month; fake mode and testing are free. The SDK is [`@north-light/comms`](https://www.npmjs.com/package/@north-light/comms) on npm. Install it with `npm i @north-light/comms`.
|
|
41
|
+
|
|
42
|
+
## Rules
|
|
43
|
+
|
|
44
|
+
- **People text first.** Your app can text a person only after they texted your number in that environment, and until they send STOP. A send to anyone else fails `403 not_texted_first`.
|
|
45
|
+
- **Address people by `contact_id` or `user_id`**, never by phone number.
|
|
46
|
+
- **Derive `idempotency_key` from the event you are answering**, so a retried webhook sends nothing twice. Deduplicate deliveries on `event.id`.
|
|
47
|
+
- **Verify the raw body** with `verifyWebhook` before you parse it, and answer `2xx` within 15 seconds.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Let your app use our AI
|
|
3
|
+
description: Start agent runs on each person's own Northlight runtime, with their memory, files and tools, paid by their AI subscription. Typed results, streaming, background runs and documents.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Let your app use our AI
|
|
7
|
+
|
|
8
|
+
Your app starts agents on the person's own Northlight runtime. Each run has their memory, files and tools, works under the scopes they approved, and its model calls are paid by their AI subscription, not by you.
|
|
9
|
+
|
|
10
|
+
<include lang="ts">../../examples/apps/runs-parse.ts</include>
|
|
11
|
+
|
|
12
|
+
`runs.parse` starts a run and returns a value checked against your schema. `runs.start` returns at once and lets you follow the run, reply to it or leave it running.
|
|
13
|
+
|
|
14
|
+
## Guides
|
|
15
|
+
|
|
16
|
+
| Page | What it covers |
|
|
17
|
+
|---|---|
|
|
18
|
+
| [Runs](/docs/concepts/runs) | Start a run, its status and outcome, a run's own scopes, and how to bound one |
|
|
19
|
+
| [Typed results](/docs/guides/typed-results) | Get a value back with `runs.parse` and a schema; never parse the trace |
|
|
20
|
+
| [Stream a run](/docs/guides/stream-a-run) | Show the agent's text and tool calls as they happen |
|
|
21
|
+
| [Background runs](/docs/guides/background-runs) | Learn when a run you did not wait on has ended, with `RunWatcher` or run notices |
|
|
22
|
+
| [Files and documents](/docs/guides/files-and-documents) | Download a file from a run, and read the person's public documents |
|
|
23
|
+
| [Many users](/docs/guides/many-users) | Keep each person's runtime separate when people meet in your app |
|
|
24
|
+
|
|
25
|
+
To schedule work, call `runs.start` from your own timer. A run's agent may also schedule itself with `crtr cron add` when the run holds `crtr:schedule` ([Scopes and grants](/docs/concepts/scopes-and-grants)).
|
|
26
|
+
|
|
27
|
+
An app that pays for its own model calls instead can serve them from its own service with `inferenceEndpoint` from `@north-light/sdk`; see the [release notes](/docs/release-notes) and the [reference](/docs/reference).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Let your app use our apps
|
|
3
|
+
description: Call Northlight's providers from your app on the person's runtime — texting their phone, web search, their connected accounts, their Mac — with providers.tools and providers.call.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Let your app use our apps
|
|
7
|
+
|
|
8
|
+
Northlight's own apps are providers your app can call on the person's runtime: text their phone, place calls, search the web, open a cloud browser, read and act in the accounts they connected, and use their Mac. The person approves each provider's scope once, on your app's consent page.
|
|
9
|
+
|
|
10
|
+
<include lang="ts">../../examples/apps/provider-tools.ts</include>
|
|
11
|
+
|
|
12
|
+
Every provider works the same way: ask for its scope, list its tools with `providers.tools('<provider>')`, then call one with `providers.call`. Scope strings, tool names and arguments come from those lists, never from memory.
|
|
13
|
+
|
|
14
|
+
## Providers
|
|
15
|
+
|
|
16
|
+
| Provider id | What it does | Page |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `sms` | Texts the signed-in person's own verified phone | [Texting (sms)](/docs/providers/sms) |
|
|
19
|
+
| `search` | Web search, sourced answers, page contents and paid data endpoints | [Search](/docs/providers/search) |
|
|
20
|
+
| `integrations` | The person's own accounts at other services | [Integrations](/docs/providers/integrations) |
|
|
21
|
+
| `context` | Ask about the person from their memory, and look up public profiles | [Context](/docs/providers/context) |
|
|
22
|
+
| `device` | The person's Mac: browser, files, Messages and shell | [Device](/docs/providers/device) |
|
|
23
|
+
|
|
24
|
+
These five have pages here. Northlight also runs `phone` (calls from Northlight's number, with an AI voice), `browser` (cloud browser sessions) and `meetings` (the person's meeting notes and transcripts), which have no page yet. For any of them, `providers.tools()` with no argument lists every provider installed on the person's runtime, `providers.tools('<provider>')` lists its tools and arguments, and the console's **Add permissions** list shows every scope your app can ask for.
|
|
25
|
+
|
|
26
|
+
## Guides
|
|
27
|
+
|
|
28
|
+
| Page | What it covers |
|
|
29
|
+
|---|---|
|
|
30
|
+
| [Providers](/docs/concepts/providers) | Scopes, finding and calling tools, and providers your app requires |
|
|
31
|
+
| [Providers index](/docs/providers) | Every first-party provider, its scopes and where names come from |
|
|
32
|
+
| [Grant changes](/docs/guides/grant-changes) | When a person adds or removes a scope, and waiting on a provider's setup |
|
|
@@ -5,7 +5,7 @@ description: Join a laptop to your Northlight account with crtr sys join so crtr
|
|
|
5
5
|
|
|
6
6
|
# Join a machine to your Northlight account
|
|
7
7
|
|
|
8
|
-
Joining makes this machine one of your Northlight account's machines, so `crtr cloud …` commands run as you. Building an app
|
|
8
|
+
Joining makes this machine one of your Northlight account's machines, so `crtr cloud …` commands run as you. Join when you want to run `crtr cloud apps` yourself, or to let your own crtr agents build and manage your Northlight apps. Building an app works without it too: the [SDK docs site](https://sdk.docs.northlight.ai/docs/get-started) uses `npx @north-light/sdk` and the web console.
|
|
9
9
|
|
|
10
10
|
Create your account at `https://account.northlight.ai/signup` first. Then install the CLI (`npm i -g @north-light/cli`). Joining needs `crtr` 0.3.436 or later (older versions need `crtr sys daemon stop` first and fail if a viewer is open); `crtr --version` shows yours.
|
|
11
11
|
|
package/docs/release-local.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Use this only for a release explicitly authorized by Silas. `.github/workflows/publish.yml` is the source of truth; this is its manual path when Actions cannot run. Work on clean, current `main`, with `npm whoami` showing the publishing account. Verify the code first (`npm run build:api`, `npm run build`, `npx tsc --noEmit`, relevant `npm run test:isolated -- …`). Do not start a release while another agent owns uncommitted changes in this shared checkout.
|
|
4
4
|
|
|
5
5
|
1. Check the six latest registry versions with `npm view <name> version` for each of `@north-light/cli`, `@north-light/api`, `@north-light/env-docker`, `@north-light/identity`, `@north-light/sdk` and `@north-light/plugin`. Fetch `origin/main`, ensure the release commit is current, and choose a patch version greater than every published version. Do **not** use the workflow's `git reset --hard` in a shared checkout.
|
|
6
|
-
2. Run `node scripts/release-version.mjs "$VERSION"`. It sets all six manifests to `$VERSION`, pins every dependency between them (root → identity, SDK → api and
|
|
7
|
-
3. From the tagged release commit run `npm ci`. Publish in dependency order, checking `npm view "$PACKAGE@$VERSION" version` before each and skipping only on a positive sighting: `npm run build:identity` then `npm publish` in `packages/crouter-identity`; `npm run build` then `CRTR_PACK_MINIFY=1 npm publish` at root (Docker must be running: the pack cross-builds the Linux x64 and arm64 native addons into `dist/native/linux/<arch>/addon.node` and fails the release if it cannot); `npm run build:api` then publish in `packages/crouter-api`; `npm run build:env-docker` then publish in `packages/crouter-env-docker`; `npm run build:
|
|
6
|
+
2. Run `node scripts/release-version.mjs "$VERSION"`. It sets all six manifests to `$VERSION`, pins every dependency between them (root → identity, SDK → api, identity and plugin, plugin → api and identity) to exactly `$VERSION` with no `^`, writes `SDK_VERSION` in `packages/crouter-sdk/src/version.ts` (informational: compatibility is the contract level), and renames the `## Next release` section of `docs/sdk/release-notes.md` to `## $VERSION`. One release is one version set: an app pinning `@north-light/sdk@$VERSION` gets exactly this release's api and identity. Run `npm install --package-lock-only --ignore-scripts`, then `node scripts/contract.mjs release`: it fails on an unacknowledged breaking `/v1` change or an undeclared watched file (the same check CI runs), then writes `contract/surface.txt`, `CONTRACT_LEVEL` in `src/api/contract.ts` (a minor bump only when the surface changed or a declaration says `bump`), `crouterContract` in the SDK manifest, and resets `contract/next.json`. Run `node scripts/release-version.mjs --check` (prints `one version set`). Check `git diff` and commit only the six manifests, `packages/crouter-sdk/src/version.ts`, `docs/sdk/release-notes.md`, `package-lock.json`, `contract/surface.txt`, `contract/next.json` and `src/api/contract.ts` as `chore: release v$VERSION`. Create `git tag -a "v$VERSION" -m "chore: release v$VERSION"`, then `git push --atomic origin HEAD:main "refs/tags/v$VERSION"`. If rejected due to a concurrent push, remove the *local* release tag, integrate fresh main, then recheck versions and retry; never push a tag separately.
|
|
7
|
+
3. From the tagged release commit run `npm ci`. Publish in dependency order, checking `npm view "$PACKAGE@$VERSION" version` before each and skipping only on a positive sighting: `npm run build:identity` then `npm publish` in `packages/crouter-identity`; `npm run build` then `CRTR_PACK_MINIFY=1 npm publish` at root (Docker must be running: the pack cross-builds the Linux x64 and arm64 native addons into `dist/native/linux/<arch>/addon.node` and fails the release if it cannot); `npm run build:api` then publish in `packages/crouter-api`; `npm run build:env-docker` then publish in `packages/crouter-env-docker`; `npm run build:plugin` then `CRTR_PACK_MINIFY=1 npm publish` in `packages/crouter-plugin` (the SDK depends on it, so it goes first); then `npm run build:sdk` then `npm publish --tag next` in `packages/crouter-sdk` (its `prepublishOnly` guard refuses any other form, including `--tag latest`; every SDK release lands on `next`). Use npm's interactive authentication/2FA where required (see `personal-operations/npm-2fa-cli`); a read-only token cannot publish. Provenance remains off because the source repository is private. Do not build or publish the Docker image in this no-Actions path.
|
|
8
8
|
4. Confirm all six exact versions with `npm view`. In a fresh temporary directory, `npm init -y && npm install @north-light/sdk@$VERSION`, then prove both `@north-light/sdk/errors` (`errorCodes`) and `@north-light/sdk/stores/postgres` resolve via `node --input-type=module -e '…'`. Record any partial publish and finish it from the exact release tag rather than cutting another version: `gh workflow run publish.yml -f release_tag=v$VERSION` runs `recover-release`, which verifies the tag is a release commit on main, checks it out, and publishes only the packages and image the registry does not yet show (SDK to `next`; it never writes the image `:latest`, so if the recovered tag is the newest release, `:latest` follows the next normal release).
|
|
9
9
|
5. Promote `latest` last, through CI only: `gh workflow run publish.yml -f promote=true` runs the `promote-sdk` job, the one writer of `latest`. It shares the `sdk-dist-tag` concurrency group with the automatic runs (they queue, never overlap), reads the router's `/contract` itself, re-reads `latest` right before the write and moves it only if unchanged. It also runs after each SDK publish and hourly. `PROD_CONTRACT_URL=<the router's /contract URL> node scripts/promote-sdk.mjs` is a read-only dry run; its `--apply` refuses outside Actions. **Never `npm dist-tag add` the SDK by hand.** The one exception is Actions fully down: a person then runs the printed target by hand through the npm 2FA wrapper only after re-reading `npm view @north-light/sdk dist-tags` and confirming no `promote-sdk` run is active (`gh run list --workflow publish.yml`) and that the target is above the current `latest`.
|
|
@@ -7,6 +7,12 @@ 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.545
|
|
11
|
+
|
|
12
|
+
`@north-light/sdk/stores/postgres` gains an object kit: `PostgresObjectStore` and `objectKitSchemaSql`. Additive: no existing export, request or response changes.
|
|
13
|
+
|
|
14
|
+
- `PostgresObjectStore` keeps per-person custom objects (`instance`), the nodes watching them (`watch`), and a PostgreSQL publish outbox written inside the caller's transaction (`enqueue`) and delivered at least once by `startPublisher`. `objectKitSchemaSql()` returns the DDL for its three tables. See [Watchable objects](/docs/guides/watchable-objects).
|
|
15
|
+
|
|
10
16
|
## 0.3.542
|
|
11
17
|
|
|
12
18
|
The directory's account page reads and removes individual AI subscription accounts. Additive: no app-facing request or response changes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.545",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"activate:pull": "git pull && npm install && npm run activate",
|
|
94
94
|
"build:api": "npm run build:identity && tsc -p packages/crouter-api/tsconfig.json",
|
|
95
95
|
"build:env-docker": "tsc -p packages/crouter-env-docker/tsconfig.json",
|
|
96
|
-
"build:sdk": "npm run build:api && npm run build:identity && npm run build --workspace packages/crouter-sdk",
|
|
96
|
+
"build:sdk": "npm run build:api && npm run build:identity && npm run build:plugin && npm run build --workspace packages/crouter-sdk",
|
|
97
97
|
"build:plugin": "tsc -p packages/crouter-plugin/tsconfig.json",
|
|
98
98
|
"typecheck": "tsc --noEmit && tsc -p src/doc-editor/tsconfig.json",
|
|
99
99
|
"typecheck:pi-packages": "npx tsc -p src/builtin-pi-packages/pi-crtr-extensions/tsconfig.json",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
},
|
|
141
141
|
"license": "UNLICENSED",
|
|
142
142
|
"dependencies": {
|
|
143
|
-
"@north-light/identity": "0.3.
|
|
143
|
+
"@north-light/identity": "0.3.545",
|
|
144
144
|
"@earendil-works/pi-agent-core": "1.1.0",
|
|
145
145
|
"@earendil-works/pi-ai": "1.1.0",
|
|
146
146
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.545",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/cli",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.545",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"workspaces": [
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@milkdown/preset-gfm": "^7.22.3",
|
|
25
25
|
"@milkdown/prose": "^7.22.3",
|
|
26
26
|
"@milkdown/utils": "^7.22.3",
|
|
27
|
-
"@north-light/identity": "0.3.
|
|
27
|
+
"@north-light/identity": "0.3.545",
|
|
28
28
|
"cron-parser": "^5.6.0",
|
|
29
29
|
"esbuild": "^0.27.7",
|
|
30
30
|
"jose": "^6.2.12",
|
|
@@ -12455,17 +12455,17 @@
|
|
|
12455
12455
|
},
|
|
12456
12456
|
"packages/crouter-api": {
|
|
12457
12457
|
"name": "@north-light/api",
|
|
12458
|
-
"version": "0.3.
|
|
12458
|
+
"version": "0.3.545",
|
|
12459
12459
|
"license": "UNLICENSED"
|
|
12460
12460
|
},
|
|
12461
12461
|
"packages/crouter-env-docker": {
|
|
12462
12462
|
"name": "@north-light/env-docker",
|
|
12463
|
-
"version": "0.3.
|
|
12463
|
+
"version": "0.3.545",
|
|
12464
12464
|
"license": "UNLICENSED"
|
|
12465
12465
|
},
|
|
12466
12466
|
"packages/crouter-identity": {
|
|
12467
12467
|
"name": "@north-light/identity",
|
|
12468
|
-
"version": "0.3.
|
|
12468
|
+
"version": "0.3.545",
|
|
12469
12469
|
"license": "UNLICENSED",
|
|
12470
12470
|
"dependencies": {
|
|
12471
12471
|
"jose": "^6.2.1"
|
|
@@ -12473,20 +12473,21 @@
|
|
|
12473
12473
|
},
|
|
12474
12474
|
"packages/crouter-plugin": {
|
|
12475
12475
|
"name": "@north-light/plugin",
|
|
12476
|
-
"version": "0.3.
|
|
12476
|
+
"version": "0.3.545",
|
|
12477
12477
|
"license": "UNLICENSED",
|
|
12478
12478
|
"dependencies": {
|
|
12479
|
-
"@north-light/api": "0.3.
|
|
12480
|
-
"@north-light/identity": "0.3.
|
|
12479
|
+
"@north-light/api": "0.3.545",
|
|
12480
|
+
"@north-light/identity": "0.3.545"
|
|
12481
12481
|
}
|
|
12482
12482
|
},
|
|
12483
12483
|
"packages/crouter-sdk": {
|
|
12484
12484
|
"name": "@north-light/sdk",
|
|
12485
|
-
"version": "0.3.
|
|
12485
|
+
"version": "0.3.545",
|
|
12486
12486
|
"license": "UNLICENSED",
|
|
12487
12487
|
"dependencies": {
|
|
12488
|
-
"@north-light/api": "0.3.
|
|
12489
|
-
"@north-light/identity": "0.3.
|
|
12488
|
+
"@north-light/api": "0.3.545",
|
|
12489
|
+
"@north-light/identity": "0.3.545",
|
|
12490
|
+
"@north-light/plugin": "0.3.545",
|
|
12490
12491
|
"jose": "^6.2.1"
|
|
12491
12492
|
},
|
|
12492
12493
|
"bin": {
|