@cursor/july 0.1.10 → 0.1.12
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 +1 -0
- package/dist/bin/agent-serve.js +17 -3
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +2 -1
- package/dist/channels/github/types.d.ts +4 -0
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/slack/cursor-account.d.ts.map +1 -1
- package/dist/channels/slack/cursor-account.js +1 -1
- package/dist/channels/slack/dispatch.d.ts +13 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +36 -11
- package/dist/channels/slack/eval-directive.d.ts +63 -0
- package/dist/channels/slack/eval-directive.d.ts.map +1 -0
- package/dist/channels/slack/eval-directive.js +283 -0
- 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 +4 -2
- package/dist/channels/slack/types.d.ts +7 -0
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/connections.d.ts +10 -5
- package/dist/connections.d.ts.map +1 -1
- package/dist/connections.js +10 -5
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.CY2buaEE.js → app.Dh_JkJjI.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.Er_R50vY.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.Ix954SFJ.js → VPLocalSearchBox.CptQNLkR.js} +1 -1
- package/dist/docs/assets/chunks/{theme.PDwuJbyi.js → theme.DWflH-LQ.js} +2 -2
- package/dist/docs/assets/{deployment.md.DC5-ImcM.js → deployment.md.TecHo0_2.js} +3 -3
- package/dist/docs/assets/{deployment.md.DC5-ImcM.lean.js → deployment.md.TecHo0_2.lean.js} +1 -1
- package/dist/docs/assets/guides_mcp-oauth.md.DqmEOQY1.js +29 -0
- package/dist/docs/assets/guides_mcp-oauth.md.DqmEOQY1.lean.js +1 -0
- package/dist/docs/assets/{index.md.COiu-1jL.js → index.md.t0TM2Qzz.js} +3 -3
- package/dist/docs/assets/{index.md.COiu-1jL.lean.js → index.md.t0TM2Qzz.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CjfiV2Q-.js → reference_cli.md.B74NrVzb.js} +3 -3
- package/dist/docs/assets/{reference_cli.md.CjfiV2Q-.lean.js → reference_cli.md.B74NrVzb.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.FbWupyzW.js → reference_connections.md.CsSr3rDz.js} +8 -3
- package/dist/docs/assets/{reference_connections.md.FbWupyzW.lean.js → reference_connections.md.CsSr3rDz.lean.js} +1 -1
- package/dist/docs/assets/reference_prompt.md.BaiweQxE.js +1 -0
- package/dist/docs/assets/reference_prompt.md.BaiweQxE.lean.js +1 -0
- package/dist/docs/assets/{reference_tools.md.CqgJroI0.js → reference_tools.md.BRSDnTbN.js} +16 -3
- package/dist/docs/assets/{reference_tools.md.CqgJroI0.lean.js → reference_tools.md.BRSDnTbN.lean.js} +1 -1
- package/dist/docs/assets/{troubleshooting.md.DkovjS7h.js → troubleshooting.md.CmQkmnzC.js} +1 -1
- package/dist/docs/assets/{troubleshooting.md.DkovjS7h.lean.js → troubleshooting.md.CmQkmnzC.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +7 -7
- package/dist/docs/evals.html +4 -4
- package/dist/docs/example-agents/approval-buddy.html +4 -4
- package/dist/docs/example-agents/benny.html +4 -4
- package/dist/docs/example-agents/bugbot.html +4 -4
- package/dist/docs/example-agents/codebase-wiki.html +4 -4
- package/dist/docs/example-agents/codeowners-review.html +4 -4
- package/dist/docs/example-agents/concierge.html +4 -4
- package/dist/docs/example-agents/fsd.html +4 -4
- package/dist/docs/example-agents/index.html +4 -4
- package/dist/docs/example-agents/knowledge-base.html +4 -4
- package/dist/docs/example-agents/oncall.html +4 -4
- package/dist/docs/example-agents/security-reviewer.html +4 -4
- package/dist/docs/example-agents/slack-agent.html +4 -4
- package/dist/docs/example-agents/weather-agent.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/github.html +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +53 -0
- package/dist/docs/guides/slack.html +4 -4
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +6 -6
- package/dist/docs/reference/connections.html +12 -7
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +4 -4
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.html +33 -0
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +5 -5
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +20 -7
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/evals.d.ts +39 -0
- package/dist/evals.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/internal/cli-mcp-oauth.d.ts +16 -0
- package/dist/internal/cli-mcp-oauth.d.ts.map +1 -0
- package/dist/internal/cli-mcp-oauth.js +194 -0
- package/dist/internal/cli-mcp.d.ts +4 -1
- package/dist/internal/cli-mcp.d.ts.map +1 -1
- package/dist/internal/cli-mcp.js +19 -1
- package/dist/internal/cursor/account-mcp.d.ts +17 -4
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +105 -17
- package/dist/internal/cursor-event-relay.d.ts +2 -0
- package/dist/internal/cursor-event-relay.d.ts.map +1 -1
- package/dist/internal/cursor-event-relay.js +3 -0
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +64 -10
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +1 -0
- package/dist/internal/json-dir-store.js +100 -0
- package/dist/internal/logs-client.js +1 -1
- package/dist/internal/mcp-host.d.ts.map +1 -1
- package/dist/internal/mcp-host.js +49 -26
- package/dist/internal/mcp-oauth.d.ts +88 -0
- package/dist/internal/mcp-oauth.d.ts.map +1 -0
- package/dist/internal/mcp-oauth.js +385 -0
- package/dist/internal/resolved-connections.d.ts.map +1 -1
- package/dist/internal/resolved-connections.js +4 -1
- package/dist/internal/sdk-runner.d.ts +9 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +28 -2
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +13 -5
- package/dist/internal/session-engine.d.ts +7 -9
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +96 -64
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +2 -1
- package/dist/internal/stream-progress.d.ts.map +1 -1
- package/dist/internal/stream-progress.js +8 -4
- package/dist/internal/turn-governor.d.ts +54 -0
- package/dist/internal/turn-governor.d.ts.map +1 -0
- package/dist/internal/turn-governor.js +111 -0
- package/dist/playground/assets/index-1dzluIcW.js +86 -0
- package/dist/playground/assets/index-kZjeJs1v.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/prompt.d.ts +39 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +70 -0
- package/dist/types.d.ts +78 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/docs/README.md +4 -0
- package/docs/deployment.md +6 -1
- package/docs/guides/mcp-oauth.md +157 -0
- package/docs/reference/cli.md +28 -0
- package/docs/reference/connections.md +28 -0
- package/docs/reference/prompt.md +47 -0
- package/docs/reference/tools.md +21 -0
- package/docs/troubleshooting.md +11 -0
- package/package.json +9 -2
- package/skills/create-agent/SKILL.md +7 -3
- package/skills/framework-map/SKILL.md +1 -0
- package/skills/mcp-auth/SKILL.md +138 -0
- package/src/bin/agent-serve.ts +20 -3
- package/src/channels/github/github-channel.ts +2 -0
- package/src/channels/github/types.ts +4 -0
- package/src/channels/slack/cursor-account.ts +2 -0
- package/src/channels/slack/dispatch.ts +49 -0
- package/src/channels/slack/eval-directive.ts +348 -0
- package/src/channels/slack/index.ts +1 -0
- package/src/channels/slack/slack-channel.ts +3 -0
- package/src/channels/slack/types.ts +7 -0
- package/src/connections.ts +10 -5
- package/src/evals.ts +43 -0
- package/src/index.ts +3 -0
- package/src/internal/cli-mcp-oauth.ts +254 -0
- package/src/internal/cli-mcp.ts +25 -2
- package/src/internal/cursor/account-mcp.ts +153 -41
- package/src/internal/cursor-event-relay.ts +5 -0
- package/src/internal/discovery.ts +70 -8
- package/src/internal/distribution.ts +1 -0
- package/src/internal/logs-client.ts +1 -1
- package/src/internal/mcp-host.ts +33 -9
- package/src/internal/mcp-oauth.ts +496 -0
- package/src/internal/resolved-connections.ts +6 -1
- package/src/internal/sdk-runner.ts +37 -1
- package/src/internal/server.ts +13 -5
- package/src/internal/session-engine.ts +115 -74
- package/src/internal/sessions-client.ts +2 -1
- package/src/internal/stream-progress.ts +8 -0
- package/src/internal/turn-governor.ts +145 -0
- package/src/prompt.ts +83 -0
- package/src/types.ts +76 -6
- package/dist/channels/slack/post-update-delivery.d.ts +0 -85
- package/dist/channels/slack/post-update-delivery.d.ts.map +0 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.OfDZ5CXg.js +0 -1
- package/dist/internal/persistence-coordinator.d.ts +0 -127
- package/dist/internal/persistence-coordinator.d.ts.map +0 -1
- package/dist/persistence.d.ts +0 -184
- package/dist/persistence.d.ts.map +0 -1
- package/dist/playground/assets/index-C0-QEG4O.js +0 -86
- package/dist/playground/assets/index-z3JY9O2x.css +0 -1
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Slack `eval` directive — run playground evals from a mention/DM
|
|
3
|
+
* without per-agent custom handlers (parity with CLI / playground runs).
|
|
4
|
+
*
|
|
5
|
+
* Examples (after stripping @mentions / cursorAccount agent name):
|
|
6
|
+
* eval
|
|
7
|
+
* eval triage/open-incidents smoke
|
|
8
|
+
* eval --tag oncall
|
|
9
|
+
* eval list
|
|
10
|
+
* eval status
|
|
11
|
+
* eval help
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { EvalRunSnapshot, HostEvalsApi } from "../../evals.js";
|
|
15
|
+
import {
|
|
16
|
+
EvalRunConflictError,
|
|
17
|
+
EvalRunEmptyError,
|
|
18
|
+
} from "../../internal/eval-run-store.js";
|
|
19
|
+
import { stripLeadingSlackMentions } from "./stop.js";
|
|
20
|
+
import type { SlackBinding } from "./types.js";
|
|
21
|
+
|
|
22
|
+
const EVAL_POLL_MS = 2_000;
|
|
23
|
+
const TYPING_STATUS_MAX = 50;
|
|
24
|
+
|
|
25
|
+
export type SlackEvalDirective =
|
|
26
|
+
| { kind: "help" }
|
|
27
|
+
| { kind: "list" }
|
|
28
|
+
| { kind: "status" }
|
|
29
|
+
| { kind: "run"; filterIds?: string[]; tags?: string[] };
|
|
30
|
+
|
|
31
|
+
function escapeRegExp(value: string): string {
|
|
32
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Normalize inbound Slack text for directive parsing: strip leading
|
|
37
|
+
* `<@U…>` mentions, leading `@U…` markdown mentions, and an optional
|
|
38
|
+
* cursorAccount agentName prefix (`OncallBuddy eval …`).
|
|
39
|
+
*/
|
|
40
|
+
export function normalizeSlackEvalDirectiveBody(
|
|
41
|
+
text: string,
|
|
42
|
+
options?: { agentName?: string }
|
|
43
|
+
): string {
|
|
44
|
+
let body = stripLeadingSlackMentions(text);
|
|
45
|
+
// markdown form from slackTextToMarkdown / cursorAccount envelopes
|
|
46
|
+
while (/^@[A-Za-z0-9._-]+\s+/.test(body)) {
|
|
47
|
+
body = body.replace(/^@[A-Za-z0-9._-]+\s+/, "").trim();
|
|
48
|
+
}
|
|
49
|
+
const agentName = options?.agentName?.trim();
|
|
50
|
+
if (agentName !== undefined && agentName.length > 0) {
|
|
51
|
+
const prefix = new RegExp(`^${escapeRegExp(agentName)}\\s+`, "i");
|
|
52
|
+
body = body.replace(prefix, "").trim();
|
|
53
|
+
}
|
|
54
|
+
return body;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parse a Slack eval directive. Returns null when the message is not an
|
|
59
|
+
* eval command (falls through to the normal agent handler).
|
|
60
|
+
*/
|
|
61
|
+
export function parseSlackEvalDirective(
|
|
62
|
+
text: string,
|
|
63
|
+
options?: { agentName?: string }
|
|
64
|
+
): SlackEvalDirective | null {
|
|
65
|
+
const body = normalizeSlackEvalDirectiveBody(text, options);
|
|
66
|
+
if (body.length === 0) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
const tokens = body.split(/\s+/).filter((t) => t.length > 0);
|
|
70
|
+
if (tokens.length === 0 || !/^eval$/i.test(tokens[0] ?? "")) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const rest = tokens.slice(1);
|
|
75
|
+
if (rest.length === 0) {
|
|
76
|
+
return { kind: "run" };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const head = (rest[0] ?? "").toLowerCase();
|
|
80
|
+
if (
|
|
81
|
+
rest.length === 1 &&
|
|
82
|
+
(head === "help" || head === "-h" || head === "--help")
|
|
83
|
+
) {
|
|
84
|
+
return { kind: "help" };
|
|
85
|
+
}
|
|
86
|
+
if (rest.length === 1 && (head === "list" || head === "ls")) {
|
|
87
|
+
return { kind: "list" };
|
|
88
|
+
}
|
|
89
|
+
if (rest.length === 1 && head === "status") {
|
|
90
|
+
return { kind: "status" };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const filterIds: string[] = [];
|
|
94
|
+
const tags: string[] = [];
|
|
95
|
+
for (let i = 0; i < rest.length; i++) {
|
|
96
|
+
const tok = rest[i] ?? "";
|
|
97
|
+
if (tok === "--tag" || tok === "-t") {
|
|
98
|
+
const value = rest[i + 1];
|
|
99
|
+
if (value === undefined || value.length === 0) {
|
|
100
|
+
return { kind: "help" };
|
|
101
|
+
}
|
|
102
|
+
tags.push(value);
|
|
103
|
+
i += 1;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (tok.startsWith("--tag=")) {
|
|
107
|
+
const value = tok.slice("--tag=".length);
|
|
108
|
+
if (value.length === 0) {
|
|
109
|
+
return { kind: "help" };
|
|
110
|
+
}
|
|
111
|
+
tags.push(value);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (tok.startsWith("-t=") && tok.length > 3) {
|
|
115
|
+
tags.push(tok.slice(3));
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (tok.startsWith("-")) {
|
|
119
|
+
// Unknown flag — surface help rather than treating as an eval id.
|
|
120
|
+
return { kind: "help" };
|
|
121
|
+
}
|
|
122
|
+
filterIds.push(tok);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const run: SlackEvalDirective = { kind: "run" };
|
|
126
|
+
if (filterIds.length > 0) {
|
|
127
|
+
run.filterIds = filterIds;
|
|
128
|
+
}
|
|
129
|
+
if (tags.length > 0) {
|
|
130
|
+
run.tags = tags;
|
|
131
|
+
}
|
|
132
|
+
return run;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** True when either raw Slack text or markdown form is an eval directive. */
|
|
136
|
+
export function isSlackEvalDirective(
|
|
137
|
+
text: string,
|
|
138
|
+
markdown: string,
|
|
139
|
+
options?: { agentName?: string }
|
|
140
|
+
): boolean {
|
|
141
|
+
return (
|
|
142
|
+
parseSlackEvalDirective(text, options) !== null ||
|
|
143
|
+
parseSlackEvalDirective(markdown, options) !== null
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function formatSlackEvalHelp(): string {
|
|
148
|
+
return [
|
|
149
|
+
"*Eval commands* (same batches as the playground / `agentkit eval --prod`):",
|
|
150
|
+
"• `eval` — run all evals",
|
|
151
|
+
"• `eval <id> [id…]` — run specific eval ids",
|
|
152
|
+
"• `eval --tag <tag>` — run evals with a tag (`-t` also works)",
|
|
153
|
+
"• `eval list` — list available evals",
|
|
154
|
+
"• `eval status` — show the active or latest eval run",
|
|
155
|
+
"• `eval help` — this message",
|
|
156
|
+
].join("\n");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function formatSlackEvalList(
|
|
160
|
+
evals: Array<{
|
|
161
|
+
id: string;
|
|
162
|
+
description?: string;
|
|
163
|
+
tags?: string[];
|
|
164
|
+
}>
|
|
165
|
+
): string {
|
|
166
|
+
if (evals.length === 0) {
|
|
167
|
+
return "No evals found under `evals/`.";
|
|
168
|
+
}
|
|
169
|
+
const lines = [`*${evals.length} eval(s):*`];
|
|
170
|
+
for (const item of evals) {
|
|
171
|
+
const tags =
|
|
172
|
+
item.tags === undefined || item.tags.length === 0
|
|
173
|
+
? ""
|
|
174
|
+
: ` _[${item.tags.join(", ")}]_`;
|
|
175
|
+
const desc =
|
|
176
|
+
item.description === undefined || item.description === ""
|
|
177
|
+
? ""
|
|
178
|
+
: ` — ${item.description}`;
|
|
179
|
+
lines.push(`• \`${item.id}\`${tags}${desc}`);
|
|
180
|
+
}
|
|
181
|
+
return lines.join("\n");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function formatSlackEvalRunSummary(run: EvalRunSnapshot): string {
|
|
185
|
+
const { summary } = run;
|
|
186
|
+
const statusLabel =
|
|
187
|
+
run.status === "completed"
|
|
188
|
+
? "completed"
|
|
189
|
+
: run.status === "failed"
|
|
190
|
+
? "failed"
|
|
191
|
+
: "running";
|
|
192
|
+
const lines = [
|
|
193
|
+
`*Eval run* \`${run.runId}\` — *${statusLabel}*`,
|
|
194
|
+
`• ${summary.passed} passed, ${summary.failed} failed, ${summary.total} total` +
|
|
195
|
+
(summary.done < summary.total
|
|
196
|
+
? ` (${summary.done}/${summary.total} done)`
|
|
197
|
+
: ""),
|
|
198
|
+
];
|
|
199
|
+
if (run.error !== undefined && run.error !== "") {
|
|
200
|
+
lines.push(`• error: ${run.error}`);
|
|
201
|
+
}
|
|
202
|
+
for (const c of run.cases) {
|
|
203
|
+
const mark =
|
|
204
|
+
c.status !== "done"
|
|
205
|
+
? c.status === "running"
|
|
206
|
+
? "RUN "
|
|
207
|
+
: "…. "
|
|
208
|
+
: c.ok === true
|
|
209
|
+
? "PASS"
|
|
210
|
+
: "FAIL";
|
|
211
|
+
const dur =
|
|
212
|
+
c.durationMs === undefined
|
|
213
|
+
? ""
|
|
214
|
+
: ` (${(c.durationMs / 1000).toFixed(1)}s)`;
|
|
215
|
+
const err =
|
|
216
|
+
c.ok === false && c.error !== undefined && c.error !== ""
|
|
217
|
+
? ` — ${c.error}`
|
|
218
|
+
: "";
|
|
219
|
+
lines.push(`\`${mark}\` \`${c.id}\`${dur}${err}`);
|
|
220
|
+
}
|
|
221
|
+
return lines.join("\n");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function truncateTyping(status: string): string {
|
|
225
|
+
if (status.length <= TYPING_STATUS_MAX) {
|
|
226
|
+
return status;
|
|
227
|
+
}
|
|
228
|
+
return `${status.slice(0, TYPING_STATUS_MAX - 1)}…`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function sleep(ms: number): Promise<void> {
|
|
232
|
+
await new Promise((resolve) => {
|
|
233
|
+
setTimeout(resolve, ms);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async function safeTyping(
|
|
238
|
+
binding: SlackBinding,
|
|
239
|
+
status: string
|
|
240
|
+
): Promise<void> {
|
|
241
|
+
try {
|
|
242
|
+
await binding.thread.startTyping(truncateTyping(status));
|
|
243
|
+
} catch {
|
|
244
|
+
// best-effort status
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async function safePost(binding: SlackBinding, text: string): Promise<void> {
|
|
249
|
+
try {
|
|
250
|
+
await binding.thread.post(text);
|
|
251
|
+
} catch {
|
|
252
|
+
// best-effort reply
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Handle a parsed Slack eval directive against {@link HostEvalsApi}.
|
|
258
|
+
* Posts results in-thread; does not start an agent turn.
|
|
259
|
+
*/
|
|
260
|
+
export async function handleSlackEvalDirective(args: {
|
|
261
|
+
directive: SlackEvalDirective;
|
|
262
|
+
evals: HostEvalsApi;
|
|
263
|
+
binding: SlackBinding;
|
|
264
|
+
/** Override poll interval (tests). */
|
|
265
|
+
pollMs?: number;
|
|
266
|
+
}): Promise<void> {
|
|
267
|
+
const { directive, evals, binding } = args;
|
|
268
|
+
const pollMs = args.pollMs ?? EVAL_POLL_MS;
|
|
269
|
+
|
|
270
|
+
if (directive.kind === "help") {
|
|
271
|
+
await safePost(binding, formatSlackEvalHelp());
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (directive.kind === "list") {
|
|
276
|
+
const listed = await evals.list();
|
|
277
|
+
await safePost(binding, formatSlackEvalList(listed.evals));
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (directive.kind === "status") {
|
|
282
|
+
const { runs, activeRunId } = await evals.listRunsWithActive();
|
|
283
|
+
const run =
|
|
284
|
+
(activeRunId === undefined ? undefined : await evals.get(activeRunId)) ??
|
|
285
|
+
runs[0];
|
|
286
|
+
if (run === undefined) {
|
|
287
|
+
await safePost(binding, "No eval runs yet. Try `eval list` then `eval`.");
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
await safePost(binding, formatSlackEvalRunSummary(run));
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
await safeTyping(binding, "Starting evals…");
|
|
295
|
+
let run: EvalRunSnapshot;
|
|
296
|
+
try {
|
|
297
|
+
run = await evals.start({
|
|
298
|
+
filterIds: directive.filterIds,
|
|
299
|
+
tags: directive.tags,
|
|
300
|
+
});
|
|
301
|
+
} catch (error) {
|
|
302
|
+
if (error instanceof EvalRunConflictError) {
|
|
303
|
+
const active = await evals.get(error.activeRunId);
|
|
304
|
+
await safePost(
|
|
305
|
+
binding,
|
|
306
|
+
active === undefined
|
|
307
|
+
? `An eval run is already in progress (\`${error.activeRunId}\`).`
|
|
308
|
+
: `An eval run is already in progress:\n${formatSlackEvalRunSummary(active)}`
|
|
309
|
+
);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (error instanceof EvalRunEmptyError) {
|
|
313
|
+
await safePost(
|
|
314
|
+
binding,
|
|
315
|
+
"No matching evals. Try `eval list` or `eval help`."
|
|
316
|
+
);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
320
|
+
await safePost(binding, `Failed to start evals: ${message}`);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
await safePost(
|
|
325
|
+
binding,
|
|
326
|
+
`Started eval run \`${run.runId}\` (${run.summary.total} case(s)).`
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
while (run.status === "running") {
|
|
330
|
+
await safeTyping(
|
|
331
|
+
binding,
|
|
332
|
+
`Evals ${run.summary.done}/${run.summary.total}…`
|
|
333
|
+
);
|
|
334
|
+
await sleep(pollMs);
|
|
335
|
+
const next = await evals.get(run.runId);
|
|
336
|
+
if (next === undefined) {
|
|
337
|
+
await safePost(
|
|
338
|
+
binding,
|
|
339
|
+
`Eval run \`${run.runId}\` disappeared before completion.`
|
|
340
|
+
);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
run = next;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
await safePost(binding, formatSlackEvalRunSummary(run));
|
|
347
|
+
await safeTyping(binding, "Evals done.");
|
|
348
|
+
}
|
|
@@ -29,6 +29,7 @@ export * from "./cursor-account.js";
|
|
|
29
29
|
export * from "./defaults.js";
|
|
30
30
|
export * from "./dispatch.js";
|
|
31
31
|
export * from "./doctor.js";
|
|
32
|
+
export * from "./eval-directive.js";
|
|
32
33
|
export * from "./event-id-dedupe.js";
|
|
33
34
|
export * from "./inbound.js";
|
|
34
35
|
export * from "./init.js";
|
|
@@ -138,6 +138,7 @@ export function slackChannel<const Name extends string = string>(
|
|
|
138
138
|
const engagement = options.engagement ?? {};
|
|
139
139
|
const mentionsEnabled = engagement.mentions !== false;
|
|
140
140
|
const directMessagesEnabled = engagement.directMessages !== false;
|
|
141
|
+
const evalCommandsEnabled = options.evalCommands !== false;
|
|
141
142
|
const channelPosts = engagement.channelPosts;
|
|
142
143
|
if (channelPosts !== undefined) {
|
|
143
144
|
const entries = channelPosts.allow.filter((entry) => entry.trim() !== "");
|
|
@@ -204,6 +205,7 @@ export function slackChannel<const Name extends string = string>(
|
|
|
204
205
|
log: getLog(),
|
|
205
206
|
mentionsEnabled,
|
|
206
207
|
directMessagesEnabled,
|
|
208
|
+
evalCommandsEnabled,
|
|
207
209
|
...(args.hasContinuationSession === undefined
|
|
208
210
|
? {}
|
|
209
211
|
: { hasContinuationSession: args.hasContinuationSession }),
|
|
@@ -342,6 +344,7 @@ export function slackChannel<const Name extends string = string>(
|
|
|
342
344
|
credentials,
|
|
343
345
|
host: args.host,
|
|
344
346
|
log: getLog(),
|
|
347
|
+
evalCommandsEnabled,
|
|
345
348
|
...(args.hasContinuationSession === undefined
|
|
346
349
|
? {}
|
|
347
350
|
: {
|
|
@@ -382,6 +382,13 @@ export interface SlackChannelOptions {
|
|
|
382
382
|
* entry at 50 chars). Defaults to Thinking… / Working on it… / Almost there….
|
|
383
383
|
*/
|
|
384
384
|
loadingMessages?: string[];
|
|
385
|
+
/**
|
|
386
|
+
* Built-in Slack `eval` / `eval list` / `eval status` directive that runs
|
|
387
|
+
* playground eval batches (`host.evals` / `/v1/dev/evals/runs`) without an
|
|
388
|
+
* agent turn. Defaults to `true`. Set `false` to leave `eval …` for the
|
|
389
|
+
* model handler instead.
|
|
390
|
+
*/
|
|
391
|
+
evalCommands?: boolean;
|
|
385
392
|
/** Optional teardown (e.g. stop example-local debouncers). Runs after Socket Mode stops. */
|
|
386
393
|
onStop?: () => void | Promise<void>;
|
|
387
394
|
}
|
package/src/connections.ts
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
* `defineConnection` — authored at `agent/mcp-connections/<name>.ts`.
|
|
3
3
|
*
|
|
4
4
|
* A connection gives tools from an external MCP server. The filename
|
|
5
|
-
* becomes the connection (server) name.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - the agent-serve host, via `ctx.host.mcp` on in-process tools
|
|
9
|
-
* - channel / schedule handlers, via `args.host.mcp`
|
|
5
|
+
* becomes the connection (server) name. Available to the agent (SDK
|
|
6
|
+
* `mcpServers`), host (`ctx.host.mcp`), and channel/schedule handlers.
|
|
7
|
+
* Pass `hostOnly: true` to keep it off the model (still on `host.mcp`).
|
|
10
8
|
*
|
|
11
9
|
* ```ts
|
|
12
10
|
* import { defineConnection } from "@anysphere/agent-serve/connections";
|
|
@@ -15,6 +13,13 @@
|
|
|
15
13
|
* url: "https://mcp.linear.app/mcp",
|
|
16
14
|
* headers: { authorization: `Bearer ${process.env.LINEAR_TOKEN}` },
|
|
17
15
|
* });
|
|
16
|
+
*
|
|
17
|
+
* // privileged connector, model cannot call directly:
|
|
18
|
+
* export default defineConnection({
|
|
19
|
+
* cursorAccount: true,
|
|
20
|
+
* servers: ["anytool"],
|
|
21
|
+
* hostOnly: true,
|
|
22
|
+
* });
|
|
18
23
|
* ```
|
|
19
24
|
*
|
|
20
25
|
* A **Cursor account MCP connection** exposes the MCP connectors the operator
|
package/src/evals.ts
CHANGED
|
@@ -315,6 +315,49 @@ export interface EvalRunSnapshot {
|
|
|
315
315
|
};
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
+
/** One discovered eval datapoint as returned by {@link HostEvalsApi.list}. */
|
|
319
|
+
export interface HostEvalListItem {
|
|
320
|
+
id: string;
|
|
321
|
+
fileId: string;
|
|
322
|
+
description?: string;
|
|
323
|
+
tags?: string[];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** Config slice returned with {@link HostEvalsApi.list}. */
|
|
327
|
+
export interface HostEvalListConfig {
|
|
328
|
+
maxConcurrency?: number;
|
|
329
|
+
timeoutMs?: number;
|
|
330
|
+
maxPlaygroundRuns: number;
|
|
331
|
+
/** True when `agent/storage.ts` declares an `evals` table. */
|
|
332
|
+
durableRuns: boolean;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** Input for {@link HostEvalsApi.start} (same filters as `POST /v1/dev/evals/runs`). */
|
|
336
|
+
export interface HostStartEvalRunInput {
|
|
337
|
+
filterIds?: string[];
|
|
338
|
+
tags?: string[];
|
|
339
|
+
/** Per-case timeout override (same semantics as CLI `--timeout-ms`). */
|
|
340
|
+
timeoutMs?: number;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Host-facing playground eval batches — the same surface as
|
|
345
|
+
* `/v1/dev/evals*` and `agentkit eval --prod`. Attached to
|
|
346
|
+
* {@link import("./types.js").HostContext.evals} by `serve`.
|
|
347
|
+
*/
|
|
348
|
+
export interface HostEvalsApi {
|
|
349
|
+
list(): Promise<{
|
|
350
|
+
evals: HostEvalListItem[];
|
|
351
|
+
config: HostEvalListConfig;
|
|
352
|
+
}>;
|
|
353
|
+
get(runId: string): Promise<EvalRunSnapshot | undefined>;
|
|
354
|
+
listRunsWithActive(): Promise<{
|
|
355
|
+
runs: EvalRunSnapshot[];
|
|
356
|
+
activeRunId?: string;
|
|
357
|
+
}>;
|
|
358
|
+
start(input?: HostStartEvalRunInput): Promise<EvalRunSnapshot>;
|
|
359
|
+
}
|
|
360
|
+
|
|
318
361
|
export interface EvalConfigFile {
|
|
319
362
|
timeoutMs?: number;
|
|
320
363
|
/**
|
package/src/index.ts
CHANGED
|
@@ -89,6 +89,8 @@ export {
|
|
|
89
89
|
UnknownSessionError,
|
|
90
90
|
UnknownToolError,
|
|
91
91
|
} from "./internal/session-engine.js";
|
|
92
|
+
export type { PromptTag } from "./prompt.js";
|
|
93
|
+
export { prompt } from "./prompt.js";
|
|
92
94
|
export type {
|
|
93
95
|
ReminderBusyPolicy,
|
|
94
96
|
ReminderCreateInput,
|
|
@@ -127,6 +129,7 @@ export {
|
|
|
127
129
|
isCursorAccountTransport,
|
|
128
130
|
isPeerConnectionTransport,
|
|
129
131
|
isSymbolicConnectionTransport,
|
|
132
|
+
MAX_RUNNING_TURNS_LIMIT,
|
|
130
133
|
} from "./types.js";
|
|
131
134
|
|
|
132
135
|
/**
|