@agent-native/core 0.157.9 → 0.157.11

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 (114) hide show
  1. package/corpus/templates/analytics/scripts/first-party-analytics-postgres-retention-dry-run.sql +5 -2
  2. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +3 -1
  3. package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +18 -6
  4. package/corpus/templates/analytics/server/plugins/db.ts +139 -0
  5. package/corpus/templates/slides/AGENTS.md +14 -10
  6. package/corpus/templates/slides/actions/export-pptx.ts +1215 -94
  7. package/corpus/templates/slides/actions/import-file.ts +16 -1
  8. package/corpus/templates/slides/actions/import-pptx.ts +61 -43
  9. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +222 -29
  10. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +71 -0
  11. package/corpus/templates/slides/app/global.css +19 -1
  12. package/corpus/templates/slides/app/lib/export-google-slides-client.ts +44 -5
  13. package/corpus/templates/slides/app/lib/export-pdf-client.ts +13 -6
  14. package/corpus/templates/slides/app/lib/export-pptx-client.ts +556 -25
  15. package/corpus/templates/slides/app/pages/DeckEditor.tsx +18 -1
  16. package/corpus/templates/slides/server/handlers/import/html-converter.ts +1176 -26
  17. package/corpus/templates/slides/server/handlers/import/pdf-fidelity-parser.ts +13 -0
  18. package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +24 -0
  19. package/corpus/templates/slides/server/routes/api/exports/google-slides.post.ts +12 -4
  20. package/corpus/templates/slides/shared/aspect-ratios.ts +13 -1
  21. package/dist/agent/harness/migrations.js +24 -3
  22. package/dist/agent/production-agent.js +11 -0
  23. package/dist/agent/run-loop-with-resume.js +21 -4
  24. package/dist/automations/service.d.ts +6 -0
  25. package/dist/automations/service.js +35 -0
  26. package/dist/cli/code-agent-connector.d.ts +4 -1
  27. package/dist/cli/code-agent-connector.js +154 -23
  28. package/dist/cli/code-agent-executor.js +255 -13
  29. package/dist/cli/code-agent-runs.d.ts +1 -0
  30. package/dist/cli/code-agent-runs.js +2 -1
  31. package/dist/cli/portal-workspace.d.ts +49 -0
  32. package/dist/cli/portal-workspace.js +320 -0
  33. package/dist/client/AssistantChat.d.ts +1 -1
  34. package/dist/client/AssistantChat.js +39 -61
  35. package/dist/client/ConnectBuilderCard.js +33 -5
  36. package/dist/client/agent-chat-adapter.js +4 -0
  37. package/dist/client/analytics-platform.d.ts +2 -0
  38. package/dist/client/analytics-platform.js +12 -0
  39. package/dist/client/analytics.d.ts +3 -0
  40. package/dist/client/analytics.js +10 -1
  41. package/dist/client/chat/index.d.ts +1 -0
  42. package/dist/client/chat/index.js +1 -0
  43. package/dist/client/chat/run-recovery.d.ts +2 -1
  44. package/dist/client/chat/run-recovery.js +2 -2
  45. package/dist/client/chat-first/apps-rail.d.ts +1 -1
  46. package/dist/client/chat-first/apps-rail.js +11 -11
  47. package/dist/client/chat-first/surface-tabs.d.ts +1 -1
  48. package/dist/client/chat-first/surface-tabs.js +38 -36
  49. package/dist/client/chat-first/types.d.ts +5 -0
  50. package/dist/client/chat-first.d.ts +1 -1
  51. package/dist/client/chat-first.js +4 -4
  52. package/dist/client/desktop-local-code-change.d.ts +10 -0
  53. package/dist/client/desktop-local-code-change.js +16 -0
  54. package/dist/client/index.d.ts +1 -0
  55. package/dist/client/index.js +1 -0
  56. package/dist/client/observability/ThumbsFeedback.js +21 -7
  57. package/dist/client/terminal/AgentTerminal.d.ts +9 -1
  58. package/dist/client/terminal/AgentTerminal.js +38 -3
  59. package/dist/client/terminal/index.d.ts +1 -1
  60. package/dist/client/terminal/index.js +1 -1
  61. package/dist/client/track.js +9 -1
  62. package/dist/client/use-action.js +3 -0
  63. package/dist/collab/awareness.d.ts +2 -2
  64. package/dist/collab/struct-routes.d.ts +1 -1
  65. package/dist/db/client.js +1 -0
  66. package/dist/deploy/build.js +1 -1
  67. package/dist/ingestion/pptx.d.ts +78 -0
  68. package/dist/ingestion/pptx.js +991 -107
  69. package/dist/integrations/index.d.ts +3 -3
  70. package/dist/integrations/index.js +2 -2
  71. package/dist/integrations/plugin.js +95 -6
  72. package/dist/integrations/remote-commands-store.d.ts +5 -0
  73. package/dist/integrations/remote-commands-store.js +63 -22
  74. package/dist/integrations/remote-devices-store.d.ts +2 -1
  75. package/dist/integrations/remote-devices-store.js +46 -0
  76. package/dist/integrations/remote-types.d.ts +20 -0
  77. package/dist/jobs/actions/list-recurring-jobs.d.ts +3 -0
  78. package/dist/jobs/actions/list-recurring-jobs.js +5 -1
  79. package/dist/jobs/frontmatter.d.ts +16 -0
  80. package/dist/jobs/frontmatter.js +53 -0
  81. package/dist/jobs/remote-execution.d.ts +42 -0
  82. package/dist/jobs/remote-execution.js +287 -0
  83. package/dist/jobs/scheduler.js +102 -3
  84. package/dist/jobs/tools.js +50 -3
  85. package/dist/notifications/routes.d.ts +4 -4
  86. package/dist/observability/routes.d.ts +5 -5
  87. package/dist/provider-api/actions/custom-provider-registration.d.ts +9 -9
  88. package/dist/provider-api/actions/provider-api.d.ts +14 -14
  89. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  90. package/dist/resources/handlers.d.ts +1 -1
  91. package/dist/secrets/routes.d.ts +9 -9
  92. package/dist/server/action-routes.js +4 -2
  93. package/dist/server/agent-chat-plugin.js +6 -0
  94. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  95. package/dist/server/agent-run-context.d.ts +1 -0
  96. package/dist/server/agent-run-context.js +9 -0
  97. package/dist/server/core-routes-plugin.js +8 -1
  98. package/dist/server/request-context.d.ts +2 -0
  99. package/dist/server/transcribe-voice.d.ts +1 -1
  100. package/dist/shared/analytics-platform.d.ts +6 -0
  101. package/dist/shared/analytics-platform.js +14 -0
  102. package/dist/shared/mcp-embed-headers.d.ts +1 -1
  103. package/dist/shared/mcp-embed-headers.js +1 -1
  104. package/dist/styles/agent-native.css +83 -103
  105. package/dist/terminal/cli-registry.js +5 -0
  106. package/dist/tracking/registry.js +9 -1
  107. package/dist/triggers/actions/list-automations.d.ts +3 -0
  108. package/dist/triggers/actions/list-automations.js +3 -0
  109. package/dist/triggers/actions/manage-automation.d.ts +9 -0
  110. package/dist/triggers/actions/manage-automation.js +14 -2
  111. package/dist/triggers/actions.js +82 -7
  112. package/docs/content/template-content-developers.mdx +48 -0
  113. package/docs/content/toolkit-ui.mdx +57 -0
  114. package/package.json +2 -2
