@agent-native/core 0.144.2 → 0.145.0

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 (104) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/app/pages/DataSources.tsx +28 -4
  3. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +7 -3
  4. package/corpus/templates/analytics/server/plugins/dashboard-report-jobs.ts +13 -3
  5. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +64 -23
  6. package/corpus/templates/calendar/app/hooks/use-google-auth.ts +69 -46
  7. package/corpus/templates/calendar/app/hooks/use-view-preferences.ts +35 -6
  8. package/corpus/templates/calendar/app/hooks/use-zoom-auth.ts +24 -3
  9. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +45 -6
  10. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +38 -5
  11. package/corpus/templates/clips/changelog/2026-08-06-desktop-full-screen-recordings-now-normalize-microphone-leve.md +6 -0
  12. package/corpus/templates/clips/desktop/src/app.tsx +146 -45
  13. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +185 -69
  14. package/corpus/templates/clips/server/jobs/brain-export.ts +13 -6
  15. package/corpus/templates/clips/server/jobs/builder-media-compression.ts +10 -3
  16. package/corpus/templates/clips/server/jobs/meeting-reminders.ts +10 -3
  17. package/corpus/templates/clips/server/jobs/poll-calendars.ts +23 -21
  18. package/corpus/templates/clips/server/jobs/stale-meeting-sweeper.ts +10 -3
  19. package/corpus/templates/clips/server/jobs/transactional-emails.ts +10 -3
  20. package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +1 -0
  21. package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +15 -2
  22. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +47 -4
  23. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -1
  24. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +82 -39
  25. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +31 -9
  26. package/corpus/templates/mail/server/plugins/mail-jobs.ts +36 -17
  27. package/corpus/templates/slides/server/plugins/agent-chat.ts +1 -1
  28. package/dist/agent/production-agent.d.ts +6 -0
  29. package/dist/client/AssistantChat.js +73 -43
  30. package/dist/client/MultiTabAssistantChat.d.ts +3 -1
  31. package/dist/client/MultiTabAssistantChat.js +79 -92
  32. package/dist/client/browser-session-bridge.js +97 -54
  33. package/dist/client/db-admin/useAgentSync.js +34 -43
  34. package/dist/client/dynamic-suggestions.d.ts +3 -0
  35. package/dist/client/dynamic-suggestions.js +54 -52
  36. package/dist/client/hooks/index.d.ts +1 -0
  37. package/dist/client/hooks/index.js +1 -0
  38. package/dist/client/i18n.d.ts +7 -0
  39. package/dist/client/i18n.js +12 -3
  40. package/dist/client/integrations/useIntegrationStatus.d.ts +1 -1
  41. package/dist/client/integrations/useIntegrationStatus.js +9 -22
  42. package/dist/client/notifications/NotificationsBell.js +14 -9
  43. package/dist/client/progress/RunsTray.js +6 -5
  44. package/dist/client/settings/useBuilderStatus.js +95 -73
  45. package/dist/client/transcription/BuilderTranscriptionCta.js +27 -31
  46. package/dist/client/use-agent-engine-configured.js +21 -3
  47. package/dist/client/use-pausing-interval.d.ts +6 -0
  48. package/dist/client/use-pausing-interval.js +6 -0
  49. package/dist/client/use-poll-loop.d.ts +39 -0
  50. package/dist/client/use-poll-loop.js +73 -0
  51. package/dist/client/use-run-stuck-detection.js +41 -13
  52. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  53. package/dist/framework-tools.d.ts +126 -0
  54. package/dist/framework-tools.js +114 -0
  55. package/dist/integrations/google-docs-poller.js +26 -7
  56. package/dist/integrations/pending-tasks-retry-job.js +17 -23
  57. package/dist/integrations/plugin.js +16 -15
  58. package/dist/integrations/remote-push-delivery-job.js +16 -25
  59. package/dist/integrations/remote-retry-job.js +19 -23
  60. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  61. package/dist/notifications/routes.d.ts +3 -3
  62. package/dist/oauth-tokens/google-refresh.js +12 -19
  63. package/dist/observability/routes.d.ts +3 -3
  64. package/dist/progress/routes.d.ts +1 -1
  65. package/dist/provider-api/actions/custom-provider-registration.d.ts +9 -9
  66. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  67. package/dist/resources/handlers.d.ts +1 -1
  68. package/dist/secrets/routes.d.ts +3 -3
  69. package/dist/server/action-discovery.d.ts +27 -0
  70. package/dist/server/action-discovery.js +89 -0
  71. package/dist/server/agent-chat/action-filters-a2a.d.ts +11 -0
  72. package/dist/server/agent-chat/action-filters-a2a.js +17 -1
  73. package/dist/server/agent-chat/framework-prompts.d.ts +2 -0
  74. package/dist/server/agent-chat/plugin-options.d.ts +30 -0
  75. package/dist/server/agent-chat/prompt-resources.d.ts +4 -1
  76. package/dist/server/agent-chat/prompt-resources.js +8 -2
  77. package/dist/server/agent-chat-plugin.js +148 -100
  78. package/dist/server/index.d.ts +1 -0
  79. package/dist/server/index.js +1 -0
  80. package/dist/server/interval-job.d.ts +25 -0
  81. package/dist/server/interval-job.js +19 -0
  82. package/dist/server/prompts/framework-core-compact.d.ts +5 -0
  83. package/dist/server/prompts/framework-core-compact.js +28 -12
  84. package/dist/server/prompts/framework-core.d.ts +5 -0
  85. package/dist/server/prompts/framework-core.js +33 -16
  86. package/dist/server/prompts/index.d.ts +1 -1
  87. package/dist/server/prompts/index.js +1 -1
  88. package/dist/server/prompts/shared-rules.d.ts +12 -4
  89. package/dist/server/prompts/shared-rules.js +14 -4
  90. package/dist/server/realtime-token.d.ts +1 -1
  91. package/dist/shared/index.d.ts +1 -0
  92. package/dist/shared/index.js +1 -0
  93. package/dist/shared/poll-engine.d.ts +49 -0
  94. package/dist/shared/poll-engine.js +148 -0
  95. package/dist/templates/default/.agents/skills/internationalization/SKILL.md +5 -0
  96. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -3
  97. package/dist/templates/workspace-core/.agents/skills/internationalization/SKILL.md +5 -0
  98. package/dist/tracking/providers.js +10 -1
  99. package/docs/content/deployment.mdx +47 -13
  100. package/docs/content/key-concepts.mdx +13 -6
  101. package/package.json +2 -1
  102. package/src/templates/default/.agents/skills/internationalization/SKILL.md +5 -0
  103. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -3
  104. package/src/templates/workspace-core/.agents/skills/internationalization/SKILL.md +5 -0
