@agent-native/core 0.201.1 → 0.202.0-nightly-20261006033736

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 (98) hide show
  1. package/dist/automation/index.d.ts +1 -1
  2. package/dist/client/analytics/index.d.ts +1 -1
  3. package/dist/client/analytics/index.js +1 -1
  4. package/dist/client/analytics.d.ts +23 -3
  5. package/dist/client/analytics.js +189 -46
  6. package/dist/client/client-status-requests.d.ts +4 -1
  7. package/dist/client/client-status-requests.js +21 -5
  8. package/dist/client/embed-auth.d.ts +6 -0
  9. package/dist/client/embed-auth.js +13 -0
  10. package/dist/client/session-replay.js +48 -22
  11. package/dist/client/sharing/index.d.ts +2 -0
  12. package/dist/client/sharing/index.js +2 -0
  13. package/dist/client/sharing/useAccessRequestReview.d.ts +80 -0
  14. package/dist/client/sharing/useAccessRequestReview.js +100 -0
  15. package/dist/client/sharing/useResourceAccessGate.d.ts +57 -0
  16. package/dist/client/sharing/useResourceAccessGate.js +76 -0
  17. package/dist/client/use-agent-engine-configured.d.ts +2 -0
  18. package/dist/client/use-agent-engine-configured.js +4 -1
  19. package/dist/email-catalog/registry.d.ts +1 -1
  20. package/dist/email-catalog/registry.js +1 -1
  21. package/dist/email-catalog/system-emails.d.ts +2 -2
  22. package/dist/email-catalog/system-emails.js +47 -2
  23. package/dist/email-catalog/templates.d.ts +5 -1
  24. package/dist/email-catalog/templates.js +11 -1
  25. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  26. package/dist/framework-tools.js +6 -0
  27. package/dist/identity/rekey.js +9 -0
  28. package/dist/jobs/run-history.d.ts +27 -8
  29. package/dist/jobs/run-history.js +17 -10
  30. package/dist/jobs/scheduler.js +39 -10
  31. package/dist/mcp/build-server.d.ts +1 -0
  32. package/dist/mcp/build-server.js +30 -7
  33. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  34. package/dist/notifications/routes.d.ts +2 -2
  35. package/dist/observability/routes.d.ts +7 -7
  36. package/dist/org/index.d.ts +1 -1
  37. package/dist/progress/routes.d.ts +1 -1
  38. package/dist/provider-api/actions/custom-provider-registration.d.ts +10 -10
  39. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  40. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  41. package/dist/review/suggestions/actions.js +14 -35
  42. package/dist/review/suggestions/store.d.ts +0 -1
  43. package/dist/review/suggestions/store.js +0 -7
  44. package/dist/secrets/routes.d.ts +11 -11
  45. package/dist/server/action-discovery.js +24 -0
  46. package/dist/server/agent-access.js +7 -3
  47. package/dist/server/agent-chat/mcp-options.d.ts +1 -0
  48. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  49. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  50. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  51. package/dist/server/attribution.d.ts +33 -1
  52. package/dist/server/attribution.js +93 -21
  53. package/dist/server/auth.js +35 -11
  54. package/dist/server/email-templates.d.ts +34 -0
  55. package/dist/server/email-templates.js +40 -0
  56. package/dist/server/magic-link-attribution.js +2 -1
  57. package/dist/server/onboarding-html.js +35 -67
  58. package/dist/server/release-schema.js +4 -0
  59. package/dist/server/short-lived-token.d.ts +7 -0
  60. package/dist/server/short-lived-token.js +59 -0
  61. package/dist/shared/analytics-anonymous-id.d.ts +1 -0
  62. package/dist/shared/analytics-anonymous-id.js +1 -1
  63. package/dist/shared/attribution-source.d.ts +30 -0
  64. package/dist/shared/attribution-source.js +65 -0
  65. package/dist/sharing/access-request-store.d.ts +96 -0
  66. package/dist/sharing/access-request-store.js +213 -0
  67. package/dist/sharing/access-requests.d.ts +113 -0
  68. package/dist/sharing/access-requests.js +490 -0
  69. package/dist/sharing/access.d.ts +36 -2
  70. package/dist/sharing/access.js +74 -12
  71. package/dist/sharing/actions/approve-resource-access-request.d.ts +10 -0
  72. package/dist/sharing/actions/approve-resource-access-request.js +15 -0
  73. package/dist/sharing/actions/decline-resource-access-request.d.ts +7 -0
  74. package/dist/sharing/actions/decline-resource-access-request.js +14 -0
  75. package/dist/sharing/actions/get-resource-access-request.d.ts +4 -0
  76. package/dist/sharing/actions/get-resource-access-request.js +13 -0
  77. package/dist/sharing/actions/get-resource-access-status.d.ts +5 -0
  78. package/dist/sharing/actions/get-resource-access-status.js +19 -0
  79. package/dist/sharing/actions/list-resource-access-requests.d.ts +5 -0
  80. package/dist/sharing/actions/list-resource-access-requests.js +16 -0
  81. package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
  82. package/dist/sharing/actions/request-resource-access.d.ts +6 -0
  83. package/dist/sharing/actions/request-resource-access.js +17 -0
  84. package/dist/sharing/actions/share-resource.d.ts +1 -1
  85. package/dist/sharing/actions/share-resource.js +18 -144
  86. package/dist/sharing/grant.d.ts +49 -0
  87. package/dist/sharing/grant.js +195 -0
  88. package/dist/sharing/index.d.ts +2 -1
  89. package/dist/sharing/index.js +2 -1
  90. package/dist/sharing/registry.d.ts +36 -0
  91. package/dist/templates/chat/server/plugins/auth.ts +2 -2
  92. package/dist/templates/default/app/routes/access-requests.$requestId.tsx +7 -0
  93. package/dist/templates/default/server/plugins/auth.ts +2 -2
  94. package/dist/vite/action-types-plugin.js +24 -0
  95. package/package.json +11 -3
  96. package/src/templates/chat/server/plugins/auth.ts +2 -2
  97. package/src/templates/default/app/routes/access-requests.$requestId.tsx +7 -0
  98. package/src/templates/default/server/plugins/auth.ts +2 -2
