@agent-native/core 0.154.4 → 0.155.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/account-health/SKILL.md +76 -0
  3. package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +3 -0
  4. package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +2 -1
  5. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +6 -5
  6. package/corpus/templates/analytics/AGENTS.md +3 -0
  7. package/corpus/templates/analytics/actions/account-deep-dive.ts +3 -2
  8. package/corpus/templates/analytics/actions/bigquery.ts +1 -1
  9. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +4 -1
  10. package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
  11. package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyCombobox.tsx +12 -4
  12. package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyValueCombobox.tsx +5 -2
  13. package/corpus/templates/analytics/app/pages/adhoc/explorer/property-label.ts +32 -0
  14. package/corpus/templates/analytics/changelog/2026-08-13-account-health-readouts-verify-customer-scope-and-contract-metrics.md +7 -0
  15. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +43 -17
  16. package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +17 -0
  17. package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -0
  18. package/corpus/templates/calendar/AGENTS.md +2 -0
  19. package/corpus/templates/calendar/DEVELOPING.md +4 -4
  20. package/corpus/templates/calendar/actions/get-settings.ts +4 -11
  21. package/corpus/templates/calendar/actions/update-availability.ts +15 -4
  22. package/corpus/templates/calendar/actions/update-settings.ts +15 -4
  23. package/corpus/templates/calendar/app/components/booking/DatePicker.tsx +9 -3
  24. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +21 -19
  25. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +9 -6
  26. package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +25 -3
  27. package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +10 -3
  28. package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +9 -9
  29. package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -3
  30. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +10 -4
  31. package/corpus/templates/calendar/app/i18n-data.ts +30 -0
  32. package/corpus/templates/calendar/app/lib/availability-schedule.ts +53 -0
  33. package/corpus/templates/calendar/app/lib/event-form-utils.ts +5 -0
  34. package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +90 -28
  35. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +135 -61
  36. package/corpus/templates/calendar/app/pages/BookingPage.tsx +2 -0
  37. package/corpus/templates/calendar/app/pages/CalendarView.tsx +30 -15
  38. package/corpus/templates/calendar/app/pages/Settings.tsx +60 -1
  39. package/corpus/templates/calendar/changelog/2026-08-13-find-a-time-now-closes-from-a-clear-header-action.md +6 -0
  40. package/corpus/templates/calendar/server/handlers/bookings.ts +2 -1
  41. package/corpus/templates/calendar/server/handlers/settings.ts +12 -16
  42. package/corpus/templates/calendar/shared/api.ts +1 -0
  43. package/corpus/templates/calendar/shared/availability-schedule.ts +64 -0
  44. package/corpus/templates/calendar/shared/calendar-week.ts +21 -0
  45. package/corpus/templates/calendar/shared/settings.ts +44 -0
  46. package/corpus/templates/clips/AGENTS.md +2 -0
  47. package/corpus/templates/clips/actions/add-comment.ts +5 -2
  48. package/corpus/templates/clips/actions/finalize-recording.ts +31 -1
  49. package/corpus/templates/clips/actions/get-recording-player-data.ts +9 -0
  50. package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +21 -1
  51. package/corpus/templates/clips/actions/reply-to-comment.ts +5 -2
  52. package/corpus/templates/clips/actions/update-comment.ts +9 -2
  53. package/corpus/templates/clips/app/components/library/search-bar.tsx +26 -13
  54. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +135 -3
  55. package/corpus/templates/clips/app/components/player/comments-panel.tsx +5 -99
  56. package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +7 -3
  57. package/corpus/templates/clips/app/components/player/video-player.tsx +84 -24
  58. package/corpus/templates/clips/app/components/workspace/notifications-list.tsx +11 -3
  59. package/corpus/templates/clips/app/i18n/en-US.ts +12 -0
  60. package/corpus/templates/clips/app/lib/public-meeting.ts +11 -3
  61. package/corpus/templates/clips/app/lib/search-focus.ts +15 -0
  62. package/corpus/templates/clips/app/root.tsx +2 -1
  63. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +94 -26
  64. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +24 -7
  65. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +8 -4
  66. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +14 -7
  67. package/corpus/templates/clips/app/routes/share.$shareId.tsx +8 -4
  68. package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +72 -26
  69. package/corpus/templates/clips/changelog/2026-08-13-inline-markdown-comments.md +6 -0
  70. package/corpus/templates/clips/changelog/2026-08-13-private-meeting-agent-links.md +6 -0
  71. package/corpus/templates/clips/desktop/src/app.tsx +116 -19
  72. package/corpus/templates/clips/desktop/src/lib/recorder.ts +13 -29
  73. package/corpus/templates/clips/desktop/src/lib/recording-request.ts +39 -0
  74. package/corpus/templates/clips/desktop/src/lib/settings-navigation.ts +11 -0
  75. package/corpus/templates/clips/desktop/src/lib/whisper-model-picker.ts +7 -0
  76. package/corpus/templates/clips/desktop/src/styles.css +117 -0
  77. package/corpus/templates/clips/server/db/index.ts +10 -0
  78. package/corpus/templates/clips/server/db/schema.ts +1 -0
  79. package/corpus/templates/clips/server/lib/recordings.ts +3 -1
  80. package/corpus/templates/clips/server/lib/seekable-media-state.ts +90 -0
  81. package/corpus/templates/clips/server/plugins/db.ts +5 -0
  82. package/corpus/templates/clips/server/routes/api/public-meeting.get.ts +37 -4
  83. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +16 -5
  84. package/corpus/templates/clips/shared/clips-ai-prefs.ts +3 -0
  85. package/corpus/templates/clips/shared/meeting-agent-access.ts +5 -0
  86. package/corpus/templates/content/.agents/skills/content/SKILL.md +2 -2
  87. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +20 -4
  88. package/corpus/templates/content/actions/_database-row-mutation.ts +1490 -0
  89. package/corpus/templates/content/actions/_database-utils.ts +44 -0
  90. package/corpus/templates/content/actions/_property-utils.ts +4 -1
  91. package/corpus/templates/content/actions/add-comment.ts +2 -1
  92. package/corpus/templates/content/actions/add-database-item.ts +62 -240
  93. package/corpus/templates/content/actions/configure-document-property.ts +165 -1
  94. package/corpus/templates/content/actions/delete-document-property.ts +18 -0
  95. package/corpus/templates/content/actions/set-document-property.ts +78 -1
  96. package/corpus/templates/content/actions/update-comment.ts +1 -1
  97. package/corpus/templates/content/actions/update-database-item.ts +62 -0
  98. package/corpus/templates/content/actions/upsert-database-item-by-key.ts +43 -796
  99. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +24 -15
  100. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +10 -8
  101. package/corpus/templates/content/app/hooks/use-content-database.ts +33 -32
  102. package/corpus/templates/content/changelog/2026-08-10-database-row-actions-now-validate-exact-schemas-and-safe-ret.md +6 -0
  103. package/corpus/templates/content/parity/matrix.md +1 -1
  104. package/corpus/templates/content/parity/matrix.ts +2 -0
  105. package/corpus/templates/content/server/db/schema.ts +39 -3
  106. package/corpus/templates/content/server/plugins/db.ts +30 -0
  107. package/corpus/templates/content/shared/api.ts +75 -2
  108. package/corpus/templates/design/actions/generate-design.ts +10 -7
  109. package/corpus/templates/design/actions/present-design-variants.ts +35 -6
  110. package/corpus/templates/design/actions/run-design-audit.ts +33 -0
  111. package/corpus/templates/design/changelog/2026-08-13-the-design-audit-now-catches-a-screen-that-renders-behind-an.md +6 -0
  112. package/corpus/templates/design/shared/design-review.ts +1 -0
  113. package/corpus/templates/design/shared/html-integrity.ts +66 -0
  114. package/corpus/templates/dispatch/.env.example +5 -0
  115. package/corpus/templates/dispatch/AGENTS.md +24 -19
  116. package/corpus/templates/dispatch/app/i18n-data.ts +20 -0
  117. package/corpus/templates/dispatch/server/lib/identity-sso.ts +21 -90
  118. package/corpus/templates/dispatch/server/plugins/identity-sso.ts +3 -12
  119. package/corpus/templates/dispatch/shared/feature-flags.ts +4 -0
  120. package/corpus/templates/factory/AGENTS.md +5 -1
  121. package/corpus/templates/factory/README.md +23 -0
  122. package/corpus/templates/factory/actions/view-screen.ts +17 -0
  123. package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +239 -0
  124. package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +2 -0
  125. package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +130 -7
  126. package/corpus/templates/factory/app/i18n/en-US.ts +20 -0
  127. package/corpus/templates/factory/app/routes/factory.tsx +41 -0
  128. package/corpus/templates/factory/package.json +1 -0
  129. package/corpus/templates/factory/server/factory-graph/contracts.ts +2 -0
  130. package/corpus/templates/factory/server/plugins/agent-chat.ts +9 -0
  131. package/corpus/templates/factory/server/plugins/dispatch-db.ts +1 -0
  132. package/corpus/templates/factory/server/plugins/setup-dispatch.ts +3 -0
  133. package/corpus/templates/mail/app/lib/native-mcp-exclusions.ts +3 -0
  134. package/corpus/templates/mail/vite.config.ts +7 -0
  135. package/corpus/templates/plan/actions/reply-to-plan-comment.ts +7 -2
  136. package/corpus/templates/plan/actions/resolve-plan-comment.ts +2 -2
  137. package/corpus/templates/plan/actions/update-visual-plan.ts +1 -1
  138. package/corpus/templates/plan/app/pages/PlansPage.tsx +29 -20
  139. package/corpus/templates/slides/actions/add-slide-comment.ts +1 -1
  140. package/corpus/templates/slides/actions/update-slide-comment.ts +1 -1
  141. package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +9 -6
  142. package/dist/action.d.ts +22 -0
  143. package/dist/action.js +27 -0
  144. package/dist/agent/production-agent.js +5 -1
  145. package/dist/agent/thread-data-builder.js +17 -1
  146. package/dist/cli/skills-content/help.js +6 -4
  147. package/dist/cli/skills.js +17 -2
  148. package/dist/cli/workspacify.d.ts +5 -0
  149. package/dist/cli/workspacify.js +65 -8
  150. package/dist/client/AgentPanel.d.ts +5 -0
  151. package/dist/client/AgentPanel.js +20 -4
  152. package/dist/client/AssistantChat.d.ts +21 -0
  153. package/dist/client/AssistantChat.js +66 -68
  154. package/dist/client/active-run-state.d.ts +14 -1
  155. package/dist/client/active-run-state.js +0 -0
  156. package/dist/client/agent-chat-adapter.js +107 -5
  157. package/dist/client/analytics.js +9 -2
  158. package/dist/client/chat/tool-call-display.js +4 -4
  159. package/dist/client/chat-first/apps-rail.js +9 -4
  160. package/dist/client/chat-first/primary-nav.d.ts +2 -1
  161. package/dist/client/chat-first/primary-nav.js +3 -3
  162. package/dist/client/chat-first/types.d.ts +5 -1
  163. package/dist/client/markdown/InlineMarkdown.d.ts +23 -0
  164. package/dist/client/markdown/InlineMarkdown.js +65 -0
  165. package/dist/client/markdown/index.d.ts +1 -0
  166. package/dist/client/markdown/index.js +1 -0
  167. package/dist/client/review/ReviewThreadPanel.js +2 -1
  168. package/dist/client/run-stream-ownership.d.ts +39 -0
  169. package/dist/client/run-stream-ownership.js +65 -0
  170. package/dist/collab/routes.d.ts +1 -1
  171. package/dist/collab/struct-routes.d.ts +1 -1
  172. package/dist/feature-flags/index.d.ts +1 -1
  173. package/dist/feature-flags/index.js +1 -1
  174. package/dist/feature-flags/store.d.ts +10 -0
  175. package/dist/feature-flags/store.js +112 -1
  176. package/dist/guards/no-env-credentials.js +4 -0
  177. package/dist/index.browser.d.ts +1 -1
  178. package/dist/index.browser.js +1 -1
  179. package/dist/index.d.ts +2 -2
  180. package/dist/index.js +2 -2
  181. package/dist/integrations/adapters/slack.js +5 -1
  182. package/dist/localization/default-messages.d.ts +1 -0
  183. package/dist/localization/default-messages.js +1 -0
  184. package/dist/notifications/routes.d.ts +1 -1
  185. package/dist/observability/routes.d.ts +1 -1
  186. package/dist/progress/routes.d.ts +1 -1
  187. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  188. package/dist/provider-api/actions/provider-api.d.ts +15 -15
  189. package/dist/resources/agents.js +40 -5
  190. package/dist/resources/handlers.d.ts +1 -1
  191. package/dist/resources/metadata.d.ts +10 -0
  192. package/dist/resources/metadata.js +7 -3
  193. package/dist/review/actions/create-review-comment.js +1 -1
  194. package/dist/review/actions/reply-review-comment.js +1 -1
  195. package/dist/review/actions/resolve-review-thread.js +1 -1
  196. package/dist/server/action-routes.js +42 -8
  197. package/dist/server/agent-discovery.js +14 -3
  198. package/dist/server/core-routes-plugin.js +1 -1
  199. package/dist/server/identity-sso-migrations.d.ts +7 -0
  200. package/dist/server/identity-sso-migrations.js +36 -0
  201. package/dist/server/identity-sso-store.d.ts +3 -2
  202. package/dist/server/identity-sso-store.js +8 -3
  203. package/dist/server/realtime-token.d.ts +1 -1
  204. package/dist/server/release-migrations.js +4 -0
  205. package/dist/tracking/providers.js +13 -3
  206. package/dist/workspace-files/tool.js +1 -1
  207. package/package.json +3 -2
