@cursor/july 0.1.42 → 0.1.45
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 +3 -1
- package/dist/channels/github/api.d.ts +5 -0
- package/dist/channels/github/api.d.ts.map +1 -1
- package/dist/channels/github/api.js +18 -0
- package/dist/channels/github/defaults.d.ts +4 -5
- package/dist/channels/github/defaults.d.ts.map +1 -1
- package/dist/channels/github/defaults.js +27 -1
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +41 -10
- package/dist/channels/github/index.d.ts +1 -0
- package/dist/channels/github/index.d.ts.map +1 -1
- package/dist/channels/github/index.js +1 -0
- package/dist/channels/github/progress.d.ts +54 -0
- package/dist/channels/github/progress.d.ts.map +1 -0
- package/dist/channels/github/progress.js +168 -0
- package/dist/channels/github/state.d.ts +2 -0
- package/dist/channels/github/state.d.ts.map +1 -1
- package/dist/channels/github/state.js +1 -1
- package/dist/channels/github/types.d.ts +16 -4
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.d.ts +4 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +4 -0
- package/dist/channels.d.ts +17 -0
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +31 -0
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.C4-Gwi7g.js → app.fHnNXEJ6.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BMT0xM4I.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DDoLm843.js → VPLocalSearchBox.Cf6ghfFY.js} +1 -1
- package/dist/docs/assets/chunks/{theme.SbjGIiM0.js → theme.B_5-VLe8.js} +2 -2
- package/dist/docs/assets/{deployment.md.BHVjVqRa.js → deployment.md.Cdp4rTE4.js} +1 -1
- package/dist/docs/assets/{guides_github.md.R2QlpR75.js → guides_github.md.DSg0j9qj.js} +29 -3
- package/dist/docs/assets/{guides_github.md.R2QlpR75.lean.js → guides_github.md.DSg0j9qj.lean.js} +1 -1
- package/dist/docs/assets/guides_opentelemetry.md.Csn7ZI25.js +27 -0
- package/dist/docs/assets/guides_opentelemetry.md.Csn7ZI25.lean.js +1 -0
- package/dist/docs/assets/index.md.COeoSkcF.js +5 -0
- package/dist/docs/assets/index.md.COeoSkcF.lean.js +1 -0
- package/dist/docs/assets/{quickstart.md.rIbfahJM.js → quickstart.md.DZxBu44y.js} +18 -49
- package/dist/docs/assets/quickstart.md.DZxBu44y.lean.js +1 -0
- package/dist/docs/assets/{reference_agent-config.md.CRmkoxd6.js → reference_agent-config.md.XRpxctsA.js} +9 -4
- package/dist/docs/assets/{reference_agent-config.md.CRmkoxd6.lean.js → reference_agent-config.md.XRpxctsA.lean.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.BIabFUAI.js → reference_channels.md.MN8iDy8V.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.DqEqQpGn.js → reference_cli.md.BDmjPPAm.js} +2 -2
- package/dist/docs/assets/{reference_hooks.md.B40QAG6m.js → reference_hooks.md.4cbRRIIu.js} +2 -2
- package/dist/docs/assets/{reference_hooks.md.B40QAG6m.lean.js → reference_hooks.md.4cbRRIIu.lean.js} +1 -1
- package/dist/docs/assets/{reference_project-layout.md._XdeMahr.js → reference_project-layout.md.D3MdHM2z.js} +2 -1
- package/dist/docs/assets/{reference_tools.md.lSrsTxYJ.js → reference_tools.md.kJfJAP2m.js} +1 -1
- package/dist/docs/assets/templates_triage.md.CConZt1z.js +11 -0
- package/dist/docs/assets/templates_triage.md.CConZt1z.lean.js +1 -0
- package/dist/docs/building-with-agents.html +5 -5
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +6 -6
- 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 +5 -5
- 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 +5 -5
- package/dist/docs/guides/github.html +33 -7
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +51 -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 +8 -27
- package/dist/docs/quickstart.html +24 -55
- package/dist/docs/reference/agent-config.html +12 -7
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +6 -6
- package/dist/docs/reference/cli.html +7 -7
- package/dist/docs/reference/connections.html +4 -4
- package/dist/docs/reference/hooks.html +6 -6
- 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 +7 -6
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +6 -6
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/triage.html +35 -0
- package/dist/docs/troubleshooting.html +4 -4
- 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-ax.d.ts +1 -0
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +20 -5
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +38 -7
- package/dist/internal/deploy-client.d.ts +8 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +5 -2
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +82 -13
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +1 -0
- package/dist/internal/host-otel.d.ts +25 -0
- package/dist/internal/host-otel.d.ts.map +1 -0
- package/dist/internal/host-otel.js +162 -0
- package/dist/internal/init-project.d.ts +24 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +136 -17
- package/dist/internal/otel/attrs.d.ts +7 -0
- package/dist/internal/otel/attrs.d.ts.map +1 -0
- package/dist/internal/otel/attrs.js +13 -0
- package/dist/internal/otel/collector.d.ts +21 -0
- package/dist/internal/otel/collector.d.ts.map +1 -0
- package/dist/internal/otel/collector.js +605 -0
- package/dist/internal/otel/config.d.ts +42 -0
- package/dist/internal/otel/config.d.ts.map +1 -0
- package/dist/internal/otel/config.js +236 -0
- package/dist/internal/otel/http.d.ts +11 -0
- package/dist/internal/otel/http.d.ts.map +1 -0
- package/dist/internal/otel/http.js +97 -0
- package/dist/internal/otel/runtime.d.ts +21 -0
- package/dist/internal/otel/runtime.d.ts.map +1 -0
- package/dist/internal/otel/runtime.js +188 -0
- package/dist/internal/sdk-runner.d.ts +1 -1
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +1 -1
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +26 -1
- package/dist/internal/session-engine.d.ts +15 -2
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +58 -7
- package/dist/memory.d.ts +4 -0
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +4 -0
- package/dist/otel.d.ts +88 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +64 -0
- package/dist/playground/assets/index-CZH9EFvO.css +1 -0
- package/dist/playground/assets/{index-B3HBneZZ.js → index-Dces8BDp.js} +34 -34
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +103 -3
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +35 -105
- package/docs/deployment.md +2 -1
- package/docs/guides/github.md +79 -6
- package/docs/guides/opentelemetry.md +214 -0
- package/docs/quickstart.md +89 -227
- package/docs/reference/agent-config.md +52 -0
- package/docs/reference/channels.md +3 -1
- package/docs/reference/cli.md +2 -2
- package/docs/reference/hooks.md +21 -4
- package/docs/reference/project-layout.md +2 -0
- package/docs/reference/tools.md +5 -4
- package/docs/templates/triage.md +147 -0
- package/package.json +24 -2
- package/skills/create-agent/SKILL.md +2 -2
- package/skills/framework-map/SKILL.md +2 -0
- package/skills/otel/SKILL.md +98 -0
- package/src/bin/agent-serve.ts +3 -1
- package/src/channels/github/api.ts +22 -0
- package/src/channels/github/defaults.ts +27 -6
- package/src/channels/github/github-channel.ts +36 -1
- package/src/channels/github/index.ts +1 -0
- package/src/channels/github/progress.ts +243 -0
- package/src/channels/github/state.ts +3 -0
- package/src/channels/github/types.ts +12 -4
- package/src/channels/slack/slack-channel.ts +4 -0
- package/src/channels.ts +38 -0
- package/src/index.ts +7 -0
- package/src/internal/cli-ax.ts +21 -3
- package/src/internal/cli-deploy.ts +58 -3
- package/src/internal/deploy-client.ts +11 -0
- package/src/internal/discovery.ts +108 -4
- package/src/internal/distribution.ts +1 -0
- package/src/internal/host-otel.ts +252 -0
- package/src/internal/init-project.ts +160 -17
- package/src/internal/otel/attrs.ts +18 -0
- package/src/internal/otel/collector.ts +881 -0
- package/src/internal/otel/config.ts +307 -0
- package/src/internal/otel/http.ts +126 -0
- package/src/internal/otel/runtime.ts +271 -0
- package/src/internal/sdk-runner.ts +6 -0
- package/src/internal/server.ts +39 -1
- package/src/internal/session-engine.ts +83 -2
- package/src/memory.ts +4 -0
- package/src/otel.ts +155 -0
- package/src/types.ts +109 -3
- package/templates/triage/README.md +48 -0
- package/templates/triage/agent/agent.ts +14 -0
- package/templates/triage/agent/channels/intake.ts +20 -0
- package/templates/triage/agent/channels/slack.ts +3 -0
- package/templates/triage/agent/hooks/memory.ts +3 -0
- package/templates/triage/agent/instructions.md +27 -0
- package/templates/triage/agent/skills/triage-rubric.md +43 -0
- package/templates/triage/agent/tools/record_triage.ts +23 -0
- package/templates/triage/evals/evals.config.ts +5 -0
- package/templates/triage/evals/triage.eval.ts +43 -0
- package/templates/triage/package.json +18 -0
- package/templates/triage/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.BlU3A8EB.js +0 -1
- package/dist/docs/assets/index.md.BKpbkCa6.js +0 -24
- package/dist/docs/assets/index.md.BKpbkCa6.lean.js +0 -1
- package/dist/docs/assets/quickstart.md.rIbfahJM.lean.js +0 -1
- package/dist/playground/assets/index-Bqk9nplh.css +0 -1
- /package/dist/docs/assets/{deployment.md.BHVjVqRa.lean.js → deployment.md.Cdp4rTE4.lean.js} +0 -0
- /package/dist/docs/assets/{reference_channels.md.BIabFUAI.lean.js → reference_channels.md.MN8iDy8V.lean.js} +0 -0
- /package/dist/docs/assets/{reference_cli.md.DqEqQpGn.lean.js → reference_cli.md.BDmjPPAm.lean.js} +0 -0
- /package/dist/docs/assets/{reference_project-layout.md._XdeMahr.lean.js → reference_project-layout.md.D3MdHM2z.lean.js} +0 -0
- /package/dist/docs/assets/{reference_tools.md.lSrsTxYJ.lean.js → reference_tools.md.kJfJAP2m.lean.js} +0 -0
|
@@ -52,6 +52,7 @@ export type RunnerPrewarmRequest = Pick<
|
|
|
52
52
|
| "workspaceDir"
|
|
53
53
|
| "runnerStateDir"
|
|
54
54
|
| "sandbox"
|
|
55
|
+
| "tools"
|
|
55
56
|
| "mcpServers"
|
|
56
57
|
| "subagents"
|
|
57
58
|
| "model"
|
|
@@ -373,6 +374,11 @@ export class CursorSdkRunner implements AgentRunner {
|
|
|
373
374
|
this.options.store ?? (await this.getStore(request.runnerStateDir));
|
|
374
375
|
return {
|
|
375
376
|
...this.buildSharedOptions(request),
|
|
377
|
+
// The built-in tool allowlist rides AgentOptions, not `local`, and is
|
|
378
|
+
// deliberately absent from openCloudAgent's options: the SDK rejects
|
|
379
|
+
// tool restrictions on cloud agents. Passed on create *and* resume
|
|
380
|
+
// (both flow through here) — the SDK does not persist it across runs.
|
|
381
|
+
...(request.tools === undefined ? {} : { tools: request.tools }),
|
|
376
382
|
local: {
|
|
377
383
|
cwd: request.workspaceDir,
|
|
378
384
|
settingSources: ["project"],
|
package/src/internal/server.ts
CHANGED
|
@@ -112,6 +112,10 @@ import {
|
|
|
112
112
|
TOOL_MCP_ENDPOINT_PATH,
|
|
113
113
|
} from "./mcp-endpoint.js";
|
|
114
114
|
import { isLoopbackAddress } from "./net.js";
|
|
115
|
+
import { createOtelCollector, type OtelCollector } from "./otel/collector.js";
|
|
116
|
+
import { pickAuthoredOtel, resolveOtelConfig } from "./otel/config.js";
|
|
117
|
+
import { instrumentHttp } from "./otel/http.js";
|
|
118
|
+
import { createOtelRuntime, shutdownOtelRuntime } from "./otel/runtime.js";
|
|
115
119
|
import { collectPeerConnections } from "./peer-connections.js";
|
|
116
120
|
import {
|
|
117
121
|
PLATFORM_SCHEDULE_CATALOG_FILENAME,
|
|
@@ -222,6 +226,30 @@ export async function startServer(
|
|
|
222
226
|
// agentkit_enabled gate applies to every turn.
|
|
223
227
|
process.env.CURSOR_AGENTKIT_VERSION ??= packageVersion();
|
|
224
228
|
|
|
229
|
+
const authoredOtel = pickAuthoredOtel(
|
|
230
|
+
mounts.map((m) => ({
|
|
231
|
+
slug: m.slug,
|
|
232
|
+
name: m.project.name,
|
|
233
|
+
otel: m.project.otel,
|
|
234
|
+
}))
|
|
235
|
+
);
|
|
236
|
+
const otelRuntime = createOtelRuntime(
|
|
237
|
+
resolveOtelConfig({
|
|
238
|
+
authored: authoredOtel,
|
|
239
|
+
serve: options.otel,
|
|
240
|
+
}),
|
|
241
|
+
logger
|
|
242
|
+
);
|
|
243
|
+
if (
|
|
244
|
+
otelRuntime === undefined &&
|
|
245
|
+
options.otel !== false &&
|
|
246
|
+
authoredOtel !== undefined
|
|
247
|
+
) {
|
|
248
|
+
logger(
|
|
249
|
+
"[agent-sdk] otel: agent/otel.ts present but no OTLP exporters configured (set exporters or OTEL_EXPORTER_OTLP_ENDPOINT)"
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
225
253
|
const cursorGithubTargets = collectCursorGithubTargets(mounts);
|
|
226
254
|
const cursorGithubConfig = resolveCursorGithubEventConfig({
|
|
227
255
|
configured: options.cursorEvents,
|
|
@@ -396,12 +424,18 @@ export async function startServer(
|
|
|
396
424
|
const baseStateRoot =
|
|
397
425
|
options.stateRoot ?? join(project.rootDir, ".agent-serve");
|
|
398
426
|
const stateRoot = slug === "" ? baseStateRoot : join(baseStateRoot, slug);
|
|
427
|
+
const otelCollector: OtelCollector | undefined =
|
|
428
|
+
otelRuntime === undefined
|
|
429
|
+
? undefined
|
|
430
|
+
: createOtelCollector(otelRuntime, project.name, logger);
|
|
399
431
|
const engine = new SessionEngine({
|
|
400
432
|
project,
|
|
401
433
|
stateRoot,
|
|
402
434
|
runner,
|
|
403
435
|
logger,
|
|
404
436
|
platforms: hostPlatforms,
|
|
437
|
+
otel: otelCollector,
|
|
438
|
+
otelMeter: otelRuntime?.meter,
|
|
405
439
|
});
|
|
406
440
|
// Rehydrate sessions from the authored storage sink before any
|
|
407
441
|
// channel or route can address them (continuation tokens must resolve).
|
|
@@ -696,7 +730,9 @@ export async function startServer(
|
|
|
696
730
|
});
|
|
697
731
|
|
|
698
732
|
const server = createServer((req, res) => {
|
|
699
|
-
void
|
|
733
|
+
void instrumentHttp(otelRuntime, req, res, () =>
|
|
734
|
+
handleRequest(router, req, res, logger)
|
|
735
|
+
);
|
|
700
736
|
});
|
|
701
737
|
|
|
702
738
|
const host = options.host ?? "127.0.0.1";
|
|
@@ -715,6 +751,7 @@ export async function startServer(
|
|
|
715
751
|
await cursorEventRelay?.stop();
|
|
716
752
|
await cursorSlackRelay?.stop();
|
|
717
753
|
cursorGithubCredentials?.stop();
|
|
754
|
+
await shutdownOtelRuntime(otelRuntime);
|
|
718
755
|
throw error;
|
|
719
756
|
}
|
|
720
757
|
const address = server.address() as AddressInfo;
|
|
@@ -900,6 +937,7 @@ export async function startServer(
|
|
|
900
937
|
await Promise.all(runtimes.map((runtime) => runtime.engine.close()));
|
|
901
938
|
} finally {
|
|
902
939
|
cursorGithubCredentials?.stop();
|
|
940
|
+
await shutdownOtelRuntime(otelRuntime);
|
|
903
941
|
}
|
|
904
942
|
},
|
|
905
943
|
};
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
11
11
|
import { dirname, join } from "node:path";
|
|
12
12
|
import type { SDKCustomTool, SDKCustomToolResult } from "@cursor/sdk";
|
|
13
|
+
import type { Meter } from "@opentelemetry/api";
|
|
13
14
|
import {
|
|
14
15
|
type ABDefinition,
|
|
15
16
|
mergeABInstructions,
|
|
@@ -95,6 +96,7 @@ import { TurnEventMapper } from "./event-mapper.js";
|
|
|
95
96
|
import { selectFrameworkStorageDefinition } from "./framework-storage-selection.js";
|
|
96
97
|
import { createHostFilesApi } from "./host-files.js";
|
|
97
98
|
import { createHostKvApi } from "./host-kv.js";
|
|
99
|
+
import { createHostOtelApi, type HostOtelSessionApi } from "./host-otel.js";
|
|
98
100
|
import {
|
|
99
101
|
createHostPlatforms,
|
|
100
102
|
createHostSlackClient,
|
|
@@ -109,6 +111,7 @@ import {
|
|
|
109
111
|
import { validateToolInput } from "./json-schema.js";
|
|
110
112
|
import { LedgerServing, newLedgerPodId } from "./ledger-serving.js";
|
|
111
113
|
import { McpHost } from "./mcp-host.js";
|
|
114
|
+
import type { OtelCollector } from "./otel/collector.js";
|
|
112
115
|
import {
|
|
113
116
|
buildSessionContextBlock,
|
|
114
117
|
SCHEDULE_CHANNEL_PREFIX,
|
|
@@ -243,6 +246,10 @@ export interface SessionEngineOptions {
|
|
|
243
246
|
* *without* `cas` fails fast. Ignored for resident-mode agents.
|
|
244
247
|
*/
|
|
245
248
|
durableSessionStore?: HostKvApi;
|
|
249
|
+
/** Process-level OTel collector; observe-only, never fatal. */
|
|
250
|
+
otel?: OtelCollector;
|
|
251
|
+
/** Process-level meter for {@link HostContext.otel}. Absent → no-op counters. */
|
|
252
|
+
otelMeter?: Meter;
|
|
246
253
|
}
|
|
247
254
|
|
|
248
255
|
/**
|
|
@@ -358,6 +365,8 @@ export class SessionEngine {
|
|
|
358
365
|
private readonly platforms: HostPlatforms;
|
|
359
366
|
private readonly approvals = new ApprovalGate();
|
|
360
367
|
private readonly abCollector: ABCollector;
|
|
368
|
+
private readonly otel: OtelCollector | undefined;
|
|
369
|
+
private readonly otelHost: HostOtelSessionApi;
|
|
361
370
|
private reminderApi: HostContext["reminders"];
|
|
362
371
|
private evalsApi: HostContext["evals"];
|
|
363
372
|
private readonly kvApi: HostContext["kv"];
|
|
@@ -390,6 +399,12 @@ export class SessionEngine {
|
|
|
390
399
|
this.logger = options.logger ?? (() => {});
|
|
391
400
|
this.getCloudUsage = options.getCloudUsage ?? defaultGetCloudUsage;
|
|
392
401
|
this.estimateTurnCost = options.estimateTurnCost ?? estimateTurnCostFromApi;
|
|
402
|
+
this.otel = options.otel;
|
|
403
|
+
this.otelHost = createHostOtelApi({
|
|
404
|
+
agentName: options.project.name,
|
|
405
|
+
meter: options.otelMeter,
|
|
406
|
+
collector: options.otel,
|
|
407
|
+
});
|
|
393
408
|
this.turnGovernor = new TurnGovernor(options.project.agent.concurrency);
|
|
394
409
|
this.sessions = new SessionStore(join(options.stateRoot, "sessions"));
|
|
395
410
|
this.nudgeStore = new SlackNudgeStore(
|
|
@@ -569,7 +584,7 @@ export class SessionEngine {
|
|
|
569
584
|
this.cloudServerToolsConnection = connection;
|
|
570
585
|
}
|
|
571
586
|
|
|
572
|
-
/** Shared host services (MCP / GitHub / Slack / reminders / evals / kv / Slack nudges). */
|
|
587
|
+
/** Shared host services (MCP / GitHub / Slack / reminders / evals / kv / files / otel / Slack nudges). */
|
|
573
588
|
get host(): HostContext {
|
|
574
589
|
return {
|
|
575
590
|
mcp: this.mcpHost,
|
|
@@ -579,6 +594,7 @@ export class SessionEngine {
|
|
|
579
594
|
evals: this.evalsApi,
|
|
580
595
|
kv: this.kvApi,
|
|
581
596
|
files: this.filesApi,
|
|
597
|
+
otel: this.otelHost,
|
|
582
598
|
slackNudges: this.slackNudgeHostApi(),
|
|
583
599
|
};
|
|
584
600
|
}
|
|
@@ -593,7 +609,11 @@ export class SessionEngine {
|
|
|
593
609
|
const host = this.host;
|
|
594
610
|
return sessionId === undefined
|
|
595
611
|
? host
|
|
596
|
-
: {
|
|
612
|
+
: {
|
|
613
|
+
...host,
|
|
614
|
+
files: this.filesApi.forSession(sessionId),
|
|
615
|
+
otel: this.otelHost.forSession(sessionId),
|
|
616
|
+
};
|
|
597
617
|
}
|
|
598
618
|
|
|
599
619
|
/** Unbound `ctx.artifacts` facade (channel handlers, scratch tool calls). */
|
|
@@ -775,6 +795,17 @@ export class SessionEngine {
|
|
|
775
795
|
cloudOverride: options.cloud,
|
|
776
796
|
}));
|
|
777
797
|
}
|
|
798
|
+
// Refresh wake-derived channel state (GitHub headSha / refs) without
|
|
799
|
+
// wiping sticky fields. Null patch values are skipped.
|
|
800
|
+
if (options.refreshState !== undefined) {
|
|
801
|
+
record = await this.updateRecord(record.sessionId, (current) => ({
|
|
802
|
+
...current,
|
|
803
|
+
channelState: mergeChannelStateSkipNull(
|
|
804
|
+
current.channelState,
|
|
805
|
+
options.refreshState
|
|
806
|
+
),
|
|
807
|
+
}));
|
|
808
|
+
}
|
|
778
809
|
const coalesced = await this.startTurn(record.sessionId, message, {
|
|
779
810
|
admission: options.admission ?? "preempt",
|
|
780
811
|
...(options.coalesceSourceTs === undefined
|
|
@@ -1343,6 +1374,9 @@ export class SessionEngine {
|
|
|
1343
1374
|
workspaceDir,
|
|
1344
1375
|
runnerStateDir: join(this.stateRoot, "runner"),
|
|
1345
1376
|
sandbox: agent.local?.sandbox === true,
|
|
1377
|
+
...(agent.allowedTools === undefined
|
|
1378
|
+
? {}
|
|
1379
|
+
: { tools: agent.allowedTools }),
|
|
1346
1380
|
mcpServers: this.buildMcpServers("local"),
|
|
1347
1381
|
subagents: buildRunnerSubagents(agent),
|
|
1348
1382
|
...(agent.model === undefined ? {} : { model: agent.model }),
|
|
@@ -1598,6 +1632,15 @@ export class SessionEngine {
|
|
|
1598
1632
|
agentRuntime: agent.runtime,
|
|
1599
1633
|
cloudOverride: record.cloudOverride,
|
|
1600
1634
|
});
|
|
1635
|
+
// Fail closed: the SDK cannot enforce the built-in tool allowlist on
|
|
1636
|
+
// cloud agents yet, and a restriction that silently does not apply is
|
|
1637
|
+
// worse than a refused turn. Cloud-runtime agents already fail
|
|
1638
|
+
// discovery; this guards hybrid agents' per-send cloud sessions.
|
|
1639
|
+
if (runtime === "cloud" && agent.allowedTools !== undefined) {
|
|
1640
|
+
throw new Error(
|
|
1641
|
+
`Agent "${agent.name}" declares a built-in tool allowlist (tools), which cannot be enforced on cloud turns yet. Refusing the cloud session rather than running it unrestricted.`
|
|
1642
|
+
);
|
|
1643
|
+
}
|
|
1601
1644
|
const mergedCloud =
|
|
1602
1645
|
runtime === "cloud"
|
|
1603
1646
|
? mergeCloudOptions({
|
|
@@ -1652,6 +1695,9 @@ export class SessionEngine {
|
|
|
1652
1695
|
: { sdkAgentId: record.sdkAgentId }),
|
|
1653
1696
|
workspaceDir: this.harnessCwd(record),
|
|
1654
1697
|
sandbox: this.project.agent.local?.sandbox === true,
|
|
1698
|
+
...(runtime === "local" && agent.allowedTools !== undefined
|
|
1699
|
+
? { tools: agent.allowedTools }
|
|
1700
|
+
: {}),
|
|
1655
1701
|
runnerStateDir: join(this.stateRoot, "runner"),
|
|
1656
1702
|
prompt: turnPrompt,
|
|
1657
1703
|
isFirstTurn,
|
|
@@ -2457,6 +2503,8 @@ export class SessionEngine {
|
|
|
2457
2503
|
this.project.name
|
|
2458
2504
|
);
|
|
2459
2505
|
}
|
|
2506
|
+
|
|
2507
|
+
this.otel?.onEvent(event, this.sessionInfo(record));
|
|
2460
2508
|
}
|
|
2461
2509
|
|
|
2462
2510
|
private channelEventHandlersFor(
|
|
@@ -3352,6 +3400,7 @@ export class SessionEngine {
|
|
|
3352
3400
|
await this.storage?.close();
|
|
3353
3401
|
await this.mcpHost.close();
|
|
3354
3402
|
await this.runner.dispose?.();
|
|
3403
|
+
this.otel?.close();
|
|
3355
3404
|
}
|
|
3356
3405
|
}
|
|
3357
3406
|
|
|
@@ -3385,6 +3434,38 @@ function mergePendingWorkspaceFiles(
|
|
|
3385
3434
|
return { ...current, ...incoming };
|
|
3386
3435
|
}
|
|
3387
3436
|
|
|
3437
|
+
/**
|
|
3438
|
+
* Shallow-merge a wake patch into durable channel state. Null / undefined
|
|
3439
|
+
* patch values leave the existing key alone so sticky fields survive.
|
|
3440
|
+
*/
|
|
3441
|
+
export function mergeChannelStateSkipNull(
|
|
3442
|
+
current: JsonValue | undefined,
|
|
3443
|
+
patch: JsonValue | undefined
|
|
3444
|
+
): JsonValue | undefined {
|
|
3445
|
+
if (patch === undefined) {
|
|
3446
|
+
return current;
|
|
3447
|
+
}
|
|
3448
|
+
if (
|
|
3449
|
+
typeof patch !== "object" ||
|
|
3450
|
+
patch === null ||
|
|
3451
|
+
Array.isArray(patch) ||
|
|
3452
|
+
typeof current !== "object" ||
|
|
3453
|
+
current === null ||
|
|
3454
|
+
Array.isArray(current)
|
|
3455
|
+
) {
|
|
3456
|
+
return structuredClone(patch);
|
|
3457
|
+
}
|
|
3458
|
+
const merged: Record<string, JsonValue> = {
|
|
3459
|
+
...(current as Record<string, JsonValue>),
|
|
3460
|
+
};
|
|
3461
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
3462
|
+
if (value !== null && value !== undefined) {
|
|
3463
|
+
merged[key] = value as JsonValue;
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
return merged;
|
|
3467
|
+
}
|
|
3468
|
+
|
|
3388
3469
|
function eventsNdjson(events: SessionEvent[]): string | undefined {
|
|
3389
3470
|
if (events.length === 0) {
|
|
3390
3471
|
return undefined;
|
package/src/memory.ts
CHANGED
|
@@ -237,6 +237,10 @@ function truncate(text: string, max: number): string {
|
|
|
237
237
|
* import { memoryHook } from "@cursor/july/memory";
|
|
238
238
|
* export default memoryHook();
|
|
239
239
|
* ```
|
|
240
|
+
*
|
|
241
|
+
* The journal is shared across every session — and every user — of the
|
|
242
|
+
* agent. Pass your own {@link MemoryHookOptions.backend} to change where
|
|
243
|
+
* memories live; delete the hook file to opt out entirely.
|
|
240
244
|
*/
|
|
241
245
|
export function memoryHook(options: MemoryHookOptions = {}): HookDefinition {
|
|
242
246
|
const backend = options.backend ?? defaultMemoryBackend();
|
package/src/otel.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry for Agent SDK — author `agent/otel.ts`, pass `serve({ otel })`,
|
|
3
|
+
* or set `OTEL_EXPORTER_OTLP_ENDPOINT` (standard OTel env).
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { defineOtel } from "@cursor/july/otel";
|
|
7
|
+
*
|
|
8
|
+
* export default defineOtel({
|
|
9
|
+
* serviceName: "cursor",
|
|
10
|
+
* exporters: [{ url: "https://otel.example.com", protocol: "http/protobuf" }],
|
|
11
|
+
* });
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { brandDefinition } from "./internal/brand.js";
|
|
16
|
+
|
|
17
|
+
export type OtelSignal = "traces" | "metrics" | "logs";
|
|
18
|
+
|
|
19
|
+
/** One OTLP destination. Multiple entries fan out. */
|
|
20
|
+
export interface OtelExporterConfig {
|
|
21
|
+
/**
|
|
22
|
+
* OTLP base URL (`https://otel.example.com`) or signal path
|
|
23
|
+
* (`…/v1/traces`). Signal paths are stripped to the base; the runtime
|
|
24
|
+
* re-appends `/v1/{signal}`.
|
|
25
|
+
*/
|
|
26
|
+
url: string;
|
|
27
|
+
/** Extra HTTP headers (merged with `OTEL_EXPORTER_OTLP_HEADERS`). */
|
|
28
|
+
headers?: Record<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* Wire format. Default `http/protobuf` (matches Cursor enterprise OTLP).
|
|
31
|
+
* Use `http/json` for collectors that only accept JSON.
|
|
32
|
+
*/
|
|
33
|
+
protocol?: "http/json" | "http/protobuf";
|
|
34
|
+
/**
|
|
35
|
+
* Restrict this destination to these signals. Default: all enabled
|
|
36
|
+
* signals. Set by env when per-signal `OTEL_EXPORTER_OTLP_*_ENDPOINT`
|
|
37
|
+
* vars differ.
|
|
38
|
+
*/
|
|
39
|
+
signals?: OtelSignal[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface OtelTraceOptions {
|
|
43
|
+
/** Sample ratio in `[0, 1]`. Default `1`. */
|
|
44
|
+
sampleRatio?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface OtelMetricOptions {
|
|
48
|
+
/** Export interval in ms. Default `10000`. */
|
|
49
|
+
exportIntervalMillis?: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface OtelLogOptions {
|
|
53
|
+
/**
|
|
54
|
+
* Include user prompt text on log records / span events.
|
|
55
|
+
* Default false; also toggled by `OTEL_LOG_USER_PROMPTS=1`.
|
|
56
|
+
*/
|
|
57
|
+
userPrompts?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Include tool argument / result payloads and failure text (truncated).
|
|
60
|
+
* Default false; also `OTEL_LOG_TOOL_CONTENT=1`.
|
|
61
|
+
*/
|
|
62
|
+
toolContent?: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Authored / programmatic OTel config. Empty config still enables when
|
|
67
|
+
* standard `OTEL_EXPORTER_OTLP_*` env vars are set.
|
|
68
|
+
*/
|
|
69
|
+
export interface OtelConfig {
|
|
70
|
+
/**
|
|
71
|
+
* Resource `service.name`. Default: `OTEL_SERVICE_NAME` or `"cursor"`
|
|
72
|
+
* (same as enterprise export) so Agent SDK signals join org streams.
|
|
73
|
+
*/
|
|
74
|
+
serviceName?: string;
|
|
75
|
+
/** Resource `service.version`. */
|
|
76
|
+
serviceVersion?: string;
|
|
77
|
+
/** Extra resource attributes on every signal. */
|
|
78
|
+
resourceAttributes?: Record<string, string>;
|
|
79
|
+
/**
|
|
80
|
+
* OTLP destinations. Default: from `OTEL_EXPORTER_OTLP_ENDPOINT` /
|
|
81
|
+
* per-signal `*_TRACES_ENDPOINT` etc. Empty with no env = disabled.
|
|
82
|
+
*/
|
|
83
|
+
exporters?: OtelExporterConfig[];
|
|
84
|
+
/** Traces on/off or options. Default on. */
|
|
85
|
+
traces?: boolean | OtelTraceOptions;
|
|
86
|
+
/** Metrics on/off or options. Default on. */
|
|
87
|
+
metrics?: boolean | OtelMetricOptions;
|
|
88
|
+
/** Logs on/off or options. Default off (opt-in content). */
|
|
89
|
+
logs?: boolean | OtelLogOptions;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export type OtelDefinition = OtelConfig & { readonly __agentServe: "otel" };
|
|
93
|
+
|
|
94
|
+
/** Author OpenTelemetry export under `agent/otel.ts`. */
|
|
95
|
+
export function defineOtel(config: OtelConfig = {}): OtelDefinition {
|
|
96
|
+
if (config.exporters !== undefined) {
|
|
97
|
+
for (const exporter of config.exporters) {
|
|
98
|
+
if (typeof exporter.url !== "string" || exporter.url.length === 0) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
"defineOtel: exporters[].url must be a non-empty string"
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
if (
|
|
104
|
+
exporter.protocol !== undefined &&
|
|
105
|
+
exporter.protocol !== "http/json" &&
|
|
106
|
+
exporter.protocol !== "http/protobuf"
|
|
107
|
+
) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
'defineOtel: exporters[].protocol must be "http/json" or "http/protobuf"'
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
assertSignals(exporter.signals);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (config.resourceAttributes !== undefined) {
|
|
116
|
+
for (const [key, value] of Object.entries(config.resourceAttributes)) {
|
|
117
|
+
if (typeof value !== "string") {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`defineOtel: resourceAttributes.${key} must be a string`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
assertSampleRatio(config.traces);
|
|
125
|
+
return brandDefinition("otel", config);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function assertSignals(signals: OtelSignal[] | undefined): void {
|
|
129
|
+
if (signals === undefined) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (signals.length === 0) {
|
|
133
|
+
throw new Error("defineOtel: exporters[].signals must be non-empty");
|
|
134
|
+
}
|
|
135
|
+
for (const signal of signals) {
|
|
136
|
+
if (signal !== "traces" && signal !== "metrics" && signal !== "logs") {
|
|
137
|
+
throw new Error(
|
|
138
|
+
'defineOtel: exporters[].signals must be "traces" | "metrics" | "logs"'
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function assertSampleRatio(traces: OtelConfig["traces"]): void {
|
|
145
|
+
if (traces === undefined || typeof traces === "boolean") {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const ratio = traces.sampleRatio;
|
|
149
|
+
if (ratio === undefined) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (!Number.isFinite(ratio) || ratio < 0 || ratio > 1) {
|
|
153
|
+
throw new Error("defineOtel: traces.sampleRatio must be in [0, 1]");
|
|
154
|
+
}
|
|
155
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
* SDK as the execution harness.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type { InteractionUpdate, SDKCustomTool } from "@cursor/sdk";
|
|
11
|
+
import type { InteractionUpdate, SDKCustomTool, ToolName } from "@cursor/sdk";
|
|
12
12
|
import type { z } from "zod";
|
|
13
13
|
import type { ABConfigFile } from "./ab.js";
|
|
14
|
+
import type { OtelConfig, OtelDefinition } from "./otel.js";
|
|
14
15
|
import type { StorageDefinition } from "./storage.js";
|
|
15
16
|
|
|
16
17
|
// ============================================================================
|
|
@@ -46,7 +47,8 @@ export type DefinitionKind =
|
|
|
46
47
|
| "eval"
|
|
47
48
|
| "ab"
|
|
48
49
|
| "storage"
|
|
49
|
-
| "artifacts"
|
|
50
|
+
| "artifacts"
|
|
51
|
+
| "otel";
|
|
50
52
|
|
|
51
53
|
export interface BrandedDefinition<K extends DefinitionKind> {
|
|
52
54
|
readonly __agentServe: K;
|
|
@@ -204,6 +206,40 @@ export interface AgentConfig {
|
|
|
204
206
|
* {@link BuiltinToolsConfig}.
|
|
205
207
|
*/
|
|
206
208
|
builtinTools?: BuiltinToolsConfig;
|
|
209
|
+
/**
|
|
210
|
+
* Allowlist of built-in harness tools offered to the model
|
|
211
|
+
* (`AgentOptions.tools` on the SDK). Opt-in by design: unset keeps the
|
|
212
|
+
* model's full standard toolset, and once set the agent gets exactly
|
|
213
|
+
* what it names — nothing more, `[]` meaning no native built-in tools.
|
|
214
|
+
* There is deliberately no exclusion form: an agent that restricts
|
|
215
|
+
* tools states what it keeps, so tools the platform adds later stay
|
|
216
|
+
* off until someone opts in.
|
|
217
|
+
*
|
|
218
|
+
* `"mcp"` is always granted alongside a configured allowlist. It is
|
|
219
|
+
* transport, not capability: this kit's own server tools reach the
|
|
220
|
+
* model over the SDK custom-tool MCP path, so omitting it would
|
|
221
|
+
* silently strand `agent/tools/`. What MCP actually exposes stays
|
|
222
|
+
* governed by the second layer — the tools you author, the connections
|
|
223
|
+
* you declare, and the harness cwd's ambient `.cursor` config (point
|
|
224
|
+
* `local.cwd` outside checkouts whose MCP servers the agent must not
|
|
225
|
+
* see, and `local.sandbox` makes MCP calls fail closed).
|
|
226
|
+
*
|
|
227
|
+
* Names use the SDK's public tool vocabulary (`"shell"`, `"read"`,
|
|
228
|
+
* `"edit"`, `"grep"`, `"glob"`, `"ls"`, `"task"`, ...). `"shell"` is a
|
|
229
|
+
* capability group that also grants shell stdin writes — and is what
|
|
230
|
+
* `execution: "agent"` tool scripts run through, so an allowlist
|
|
231
|
+
* without it strands them (discovery warns). `"task"` gates subagents.
|
|
232
|
+
* Unknown names fail the turn (`ConfigurationError` at `Agent.create`).
|
|
233
|
+
*
|
|
234
|
+
* The allowlist states runtime-agnostic intent, but the SDK cannot
|
|
235
|
+
* enforce tool restrictions on cloud agents yet, and it must never
|
|
236
|
+
* silently not apply: a `runtime: "cloud"` agent that sets it fails at
|
|
237
|
+
* serve start (error diagnostic), and a hybrid agent's per-send cloud
|
|
238
|
+
* sessions are refused (the turn errors) rather than run unrestricted.
|
|
239
|
+
* Not a security boundary against the serve host: like `local.sandbox`,
|
|
240
|
+
* it only shapes what the model can call.
|
|
241
|
+
*/
|
|
242
|
+
tools?: ToolName[];
|
|
207
243
|
/**
|
|
208
244
|
* How the serve host coordinates event delivery and turn execution. See
|
|
209
245
|
* {@link AgentServingMode}. Defaults to `"resident"`; opt in to
|
|
@@ -504,6 +540,12 @@ export interface HostContext {
|
|
|
504
540
|
* process.
|
|
505
541
|
*/
|
|
506
542
|
files: HostFilesApi;
|
|
543
|
+
/**
|
|
544
|
+
* Author-facing OpenTelemetry metrics and session tags. Always present.
|
|
545
|
+
* Counters and histograms no-op when no meter is running. `setAttributes`
|
|
546
|
+
* still tags the open session when a collector is attached.
|
|
547
|
+
*/
|
|
548
|
+
otel: HostOtelApi;
|
|
507
549
|
}
|
|
508
550
|
|
|
509
551
|
/** Host-facing JSON key-value API attached to {@link HostContext.kv}. */
|
|
@@ -704,6 +746,39 @@ export interface HostFilesApi {
|
|
|
704
746
|
): string | undefined;
|
|
705
747
|
}
|
|
706
748
|
|
|
749
|
+
/** Attribute bag accepted by {@link HostOtelApi}. `undefined` values are dropped. */
|
|
750
|
+
export type HostOtelAttributes = Record<
|
|
751
|
+
string,
|
|
752
|
+
string | number | boolean | undefined
|
|
753
|
+
>;
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Author-facing OpenTelemetry surface on {@link HostContext.otel}.
|
|
757
|
+
*
|
|
758
|
+
* Metrics and tags only — no custom spans, and no raw OTel `Meter` /
|
|
759
|
+
* `Tracer`. First-party names (`cursor.token.usage`, …) and join keys
|
|
760
|
+
* (`cursor.conversation.id`, `agent_sdk.agent`, …) are reserved.
|
|
761
|
+
*/
|
|
762
|
+
export interface HostOtelApi {
|
|
763
|
+
/** True when a meter is running and `increment` / `record` export. */
|
|
764
|
+
readonly enabled: boolean;
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Merge tags onto this host binding. On a session-bound host they join
|
|
768
|
+
* the open session span and later first-party metrics. Unbound tags
|
|
769
|
+
* stay on this host instance only.
|
|
770
|
+
*/
|
|
771
|
+
setAttributes(attributes: HostOtelAttributes): void;
|
|
772
|
+
|
|
773
|
+
/** Add 1 to a counter. */
|
|
774
|
+
increment(name: string, attributes?: HostOtelAttributes): void;
|
|
775
|
+
/** Add `value` to a counter. */
|
|
776
|
+
increment(name: string, value: number, attributes?: HostOtelAttributes): void;
|
|
777
|
+
|
|
778
|
+
/** Record one histogram observation. */
|
|
779
|
+
record(name: string, value: number, attributes?: HostOtelAttributes): void;
|
|
780
|
+
}
|
|
781
|
+
|
|
707
782
|
/** Runtime context handed to a tool's `execute`. */
|
|
708
783
|
export interface ToolContext {
|
|
709
784
|
/** Correlates with `actions.requested` / `action.result` stream events. */
|
|
@@ -1422,6 +1497,14 @@ export interface SendMessageOptions {
|
|
|
1422
1497
|
continuationToken?: string;
|
|
1423
1498
|
/** Initial channel state for newly created sessions. */
|
|
1424
1499
|
state?: JsonValue;
|
|
1500
|
+
/**
|
|
1501
|
+
* On resume (continuation hit), shallow-merge into the existing session
|
|
1502
|
+
* channel state before the turn starts. Null / undefined values in the
|
|
1503
|
+
* patch do not overwrite existing keys, so sticky fields (stream ts,
|
|
1504
|
+
* progress banner comment id, …) survive while wake-derived fields
|
|
1505
|
+
* (`headSha`, refs) refresh. Ignored on create; pass {@link state} there.
|
|
1506
|
+
*/
|
|
1507
|
+
refreshState?: JsonValue;
|
|
1425
1508
|
/** Session display title (applied when creating a new session). */
|
|
1426
1509
|
title?: string;
|
|
1427
1510
|
/**
|
|
@@ -1828,7 +1911,12 @@ export interface ChannelMeta {
|
|
|
1828
1911
|
}
|
|
1829
1912
|
|
|
1830
1913
|
export interface ChannelConfig<TState = JsonValue> {
|
|
1831
|
-
/**
|
|
1914
|
+
/**
|
|
1915
|
+
* Route auth chain. Defaults to `[localDevStrict()]`. Include
|
|
1916
|
+
* `publicEndpoint()` to serve this channel WITHOUT the platform alias
|
|
1917
|
+
* token on Cursor hosting (for webhook senders that cannot attach custom
|
|
1918
|
+
* headers — the handler must verify deliveries itself).
|
|
1919
|
+
*/
|
|
1832
1920
|
auth?: AuthPolicy[];
|
|
1833
1921
|
routes?: ChannelRoute[];
|
|
1834
1922
|
/**
|
|
@@ -2337,6 +2425,13 @@ export interface ResolvedAgent {
|
|
|
2337
2425
|
* (`cwd` is absolute — relative paths resolved against the project root).
|
|
2338
2426
|
*/
|
|
2339
2427
|
local?: AgentLocalOptions;
|
|
2428
|
+
/**
|
|
2429
|
+
* Built-in harness tool allowlist from {@link AgentConfig.tools}, with
|
|
2430
|
+
* the "mcp" transport grant injected. Named apart from {@link tools}
|
|
2431
|
+
* (the authored `agent/tools/` list). Applied to local turns; cloud
|
|
2432
|
+
* turns fail closed (cloud-runtime agents already fail discovery).
|
|
2433
|
+
*/
|
|
2434
|
+
allowedTools?: ToolName[];
|
|
2340
2435
|
/** Managed-hosting declarations from {@link AgentConfig.hosting}. */
|
|
2341
2436
|
hosting?: AgentHostingOptions;
|
|
2342
2437
|
/** Validated turn admission limits from {@link AgentConfig.concurrency}. */
|
|
@@ -2374,6 +2469,8 @@ export interface AgentProject {
|
|
|
2374
2469
|
storage?: StorageDefinition;
|
|
2375
2470
|
/** Optional `agent/artifacts.ts` (`defineArtifacts`). */
|
|
2376
2471
|
artifacts?: ArtifactsDefinition;
|
|
2472
|
+
/** Optional `agent/otel.ts` (`defineOtel`). */
|
|
2473
|
+
otel?: OtelDefinition;
|
|
2377
2474
|
diagnostics: Diagnostic[];
|
|
2378
2475
|
}
|
|
2379
2476
|
|
|
@@ -2456,6 +2553,7 @@ export interface AgentProjectInfo {
|
|
|
2456
2553
|
};
|
|
2457
2554
|
/** Project storage sink from `agent/storage.ts`, when authored. */
|
|
2458
2555
|
storage?: { name?: string };
|
|
2556
|
+
otel?: { serviceName?: string; enabled: true };
|
|
2459
2557
|
/** Declared artifact kinds from `agent/artifacts.ts`, when authored. */
|
|
2460
2558
|
artifacts?: { kinds: string[]; agentTool: boolean; max: number };
|
|
2461
2559
|
diagnostics: Diagnostic[];
|
|
@@ -2490,6 +2588,8 @@ export interface RunnerTurnRequest {
|
|
|
2490
2588
|
workspaceDir: string;
|
|
2491
2589
|
/** Run the local harness sandboxed ({@link AgentLocalOptions.sandbox}). */
|
|
2492
2590
|
sandbox?: boolean;
|
|
2591
|
+
/** Built-in tool allowlist ({@link AgentConfig.tools}, resolved). */
|
|
2592
|
+
tools?: ToolName[];
|
|
2493
2593
|
/** Absolute path for runner-owned durable state (conversation store). */
|
|
2494
2594
|
runnerStateDir: string;
|
|
2495
2595
|
prompt: string;
|
|
@@ -2646,6 +2746,12 @@ export interface ServeOptions {
|
|
|
2646
2746
|
apiKey?: string;
|
|
2647
2747
|
};
|
|
2648
2748
|
logger?: (line: string) => void;
|
|
2749
|
+
/**
|
|
2750
|
+
* OpenTelemetry export. Pass a config object, or `false` to force-disable
|
|
2751
|
+
* even when `OTEL_EXPORTER_OTLP_*` env vars / `agent/otel.ts` are set.
|
|
2752
|
+
* When omitted, env + authored `defineOtel` still enable export.
|
|
2753
|
+
*/
|
|
2754
|
+
otel?: OtelConfig | false;
|
|
2649
2755
|
}
|
|
2650
2756
|
|
|
2651
2757
|
/** One agent mounted on a server (its URL slug + compiled project). */
|