norns-sdk 0.1.0 → 0.2.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 +10 -0
- package/dist/index.cjs +62 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +62 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `norns-sdk` are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.2.0] - 2026-10-16
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- The worker joins with `features: ["message_cache"]` and keeps the message
|
|
9
|
+
list Norns last sent it per run, so Norns can send later steps as
|
|
10
|
+
`messages_delta` (the change) instead of the whole history. A delta on a
|
|
11
|
+
base the worker no longer holds is answered with `message_cache_miss` and
|
|
12
|
+
Norns resends in full. Older Norns ignores the feature and sends the full
|
|
13
|
+
list as before.
|
|
14
|
+
|
|
5
15
|
## [0.1.0] - 2026-10-15
|
|
6
16
|
|
|
7
17
|
### Added
|
package/dist/index.cjs
CHANGED
|
@@ -1149,6 +1149,51 @@ function neutralUsage(usage) {
|
|
|
1149
1149
|
return out;
|
|
1150
1150
|
}
|
|
1151
1151
|
|
|
1152
|
+
// src/history-cache.ts
|
|
1153
|
+
var HistoryCache = class {
|
|
1154
|
+
#runs = /* @__PURE__ */ new Map();
|
|
1155
|
+
#maxRuns;
|
|
1156
|
+
constructor(maxRuns = 256) {
|
|
1157
|
+
this.#maxRuns = maxRuns;
|
|
1158
|
+
}
|
|
1159
|
+
/** The task with `messages` filled in, or `undefined` on a miss. */
|
|
1160
|
+
resolve(task) {
|
|
1161
|
+
if (task.purpose === "compact") return task;
|
|
1162
|
+
const runId = task.run_id;
|
|
1163
|
+
const delta = task.messages_delta;
|
|
1164
|
+
if (delta === void 0) {
|
|
1165
|
+
if (runId !== void 0 && Array.isArray(task.messages)) this.#remember(runId, task.messages);
|
|
1166
|
+
return task;
|
|
1167
|
+
}
|
|
1168
|
+
const previous = runId === void 0 ? void 0 : this.#runs.get(runId);
|
|
1169
|
+
if (runId === void 0 || previous === void 0 || previous.length !== delta.base_count) {
|
|
1170
|
+
return void 0;
|
|
1171
|
+
}
|
|
1172
|
+
const messages = [...previous.slice(delta.drop), ...delta.append];
|
|
1173
|
+
this.#remember(runId, messages);
|
|
1174
|
+
const resolved = { ...task, messages };
|
|
1175
|
+
delete resolved.messages_delta;
|
|
1176
|
+
return resolved;
|
|
1177
|
+
}
|
|
1178
|
+
/** Forget everything: a new connection gets the full history anyway. */
|
|
1179
|
+
clear() {
|
|
1180
|
+
this.#runs.clear();
|
|
1181
|
+
}
|
|
1182
|
+
/** How many runs are held; for tests. */
|
|
1183
|
+
get size() {
|
|
1184
|
+
return this.#runs.size;
|
|
1185
|
+
}
|
|
1186
|
+
#remember(runId, messages) {
|
|
1187
|
+
this.#runs.delete(runId);
|
|
1188
|
+
this.#runs.set(runId, messages);
|
|
1189
|
+
while (this.#runs.size > this.#maxRuns) {
|
|
1190
|
+
const oldest = this.#runs.keys().next().value;
|
|
1191
|
+
if (oldest === void 0) break;
|
|
1192
|
+
this.#runs.delete(oldest);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
|
|
1152
1197
|
// src/worker.ts
|
|
1153
1198
|
var TOPIC = "worker:lobby";
|
|
1154
1199
|
var NornsWorker = class {
|
|
@@ -1169,6 +1214,7 @@ var NornsWorker = class {
|
|
|
1169
1214
|
#client;
|
|
1170
1215
|
#resolveModel;
|
|
1171
1216
|
#inFlight = /* @__PURE__ */ new Set();
|
|
1217
|
+
#history = new HistoryCache();
|
|
1172
1218
|
#state = "idle";
|
|
1173
1219
|
#socket;
|
|
1174
1220
|
#channel;
|
|
@@ -1261,7 +1307,10 @@ var NornsWorker = class {
|
|
|
1261
1307
|
...this.#socketOptions
|
|
1262
1308
|
});
|
|
1263
1309
|
this.#socket = socket;
|
|
1264
|
-
socket.onOpen(() =>
|
|
1310
|
+
socket.onOpen(() => {
|
|
1311
|
+
this.#logger.info(`Connected to ${this.url}`);
|
|
1312
|
+
this.#history.clear();
|
|
1313
|
+
});
|
|
1265
1314
|
socket.onError((err) => {
|
|
1266
1315
|
if (this.#state === "starting" || this.#state === "running") {
|
|
1267
1316
|
this.#logger.warn(`Connection error (${errorMessage(err)}); retrying`);
|
|
@@ -1320,7 +1369,10 @@ var NornsWorker = class {
|
|
|
1320
1369
|
const params = {
|
|
1321
1370
|
worker_id: this.workerId,
|
|
1322
1371
|
tools: [...this.#tools.values()].map(toolRegistration),
|
|
1323
|
-
capabilities: this.#capabilities
|
|
1372
|
+
capabilities: this.#capabilities,
|
|
1373
|
+
// This worker keeps the history it was last sent per run, so Norns may
|
|
1374
|
+
// send later steps as the change only (HistoryCache).
|
|
1375
|
+
features: ["message_cache"]
|
|
1324
1376
|
};
|
|
1325
1377
|
if (this.gard !== void 0) {
|
|
1326
1378
|
params.gard = this.gard;
|
|
@@ -1449,7 +1501,14 @@ var NornsWorker = class {
|
|
|
1449
1501
|
(resp) => this.#logger.warn(`Server rejected result for ${taskId}: ${errorMessage(resp)}`)
|
|
1450
1502
|
);
|
|
1451
1503
|
}
|
|
1452
|
-
async #runLlm(
|
|
1504
|
+
async #runLlm(received, signal) {
|
|
1505
|
+
const task = this.#history.resolve(received);
|
|
1506
|
+
if (task === void 0) {
|
|
1507
|
+
this.#logger.info(
|
|
1508
|
+
"LLM task arrived as a delta on an unknown base; asking for the full history"
|
|
1509
|
+
);
|
|
1510
|
+
return { status: "error", error: "message_cache_miss" };
|
|
1511
|
+
}
|
|
1453
1512
|
const model = task.model ?? "?";
|
|
1454
1513
|
const tools = task.tools ?? [];
|
|
1455
1514
|
this.#logger.info(
|