@agentconnect.md/daemon 1.0.0-rc.345 → 1.0.0-rc.346

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.
@@ -3,10 +3,10 @@ import { n as require_ms, t as require_src$3 } from "./src-DDtlVutj.js";
3
3
  import { n as init_esm_shims, t as __dirname } from "./esm-shims-DxGcm4Hw.js";
4
4
  import { t as DAEMON_VERSION } from "./version-DGaRXjBK.js";
5
5
  import { C as _coercedNumber, T as NEVER, a as array, d as literal, f as looseObject, i as any, m as object, o as boolean, p as number$1, t as ZodNumber, v as string, x as url$4 } from "./schemas-CQkO9hC5.js";
6
- import { _ as HookReport, a as RELAY_DAEMON_WS_PATH, b as ZodIssueCode, c as SHARED_CONFIG_ACTION_ID, d as buildEnvelope, f as decodeEnvelope, i as RELAY_DAEMON_SUBPROTOCOL, l as SLACK_STATUS_ACTION, m as MAX_FRAME_BYTES, n as gitRepoLabel, o as buildRelayDaemonFrame, p as encode, r as normalizeGitUrl, s as decodeRelayDaemonFrame, u as encodeSharedSlackStatusTarget, y as RESERVED_MCP_SERVER_NAME } from "./dist-CUolJeCB.js";
7
- import { a as agentChildEnv, c as persistRelays, i as selectAgent, n as findAgentFiles, o as loadConfig, r as loadAgents, s as persistDaemonId } from "./load-agents-DnGX_xbK.js";
6
+ import { _ as HookReport, a as RELAY_DAEMON_WS_PATH, b as ZodIssueCode, c as SHARED_AGENT_SELECT_ACTION_ID, d as buildEnvelope, f as decodeEnvelope, i as RELAY_DAEMON_SUBPROTOCOL, l as SLACK_STATUS_ACTION, m as MAX_FRAME_BYTES, n as gitRepoLabel, o as buildRelayDaemonFrame, p as encode, r as normalizeGitUrl, s as decodeRelayDaemonFrame, u as encodeSharedSlackStatusTarget, y as RESERVED_MCP_SERVER_NAME } from "./dist-nbZ5Ymz0.js";
7
+ import { a as agentChildEnv, c as persistRelays, i as selectAgent, n as findAgentFiles, o as loadConfig, r as loadAgents, s as persistDaemonId } from "./load-agents-D02wd-zM.js";
8
8
  import { l as resolveRoot, o as mcpSocketPath, u as statePath } from "./paths-DEcUO8lC.js";
9
- import { C as toolsForIntegrations, E as resolveRuntimes, S as MEMORY_TOOL_NAMES, T as cachedRuntimeVersions, _ as listMemory, a as prefetchWorkspace, b as ALL_TOOL_NAMES, c as probeGitVersion, d as createMemoryProvider, f as memoryKindOf, g as MemoryTooLargeError, h as MemoryPathError, i as installedRuntimes, l as sessionGitEnv, m as MemoryConflictError, n as turnFailureCode, o as prepareWorkspace, p as memoryProviderFor, r as turnFailureReason, s as initGitInjection, t as AcpHost, u as simpleGit, v as resolveInMemoryDir, w as cachedRuntimeNames, x as GITHUB_REVIEW_TOOLS, y as writeMemoryFile } from "./acp-host-DRUQVPb2.js";
9
+ import { C as toolsForIntegrations, E as resolveRuntimes, S as MEMORY_TOOL_NAMES, T as cachedRuntimeVersions, _ as listMemory, a as prefetchWorkspace, b as ALL_TOOL_NAMES, c as probeGitVersion, d as createMemoryProvider, f as memoryKindOf, g as MemoryTooLargeError, h as MemoryPathError, i as installedRuntimes, l as sessionGitEnv, m as MemoryConflictError, n as turnFailureCode, o as prepareWorkspace, p as memoryProviderFor, r as turnFailureReason, s as initGitInjection, t as AcpHost, u as simpleGit, v as resolveInMemoryDir, w as cachedRuntimeNames, x as GITHUB_REVIEW_TOOLS, y as writeMemoryFile } from "./acp-host-cFIM27G4.js";
10
10
  import { i as GitCredentialCache, n as gitcredSocketPath, r as writeGitcredShim, t as GitCredServer } from "./gitcred-server-Bu-Svl7L.js";
