@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-session reminder runner: durable wake subscriptions with
|
|
3
|
-
* prompt XOR run, every/cron/delay/at schedules, and
|
|
4
|
-
* function XOR prompt.
|
|
3
|
+
* prompt XOR named handler XOR run, every/cron/delay/at schedules, and
|
|
4
|
+
* until as function XOR prompt.
|
|
5
5
|
*/
|
|
6
6
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
7
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
@@ -13,11 +13,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
13
13
|
});
|
|
14
14
|
};
|
|
15
15
|
import { randomBytes } from "node:crypto";
|
|
16
|
+
import { NAME_PATTERN } from "./discovery/names.js";
|
|
16
17
|
import { parseDuration } from "./duration.js";
|
|
18
|
+
import { REMINDER_CP_PROTOCOL_VERSION, scheduleSpecFromCreateInput, toWireReschedule, } from "./reminder-control-plane-protocol.js";
|
|
17
19
|
import { defaultBusyPolicy, MAX_TIMER_MS, nextCronFireMs, ReminderValidationError, resolveSchedule, } from "./reminder-schedule.js";
|
|
18
20
|
import { APP_AUTH } from "./schedule-runner.js";
|
|
19
21
|
import { SessionBusyError } from "./session-engine.js";
|
|
20
22
|
export { ReminderValidationError } from "./reminder-schedule.js";
|
|
23
|
+
/** Max UTF-8 byte length of `JSON.stringify(args)` on named-handler create. */
|
|
24
|
+
export const REMINDER_ARGS_MAX_BYTES = 32 * 1024;
|
|
21
25
|
export class UnknownReminderError extends Error {
|
|
22
26
|
constructor(reminderId, availableReminderIds) {
|
|
23
27
|
super(`Unknown reminder "${reminderId}"`);
|
|
@@ -25,9 +29,46 @@ export class UnknownReminderError extends Error {
|
|
|
25
29
|
this.name = "UnknownReminderError";
|
|
26
30
|
}
|
|
27
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Server wiring for {@link ReminderRunnerOptions.rejectAnonymousHandlers}:
|
|
34
|
+
* architecture v2 always rejects anonymous run/until (local or hosted).
|
|
35
|
+
*/
|
|
36
|
+
export function rejectAnonymousReminderHandlers(options) {
|
|
37
|
+
return options.architecture === "v2";
|
|
38
|
+
}
|
|
28
39
|
function newReminderId() {
|
|
29
40
|
return `rem_${randomBytes(8).toString("hex")}`;
|
|
30
41
|
}
|
|
42
|
+
function isJsonObject(value) {
|
|
43
|
+
return (typeof value === "object" &&
|
|
44
|
+
value !== null &&
|
|
45
|
+
!Array.isArray(value) &&
|
|
46
|
+
Object.values(value).every(isJsonValue));
|
|
47
|
+
}
|
|
48
|
+
function isJsonValue(value) {
|
|
49
|
+
if (value === null ||
|
|
50
|
+
typeof value === "string" ||
|
|
51
|
+
typeof value === "boolean") {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
if (typeof value === "number") {
|
|
55
|
+
return Number.isFinite(value);
|
|
56
|
+
}
|
|
57
|
+
if (Array.isArray(value)) {
|
|
58
|
+
return value.every(isJsonValue);
|
|
59
|
+
}
|
|
60
|
+
return isJsonObject(value);
|
|
61
|
+
}
|
|
62
|
+
/** Same stem rules as `agent/reminders/<name>.ts` discovery. */
|
|
63
|
+
function isValidReminderHandlerName(name) {
|
|
64
|
+
return NAME_PATTERN.test(name) && !name.includes("__");
|
|
65
|
+
}
|
|
66
|
+
function assertReminderArgsSize(args) {
|
|
67
|
+
const bytes = Buffer.byteLength(JSON.stringify(args), "utf8");
|
|
68
|
+
if (bytes > REMINDER_ARGS_MAX_BYTES) {
|
|
69
|
+
throw new ReminderValidationError(`reminders.create args exceed ${REMINDER_ARGS_MAX_BYTES} bytes (got ${bytes})`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
31
72
|
function toInfo(record) {
|
|
32
73
|
return {
|
|
33
74
|
id: record.id,
|
|
@@ -38,9 +79,11 @@ function toInfo(record) {
|
|
|
38
79
|
scheduleKind: record.scheduleKind,
|
|
39
80
|
scheduleValue: record.scheduleValue,
|
|
40
81
|
prompt: record.prompt,
|
|
82
|
+
handler: record.handler,
|
|
83
|
+
args: record.args,
|
|
41
84
|
untilPrompt: record.untilPrompt,
|
|
42
85
|
busyPolicy: record.busyPolicy,
|
|
43
|
-
status: record.status,
|
|
86
|
+
status: record.status === "firing" ? "armed" : record.status,
|
|
44
87
|
disarmReason: record.disarmReason,
|
|
45
88
|
fireCount: record.fireCount,
|
|
46
89
|
nextFireAt: new Date(record.nextFireAtMs).toISOString(),
|
|
@@ -69,17 +112,31 @@ function buildFirePrompt(record) {
|
|
|
69
112
|
return lines.join("\n");
|
|
70
113
|
}
|
|
71
114
|
export class ReminderRunner {
|
|
72
|
-
constructor(engine, logger = () => { }, platformTimers) {
|
|
115
|
+
constructor(engine, logger = () => { }, platformTimers, options = {}) {
|
|
116
|
+
var _a;
|
|
73
117
|
this.engine = engine;
|
|
74
118
|
this.logger = logger;
|
|
75
119
|
this.platformTimers = platformTimers;
|
|
76
120
|
this.records = new Map();
|
|
77
121
|
this.handlers = new Map();
|
|
122
|
+
this.namedHandlers = new Map();
|
|
123
|
+
this.namedHandlerNames = new Map();
|
|
78
124
|
this.timers = new Map();
|
|
79
125
|
this.firing = new Set();
|
|
80
126
|
/** Single-flight idle gates keyed by `channelId:continuationToken`. */
|
|
81
127
|
this.idleGates = new Map();
|
|
82
128
|
this.started = false;
|
|
129
|
+
this.rejectAnonymousHandlers = options.rejectAnonymousHandlers === true;
|
|
130
|
+
this.controlPlane = options.controlPlane;
|
|
131
|
+
this.architecture = options.architecture;
|
|
132
|
+
for (const reminder of (_a = options.namedHandlers) !== null && _a !== void 0 ? _a : []) {
|
|
133
|
+
this.namedHandlers.set(reminder.name, reminder.definition);
|
|
134
|
+
this.namedHandlerNames.set(reminder.definition, reminder.name);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** True when create/cancel/rekey/fire go through the CP protocol. */
|
|
138
|
+
get usesControlPlaneProtocol() {
|
|
139
|
+
return this.controlPlane !== undefined && this.architecture === "v2";
|
|
83
140
|
}
|
|
84
141
|
/**
|
|
85
142
|
* Load reminder documents from the control plane into memory. Does not
|
|
@@ -107,6 +164,13 @@ export class ReminderRunner {
|
|
|
107
164
|
if (record.status !== "armed") {
|
|
108
165
|
continue;
|
|
109
166
|
}
|
|
167
|
+
if (record.handler !== undefined) {
|
|
168
|
+
if (this.namedHandlers.get(record.handler) === undefined) {
|
|
169
|
+
yield this.disarm(record, "handler_missing");
|
|
170
|
+
disarmedOrphan += 1;
|
|
171
|
+
}
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
110
174
|
if ((record.hasRunHandler === true || record.hasUntilFn === true) &&
|
|
111
175
|
this.handlers.get(record.id) === undefined) {
|
|
112
176
|
yield this.disarm(record, "handler_lost_on_restart");
|
|
@@ -135,6 +199,16 @@ export class ReminderRunner {
|
|
|
135
199
|
let restored = 0;
|
|
136
200
|
let disarmedOrphan = 0;
|
|
137
201
|
for (const record of armed) {
|
|
202
|
+
if (record.handler !== undefined) {
|
|
203
|
+
if (this.namedHandlers.get(record.handler) === undefined) {
|
|
204
|
+
yield this.disarm(record, "handler_missing");
|
|
205
|
+
disarmedOrphan += 1;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
this.armTimer(record);
|
|
209
|
+
restored += 1;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
138
212
|
if ((record.hasRunHandler === true || record.hasUntilFn === true) &&
|
|
139
213
|
this.handlers.get(record.id) === undefined) {
|
|
140
214
|
yield this.disarm(record, "handler_lost_on_restart");
|
|
@@ -207,11 +281,13 @@ export class ReminderRunner {
|
|
|
207
281
|
}
|
|
208
282
|
create(input) {
|
|
209
283
|
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
-
var _a;
|
|
284
|
+
var _a, _b;
|
|
211
285
|
const hasPrompt = input.prompt !== undefined;
|
|
212
286
|
const hasRun = input.run !== undefined;
|
|
213
|
-
|
|
214
|
-
|
|
287
|
+
const hasHandler = input.handler !== undefined;
|
|
288
|
+
const formCount = [hasPrompt, hasRun, hasHandler].filter(Boolean).length;
|
|
289
|
+
if (formCount !== 1) {
|
|
290
|
+
throw new ReminderValidationError("reminders.create requires exactly one of prompt, handler, or run");
|
|
215
291
|
}
|
|
216
292
|
if (input.continuationToken.trim() === "") {
|
|
217
293
|
throw new ReminderValidationError("continuationToken is required");
|
|
@@ -222,41 +298,111 @@ export class ReminderRunner {
|
|
|
222
298
|
if (input.purpose.trim() === "") {
|
|
223
299
|
throw new ReminderValidationError("purpose is required");
|
|
224
300
|
}
|
|
225
|
-
const schedule = resolveSchedule(input);
|
|
226
|
-
const busyPolicy = (_a = input.busyPolicy) !== null && _a !== void 0 ? _a : defaultBusyPolicy(schedule.kind);
|
|
227
|
-
const now = new Date().toISOString();
|
|
228
|
-
const id = newReminderId();
|
|
229
301
|
const untilPrompt = typeof input.until === "string" ? input.until : undefined;
|
|
230
302
|
const untilFn = typeof input.until === "function" ? input.until : undefined;
|
|
303
|
+
if (hasHandler && input.until !== undefined) {
|
|
304
|
+
throw new ReminderValidationError("reminders.create: until is not valid with handler; encode the stop condition in args and the handler body");
|
|
305
|
+
}
|
|
306
|
+
if (this.rejectAnonymousHandlers) {
|
|
307
|
+
if (hasRun) {
|
|
308
|
+
throw new ReminderValidationError("reminders.create: anonymous run handlers are not durable on architecture v2; author agent/reminders/<name>.ts and pass handler + args");
|
|
309
|
+
}
|
|
310
|
+
if (untilFn !== undefined) {
|
|
311
|
+
throw new ReminderValidationError("reminders.create: function until is not durable on architecture v2; use a string until prompt");
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
let handlerName;
|
|
315
|
+
let handlerArgs;
|
|
316
|
+
if (hasHandler) {
|
|
317
|
+
const handler = input.handler;
|
|
318
|
+
const name = typeof handler === "string"
|
|
319
|
+
? handler.trim()
|
|
320
|
+
: this.namedHandlerNames.get(handler);
|
|
321
|
+
if (name === undefined) {
|
|
322
|
+
throw new ReminderValidationError("Unknown reminder handler definition (expected a default export discovered under agent/reminders/)");
|
|
323
|
+
}
|
|
324
|
+
if (name === "") {
|
|
325
|
+
throw new ReminderValidationError("handler name is required");
|
|
326
|
+
}
|
|
327
|
+
if (!isValidReminderHandlerName(name)) {
|
|
328
|
+
throw new ReminderValidationError(name.includes("__")
|
|
329
|
+
? `Invalid reminder handler name "${name}": may not contain "__"`
|
|
330
|
+
: `Invalid reminder handler name "${name}": must match ${NAME_PATTERN}`);
|
|
331
|
+
}
|
|
332
|
+
if (this.namedHandlers.get(name) === undefined) {
|
|
333
|
+
throw new ReminderValidationError(`Unknown reminder handler "${name}" (expected agent/reminders/${name}.ts)`);
|
|
334
|
+
}
|
|
335
|
+
if (input.args !== undefined && !isJsonObject(input.args)) {
|
|
336
|
+
throw new ReminderValidationError("reminders.create args must be a JSON object");
|
|
337
|
+
}
|
|
338
|
+
handlerName = name;
|
|
339
|
+
handlerArgs = (_a = input.args) !== null && _a !== void 0 ? _a : {};
|
|
340
|
+
assertReminderArgsSize(handlerArgs);
|
|
341
|
+
}
|
|
342
|
+
else if (input.args !== undefined) {
|
|
343
|
+
throw new ReminderValidationError("reminders.create args is only valid with handler");
|
|
344
|
+
}
|
|
345
|
+
const schedule = resolveSchedule(input);
|
|
346
|
+
const busyPolicy = (_b = input.busyPolicy) !== null && _b !== void 0 ? _b : defaultBusyPolicy(schedule.kind);
|
|
231
347
|
const hasRunHandler = input.run !== undefined;
|
|
232
348
|
const hasUntilFn = untilFn !== undefined;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
349
|
+
let record;
|
|
350
|
+
if (this.usesControlPlaneProtocol) {
|
|
351
|
+
const intent = {
|
|
352
|
+
protocolVersion: REMINDER_CP_PROTOCOL_VERSION,
|
|
353
|
+
purpose: input.purpose,
|
|
354
|
+
channelId: input.channelId,
|
|
355
|
+
continuationToken: input.continuationToken,
|
|
356
|
+
target: input.target,
|
|
357
|
+
// CP recalculates nextFireAtMs / intervalMs from the raw schedule.
|
|
358
|
+
schedule: scheduleSpecFromCreateInput(input),
|
|
359
|
+
prompt: input.prompt,
|
|
360
|
+
handler: handlerName,
|
|
361
|
+
args: handlerArgs,
|
|
362
|
+
hasRunHandler,
|
|
363
|
+
hasUntilFn,
|
|
364
|
+
untilPrompt,
|
|
365
|
+
busyPolicy,
|
|
366
|
+
};
|
|
367
|
+
record = yield this.controlPlane.createReminder(intent);
|
|
368
|
+
this.records.set(record.id, record);
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
const now = new Date().toISOString();
|
|
372
|
+
const id = newReminderId();
|
|
373
|
+
record = {
|
|
374
|
+
version: 1,
|
|
375
|
+
id,
|
|
376
|
+
purpose: input.purpose,
|
|
377
|
+
channelId: input.channelId,
|
|
378
|
+
continuationToken: input.continuationToken,
|
|
379
|
+
target: input.target,
|
|
380
|
+
scheduleKind: schedule.kind,
|
|
381
|
+
scheduleValue: schedule.value,
|
|
382
|
+
intervalMs: schedule.intervalMs,
|
|
383
|
+
prompt: input.prompt,
|
|
384
|
+
handler: handlerName,
|
|
385
|
+
args: handlerArgs,
|
|
386
|
+
hasRunHandler,
|
|
387
|
+
hasUntilFn,
|
|
388
|
+
untilPrompt,
|
|
389
|
+
busyPolicy,
|
|
390
|
+
status: "armed",
|
|
391
|
+
fireCount: 0,
|
|
392
|
+
nextFireAtMs: schedule.nextFireAtMs,
|
|
393
|
+
generation: 0,
|
|
394
|
+
createdAt: now,
|
|
395
|
+
updatedAt: now,
|
|
396
|
+
};
|
|
397
|
+
yield this.persist(record);
|
|
398
|
+
}
|
|
399
|
+
this.handlers.set(record.id, {
|
|
256
400
|
run: input.run,
|
|
257
401
|
untilFn,
|
|
258
402
|
});
|
|
259
|
-
if (this.started &&
|
|
403
|
+
if (this.started &&
|
|
404
|
+
this.platformTimers === undefined &&
|
|
405
|
+
!this.usesControlPlaneProtocol) {
|
|
260
406
|
this.armTimer(record);
|
|
261
407
|
}
|
|
262
408
|
return toInfo(record);
|
|
@@ -267,8 +413,11 @@ export class ReminderRunner {
|
|
|
267
413
|
const all = yield this.allRecords();
|
|
268
414
|
return all
|
|
269
415
|
.filter((r) => {
|
|
270
|
-
if ((filter === null || filter === void 0 ? void 0 : filter.status) !== undefined
|
|
271
|
-
|
|
416
|
+
if ((filter === null || filter === void 0 ? void 0 : filter.status) !== undefined) {
|
|
417
|
+
const publicStatus = r.status === "firing" ? "armed" : r.status;
|
|
418
|
+
if (publicStatus !== filter.status) {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
272
421
|
}
|
|
273
422
|
if ((filter === null || filter === void 0 ? void 0 : filter.purpose) !== undefined && r.purpose !== filter.purpose) {
|
|
274
423
|
return false;
|
|
@@ -290,15 +439,27 @@ export class ReminderRunner {
|
|
|
290
439
|
}
|
|
291
440
|
cancel(id_1) {
|
|
292
441
|
return __awaiter(this, arguments, void 0, function* (id, reason = "explicit_cancel") {
|
|
442
|
+
var _a;
|
|
443
|
+
if (this.usesControlPlaneProtocol) {
|
|
444
|
+
const updated = yield this.controlPlane.cancelReminder(id, reason);
|
|
445
|
+
if (updated === undefined) {
|
|
446
|
+
this.records.delete(id);
|
|
447
|
+
this.handlers.delete(id);
|
|
448
|
+
return undefined;
|
|
449
|
+
}
|
|
450
|
+
this.records.set(id, updated);
|
|
451
|
+
this.handlers.delete(id);
|
|
452
|
+
return toInfo(updated);
|
|
453
|
+
}
|
|
293
454
|
const record = yield this.getRecord(id);
|
|
294
455
|
if (record === undefined) {
|
|
295
456
|
return undefined;
|
|
296
457
|
}
|
|
297
|
-
if (record.status !== "armed") {
|
|
458
|
+
if (record.status !== "armed" && record.status !== "firing") {
|
|
298
459
|
return toInfo(record);
|
|
299
460
|
}
|
|
300
461
|
this.clearTimer(id);
|
|
301
|
-
const updated = Object.assign(Object.assign({}, record), { status: "cancelled", disarmReason: reason, updatedAt: new Date().toISOString() });
|
|
462
|
+
const updated = Object.assign(Object.assign({}, record), { status: "cancelled", disarmReason: reason, generation: ((_a = record.generation) !== null && _a !== void 0 ? _a : 0) + 1, updatedAt: new Date().toISOString() });
|
|
302
463
|
yield this.persist(updated);
|
|
303
464
|
this.handlers.delete(id);
|
|
304
465
|
return toInfo(updated);
|
|
@@ -326,14 +487,18 @@ export class ReminderRunner {
|
|
|
326
487
|
*/
|
|
327
488
|
rekeyContinuation(channelId, oldToken, newToken) {
|
|
328
489
|
return __awaiter(this, void 0, void 0, function* () {
|
|
329
|
-
|
|
490
|
+
var _a;
|
|
491
|
+
if (this.usesControlPlaneProtocol) {
|
|
492
|
+
return this.controlPlane.rekeyReminders(channelId, oldToken, newToken);
|
|
493
|
+
}
|
|
494
|
+
const armed = (yield this.allRecords()).filter((r) => r.status === "armed" || r.status === "firing");
|
|
330
495
|
let n = 0;
|
|
331
496
|
for (const record of armed) {
|
|
332
497
|
if (record.channelId !== channelId ||
|
|
333
498
|
record.continuationToken !== oldToken) {
|
|
334
499
|
continue;
|
|
335
500
|
}
|
|
336
|
-
yield this.persist(Object.assign(Object.assign({}, record), { continuationToken: newToken, updatedAt: new Date().toISOString() }));
|
|
501
|
+
yield this.persist(Object.assign(Object.assign({}, record), { continuationToken: newToken, generation: ((_a = record.generation) !== null && _a !== void 0 ? _a : 0) + 1, updatedAt: new Date().toISOString() }));
|
|
337
502
|
n += 1;
|
|
338
503
|
}
|
|
339
504
|
return n;
|
|
@@ -359,6 +524,108 @@ export class ReminderRunner {
|
|
|
359
524
|
return Object.assign({ reminderId }, result);
|
|
360
525
|
});
|
|
361
526
|
}
|
|
527
|
+
/**
|
|
528
|
+
* Architecture v2 / CP protocol guest entrypoint: execute an immutable fire
|
|
529
|
+
* descriptor and return an outcome. Does not mint ids or mutate
|
|
530
|
+
* authoritative status/fireCount — the control plane applies the outcome.
|
|
531
|
+
*/
|
|
532
|
+
executeFire(descriptor) {
|
|
533
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
534
|
+
var _a;
|
|
535
|
+
const record = this.recordFromDescriptor(descriptor);
|
|
536
|
+
this.records.set(record.id, record);
|
|
537
|
+
const live = (_a = this.handlers.get(record.id)) !== null && _a !== void 0 ? _a : {};
|
|
538
|
+
if (record.handler !== undefined) {
|
|
539
|
+
if (this.resolveNamedHandler(record.handler) === undefined) {
|
|
540
|
+
return { kind: "stop", reason: "handler_missing" };
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
else if ((record.hasRunHandler === true || record.hasUntilFn === true) &&
|
|
544
|
+
live.run === undefined &&
|
|
545
|
+
live.untilFn === undefined) {
|
|
546
|
+
return { kind: "stop", reason: "handler_lost_on_restart" };
|
|
547
|
+
}
|
|
548
|
+
if (live.untilFn !== undefined) {
|
|
549
|
+
try {
|
|
550
|
+
const done = yield live.untilFn(this.buildUntilContext(record));
|
|
551
|
+
if (done) {
|
|
552
|
+
return { kind: "stop", reason: "until_fn" };
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
catch (error) {
|
|
556
|
+
this.logger(`[agent-sdk] reminder "${record.id}" until() failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
if (yield this.isSessionBusy(record.channelId, record.continuationToken)) {
|
|
560
|
+
if (record.busyPolicy === "skipIfBusy") {
|
|
561
|
+
this.logger(`[agent-sdk] reminder "${record.id}" (${record.purpose}) skipped: session busy`);
|
|
562
|
+
return { kind: "skipped" };
|
|
563
|
+
}
|
|
564
|
+
yield this.whenSessionIdle(record.channelId, record.continuationToken);
|
|
565
|
+
}
|
|
566
|
+
let result;
|
|
567
|
+
if (record.handler !== undefined) {
|
|
568
|
+
const named = this.resolveNamedHandler(record.handler);
|
|
569
|
+
if (named === undefined) {
|
|
570
|
+
return { kind: "stop", reason: "handler_missing" };
|
|
571
|
+
}
|
|
572
|
+
result = yield named.run(this.buildFireContext(record));
|
|
573
|
+
}
|
|
574
|
+
else if (live.run !== undefined) {
|
|
575
|
+
result = yield live.run(this.buildFireContext(record));
|
|
576
|
+
}
|
|
577
|
+
else if (record.prompt !== undefined) {
|
|
578
|
+
result = yield this.deliverPrompt(record);
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
return { kind: "stop", reason: "missing_handler" };
|
|
582
|
+
}
|
|
583
|
+
if (result.action === "stop") {
|
|
584
|
+
return { kind: "stop", reason: "run_stop" };
|
|
585
|
+
}
|
|
586
|
+
if (result.action === "skip") {
|
|
587
|
+
return {
|
|
588
|
+
kind: "skipped",
|
|
589
|
+
reschedule: result.reschedule !== undefined
|
|
590
|
+
? toWireReschedule(result.reschedule)
|
|
591
|
+
: undefined,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
return {
|
|
595
|
+
kind: "delivered",
|
|
596
|
+
reschedule: result.reschedule !== undefined
|
|
597
|
+
? toWireReschedule(result.reschedule)
|
|
598
|
+
: undefined,
|
|
599
|
+
};
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
recordFromDescriptor(descriptor) {
|
|
603
|
+
const now = new Date().toISOString();
|
|
604
|
+
return {
|
|
605
|
+
version: 1,
|
|
606
|
+
id: descriptor.id,
|
|
607
|
+
purpose: descriptor.purpose,
|
|
608
|
+
channelId: descriptor.channelId,
|
|
609
|
+
continuationToken: descriptor.continuationToken,
|
|
610
|
+
target: descriptor.target,
|
|
611
|
+
scheduleKind: descriptor.scheduleKind,
|
|
612
|
+
scheduleValue: descriptor.scheduleValue,
|
|
613
|
+
intervalMs: descriptor.intervalMs,
|
|
614
|
+
prompt: descriptor.prompt,
|
|
615
|
+
handler: descriptor.handler,
|
|
616
|
+
args: descriptor.args,
|
|
617
|
+
hasRunHandler: descriptor.hasRunHandler,
|
|
618
|
+
hasUntilFn: descriptor.hasUntilFn,
|
|
619
|
+
untilPrompt: descriptor.untilPrompt,
|
|
620
|
+
busyPolicy: descriptor.busyPolicy,
|
|
621
|
+
status: "firing",
|
|
622
|
+
fireCount: descriptor.fireCount,
|
|
623
|
+
nextFireAtMs: descriptor.nextFireAtMs,
|
|
624
|
+
generation: descriptor.generation,
|
|
625
|
+
createdAt: now,
|
|
626
|
+
updatedAt: now,
|
|
627
|
+
};
|
|
628
|
+
}
|
|
362
629
|
armTimer(record) {
|
|
363
630
|
var _a;
|
|
364
631
|
this.clearTimer(record.id);
|
|
@@ -401,6 +668,9 @@ export class ReminderRunner {
|
|
|
401
668
|
this.timers.delete(id);
|
|
402
669
|
}
|
|
403
670
|
}
|
|
671
|
+
resolveNamedHandler(name) {
|
|
672
|
+
return this.namedHandlers.get(name);
|
|
673
|
+
}
|
|
404
674
|
fire(id_1) {
|
|
405
675
|
return __awaiter(this, arguments, void 0, function* (id, opts = {}) {
|
|
406
676
|
var _a, _b;
|
|
@@ -420,7 +690,13 @@ export class ReminderRunner {
|
|
|
420
690
|
return { outcome: "noop", reason: "not_due" };
|
|
421
691
|
}
|
|
422
692
|
const live = (_a = this.handlers.get(id)) !== null && _a !== void 0 ? _a : {};
|
|
423
|
-
if (
|
|
693
|
+
if (record.handler !== undefined) {
|
|
694
|
+
if (this.resolveNamedHandler(record.handler) === undefined) {
|
|
695
|
+
yield this.disarm(record, "handler_missing");
|
|
696
|
+
return { outcome: "noop", reason: "handler_missing" };
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
else if ((record.hasRunHandler === true || record.hasUntilFn === true) &&
|
|
424
700
|
live.run === undefined &&
|
|
425
701
|
live.untilFn === undefined) {
|
|
426
702
|
yield this.disarm(record, "handler_lost_on_restart");
|
|
@@ -452,9 +728,16 @@ export class ReminderRunner {
|
|
|
452
728
|
}
|
|
453
729
|
}
|
|
454
730
|
let result;
|
|
455
|
-
if (
|
|
456
|
-
const
|
|
457
|
-
|
|
731
|
+
if (record.handler !== undefined) {
|
|
732
|
+
const named = this.resolveNamedHandler(record.handler);
|
|
733
|
+
if (named === undefined) {
|
|
734
|
+
yield this.disarm(record, "handler_missing");
|
|
735
|
+
return { outcome: "noop", reason: "handler_missing" };
|
|
736
|
+
}
|
|
737
|
+
result = yield named.run(this.buildFireContext(record));
|
|
738
|
+
}
|
|
739
|
+
else if (live.run !== undefined) {
|
|
740
|
+
result = yield live.run(this.buildFireContext(record));
|
|
458
741
|
}
|
|
459
742
|
else if (record.prompt !== undefined) {
|
|
460
743
|
result = yield this.deliverPrompt(record);
|
|
@@ -485,7 +768,7 @@ export class ReminderRunner {
|
|
|
485
768
|
return { outcome: "fired", reason: "skipped" };
|
|
486
769
|
}
|
|
487
770
|
yield this.afterFire(latest, "delivered", result.reschedule);
|
|
488
|
-
this.logger(`[agent-sdk] reminder "${id}" (${record.purpose})
|
|
771
|
+
this.logger(`[agent-sdk] reminder "${id}" (${record.purpose}) fired`);
|
|
489
772
|
return { outcome: "fired", reason: "delivered" };
|
|
490
773
|
}
|
|
491
774
|
finally {
|
|
@@ -534,7 +817,11 @@ export class ReminderRunner {
|
|
|
534
817
|
return __awaiter(this, void 0, void 0, function* () {
|
|
535
818
|
const auth = yield this.resolveFollowupAuth(record.channelId, record.continuationToken);
|
|
536
819
|
if (auth === undefined) {
|
|
537
|
-
|
|
820
|
+
// Under CP protocol, return stop and let the CP apply/CAS; do not
|
|
821
|
+
// mutate authoritative status from the guest mid-fire.
|
|
822
|
+
if (!this.usesControlPlaneProtocol) {
|
|
823
|
+
yield this.disarm(record, "session_gone");
|
|
824
|
+
}
|
|
538
825
|
return { action: "stop" };
|
|
539
826
|
}
|
|
540
827
|
return this.sendFollowup(record, buildFirePrompt(record), auth);
|
|
@@ -576,13 +863,14 @@ export class ReminderRunner {
|
|
|
576
863
|
});
|
|
577
864
|
}
|
|
578
865
|
buildFireContext(record) {
|
|
579
|
-
var _a;
|
|
866
|
+
var _a, _b;
|
|
580
867
|
const self = this;
|
|
581
868
|
return {
|
|
582
869
|
id: record.id,
|
|
583
870
|
purpose: record.purpose,
|
|
584
871
|
fireCount: record.fireCount,
|
|
585
872
|
target: Object.assign({ channelId: record.channelId, continuationToken: record.continuationToken }, ((_a = record.target) !== null && _a !== void 0 ? _a : {})),
|
|
873
|
+
args: (_b = record.args) !== null && _b !== void 0 ? _b : {},
|
|
586
874
|
host: this.engine.host,
|
|
587
875
|
mcp: this.engine.host.mcp,
|
|
588
876
|
appAuth: APP_AUTH,
|
|
@@ -13,8 +13,11 @@ export interface ResolvedSchedule {
|
|
|
13
13
|
intervalMs?: number;
|
|
14
14
|
nextFireAtMs: number;
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Resolve create-input schedule fields into a concrete next-fire plan.
|
|
18
|
+
* Pass `nowMs` for deterministic CP / test resolution; CP owns this call.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveSchedule(input: Pick<ReminderCreateInput, "every" | "cron" | "delay" | "at">, nowMs?: number): ResolvedSchedule;
|
|
18
21
|
/** Next UTC fire strictly after `afterMs` for a 5-field cron. */
|
|
19
22
|
export declare function nextCronFireMs(cronSource: string, afterMs: number): number;
|
|
20
23
|
/** Default busy policy: recurring may skip; one-shots queue behind the turn. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reminder-schedule.d.ts","sourceRoot":"","sources":["../../src/internal/reminder-schedule.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAI7E,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,4EAA4E;AAC5E,eAAO,MAAM,YAAY,aAAgB,CAAC;AAE1C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED
|
|
1
|
+
{"version":3,"file":"reminder-schedule.d.ts","sourceRoot":"","sources":["../../src/internal/reminder-schedule.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAI7E,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,4EAA4E;AAC5E,eAAO,MAAM,YAAY,aAAgB,CAAC;AAE1C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,EACnE,KAAK,GAAE,MAAmB,GACzB,gBAAgB,CA0DlB;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAU1E;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,oBAAoB,GACzB,YAAY,GAAG,iBAAiB,CAElC"}
|
|
@@ -11,8 +11,11 @@ export class ReminderValidationError extends Error {
|
|
|
11
11
|
}
|
|
12
12
|
/** Node setTimeout overflows past ~2^31-1 ms (~24.8d); chunk long waits. */
|
|
13
13
|
export const MAX_TIMER_MS = 2147483647;
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Resolve create-input schedule fields into a concrete next-fire plan.
|
|
16
|
+
* Pass `nowMs` for deterministic CP / test resolution; CP owns this call.
|
|
17
|
+
*/
|
|
18
|
+
export function resolveSchedule(input, nowMs = Date.now()) {
|
|
16
19
|
const shapes = [
|
|
17
20
|
input.every !== undefined,
|
|
18
21
|
input.cron !== undefined,
|
|
@@ -22,7 +25,6 @@ export function resolveSchedule(input) {
|
|
|
22
25
|
if (shapes.length !== 1) {
|
|
23
26
|
throw new ReminderValidationError("reminders.create requires exactly one of every, cron, delay, or at");
|
|
24
27
|
}
|
|
25
|
-
const now = Date.now();
|
|
26
28
|
if (input.every !== undefined) {
|
|
27
29
|
const intervalMs = parseDuration(input.every);
|
|
28
30
|
if (intervalMs <= 0) {
|
|
@@ -32,7 +34,7 @@ export function resolveSchedule(input) {
|
|
|
32
34
|
kind: "every",
|
|
33
35
|
value: String(input.every),
|
|
34
36
|
intervalMs,
|
|
35
|
-
nextFireAtMs:
|
|
37
|
+
nextFireAtMs: nowMs + intervalMs,
|
|
36
38
|
};
|
|
37
39
|
}
|
|
38
40
|
if (input.cron !== undefined) {
|
|
@@ -40,7 +42,7 @@ export function resolveSchedule(input) {
|
|
|
40
42
|
return {
|
|
41
43
|
kind: "cron",
|
|
42
44
|
value: input.cron,
|
|
43
|
-
nextFireAtMs: nextCronFireMs(input.cron,
|
|
45
|
+
nextFireAtMs: nextCronFireMs(input.cron, nowMs),
|
|
44
46
|
};
|
|
45
47
|
}
|
|
46
48
|
if (input.delay !== undefined) {
|
|
@@ -48,7 +50,7 @@ export function resolveSchedule(input) {
|
|
|
48
50
|
return {
|
|
49
51
|
kind: "delay",
|
|
50
52
|
value: String(input.delay),
|
|
51
|
-
nextFireAtMs:
|
|
53
|
+
nextFireAtMs: nowMs + delayMs,
|
|
52
54
|
};
|
|
53
55
|
}
|
|
54
56
|
const atMs = typeof input.at === "number"
|