@agent-native/core 0.157.8 → 0.157.10

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 (154) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +26 -8
  3. package/corpus/templates/analytics/scripts/first-party-analytics-postgres-retention-dry-run.sql +261 -0
  4. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +3 -1
  5. package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +75 -31
  6. package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +4 -1
  7. package/corpus/templates/analytics/server/plugins/db.ts +139 -0
  8. package/corpus/templates/slides/AGENTS.md +14 -10
  9. package/corpus/templates/slides/actions/export-pptx.ts +1311 -121
  10. package/corpus/templates/slides/actions/import-file.ts +28 -1
  11. package/corpus/templates/slides/actions/import-pptx.ts +69 -42
  12. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +222 -29
  13. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +71 -0
  14. package/corpus/templates/slides/app/global.css +19 -1
  15. package/corpus/templates/slides/app/lib/export-google-slides-client.ts +44 -5
  16. package/corpus/templates/slides/app/lib/export-pdf-client.ts +13 -6
  17. package/corpus/templates/slides/app/lib/export-pptx-client.ts +601 -30
  18. package/corpus/templates/slides/app/pages/DeckEditor.tsx +18 -1
  19. package/corpus/templates/slides/server/handlers/import/html-converter.ts +1240 -22
  20. package/corpus/templates/slides/server/handlers/import/pdf-fidelity-parser.ts +329 -64
  21. package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +24 -0
  22. package/corpus/templates/slides/server/lib/source-import.ts +10 -1
  23. package/corpus/templates/slides/shared/aspect-ratios.ts +13 -1
  24. package/dist/agent/harness/migrations.d.ts +4 -0
  25. package/dist/agent/harness/migrations.js +60 -0
  26. package/dist/agent/production-agent.d.ts +2 -0
  27. package/dist/agent/production-agent.js +15 -0
  28. package/dist/agent/run-loop-with-resume.d.ts +1 -0
  29. package/dist/agent/run-loop-with-resume.js +44 -12
  30. package/dist/agent/run-migrations.d.ts +8 -0
  31. package/dist/agent/run-migrations.js +61 -0
  32. package/dist/automations/service.d.ts +6 -0
  33. package/dist/automations/service.js +35 -0
  34. package/dist/chat-threads/migrations.d.ts +1 -0
  35. package/dist/chat-threads/migrations.js +1 -0
  36. package/dist/chat-threads/schema-migrations.d.ts +8 -0
  37. package/dist/chat-threads/schema-migrations.js +60 -0
  38. package/dist/cli/code-agent-connector.d.ts +4 -1
  39. package/dist/cli/code-agent-connector.js +154 -23
  40. package/dist/cli/code-agent-executor.js +255 -13
  41. package/dist/cli/code-agent-runs.d.ts +1 -0
  42. package/dist/cli/code-agent-runs.js +2 -1
  43. package/dist/cli/portal-workspace.d.ts +49 -0
  44. package/dist/cli/portal-workspace.js +320 -0
  45. package/dist/client/AssistantChat.d.ts +1 -1
  46. package/dist/client/AssistantChat.js +43 -61
  47. package/dist/client/ConnectBuilderCard.js +33 -5
  48. package/dist/client/agent-chat-adapter.js +4 -0
  49. package/dist/client/analytics-platform.d.ts +2 -0
  50. package/dist/client/analytics-platform.js +12 -0
  51. package/dist/client/analytics.d.ts +3 -0
  52. package/dist/client/analytics.js +10 -1
  53. package/dist/client/chat/index.d.ts +1 -0
  54. package/dist/client/chat/index.js +1 -0
  55. package/dist/client/chat/message-components.d.ts +2 -0
  56. package/dist/client/chat/message-components.js +11 -1
  57. package/dist/client/chat/run-recovery.d.ts +2 -1
  58. package/dist/client/chat/run-recovery.js +2 -2
  59. package/dist/client/chat-first/apps-rail.d.ts +1 -1
  60. package/dist/client/chat-first/apps-rail.js +11 -11
  61. package/dist/client/chat-first/surface-tabs.d.ts +1 -1
  62. package/dist/client/chat-first/surface-tabs.js +38 -36
  63. package/dist/client/chat-first/types.d.ts +5 -0
  64. package/dist/client/chat-first.d.ts +1 -1
  65. package/dist/client/chat-first.js +4 -4
  66. package/dist/client/desktop-local-code-change.d.ts +10 -0
  67. package/dist/client/desktop-local-code-change.js +16 -0
  68. package/dist/client/index.d.ts +1 -0
  69. package/dist/client/index.js +1 -0
  70. package/dist/client/observability/ThumbsFeedback.js +53 -26
  71. package/dist/client/observability/useObservability.d.ts +1 -1
  72. package/dist/client/observability/useObservability.js +6 -3
  73. package/dist/client/terminal/AgentTerminal.d.ts +9 -1
  74. package/dist/client/terminal/AgentTerminal.js +38 -3
  75. package/dist/client/terminal/index.d.ts +1 -1
  76. package/dist/client/terminal/index.js +1 -1
  77. package/dist/client/track.js +9 -1
  78. package/dist/client/use-action.js +3 -0
  79. package/dist/collab/awareness.d.ts +2 -2
  80. package/dist/deploy/build.js +1 -1
  81. package/dist/feature-flags/a2a-action-route.js +4 -2
  82. package/dist/feature-flags/permissions.d.ts +2 -0
  83. package/dist/feature-flags/permissions.js +6 -1
  84. package/dist/ingestion/pptx.d.ts +92 -1
  85. package/dist/ingestion/pptx.js +1180 -115
  86. package/dist/integrations/index.d.ts +3 -3
  87. package/dist/integrations/index.js +2 -2
  88. package/dist/integrations/plugin.js +95 -6
  89. package/dist/integrations/remote-commands-store.d.ts +5 -0
  90. package/dist/integrations/remote-commands-store.js +63 -22
  91. package/dist/integrations/remote-devices-store.d.ts +2 -1
  92. package/dist/integrations/remote-devices-store.js +46 -0
  93. package/dist/integrations/remote-types.d.ts +20 -0
  94. package/dist/jobs/actions/list-recurring-jobs.d.ts +3 -0
  95. package/dist/jobs/actions/list-recurring-jobs.js +5 -1
  96. package/dist/jobs/frontmatter.d.ts +16 -0
  97. package/dist/jobs/frontmatter.js +53 -0
  98. package/dist/jobs/remote-execution.d.ts +42 -0
  99. package/dist/jobs/remote-execution.js +287 -0
  100. package/dist/jobs/scheduler.js +102 -3
  101. package/dist/jobs/tools.js +50 -3
  102. package/dist/localization/core-messages/ar-SA.js +4 -0
  103. package/dist/localization/core-messages/de-DE.js +4 -0
  104. package/dist/localization/core-messages/en-US.d.ts +4 -0
  105. package/dist/localization/core-messages/en-US.js +4 -0
  106. package/dist/localization/core-messages/es-ES.js +4 -0
  107. package/dist/localization/core-messages/fr-FR.js +4 -0
  108. package/dist/localization/core-messages/hi-IN.js +4 -0
  109. package/dist/localization/core-messages/ja-JP.js +4 -0
  110. package/dist/localization/core-messages/ko-KR.js +4 -0
  111. package/dist/localization/core-messages/pt-BR.js +4 -0
  112. package/dist/localization/core-messages/zh-CN.js +4 -0
  113. package/dist/localization/core-messages/zh-TW.js +4 -0
  114. package/dist/localization/core-messages.d.ts +4 -0
  115. package/dist/notifications/routes.d.ts +3 -3
  116. package/dist/observability/feedback.js +40 -16
  117. package/dist/observability/routes.d.ts +6 -6
  118. package/dist/observability/routes.js +15 -3
  119. package/dist/observability/store.js +2 -0
  120. package/dist/observability/traces.js +5 -1
  121. package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
  122. package/dist/provider-api/actions/provider-api.d.ts +13 -13
  123. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  124. package/dist/resources/handlers.d.ts +1 -1
  125. package/dist/secrets/routes.d.ts +9 -9
  126. package/dist/server/action-routes.d.ts +7 -5
  127. package/dist/server/action-routes.js +13 -6
  128. package/dist/server/agent-chat-plugin.js +6 -0
  129. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  130. package/dist/server/agent-run-context.d.ts +1 -0
  131. package/dist/server/agent-run-context.js +9 -0
  132. package/dist/server/better-auth-instance.js +4 -0
  133. package/dist/server/core-routes-plugin.js +8 -1
  134. package/dist/server/realtime-voice.js +2 -1
  135. package/dist/server/release-migrations.js +16 -0
  136. package/dist/server/request-context.d.ts +2 -0
  137. package/dist/server/transcribe-voice.d.ts +1 -1
  138. package/dist/shared/analytics-platform.d.ts +6 -0
  139. package/dist/shared/analytics-platform.js +14 -0
  140. package/dist/shared/mcp-embed-headers.d.ts +1 -1
  141. package/dist/shared/mcp-embed-headers.js +1 -1
  142. package/dist/styles/agent-native.css +83 -103
  143. package/dist/terminal/cli-registry.js +5 -0
  144. package/dist/tracking/registry.js +9 -1
  145. package/dist/triggers/actions/list-automations.d.ts +3 -0
  146. package/dist/triggers/actions/list-automations.js +3 -0
  147. package/dist/triggers/actions/manage-automation.d.ts +9 -0
  148. package/dist/triggers/actions/manage-automation.js +14 -2
  149. package/dist/triggers/actions.js +82 -7
  150. package/dist/usage/migrations.d.ts +4 -0
  151. package/dist/usage/migrations.js +45 -0
  152. package/docs/content/template-content-developers.mdx +48 -0
  153. package/docs/content/toolkit-ui.mdx +57 -0
  154. package/package.json +3 -3
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import { defineAutomation, deleteAutomation, listAutomationDefinitions, updateAutomation, } from "../automations/service.js";
12
12
  import { listEvents } from "../event-bus/index.js";
