@cursor/july 0.1.3 → 0.1.4
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.d.ts +1 -1
- package/dist/bin/agent-serve.js +40 -16
- package/dist/channels/slack/log.d.ts +1 -1
- package/dist/channels/slack/log.d.ts.map +1 -1
- package/dist/channels/slack/log.js +4 -5
- package/dist/channels/slack/setup.js +1 -1
- package/dist/channels/slack/socket-mode.d.ts.map +1 -1
- package/dist/channels/slack/socket-mode.js +10 -9
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.BR0RbIdx.js → app.DF-Yx4OP.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.0XrheBv2.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.qjsVTneI.js → VPLocalSearchBox.DSeJSudL.js} +1 -1
- package/dist/docs/assets/chunks/{theme.2Kg8jIp_.js → theme.DZVLTXOC.js} +2 -2
- package/dist/docs/assets/{index.md.m81y7TY7.js → index.md.Cylk70gg.js} +1 -1
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +3 -3
- package/dist/docs/deployment.html +3 -3
- package/dist/docs/evals.html +3 -3
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +3 -3
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/slack.html +3 -3
- package/dist/docs/guides/webhooks.html +3 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +5 -5
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/reference/agent-config.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +3 -3
- package/dist/docs/reference/connections.html +3 -3
- package/dist/docs/reference/hooks.html +3 -3
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +3 -3
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +3 -3
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +3 -3
- package/dist/docs/troubleshooting.html +3 -3
- package/dist/internal/ab-collector.js +3 -3
- package/dist/internal/ab-fold.js +1 -1
- package/dist/internal/cli-ax.d.ts +13 -5
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +41 -15
- package/dist/internal/cli-github.js +13 -13
- package/dist/internal/cursor/account-mcp.js +3 -3
- package/dist/internal/cursor/backend-client.js +1 -1
- package/dist/internal/cursor/credentials.d.ts +5 -3
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +9 -6
- package/dist/internal/cursor/github-credentials.js +3 -3
- package/dist/internal/cursor-event-relay.js +1 -1
- package/dist/internal/cursor-relay-core.d.ts +1 -1
- package/dist/internal/cursor-relay-core.d.ts.map +1 -1
- package/dist/internal/cursor-relay-core.js +2 -1
- package/dist/internal/cursor-slack-relay.js +1 -1
- package/dist/internal/distribution.d.ts +7 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +7 -0
- package/dist/internal/docs-site.js +3 -3
- package/dist/internal/eval-run-store.d.ts.map +1 -1
- package/dist/internal/eval-run-store.js +8 -8
- package/dist/internal/github-fanout.js +2 -2
- package/dist/internal/host-platforms.js +5 -5
- package/dist/internal/mcp-endpoint.d.ts.map +1 -1
- package/dist/internal/mcp-endpoint.js +1 -1
- package/dist/internal/playground/toolchain.js +6 -6
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +11 -11
- package/dist/internal/resolve-prod-target.d.ts +2 -0
- package/dist/internal/resolve-prod-target.d.ts.map +1 -1
- package/dist/internal/resolve-prod-target.js +44 -21
- package/dist/internal/resolved-connections.js +5 -5
- package/dist/internal/schedule-runner.js +1 -1
- package/dist/internal/server.js +14 -14
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +13 -13
- package/dist/internal/sessions-client.d.ts +13 -0
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +25 -0
- package/dist/internal/storage-coordinator.js +6 -6
- package/dist/internal/update-check.d.ts +93 -0
- package/dist/internal/update-check.d.ts.map +1 -0
- package/dist/internal/update-check.js +431 -0
- package/dist/playground/assets/{index-D-vo2lV_.css → index-Ct_Usdm8.css} +1 -1
- package/dist/playground/assets/index-Dsyb-Vaj.js +319 -0
- package/dist/playground/index.html +2 -2
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +0 -1
- package/package.json +2 -1
- package/skills/setup-slack/SKILL.md +1 -1
- package/src/bin/agent-serve.ts +42 -16
- package/src/channels/slack/log.ts +5 -5
- package/src/channels/slack/setup.ts +1 -1
- package/src/channels/slack/socket-mode.ts +11 -9
- package/src/internal/ab-collector.ts +3 -3
- package/src/internal/ab-fold.ts +1 -1
- package/src/internal/cli-ax.ts +55 -16
- package/src/internal/cli-github.ts +13 -15
- package/src/internal/cursor/account-mcp.ts +3 -3
- package/src/internal/cursor/backend-client.ts +1 -1
- package/src/internal/cursor/credentials.ts +12 -7
- package/src/internal/cursor/github-credentials.ts +3 -3
- package/src/internal/cursor-event-relay.ts +1 -1
- package/src/internal/cursor-relay-core.ts +4 -2
- package/src/internal/cursor-slack-relay.ts +1 -1
- package/src/internal/distribution.ts +8 -0
- package/src/internal/docs-site.ts +3 -3
- package/src/internal/eval-run-store.ts +8 -10
- package/src/internal/github-fanout.ts +2 -2
- package/src/internal/host-platforms.ts +5 -5
- package/src/internal/mcp-endpoint.ts +1 -3
- package/src/internal/playground/toolchain.ts +6 -6
- package/src/internal/reminder-runner.ts +11 -17
- package/src/internal/resolve-prod-target.ts +55 -23
- package/src/internal/resolved-connections.ts +5 -5
- package/src/internal/schedule-runner.ts +1 -1
- package/src/internal/server.ts +14 -14
- package/src/internal/session-engine.ts +13 -15
- package/src/internal/sessions-client.ts +34 -0
- package/src/internal/storage-coordinator.ts +6 -6
- package/src/internal/update-check.ts +552 -0
- package/src/types.ts +3 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DtIOQzGj.js +0 -1
- package/dist/playground/assets/index-x60b9q2j.js +0 -312
- /package/dist/docs/assets/{index.md.m81y7TY7.lean.js → index.md.Cylk70gg.lean.js} +0 -0
|
@@ -143,7 +143,7 @@ export class ReminderRunner {
|
|
|
143
143
|
}
|
|
144
144
|
if (restored > 0 || disarmedOrphan > 0) {
|
|
145
145
|
this.logger(
|
|
146
|
-
`[
|
|
146
|
+
`[agentkit] reminders: restored ${restored} armed reminder(s)` +
|
|
147
147
|
(disarmedOrphan > 0
|
|
148
148
|
? `; disarmed ${disarmedOrphan} without live handlers`
|
|
149
149
|
: "")
|
|
@@ -174,14 +174,12 @@ export class ReminderRunner {
|
|
|
174
174
|
}
|
|
175
175
|
} catch (error) {
|
|
176
176
|
const message = error instanceof Error ? error.message : String(error);
|
|
177
|
-
this.logger(
|
|
178
|
-
`[agent-serve] reminders: storage hydrate failed: ${message}`
|
|
179
|
-
);
|
|
177
|
+
this.logger(`[agentkit] reminders: storage hydrate failed: ${message}`);
|
|
180
178
|
return;
|
|
181
179
|
}
|
|
182
180
|
if (hydrated > 0) {
|
|
183
181
|
this.logger(
|
|
184
|
-
`[
|
|
182
|
+
`[agentkit] reminders: hydrated ${hydrated} reminder(s) from storage`
|
|
185
183
|
);
|
|
186
184
|
}
|
|
187
185
|
}
|
|
@@ -366,7 +364,7 @@ export class ReminderRunner {
|
|
|
366
364
|
const timer = setTimeout(() => {
|
|
367
365
|
void this.fire(record.id).catch(async (error) => {
|
|
368
366
|
this.logger(
|
|
369
|
-
`[
|
|
367
|
+
`[agentkit] reminder "${record.id}" fire failed: ${
|
|
370
368
|
error instanceof Error ? error.message : String(error)
|
|
371
369
|
}`
|
|
372
370
|
);
|
|
@@ -384,7 +382,7 @@ export class ReminderRunner {
|
|
|
384
382
|
await this.afterFire(current, "skip");
|
|
385
383
|
} catch (rescheduleError) {
|
|
386
384
|
this.logger(
|
|
387
|
-
`[
|
|
385
|
+
`[agentkit] reminder "${record.id}" reschedule after failure failed: ${
|
|
388
386
|
rescheduleError instanceof Error
|
|
389
387
|
? rescheduleError.message
|
|
390
388
|
: String(rescheduleError)
|
|
@@ -447,7 +445,7 @@ export class ReminderRunner {
|
|
|
447
445
|
}
|
|
448
446
|
} catch (error) {
|
|
449
447
|
this.logger(
|
|
450
|
-
`[
|
|
448
|
+
`[agentkit] reminder "${id}" until() failed: ${
|
|
451
449
|
error instanceof Error ? error.message : String(error)
|
|
452
450
|
}`
|
|
453
451
|
);
|
|
@@ -460,7 +458,7 @@ export class ReminderRunner {
|
|
|
460
458
|
if (record.busyPolicy === "skipIfBusy") {
|
|
461
459
|
await this.afterFire(record, "skip");
|
|
462
460
|
this.logger(
|
|
463
|
-
`[
|
|
461
|
+
`[agentkit] reminder "${id}" (${record.purpose}) skipped: session busy`
|
|
464
462
|
);
|
|
465
463
|
return { outcome: "fired", reason: "skipped_busy" };
|
|
466
464
|
}
|
|
@@ -488,7 +486,7 @@ export class ReminderRunner {
|
|
|
488
486
|
if (latest !== undefined && latest.status === "armed") {
|
|
489
487
|
await this.disarm(latest, "run_stop");
|
|
490
488
|
this.logger(
|
|
491
|
-
`[
|
|
489
|
+
`[agentkit] reminder "${id}" (${record.purpose}) disarmed: run_stop`
|
|
492
490
|
);
|
|
493
491
|
return { outcome: "fired", reason: "run_stop" };
|
|
494
492
|
}
|
|
@@ -503,15 +501,11 @@ export class ReminderRunner {
|
|
|
503
501
|
|
|
504
502
|
if (result.action === "skip") {
|
|
505
503
|
await this.afterFire(latest, "skip", result.reschedule);
|
|
506
|
-
this.logger(
|
|
507
|
-
`[agent-serve] reminder "${id}" (${record.purpose}) skipped`
|
|
508
|
-
);
|
|
504
|
+
this.logger(`[agentkit] reminder "${id}" (${record.purpose}) skipped`);
|
|
509
505
|
return { outcome: "fired", reason: "skipped" };
|
|
510
506
|
}
|
|
511
507
|
await this.afterFire(latest, "delivered", result.reschedule);
|
|
512
|
-
this.logger(
|
|
513
|
-
`[agent-serve] reminder "${id}" (${record.purpose}) delivered`
|
|
514
|
-
);
|
|
508
|
+
this.logger(`[agentkit] reminder "${id}" (${record.purpose}) delivered`);
|
|
515
509
|
return { outcome: "fired", reason: "delivered" };
|
|
516
510
|
} finally {
|
|
517
511
|
this.firing.delete(id);
|
|
@@ -613,7 +607,7 @@ export class ReminderRunner {
|
|
|
613
607
|
return { action: "delivered" };
|
|
614
608
|
} catch (retryError) {
|
|
615
609
|
this.logger(
|
|
616
|
-
`[
|
|
610
|
+
`[agentkit] reminder "${record.id}" followup failed after wait: ${
|
|
617
611
|
retryError instanceof Error
|
|
618
612
|
? retryError.message
|
|
619
613
|
: String(retryError)
|
|
@@ -37,6 +37,8 @@ export interface ResolveProdTargetOptions {
|
|
|
37
37
|
apiKey?: string;
|
|
38
38
|
fetchImpl?: typeof fetch;
|
|
39
39
|
err?: (text: string) => void;
|
|
40
|
+
/** Test seam for reachability-retry backoff. */
|
|
41
|
+
sleep?: (ms: number) => Promise<void>;
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export interface ResolvedProdTarget {
|
|
@@ -68,35 +70,59 @@ export async function resolveProdTarget(
|
|
|
68
70
|
);
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
// A hibernated engine can briefly omit engineAccess while getPod fails
|
|
74
|
+
// during wake. Retry a few times before surfacing "not reachable yet".
|
|
75
|
+
const maxReachabilityAttempts = 5;
|
|
76
|
+
const sleep = options.sleep ?? sleepMs;
|
|
77
|
+
let detail: DeploymentDetail | undefined;
|
|
78
|
+
for (let attempt = 0; attempt < maxReachabilityAttempts; attempt++) {
|
|
79
|
+
try {
|
|
80
|
+
detail = await auth.client.getDeployment({
|
|
81
|
+
teamId: auth.teamId,
|
|
82
|
+
slug,
|
|
83
|
+
});
|
|
84
|
+
} catch (error) {
|
|
85
|
+
if (error instanceof DeployApiError) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`Deployment "${slug}" (team ${auth.teamId}): ${error.message}`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// `degraded` still serves the previous ACTIVE engine; allow runtime access
|
|
94
|
+
// when the control plane minted engineAccess for it.
|
|
95
|
+
const statusOk =
|
|
96
|
+
detail.status === "running" || detail.status === "degraded";
|
|
97
|
+
if (!statusOk) {
|
|
98
|
+
const lastError =
|
|
99
|
+
detail.lastError === null || detail.lastError === undefined
|
|
100
|
+
? ""
|
|
101
|
+
: ` ${sanitizeCustomerFacingDetail(detail.lastError)}`;
|
|
79
102
|
throw new Error(
|
|
80
|
-
`Deployment "${slug}"
|
|
103
|
+
`Deployment "${slug}" is ${detail.status}, not running.${lastError}\n` +
|
|
104
|
+
`Deploy or wait: \`${CLI} deploy --slug ${slug}\` / \`${CLI} deployment ${slug}\``
|
|
81
105
|
);
|
|
82
106
|
}
|
|
83
|
-
|
|
107
|
+
if (detail.engineAccess !== null && detail.engineAccess !== undefined) {
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
if (attempt + 1 < maxReachabilityAttempts) {
|
|
111
|
+
if (attempt === 0) {
|
|
112
|
+
err(
|
|
113
|
+
`${stderrPalette().dim(
|
|
114
|
+
`Deployment "${slug}" is waking; waiting for engine access…`
|
|
115
|
+
)}\n`
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
await sleep(1000 * (attempt + 1));
|
|
119
|
+
}
|
|
84
120
|
}
|
|
85
121
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const access = detail.engineAccess;
|
|
89
|
-
const statusOk = detail.status === "running" || detail.status === "degraded";
|
|
90
|
-
if (!statusOk) {
|
|
91
|
-
const lastError =
|
|
92
|
-
detail.lastError === null || detail.lastError === undefined
|
|
93
|
-
? ""
|
|
94
|
-
: ` ${sanitizeCustomerFacingDetail(detail.lastError)}`;
|
|
95
|
-
throw new Error(
|
|
96
|
-
`Deployment "${slug}" is ${detail.status}, not running.${lastError}\n` +
|
|
97
|
-
`Deploy or wait: \`${CLI} deploy --slug ${slug}\` / \`${CLI} deployment ${slug}\``
|
|
98
|
-
);
|
|
122
|
+
if (detail === undefined) {
|
|
123
|
+
throw new Error(`Deployment "${slug}" lookup failed.`);
|
|
99
124
|
}
|
|
125
|
+
const access = detail.engineAccess;
|
|
100
126
|
if (access === null || access === undefined) {
|
|
101
127
|
throw new Error(
|
|
102
128
|
`Deployment "${slug}" is ${detail.status} but is not reachable yet. ` +
|
|
@@ -126,6 +152,12 @@ function sanitizeCustomerFacingDetail(message: string): string {
|
|
|
126
152
|
.replace(/\bcursorvm\.com\b/gi, "host");
|
|
127
153
|
}
|
|
128
154
|
|
|
155
|
+
function sleepMs(ms: number): Promise<void> {
|
|
156
|
+
return new Promise((resolve) => {
|
|
157
|
+
setTimeout(resolve, ms);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
129
161
|
/** Resolve the deployment slug the same way `deploy` does for a single dir. */
|
|
130
162
|
export function resolveProdSlug(options: {
|
|
131
163
|
dir: string;
|
|
@@ -42,7 +42,7 @@ export function validateMountConnectionsConfig(args: {
|
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
throw new Error(
|
|
45
|
-
`[
|
|
45
|
+
`[agentkit] agent "${label}" has Cursor account MCP connections with \`servers\` filters (${filteredRefs
|
|
46
46
|
.map((ref) => ref.name)
|
|
47
47
|
.join(
|
|
48
48
|
", "
|
|
@@ -67,7 +67,7 @@ export function assertCloudCanHonorAccountServersFilters(args: {
|
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
69
|
throw new Error(
|
|
70
|
-
`[
|
|
70
|
+
`[agentkit] cloud turn cannot honor Cursor account \`servers\` filters (${blocked
|
|
71
71
|
.map((connection) => connection.name)
|
|
72
72
|
.join(
|
|
73
73
|
", "
|
|
@@ -82,7 +82,7 @@ export function assertAccountConnectionsNotAnonymous(args: {
|
|
|
82
82
|
}): void {
|
|
83
83
|
if (args.allowAnonymous === true && args.hasAccountConnections) {
|
|
84
84
|
throw new Error(
|
|
85
|
-
"[
|
|
85
|
+
"[agentkit] --allow-anonymous cannot be used with Cursor account MCP connections (defineConnection({ cursorAccount: true })); use --bearer-token or remove the account MCP connections."
|
|
86
86
|
);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -113,7 +113,7 @@ export function resolveMountConnections(args: {
|
|
|
113
113
|
resolved.push(...peers);
|
|
114
114
|
if (cloudCapable && args.publicUrl === undefined) {
|
|
115
115
|
args.logger(
|
|
116
|
-
`[
|
|
116
|
+
`[agentkit] warning: agent "${label}" has peer MCP connections (${peers
|
|
117
117
|
.map((peer) => peer.name)
|
|
118
118
|
.join(
|
|
119
119
|
", "
|
|
@@ -136,7 +136,7 @@ export function resolveMountConnections(args: {
|
|
|
136
136
|
args.accountBridge.logPreflight(args.accountRefs);
|
|
137
137
|
if (cloudCapable && args.publicUrl === undefined) {
|
|
138
138
|
args.logger(
|
|
139
|
-
`[
|
|
139
|
+
`[agentkit] agent "${label}": cloud-runtime turns omit the account bridge without --public-url (cloud agents fall back to the account's native connectors).`
|
|
140
140
|
);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
@@ -90,7 +90,7 @@ export class ScheduleRunner {
|
|
|
90
90
|
if (schedule.cron.matches(now)) {
|
|
91
91
|
void this.dispatch(schedule.name).catch((error) => {
|
|
92
92
|
this.logger(
|
|
93
|
-
`[
|
|
93
|
+
`[agentkit] schedule "${schedule.name}" dispatch failed: ${
|
|
94
94
|
error instanceof Error ? error.message : String(error)
|
|
95
95
|
}`
|
|
96
96
|
);
|
package/src/internal/server.ts
CHANGED
|
@@ -234,12 +234,12 @@ export async function startServer(
|
|
|
234
234
|
);
|
|
235
235
|
}
|
|
236
236
|
logger(
|
|
237
|
-
"[
|
|
237
|
+
"[agentkit] warning: --allow-anonymous-cursor-github — every admitted HTTP caller can drive sessions holding the signed-in account's repo-scoped GitHub credential; serve this only behind a trusted boundary (e.g. an SSO proxy)"
|
|
238
238
|
);
|
|
239
239
|
}
|
|
240
240
|
if (cursorGithubConfig.scope.permissions === "contents-write") {
|
|
241
241
|
logger(
|
|
242
|
-
'[
|
|
242
|
+
'[agentkit] warning: Cursor GitHub credentials include contents:write — the host holds a push-capable token shared with model-driven tools and untrusted webhook content; prefer permissions: "pr-write" unless this agent must push code'
|
|
243
243
|
);
|
|
244
244
|
}
|
|
245
245
|
const provider = new CursorGithubCredentialProvider({
|
|
@@ -281,7 +281,7 @@ export async function startServer(
|
|
|
281
281
|
}
|
|
282
282
|
if (options.allowAnonymous === true) {
|
|
283
283
|
logger(
|
|
284
|
-
"[
|
|
284
|
+
"[agentkit] warning: --allow-anonymous admits every HTTP caller as the same principal; use only on a trusted network (e.g. Tailscale) and prefer --bearer-token for shared hosts"
|
|
285
285
|
);
|
|
286
286
|
}
|
|
287
287
|
const runner =
|
|
@@ -430,7 +430,7 @@ export async function startServer(
|
|
|
430
430
|
await definition.onStart(startArgs);
|
|
431
431
|
} catch (error) {
|
|
432
432
|
logger(
|
|
433
|
-
`[
|
|
433
|
+
`[agentkit] channel "${channel.id}" onStart failed: ${
|
|
434
434
|
error instanceof Error
|
|
435
435
|
? (error.stack ?? error.message)
|
|
436
436
|
: String(error)
|
|
@@ -744,7 +744,7 @@ export async function startServer(
|
|
|
744
744
|
await stop();
|
|
745
745
|
} catch (error) {
|
|
746
746
|
logger(
|
|
747
|
-
`[
|
|
747
|
+
`[agentkit] channel onStop failed: ${
|
|
748
748
|
error instanceof Error
|
|
749
749
|
? (error.stack ?? error.message)
|
|
750
750
|
: String(error)
|
|
@@ -1331,7 +1331,7 @@ function requireCursorEventsAuth(
|
|
|
1331
1331
|
const apiKey = (config.apiKey ?? accountKey?.apiKey ?? "").trim();
|
|
1332
1332
|
if (apiKey === "") {
|
|
1333
1333
|
throw new Error(
|
|
1334
|
-
`[
|
|
1334
|
+
`[agentkit] --cursor-events (serve({ cursorEvents })) requires a signed-in Cursor account: the SCM event stream is read as the host's user. ${SIGN_IN_HINT}`
|
|
1335
1335
|
);
|
|
1336
1336
|
}
|
|
1337
1337
|
return {
|
|
@@ -1367,7 +1367,7 @@ function startCursorEventRelay(input: {
|
|
|
1367
1367
|
);
|
|
1368
1368
|
if (repos.length === 0) {
|
|
1369
1369
|
logger(
|
|
1370
|
-
"[
|
|
1370
|
+
"[agentkit] cursor-events: no repos configured (pass --repo owner/name); relay disabled"
|
|
1371
1371
|
);
|
|
1372
1372
|
return undefined;
|
|
1373
1373
|
}
|
|
@@ -1375,7 +1375,7 @@ function startCursorEventRelay(input: {
|
|
|
1375
1375
|
const events = [...new Set(githubTargets.flatMap((target) => target.events))];
|
|
1376
1376
|
if (events.length === 0) {
|
|
1377
1377
|
logger(
|
|
1378
|
-
"[
|
|
1378
|
+
"[agentkit] cursor-events: no mounted agent declares a github channel; relay disabled"
|
|
1379
1379
|
);
|
|
1380
1380
|
return undefined;
|
|
1381
1381
|
}
|
|
@@ -1419,13 +1419,13 @@ function startCursorEventRelay(input: {
|
|
|
1419
1419
|
.map((target) => `${target.slug || "default"}:${target.status}`)
|
|
1420
1420
|
.join(", ");
|
|
1421
1421
|
logger(
|
|
1422
|
-
`[
|
|
1422
|
+
`[agentkit] cursor-events: dispatched ${formatCursorScmEventLog(event)}${outcomes === "" ? "" : ` → ${outcomes}`}`
|
|
1423
1423
|
);
|
|
1424
1424
|
},
|
|
1425
1425
|
});
|
|
1426
1426
|
relay.start();
|
|
1427
1427
|
logger(
|
|
1428
|
-
`[
|
|
1428
|
+
`[agentkit] cursor-events: relaying ${events.length} event kind(s) for ${repos.join(", ")} from ${auth.baseUrl}`
|
|
1429
1429
|
);
|
|
1430
1430
|
return relay;
|
|
1431
1431
|
}
|
|
@@ -1611,7 +1611,7 @@ async function startCursorSlackRelay(input: {
|
|
|
1611
1611
|
channelId: target.channelId,
|
|
1612
1612
|
});
|
|
1613
1613
|
logger(
|
|
1614
|
-
`[
|
|
1614
|
+
`[agentkit] cursor-slack: dispatching ${formatCursorSlackEventLog(envelope)} → ${target.runtime.slug || "default"}`
|
|
1615
1615
|
);
|
|
1616
1616
|
await dispatchCursorSlackEnvelope({
|
|
1617
1617
|
runtime: target.accountRuntime,
|
|
@@ -1639,7 +1639,7 @@ async function startCursorSlackRelay(input: {
|
|
|
1639
1639
|
|
|
1640
1640
|
relay.start();
|
|
1641
1641
|
logger(
|
|
1642
|
-
`[
|
|
1642
|
+
`[agentkit] cursor-slack: relaying Slack for ${targets
|
|
1643
1643
|
.map(
|
|
1644
1644
|
(target) => `${target.agentName} (${target.runtime.slug || "default"})`
|
|
1645
1645
|
)
|
|
@@ -1735,7 +1735,7 @@ async function handleRequest(
|
|
|
1735
1735
|
response = errorResponse(403, "forbidden", error.message);
|
|
1736
1736
|
} else {
|
|
1737
1737
|
logger(
|
|
1738
|
-
`[
|
|
1738
|
+
`[agentkit] request failed: ${
|
|
1739
1739
|
error instanceof Error
|
|
1740
1740
|
? (error.stack ?? error.message)
|
|
1741
1741
|
: String(error)
|
|
@@ -1749,7 +1749,7 @@ async function handleRequest(
|
|
|
1749
1749
|
await writeFetchResponse(response, res, method);
|
|
1750
1750
|
} catch (error) {
|
|
1751
1751
|
logger(
|
|
1752
|
-
`[
|
|
1752
|
+
`[agentkit] response write failed: ${
|
|
1753
1753
|
error instanceof Error ? error.message : String(error)
|
|
1754
1754
|
}`
|
|
1755
1755
|
);
|
|
@@ -249,7 +249,7 @@ export class SessionEngine {
|
|
|
249
249
|
(sessionId) => this.sessions.eventFilePath(sessionId),
|
|
250
250
|
(sessionId, error) =>
|
|
251
251
|
this.logger(
|
|
252
|
-
`[
|
|
252
|
+
`[agentkit] failed to persist events for ${sessionId}: ${describeError(error)}`
|
|
253
253
|
)
|
|
254
254
|
);
|
|
255
255
|
this.storage =
|
|
@@ -445,7 +445,7 @@ export class SessionEngine {
|
|
|
445
445
|
}
|
|
446
446
|
} catch (error) {
|
|
447
447
|
this.logger(
|
|
448
|
-
`[
|
|
448
|
+
`[agentkit] ab "${experiment.name}" enrollment failed (sticky skip): ${describeError(error)}`
|
|
449
449
|
);
|
|
450
450
|
variant = null;
|
|
451
451
|
}
|
|
@@ -712,7 +712,7 @@ export class SessionEngine {
|
|
|
712
712
|
this.queueDispatch(sessionId, event);
|
|
713
713
|
} catch (error) {
|
|
714
714
|
this.logger(
|
|
715
|
-
`[
|
|
715
|
+
`[agentkit] failed to record event for ${sessionId}: ${describeError(error)}`
|
|
716
716
|
);
|
|
717
717
|
}
|
|
718
718
|
};
|
|
@@ -1401,7 +1401,7 @@ export class SessionEngine {
|
|
|
1401
1401
|
.then(() => this.dispatchEvent(sessionId, event))
|
|
1402
1402
|
.catch((error) => {
|
|
1403
1403
|
this.logger(
|
|
1404
|
-
`[
|
|
1404
|
+
`[agentkit] event dispatch failed for ${sessionId}: ${describeError(error)}`
|
|
1405
1405
|
);
|
|
1406
1406
|
})
|
|
1407
1407
|
.then(() => {
|
|
@@ -1446,7 +1446,7 @@ export class SessionEngine {
|
|
|
1446
1446
|
await handler(event, channelCtx, sessionCtx);
|
|
1447
1447
|
} catch (error) {
|
|
1448
1448
|
this.logger(
|
|
1449
|
-
`[
|
|
1449
|
+
`[agentkit] channel "${record.channelId}" handler for ${event.type} threw: ${describeError(error)}`
|
|
1450
1450
|
);
|
|
1451
1451
|
}
|
|
1452
1452
|
}
|
|
@@ -1474,7 +1474,7 @@ export class SessionEngine {
|
|
|
1474
1474
|
});
|
|
1475
1475
|
} catch (error) {
|
|
1476
1476
|
this.logger(
|
|
1477
|
-
`[
|
|
1477
|
+
`[agentkit] hook "${hook.name}" handler for ${event.type} threw: ${describeError(error)}`
|
|
1478
1478
|
);
|
|
1479
1479
|
}
|
|
1480
1480
|
}
|
|
@@ -1616,7 +1616,7 @@ export class SessionEngine {
|
|
|
1616
1616
|
});
|
|
1617
1617
|
} catch (error) {
|
|
1618
1618
|
this.logger(
|
|
1619
|
-
`[
|
|
1619
|
+
`[agentkit] ab persistSnapshots.save threw: ${describeError(error)}`
|
|
1620
1620
|
);
|
|
1621
1621
|
}
|
|
1622
1622
|
} else {
|
|
@@ -1825,9 +1825,7 @@ export class SessionEngine {
|
|
|
1825
1825
|
try {
|
|
1826
1826
|
await this.runBulkRestore(storage, policy);
|
|
1827
1827
|
} catch (error) {
|
|
1828
|
-
this.logger(
|
|
1829
|
-
`[agent-serve] session restore failed: ${describeError(error)}`
|
|
1830
|
-
);
|
|
1828
|
+
this.logger(`[agentkit] session restore failed: ${describeError(error)}`);
|
|
1831
1829
|
}
|
|
1832
1830
|
}
|
|
1833
1831
|
|
|
@@ -1884,7 +1882,7 @@ export class SessionEngine {
|
|
|
1884
1882
|
return { record, events };
|
|
1885
1883
|
} catch (error) {
|
|
1886
1884
|
this.logger(
|
|
1887
|
-
`[
|
|
1885
|
+
`[agentkit] failed to restore session ${record.sessionId}: ${describeError(error)}`
|
|
1888
1886
|
);
|
|
1889
1887
|
return undefined;
|
|
1890
1888
|
}
|
|
@@ -1903,7 +1901,7 @@ export class SessionEngine {
|
|
|
1903
1901
|
(ndjson === undefined ? 0 : Buffer.byteLength(ndjson, "utf8"));
|
|
1904
1902
|
if (bytes > budget) {
|
|
1905
1903
|
this.logger(
|
|
1906
|
-
`[
|
|
1904
|
+
`[agentkit] session restore stopped at the ${policy.maxTotalBytes}-byte budget after ${restored} session(s); remaining sessions restore lazily on resume`
|
|
1907
1905
|
);
|
|
1908
1906
|
break outer;
|
|
1909
1907
|
}
|
|
@@ -1913,13 +1911,13 @@ export class SessionEngine {
|
|
|
1913
1911
|
restored += 1;
|
|
1914
1912
|
} catch (error) {
|
|
1915
1913
|
this.logger(
|
|
1916
|
-
`[
|
|
1914
|
+
`[agentkit] failed to restore session ${item.record.sessionId}: ${describeError(error)}`
|
|
1917
1915
|
);
|
|
1918
1916
|
}
|
|
1919
1917
|
}
|
|
1920
1918
|
}
|
|
1921
1919
|
if (restored > 0) {
|
|
1922
|
-
this.logger(`[
|
|
1920
|
+
this.logger(`[agentkit] restored ${restored} session(s) from storage`);
|
|
1923
1921
|
}
|
|
1924
1922
|
}
|
|
1925
1923
|
|
|
@@ -1975,7 +1973,7 @@ export class SessionEngine {
|
|
|
1975
1973
|
const events = await storage.listSessionEvents(record.sessionId);
|
|
1976
1974
|
await this.materializeSession(record, eventsNdjson(events));
|
|
1977
1975
|
this.logger(
|
|
1978
|
-
`[
|
|
1976
|
+
`[agentkit] lazily restored session ${record.sessionId} from storage`
|
|
1979
1977
|
);
|
|
1980
1978
|
return record;
|
|
1981
1979
|
}
|
|
@@ -152,6 +152,40 @@ function parseSessionSummary(value: unknown): SessionSummary | undefined {
|
|
|
152
152
|
};
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Pick the previous (most recently updated) followable session for
|
|
157
|
+
* `resume` / `chat --resume` when no session id was passed.
|
|
158
|
+
* Followable = has a non-empty continuation token (task sessions without
|
|
159
|
+
* one are skipped).
|
|
160
|
+
*/
|
|
161
|
+
export function pickPreviousSession(
|
|
162
|
+
sessions: readonly SessionSummary[]
|
|
163
|
+
): SessionSummary | undefined {
|
|
164
|
+
const followable = sessions.filter(
|
|
165
|
+
(s) => typeof s.continuationToken === "string" && s.continuationToken !== ""
|
|
166
|
+
);
|
|
167
|
+
if (followable.length === 0) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
return [...followable].sort((a, b) =>
|
|
171
|
+
b.updatedAt.localeCompare(a.updatedAt)
|
|
172
|
+
)[0];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Look up the most recently updated followable session id. */
|
|
176
|
+
export async function resolvePreviousSessionId(args: {
|
|
177
|
+
baseUrl: string;
|
|
178
|
+
auth?: RequestAuth;
|
|
179
|
+
fetchImpl?: typeof fetch;
|
|
180
|
+
}): Promise<string | undefined> {
|
|
181
|
+
const sessions = await listSessions({
|
|
182
|
+
baseUrl: args.baseUrl,
|
|
183
|
+
auth: args.auth,
|
|
184
|
+
fetchImpl: args.fetchImpl,
|
|
185
|
+
});
|
|
186
|
+
return pickPreviousSession(sessions)?.sessionId;
|
|
187
|
+
}
|
|
188
|
+
|
|
155
189
|
/** Format a sessions table (id, channel, mode, turns, running, updated). */
|
|
156
190
|
export function formatSessionsTable(sessions: SessionSummary[]): string {
|
|
157
191
|
if (sessions.length === 0) {
|
|
@@ -317,7 +317,7 @@ export class StorageCoordinator {
|
|
|
317
317
|
// under at-most-once). The session is unrecoverable; treat as a miss
|
|
318
318
|
// so the conversation can continue rather than failing forever.
|
|
319
319
|
this.logger(
|
|
320
|
-
`[
|
|
320
|
+
`[agentkit] storage continuation entry points at missing session ${sessionId}; treating as a miss`
|
|
321
321
|
);
|
|
322
322
|
return undefined;
|
|
323
323
|
}
|
|
@@ -488,7 +488,7 @@ export class StorageCoordinator {
|
|
|
488
488
|
return value == null ? undefined : (value as unknown as ABSnapshot);
|
|
489
489
|
} catch (error) {
|
|
490
490
|
this.logger(
|
|
491
|
-
`[
|
|
491
|
+
`[agentkit] storage get(ab-snapshot) failed: ${describeError(error)}`
|
|
492
492
|
);
|
|
493
493
|
return undefined;
|
|
494
494
|
}
|
|
@@ -521,7 +521,7 @@ export class StorageCoordinator {
|
|
|
521
521
|
clearTimeout(timer);
|
|
522
522
|
if (!drained) {
|
|
523
523
|
this.logger(
|
|
524
|
-
`[
|
|
524
|
+
`[agentkit] storage shutdown drain timed out after ${CLOSE_DRAIN_TIMEOUT_MS}ms with ${this.pending} write(s) undelivered`
|
|
525
525
|
);
|
|
526
526
|
}
|
|
527
527
|
}
|
|
@@ -569,7 +569,7 @@ export class StorageCoordinator {
|
|
|
569
569
|
return Array.isArray(entries) ? entries : [];
|
|
570
570
|
} catch (error) {
|
|
571
571
|
this.logger(
|
|
572
|
-
`[
|
|
572
|
+
`[agentkit] storage list(${prefix}) failed: ${describeError(error)}`
|
|
573
573
|
);
|
|
574
574
|
return [];
|
|
575
575
|
}
|
|
@@ -583,7 +583,7 @@ export class StorageCoordinator {
|
|
|
583
583
|
this.dropped += ops.length;
|
|
584
584
|
if (this.dropped <= ops.length || this.dropped % 1_000 < ops.length) {
|
|
585
585
|
this.logger(
|
|
586
|
-
`[
|
|
586
|
+
`[agentkit] storage queue full (${MAX_PENDING_OPS} pending writes); dropped ${this.dropped} write(s) so far — the sink is too slow for the traffic`
|
|
587
587
|
);
|
|
588
588
|
}
|
|
589
589
|
return;
|
|
@@ -600,7 +600,7 @@ export class StorageCoordinator {
|
|
|
600
600
|
}
|
|
601
601
|
} catch (error) {
|
|
602
602
|
this.logger(
|
|
603
|
-
`[
|
|
603
|
+
`[agentkit] storage ${op.op}(${op.key}) failed: ${describeError(error)}`
|
|
604
604
|
);
|
|
605
605
|
} finally {
|
|
606
606
|
this.pending -= 1;
|