@cursor/july 0.1.75 → 0.1.78

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.
Files changed (143) hide show
  1. package/dist/channels/origin/origin-webhook.d.ts +23 -2
  2. package/dist/channels/origin/origin-webhook.d.ts.map +1 -1
  3. package/dist/channels/origin/origin-webhook.js +82 -20
  4. package/dist/docs/404.html +2 -2
  5. package/dist/docs/ab.html +3 -3
  6. package/dist/docs/assets/{app.b8bhB2SV.js → app.BsA7t7rS.js} +1 -1
  7. package/dist/docs/assets/chunks/@localSearchIndexroot.Dcs6boxD.js +1 -0
  8. package/dist/docs/assets/chunks/{VPLocalSearchBox.lLSeIyWw.js → VPLocalSearchBox.B1hHhktM.js} +1 -1
  9. package/dist/docs/assets/chunks/{theme.C_owesa-.js → theme.DLpLSsQh.js} +2 -2
  10. package/dist/docs/assets/{storage.md.D8NQ389l.js → storage.md.ks1u64_R.js} +3 -3
  11. package/dist/docs/assets/storage.md.ks1u64_R.lean.js +1 -0
  12. package/dist/docs/building-with-agents.html +3 -3
  13. package/dist/docs/concepts.html +3 -3
  14. package/dist/docs/deployment.html +3 -3
  15. package/dist/docs/evals.html +3 -3
  16. package/dist/docs/example-agents/approval-buddy.html +3 -3
  17. package/dist/docs/example-agents/benny.html +3 -3
  18. package/dist/docs/example-agents/bugbot.html +3 -3
  19. package/dist/docs/example-agents/codebase-wiki.html +3 -3
  20. package/dist/docs/example-agents/codeowners-review.html +3 -3
  21. package/dist/docs/example-agents/concierge.html +3 -3
  22. package/dist/docs/example-agents/fsd.html +3 -3
  23. package/dist/docs/example-agents/index.html +3 -3
  24. package/dist/docs/example-agents/knowledge-base.html +3 -3
  25. package/dist/docs/example-agents/oncall.html +3 -3
  26. package/dist/docs/example-agents/security-reviewer.html +3 -3
  27. package/dist/docs/example-agents/slack-agent.html +3 -3
  28. package/dist/docs/example-agents/weather-agent.html +3 -3
  29. package/dist/docs/guides/agent-to-agent.html +3 -3
  30. package/dist/docs/guides/cloud-runtime.html +3 -3
  31. package/dist/docs/guides/convert-automation.html +3 -3
  32. package/dist/docs/guides/github.html +3 -3
  33. package/dist/docs/guides/human-in-the-loop.html +3 -3
  34. package/dist/docs/guides/mcp-oauth.html +3 -3
  35. package/dist/docs/guides/opentelemetry.html +3 -3
  36. package/dist/docs/guides/slack.html +3 -3
  37. package/dist/docs/guides/webhooks.html +3 -3
  38. package/dist/docs/hashmap.json +1 -1
  39. package/dist/docs/hillclimbing.html +3 -3
  40. package/dist/docs/index.html +3 -3
  41. package/dist/docs/quickstart.html +3 -3
  42. package/dist/docs/reference/agent-config.html +3 -3
  43. package/dist/docs/reference/artifacts.html +3 -3
  44. package/dist/docs/reference/channels.html +3 -3
  45. package/dist/docs/reference/cli.html +3 -3
  46. package/dist/docs/reference/connections.html +3 -3
  47. package/dist/docs/reference/hooks.html +3 -3
  48. package/dist/docs/reference/http-api.html +3 -3
  49. package/dist/docs/reference/instructions.html +3 -3
  50. package/dist/docs/reference/playground.html +3 -3
  51. package/dist/docs/reference/project-layout.html +3 -3
  52. package/dist/docs/reference/prompt.html +3 -3
  53. package/dist/docs/reference/schedules.html +3 -3
  54. package/dist/docs/reference/sessions.html +3 -3
  55. package/dist/docs/reference/skills.html +3 -3
  56. package/dist/docs/reference/subagents.html +3 -3
  57. package/dist/docs/reference/tools.html +3 -3
  58. package/dist/docs/scaffolding-agents.html +3 -3
  59. package/dist/docs/storage.html +7 -7
  60. package/dist/docs/templates/agentic-owners.html +3 -3
  61. package/dist/docs/templates/demo.html +3 -3
  62. package/dist/docs/templates/pr-autofixer.html +3 -3
  63. package/dist/docs/templates/security-reviewer.html +3 -3
  64. package/dist/docs/templates/triage.html +3 -3
  65. package/dist/docs/troubleshooting.html +3 -3
  66. package/dist/index.d.ts +0 -1
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +0 -1
  69. package/dist/internal/authored-alias-hooks.d.ts +12 -0
  70. package/dist/internal/authored-alias-hooks.d.ts.map +1 -1
  71. package/dist/internal/authored-alias-hooks.js +60 -8
  72. package/dist/internal/authored-loaders.d.ts +5 -3
  73. package/dist/internal/authored-loaders.d.ts.map +1 -1
  74. package/dist/internal/authored-loaders.js +13 -4
  75. package/dist/internal/deployment-scm-event-stream.js +4 -4
  76. package/dist/internal/discovery.d.ts.map +1 -1
  77. package/dist/internal/discovery.js +3 -21
  78. package/dist/internal/distribution.d.ts.map +1 -1
  79. package/dist/internal/distribution.js +0 -1
  80. package/dist/internal/review-comments.d.ts +62 -0
  81. package/dist/internal/review-comments.d.ts.map +1 -1
  82. package/dist/internal/review-comments.js +199 -0
  83. package/dist/internal/session-engine.d.ts +1 -60
  84. package/dist/internal/session-engine.d.ts.map +1 -1
  85. package/dist/internal/session-engine.js +10 -109
  86. package/dist/kv/memory-kv.d.ts +1 -10
  87. package/dist/kv/memory-kv.d.ts.map +1 -1
  88. package/dist/kv/memory-kv.js +1 -10
  89. package/dist/kv.d.ts +2 -3
  90. package/dist/kv.d.ts.map +1 -1
  91. package/dist/kv.js +2 -3
  92. package/dist/playground/assets/index-DJzcIeGt.css +1 -0
  93. package/dist/playground/assets/{index-BJy9UJrF.js → index-K3Sxyx0I.js} +48 -45
  94. package/dist/playground/index.html +2 -2
  95. package/dist/storage-backends/cursor-hosted.js +3 -3
  96. package/dist/storage-protocol.d.ts +3 -8
  97. package/dist/storage-protocol.d.ts.map +1 -1
  98. package/dist/storage-protocol.js +4 -10
  99. package/dist/storage.d.ts +5 -11
  100. package/dist/storage.d.ts.map +1 -1
  101. package/dist/storage.js +3 -4
  102. package/dist/types.d.ts +5 -34
  103. package/dist/types.d.ts.map +1 -1
  104. package/docs/storage.md +11 -44
  105. package/package.json +1 -8
  106. package/src/channels/origin/origin-webhook.ts +111 -25
  107. package/src/index.ts +0 -6
  108. package/src/internal/authored-alias-hooks.ts +75 -7
  109. package/src/internal/authored-loaders.ts +15 -4
  110. package/src/internal/deployment-scm-event-stream.ts +4 -4
  111. package/src/internal/discovery.ts +3 -27
  112. package/src/internal/distribution.ts +0 -1
  113. package/src/internal/review-comments.ts +286 -0
  114. package/src/internal/session-engine.ts +1 -168
  115. package/src/kv/memory-kv.ts +1 -10
  116. package/src/kv.ts +2 -3
  117. package/src/storage-backends/cursor-hosted.ts +3 -3
  118. package/src/storage-protocol.ts +4 -10
  119. package/src/storage.ts +6 -12
  120. package/src/types.ts +5 -35
  121. package/dist/docs/assets/chunks/@localSearchIndexroot.DGZeXVqn.js +0 -1
  122. package/dist/docs/assets/storage.md.D8NQ389l.lean.js +0 -1
  123. package/dist/internal/durable-session-store.d.ts +0 -60
  124. package/dist/internal/durable-session-store.d.ts.map +0 -1
  125. package/dist/internal/durable-session-store.js +0 -131
  126. package/dist/internal/ledger-serving.d.ts +0 -169
  127. package/dist/internal/ledger-serving.d.ts.map +0 -1
  128. package/dist/internal/ledger-serving.js +0 -393
  129. package/dist/ledger/janitor.d.ts +0 -60
  130. package/dist/ledger/janitor.d.ts.map +0 -1
  131. package/dist/ledger/janitor.js +0 -137
  132. package/dist/ledger/session-ledger.d.ts +0 -293
  133. package/dist/ledger/session-ledger.d.ts.map +0 -1
  134. package/dist/ledger/session-ledger.js +0 -614
  135. package/dist/ledger.d.ts +0 -12
  136. package/dist/ledger.d.ts.map +0 -1
  137. package/dist/ledger.js +0 -9
  138. package/dist/playground/assets/index-BrSd5vff.css +0 -1
  139. package/src/internal/durable-session-store.ts +0 -134
  140. package/src/internal/ledger-serving.ts +0 -531
  141. package/src/ledger/janitor.ts +0 -193
  142. package/src/ledger/session-ledger.ts +0 -839
  143. package/src/ledger.ts +0 -44
