@dashup/connector 0.1.10 → 0.1.11
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 +117 -45
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2728,6 +2728,7 @@ var PROTOCOL_VERSION = 1;
|
|
|
2728
2728
|
var MAX_ENVELOPE_BYTES = 8 * 1024 * 1024;
|
|
2729
2729
|
var HISTORY_PAGE_ITEMS = 30;
|
|
2730
2730
|
var HISTORY_TEXT_CHARS = 4e3;
|
|
2731
|
+
var HISTORY_TOOL_CHARS = 500;
|
|
2731
2732
|
var HISTORY_PAGE_BYTES = 256 * 1024;
|
|
2732
2733
|
var HISTORY_BATCH_ITEMS = 50;
|
|
2733
2734
|
var HISTORY_BATCH_BYTES = HISTORY_PAGE_BYTES;
|
|
@@ -4045,7 +4046,7 @@ import * as ui from "@clack/prompts";
|
|
|
4045
4046
|
import { z } from "zod";
|
|
4046
4047
|
|
|
4047
4048
|
// package.json
|
|
4048
|
-
var version = "0.1.
|
|
4049
|
+
var version = "0.1.11";
|
|
4049
4050
|
|
|
4050
4051
|
// src/pair.ts
|
|
4051
4052
|
var Invitation = z.object({
|
|
@@ -4390,7 +4391,6 @@ function prose(id, role, content) {
|
|
|
4390
4391
|
const files2 = attachments(id, content);
|
|
4391
4392
|
return value2 || files2.length ? [{ id, role, text: value2, ...files2.length ? { attachments: files2 } : {} }] : [];
|
|
4392
4393
|
}
|
|
4393
|
-
var SUMMARY_LIMIT = 200;
|
|
4394
4394
|
var SUMMARY_FIELDS = [
|
|
4395
4395
|
"command",
|
|
4396
4396
|
"cmd",
|
|
@@ -4412,8 +4412,12 @@ function describe(input) {
|
|
|
4412
4412
|
);
|
|
4413
4413
|
const value2 = typeof input === "string" ? input : named2 ?? (fields && Object.keys(fields).length ? JSON.stringify(fields) : "");
|
|
4414
4414
|
const paths = [...value2.matchAll(PATCH_FILE)].map((match) => match[2]).join(", ");
|
|
4415
|
-
|
|
4416
|
-
|
|
4415
|
+
return (paths || value2.trim()).slice(0, HISTORY_TOOL_CHARS) || void 0;
|
|
4416
|
+
}
|
|
4417
|
+
function said(input, summary) {
|
|
4418
|
+
const value2 = object(input)?.description;
|
|
4419
|
+
const line = typeof value2 === "string" ? value2.trim().split("\n")[0] : "";
|
|
4420
|
+
return line && line !== summary ? line.slice(0, HISTORY_TOOL_CHARS) : void 0;
|
|
4417
4421
|
}
|
|
4418
4422
|
function elapsed(start, end) {
|
|
4419
4423
|
const ms = instant(end) - instant(start);
|
|
@@ -4429,18 +4433,22 @@ function added(path, content) {
|
|
|
4429
4433
|
].join("\n");
|
|
4430
4434
|
}
|
|
4431
4435
|
var binary = (diff) => diff.slice(0, 8e3).includes("\0");
|
|
4432
|
-
function step(id, name, input, result) {
|
|
4436
|
+
function step(id, name, input, result, started) {
|
|
4433
4437
|
const summary = describe(input);
|
|
4438
|
+
const label = said(input, summary);
|
|
4439
|
+
const at = instant(started);
|
|
4434
4440
|
const diff = result?.status === "ok" && result.diff && !binary(result.diff) ? result.diff : void 0;
|
|
4435
4441
|
return {
|
|
4436
4442
|
id,
|
|
4437
4443
|
role: "tool",
|
|
4438
4444
|
text: diff || result?.text || "",
|
|
4439
4445
|
tool: {
|
|
4440
|
-
name: typeof name === "string" && name ? name.slice(0,
|
|
4446
|
+
name: typeof name === "string" && name ? name.slice(0, HISTORY_TOOL_CHARS) : "Tool",
|
|
4447
|
+
...label ? { label } : {},
|
|
4441
4448
|
...summary ? { summary } : {},
|
|
4442
4449
|
...result?.status ? { status: result.status } : {},
|
|
4443
4450
|
...result?.status && result.ms !== void 0 ? { ms: result.ms } : {},
|
|
4451
|
+
...!result?.status && Number.isFinite(at) ? { at: new Date(at).toISOString() } : {},
|
|
4444
4452
|
...diff ? { diff: true } : {}
|
|
4445
4453
|
},
|
|
4446
4454
|
...result?.attachments?.length ? { attachments: result.attachments } : {}
|
|
@@ -4511,7 +4519,8 @@ function claudeConversation(conversation, rows) {
|
|
|
4511
4519
|
ms: elapsed(row.timestamp, result.row.timestamp),
|
|
4512
4520
|
diff: claudeChange(object(result.row.toolUseResult)),
|
|
4513
4521
|
attachments: attachments(call, result.part.content)
|
|
4514
|
-
}
|
|
4522
|
+
},
|
|
4523
|
+
row.timestamp
|
|
4515
4524
|
)
|
|
4516
4525
|
];
|
|
4517
4526
|
})
|
|
@@ -4600,7 +4609,8 @@ function codexMessages(path) {
|
|
|
4600
4609
|
ms: elapsed(row.timestamp, output.timestamp),
|
|
4601
4610
|
diff: patch && applyPatch(patch),
|
|
4602
4611
|
attachments: attachments(call, output.payload.output)
|
|
4603
|
-
}
|
|
4612
|
+
},
|
|
4613
|
+
row.timestamp
|
|
4604
4614
|
)
|
|
4605
4615
|
];
|
|
4606
4616
|
});
|
|
@@ -4699,7 +4709,8 @@ function openCodeParts(id, role, parts2) {
|
|
|
4699
4709
|
ms: elapsed(state.time?.start, state.time?.end),
|
|
4700
4710
|
diff: openCodeChange(state),
|
|
4701
4711
|
attachments: attachments(key, state.attachments)
|
|
4702
|
-
}
|
|
4712
|
+
},
|
|
4713
|
+
state.time?.start
|
|
4703
4714
|
)
|
|
4704
4715
|
];
|
|
4705
4716
|
});
|
|
@@ -5060,6 +5071,7 @@ var Discovery = class {
|
|
|
5060
5071
|
read: true,
|
|
5061
5072
|
send: Boolean(session.send),
|
|
5062
5073
|
stop: Boolean(session.stop),
|
|
5074
|
+
now: Boolean(session.now),
|
|
5063
5075
|
approve: Boolean(session.approve)
|
|
5064
5076
|
}
|
|
5065
5077
|
});
|
|
@@ -16172,12 +16184,13 @@ var ID = /^[a-f0-9]{64}$/;
|
|
|
16172
16184
|
var ROLES = new Set(MESSAGE_ROLES);
|
|
16173
16185
|
var ROUTING_FIELDS = ["pairing", "sender", "recipient", "project", "thread"];
|
|
16174
16186
|
var MIME = /^[\w.+-]{1,64}\/[\w.+-]{1,64}$/;
|
|
16175
|
-
var TOOL_TEXT = 500;
|
|
16176
16187
|
function validAttachment(value2) {
|
|
16177
16188
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && typeof value2.id === "string" && ID.test(value2.id) && typeof value2.mime === "string" && MIME.test(value2.mime) && Number.isSafeInteger(value2.bytes) && value2.bytes >= 0 && (value2.name === void 0 || typeof value2.name === "string" && value2.name.length <= ATTACHMENT_NAME_CHARS);
|
|
16178
16189
|
}
|
|
16179
16190
|
function validTool(value2) {
|
|
16180
|
-
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && typeof value2.name === "string" && value2.name.length <=
|
|
16191
|
+
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && typeof value2.name === "string" && value2.name.length <= HISTORY_TOOL_CHARS && [value2.label, value2.summary].every(
|
|
16192
|
+
(text3) => text3 === void 0 || typeof text3 === "string" && text3.length <= HISTORY_TOOL_CHARS
|
|
16193
|
+
) && (value2.at === void 0 || typeof value2.at === "string" && !Number.isNaN(Date.parse(value2.at))) && (value2.status === void 0 || value2.status === "ok" || value2.status === "error") && (value2.ms === void 0 || Number.isSafeInteger(value2.ms) && value2.ms >= 0) && (value2.diff === void 0 || typeof value2.diff === "boolean");
|
|
16181
16194
|
}
|
|
16182
16195
|
function validMessage(value2) {
|
|
16183
16196
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && typeof value2.id === "string" && ID.test(value2.id) && ROLES.has(value2.role) && typeof value2.text === "string" && value2.text.length <= HISTORY_TEXT_CHARS && Number.isSafeInteger(value2.part) && Number.isSafeInteger(value2.parts) && value2.part >= 0 && value2.parts > value2.part && (value2.tool === void 0 || value2.part === 0 && validTool(value2.tool)) && (value2.full === void 0 || value2.part === 0 && validAttachment(value2.full)) && (value2.attachments === void 0 || value2.part === 0 && Array.isArray(value2.attachments) && value2.attachments.length <= HISTORY_ATTACHMENTS && value2.attachments.every(validAttachment));
|
|
@@ -16494,6 +16507,8 @@ var Client = class {
|
|
|
16494
16507
|
pending = /* @__PURE__ */ new Map();
|
|
16495
16508
|
approvals = /* @__PURE__ */ new Map();
|
|
16496
16509
|
requests = /* @__PURE__ */ new Map();
|
|
16510
|
+
// The reply each thread is writing, as far as it has streamed, and the item it belongs to.
|
|
16511
|
+
typing = /* @__PURE__ */ new Map();
|
|
16497
16512
|
async connect() {
|
|
16498
16513
|
if (this.socket?.readyState === WebSocket2.OPEN) return;
|
|
16499
16514
|
if (this.connecting) return this.connecting;
|
|
@@ -16528,13 +16543,20 @@ var Client = class {
|
|
|
16528
16543
|
return;
|
|
16529
16544
|
}
|
|
16530
16545
|
if (typeof message.method !== "string") return;
|
|
16546
|
+
const params = message.params;
|
|
16547
|
+
if (message.method === "item/agentMessage/delta" && typeof params?.threadId === "string" && typeof params.delta === "string") {
|
|
16548
|
+
const known = this.typing.get(params.threadId);
|
|
16549
|
+
this.typing.set(params.threadId, {
|
|
16550
|
+
item: params.itemId,
|
|
16551
|
+
text: (known && known.item === params.itemId ? known.text : "") + params.delta
|
|
16552
|
+
});
|
|
16553
|
+
}
|
|
16531
16554
|
if (message.method === "serverRequest/resolved") {
|
|
16532
16555
|
for (const [id, pending] of this.approvals)
|
|
16533
16556
|
if (pending.requestId === message.params?.requestId) this.approvals.delete(id);
|
|
16534
16557
|
}
|
|
16535
16558
|
if ((message.method === "item/commandExecution/requestApproval" || message.method === "item/fileChange/requestApproval") && (typeof message.id === "string" || typeof message.id === "number") && typeof message.params?.threadId === "string") {
|
|
16536
16559
|
const id = randomUUID2();
|
|
16537
|
-
const params = message.params;
|
|
16538
16560
|
this.approvals.set(id, {
|
|
16539
16561
|
requestId: message.id,
|
|
16540
16562
|
threadId: params.threadId,
|
|
@@ -16644,6 +16666,7 @@ var Client = class {
|
|
|
16644
16666
|
updatedAt: new Date(Number(thread.updatedAt ?? 0) * 1e3).toISOString(),
|
|
16645
16667
|
status: approvals.length ? "attention" : status(thread),
|
|
16646
16668
|
messages: messages2(thread),
|
|
16669
|
+
typing: this.typing.get(id)?.text,
|
|
16647
16670
|
approvals,
|
|
16648
16671
|
// An interrupt for a finished turn is never answered, so the active turn is read first.
|
|
16649
16672
|
stop: this.controls ? (requestId) => this.once(requestId, async () => {
|
|
@@ -16851,12 +16874,21 @@ var Session = class {
|
|
|
16851
16874
|
turn;
|
|
16852
16875
|
// Messages written to this turn's process that Claude Code has not finished answering.
|
|
16853
16876
|
open = 0;
|
|
16877
|
+
// The text Claude Code is writing, as far as it has streamed.
|
|
16878
|
+
typing = "";
|
|
16854
16879
|
approvals = /* @__PURE__ */ new Map();
|
|
16855
16880
|
requests = /* @__PURE__ */ new Map();
|
|
16856
16881
|
write(value2) {
|
|
16857
16882
|
this.turn?.stdin.write(`${JSON.stringify(value2)}
|
|
16858
16883
|
`);
|
|
16859
16884
|
}
|
|
16885
|
+
interrupt() {
|
|
16886
|
+
this.write({
|
|
16887
|
+
type: "control_request",
|
|
16888
|
+
request_id: randomUUID3(),
|
|
16889
|
+
request: { subtype: "interrupt" }
|
|
16890
|
+
});
|
|
16891
|
+
}
|
|
16860
16892
|
once(id, action) {
|
|
16861
16893
|
const known = this.requests.get(id);
|
|
16862
16894
|
if (known) return known;
|
|
@@ -16866,13 +16898,16 @@ var Session = class {
|
|
|
16866
16898
|
this.requests.set(id, result);
|
|
16867
16899
|
return result;
|
|
16868
16900
|
}
|
|
16869
|
-
// Resolves once Claude Code takes the message, or says why it could not start.
|
|
16870
|
-
|
|
16901
|
+
// Resolves once Claude Code takes the message, or says why it could not start. `now` stops the
|
|
16902
|
+
// turn under way, so Claude Code takes the message at once.
|
|
16903
|
+
say(text3, now = false) {
|
|
16871
16904
|
this.messages.push({ id: randomUUID3(), role: "user", text: text3 });
|
|
16905
|
+
this.typing = "";
|
|
16872
16906
|
this.status = "working";
|
|
16873
16907
|
this.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
16874
16908
|
const message = { type: "user", message: { role: "user", content: text3 } };
|
|
16875
16909
|
if (this.turn) {
|
|
16910
|
+
if (now) this.interrupt();
|
|
16876
16911
|
this.open++;
|
|
16877
16912
|
this.write(message);
|
|
16878
16913
|
this.changed();
|
|
@@ -16887,6 +16922,7 @@ var Session = class {
|
|
|
16887
16922
|
"--output-format",
|
|
16888
16923
|
"stream-json",
|
|
16889
16924
|
"--verbose",
|
|
16925
|
+
"--include-partial-messages",
|
|
16890
16926
|
"--permission-prompt-tool",
|
|
16891
16927
|
"stdio",
|
|
16892
16928
|
...this.saved ? ["--resume", this.id] : ["--session-id", this.id]
|
|
@@ -16944,6 +16980,14 @@ var Session = class {
|
|
|
16944
16980
|
this.status = "attention";
|
|
16945
16981
|
} else if (message.type === "result") {
|
|
16946
16982
|
if (--this.open <= 0) this.turn?.stdin.end();
|
|
16983
|
+
} else if (message.type === "stream_event" && !message.parent_tool_use_id) {
|
|
16984
|
+
const event = message.event;
|
|
16985
|
+
if (event?.type === "content_block_start") this.typing = "";
|
|
16986
|
+
else if (event?.type === "content_block_delta" && event.delta?.type === "text_delta")
|
|
16987
|
+
this.typing += String(event.delta.text ?? "");
|
|
16988
|
+
else return false;
|
|
16989
|
+
this.changed();
|
|
16990
|
+
return false;
|
|
16947
16991
|
} else return false;
|
|
16948
16992
|
this.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
16949
16993
|
this.changed();
|
|
@@ -16958,15 +17002,13 @@ var Session = class {
|
|
|
16958
17002
|
updatedAt: this.updatedAt,
|
|
16959
17003
|
status: this.status,
|
|
16960
17004
|
messages: [...this.messages],
|
|
17005
|
+
typing: this.typing,
|
|
16961
17006
|
approvals: [...this.approvals.values()].map((pending) => pending.approval),
|
|
16962
|
-
send: (requestId, text3) => this.once(requestId, () => this.say(text3)),
|
|
17007
|
+
send: (requestId, text3, now) => this.once(requestId, () => this.say(text3, now)),
|
|
17008
|
+
now: true,
|
|
16963
17009
|
stop: this.turn ? (requestId) => this.once(requestId, async () => {
|
|
16964
17010
|
if (!this.turn) throw new Error("Nothing is running in this Claude Code session");
|
|
16965
|
-
this.
|
|
16966
|
-
type: "control_request",
|
|
16967
|
-
request_id: randomUUID3(),
|
|
16968
|
-
request: { subtype: "interrupt" }
|
|
16969
|
-
});
|
|
17011
|
+
this.interrupt();
|
|
16970
17012
|
}) : void 0,
|
|
16971
17013
|
approve: this.approvals.size ? (requestId, approvalId, choice) => this.once(requestId, async () => {
|
|
16972
17014
|
const pending = this.approvals.get(approvalId);
|
|
@@ -17044,6 +17086,7 @@ import { join as join5 } from "node:path";
|
|
|
17044
17086
|
import { connect as connect2 } from "node:net";
|
|
17045
17087
|
import { watch as watch2 } from "node:fs";
|
|
17046
17088
|
import { lstat, readdir as readdir2, readFile as readFile2 } from "node:fs/promises";
|
|
17089
|
+
var STOP = "Stop here, and wait for my next message.";
|
|
17047
17090
|
var PEER_PROTOCOL = 1;
|
|
17048
17091
|
var MAX_SESSIONS2 = 100;
|
|
17049
17092
|
var REQUEST_MS2 = 4e3;
|
|
@@ -17073,7 +17116,7 @@ async function registrations() {
|
|
|
17073
17116
|
);
|
|
17074
17117
|
return found.flat();
|
|
17075
17118
|
}
|
|
17076
|
-
async function post(session, path, text3) {
|
|
17119
|
+
async function post(session, path, text3, priority) {
|
|
17077
17120
|
const file = await lstat(path);
|
|
17078
17121
|
if (!file.isSocket() || process.getuid && file.uid !== process.getuid())
|
|
17079
17122
|
throw new Error("Claude Code inbox is not owned by this user");
|
|
@@ -17081,7 +17124,7 @@ async function post(session, path, text3) {
|
|
|
17081
17124
|
const line = JSON.stringify({
|
|
17082
17125
|
type: "user",
|
|
17083
17126
|
session_id: session.sessionId,
|
|
17084
|
-
priority
|
|
17127
|
+
priority,
|
|
17085
17128
|
message: { role: "user", content: `<${ENVELOPE} from-name="Dashup">
|
|
17086
17129
|
${body2}
|
|
17087
17130
|
</${ENVELOPE}>` }
|
|
@@ -17114,7 +17157,9 @@ var Claude = class {
|
|
|
17114
17157
|
status: STATUS[session.status ?? ""] ?? "unknown",
|
|
17115
17158
|
messages: [],
|
|
17116
17159
|
approvals: [],
|
|
17117
|
-
send: path ? (requestId, text3) => this.once(requestId, () => post(session, path, text3)) : void 0
|
|
17160
|
+
send: path ? (requestId, text3, now) => this.once(requestId, () => post(session, path, text3, now ? "now" : "next")) : void 0,
|
|
17161
|
+
stop: path ? (requestId) => this.once(requestId, () => post(session, path, STOP, "now")) : void 0,
|
|
17162
|
+
now: Boolean(path)
|
|
17118
17163
|
};
|
|
17119
17164
|
});
|
|
17120
17165
|
}
|
|
@@ -18655,7 +18700,7 @@ var NativeQueue = class {
|
|
|
18655
18700
|
// src/connector.ts
|
|
18656
18701
|
var EPHEMERAL_TTL_MS = 6e4;
|
|
18657
18702
|
var HOME_RECENT = 20;
|
|
18658
|
-
var FOLLOW_MS =
|
|
18703
|
+
var FOLLOW_MS = 2 * 6e4;
|
|
18659
18704
|
var RESCAN_MS = 1e3;
|
|
18660
18705
|
var Command = z2.object({
|
|
18661
18706
|
type: z2.literal("command"),
|
|
@@ -18665,7 +18710,12 @@ var Command = z2.object({
|
|
|
18665
18710
|
action: z2.discriminatedUnion("kind", [
|
|
18666
18711
|
z2.object({ kind: z2.literal("projects.refresh") }).strict(),
|
|
18667
18712
|
z2.object({ kind: z2.literal("thread.read") }).strict(),
|
|
18668
|
-
z2.object({ kind: z2.literal("thread.
|
|
18713
|
+
z2.object({ kind: z2.literal("thread.follow") }).strict(),
|
|
18714
|
+
z2.object({
|
|
18715
|
+
kind: z2.literal("thread.send"),
|
|
18716
|
+
text: z2.string().min(1).max(1e5),
|
|
18717
|
+
now: z2.boolean().optional()
|
|
18718
|
+
}).strict(),
|
|
18669
18719
|
z2.object({ kind: z2.literal("thread.queue"), text: z2.string().min(1).max(1e5) }).strict(),
|
|
18670
18720
|
z2.object({ kind: z2.literal("thread.stop") }).strict(),
|
|
18671
18721
|
z2.object({ kind: z2.literal("approval.respond"), approvalId: z2.string(), choice: z2.string() }).strict(),
|
|
@@ -19059,6 +19109,27 @@ var Connector = class {
|
|
|
19059
19109
|
for (const pair of this.activePairs()) await this.listProjects(pair);
|
|
19060
19110
|
await this.publishQueueReceipts();
|
|
19061
19111
|
}
|
|
19112
|
+
// Publishes a conversation for the phone, which then gets what changes in it.
|
|
19113
|
+
async read(pair, project, thread) {
|
|
19114
|
+
const messages5 = this.discovery.read(thread, this.attached(thread)?.messages);
|
|
19115
|
+
const history = await publishHistory(this.config, pair, project.id, thread, messages5);
|
|
19116
|
+
this.follows.set(`${pair.id}:${thread.id}`, {
|
|
19117
|
+
pair,
|
|
19118
|
+
project: project.id,
|
|
19119
|
+
thread: thread.id,
|
|
19120
|
+
until: Date.now() + FOLLOW_MS,
|
|
19121
|
+
copy: copy(messages5),
|
|
19122
|
+
updatedAt: thread.updatedAt,
|
|
19123
|
+
typing: ""
|
|
19124
|
+
});
|
|
19125
|
+
return this.thread(pair, project, thread, history);
|
|
19126
|
+
}
|
|
19127
|
+
// The reply an agent this computer runs is still writing, until the conversation holds it.
|
|
19128
|
+
typing(thread, messages5) {
|
|
19129
|
+
const typing = this.discovery.locations.get(thread.id)?.live?.typing ?? "";
|
|
19130
|
+
const last = messages5.filter((message) => message.role === "assistant").at(-1);
|
|
19131
|
+
return typing && !last?.text.startsWith(typing) ? typing : "";
|
|
19132
|
+
}
|
|
19062
19133
|
// A phone reading a conversation gets its messages as they change, before anything that says the
|
|
19063
19134
|
// conversation changed, so it never asks for a copy it already has.
|
|
19064
19135
|
async stream() {
|
|
@@ -19067,18 +19138,19 @@ var Connector = class {
|
|
|
19067
19138
|
let messages5;
|
|
19068
19139
|
try {
|
|
19069
19140
|
if (thread && follow.until > Date.now() && activePair(this.config, follow.pair))
|
|
19070
|
-
messages5 =
|
|
19071
|
-
follow.copy,
|
|
19072
|
-
this.discovery.read(thread, this.attached(thread)?.messages)
|
|
19073
|
-
);
|
|
19141
|
+
messages5 = this.discovery.read(thread, this.attached(thread)?.messages);
|
|
19074
19142
|
} catch {
|
|
19075
19143
|
}
|
|
19076
19144
|
if (!thread || !messages5) {
|
|
19077
19145
|
this.follows.delete(key);
|
|
19078
19146
|
continue;
|
|
19079
19147
|
}
|
|
19080
|
-
|
|
19148
|
+
const changed = changes(follow.copy, messages5);
|
|
19149
|
+
const typing = this.typing(thread, messages5);
|
|
19150
|
+
if (!changed.length && thread.updatedAt === follow.updatedAt && typing === follow.typing)
|
|
19151
|
+
continue;
|
|
19081
19152
|
follow.updatedAt = thread.updatedAt;
|
|
19153
|
+
follow.typing = typing;
|
|
19082
19154
|
await this.send(follow.pair, {
|
|
19083
19155
|
type: "thread-tail",
|
|
19084
19156
|
projectId: follow.project,
|
|
@@ -19088,8 +19160,9 @@ var Connector = class {
|
|
|
19088
19160
|
this.config.pairs[follow.pair.id].key,
|
|
19089
19161
|
follow.project,
|
|
19090
19162
|
follow.thread,
|
|
19091
|
-
|
|
19092
|
-
)
|
|
19163
|
+
changed
|
|
19164
|
+
),
|
|
19165
|
+
...typing ? { typing } : {}
|
|
19093
19166
|
});
|
|
19094
19167
|
}
|
|
19095
19168
|
}
|
|
@@ -19164,6 +19237,7 @@ var Connector = class {
|
|
|
19164
19237
|
throw new Error("Command expired. Try again while this computer is online.");
|
|
19165
19238
|
const outcome = await this.command(pair, content);
|
|
19166
19239
|
delete this.config.unconfirmed[content.requestId];
|
|
19240
|
+
if (content.action.kind === "thread.follow") return;
|
|
19167
19241
|
if (outcome && "state" in outcome) {
|
|
19168
19242
|
queue = outcome;
|
|
19169
19243
|
await this.queueResult(pair, content.requestId, content.projectId, queue);
|
|
@@ -19177,6 +19251,7 @@ var Connector = class {
|
|
|
19177
19251
|
);
|
|
19178
19252
|
} catch (error) {
|
|
19179
19253
|
delete this.config.unconfirmed[content.requestId];
|
|
19254
|
+
if (content.action.kind === "thread.follow") return;
|
|
19180
19255
|
if (queue) {
|
|
19181
19256
|
await this.queueResult(pair, content.requestId, content.projectId, queue);
|
|
19182
19257
|
return;
|
|
@@ -19309,19 +19384,15 @@ var Connector = class {
|
|
|
19309
19384
|
if (!project) throw new Error("Project is no longer open on this computer");
|
|
19310
19385
|
const thread = project.threads.find((item) => item.id === command2.threadId);
|
|
19311
19386
|
switch (command2.action.kind) {
|
|
19312
|
-
case "thread.read":
|
|
19387
|
+
case "thread.read":
|
|
19313
19388
|
if (!thread) throw new Error("Thread not found");
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
|
|
19319
|
-
|
|
19320
|
-
|
|
19321
|
-
copy: copy(messages5),
|
|
19322
|
-
updatedAt: thread.updatedAt
|
|
19323
|
-
});
|
|
19324
|
-
return this.thread(pair, project, thread, history);
|
|
19389
|
+
return this.read(pair, project, thread);
|
|
19390
|
+
case "thread.follow": {
|
|
19391
|
+
if (!thread) throw new Error("Thread not found");
|
|
19392
|
+
const follow = this.follows.get(`${pair.id}:${thread.id}`);
|
|
19393
|
+
if (!follow) return this.read(pair, project, thread);
|
|
19394
|
+
follow.until = Date.now() + FOLLOW_MS;
|
|
19395
|
+
return;
|
|
19325
19396
|
}
|
|
19326
19397
|
case "attachment.read": {
|
|
19327
19398
|
if (!thread) throw new Error("Thread not found");
|
|
@@ -19341,7 +19412,8 @@ var Connector = class {
|
|
|
19341
19412
|
"This session has no live reply connection. Use the existing agent on your computer."
|
|
19342
19413
|
);
|
|
19343
19414
|
const location2 = this.discovery.locations.get(thread.id);
|
|
19344
|
-
if (location2?.live?.send)
|
|
19415
|
+
if (location2?.live?.send)
|
|
19416
|
+
return location2.live.send(command2.requestId, command2.action.text, command2.action.now);
|
|
19345
19417
|
const agent = this.attached(thread);
|
|
19346
19418
|
const saved = thread.agent;
|
|
19347
19419
|
if (!agent && location2?.history && saved && saved.harness !== "other") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dashup/connector",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
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/models": "0.1.0",
|
|
32
33
|
"@dashup/typescript-config": "0.0.0",
|
|
33
|
-
"@dashup/protocol": "0.1.0",
|
|
34
34
|
"@parcae/lynx": "0.1.0",
|
|
35
35
|
"@parcae/sdk": "0.8.1",
|
|
36
|
-
"@dashup/
|
|
36
|
+
"@dashup/protocol": "0.1.0"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"dashup": "tsx src/index.ts",
|