@agent-native/core 0.167.0 → 0.167.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.
Files changed (79) hide show
  1. package/corpus/templates/analytics/.agents/skills/agent-native-docs/SKILL.md +11 -0
  2. package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +11 -0
  3. package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +11 -0
  4. package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +11 -0
  5. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +11 -0
  6. package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +11 -0
  7. package/corpus/templates/clips/CHANGELOG.md +1 -0
  8. package/corpus/templates/clips/app/routes/download.tsx +78 -131
  9. package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +11 -0
  10. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +11 -0
  11. package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +11 -0
  12. package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +11 -0
  13. package/corpus/templates/factory/.agents/skills/agent-native-docs/SKILL.md +11 -0
  14. package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +11 -0
  15. package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +11 -0
  16. package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +11 -0
  17. package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +11 -0
  18. package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +11 -0
  19. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +11 -0
  20. package/dist/changelog/parse.js +219 -8
  21. package/dist/chat-threads/store.d.ts +7 -0
  22. package/dist/chat-threads/store.js +15 -0
  23. package/dist/client/AgentPanel.d.ts +5 -1
  24. package/dist/client/AgentPanel.js +8 -8
  25. package/dist/client/AssistantChat.d.ts +3 -1
  26. package/dist/client/AssistantChat.js +22 -6
  27. package/dist/client/MultiTabAssistantChat.d.ts +3 -1
  28. package/dist/client/MultiTabAssistantChat.js +5 -4
  29. package/dist/client/agent-page/AgentJobsTab.js +39 -6
  30. package/dist/client/agent-page/AutomationScheduleDialog.d.ts +10 -1
  31. package/dist/client/agent-page/AutomationScheduleDialog.js +3 -2
  32. package/dist/client/agent-page/ScheduledTriggerNotice.d.ts +22 -0
  33. package/dist/client/agent-page/ScheduledTriggerNotice.js +84 -0
  34. package/dist/client/agent-page/scheduled-trigger-state.d.ts +28 -0
  35. package/dist/client/agent-page/scheduled-trigger-state.js +10 -0
  36. package/dist/client/agent-page/use-jobs.d.ts +7 -0
  37. package/dist/client/agent-page/use-jobs.js +14 -0
  38. package/dist/client/blocks/library/diagram.config.d.ts +4 -1
  39. package/dist/client/blocks/library/diagram.js +1 -1
  40. package/dist/client/chat/run-recovery.js +15 -7
  41. package/dist/client/use-chat-threads.d.ts +7 -0
  42. package/dist/client/use-chat-threads.js +144 -40
  43. package/dist/deploy/build.d.ts +5 -0
  44. package/dist/deploy/build.js +12 -1
  45. package/dist/framework-tools.js +1 -0
  46. package/dist/jobs/actions/get-scheduled-trigger-status.d.ts +13 -0
  47. package/dist/jobs/actions/get-scheduled-trigger-status.js +21 -0
  48. package/dist/localization/default-messages.d.ts +14 -0
  49. package/dist/localization/default-messages.js +14 -0
  50. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  51. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  52. package/dist/provider-api/actions/provider-api.d.ts +13 -13
  53. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  54. package/dist/secrets/routes.d.ts +9 -9
  55. package/dist/server/action-discovery.js +4 -0
  56. package/dist/server/agent-chat/recurring-jobs-runtime.d.ts +42 -1
  57. package/dist/server/agent-chat/recurring-jobs-runtime.js +102 -9
  58. package/dist/server/agent-chat-plugin.d.ts +3 -1
  59. package/dist/server/agent-chat-plugin.js +115 -24
  60. package/dist/server/attribution.d.ts +29 -0
  61. package/dist/server/attribution.js +68 -0
  62. package/dist/server/auth.js +58 -15
  63. package/dist/server/better-auth-instance.js +16 -4
  64. package/dist/server/identity-sso.js +14 -2
  65. package/dist/server/realtime-token.d.ts +1 -1
  66. package/dist/server/request-context.d.ts +8 -0
  67. package/dist/server/request-context.js +4 -0
  68. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +11 -0
  69. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +11 -0
  70. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +11 -0
  71. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +11 -0
  72. package/dist/vite/client.js +10 -0
  73. package/docs/content/deployment.mdx +3 -1
  74. package/docs/content/recurring-jobs.mdx +6 -0
  75. package/package.json +2 -2
  76. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +11 -0
  77. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +11 -0
  78. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +11 -0
  79. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +11 -0