@@ -10,11 +10,14 @@
10
10
  -- never included in the candidate count. Session replay, exception issues,
11
11
  -- public-key metadata, rollups, alerts, and pressure data are reported as
12
12
  -- preserved SQL rows; they are not deletion candidates.
13
+ -- The organization and owner values below are intentionally fake safe
14
+ -- defaults. Supply scoped values in a local copy or SQL-client parameters;
15
+ -- never commit real organization IDs or employee addresses here.
13
16
 
14
17
  WITH params AS (
15
18
  SELECT
16
- 'PlRt3bfcpJNnOyF_Wfgsh'::text AS org_id,
17
- 'steve@builder.io'::text AS owner_email,
19
+ 'org-example'::text AS org_id,
20
+ 'owner@example.com'::text AS owner_email,
18
21
  '2026-06-10T18:50:43.370Z'::text AS lookback_start,
19
22
  '2026-08-09T19:11:44.834Z'::text AS cutoff,
20
23
  'http.response'::text AS excluded_event_name
@@ -1130,7 +1130,9 @@ export async function getFirstPartyAnalyticsBigQueryMetrics(
1130
1130
  WITH scoped_events AS (
1131
1131
  SELECT *
1132
1132
  FROM \`${physical.events}\`
1133
- WHERE ${tenantFilter}${startDateFilter} AND event_date <= ${today}
1133
+ WHERE ${tenantFilter}${startDateFilter}
1134
+ AND event_name IS DISTINCT FROM 'http.response'
1135
+ AND event_date <= ${today}
1134
1136
  )
1135
1137
  SELECT
1136
1138
  COUNT(*) AS event_count,
@@ -1,5 +1,5 @@
1
1
  import { getDbExec } from "@agent-native/core/db";
2
- import { and, eq, gte, isNull, or } from "drizzle-orm";
2
+ import { and, eq, gte, isNull, ne, or } from "drizzle-orm";
3
3
 
4
4
  import { getDb, schema } from "../db/index.js";
5
5
 
@@ -67,6 +67,10 @@ async function countScopedRows(
67
67
  const args: unknown[] = includeLegacyOwnerRows
68
68
  ? [scope.orgId, scope.userEmail]
69
69
  : [scope.orgId];
70
+ const eventFilter =
71
+ table === "analytics_events"
72
+ ? "\n AND event_name IS DISTINCT FROM 'http.response'"
73
+ : "";
70
74
  args.push(
71
75
  timeColumn === "received_at"
72
76
  ? window.startReceivedAt
@@ -75,8 +79,9 @@ async function countScopedRows(
75
79
 
76
80
  const { rows } = await getDbExec().execute({
77
81
  sql: `SELECT COUNT(*) AS row_count
78
- FROM ${table}
82
+ FROM ${table}
79
83
  WHERE ${scopeSql}
84
+ ${eventFilter}
80
85
  AND ${timeColumn} >= ?`,
81
86
  args,
82
87
  timeoutMs: 5_000,
@@ -135,10 +140,17 @@ export async function purgeFirstPartyAnalyticsPostgresRows(
135
140
  await tx
136
141
  .delete(schema.analyticsEvents)
137
142
  .where(
138
- windowPredicate(
139
- schema.analyticsEvents,
140
- scopePredicate(schema.analyticsEvents, scope, includeLegacyOwnerRows),
141
- window,
143
+ and(
144
+ windowPredicate(
145
+ schema.analyticsEvents,
146
+ scopePredicate(
147
+ schema.analyticsEvents,
148
+ scope,
149
+ includeLegacyOwnerRows,
150
+ ),
151
+ window,
152
+ ),
153
+ ne(schema.analyticsEvents.eventName, "http.response"),
142
154
  ),
143
155
  );
144
156
  await tx
@@ -1,6 +1,11 @@
1
1
  import {
2
+ deferMigration,
2
3
  ensureAdditiveColumns,
4
+ createDbExec,
3
5
  getDbExec,
6
+ getDatabaseUrl,
7
+ isPostgres,
8
+ MIGRATION_DEFERRED,
4
9
  runMigrations,
5
10
  withMigrationRuntime,
6
11
  } from "@agent-native/core/db";
@@ -34,6 +39,102 @@ const schemaTables = Object.values(schema).filter(isDrizzleTable);
34
39
  // packages/core/src/db/migrations.ts for the full rationale). Version numbers
35
40
  // alone are not a safe identity across parallel branches that each extend
36
41
  // this list independently — see the v75-v83 incident documented on v75 below.
42
+ const ANALYTICS_EVENT_CURSOR_INDEX_REPAIR_TIMEOUT_MS = 15 * 60 * 1000;
43
+
44
+ function getAnalyticsMigrationDatabaseUrl(): string {
45
+ const appName = process.env.APP_NAME?.toUpperCase().replace(/-/g, "_");
46
+ const directUrl = appName
47
+ ? process.env[`${appName}_DATABASE_URL_UNPOOLED`]
48
+ : undefined;
49
+ const url =
50
+ directUrl ||
51
+ process.env.NETLIFY_DATABASE_URL_UNPOOLED ||
52
+ process.env.DATABASE_URL_UNPOOLED ||
53
+ getDatabaseUrl();
54
+ return url.replace(/-pooler(\.[a-z0-9.-]+\.neon\.tech)/, "$1");
55
+ }
56
+
57
+ const ANALYTICS_EVENT_CURSOR_INDEX_REPAIR_LOCK =
58
+ "hashtext('agent-native:analytics-event-cursor-index-repair')";
59
+
60
+ async function repairAnalyticsEventCursorIndexes(): Promise<
61
+ void | typeof MIGRATION_DEFERRED
62
+ > {
63
+ if (!isPostgres()) return;
64
+
65
+ const repairIndexes = [
66
+ {
67
+ name: "analytics_events_org_received_id_non_http_idx",
68
+ createSql: `CREATE INDEX CONCURRENTLY IF NOT EXISTS analytics_events_org_received_id_non_http_idx
69
+ ON analytics_events (org_id, received_at, id)
70
+ WHERE event_name IS DISTINCT FROM 'http.response'`,
71
+ },
72
+ {
73
+ name: "analytics_events_owner_received_id_non_http_idx",
74
+ createSql: `CREATE INDEX CONCURRENTLY IF NOT EXISTS analytics_events_owner_received_id_non_http_idx
75
+ ON analytics_events (owner_email, received_at, id)
76
+ WHERE org_id IS NULL AND event_name IS DISTINCT FROM 'http.response'`,
77
+ },
78
+ {
79
+ name: "analytics_event_daily_rollups_org_event_date_idx",
80
+ createSql: `CREATE INDEX CONCURRENTLY IF NOT EXISTS analytics_event_daily_rollups_org_event_date_idx
81
+ ON analytics_event_daily_rollups (org_id, event_date)`,
82
+ },
83
+ {
84
+ name: "analytics_user_days_org_event_date_idx",
85
+ createSql: `CREATE INDEX CONCURRENTLY IF NOT EXISTS analytics_user_days_org_event_date_idx
86
+ ON analytics_user_days (org_id, event_date)`,
87
+ },
88
+ ];
89
+
90
+ const exec = await createDbExec({ url: getAnalyticsMigrationDatabaseUrl() });
91
+ const query = (sql: string) =>
92
+ exec.execute({
93
+ sql,
94
+ timeoutMs: ANALYTICS_EVENT_CURSOR_INDEX_REPAIR_TIMEOUT_MS,
95
+ maxAttempts: 1,
96
+ });
97
+
98
+ try {
99
+ const lockResult = await query(
100
+ `SELECT pg_try_advisory_lock(${ANALYTICS_EVENT_CURSOR_INDEX_REPAIR_LOCK}) AS acquired`,
101
+ );
102
+ if (lockResult.rows[0]?.acquired !== true) return deferMigration();
103
+
104
+ let lockHeld = true;
105
+ try {
106
+ const { rows } = await query(`
107
+ SELECT c.relname, i.indisvalid, i.indisready
108
+ FROM pg_class c
109
+ JOIN pg_index i ON i.indexrelid = c.oid
110
+ WHERE c.relname IN (${repairIndexes.map(({ name }) => `'${name}'`).join(", ")})
111
+ `);
112
+ const readyIndexes = new Set(
113
+ rows
114
+ .filter((row) => row.indisvalid === true && row.indisready === true)
115
+ .map((row) => String(row.relname)),
116
+ );
117
+ const expectedIndexes = repairIndexes.map(({ name }) => name);
118
+ if (expectedIndexes.every((name) => readyIndexes.has(name))) return;
119
+
120
+ for (const { name, createSql } of repairIndexes) {
121
+ if (readyIndexes.has(name)) continue;
122
+ await query(`DROP INDEX CONCURRENTLY IF EXISTS ${name}`);
123
+ await query(createSql);
124
+ }
125
+ } finally {
126
+ if (lockHeld) {
127
+ await query(
128
+ `SELECT pg_advisory_unlock(${ANALYTICS_EVENT_CURSOR_INDEX_REPAIR_LOCK})`,
129
+ );
130
+ lockHeld = false;
131
+ }
132
+ }
133
+ } finally {
134
+ await exec.close?.();
135
+ }
136
+ }
137
+
37
138
  export const runAnalyticsMigrations = runMigrations(
38
139
  [
39
140
  {
@@ -1660,6 +1761,44 @@ export const runAnalyticsMigrations = runMigrations(
1660
1761
  ON analytics_bigquery_backfill_shards (job_id, status, next_run_at, lease_expires_at, start_at);`,
1661
1762
  },
1662
1763
  },
1764
+ {
1765
+ version: 144,
1766
+ name: "analytics-events-backfill-filtered-cursor-index-repair",
1767
+ sql: {
1768
+ postgres: `DROP INDEX CONCURRENTLY IF EXISTS analytics_events_org_received_id_non_http_idx;
1769
+ CREATE INDEX CONCURRENTLY IF NOT EXISTS analytics_events_org_received_id_non_http_idx
1770
+ ON analytics_events (org_id, received_at, id)
1771
+ WHERE event_name IS DISTINCT FROM 'http.response';
1772
+ DROP INDEX CONCURRENTLY IF EXISTS analytics_events_owner_received_id_non_http_idx;
1773
+ CREATE INDEX CONCURRENTLY IF NOT EXISTS analytics_events_owner_received_id_non_http_idx
1774
+ ON analytics_events (owner_email, received_at, id)
1775
+ WHERE org_id IS NULL AND event_name IS DISTINCT FROM 'http.response';`,
1776
+ sqlite: `CREATE INDEX IF NOT EXISTS analytics_events_org_received_id_non_http_idx
1777
+ ON analytics_events (org_id, received_at, id)
1778
+ WHERE event_name IS NOT 'http.response';
1779
+ CREATE INDEX IF NOT EXISTS analytics_events_owner_received_id_non_http_idx
1780
+ ON analytics_events (owner_email, received_at, id)
1781
+ WHERE org_id IS NULL AND event_name IS NOT 'http.response';`,
1782
+ },
1783
+ },
1784
+ {
1785
+ version: 145,
1786
+ name: "analytics-events-backfill-filtered-cursor-index-direct-repair",
1787
+ run: repairAnalyticsEventCursorIndexes,
1788
+ sql: {
1789
+ postgres: "SELECT 1",
1790
+ sqlite: "SELECT 1",
1791
+ },
1792
+ },
1793
+ {
1794
+ version: 146,
1795
+ name: "analytics-events-purge-inventory-index-direct-repair",
1796
+ run: repairAnalyticsEventCursorIndexes,
1797
+ sql: {
1798
+ postgres: "SELECT 1",
1799
+ sqlite: "SELECT 1",
1800
+ },
1801
+ },
1663
1802
  ],