13
+ import { getRemoteExecutionCapabilities, listRemoteDevicesForOwner, } from "../integrations/remote-devices-store.js";
13
14
  import { describeCron, effectiveTimezone } from "../jobs/cron.js";
14
15
  import { queueAutomationRunNow } from "../jobs/run-now.js";
15
16
  import { getIntegrationRequestContext, getRequestOrgId, } from "../server/request-context.js";
@@ -41,6 +42,27 @@ async function handleListEvents() {
41
42
  });
42
43
  return lines.join("\n");
43
44
  }
45
+ async function handleListHosts(getCurrentUser) {
46
+ const devices = await listRemoteDevicesForOwner({
47
+ ownerEmail: getCurrentUser(),
48
+ orgId: getRequestOrgId(),
49
+ status: "active",
50
+ limit: 50,
51
+ });
52
+ const now = Date.now();
53
+ return JSON.stringify(devices.map((device) => ({
54
+ id: device.id,
55
+ name: device.label,
56
+ platform: device.platform,
57
+ hostName: device.hostName,
58
+ status: device.status,
59
+ online: device.lastSeenAt !== null && now - device.lastSeenAt <= 90_000,
60
+ lastSeenAt: device.lastSeenAt
61
+ ? new Date(device.lastSeenAt).toISOString()
62
+ : null,
63
+ executionCapabilities: getRemoteExecutionCapabilities(device),
64
+ })), null, 2);
65
+ }
44
66
  async function handleList(args, getCurrentUser, appId) {
45
67
  const scope = automationScope(args.scope);
46
68
  const definitions = await listAutomationDefinitions({ userEmail: getCurrentUser(), orgId: getRequestOrgId(), appId }, scope);
@@ -69,6 +91,9 @@ async function handleList(args, getCurrentUser, appId) {
69
91
  createdBy: meta.createdBy ?? null,
70
92
  runAs: meta.runAs ?? null,
71
93
  model: meta.model ?? null,
94
+ executionHostId: meta.executionHostId ?? null,
95
+ executionEngine: meta.executionEngine ?? null,
96
+ executionCwd: meta.executionCwd ?? null,
72
97
  mcpTools: meta.mcpTools ?? [],
73
98
  originScopeId: meta.originScopeId ?? null,
74
99
  deliveryPlatform: meta.deliveryPlatform ?? null,
@@ -118,6 +143,15 @@ async function handleDefine(args, getCurrentUser, appId) {
118
143
  ? args.delegated_policy_id
119
144
  : undefined,
120
145
  model: typeof args.model === "string" ? args.model : undefined,
146
+ executionHostId: typeof args.execution_host_id === "string"
147
+ ? args.execution_host_id
148
+ : undefined,
149
+ executionEngine: typeof args.execution_engine === "string"
150
+ ? args.execution_engine
151
+ : undefined,
152
+ executionCwd: typeof args.execution_cwd === "string"
153
+ ? args.execution_cwd
154
+ : undefined,
121
155
  mcpTools: args.mcpTools,
122
156
  delivery: integration
123
157
  ? {
@@ -147,6 +181,9 @@ async function handleDefine(args, getCurrentUser, appId) {
147
181
  createdBy: definition.meta.createdBy,
148
182
  runAs: definition.meta.runAs,
149
183
  model: definition.meta.model ?? null,
184
+ executionHostId: definition.meta.executionHostId ?? null,
185
+ executionEngine: definition.meta.executionEngine ?? null,
186
+ executionCwd: definition.meta.executionCwd ?? null,
150
187
  mcpTools: definition.meta.mcpTools ?? [],
151
188
  originScopeId: definition.meta.originScopeId ?? null,
152
189
  deliveryPlatform: definition.meta.deliveryPlatform ?? null,
@@ -185,6 +222,21 @@ async function handleUpdate(args, getCurrentUser, appId) {
185
222
  : typeof args.model === "string"
186
223
  ? args.model
187
224
  : null,
225
+ executionHostId: args.execution_host_id === undefined
226
+ ? undefined
227
+ : typeof args.execution_host_id === "string"
228
+ ? args.execution_host_id
229
+ : null,
230
+ executionEngine: args.execution_engine === undefined
231
+ ? undefined
232
+ : typeof args.execution_engine === "string"
233
+ ? args.execution_engine
234
+ : null,
235
+ executionCwd: args.execution_cwd === undefined
236
+ ? undefined
237
+ : typeof args.execution_cwd === "string"
238
+ ? args.execution_cwd
239
+ : null,
188
240
  mcpTools: args.mcpTools,
189
241
  });
190
242
  await refreshEventSubscriptions();
@@ -200,6 +252,9 @@ async function handleUpdate(args, getCurrentUser, appId) {
200
252
  createdBy: definition.meta.createdBy,
201
253
  runAs: definition.meta.runAs,
202
254
  model: definition.meta.model ?? null,
255
+ executionHostId: definition.meta.executionHostId ?? null,
256
+ executionEngine: definition.meta.executionEngine ?? null,
257
+ executionCwd: definition.meta.executionCwd ?? null,
203
258
  mcpTools: definition.meta.mcpTools ?? [],
204
259
  originScopeId: definition.meta.originScopeId ?? null,
205
260
  deliveryPlatform: definition.meta.deliveryPlatform ?? null,
@@ -264,6 +319,7 @@ async function handleRunNow(args, getCurrentUser, appId, context) {
264
319
  /* ------------------------------------------------------------------ */
265
320
  const VALID_ACTIONS = [
266
321
  "list-events",
322
+ "list-hosts",
267
323
  "list",
268
324
  "define",
269
325
  "update",
@@ -278,9 +334,10 @@ export function createAutomationToolEntries(getCurrentUser, appId) {
278
334
  description: `Manage automations (event-triggered and scheduled tasks). Use the "action" parameter to choose an operation:
279
335
 
280
336
  - **list-events**: List all registered event types that automations can subscribe to. Returns event names, descriptions, and payload schemas. Call this BEFORE defining an automation to discover available events.
281
- - **list**: List all automations (triggers). Shows trigger, status, model, MCP allowlist, and delivery metadata. Optional params: scope, domain, enabled_only.
282
- - **define**: Create a new automation. IMPORTANT: Always confirm with the user before calling — show them a summary of what will be created. Required params: name, trigger_type, body. Optional: scope, event, schedule, timezone, condition, mode, domain, delegated_policy_id, model, mcpTools. A scheduled automation with no schedule defaults to once per hour; use an event trigger when it should run only when something changes.
283
- - **update**: Update an existing automation's settings without changing its creator (enabled, schedule, timezone, condition, body, policy, model, MCP allowlist). Required param: name. Use the same scope it was created in.
337
+ - **list-hosts**: List paired execution hosts and their non-secret capabilities. Call this before assigning execution_host_id.
338
+ - **list**: List all automations (triggers). Shows trigger, status, model, execution host, MCP allowlist, and delivery metadata. Optional params: scope, domain, enabled_only.
339
+ - **define**: Create a new automation. IMPORTANT: Always confirm with the user before calling — show them a summary of what will be created. Required params: name, trigger_type, body. Optional: scope, event, schedule, timezone, condition, mode, domain, delegated_policy_id, model, execution_host_id, execution_engine, execution_cwd, mcpTools. A scheduled automation with no schedule defaults to once per hour; use an event trigger when it should run only when something changes. Host-targeted automations queue code-agent work on that host and do not silently fall back to this server.
340
+ - **update**: Update an existing automation's settings without changing its creator (enabled, schedule, timezone, condition, body, policy, model, execution host, MCP allowlist). Required param: name. Use the same scope it was created in.
284
341
  - **delete**: Delete an automation. Always confirm with the user first. Required param: name.
285
342
  - **fire-test**: Fire a test event to validate automations. Emits a test.event.fired event. Optional param: data (JSON string).
286
343
  - **run-now**: Run one automation immediately using its real actions and side effects. This is an explicit user-authorized run and returns a durable run id; it does not change the automation's next scheduled run. Required params: name; optional scope.`,
@@ -289,7 +346,7 @@ export function createAutomationToolEntries(getCurrentUser, appId) {
289
346
  properties: {
290
347
  action: {
291
348
  type: "string",
292
- description: "The operation to perform: list-events, list, define, update, delete, fire-test, or run-now.",
349
+ description: "The operation to perform: list-events, list-hosts, list, define, update, delete, fire-test, or run-now.",
293
350
  enum: [...VALID_ACTIONS],
294
351
  },
295
352
  name: {
@@ -335,6 +392,18 @@ export function createAutomationToolEntries(getCurrentUser, appId) {
335
392
  type: "string",
336
393
  description: "Optional model id for this automation. The default model is used when omitted.",
337
394
  },
395
+ execution_host_id: {
396
+ type: "string",
397
+ description: "Optional exact paired host id for scheduled code-agent execution. Call list-hosts first; a selected host is never silently replaced by another host.",
398
+ },
399
+ execution_engine: {
400
+ type: "string",
401
+ description: "Optional host engine id, such as codex-cli or claude-cli. It must be advertised by the selected host when host capabilities include an engine list.",
402
+ },
403
+ execution_cwd: {
404
+ type: "string",
405
+ description: "Optional workspace path on the execution host. Use the host connector's configured workspace when omitted.",
406
+ },
338
407
  mcpTools: {
339
408
  type: "array",
340
409
  items: { type: "string" },
@@ -365,17 +434,23 @@ export function createAutomationToolEntries(getCurrentUser, appId) {
365
434
  },
366
435
  },
367
436
  planMode: {
368
- effect: (args) => args.action === "list" || args.action === "list-events"
437
+ effect: (args) => args.action === "list" ||
438
+ args.action === "list-events" ||
439
+ args.action === "list-hosts"
369
440
  ? "read"
370
441
  : "write",
371
- allowedValues: { action: ["list-events", "list"] },
372
- description: "Plan mode allows listing automations and event types.",
442
+ allowedValues: {
443
+ action: ["list-events", "list-hosts", "list"],
444
+ },
445
+ description: "Plan mode allows listing automations, execution hosts, and event types.",
373
446
  },
374
447
  run: async (args, context) => {
375
448
  const action = args.action;
376
449
  switch (action) {
377
450
  case "list-events":
378
451
  return handleListEvents();
452
+ case "list-hosts":
453
+ return handleListHosts(getCurrentUser);
379
454
  case "list":
380
455
  return handleList(args, getCurrentUser, appId);
381
456
  case "define":
@@ -0,0 +1,4 @@
1
+ import type { MigrationEntry } from "../db/migrations.js";
2
+ export declare const USAGE_ALERT_MIGRATIONS_TABLE = "_usage_alert_migrations";
3
+ /** Authoritative release-time schema for usage alert rules and events. */
4
+ export declare const USAGE_ALERT_MIGRATIONS: MigrationEntry[];
@@ -0,0 +1,45 @@
1
+ export const USAGE_ALERT_MIGRATIONS_TABLE = "_usage_alert_migrations";
2
+ /** Authoritative release-time schema for usage alert rules and events. */
3
+ export const USAGE_ALERT_MIGRATIONS = [
4
+ {
5
+ version: 1,
6
+ name: "usage-alert-rules-and-events-tables",
7
+ sql: `
8
+ CREATE TABLE IF NOT EXISTS usage_alert_rules (
9
+ id TEXT PRIMARY KEY,
10
+ scope TEXT NOT NULL,
11
+ owner_email TEXT NOT NULL,
12
+ org_id TEXT,
13
+ app_id TEXT,
14
+ unit TEXT NOT NULL,
15
+ period TEXT NOT NULL,
16
+ limit_value INTEGER NOT NULL,
17
+ channels TEXT NOT NULL,
18
+ enabled INTEGER NOT NULL DEFAULT 1,
19
+ dismissed_window_start INTEGER,
20
+ created_at INTEGER NOT NULL,
21
+ updated_at INTEGER NOT NULL
22
+ );
23
+ CREATE TABLE IF NOT EXISTS usage_alert_events (
24
+ id TEXT PRIMARY KEY,
25
+ rule_id TEXT NOT NULL,
26
+ window_start INTEGER NOT NULL,
27
+ created_at INTEGER NOT NULL
28
+ );
29
+ CREATE INDEX IF NOT EXISTS idx_usage_alert_rules_owner
30
+ ON usage_alert_rules (owner_email, org_id, scope);
31
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_usage_alert_events_rule_window
32
+ ON usage_alert_events (rule_id, window_start)
33
+ `,
34
+ },
35
+ {
36
+ version: 2,
37
+ name: "usage-alert-default-column",
38
+ sql: `ALTER TABLE usage_alert_rules ADD COLUMN IF NOT EXISTS is_default INTEGER NOT NULL DEFAULT 0`,
39
+ },
40
+ {
41
+ version: 3,
42
+ name: "usage-alert-notification-column",
43
+ sql: "ALTER TABLE usage_alert_events ADD COLUMN IF NOT EXISTS notification_id TEXT",
44
+ },
45
+ ];
@@ -312,6 +312,51 @@ Every operation is a TypeScript file in `templates/content/actions/`, auto-mount
312
312
 
313
313
  ## Customizing it
314
314
 
315
+ ### Data grid boundary {#data-grid}
316
+
317
+ Content's database table view composes the reusable `DataGrid` component from
318
+ `@agent-native/toolkit/data-grid`. The adapter is
319
+ `app/components/editor/database/DatabaseView.tsx`.
320
+
321
+ Toolkit supplies the shared spreadsheet mechanics: keyboard navigation,
322
+ active-cell behavior, the scroll surface, and the optional selection and column
323
+ width callbacks. Content supplies `ContentDatabaseItem` rows and typed
324
+ columns, then keeps database-specific property rendering, grouping, filters,
325
+ row drag and drop, previews, access checks, and action-backed mutations in the
326
+ app.
327
+
328
+ The table preserves its existing Content surface through the grid's custom
329
+ slots and scroll-container props:
330
+
331
+ ```tsx filename="app/components/editor/database/DatabaseView.tsx"
332
+ import { DataGrid, type DataGridColumn } from "@agent-native/toolkit/data-grid";
333
+ import type { ContentDatabaseItem } from "@shared/api";
334
+
335
+ const dataGridColumns: readonly DataGridColumn<ContentDatabaseItem>[] = [
336
+ // Content maps its name, property, and action columns here.
337
+ ];
338
+
339
+ <DataGrid
340
+ rows={items}
341
+ columns={dataGridColumns}
342
+ getRowId={(item) => item.id}
343
+ columnWidths={columnWidths}
344
+ contentClassName="min-w-[720px]"
345
+ scrollContainerProps={{
346
+ "data-database-scroll-surface": "table",
347
+ tabIndex: 0,
348
+ }}
349
+ />;
350
+ ```
351
+
352
+ The live implementation also supplies Content's custom `renderHeader` and
353
+ `renderBody` callbacks around this shell.
354
+
355
+ Do not move Content database models, access checks, grouping, drag and drop,
356
+ or domain actions into Toolkit. If a change is reusable spreadsheet behavior,
357
+ extend the Toolkit contract first. If it describes how Content rows behave,
358
+ keep it in the app adapter and its actions.
359
+
315
360
  <AnnotatedCode
316
361
  id="doc-block-content10"
317
362
  title="A soft-delete action reusing shared trash logic"
@@ -343,6 +388,9 @@ The places to look when changing behavior:
343
388
 
344
389
  - **`actions/`** — every operation the agent or UI can perform. Add a new file like `actions/publish-to-wordpress.ts` using `defineAction` and both sides get it for free.
345
390
  - **`app/routes/`** — the page surface described above.
391
+ - **`app/components/editor/database/DatabaseView.tsx`** — the Content database
392
+ table adapter. It composes `@agent-native/toolkit/data-grid` while keeping
393
+ database-specific rendering and actions local.
346
394
  - **`app/components/editor/`** — the Tiptap editor. Add a new node type under `extensions/` and register it in `DocumentEditor.tsx`. The bubble toolbar, slash menu, and hover previews are all component files you can edit.
347
395
  - **`.agents/skills/`** — guidance the agent reads before acting: `content`, `document-editing`, `notion-integration`, `creative-context`, plus the framework skills. Add a new skill folder when you add a capability big enough to need its own guidance.
348
396
  - **`AGENTS.md`** — the top-level agent guide with the action cheatsheet. Update it whenever you add a feature so the agent discovers it without exploring.
@@ -121,6 +121,63 @@ open state rather than shadcn variant names. When both APIs provide the button,
121
121
  falls back to Toolkit’s default adapter without disabling the rest of the
122
122
  registered system.
123
123
 
124
+ ## Data grid kit {#data-grid}
125
+
126
+ `@agent-native/toolkit/data-grid` provides a Core-free, spreadsheet-like grid
127
+ surface. The app supplies rows, typed columns, editor slots, selection state,
128
+ and persistence callbacks. The kit provides keyboard navigation, active-cell
129
+ behavior, optional selection, column sizing, and the scroll surface.
130
+
131
+ The grid does not fetch data, call actions, resolve credentials, or persist
132
+ edits. Use `renderHeader`, `renderBody`, `renderRow`, and `renderFooter` when an
133
+ app needs to keep its own headers, grouping, row actions, or summary rows.
134
+
135
+ | Export | Purpose |
136
+ | ---------------------------- | ---------------------------------------------------------------------- |
137
+ | `<DataGrid>` | Render rows and columns with shared grid mechanics. |
138
+ | `DataGridColumn<Row>` | Describe a typed column, including values, widths, cells, and editors. |
139
+ | `clampDataGridColumnWidth()` | Clamp an app-owned width to a column's configured bounds. |
140
+ | `dataGridColumnTemplate()` | Build the shared CSS grid template for custom slots. |
141
+
142
+ The smallest adapter only supplies rows, columns, and stable row IDs:
143
+
144
+ ```tsx
145
+ import { DataGrid, type DataGridColumn } from "@agent-native/toolkit/data-grid";
146
+
147
+ type Row = { id: string; title: string };
148
+
149
+ const columns: readonly DataGridColumn<Row>[] = [
150
+ {
151
+ id: "title",
152
+ label: "Title",
153
+ getValue: (row) => row.title,
154
+ },
155
+ ];
156
+
157
+ <DataGrid rows={rows} columns={columns} getRowId={(row) => row.id} />;
158
+ ```
159
+
160
+ Make selection and column widths controlled when the app needs to save them in
161
+ its own state or database view preferences:
162
+
163
+ ```tsx
164
+ <DataGrid
165
+ rows={rows}
166
+ columns={columns}
167
+ getRowId={(row) => row.id}
168
+ selection="multiple"
169
+ selectedRowIds={selectedRowIds}
170
+ onSelectedRowIdsChange={setSelectedRowIds}
171
+ columnWidths={columnWidths}
172
+ onColumnWidthsChange={setColumnWidths}
173
+ />
174
+ ```
175
+
176
+ Content uses this surface in its database table view. `DatabaseView.tsx` keeps
177
+ Content-specific property rendering, grouping, row drag and drop, selection
178
+ actions, and row previews in the app while the Toolkit component supplies the
179
+ shared grid mechanics. Use the [Content Developer Guide](/docs/template-content-developers#data-grid) when changing that adapter.
180
+
124
181
  ## Shell hooks {#shell-hooks}
125
182
 
126
183
  Toolkit includes small shell helpers and hooks that are useful across apps:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.157.8",
3
+ "version": "0.157.10",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -385,7 +385,7 @@
385
385
  "@tanstack/react-table": "^8.21.3",
386
386
  "@uiw/react-codemirror": "^4.25.10",
387
387
  "ajv": "^8.20.0",
388
- "better-auth": "1.6.16",
388
+ "better-auth": "1.6.28",
389
389
  "better-sqlite3": "^12.8.0",
390
390
  "botframework-connector": "^4.23.3",
391
391
  "clsx": "^2.1.1",
@@ -426,7 +426,7 @@
426
426
  "yjs": "^13.6.31",
427
427
  "zod": "^4.3.6",
428
428
  "@agent-native/recap-cli": "0.5.4",
429
- "@agent-native/toolkit": "^0.16.1"
429
+ "@agent-native/toolkit": "^0.16.3"
430
430
  },
431
431
  "devDependencies": {
432
432
  "@ai-sdk/anthropic": "^3.0.71",