@@ -137,13 +137,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
137
137
  inputSchema: {
138
138
  type: string;
139
139
  properties: {
140
- count?: undefined;
141
140
  query?: undefined;
142
141
  minutes?: undefined;
143
142
  limit?: undefined;
144
143
  clientHint?: undefined;
145
144
  timestamp?: undefined;
146
145
  chapterId?: undefined;
146
+ count?: undefined;
147
147
  startAt?: undefined;
148
148
  endAt?: undefined;
149
149
  reason?: undefined;
@@ -159,7 +159,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
159
159
  inputSchema: {
160
160
  type: string;
161
161
  properties: {
162
- count?: undefined;
163
162
  query: {
164
163
  type: string;
165
164
  description: string;
@@ -175,6 +174,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
175
174
  clientHint?: undefined;
176
175
  timestamp?: undefined;
177
176
  chapterId?: undefined;
177
+ count?: undefined;
178
178
  startAt?: undefined;
179
179
  endAt?: undefined;
180
180
  reason?: undefined;
@@ -190,7 +190,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
190
190
  inputSchema: {
191
191
  type: string;
192
192
  properties: {
193
- count?: undefined;
194
193
  minutes: {
195
194
  type: string;
196
195
  description: string;
@@ -200,6 +199,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
200
199
  clientHint?: undefined;
201
200
  timestamp?: undefined;
202
201
  chapterId?: undefined;
202
+ count?: undefined;
203
203
  startAt?: undefined;
204
204
  endAt?: undefined;
205
205
  reason?: undefined;
@@ -216,7 +216,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
216
216
  type: string;
217
217
  required: string[];
218
218
  properties: {
219
- count?: undefined;
220
219
  query: {
221
220
  type: string;
222
221
  description: string;
@@ -235,6 +234,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
235
234
  };
236
235
  timestamp?: undefined;
237
236
  chapterId?: undefined;
237
+ count?: undefined;
238
238
  startAt?: undefined;
239
239
  endAt?: undefined;
240
240
  reason?: undefined;
@@ -250,7 +250,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
250
250
  type: string;
251
251
  required: string[];
252
252
  properties: {
253
- count?: undefined;
254
253
  query?: undefined;
255
254
  minutes?: undefined;
256
255
  limit?: undefined;
@@ -264,6 +263,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
264
263
  description: string;
265
264
  };
266
265
  chapterId?: undefined;
266
+ count?: undefined;
267
267
  startAt?: undefined;
268
268
  endAt?: undefined;
269
269
  includeMicrophone?: undefined;
@@ -314,13 +314,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
314
314
  type: string;
315
315
  required: string[];
316
316
  properties: {
317
- count?: undefined;
318
317
  query?: undefined;
319
318
  minutes?: undefined;
320
319
  limit?: undefined;
321
320
  clientHint?: undefined;
322
321
  timestamp?: undefined;
323
322
  chapterId?: undefined;
323
+ count?: undefined;
324
324
  startAt: {
325
325
  type: string;
326
326
  description: string;
@@ -349,13 +349,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
349
349
  type: string;
350
350
  required: string[];
351
351
  properties: {
352
- count?: undefined;
353
352
  query?: undefined;
354
353
  minutes?: undefined;
355
354
  limit?: undefined;
356
355
  clientHint?: undefined;
357
356
  timestamp?: undefined;
358
357
  chapterId?: undefined;
358
+ count?: undefined;
359
359
  startAt?: undefined;
360
360
  endAt?: undefined;
361
361
  reason?: undefined;
@@ -94,28 +94,28 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
94
94
  message?: undefined;
95
95
  } | {
96
96
  id?: undefined;
97
- count?: undefined;
98
97
  deleted?: undefined;
99
98
  providers?: undefined;
99
+ count?: undefined;
100
100
  found: boolean;
101
101
  provider: import("../custom-registry.js").CustomProviderConfig;
102
102
  registered?: undefined;
103
103
  label?: undefined;
104
104
  message?: undefined;
105
105
  } | {
106
- count?: undefined;
107
106
  provider?: undefined;
108
107
  deleted?: undefined;
109
108
  providers?: undefined;
109
+ count?: undefined;
110
110
  found: boolean;
111
111
  id: string;
112
112
  registered?: undefined;
113
113
  label?: undefined;
114
114
  message?: undefined;
115
115
  } | {
116
- count?: undefined;
117
116
  provider?: undefined;
118
117
  providers?: undefined;
118
+ count?: undefined;
119
119
  found?: undefined;
120
120
  deleted: boolean;
121
121
  id: string;
@@ -123,10 +123,10 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
123
123
  label?: undefined;
124
124
  message?: undefined;
125
125
  } | {
126
- count?: undefined;
127
126
  provider?: undefined;
128
127
  deleted?: undefined;
129
128
  providers?: undefined;
129
+ count?: undefined;
130
130
  found?: undefined;
131
131
  registered: boolean;
132
132
  id: string;
@@ -311,9 +311,9 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
311
311
  notes?: string | undefined;
312
312
  scope?: "org" | "user" | undefined;
313
313
  }, {
314
- message?: undefined;
315
- deleted?: undefined;
316
314
  id?: undefined;
315
+ provider?: undefined;
316
+ deleted?: undefined;
317
317
  providers: {
318
318
  id: string;
319
319
  label: string;
@@ -324,45 +324,45 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
324
324
  updatedAt: number;
325
325
  }[];
326
326
  count: number;
327
- provider?: undefined;
328
327
  found?: undefined;
329
328
  registered?: undefined;
330
329
  label?: undefined;
331
- } | {
332
330
  message?: undefined;
333
- deleted?: undefined;
331
+ } | {
332
+ count?: undefined;
334
333
  id?: undefined;
334
+ deleted?: undefined;
335
335
  providers?: undefined;
336
- count?: undefined;
337
336
  found: boolean;
338
337
  provider: import("../custom-registry.js").CustomProviderConfig;
339
338
  registered?: undefined;
340
339
  label?: undefined;
341
- } | {
342
340
  message?: undefined;
343
- deleted?: undefined;
344
- providers?: undefined;
341
+ } | {
345
342
  count?: undefined;
346
343
  provider?: undefined;
344
+ deleted?: undefined;
345
+ providers?: undefined;
347
346
  found: boolean;
348
347
  id: string;
349
348
  registered?: undefined;
350
349
  label?: undefined;
351
- } | {
352
350
  message?: undefined;
353
- providers?: undefined;
351
+ } | {
354
352
  count?: undefined;
355
353
  provider?: undefined;
354
+ providers?: undefined;
356
355
  found?: undefined;
357
356
  deleted: boolean;
358
357
  id: string;
359
358
  registered?: undefined;
360
359
  label?: undefined;
360
+ message?: undefined;
361
361
  } | {
362
- deleted?: undefined;
363
- providers?: undefined;
364
362
  count?: undefined;
365
363
  provider?: undefined;
364
+ deleted?: undefined;
365
+ providers?: 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;
@@ -34,37 +34,37 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
34
34
  /** POST /_agent-native/secrets/:key — write a secret. */
35
35
  export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
36
36
  error: string;
37
- ok?: undefined;
38
37
  status?: undefined;
38
+ ok?: undefined;
39
39
  } | {
40
- error?: undefined;
41
40
  ok: boolean;
42
41
  status: string;
42
+ error?: undefined;
43
43
  } | {
44
- ok?: undefined;
45
44
  error: string;
46
45
  removed?: undefined;
46
+ ok?: undefined;
47
47
  } | {
48
- error?: undefined;
49
48
  ok: boolean;
50
49
  removed: boolean;
50
+ error?: undefined;
51
51
  }>>;
52
52
  /**
53
53
  * POST /_agent-native/secrets/:key/test — validate an optional candidate value
54
54
  * or the current stored value without changing anything.
55
55
  */
56
56
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
57
- ok?: undefined;
58
57
  error: string;
59
58
  note?: undefined;
59
+ ok?: undefined;
60
60
  } | {
61
- error?: undefined;
62
61
  ok: boolean;
63
62
  note?: undefined;
64
- } | {
65
63
  error?: undefined;
64
+ } | {
66
65
  ok: boolean;
67
66
  note: string;
67
+ error?: undefined;
68
68
  } | {
69
69
  note?: undefined;
70
70
  ok: boolean;
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
95
95
  export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
96
96
  error: string;
97
97
  } | {
98
- error?: undefined;
99
98
  ok: boolean;
100
99
  key: string;
101
- } | {
102
100
  error?: undefined;
101
+ } | {
103
102
  ok: boolean;
104
103
  removed: boolean;
104
+ error?: undefined;
105
105
  }>>;
@@ -626,6 +626,10 @@ export async function mergeCoreSharingActions(registry) {
626
626
  "list-automation-runs",
627
627
  () => import("../jobs/actions/list-automation-runs.js"),
628
628
  ],
629
+ [
630
+ "get-scheduled-trigger-status",
631
+ () => import("../jobs/actions/get-scheduled-trigger-status.js"),
632
+ ],
629
633
  [
630
634
  "list-automations",
631
635
  () => import("../triggers/actions/list-automations.js"),
@@ -1,4 +1,4 @@
1
- type RecurringJobsRuntimeEnvKey = "AGENT_NATIVE_DISABLE_RECURRING_JOBS" | "AGENT_NATIVE_ENABLE_LOCAL_RECURRING_JOBS" | "APP_URL" | "BETTER_AUTH_URL" | "CF_PAGES" | "DEPLOY_URL" | "AWS_EXECUTION_ENV" | "AWS_LAMBDA_FUNCTION_NAME" | "NETLIFY" | "NETLIFY_LOCAL" | "NITRO_PRESET" | "NODE_ENV" | "SITE_ID" | "URL" | "VERCEL" | "VITE_APP_URL" | "VITE_WORKSPACE_GATEWAY_URL" | "WORKSPACE_GATEWAY_URL";
1
+ type RecurringJobsRuntimeEnvKey = "AGENT_NATIVE_BUILD_RECURRING_JOBS" | "AGENT_NATIVE_DISABLE_RECURRING_JOBS" | "AGENT_NATIVE_ENABLE_LOCAL_RECURRING_JOBS" | "APP_URL" | "BETTER_AUTH_URL" | "CF_PAGES" | "DEPLOY_URL" | "AWS_EXECUTION_ENV" | "AWS_LAMBDA_FUNCTION_NAME" | "NETLIFY" | "NETLIFY_LOCAL" | "NITRO_PRESET" | "NODE_ENV" | "SITE_ID" | "URL" | "VERCEL" | "VITE_APP_URL" | "VITE_WORKSPACE_GATEWAY_URL" | "WORKSPACE_GATEWAY_URL";
2
2
  type RecurringJobsRuntimeEnv = Partial<Record<RecurringJobsRuntimeEnvKey, string | undefined>>;
3
3
  export declare function shouldDisableRecurringJobsRuntime(env?: RecurringJobsRuntimeEnv): boolean;
4
4
  /**
@@ -7,4 +7,45 @@ export declare function shouldDisableRecurringJobsRuntime(env?: RecurringJobsRun
7
7
  * that timer, which is exactly the failure mode the emitted sweep fixes.
8
8
  */
9
9
  export declare function isNetlifyRecurringJobsRuntime(env?: RecurringJobsRuntimeEnv): boolean;
10
+ /** What the BUILD decided about recurring jobs, as carried into the runtime. */
11
+ export type RecurringJobsBuildMarker = "enabled" | "disabled";
12
+ /**
13
+ * Env name the build embeds its recurring-jobs decision under.
14
+ *
15
+ * Netlify's scheduled function is emitted — or omitted — while the build runs,
16
+ * and a deployed serverless runtime never sees the build environment. So the
17
+ * build has to hand the decision over explicitly; nothing observable at runtime
18
+ * can reconstruct it. Consumed below as a LITERAL `process.env.<name>` member
19
+ * expression because that is the only form Vite's `define` and Nitro's
20
+ * `replace` inline at build time.
21
+ */
22
+ export declare const RECURRING_JOBS_BUILD_MARKER_ENV_VAR = "AGENT_NATIVE_BUILD_RECURRING_JOBS";
23
+ /**
24
+ * Build-side resolver: what the build environment decided. Shared with
25
+ * `isRecurringJobsDeployEnabled` in the deploy build so the gate that emits the
26
+ * scheduled function and the marker that reports it cannot disagree.
27
+ */
28
+ export declare function resolveRecurringJobsBuildMarker(env?: RecurringJobsRuntimeEnv): RecurringJobsBuildMarker;
29
+ export type ScheduledTriggerAvailability = {
30
+ available: true;
31
+ driver: "netlify-scheduled-function" | "in-process";
32
+ } | {
33
+ available: false;
34
+ reason: "disabled-by-env" | "no-platform-scheduler" | "local-development";
35
+ };
36
+ /**
37
+ * Whether ANY driver will actually fire a schedule-triggered automation in this
38
+ * deploy. Distinct from `shouldDisableRecurringJobsRuntime`, which answers the
39
+ * narrower "should THIS process run an in-process timer" and is therefore `true`
40
+ * on hosted Netlify even though schedules do fire there via the emitted
41
+ * scheduled function — reporting that value to a user would call the one
42
+ * working production runtime broken.
43
+ *
44
+ * Each branch reads the scope that actually decides its driver. The Netlify
45
+ * driver is a BUILD artifact, so it is answered by the build marker; every other
46
+ * driver is an in-process timer started from the RUNTIME env, so it is answered
47
+ * by the runtime flag. Reading runtime-only platform markers for the Netlify
48
+ * branch would report `available` off a build that emitted no trigger at all.
49
+ */
50
+ export declare function scheduledTriggerAvailability(env?: RecurringJobsRuntimeEnv): ScheduledTriggerAvailability;
10
51
  export {};
@@ -30,20 +30,27 @@ function isLoopbackAppUrl(value) {
30
30
  }
31
31
  return false;
32
32
  }
33
- export function shouldDisableRecurringJobsRuntime(env = process.env) {
34
- if (isTruthyEnv(env.AGENT_NATIVE_DISABLE_RECURRING_JOBS))
35
- return true;
36
- // A serverless isolate is not a durable scheduler. Keep this check separate
37
- // from the platform-specific scheduler branch below so a new sweep cannot
38
- // accidentally start an in-process timer before its platform trigger exists.
39
- const isServerlessRuntime = env.NETLIFY_LOCAL !== "true" &&
33
+ /**
34
+ * A serverless isolate is not a durable scheduler. Shared so
35
+ * `shouldDisableRecurringJobsRuntime` and `scheduledTriggerAvailability` cannot
36
+ * drift on what counts as serverless.
37
+ */
38
+ function isServerlessRecurringJobsRuntime(env) {
39
+ return (env.NETLIFY_LOCAL !== "true" &&
40
40
  (isTruthyEnv(env.NETLIFY) ||
41
41
  env.NITRO_PRESET === "netlify" ||
42
42
  Boolean(env.AWS_LAMBDA_FUNCTION_NAME) ||
43
43
  env.AWS_EXECUTION_ENV?.startsWith("AWS_Lambda") === true ||
44
44
  isTruthyEnv(env.CF_PAGES) ||
45
- isTruthyEnv(env.VERCEL));
46
- if (isServerlessRuntime)
45
+ isTruthyEnv(env.VERCEL)));
46
+ }
47
+ export function shouldDisableRecurringJobsRuntime(env = process.env) {
48
+ if (isTruthyEnv(env.AGENT_NATIVE_DISABLE_RECURRING_JOBS))
49
+ return true;
50
+ // Keep this check separate from the platform-specific scheduler branch below
51
+ // so a new sweep cannot accidentally start an in-process timer before its
52
+ // platform trigger exists.
53
+ if (isServerlessRecurringJobsRuntime(env))
47
54
  return true;
48
55
  const isLocalRuntime = env.NODE_ENV === "development" ||
49
56
  env.NODE_ENV === "test" ||
@@ -74,3 +81,89 @@ export function isNetlifyRecurringJobsRuntime(env = process.env) {
74
81
  return false;
75
82
  return Boolean((env.NETLIFY && env.NETLIFY !== "false") || env.SITE_ID);
76
83
  }
84
+ /**
85
+ * Env name the build embeds its recurring-jobs decision under.
86
+ *
87
+ * Netlify's scheduled function is emitted — or omitted — while the build runs,
88
+ * and a deployed serverless runtime never sees the build environment. So the
89
+ * build has to hand the decision over explicitly; nothing observable at runtime
90
+ * can reconstruct it. Consumed below as a LITERAL `process.env.<name>` member
91
+ * expression because that is the only form Vite's `define` and Nitro's
92
+ * `replace` inline at build time.
93
+ */
94
+ export const RECURRING_JOBS_BUILD_MARKER_ENV_VAR = "AGENT_NATIVE_BUILD_RECURRING_JOBS";
95
+ /**
96
+ * Build-side resolver: what the build environment decided. Shared with
97
+ * `isRecurringJobsDeployEnabled` in the deploy build so the gate that emits the
98
+ * scheduled function and the marker that reports it cannot disagree.
99
+ */
100
+ export function resolveRecurringJobsBuildMarker(env = process.env) {
101
+ return isTruthyEnv(env.AGENT_NATIVE_DISABLE_RECURRING_JOBS)
102
+ ? "disabled"
103
+ : "enabled";
104
+ }
105
+ function readRecurringJobsBuildMarker(env) {
106
+ const raw = env.AGENT_NATIVE_BUILD_RECURRING_JOBS ??
107
+ // config-ok: this value is INLINED at build time by Vite's `define` /
108
+ // Nitro's `replace`, which rewrite the literal `process.env.<NAME>` member
109
+ // expression and nothing else. A declared app-config field is read at
110
+ // runtime from the deployed environment, which is precisely the scope that
111
+ // cannot see the build's decision — the bug this marker exists to fix.
112
+ // Reading through the aliased `env` parameter would also survive the build
113
+ // unreplaced, so the literal form is load-bearing.
114
+ process.env.AGENT_NATIVE_BUILD_RECURRING_JOBS;
115
+ const value = raw?.trim();
116
+ return value === "enabled" || value === "disabled" ? value : undefined;
117
+ }
118
+ /**
119
+ * Whether ANY driver will actually fire a schedule-triggered automation in this
120
+ * deploy. Distinct from `shouldDisableRecurringJobsRuntime`, which answers the
121
+ * narrower "should THIS process run an in-process timer" and is therefore `true`
122
+ * on hosted Netlify even though schedules do fire there via the emitted
123
+ * scheduled function — reporting that value to a user would call the one
124
+ * working production runtime broken.
125
+ *
126
+ * Each branch reads the scope that actually decides its driver. The Netlify
127
+ * driver is a BUILD artifact, so it is answered by the build marker; every other
128
+ * driver is an in-process timer started from the RUNTIME env, so it is answered
129
+ * by the runtime flag. Reading runtime-only platform markers for the Netlify
130
+ * branch would report `available` off a build that emitted no trigger at all.
131
+ */
132
+ export function scheduledTriggerAvailability(env = process.env) {
133
+ const buildMarker = readRecurringJobsBuildMarker(env);
134
+ // Netlify: the driver IS the emitted scheduled function. It fires on the
135
+ // platform's clock without consulting the deployed env, and no runtime value
136
+ // can conjure it back once the build omitted it — so the build marker is the
137
+ // only honest input here, in both directions.
138
+ if (isNetlifyRecurringJobsRuntime(env)) {
139
+ if (buildMarker === "disabled") {
140
+ return { available: false, reason: "disabled-by-env" };
141
+ }
142
+ if (buildMarker === "enabled") {
143
+ return { available: true, driver: "netlify-scheduled-function" };
144
+ }
145
+ // No marker: a build predating it, or a caller passing a synthetic env.
146
+ // Fall back to the runtime flag, which only agrees with the build when the
147
+ // pipeline sets the same value in both scopes.
148
+ return isTruthyEnv(env.AGENT_NATIVE_DISABLE_RECURRING_JOBS)
149
+ ? { available: false, reason: "disabled-by-env" }
150
+ : { available: true, driver: "netlify-scheduled-function" };
151
+ }
152
+ // Everything below is driven by an in-process timer, and the runtime flag is
153
+ // what `shouldDisableRecurringJobsRuntime` reads before starting it. A build
154
+ // marker cannot speak for this branch: a build with recurring jobs turned off
155
+ // still starts the timer if the deployed env does not repeat the switch.
156
+ if (isTruthyEnv(env.AGENT_NATIVE_DISABLE_RECURRING_JOBS)) {
157
+ return { available: false, reason: "disabled-by-env" };
158
+ }
159
+ // Every other serverless host: the build emits a scheduled trigger only for
160
+ // Netlify, and a frozen isolate cannot hold a timer.
161
+ if (isServerlessRecurringJobsRuntime(env)) {
162
+ return { available: false, reason: "no-platform-scheduler" };
163
+ }
164
+ // Long-lived host. Whatever is left of the runtime gate here is the
165
+ // local/loopback branch, which needs AGENT_NATIVE_ENABLE_LOCAL_RECURRING_JOBS.
166
+ return shouldDisableRecurringJobsRuntime(env)
167
+ ? { available: false, reason: "local-development" }
168
+ : { available: true, driver: "in-process" };
169
+ }
@@ -9,7 +9,7 @@ import { _agentChatPromptSectionsForTests } from "./agent-chat/framework-prompts
9
9
  import { type AgentChatPluginOptions, type NitroPluginDef } from "./agent-chat/plugin-options.js";
10
10
  import { finalizeClaimedAgentChatProcessRunFailure } from "./agent-chat/process-run-failure.js";
11
11
  import { loadResourcesForPrompt } from "./agent-chat/prompt-resources.js";
12
- import { isNetlifyRecurringJobsRuntime, shouldDisableRecurringJobsRuntime } from "./agent-chat/recurring-jobs-runtime.js";
12
+ import { isNetlifyRecurringJobsRuntime, resolveRecurringJobsBuildMarker, scheduledTriggerAvailability, shouldDisableRecurringJobsRuntime } from "./agent-chat/recurring-jobs-runtime.js";
13
13
  import { shouldBlockInProductCodeEditingSurface } from "./agent-chat/request-surface.js";
14
14
  import { loadRunCodeToolEntries } from "./agent-chat/run-code-tools.js";
15
15
  export { loadResourcesForPrompt };
@@ -34,6 +34,8 @@ export { DEFAULT_DELEGATED_MAX_ITERATIONS, DEFAULT_DELEGATED_MAX_RUN_INPUT_TOKEN
34
34
  export { shouldBlockInProductCodeEditingSurface };
35
35
  export { loadRunCodeToolEntries };
36
36
  export { isNetlifyRecurringJobsRuntime };
37
+ export { resolveRecurringJobsBuildMarker };
38
+ export { scheduledTriggerAvailability };
37
39
  export { shouldDisableRecurringJobsRuntime };
38
40
  export { finalizeClaimedAgentChatProcessRunFailure };
39
41
  export declare function resolveInteractiveAgentRunOptions(options?: Pick<AgentChatPluginOptions, "runSoftTimeoutMs" | "runNoProgressTimeoutMs" | "durableBackgroundRuns">): {