@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
@@ -311,9 +311,11 @@ 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;
315
+ provider?: undefined;
316
316
  deleted?: undefined;
317
+ found?: undefined;
318
+ message?: undefined;
317
319
  providers: {
318
320
  id: string;
319
321
  label: string;
@@ -324,46 +326,44 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
324
326
  updatedAt: number;
325
327
  }[];
326
328
  count: number;
327
- provider?: undefined;
328
- found?: undefined;
329
329
  registered?: undefined;
330
330
  label?: undefined;
331
331
  } | {
332
- message?: undefined;
333
- count?: undefined;
334
332
  id?: undefined;
335
333
  deleted?: undefined;
334
+ message?: undefined;
336
335
  providers?: undefined;
336
+ count?: undefined;
337
337
  found: boolean;
338
338
  provider: import("../custom-registry.js").CustomProviderConfig;
339
339
  registered?: undefined;
340
340
  label?: undefined;
341
341
  } | {
342
- message?: undefined;
343
- count?: undefined;
342
+ provider?: undefined;
344
343
  deleted?: undefined;
344
+ message?: undefined;
345
345
  providers?: undefined;
346
- provider?: undefined;
346
+ count?: undefined;
347
347
  found: boolean;
348
348
  id: string;
349
349
  registered?: undefined;
350
350
  label?: undefined;
351
351
  } | {
352
- message?: undefined;
353
- count?: undefined;
354
- providers?: undefined;
355
352
  provider?: undefined;
356
353
  found?: undefined;
354
+ message?: undefined;
355
+ providers?: undefined;
356
+ count?: undefined;
357
357
  deleted: boolean;
358
358
  id: string;
359
359
  registered?: undefined;
360
360
  label?: undefined;
361
361
  } | {
362
- count?: undefined;
363
- deleted?: undefined;
364
- providers?: undefined;
365
362
  provider?: undefined;
363
+ deleted?: undefined;
366
364
  found?: undefined;
365
+ providers?: undefined;
366
+ count?: undefined;
367
367
  registered: boolean;
368
368
  id: string;
369
369
  label: string;
@@ -73,7 +73,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
73
73
  offset?: unknown;
74
74
  limit?: unknown;
75
75
  }, {
76
- deleted?: undefined;
77
76
  jobs: {
78
77
  id: string;
79
78
  name: string;
@@ -84,6 +83,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
84
83
  updatedAt: string;
85
84
  }[];
86
85
  total: number;
86
+ deleted?: undefined;
87
87
  jobId?: undefined;
88
88
  } | {
89
89
  jobs?: undefined;
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
91
91
  deleted: boolean;
92
92
  jobId: string;
93
93
  } | {
94
- deleted?: undefined;
95
94
  jobs?: undefined;
96
95
  total?: undefined;
96
+ deleted?: undefined;
97
97
  jobId?: undefined;
98
98
  hits: Record<string, unknown>[];
99
99
  offset: number;
@@ -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
- ok?: undefined;
52
51
  error: string;
52
+ ok?: undefined;
53
53
  } | {
54
54
  error?: undefined;
55
55
  ok: boolean;
@@ -34,37 +34,37 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
34
34
  /** POST /_agent-native/secrets/:key — write a secret. */
35
35
  export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
36
36
  error: string;
37
- ok?: undefined;
38
37
  status?: undefined;
38
+ ok?: undefined;
39
39
  } | {
40
- error?: undefined;
41
40
  ok: boolean;
42
41
  status: string;
42
+ error?: undefined;
43
43
  } | {
44
- ok?: undefined;
45
44
  error: string;
46
45
  removed?: undefined;
46
+ ok?: undefined;
47
47
  } | {
48
- error?: undefined;
49
48
  ok: boolean;
50
49
  removed: boolean;
50
+ error?: undefined;
51
51
  }>>;
52
52
  /**
53
53
  * POST /_agent-native/secrets/:key/test — validate an optional candidate value
54
54
  * or the current stored value without changing anything.
55
55
  */
56
56
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
57
- ok?: undefined;
58
57
  error: string;
59
58
  note?: undefined;
