@agentconnect.md/daemon 1.0.0-rc.259 → 1.0.0-rc.260
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/{acp-host-hnOn2UR9.js → acp-host-DRbb-vvg.js} +2 -2
- package/dist/{acp-host-hnOn2UR9.js.map → acp-host-DRbb-vvg.js.map} +1 -1
- package/dist/{agent-list-7JSTLtcu.js → agent-list-csC2r5tB.js} +2 -2
- package/dist/{agent-list-7JSTLtcu.js.map → agent-list-csC2r5tB.js.map} +1 -1
- package/dist/{chat-DJDh08Id.js → chat-BxQhnDKg.js} +3 -3
- package/dist/{chat-DJDh08Id.js.map → chat-BxQhnDKg.js.map} +1 -1
- package/dist/index.js +4 -4
- package/dist/{load-agents-DspcHKeP.js → load-agents-CW9Q6eYo.js} +282 -17
- package/dist/load-agents-CW9Q6eYo.js.map +1 -0
- package/dist/{login-BDX6YKlb.js → login-CiTSpQlT.js} +3 -3
- package/dist/{login-BDX6YKlb.js.map → login-CiTSpQlT.js.map} +1 -1
- package/dist/{run-foreground-FYqgRmz9.js → run-foreground-BqNCGDXc.js} +191 -39
- package/dist/{run-foreground-FYqgRmz9.js.map → run-foreground-BqNCGDXc.js.map} +1 -1
- package/dist/run-foreground-C0awGplP.js +2 -0
- package/package.json +1 -1
- package/dist/load-agents-DspcHKeP.js.map +0 -1
- package/dist/run-foreground-CD5jrAvS.js +0 -2
|
@@ -3,9 +3,9 @@ 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
|
|
6
|
+
import { C as ZodIssueCode, S as RESERVED_MCP_SERVER_NAME, _ as buildEnvelope, a as agentChildEnv, b as MAX_FRAME_BYTES, c as persistRelays, d as normalizeGitUrl, f as RELAY_DAEMON_SUBPROTOCOL, g as SHARED_CONFIG_ACTION_ID, h as decodeRelayDaemonFrame, i as selectAgent, m as buildRelayDaemonFrame, n as findAgentFiles, o as loadConfig, p as RELAY_DAEMON_WS_PATH, r as loadAgents, s as persistDaemonId, v as decodeEnvelope, y as encode } from "./load-agents-CW9Q6eYo.js";
|
|
7
7
|
import { l as resolveRoot, o as mcpSocketPath, u as statePath } from "./paths-DEcUO8lC.js";
|
|
8
|
-
import { S as resolveRuntimes, _ as writeMemoryFile, a as initGitInjection, b as cachedRuntimeNames, c as simpleGit, d as memoryProviderFor, f as MemoryConflictError, g as resolveInMemoryDir, h as listMemory, i as prepareWorkspace, l as createMemoryProvider, m as MemoryTooLargeError, n as installedRuntimes, o as probeGitVersion, p as MemoryPathError, r as prefetchWorkspace, s as sessionGitEnv, t as AcpHost, u as memoryKindOf, v as MEMORY_TOOL_NAMES, x as cachedRuntimeVersions, y as toolsForIntegrations } from "./acp-host-
|
|
8
|
+
import { S as resolveRuntimes, _ as writeMemoryFile, a as initGitInjection, b as cachedRuntimeNames, c as simpleGit, d as memoryProviderFor, f as MemoryConflictError, g as resolveInMemoryDir, h as listMemory, i as prepareWorkspace, l as createMemoryProvider, m as MemoryTooLargeError, n as installedRuntimes, o as probeGitVersion, p as MemoryPathError, r as prefetchWorkspace, s as sessionGitEnv, t as AcpHost, u as memoryKindOf, v as MEMORY_TOOL_NAMES, x as cachedRuntimeVersions, y as toolsForIntegrations } from "./acp-host-DRbb-vvg.js";
|
|
9
9
|
import { i as GitCredentialCache, n as gitcredSocketPath, r as writeGitcredShim, t as GitCredServer } from "./gitcred-server-Dcsq6QJe.js";
|
|
10
10
|
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";
|
|
11
11
|
import { URL as URL$1 } from "url";
|
|
@@ -25,25 +25,6 @@ import net from "node:net";
|
|
|
25
25
|
import { lstat, open, readdir, realpath, stat as stat$1 } from "node:fs/promises";
|
|
26
26
|
import { DatabaseSync } from "node:sqlite";
|
|
27
27
|
import assert from "assert";
|
|
28
|
-
//#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/compat.js
|
|
29
|
-
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
30
|
-
const ZodIssueCode = {
|
|
31
|
-
invalid_type: "invalid_type",
|
|
32
|
-
too_big: "too_big",
|
|
33
|
-
too_small: "too_small",
|
|
34
|
-
invalid_format: "invalid_format",
|
|
35
|
-
not_multiple_of: "not_multiple_of",
|
|
36
|
-
unrecognized_keys: "unrecognized_keys",
|
|
37
|
-
invalid_union: "invalid_union",
|
|
38
|
-
invalid_key: "invalid_key",
|
|
39
|
-
invalid_element: "invalid_element",
|
|
40
|
-
invalid_value: "invalid_value",
|
|
41
|
-
custom: "custom"
|
|
42
|
-
};
|
|
43
|
-
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
|
44
|
-
var ZodFirstPartyTypeKind;
|
|
45
|
-
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
46
|
-
//#endregion
|
|
47
28
|
//#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/coerce.js
|
|
48
29
|
function number(params) {
|
|
49
30
|
return _coercedNumber(ZodNumber, params);
|
|
@@ -67116,6 +67097,7 @@ var require_dist$9 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
67116
67097
|
}));
|
|
67117
67098
|
//#endregion
|
|
67118
67099
|
//#region src/slack/normalize.ts
|
|
67100
|
+
var import_dist$1 = require_dist$13();
|
|
67119
67101
|
var import_dist = /* @__PURE__ */ __toESM(require_dist$9(), 1);
|
|
67120
67102
|
const MENTION_RE$1 = /<@([A-Z0-9]+)>/g;
|
|
67121
67103
|
/** Map a Slack file element to a NormalizedMessage Attachment, dropping any
|
|
@@ -67311,6 +67293,32 @@ function attributionBlocks(webAppUrl) {
|
|
|
67311
67293
|
}]
|
|
67312
67294
|
};
|
|
67313
67295
|
}
|
|
67296
|
+
/** The shared-bot footer (§10.1): "sent by <agent_name>" (linking to the agent in the
|
|
67297
|
+
* console) with a right-aligned ⚙ Config button that opens the per-channel
|
|
67298
|
+
* default-agent modal. A `section` (not `context`) because only sections take a
|
|
67299
|
+
* button accessory — the click lands on the RELAY (it owns Socket Mode), which reads
|
|
67300
|
+
* {@link SHARED_CONFIG_ACTION_ID}. */
|
|
67301
|
+
function sharedFooterBlocks(agentName, agentUrl) {
|
|
67302
|
+
return {
|
|
67303
|
+
text: `sent by ${agentName}`,
|
|
67304
|
+
blocks: [{
|
|
67305
|
+
type: "section",
|
|
67306
|
+
text: {
|
|
67307
|
+
type: "mrkdwn",
|
|
67308
|
+
text: `sent by <${agentUrl}|${agentName}>`
|
|
67309
|
+
},
|
|
67310
|
+
accessory: {
|
|
67311
|
+
type: "button",
|
|
67312
|
+
text: {
|
|
67313
|
+
type: "plain_text",
|
|
67314
|
+
text: "👤",
|
|
67315
|
+
emoji: true
|
|
67316
|
+
},
|
|
67317
|
+
action_id: SHARED_CONFIG_ACTION_ID
|
|
67318
|
+
}
|
|
67319
|
+
}]
|
|
67320
|
+
};
|
|
67321
|
+
}
|
|
67314
67322
|
/** Pull human-readable output text out of an ACP tool_call/_update. Prefers the `content[]`
|
|
67315
67323
|
* text blocks (the tool's reported output); falls back to a string `rawOutput`. diff /
|
|
67316
67324
|
* terminal blocks and non-string rawOutput are skipped — they have no compact inline text. */
|
|
@@ -67779,12 +67787,15 @@ var OutputConverger = class {
|
|
|
67779
67787
|
* — in medium/high — append a footer linking to the Web App session detail. The
|
|
67780
67788
|
* link is omitted entirely when none is configured (no `local://` placeholder).
|
|
67781
67789
|
*/
|
|
67782
|
-
onFinal(link, webAppUrl) {
|
|
67790
|
+
onFinal(link, webAppUrl, shared) {
|
|
67783
67791
|
const clear = {
|
|
67784
67792
|
kind: "set-status",
|
|
67785
67793
|
text: ""
|
|
67786
67794
|
};
|
|
67787
|
-
const attribution =
|
|
67795
|
+
const attribution = shared ? [{
|
|
67796
|
+
kind: "attribution",
|
|
67797
|
+
...sharedFooterBlocks(shared.agentName, shared.agentUrl)
|
|
67798
|
+
}] : webAppUrl ? [{
|
|
67788
67799
|
kind: "attribution",
|
|
67789
67800
|
...attributionBlocks(webAppUrl)
|
|
67790
67801
|
}] : [];
|
|
@@ -67793,16 +67804,10 @@ var OutputConverger = class {
|
|
|
67793
67804
|
clear,
|
|
67794
67805
|
...attribution
|
|
67795
67806
|
];
|
|
67796
|
-
const reasoning = this.drainReasoning();
|
|
67797
|
-
const footer = link ? [{
|
|
67798
|
-
kind: "notice",
|
|
67799
|
-
text: `:white_check_mark: done — [details](${link})`
|
|
67800
|
-
}] : [];
|
|
67801
67807
|
return [
|
|
67802
|
-
...
|
|
67808
|
+
...this.drainReasoning(),
|
|
67803
67809
|
...this.flush(),
|
|
67804
67810
|
clear,
|
|
67805
|
-
...footer,
|
|
67806
67811
|
...attribution
|
|
67807
67812
|
];
|
|
67808
67813
|
}
|
|
@@ -67810,11 +67815,16 @@ var OutputConverger = class {
|
|
|
67810
67815
|
//#endregion
|
|
67811
67816
|
//#region src/slack/connection.ts
|
|
67812
67817
|
const { App, LogLevel } = import_dist.default;
|
|
67813
|
-
/** §6.1: one Slack Socket Mode connection per unique appToken.
|
|
67818
|
+
/** §6.1: one Slack Socket Mode connection per unique appToken.
|
|
67819
|
+
* Shared-mode integrations are SKIPPED here — their inbound lives on a relay, so
|
|
67820
|
+
* the daemon opens no socket for them (it reaches them send-only via RelayClient;
|
|
67821
|
+
* see shared-bot-relay.md §11). They carry no appToken, so there is nothing to
|
|
67822
|
+
* consolidate on. */
|
|
67814
67823
|
function consolidate(agents) {
|
|
67815
67824
|
const groups = /* @__PURE__ */ new Map();
|
|
67816
67825
|
for (const a of agents) for (const int of a.integrations) {
|
|
67817
67826
|
if (int.platform !== "slack") continue;
|
|
67827
|
+
if (int.slack.mode === "shared" || !int.slack.appToken) continue;
|
|
67818
67828
|
const k = int.slack.appToken;
|
|
67819
67829
|
const g = groups.get(k) ?? {
|
|
67820
67830
|
appToken: k,
|
|
@@ -67829,6 +67839,27 @@ function consolidate(agents) {
|
|
|
67829
67839
|
}
|
|
67830
67840
|
return groups;
|
|
67831
67841
|
}
|
|
67842
|
+
/** Group SHARED-mode Slack integrations by xoxb (one send-only client per bot
|
|
67843
|
+
* token). These have no appToken (the relay owns inbound), so they can't be keyed
|
|
67844
|
+
* by appToken like {@link consolidate} — the bot token is the identity. */
|
|
67845
|
+
function consolidateShared(agents) {
|
|
67846
|
+
const groups = /* @__PURE__ */ new Map();
|
|
67847
|
+
for (const a of agents) for (const int of a.integrations) {
|
|
67848
|
+
if (int.platform !== "slack" || int.slack.mode !== "shared") continue;
|
|
67849
|
+
const k = int.slack.botToken;
|
|
67850
|
+
const g = groups.get(k) ?? {
|
|
67851
|
+
appToken: "",
|
|
67852
|
+
botToken: k,
|
|
67853
|
+
integrations: []
|
|
67854
|
+
};
|
|
67855
|
+
g.integrations.push({
|
|
67856
|
+
agentId: a.id,
|
|
67857
|
+
integrationId: int.id
|
|
67858
|
+
});
|
|
67859
|
+
groups.set(k, g);
|
|
67860
|
+
}
|
|
67861
|
+
return groups;
|
|
67862
|
+
}
|
|
67832
67863
|
/** Cap on members enriched per `listChannelMembers` call (bounds users.info fan-out). */
|
|
67833
67864
|
const MEMBER_ENRICH_CAP = 50;
|
|
67834
67865
|
/**
|
|
@@ -67846,6 +67877,25 @@ function markdownBlock(text) {
|
|
|
67846
67877
|
}]
|
|
67847
67878
|
};
|
|
67848
67879
|
}
|
|
67880
|
+
/** Build the send-only {@link AppLike}: a real Slack `WebClient` (xoxb) for the send
|
|
67881
|
+
* surface + inert event/start/stop members (shared-bot-relay.md §11). Same proxy +
|
|
67882
|
+
* timeout/retry tuning as the socket-mode factory. */
|
|
67883
|
+
function sendOnlyApp(botToken) {
|
|
67884
|
+
const proxyUrl = process.env.HTTPS_PROXY ?? process.env.HTTP_PROXY;
|
|
67885
|
+
const agent = proxyUrl ? new HttpsProxyAgent(proxyUrl) : void 0;
|
|
67886
|
+
return {
|
|
67887
|
+
message: () => {},
|
|
67888
|
+
event: () => {},
|
|
67889
|
+
action: () => {},
|
|
67890
|
+
client: new import_dist$1.WebClient(botToken, {
|
|
67891
|
+
...agent ? { agent } : {},
|
|
67892
|
+
timeout: 3e4,
|
|
67893
|
+
retryConfig: { retries: 2 }
|
|
67894
|
+
}),
|
|
67895
|
+
start: async () => {},
|
|
67896
|
+
stop: async () => {}
|
|
67897
|
+
};
|
|
67898
|
+
}
|
|
67849
67899
|
var SlackConnection = class {
|
|
67850
67900
|
deps;
|
|
67851
67901
|
app;
|
|
@@ -67876,7 +67926,7 @@ var SlackConnection = class {
|
|
|
67876
67926
|
this.deps = deps;
|
|
67877
67927
|
this.appToken = deps.group.appToken;
|
|
67878
67928
|
this.botToken = deps.group.botToken;
|
|
67879
|
-
this.app = factory({
|
|
67929
|
+
this.app = deps.sendOnly ? sendOnlyApp(deps.group.botToken) : factory({
|
|
67880
67930
|
token: deps.group.botToken,
|
|
67881
67931
|
appToken: deps.group.appToken
|
|
67882
67932
|
});
|
|
@@ -67890,6 +67940,10 @@ var SlackConnection = class {
|
|
|
67890
67940
|
this.botId = auth.bot_id ?? "";
|
|
67891
67941
|
this.workspaceUrl = auth.url ?? "";
|
|
67892
67942
|
log?.debug(`slack: auth.test ok → bot user ${this.botUserId} (bot_id ${this.botId || "n/a"})`);
|
|
67943
|
+
if (this.deps.sendOnly) {
|
|
67944
|
+
log?.info("slack: send-only connection ready (shared bot — inbound via relay)");
|
|
67945
|
+
return;
|
|
67946
|
+
}
|
|
67893
67947
|
const deliver = (ev, kind) => {
|
|
67894
67948
|
const msg = normalizeSlackEvent(this.withAssistantThread(ev), { traceId: this.deps.newTraceId() });
|
|
67895
67949
|
log?.debug(`slack: inbound ${kind} ch=${msg.channel} thread=${msg.thread ?? "none"} user=${msg.sender.id} isBot=${msg.sender.isBot} isDm=${msg.isDm} mentions=[${msg.mentionedBots.join(",")}] text=${JSON.stringify(msg.text.slice(0, 80))}`);
|
|
@@ -196923,8 +196977,9 @@ var RelayClient = class {
|
|
|
196923
196977
|
}
|
|
196924
196978
|
this.deps.log.debug(`relay(${this.relayId}): ignoring ${frame.type}`);
|
|
196925
196979
|
}
|
|
196926
|
-
/** An inbound rd/msg: dispatch it, reply `rd/ack`; a webchat op
|
|
196927
|
-
*
|
|
196980
|
+
/** An inbound rd/msg: dispatch it, reply `rd/ack`; only a webchat op streams
|
|
196981
|
+
* `rd/chat` back over this socket. A shared-bot `im` replies out-of-band via the
|
|
196982
|
+
* daemon's own Slack send, and a hook fire has no reply stream — both get a noop. */
|
|
196928
196983
|
handleMsg(reqId, msg) {
|
|
196929
196984
|
const chat = msg.source === "webchat" ? (event) => this.sendChat(msg.chatId, event) : () => void 0;
|
|
196930
196985
|
const ack = this.deps.onRelayMsg(msg, chat);
|
|
@@ -197741,8 +197796,10 @@ function toIntegration(spec) {
|
|
|
197741
197796
|
id: spec.integrationId,
|
|
197742
197797
|
platform: "slack",
|
|
197743
197798
|
slack: {
|
|
197799
|
+
mode: spec.slack.mode,
|
|
197744
197800
|
botToken: spec.slack.botToken,
|
|
197745
|
-
appToken: spec.slack.appToken,
|
|
197801
|
+
...spec.slack.appToken ? { appToken: spec.slack.appToken } : {},
|
|
197802
|
+
...spec.slack.botUserId ? { botUserId: spec.slack.botUserId } : {},
|
|
197746
197803
|
allowedUserIds: spec.slack.allowedUserIds,
|
|
197747
197804
|
bindRules: spec.slack.bindRules
|
|
197748
197805
|
}
|
|
@@ -213586,6 +213643,7 @@ var Daemon = class Daemon {
|
|
|
213586
213643
|
agents = /* @__PURE__ */ new Map();
|
|
213587
213644
|
fileAgents = /* @__PURE__ */ new Map();
|
|
213588
213645
|
hosts = /* @__PURE__ */ new Map();
|
|
213646
|
+
hostStartedAt = /* @__PURE__ */ new Map();
|
|
213589
213647
|
connections = [];
|
|
213590
213648
|
telegramConns = [];
|
|
213591
213649
|
discordConns = [];
|
|
@@ -213594,6 +213652,7 @@ var Daemon = class Daemon {
|
|
|
213594
213652
|
scheduler;
|
|
213595
213653
|
sessions;
|
|
213596
213654
|
connByIntegration = /* @__PURE__ */ new Map();
|
|
213655
|
+
sharedSlackConns = /* @__PURE__ */ new Map();
|
|
213597
213656
|
tgConnByIntegration = /* @__PURE__ */ new Map();
|
|
213598
213657
|
dcConnByIntegration = /* @__PURE__ */ new Map();
|
|
213599
213658
|
hostStarts = /* @__PURE__ */ new Map();
|
|
@@ -213819,6 +213878,7 @@ var Daemon = class Daemon {
|
|
|
213819
213878
|
this.slackRetryTimers.set(group.appToken, timer);
|
|
213820
213879
|
}
|
|
213821
213880
|
}
|
|
213881
|
+
await this.openSharedSlackConnections(agents);
|
|
213822
213882
|
await this.reconcileTelegramConnections();
|
|
213823
213883
|
await this.reconcileDiscordConnections();
|
|
213824
213884
|
for (const a of agents) this.scheduler.sync(a.id, a.crons);
|
|
@@ -214014,6 +214074,52 @@ var Daemon = class Daemon {
|
|
|
214014
214074
|
this.log.error(`slack: failed to open runtime socket for appToken — leaving existing sockets intact: ${formatErr(err)}`);
|
|
214015
214075
|
}
|
|
214016
214076
|
}
|
|
214077
|
+
await this.openSharedSlackConnections([...this.agents.values()]);
|
|
214078
|
+
}
|
|
214079
|
+
/**
|
|
214080
|
+
* Open (or reuse) a SEND-ONLY Slack Web-API client per shared bot token and bind
|
|
214081
|
+
* it into `connByIntegration`, so replies / attachment fetches / MCP platform
|
|
214082
|
+
* tools / cron anchors resolve a connection for a `mode:'shared'` integration
|
|
214083
|
+
* (shared-bot-relay.md §11). No Socket Mode socket is opened — the bot's inbound
|
|
214084
|
+
* arrives from the relay as `rd/msg(im)`. Idempotent: an already-open client for
|
|
214085
|
+
* the same xoxb is reused; when a bot flips direct→shared its old direct socket
|
|
214086
|
+
* (same botToken) is stopped so it stops competing with the relay for the single
|
|
214087
|
+
* Socket Mode consumer.
|
|
214088
|
+
*/
|
|
214089
|
+
async openSharedSlackConnections(agents) {
|
|
214090
|
+
const groups = consolidateShared(agents);
|
|
214091
|
+
for (const group of groups.values()) {
|
|
214092
|
+
const staleDirect = this.connections.find((c) => c.botToken === group.botToken && c.appToken !== "");
|
|
214093
|
+
if (staleDirect) {
|
|
214094
|
+
this.log.info(`slack: bot flipped to shared — stopping its direct socket (bot ${staleDirect.botUserId})`);
|
|
214095
|
+
await staleDirect.stop().catch(() => {});
|
|
214096
|
+
this.connections = this.connections.filter((c) => c !== staleDirect);
|
|
214097
|
+
}
|
|
214098
|
+
let conn = this.sharedSlackConns.get(group.botToken);
|
|
214099
|
+
if (!conn) {
|
|
214100
|
+
conn = new SlackConnection({
|
|
214101
|
+
group,
|
|
214102
|
+
sendOnly: true,
|
|
214103
|
+
newTraceId: () => randomUUID(),
|
|
214104
|
+
onMessage: () => {},
|
|
214105
|
+
onStatusAction: (a) => this.handleStatusAction(a),
|
|
214106
|
+
onStatusInfo: (key) => this.statusInfoForKey(key),
|
|
214107
|
+
log: this.log
|
|
214108
|
+
});
|
|
214109
|
+
try {
|
|
214110
|
+
await conn.start();
|
|
214111
|
+
this.sharedSlackConns.set(group.botToken, conn);
|
|
214112
|
+
this.log.info(`slack: send-only (shared) client ready as bot user ${conn.botUserId}`);
|
|
214113
|
+
} catch (err) {
|
|
214114
|
+
this.log.warn(`slack: shared send-only client failed — retry on next reconcile: ${formatErr(err)}`);
|
|
214115
|
+
continue;
|
|
214116
|
+
}
|
|
214117
|
+
}
|
|
214118
|
+
for (const { integrationId } of group.integrations) {
|
|
214119
|
+
this.botUserIds[integrationId] = conn.botUserId;
|
|
214120
|
+
this.connByIntegration.set(integrationId, conn);
|
|
214121
|
+
}
|
|
214122
|
+
}
|
|
214017
214123
|
}
|
|
214018
214124
|
/**
|
|
214019
214125
|
* Reconcile the connection-derived Telegram state (`botUserIds`,
|
|
@@ -214238,6 +214344,7 @@ var Daemon = class Daemon {
|
|
|
214238
214344
|
});
|
|
214239
214345
|
}
|
|
214240
214346
|
this.hosts.set(agentId, host);
|
|
214347
|
+
this.hostStartedAt.set(agentId, this.clock.now());
|
|
214241
214348
|
return host;
|
|
214242
214349
|
}
|
|
214243
214350
|
/** The bare Telegram message id from a normalized `telegram:<chatId>:<messageId>`
|
|
@@ -214554,12 +214661,35 @@ var Daemon = class Daemon {
|
|
|
214554
214661
|
this.log.debug(`relay: duplicate rd/msg ${dedupKey} — replaying ack (no re-dispatch)`);
|
|
214555
214662
|
return prior;
|
|
214556
214663
|
}
|
|
214557
|
-
const ack = msg.source === "
|
|
214664
|
+
const ack = msg.source === "webchat" ? this.dispatchRelayOp(msg, chat) : msg.source === "im" ? this.handleRelayIm(msg) : this.dispatchRelayHook(msg);
|
|
214558
214665
|
if (this.relayMsgAcks.size >= 2e3) this.relayMsgAcks.clear();
|
|
214559
214666
|
this.relayMsgAcks.set(dedupKey, ack);
|
|
214560
214667
|
return ack;
|
|
214561
214668
|
}
|
|
214562
214669
|
/**
|
|
214670
|
+
* A shared-bot inbound (`rd/msg` `im`): the relay already arbitrated the target
|
|
214671
|
+
* agent + integration, so this is the explicit-agent path — no local routing. The
|
|
214672
|
+
* reply flows out-of-band through the agent's send-only Slack connection
|
|
214673
|
+
* (`replyConnFor`), NOT `rd/chat` (that is webchat-only). The `rd/ack` is a plain
|
|
214674
|
+
* receipt; the turn runs async.
|
|
214675
|
+
*/
|
|
214676
|
+
handleRelayIm(msg) {
|
|
214677
|
+
if (!this.agents.get(msg.agentId)) {
|
|
214678
|
+
this.log.warn(`relay: rd/msg(im) for unknown agent ${msg.agentId} — dropping`);
|
|
214679
|
+
return {
|
|
214680
|
+
msgId: msg.msgId,
|
|
214681
|
+
accepted: false,
|
|
214682
|
+
reason: "no_agent"
|
|
214683
|
+
};
|
|
214684
|
+
}
|
|
214685
|
+
const normalized = msg.payload;
|
|
214686
|
+
this.dispatch(msg.agentId, normalized, msg.integrationId).catch((err) => this.log.error(`relay im dispatch failed for agent "${msg.agentId}": ${formatErr(err)}`));
|
|
214687
|
+
return {
|
|
214688
|
+
msgId: msg.msgId,
|
|
214689
|
+
accepted: true
|
|
214690
|
+
};
|
|
214691
|
+
}
|
|
214692
|
+
/**
|
|
214563
214693
|
* Ack-verdict gate for one hook fire (`rd/msg` hook member) — the mirror of
|
|
214564
214694
|
* {@link dispatchWebchatTurn}'s synchronous gates: the relay's rc/run-report
|
|
214565
214695
|
* needs a REASONED rejection now, not a silently dropped fire-and-forget
|
|
@@ -215241,7 +215371,7 @@ var Daemon = class Daemon {
|
|
|
215241
215371
|
});
|
|
215242
215372
|
} else {
|
|
215243
215373
|
const link = this.sessionLink(sessionId);
|
|
215244
|
-
const finals = conv instanceof TelegramConverger || conv instanceof DiscordConverger ? conv.onFinal(link) : conv.onFinal(link, this.webAppBase());
|
|
215374
|
+
const finals = conv instanceof TelegramConverger || conv instanceof DiscordConverger ? conv.onFinal(link) : conv.onFinal(link, this.webAppBase(), this.sharedFooterFor(agentId, integrationId));
|
|
215245
215375
|
for (const action of finals) this.enqueueApply(p, action);
|
|
215246
215376
|
}
|
|
215247
215377
|
for (const ev of rec.onFinal()) this.recordEvent(agentId, msg.channel, statusThread, ev);
|
|
@@ -215540,6 +215670,27 @@ var Daemon = class Daemon {
|
|
|
215540
215670
|
const orgSeg = this.cpOrgSlug ? `/${encodeURIComponent(this.cpOrgSlug)}` : "";
|
|
215541
215671
|
return `${this.webAppBase()}${orgSeg}/sessions/${acpSessionId}`;
|
|
215542
215672
|
}
|
|
215673
|
+
/** The console deep link to an agent: `<base>/<orgSlug>/agents/<agentId>` — the
|
|
215674
|
+
* shared-bot footer's "sent by <agent_name>" link (§10.1). Same org-seg rule as
|
|
215675
|
+
* {@link sessionLink}. */
|
|
215676
|
+
agentLink(agentId) {
|
|
215677
|
+
const orgSeg = this.cpOrgSlug ? `/${encodeURIComponent(this.cpOrgSlug)}` : "";
|
|
215678
|
+
return `${this.webAppBase()}${orgSeg}/agents/${agentId}`;
|
|
215679
|
+
}
|
|
215680
|
+
/** The shared-bot footer context for a turn, or undefined when this isn't a shared
|
|
215681
|
+
* Slack channel (then the classic "sent by agentconnect.md" footer is used). A
|
|
215682
|
+
* shared integration (`slack.mode==='shared'`) means the bot's inbound rode the
|
|
215683
|
+
* relay, so the footer attributes the specific agent + offers the config button. */
|
|
215684
|
+
sharedFooterFor(agentId, integrationId) {
|
|
215685
|
+
if (!integrationId) return void 0;
|
|
215686
|
+
const agent = this.agents.get(agentId);
|
|
215687
|
+
const int = agent?.integrations.find((i) => i.id === integrationId);
|
|
215688
|
+
if (!int || int.platform !== "slack" || int.slack.mode !== "shared") return void 0;
|
|
215689
|
+
return {
|
|
215690
|
+
agentName: agent?.name ?? agentId,
|
|
215691
|
+
agentUrl: this.agentLink(agentId)
|
|
215692
|
+
};
|
|
215693
|
+
}
|
|
215543
215694
|
/** The Web App console origin (trailing slash stripped): the explicit local `webAppUrl`,
|
|
215544
215695
|
* else the CP-provided origin, else the public default. Backs both the session deep link
|
|
215545
215696
|
* and the per-turn "sent by agentconnect.md" attribution footer. Always resolves. */
|
|
@@ -215901,6 +216052,7 @@ var Daemon = class Daemon {
|
|
|
215901
216052
|
const host = this.hosts.get(agentId);
|
|
215902
216053
|
this.hosts.delete(agentId);
|
|
215903
216054
|
this.hostStarts.delete(agentId);
|
|
216055
|
+
this.hostStartedAt.delete(agentId);
|
|
215904
216056
|
if (!host) return;
|
|
215905
216057
|
const stop = host.stop(deadlineMs).finally(() => {
|
|
215906
216058
|
if (this.hostStopping.get(agentId) === stop) this.hostStopping.delete(agentId);
|
|
@@ -215942,7 +216094,7 @@ var Daemon = class Daemon {
|
|
|
215942
216094
|
for (const [agentId] of [...this.hosts]) {
|
|
215943
216095
|
if (this.drainingAgents.has(agentId)) continue;
|
|
215944
216096
|
if ([...this.pending.values()].some((p) => p.agentId === agentId)) continue;
|
|
215945
|
-
const last = this.store.agentLastActivityTs(agentId) ?? 0;
|
|
216097
|
+
const last = Math.max(this.store.agentLastActivityTs(agentId) ?? 0, this.hostStartedAt.get(agentId) ?? 0);
|
|
215946
216098
|
if (now - last <= ttl) continue;
|
|
215947
216099
|
this.log.info(`idle: reclaiming host "${agentId}" (idle ${Math.round((now - last) / 1e3)}s) → provisioned`);
|
|
215948
216100
|
this.stopHost(agentId).catch((err) => this.log.error(`idle: stop host "${agentId}" failed: ${formatErr(err)}`));
|
|
@@ -216447,4 +216599,4 @@ async function runForeground(opts, deps = {}) {
|
|
|
216447
216599
|
//#endregion
|
|
216448
216600
|
export { ClientTransport as i, CP_SUBPROTOCOL as n, CP_WS_PATH as r, runForeground as t };
|
|
216449
216601
|
|
|
216450
|
-
//# sourceMappingURL=run-foreground-
|
|
216602
|
+
//# sourceMappingURL=run-foreground-BqNCGDXc.js.map
|