@cursor/july 0.1.80 → 0.1.82
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 +0 -12
- package/dist/channels/github/cursor-account.d.ts +11 -0
- package/dist/channels/github/cursor-account.d.ts.map +1 -1
- package/dist/channels/github/cursor-account.js +13 -0
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +29 -1
- package/dist/channels/github/types.d.ts +8 -0
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +32 -10
- package/dist/channels/origin/types.d.ts +7 -0
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/cursor-account.d.ts.map +1 -1
- package/dist/channels/slack/cursor-account.js +2 -2
- package/dist/channels/slack/dispatch.d.ts +3 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +18 -18
- package/dist/channels/slack/interactive.d.ts +2 -0
- package/dist/channels/slack/interactive.d.ts.map +1 -1
- package/dist/channels/slack/interactive.js +4 -16
- package/dist/channels/slack/slack-channel.d.ts +1 -1
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +21 -10
- package/dist/channels/slack/types.d.ts +7 -0
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +4 -0
- package/dist/continuation.d.ts +20 -0
- package/dist/continuation.d.ts.map +1 -0
- package/dist/continuation.js +18 -0
- package/dist/docs/404.html +1 -1
- package/dist/docs/ab.html +2 -2
- package/dist/docs/assets/{app.e4_wtjUS.js → app.BEHVaPKt.js} +1 -1
- package/dist/docs/assets/chunks/{@localSearchIndexroot.BGiMJpnL.js → @localSearchIndexroot.Vvio4stV.js} +1 -1
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DbdzyEie.js → VPLocalSearchBox.D2-5PKih.js} +1 -1
- package/dist/docs/assets/chunks/{theme.D8HpLrLK.js → theme.uNqJ4MUO.js} +2 -2
- package/dist/docs/building-with-agents.html +2 -2
- package/dist/docs/concepts.html +2 -2
- package/dist/docs/deployment.html +2 -2
- package/dist/docs/evals.html +2 -2
- package/dist/docs/example-agents/approval-buddy.html +2 -2
- package/dist/docs/example-agents/benny.html +2 -2
- package/dist/docs/example-agents/bugbot.html +2 -2
- package/dist/docs/example-agents/codebase-wiki.html +2 -2
- package/dist/docs/example-agents/codeowners-review.html +2 -2
- package/dist/docs/example-agents/concierge.html +2 -2
- package/dist/docs/example-agents/fsd.html +2 -2
- package/dist/docs/example-agents/index.html +2 -2
- package/dist/docs/example-agents/knowledge-base.html +2 -2
- package/dist/docs/example-agents/oncall.html +2 -2
- package/dist/docs/example-agents/security-reviewer.html +2 -2
- package/dist/docs/example-agents/slack-agent.html +2 -2
- package/dist/docs/example-agents/weather-agent.html +2 -2
- package/dist/docs/guides/agent-to-agent.html +2 -2
- package/dist/docs/guides/cloud-runtime.html +2 -2
- package/dist/docs/guides/convert-automation.html +2 -2
- package/dist/docs/guides/github.html +2 -2
- package/dist/docs/guides/human-in-the-loop.html +2 -2
- package/dist/docs/guides/mcp-oauth.html +2 -2
- package/dist/docs/guides/opentelemetry.html +2 -2
- package/dist/docs/guides/slack.html +2 -2
- package/dist/docs/guides/webhooks.html +2 -2
- package/dist/docs/hillclimbing.html +2 -2
- package/dist/docs/index.html +2 -2
- package/dist/docs/quickstart.html +2 -2
- package/dist/docs/reference/agent-config.html +2 -2
- package/dist/docs/reference/artifacts.html +2 -2
- package/dist/docs/reference/channels.html +2 -2
- package/dist/docs/reference/cli.html +2 -2
- package/dist/docs/reference/connections.html +2 -2
- package/dist/docs/reference/hooks.html +2 -2
- package/dist/docs/reference/http-api.html +2 -2
- package/dist/docs/reference/instructions.html +2 -2
- package/dist/docs/reference/playground.html +2 -2
- package/dist/docs/reference/project-layout.html +2 -2
- package/dist/docs/reference/prompt.html +2 -2
- package/dist/docs/reference/schedules.html +2 -2
- package/dist/docs/reference/sessions.html +2 -2
- package/dist/docs/reference/skills.html +2 -2
- package/dist/docs/reference/subagents.html +2 -2
- package/dist/docs/reference/tools.html +2 -2
- package/dist/docs/scaffolding-agents.html +2 -2
- package/dist/docs/storage.html +2 -2
- package/dist/docs/templates/agentic-owners.html +2 -2
- package/dist/docs/templates/demo.html +2 -2
- package/dist/docs/templates/pr-autofixer.html +2 -2
- package/dist/docs/templates/security-reviewer.html +2 -2
- package/dist/docs/templates/triage.html +2 -2
- package/dist/docs/troubleshooting.html +2 -2
- package/dist/files.d.ts +9 -3
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +9 -3
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/internal/continuation-channel.d.ts +29 -0
- package/dist/internal/continuation-channel.d.ts.map +1 -0
- package/dist/internal/continuation-channel.js +88 -0
- package/dist/internal/continuation-identity.d.ts +95 -0
- package/dist/internal/continuation-identity.d.ts.map +1 -0
- package/dist/internal/continuation-identity.js +445 -0
- package/dist/internal/deploy-manifest.d.ts +12 -2
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +15 -7
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +32 -5
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +18 -8
- package/dist/internal/session-engine.d.ts +24 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +104 -34
- package/dist/internal/session-store.d.ts.map +1 -1
- package/dist/internal/session-store.js +6 -0
- package/dist/internal/skills-sync.d.ts +25 -0
- package/dist/internal/skills-sync.d.ts.map +1 -0
- package/dist/internal/skills-sync.js +96 -0
- package/dist/playground/assets/{index-DJzcIeGt.css → index-ChETdG-_.css} +1 -1
- package/dist/playground/assets/{index-K3Sxyx0I.js → index-CkuIrhg4.js} +3 -3
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +44 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/channels/github/cursor-account.ts +20 -0
- package/src/channels/github/github-channel.ts +52 -1
- package/src/channels/github/types.ts +8 -0
- package/src/channels/origin/origin-channel.ts +48 -10
- package/src/channels/origin/types.ts +7 -0
- package/src/channels/slack/cursor-account.ts +1 -0
- package/src/channels/slack/dispatch.ts +44 -2
- package/src/channels/slack/interactive.ts +5 -0
- package/src/channels/slack/slack-channel.ts +23 -2
- package/src/channels/slack/types.ts +7 -0
- package/src/channels.ts +7 -0
- package/src/continuation.ts +49 -0
- package/src/files.ts +10 -3
- package/src/index.ts +30 -1
- package/src/internal/continuation-channel.ts +129 -0
- package/src/internal/continuation-identity.ts +597 -0
- package/src/internal/deploy-manifest.ts +36 -3
- package/src/internal/discovery.ts +40 -2
- package/src/internal/server.ts +23 -9
- package/src/internal/session-engine.ts +132 -37
- package/src/internal/session-store.ts +6 -0
- package/src/internal/skills-sync.ts +107 -0
- package/src/types.ts +55 -0
|
@@ -6,6 +6,12 @@ import {
|
|
|
6
6
|
loopbackOnly,
|
|
7
7
|
POST,
|
|
8
8
|
} from "../../channels.js";
|
|
9
|
+
import {
|
|
10
|
+
bindMailboxContinuationSend,
|
|
11
|
+
continuationSource,
|
|
12
|
+
normalizeIdentity,
|
|
13
|
+
stampMailboxContinuation,
|
|
14
|
+
} from "../../internal/continuation-identity.js";
|
|
9
15
|
import { isDevMode } from "../../internal/dev-mode.js";
|
|
10
16
|
import type {
|
|
11
17
|
AgentCloudOptions,
|
|
@@ -443,15 +449,19 @@ function acknowledgeTask(
|
|
|
443
449
|
}
|
|
444
450
|
|
|
445
451
|
async function startTurn(input: {
|
|
452
|
+
options: OriginChannelOptions;
|
|
446
453
|
args: ChannelHandlerArgs;
|
|
447
454
|
ctx: OriginEventContext;
|
|
448
455
|
message: string;
|
|
449
456
|
dispatch: OriginTurnDispatch;
|
|
450
457
|
cloud?: AgentCloudOptions;
|
|
451
458
|
}): Promise<Response> {
|
|
459
|
+
const source = continuationSource(input.options.continuation, "origin");
|
|
452
460
|
const session = await input.args.send(input.message, {
|
|
453
461
|
auth: input.dispatch.auth,
|
|
454
|
-
|
|
462
|
+
...(source === "engine"
|
|
463
|
+
? { continuationToken: originContinuationKey(input.ctx) }
|
|
464
|
+
: {}),
|
|
455
465
|
title: input.dispatch.title ?? defaultOriginTitle(input.ctx),
|
|
456
466
|
...(input.cloud === undefined ? {} : { cloud: input.cloud }),
|
|
457
467
|
});
|
|
@@ -489,6 +499,7 @@ async function resolveCloudOptions(
|
|
|
489
499
|
}
|
|
490
500
|
|
|
491
501
|
async function applyDispatch(input: {
|
|
502
|
+
options: OriginChannelOptions;
|
|
492
503
|
args: ChannelHandlerArgs;
|
|
493
504
|
ctx: OriginEventContext;
|
|
494
505
|
dispatch: OriginDispatch | null;
|
|
@@ -507,6 +518,7 @@ async function applyDispatch(input: {
|
|
|
507
518
|
...(input.dispatch.context ?? []),
|
|
508
519
|
].join("\n");
|
|
509
520
|
return startTurn({
|
|
521
|
+
options: input.options,
|
|
510
522
|
args: input.args,
|
|
511
523
|
ctx: input.ctx,
|
|
512
524
|
message,
|
|
@@ -533,9 +545,21 @@ export async function dispatchOriginWebhook(input: {
|
|
|
533
545
|
{ status: 400 }
|
|
534
546
|
);
|
|
535
547
|
}
|
|
548
|
+
const identity = normalizeIdentity(input.options.continuation, "origin");
|
|
549
|
+
let args = input.args;
|
|
550
|
+
if (continuationSource(identity, "origin") === "control-plane") {
|
|
551
|
+
const mailbox = stampMailboxContinuation(identity, eventType, {
|
|
552
|
+
pullRequest: { number: parsed.ctx.pullRequestNumber },
|
|
553
|
+
repository: { fullName: parsed.ctx.repository.fullName },
|
|
554
|
+
});
|
|
555
|
+
args = {
|
|
556
|
+
...input.args,
|
|
557
|
+
send: bindMailboxContinuationSend(input.args.send, mailbox),
|
|
558
|
+
};
|
|
559
|
+
}
|
|
536
560
|
const ctx = enrichEventContext({
|
|
537
561
|
ctx: parsed.ctx,
|
|
538
|
-
args
|
|
562
|
+
args,
|
|
539
563
|
options: input.options,
|
|
540
564
|
});
|
|
541
565
|
const { pullRequest, payload } = parsed;
|
|
@@ -568,7 +592,8 @@ export async function dispatchOriginWebhook(input: {
|
|
|
568
592
|
};
|
|
569
593
|
const dispatch = await input.options.onComment(ctx, comment);
|
|
570
594
|
return applyDispatch({
|
|
571
|
-
|
|
595
|
+
options: input.options,
|
|
596
|
+
args,
|
|
572
597
|
ctx,
|
|
573
598
|
dispatch,
|
|
574
599
|
extra: { event: eventType },
|
|
@@ -588,7 +613,8 @@ export async function dispatchOriginWebhook(input: {
|
|
|
588
613
|
};
|
|
589
614
|
const dispatch = await input.options.onReview(ctx, review);
|
|
590
615
|
return applyDispatch({
|
|
591
|
-
|
|
616
|
+
options: input.options,
|
|
617
|
+
args,
|
|
592
618
|
ctx,
|
|
593
619
|
dispatch,
|
|
594
620
|
extra: { event: eventType },
|
|
@@ -607,7 +633,8 @@ export async function dispatchOriginWebhook(input: {
|
|
|
607
633
|
pullRequest
|
|
608
634
|
);
|
|
609
635
|
return applyDispatch({
|
|
610
|
-
|
|
636
|
+
options: input.options,
|
|
637
|
+
args,
|
|
611
638
|
ctx,
|
|
612
639
|
dispatch,
|
|
613
640
|
extra: { event: eventType },
|
|
@@ -622,7 +649,8 @@ export async function dispatchOriginWebhook(input: {
|
|
|
622
649
|
payload,
|
|
623
650
|
});
|
|
624
651
|
return applyDispatch({
|
|
625
|
-
|
|
652
|
+
options: input.options,
|
|
653
|
+
args,
|
|
626
654
|
ctx,
|
|
627
655
|
dispatch,
|
|
628
656
|
extra: { event: eventType },
|
|
@@ -725,13 +753,23 @@ export function originChannel(
|
|
|
725
753
|
: localDevStrict())(request, info),
|
|
726
754
|
];
|
|
727
755
|
|
|
756
|
+
const channelOptions: OriginChannelOptions = {
|
|
757
|
+
...options,
|
|
758
|
+
};
|
|
759
|
+
if (channelOptions.continuation !== undefined) {
|
|
760
|
+
channelOptions.continuation = normalizeIdentity(
|
|
761
|
+
channelOptions.continuation,
|
|
762
|
+
"origin"
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
|
|
728
766
|
const definition = defineChannel({
|
|
729
767
|
auth,
|
|
730
768
|
onStart: options.onStart,
|
|
731
769
|
onStop: options.onStop,
|
|
732
770
|
meta: {
|
|
733
771
|
kind: ORIGIN_CHANNEL_KIND,
|
|
734
|
-
originWebhookEvents: deriveOriginWebhookEvents(
|
|
772
|
+
originWebhookEvents: deriveOriginWebhookEvents(channelOptions),
|
|
735
773
|
},
|
|
736
774
|
routes: [
|
|
737
775
|
POST(routePath, {
|
|
@@ -739,17 +777,17 @@ export function originChannel(
|
|
|
739
777
|
description: "Origin webhook ingress",
|
|
740
778
|
handler: async (request, args) =>
|
|
741
779
|
handleOriginWebhookRequest({
|
|
742
|
-
options,
|
|
780
|
+
options: channelOptions,
|
|
743
781
|
request,
|
|
744
782
|
args,
|
|
745
783
|
}),
|
|
746
784
|
}),
|
|
747
785
|
],
|
|
748
786
|
});
|
|
749
|
-
originChannelOptionsByDefinition.set(definition,
|
|
787
|
+
originChannelOptionsByDefinition.set(definition, channelOptions);
|
|
750
788
|
if (usesCursorAccount) {
|
|
751
789
|
registerOriginCursorAccountRuntime(definition, {
|
|
752
|
-
options,
|
|
790
|
+
options: channelOptions,
|
|
753
791
|
scope: cursorScope,
|
|
754
792
|
});
|
|
755
793
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ContinuationIdentity } from "../../continuation.js";
|
|
1
2
|
import type {
|
|
2
3
|
AgentCloudOptions,
|
|
3
4
|
ArtifactsApi,
|
|
@@ -195,6 +196,12 @@ export interface OriginChannelOptions {
|
|
|
195
196
|
* `meta.originWebhookEvents`). Defaults to the set derived from hooks.
|
|
196
197
|
*/
|
|
197
198
|
webhookEvents?: readonly string[];
|
|
199
|
+
/**
|
|
200
|
+
* Continuation selector. Omitted inherits {@link AgentConfig.architecture}:
|
|
201
|
+
* `"origin.pr/v1"` unless the agent set `architecture: "v2"` (then
|
|
202
|
+
* `"origin.pr/v2"`). Override with `"origin.none/v2"` for one-shot events.
|
|
203
|
+
*/
|
|
204
|
+
continuation?: ContinuationIdentity;
|
|
198
205
|
/**
|
|
199
206
|
* Decide whether an inbound pull-request event starts a turn. Return
|
|
200
207
|
* `{ auth: defaultOriginAuth(ctx) }` to dispatch, `null` to ignore.
|
|
@@ -196,6 +196,7 @@ export async function dispatchCursorSlackEnvelope(args: {
|
|
|
196
196
|
...(args.interruptContinuation === undefined
|
|
197
197
|
? {}
|
|
198
198
|
: { interruptContinuation: args.interruptContinuation }),
|
|
199
|
+
continuation: runtime.options.continuation,
|
|
199
200
|
...(envelope.eventId === undefined ? {} : { eventId: envelope.eventId }),
|
|
200
201
|
});
|
|
201
202
|
}
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
* Shared inbound dispatch for Slack Events API bodies and Socket Mode.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import {
|
|
6
|
+
type ContinuationIdentity,
|
|
7
|
+
continuationSource,
|
|
8
|
+
type MailboxContinuation,
|
|
9
|
+
normalizeIdentity,
|
|
10
|
+
stampMailboxContinuation,
|
|
11
|
+
} from "../../internal/continuation-identity.js";
|
|
5
12
|
import type {
|
|
6
13
|
ArtifactsApi,
|
|
7
14
|
HostContext,
|
|
@@ -121,6 +128,7 @@ export function emptySlackChannelState(
|
|
|
121
128
|
|
|
122
129
|
export interface SlackInboundDispatchDeps extends SlackContinuationProbes {
|
|
123
130
|
send: SendMessageFn;
|
|
131
|
+
continuation?: ContinuationIdentity;
|
|
124
132
|
waitUntil: (promise: Promise<unknown>) => void;
|
|
125
133
|
onAppMention: SlackMessageHandler;
|
|
126
134
|
onDirectMessage: SlackMessageHandler;
|
|
@@ -180,6 +188,35 @@ function triggeringMergeMessage(
|
|
|
180
188
|
};
|
|
181
189
|
}
|
|
182
190
|
|
|
191
|
+
function continuationArg(identity: ContinuationIdentity | undefined): {
|
|
192
|
+
continuation?: ContinuationIdentity;
|
|
193
|
+
} {
|
|
194
|
+
return identity === undefined ? {} : { continuation: identity };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function slackSessionContinuation(
|
|
198
|
+
identity: ContinuationIdentity | undefined,
|
|
199
|
+
channelId: string,
|
|
200
|
+
threadTs: string
|
|
201
|
+
): {
|
|
202
|
+
probeKey: string;
|
|
203
|
+
sendPatch:
|
|
204
|
+
| { continuationToken: string }
|
|
205
|
+
| { mailboxContinuation: MailboxContinuation };
|
|
206
|
+
} {
|
|
207
|
+
if (continuationSource(identity, "slack") === "engine") {
|
|
208
|
+
const key = slackContinuationKey(channelId, threadTs);
|
|
209
|
+
return { probeKey: key, sendPatch: { continuationToken: key } };
|
|
210
|
+
}
|
|
211
|
+
const mailbox = stampMailboxContinuation(
|
|
212
|
+
normalizeIdentity(identity, "slack"),
|
|
213
|
+
"message",
|
|
214
|
+
{ channelId, threadTs },
|
|
215
|
+
"slack"
|
|
216
|
+
);
|
|
217
|
+
return { probeKey: mailbox.key, sendPatch: { mailboxContinuation: mailbox } };
|
|
218
|
+
}
|
|
219
|
+
|
|
183
220
|
export async function dispatchInboundMessage(args: {
|
|
184
221
|
kind:
|
|
185
222
|
| "app_mention"
|
|
@@ -210,6 +247,7 @@ export async function dispatchInboundMessage(args: {
|
|
|
210
247
|
*/
|
|
211
248
|
cursorAgentName?: string;
|
|
212
249
|
blockExternals?: boolean;
|
|
250
|
+
continuation?: ContinuationIdentity;
|
|
213
251
|
}): Promise<void> {
|
|
214
252
|
const { message, kind } = args;
|
|
215
253
|
const log = args.log ?? defaultSlackLog;
|
|
@@ -265,7 +303,8 @@ export async function dispatchInboundMessage(args: {
|
|
|
265
303
|
}
|
|
266
304
|
}
|
|
267
305
|
|
|
268
|
-
const continuation =
|
|
306
|
+
const { probeKey: continuation, sendPatch } = slackSessionContinuation(
|
|
307
|
+
args.continuation,
|
|
269
308
|
message.channelId,
|
|
270
309
|
message.threadTs
|
|
271
310
|
);
|
|
@@ -454,7 +493,7 @@ export async function dispatchInboundMessage(args: {
|
|
|
454
493
|
|
|
455
494
|
const sendOptions = {
|
|
456
495
|
auth: decision.auth,
|
|
457
|
-
|
|
496
|
+
...sendPatch,
|
|
458
497
|
admission: "coalesce" as const,
|
|
459
498
|
coalesceSourceTs: message.ts,
|
|
460
499
|
state: emptySlackChannelState({
|
|
@@ -617,6 +656,7 @@ export function dispatchInboundFromEventBody(
|
|
|
617
656
|
cursorAgentName: deps.cursorAgentName,
|
|
618
657
|
followUpStatus: deps.followUpStatus,
|
|
619
658
|
blockExternals: deps.blockExternals,
|
|
659
|
+
...continuationArg(deps.continuation),
|
|
620
660
|
...(deps.hasContinuationSession === undefined
|
|
621
661
|
? {}
|
|
622
662
|
: { hasContinuationSession: deps.hasContinuationSession }),
|
|
@@ -660,6 +700,7 @@ export function dispatchInboundFromEventBody(
|
|
|
660
700
|
cursorAgentName: deps.cursorAgentName,
|
|
661
701
|
followUpStatus: deps.followUpStatus,
|
|
662
702
|
blockExternals: deps.blockExternals,
|
|
703
|
+
...continuationArg(deps.continuation),
|
|
663
704
|
...(deps.hasContinuationSession === undefined
|
|
664
705
|
? {}
|
|
665
706
|
: { hasContinuationSession: deps.hasContinuationSession }),
|
|
@@ -697,6 +738,7 @@ export function dispatchInboundFromEventBody(
|
|
|
697
738
|
cursorAgentName: deps.cursorAgentName,
|
|
698
739
|
followUpStatus: deps.followUpStatus,
|
|
699
740
|
blockExternals: deps.blockExternals,
|
|
741
|
+
...continuationArg(deps.continuation),
|
|
700
742
|
...(deps.hasContinuationSession === undefined
|
|
701
743
|
? {}
|
|
702
744
|
: { hasContinuationSession: deps.hasContinuationSession }),
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* `slackChannel({ onBlockAction })`).
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import type { ContinuationIdentity } from "../../internal/continuation-identity.js";
|
|
10
11
|
import type {
|
|
11
12
|
ApprovalDecision,
|
|
12
13
|
ArtifactsApi,
|
|
@@ -298,6 +299,7 @@ export async function resolveBlockActionCard(args: {
|
|
|
298
299
|
export interface SlackBlockActionDispatchDeps extends SlackContinuationProbes {
|
|
299
300
|
handler: SlackBlockActionHandler;
|
|
300
301
|
send: SendMessageFn;
|
|
302
|
+
continuation?: ContinuationIdentity;
|
|
301
303
|
credentials: SlackCredentials | undefined;
|
|
302
304
|
host: HostContext;
|
|
303
305
|
artifacts: ArtifactsApi;
|
|
@@ -389,6 +391,9 @@ export async function dispatchBlockAction(
|
|
|
389
391
|
isContinuationBusy: deps.isContinuationBusy,
|
|
390
392
|
getContinuationLastBotMessageTs: deps.getContinuationLastBotMessageTs,
|
|
391
393
|
interruptContinuation: deps.interruptContinuation,
|
|
394
|
+
...(deps.continuation === undefined
|
|
395
|
+
? {}
|
|
396
|
+
: { continuation: deps.continuation }),
|
|
392
397
|
});
|
|
393
398
|
return true;
|
|
394
399
|
}
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { allowAll, defineChannel } from "../../channels.js";
|
|
11
|
+
import {
|
|
12
|
+
continuationSource,
|
|
13
|
+
normalizeIdentity,
|
|
14
|
+
} from "../../internal/continuation-identity.js";
|
|
11
15
|
import type {
|
|
12
16
|
ArtifactsApi,
|
|
13
17
|
ChannelDefinition,
|
|
@@ -126,10 +130,14 @@ export function resolveDedicatedSlackHostBinding(
|
|
|
126
130
|
* runtime values are still checked by {@link assertSlackCursorAgentName}.
|
|
127
131
|
*/
|
|
128
132
|
export function slackChannel<const Name extends string = string>(
|
|
129
|
-
|
|
133
|
+
authored: Omit<SlackChannelOptions, "agentName"> & {
|
|
130
134
|
agentName?: SlackCursorAgentName<Name>;
|
|
131
135
|
} = {}
|
|
132
136
|
): ChannelDefinition<SlackChannelState> {
|
|
137
|
+
const options = { ...authored };
|
|
138
|
+
if (options.continuation !== undefined) {
|
|
139
|
+
options.continuation = normalizeIdentity(options.continuation, "slack");
|
|
140
|
+
}
|
|
133
141
|
const cursorAccount = options.cursorAccount === true;
|
|
134
142
|
if (cursorAccount) {
|
|
135
143
|
// Token pair and the Cursor connection are different Slack apps —
|
|
@@ -285,6 +293,7 @@ export function slackChannel<const Name extends string = string>(
|
|
|
285
293
|
}): SlackInboundDispatchDeps {
|
|
286
294
|
return {
|
|
287
295
|
send: args.send,
|
|
296
|
+
continuation: options.continuation,
|
|
288
297
|
waitUntil: args.waitUntil,
|
|
289
298
|
onAppMention,
|
|
290
299
|
onDirectMessage,
|
|
@@ -359,7 +368,17 @@ export function slackChannel<const Name extends string = string>(
|
|
|
359
368
|
return send(input.message, {
|
|
360
369
|
auth: input.auth,
|
|
361
370
|
admission: "coalesce",
|
|
362
|
-
|
|
371
|
+
...(continuationSource(options.continuation, "slack") ===
|
|
372
|
+
"control-plane"
|
|
373
|
+
? {
|
|
374
|
+
claim: {
|
|
375
|
+
type: "thread" as const,
|
|
376
|
+
resource: { channelId, threadTs },
|
|
377
|
+
},
|
|
378
|
+
}
|
|
379
|
+
: {
|
|
380
|
+
continuationToken: slackContinuationKey(channelId, threadTs),
|
|
381
|
+
}),
|
|
363
382
|
state: emptySlackChannelState({
|
|
364
383
|
channelId,
|
|
365
384
|
threadTs,
|
|
@@ -488,6 +507,7 @@ export function slackChannel<const Name extends string = string>(
|
|
|
488
507
|
evalCommandsEnabled,
|
|
489
508
|
followUpStatus,
|
|
490
509
|
blockExternals,
|
|
510
|
+
continuation: options.continuation,
|
|
491
511
|
...(args.hasContinuationSession === undefined
|
|
492
512
|
? {}
|
|
493
513
|
: {
|
|
@@ -583,6 +603,7 @@ export function slackChannel<const Name extends string = string>(
|
|
|
583
603
|
getContinuationLastBotMessageTs:
|
|
584
604
|
args.getContinuationLastBotMessageTs,
|
|
585
605
|
interruptContinuation: args.interruptContinuation,
|
|
606
|
+
continuation: options.continuation,
|
|
586
607
|
});
|
|
587
608
|
};
|
|
588
609
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Types for the Slack platform channel pack.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { ContinuationIdentity } from "../../continuation.js";
|
|
5
6
|
import type {
|
|
6
7
|
AgentCloudOptions,
|
|
7
8
|
ArtifactsApi,
|
|
@@ -490,6 +491,12 @@ export interface SlackAccessPolicy {
|
|
|
490
491
|
|
|
491
492
|
export interface SlackChannelOptions {
|
|
492
493
|
credentials?: SlackCredentials;
|
|
494
|
+
/**
|
|
495
|
+
* Continuation selector. Omitted inherits {@link AgentConfig.architecture}:
|
|
496
|
+
* `"slack.thread/v1"` unless the agent set `architecture: "v2"` (then
|
|
497
|
+
* `"slack.thread/v2"`). Override with `"slack.none/v2"` for one-shot events.
|
|
498
|
+
*/
|
|
499
|
+
continuation?: ContinuationIdentity;
|
|
493
500
|
/** Defaults to `{ respondTo: "thread", blockExternals: true }`. */
|
|
494
501
|
policy?: SlackAccessPolicy;
|
|
495
502
|
/**
|
package/src/channels.ts
CHANGED
|
@@ -66,6 +66,7 @@ export {
|
|
|
66
66
|
import { Buffer } from "node:buffer";
|
|
67
67
|
import { timingSafeEqual } from "node:crypto";
|
|
68
68
|
import { brandDefinition } from "./internal/brand.js";
|
|
69
|
+
import { normalizeIdentity } from "./internal/continuation-identity.js";
|
|
69
70
|
import { isLoopbackAddress, isLoopbackHostname } from "./internal/net.js";
|
|
70
71
|
import type {
|
|
71
72
|
AuthContext,
|
|
@@ -127,6 +128,12 @@ export function defineChannel<TState = JsonValue>(
|
|
|
127
128
|
export function httpChannel(
|
|
128
129
|
config: HttpChannelConfig = {}
|
|
129
130
|
): HttpChannelDefinition {
|
|
131
|
+
if (config.continuation !== undefined) {
|
|
132
|
+
return brandDefinition("http-channel", {
|
|
133
|
+
...config,
|
|
134
|
+
continuation: normalizeIdentity(config.continuation, "http"),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
130
137
|
return brandDefinition("http-channel", config);
|
|
131
138
|
}
|
|
132
139
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public continuation-identity surface for `@cursor/july`.
|
|
3
|
+
*
|
|
4
|
+
* Omitted `continuation` on a channel constructor stays `/v1` (engine
|
|
5
|
+
* minting). Deploy onto the v2 control plane with a root architecture
|
|
6
|
+
* flag; omitted channels then inherit the kind `/v2` default:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* export default defineAgent({
|
|
10
|
+
* architecture: "v2",
|
|
11
|
+
* });
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Per-channel selectors still override type (`"github.issue/v2"`,
|
|
15
|
+
* `"github.none/v2"`). Other `/v2` selectors: `"slack.thread/v2"`,
|
|
16
|
+
* `"origin.pr/v2"`, `"none/v2"`.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export type {
|
|
20
|
+
ContinuationBuiltin,
|
|
21
|
+
ContinuationClaim,
|
|
22
|
+
ContinuationIdentity,
|
|
23
|
+
ContinuationProtocolVersion,
|
|
24
|
+
ContinuationSelector,
|
|
25
|
+
ConversationType,
|
|
26
|
+
MailboxContinuation,
|
|
27
|
+
ParsedContinuation,
|
|
28
|
+
} from "./internal/continuation-identity.js";
|
|
29
|
+
export {
|
|
30
|
+
BUILTINS,
|
|
31
|
+
bindMailboxContinuationSend,
|
|
32
|
+
builtinForType,
|
|
33
|
+
CONTINUATION_SELECTORS,
|
|
34
|
+
continuationSource,
|
|
35
|
+
defaultContinuationSelector,
|
|
36
|
+
extractContinuation,
|
|
37
|
+
formatConversationKey,
|
|
38
|
+
handshakeContinuation,
|
|
39
|
+
isContinuationSelector,
|
|
40
|
+
isV2DurableContinuationKey,
|
|
41
|
+
mintClaim,
|
|
42
|
+
newEvtKey,
|
|
43
|
+
normalizeIdentity,
|
|
44
|
+
parseContinuationSelector,
|
|
45
|
+
resolveContinuation,
|
|
46
|
+
resolveV2Key,
|
|
47
|
+
stampMailboxContinuation,
|
|
48
|
+
V2EngineError,
|
|
49
|
+
} from "./internal/continuation-identity.js";
|
package/src/files.ts
CHANGED
|
@@ -142,9 +142,13 @@ export const fileKeys = {
|
|
|
142
142
|
|
|
143
143
|
/**
|
|
144
144
|
* Framework-owned keys for state that lives on the deployment's Agent Store
|
|
145
|
-
* but is not author `host.files` data: artifact rows and payloads,
|
|
146
|
-
* cross-session memory journal. Kept
|
|
147
|
-
* see framework rows.
|
|
145
|
+
* but is not author `host.files` data: artifact rows and payloads, authored
|
|
146
|
+
* skills synced for cloud turns, and the cross-session memory journal. Kept
|
|
147
|
+
* out of `files/` so author listings never see framework rows.
|
|
148
|
+
*
|
|
149
|
+
* Skills sit at store-root `skills/<name>/…` so exec-daemon's
|
|
150
|
+
* `--agent-store-skills-dir` walk finds them the same way it finds user-store
|
|
151
|
+
* skills. Memory and artifacts stay under {@link STORAGE_KEY_ROOT}.
|
|
148
152
|
*/
|
|
149
153
|
export const agentStoreKeys = {
|
|
150
154
|
artifactRow: (agent: string, id: string): string =>
|
|
@@ -153,6 +157,9 @@ export const agentStoreKeys = {
|
|
|
153
157
|
`${STORAGE_KEY_ROOT}/${agent}/artifacts/rows/`,
|
|
154
158
|
artifactContent: (agent: string, id: string): string =>
|
|
155
159
|
`${STORAGE_KEY_ROOT}/${agent}/artifacts/content/${encodeURIComponent(id)}`,
|
|
160
|
+
skillFile: (skillName: string, relPath: string): string =>
|
|
161
|
+
`skills/${skillName}/${relPath}`,
|
|
162
|
+
skillsPrefix: (): string => "skills/",
|
|
156
163
|
memoryDir: (agent: string): string => `${STORAGE_KEY_ROOT}/${agent}/memory`,
|
|
157
164
|
memoryJournal: (agent: string): string =>
|
|
158
165
|
`${STORAGE_KEY_ROOT}/${agent}/memory/journal.jsonl`,
|
package/src/index.ts
CHANGED
|
@@ -51,6 +51,33 @@ export {
|
|
|
51
51
|
publicEndpoint,
|
|
52
52
|
} from "./channels.js";
|
|
53
53
|
export { defineConnection } from "./connections.js";
|
|
54
|
+
export type {
|
|
55
|
+
ContinuationBuiltin,
|
|
56
|
+
ContinuationClaim,
|
|
57
|
+
ContinuationIdentity,
|
|
58
|
+
ContinuationSelector,
|
|
59
|
+
ConversationType,
|
|
60
|
+
MailboxContinuation,
|
|
61
|
+
ParsedContinuation,
|
|
62
|
+
} from "./continuation.js";
|
|
63
|
+
export {
|
|
64
|
+
BUILTINS,
|
|
65
|
+
bindMailboxContinuationSend,
|
|
66
|
+
CONTINUATION_SELECTORS,
|
|
67
|
+
continuationSource,
|
|
68
|
+
defaultContinuationSelector,
|
|
69
|
+
extractContinuation,
|
|
70
|
+
formatConversationKey,
|
|
71
|
+
handshakeContinuation,
|
|
72
|
+
isContinuationSelector,
|
|
73
|
+
mintClaim,
|
|
74
|
+
normalizeIdentity,
|
|
75
|
+
parseContinuationSelector,
|
|
76
|
+
resolveContinuation,
|
|
77
|
+
resolveV2Key,
|
|
78
|
+
stampMailboxContinuation,
|
|
79
|
+
V2EngineError,
|
|
80
|
+
} from "./continuation.js";
|
|
54
81
|
export { defineHook } from "./hooks.js";
|
|
55
82
|
export type { LoadAgentProjectOptions } from "./internal/discovery.js";
|
|
56
83
|
export {
|
|
@@ -162,7 +189,9 @@ export {
|
|
|
162
189
|
|
|
163
190
|
/**
|
|
164
191
|
* Runtime config for an agent — authored at `agent/agent.ts` (the root
|
|
165
|
-
* agent) or `agent/subagents/<id>/agent.ts` (a subagent).
|
|
192
|
+
* agent) or `agent/subagents/<id>/agent.ts` (a subagent). Set
|
|
193
|
+
* `architecture: "v2"` to deploy onto the v2 control plane; omitted
|
|
194
|
+
* channel continuation then inherits kind `/v2` defaults.
|
|
166
195
|
*/
|
|
167
196
|
export function defineAgent(config: AgentConfig): AgentConfigDefinition {
|
|
168
197
|
return brandDefinition("agent", config);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { getGitHubChannelOptions } from "../channels/github/github-channel.js";
|
|
2
|
+
import { getOriginChannelOptions } from "../channels/origin/origin-channel.js";
|
|
3
|
+
import { getSlackChannelOptions } from "../channels/slack/slack-channel.js";
|
|
4
|
+
import type {
|
|
5
|
+
AgentArchitecture,
|
|
6
|
+
ChannelDefinition,
|
|
7
|
+
HttpChannelDefinition,
|
|
8
|
+
} from "../types.js";
|
|
9
|
+
import {
|
|
10
|
+
type ContinuationIdentity,
|
|
11
|
+
type ContinuationProtocolVersion,
|
|
12
|
+
defaultContinuationSelector,
|
|
13
|
+
handshakeContinuation,
|
|
14
|
+
normalizeIdentity,
|
|
15
|
+
} from "./continuation-identity.js";
|
|
16
|
+
|
|
17
|
+
export function channelContinuationIdentity(
|
|
18
|
+
definition: object | undefined
|
|
19
|
+
): ContinuationIdentity {
|
|
20
|
+
if (definition === undefined) {
|
|
21
|
+
return defaultContinuationSelector();
|
|
22
|
+
}
|
|
23
|
+
const github = getGitHubChannelOptions(definition);
|
|
24
|
+
if (github !== undefined) {
|
|
25
|
+
return normalizeIdentity(github.continuation, "github");
|
|
26
|
+
}
|
|
27
|
+
const slack = getSlackChannelOptions(definition);
|
|
28
|
+
if (slack !== undefined) {
|
|
29
|
+
return normalizeIdentity(slack.continuation, "slack");
|
|
30
|
+
}
|
|
31
|
+
const origin = getOriginChannelOptions(definition);
|
|
32
|
+
if (origin !== undefined) {
|
|
33
|
+
return normalizeIdentity(origin.continuation, "origin");
|
|
34
|
+
}
|
|
35
|
+
return defaultContinuationSelector();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function httpContinuationIdentity(
|
|
39
|
+
httpChannel: HttpChannelDefinition | undefined
|
|
40
|
+
): ContinuationIdentity {
|
|
41
|
+
return normalizeIdentity(httpChannel?.continuation, "http");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Stamp `/v2` continuation defaults onto channel constructors that omitted
|
|
46
|
+
* `continuation` when the agent deploys onto v2 architecture. GitHub/Origin
|
|
47
|
+
* type (`pr` / `issue` / `none`) follows declared webhook events. Explicit
|
|
48
|
+
* per-channel selectors are left alone. Idempotent.
|
|
49
|
+
*/
|
|
50
|
+
export function applyAgentContinuationDefaults(project: {
|
|
51
|
+
agent: { architecture?: AgentArchitecture };
|
|
52
|
+
channels: ReadonlyArray<{ definition: object }>;
|
|
53
|
+
httpChannel: HttpChannelDefinition;
|
|
54
|
+
}): void {
|
|
55
|
+
if (project.agent.architecture !== "v2") {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
for (const channel of project.channels) {
|
|
59
|
+
stampOmittedChannelContinuation(channel.definition, "v2");
|
|
60
|
+
}
|
|
61
|
+
if (project.httpChannel.continuation === undefined) {
|
|
62
|
+
project.httpChannel.continuation = defaultContinuationSelector(
|
|
63
|
+
"http",
|
|
64
|
+
"v2"
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function stampOmittedChannelContinuation(
|
|
70
|
+
definition: object,
|
|
71
|
+
version: ContinuationProtocolVersion
|
|
72
|
+
): void {
|
|
73
|
+
const events = declaredChannelEventTypes(definition);
|
|
74
|
+
const github = getGitHubChannelOptions(definition);
|
|
75
|
+
if (github !== undefined) {
|
|
76
|
+
if (github.continuation === undefined) {
|
|
77
|
+
github.continuation = defaultContinuationSelector(
|
|
78
|
+
"github",
|
|
79
|
+
version,
|
|
80
|
+
events
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const slack = getSlackChannelOptions(definition);
|
|
86
|
+
if (slack !== undefined) {
|
|
87
|
+
if (slack.continuation === undefined) {
|
|
88
|
+
slack.continuation = defaultContinuationSelector("slack", version);
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const origin = getOriginChannelOptions(definition);
|
|
93
|
+
if (origin !== undefined) {
|
|
94
|
+
if (origin.continuation === undefined) {
|
|
95
|
+
origin.continuation = defaultContinuationSelector(
|
|
96
|
+
"origin",
|
|
97
|
+
version,
|
|
98
|
+
events
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function declaredChannelEventTypes(
|
|
105
|
+
definition: object
|
|
106
|
+
): readonly string[] | undefined {
|
|
107
|
+
const meta = (definition as ChannelDefinition).meta;
|
|
108
|
+
return meta?.githubWebhookEvents ?? meta?.originWebhookEvents;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function handshakeChannelContinuation(input: {
|
|
112
|
+
id: string;
|
|
113
|
+
definition: ChannelDefinition;
|
|
114
|
+
}): { ok: true } | { ok: false; error: string } {
|
|
115
|
+
const kind = input.definition.meta?.kind;
|
|
116
|
+
const eventTypes = [
|
|
117
|
+
...(input.definition.meta?.githubWebhookEvents ?? []),
|
|
118
|
+
...(input.definition.meta?.originWebhookEvents ?? []),
|
|
119
|
+
];
|
|
120
|
+
const result = handshakeContinuation({
|
|
121
|
+
kind,
|
|
122
|
+
eventTypes,
|
|
123
|
+
identity: channelContinuationIdentity(input.definition),
|
|
124
|
+
});
|
|
125
|
+
if (!result.ok) {
|
|
126
|
+
return { ok: false, error: `channel ${input.id}: ${result.error}` };
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|