norns-sdk 0.2.0 → 0.4.0
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/CHANGELOG.md +17 -0
- package/README.md +6 -2
- package/dist/index.cjs +26 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +24 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `norns-sdk` are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.4.0] - 2026-10-23
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- `mode` is no longer sent on agent registration and is deprecated on
|
|
9
|
+
`defineAgent()`. Norns never read it: a conversation starts from a
|
|
10
|
+
`conversationKey` on the message, not from the definition.
|
|
11
|
+
|
|
12
|
+
## [0.3.0] - 2026-10-22
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- A worker holding a scoped key (`nrnw_...`, issued for one gard's worker)
|
|
16
|
+
skips the agent registration on `start()`, since the key cannot reach the
|
|
17
|
+
REST API; the definitions are registered with a tenant key instead.
|
|
18
|
+
`isScopedKey()` is exported.
|
|
19
|
+
- `KeyRevokedError`: `worker.stopped` rejects with it when Norns revokes the
|
|
20
|
+
key the worker joined on.
|
|
21
|
+
|
|
5
22
|
## [0.2.0] - 2026-10-16
|
|
6
23
|
|
|
7
24
|
### Added
|
package/README.md
CHANGED
|
@@ -44,7 +44,6 @@ const supportBot = defineAgent({
|
|
|
44
44
|
model: "claude-sonnet-5",
|
|
45
45
|
systemPrompt: "You are a customer support agent. Look up docs and help customers.",
|
|
46
46
|
tools: [searchDocs, sendEmail],
|
|
47
|
-
mode: "conversation",
|
|
48
47
|
});
|
|
49
48
|
|
|
50
49
|
const worker = new NornsWorker({ agents: [supportBot] });
|
|
@@ -90,6 +89,12 @@ execute: async ({ port }, ctx) => {
|
|
|
90
89
|
|
|
91
90
|
A fatally rejected claim (bad token, destroyed gard) rejects `start()` with `JoinError` instead of reconnect-looping. If the gard is destroyed while the worker is connected, `worker.stopped` rejects with `GardDestroyedError`.
|
|
92
91
|
|
|
92
|
+
A worker inside a gard should hold a [scoped key](https://github.com/nornscode/norns/blob/main/docs/gards.md#scoped-worker-keys) (`nrnw_...`) rather than the tenant key: it can join the worker socket, claim its gard and serve tasks, and nothing else. With one, `start()` skips the agent registration, since the key cannot reach the REST API; register the definitions with a tenant key instead. Pass `capabilities: ["tools"]` for a worker with no LLM access, matching what the key allows. If the key is revoked while the worker is connected, `worker.stopped` rejects with `KeyRevokedError`.
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
const worker = new NornsWorker({ agents: [coder], gard: 3, claimToken: "tok_...", capabilities: ["tools"] });
|
|
96
|
+
```
|
|
97
|
+
|
|
93
98
|
### Shutdown
|
|
94
99
|
|
|
95
100
|
On SIGTERM or SIGINT the worker drains instead of dying mid-task: it tells Norns to stop sending it work, finishes the tasks it holds, reports their results, leaves the channel, and the process exits. Tasks still running after `shutdownTimeoutMs` (default 30 seconds, or `NORNS_SHUTDOWN_TIMEOUT` in seconds) are dropped and Norns re-dispatches them. A second signal exits at once.
|
|
@@ -202,7 +207,6 @@ const agent = defineAgent({
|
|
|
202
207
|
model: "claude-sonnet-5",
|
|
203
208
|
systemPrompt: "You are helpful.",
|
|
204
209
|
tools: [search, sendEmail],
|
|
205
|
-
mode: "conversation", // "task" or "conversation"
|
|
206
210
|
checkpointPolicy: "on_tool_call", // "every_step", "on_tool_call", "manual"
|
|
207
211
|
contextWindow: 20,
|
|
208
212
|
maxSteps: 50,
|
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(index_exports, {
|
|
|
23
23
|
DEFAULT_MODEL: () => DEFAULT_MODEL,
|
|
24
24
|
GardDestroyedError: () => GardDestroyedError,
|
|
25
25
|
JoinError: () => JoinError,
|
|
26
|
+
KeyRevokedError: () => KeyRevokedError,
|
|
26
27
|
NornsApiError: () => NornsApiError,
|
|
27
28
|
NornsClient: () => NornsClient,
|
|
28
29
|
NornsError: () => NornsError,
|
|
@@ -33,6 +34,7 @@ __export(index_exports, {
|
|
|
33
34
|
consoleLogger: () => consoleLogger,
|
|
34
35
|
defineAgent: () => defineAgent,
|
|
35
36
|
inferProvider: () => inferProvider,
|
|
37
|
+
isScopedKey: () => isScopedKey,
|
|
36
38
|
jsonSchema: () => import_ai4.jsonSchema,
|
|
37
39
|
silentLogger: () => silentLogger,
|
|
38
40
|
tool: () => tool
|
|
@@ -73,7 +75,6 @@ function defineAgent(options) {
|
|
|
73
75
|
model: options.model ?? DEFAULT_MODEL,
|
|
74
76
|
systemPrompt: options.systemPrompt ?? "",
|
|
75
77
|
tools: Object.freeze([...tools]),
|
|
76
|
-
mode: options.mode ?? "task",
|
|
77
78
|
checkpointPolicy: options.checkpointPolicy ?? "on_tool_call",
|
|
78
79
|
contextStrategy: options.contextStrategy ?? "sliding_window",
|
|
79
80
|
contextWindow: options.contextWindow ?? 20,
|
|
@@ -88,7 +89,6 @@ function defineAgent(options) {
|
|
|
88
89
|
}
|
|
89
90
|
function agentBody(agent) {
|
|
90
91
|
const modelConfig = {
|
|
91
|
-
mode: agent.mode,
|
|
92
92
|
checkpoint_policy: agent.checkpointPolicy,
|
|
93
93
|
context_strategy: agent.contextStrategy,
|
|
94
94
|
context_window: agent.contextWindow,
|
|
@@ -245,6 +245,12 @@ var GardDestroyedError = class extends NornsError {
|
|
|
245
245
|
this.name = "GardDestroyedError";
|
|
246
246
|
}
|
|
247
247
|
};
|
|
248
|
+
var KeyRevokedError = class extends NornsError {
|
|
249
|
+
constructor() {
|
|
250
|
+
super("the worker's scoped key was revoked");
|
|
251
|
+
this.name = "KeyRevokedError";
|
|
252
|
+
}
|
|
253
|
+
};
|
|
248
254
|
var StreamClosedError = class extends NornsError {
|
|
249
255
|
reason;
|
|
250
256
|
constructor(reason) {
|
|
@@ -573,6 +579,9 @@ function resolveApiKey(apiKey) {
|
|
|
573
579
|
if (!value) throw new NornsError("Norns API key missing: pass `apiKey` or set NORNS_API_KEY");
|
|
574
580
|
return value;
|
|
575
581
|
}
|
|
582
|
+
function isScopedKey(apiKey) {
|
|
583
|
+
return apiKey.startsWith("nrnw_");
|
|
584
|
+
}
|
|
576
585
|
function wsBase(url) {
|
|
577
586
|
return url.replace(/^http:\/\//, "ws://").replace(/^https:\/\//, "wss://");
|
|
578
587
|
}
|
|
@@ -1283,9 +1292,15 @@ var NornsWorker = class {
|
|
|
1283
1292
|
return this.#starting;
|
|
1284
1293
|
}
|
|
1285
1294
|
async #start() {
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1295
|
+
if (isScopedKey(this.#apiKey)) {
|
|
1296
|
+
this.#logger.info(
|
|
1297
|
+
"Worker key is scoped (nrnw_): skipping agent registration. Register the agent definitions with a tenant key."
|
|
1298
|
+
);
|
|
1299
|
+
} else {
|
|
1300
|
+
for (const agent of this.#agents) {
|
|
1301
|
+
const info = await this.#client.agents.ensure(agent);
|
|
1302
|
+
this.#logger.info(`Registered agent '${agent.name}' (id=${info.id})`);
|
|
1303
|
+
}
|
|
1289
1304
|
}
|
|
1290
1305
|
if (this.#capabilities.includes("llm")) {
|
|
1291
1306
|
for (const model of new Set(this.#agents.map((a) => a.model))) {
|
|
@@ -1336,6 +1351,10 @@ var NornsWorker = class {
|
|
|
1336
1351
|
this.#logger.error("This worker's gard was destroyed; shutting down");
|
|
1337
1352
|
this.#fail(new GardDestroyedError(this.gard));
|
|
1338
1353
|
});
|
|
1354
|
+
channel.on("key_revoked", () => {
|
|
1355
|
+
this.#logger.error("This worker's key was revoked; shutting down");
|
|
1356
|
+
this.#fail(new KeyRevokedError());
|
|
1357
|
+
});
|
|
1339
1358
|
channel.onError((reason) => {
|
|
1340
1359
|
if (this.#state === "running")
|
|
1341
1360
|
this.#logger.warn(`Channel error (${errorMessage(reason)}); rejoining`);
|
|
@@ -1649,6 +1668,7 @@ var NornsWorker = class {
|
|
|
1649
1668
|
DEFAULT_MODEL,
|
|
1650
1669
|
GardDestroyedError,
|
|
1651
1670
|
JoinError,
|
|
1671
|
+
KeyRevokedError,
|
|
1652
1672
|
NornsApiError,
|
|
1653
1673
|
NornsClient,
|
|
1654
1674
|
NornsError,
|
|
@@ -1659,6 +1679,7 @@ var NornsWorker = class {
|
|
|
1659
1679
|
consoleLogger,
|
|
1660
1680
|
defineAgent,
|
|
1661
1681
|
inferProvider,
|
|
1682
|
+
isScopedKey,
|
|
1662
1683
|
jsonSchema,
|
|
1663
1684
|
silentLogger,
|
|
1664
1685
|
tool
|