59
+ ok?: undefined;
60
60
  } | {
61
- error?: undefined;
62
61
  ok: boolean;
63
62
  note?: undefined;
64
- } | {
65
63
  error?: undefined;
64
+ } | {
66
65
  ok: boolean;
67
66
  note: string;
67
+ error?: undefined;
68
68
  } | {
69
69
  note?: undefined;
70
70
  ok: boolean;
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
95
95
  export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
96
96
  error: string;
97
97
  } | {
98
- error?: undefined;
99
98
  ok: boolean;
100
99
  key: string;
101
- } | {
102
100
  error?: undefined;
101
+ } | {
103
102
  ok: boolean;
104
103
  removed: boolean;
104
+ error?: undefined;
105
105
  }>>;
@@ -9,7 +9,7 @@ import { readBody } from "../server/h3-helpers.js";
9
9
  import { EMBED_TARGET_HEADER } from "../shared/embed-auth.js";
10
10
  import { isMcpEmbedCorsOrigin, MCP_EMBED_CORS_ALLOW_HEADERS, shouldAllowMcpEmbedCredentials, } from "../shared/mcp-embed-headers.js";
11
11
  import { actionCallIsReadOnly, notifyActionChange } from "./action-change.js";
12
- import { readBrowserSessionIdHeader, seedAgentRunOwnerContext, } from "./agent-run-context.js";
12
+ import { readBrowserSessionIdHeader, readAnalyticsClientPlatformHeader, seedAgentRunOwnerContext, } from "./agent-run-context.js";
13
13
  import { captureError } from "./capture-error.js";
14
14
  import { getAllowedCorsOrigin as resolveAllowedCorsOrigin, readCorsAllowedOrigins, } from "./cors-origins.js";
15
15
  import { resolveEmbedSessionFromRequest, resolvedEmbedCapabilityScope, } from "./embed-session.js";
@@ -168,7 +168,7 @@ function handleOptionsRequest(event) {
168
168
  }
169
169
  setResponseHeader(event, "Access-Control-Allow-Methods", "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS");
170
170
  setResponseHeader(event, "Access-Control-Allow-Headers", cors.credentials
171
- ? `Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-User-Timezone,X-Agent-Native-Session-Id,X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend,X-Agent-Native-Client-Compatibility,X-Agent-Native-Build-Id,${EMBED_TARGET_HEADER}`
171
+ ? `Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-User-Timezone,X-Agent-Native-Session-Id,X-Agent-Native-Client-Platform,X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend,X-Agent-Native-Client-Compatibility,X-Agent-Native-Build-Id,${EMBED_TARGET_HEADER}`
172
172
  : `${MCP_EMBED_CORS_ALLOW_HEADERS},X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend,X-Agent-Native-Client-Compatibility,X-Agent-Native-Build-Id`);
173
173
  }
174
174
  setResponseStatus(event, 204);
@@ -390,6 +390,7 @@ export function mountActionRoutes(nitroApp, actions, options) {
390
390
  }
391
391
  const timezone = readTimezoneHeader(event);
392
392
  const browserSessionId = readBrowserSessionIdHeader(event);
