@agentconnect.md/daemon 1.0.0-rc.109 → 1.0.0-rc.110

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 CHANGED
@@ -13290,7 +13290,8 @@ const SessionListItem = object({
13290
13290
  usage: SessionUsage.optional(),
13291
13291
  triggeredBy: string().optional(),
13292
13292
  channelName: string().optional(),
13293
- triggeredByName: string().optional()
13293
+ triggeredByName: string().optional(),
13294
+ threadUrl: string().optional()
13294
13295
  });
13295
13296
  /** C→D REQ: list the daemon's sessions (optionally just one agent's). */
13296
13297
  const SessionListReq = object({ agentId: string().uuid().optional() });
@@ -81159,6 +81160,7 @@ var SlackConnection = class {
81159
81160
  /** The botToken this socket authenticated with (used to detect a same-appToken swap). */
81160
81161
  botToken;
81161
81162
  botId = "";
81163
+ workspaceUrl = "";
81162
81164
  constructor(deps, factory = (o) => new App({
81163
81165
  token: o.token,
81164
81166
  appToken: o.appToken,
@@ -81184,6 +81186,7 @@ var SlackConnection = class {
81184
81186
  const auth = await this.app.client.auth.test();
81185
81187
  this.botUserId = auth.user_id ?? "";
81186
81188
  this.botId = auth.bot_id ?? "";
81189
+ this.workspaceUrl = auth.url ?? "";
81187
81190
  log?.debug(`slack: auth.test ok → bot user ${this.botUserId} (bot_id ${this.botId || "n/a"})`);
81188
81191
  const deliver = (ev, kind) => {
81189
81192
  const msg = normalizeSlackEvent(ev, { traceId: this.deps.newTraceId() });
@@ -83289,6 +83292,27 @@ var CpClient = class {
83289
83292
  }
83290
83293
  };
83291
83294
  //#endregion
83295
+ //#region src/slack/permalink.ts
83296
+ /**
83297
+ * Build a Slack permalink to a thread from the pieces the daemon already holds:
83298
+ * the workspace's base URL (auth.test's `url`, e.g. "https://acme.slack.com/"),
83299
+ * the channel id and the thread's ROOT ts.
83300
+ *
83301
+ * Slack's canonical message permalink is `<base>/archives/<channel>/p<ts>`, where
83302
+ * `<ts>` is the message ts with its dot stripped (e.g. "1710799200.123456" →
83303
+ * "p1710799200123456"). This is exactly what `chat.getPermalink` returns for a
83304
+ * root message — opening it lands on that message and, when it has replies, its
83305
+ * thread. Since a session is keyed by its thread-root ts (`thread_ts ?? ts`), the
83306
+ * root permalink IS the link to the thread, so no `chat.getPermalink` round-trip
83307
+ * is needed.
83308
+ *
83309
+ * Returns undefined when any input is missing, so callers can spread it away.
83310
+ */
83311
+ function slackThreadUrl(workspaceUrl, channel, threadTs) {
83312
+ if (!workspaceUrl || !channel || !threadTs) return void 0;
83313
+ return `${workspaceUrl.replace(/\/+$/, "")}/archives/${channel}/${`p${threadTs.replace(".", "")}`}`;
83314
+ }
83315
+ //#endregion
83292
83316
  //#region src/cp/session-reader.ts
83293
83317
  /**
83294
83318
  * `SessionReader` — the read-only seam answering the CP's `session/list`,
@@ -83375,7 +83399,12 @@ function previewBody(full) {
83375
83399
  preview.content = void 0;
83376
83400
  return preview;
83377
83401
  }
83378
- function createSessionReader(store) {
83402
+ /**
83403
+ * @param workspaceUrlFor Resolve an agent's Slack workspace base URL (the daemon's
83404
+ * live `SlackConnection.workspaceUrl` for that agent), used to build each Slack
83405
+ * session's thread permalink. Absent (or returning undefined) ⇒ no `threadUrl`.
83406
+ */
83407
+ function createSessionReader(store, workspaceUrlFor) {
83379
83408
  return {
83380
83409
  list(req) {
83381
83410
  const rows = store.listSessions(req.agentId);
@@ -83389,6 +83418,7 @@ function createSessionReader(store) {
83389
83418
  const channelName = names.get(r.channel);
83390
83419
  const triggeredByName = r.triggeredBy ? names.get(r.triggeredBy) : void 0;
83391
83420
  const title = r.title ? substituteUserMentions(r.title, names) : void 0;
83421
+ const threadUrl = r.platform === "slack" ? slackThreadUrl(workspaceUrlFor?.(r.agentId), r.channel, r.thread) : void 0;
83392
83422
  return {
83393
83423
  sessionId: r.acpSessionId,
83394
83424
  sessionKey: {
@@ -83403,7 +83433,8 @@ function createSessionReader(store) {
83403
83433
  ...title ? { title } : {},
83404
83434
  ...r.triggeredBy ? { triggeredBy: r.triggeredBy } : {},
83405
83435
  ...channelName ? { channelName } : {},
83406
- ...triggeredByName ? { triggeredByName } : {}
83436
+ ...triggeredByName ? { triggeredByName } : {},
83437
+ ...threadUrl ? { threadUrl } : {}
83407
83438
  };
83408
83439
  }) };
83409
83440
  },
@@ -85334,7 +85365,7 @@ var Daemon = class Daemon {
85334
85365
  activeSessions: () => this.pending.size,
85335
85366
  degradedScopes: () => this.cpDegradedScopes(),
85336
85367
  configApply: this.cpConfigApply(),
85337
- sessionRead: createSessionReader(this.store),
85368
+ sessionRead: createSessionReader(this.store, (agentId) => this.replyConnFor(agentId)?.workspaceUrl),
85338
85369
  workspaceRead: createWorkspaceReader((id) => this.agents.get(id)?.workspace.path),
85339
85370
  workspaceGit: createWorkspaceGit((id) => this.agents.get(id)?.workspace.path),
85340
85371
  clock: systemClock,