@cursor/july 0.1.19 → 0.1.21
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/AGENTS.md +10 -0
- package/dist/bin/agent-serve.js +0 -0
- package/dist/channels/github/instrument.d.ts +20 -0
- package/dist/channels/github/instrument.d.ts.map +1 -0
- package/dist/channels/slack/api.d.ts +2 -0
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +3 -0
- package/dist/channels/slack/bot-mentions.d.ts +106 -0
- package/dist/channels/slack/bot-mentions.d.ts.map +1 -0
- package/dist/channels/slack/bot-mentions.js +243 -0
- package/dist/channels/slack/dispatch.d.ts +6 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +24 -3
- package/dist/channels/slack/inbound.d.ts +10 -1
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +12 -4
- package/dist/channels/slack/index.d.ts +1 -0
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +1 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +61 -22
- package/dist/channels/slack/types.d.ts +58 -0
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +1 -1
- package/dist/docs/ab.html +2 -2
- package/dist/docs/assets/{app.CrsWMchO.js → app.jDxLzWv4.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DoJHJjqF.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.D1JqzSh8.js → VPLocalSearchBox.Y6bDR1-a.js} +1 -1
- package/dist/docs/assets/chunks/{theme.DaBvZYwl.js → theme.CLazCWlJ.js} +2 -2
- package/dist/docs/building-with-agents.html +2 -2
- package/dist/docs/concepts.html +2 -2
- package/dist/docs/deployment.html +2 -2
- package/dist/docs/evals.html +2 -2
- package/dist/docs/example-agents/approval-buddy.html +2 -2
- package/dist/docs/example-agents/benny.html +2 -2
- package/dist/docs/example-agents/bugbot.html +2 -2
- package/dist/docs/example-agents/codebase-wiki.html +2 -2
- package/dist/docs/example-agents/codeowners-review.html +2 -2
- package/dist/docs/example-agents/concierge.html +2 -2
- package/dist/docs/example-agents/fsd.html +2 -2
- package/dist/docs/example-agents/index.html +2 -2
- package/dist/docs/example-agents/knowledge-base.html +2 -2
- package/dist/docs/example-agents/oncall.html +2 -2
- package/dist/docs/example-agents/security-reviewer.html +2 -2
- package/dist/docs/example-agents/slack-agent.html +2 -2
- package/dist/docs/example-agents/weather-agent.html +2 -2
- package/dist/docs/guides/agent-to-agent.html +2 -2
- package/dist/docs/guides/cloud-runtime.html +2 -2
- package/dist/docs/guides/github.html +2 -2
- package/dist/docs/guides/human-in-the-loop.html +2 -2
- package/dist/docs/guides/mcp-oauth.html +2 -2
- package/dist/docs/guides/slack.html +2 -2
- package/dist/docs/guides/webhooks.html +2 -2
- package/dist/docs/hillclimbing.html +2 -2
- package/dist/docs/index.html +2 -2
- package/dist/docs/quickstart.html +2 -2
- package/dist/docs/reference/agent-config.html +2 -2
- package/dist/docs/reference/channels.html +2 -2
- package/dist/docs/reference/cli.html +2 -2
- package/dist/docs/reference/connections.html +2 -2
- package/dist/docs/reference/hooks.html +2 -2
- package/dist/docs/reference/http-api.html +2 -2
- package/dist/docs/reference/instructions.html +2 -2
- package/dist/docs/reference/playground.html +2 -2
- package/dist/docs/reference/project-layout.html +2 -2
- package/dist/docs/reference/prompt.html +2 -2
- package/dist/docs/reference/schedules.html +2 -2
- package/dist/docs/reference/sessions.html +2 -2
- package/dist/docs/reference/skills.html +2 -2
- package/dist/docs/reference/subagents.html +2 -2
- package/dist/docs/reference/tools.html +2 -2
- package/dist/docs/scaffolding-agents.html +2 -2
- package/dist/docs/storage.html +2 -2
- package/dist/docs/troubleshooting.html +2 -2
- package/dist/internal/json-dir-store.d.ts +32 -0
- package/dist/internal/json-dir-store.d.ts.map +1 -0
- package/dist/internal/json-dir-store.js +100 -0
- package/dist/internal/resolved-connections.d.ts +1 -1
- package/dist/internal/resolved-connections.d.ts.map +1 -1
- package/dist/internal/resolved-connections.js +10 -0
- package/dist/internal/session-engine.d.ts +4 -1
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +13 -2
- package/dist/playground/assets/index-CjOQ4hN9.css +1 -0
- package/dist/playground/assets/{index-C2SU2xV5.js → index-dshZQJCp.js} +46 -46
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -0
- package/package.json +25 -25
- package/skills/create-agent/SKILL.md +36 -4
- package/skills/evals/SKILL.md +3 -0
- package/skills/framework-map/SKILL.md +14 -0
- package/skills/github/SKILL.md +6 -1
- package/skills/hillclimb/SKILL.md +28 -7
- package/src/bin/agent-serve.version.test.ts +62 -0
- package/src/channels/github/api.test.ts +64 -0
- package/src/channels/github/auth.test.ts +105 -0
- package/src/channels/github/cursor-account.test.ts +204 -0
- package/src/channels/github/forward.test.ts +457 -0
- package/src/channels/github/github.test.ts +937 -0
- package/src/channels/github/replay.test.ts +179 -0
- package/src/channels/slack/api.post-message.test.ts +148 -0
- package/src/channels/slack/api.ts +5 -0
- package/src/channels/slack/approvals.test.ts +328 -0
- package/src/channels/slack/block-actions.test.ts +452 -0
- package/src/channels/slack/bot-mentions.test.ts +217 -0
- package/src/channels/slack/bot-mentions.ts +315 -0
- package/src/channels/slack/channel-watch.test.ts +363 -0
- package/src/channels/slack/cursor-account.test.ts +253 -0
- package/src/channels/slack/defaults.final-post.test.ts +182 -0
- package/src/channels/slack/dispatch.test.ts +795 -0
- package/src/channels/slack/dispatch.ts +27 -1
- package/src/channels/slack/eval-directive.test.ts +273 -0
- package/src/channels/slack/inbound.ts +25 -4
- package/src/channels/slack/index.ts +1 -0
- package/src/channels/slack/message-body.test.ts +54 -0
- package/src/channels/slack/nudge-store.test.ts +143 -0
- package/src/channels/slack/slack-channel.ts +66 -8
- package/src/channels/slack/slack.test.ts +391 -0
- package/src/channels/slack/stop.test.ts +23 -0
- package/src/channels/slack/thread-context.test.ts +202 -0
- package/src/channels/slack/types.ts +60 -0
- package/src/evals/assertions.test.ts +580 -0
- package/src/evals/expect.test.ts +144 -0
- package/src/evals/judge.test.ts +181 -0
- package/src/evals/loaders.test.ts +132 -0
- package/src/evals/matchers.test.ts +95 -0
- package/src/evals/reporters.test.ts +303 -0
- package/src/evals/run-facts.test.ts +259 -0
- package/src/internal/ab-snapshot.test.ts +325 -0
- package/src/internal/approval-gate.test.ts +49 -0
- package/src/internal/approvals.integration.test.ts +383 -0
- package/src/internal/authored-loaders.test.ts +31 -0
- package/src/internal/builtin-tools/reminders.test.ts +201 -0
- package/src/internal/channel-route-schema.test.ts +294 -0
- package/src/internal/chat-attach.test.ts +262 -0
- package/src/internal/cli-deploy.test.ts +1991 -0
- package/src/internal/cli-mcp.test.ts +789 -0
- package/src/internal/cli-skills.test.ts +133 -0
- package/src/internal/cli-slack.test.ts +1647 -0
- package/src/internal/cloud-merge.test.ts +74 -0
- package/src/internal/cron.test.ts +22 -0
- package/src/internal/cursor/account-mcp.test.ts +807 -0
- package/src/internal/cursor/backend-client.test.ts +591 -0
- package/src/internal/cursor/credentials.test.ts +351 -0
- package/src/internal/cursor/github-credentials.test.ts +136 -0
- package/src/internal/cursor-account-mcp-auth.test.ts +310 -0
- package/src/internal/cursor-account.integration.test.ts +441 -0
- package/src/internal/cursor-event-relay.test.ts +746 -0
- package/src/internal/cursor-github-credentials.integration.test.ts +271 -0
- package/src/internal/cursor-slack-relay.test.ts +525 -0
- package/src/internal/deploy-source.test.ts +111 -0
- package/src/internal/discovery.builtin-tools.test.ts +94 -0
- package/src/internal/discovery.concurrency.test.ts +60 -0
- package/src/internal/discovery.cursor-account.test.ts +133 -0
- package/src/internal/discovery.cwd.test.ts +83 -0
- package/src/internal/discovery.hosting.test.ts +80 -0
- package/src/internal/discovery.identity.test.ts +44 -0
- package/src/internal/docs-site.test.ts +66 -0
- package/src/internal/duration.test.ts +29 -0
- package/src/internal/eval-judge-model.test.ts +187 -0
- package/src/internal/eval-run-store.cancel.test.ts +142 -0
- package/src/internal/eval-run-store.storage.test.ts +211 -0
- package/src/internal/eval-runner.http.test.ts +403 -0
- package/src/internal/eval-runner.run.test.ts +928 -0
- package/src/internal/evals-client.test.ts +307 -0
- package/src/internal/event-mapper.test.ts +243 -0
- package/src/internal/github-fanout.test.ts +213 -0
- package/src/internal/handleAgentServeTrigger.test.ts +179 -0
- package/src/internal/host-kv.test.ts +82 -0
- package/src/internal/host-platforms.test.ts +126 -0
- package/src/internal/http-channel.test.ts +402 -0
- package/src/internal/init-project.test.ts +269 -0
- package/src/internal/install-cursor-skills.test.ts +262 -0
- package/src/internal/local-env.test.ts +100 -0
- package/src/internal/log-ring.test.ts +31 -0
- package/src/internal/logs-client.test.ts +350 -0
- package/src/internal/mcp-endpoint.test.ts +436 -0
- package/src/internal/mcp-host.test.ts +298 -0
- package/src/internal/mcp-oauth.test.ts +148 -0
- package/src/internal/net.test.ts +17 -0
- package/src/internal/peer-connections.test.ts +128 -0
- package/src/internal/peer-mcp.integration.test.ts +289 -0
- package/src/internal/playground/toolchain.test.ts +53 -0
- package/src/internal/playground-cli.test.ts +187 -0
- package/src/internal/playground-proxy.test.ts +376 -0
- package/src/internal/prompt-context.integration.test.ts +232 -0
- package/src/internal/prompt-context.test.ts +127 -0
- package/src/internal/reminder-runner.test.ts +390 -0
- package/src/internal/reminder-store.test.ts +53 -0
- package/src/internal/request-headers.test.ts +27 -0
- package/src/internal/resolve-prod-target.test.ts +787 -0
- package/src/internal/resolved-connections.test.ts +295 -0
- package/src/internal/resolved-connections.ts +18 -1
- package/src/internal/router.test.ts +57 -0
- package/src/internal/sdk-runner.test.ts +290 -0
- package/src/internal/session-engine.coalesce.test.ts +169 -0
- package/src/internal/session-engine.concurrency.test.ts +250 -0
- package/src/internal/session-engine.host-oauth-mcp.test.ts +110 -0
- package/src/internal/session-engine.interrupt.test.ts +577 -0
- package/src/internal/session-engine.storage.test.ts +547 -0
- package/src/internal/session-engine.ts +15 -1
- package/src/internal/session-urls.test.ts +28 -0
- package/src/internal/sessions-client.test.ts +518 -0
- package/src/internal/storage-coordinator.test.ts +517 -0
- package/src/internal/tool-call.test.ts +458 -0
- package/src/internal/tool-result.test.ts +52 -0
- package/src/internal/trajectory.approvals.test.ts +83 -0
- package/src/internal/trajectory.subagents.test.ts +198 -0
- package/src/internal/turn-governor.test.ts +137 -0
- package/src/internal/update-check.test.ts +485 -0
- package/src/internal/workspace.test.ts +81 -0
- package/src/storage-backends/cursor-hosted.test.ts +121 -0
- package/src/types.ts +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.BnHRjfoe.js +0 -1
- package/dist/playground/assets/index-CidizGZv.css +0 -1
package/AGENTS.md
CHANGED
|
@@ -303,6 +303,16 @@ Fixtures still work for offline replay: `POST` a saved payload with an
|
|
|
303
303
|
part of a code change. Docs are written intentionally, on explicit request
|
|
304
304
|
only — never as a side effect of a feature or fix. If a change makes docs
|
|
305
305
|
stale, say so in the PR description instead of editing them unprompted.
|
|
306
|
+
- Grow an agent's deterministic path by default. Host code owns side-effect
|
|
307
|
+
gates and actuation, dedupe of external writes, auth, evidence seeding,
|
|
308
|
+
and hard API caps; formatting, summarizing, classification, and reply
|
|
309
|
+
composition stay with the model under an output contract in
|
|
310
|
+
`instructions.md` / skills (prose in `.md`, never TS string builders).
|
|
311
|
+
Speculative caches (prefetch, fingerprint dedupe, write coalescing) need
|
|
312
|
+
measured pressure first, and framework gaps (posting, chunking, retries)
|
|
313
|
+
get fixed or filed in the framework, not worked around in `agent/lib/`.
|
|
314
|
+
Budget + smells: `skills/create-agent/SKILL.md` § "The deterministic-path
|
|
315
|
+
budget".
|
|
306
316
|
- Put durable `--state-root` inside a large monorepo if you care about
|
|
307
317
|
ambient `AGENTS.md` / `.cursor` rules leaking into the agent workspace.
|
|
308
318
|
Prefer `defineAgent({ local: { cwd } })` pointing outside the monorepo
|
package/dist/bin/agent-serve.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request observability for GitHub channel Octokit clients.
|
|
3
|
+
*
|
|
4
|
+
* Every Octokit built by `createGitHubOctokit` / `callGitHubApi` gets one
|
|
5
|
+
* structured `[agentkit/github]` line per GitHub API request (REST and
|
|
6
|
+
* GraphQL), including rate-limit headers so installation-quota pressure can
|
|
7
|
+
* be attributed to agentkit deployments from hosted-runtime logs.
|
|
8
|
+
*/
|
|
9
|
+
import type { Octokit } from "@octokit/rest";
|
|
10
|
+
export type GitHubRequestLogWrite = (line: string) => void;
|
|
11
|
+
/** Best-effort GraphQL operation name (`query Foo` / `mutation Bar`). */
|
|
12
|
+
export declare function parseGraphQLOperationName(query: unknown): string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Wrap an Octokit so every request emits one structured log line. Returns
|
|
15
|
+
* the same instance for call-through convenience. Idempotent per instance.
|
|
16
|
+
*/
|
|
17
|
+
export declare function instrumentGitHubOctokit(octokit: Octokit, input?: {
|
|
18
|
+
write?: GitHubRequestLogWrite;
|
|
19
|
+
}): Octokit;
|
|
20
|
+
//# sourceMappingURL=instrument.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument.d.ts","sourceRoot":"","sources":["../../../src/channels/github/instrument.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AA4C3D,yEAAyE;AACzE,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQ5E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,EAChB,KAAK,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,qBAAqB,CAAA;CAAE,GACxC,OAAO,CAmDT"}
|
|
@@ -90,6 +90,8 @@ export declare function postMessage(args: {
|
|
|
90
90
|
* `markdown_text` hard-caps at 12k while `text` allows ~40k.
|
|
91
91
|
*/
|
|
92
92
|
plainText?: boolean;
|
|
93
|
+
/** Slack message metadata (`{ event_type, event_payload }`). */
|
|
94
|
+
metadata?: Record<string, unknown>;
|
|
93
95
|
}): Promise<{
|
|
94
96
|
ts: string;
|
|
95
97
|
channel: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/api.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -261,6 +261,9 @@ export function postMessage(args) {
|
|
|
261
261
|
if (args.threadTs !== undefined && args.threadTs !== "") {
|
|
262
262
|
base.thread_ts = args.threadTs;
|
|
263
263
|
}
|
|
264
|
+
if (args.metadata !== undefined) {
|
|
265
|
+
base.metadata = args.metadata;
|
|
266
|
+
}
|
|
264
267
|
const hasBlocks = args.blocks !== undefined && args.blocks.length > 0;
|
|
265
268
|
// User-group mentions (`<!subteam^…>`) and Slack mrkdwn links
|
|
266
269
|
// (`<https://…|label>`) only render correctly via mrkdwn `text`,
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in bot-to-bot mention wake (`engagement.botMentions`).
|
|
3
|
+
*
|
|
4
|
+
* Layered loop protection, any one of which blocks a runaway chain:
|
|
5
|
+
* 1. Allowlist — only mentions from explicitly trusted bots wake the agent.
|
|
6
|
+
* 2. Own-post filter — the agent's own posts never wake it (always on).
|
|
7
|
+
* 3. Depth budget — delegation metadata carries a hop count; mentions
|
|
8
|
+
* without metadata count as depth 1. Default max is 2.
|
|
9
|
+
* 4. Thread budgets — a sliding-window rate cap plus a lifetime total per
|
|
10
|
+
* thread, so undetected ping-pong between trusted bots terminates
|
|
11
|
+
* instead of merely slowing down.
|
|
12
|
+
*/
|
|
13
|
+
import { type SlackLog } from "./log.js";
|
|
14
|
+
import type { SlackBotMentionsOptions, SlackBotToken, SlackDelegationInfo, SlackMessage } from "./types.js";
|
|
15
|
+
/** Slack message `metadata.event_type` for agentkit delegation posts. */
|
|
16
|
+
export declare const SLACK_DELEGATION_METADATA_EVENT_TYPE = "agentkit_delegation";
|
|
17
|
+
/** Default budgets for {@link SlackBotMentionsOptions}. */
|
|
18
|
+
export declare const SLACK_BOT_MENTION_DEFAULTS: {
|
|
19
|
+
readonly maxDepth: 2;
|
|
20
|
+
readonly maxPerThreadPerHour: 5;
|
|
21
|
+
readonly maxPerThreadTotal: 20;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Parse delegation metadata off a raw Slack event (`event.metadata`).
|
|
25
|
+
* Returns undefined for absent, foreign, or malformed metadata.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseDelegationMetadata(event: unknown): SlackDelegationInfo | undefined;
|
|
28
|
+
/** Build the Slack `metadata` body for an outbound delegation post. */
|
|
29
|
+
export declare function buildDelegationMetadata(args: {
|
|
30
|
+
depth: number;
|
|
31
|
+
fromAgent?: string;
|
|
32
|
+
originSessionId?: string;
|
|
33
|
+
}): Record<string, unknown>;
|
|
34
|
+
/**
|
|
35
|
+
* Validate and normalize a `botMentions.allowFrom` list. Shared by channel
|
|
36
|
+
* construction (fail at definition time) and the gate (fail at start).
|
|
37
|
+
*/
|
|
38
|
+
export declare function normalizeBotMentionAllowlist(allowFrom: readonly string[]): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Read `engagement.botMentions` options from the environment: a
|
|
41
|
+
* comma-separated bot-id allowlist in `AGENT_DELEGATOR_SLACK_BOT_IDS` (or a
|
|
42
|
+
* custom var). Returns undefined when unset, so channels can pass the
|
|
43
|
+
* result straight through and stay bot-mention-free by default:
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* engagement: { botMentions: botMentionsFromEnv() }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function botMentionsFromEnv(envVar?: string): SlackBotMentionsOptions | undefined;
|
|
50
|
+
export type SlackBotMentionVerdict = {
|
|
51
|
+
allow: true;
|
|
52
|
+
depth: number;
|
|
53
|
+
} | {
|
|
54
|
+
allow: false;
|
|
55
|
+
reason: string;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Admission gate for bot-authored mentions. One instance per channel;
|
|
59
|
+
* thread budgets are in-memory (reset on restart — acceptable, the depth
|
|
60
|
+
* and allowlist layers do not depend on process state). Threads idle for
|
|
61
|
+
* 24h are evicted, which also resets their lifetime budget.
|
|
62
|
+
*/
|
|
63
|
+
export declare class SlackBotMentionGate {
|
|
64
|
+
private readonly identity;
|
|
65
|
+
private readonly allowFrom;
|
|
66
|
+
private readonly maxDepth;
|
|
67
|
+
private readonly maxPerThreadPerHour;
|
|
68
|
+
private readonly maxPerThreadTotal;
|
|
69
|
+
private readonly windowMs;
|
|
70
|
+
private readonly threadBudgets;
|
|
71
|
+
private readonly log;
|
|
72
|
+
constructor(options: SlackBotMentionsOptions, identity: {
|
|
73
|
+
botUserId?: string;
|
|
74
|
+
botId?: string;
|
|
75
|
+
}, args?: {
|
|
76
|
+
log?: SlackLog;
|
|
77
|
+
windowMs?: number;
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* Evaluate a bot-authored mention. Callers must only pass messages whose
|
|
81
|
+
* author `isBot`; human mentions never consult the gate. An `allow`
|
|
82
|
+
* verdict consumes thread budget.
|
|
83
|
+
*/
|
|
84
|
+
evaluate(message: SlackMessage, nowMs?: number): SlackBotMentionVerdict;
|
|
85
|
+
private maybeEvictIdleThreads;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Post an @mention of another bot with delegation metadata attached, so the
|
|
89
|
+
* target's `engagement.botMentions` gate can read the hop count. Use this
|
|
90
|
+
* from dispatcher tools instead of a bare `chat.postMessage`.
|
|
91
|
+
*/
|
|
92
|
+
export declare function postDelegationMention(args: {
|
|
93
|
+
botToken: SlackBotToken | undefined;
|
|
94
|
+
channelId: string;
|
|
95
|
+
/** Target bot's Slack *user* id (`U…`) — what `<@…>` mentions require. */
|
|
96
|
+
targetUserId: string;
|
|
97
|
+
text: string;
|
|
98
|
+
threadTs?: string;
|
|
99
|
+
/** Defaults to 1 (dispatcher woken by a human). */
|
|
100
|
+
depth?: number;
|
|
101
|
+
fromAgent?: string;
|
|
102
|
+
originSessionId?: string;
|
|
103
|
+
}): Promise<{
|
|
104
|
+
ts: string;
|
|
105
|
+
}>;
|
|
106
|
+
//# sourceMappingURL=bot-mentions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-mentions.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/bot-mentions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EACb,mBAAmB,EACnB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,yEAAyE;AACzE,eAAO,MAAM,oCAAoC,wBAAwB,CAAC;AAE1E,2DAA2D;AAC3D,eAAO,MAAM,0BAA0B;aACrC,QAAQ,EAAE,CAAC;aACX,mBAAmB,EAAE,CAAC;aACtB,iBAAiB,EAAE,EAAE;CACb,CAAC;AAeX;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,GACb,mBAAmB,GAAG,SAAS,CA+BjC;AAED,uEAAuE;AACvE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAY1B;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,MAAM,EAAE,CAUV;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,SAAkC,GACvC,uBAAuB,GAAG,SAAS,CAMrC;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAUrC;;;;;GAKG;AACH,qBAAa,mBAAmB;IAW5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAV3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;IACjE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAW;IAE/B,YACE,OAAO,EAAE,uBAAuB,EACf,QAAQ,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EACjE,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,QAAQ,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAgB7C;IAED;;;;OAIG;IACH,QAAQ,CACN,OAAO,EAAE,YAAY,EACrB,KAAK,GAAE,MAAmB,GACzB,sBAAsB,CAkExB;IAED,OAAO,CAAC,qBAAqB;CAU9B;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,QAAQ,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB1B"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in bot-to-bot mention wake (`engagement.botMentions`).
|
|
3
|
+
*
|
|
4
|
+
* Layered loop protection, any one of which blocks a runaway chain:
|
|
5
|
+
* 1. Allowlist — only mentions from explicitly trusted bots wake the agent.
|
|
6
|
+
* 2. Own-post filter — the agent's own posts never wake it (always on).
|
|
7
|
+
* 3. Depth budget — delegation metadata carries a hop count; mentions
|
|
8
|
+
* without metadata count as depth 1. Default max is 2.
|
|
9
|
+
* 4. Thread budgets — a sliding-window rate cap plus a lifetime total per
|
|
10
|
+
* thread, so undetected ping-pong between trusted bots terminates
|
|
11
|
+
* instead of merely slowing down.
|
|
12
|
+
*/
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
import { postMessage } from "./api.js";
|
|
23
|
+
import { defaultSlackLog } from "./log.js";
|
|
24
|
+
/** Slack message `metadata.event_type` for agentkit delegation posts. */
|
|
25
|
+
export const SLACK_DELEGATION_METADATA_EVENT_TYPE = "agentkit_delegation";
|
|
26
|
+
/** Default budgets for {@link SlackBotMentionsOptions}. */
|
|
27
|
+
export const SLACK_BOT_MENTION_DEFAULTS = {
|
|
28
|
+
maxDepth: 2,
|
|
29
|
+
maxPerThreadPerHour: 5,
|
|
30
|
+
maxPerThreadTotal: 20,
|
|
31
|
+
};
|
|
32
|
+
const THREAD_BUDGET_WINDOW_MS = 60 * 60 * 1000;
|
|
33
|
+
/** Threads idle this long are evicted (their lifetime budget resets). */
|
|
34
|
+
const THREAD_IDLE_EVICT_MS = 24 * 60 * 60 * 1000;
|
|
35
|
+
/** Eviction sweep runs when the thread map grows past this many keys. */
|
|
36
|
+
const THREAD_SWEEP_THRESHOLD = 512;
|
|
37
|
+
function asRecord(value) {
|
|
38
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parse delegation metadata off a raw Slack event (`event.metadata`).
|
|
45
|
+
* Returns undefined for absent, foreign, or malformed metadata.
|
|
46
|
+
*/
|
|
47
|
+
export function parseDelegationMetadata(event) {
|
|
48
|
+
const root = asRecord(event);
|
|
49
|
+
const metadata = asRecord(root === null || root === void 0 ? void 0 : root.metadata);
|
|
50
|
+
if (metadata === null ||
|
|
51
|
+
metadata.event_type !== SLACK_DELEGATION_METADATA_EVENT_TYPE) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
const payload = asRecord(metadata.event_payload);
|
|
55
|
+
if (payload === null) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
const depth = typeof payload.depth === "number" && Number.isFinite(payload.depth)
|
|
59
|
+
? Math.floor(payload.depth)
|
|
60
|
+
: undefined;
|
|
61
|
+
if (depth === undefined || depth < 1) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const info = { depth };
|
|
65
|
+
if (typeof payload.from_agent === "string" && payload.from_agent !== "") {
|
|
66
|
+
info.fromAgent = payload.from_agent;
|
|
67
|
+
}
|
|
68
|
+
if (typeof payload.origin_session_id === "string" &&
|
|
69
|
+
payload.origin_session_id !== "") {
|
|
70
|
+
info.originSessionId = payload.origin_session_id;
|
|
71
|
+
}
|
|
72
|
+
return info;
|
|
73
|
+
}
|
|
74
|
+
/** Build the Slack `metadata` body for an outbound delegation post. */
|
|
75
|
+
export function buildDelegationMetadata(args) {
|
|
76
|
+
const payload = { depth: args.depth };
|
|
77
|
+
if (args.fromAgent !== undefined && args.fromAgent !== "") {
|
|
78
|
+
payload.from_agent = args.fromAgent;
|
|
79
|
+
}
|
|
80
|
+
if (args.originSessionId !== undefined && args.originSessionId !== "") {
|
|
81
|
+
payload.origin_session_id = args.originSessionId;
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
event_type: SLACK_DELEGATION_METADATA_EVENT_TYPE,
|
|
85
|
+
event_payload: payload,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Validate and normalize a `botMentions.allowFrom` list. Shared by channel
|
|
90
|
+
* construction (fail at definition time) and the gate (fail at start).
|
|
91
|
+
*/
|
|
92
|
+
export function normalizeBotMentionAllowlist(allowFrom) {
|
|
93
|
+
const entries = allowFrom
|
|
94
|
+
.map((entry) => entry.trim())
|
|
95
|
+
.filter((entry) => entry !== "");
|
|
96
|
+
if (entries.length === 0) {
|
|
97
|
+
throw new Error("slackChannel engagement.botMentions.allowFrom must list at least one bot id (B…) or bot user id (U…); there is no wildcard.");
|
|
98
|
+
}
|
|
99
|
+
return entries;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Read `engagement.botMentions` options from the environment: a
|
|
103
|
+
* comma-separated bot-id allowlist in `AGENT_DELEGATOR_SLACK_BOT_IDS` (or a
|
|
104
|
+
* custom var). Returns undefined when unset, so channels can pass the
|
|
105
|
+
* result straight through and stay bot-mention-free by default:
|
|
106
|
+
*
|
|
107
|
+
* ```ts
|
|
108
|
+
* engagement: { botMentions: botMentionsFromEnv() }
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export function botMentionsFromEnv(envVar = "AGENT_DELEGATOR_SLACK_BOT_IDS") {
|
|
112
|
+
var _a;
|
|
113
|
+
const allowFrom = ((_a = process.env[envVar]) !== null && _a !== void 0 ? _a : "")
|
|
114
|
+
.split(",")
|
|
115
|
+
.map((entry) => entry.trim())
|
|
116
|
+
.filter((entry) => entry !== "");
|
|
117
|
+
return allowFrom.length === 0 ? undefined : { allowFrom };
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Admission gate for bot-authored mentions. One instance per channel;
|
|
121
|
+
* thread budgets are in-memory (reset on restart — acceptable, the depth
|
|
122
|
+
* and allowlist layers do not depend on process state). Threads idle for
|
|
123
|
+
* 24h are evicted, which also resets their lifetime budget.
|
|
124
|
+
*/
|
|
125
|
+
export class SlackBotMentionGate {
|
|
126
|
+
constructor(options, identity, args) {
|
|
127
|
+
var _a, _b, _c, _d, _e;
|
|
128
|
+
this.identity = identity;
|
|
129
|
+
this.threadBudgets = new Map();
|
|
130
|
+
if (identity.botUserId === undefined && identity.botId === undefined) {
|
|
131
|
+
throw new Error("SlackBotMentionGate requires the agent's own bot identity (auth.test) for loop safety.");
|
|
132
|
+
}
|
|
133
|
+
this.allowFrom = new Set(normalizeBotMentionAllowlist(options.allowFrom));
|
|
134
|
+
this.maxDepth = (_a = options.maxDepth) !== null && _a !== void 0 ? _a : SLACK_BOT_MENTION_DEFAULTS.maxDepth;
|
|
135
|
+
this.maxPerThreadPerHour = (_b = options.maxPerThreadPerHour) !== null && _b !== void 0 ? _b : SLACK_BOT_MENTION_DEFAULTS.maxPerThreadPerHour;
|
|
136
|
+
this.maxPerThreadTotal = (_c = options.maxPerThreadTotal) !== null && _c !== void 0 ? _c : SLACK_BOT_MENTION_DEFAULTS.maxPerThreadTotal;
|
|
137
|
+
this.windowMs = (_d = args === null || args === void 0 ? void 0 : args.windowMs) !== null && _d !== void 0 ? _d : THREAD_BUDGET_WINDOW_MS;
|
|
138
|
+
this.log = (_e = args === null || args === void 0 ? void 0 : args.log) !== null && _e !== void 0 ? _e : defaultSlackLog;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Evaluate a bot-authored mention. Callers must only pass messages whose
|
|
142
|
+
* author `isBot`; human mentions never consult the gate. An `allow`
|
|
143
|
+
* verdict consumes thread budget.
|
|
144
|
+
*/
|
|
145
|
+
evaluate(message, nowMs = Date.now()) {
|
|
146
|
+
var _a;
|
|
147
|
+
var _b, _c, _d;
|
|
148
|
+
const author = message.author;
|
|
149
|
+
if (author === undefined || !author.isBot) {
|
|
150
|
+
return { allow: false, reason: "not bot-authored" };
|
|
151
|
+
}
|
|
152
|
+
// Own posts never wake the agent, allowlisted or not.
|
|
153
|
+
if ((this.identity.botId !== undefined &&
|
|
154
|
+
author.botId === this.identity.botId) ||
|
|
155
|
+
(this.identity.botUserId !== undefined &&
|
|
156
|
+
author.userId !== "" &&
|
|
157
|
+
author.userId === this.identity.botUserId)) {
|
|
158
|
+
return { allow: false, reason: "own post (loop safety)" };
|
|
159
|
+
}
|
|
160
|
+
const allowed = (author.botId !== undefined && this.allowFrom.has(author.botId)) ||
|
|
161
|
+
(author.userId !== "" && this.allowFrom.has(author.userId));
|
|
162
|
+
if (!allowed) {
|
|
163
|
+
return { allow: false, reason: "author not in botMentions.allowFrom" };
|
|
164
|
+
}
|
|
165
|
+
const depth = (_b = (_a = message.delegation) === null || _a === void 0 ? void 0 : _a.depth) !== null && _b !== void 0 ? _b : 1;
|
|
166
|
+
if (depth > this.maxDepth) {
|
|
167
|
+
return {
|
|
168
|
+
allow: false,
|
|
169
|
+
reason: `delegation depth ${depth} exceeds max ${this.maxDepth}`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
this.maybeEvictIdleThreads(nowMs);
|
|
173
|
+
const key = `${message.channelId}:${message.threadTs}`;
|
|
174
|
+
const budget = (_c = this.threadBudgets.get(key)) !== null && _c !== void 0 ? _c : {
|
|
175
|
+
total: 0,
|
|
176
|
+
recent: [],
|
|
177
|
+
lastAtMs: nowMs,
|
|
178
|
+
};
|
|
179
|
+
budget.recent = budget.recent.filter((atMs) => atMs > nowMs - this.windowMs);
|
|
180
|
+
if (budget.total >= this.maxPerThreadTotal) {
|
|
181
|
+
return {
|
|
182
|
+
allow: false,
|
|
183
|
+
reason: `thread lifetime budget exhausted (${this.maxPerThreadTotal})`,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (budget.recent.length >= this.maxPerThreadPerHour) {
|
|
187
|
+
return {
|
|
188
|
+
allow: false,
|
|
189
|
+
reason: `thread rate budget exhausted (${this.maxPerThreadPerHour}/window)`,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
budget.total += 1;
|
|
193
|
+
budget.recent.push(nowMs);
|
|
194
|
+
budget.lastAtMs = nowMs;
|
|
195
|
+
this.threadBudgets.set(key, budget);
|
|
196
|
+
this.log.info("bot mention admitted", {
|
|
197
|
+
channel: message.channelId,
|
|
198
|
+
thread_ts: message.threadTs,
|
|
199
|
+
from_bot: (_d = author.botId) !== null && _d !== void 0 ? _d : author.userId,
|
|
200
|
+
depth,
|
|
201
|
+
thread_total: budget.total,
|
|
202
|
+
});
|
|
203
|
+
return { allow: true, depth };
|
|
204
|
+
}
|
|
205
|
+
maybeEvictIdleThreads(nowMs) {
|
|
206
|
+
if (this.threadBudgets.size < THREAD_SWEEP_THRESHOLD) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
for (const [key, budget] of this.threadBudgets) {
|
|
210
|
+
if (nowMs - budget.lastAtMs > THREAD_IDLE_EVICT_MS) {
|
|
211
|
+
this.threadBudgets.delete(key);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Post an @mention of another bot with delegation metadata attached, so the
|
|
218
|
+
* target's `engagement.botMentions` gate can read the hop count. Use this
|
|
219
|
+
* from dispatcher tools instead of a bare `chat.postMessage`.
|
|
220
|
+
*/
|
|
221
|
+
export function postDelegationMention(args) {
|
|
222
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
223
|
+
var _a;
|
|
224
|
+
const posted = yield postMessage({
|
|
225
|
+
botToken: args.botToken,
|
|
226
|
+
channel: args.channelId,
|
|
227
|
+
text: `<@${args.targetUserId}> ${args.text}`.trim(),
|
|
228
|
+
threadTs: args.threadTs,
|
|
229
|
+
// Mention markup only notifies via mrkdwn `text`, and metadata must
|
|
230
|
+
// ride the same chat.postMessage call.
|
|
231
|
+
plainText: true,
|
|
232
|
+
metadata: buildDelegationMetadata({
|
|
233
|
+
depth: (_a = args.depth) !== null && _a !== void 0 ? _a : 1,
|
|
234
|
+
fromAgent: args.fromAgent,
|
|
235
|
+
originSessionId: args.originSessionId,
|
|
236
|
+
}),
|
|
237
|
+
});
|
|
238
|
+
if (posted.ts === "") {
|
|
239
|
+
throw new Error("Slack delegation mention posted without a message ts; cannot track the handoff.");
|
|
240
|
+
}
|
|
241
|
+
return { ts: posted.ts };
|
|
242
|
+
});
|
|
243
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Shared inbound dispatch for Slack Events API bodies and Socket Mode.
|
|
3
3
|
*/
|
|
4
4
|
import type { HostContext, SendMessageFn } from "../../types.js";
|
|
5
|
+
import type { SlackBotMentionGate } from "./bot-mentions.js";
|
|
5
6
|
import type { ChannelPostWatcher } from "./channel-watch.js";
|
|
6
7
|
import type { EventIdDedupe } from "./event-id-dedupe.js";
|
|
7
8
|
import { type SlackLog } from "./log.js";
|
|
@@ -23,6 +24,11 @@ export interface SlackInboundDispatchDeps extends SlackContinuationProbes {
|
|
|
23
24
|
directMessagesEnabled?: boolean;
|
|
24
25
|
/** Opt-in channel watch; absent = channel posts are ignored. */
|
|
25
26
|
channelWatch?: ChannelPostWatcher;
|
|
27
|
+
/**
|
|
28
|
+
* Opt-in bot-to-bot mention gate; absent = bot-authored mentions are
|
|
29
|
+
* dropped at parse time (loop safety).
|
|
30
|
+
*/
|
|
31
|
+
botMentionGate?: SlackBotMentionGate;
|
|
26
32
|
/**
|
|
27
33
|
* When false, skip the built-in `eval` directive. Defaults to true when
|
|
28
34
|
* `host.evals` is present.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/dispatch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAa,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAK7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAO1D,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAM1D,OAAO,KAAK,EACV,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EAEhB,YAAY,EACZ,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAIpB,uCAAuC;AACvC,wBAAgB,sBAAsB,CACpC,KAAK,GAAE,OAAO,CAAC,iBAAiB,CAAM,GACrC,iBAAiB,CAiBnB;AAED,MAAM,WAAW,wBAAyB,SAAQ,uBAAuB;IACvE,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC/C,YAAY,EAAE,mBAAmB,CAAC;IAClC,eAAe,EAAE,mBAAmB,CAAC;IACrC,WAAW,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC1C,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,qDAAqD;IACrD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uDAAuD;IACvD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gEAAgE;IAChE,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAmBD,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,cAAc,GAAG,cAAc,CAAC;IACzE,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC1C,IAAI,EAAE,WAAW,CAAC;IAClB,sBAAsB,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,kBAAkB,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACrE,+BAA+B,CAAC,EAAE,CAChC,iBAAiB,EAAE,MAAM,KACtB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACjC,qBAAqB,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxE,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CA2QhB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,wBAAwB,GAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/dispatch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAa,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAK7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAO1D,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAM1D,OAAO,KAAK,EACV,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EAEhB,YAAY,EACZ,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAIpB,uCAAuC;AACvC,wBAAgB,sBAAsB,CACpC,KAAK,GAAE,OAAO,CAAC,iBAAiB,CAAM,GACrC,iBAAiB,CAiBnB;AAED,MAAM,WAAW,wBAAyB,SAAQ,uBAAuB;IACvE,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC/C,YAAY,EAAE,mBAAmB,CAAC;IAClC,eAAe,EAAE,mBAAmB,CAAC;IACrC,WAAW,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC1C,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,qDAAqD;IACrD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uDAAuD;IACvD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gEAAgE;IAChE,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC;;;OAGG;IACH,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAmBD,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,cAAc,GAAG,cAAc,CAAC;IACzE,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC1C,IAAI,EAAE,WAAW,CAAC;IAClB,sBAAsB,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,kBAAkB,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACrE,+BAA+B,CAAC,EAAE,CAChC,iBAAiB,EAAE,MAAM,KACtB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACjC,qBAAqB,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxE,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CA2QhB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,wBAAwB,GAC7B,OAAO,CA8HT"}
|
|
@@ -248,8 +248,9 @@ export function dispatchInboundMessage(args) {
|
|
|
248
248
|
* true when a handler was scheduled.
|
|
249
249
|
*/
|
|
250
250
|
export function dispatchInboundFromEventBody(body, deps) {
|
|
251
|
-
var _a;
|
|
252
|
-
|
|
251
|
+
var _a, _b;
|
|
252
|
+
var _c, _d, _e;
|
|
253
|
+
const log = (_c = deps.log) !== null && _c !== void 0 ? _c : defaultSlackLog;
|
|
253
254
|
let eventId;
|
|
254
255
|
if (body !== null && typeof body === "object" && !Array.isArray(body)) {
|
|
255
256
|
const root = body;
|
|
@@ -261,12 +262,32 @@ export function dispatchInboundFromEventBody(body, deps) {
|
|
|
261
262
|
}
|
|
262
263
|
}
|
|
263
264
|
}
|
|
264
|
-
const mention = parseAppMentionEvent(body
|
|
265
|
+
const mention = parseAppMentionEvent(body, {
|
|
266
|
+
includeBotAuthored: deps.botMentionGate !== undefined,
|
|
267
|
+
});
|
|
265
268
|
if (mention !== null) {
|
|
266
269
|
if (deps.mentionsEnabled === false) {
|
|
267
270
|
log.debug("inbound ignored (mentions disabled)", { event_id: eventId });
|
|
268
271
|
return false;
|
|
269
272
|
}
|
|
273
|
+
if (((_a = mention.author) === null || _a === void 0 ? void 0 : _a.isBot) === true) {
|
|
274
|
+
// Parse only admits bot-authored mentions when a gate exists, so the
|
|
275
|
+
// fallback is defensive.
|
|
276
|
+
const verdict = (_d = (_b = deps.botMentionGate) === null || _b === void 0 ? void 0 : _b.evaluate(mention)) !== null && _d !== void 0 ? _d : {
|
|
277
|
+
allow: false,
|
|
278
|
+
reason: "bot mentions not enabled",
|
|
279
|
+
};
|
|
280
|
+
if (!verdict.allow) {
|
|
281
|
+
log.info("bot mention dropped", {
|
|
282
|
+
event_id: eventId,
|
|
283
|
+
channel: mention.channelId,
|
|
284
|
+
thread_ts: mention.threadTs,
|
|
285
|
+
from_bot: (_e = mention.author.botId) !== null && _e !== void 0 ? _e : mention.author.userId,
|
|
286
|
+
reason: verdict.reason,
|
|
287
|
+
});
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
270
291
|
deps.waitUntil(dispatchInboundMessage(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ kind: "app_mention", message: mention, handler: deps.onAppMention, send: deps.send, credentials: deps.credentials, host: deps.host, log, evalCommandsEnabled: deps.evalCommandsEnabled, cursorAgentName: deps.cursorAgentName }, (deps.hasContinuationSession === undefined
|
|
271
292
|
? {}
|
|
272
293
|
: { hasContinuationSession: deps.hasContinuationSession })), (deps.isContinuationBusy === undefined
|
|
@@ -4,7 +4,16 @@
|
|
|
4
4
|
import type { SlackMessage } from "./types.js";
|
|
5
5
|
/** Strip common Slack mention tokens for a cleaner model prompt. */
|
|
6
6
|
export declare function slackTextToMarkdown(text: string): string;
|
|
7
|
-
export
|
|
7
|
+
export interface ParseAppMentionOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Keep bot-authored mentions instead of dropping them at parse time.
|
|
10
|
+
* The dispatch layer enforces the per-channel policy
|
|
11
|
+
* ({@link SlackBotMentionsOptions}: allowlist, depth, thread budget)
|
|
12
|
+
* and always drops the agent's own posts.
|
|
13
|
+
*/
|
|
14
|
+
includeBotAuthored?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function parseAppMentionEvent(body: unknown, options?: ParseAppMentionOptions): SlackMessage | null;
|
|
8
17
|
/**
|
|
9
18
|
* Parse DM / IM messages. More generous than a strict channel_type check:
|
|
10
19
|
* accepts `channel_type === "im"` or channel ids starting with `D`, and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/inbound.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/inbound.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,YAAY,CAAC;AAe5D,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASxD;AAoDD,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,sBAAsB,GAC/B,YAAY,GAAG,IAAI,CAsBrB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CA8B1E;AAED,4EAA4E;AAC5E,MAAM,MAAM,wBAAwB,GAChC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,0BAA0B,GACnC,wBAAwB,GAAG,IAAI,CA4DjC;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAYT"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Parse Slack Events API payloads into structured inbound messages.
|
|
3
3
|
*/
|
|
4
|
+
import { parseDelegationMetadata } from "./bot-mentions.js";
|
|
4
5
|
import { slackApiMessageBody } from "./message-body.js";
|
|
5
6
|
function asRecord(value) {
|
|
6
7
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -53,7 +54,7 @@ function buildSlackMessage(event, teamId) {
|
|
|
53
54
|
threadTs,
|
|
54
55
|
channelId }, (teamId === undefined ? {} : { teamId })), (author === undefined ? {} : { author }));
|
|
55
56
|
}
|
|
56
|
-
export function parseAppMentionEvent(body) {
|
|
57
|
+
export function parseAppMentionEvent(body, options) {
|
|
57
58
|
const root = asRecord(body);
|
|
58
59
|
if (root === null || root.type !== "event_callback") {
|
|
59
60
|
return null;
|
|
@@ -62,12 +63,19 @@ export function parseAppMentionEvent(body) {
|
|
|
62
63
|
if (event === null || event.type !== "app_mention") {
|
|
63
64
|
return null;
|
|
64
65
|
}
|
|
65
|
-
// Drop bot-authored mentions (mirrors DM filtering) to avoid loops
|
|
66
|
+
// Drop bot-authored mentions (mirrors DM filtering) to avoid loops,
|
|
67
|
+
// unless the caller opted into the gated bot-mention path.
|
|
66
68
|
const botId = asString(event.bot_id);
|
|
67
|
-
|
|
69
|
+
const isBotAuthored = botId !== undefined && botId.length > 0;
|
|
70
|
+
if (isBotAuthored && (options === null || options === void 0 ? void 0 : options.includeBotAuthored) !== true) {
|
|
68
71
|
return null;
|
|
69
72
|
}
|
|
70
|
-
|
|
73
|
+
const message = buildSlackMessage(event, asString(root.team_id));
|
|
74
|
+
if (message === null || !isBotAuthored) {
|
|
75
|
+
return message;
|
|
76
|
+
}
|
|
77
|
+
const delegation = parseDelegationMetadata(event);
|
|
78
|
+
return delegation === undefined ? message : Object.assign(Object.assign({}, message), { delegation });
|
|
71
79
|
}
|
|
72
80
|
/**
|
|
73
81
|
* Parse DM / IM messages. More generous than a strict channel_type check:
|
|
@@ -22,6 +22,7 @@ export * from "./approvals.js";
|
|
|
22
22
|
export * from "./assistant.js";
|
|
23
23
|
export * from "./auth.js";
|
|
24
24
|
export * from "./blocks.js";
|
|
25
|
+
export * from "./bot-mentions.js";
|
|
25
26
|
export * from "./channel-watch.js";
|
|
26
27
|
export * from "./constants.js";
|
|
27
28
|
export * from "./credentials.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC"}
|
|
@@ -22,6 +22,7 @@ export * from "./approvals.js";
|
|
|
22
22
|
export * from "./assistant.js";
|
|
23
23
|
export * from "./auth.js";
|
|
24
24
|
export * from "./blocks.js";
|
|
25
|
+
export * from "./bot-mentions.js";
|
|
25
26
|
export * from "./channel-watch.js";
|
|
26
27
|
export * from "./constants.js";
|
|
27
28
|
export * from "./credentials.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slack-channel.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/slack-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,iBAAiB,EAMlB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"slack-channel.d.ts","sourceRoot":"","sources":["../../../src/channels/slack/slack-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,iBAAiB,EAMlB,MAAM,gBAAgB,CAAC;AA8CxB,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,EAC7D,OAAO,GAAE,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,GAAG;IAChD,SAAS,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAC;CACnC,GACL,iBAAiB,CAAC,iBAAiB,CAAC,CAydtC"}
|