@@ -33,7 +33,16 @@ function resolveRunLivenessCeilingMs() {
33
33
  const INTERRUPTED_RUN_MESSAGE = "Worker stopped before a terminal result was recorded. The serverless worker may have timed out or been recycled. No delivery was confirmed.";
34
34
  const INTERRUPTED_RUN_ERROR_CODE = "background_automation_interrupted";
35
35
  const claimLeaseMs = () => resolveRunLivenessCeilingMs();
36
- const RUNS_RETAINED_PER_AUTOMATION = 50;
36
+ /**
37
+ * How long a queued dispatch's claim stays valid before another worker may take
38
+ * it over (`claimAutomationRun`). The stale-lock recovery must leave a row
39
+ * inside this lease to its own worker.
40
+ */
41
+ export function automationRunClaimLeaseMs() {
42
+ return claimLeaseMs();
43
+ }
44
+ /** How many runs each automation retains; pruning bounds unfinished rows to this. */
45
+ export const RUNS_RETAINED_PER_AUTOMATION = 50;
37
46
  const FAILURE_ALERT_LEASE_MS = 60_000;
38
47
  const FAILURE_ALERT_RETRY_BASE_MS = 60_000;
39
48
  const FAILURE_ALERT_RETRY_MAX_MS = 6 * 60 * 60_000;
@@ -203,6 +212,8 @@ function toRun(row, now) {
203
212
  : row.error_code == null
204
213
  ? null
205
214
  : stringifyValue(row.error_code),
215
+ dispatchPending: Number(row.dispatch_pending ?? 0) === 1,
216
+ claimedAt: row.claimed_at == null ? null : Number(row.claimed_at),
206
217
  };
207
218
  }
208
219
  export async function startAutomationRun(input) {
@@ -556,16 +567,10 @@ export async function processPendingAutomationFailureAlerts(options) {
556
567
  }
557
568
  return { attempted, delivered, deferred, suppressed, uncertain, failed };
558
569
  }
