@dashup/connector 0.1.7 → 0.1.8
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/index.js +62 -22
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -4017,7 +4017,7 @@ import * as ui from "@clack/prompts";
|
|
|
4017
4017
|
import { z } from "zod";
|
|
4018
4018
|
|
|
4019
4019
|
// package.json
|
|
4020
|
-
var version = "0.1.
|
|
4020
|
+
var version = "0.1.8";
|
|
4021
4021
|
|
|
4022
4022
|
// src/pair.ts
|
|
4023
4023
|
var Invitation = z.object({
|
|
@@ -4425,6 +4425,11 @@ import { join as join2, dirname as dirname2, resolve as resolve2, isAbsolute } f
|
|
|
4425
4425
|
import { closeSync as closeSync2, existsSync as existsSync3, openSync as openSync2, readSync, realpathSync, readdirSync, statSync } from "node:fs";
|
|
4426
4426
|
|
|
4427
4427
|
// src/harness/session.ts
|
|
4428
|
+
var EARLIER = {
|
|
4429
|
+
id: "earlier",
|
|
4430
|
+
role: "system",
|
|
4431
|
+
text: "Earlier messages stay on your computer."
|
|
4432
|
+
};
|
|
4428
4433
|
var sessionKey = (session) => `${session.harness}\0${session.id}`;
|
|
4429
4434
|
function agentHarness(name) {
|
|
4430
4435
|
if (/claude/i.test(name)) return "claude";
|
|
@@ -4439,6 +4444,8 @@ var SCREEN_PREVIEW = "Open Screen to review the full request before approving.";
|
|
|
4439
4444
|
var SAMPLE_BYTES = 128 * 1024;
|
|
4440
4445
|
var READ_BYTES = 64 * 1024;
|
|
4441
4446
|
var TITLE_LIMIT = 120;
|
|
4447
|
+
var LATEST_BYTES = 8 * 1024 * 1024;
|
|
4448
|
+
var JOURNALS = 16;
|
|
4442
4449
|
var journals = /* @__PURE__ */ new Map();
|
|
4443
4450
|
var metadata = /* @__PURE__ */ new Map();
|
|
4444
4451
|
function object(value2) {
|
|
@@ -4505,33 +4512,42 @@ function sample(path, until) {
|
|
|
4505
4512
|
metadata.set(path, { stamp, rows });
|
|
4506
4513
|
return rows;
|
|
4507
4514
|
}
|
|
4508
|
-
|
|
4515
|
+
var windowed = (path, messages5) => journals.get(path)?.start ? [EARLIER, ...messages5] : messages5;
|
|
4516
|
+
function journal(path, latest = false) {
|
|
4509
4517
|
const stamp = statSync(path);
|
|
4510
4518
|
let saved = journals.get(path);
|
|
4511
4519
|
if (saved && unchanged(saved.stamp, stamp)) {
|
|
4520
|
+
journals.delete(path);
|
|
4521
|
+
journals.set(path, saved);
|
|
4512
4522
|
const tail2 = parse(saved.tail.toString("utf8"));
|
|
4513
4523
|
return tail2 ? [...saved.rows, tail2] : saved.rows;
|
|
4514
4524
|
}
|
|
4515
|
-
if (!saved || saved.stamp.ino !== stamp.ino || stamp.size <= saved.offset)
|
|
4516
|
-
|
|
4525
|
+
if (!saved || saved.stamp.ino !== stamp.ino || stamp.size <= saved.offset || latest && stamp.size - saved.start > 2 * LATEST_BYTES) {
|
|
4526
|
+
const start = latest ? Math.max(0, stamp.size - LATEST_BYTES) : 0;
|
|
4527
|
+
saved = { stamp, start, offset: start, tail: Buffer.alloc(0), rows: [] };
|
|
4528
|
+
}
|
|
4517
4529
|
while (saved.offset < stamp.size) {
|
|
4518
4530
|
const chunk = readRange(path, saved.offset, Math.min(READ_BYTES, stamp.size - saved.offset));
|
|
4519
4531
|
if (!chunk.length) break;
|
|
4532
|
+
const first = saved.offset === saved.start && saved.start > 0;
|
|
4520
4533
|
saved.offset += chunk.length;
|
|
4521
4534
|
const buffer = Buffer.concat([saved.tail, chunk]);
|
|
4522
4535
|
const end = buffer.lastIndexOf(10);
|
|
4523
4536
|
if (end < 0) {
|
|
4524
|
-
saved.tail = buffer;
|
|
4537
|
+
saved.tail = first ? Buffer.alloc(0) : buffer;
|
|
4525
4538
|
continue;
|
|
4526
4539
|
}
|
|
4527
|
-
|
|
4540
|
+
const lines = buffer.subarray(0, end).toString("utf8").split("\n");
|
|
4541
|
+
for (const line of first ? lines.slice(1) : lines) {
|
|
4528
4542
|
const row = parse(line);
|
|
4529
4543
|
if (row) saved.rows.push(row);
|
|
4530
4544
|
}
|
|
4531
4545
|
saved.tail = Buffer.from(buffer.subarray(end + 1));
|
|
4532
4546
|
}
|
|
4533
4547
|
saved.stamp = stamp;
|
|
4548
|
+
journals.delete(path);
|
|
4534
4549
|
journals.set(path, saved);
|
|
4550
|
+
if (journals.size > JOURNALS) journals.delete(journals.keys().next().value);
|
|
4535
4551
|
const tail = parse(saved.tail.toString("utf8"));
|
|
4536
4552
|
return tail ? [...saved.rows, tail] : saved.rows;
|
|
4537
4553
|
}
|
|
@@ -4659,7 +4675,7 @@ function claudeChange(change2) {
|
|
|
4659
4675
|
].join("\n");
|
|
4660
4676
|
}
|
|
4661
4677
|
function claudeMessages(path) {
|
|
4662
|
-
const rows = journal(path);
|
|
4678
|
+
const rows = journal(path, true);
|
|
4663
4679
|
const chain = /* @__PURE__ */ new Map();
|
|
4664
4680
|
let leaf;
|
|
4665
4681
|
for (const row of rows) {
|
|
@@ -4679,6 +4695,9 @@ function claudeMessages(path) {
|
|
|
4679
4695
|
leaf = typeof row.parentUuid === "string" ? row.parentUuid : void 0;
|
|
4680
4696
|
}
|
|
4681
4697
|
const conversation = selected.length ? selected.reverse() : rows;
|
|
4698
|
+
return windowed(path, claudeConversation(conversation, rows));
|
|
4699
|
+
}
|
|
4700
|
+
function claudeConversation(conversation, rows) {
|
|
4682
4701
|
const results = /* @__PURE__ */ new Map();
|
|
4683
4702
|
for (const row of rows)
|
|
4684
4703
|
for (const part of row.type === "user" ? list(row.message?.content) : [])
|
|
@@ -4759,7 +4778,7 @@ function applyPatch(patch) {
|
|
|
4759
4778
|
).replace(/^\*\*\* .*\n?/gm, "");
|
|
4760
4779
|
}
|
|
4761
4780
|
function codexMessages(path) {
|
|
4762
|
-
const rows = journal(path);
|
|
4781
|
+
const rows = journal(path, true);
|
|
4763
4782
|
const outputs = /* @__PURE__ */ new Map();
|
|
4764
4783
|
for (const row of rows)
|
|
4765
4784
|
if (["function_call_output", "custom_tool_call_output"].includes(row.payload?.type))
|
|
@@ -4788,8 +4807,8 @@ function codexMessages(path) {
|
|
|
4788
4807
|
)
|
|
4789
4808
|
];
|
|
4790
4809
|
});
|
|
4791
|
-
if (result.length) return result;
|
|
4792
|
-
return rows.flatMap((row, index) => {
|
|
4810
|
+
if (result.length) return windowed(path, result);
|
|
4811
|
+
return windowed(path, rows.flatMap((row, index) => {
|
|
4793
4812
|
if (row.type !== "event_msg") return [];
|
|
4794
4813
|
const item = object(row.payload);
|
|
4795
4814
|
if (!item || !["user_message", "agent_message"].includes(item.type)) return [];
|
|
@@ -4798,7 +4817,7 @@ function codexMessages(path) {
|
|
|
4798
4817
|
item.type === "user_message" ? "user" : "assistant",
|
|
4799
4818
|
item.message
|
|
4800
4819
|
);
|
|
4801
|
-
});
|
|
4820
|
+
}));
|
|
4802
4821
|
}
|
|
4803
4822
|
function codex(root, scan) {
|
|
4804
4823
|
const index = join2(root, "session_index.jsonl");
|
|
@@ -5141,11 +5160,15 @@ var Discovery = class {
|
|
|
5141
5160
|
secret;
|
|
5142
5161
|
projects = /* @__PURE__ */ new Map();
|
|
5143
5162
|
locations = /* @__PURE__ */ new Map();
|
|
5163
|
+
// Each native agent session's thread, so finding it costs the same however many sessions a scan
|
|
5164
|
+
// sees. The first project to list a thread keeps it.
|
|
5165
|
+
agents = /* @__PURE__ */ new Map();
|
|
5144
5166
|
paths = /* @__PURE__ */ new Set();
|
|
5145
5167
|
warnings = [];
|
|
5146
5168
|
scan() {
|
|
5147
5169
|
this.projects.clear();
|
|
5148
5170
|
this.locations.clear();
|
|
5171
|
+
this.agents.clear();
|
|
5149
5172
|
this.paths.clear();
|
|
5150
5173
|
this.warnings.length = 0;
|
|
5151
5174
|
const defaults = dataPaths();
|
|
@@ -5160,12 +5183,8 @@ var Discovery = class {
|
|
|
5160
5183
|
return [...this.projects.values()];
|
|
5161
5184
|
}
|
|
5162
5185
|
native(session) {
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
(item) => item.agent?.harness === session.harness && item.agent.sessionId === session.id
|
|
5166
|
-
);
|
|
5167
|
-
if (thread2) return { project: project2, thread: thread2 };
|
|
5168
|
-
}
|
|
5186
|
+
const known = this.agents.get(`${session.harness}\0${session.id}`);
|
|
5187
|
+
if (known) return known;
|
|
5169
5188
|
const project = this.project(session.cwd);
|
|
5170
5189
|
const thread = {
|
|
5171
5190
|
id: agentThread(session.harness, session.id, this.secret),
|
|
@@ -5178,6 +5197,7 @@ var Discovery = class {
|
|
|
5178
5197
|
};
|
|
5179
5198
|
project.threads.push(thread);
|
|
5180
5199
|
this.locations.set(thread.id, { editor: "cli", path: "" });
|
|
5200
|
+
this.agents.set(`${session.harness}\0${session.id}`, { project, thread });
|
|
5181
5201
|
return { project, thread };
|
|
5182
5202
|
}
|
|
5183
5203
|
// The native history owns the conversation's last message time, whichever editor lists it.
|
|
@@ -5300,8 +5320,8 @@ var Discovery = class {
|
|
|
5300
5320
|
...ssh.port ? { port: Number(ssh.port) } : {}
|
|
5301
5321
|
} : void 0;
|
|
5302
5322
|
const project = this.project(folder, remote);
|
|
5303
|
-
if (!project.threads.some((thread) => thread.id === id))
|
|
5304
|
-
|
|
5323
|
+
if (!project.threads.some((thread) => thread.id === id)) {
|
|
5324
|
+
const thread = {
|
|
5305
5325
|
id,
|
|
5306
5326
|
title: row.title_override || row.title,
|
|
5307
5327
|
editor: "zed",
|
|
@@ -5309,7 +5329,11 @@ var Discovery = class {
|
|
|
5309
5329
|
updatedAt,
|
|
5310
5330
|
capabilities: this.capabilities,
|
|
5311
5331
|
...harness ? { agent: { harness, sessionId: session } } : {}
|
|
5312
|
-
}
|
|
5332
|
+
};
|
|
5333
|
+
project.threads.push(thread);
|
|
5334
|
+
if (harness && !this.agents.has(`${harness}\0${session}`))
|
|
5335
|
+
this.agents.set(`${harness}\0${session}`, { project, thread });
|
|
5336
|
+
}
|
|
5313
5337
|
this.locations.set(id, { editor: "zed", path: store, session });
|
|
5314
5338
|
}
|
|
5315
5339
|
}
|
|
@@ -16385,6 +16409,7 @@ function sealHistory(key, routing, message, random) {
|
|
|
16385
16409
|
|
|
16386
16410
|
// src/history.ts
|
|
16387
16411
|
var HISTORY_PATH = "/dashup/history";
|
|
16412
|
+
var HISTORY_KEPT = 300;
|
|
16388
16413
|
async function upload(config2, batch) {
|
|
16389
16414
|
if (batch.records.length > HISTORY_BATCH_ITEMS || Buffer.byteLength(JSON.stringify(batch)) > HISTORY_BATCH_BYTES)
|
|
16390
16415
|
throw new Error("The encrypted history upload exceeds the batch limit");
|
|
@@ -16400,7 +16425,14 @@ async function publishHistory(config2, pair, project, thread, messages5) {
|
|
|
16400
16425
|
const generation = ++local.sequence;
|
|
16401
16426
|
saveConfig(config2);
|
|
16402
16427
|
const opaque = (value2) => createHmac2("sha256", Buffer.from(local.key, "hex")).update(JSON.stringify(value2)).digest("hex");
|
|
16403
|
-
const
|
|
16428
|
+
const named = (id) => opaque(["history-message", project, thread.id, id]);
|
|
16429
|
+
const all = splitHistoryMessages(messages5, named);
|
|
16430
|
+
let start = Math.max(0, all.length - HISTORY_KEPT);
|
|
16431
|
+
while (start < all.length && (all[start].part ?? 0) > 0) start++;
|
|
16432
|
+
const fragments = start ? [
|
|
16433
|
+
...splitHistoryMessages([EARLIER], named),
|
|
16434
|
+
...all.slice(start)
|
|
16435
|
+
] : all;
|
|
16404
16436
|
const summary = { generation, total: fragments.length, updatedAt: thread.updatedAt };
|
|
16405
16437
|
const batch = {
|
|
16406
16438
|
pairing: pair.id,
|
|
@@ -18800,6 +18832,7 @@ var Connector = class {
|
|
|
18800
18832
|
listed = /* @__PURE__ */ new Map();
|
|
18801
18833
|
listedProjects = /* @__PURE__ */ new Map();
|
|
18802
18834
|
overviewQueued = false;
|
|
18835
|
+
pendingChange;
|
|
18803
18836
|
// The agents that can start sessions here.
|
|
18804
18837
|
startable = [];
|
|
18805
18838
|
snapshots = /* @__PURE__ */ new Set();
|
|
@@ -19062,8 +19095,15 @@ var Connector = class {
|
|
|
19062
19095
|
for (const pair of this.activePairs()) await this.listProjects(pair);
|
|
19063
19096
|
}).catch((error) => this.report(error));
|
|
19064
19097
|
}
|
|
19098
|
+
// A change still waiting to start covers every event after it, so a burst of writes to a
|
|
19099
|
+
// transcript costs one rescan rather than one each.
|
|
19065
19100
|
queueChange() {
|
|
19066
|
-
|
|
19101
|
+
if (this.pendingChange) return this.pendingChange;
|
|
19102
|
+
const run5 = this.work.then(() => {
|
|
19103
|
+
this.pendingChange = void 0;
|
|
19104
|
+
return this.changed();
|
|
19105
|
+
});
|
|
19106
|
+
this.pendingChange = run5;
|
|
19067
19107
|
this.work = run5.catch((error) => this.report(error));
|
|
19068
19108
|
return run5;
|
|
19069
19109
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dashup/connector",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dashup": "dist/index.js"
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"tsup": "^8.5.1",
|
|
30
30
|
"tsx": "^4.22.4",
|
|
31
31
|
"typescript": "^5.9.3",
|
|
32
|
-
"@dashup/typescript-config": "0.0.0",
|
|
33
32
|
"@dashup/models": "0.1.0",
|
|
33
|
+
"@dashup/protocol": "0.1.0",
|
|
34
|
+
"@dashup/typescript-config": "0.0.0",
|
|
34
35
|
"@parcae/lynx": "0.1.0",
|
|
35
|
-
"@parcae/sdk": "0.8.1"
|
|
36
|
-
"@dashup/protocol": "0.1.0"
|
|
36
|
+
"@parcae/sdk": "0.8.1"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"dashup": "tsx src/index.ts",
|