@@ -137,13 +137,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
137
137
  inputSchema: {
138
138
  type: string;
139
139
  properties: {
140
+ count?: undefined;
140
141
  query?: undefined;
141
142
  minutes?: undefined;
142
143
  limit?: undefined;
143
144
  clientHint?: undefined;
144
145
  timestamp?: undefined;
145
146
  chapterId?: undefined;
146
- count?: undefined;
147
147
  startAt?: undefined;
148
148
  endAt?: undefined;
149
149
  reason?: undefined;
@@ -159,6 +159,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
159
159
  inputSchema: {
160
160
  type: string;
161
161
  properties: {
162
+ count?: undefined;
162
163
  query: {
163
164
  type: string;
164
165
  description: string;
@@ -174,7 +175,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
174
175
  clientHint?: undefined;
175
176
  timestamp?: undefined;
176
177
  chapterId?: undefined;
177
- count?: undefined;
178
178
  startAt?: undefined;
179
179
  endAt?: undefined;
180
180
  reason?: undefined;
@@ -190,6 +190,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
190
190
  inputSchema: {
191
191
  type: string;
192
192
  properties: {
193
+ count?: undefined;
193
194
  minutes: {
194
195
  type: string;
195
196
  description: string;
@@ -199,7 +200,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
199
200
  clientHint?: undefined;
200
201
  timestamp?: undefined;
201
202
  chapterId?: undefined;
202
- count?: undefined;
203
203
  startAt?: undefined;
204
204
  endAt?: undefined;
205
205
  reason?: undefined;
@@ -216,6 +216,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
216
216
  type: string;
217
217
  required: string[];
218
218
  properties: {
219
+ count?: undefined;
219
220
  query: {
220
221
  type: string;
221
222
  description: string;
@@ -234,7 +235,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
234
235
  };
235
236
  timestamp?: undefined;
236
237
  chapterId?: undefined;
237
- count?: undefined;
238
238
  startAt?: undefined;
239
239
  endAt?: undefined;
240
240
  reason?: undefined;
@@ -250,6 +250,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
250
250
  type: string;
251
251
  required: string[];
252
252
  properties: {
253
+ count?: undefined;
253
254
  query?: undefined;
254
255
  minutes?: undefined;
255
256
  limit?: undefined;
@@ -263,7 +264,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
263
264
  description: string;
264
265
  };
265
266
  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;
317
318
  query?: undefined;
318
319
  minutes?: undefined;
319
320
  limit?: undefined;
320
321
  clientHint?: undefined;
321
322
  timestamp?: undefined;
322
323
  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;
352
353
  query?: undefined;
353
354
  minutes?: undefined;
354
355
  limit?: undefined;
355
356
  clientHint?: undefined;
356
357
  timestamp?: undefined;
357
358
  chapterId?: undefined;
358
- count?: undefined;
359
359
  startAt?: undefined;
360
360
  endAt?: undefined;
361
361
  reason?: undefined;
@@ -16,18 +16,18 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
16
16
  error?: undefined;
17
17
  ok?: undefined;
18
18
  } | {
19
+ count?: undefined;
19
20
  updated: number;
20
21
  error?: undefined;
21
22
  ok?: undefined;
22
- count?: undefined;
23
23
  } | {
24
+ count?: undefined;
24
25
  updated?: undefined;
25
26
  error: string;
26
27
  ok?: undefined;
27
- count?: undefined;
28
28
  } | {
29
+ count?: undefined;
29
30
  updated?: undefined;
30
31
  error?: undefined;
31
32
  ok: boolean;
32
- count?: undefined;
33
33
  }>>;
@@ -11,8 +11,11 @@
11
11
  * server plugin (see `templates/mail/server/plugins/oauth-refresh.ts`).
12
12
  */
13
13
  import { resolveGoogleProviderCredentialCandidates } from "../server/google-oauth-credentials.js";
14
+ import { startIntervalJob } from "../server/interval-job.js";
14
15
  import { listOAuthAccounts, saveOAuthTokens } from "./store.js";
15
16
  const GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
17
+ /** Bounds each per-account refresh call — this loop runs sequentially over every expiring account. */
18
+ const REFRESH_REQUEST_TIMEOUT_MS = 15_000;
16
19
  async function refreshOne(refreshToken) {
17
20
  const credentialCandidates = resolveGoogleProviderCredentialCandidates();
18
21
  if (!credentialCandidates.length) {
@@ -30,6 +33,7 @@ async function refreshOne(refreshToken) {
30
33
  client_secret: credentials.clientSecret,
31
34
  grant_type: "refresh_token",
32
35
  }),
36
+ signal: AbortSignal.timeout(REFRESH_REQUEST_TIMEOUT_MS),
33
37
  });
34
38
  lastStatusText = res.statusText;
35
39
  data = (await res.json());
@@ -91,7 +95,6 @@ export async function refreshExpiringGoogleTokens(opts = {}) {
91
95
  }
92
96
  }
93
97
  let _started = false;
94
- let _timer;
95
98
  /**
96
99
  * Start the refresh loop. Idempotent — calling more than once is a no-op,
97
100
  * so multiple plugins/templates loading this in the same process are safe.
@@ -108,25 +111,15 @@ export function startGoogleTokenRefreshLoop(opts = {}) {
108
111
  }
109
112
  const intervalMs = opts.intervalMs ?? 20 * 60 * 1000;
110
113
  const bufferMs = opts.bufferMs ?? 15 * 60 * 1000;
111
- // Kick off an initial pass shortly after startup (not immediately — the DB
114
+ // Kick off the first pass shortly after startup (not immediately — the DB
112
115
  // may still be initializing).
113
- const initialTimer = setTimeout(() => {
114
- refreshExpiringGoogleTokens({ bufferMs }).catch((err) => {
115
- console.error("[google-refresh] initial pass failed:", err);
116
+ const startupTimer = setTimeout(() => {
117
+ startIntervalJob(() => refreshExpiringGoogleTokens({ bufferMs }), {
118
+ intervalMs,
119
+ onError: (err) => {
120
+ console.error("[google-refresh] refresh pass failed:", err);
121
+ },
116
122
  });
117
123
  }, 30_000);
118
- _timer = setInterval(() => {
119
- refreshExpiringGoogleTokens({ bufferMs }).catch((err) => {
120
- console.error("[google-refresh] interval pass failed:", err);
121
- });
122
- }, intervalMs);
123
- // Don't let either timer keep the process alive on its own.
124
- if (typeof initialTimer === "object" &&
125
- initialTimer &&
126
- "unref" in initialTimer) {
127
- initialTimer.unref();
128
- }
129
- if (typeof _timer === "object" && _timer && "unref" in _timer) {
130
- _timer.unref();
131
- }
124
+ startupTimer.unref?.();
132
125
  }
@@ -42,22 +42,22 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
42
42
  avgEvalScore: number;
43
43
  } | {
44
44
  error?: undefined;
45
+ ok?: undefined;
45
46
  summary: import("./types.js").TraceSummary;
46
47
  spans: import("./types.js").TraceSpan[];
47
48
  id?: undefined;
48
- ok?: undefined;
49
49
  } | {
50
50
  error?: undefined;
51
+ ok?: undefined;
51
52
  summary?: undefined;
52
53
  spans?: undefined;
53
54
  id: string;
54
- ok?: undefined;
55
55
  } | {
56
+ ok?: undefined;
56
57
  summary?: undefined;
57
58
  spans?: undefined;
58
59
  id?: undefined;
59
60
  error: any;
60
- ok?: undefined;
61
61
  } | {
62
62
  error?: undefined;
63
63
  summary?: undefined;
@@ -15,6 +15,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
15
15
  error: string;
16
16
  ok?: undefined;
17
17
  } | {
18
- ok: boolean;
19
18
  error?: undefined;
19
+ ok: boolean;
20
20
  }>>;
@@ -76,7 +76,7 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
76
76
  }>>;
77
77
  }, z.core.$strip>>, {
78
78
  deleted?: undefined;
79
- id?: undefined;
79
+ found?: undefined;
80
80
  providers: {
81
81
  id: string;
82
82
  label: string;
@@ -88,24 +88,24 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
88
88
  }[];
89
89
  count: number;
90
90
  provider?: undefined;
91
- found?: undefined;
92
91
  registered?: undefined;
92
+ id?: undefined;
93
93
  label?: undefined;
94
94
  message?: undefined;
95
95
  } | {
96
96
  deleted?: undefined;
97
- count?: undefined;
98
- id?: undefined;
99
97
  providers?: undefined;
98
+ count?: undefined;
100
99
  found: boolean;
101
100
  provider: import("../custom-registry.js").CustomProviderConfig;
102
101
  registered?: undefined;
102
+ id?: undefined;
103
103
  label?: undefined;
104
104
  message?: undefined;
105
105
  } | {
106
106
  deleted?: undefined;
107
- count?: undefined;
108
107
  providers?: undefined;
108
+ count?: undefined;
109
109
  provider?: undefined;
110
110
  found: boolean;
111
111
  id: string;
@@ -113,10 +113,10 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
113
113
  label?: undefined;
114
114
  message?: undefined;
115
115
  } | {
116
- count?: undefined;
116
+ found?: undefined;
117
117
  providers?: undefined;
118
+ count?: undefined;
118
119
  provider?: undefined;
119
- found?: undefined;
120
120
  deleted: boolean;
121
121
  id: string;
122
122
  registered?: undefined;
@@ -124,10 +124,10 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
124
124
  message?: undefined;
125
125
  } | {
126
126
  deleted?: undefined;
127
- count?: undefined;
127
+ found?: undefined;
128
128
  providers?: undefined;
129
+ count?: undefined;
129
130
  provider?: undefined;
130
- found?: undefined;
131
131
  registered: boolean;
132
132
  id: string;
133
133
  label: string;
@@ -311,10 +311,10 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
311
311
  notes?: string | undefined;
312
312
  scope?: "org" | "user" | undefined;
313
313
  }, {
314
- message?: undefined;
315
314
  id?: undefined;
316
315
  provider?: undefined;
317
316
  deleted?: undefined;
317
+ found?: undefined;
318
318
  providers: {
319
319
  id: string;
320
320
  label: string;
@@ -325,45 +325,45 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
325
325
  updatedAt: number;
326
326
  }[];
327
327
  count: number;
328
- found?: undefined;
329
328
  registered?: undefined;
330
329
  label?: undefined;
331
- } | {
332
330
  message?: undefined;
333
- count?: undefined;
331
+ } | {
334
332
  id?: undefined;
335
333
  deleted?: undefined;
334
+ count?: undefined;
336
335
  providers?: 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
- count?: undefined;
341
+ } | {
344
342
  provider?: undefined;
345
343
  deleted?: undefined;
344
+ count?: undefined;
346
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
- count?: undefined;
351
+ } | {
354
352
  provider?: undefined;
355
- providers?: undefined;
356
353
  found?: undefined;
354
+ count?: undefined;
355
+ providers?: undefined;
357
356
  deleted: boolean;
358
357
  id: string;
359
358
  registered?: undefined;
360
359
  label?: undefined;
360
+ message?: undefined;
361
361
  } | {
362
- count?: undefined;
363
362
  provider?: undefined;
364
363
  deleted?: undefined;
365
- providers?: undefined;
366
364
  found?: undefined;
365
+ count?: undefined;
366
+ providers?: undefined;
367
367
  registered: boolean;
368
368
  id: string;
369
369
  label: string;
@@ -48,8 +48,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
48
48
  }>;
49
49
  /** DELETE /_agent-native/resources/:id — delete a resource */
50
50
  export declare function handleDeleteResource(event: any): Promise<{
51
- error: string;
52
51
  ok?: undefined;
52
+ error: string;
53
53
  } | {
54
54
  error?: undefined;
55
55
  ok: boolean;
@@ -34,16 +34,16 @@ 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
- status?: undefined;
38
37
  ok?: undefined;
38
+ status?: undefined;
39
39
  } | {
40
40
  ok: boolean;
41
41
  status: string;
42
42
  error?: undefined;
43
43
  } | {
44
+ ok?: undefined;
44
45
  error: string;
45
46
  removed?: undefined;
46
- ok?: undefined;
47
47
  } | {
48
48
  ok: boolean;
49
49
  removed: boolean;
@@ -54,9 +54,9 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
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;
57
58
  error: string;
58
59
  note?: undefined;
59
- ok?: undefined;
60
60
  } | {
61
61
  ok: boolean;
62
62
  note?: undefined;
@@ -26,6 +26,7 @@
26
26
  * ```
27
27
  */
28
28
  import type { ActionEntry } from "../agent/production-agent.js";
29
+ import type { FrameworkToolGroup } from "../framework-tools.js";
29
30
  /**
30
31
  * Register a map of actions contributed by a published package.
31
32
  *
@@ -80,6 +81,32 @@ export declare function loadActionsFromStaticRegistry(modules: Record<string, un
80
81
  * passing to `createAgentChatPlugin({ actions })`.
81
82
  */
82
83
  export declare function autoDiscoverActions(from: string): Promise<Record<string, ActionEntry>>;
84
+ /**
85
+ * Which `frameworkTools` switch owns each framework action kit.
86
+ *
87
+ * The group is stamped onto the entry as `frameworkGroup`, which is what lets
88
+ * one filter subtract a whole kit from every agent tool surface at once — the
89
+ * plugin spreads these registries at thirteen composition sites, and a
90
+ * per-site condition would be the same omission waiting to happen thirteen
91
+ * times. The tag also keeps these ~45 schemas out of the DEFAULT first-request
92
+ * tool list; they stay reachable through `tool-search`.
93
+ *
94
+ * Anything absent from this map is always-on and must be listed in
95
+ * `ALWAYS_ON_CORE_ACTIONS` instead. `action-discovery.spec.ts` fails when a new
96
+ * core action appears in neither, so "always-on" stays a decision someone made
97
+ * rather than the default that happens when a map goes un-updated.
98
+ */
99
+ export declare const CORE_ACTION_GROUPS: Record<string, FrameworkToolGroup>;
100
+ /**
101
+ * Core actions with no `frameworkTools` switch, and why:
102
+ *
103
+ * - `upload-image` is load-bearing for ordinary work.
104
+ * - The email catalog is mounted everywhere on purpose so Dispatch can ask any
105
+ * app what it sends without that app opting in (see its comment below). It is
106
+ * a read surface, not the `email` group's send capability.
107
+ * - MCP tools and org service tokens are already governed by `disableMcp`.
108
+ */
109
+ export declare const ALWAYS_ON_CORE_ACTIONS: ReadonlySet<string>;
83
110
  export declare function mergeCoreSharingActions(registry: Record<string, ActionEntry>): Promise<void>;
84
111
  /** @deprecated Use `autoDiscoverActions` instead */
85
112
  export declare const autoDiscoverScripts: typeof autoDiscoverActions;
@@ -497,6 +497,92 @@ export async function autoDiscoverActions(from) {
497
497
  }
498
498
  return registry;
499
499
  }
500
+ /**
501
+ * Which `frameworkTools` switch owns each framework action kit.
502
+ *
503
+ * The group is stamped onto the entry as `frameworkGroup`, which is what lets
504
+ * one filter subtract a whole kit from every agent tool surface at once — the
505
+ * plugin spreads these registries at thirteen composition sites, and a
506
+ * per-site condition would be the same omission waiting to happen thirteen
507
+ * times. The tag also keeps these ~45 schemas out of the DEFAULT first-request
508
+ * tool list; they stay reachable through `tool-search`.
509
+ *
510
+ * Anything absent from this map is always-on and must be listed in
511
+ * `ALWAYS_ON_CORE_ACTIONS` instead. `action-discovery.spec.ts` fails when a new
512
+ * core action appears in neither, so "always-on" stays a decision someone made
513
+ * rather than the default that happens when a map goes un-updated.
514
+ */
515
+ export const CORE_ACTION_GROUPS = {
516
+ "share-resource": "sharing",
517
+ "unshare-resource": "sharing",
518
+ "list-resource-shares": "sharing",
519
+ "set-resource-visibility": "sharing",
520
+ "create-agent-resource-link": "sharing",
521
+ "get-feature-flags": "featureFlags",
522
+ "list-feature-flags": "featureFlags",
523
+ "set-feature-flag": "featureFlags",
524
+ "list-recurring-jobs": "automation",
525
+ "manage-recurring-job": "automation",
526
+ "run-automation-now": "automation",
527
+ "list-automation-runs": "automation",
528
+ "list-automations": "automation",
529
+ "manage-automation": "automation",
530
+ "context-manifest-get": "contextXray",
531
+ "context-preview-get": "contextXray",
532
+ "context-pin": "contextXray",
533
+ "context-evict": "contextXray",
534
+ "context-restore": "contextXray",
535
+ "context-report": "contextXray",
536
+ "get-localization-preference": "localization",
537
+ "set-localization-preference": "localization",
538
+ // Profile, credentials, and appearance share one switch: an app that hides
539
+ // its profile surface from the agent hides password management with it.
540
+ "get-user-profile": "userProfile",
541
+ "update-user-profile": "userProfile",
542
+ "get-auth-methods": "userProfile",
543
+ "set-password": "userProfile",
544
+ "change-password": "userProfile",
545
+ "change-appearance": "userProfile",
546
+ "list-audit-events": "audit",
547
+ "get-audit-event": "audit",
548
+ "export-audit-events": "audit",
549
+ "create-resource-version": "history",
550
+ "list-resource-versions": "history",
551
+ "get-resource-version": "history",
552
+ "restore-resource-version": "history",
553
+ "list-resource-history": "history",
554
+ "list-review-comments": "review",
555
+ "create-review-comment": "review",
556
+ "reply-review-comment": "review",
557
+ "resolve-review-thread": "review",
558
+ "delete-review-comment": "review",
559
+ "consume-review-feedback": "review",
560
+ "get-review-feedback": "review",
561
+ "set-review-status": "review",
562
+ "send-review-thread-to-agent": "review",
563
+ };
564
+ /**
565
+ * Core actions with no `frameworkTools` switch, and why:
566
+ *
567
+ * - `upload-image` is load-bearing for ordinary work.
568
+ * - The email catalog is mounted everywhere on purpose so Dispatch can ask any
569
+ * app what it sends without that app opting in (see its comment below). It is
570
+ * a read surface, not the `email` group's send capability.
571
+ * - MCP tools and org service tokens are already governed by `disableMcp`.
572
+ */
573
+ export const ALWAYS_ON_CORE_ACTIONS = new Set([
574
+ "upload-image",
575
+ "list-transactional-emails",
576
+ "render-transactional-email-preview",
577
+ "list-email-log",
578
+ "list-email-activity",
579
+ "list-email-engagement",
580
+ "create-org-service-token",
581
+ "list-org-service-tokens",
582
+ "revoke-org-service-token",
583
+ "list-mcp-tools",
584
+ "call-mcp-tool",
585
+ ]);
500
586
  export async function mergeCoreSharingActions(registry) {
501
587
  const entries = [
502
588
  ["share-resource", () => import("../sharing/actions/share-resource.js")],
@@ -732,6 +818,9 @@ export async function mergeCoreSharingActions(registry) {
732
818
  // actions' `toolCallable: false` (audit-H5) is dropped and the
733
819
  // tools-iframe bridge 403 in action-routes.ts never fires.
734
820
  ...preserveActionFlags(def),
821
+ ...(CORE_ACTION_GROUPS[name]
822
+ ? { frameworkGroup: CORE_ACTION_GROUPS[name] }
823
+ : {}),
735
824
  };
736
825
  }
737
826
  }
@@ -117,5 +117,16 @@ export declare function createA2AEngineToolSurface(availableTools: EngineTool[],
117
117
  tools: EngineTool[];
118
118
  availableTools: EngineTool[];
119
119
  };
120
+ /**
121
+ * The first-request tool catalog: an explicit `initialToolNames` verbatim, or
122
+ * the app's OWN actions by default.
123
+ *
124
+ * "Its own actions" excludes the framework kits. They arrive in this same
125
+ * registry through `autoDiscoverActions` -> `mergeCoreSharingActions`, so the
126
+ * plain `Object.keys` default promoted ~45 sharing/review/history/flag schemas
127
+ * into every app's first request whether or not the app had those surfaces. They
128
+ * remain in `availableTools` and are still found by `tool-search`; an app that
129
+ * wants one on turn one names it in `initialToolNames`.
130
+ */
120
131
  export declare function resolveInitialToolNames(templateActions: Record<string, ActionEntry>, configured?: string[]): string[];
121
132
  export {};
@@ -5,6 +5,7 @@ import { resolveMainChatMaxOutputTokens } from "../../agent/engine/output-tokens
5
5
  import { filterInitialEngineTools, resolveAgentRequestReasoningEffort, } from "../../agent/production-agent.js";
6
6
  import { runAgentLoopDirectWithSoftTimeout } from "../../agent/run-loop-with-resume.js";
7
7
  import { resolveRunSoftTimeoutMs } from "../../agent/run-manager.js";
8
+ import { isFrameworkGroupedAction } from "../../framework-tools.js";
8
9
  import { isAuthenticatedReadAction, isAutoReadExcludedActionName, } from "../../mcp/build-server.js";
9
10
  import { withConfiguredAppBasePath } from "../app-base-path.js";
10
11
  // ---------------------------------------------------------------------------
@@ -389,6 +390,21 @@ export function createA2AEngineToolSurface(availableTools, initialToolNames) {
389
390
  availableTools,
390
391
  };
391
392
  }
393
+ /**
394
+ * The first-request tool catalog: an explicit `initialToolNames` verbatim, or
395
+ * the app's OWN actions by default.
396
+ *
397
+ * "Its own actions" excludes the framework kits. They arrive in this same
398
+ * registry through `autoDiscoverActions` -> `mergeCoreSharingActions`, so the
399
+ * plain `Object.keys` default promoted ~45 sharing/review/history/flag schemas
400
+ * into every app's first request whether or not the app had those surfaces. They
401
+ * remain in `availableTools` and are still found by `tool-search`; an app that
402
+ * wants one on turn one names it in `initialToolNames`.
403
+ */
392
404
  export function resolveInitialToolNames(templateActions, configured) {
393
- return configured ?? Object.keys(templateActions);
405
+ if (configured)
406
+ return configured;
407
+ return Object.entries(templateActions)
408
+ .filter(([, entry]) => !isFrameworkGroupedAction(entry))
409
+ .map(([name]) => name);
394
410
  }
@@ -1,4 +1,5 @@
1
1
  import type { ActionEntry } from "../../agent/production-agent.js";
2
+ import type { FrameworkToolGroup } from "../../framework-tools.js";
2
3
  import type { DatabaseToolsOption } from "../../scripts/db/tool-mode.js";
3
4
  import { type PromptExamples } from "../prompts/index.js";
4
5
  import { resolveInitialToolNames } from "./action-filters-a2a.js";
@@ -15,6 +16,7 @@ import { createDataWidgetActionEntries } from "./context-tools.js";
15
16
  export declare function buildFrameworkPrompts(examples?: PromptExamples, options?: {
16
17
  databaseTools?: DatabaseToolsOption;
17
18
  extensionTools?: boolean;
19
+ disabledFrameworkGroups?: ReadonlySet<FrameworkToolGroup>;
18
20
  }): {
19
21
  FRAMEWORK_CORE: string;
20
22
  FRAMEWORK_CORE_COMPACT: string;
@@ -1,6 +1,7 @@
1
1
  import type { ActionEntry } from "../../agent/production-agent.js";
2
2
  import type { AgentLoopFinalResponseGuard } from "../../agent/production-agent.js";
3
3
  import type { AgentChatAttachment, AgentChatReference, MentionProvider } from "../../agent/types.js";
4
+ import type { FrameworkToolsConfig } from "../../framework-tools.js";
4
5
  import type { ExternalAgentPolicy } from "../../mcp/external-agent-policy.js";
5
6
  import type { DatabaseToolsOption } from "../../scripts/db/tool-mode.js";
6
7
  import type { PromptExamples } from "../prompts/index.js";
@@ -236,6 +237,29 @@ export interface AgentChatPluginOptions {
236
237
  * Defaults to `false`.
237
238
  */
238
239
  nativeActionsInDev?: boolean;
240
+ /**
241
+ * Which of the framework's OWN agent tools this app exposes — raw SQL,
242
+ * extensions, sharing, review comments, version history, feature flags,
243
+ * localization, audit, context X-Ray, profile, automations, docs, resources,
244
+ * web, cross-app delegation, chat, email.
245
+ *
246
+ * Every group defaults to today's behavior, so omitting this leaves the tool
247
+ * surface unchanged. `"minimal"` (or `{ preset: "minimal" }`) turns them all
248
+ * off for voice-first and single-purpose apps; an explicit group key wins over
249
+ * the preset.
250
+ *
251
+ * Disabling a group removes it from the AGENT surfaces only — chat, MCP, A2A,
252
+ * background runs. The matching HTTP action routes stay mounted because the UI
253
+ * reaches them through client hooks. Weigh the parity cost first: the
254
+ * framework's contract is that anything the UI can do, the agent can do, so
255
+ * `sharing: false` alongside a visible `ShareButton` is a deliberate break and
256
+ * only makes sense when the app has no such surface.
257
+ *
258
+ * Independent of this option, framework tools are no longer promoted into the
259
+ * first model request by default — they are reachable through `tool-search`,
260
+ * or by naming them in `initialToolNames`.
261
+ */
262
+ frameworkTools?: FrameworkToolsConfig;
239
263
  /**
240
264
  * Expose raw SQL/native database tools to the app agent.
241
265
  *
@@ -244,6 +268,9 @@ export interface AgentChatPluginOptions {
244
268
  * `true`) to expose `db-exec`/`db-patch` for scoped raw SQL maintenance.
245
269
  * Set to `"off"` (also `false`) for chat-first apps that want agents to use
246
270
  * typed actions only.
271
+ *
272
+ * @deprecated Use `frameworkTools: { database: … }`. Still honored for one
273
+ * minor; setting both to conflicting values throws at plugin init.
247
274
  */
248
275
  databaseTools?: DatabaseToolsOption;
249
276
  /**
@@ -252,6 +279,9 @@ export interface AgentChatPluginOptions {
252
279
  * false. Set to true for apps that intentionally let the LLM create or
253
280
  * manage sandboxed extension mini-apps. Core extension routes may still be
254
281
  * mounted for compatibility and app-owned surfaces.
282
+ *
283
+ * @deprecated Use `frameworkTools: { extensions: … }`. Still honored for one
284
+ * minor; setting both to conflicting values throws at plugin init.
255
285
  */
256
286
  extensionTools?: boolean;
257
287
  /**