559
- export async function finishAutomationRun(id, status, error, errorCode,
560
- /**
561
- * `notify: false` records the run without queueing the owner email. Used for
562
- * the early failures of a streak that will pause: the owner is told once,
563
- * by the run that pauses it.
564
- */
565
- options = {}) {
570
+ export async function finishAutomationRun(id, status, error, errorCode, options = {}) {
566
571
  await ensureTable();
567
572
  const existing = await getDbExec().execute({
568
- sql: `SELECT owner, automation, path, org_id, app_id, notification_email, run_id, thread_id, started_at, status FROM ${TABLE} WHERE id = ? LIMIT 1`,
573
+ sql: `SELECT owner, automation, path, org_id, app_id, notification_email, run_id, thread_id, started_at, status, claimed_at FROM ${TABLE} WHERE id = ? LIMIT 1`,
569
574
  args: [id],
570
575
  });
571
576
  const row = existing.rows?.[0];
@@ -573,12 +578,13 @@ options = {}) {
573
578
  const shouldQueueFailureAlert = status !== "success" &&
574
579
  options.notify !== false &&
575
580
  Boolean(row?.notification_email);
581
+ const claimGuard = options.expectedClaimedAt !== undefined;
576
582
  const update = await getDbExec().execute({
577
583
  sql: `UPDATE ${TABLE}
578
584
  SET status = ?, finished_at = ?, error = ?, error_code = ?,
579
585
  failure_alert_state = ?, failure_alert_next_attempt_at = ?,
580
586
  failure_alert_claimed_at = NULL
581
- WHERE id = ? AND status = 'running'`,
587
+ WHERE id = ? AND status = 'running'${claimGuard ? " AND claimed_at IS NOT DISTINCT FROM ?" : ""}`,
582
588
  args: [
583
589
  status,
584
590
  finishedAt,
@@ -587,6 +593,7 @@ options = {}) {
587
593
  shouldQueueFailureAlert ? "evaluating" : null,
588
594
  shouldQueueFailureAlert ? finishedAt : null,
589
595
  id,
596
+ ...(claimGuard ? [options.expectedClaimedAt] : []),
590
597
  ],
591
598
  });
592
599
  if (!row || Number(update.rowsAffected ?? 0) === 0)
@@ -1,3 +1,4 @@
1
+ import { resolveBackgroundRunHardTimeoutMs } from "../agent/run-manager.js";
1
2
  import { resourceGetByPath, resourceListAllOwners, resourcePutIfCurrent, } from "../resources/store.js";
2
3
  import { countAutomationCredentialState, trackAutomationPaused, trackAutomationResumed, } from "./automation-events.js";
3
4
  import { applyAutomationFailure, classifyAutomationFailure, CLEAR_FAILURE_STATE, CONFIG_INVALID_ERROR_CODE, hasStalePause, isMissingCredentialCode, isPausedByFramework, isReservedIdentityBlocked, isTransientPauseProbeDue, OWNER_MISSING_ERROR_CODE, OWNER_RESERVED_ERROR_CODE, pauseNow, RESUME_AUTOMATION_PATCH, reservedIdentityMessage, runtimeFailureNextRun, TRANSIENT_PROBE_RESUME_PATCH, withDeliveryNote, } from "./automation-outcome.js";
@@ -5,7 +6,7 @@ import { backgroundRunCutOffReason, checkBackgroundAutomationCredentials, isBack
5
6
  import { nextOccurrence, isValidCron, describeCron, effectiveTimezone, } from "./cron.js";
6
7
  import { buildJobResourceContent, isRecoveredFactoryJob, jobBelongsToApp, parseJobResource, patchJobFrontmatterFields, recoveredFactoryOwnerOrgId, } from "./frontmatter.js";
7
8
  import { dispatchRemoteAutomation, finishRemoteAutomationHistory, getRemoteAutomationStatus, } from "./remote-execution.js";
8
- import { claimAutomationRun, finishAutomationRun, getAutomationRun, listAutomationRuns, } from "./run-history.js";
9
+ import { automationRunClaimLeaseMs, claimAutomationRun, finishAutomationRun, getAutomationRun, listAutomationRuns, RUNS_RETAINED_PER_AUTOMATION, } from "./run-history.js";
9
10
  import { acquireAutomationSchedulerLease, recordAutomationSchedulerHealth, releaseAutomationSchedulerLease, renewAutomationSchedulerLease, AUTOMATION_SCHEDULER_LEASE_RENEWAL_MS, } from "./scheduler-health.js";
10
11
  import { reapStaleWork } from "./stale-reaper.js";
11
12
  export { classifyJobFrontmatter, classifyJobResource, normalizeJobMcpTools, parseJobResource, } from "./frontmatter.js";
@@ -187,7 +188,7 @@ async function processRecurringJobsWithLease(deps) {
187
188
  meta.nextRun = nextOccurrence(meta.schedule, now, meta.timezone).toISOString();
188
189
  }
189
190
  if (await updateResource(resource, meta, body)) {
190
- await recoverStaleAutomationHistory(resource.owner, resource.path);
191
+ await recoverStaleAutomationHistory(resource.owner, resource.path, now);
191
192
  }
192
193
  continue;
193
194
  }
@@ -337,20 +338,48 @@ async function processRecurringJobsWithLease(deps) {
337
338
  });
338
339
  }
339
340
  }
340
- async function recoverStaleAutomationHistory(owner, path) {
341
+ async function recoverStaleAutomationHistory(owner, path, now) {
341
342
  const automation = path.replace(/^jobs\//, "").replace(/\.md$/, "");
343
+ const nowMs = now.getTime();
344
+ const livenessMs = resolveBackgroundRunHardTimeoutMs();
345
+ const claimLeaseMs = automationRunClaimLeaseMs();
342
346
  try {
343
- const [run] = await listAutomationRuns({
347
+ // Settle every run the stopped worker left behind, not only the newest:
348
+ // a queued "Run now" can be newer than the run that actually stopped.
349
+ // Pruning bounds unfinished rows to this; a smaller batch could strand an
350
+ // older stopped row behind newer ones because this recovery runs once per
351
+ // stale lock.
352
+ const runs = await listAutomationRuns({
344
353
  owners: [owner],
345
354
  automation,
346
- limit: 1,
355
+ limit: RUNS_RETAINED_PER_AUTOMATION,
347
356
  });
348
- if (!run ||
349
- run.finishedAt !== null ||
350
- (run.status !== "running" && run.status !== "interrupted")) {
351
- return;
357
+ for (const run of runs) {
358
+ if (run.finishedAt !== null ||
359
+ (run.status !== "running" && run.status !== "interrupted")) {
360
+ continue;
361
+ }
362
+ // A queued "Run now" inserts its history row before its worker starts.
363
+ // Until its claim lease passes, its worker (or the redelivery sweep) can
364
+ // still pick it up, so it is not stale however old the frontmatter lock
365
+ // it inherits is. This reads the stored claim, not the derived status: a
366
+ // row past the read-liveness ceiling still reports `interrupted`.
367
+ const lastQueueTouch = run.claimedAt ?? run.startedAt;
368
+ const dispatchIsClaimable = run.dispatchPending &&
369
+ Number.isFinite(lastQueueTouch) &&
370
+ lastQueueTouch > nowMs - claimLeaseMs;
371
+ const runIsWithinLiveness = Number.isFinite(run.startedAt) && run.startedAt > nowMs - livenessMs;
372
+ if (dispatchIsClaimable || runIsWithinLiveness)
373
+ continue;
374
+ try {
375
+ await finishAutomationRun(run.id, "error", "Worker stopped before a terminal result was recorded. The serverless worker may have timed out or been recycled. No delivery was confirmed.", "background_automation_interrupted", { expectedClaimedAt: run.claimedAt });
376
+ }
377
+ catch (error) {
378
+ // One failed write must not strand the rest of the batch: the
379
+ // frontmatter is already reset and this recovery runs once per lock.
380
+ console.warn(`[recurring-jobs] Could not record stale history for run "${run.id}":`, error instanceof Error ? error.message : error);
381
+ }
352
382
  }
353
- await finishAutomationRun(run.id, "error", "Worker stopped before a terminal result was recorded. The serverless worker may have timed out or been recycled. No delivery was confirmed.", "background_automation_interrupted");
354
383
  }
355
384
  catch (error) {
356
385
  console.warn(`[recurring-jobs] Could not record stale history for "${automation}":`, error instanceof Error ? error.message : error);
@@ -48,6 +48,7 @@ export interface MCPConfig {
48
48
  directoryProfile?: {
49
49
  connectorCatalog: string[];
50
50
  instructions?: string;
51
+ widgets?: boolean;
51
52
  keyToolNames?: readonly string[];
52
53
  toolDescriptions?: Record<string, string>;
53
54
  toolParameterDescriptions?: Record<string, Record<string, string>>;
@@ -961,8 +961,24 @@ async function resolveMcpAppResourceSafely(config, actionName, entry, requestMet
961
961
  return null;
962
962
  }
963
963
  }
964
+ function mcpAppWidgetsEnabled(config) {
965
+ return !(config.catalogMode === "directory" &&
966
+ config.directoryProfile?.widgets === false);
967
+ }
968
+ function stripDirectoryWidgetMeta(config, metadata) {
969
+ if (mcpAppWidgetsEnabled(config))
970
+ return;
971
+ delete metadata.ui;
972
+ delete metadata[MCP_APP_RESOURCE_URI_META_KEY];
973
+ delete metadata["openai/ui"];
974
+ delete metadata["openai/outputTemplate"];
975
+ for (const key of Object.keys(metadata)) {
976
+ if (key.startsWith("openai/widget"))
977
+ delete metadata[key];
978
+ }
979
+ }
964
980
  async function getMcpAppResources(config, actions, requestMeta) {
965
- if (!requestMeta?.inlineMcpApps)
981
+ if (!requestMeta?.inlineMcpApps || !mcpAppWidgetsEnabled(config))
966
982
  return [];
967
983
  const resources = await Promise.all(Object.entries(actions).map(([name, entry]) => resolveMcpAppResourceSafely(config, name, entry, requestMeta)));
968
984
  return resources.filter((resource) => Boolean(resource));
@@ -1256,9 +1272,10 @@ export async function createMCPServerForRequest(config, identity, requestMeta) {
1256
1272
  approvalConfigurationError = true;
1257
1273
  }
1258
1274
  }
1259
- const supportsMcpApps = compactMcpAppCatalog ||
1260
- directoryCatalog ||
1261
- Object.values(advertisedActions).some((entry) => Boolean(entry.mcpApp?.resource));
1275
+ const supportsMcpApps = mcpAppWidgetsEnabled(config) &&
1276
+ (compactMcpAppCatalog ||
1277
+ directoryCatalog ||
1278
+ Object.values(advertisedActions).some((entry) => Boolean(entry.mcpApp?.resource)));
1262
1279
  const servedKeyToolNames = config.keyToolNames?.filter((name) => name in advertisedActions);
1263
1280
  const server = new Server(mcpServerInfo(config, requestMeta), {
1264
1281
  instructions: directoryCatalog
@@ -1400,12 +1417,15 @@ export async function createMCPServerForRequest(config, identity, requestMeta) {
1400
1417
  .sort(([a], [b]) => compareMcpCatalogValues(a, b))
1401
1418
  .map(async ([name, entry]) => {
1402
1419
  const hasLink = typeof entry.link === "function";
1403
- const mcpAppResource = await resolveMcpAppResourceSafely(config, name, entry, requestMeta);
1420
+ const mcpAppResource = mcpAppWidgetsEnabled(config)
1421
+ ? await resolveMcpAppResourceSafely(config, name, entry, requestMeta)
1422
+ : null;
1404
1423
  const rawToolMeta = entry.tool._meta &&
1405
1424
  typeof entry.tool._meta === "object" &&
1406
1425
  !Array.isArray(entry.tool._meta)
1407
1426
  ? { ...entry.tool._meta }
1408
1427
  : {};
1428
+ stripDirectoryWidgetMeta(config, rawToolMeta);
1409
1429
  const inputSchema = mcpToolInputSchema(name, entry.tool.parameters);
1410
1430
  if (directoryCatalog) {
1411
1431
  const properties = inputSchema.properties;
@@ -1635,7 +1655,7 @@ export async function createMCPServerForRequest(config, identity, requestMeta) {
1635
1655
  !!mcpResult.raw &&
1636
1656
  typeof mcpResult.raw === "object" &&
1637
1657
  mcpResult.raw.isError === true;
1638
- const mcpAppResourceCandidate = requestMeta?.inlineMcpApps
1658
+ const mcpAppResourceCandidate = requestMeta?.inlineMcpApps && mcpAppWidgetsEnabled(config)
1639
1659
  ? await resolveMcpAppResourceSafely(config, name, entry, requestMeta)
1640
1660
  : null;
1641
1661
  let directoryLinkUrl;
@@ -1846,7 +1866,10 @@ export async function createMCPServerForRequest(config, identity, requestMeta) {
1846
1866
  return await withCallerContext(async () => {
1847
1867
  const uri = request.params?.uri;
1848
1868
  let found = null;
1849
- for (const [name, entry] of Object.entries(advertisedActions)) {
1869
+ const resourceActions = mcpAppWidgetsEnabled(config)
1870
+ ? Object.entries(advertisedActions)
1871
+ : [];
1872
+ for (const [name, entry] of resourceActions) {
1850
1873
  const resourceUri = getMcpAppResourceUri(config, name, entry);
1851
1874
  if (!resourceUri || !matchesMcpAppResourceUri(resourceUri, uri)) {
1852
1875
  continue;
@@ -140,13 +140,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
140
140
  clientHint?: undefined;
141
141
  timestamp?: undefined;
142
142
  chapterId?: undefined;
143
+ count?: undefined;
143
144
  startAt?: undefined;
144
145
  endAt?: undefined;
145
146
  reason?: undefined;
146
147
  includeMicrophone?: undefined;
147
148
  includeSystemAudio?: undefined;
148
149
  requestId?: undefined;
149
- count?: undefined;
150
150
  };
151
151
  required?: undefined;
152
152
  };
@@ -171,13 +171,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
171
171
  clientHint?: undefined;
172
172
  timestamp?: undefined;
173
173
  chapterId?: undefined;
174
+ count?: undefined;
174
175
  startAt?: undefined;
175
176
  endAt?: undefined;
176
177
  reason?: undefined;
177
178
  includeMicrophone?: undefined;
178
179
  includeSystemAudio?: undefined;
179
180
  requestId?: undefined;
180
- count?: undefined;
181
181
  };
182
182
  required?: undefined;
183
183
  };
@@ -196,13 +196,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
196
196
  clientHint?: undefined;
197
197
  timestamp?: undefined;
198
198
  chapterId?: undefined;
199
+ count?: undefined;
199
200
  startAt?: undefined;
200
201
  endAt?: undefined;
201
202
  reason?: undefined;
202
203
  includeMicrophone?: undefined;
203
204
  includeSystemAudio?: undefined;
204
205
  requestId?: undefined;
205
- count?: undefined;
206
206
  };
207
207
  required?: undefined;
208
208
  };
@@ -231,13 +231,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
231
231
  };
232
232
  timestamp?: undefined;
233
233
  chapterId?: undefined;
234
+ count?: undefined;
234
235
  startAt?: undefined;
235
236
  endAt?: undefined;
236
237
  reason?: undefined;
237
238
  includeMicrophone?: undefined;
238
239
  includeSystemAudio?: undefined;
239
240
  requestId?: undefined;
240
- count?: undefined;
241
241
  };
242
242
  };
243
243
  } | {
@@ -260,12 +260,12 @@ export declare function screenMemoryMcpToolDefinitions(): ({
260
260
  description: string;
261
261
  };
262
262
  chapterId?: undefined;
263
+ count?: undefined;
263
264
  startAt?: undefined;
264
265
  endAt?: undefined;
265
266
  includeMicrophone?: undefined;
266
267
  includeSystemAudio?: undefined;
267
268
  requestId?: undefined;
268
- count?: undefined;
269
269
  };
270
270
  };
271
271
  } | {
@@ -317,6 +317,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
317
317
  clientHint?: undefined;
318
318
  timestamp?: undefined;
319
319
  chapterId?: undefined;
320
+ count?: undefined;
320
321
  startAt: {
321
322
  type: string;
322
323
  description: string;
@@ -336,7 +337,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
336
337
  type: string;
337
338
  };
338
339
  requestId?: undefined;
339
- count?: undefined;
340
340
  };
341
341
  };
342
342
  } | {
@@ -352,6 +352,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
352
352
  clientHint?: undefined;
353
353
  timestamp?: undefined;
354
354
  chapterId?: undefined;
355
+ count?: undefined;
355
356
  startAt?: undefined;
356
357
  endAt?: undefined;
357
358
  reason?: undefined;
@@ -360,7 +361,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
360
361
  requestId: {
361
362
  type: string;
362
363
  };
363
- count?: undefined;
364
364
  };
365
365
  };
366
366
  })[];
@@ -1,13 +1,13 @@
1
1
  export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
2
2
  count: number;
3
3
  updated?: undefined;
4
- ok?: undefined;
5
4
  error?: undefined;
5
+ ok?: undefined;
6
6
  } | {
7
7
  count?: undefined;
8
8
  updated: number;
9
- ok?: undefined;
10
9
  error?: undefined;
10
+ ok?: undefined;
11
11
  } | {
12
12
  count?: undefined;
13
13
  updated?: undefined;
@@ -27,38 +27,38 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
27
27
  thumbsUpRate: number;
28
28
  avgEvalScore: number;
29
29
  } | {
30
+ id?: undefined;
30
31
  error: string;
31
32
  message: string;
32
33
  summary?: undefined;
33
34
  spans?: undefined;
34
- id?: undefined;
35
35
  ok?: undefined;
36
36
  } | {
37
+ id?: undefined;
38
+ error?: undefined;
37
39
  message?: undefined;
38
40
  summary: import("./types.js").TraceSummary;
39
41
  spans: import("./types.js").TraceSpan[];
40
- id?: undefined;
41
- error?: undefined;
42
42
  ok?: undefined;
43
43
  } | {
44
+ error?: undefined;
44
45
  message?: undefined;
45
46
  summary?: undefined;
46
47
  spans?: undefined;
47
48
  id: string;
48
- error?: undefined;
49
49
  ok?: undefined;
50
50
  } | {
51
+ id?: undefined;
51
52
  message?: undefined;
52
53
  summary?: undefined;
53
54
  spans?: undefined;
54
- id?: undefined;
55
55
  error: any;
56
56
  ok?: undefined;
57
57
  } | {
58
+ id?: undefined;
59
+ error?: undefined;
58
60
  message?: undefined;
59
61
  summary?: undefined;
60
62
  spans?: undefined;
61
- id?: undefined;
62
- error?: undefined;
63
63
  ok: boolean;
64
64
  }>>;
@@ -179,8 +179,8 @@ export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import(
179
179
  export declare const createOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
180
180
  name?: undefined;
181
181
  success: boolean;
182
- id?: undefined;
183
182
  role?: undefined;
183
+ id?: undefined;
184
184
  } | {
185
185
  success?: undefined;
186
186
  id: string;
@@ -2,6 +2,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
2
2
  error: string;
3
3
  ok?: undefined;
4
4
  } | {
5
- error?: undefined;
6
5
  ok: boolean;
6
+ error?: undefined;
7
7
  }>>;
@@ -75,9 +75,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
75
75
  user: "user";
76
76
  }>>;
77
77
  }, z.core.$strip>>, {
78
- message?: undefined;
79
78
  id?: undefined;
80
- provider?: undefined;
79
+ message?: undefined;
81
80
  deleted?: undefined;
82
81
  providers: {
83
82
  id: string;
@@ -89,44 +88,45 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
89
88
  updatedAt: number;
90
89
  }[];
91
90
  count: number;
91
+ provider?: undefined;
92
92
  found?: undefined;
93
93
  registered?: undefined;
94
94
  label?: undefined;
95
95
  } | {
96
- message?: undefined;
97
96
  id?: undefined;
97
+ count?: undefined;
98
+ message?: undefined;
98
99
  deleted?: undefined;
99
100
  providers?: undefined;
100
- count?: undefined;
101
101
  found: boolean;
102
102
  provider: import("../custom-registry.js").CustomProviderConfig;
103
103
  registered?: undefined;
104
104
  label?: undefined;
105
105
  } | {
106
+ count?: undefined;
106
107
  message?: undefined;
107
- provider?: undefined;
108
108
  deleted?: undefined;
109
109
  providers?: undefined;
110
- count?: undefined;
110
+ provider?: undefined;
111
111
  found: boolean;
112
112
  id: string;
113
113
  registered?: undefined;
114
114
  label?: undefined;
115
115
  } | {
116
+ count?: undefined;
116
117
  message?: undefined;
117
- provider?: undefined;
118
118
  providers?: undefined;
119
- count?: undefined;
119
+ provider?: undefined;
120
120
  found?: undefined;
121
121
  deleted: boolean;
122
122
  id: string;
123
123
  registered?: undefined;
124
124
  label?: undefined;
125
125
  } | {
126
- provider?: undefined;
126
+ count?: undefined;
127
127
  deleted?: undefined;
128
128
  providers?: undefined;
129
- count?: undefined;
129
+ provider?: undefined;
130
130
  found?: undefined;
131
131
  registered: boolean;
132
132
  id: string;
@@ -311,9 +311,10 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
311
311
  notes?: string | undefined;
312
312
  scope?: "org" | "user" | undefined;
313
313
  }, {
314
+ provider?: undefined;
315
+ message?: undefined;
314
316
  id?: undefined;
315
317
  deleted?: undefined;
316
- message?: undefined;
317
318
  providers: {
318
319
  id: string;
319
320
  label: string;
@@ -324,45 +325,44 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
324
325
  updatedAt: number;
325
326
  }[];
326
327
  count: number;
327
- provider?: undefined;
328
328
  found?: undefined;
329
329
  registered?: undefined;
330
330
  label?: undefined;
331
331
  } | {
332
+ message?: undefined;
332
333
  id?: undefined;
333
- count?: undefined;
334
334
  deleted?: undefined;
335
- message?: undefined;
336
335
  providers?: undefined;
336
+ count?: undefined;
337
337
  found: boolean;
338
338
  provider: import("../custom-registry.js").CustomProviderConfig;
339
339
  registered?: undefined;
340
340
  label?: undefined;
341
341
  } | {
342
- count?: undefined;
343
- deleted?: undefined;
342
+ provider?: undefined;
344
343
  message?: undefined;
344
+ deleted?: undefined;
345
345
  providers?: undefined;
346
- provider?: undefined;
346
+ count?: undefined;
347
347
  found: boolean;
348
348
  id: string;
349
349
  registered?: undefined;
350
350
  label?: undefined;
351
351
  } | {
352
- count?: undefined;
352
+ provider?: undefined;
353
353
  message?: undefined;
354
354
  providers?: undefined;
355
- provider?: undefined;
355
+ count?: undefined;
356
356
  found?: undefined;
357
357
  deleted: boolean;
358
358
  id: string;
359
359
  registered?: undefined;
360
360
  label?: undefined;
361
361
  } | {
362
- count?: undefined;
362
+ provider?: undefined;
363
363
  deleted?: undefined;
364
364
  providers?: undefined;
365
- provider?: undefined;
365
+ count?: undefined;
366
366
  found?: undefined;
367
367
  registered: boolean;
368
368
  id: string;
@@ -73,7 +73,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
73
73
  offset?: unknown;
74
74
  limit?: unknown;
75
75
  }, {
76
- deleted?: undefined;
77
76
  jobs: {
78
77
  id: string;
79
78
  name: string;
@@ -84,6 +83,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
84
83
  updatedAt: string;
85
84
  }[];
86
85
  total: number;
86
+ deleted?: undefined;
87
87
  jobId?: undefined;
88
88
  } | {
89
89
  jobs?: undefined;
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
91
91
  deleted: boolean;
92
92
  jobId: string;
93
93
  } | {
94
- deleted?: undefined;
95
94
  jobs?: undefined;
96
95
  total?: undefined;
96
+ deleted?: undefined;
97
97
  jobId?: undefined;
98
98
  hits: Record<string, unknown>[];
99
99
  offset: number;
@@ -6,7 +6,7 @@ import { assertReviewableResourceAccess } from "../registry.js";
6
6
  import { ensureReviewTables, insertReviewCommentWithClient, resolveReviewThreadWithClient, } from "../store.js";
7
7
  import { suggestionActorKind, suggestionActorKindMatchesReceipt, } from "./actor-kind.js";
8
8
  import { getSuggestionAdapter } from "./registry.js";
9
- import { getSuggestion, ensureSuggestionTables, insertSuggestion, listSuggestions, recordDecision, getDecision, getSuggestionByCreationKey, recordSuggestionCreation, replaceSuggestionStatus, updateSuggestionStatus, getSuggestionAmendment, amendSuggestion, deleteUnclaimedSuggestion, getSuggestionProposal, insertSuggestionProposal, getProposalCreation, recordProposalCreation, getProposalDecision, recordProposalDecision, } from "./store.js";
9
+ import { getSuggestion, ensureSuggestionTables, insertSuggestion, listSuggestions, recordDecision, getDecision, getSuggestionByCreationKey, recordSuggestionCreation, updateSuggestionStatus, getSuggestionAmendment, amendSuggestion, deleteUnclaimedSuggestion, getSuggestionProposal, insertSuggestionProposal, getProposalCreation, recordProposalCreation, getProposalDecision, recordProposalDecision, } from "./store.js";
10
10
  const base = { resourceType: z.string().min(1), resourceId: z.string().min(1) };
11
11
  const operation = z.object({
12
12
  ordinal: z.number().int().nonnegative(),
@@ -308,7 +308,7 @@ export const getResourceSuggestion = defineAction({
308
308
  },
309
309
  });
310
310
  export const decideResourceSuggestion = defineAction({
311
- description: "Accept or reject a pending suggestion atomically.",
311
+ description: "Accept or reject a pending suggestion atomically. An accept that can no longer be placed on the current resource fails with 409 `suggestion_stale`, changes nothing, and leaves the suggestion pending.",
312
312
  schema: z.object({
313
313
  id: z.string().min(1),
314
314
  decision: z.enum(["accepted", "rejected"]),
@@ -365,22 +365,10 @@ export const decideResourceSuggestion = defineAction({
365
365
  currentAdapter.version !== current.adapterVersion)
366
366
  throw new Error("Suggestion adapter version is unavailable");
367
367
  if (current.baseRevision !== args.observedBase) {
368
- if (!(await updateSuggestionStatus(tx, current.id, "stale", current.revision))) {
369
- return replayDecision(tx);
370
- }
371
- const decision = await recordDecision(tx, {
372
- suggestionId: current.id,
373
- idempotencyKey: args.idempotencyKey,
374
- reviewer: ctx?.userEmail ?? null,
375
- decision: args.decision,
376
- observedBase: args.observedBase,
377
- outcome: "stale",
378
- detail: "Base revision changed",
368
+ fail("The suggestion changed; refresh before deciding", {
369
+ statusCode: 409,
370
+ errorCode: "suggestion_conflict",
379
371
  });
380
- return {
381
- suggestion: await getSuggestion(current.id, tx),
382
- decision: decision.record,
383
- };
384
372
  }
385
373
  const claimed = await updateSuggestionStatus(tx, current.id, args.decision, current.revision);
386
374
  if (!claimed)
@@ -412,23 +400,14 @@ export const decideResourceSuggestion = defineAction({
412
400
  });
413
401
  }
414
402
  catch (error) {
415
- if (!(error instanceof Error) ||
416
- error.name !== "SuggestionStaleError") {
417
- throw error;
418
- }
419
- await replaceSuggestionStatus(tx, current.id, "accepted", "stale");
420
- await tx.execute({
421
- sql: "UPDATE agent_review_suggestion_decisions SET outcome = ?, detail = ? WHERE id = ?",
422
- args: ["stale", error.message, prior.record.id],
423
- });
424
- return {
425
- suggestion: await getSuggestion(current.id, tx),
426
- decision: {
427
- ...prior.record,
428
- outcome: "stale",
429
- detail: error.message,
430
- },
431
- };
403
+ // Failing inside the transaction also rolls back the claim and
404
+ // decision above, so the suggestion stays pending and reviewable.
405
+ if (error instanceof Error && error.name === "SuggestionStaleError")
406
+ fail(error.message, {
407
+ statusCode: 409,
408
+ errorCode: "suggestion_stale",
409
+ });
410
+ throw error;
432
411
  }
433
412
  }
434
413
  if (!prior.duplicate) {
@@ -809,7 +788,7 @@ export const decideResourceSuggestionProposal = defineAction({
809
788
  catch (error) {
810
789
  if (error instanceof Error &&
811
790
  error.name === "SuggestionStaleError") {
812
- fail("A proposal member is stale; no proposal edits were applied", { statusCode: 409, errorCode: "suggestion_conflict" });
791
+ fail("A proposal member is stale; no proposal edits were applied", { statusCode: 409, errorCode: "suggestion_stale" });
813
792
  }
814
793
  throw error;
815
794
  }