@@ -75,9 +75,11 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
75
75
  user: "user";
76
76
  }>>;
77
77
  }, z.core.$strip>>, {
78
- deleted?: undefined;
79
78
  id?: undefined;
80
79
  provider?: undefined;
80
+ deleted?: undefined;
81
+ found?: undefined;
82
+ message?: undefined;
81
83
  providers: {
82
84
  id: string;
83
85
  label: string;
@@ -88,46 +90,44 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
88
90
  updatedAt: number;
89
91
  }[];
90
92
  count: number;
91
- found?: undefined;
92
93
  registered?: undefined;
93
94
  label?: undefined;
94
- message?: undefined;
95
95
  } | {
96
- deleted?: undefined;
97
96
  id?: undefined;
97
+ deleted?: undefined;
98
+ message?: undefined;
98
99
  providers?: undefined;
99
100
  count?: undefined;
100
101
  found: boolean;
101
102
  provider: import("../custom-registry.js").CustomProviderConfig;
102
103
  registered?: undefined;
103
104
  label?: undefined;
104
- message?: undefined;
105
105
  } | {
106
- deleted?: undefined;
107
106
  provider?: undefined;
107
+ deleted?: undefined;
108
+ message?: undefined;
108
109
  providers?: undefined;
109
110
  count?: undefined;
110
111
  found: boolean;
111
112
  id: string;
112
113
  registered?: undefined;
113
114
  label?: undefined;
114
- message?: undefined;
115
115
  } | {
116
116
  provider?: undefined;
117
+ found?: undefined;
118
+ message?: undefined;
117
119
  providers?: undefined;
118
120
  count?: undefined;
119
- found?: undefined;
120
121
  deleted: boolean;
121
122
  id: string;
122
123
  registered?: undefined;
123
124
  label?: undefined;
124
- message?: undefined;
125
125
  } | {
126
- deleted?: undefined;
127
126
  provider?: undefined;
127
+ deleted?: undefined;
128
+ found?: undefined;
128
129
  providers?: undefined;
129
130
  count?: undefined;
130
- found?: undefined;
131
131
  registered: boolean;
132
132
  id: string;
133
133
  label: string;
@@ -311,9 +311,8 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
311
311
  notes?: string | undefined;
312
312
  scope?: "org" | "user" | undefined;
313
313
  }, {
314
- message?: undefined;
315
314
  id?: undefined;
316
- deleted?: undefined;
315
+ found?: undefined;
317
316
  providers: {
318
317
  id: string;
319
318
  label: string;
@@ -325,45 +324,46 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
325
324
  }[];
326
325
  count: number;
327
326
  provider?: undefined;
328
- found?: undefined;
327
+ deleted?: undefined;
329
328
  registered?: undefined;
330
329
  label?: undefined;
331
- } | {
332
330
  message?: undefined;
333
- count?: undefined;
331
+ } | {
334
332
  id?: undefined;
335
- deleted?: undefined;
336
333
  providers?: undefined;
334
+ count?: undefined;
337
335
  found: boolean;
338
336
  provider: import("../custom-registry.js").CustomProviderConfig;
337
+ deleted?: undefined;
339
338
  registered?: undefined;
340
339
  label?: undefined;
341
- } | {
342
340
  message?: undefined;
343
- count?: undefined;
344
- deleted?: undefined;
341
+ } | {
345
342
  providers?: undefined;
343
+ count?: undefined;
346
344
  provider?: undefined;
347
345
  found: boolean;
348
346
  id: string;
347
+ deleted?: undefined;
349
348
  registered?: undefined;
350
349
  label?: undefined;
351
- } | {
352
350
  message?: undefined;
353
- count?: undefined;
351
+ } | {
352
+ found?: undefined;
354
353
  providers?: undefined;
354
+ count?: undefined;
355
355
  provider?: undefined;
356
- found?: undefined;
357
356
  deleted: boolean;
358
357
  id: string;
359
358
  registered?: undefined;
360
359
  label?: undefined;
360
+ message?: undefined;
361
361
  } | {
362
- count?: undefined;
363
- deleted?: undefined;
362
+ found?: undefined;
364
363
  providers?: undefined;
364
+ count?: undefined;
365
365
  provider?: undefined;
366
- found?: undefined;
366
+ deleted?: undefined;
367
367
  registered: boolean;
368
368
  id: string;
369
369
  label: string;
@@ -1,5 +1,35 @@
1
- import { parseCustomAgentProfile, } from "./metadata.js";
1
+ import { getResourceKind, parseCustomAgentProfile, } from "./metadata.js";
2
2
  import { resourceGet, resourceGetByPath, resourceListAccessible, SHARED_OWNER, } from "./store.js";
3
+ function metadataFields(metadata) {
4
+ if (!metadata)
5
+ return {};
6
+ try {
7
+ const parsed = JSON.parse(metadata);
8
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
9
+ ? parsed
10
+ : null;
11
+ // coercion-ok: malformed resource metadata is absent, not a valid profile field
12
+ }
13
+ catch (_error) {
14
+ return null;
15
+ }
16
+ }
17
+ async function enrichAgentProfile(owner, profile, accessibleResources) {
18
+ const root = profile.path.replace(/\.md$/i, "");
19
+ const resources = accessibleResources ?? (await resourceListAccessible(owner, `${root}/`));
20
+ const workspace = resources.map((resource) => {
21
+ const metadata = metadataFields(resource.metadata) ?? {};
22
+ return {
23
+ path: resource.path,
24
+ kind: getResourceKind(resource.path),
25
+ name: typeof metadata.name === "string" ? metadata.name : undefined,
26
+ description: typeof metadata.description === "string"
27
+ ? metadata.description
28
+ : undefined,
29
+ };
30
+ });
31
+ return { ...profile, workspace: { root, resources: workspace } };
32
+ }
3
33
  export async function listAccessibleCustomAgents(owner) {
4
34
  const resources = await resourceListAccessible(owner, "agents/");
5
35
  const profiles = await Promise.all(resources
@@ -8,9 +38,14 @@ export async function listAccessibleCustomAgents(owner) {
8
38
  const full = await resourceGet(resource.id);
9
39
  if (!full)
10
40
  return null;
11
- return parseCustomAgentProfile(full.content, resource.path);
41
+ const profile = parseCustomAgentProfile(full.content, resource.path);
42
+ return profile;
43
+ }));
44
+ const validProfiles = profiles.filter((profile) => !!profile);
45
+ return Promise.all(validProfiles.map((profile) => {
46
+ const root = `${profile.path.replace(/\.md$/i, "")}/`;
47
+ return enrichAgentProfile(owner, profile, resources.filter((resource) => resource.path.startsWith(root)));
12
48
  }));
13
- return profiles.filter((profile) => !!profile);
14
49
  }