393
+ const clientPlatform = readAnalyticsClientPlatformHeader(event);
393
394
  return runWithRequestContext({
394
395
  userEmail,
395
396
  userName,
@@ -397,6 +398,7 @@ export function mountActionRoutes(nitroApp, actions, options) {
397
398
  authCapability,
398
399
  timezone,
399
400
  browserSessionId,
401
+ clientPlatform,
400
402
  requestOrigin: getRequestURL(event).origin,
401
403
  // Captured here because this is the last layer that still holds
402
404
  // the h3 event; everything below reads it off the request store.
@@ -35,6 +35,7 @@ import { getSkillNameFromPath } from "../resources/metadata.js";
35
35
  import { resourceList, resourceListAccessible, resourceGet, ensurePersonalDefaults, SHARED_OWNER, WORKSPACE_OWNER, } from "../resources/store.js";
36
36
  import { normalizeDatabaseToolsMode } from "../scripts/db/tool-mode.js";
37
37
  import { getSetting, putSetting } from "../settings/store.js";
38
+ import { ANALYTICS_CLIENT_PLATFORM_BODY_FIELD, normalizeAnalyticsClientPlatform, } from "../shared/analytics-platform.js";
38
39
  import { docsUrl } from "../shared/docs-url.js";
39
40
  import { handleSharedThreadRequest, } from "./agent-chat/shared-thread.js";
40
41
  import { discoverAgents } from "./agent-discovery.js";
@@ -4909,6 +4910,11 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
4909
4910
  // is already consumed, so the handler reads this instead.
4910
4911
  event.context = event.context ?? {};
4911
4912
  event.context.__agentChatBackgroundBody = workerBody;
4913
+ const persistedClientPlatform = normalizeAnalyticsClientPlatform(workerBody[ANALYTICS_CLIENT_PLATFORM_BODY_FIELD]);
4914
+ if (persistedClientPlatform) {
4915
+ event.context[ANALYTICS_CLIENT_PLATFORM_BODY_FIELD] =
4916
+ persistedClientPlatform;
4917
+ }
4912
4918
  // Durable owner context: this self-dispatch is cookieless (HMAC-only).
4913
4919
  // Resolve the owner from the persisted run row, never the request
4914
4920
  // body, then invoke the normal handler. The shared agent-run context
@@ -27,10 +27,10 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
27
27
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
28
28
  error: any;
29
29
  } | {
30
- error?: undefined;
31
30
  ok: boolean;
32
31
  key: string;
33
32
  baseUrlKey?: string;
34
33
  scope: AgentEngineApiKeyScope;
34
+ error?: undefined;
35
35
  }>>;
36
36
  export {};
@@ -25,6 +25,7 @@ export declare function readAgentRunTimezone(event: H3Event): string | undefined
25
25
  * action calls and the agent's.
26
26
  */
27
27
  export declare function readBrowserSessionIdHeader(event: H3Event): string | undefined;
28
+ export declare function readAnalyticsClientPlatformHeader(event: H3Event): import("../shared/analytics-platform.js").AnalyticsClientPlatform | undefined;
28
29
  export declare function seedAgentRunOwnerContext(event: H3Event, ownerContext: AgentRunOwnerContext): AgentRunOwnerContext;
29
30
  export declare function seedBackgroundAgentRunOwnerContext(event: H3Event, runId: string, orgId?: string | null): Promise<AgentRunOwnerContext | null>;
30
31
  export declare function resolveAgentRunOwnerContext(event: H3Event, options?: {
@@ -1,5 +1,6 @@
1
1
  import { createError, getHeader } from "h3";
2
2
  import { resolveOrgIdForEmail, getOrgContext } from "../org/context.js";
3
+ import { ANALYTICS_CLIENT_PLATFORM_BODY_FIELD, ANALYTICS_CLIENT_PLATFORM_HEADER, normalizeAnalyticsClientPlatform, } from "../shared/analytics-platform.js";
3
4
  import { getSession } from "./auth.js";
4
5
  import { runWithRequestContext, } from "./request-context.js";
5
6
  export const AGENT_RUN_OWNER_CONTEXT_KEY = "__agentNativeOwnerContext";
@@ -62,6 +63,12 @@ export function readBrowserSessionIdHeader(event) {
62
63
  ? value.trim()
63
64
  : undefined;
64
65
  }
66
+ export function readAnalyticsClientPlatformHeader(event) {
67
+ const raw = readHeaderValue(event, ANALYTICS_CLIENT_PLATFORM_HEADER);
68
+ const value = Array.isArray(raw) ? raw[0] : raw;
69
+ return (normalizeAnalyticsClientPlatform(value) ??
70
+ normalizeAnalyticsClientPlatform(event.context?.[ANALYTICS_CLIENT_PLATFORM_BODY_FIELD]));
71
+ }
65
72
  export function seedAgentRunOwnerContext(event, ownerContext) {
66
73
  eventContext(event)[AGENT_RUN_OWNER_CONTEXT_KEY] =
67
74
  ownerContext;
@@ -150,6 +157,7 @@ export async function resolveAgentRunRequestContext(options) {
150
157
  const orgId = await resolveAgentRunOrgId(options);
151
158
  const timezone = readAgentRunTimezone(options.event);
152
159
  const browserSessionId = readBrowserSessionIdHeader(options.event);
160
+ const clientPlatform = readAnalyticsClientPlatformHeader(options.event);
153
161
  const waitUntil = requestWaitUntil(options.event);
154
162
  const run = {
155
163
  ...(options.isBackgroundWorker ? { isBackgroundWorker: true } : {}),
@@ -161,6 +169,7 @@ export async function resolveAgentRunRequestContext(options) {
161
169
  orgId,
162
170
  timezone,
163
171
  ...(browserSessionId ? { browserSessionId } : {}),
172
+ ...(clientPlatform ? { clientPlatform } : {}),
164
173
  ...(Object.keys(run).length > 0 ? { run } : {}),
165
174
  };
166
175
  }
@@ -24,6 +24,7 @@ import { registerFrameworkSecrets } from "../secrets/register-framework-secrets.
24
24
  import { createListSecretsHandler, createWriteSecretHandler, createTestSecretHandler, createAdHocSecretHandler, } from "../secrets/routes.js";
25
25
  import { getSetting, putSetting, deleteSetting } from "../settings/store.js";
26
26
  import { getUserSetting, putUserSetting, deleteUserSetting, } from "../settings/user-settings.js";
27
+ import { ANALYTICS_CLIENT_PLATFORM_PROPERTY } from "../shared/analytics-platform.js";
27
28
  import { EMPTY_SPECULATION_RULES, resolveSsrCacheHeaders, } from "../shared/cache-control.js";
28
29
  import { EMBED_TARGET_HEADER } from "../shared/embed-auth.js";
29
30
  import { llmConnectionTrackingProperties } from "../shared/llm-connection.js";
@@ -35,7 +36,7 @@ import { registerBuiltinProviders } from "../tracking/providers.js";
35
36
  import { validateTrackPayload } from "../tracking/route.js";
36
37
  import { createAutomationsHandler } from "../triggers/routes.js";
37
38
  import { createAgentEngineApiKeyHandler } from "./agent-engine-api-key-route.js";
38
- import { readBrowserSessionIdHeader } from "./agent-run-context.js";
39
+ import { readAnalyticsClientPlatformHeader, readBrowserSessionIdHeader, } from "./agent-run-context.js";
39
40
  import { getConfiguredAppBasePath, stripAppBasePath } from "./app-base-path.js";
40
41
  import { getAppName } from "./app-name.js";
41
42
  import { getSession } from "./auth.js";
@@ -2608,8 +2609,14 @@ export function createCoreRoutesPlugin(options = {}) {
2608
2609
  catch {
2609
2610
  /* org module not present in this template — keep userEmail-only */
2610
2611
  }
2612
+ const clientPlatform = readAnalyticsClientPlatformHeader(event);
2611
2613
  const properties = {
2612
2614
  ...(validation.properties ?? {}),
2615
+ ...(clientPlatform
2616
+ ? {
2617
+ [ANALYTICS_CLIENT_PLATFORM_PROPERTY]: clientPlatform,
2618
+ }
2619
+ : {}),
2613
2620
  source: "client",
2614
2621
  };
2615
2622
  if (orgId)
@@ -109,6 +109,8 @@ export interface RequestContext {
109
109
  * replay; never used for authorization.
110
110
  */
111
111
  browserSessionId?: string;
112
+ /** Canonical client surface for analytics attribution. */
113
+ clientPlatform?: import("../shared/analytics-platform.js").AnalyticsClientPlatform;
112
114
  /**
113
115
  * Set when code reads authenticated request context. Public SSR shell/data
114
116
  * should not depend on this value; user/org-specific reads belong behind
@@ -20,6 +20,6 @@ export declare function createTranscribeVoiceHandler(): import("h3").EventHandle
20
20
  error: string;
21
21
  text?: undefined;
22
22
  } | {
23
- text: string;
24
23
  error?: undefined;
24
+ text: string;
25
25
  }>>;
@@ -0,0 +1,6 @@
1
+ export declare const ANALYTICS_CLIENT_PLATFORM_HEADER = "X-Agent-Native-Client-Platform";
2
+ export declare const ANALYTICS_CLIENT_PLATFORM_PROPERTY = "client_platform";
3
+ export declare const ANALYTICS_CLIENT_PLATFORM_BODY_FIELD = "__agentNativeClientPlatform";
4
+ export declare const ANALYTICS_CLIENT_PLATFORMS: readonly ["web", "electron", "mobile"];
5
+ export type AnalyticsClientPlatform = (typeof ANALYTICS_CLIENT_PLATFORMS)[number];
6
+ export declare function normalizeAnalyticsClientPlatform(value: unknown): AnalyticsClientPlatform | undefined;
@@ -0,0 +1,14 @@
1
+ export const ANALYTICS_CLIENT_PLATFORM_HEADER = "X-Agent-Native-Client-Platform";
2
+ export const ANALYTICS_CLIENT_PLATFORM_PROPERTY = "client_platform";
3
+ export const ANALYTICS_CLIENT_PLATFORM_BODY_FIELD = "__agentNativeClientPlatform";
4
+ export const ANALYTICS_CLIENT_PLATFORMS = [
5
+ "web",
6
+ "electron",
7
+ "mobile",
8
+ ];
9
+ export function normalizeAnalyticsClientPlatform(value) {
10
+ return typeof value === "string" &&
11
+ ANALYTICS_CLIENT_PLATFORMS.includes(value)
12
+ ? value
13
+ : undefined;
14
+ }
@@ -1,4 +1,4 @@
1
- export declare const MCP_EMBED_CORS_ALLOW_HEADERS = "Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-Agent-Native-Frontend,X-Agent-Native-Client-Compatibility,X-Agent-Native-Build-Id,X-User-Timezone,X-Agent-Native-Session-Id,X-Agent-Native-Embed-Target,X-Agent-Native-Embed-Transplant";
1
+ export declare const MCP_EMBED_CORS_ALLOW_HEADERS = "Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-Agent-Native-Frontend,X-Agent-Native-Client-Compatibility,X-Agent-Native-Build-Id,X-User-Timezone,X-Agent-Native-Session-Id,X-Agent-Native-Client-Platform,X-Agent-Native-Embed-Target,X-Agent-Native-Embed-Transplant";
2
2
  export declare const EMBED_TRANSPLANT_HEADER = "x-agent-native-embed-transplant";
3
3
  export declare function isLocalMcpEmbedOrigin(origin: string | null | undefined): boolean;
4
4
  export declare function isClaudeMcpContentOrigin(origin: string | null | undefined): boolean;
@@ -1,4 +1,4 @@
1
- export const MCP_EMBED_CORS_ALLOW_HEADERS = "Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-Agent-Native-Frontend,X-Agent-Native-Client-Compatibility,X-Agent-Native-Build-Id,X-User-Timezone,X-Agent-Native-Session-Id,X-Agent-Native-Embed-Target,X-Agent-Native-Embed-Transplant";
1
+ export const MCP_EMBED_CORS_ALLOW_HEADERS = "Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-Agent-Native-Frontend,X-Agent-Native-Client-Compatibility,X-Agent-Native-Build-Id,X-User-Timezone,X-Agent-Native-Session-Id,X-Agent-Native-Client-Platform,X-Agent-Native-Embed-Target,X-Agent-Native-Embed-Transplant";
2
2
  export const EMBED_TRANSPLANT_HEADER = "x-agent-native-embed-transplant";
3
3
  const CLAUDE_MCP_CONTENT_HOST_RE = /^[a-f0-9]{32}\.claudemcpcontent\.com$/i;
4
4
  const CHATGPT_MCP_SANDBOX_HOST_RE = /^(?:[^.]+\.)?web-sandbox\.oaiusercontent\.com$/i;
@@ -492,7 +492,7 @@
492
492
 
493
493
  --animate-accordion-down: accordion-down 0.2s ease-out;
494
494
  --animate-accordion-up: accordion-up 0.2s ease-out;
495
- --animate-bounce-once: bounce-once 0.55s cubic-bezier(0.34, 1.56, 0.64, 1);
495
+ --animate-bounce-once: bounce-once 0.46s cubic-bezier(0.34, 1.56, 0.64, 1);
496
496
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
497
497
  --ease-collapse: cubic-bezier(0.2, 0, 0, 1);
498
498
  --ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1);
@@ -518,10 +518,10 @@
518
518
  transform: translateY(0);
519
519
  }
520
520
  35% {
521
- transform: translateY(-8px);
521
+ transform: translateY(-5px);
522
522
  }
523
523
  65% {
524
- transform: translateY(-2px);
524
+ transform: translateY(-1px);
525
525
  }
526
526
  100% {
527
527
  transform: translateY(0);
@@ -838,6 +838,55 @@
838
838
  min-inline-size: min(18rem, 100%);
839
839
  }
840
840
 
841
+ /* Provider setup tucks behind the composer. The extra bottom paint is hidden
842
+ by the higher composer layer, leaving one connected control. */
843
+ .agent-builder-setup-card--attached {
844
+ position: relative;
845
+ z-index: 1;
846
+ margin-bottom: -2.5rem;
847
+ padding-bottom: 0 !important;
848
+ }
849
+
850
+ .agent-builder-setup-card--attached .agent-builder-setup-card__panel {
851
+ padding-bottom: calc(0.75rem + 1.875rem);
852
+ border-bottom-color: transparent;
853
+ border-bottom-left-radius: 0;
854
+ border-bottom-right-radius: 0;
855
+ background: color-mix(
856
+ in srgb,
857
+ hsl(var(--card)) 97%,
858
+ hsl(var(--foreground)) 3%
859
+ );
860
+ box-shadow: none;
861
+ }
862
+
863
+ .agent-builder-setup-card--attached.agent-builder-setup-card--sidebar
864
+ .agent-builder-setup-card__panel {
865
+ padding-bottom: calc(0.625rem + 1.875rem);
866
+ }
867
+
868
+ .agent-builder-setup-card--attached:not(.agent-builder-setup-card--sidebar) {
869
+ max-inline-size: min(100%, 750px);
870
+ margin-inline: auto;
871
+ padding-inline: 0 !important;
872
+ }
873
+
874
+ .agent-builder-setup-inline--attached {
875
+ position: relative;
876
+ z-index: 1;
877
+ margin-bottom: -2.5rem !important;
878
+ padding-bottom: calc(0.625rem + 1.875rem) !important;
879
+ border-bottom-color: transparent;
880
+ border-bottom-left-radius: 0;
881
+ border-bottom-right-radius: 0;
882
+ background: color-mix(
883
+ in srgb,
884
+ hsl(var(--card)) 97%,
885
+ hsl(var(--foreground)) 3%
886
+ );
887
+ box-shadow: none;
888
+ }
889
+
841
890
  .agent-builder-setup-card--sidebar {
842
891
  container-type: inline-size;
843
892
  container-name: agent-builder-setup;
@@ -913,6 +962,37 @@
913
962
  padding-block: 0.5rem;
914
963
  }
915
964
 
965
+ .agent-composer-area--attached-above {
966
+ padding-top: 0 !important;
967
+ }
968
+
969
+ .agent-composer-area--attached-above .agent-composer-root {
970
+ position: relative;
971
+ z-index: 3;
972
+ background: hsl(var(--muted));
973
+ background: color-mix(
974
+ in srgb,
975
+ hsl(var(--card)) 98%,
976
+ hsl(var(--foreground)) 2%
977
+ );
978
+ }
979
+
980
+ .dark .agent-composer-area--attached-above .agent-composer-root {
981
+ background: hsl(var(--card));
982
+ }
983
+
984
+ @media (prefers-color-scheme: dark) {
985
+ :root:not(.light) .agent-composer-area--attached-above .agent-composer-root {
986
+ background: hsl(var(--card));
987
+ }
988
+ }
989
+
990
+ @media (prefers-reduced-motion: reduce) {
991
+ .agent-builder-setup-card--attached.animate-bounce-once {
992
+ animation: none;
993
+ }
994
+ }
995
+
916
996
  .agent-composer-root--hero {
917
997
  min-height: 5.625rem;
918
998
  border-radius: 1rem;
@@ -937,106 +1017,6 @@
937
1017
  line-height: 1.75rem;
938
1018
  }
939
1019
 
940
- .agent-composer-root--missing-key {
941
- overflow: visible;
942
- }
943
-
944
- .agent-composer-missing-key-trigger {
945
- display: flex;
946
- cursor: pointer;
947
- min-height: 4.5rem;
948
- width: 100%;
949
- flex: 1;
950
- align-items: center;
951
- justify-content: flex-start;
952
- border: 0;
953
- border-radius: inherit;
954
- background: transparent;
955
- padding: 0.875rem;
956
- text-align: start;
957
- color: hsl(var(--foreground));
958
- outline: none;
959
- transition:
960
- background-color 150ms ease-out,
961
- box-shadow 150ms ease-out;
962
- }
963
-
964
- .agent-composer-missing-key-trigger:hover {
965
- background: hsl(var(--accent) / 0.45);
966
- }
967
-
968
- .agent-composer-missing-key-trigger:focus-visible {
969
- box-shadow: inset 0 0 0 2px hsl(var(--ring));
970
- }
971
-
972
- .agent-composer-missing-key-content {
973
- display: flex;
974
- min-width: 0;
975
- flex-direction: column;
976
- align-items: flex-start;
977
- gap: 0.5rem;
978
- }
979
-
980
- .agent-composer-missing-key-copy {
981
- display: flex;
982
- min-width: 0;
983
- flex-direction: column;
984
- gap: 0.25rem;
985
- }
986
-
987
- .agent-composer-missing-key-title {
988
- font-size: 0.8125rem;
989
- font-weight: 500;
990
- line-height: 1.25rem;
991
- }
992
-
993
- .agent-composer-missing-key-description {
994
- font-size: 0.6875rem;
995
- line-height: 1rem;
996
- color: hsl(var(--muted-foreground));
997
- }
998
-
999
- .agent-composer-missing-key-cta {
1000
- display: inline-flex;
1001
- min-height: 2rem;
1002
- align-items: center;
1003
- justify-content: center;
1004
- border-radius: 0.375rem;
1005
- background: hsl(var(--foreground));
1006
- padding: 0.5rem 0.75rem;
1007
- color: hsl(var(--background));
1008
- font-size: 0.75rem;
1009
- font-weight: 600;
1010
- line-height: 1rem;
1011
- transition:
1012
- opacity 150ms ease-out,
1013
- transform 150ms ease-out;
1014
- }
1015
-
1016
- .agent-composer-missing-key-trigger:hover .agent-composer-missing-key-cta {
1017
- opacity: 0.9;
1018
- }
1019
-
1020
- .agent-composer-missing-key-trigger:active .agent-composer-missing-key-cta {
1021
- transform: scale(0.98);
1022
- }
1023
-
1024
- .agent-composer-root--hero .agent-composer-missing-key-trigger {
1025
- min-height: 7.5rem;
1026
- justify-content: center;
1027
- padding: 1.25rem;
1028
- text-align: center;
1029
- }
1030
-
1031
- .agent-composer-root--hero .agent-composer-missing-key-title {
1032
- font-size: 0.9375rem;
1033
- line-height: 1.375rem;
1034
- }
1035
-
1036
- .agent-composer-root--hero .agent-composer-missing-key-content {
1037
- align-items: center;
1038
- }
1039
-
1040
1020
  .agent-composer-stack {
1041
1021
  position: relative;
1042
1022
  flex-shrink: 0;
@@ -28,6 +28,11 @@ export const CLI_REGISTRY = {
28
28
  installPackage: "opencode-ai",
29
29
  stripEnv: [],
30
30
  },
31
+ pi: {
32
+ label: "Pi",
33
+ installPackage: "",
34
+ stripEnv: [],
35
+ },
31
36
  };
32
37
  /** Check if a command name is in the CLI_REGISTRY allowlist */
33
38
  export function isAllowedCommand(cmd) {
@@ -1,4 +1,5 @@
1
1
  import { getRequestContext } from "../server/request-context.js";
2
+ import { ANALYTICS_CLIENT_PLATFORM_PROPERTY } from "../shared/analytics-platform.js";
2
3
  const REGISTRY_KEY = Symbol.for("@agent-native/core/tracking.registry");
3
4
  function getRegistry() {
4
5
  const g = globalThis;
@@ -44,9 +45,16 @@ function resolveTrackingSource(source) {
44
45
  }
45
46
  export function track(name, properties, source) {
46
47
  const { userId, anonymousId, sessionId } = resolveTrackingSource(source);
48
+ const clientPlatform = getRequestContext()?.clientPlatform;
49
+ const trackedProperties = clientPlatform
50
+ ? {
51
+ ...(properties ?? {}),
52
+ [ANALYTICS_CLIENT_PLATFORM_PROPERTY]: clientPlatform,
53
+ }
54
+ : properties;
47
55
  const event = {
48
56
  name,
49
- properties,
57
+ properties: trackedProperties,
50
58
  timestamp: new Date().toISOString(),
51
59
  userId,
52
60
  anonymousId,
@@ -18,6 +18,9 @@ export interface AutomationActionItem {
18
18
  nextRun: string | null;
19
19
  createdBy: string | null;
20
20
  model: string | null;
21
+ executionHostId: string | null;
22
+ executionEngine: string | null;
23
+ executionCwd: string | null;
21
24
  mcpTools: string[];
22
25
  originScopeId: string | null;
23
26
  deliveryPlatform: string | null;
@@ -58,6 +58,9 @@ export default defineAction({
58
58
  nextRun: nextRun(meta),
59
59
  createdBy: meta.createdBy ?? null,
60
60
  model: meta.model ?? null,
61
+ executionHostId: meta.executionHostId ?? null,
62
+ executionEngine: meta.executionEngine ?? null,
63
+ executionCwd: meta.executionCwd ?? null,
61
64
  mcpTools: meta.mcpTools ?? [],
62
65
  originScopeId: meta.originScopeId ?? null,
63
66
  deliveryPlatform: meta.deliveryPlatform ?? null,