11
11
  import { B as ToolListChangedNotificationSchema, D as ListPromptsResultSchema, E as ListChangedOptionsBaseSchema, F as PromptListChangedNotificationSchema, G as isZ4Schema, H as isJSONRPCRequest, I as ReadResourceResultSchema, J as encodeFrame, K as safeParse, L as ResourceListChangedNotificationSchema, M as ListToolsResultSchema, O as ListResourceTemplatesResultSchema, P as McpError, R as SUPPORTED_PROTOCOL_VERSIONS, S as InitializeResultSchema, T as LATEST_PROTOCOL_VERSION, U as isJSONRPCResultResponse, V as isInitializedNotification, W as getObjectShape, _ as ElicitResultSchema, a as AjvJsonSchemaValidator, b as GetPromptResultSchema, c as mergeCapabilities, d as CompleteResultSchema, f as CreateMessageRequestSchema, g as ElicitRequestSchema, h as CreateTaskResultSchema, i as assertToolsCallTaskCapability, k as ListResourcesResultSchema, m as CreateMessageResultWithToolsSchema, n as serializeMessage, o as require_fast_deep_equal, p as CreateMessageResultSchema, q as decodeFrames, r as assertClientRequestTaskCapability, s as Protocol, t as ReadBuffer, u as CallToolResultSchema, v as EmptyResultSchema, w as JSONRPCMessageSchema, y as ErrorCode } from "./stdio-DnS8WcXi.js";
12
12
  import { createRequire } from "node:module";
@@ -68195,8 +68195,10 @@ function attributionMrkdwn(info) {
68195
68195
  const model = escapeMrkdwnLabel(info.model);
68196
68196
  return `sent by <${info.botUrl}|${botName}> (${runtime} · ${model}) · <${info.sessionUrl}|open in session>`;
68197
68197
  }
