@workerdeck/server 2.11.0 → 2.12.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/build/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createServer } from "node:http";
2
2
  import { WebSocketServer } from "ws";
3
- import { BrowserBridgeExecutor, PEER_MESSAGE_MAX_CHARS, PEER_RECENT_DEFAULT, PEER_RECENT_MAX, SessionRunner, attachmentKind, checkClaudeAuth, createEngineSession, getEngineAdapter, installPeerDirectory, normalizeMediaType, peerDirectoryHandle, peerSummary, recentLines } from "@workerdeck/core";
3
+ import { BrowserBridgeExecutor, PEER_MESSAGE_MAX_CHARS, PEER_RECENT_DEFAULT, PEER_RECENT_MAX, SessionRunner, attachmentKind, checkClaudeAuth, createEngineSession, getEngineAdapter, installPeerDirectory, isSlashCommand, normalizeMediaType, peerDirectoryHandle, peerSummary, recentLines } from "@workerdeck/core";
4
4
  import { JobQueue } from "@workerdeck/queue";
5
- import { ENGINE_CAPABILITIES, PROTOCOL_VERSION, SHELL_COMMAND_MAX, costOfByModel, imagePartRef, isJobRun, mergeByModel, sessionState, setPricingOverrides, subscriptionComparison, supportsPermissionMode } from "@workerdeck/protocol";
5
+ import { ENGINE_CAPABILITIES, PEER_MENTION_MAX, PROTOCOL_VERSION, SHELL_COMMAND_MAX, costOfByModel, imagePartRef, isJobRun, mergeByModel, peerMentionKey, peerMentionSlug, scanPeerMentions, sessionState, setPricingOverrides, subscriptionComparison, supportsPermissionMode } from "@workerdeck/protocol";
6
6
  import { createHash, randomUUID } from "node:crypto";
7
7
  import { closeSync, constants, createReadStream, existsSync, fstatSync, ftruncateSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, statSync, writeFileSync } from "node:fs";
8
8
  import { constants as constants$1, homedir } from "node:os";
@@ -1854,13 +1854,15 @@ async function handleCommand(ctx, frame, runner, access) {
1854
1854
  const { attachmentStore, bridge } = ctx;
1855
1855
  switch (frame.type) {
1856
1856
  case "user_message": {
1857
+ const mentions = ctx.peers && !isSlashCommand(frame.text) ? await ctx.peers.mentions(runner.id, frame.text).catch(() => []) : [];
1858
+ const options = mentions.length > 0 ? { mentions } : void 0;
1857
1859
  if (!frame.attachmentIds?.length) {
1858
- runner.sendMessage(frame.text);
1860
+ runner.sendMessage(frame.text, void 0, options);
1859
1861
  return;
1860
1862
  }
1861
1863
  const resolved = attachmentStore.resolve(runner.id, frame.attachmentIds);
1862
1864
  if (!resolved.ok) throw new Error(`unknown attachment(s): ${resolved.missing.join(", ")}`);
1863
- runner.sendMessage(frame.text, resolved.attachments);
1865
+ runner.sendMessage(frame.text, resolved.attachments, options);
1864
1866
  return;
1865
1867
  }
1866
1868
  case "permission_decision":
@@ -3164,6 +3166,44 @@ function createPeerService(deps) {
3164
3166
  queued: before === "running" || before === "awaiting_approval"
3165
3167
  };
3166
3168
  };
3169
+ const mentions = async (from, text) => {
3170
+ const tokens = scanPeerMentions(text);
3171
+ if (tokens.length === 0) return [];
3172
+ const rows = await list(from);
3173
+ const byKey = /* @__PURE__ */ new Map();
3174
+ const add = (key, row) => {
3175
+ const held = byKey.get(key);
3176
+ if (held) held.push(row);
3177
+ else byKey.set(key, [row]);
3178
+ };
3179
+ for (const row of rows) {
3180
+ add(peerMentionKey(peerMentionSlug(row.title, row.id)), row);
3181
+ add(peerMentionKey(row.id), row);
3182
+ }
3183
+ const resolved = [];
3184
+ const seen = /* @__PURE__ */ new Set();
3185
+ for (const token of tokens) {
3186
+ const key = peerMentionKey(token.body);
3187
+ const exact = byKey.get(key);
3188
+ const matches = exact ?? (key.length >= 4 ? rows.filter((row) => row.id.startsWith(key)) : []);
3189
+ const target = matches[0];
3190
+ if (!target || matches.length > 1 && !exact) continue;
3191
+ if (seen.has(target.id)) continue;
3192
+ seen.add(target.id);
3193
+ const others = matches.slice(1, 4).map((row) => row.id);
3194
+ resolved.push({
3195
+ typed: token.body,
3196
+ id: target.id,
3197
+ name: target.title,
3198
+ engine: target.engine,
3199
+ status: target.status,
3200
+ cwd: target.cwd,
3201
+ ...others.length ? { ambiguousWith: others } : {}
3202
+ });
3203
+ if (resolved.length >= PEER_MENTION_MAX) break;
3204
+ }
3205
+ return resolved;
3206
+ };
3167
3207
  const watch = (runner) => runner.subscribe((event) => {
3168
3208
  if (event.type === "user_message" && !event.origin && !event.synthetic && event.parentToolUseId == null && !event.replay) inbound.delete(runner.id);
3169
3209
  }, runner.info().lastSeq);
@@ -3171,6 +3211,7 @@ function createPeerService(deps) {
3171
3211
  list,
3172
3212
  peek,
3173
3213
  send,
3214
+ mentions,
3174
3215
  watch
3175
3216
  };
3176
3217
  }
@@ -3664,6 +3705,7 @@ function createWorkerServer(options = {}) {
3664
3705
  factory,
3665
3706
  registry,
3666
3707
  parking,
3708
+ peers,
3667
3709
  bridge,
3668
3710
  projects,
3669
3711
  queue,