1664
1803
  { table: "analytics_migrations" },
1665
1804
  );
@@ -89,16 +89,20 @@ Deck data lives in SQL and all writes go through server-side actions. Read
89
89
 
90
90
  ## Export Behavior
91
91
 
92
- - Browser PowerPoint export uses the rendered slide DOM to generate native,
93
- editable PPTX text/shapes/images. Do not replace it with full-slide images
94
- unless the user explicitly asks for non-editable visual snapshots.
95
- - The server-side `export-pptx` action cannot measure browser-rendered
96
- freeform geometry. It must fail clearly for positioned objects and direct the
97
- user to the editor's Export > PowerPoint path instead of silently reflowing
98
- them.
99
- - Google Slides export is a PPTX import workflow: generate the same editable
100
- PPTX and have the user import it into Google Slides. Creating a native Google
101
- Slides file directly requires a separate Google Slides API batchUpdate path.
92
+ - PowerPoint and Google Slides export share two paths. Source-imported decks
93
+ with no browser-authored freeform objects export through the server
94
+ `export-pptx`, which writes their source geometry as real vector shapes; the
95
+ browser exporter can only rasterize it. Every other deck exports from the
96
+ rendered slide DOM, the one place editor-authored geometry is measurable. Do
97
+ not substitute full-slide images unless the user asks for non-editable
98
+ snapshots.
99
+ - Browser-authored means `data-slide-object-id` without
100
+ `data-pptx-element-kind`, or `fmd-freeform-object`. `export-pptx` cannot
101
+ measure those and fails loudly; show that failure instead of quietly
102
+ re-exporting at lower fidelity.
103
+ - Google Slides export is a PPTX import workflow: generate that PPTX and have
104
+ the user import it into Google Slides. Creating a native Google Slides file
105
+ directly requires a separate Google Slides API batchUpdate path.
102
106
 
103
107
  ## Source Changes
104
108