zooid 0.7.3 → 0.8.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/dist/bin.js +214 -109
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-3IKBBKGI.js → chunk-R6EDLH23.js} +283 -11
- package/dist/chunk-R6EDLH23.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +12 -8
- package/src/bin.ts +1 -1
- package/src/commands/dev.ts +23 -9
- package/src/daemon/start-daemon.ts +20 -1
- package/src/web/fetch.integration.test.ts +61 -0
- package/src/web/fetch.test.ts +139 -0
- package/src/web/fetch.ts +85 -0
- package/src/web/pin.test.ts +24 -0
- package/src/web/pin.ts +13 -0
- package/src/web/resolve.test.ts +54 -26
- package/src/web/resolve.ts +22 -10
- package/src/web/test-helpers.ts +28 -0
- package/dist/chunk-3IKBBKGI.js.map +0 -1
- package/dist/web/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
- package/dist/web/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
- package/dist/web/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
- package/dist/web/assets/index-BqOX0Pv4.js +0 -305
- package/dist/web/assets/index-C-ZtBp7U.css +0 -1
- package/dist/web/assets/index-Dc8BJYf_.js +0 -118066
- package/dist/web/assets/reaction-picker-emoji-xD2HkULN.js +0 -716
- package/dist/web/favicon.svg +0 -1
- package/dist/web/index.html +0 -14
|
@@ -6979,6 +6979,7 @@ var DockerAcpRuntime = class {
|
|
|
6979
6979
|
this.opts = opts;
|
|
6980
6980
|
this.engine = opts.engine ?? "docker";
|
|
6981
6981
|
}
|
|
6982
|
+
opts;
|
|
6982
6983
|
engine;
|
|
6983
6984
|
buildArgv(spec) {
|
|
6984
6985
|
const image = spec.image ?? this.opts.defaultImage;
|
|
@@ -23115,6 +23116,7 @@ var AgentProcess = class extends EventEmitter {
|
|
|
23115
23116
|
super();
|
|
23116
23117
|
this.options = options;
|
|
23117
23118
|
}
|
|
23119
|
+
options;
|
|
23118
23120
|
child = null;
|
|
23119
23121
|
start() {
|
|
23120
23122
|
if (this.child) return;
|
|
@@ -23182,6 +23184,7 @@ var JsonFileSessionStore = class {
|
|
|
23182
23184
|
this.opts = opts;
|
|
23183
23185
|
this.path = join(opts.dir, "sessions.json");
|
|
23184
23186
|
}
|
|
23187
|
+
opts;
|
|
23185
23188
|
mem = /* @__PURE__ */ new Map();
|
|
23186
23189
|
path;
|
|
23187
23190
|
writeChain = Promise.resolve();
|
|
@@ -23352,7 +23355,11 @@ function acpUpdateToAgentEvent(notif) {
|
|
|
23352
23355
|
return {
|
|
23353
23356
|
type: "agent_message_chunk",
|
|
23354
23357
|
sessionId,
|
|
23355
|
-
content: update.content
|
|
23358
|
+
content: update.content,
|
|
23359
|
+
// `messageId` is not part of the ACP `agent_message_chunk` schema, but
|
|
23360
|
+
// opencode includes it. Forward it so transports can split on message
|
|
23361
|
+
// boundaries; harmlessly undefined for agents that omit it.
|
|
23362
|
+
messageId: update.messageId
|
|
23356
23363
|
};
|
|
23357
23364
|
case "tool_call":
|
|
23358
23365
|
return {
|
|
@@ -23494,6 +23501,7 @@ var AcpClient = class {
|
|
|
23494
23501
|
this.options = options;
|
|
23495
23502
|
this.turns = options.onTap ? new TurnTracker({ agentId: options.agent.id, onTap: options.onTap }) : null;
|
|
23496
23503
|
}
|
|
23504
|
+
options;
|
|
23497
23505
|
process = null;
|
|
23498
23506
|
runtimeChild = null;
|
|
23499
23507
|
connection = null;
|
|
@@ -25043,6 +25051,7 @@ var MatrixContextProvider = class {
|
|
|
25043
25051
|
constructor(opts) {
|
|
25044
25052
|
this.opts = opts;
|
|
25045
25053
|
}
|
|
25054
|
+
opts;
|
|
25046
25055
|
async getRoomHistory(channelId, hopts) {
|
|
25047
25056
|
const { chunk, end } = await this.opts.client.fetchRoomMessages({
|
|
25048
25057
|
roomId: channelId,
|
|
@@ -25130,14 +25139,29 @@ var MatrixContextProvider = class {
|
|
|
25130
25139
|
}
|
|
25131
25140
|
toMessage(ev) {
|
|
25132
25141
|
if (ev.type !== "m.room.message") return null;
|
|
25133
|
-
|
|
25142
|
+
const msgtype = ev.content?.msgtype;
|
|
25143
|
+
const body = ev.content?.body;
|
|
25134
25144
|
const agent = this.opts.agentBots.get(ev.sender);
|
|
25135
|
-
const relatesTo = ev.content["m.relates_to"];
|
|
25145
|
+
const relatesTo = ev.content?.["m.relates_to"];
|
|
25136
25146
|
const threadId = relatesTo?.rel_type === "m.thread" && relatesTo.event_id ? relatesTo.event_id : void 0;
|
|
25147
|
+
if (msgtype === "m.image" || msgtype === "m.file" || msgtype === "m.video" || msgtype === "m.audio") {
|
|
25148
|
+
const kind = msgtype.slice(2);
|
|
25149
|
+
const name = typeof body === "string" && body ? body : "untitled";
|
|
25150
|
+
return {
|
|
25151
|
+
id: ev.event_id,
|
|
25152
|
+
sender: ev.sender,
|
|
25153
|
+
text: `[${kind}: ${name}]`,
|
|
25154
|
+
timestamp: new Date(ev.origin_server_ts).toISOString(),
|
|
25155
|
+
is_agent: agent !== void 0,
|
|
25156
|
+
...agent !== void 0 ? { agent_name: agent } : {},
|
|
25157
|
+
...threadId !== void 0 ? { thread_id: threadId } : {}
|
|
25158
|
+
};
|
|
25159
|
+
}
|
|
25160
|
+
if (msgtype !== "m.text" || typeof body !== "string") return null;
|
|
25137
25161
|
return {
|
|
25138
25162
|
id: ev.event_id,
|
|
25139
25163
|
sender: ev.sender,
|
|
25140
|
-
text:
|
|
25164
|
+
text: body,
|
|
25141
25165
|
timestamp: new Date(ev.origin_server_ts).toISOString(),
|
|
25142
25166
|
is_agent: agent !== void 0,
|
|
25143
25167
|
...agent !== void 0 ? { agent_name: agent } : {},
|
|
@@ -25211,6 +25235,10 @@ function stripMention(body, userId) {
|
|
|
25211
25235
|
}
|
|
25212
25236
|
|
|
25213
25237
|
// ../transport-matrix/src/router.ts
|
|
25238
|
+
var MEDIA_MSGTYPES = /* @__PURE__ */ new Set(["m.image", "m.file", "m.video", "m.audio"]);
|
|
25239
|
+
function isMediaMsgtype(t) {
|
|
25240
|
+
return t !== void 0 && MEDIA_MSGTYPES.has(t);
|
|
25241
|
+
}
|
|
25214
25242
|
function inboundThreadRoot(event) {
|
|
25215
25243
|
const r = event.content?.["m.relates_to"];
|
|
25216
25244
|
return r?.rel_type === "m.thread" && r.event_id ? r.event_id : void 0;
|
|
@@ -25218,6 +25246,7 @@ function inboundThreadRoot(event) {
|
|
|
25218
25246
|
function route(event, agents, threadStates) {
|
|
25219
25247
|
if (event.type !== "m.room.message") return [];
|
|
25220
25248
|
if (!event.content?.msgtype) return [];
|
|
25249
|
+
if (isMediaMsgtype(event.content.msgtype)) return [];
|
|
25221
25250
|
const mentions = new Set(extractMentions(event));
|
|
25222
25251
|
const matches = [];
|
|
25223
25252
|
const threadRoot = inboundThreadRoot(event);
|
|
@@ -25256,10 +25285,12 @@ async function ensureWorkforceSpace(opts) {
|
|
|
25256
25285
|
name: display,
|
|
25257
25286
|
preset: opts.preset,
|
|
25258
25287
|
creation_content: { type: "m.space" },
|
|
25259
|
-
//
|
|
25260
|
-
//
|
|
25261
|
-
//
|
|
25262
|
-
initial_state: [
|
|
25288
|
+
// Pin the join rule regardless of preset. Defaults to invite so the space
|
|
25289
|
+
// can't be walked into (which would otherwise satisfy every restricted
|
|
25290
|
+
// child room's allow); `zooid dev` opts into `public` for local-only use.
|
|
25291
|
+
initial_state: [
|
|
25292
|
+
{ type: "m.room.join_rules", state_key: "", content: { join_rule: opts.joinRule ?? "invite" } }
|
|
25293
|
+
]
|
|
25263
25294
|
};
|
|
25264
25295
|
if (opts.admins && opts.admins.length > 0) {
|
|
25265
25296
|
body.invite = opts.admins;
|
|
@@ -25310,6 +25341,8 @@ var BotPool = class {
|
|
|
25310
25341
|
this.client = client;
|
|
25311
25342
|
this.agents = agents;
|
|
25312
25343
|
}
|
|
25344
|
+
client;
|
|
25345
|
+
agents;
|
|
25313
25346
|
async bootstrap(opts = {}) {
|
|
25314
25347
|
const aliasToId = /* @__PURE__ */ new Map();
|
|
25315
25348
|
const attachedToSpace = /* @__PURE__ */ new Set();
|
|
@@ -25572,8 +25605,180 @@ function toMatrixHtml(markdown) {
|
|
|
25572
25605
|
});
|
|
25573
25606
|
}
|
|
25574
25607
|
|
|
25608
|
+
// ../transport-matrix/src/pending-media.ts
|
|
25609
|
+
var MAX_MEDIA_PER_TURN = 8;
|
|
25610
|
+
var PendingMediaStore = class {
|
|
25611
|
+
queues = /* @__PURE__ */ new Map();
|
|
25612
|
+
key(roomId, threadKey) {
|
|
25613
|
+
return `${roomId} ${threadKey ?? "main"}`;
|
|
25614
|
+
}
|
|
25615
|
+
add(roomId, threadKey, item) {
|
|
25616
|
+
const k = this.key(roomId, threadKey);
|
|
25617
|
+
const q = this.queues.get(k) ?? [];
|
|
25618
|
+
q.push(item);
|
|
25619
|
+
while (q.length > MAX_MEDIA_PER_TURN) q.shift();
|
|
25620
|
+
this.queues.set(k, q);
|
|
25621
|
+
}
|
|
25622
|
+
drain(roomId, threadKey, sender) {
|
|
25623
|
+
const k = this.key(roomId, threadKey);
|
|
25624
|
+
const q = this.queues.get(k) ?? [];
|
|
25625
|
+
const mine = q.filter((i) => i.sender === sender);
|
|
25626
|
+
const rest = q.filter((i) => i.sender !== sender);
|
|
25627
|
+
if (rest.length) this.queues.set(k, rest);
|
|
25628
|
+
else this.queues.delete(k);
|
|
25629
|
+
return mine;
|
|
25630
|
+
}
|
|
25631
|
+
};
|
|
25632
|
+
|
|
25633
|
+
// ../transport-matrix/src/media-client.ts
|
|
25634
|
+
var MAX_INLINE_IMAGE_BYTES = 524288;
|
|
25635
|
+
var INLINE_IMAGE_MIMES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
|
|
25636
|
+
var MAX_DOWNLOAD_BYTES = 33554432;
|
|
25637
|
+
function parseMxcUri(uri) {
|
|
25638
|
+
const m = /^mxc:\/\/([^/]+)\/(.+)$/.exec(uri);
|
|
25639
|
+
return m ? { serverName: m[1], mediaId: m[2] } : null;
|
|
25640
|
+
}
|
|
25641
|
+
var MediaClient = class {
|
|
25642
|
+
homeserver;
|
|
25643
|
+
asToken;
|
|
25644
|
+
fetch;
|
|
25645
|
+
constructor(opts) {
|
|
25646
|
+
this.homeserver = opts.homeserver.replace(/\/$/, "");
|
|
25647
|
+
this.asToken = opts.asToken;
|
|
25648
|
+
this.fetch = opts.fetch ?? globalThis.fetch;
|
|
25649
|
+
}
|
|
25650
|
+
async download(input) {
|
|
25651
|
+
const parsed = parseMxcUri(input.mxcUri);
|
|
25652
|
+
if (!parsed) throw new Error(`not an mxc uri: ${input.mxcUri}`);
|
|
25653
|
+
const url2 = `${this.homeserver}/_matrix/client/v1/media/download/${encodeURIComponent(parsed.serverName)}/${encodeURIComponent(parsed.mediaId)}?user_id=${encodeURIComponent(input.asUserId)}`;
|
|
25654
|
+
const r = await this.fetch(url2, {
|
|
25655
|
+
headers: { Authorization: `Bearer ${this.asToken}` }
|
|
25656
|
+
});
|
|
25657
|
+
if (!r.ok) throw new Error(`media download failed: ${r.status}`);
|
|
25658
|
+
const buf = new Uint8Array(await r.arrayBuffer());
|
|
25659
|
+
const max = input.maxBytes ?? MAX_DOWNLOAD_BYTES;
|
|
25660
|
+
if (buf.byteLength > max) {
|
|
25661
|
+
throw new Error(`media too large: ${buf.byteLength} > ${max}`);
|
|
25662
|
+
}
|
|
25663
|
+
return { data: buf, contentType: r.headers.get("content-type") ?? "application/octet-stream" };
|
|
25664
|
+
}
|
|
25665
|
+
async upload(input) {
|
|
25666
|
+
const params = new URLSearchParams();
|
|
25667
|
+
if (input.filename) params.set("filename", input.filename);
|
|
25668
|
+
params.set("user_id", input.asUserId);
|
|
25669
|
+
const r = await this.fetch(`${this.homeserver}/_matrix/media/v3/upload?${params}`, {
|
|
25670
|
+
method: "POST",
|
|
25671
|
+
headers: { Authorization: `Bearer ${this.asToken}`, "Content-Type": input.contentType },
|
|
25672
|
+
body: input.data
|
|
25673
|
+
});
|
|
25674
|
+
if (!r.ok) throw new Error(`media upload failed: ${r.status}`);
|
|
25675
|
+
return await r.json();
|
|
25676
|
+
}
|
|
25677
|
+
};
|
|
25678
|
+
|
|
25679
|
+
// ../transport-matrix/src/attachments.ts
|
|
25680
|
+
import { mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
25681
|
+
import { join as join4 } from "path";
|
|
25682
|
+
import { posix } from "path";
|
|
25683
|
+
function sanitize(s, fallback) {
|
|
25684
|
+
const cleaned = s.replace(/[^A-Za-z0-9._-]/g, "").replace(/^\.+/, "");
|
|
25685
|
+
return cleaned || fallback;
|
|
25686
|
+
}
|
|
25687
|
+
function writeAttachment(input) {
|
|
25688
|
+
const dir = sanitize(input.eventId, "event");
|
|
25689
|
+
const name = sanitize(input.filename, "file");
|
|
25690
|
+
const hostDir = join4(input.workspaceDir, ".zooid", "attachments", dir);
|
|
25691
|
+
mkdirSync2(hostDir, { recursive: true });
|
|
25692
|
+
const hostPath = join4(hostDir, name);
|
|
25693
|
+
writeFileSync(hostPath, input.data);
|
|
25694
|
+
const agentPath = posix.join(input.agentWorkspacePath, ".zooid", "attachments", dir, name);
|
|
25695
|
+
return { hostPath, agentPath };
|
|
25696
|
+
}
|
|
25697
|
+
|
|
25575
25698
|
// ../transport-matrix/src/transport.ts
|
|
25576
25699
|
var STARTUP_GRACE_MS = 5e3;
|
|
25700
|
+
async function buildMediaBlocks(items, opts) {
|
|
25701
|
+
const blocks = [];
|
|
25702
|
+
const pathLines = [];
|
|
25703
|
+
if (!opts.media || items.length === 0) return { blocks, pathLines };
|
|
25704
|
+
for (const item of items) {
|
|
25705
|
+
try {
|
|
25706
|
+
const isInlineCandidate = item.msgtype === "m.image" && INLINE_IMAGE_MIMES.includes(item.info?.mimetype ?? "") && (item.info?.size === void 0 || item.info.size <= MAX_INLINE_IMAGE_BYTES);
|
|
25707
|
+
if (isInlineCandidate) {
|
|
25708
|
+
const { data, contentType } = await opts.media.download({
|
|
25709
|
+
mxcUri: item.url,
|
|
25710
|
+
asUserId: opts.agent.userId
|
|
25711
|
+
});
|
|
25712
|
+
if (data.byteLength <= MAX_INLINE_IMAGE_BYTES) {
|
|
25713
|
+
blocks.push({
|
|
25714
|
+
type: "image",
|
|
25715
|
+
data: Buffer.from(data).toString("base64"),
|
|
25716
|
+
mimeType: contentType
|
|
25717
|
+
});
|
|
25718
|
+
continue;
|
|
25719
|
+
}
|
|
25720
|
+
if (opts.agent.workspaceDir) {
|
|
25721
|
+
const paths = opts.writeAttachmentFn({
|
|
25722
|
+
workspaceDir: opts.agent.workspaceDir,
|
|
25723
|
+
agentWorkspacePath: opts.agent.agentWorkspacePath ?? opts.agent.workspaceDir,
|
|
25724
|
+
eventId: item.eventId,
|
|
25725
|
+
filename: item.filename ?? item.body,
|
|
25726
|
+
data
|
|
25727
|
+
});
|
|
25728
|
+
blocks.push({
|
|
25729
|
+
type: "resource_link",
|
|
25730
|
+
uri: `file://${paths.agentPath}`,
|
|
25731
|
+
name: item.filename ?? item.body
|
|
25732
|
+
});
|
|
25733
|
+
pathLines.push(`Attached file: ${paths.agentPath}`);
|
|
25734
|
+
}
|
|
25735
|
+
} else {
|
|
25736
|
+
if (!opts.agent.workspaceDir) continue;
|
|
25737
|
+
const { data } = await opts.media.download({
|
|
25738
|
+
mxcUri: item.url,
|
|
25739
|
+
asUserId: opts.agent.userId
|
|
25740
|
+
});
|
|
25741
|
+
const paths = opts.writeAttachmentFn({
|
|
25742
|
+
workspaceDir: opts.agent.workspaceDir,
|
|
25743
|
+
agentWorkspacePath: opts.agent.agentWorkspacePath ?? opts.agent.workspaceDir,
|
|
25744
|
+
eventId: item.eventId,
|
|
25745
|
+
filename: item.filename ?? item.body,
|
|
25746
|
+
data
|
|
25747
|
+
});
|
|
25748
|
+
blocks.push({
|
|
25749
|
+
type: "resource_link",
|
|
25750
|
+
uri: `file://${paths.agentPath}`,
|
|
25751
|
+
name: item.filename ?? item.body,
|
|
25752
|
+
mimeType: item.info?.mimetype,
|
|
25753
|
+
size: item.info?.size
|
|
25754
|
+
});
|
|
25755
|
+
pathLines.push(`Attached file: ${paths.agentPath}`);
|
|
25756
|
+
}
|
|
25757
|
+
} catch (err) {
|
|
25758
|
+
opts.onError(item, err);
|
|
25759
|
+
}
|
|
25760
|
+
}
|
|
25761
|
+
return { blocks, pathLines };
|
|
25762
|
+
}
|
|
25763
|
+
async function sendMediaError(ctx, _err, message, client) {
|
|
25764
|
+
await client.sendCustomEvent({
|
|
25765
|
+
roomId: ctx.roomId,
|
|
25766
|
+
asUserId: ctx.agent.userId,
|
|
25767
|
+
eventType: "eco.zoon.error",
|
|
25768
|
+
content: toErrorBody(
|
|
25769
|
+
{
|
|
25770
|
+
kind: "error",
|
|
25771
|
+
agentId: ctx.agent.name,
|
|
25772
|
+
sessionId: null,
|
|
25773
|
+
turnId: null,
|
|
25774
|
+
code: "media_failed",
|
|
25775
|
+
message: message.slice(0, 250),
|
|
25776
|
+
transient: false
|
|
25777
|
+
},
|
|
25778
|
+
ctx.threadRoot
|
|
25779
|
+
)
|
|
25780
|
+
}).catch((e) => console.warn(`[matrix:${ctx.agent.name}] eco.zoon.error send failed:`, e));
|
|
25781
|
+
}
|
|
25577
25782
|
var SEEN_EVENT_CAP = 5e3;
|
|
25578
25783
|
var DRAIN_QUIET_MS = 300;
|
|
25579
25784
|
var DRAIN_MAX_MS = 3e4;
|
|
@@ -25586,9 +25791,13 @@ function createMatrixTransport(opts) {
|
|
|
25586
25791
|
const { agents, approvals, client, bindings, hsToken, adminUserId } = opts;
|
|
25587
25792
|
const drainQuietMs = opts.drainQuietMs ?? DRAIN_QUIET_MS;
|
|
25588
25793
|
const drainMaxMs = opts.drainMaxMs ?? DRAIN_MAX_MS;
|
|
25794
|
+
const mediaClient = opts.media;
|
|
25795
|
+
const writeAttachmentFn = opts.writeAttachmentFn ?? writeAttachment;
|
|
25796
|
+
const pendingMedia = new PendingMediaStore();
|
|
25589
25797
|
const pool = new BotPool(client, bindings);
|
|
25590
25798
|
const sessions = /* @__PURE__ */ new Map();
|
|
25591
25799
|
const buffers = /* @__PURE__ */ new Map();
|
|
25800
|
+
const bufferMessageIds = /* @__PURE__ */ new Map();
|
|
25592
25801
|
const sendQueue = /* @__PURE__ */ new Map();
|
|
25593
25802
|
const threadStates = /* @__PURE__ */ new Map();
|
|
25594
25803
|
const cutoffTs = Date.now() - STARTUP_GRACE_MS;
|
|
@@ -25603,8 +25812,36 @@ function createMatrixTransport(opts) {
|
|
|
25603
25812
|
const block = event.content;
|
|
25604
25813
|
if (block.type === "text" && typeof block.text === "string") {
|
|
25605
25814
|
const current = buffers.get(event.sessionId) ?? "";
|
|
25606
|
-
const
|
|
25815
|
+
const prevMessageId = bufferMessageIds.get(event.sessionId);
|
|
25816
|
+
const messageChanged = event.messageId !== void 0 && prevMessageId !== void 0 && event.messageId !== prevMessageId;
|
|
25817
|
+
const needsBreak = current.length > 0 && (block.text === "" || messageChanged);
|
|
25818
|
+
const prefix = needsBreak ? "\n\n" : "";
|
|
25607
25819
|
buffers.set(event.sessionId, current + prefix + block.text);
|
|
25820
|
+
if (event.messageId !== void 0)
|
|
25821
|
+
bufferMessageIds.set(event.sessionId, event.messageId);
|
|
25822
|
+
} else if (block.type === "image" && typeof block.data === "string" && typeof block.mimeType === "string" && mediaClient) {
|
|
25823
|
+
const ctx2 = sessions.get(event.sessionId);
|
|
25824
|
+
if (ctx2) {
|
|
25825
|
+
const bytes = Buffer.from(block.data, "base64");
|
|
25826
|
+
const ext = (block.mimeType.split("/")[1] ?? "png").replace(/[^a-z0-9]/gi, "");
|
|
25827
|
+
const filename = `image.${ext}`;
|
|
25828
|
+
void mediaClient.upload({ data: bytes, contentType: block.mimeType, filename, asUserId: ctx2.agent.userId }).then(
|
|
25829
|
+
({ content_uri }) => client.sendMessage({
|
|
25830
|
+
roomId: ctx2.roomId,
|
|
25831
|
+
asUserId: ctx2.agent.userId,
|
|
25832
|
+
threadRoot: ctx2.threadRoot,
|
|
25833
|
+
content: {
|
|
25834
|
+
msgtype: "m.image",
|
|
25835
|
+
body: filename,
|
|
25836
|
+
url: content_uri,
|
|
25837
|
+
info: { mimetype: block.mimeType, size: bytes.length }
|
|
25838
|
+
}
|
|
25839
|
+
})
|
|
25840
|
+
).catch((err) => {
|
|
25841
|
+
console.warn(`[matrix:${name}] outbound image upload failed:`, err);
|
|
25842
|
+
void sendMediaError(ctx2, err, "agent image upload failed", client);
|
|
25843
|
+
});
|
|
25844
|
+
}
|
|
25608
25845
|
} else {
|
|
25609
25846
|
console.warn(`[matrix:${name}] dropped chunk block type=${block.type}`, block);
|
|
25610
25847
|
}
|
|
@@ -25747,6 +25984,18 @@ function createMatrixTransport(opts) {
|
|
|
25747
25984
|
continue;
|
|
25748
25985
|
}
|
|
25749
25986
|
logInbound(evt);
|
|
25987
|
+
if (evt.type === "m.room.message" && isMediaMsgtype(evt.content?.msgtype) && evt.room_id && evt.event_id && evt.sender && evt.content?.url && !bindings.some((b) => b.userId === evt.sender)) {
|
|
25988
|
+
pendingMedia.add(evt.room_id, inboundThreadRoot2(evt), {
|
|
25989
|
+
eventId: evt.event_id,
|
|
25990
|
+
sender: evt.sender,
|
|
25991
|
+
msgtype: evt.content.msgtype,
|
|
25992
|
+
body: evt.content.body ?? "",
|
|
25993
|
+
filename: evt.content.filename,
|
|
25994
|
+
url: evt.content.url,
|
|
25995
|
+
info: evt.content.info
|
|
25996
|
+
});
|
|
25997
|
+
continue;
|
|
25998
|
+
}
|
|
25750
25999
|
const promotedRoot = inboundThreadRoot2(evt) ?? evt.event_id;
|
|
25751
26000
|
const inboundRel = inboundThreadRoot2(evt);
|
|
25752
26001
|
if (evt.type === "m.room.message" && inboundRel && !threadStates.has(inboundRel) && evt.room_id) {
|
|
@@ -25847,6 +26096,7 @@ function createMatrixTransport(opts) {
|
|
|
25847
26096
|
const sessionId = await agents.ensureSession(agent.name, sessionKey, evt.room_id);
|
|
25848
26097
|
sessions.set(sessionId, { agent, roomId: evt.room_id, threadRoot });
|
|
25849
26098
|
buffers.set(sessionId, "");
|
|
26099
|
+
bufferMessageIds.delete(sessionId);
|
|
25850
26100
|
const roomId = evt.room_id;
|
|
25851
26101
|
const TYPING_TTL_MS = 3e4;
|
|
25852
26102
|
const TYPING_REFRESH_MS = 25e3;
|
|
@@ -25862,10 +26112,30 @@ function createMatrixTransport(opts) {
|
|
|
25862
26112
|
try {
|
|
25863
26113
|
const rawBody = evt.content?.body ?? "";
|
|
25864
26114
|
const promptText = stripMention(rawBody, agent.userId);
|
|
26115
|
+
const pendingItems = pendingMedia.drain(
|
|
26116
|
+
evt.room_id,
|
|
26117
|
+
inboundThreadRoot2(evt),
|
|
26118
|
+
evt.sender ?? ""
|
|
26119
|
+
);
|
|
26120
|
+
const { blocks, pathLines } = await buildMediaBlocks(pendingItems, {
|
|
26121
|
+
agent,
|
|
26122
|
+
media: mediaClient,
|
|
26123
|
+
writeAttachmentFn,
|
|
26124
|
+
onError: (item, err) => {
|
|
26125
|
+
console.warn(`[matrix:${agent.name}] media_failed for ${item.body}:`, err);
|
|
26126
|
+
void sendMediaError(
|
|
26127
|
+
{ agent, roomId: evt.room_id, threadRoot },
|
|
26128
|
+
err,
|
|
26129
|
+
`Could not process attachment: ${item.body}`,
|
|
26130
|
+
client
|
|
26131
|
+
);
|
|
26132
|
+
}
|
|
26133
|
+
});
|
|
26134
|
+
const fullPromptText = [promptText, ...pathLines].filter(Boolean).join("\n");
|
|
25865
26135
|
await agents.prompt(agent.name, {
|
|
25866
26136
|
threadId: sessionKey,
|
|
25867
26137
|
channelId: evt.room_id,
|
|
25868
|
-
content: [{ type: "text", text:
|
|
26138
|
+
content: [...blocks, { type: "text", text: fullPromptText }]
|
|
25869
26139
|
});
|
|
25870
26140
|
const drainStart = Date.now();
|
|
25871
26141
|
let drained = buffers.get(sessionId) ?? "";
|
|
@@ -25907,6 +26177,7 @@ function createMatrixTransport(opts) {
|
|
|
25907
26177
|
await safeTyping(false);
|
|
25908
26178
|
await safePresence("online");
|
|
25909
26179
|
buffers.delete(sessionId);
|
|
26180
|
+
bufferMessageIds.delete(sessionId);
|
|
25910
26181
|
}
|
|
25911
26182
|
}
|
|
25912
26183
|
return {
|
|
@@ -31579,10 +31850,11 @@ export {
|
|
|
31579
31850
|
renderRegistration,
|
|
31580
31851
|
ensureWorkforceSpace,
|
|
31581
31852
|
ensureDefaultChannel,
|
|
31853
|
+
MediaClient,
|
|
31582
31854
|
createMatrixTransport,
|
|
31583
31855
|
startWorkforcePublisher,
|
|
31584
31856
|
SpawnRegistry,
|
|
31585
31857
|
startDaemonSocketServer,
|
|
31586
31858
|
buildAcpRegistry
|
|
31587
31859
|
};
|
|
31588
|
-
//# sourceMappingURL=chunk-
|
|
31860
|
+
//# sourceMappingURL=chunk-R6EDLH23.js.map
|