15
50
  export async function findAccessibleCustomAgent(owner, identifier) {
16
51
  const trimmed = identifier.trim();
@@ -26,13 +61,13 @@ export async function findAccessibleCustomAgent(owner, identifier) {
26
61
  if (personal) {
27
62
  const profile = parseCustomAgentProfile(personal.content, personal.path);
28
63
  if (profile)
29
- return profile;
64
+ return enrichAgentProfile(owner, profile);
30
65
  }
31
66
  const shared = await resourceGetByPath(SHARED_OWNER, path);
32
67
  if (shared) {
33
68
  const profile = parseCustomAgentProfile(shared.content, shared.path);
34
69
  if (profile)
35
- return profile;
70
+ return enrichAgentProfile(owner, profile);
36
71
  }
37
72
  }
38
73
  const lower = trimmed.toLowerCase();
@@ -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;
@@ -11,6 +11,12 @@ export interface SkillMetadata {
11
11
  name: string;
12
12
  description?: string;
13
13
  }
14
+ export interface AgentWorkspaceResource {
15
+ path: string;
16
+ kind: ResourceKind;
17
+ name?: string;
18
+ description?: string;
19
+ }
14
20
  export interface CustomAgentProfile {
15
21
  id: string;
16
22
  path: string;
@@ -21,6 +27,10 @@ export interface CustomAgentProfile {
21
27
  color?: string;
22
28
  delegateDefault?: boolean;
23
29
  instructions: string;
30
+ workspace?: {
31
+ root: string;
32
+ resources: AgentWorkspaceResource[];
33
+ };
24
34
  }
25
35
  export interface RemoteAgentManifest {
26
36
  id: string;
@@ -81,15 +81,19 @@ export function frontmatterFieldsToObject(frontmatter) {
81
81
  return Object.fromEntries(frontmatter?.fields.map((f) => [f.key, f.value]) ?? []);
82
82
  }
83
83
  export function isSkillPath(path) {
84
- if (!path.startsWith("skills/") || !path.endsWith(".md"))
84
+ const prefix = path.startsWith("skills/")
85
+ ? "skills/"
86
+ : path.match(/^agents\/[^/]+\/skills\//)?.[0];
87
+ if (!prefix || !path.endsWith(".md"))
85
88
  return false;
86
- const relative = path.replace(/^skills\//, "");
89
+ const relative = path.slice(prefix.length);
87
90
  return (relative.endsWith("/SKILL.md") ||
88
91
  (relative.endsWith(".md") && !relative.includes("/")));
89
92
  }
90
93
  export function getSkillNameFromPath(path) {
91
94
  const relative = path
92
95
  .replace(/^\.agents\/skills\//, "")
96
+ .replace(/^agents\/[^/]+\/skills\//, "")
93
97
  .replace(/^skills\//, "");
94
98
  if (relative.endsWith("/SKILL.md")) {
95
99
  return (relative
@@ -103,7 +107,7 @@ export function isJobPath(path) {
103
107
  return path.startsWith("jobs/") && path.endsWith(".md");
104
108
  }
105
109
  export function isCustomAgentPath(path) {
106
- return path.startsWith("agents/") && path.endsWith(".md");
110
+ return /^agents\/[^/]+\.md$/.test(path);
107
111
  }
108
112
  export function isRemoteAgentPath(path) {
109
113
  return (path.endsWith(".json") &&
@@ -32,7 +32,7 @@ const schema = z.object({
32
32
  metadata: z.record(z.string(), z.unknown()).optional(),
33
33
  });
34
34
  export default defineAction({
35
- description: "Create an inline comment, annotation, or review thread for a resource.",
35
+ description: "Create an inline comment, annotation, or review thread for a resource. Body text supports inline Markdown without headings.",
36
36
  schema,
37
37
  run: async (args, ctx) => {
38
38
  const actionCtx = ctx;
@@ -21,7 +21,7 @@ const schema = z.object({
21
21
  metadata: z.record(z.string(), z.unknown()).optional(),
22
22
  });
23
23
  export default defineAction({
24
- description: "Reply to an existing review comment thread.",
24
+ description: "Reply to an existing review comment thread with inline Markdown text without headings.",
25
25
  schema,
26
26
  run: async (args, ctx) => {
27
27
  const actionCtx = ctx;
@@ -10,7 +10,7 @@ const schema = z.object({
10
10
  resolutionNote: z.string().trim().min(1).max(2_000).optional(),
11
11
  });
12
12
  export default defineAction({
13
- description: "Resolve an inline comment or review thread.",
13
+ description: "Resolve an inline comment or review thread. An optional resolution note supports inline Markdown without headings.",
14
14
  schema,
15
15
  run: async (args, ctx) => {
16
16
  const actionCtx = ctx;
@@ -1,6 +1,7 @@
1
1
  import { createError, defineEventHandler, setResponseStatus, setResponseHeader, getMethod, getQuery, getHeader, getRequestURL, } from "h3";
2
2
  import { verifyA2ATokenWithClaims } from "../a2a-claims.js";
3
- import { isAgentActionStopError } from "../action.js";
3
+ import { isActionContractError, isAgentActionStopError } from "../action.js";
4
+ import { isTransientDatabaseError } from "../db/client.js";
4
5
  import { declaresFeatureFlagDelegation } from "../feature-flags/a2a-action-route.js";
5
6
  import { resolveOrgByDomain, resolveOrgIdForEmail } from "../org/context.js";
6
7
  import { readBody } from "../server/h3-helpers.js";
@@ -177,6 +178,34 @@ function normalizeOrgId(value) {
177
178
  ? value.trim()
178
179
  : undefined;
179
180
  }
181
+ function isFirstBootMissingOrgTableError(error) {
182
+ if (!(error instanceof Error))
183
+ return false;
184
+ return (/no such table:?\s*["'`]?org_members["'`]?/i.test(error.message) ||
185
+ /relation\s+["'`]?org_members["'`]?\s+does not exist/i.test(error.message));
186
+ }
187
+ /**
188
+ * The user's stored active org, for a request whose own org resolution came
189
+ * back empty. An empty `orgId` is not "this user has no org": it silently
190
+ * narrows every scoped read to rows with a null `org_id`, so a session minted
191
+ * before org selection — or one whose membership read failed — stops seeing
192
+ * the user's own org-scoped dashboards, credentials, and resources. This
193
+ * honors an explicit Personal selection by returning undefined, so it can
194
+ * never promote a user into an org they left. A transient database failure is
195
+ * not an answer and propagates.
196
+ */
197
+ async function storedActiveOrgId(email) {
198
+ try {
199
+ return normalizeOrgId(await resolveOrgIdForEmail(email));
200
+ }
201
+ catch (error) {
202
+ if (isTransientDatabaseError(error) ||
203
+ !isFirstBootMissingOrgTableError(error)) {
204
+ throw error;
205
+ }
206
+ return undefined;
207
+ }
208
+ }
180
209
  function isAuthResolutionFailure(error) {
181
210
  if (!error || typeof error !== "object")
182
211
  return false;
@@ -344,18 +373,15 @@ export function mountActionRoutes(nitroApp, actions, options) {
344
373
  if (resolvedCaller) {
345
374
  orgId = normalizeOrgId(resolvedCaller.orgId);
346
375
  if (!orgId && resolvedCaller.owner && !resolvedCaller.anonymous) {
347
- try {
348
- orgId = normalizeOrgId(await resolveOrgIdForEmail(resolvedCaller.owner));
349
- }
350
- catch {
351
- // Org tables may not exist yet on first boot.
352
- }
376
+ orgId = await storedActiveOrgId(resolvedCaller.owner);
353
377
  }
354
378
  }
355
379
  else {
356
380
  orgId = options?.resolveOrgId
357
381
  ? ((await options.resolveOrgId(event)) ?? undefined)
358
382
  : undefined;
383
+ if (!orgId && userEmail)
384
+ orgId = await storedActiveOrgId(userEmail);
359
385
  }
360
386
  const timezone = readTimezoneHeader(event);
361
387
  const browserSessionId = readBrowserSessionIdHeader(event);
@@ -507,7 +533,15 @@ export function mountActionRoutes(nitroApp, actions, options) {
507
533
  isAgentActionStopError(err) ||
508
534
  (explicitStatus !== undefined && explicitStatus < 500);
509
535
  if (isUserFacing) {
510
- return { error: msg };
536
+ return isActionContractError(err)
537
+ ? {
538
+ error: msg,
539
+ errorCode: err.errorCode,
540
+ ...(err.details === undefined
541
+ ? {}
542
+ : { details: err.details }),
543
+ }
544
+ : { error: msg };
511
545
  }
512
546
  const requestId = getHttpRequestTelemetryId(event);
513
547
  const captureId = captureError(err, {
@@ -214,11 +214,22 @@ export async function discoverAgents(selfAppId, options) {
214
214
  }
215
215
  // Overlay custom agents from resources
216
216
  try {
217
- const { resourceList, resourceGet, SHARED_OWNER } = await import("../resources/store.js");
217
+ const { resourceList, resourceGet, SHARED_OWNER, sharedResourceOwner } = await import("../resources/store.js");
218
218
  const { parseRemoteAgentManifest, REMOTE_AGENT_RESOURCE_PREFIXES } = await import("../resources/metadata.js");
219
+ const activeOwner = sharedResourceOwner(getRequestOrgId());
220
+ const owners = [...new Set([SHARED_OWNER, activeOwner])];
219
221
  const resources = [];
220
- for (const prefix of [...REMOTE_AGENT_RESOURCE_PREFIXES].reverse()) {
221
- resources.push(...(await resourceList(SHARED_OWNER, prefix)));
222
+ const seenResources = new Set();
223
+ for (const owner of owners) {
224
+ for (const prefix of [...REMOTE_AGENT_RESOURCE_PREFIXES].reverse()) {
225
+ for (const resource of await resourceList(owner, prefix)) {
226
+ const resourceKey = `${owner}\0${resource.id}`;
227
+ if (seenResources.has(resourceKey))
228
+ continue;
229
+ seenResources.add(resourceKey);
230
+ resources.push(resource);
231
+ }
232
+ }
222
233
  }
223
234
  for (const r of resources) {
224
235
  if (!r.path.endsWith(".json"))
@@ -624,7 +624,7 @@ function isAgentNativeAnonymousOwner(email) {
624
624
  return /^anon-[^@]+@agent-native\.com$/i.test(email ?? "");
625
625
  }
626
626
  export async function resolveBuilderOwnerContextForRequest(event, options = {}, mode) {
627
- const searchParams = getRequestURL(event).searchParams;
627
+ const searchParams = getFrameworkRouteRequestUrl(event).searchParams;
628
628
  const signedOwner = mode === "connect"
629
629
  ? verifyBuilderConnectTokenAndGetOwner(searchParams.get(BUILDER_CONNECT_PARAM))
630
630
  : mode === "callback"
@@ -0,0 +1,7 @@
1
+ import type { MigrationEntry } from "../db/migrations.js";
2
+ /**
3
+ * Cross-app SSO state belongs to every app that can receive a callback. Keep
4
+ * these tables in the framework release migration so production serverless
5
+ * requests never need to create schema before starting a login.
6
+ */
7
+ export declare const IDENTITY_SSO_MIGRATIONS: MigrationEntry[];
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Cross-app SSO state belongs to every app that can receive a callback. Keep
3
+ * these tables in the framework release migration so production serverless
4
+ * requests never need to create schema before starting a login.
5
+ */
6
+ export const IDENTITY_SSO_MIGRATIONS = [
7
+ {
8
+ version: 1,
9
+ name: "identity-sso-flow-state-and-jti",
10
+ sql: `
11
+ CREATE TABLE IF NOT EXISTS identity_sso_flow_state (
12
+ state TEXT PRIMARY KEY,
13
+ return_path TEXT,
14
+ app_id TEXT NOT NULL,
15
+ client_id TEXT NOT NULL,
16
+ redirect_uri TEXT NOT NULL,
17
+ authority TEXT NOT NULL,
18
+ code_challenge TEXT NOT NULL,
19
+ created_at INTEGER,
20
+ expires_at INTEGER,
21
+ consumed_at INTEGER
22
+ );
23
+
24
+ CREATE INDEX IF NOT EXISTS identity_sso_flow_state_expires_idx
25
+ ON identity_sso_flow_state (expires_at);
26
+
27
+ CREATE TABLE IF NOT EXISTS identity_sso_jti (
28
+ jti TEXT PRIMARY KEY,
29
+ seen_at INTEGER
30
+ );
31
+
32
+ CREATE INDEX IF NOT EXISTS identity_sso_jti_seen_idx
33
+ ON identity_sso_jti (seen_at);
34
+ `,
35
+ },
36
+ ];
@@ -11,8 +11,9 @@
11
11
  * server-to-server assertions, including identity SSO and privileged A2A
12
12
  * mutations.
13
13
  *
14
- * Uses the same portable raw-SQL pattern as the other framework stores. DDL is
15
- * additive and lazy, and PostgreSQL creation goes through the DDL guard.
14
+ * Uses the same portable raw-SQL pattern as the other framework stores. Local
15
+ * development may initialize these tables lazily; production release
16
+ * migrations own their creation before serverless requests are served.
16
17
  */
17
18
  export declare const SSO_STATE_TTL_MS: number;
18
19
  export declare const SSO_LOGIN_MAX = 60;
@@ -11,11 +11,12 @@
11
11
  * server-to-server assertions, including identity SSO and privileged A2A
12
12
  * mutations.
13
13
  *
14
- * Uses the same portable raw-SQL pattern as the other framework stores. DDL is
15
- * additive and lazy, and PostgreSQL creation goes through the DDL guard.
14
+ * Uses the same portable raw-SQL pattern as the other framework stores. Local
15
+ * development may initialize these tables lazily; production release
16
+ * migrations own their creation before serverless requests are served.
16
17
  */
17
18
  import { randomBytes } from "node:crypto";
18
- import { getDbExec, intType, isConnectionError, isPostgres, } from "../db/client.js";
19
+ import { getDbExec, intType, isConnectionError, isPostgres, isProductionServerlessFunctionRuntime, } from "../db/client.js";
19
20
  import { ensureTableExists } from "../db/ddl-guard.js";
20
21
  let _initPromise;
21
22
  const DESKTOP_SSO_CANARY_USER_AGENT = /AgentNativeDesktopSsoCanary\//i;
@@ -138,6 +139,10 @@ function buildIdentitySsoJtiCreateSql() {
138
139
  `;
139
140
  }
140
141
  async function ensureTable() {
142
+ // Release migrations own schema in production serverless functions. A
143
+ // request must not turn a missing migration into request-time DDL.
144
+ if (isProductionServerlessFunctionRuntime())
145
+ return;
141
146
  if (!_initPromise) {
142
147
  _initPromise = (async () => {
143
148
  const flowStateSql = buildIdentitySsoFlowStateCreateSql();
@@ -26,8 +26,8 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
26
26
  expiresAt?: undefined;
27
27
  ttlSeconds?: undefined;
28
28
  } | {
29
- error?: undefined;
30
29
  token: string;
31
30
  expiresAt: string;
32
31
  ttlSeconds: number;
32
+ error?: undefined;
33
33
  }>>;
@@ -7,6 +7,7 @@ import { runAutomationSchedulerHealthMigrations } from "../jobs/scheduler-health
7
7
  import { OAUTH_TOKEN_MIGRATIONS, OAUTH_TOKEN_MIGRATIONS_TABLE, } from "../oauth-tokens/migrations.js";
8
8
  import { ORG_MIGRATIONS } from "../org/migrations.js";
9
9
  import { runBetterAuthMigrations } from "./better-auth-migrations.js";
10
+ import { IDENTITY_SSO_MIGRATIONS } from "./identity-sso-migrations.js";
10
11
  /**
11
12
  * Apply framework-owned schema in one explicit release step.
12
13
  *
@@ -23,6 +24,9 @@ export async function runFrameworkReleaseMigrations(nitroApp) {
23
24
  table: OAUTH_TOKEN_MIGRATIONS_TABLE,
24
25
  })(nitroApp);
25
26
  await runMigrations(ORG_MIGRATIONS, { table: "_org_migrations" })(nitroApp);
27
+ await runMigrations(IDENTITY_SSO_MIGRATIONS, {
28
+ table: "_identity_sso_migrations",
29
+ })(nitroApp);
26
30
  await runMigrations(CONTEXT_XRAY_MIGRATIONS, {
27
31
  table: "_context_xray_migrations",
28
32
  })(nitroApp);
@@ -257,6 +257,18 @@ function createMixpanelProvider(token) {
257
257
  };
258
258
  }
259
259
  // ─── Amplitude ─────────────────────────────────────────────────────────────
260
+ function stripExceptionContextForAmplitude(properties) {
261
+ const { exceptionTags: _exceptionTags, exceptionExtra: _exceptionExtra, ...stableProperties } = properties;
262
+ return stableProperties;
263
+ }
264
+ function amplitudeEventProperties(event) {
265
+ const properties = event.name === "$exception" && event.properties
266
+ ? stripExceptionContextForAmplitude(event.properties)
267
+ : event.properties;
268
+ if (!event.sessionId)
269
+ return properties;
270
+ return { ...(properties ?? {}), session_id: event.sessionId };
271
+ }
260
272
  function createAmplitudeProvider(apiKey) {
261
273
  return {
262
274
  name: "amplitude",
@@ -269,9 +281,7 @@ function createAmplitudeProvider(apiKey) {
269
281
  user_id: event.userId || "anonymous",
270
282
  // Amplitude's top-level `session_id` must be a numeric epoch, so
271
283
  // the browser session ships as an event property instead.
272
- event_properties: event.sessionId
273
- ? { ...event.properties, session_id: event.sessionId }
274
- : event.properties,
284
+ event_properties: amplitudeEventProperties(event),
275
285
  time: event.timestamp
276
286
  ? new Date(event.timestamp).getTime()
277
287
  : undefined,
@@ -34,7 +34,7 @@ export function createWorkspaceFilesTool() {
34
34
  "Use scratch/... for temporary intermediate results; scratch files are hidden from the Resources view by default and expire. Use durable folder names for files the user explicitly wants to keep/manage.",
35
35
  "Use this to stage large intermediate results (fetched pages, per-item analysis memos, API payloads) so they don't consume context window, then read them back selectively for synthesis.",
36
36
  "",
37
- "Typical fusion-style workflow:",
37
+ "Typical staged-analysis workflow:",
38
38
  " 1. Fan out: for each item, fetch data and `write` a per-item memo file.",
39
39
  " 2. Synthesize: `list` files, then `read` each memo (with offset/maxChars to page large ones).",
40
40
  " 3. Optionally `grep` across all memos to find patterns.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.154.4",
3
+ "version": "0.155.0",
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": {
@@ -116,6 +116,7 @@
116
116
  "./client/automation": "./dist/client/automation/index.js",
117
117
  "./client/chat": "./dist/client/chat/index.js",
118
118
  "./client/changelog": "./dist/client/changelog/index.js",
119
+ "./client/markdown": "./dist/client/markdown/index.js",
119
120
  "./client/collab": "./dist/client/collab/index.js",
120
121
  "./client/composer": "./dist/client/composer/index.js",
121
122
  "./client/conversation": "./dist/client/conversation/index.js",
@@ -423,7 +424,7 @@
423
424
  "yjs": "^13.6.31",
424
425
  "zod": "^4.3.6",
425
426
  "@agent-native/recap-cli": "0.5.4",
426
- "@agent-native/toolkit": "^0.14.2"
427
+ "@agent-native/toolkit": "^0.14.3"
427
428
  },
428
429
  "devDependencies": {
429
430
  "@ai-sdk/anthropic": "^3.0.71",