@agent-native/core 0.157.9 → 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.
- package/corpus/templates/analytics/scripts/first-party-analytics-postgres-retention-dry-run.sql +5 -2
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +3 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +18 -6
- package/corpus/templates/analytics/server/plugins/db.ts +139 -0
- package/corpus/templates/slides/AGENTS.md +14 -10
- package/corpus/templates/slides/actions/export-pptx.ts +1094 -94
- package/corpus/templates/slides/actions/import-file.ts +16 -1
- package/corpus/templates/slides/actions/import-pptx.ts +61 -43
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +222 -29
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +71 -0
- package/corpus/templates/slides/app/global.css +19 -1
- package/corpus/templates/slides/app/lib/export-google-slides-client.ts +44 -5
- package/corpus/templates/slides/app/lib/export-pdf-client.ts +13 -6
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +556 -25
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +18 -1
- package/corpus/templates/slides/server/handlers/import/html-converter.ts +1176 -26
- package/corpus/templates/slides/server/handlers/import/pdf-fidelity-parser.ts +13 -0
- package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +24 -0
- package/corpus/templates/slides/shared/aspect-ratios.ts +13 -1
- package/dist/agent/harness/migrations.js +24 -3
- package/dist/agent/production-agent.js +11 -0
- package/dist/agent/run-loop-with-resume.js +21 -4
- package/dist/automations/service.d.ts +6 -0
- package/dist/automations/service.js +35 -0
- package/dist/cli/code-agent-connector.d.ts +4 -1
- package/dist/cli/code-agent-connector.js +154 -23
- package/dist/cli/code-agent-executor.js +255 -13
- package/dist/cli/code-agent-runs.d.ts +1 -0
- package/dist/cli/code-agent-runs.js +2 -1
- package/dist/cli/portal-workspace.d.ts +49 -0
- package/dist/cli/portal-workspace.js +320 -0
- package/dist/client/AssistantChat.d.ts +1 -1
- package/dist/client/AssistantChat.js +39 -61
- package/dist/client/ConnectBuilderCard.js +33 -5
- package/dist/client/agent-chat-adapter.js +4 -0
- package/dist/client/analytics-platform.d.ts +2 -0
- package/dist/client/analytics-platform.js +12 -0
- package/dist/client/analytics.d.ts +3 -0
- package/dist/client/analytics.js +10 -1
- package/dist/client/chat/index.d.ts +1 -0
- package/dist/client/chat/index.js +1 -0
- package/dist/client/chat/run-recovery.d.ts +2 -1
- package/dist/client/chat/run-recovery.js +2 -2
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +11 -11
- package/dist/client/chat-first/surface-tabs.d.ts +1 -1
- package/dist/client/chat-first/surface-tabs.js +38 -36
- package/dist/client/chat-first/types.d.ts +5 -0
- package/dist/client/chat-first.d.ts +1 -1
- package/dist/client/chat-first.js +4 -4
- package/dist/client/desktop-local-code-change.d.ts +10 -0
- package/dist/client/desktop-local-code-change.js +16 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +1 -0
- package/dist/client/observability/ThumbsFeedback.js +21 -7
- package/dist/client/terminal/AgentTerminal.d.ts +9 -1
- package/dist/client/terminal/AgentTerminal.js +38 -3
- package/dist/client/terminal/index.d.ts +1 -1
- package/dist/client/terminal/index.js +1 -1
- package/dist/client/track.js +9 -1
- package/dist/client/use-action.js +3 -0
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.js +1 -1
- package/dist/ingestion/pptx.d.ts +78 -0
- package/dist/ingestion/pptx.js +991 -107
- package/dist/integrations/index.d.ts +3 -3
- package/dist/integrations/index.js +2 -2
- package/dist/integrations/plugin.js +95 -6
- package/dist/integrations/remote-commands-store.d.ts +5 -0
- package/dist/integrations/remote-commands-store.js +63 -22
- package/dist/integrations/remote-devices-store.d.ts +2 -1
- package/dist/integrations/remote-devices-store.js +46 -0
- package/dist/integrations/remote-types.d.ts +20 -0
- package/dist/jobs/actions/list-recurring-jobs.d.ts +3 -0
- package/dist/jobs/actions/list-recurring-jobs.js +5 -1
- package/dist/jobs/frontmatter.d.ts +16 -0
- package/dist/jobs/frontmatter.js +53 -0
- package/dist/jobs/remote-execution.d.ts +42 -0
- package/dist/jobs/remote-execution.js +287 -0
- package/dist/jobs/scheduler.js +102 -3
- package/dist/jobs/tools.js +50 -3
- package/dist/notifications/routes.d.ts +4 -4
- package/dist/provider-api/actions/custom-provider-registration.d.ts +9 -9
- package/dist/provider-api/actions/provider-api.d.ts +14 -14
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/action-routes.js +4 -2
- package/dist/server/agent-chat-plugin.js +6 -0
- package/dist/server/agent-run-context.d.ts +1 -0
- package/dist/server/agent-run-context.js +9 -0
- package/dist/server/core-routes-plugin.js +8 -1
- package/dist/server/request-context.d.ts +2 -0
- package/dist/shared/analytics-platform.d.ts +6 -0
- package/dist/shared/analytics-platform.js +14 -0
- package/dist/shared/mcp-embed-headers.d.ts +1 -1
- package/dist/shared/mcp-embed-headers.js +1 -1
- package/dist/styles/agent-native.css +83 -103
- package/dist/terminal/cli-registry.js +5 -0
- package/dist/tracking/registry.js +9 -1
- package/dist/triggers/actions/list-automations.d.ts +3 -0
- package/dist/triggers/actions/list-automations.js +3 -0
- package/dist/triggers/actions/manage-automation.d.ts +9 -0
- package/dist/triggers/actions/manage-automation.js +14 -2
- package/dist/triggers/actions.js +82 -7
- package/docs/content/template-content-developers.mdx +48 -0
- package/docs/content/toolkit-ui.mdx +57 -0
- package/package.json +2 -2
package/corpus/templates/analytics/scripts/first-party-analytics-postgres-retention-dry-run.sql
CHANGED
|
@@ -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
|
-
'
|
|
17
|
-
'
|
|
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}
|
|
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
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|