@cursor/july 0.1.104 → 0.1.107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agent-serve.js +1 -8
- package/dist/channels/bitbucket/types.d.ts +2 -4
- package/dist/channels/bitbucket/types.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +1 -0
- package/dist/channels/deployments/types.d.ts +7 -8
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/types.d.ts +2 -4
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/gitlab/types.d.ts +2 -5
- package/dist/channels/gitlab/types.d.ts.map +1 -1
- package/dist/channels/origin/types.d.ts +2 -3
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +3 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +1 -1
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +48 -11
- package/dist/channels/slack/types.d.ts +4 -3
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +3 -3
- package/dist/docs/ab.html +6 -6
- package/dist/docs/assets/{app.DbMWUyGb.js → app.CtuckIiL.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DXXZxiMv.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DcNeTh9o.js → VPLocalSearchBox.Bkkhnu8K.js} +2 -2
- package/dist/docs/assets/chunks/{theme.DMjhY3gl.js → theme.DhpIe0Pa.js} +2 -2
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.js +9 -0
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.lean.js +1 -0
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.js → guides_opentelemetry.md.SCRMskno.js} +3 -3
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.lean.js → guides_opentelemetry.md.SCRMskno.lean.js} +1 -1
- package/dist/docs/assets/index.md.BW_6tOgR.js +5 -0
- package/dist/docs/assets/index.md.BW_6tOgR.lean.js +1 -0
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.js → reference_channels.md.D-qTqwcq.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.lean.js → reference_channels.md.D-qTqwcq.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CJNc_xYK.js → reference_cli.md.Dm67hd2D.js} +3 -2
- package/dist/docs/assets/{reference_extensions.md.DykHW3qL.js → reference_extensions.md.CGmMLblt.js} +1 -1
- package/dist/docs/assets/{skills_otel.md.CqhobH3B.js → skills_otel.md.B5Ddv1xH.js} +1 -1
- package/dist/docs/assets/{style.BRuM8477.css → style.DCD_zyg3.css} +1 -1
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.js +3 -0
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.lean.js +1 -0
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +6 -6
- package/dist/docs/evals.html +6 -6
- package/dist/docs/guides/agent-to-agent.html +6 -6
- package/dist/docs/guides/cloud-agents.html +6 -6
- package/dist/docs/guides/convert-automation.html +6 -6
- package/dist/docs/guides/github.html +6 -6
- package/dist/docs/guides/grokbot-agents.html +35 -0
- package/dist/docs/guides/grokbot-agents.md +88 -0
- package/dist/docs/guides/human-in-the-loop.html +6 -6
- package/dist/docs/guides/mcp-oauth.html +6 -6
- package/dist/docs/guides/opentelemetry.html +8 -8
- package/dist/docs/guides/opentelemetry.md +3 -4
- package/dist/docs/guides/slack.html +6 -6
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/index.html +8 -8
- package/dist/docs/index.md +6 -1
- package/dist/docs/llms-full.txt +178 -30
- package/dist/docs/llms.txt +2 -0
- package/dist/docs/quickstart.html +6 -6
- package/dist/docs/reference/agent-config.html +6 -6
- package/dist/docs/reference/artifacts.html +6 -6
- package/dist/docs/reference/channels.html +7 -7
- package/dist/docs/reference/channels.md +11 -19
- package/dist/docs/reference/cli.html +10 -9
- package/dist/docs/reference/cli.md +7 -3
- package/dist/docs/reference/connections.html +6 -6
- package/dist/docs/reference/extensions.html +7 -7
- package/dist/docs/reference/extensions.md +2 -0
- package/dist/docs/reference/hooks.html +6 -6
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/instructions.html +6 -6
- package/dist/docs/reference/playground.html +5 -5
- package/dist/docs/reference/project-layout.html +6 -6
- package/dist/docs/reference/prompt.html +6 -6
- package/dist/docs/reference/result.html +6 -6
- package/dist/docs/reference/schedules.html +6 -6
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/skills.html +6 -6
- package/dist/docs/reference/subagents.html +6 -6
- package/dist/docs/reference/tools.html +6 -6
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/skills/ab.html +6 -6
- package/dist/docs/skills/create-agent.html +6 -6
- package/dist/docs/skills/debug.html +5 -5
- package/dist/docs/skills/evals.html +6 -6
- package/dist/docs/skills/framework-map.html +5 -5
- package/dist/docs/skills/github.html +6 -6
- package/dist/docs/skills/hillclimb.html +6 -6
- package/dist/docs/skills/index.html +5 -5
- package/dist/docs/skills/mcp-auth.html +6 -6
- package/dist/docs/skills/otel.html +8 -8
- package/dist/docs/skills/otel.md +3 -3
- package/dist/docs/skills/setup-slack.html +6 -6
- package/dist/docs/storage.html +6 -6
- package/dist/docs/templates/agentic-owners.html +6 -6
- package/dist/docs/templates/agents-md.html +6 -6
- package/dist/docs/templates/code-wiki.html +6 -6
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/grokbot-agents.html +29 -0
- package/dist/docs/templates/grokbot-agents.md +48 -0
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/security-help.html +6 -6
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/triage.html +6 -6
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/files.d.ts +7 -2
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +7 -2
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +23 -11
- package/dist/internal/cursor/backend-client.d.ts +25 -0
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +57 -2
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- 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 +14 -0
- package/dist/internal/deploy-manifest.d.ts +3 -0
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +15 -12
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +1 -0
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +7 -3
- package/dist/internal/discovery/modules.d.ts +1 -1
- package/dist/internal/discovery/modules.d.ts.map +1 -1
- package/dist/internal/discovery/modules.js +1 -0
- package/dist/internal/discovery/project.d.ts.map +1 -1
- package/dist/internal/discovery/project.js +3 -0
- package/dist/internal/discovery/reminders.d.ts +7 -0
- package/dist/internal/discovery/reminders.d.ts.map +1 -0
- package/dist/internal/discovery/reminders.js +65 -0
- package/dist/internal/discovery/subagent.js +1 -0
- package/dist/internal/distribution.d.ts +5 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +17 -0
- package/dist/internal/framework-file-storage.d.ts +3 -1
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +3 -1
- package/dist/internal/framework-storage-selection.d.ts +14 -3
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +36 -6
- package/dist/internal/guest-network.d.ts.map +1 -1
- package/dist/internal/guest-network.js +2 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +48 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +60 -0
- package/dist/internal/hosted-delivery.d.ts +17 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +112 -19
- package/dist/internal/hosted-managed-automation.d.ts.map +1 -1
- package/dist/internal/hosted-managed-automation.js +27 -2
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +4 -1
- package/dist/internal/local-control-plane.d.ts +18 -2
- package/dist/internal/local-control-plane.d.ts.map +1 -1
- package/dist/internal/local-control-plane.js +199 -17
- package/dist/internal/reminder-control-plane-protocol.d.ts +187 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -0
- package/dist/internal/reminder-control-plane-protocol.js +244 -0
- package/dist/internal/reminder-runner.d.ts +48 -6
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +336 -48
- package/dist/internal/reminder-schedule.d.ts +5 -2
- package/dist/internal/reminder-schedule.d.ts.map +1 -1
- package/dist/internal/reminder-schedule.js +8 -6
- package/dist/internal/reminder-store.d.ts +24 -7
- package/dist/internal/reminder-store.d.ts.map +1 -1
- package/dist/internal/reminder-store.js +6 -5
- package/dist/internal/request-error-status.d.ts +2 -0
- package/dist/internal/request-error-status.d.ts.map +1 -1
- package/dist/internal/request-error-status.js +22 -3
- package/dist/internal/scm/pr-url.d.ts +40 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -1
- package/dist/internal/scm/pr-url.js +93 -14
- package/dist/internal/sdk-runner.d.ts +12 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +18 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +78 -30
- package/dist/internal/session-engine.d.ts +12 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +137 -52
- package/dist/internal/store-mirror.d.ts +2 -2
- package/dist/internal/store-mirror.js +2 -2
- package/dist/internal/tenant-slack/relay.d.ts +2 -0
- package/dist/internal/tenant-slack/relay.d.ts.map +1 -1
- package/dist/internal/tenant-slack/relay.js +18 -8
- package/dist/internal/workspace-sync.d.ts +31 -6
- package/dist/internal/workspace-sync.d.ts.map +1 -1
- package/dist/internal/workspace-sync.js +67 -12
- package/dist/internal/workspace.d.ts +9 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +16 -0
- package/dist/playground/assets/index-Bq2HpEQB.js +67 -0
- package/dist/playground/assets/index-CZKKNlmb.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/reminders.d.ts +24 -5
- package/dist/reminders.d.ts.map +1 -1
- package/dist/reminders.js +28 -5
- package/dist/types.d.ts +98 -28
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +6 -1
- package/docs/guides/grokbot-agents.md +93 -0
- package/docs/guides/opentelemetry.md +3 -4
- package/docs/reference/channels.md +11 -19
- package/docs/reference/cli.md +7 -3
- package/docs/reference/extensions.md +2 -0
- package/docs/templates/grokbot-agents.md +53 -0
- package/package.json +12 -3
- package/skills/otel/SKILL.md +3 -3
- package/src/bin/agent-serve.ts +1 -9
- package/src/channels/bitbucket/types.ts +2 -4
- package/src/channels/deployments/deployments-channel.ts +1 -0
- package/src/channels/deployments/types.ts +7 -8
- package/src/channels/github/types.ts +2 -4
- package/src/channels/gitlab/types.ts +2 -5
- package/src/channels/origin/types.ts +2 -3
- package/src/channels/slack/defaults.ts +3 -0
- package/src/channels/slack/dispatch.ts +1 -0
- package/src/channels/slack/live-delivery.ts +53 -12
- package/src/channels/slack/types.ts +4 -3
- package/src/files.ts +9 -2
- package/src/index.ts +6 -3
- package/src/internal/cli-deploy.ts +30 -12
- package/src/internal/cursor/backend-client.ts +90 -2
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/deploy-client.ts +16 -0
- package/src/internal/deploy-manifest.ts +16 -11
- package/src/internal/discovery/agent.ts +1 -0
- package/src/internal/discovery/info.ts +6 -0
- package/src/internal/discovery/modules.ts +2 -4
- package/src/internal/discovery/project.ts +3 -0
- package/src/internal/discovery/reminders.ts +65 -0
- package/src/internal/discovery/subagent.ts +1 -0
- package/src/internal/distribution.ts +20 -0
- package/src/internal/framework-file-storage.ts +3 -1
- package/src/internal/framework-storage-selection.ts +43 -6
- package/src/internal/guest-network.ts +3 -0
- package/src/internal/hosted-delivery-protocol.ts +96 -0
- package/src/internal/hosted-delivery.ts +207 -28
- package/src/internal/hosted-managed-automation.ts +49 -5
- package/src/internal/init-project.ts +4 -1
- package/src/internal/local-control-plane.ts +281 -22
- package/src/internal/reminder-control-plane-protocol.ts +499 -0
- package/src/internal/reminder-runner.ts +421 -48
- package/src/internal/reminder-schedule.ts +11 -6
- package/src/internal/reminder-store.ts +27 -7
- package/src/internal/request-error-status.ts +27 -3
- package/src/internal/scm/pr-url.ts +167 -20
- package/src/internal/sdk-runner.ts +19 -0
- package/src/internal/server.ts +85 -16
- package/src/internal/session-engine.ts +173 -56
- package/src/internal/store-mirror.ts +2 -2
- package/src/internal/tenant-slack/relay.ts +28 -4
- package/src/internal/workspace-sync.ts +84 -12
- package/src/internal/workspace.ts +20 -0
- package/src/reminders.ts +35 -4
- package/src/types.ts +104 -28
- package/templates/grokbot-agents/README.md +26 -0
- package/templates/grokbot-agents/agent/agent.ts +6 -0
- package/templates/grokbot-agents/agent/extensions/grokbot.ts +5 -0
- package/templates/grokbot-agents/agent/instructions.md +7 -0
- package/templates/grokbot-agents/evals/evals.config.ts +5 -0
- package/templates/grokbot-agents/evals/grokbot-agents.eval.ts +18 -0
- package/templates/grokbot-agents/init.json +18 -0
- package/templates/grokbot-agents/package.json +17 -0
- package/templates/grokbot-agents/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.Bqsulb9K.js +0 -1
- package/dist/docs/assets/index.md.D75GWhPl.js +0 -5
- package/dist/docs/assets/index.md.D75GWhPl.lean.js +0 -1
- package/dist/playground/assets/index-8YiozU89.js +0 -67
- package/dist/playground/assets/index-MbMxXg-y.css +0 -1
- /package/dist/docs/assets/{reference_cli.md.CJNc_xYK.lean.js → reference_cli.md.Dm67hd2D.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.DykHW3qL.lean.js → reference_extensions.md.CGmMLblt.lean.js} +0 -0
- /package/dist/docs/assets/{skills_otel.md.CqhobH3B.lean.js → skills_otel.md.B5Ddv1xH.lean.js} +0 -0
|
@@ -2,6 +2,43 @@ export const HOSTED_DELIVERY_PROTOCOL_VERSION = 2;
|
|
|
2
2
|
export const HOSTED_DELIVERY_HEADER = "x-agent-sdk-hosted-delivery";
|
|
3
3
|
export const HOSTED_ADMISSION_PATH = "/v1/internal/hosted-admission";
|
|
4
4
|
export const HOSTED_EXECUTION_PATH = "/v1/internal/hosted-execution";
|
|
5
|
+
export const HOSTED_GUEST_RETRY_TRANSIENT = "transient";
|
|
6
|
+
export const HOSTED_GUEST_RETRY_TERMINAL = "terminal";
|
|
7
|
+
|
|
8
|
+
export type HostedGuestRetryDisposition =
|
|
9
|
+
| typeof HOSTED_GUEST_RETRY_TRANSIENT
|
|
10
|
+
| typeof HOSTED_GUEST_RETRY_TERMINAL;
|
|
11
|
+
|
|
12
|
+
export type HostedGuestError = {
|
|
13
|
+
ok: false;
|
|
14
|
+
error: string;
|
|
15
|
+
retry: HostedGuestRetryDisposition;
|
|
16
|
+
message?: string;
|
|
17
|
+
turnStatus?: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Hosted delivery is the only HTTP surface whose failures drive Temporal
|
|
22
|
+
* retries. Keep its retry disposition explicit instead of making the shared
|
|
23
|
+
* HTTP error helper guess from a status code.
|
|
24
|
+
*/
|
|
25
|
+
export function hostedGuestErrorResponse(input: {
|
|
26
|
+
status: number;
|
|
27
|
+
error: string;
|
|
28
|
+
retry: HostedGuestRetryDisposition;
|
|
29
|
+
message?: string;
|
|
30
|
+
turnStatus?: string;
|
|
31
|
+
}): Response {
|
|
32
|
+
const body: HostedGuestError = {
|
|
33
|
+
ok: false,
|
|
34
|
+
error: input.error,
|
|
35
|
+
retry: input.retry,
|
|
36
|
+
message: input.message,
|
|
37
|
+
turnStatus: input.turnStatus,
|
|
38
|
+
};
|
|
39
|
+
return Response.json(body, { status: input.status });
|
|
40
|
+
}
|
|
41
|
+
|
|
5
42
|
/**
|
|
6
43
|
* Filename under the serve `--state-root` (not the per-slug SessionEngine
|
|
7
44
|
* dir). Hosted freeze uses `/workspace/.agent-serve`; the Temporal host
|
|
@@ -10,6 +47,25 @@ export const HOSTED_EXECUTION_PATH = "/v1/internal/hosted-execution";
|
|
|
10
47
|
*/
|
|
11
48
|
export const HOSTED_EXECUTION_DIAG_FILENAME = "hosted-execution.json";
|
|
12
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Reserved hosted-admission `channelKind` for durable reminder fires.
|
|
52
|
+
* Bypasses authored channel admission and invokes ReminderRunner.dispatch.
|
|
53
|
+
* Backend builds envelopes with this constant + {@link HOSTED_REMINDER_EVENT_TYPE}.
|
|
54
|
+
*/
|
|
55
|
+
export const HOSTED_REMINDER_CHANNEL_KIND = "agent-sdk:reminder";
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Reserved hosted-admission `eventType` for durable reminder fires.
|
|
59
|
+
* Payload is {@link HostedReminderFirePayload}.
|
|
60
|
+
*/
|
|
61
|
+
export const HOSTED_REMINDER_EVENT_TYPE = "agent-sdk.reminder/fire";
|
|
62
|
+
|
|
63
|
+
/** Compact reminder-fire payload on the reserved hosted-admission path. */
|
|
64
|
+
export type HostedReminderFirePayload = {
|
|
65
|
+
reminderId: string;
|
|
66
|
+
fireCount: number;
|
|
67
|
+
};
|
|
68
|
+
|
|
13
69
|
export type HostedAdmissionManagedAutomation = {
|
|
14
70
|
automationUuid: string;
|
|
15
71
|
mcpServerNames: string[];
|
|
@@ -171,6 +227,46 @@ export function parseHostedExecution(
|
|
|
171
227
|
return body as HostedExecution;
|
|
172
228
|
}
|
|
173
229
|
|
|
230
|
+
/**
|
|
231
|
+
* True when the admission envelope is the reserved internal reminder fire
|
|
232
|
+
* path (not an authored channel event).
|
|
233
|
+
*/
|
|
234
|
+
export function isHostedReminderAdmission(delivery: HostedAdmission): boolean {
|
|
235
|
+
return (
|
|
236
|
+
delivery.channelKind === HOSTED_REMINDER_CHANNEL_KIND &&
|
|
237
|
+
delivery.eventType === HOSTED_REMINDER_EVENT_TYPE
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Parse `{ reminderId, fireCount }` from a reserved reminder admission
|
|
243
|
+
* payload. Rejects unknown keys and non-integer fireCount.
|
|
244
|
+
*/
|
|
245
|
+
export function parseHostedReminderFirePayload(
|
|
246
|
+
value: unknown
|
|
247
|
+
): HostedReminderFirePayload | undefined {
|
|
248
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
const body = value as Record<string, unknown>;
|
|
252
|
+
const keys = Object.keys(body);
|
|
253
|
+
if (
|
|
254
|
+
keys.length !== 2 ||
|
|
255
|
+
!Object.hasOwn(body, "reminderId") ||
|
|
256
|
+
!Object.hasOwn(body, "fireCount") ||
|
|
257
|
+
!boundedString(body.reminderId, 128) ||
|
|
258
|
+
typeof body.fireCount !== "number" ||
|
|
259
|
+
!Number.isInteger(body.fireCount) ||
|
|
260
|
+
body.fireCount < 0
|
|
261
|
+
) {
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
reminderId: body.reminderId,
|
|
266
|
+
fireCount: body.fireCount,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
174
270
|
export function parseHostedAdmissionOutcome(
|
|
175
271
|
value: unknown
|
|
176
272
|
): HostedAdmissionOutcome | undefined {
|
|
@@ -36,9 +36,15 @@ import {
|
|
|
36
36
|
HOSTED_DELIVERY_HEADER,
|
|
37
37
|
HOSTED_DELIVERY_PROTOCOL_VERSION,
|
|
38
38
|
HOSTED_EXECUTION_PATH,
|
|
39
|
+
HOSTED_GUEST_RETRY_TERMINAL,
|
|
40
|
+
HOSTED_GUEST_RETRY_TRANSIENT,
|
|
39
41
|
type HostedAdmission,
|
|
42
|
+
type HostedGuestRetryDisposition,
|
|
43
|
+
hostedGuestErrorResponse,
|
|
44
|
+
isHostedReminderAdmission,
|
|
40
45
|
parseHostedAdmission,
|
|
41
46
|
parseHostedExecution,
|
|
47
|
+
parseHostedReminderFirePayload,
|
|
42
48
|
} from "./hosted-delivery-protocol.js";
|
|
43
49
|
import {
|
|
44
50
|
abortReasonFromTurnStatus,
|
|
@@ -50,9 +56,13 @@ import {
|
|
|
50
56
|
type HostedExecutionFlushSinks,
|
|
51
57
|
} from "./hosted-execution-flush.js";
|
|
52
58
|
import { recordHostedManagedAutomation } from "./hosted-managed-automation.js";
|
|
53
|
-
import {
|
|
59
|
+
import { readJsonObject } from "./http-channel.js";
|
|
54
60
|
import type { LogRingEntry } from "./log-ring.js";
|
|
55
61
|
import { endActiveHttpSpan } from "./otel/http.js";
|
|
62
|
+
import {
|
|
63
|
+
ReminderValidationError,
|
|
64
|
+
UnknownReminderError,
|
|
65
|
+
} from "./reminder-runner.js";
|
|
56
66
|
import { statusForThrownRequestError } from "./request-error-status.js";
|
|
57
67
|
import type { Router } from "./router.js";
|
|
58
68
|
import type { SessionRunExecutionWrite } from "./session-run-log.js";
|
|
@@ -108,6 +118,32 @@ function boundedMessage(text: string): string {
|
|
|
108
118
|
: text;
|
|
109
119
|
}
|
|
110
120
|
|
|
121
|
+
function terminalHostedError(
|
|
122
|
+
status: number,
|
|
123
|
+
error: string,
|
|
124
|
+
message?: string
|
|
125
|
+
): Response {
|
|
126
|
+
return hostedGuestErrorResponse({
|
|
127
|
+
status,
|
|
128
|
+
error,
|
|
129
|
+
retry: HOSTED_GUEST_RETRY_TERMINAL,
|
|
130
|
+
message,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function transientHostedError(
|
|
135
|
+
status: number,
|
|
136
|
+
error: string,
|
|
137
|
+
message?: string
|
|
138
|
+
): Response {
|
|
139
|
+
return hostedGuestErrorResponse({
|
|
140
|
+
status,
|
|
141
|
+
error,
|
|
142
|
+
retry: HOSTED_GUEST_RETRY_TRANSIENT,
|
|
143
|
+
message,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
111
147
|
/**
|
|
112
148
|
* Classify deterministic authored protocol violations as non-retryable 422
|
|
113
149
|
* admissions. Anything else returns `undefined` so callers fall through to
|
|
@@ -126,7 +162,7 @@ function nonRetryableRejection(error: unknown): AdmissionDispatch | undefined {
|
|
|
126
162
|
return undefined;
|
|
127
163
|
}
|
|
128
164
|
return {
|
|
129
|
-
response:
|
|
165
|
+
response: terminalHostedError(
|
|
130
166
|
422,
|
|
131
167
|
code,
|
|
132
168
|
boundedMessage((error as Error).message)
|
|
@@ -150,10 +186,7 @@ export async function dispatchHostedAdmission(
|
|
|
150
186
|
const adapter = getHostedAdmissionAdapter(input.definition);
|
|
151
187
|
if (adapter === undefined || adapter.kind !== input.delivery.channelKind) {
|
|
152
188
|
return {
|
|
153
|
-
response:
|
|
154
|
-
{ ok: false, error: "channel_kind_mismatch" },
|
|
155
|
-
{ status: 422 }
|
|
156
|
-
),
|
|
189
|
+
response: terminalHostedError(422, "channel_kind_mismatch"),
|
|
157
190
|
};
|
|
158
191
|
}
|
|
159
192
|
// The admission window marker follows the async graph into task bodies so
|
|
@@ -161,6 +194,70 @@ export async function dispatchHostedAdmission(
|
|
|
161
194
|
return runDuringHostedAdmission(() => runAdmission(input, adapter));
|
|
162
195
|
}
|
|
163
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Reserved reminder admission: parse the compact payload and invoke
|
|
199
|
+
* ReminderRunner.dispatch. Returns a standard hosted outcome (`task` /
|
|
200
|
+
* `skip`) and never opens the send-capture / model-session path here —
|
|
201
|
+
* prompt-form fires still follow up inside the runner.
|
|
202
|
+
*/
|
|
203
|
+
async function dispatchHostedReminderAdmission(
|
|
204
|
+
input: {
|
|
205
|
+
fireReminder?(
|
|
206
|
+
reminderId: string,
|
|
207
|
+
expectedFireCount: number
|
|
208
|
+
): Promise<{
|
|
209
|
+
reminderId: string;
|
|
210
|
+
outcome: "fired" | "noop";
|
|
211
|
+
reason?: string;
|
|
212
|
+
}>;
|
|
213
|
+
},
|
|
214
|
+
delivery: HostedAdmission
|
|
215
|
+
): Promise<Response> {
|
|
216
|
+
if (input.fireReminder === undefined) {
|
|
217
|
+
return transientHostedError(
|
|
218
|
+
503,
|
|
219
|
+
"reminder_dispatch_unavailable",
|
|
220
|
+
"This guest has no reminder runner wired for hosted admission."
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
const payload = parseHostedReminderFirePayload(delivery.payload);
|
|
224
|
+
if (payload === undefined) {
|
|
225
|
+
return terminalHostedError(
|
|
226
|
+
400,
|
|
227
|
+
"invalid_reminder_payload",
|
|
228
|
+
"Expected reminder payload { reminderId, fireCount }."
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
const result = await input.fireReminder(
|
|
233
|
+
payload.reminderId,
|
|
234
|
+
payload.fireCount
|
|
235
|
+
);
|
|
236
|
+
const outcome = result.outcome === "noop" ? "skip" : "task";
|
|
237
|
+
return Response.json({
|
|
238
|
+
ok: true,
|
|
239
|
+
v: HOSTED_DELIVERY_PROTOCOL_VERSION,
|
|
240
|
+
outcome,
|
|
241
|
+
});
|
|
242
|
+
} catch (error) {
|
|
243
|
+
if (error instanceof UnknownReminderError) {
|
|
244
|
+
return terminalHostedError(
|
|
245
|
+
404,
|
|
246
|
+
"unknown_reminder",
|
|
247
|
+
boundedMessage(error.message)
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
if (error instanceof ReminderValidationError) {
|
|
251
|
+
return terminalHostedError(
|
|
252
|
+
400,
|
|
253
|
+
"invalid_reminder",
|
|
254
|
+
boundedMessage(error.message)
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
164
261
|
async function runAdmission(
|
|
165
262
|
input: DispatchInput,
|
|
166
263
|
adapter: HostedAdmissionAdapter
|
|
@@ -198,9 +295,9 @@ async function runAdmission(
|
|
|
198
295
|
}
|
|
199
296
|
if (!dispatched.ok) {
|
|
200
297
|
return {
|
|
201
|
-
response:
|
|
202
|
-
|
|
203
|
-
|
|
298
|
+
response: terminalHostedError(
|
|
299
|
+
dispatched.status >= 400 ? dispatched.status : 502,
|
|
300
|
+
"channel_dispatch_failed"
|
|
204
301
|
),
|
|
205
302
|
};
|
|
206
303
|
}
|
|
@@ -213,7 +310,7 @@ async function runAdmission(
|
|
|
213
310
|
return rejected;
|
|
214
311
|
}
|
|
215
312
|
return {
|
|
216
|
-
response:
|
|
313
|
+
response: terminalHostedError(
|
|
217
314
|
503,
|
|
218
315
|
"background_dispatch_failed",
|
|
219
316
|
boundedMessage(error instanceof Error ? error.message : String(error))
|
|
@@ -240,10 +337,7 @@ async function runAdmission(
|
|
|
240
337
|
const outcome = dispatchOutcome(dispatched);
|
|
241
338
|
if (outcome === undefined || outcome === "send") {
|
|
242
339
|
return {
|
|
243
|
-
response:
|
|
244
|
-
{ ok: false, error: "channel_outcome_missing" },
|
|
245
|
-
{ status: 502 }
|
|
246
|
-
),
|
|
340
|
+
response: terminalHostedError(502, "channel_outcome_missing"),
|
|
247
341
|
};
|
|
248
342
|
}
|
|
249
343
|
return {
|
|
@@ -329,6 +423,19 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
329
423
|
channelId: string,
|
|
330
424
|
sessionPublicId?: string
|
|
331
425
|
): ChannelHandlerArgs;
|
|
426
|
+
/**
|
|
427
|
+
* Reserved reminder admission: dispatch a hydrated ReminderRunner fire
|
|
428
|
+
* without authored channel admission. Returns the runner's outcome so the
|
|
429
|
+
* route can map fired → task and noop → skip.
|
|
430
|
+
*/
|
|
431
|
+
fireReminder?(
|
|
432
|
+
reminderId: string,
|
|
433
|
+
expectedFireCount: number
|
|
434
|
+
): Promise<{
|
|
435
|
+
reminderId: string;
|
|
436
|
+
outcome: "fired" | "noop";
|
|
437
|
+
reason?: string;
|
|
438
|
+
}>;
|
|
332
439
|
/**
|
|
333
440
|
* Await the session's durable mirror (dispatch chain + storage queue)
|
|
334
441
|
* before the execution reply: the control plane may park the pod the
|
|
@@ -358,6 +465,13 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
358
465
|
flushStartLog?(startLogId: string): Promise<void>;
|
|
359
466
|
/** Snapshot of the process log ring at persist time. */
|
|
360
467
|
snapshotLogs?(): LogRingEntry[];
|
|
468
|
+
/**
|
|
469
|
+
* Drop the cached SDK agent handle before the HTTP reply. Hosted v2
|
|
470
|
+
* hibernates this process as soon as the reply lands; leaving the handle
|
|
471
|
+
* in memory freezes a dead Connect/HTTP2 session that the next wake
|
|
472
|
+
* then reuses.
|
|
473
|
+
*/
|
|
474
|
+
evictSdkSession?(sessionId: string): void;
|
|
361
475
|
/**
|
|
362
476
|
* Wait until guest egress works before authored admission/execution.
|
|
363
477
|
* Defaults to {@link waitForGuestNetworkReady}. Tests inject a stub.
|
|
@@ -393,7 +507,11 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
393
507
|
const consumed = consumeBoundSecrets();
|
|
394
508
|
return consumed.ok
|
|
395
509
|
? undefined
|
|
396
|
-
:
|
|
510
|
+
: transientHostedError(
|
|
511
|
+
503,
|
|
512
|
+
consumed.code,
|
|
513
|
+
boundedMessage(consumed.message)
|
|
514
|
+
);
|
|
397
515
|
};
|
|
398
516
|
const finishNetworkWait = async (
|
|
399
517
|
phase: "admission" | "execution"
|
|
@@ -416,7 +534,7 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
416
534
|
: "Guest network is not ready for outbound requests.";
|
|
417
535
|
return {
|
|
418
536
|
timing,
|
|
419
|
-
response:
|
|
537
|
+
response: transientHostedError(
|
|
420
538
|
503,
|
|
421
539
|
GUEST_NETWORK_UNAVAILABLE,
|
|
422
540
|
boundedMessage(message)
|
|
@@ -463,23 +581,44 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
463
581
|
if (unconsumed !== undefined) {
|
|
464
582
|
return finish(unconsumed);
|
|
465
583
|
}
|
|
466
|
-
const
|
|
584
|
+
const rawAdmission = await readJsonObject(request);
|
|
585
|
+
const delivery = parseHostedAdmission(rawAdmission);
|
|
467
586
|
if (delivery === undefined) {
|
|
587
|
+
const rawKeys =
|
|
588
|
+
typeof rawAdmission === "object" &&
|
|
589
|
+
rawAdmission !== null &&
|
|
590
|
+
!Array.isArray(rawAdmission)
|
|
591
|
+
? Object.keys(rawAdmission as Record<string, unknown>)
|
|
592
|
+
: [];
|
|
593
|
+
console.info(
|
|
594
|
+
`[agent-sdk] hosted admission rejected: envelope failed to parse keys=${JSON.stringify(rawKeys)} hasManagedAutomation=${String(rawKeys.includes("managedAutomation"))}`
|
|
595
|
+
);
|
|
468
596
|
return finish(
|
|
469
|
-
|
|
597
|
+
terminalHostedError(
|
|
470
598
|
400,
|
|
471
599
|
"invalid_hosted_admission",
|
|
472
600
|
"Expected a supported Agent SDK hosted-admission envelope."
|
|
473
601
|
)
|
|
474
602
|
);
|
|
475
603
|
}
|
|
604
|
+
console.info(
|
|
605
|
+
`[agent-sdk] hosted admission received deliveryId=${delivery.deliveryId} channelId=${delivery.channelId} channelKind=${delivery.channelKind} eventType=${delivery.eventType} sessionMode=${delivery.sessionMode} managedAutomation=${delivery.managedAutomation === undefined ? "<absent>" : `automationUuid=${delivery.managedAutomation.automationUuid} mcpServerNames=${String(delivery.managedAutomation.mcpServerNames.length)} slackChannels=${delivery.managedAutomation.slackChannels === undefined ? "<absent>" : JSON.stringify(delivery.managedAutomation.slackChannels)}`}`
|
|
606
|
+
);
|
|
476
607
|
recordHostedManagedAutomation(delivery);
|
|
608
|
+
if (isHostedReminderAdmission(delivery)) {
|
|
609
|
+
const network = await finishNetworkWait("admission");
|
|
610
|
+
guestNetwork = network.timing;
|
|
611
|
+
if (network.response !== undefined) {
|
|
612
|
+
return finish(network.response);
|
|
613
|
+
}
|
|
614
|
+
return finish(await dispatchHostedReminderAdmission(input, delivery));
|
|
615
|
+
}
|
|
477
616
|
const channel = input.channels.find(
|
|
478
617
|
(candidate) => candidate.id === delivery.channelId
|
|
479
618
|
);
|
|
480
619
|
if (channel === undefined) {
|
|
481
620
|
return finish(
|
|
482
|
-
|
|
621
|
+
terminalHostedError(
|
|
483
622
|
404,
|
|
484
623
|
"channel_not_found",
|
|
485
624
|
`No channel named "${delivery.channelId}" is mounted.`
|
|
@@ -536,7 +675,7 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
536
675
|
const execution = parseHostedExecution(await readJsonObject(request));
|
|
537
676
|
if (execution === undefined) {
|
|
538
677
|
return finish(
|
|
539
|
-
|
|
678
|
+
terminalHostedError(
|
|
540
679
|
400,
|
|
541
680
|
"invalid_hosted_execution",
|
|
542
681
|
"Expected a supported Agent SDK hosted-execution envelope."
|
|
@@ -547,7 +686,7 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
547
686
|
const admitted = pending.get(execution.admissionToken);
|
|
548
687
|
if (admitted === undefined) {
|
|
549
688
|
return finish(
|
|
550
|
-
|
|
689
|
+
transientHostedError(
|
|
551
690
|
409,
|
|
552
691
|
"hosted_admission_unavailable",
|
|
553
692
|
"The hosted admission token is missing or expired."
|
|
@@ -559,7 +698,7 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
559
698
|
admitted.sessionPublicId !== execution.sessionPublicId
|
|
560
699
|
) {
|
|
561
700
|
return finish(
|
|
562
|
-
|
|
701
|
+
transientHostedError(
|
|
563
702
|
409,
|
|
564
703
|
"hosted_admission_session_mismatch",
|
|
565
704
|
"The hosted admission token is already bound to another session."
|
|
@@ -624,6 +763,7 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
624
763
|
sessionId: "",
|
|
625
764
|
turnStatus: HOSTED_EXECUTION_DIAG_RUNNING_STATUS,
|
|
626
765
|
});
|
|
766
|
+
let sessionId = "";
|
|
627
767
|
try {
|
|
628
768
|
const args = input.buildHandlerArgs(
|
|
629
769
|
admitted.send.channelId,
|
|
@@ -635,10 +775,19 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
635
775
|
key: admitted.send.mailboxContinuationKey,
|
|
636
776
|
},
|
|
637
777
|
});
|
|
778
|
+
sessionId = session.id;
|
|
638
779
|
const outcome = await session.waitForCompletion();
|
|
639
780
|
// Failed turns drain too: their record/continuation updates must
|
|
640
781
|
// survive the park just like a finished turn's.
|
|
641
782
|
await input.drainSessionDurability?.(session.id);
|
|
783
|
+
// Evict before the reply: TAS parks and hibernates this process
|
|
784
|
+
// as soon as the POST returns. A leftover SDK handle freezes a
|
|
785
|
+
// dead Connect/HTTP2 session that the next wake then reuses.
|
|
786
|
+
evictHostedSdkSessions(
|
|
787
|
+
input.evictSdkSession,
|
|
788
|
+
session.id,
|
|
789
|
+
execution.sessionPublicId
|
|
790
|
+
);
|
|
642
791
|
await writeDiag({
|
|
643
792
|
sessionId: session.id,
|
|
644
793
|
turnStatus: outcome.status,
|
|
@@ -652,11 +801,15 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
652
801
|
// waitForCompletion resolves (does not throw) on a quiet
|
|
653
802
|
// Connect abort. Map that to guest_connect_stalled so TAS
|
|
654
803
|
// retries the same pod. Real runner failures stay turn_failed.
|
|
804
|
+
const hostedFailure = hostedFailureForUnfinishedTurn(
|
|
805
|
+
outcome.errorMessage
|
|
806
|
+
);
|
|
655
807
|
return {
|
|
656
808
|
status: 503,
|
|
657
809
|
body: {
|
|
658
810
|
ok: false,
|
|
659
|
-
error:
|
|
811
|
+
error: hostedFailure.error,
|
|
812
|
+
retry: hostedFailure.retry,
|
|
660
813
|
turnStatus: outcome.status,
|
|
661
814
|
message: outcome.errorMessage,
|
|
662
815
|
},
|
|
@@ -671,6 +824,11 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
671
824
|
},
|
|
672
825
|
};
|
|
673
826
|
} catch (error) {
|
|
827
|
+
evictHostedSdkSessions(
|
|
828
|
+
input.evictSdkSession,
|
|
829
|
+
sessionId,
|
|
830
|
+
execution.sessionPublicId
|
|
831
|
+
);
|
|
674
832
|
await writeDiag({
|
|
675
833
|
sessionId: "",
|
|
676
834
|
turnStatus: "error",
|
|
@@ -687,16 +845,37 @@ export function registerHostedDeliveryRoute(input: {
|
|
|
687
845
|
});
|
|
688
846
|
}
|
|
689
847
|
|
|
690
|
-
function
|
|
691
|
-
|
|
692
|
-
|
|
848
|
+
function evictHostedSdkSessions(
|
|
849
|
+
evict: ((sessionId: string) => void) | undefined,
|
|
850
|
+
...ids: Array<string | undefined>
|
|
851
|
+
): void {
|
|
852
|
+
if (evict === undefined) {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
const seen = new Set<string>();
|
|
856
|
+
for (const id of ids) {
|
|
857
|
+
if (id === undefined || id === "" || seen.has(id)) {
|
|
858
|
+
continue;
|
|
859
|
+
}
|
|
860
|
+
seen.add(id);
|
|
861
|
+
evict(id);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
function hostedFailureForUnfinishedTurn(errorMessage: string | undefined): {
|
|
866
|
+
error: typeof GUEST_CONNECT_STALLED | "turn_failed";
|
|
867
|
+
retry: HostedGuestRetryDisposition;
|
|
868
|
+
} {
|
|
693
869
|
if (
|
|
694
870
|
errorMessage !== undefined &&
|
|
695
871
|
isQuietGuestConnectStallMessage(errorMessage)
|
|
696
872
|
) {
|
|
697
|
-
return
|
|
873
|
+
return {
|
|
874
|
+
error: GUEST_CONNECT_STALLED,
|
|
875
|
+
retry: HOSTED_GUEST_RETRY_TRANSIENT,
|
|
876
|
+
};
|
|
698
877
|
}
|
|
699
|
-
return "turn_failed";
|
|
878
|
+
return { error: "turn_failed", retry: HOSTED_GUEST_RETRY_TERMINAL };
|
|
700
879
|
}
|
|
701
880
|
|
|
702
881
|
async function afterHostedWork<T>(
|
|
@@ -17,10 +17,36 @@
|
|
|
17
17
|
|
|
18
18
|
import type { HostedAdmissionManagedAutomation } from "./hosted-delivery-protocol.js";
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
type ManagedAutomationEntry = {
|
|
21
|
+
managedAutomation: HostedAdmissionManagedAutomation;
|
|
22
|
+
expiresAt: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Process-wide slot for the table. Hosted engines run the compiled CLI
|
|
27
|
+
* (`dist/`), which records at admission, while first-party factory agents
|
|
28
|
+
* relative-import this file from `src/` and read at finalize — two module
|
|
29
|
+
* instances in one process. A module-local Map would be recorded in one
|
|
30
|
+
* copy and read from the other (always undefined, so a fork never sees its
|
|
31
|
+
* Slack channels or MCP servers); the shared symbol keeps one table.
|
|
32
|
+
*/
|
|
33
|
+
const MANAGED_AUTOMATION_TABLE_KEY = Symbol.for(
|
|
34
|
+
"cursor.agentkit.hostedManagedAutomationByDelivery"
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
function managedAutomationTable(): Map<string, ManagedAutomationEntry> {
|
|
38
|
+
const slots = globalThis as unknown as Record<
|
|
39
|
+
symbol,
|
|
40
|
+
Map<string, ManagedAutomationEntry> | undefined
|
|
41
|
+
>;
|
|
42
|
+
let table = slots[MANAGED_AUTOMATION_TABLE_KEY];
|
|
43
|
+
if (table === undefined) {
|
|
44
|
+
table = new Map();
|
|
45
|
+
slots[MANAGED_AUTOMATION_TABLE_KEY] = table;
|
|
46
|
+
}
|
|
47
|
+
return table;
|
|
48
|
+
}
|
|
49
|
+
|
|
24
50
|
/** Long enough to outlive a slow review run kicked off by the delivery. */
|
|
25
51
|
const MANAGED_AUTOMATION_TTL_MS = 60 * 60_000;
|
|
26
52
|
const MANAGED_AUTOMATION_MAX_ENTRIES = 10_000;
|
|
@@ -30,8 +56,12 @@ export function recordHostedManagedAutomation(delivery: {
|
|
|
30
56
|
managedAutomation?: HostedAdmissionManagedAutomation;
|
|
31
57
|
}): void {
|
|
32
58
|
if (delivery.managedAutomation === undefined) {
|
|
59
|
+
console.info(
|
|
60
|
+
`[agent-sdk] hosted managedAutomation not recorded deliveryId=${delivery.deliveryId}: admission envelope carried no managedAutomation slice (non-managed delivery, or the control plane resolved no MCP servers and no Slack channels)`
|
|
61
|
+
);
|
|
33
62
|
return;
|
|
34
63
|
}
|
|
64
|
+
const managedAutomationByDelivery = managedAutomationTable();
|
|
35
65
|
const now = Date.now();
|
|
36
66
|
for (const [key, entry] of managedAutomationByDelivery) {
|
|
37
67
|
if (entry.expiresAt <= now) {
|
|
@@ -39,12 +69,19 @@ export function recordHostedManagedAutomation(delivery: {
|
|
|
39
69
|
}
|
|
40
70
|
}
|
|
41
71
|
if (managedAutomationByDelivery.size >= MANAGED_AUTOMATION_MAX_ENTRIES) {
|
|
72
|
+
console.info(
|
|
73
|
+
`[agent-sdk] hosted managedAutomation table full (${String(managedAutomationByDelivery.size)} entries); clearing before recording deliveryId=${delivery.deliveryId}`
|
|
74
|
+
);
|
|
42
75
|
managedAutomationByDelivery.clear();
|
|
43
76
|
}
|
|
44
77
|
managedAutomationByDelivery.set(delivery.deliveryId, {
|
|
45
78
|
managedAutomation: delivery.managedAutomation,
|
|
46
79
|
expiresAt: now + MANAGED_AUTOMATION_TTL_MS,
|
|
47
80
|
});
|
|
81
|
+
const slackChannels = delivery.managedAutomation.slackChannels;
|
|
82
|
+
console.info(
|
|
83
|
+
`[agent-sdk] hosted managedAutomation recorded deliveryId=${delivery.deliveryId} automationUuid=${delivery.managedAutomation.automationUuid} mcpServerNames=${String(delivery.managedAutomation.mcpServerNames.length)} slackChannels=${slackChannels === undefined ? "<absent>" : JSON.stringify(slackChannels)} ttlMs=${String(MANAGED_AUTOMATION_TTL_MS)} tableSize=${String(managedAutomationByDelivery.size)}`
|
|
84
|
+
);
|
|
48
85
|
}
|
|
49
86
|
|
|
50
87
|
/**
|
|
@@ -55,11 +92,18 @@ export function recordHostedManagedAutomation(delivery: {
|
|
|
55
92
|
export function getHostedManagedAutomation(
|
|
56
93
|
deliveryId: string
|
|
57
94
|
): HostedAdmissionManagedAutomation | undefined {
|
|
95
|
+
const managedAutomationByDelivery = managedAutomationTable();
|
|
58
96
|
const entry = managedAutomationByDelivery.get(deliveryId);
|
|
59
97
|
if (entry === undefined) {
|
|
98
|
+
console.info(
|
|
99
|
+
`[agent-sdk] hosted managedAutomation lookup miss deliveryId=${deliveryId}: no entry (never recorded in this process, or evicted) tableSize=${String(managedAutomationByDelivery.size)} knownDeliveryIds=${JSON.stringify([...managedAutomationByDelivery.keys()].slice(0, 10))}`
|
|
100
|
+
);
|
|
60
101
|
return undefined;
|
|
61
102
|
}
|
|
62
103
|
if (entry.expiresAt <= Date.now()) {
|
|
104
|
+
console.info(
|
|
105
|
+
`[agent-sdk] hosted managedAutomation lookup expired deliveryId=${deliveryId} automationUuid=${entry.managedAutomation.automationUuid} expiredMsAgo=${String(Date.now() - entry.expiresAt)}`
|
|
106
|
+
);
|
|
63
107
|
managedAutomationByDelivery.delete(deliveryId);
|
|
64
108
|
return undefined;
|
|
65
109
|
}
|
|
@@ -68,5 +112,5 @@ export function getHostedManagedAutomation(
|
|
|
68
112
|
|
|
69
113
|
/** Drop recorded managed-automation slices (tests only). */
|
|
70
114
|
export function resetHostedManagedAutomationForTest(): void {
|
|
71
|
-
|
|
115
|
+
managedAutomationTable().clear();
|
|
72
116
|
}
|
|
@@ -77,6 +77,7 @@ const TEMPLATES: Readonly<Record<TemplateName, TemplateEntry>> = {
|
|
|
77
77
|
"agents-md": { dir: "agents-md" },
|
|
78
78
|
"code-wiki": { dir: "code-wiki" },
|
|
79
79
|
demo: { dir: "demo" },
|
|
80
|
+
"grokbot-agents": { dir: "grokbot-agents" },
|
|
80
81
|
"pr-autofixer": { dir: "pr-autofixer" },
|
|
81
82
|
"security-help": { dir: "security-help" },
|
|
82
83
|
"security-reviewer": { dir: "security-reviewer" },
|
|
@@ -711,6 +712,7 @@ export function printInitGuide(): void {
|
|
|
711
712
|
Scaffold a project, then open the playground:
|
|
712
713
|
npx ${PACKAGE_NAME} init ./my-agent # installs deps + links agent-sdk onto PATH
|
|
713
714
|
npx ${PACKAGE_NAME} init ./my-demo --template demo # record a PR walkthrough
|
|
715
|
+
npx ${PACKAGE_NAME} init ./grokbot --template grokbot-agents # talk to Grok Bot agents
|
|
714
716
|
npx ${PACKAGE_NAME} init ./code-wiki --template code-wiki # keep wiki pages current after merge
|
|
715
717
|
npx ${PACKAGE_NAME} init ./agents-md --template agents-md # keep AGENTS.md current from last week's PRs and Slack
|
|
716
718
|
npx ${PACKAGE_NAME} init ./my-reviewer --template security-reviewer # review PRs for security bugs
|
|
@@ -719,8 +721,9 @@ Scaffold a project, then open the playground:
|
|
|
719
721
|
npx ${PACKAGE_NAME} init ./my-triage --template triage-jira # comment on Jira issues
|
|
720
722
|
npx ${PACKAGE_NAME} init ./my-owners --template agentic-owners # review PRs via owners policies
|
|
721
723
|
npx ${PACKAGE_NAME} init ./pr-autofixer --template pr-autofixer # fix PRs on a cloud VM
|
|
722
|
-
# TTY asks
|
|
724
|
+
# TTY asks the template's questions. Scripts pass --var:
|
|
723
725
|
# --var repos=acme/widgets,acme/api
|
|
726
|
+
# --var agents="Plan Keeper, Chief of Staff"
|
|
724
727
|
cd ./my-agent && agent-sdk dev # or: npx ${PACKAGE_NAME} dev
|
|
725
728
|
|
|
726
729
|
Recommended loop once the project exists (from the project directory):
|