@@ -32,8 +32,6 @@ const V1ED_TIMESTAMP_TOLERANCE_SECONDS = 5 * 60;
32
32
  */
33
33
  const MAX_V1ED_CANDIDATE_SIGNATURES = 1;
34
34
 
35
- const JWKS_CACHE_TTL_MS = 5 * 60 * 1000;
36
-
37
35
  export type OriginJwk = Record<string, unknown>;
38
36
 
39
37
  export type OriginWebhookHeaders = {
@@ -131,41 +129,115 @@ export function verifyV1edWebhookPayload(args: {
131
129
  return false;
132
130
  }
133
131
 
132
+ function cacheControlDeltaMs(
133
+ cacheControl: string | null | undefined,
134
+ directive: "max-age" | "stale-if-error"
135
+ ): number | undefined {
136
+ if (cacheControl == null || cacheControl === "") {
137
+ return undefined;
138
+ }
139
+ const match = new RegExp(`(?:^|,)\\s*${directive}\\s*=\\s*(\\d+)`, "i").exec(
140
+ cacheControl
141
+ );
142
+ if (match === null) {
143
+ return undefined;
144
+ }
145
+ return Number(match[1]) * 1000;
146
+ }
147
+
148
+ /**
149
+ * RFC 9111 `max-age` (seconds → ms) from a Cache-Control header.
150
+ * Does not read `s-maxage`. Missing or unparsable → `undefined`.
151
+ */
152
+ export function cacheControlMaxAgeMs(
153
+ cacheControl: string | null | undefined
154
+ ): number | undefined {
155
+ return cacheControlDeltaMs(cacheControl, "max-age");
156
+ }
157
+
158
+ /**
159
+ * RFC 5861 `stale-if-error` (seconds → ms). Missing → `undefined` (no
160
+ * fail-open after `max-age`).
161
+ */
162
+ export function cacheControlStaleIfErrorMs(
163
+ cacheControl: string | null | undefined
164
+ ): number | undefined {
165
+ return cacheControlDeltaMs(cacheControl, "stale-if-error");
166
+ }
167
+
134
168
  let jwksCache:
135
- | { apiBaseUrl: string; keys: OriginJwk[]; fetchedAtMs: number }
169
+ | {
170
+ apiBaseUrl: string;
171
+ keys: OriginJwk[];
172
+ freshUntilMs: number;
173
+ staleUntilMs: number;
174
+ }
136
175
  | undefined;
137
176
 
138
- /** Fetch (and cache for 5 minutes) the Origin signing JWKS. */
177
+ export type FetchOriginJwksOptions = {
178
+ /** Skip the in-memory hit and call `/v1/origin/keys` (used after a verify miss). */
179
+ force?: boolean;
180
+ };
181
+
182
+ /**
183
+ * Return the in-memory Origin signing JWKS.
184
+ *
185
+ * Freshness is the JWKS response `Cache-Control: max-age`. After that, or
186
+ * when `force` is set, refetch. A failed refetch returns the last keys only
187
+ * while `stale-if-error` still applies; otherwise it throws (including a
188
+ * cold-cache miss).
189
+ */
139
190
  export async function fetchOriginJwks(
140
191
  apiBaseUrl: string,
141
- fetchImpl: typeof fetch = fetch
192
+ fetchImpl: typeof fetch = fetch,
193
+ options?: FetchOriginJwksOptions
142
194
  ): Promise<readonly OriginJwk[]> {
143
195
  const now = Date.now();
144
196
  if (
197
+ options?.force !== true &&
145
198
  jwksCache !== undefined &&
146
199
  jwksCache.apiBaseUrl === apiBaseUrl &&
147
- now - jwksCache.fetchedAtMs < JWKS_CACHE_TTL_MS
200
+ now < jwksCache.freshUntilMs
148
201
  ) {
149
202
  return jwksCache.keys;
150
203
  }
151
- const response = await fetchImpl(
152
- `${apiBaseUrl.replace(/\/+$/, "")}/v1/origin/keys`
153
- );
154
- if (!response.ok) {
155
- throw new Error(`Origin JWKS fetch failed: status=${response.status}`);
156
- }
157
- const body: unknown = await response.json().catch(() => undefined);
158
- const keys =
159
- typeof body === "object" &&
160
- body !== null &&
161
- Array.isArray((body as Record<string, unknown>).keys)
162
- ? ((body as Record<string, unknown>).keys as OriginJwk[])
163
- : [];
164
- if (keys.length === 0) {
165
- throw new Error("Origin JWKS fetch returned no keys");
204
+ try {
205
+ const response = await fetchImpl(
206
+ `${apiBaseUrl.replace(/\/+$/, "")}/v1/origin/keys`
207
+ );
208
+ if (!response.ok) {
209
+ throw new Error(`Origin JWKS fetch failed: status=${response.status}`);
210
+ }
211
+ const body: unknown = await response.json().catch(() => undefined);
212
+ const keys =
213
+ typeof body === "object" &&
214
+ body !== null &&
215
+ Array.isArray((body as Record<string, unknown>).keys)
216
+ ? ((body as Record<string, unknown>).keys as OriginJwk[])
217
+ : [];
218
+ if (keys.length === 0) {
219
+ throw new Error("Origin JWKS fetch returned no keys");
220
+ }
221
+ const cacheControl = response.headers.get("cache-control");
222
+ const maxAgeMs = cacheControlMaxAgeMs(cacheControl) ?? 0;
223
+ const staleIfErrorMs = cacheControlStaleIfErrorMs(cacheControl) ?? 0;
224
+ jwksCache = {
225
+ apiBaseUrl,
226
+ keys,
227
+ freshUntilMs: now + maxAgeMs,
228
+ staleUntilMs: now + maxAgeMs + staleIfErrorMs,
229
+ };
230
+ return keys;
231
+ } catch (error) {
232
+ if (
233
+ jwksCache !== undefined &&
234
+ jwksCache.apiBaseUrl === apiBaseUrl &&
235
+ now < jwksCache.staleUntilMs
236
+ ) {
237
+ return jwksCache.keys;
238
+ }
239
+ throw error;
166
240
  }
167
- jwksCache = { apiBaseUrl, keys, fetchedAtMs: now };
168
- return keys;
169
241
  }
170
242
 
171
243
  export interface VerifyOriginWebhookOptions {
@@ -183,14 +255,28 @@ export async function verifyOriginWebhook(
183
255
  options?: VerifyOriginWebhookOptions
184
256
  ): Promise<void> {
185
257
  const apiBaseUrl = options?.apiBaseUrl ?? DEFAULT_ORIGIN_API_BASE_URL;
186
- const keys = await fetchOriginJwks(apiBaseUrl, options?.fetchImpl ?? fetch);
258
+ const fetchImpl = options?.fetchImpl ?? fetch;
259
+ const keys = await fetchOriginJwks(apiBaseUrl, fetchImpl);
187
260
  if (
188
- !verifyV1edWebhookPayload({
261
+ verifyV1edWebhookPayload({
189
262
  publicJwks: keys,
190
263
  body,
191
264
  headers,
192
265
  nowMs: options?.nowMs,
193
266
  })
267
+ ) {
268
+ return;
269
+ }
270
+ const refreshed = await fetchOriginJwks(apiBaseUrl, fetchImpl, {
271
+ force: true,
272
+ });
273
+ if (
274
+ !verifyV1edWebhookPayload({
275
+ publicJwks: refreshed,
276
+ body,
277
+ headers,
278
+ nowMs: options?.nowMs,
279
+ })
194
280
  ) {
195
281
  throw new Error("Origin webhook signature verification failed");
196
282
  }
package/src/index.ts CHANGED
@@ -96,12 +96,6 @@ export {
96
96
  UnknownToolError,
97
97
  } from "./internal/session-engine.js";
98
98
  export { createMemoryKv, memoryCasTable } from "./kv/memory-kv.js";
99
- export {
100
- LedgerCasExhaustedError,
101
- LedgerFencedError,
102
- SessionLedger,
103
- supportsSessionLedgerKv,
104
- } from "./ledger.js";
105
99
  export type { MemoryBackend, TurnMemoryRecord } from "./memory.js";
106
100
  export {
107
101
  agentStoreMemoryBackend,
@@ -14,16 +14,29 @@
14
14
  * project's own node_modules; `fallbackAliases` only apply when that
15
15
  * fails (npx/global installs, projects without a local dependency), so a
16
16
  * real install in the user's project keeps precedence.
17
+ *
18
+ * A third case is first-party factory agents that relative-import this
19
+ * package's `src/` from a monorepo checkout. Hosted engines `npm install`
20
+ * only the agent directory, so files under `packages/agent-serve/src` have
21
+ * no `node_modules`. Bare specifiers from that tree (`zod`, octokit, …)
22
+ * retry against the running `@cursor/july` package.json, which does.
17
23
  */
18
24
 
19
25
  // Null-prototype copies so specifiers like "constructor" or "__proto__"
20
26
  // can never resolve to inherited Object.prototype members.
21
27
  let directAliases = toNullProtoMap({});
22
28
  let fallbackAliases = toNullProtoMap({});
29
+ let sourceTreeFallbackParentURL: string | undefined;
23
30
 
24
31
  export interface AuthoredAliasHookData {
25
32
  directAliases: Record<string, string>;
26
33
  fallbackAliases: Record<string, string>;
34
+ /**
35
+ * `file:` URL of the running `@cursor/july` package.json. Bare imports
36
+ * from monorepo `packages/agent-serve/` source retry against this parent
37
+ * when the source tree has no `node_modules` (hosted factory engines).
38
+ */
39
+ sourceTreeFallbackParentURL?: string;
27
40
  }
28
41
 
29
42
  function toNullProtoMap(
@@ -35,6 +48,9 @@ function toNullProtoMap(
35
48
  export function initialize(data: AuthoredAliasHookData): void {
36
49
  directAliases = toNullProtoMap(data.directAliases);
37
50
  fallbackAliases = toNullProtoMap(data.fallbackAliases);
51
+ const parent = data.sourceTreeFallbackParentURL;
52
+ sourceTreeFallbackParentURL =
53
+ typeof parent === "string" && parent !== "" ? parent : undefined;
38
54
  }
39
55
 
40
56
  interface ResolveResult {
@@ -58,12 +74,64 @@ export function resolve(
58
74
  return { url: direct, shortCircuit: true };
59
75
  }
60
76
  const fallback = fallbackAliases[specifier];
61
- if (fallback === undefined) {
62
- // Not ours: pass through with no promise/try-catch overhead. This hook
63
- // runs on every module resolution in the process.
64
- return nextResolve(specifier, context);
77
+ if (fallback !== undefined) {
78
+ return Promise.resolve()
79
+ .then(() => nextResolve(specifier, context))
80
+ .catch(() => ({ url: fallback, shortCircuit: true }));
81
+ }
82
+ if (
83
+ sourceTreeFallbackParentURL !== undefined &&
84
+ isBarePackageSpecifier(specifier) &&
85
+ isMonorepoAgentServeSource(parentURLOf(context))
86
+ ) {
87
+ const retryParent = sourceTreeFallbackParentURL;
88
+ return Promise.resolve()
89
+ .then(() => nextResolve(specifier, context))
90
+ .catch(() => nextResolve(specifier, withParentURL(context, retryParent)));
91
+ }
92
+ // Not ours: pass through with no promise/try-catch overhead. This hook
93
+ // runs on every module resolution in the process.
94
+ return nextResolve(specifier, context);
95
+ }
96
+
97
+ function parentURLOf(context: unknown): string | undefined {
98
+ if (context === null || typeof context !== "object") {
99
+ return undefined;
100
+ }
101
+ const parentURL = (context as { parentURL?: unknown }).parentURL;
102
+ return typeof parentURL === "string" ? parentURL : undefined;
103
+ }
104
+
105
+ function withParentURL(context: unknown, parentURL: string): unknown {
106
+ if (context !== null && typeof context === "object") {
107
+ return { ...(context as Record<string, unknown>), parentURL };
108
+ }
109
+ return { parentURL };
110
+ }
111
+
112
+ function isBarePackageSpecifier(specifier: string): boolean {
113
+ if (specifier.length === 0) {
114
+ return false;
115
+ }
116
+ const first = specifier[0];
117
+ if (first === "." || first === "/" || first === "\\") {
118
+ return false;
119
+ }
120
+ return !(
121
+ specifier.startsWith("node:") ||
122
+ specifier.startsWith("file:") ||
123
+ specifier.startsWith("data:") ||
124
+ specifier.startsWith("http:") ||
125
+ specifier.startsWith("https:")
126
+ );
127
+ }
128
+
129
+ function isMonorepoAgentServeSource(parentURL: string | undefined): boolean {
130
+ if (parentURL === undefined) {
131
+ return false;
65
132
  }
66
- return Promise.resolve()
67
- .then(() => nextResolve(specifier, context))
68
- .catch(() => ({ url: fallback, shortCircuit: true }));
133
+ return (
134
+ parentURL.includes("/packages/agent-serve/") &&
135
+ !parentURL.includes("/node_modules/")
136
+ );
69
137
  }
@@ -11,9 +11,11 @@
11
11
  * imports of the framework resolve against the running package: the
12
12
  * historical `@anysphere/agent-serve[/x]` name always, and
13
13
  * `@cursor/july[/x]` / `@cursor/agentkit[/x]` as fallbacks when the user's
14
- * project has no local install (npx / global). Source runs (tsx from the
15
- * monorepo) skip both the host loader and tsconfig paths already cover
16
- * them.
14
+ * project has no local install (npx / global). The same hooks retry bare
15
+ * npm specifiers from monorepo `packages/agent-serve/` source against this
16
+ * package (hosted factory engines install only the agent directory).
17
+ * Source runs (tsx from the monorepo) skip both — the host loader and
18
+ * tsconfig paths already cover them.
17
19
  */
18
20
 
19
21
  import { stat } from "node:fs/promises";
@@ -175,7 +177,16 @@ function registerFrameworkAliases(): void {
175
177
  fallbackAliases[`${AGENTKIT_PACKAGE_NAME}${suffix}`] = target;
176
178
  }
177
179
  const hooksUrl = new URL("./authored-alias-hooks.js", import.meta.url);
178
- const data: AuthoredAliasHookData = { directAliases, fallbackAliases };
180
+ const data: AuthoredAliasHookData = {
181
+ directAliases,
182
+ fallbackAliases,
183
+ // Hosted factory agents relative-import this package's src/ from a
184
+ // monorepo checkout while npm install ran only in the agent directory.
185
+ // Bare specifiers from that tree retry against this package.json.
186
+ sourceTreeFallbackParentURL: pathToFileURL(
187
+ join(packageRootDir(), "package.json")
188
+ ).href,
189
+ };
179
190
  // `node:module`'s register() is synchronous: it blocks until the hooks
180
191
  // thread has initialized, so the aliases are active when it returns.
181
192
  registerModuleHooks(hooksUrl, { data });
@@ -34,10 +34,10 @@
34
34
  * only.
35
35
  */
36
36
 
37
- // Node builtins only: hosted engines install the consuming agent's directory
38
- // alone and load this file as raw TypeScript source, so third-party imports
39
- // (even zod) do not resolve from here. See the tenant-mcp internals for the
40
- // same constraint.
37
+ // Hosted engines install the consuming agent's directory alone and load this
38
+ // file as raw TypeScript source. Relative and `node:` imports resolve here;
39
+ // this package's own npm dependencies retry against the running `@cursor/july`
40
+ // install (authored-alias-hooks). Do not add deps that package does not have.
41
41
  import { createHmac } from "node:crypto";
42
42
  import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
43
43
  import { join } from "node:path";
@@ -29,7 +29,6 @@ import {
29
29
  type AgentProject,
30
30
  type AgentProjectInfo,
31
31
  type AgentRuntime,
32
- type AgentServingMode,
33
32
  type ArtifactsDefinition,
34
33
  type BuiltinToolsConfig,
35
34
  type ChannelDefinition,
@@ -194,9 +193,9 @@ export async function loadAgentProjects(
194
193
  );
195
194
  }
196
195
  const results: Array<{ slug: string; project: AgentProject }> = [];
197
- // Storage namespaces (session mirror, host kv, durable-session ledger)
198
- // key on the project NAME, not the mount slug — two co-hosted agents
199
- // sharing a name would silently share sessions and coordination state.
196
+ // Storage namespaces (session mirror, host kv) key on the project
197
+ // NAME, not the mount slug — two co-hosted agents sharing a name would
198
+ // silently share sessions and KV state.
200
199
  const slugByName = new Map<string, string>();
201
200
  for (const child of children) {
202
201
  const project = await loadAgentProject(child.dir, options);
@@ -506,7 +505,6 @@ async function loadAgent(
506
505
  };
507
506
  const hosting = resolveHosting(ctx, agentDir, config?.hosting);
508
507
  const concurrency = resolveConcurrency(ctx, agentDir, config?.concurrency);
509
- const serving = resolveServing(ctx, agentDir, config?.serving);
510
508
 
511
509
  if (runtime === "cloud") {
512
510
  warnCloudRuntimeLimitations(ctx, agentDir, {
@@ -531,7 +529,6 @@ async function loadAgent(
531
529
  ...(allowedTools === undefined ? {} : { allowedTools }),
532
530
  hosting,
533
531
  concurrency,
534
- serving,
535
532
  tools,
536
533
  skills,
537
534
  connections,
@@ -540,27 +537,6 @@ async function loadAgent(
540
537
  };
541
538
  }
542
539
 
543
- /**
544
- * Validate the authored serving mode. An unrecognized value is an error
545
- * diagnostic and falls back to undefined (resident) — a typo must not
546
- * silently opt an agent into (or out of) ledger coordination.
547
- */
548
- function resolveServing(
549
- ctx: DiscoveryContext,
550
- agentDir: string,
551
- serving: AgentServingMode | undefined
552
- ): AgentServingMode | undefined {
553
- if (serving === undefined || serving === "resident" || serving === "ledger") {
554
- return serving;
555
- }
556
- ctx.diagnostics.push({
557
- severity: "error",
558
- path: displayPath(ctx, join(agentDir, "agent.ts")),
559
- message: `serving must be "resident" or "ledger"; got ${JSON.stringify(serving)}.`,
560
- });
561
- return undefined;
562
- }
563
-
564
540
  /** Absolute harness cwd parent, or undefined when unset / blank. */
565
541
  function resolveAgentCwd(
566
542
  ctx: DiscoveryContext,
@@ -112,7 +112,6 @@ export const AUTHORING_ENTRY_FILES: ReadonlyArray<
112
112
  ["artifacts", "artifacts.js"],
113
113
  ["kv", "kv.js"],
114
114
  ["kv/memory", "kv/memory-kv.js"],
115
- ["ledger", "ledger.js"],
116
115
  ["storage", "storage.js"],
117
116
  ["storage/file-kv", "storage-backends/file-kv.js"],
118
117
  ["storage/cursor-hosted", "storage-backends/cursor-hosted.js"],