68198
- /** The per-turn footer is a compact secondary/gray Slack `context` block. */
68199
- function attributionBlocks(info) {
68198
+ /** The per-turn footer is a compact secondary/gray Slack `context` block. Exported so
68199
+ * the daemon can include it in the reply's initial chat.postMessage (the only reliable
68200
+ * point at which Slack's unfurl controls apply). */
68201
+ function buildAttributionBlocks(info) {
68200
68202
  return {
68201
68203
  text: attributionText(info),
68202
68204
  blocks: [{
@@ -68455,41 +68457,57 @@ function buildElicitationResolvedCard(params, decision) {
68455
68457
  }];
68456
68458
  }
68457
68459
  /** Build the compact in-thread status message. Dedicated bots retain the single
68458
- * Configure accessory. A shared bot needs two independent controls, so its status
68459
- * message uses one `actions` block: 👤 opens the relay's channel-agent picker and ⚙️
68460
- * opens the daemon's existing session controls. Both buttons stay on the same row. */
68460
+ * Configure accessory. A shared bot shows its current agent in an inline external
68461
+ * select (the relay supplies options), followed by the session's two immediate
68462
+ * actions: Options opens the existing controls modal and Cancel stops this turn. */
68461
68463
  function buildStatusBlocks(info, sessionKey, link, shared) {
68462
68464
  const text = link ? `${renderStatusBar(info)} · <${link}|View Session>` : renderStatusBar(info);
68463
- if (shared) return [{
68464
- type: "section",
68465
- text: {
68466
- type: "mrkdwn",
68467
- text
68468
- }
68469
- }, {
68470
- type: "actions",
68471
- elements: [{
68472
- type: "button",
68473
- action_id: SHARED_CONFIG_ACTION_ID,
68465
+ if (shared) {
68466
+ const currentAgent = {
68474
68467
  text: {
68475
68468
  type: "plain_text",
68476
- text: "👤",
68477
- emoji: true
68469
+ text: clampTo$2(shared.currentAgent.name, 75) || shared.currentAgent.id
68478
68470
  },
68479
- accessibility_label: "Switch agent",
68480
- value: sessionKey
68481
- }, {
68482
- type: "button",
68483
- action_id: STATUS_ACTION.manage,
68471
+ value: shared.currentAgent.id
68472
+ };
68473
+ return [{
68474
+ type: "section",
68484
68475
  text: {
68485
- type: "plain_text",
68486
- text: "⚙️",
68487
- emoji: true
68476
+ type: "mrkdwn",
68477
+ text
68488
68478
  },
68489
- accessibility_label: "Configure agent session",
68490
- value: shared.sessionTarget
68491
- }]
68492
- }];
68479
+ accessory: {
68480
+ type: "external_select",
68481
+ action_id: SHARED_AGENT_SELECT_ACTION_ID,
68482
+ placeholder: {
68483
+ type: "plain_text",
68484
+ text: "Select agent"
68485
+ },
68486
+ initial_option: currentAgent,
68487
+ min_query_length: 0
68488
+ }
68489
+ }, {
68490
+ type: "actions",
68491
+ elements: [{
68492
+ type: "button",
68493
+ action_id: STATUS_ACTION.manage,
68494
+ text: {
68495
+ type: "plain_text",
68496
+ text: "Options"
68497
+ },
68498
+ value: shared.sessionTarget
68499
+ }, {
68500
+ type: "button",
68501
+ action_id: STATUS_ACTION.cancel,
68502
+ text: {
68503
+ type: "plain_text",
68504
+ text: "Cancel"
68505
+ },
68506
+ style: "danger",
68507
+ value: shared.sessionTarget
68508
+ }]
68509
+ }];
68510
+ }
68493
68511
  return [{
68494
68512
  type: "section",
68495
68513
  text: {
@@ -68880,7 +68898,7 @@ var OutputConverger = class {
68880
68898
  };
68881
68899
  const attribution = info ? [{
68882
68900
  kind: "attribution",
68883
- ...attributionBlocks(info)
68901
+ ...buildAttributionBlocks(info)
68884
68902
  }] : [];
68885
68903
  if (this.mode === "low") return [
68886
68904
  ...this.flush(),
@@ -69241,10 +69259,17 @@ var SlackConnection = class {
69241
69259
  }
69242
69260
  async postMessage(channel, text, threadTs, options) {
69243
69261
  return this.queue.enqueue(async () => {
69262
+ const body = markdownBlock(text);
69263
+ const trailing = options?.trailingBlocks;
69244
69264
  return (await this.postChatMessage({
69245
69265
  channel,
69246
69266
  thread_ts: threadTs,
69247
- ...markdownBlock(text)
69267
+ ...body,
69268
+ ...trailing?.length ? {
69269
+ blocks: [...body.blocks, ...trailing],
69270
+ unfurl_links: false,
69271
+ unfurl_media: false
69272
+ } : {}
69248
69273
  }, options))?.ts;
69249
69274
  });
69250
69275
  }
@@ -69279,13 +69304,12 @@ var SlackConnection = class {
69279
69304
  }, options))?.ts;
69280
69305
  });
69281
69306
  }
69282
- /** Edit a previously-posted Block Kit message in place (chat.update). Best-effort.
69283
- * `unfurl_links: false` keeps an edit from unfurling console URLs. `text` is optional:
69284
- * footer attachment omits it so Slack retains the original notification fallback and
69285
- * a 12k markdown block cannot overflow chat.update's 4k top-level text limit. */
69307
+ /** Edit a previously-posted Block Kit message in place (chat.update). Best-effort;
69308
+ * returns false after logging so footer migration can retry a failed cleanup. `text`
69309
+ * is optional so callers can preserve the original notification fallback. */
69286
69310
  async updateBlocks(channel, ts, blocks, text) {
69287
- await this.queue.enqueue(async () => {
69288
- try {
69311
+ try {
69312
+ return await this.queue.enqueue(async () => {
69289
69313
  await this.app.client.chat.update({
69290
69314
  channel,
69291
69315
  ts,
@@ -69294,10 +69318,12 @@ var SlackConnection = class {
69294
69318
  unfurl_links: false,
69295
69319
  unfurl_media: false
69296
69320
  });
69297
- } catch (err) {
69298
- this.deps.log?.debug(`slack: chat.update (blocks) failed (ch=${channel} ts=${ts}): ${err.message}`);
69299
- }
69300
- });
69321
+ return true;
69322
+ });
69323
+ } catch (err) {
69324
+ this.deps.log?.debug(`slack: chat.update (blocks) failed (ch=${channel} ts=${ts}): ${err.message}`);
69325
+ return false;
69326
+ }
69301
69327
  }
69302
69328
  /**
69303
69329
  * Pull a Slack thread's full history (conversations.replies, cursor-paginated)
@@ -219670,6 +219696,20 @@ var Daemon = class Daemon {
219670
219696
  const modelOptions = host.modelOptions?.(sessionId) ?? null;
219671
219697
  const advertisedModel = modelOptions?.current;
219672
219698
  const turnModel = modelOptions === null ? override ?? agent.runtimeOverrides?.model : advertisedModel === "default" ? void 0 : advertisedModel;
219699
+ const currentSlackAttributionInfo = () => ({
219700
+ botName: agentName,
219701
+ botUrl: this.agentLink(agentId),
219702
+ runtime: this.runtimeNames[agent.runtime] ?? agent.runtime,
219703
+ model: this.buildStatusInfo(p).model ?? turnModel ?? "default",
219704
+ sessionUrl: this.sessionLink(sessionId)
219705
+ });
219706
+ if (p.platform === "slack") {
219707
+ const attribution = buildAttributionBlocks(currentSlackAttributionInfo());
219708
+ p.attribution = {
219709
+ blocks: attribution.blocks,
219710
+ key: JSON.stringify(attribution.blocks)
219711
+ };
219712
+ }
219673
219713
  if (!wasRunning) this.showActivity(replyConn, msg.channel, statusThread, "is thinking…");
219674
219714
  this.emitStatusBar(p);
219675
219715
  const { stopReason, usage } = await host.prompt(sessionId, blocks);
@@ -219724,13 +219764,15 @@ var Daemon = class Daemon {
219724
219764
  }
219725
219765
  } else {
219726
219766
  const link = this.sessionLink(sessionId);
219727
- const finals = conv instanceof TelegramConverger || conv instanceof DiscordConverger ? conv.onFinal(link) : conv.onFinal({
219728
- botName: agentName,
219729
- botUrl: this.agentLink(agentId),
219730
- runtime: this.runtimeNames[agent.runtime] ?? agent.runtime,
219731
- model: this.buildStatusInfo(p).model ?? turnModel ?? "default",
219732
- sessionUrl: link
219733
- });
219767
+ const finalSlackAttributionInfo = currentSlackAttributionInfo();
219768
+ if (p.platform === "slack") {
219769
+ const attribution = buildAttributionBlocks(finalSlackAttributionInfo);
219770
+ p.attribution = {
219771
+ blocks: attribution.blocks,
219772
+ key: JSON.stringify(attribution.blocks)
219773
+ };
219774
+ }
219775
+ const finals = conv instanceof TelegramConverger || conv instanceof DiscordConverger ? conv.onFinal(link) : conv.onFinal(finalSlackAttributionInfo);
219734
219776
  for (const action of finals) this.enqueueApply(p, action);
219735
219777
  }
219736
219778
  for (const ev of rec.onFinal()) this.recordEvent(agentId, msg.channel, statusThread, ev);
@@ -219776,7 +219818,8 @@ var Daemon = class Daemon {
219776
219818
  }
219777
219819
  if (!covered) this.enqueueApply(p, {
219778
219820
  kind: "post",
219779
- text: `⚠️ Agent failed to respond: ${reason}`
219821
+ text: `⚠️ Agent failed to respond: ${reason}`,
219822
+ attributed: false
219780
219823
  });
219781
219824
  this.showActivity(replyConn, msg.channel, statusThread, "");
219782
219825
  await p.applyChain;
@@ -219789,6 +219832,7 @@ var Daemon = class Daemon {
219789
219832
  } finally {
219790
219833
  this.clearCancelBackstop(agentId, sessionId);
219791
219834
  if (p.outputSuppressed) await p.applyChain.catch(() => {});
219835
+ if (p.platform === "slack" && p.conn && p.staleReplyFooters?.length) await this.clearStaleSlackReplyFooters(p.conn, p);
219792
219836
  releaseReplyConn();
219793
219837
  this.clearIdle(p);
219794
219838
  this.releasePermissions(agentId, sessionId);
@@ -219970,11 +220014,11 @@ var Daemon = class Daemon {
219970
220014
  * Apply one converger action against the session's Slack connection:
219971
220015
  * - set-status → assistant.threads.setStatus (best-effort; '' clears)
219972
220016
  * - set-title → assistant.threads.setTitle (best-effort; app DMs only)
219973
- * - post → a new thread message; ALSO recorded to the transcript as the
219974
- * agent's reply text (sender = agentId), so other agents replaying the thread
219975
- * see what it said. Keyed on `statusThread` (the §8.5 replay key).
220017
+ * - post → a new thread message born with the linked footer; ALSO recorded
220018
+ * to the transcript as the agent's reply text (sender = agentId), so other agents
220019
+ * replaying the thread see what it said. Keyed on `statusThread` (§8.5).
219976
220020
  * - notice → posted to the thread but NOT recorded (system chrome).
219977
- * - attribution → folds trailing footer blocks into the last successful `post`.
220021
+ * - attribution → closes the footer lifecycle and retries stale-section cleanup.
219978
220022
  * - progress / plan → the single in-place message of that kind, posted once
219979
220023
  * then chat.update-ed (§9.1 就地更新). The first post's ts is remembered on `p`.
219980
220024
  */
@@ -219985,6 +220029,25 @@ var Daemon = class Daemon {
219985
220029
  ...p.iconUrl ? { icon_url: p.iconUrl } : {}
219986
220030
  };
219987
220031
  }
220032
+ /** Remove attribution blocks from older body sections. Slack edits are best-effort,
220033
+ * so retain failed rows for the next body post and the finalization retry. Test fakes
220034
+ * historically return void; only an explicit `false` means the update failed. */
220035
+ async clearStaleSlackReplyFooters(conn, p, additional = []) {
220036
+ const pending = [...p.staleReplyFooters ?? [], ...additional];
220037
+ if (pending.length === 0) return;
220038
+ delete p.staleReplyFooters;
220039
+ const failed = [];
220040
+ for (const reply of new Map(pending.map((item) => [item.ts, item])).values()) try {
220041
+ if (await conn.updateBlocks(p.channel, reply.ts, [{
220042
+ type: "markdown",
220043
+ text: reply.text
220044
+ }]) === false) failed.push(reply);
220045
+ } catch (err) {
220046
+ failed.push(reply);
220047
+ this.log.debug(`slack: stale footer cleanup failed (${reply.ts}): ${formatErr(err)}`);
220048
+ }
220049
+ if (failed.length > 0) p.staleReplyFooters = failed;
220050
+ }
219988
220051
  async applySlackAction(p, action) {
219989
220052
  const conn = p.conn;
219990
220053
  if (!conn) {
@@ -220007,11 +220070,25 @@ var Daemon = class Daemon {
220007
220070
  if (p.statusThread) await conn.setTitle(p.channel, p.statusThread, action.text);
220008
220071
  return;
220009
220072
  case "post": {
220010
- const ts = await conn.postMessage(p.channel, action.text, p.thread, postOptions);
220011
- if (ts) p.lastReply = {
220012
- ts,
220013
- text: action.text
220014
- };
220073
+ const trackReply = action.attributed !== false;
220074
+ const previous = trackReply ? p.lastReply : void 0;
220075
+ const attribution = trackReply ? p.attribution : void 0;
220076
+ const replyOptions = attribution ? {
220077
+ ...postOptions,
220078
+ trailingBlocks: attribution.blocks
220079
+ } : postOptions;
220080
+ const ts = await conn.postMessage(p.channel, action.text, p.thread, replyOptions);
220081
+ if (ts && trackReply) {
220082
+ if (attribution) await this.clearStaleSlackReplyFooters(conn, p, previous?.footerKey ? [{
220083
+ ts: previous.ts,
220084
+ text: previous.text
220085
+ }] : []);
220086
+ p.lastReply = {
220087
+ ts,
220088
+ text: action.text,
220089
+ ...attribution ? { footerKey: attribution.key } : {}
220090
+ };
220091
+ }
220015
220092
  this.store.appendTranscript({
220016
220093
  channel: p.channel,
220017
220094
  thread: p.statusThread,
@@ -220027,10 +220104,11 @@ var Daemon = class Daemon {
220027
220104
  await conn.postMessage(p.channel, action.text, p.thread, postOptions);
220028
220105
  return;
220029
220106
  case "attribution":
220030
- if (p.lastReply) await conn.updateBlocks(p.channel, p.lastReply.ts, [{
220031
- type: "markdown",
220032
- text: p.lastReply.text
220033
- }, ...action.blocks]);
220107
+ p.attribution = {
220108
+ blocks: action.blocks,
220109
+ key: JSON.stringify(action.blocks)
220110
+ };
220111
+ await this.clearStaleSlackReplyFooters(conn, p);
220034
220112
  return;
220035
220113
  case "progress":
220036
220114
  if (p.progressTs) await conn.updateMessage(p.channel, p.progressTs, action.text);
@@ -220408,11 +220486,17 @@ var Daemon = class Daemon {
220408
220486
  else {
220409
220487
  p.lastStatusBar = key;
220410
220488
  const link = this.sessionLink(p.acpSessionId);
220411
- const shared = p.integrationId && this.isSharedSlackIntegration(p.agentId, p.integrationId) ? { sessionTarget: encodeSharedSlackStatusTarget({
220412
- agentId: p.agentId,
220413
- integrationId: p.integrationId,
220414
- sessionKey: p.sessionKey
220415
- }) } : void 0;
220489
+ const shared = p.integrationId && this.isSharedSlackIntegration(p.agentId, p.integrationId) ? {
220490
+ sessionTarget: encodeSharedSlackStatusTarget({
220491
+ agentId: p.agentId,
220492
+ integrationId: p.integrationId,
220493
+ sessionKey: p.sessionKey
220494
+ }),
220495
+ currentAgent: {
220496
+ id: p.agentId,
220497
+ name: p.agentName
220498
+ }
220499
+ } : void 0;
220416
220500
  this.enqueueApply(p, {
220417
220501
  kind: "status-bar",
220418
220502
  text: renderStatusBar(info),
@@ -221948,4 +222032,4 @@ async function runForeground(opts, deps = {}) {
221948
222032
  //#endregion
221949
222033
  export { ClientTransport as i, CP_SUBPROTOCOL as n, CP_WS_PATH as r, runForeground as t };
221950
222034
 
221951
- //# sourceMappingURL=run-foreground-BmZ1_4vI.js.map
222035
+ //# sourceMappingURL=run-foreground-CS56Yp2s.js.map