@agent-native/core 0.189.0 → 0.190.0-nightly-20260925215540

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 (234) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +10 -0
  3. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +1 -1
  4. package/corpus/templates/analytics/AGENTS.md +11 -22
  5. package/corpus/templates/analytics/actions/list-data-dictionary.ts +7 -9
  6. package/corpus/templates/analytics/actions/search-analytics-query-catalog.ts +1 -1
  7. package/corpus/templates/analytics/app/components/AnalyticsReviewArtifactPreview.tsx +201 -0
  8. package/corpus/templates/analytics/app/i18n/en-US.ts +2 -0
  9. package/corpus/templates/analytics/app/pages/Settings.tsx +50 -3
  10. package/corpus/templates/analytics/changelog/2026-09-25-first-run-onboarding-records-setup-choices-and-builder-conne.md +6 -0
  11. package/corpus/templates/analytics/changelog/2026-09-25-human-review-previews-analytics-dashboards-as-real-charts.md +6 -0
  12. package/corpus/templates/analytics/changelog/2026-09-25-org-admins-can-review-agent-runs-from-settings.md +6 -0
  13. package/corpus/templates/analytics/changelog/2026-09-25-proactive-query-context.md +6 -0
  14. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +98 -2
  15. package/corpus/templates/analytics/server/lib/analytics-agent-context.ts +557 -0
  16. package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +217 -46
  17. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +2 -2
  18. package/corpus/templates/analytics/server/lib/dashboards-store.ts +39 -5
  19. package/corpus/templates/analytics/server/lib/data-dictionary-context.ts +4 -0
  20. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +268 -2
  21. package/corpus/templates/analytics/server/plugins/agent-chat.ts +44 -9
  22. package/corpus/templates/calendar/AGENTS.md +5 -0
  23. package/corpus/templates/calendar/CHANGELOG.md +6 -0
  24. package/corpus/templates/calendar/actions/get-event-rules-status.ts +47 -0
  25. package/corpus/templates/calendar/actions/list-events.ts +50 -4
  26. package/corpus/templates/calendar/actions/undo-calendar-event-rule.ts +229 -0
  27. package/corpus/templates/calendar/actions/update-settings.ts +8 -0
  28. package/corpus/templates/calendar/app/i18n/en-US.ts +27 -0
  29. package/corpus/templates/calendar/app/pages/Settings.tsx +196 -1
  30. package/corpus/templates/calendar/changelog/2026-09-25-calendar-feeds-with-the-same-url-keep-their-own-names-and-co.md +6 -0
  31. package/corpus/templates/calendar/changelog/2026-09-25-calendar-invitation-rules-surface-expired-connections-and-un.md +6 -0
  32. package/corpus/templates/calendar/changelog/2026-09-25-restore-locally-hidden-events-from-activity-after-disconnect.md +6 -0
  33. package/corpus/templates/calendar/server/lib/calendar-settings.ts +44 -10
  34. package/corpus/templates/calendar/server/lib/google-api.ts +15 -1
  35. package/corpus/templates/calendar/server/lib/google-calendar.ts +1 -1
  36. package/corpus/templates/calendar/server/plugins/event-rules.ts +628 -0
  37. package/corpus/templates/calendar/shared/api.ts +13 -0
  38. package/corpus/templates/calendar/shared/settings.ts +71 -1
  39. package/corpus/templates/clips/actions/create-recording.ts +83 -2
  40. package/corpus/templates/clips/actions/finalize-recording.ts +610 -110
  41. package/corpus/templates/clips/actions/get-recording-player-data.ts +6 -0
  42. package/corpus/templates/clips/actions/import-loom-recording.ts +2 -0
  43. package/corpus/templates/clips/actions/lib/create-recording-schema.ts +7 -0
  44. package/corpus/templates/clips/actions/lib/loom-import-job.ts +15 -1
  45. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +126 -26
  46. package/corpus/templates/clips/app/hooks/use-drop-video-upload.ts +75 -15
  47. package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +5 -1
  48. package/corpus/templates/clips/app/routes/record.tsx +134 -40
  49. package/corpus/templates/clips/app/routes/share.$shareId.tsx +13 -1
  50. package/corpus/templates/clips/changelog/2026-09-25-signed-in-viewers-who-hit-an-unavailable-expired-or-private-.md +6 -0
  51. package/corpus/templates/clips/chrome-extension/src/background.ts +3 -0
  52. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +73 -16
  53. package/corpus/templates/clips/desktop/src/lib/recorder.ts +188 -18
  54. package/corpus/templates/clips/desktop/src/lib/recording-request.ts +1 -0
  55. package/corpus/templates/clips/server/db/schema.ts +4 -0
  56. package/corpus/templates/clips/server/jobs/media-verification.ts +78 -4
  57. package/corpus/templates/clips/server/jobs/recording-failure-backfill.ts +142 -0
  58. package/corpus/templates/clips/server/lib/media-verification-state.ts +29 -0
  59. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +2 -0
  60. package/corpus/templates/clips/server/lib/recording-failures.ts +111 -0
  61. package/corpus/templates/clips/server/lib/recordings.ts +6 -1
  62. package/corpus/templates/clips/server/lib/s3-upload-provider.ts +8 -3
  63. package/corpus/templates/clips/server/lib/upload-lease.ts +25 -6
  64. package/corpus/templates/clips/server/plugins/calendar-jobs.ts +2 -0
  65. package/corpus/templates/clips/server/plugins/db.ts +18 -0
  66. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +48 -5
  67. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +322 -31
  68. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +223 -61
  69. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +62 -4
  70. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +74 -7
  71. package/corpus/templates/clips/shared/recording-core.ts +27 -0
  72. package/corpus/templates/design/actions/get-design.ts +35 -6
  73. package/corpus/templates/mail/.agents/skills/inbox-automations/SKILL.md +4 -0
  74. package/corpus/templates/mail/actions/consolidate-ai-filter-rules.ts +41 -0
  75. package/corpus/templates/mail/actions/get-ai-priority.ts +48 -8
  76. package/corpus/templates/mail/actions/record-ai-priority-feedback.ts +69 -0
  77. package/corpus/templates/mail/actions/update-mail-preferences.ts +2 -0
  78. package/corpus/templates/mail/app/components/email/EmailList.tsx +179 -32
  79. package/corpus/templates/mail/app/components/email/EmailListItem.tsx +97 -9
  80. package/corpus/templates/mail/app/components/email/EmailThread.tsx +55 -1
  81. package/corpus/templates/mail/app/components/email/ImportanceFeedbackMenu.tsx +52 -0
  82. package/corpus/templates/mail/app/components/email/compose-autocomplete.ts +2 -1
  83. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +219 -188
  84. package/corpus/templates/mail/app/components/onboarding/AiInboxSetup.tsx +338 -0
  85. package/corpus/templates/mail/app/components/settings/AiFilterSection.tsx +597 -781
  86. package/corpus/templates/mail/app/components/settings/AiRulePromptField.tsx +37 -0
  87. package/corpus/templates/mail/app/global.css +42 -26
  88. package/corpus/templates/mail/app/hooks/use-ai-priority-feedback.ts +43 -0
  89. package/corpus/templates/mail/app/hooks/use-automations.ts +23 -0
  90. package/corpus/templates/mail/app/i18n/en-US.ts +58 -3
  91. package/corpus/templates/mail/app/pages/InboxPage.tsx +47 -10
  92. package/corpus/templates/mail/changelog/2026-09-25-editing-importance-rules-preserves-disabled-instructions-and.md +6 -0
  93. package/corpus/templates/mail/changelog/2026-09-25-handle-astral-unicode-letters-in-autocomplete-word-boundarie.md +6 -0
  94. package/corpus/templates/mail/changelog/2026-09-25-jev-priority-feedback-and-inbox-settings.md +6 -0
  95. package/corpus/templates/mail/changelog/2026-09-25-keep-existing-ai-filter-rules-intact-when-saving-a-prompt.md +6 -0
  96. package/corpus/templates/mail/server/lib/automation-engine.ts +21 -12
  97. package/corpus/templates/mail/server/lib/automations.ts +100 -1
  98. package/corpus/templates/mail/shared/types.ts +3 -0
  99. package/corpus/templates/plan/app/i18n/en-US.ts +6 -0
  100. package/corpus/templates/plan/app/lib/plan-invite-suggestion.ts +43 -0
  101. package/corpus/templates/plan/app/pages/PlansPage.tsx +249 -4
  102. package/corpus/templates/slides/actions/create-deck.ts +11 -1
  103. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +117 -1
  104. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +373 -330
  105. package/corpus/templates/slides/app/components/design-system/builder-index-response.ts +36 -5
  106. package/corpus/templates/slides/app/components/editor/BlockBubbleMenu.tsx +21 -53
  107. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +347 -671
  108. package/corpus/templates/slides/app/components/editor/bullet-editing.ts +55 -8
  109. package/corpus/templates/slides/app/components/editor/in-place-text-session.ts +2082 -0
  110. package/corpus/templates/slides/app/components/editor/list-editing.ts +174 -16
  111. package/corpus/templates/slides/app/components/editor/rich-text-selection.ts +497 -62
  112. package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +102 -20
  113. package/corpus/templates/slides/app/context/DeckContext.tsx +9 -4
  114. package/corpus/templates/slides/app/global.css +7 -219
  115. package/corpus/templates/slides/app/i18n/en-US.ts +3 -0
  116. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +7 -0
  117. package/corpus/templates/slides/app/lib/slide-image-replacement.ts +203 -1
  118. package/corpus/templates/slides/app/lib/slide-source-map.ts +43 -0
  119. package/corpus/templates/slides/app/pages/DeckEditor.tsx +182 -4
  120. package/corpus/templates/slides/app/routes/settings.tsx +33 -2
  121. package/corpus/templates/slides/changelog/2026-09-25-improve-slides-design-system-setup-feedback.md +6 -0
  122. package/corpus/templates/slides/changelog/2026-09-25-org-admins-can-review-agent-runs-from-settings.md +6 -0
  123. package/corpus/templates/slides/changelog/2026-09-25-text-on-a-slide-is-now-edited-in-place-clicking-into-it-chan.md +6 -0
  124. package/corpus/templates/slides/package.json +0 -12
  125. package/corpus/templates/slides/scripts/edit-fidelity/README.md +4 -2
  126. package/corpus/templates/slides/scripts/edit-fidelity/run.ts +12 -3
  127. package/corpus/templates/slides/vite.config.ts +1 -10
  128. package/dist/agent/jev-tool-prefetch.d.ts +29 -3
  129. package/dist/agent/jev-tool-prefetch.js +161 -34
  130. package/dist/agent/production-agent.d.ts +11 -0
  131. package/dist/agent/production-agent.js +39 -8
  132. package/dist/app-config/runtime.d.ts +1 -0
  133. package/dist/app-config/runtime.js +4 -0
  134. package/dist/app-config/schema.d.ts +1 -0
  135. package/dist/client/AgentSidebar.d.ts +3 -1
  136. package/dist/client/AgentSidebar.js +8 -12
  137. package/dist/client/analytics/index.d.ts +1 -1
  138. package/dist/client/analytics/index.js +1 -1
  139. package/dist/client/analytics.d.ts +2 -0
  140. package/dist/client/analytics.js +9 -0
  141. package/dist/client/api-path.js +5 -2
  142. package/dist/client/chat/run-recovery.d.ts +0 -3
  143. package/dist/client/chat/run-recovery.js +13 -23
  144. package/dist/client/index.d.ts +1 -1
  145. package/dist/client/index.js +1 -1
  146. package/dist/client/observability/ObservabilityDashboard.d.ts +3 -0
  147. package/dist/client/observability/ObservabilityDashboard.js +366 -71
  148. package/dist/client/observability/ObservabilityReviewSummaryButton.d.ts +4 -1
  149. package/dist/client/observability/ObservabilityReviewSummaryButton.js +13 -9
  150. package/dist/client/observability/OutputPreview.d.ts +9 -4
  151. package/dist/client/observability/OutputPreview.js +230 -52
  152. package/dist/client/onboarding/FirstRunOnboarding.js +67 -4
  153. package/dist/client/onboarding/use-onboarding.js +2 -0
  154. package/dist/client/sharing/ShareButton.d.ts +2 -0
  155. package/dist/client/sharing/ShareButton.js +1 -0
  156. package/dist/client/sharing/useShareButtonController.d.ts +1 -0
  157. package/dist/client/sharing/useShareButtonController.js +29 -8
  158. package/dist/collab/awareness.d.ts +2 -2
  159. package/dist/collab/struct-routes.d.ts +1 -1
  160. package/dist/deploy/build.js +9 -1
  161. package/dist/embeddings/index.d.ts +3 -1
  162. package/dist/embeddings/index.js +20 -10
  163. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  164. package/dist/jobs/sweep-hooks.d.ts +7 -0
  165. package/dist/jobs/sweep-hooks.js +28 -0
  166. package/dist/localization/default-messages.d.ts +1 -0
  167. package/dist/localization/default-messages.js +1 -0
  168. package/dist/notifications/routes.d.ts +6 -6
  169. package/dist/observability/actions/authorization.d.ts +1 -0
  170. package/dist/observability/actions/authorization.js +22 -0
  171. package/dist/observability/actions/get-observability-review-detail.d.ts +5 -0
  172. package/dist/observability/actions/get-observability-review-detail.js +10 -2
  173. package/dist/observability/actions/get-observability-review-summary-source.d.ts +2 -0
  174. package/dist/observability/actions/get-observability-review-summary-source.js +3 -2
  175. package/dist/observability/actions/save-observability-instruction-update.js +2 -1
  176. package/dist/observability/actions/save-observability-review-summary.js +21 -10
  177. package/dist/observability/migrations.js +25 -0
  178. package/dist/observability/reviews.d.ts +3 -1
  179. package/dist/observability/reviews.js +410 -53
  180. package/dist/observability/routes.d.ts +6 -6
  181. package/dist/observability/store.d.ts +15 -0
  182. package/dist/observability/store.js +131 -11
  183. package/dist/observability/types.d.ts +18 -0
  184. package/dist/org/handlers.d.ts +1 -1
  185. package/dist/org/index.d.ts +1 -1
  186. package/dist/progress/routes.d.ts +1 -1
  187. package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
  188. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  189. package/dist/server/agent-chat/plugin-options.d.ts +4 -20
  190. package/dist/server/agent-chat/prompt-resources.d.ts +16 -0
  191. package/dist/server/agent-chat/prompt-resources.js +385 -22
  192. package/dist/server/agent-chat-plugin.d.ts +3 -1
  193. package/dist/server/agent-chat-plugin.js +149 -27
  194. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  195. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  196. package/dist/server/index.d.ts +3 -0
  197. package/dist/server/index.js +3 -0
  198. package/dist/server/prompts/framework-core-compact.js +1 -1
  199. package/dist/server/prompts/framework-core.js +1 -1
  200. package/dist/server/request-context.d.ts +6 -3
  201. package/dist/settings/org-settings.d.ts +4 -2
  202. package/dist/settings/org-settings.js +3 -3
  203. package/dist/settings/store.d.ts +3 -1
  204. package/dist/settings/store.js +8 -3
  205. package/dist/styles/agent-native.css +5 -0
  206. package/dist/templates/default/app/i18n/ar-SA.ts +1 -0
  207. package/dist/templates/default/app/i18n/de-DE.ts +1 -0
  208. package/dist/templates/default/app/i18n/en-US.ts +1 -0
  209. package/dist/templates/default/app/i18n/es-ES.ts +1 -0
  210. package/dist/templates/default/app/i18n/fr-FR.ts +1 -0
  211. package/dist/templates/default/app/i18n/hi-IN.ts +1 -0
  212. package/dist/templates/default/app/i18n/ja-JP.ts +1 -0
  213. package/dist/templates/default/app/i18n/ko-KR.ts +1 -0
  214. package/dist/templates/default/app/i18n/pt-BR.ts +1 -0
  215. package/dist/templates/default/app/i18n/zh-CN.ts +1 -0
  216. package/dist/templates/default/app/i18n/zh-TW.ts +1 -0
  217. package/dist/tracking/registry.js +11 -4
  218. package/dist/vite/client.js +6 -0
  219. package/package.json +4 -3
  220. package/src/templates/default/app/i18n/ar-SA.ts +1 -0
  221. package/src/templates/default/app/i18n/de-DE.ts +1 -0
  222. package/src/templates/default/app/i18n/en-US.ts +1 -0
  223. package/src/templates/default/app/i18n/es-ES.ts +1 -0
  224. package/src/templates/default/app/i18n/fr-FR.ts +1 -0
  225. package/src/templates/default/app/i18n/hi-IN.ts +1 -0
  226. package/src/templates/default/app/i18n/ja-JP.ts +1 -0
  227. package/src/templates/default/app/i18n/ko-KR.ts +1 -0
  228. package/src/templates/default/app/i18n/pt-BR.ts +1 -0
  229. package/src/templates/default/app/i18n/zh-CN.ts +1 -0
  230. package/src/templates/default/app/i18n/zh-TW.ts +1 -0
  231. package/corpus/templates/slides/app/components/editor/SlideBubbleMenu.tsx +0 -488
  232. package/corpus/templates/slides/app/components/editor/SlideInlineEditor.tsx +0 -589
  233. package/corpus/templates/slides/app/components/editor/SlideRichTextEditor.tsx +0 -1347
  234. package/corpus/templates/slides/app/components/editor/SlideSlashMenu.tsx +0 -373
@@ -1,9 +1,9 @@
1
- import { rankJevCandidates, } from "../../agent/jev-tool-prefetch.js";
1
+ import { JEV_TIMEOUT_MS, rankJevCandidatesWithStatus, } from "../../agent/jev-tool-prefetch.js";
2
2
  import { frameworkGroupEnabled, } from "../../framework-tools.js";
3
3
  import { getFrontmatterValue, getSkillNameFromPath, parseFrontmatter, } from "../../resources/metadata.js";
4
4
  import { ensurePersonalDefaults, isWorkspaceResourceOwner, organizationIdFromResourceOwner, resourceGet, resourceGetByPath, resourceList, resourceListAccessible, SHARED_OWNER, sharedResourceOwner, WORKSPACE_OWNER, workspaceResourceOwner, } from "../../resources/store.js";
5
5
  import { discoverAgents } from "../agent-discovery.js";
6
- import { getRequestOrgId } from "../request-context.js";
6
+ import { getRequestOrgId, getRequestRunContext } from "../request-context.js";
7
7
  import { isRuntimeVisibleScope, parseSkillFrontmatter, } from "./skill-frontmatter.js";
8
8
  // ---------------------------------------------------------------------------
9
9
  // System-prompt resource loading: AGENTS.md, instructions/*.md, skills
@@ -81,7 +81,12 @@ const PROMPT_INSTRUCTION_SUMMARY_LIMIT = 20;
81
81
  const PROMPT_SUMMARY_DESCRIPTION_MAX_CHARS = 180;
82
82
  const JEV_CONTEXT_ITEM_MAX_CHARS = 10_000;
83
83
  const JEV_CONTEXT_TOTAL_MAX_CHARS = 24_000;
84
- const JEV_CONTEXT_PREFIX = "<jev-prefetched-context>\nJev ranked these skills for this task. Mandatory AGENTS.md instructions remain authoritative. Treat these sources as task-specific guidance and use the existing tools to read anything else you need.\n\n";
84
+ const JEV_MEMORY_CANDIDATE_LIMIT = 8;
85
+ const JEV_MEMORY_SELECTION_LIMIT = 2;
86
+ const JEV_MEMORY_DESCRIPTION_MAX_CHARS = 240;
87
+ const JEV_PRELOAD_BUDGET_MS = 1_300;
88
+ const MIN_ANALYTICS_REFERENCE_SIMILARITY = 0.35;
89
+ const JEV_CONTEXT_PREFIX = "<jev-prefetched-context>\nThese bounded context sources were selected for this task. Mandatory AGENTS.md instructions remain authoritative. Treat stored memories as prior context and verify time-sensitive facts. For Analytics, use a matching preloaded reference first; otherwise make your first tool call search-analytics-query-catalog. Treat references as examples and definitions, then run a live query before reporting values.\n\n";
85
90
  const JEV_CONTEXT_SUFFIX = "\n</jev-prefetched-context>";
86
91
  const JEV_CONTEXT_SEPARATOR = "\n\n";
87
92
  const JEV_CONTEXT_WRAPPER_OVERHEAD_CHARS = JEV_CONTEXT_PREFIX.length + JEV_CONTEXT_SUFFIX.length;
@@ -597,9 +602,12 @@ async function loadResourceIndexForPrompt(owner, scope, orgId) {
597
602
  : "Shared app/organization reference resources are available for app-specific or team context.";
598
603
  return `<workspace-resources scope="${scope}">\n${label} ${resourceToolHint("read", `\`path: <path>\` and \`scope: "${scope}"\` when a task may depend on them`)} Do not assume their contents without reading the relevant file.\n\n${lines.join("\n")}\n</workspace-resources>`;
599
604
  }
600
- async function collectJevPromptCandidates() {
601
- // Do not send SQL resource names, paths, or descriptions to Jev. They are
602
- // user-authored metadata and can contain customer/project information.
605
+ async function collectJevPromptCandidates(signal) {
606
+ // Jev receives the current request and recent user turns, short skill and
607
+ // memory summaries, and bounded Analytics labels with metric definitions,
608
+ // source/table names, or dashboard/panel details. These may be sensitive
609
+ // user-authored metadata. Keep assistant text/results, tool payloads,
610
+ // resource IDs/paths, memory/skill bodies, and full query SQL out of ranking.
603
611
  const candidates = [];
604
612
  let nextId = 0;
605
613
  const add = (candidate) => {
@@ -612,16 +620,18 @@ async function collectJevPromptCandidates() {
612
620
  ...candidate,
613
621
  id: `context-${nextId++}`,
614
622
  description,
615
- metadata: {
616
- kind: candidate.kind,
623
+ metadata: candidate.metadata ?? {
624
+ kind: candidate.kind ?? "skill",
617
625
  scope: candidate.scope,
618
626
  },
619
627
  });
620
628
  };
621
629
  try {
622
630
  const { getRuntimeSkills, loadAgentsBundle } = await import("../agents-bundle.js");
631
+ signal.throwIfAborted();
623
632
  const bundle = await loadAgentsBundle();
624
633
  for (const skill of getRuntimeSkills(bundle)) {
634
+ signal.throwIfAborted();
625
635
  add({
626
636
  kind: "skill",
627
637
  name: skill.meta.name,
@@ -637,34 +647,381 @@ async function collectJevPromptCandidates() {
637
647
  }
638
648
  return candidates;
639
649
  }
650
+ function parseMemoryIndex(content) {
651
+ const entries = [];
652
+ for (const line of content.split("\n")) {
653
+ const match = /^\s*-\s+\[([^\]]+)\]\(([^)]+\.md)\)\s*[—-]\s*(.+)$/.exec(line);
654
+ if (!match)
655
+ continue;
656
+ const [, name, linkedPath, description] = match;
657
+ if (!name ||
658
+ !linkedPath ||
659
+ !description ||
660
+ linkedPath.includes("..") ||
661
+ /[\\/]/.test(linkedPath.replace(/^memory\//, ""))) {
662
+ continue;
663
+ }
664
+ const path = linkedPath.startsWith("memory/")
665
+ ? linkedPath
666
+ : `memory/${linkedPath}`;
667
+ entries.push({ name, path, description });
668
+ }
669
+ return entries;
670
+ }
671
+ function memoryRelevanceScore(request, text) {
672
+ const searchable = text.toLowerCase();
673
+ const terms = new Set(request.toLowerCase().match(/[a-z0-9]{3,}/g) ?? []);
674
+ let score = 0;
675
+ for (const term of terms) {
676
+ if (searchable.includes(term))
677
+ score += Math.min(term.length, 8);
678
+ }
679
+ return score;
680
+ }
681
+ async function collectJevMemoryPromptCandidates(input) {
682
+ if (!input.owner || input.owner === SHARED_OWNER) {
683
+ return { candidates: [], fallbackIds: [] };
684
+ }
685
+ try {
686
+ input.signal.throwIfAborted();
687
+ const index = await resourceGetByPath(input.owner, "memory/MEMORY.md", {
688
+ orgId: input.orgId,
689
+ });
690
+ input.signal.throwIfAborted();
691
+ if (!index?.content)
692
+ return { candidates: [], fallbackIds: [] };
693
+ const memories = parseMemoryIndex(index.content)
694
+ .filter((memory) => memory.path !== "memory/MEMORY.md")
695
+ .map((memory, index) => ({
696
+ ...memory,
697
+ updatedAt: index,
698
+ score: memoryRelevanceScore(input.request, `${memory.name} ${memory.description}`),
699
+ }))
700
+ .sort((a, b) => b.score - a.score ||
701
+ b.updatedAt - a.updatedAt ||
702
+ a.path.localeCompare(b.path))
703
+ .slice(0, JEV_MEMORY_CANDIDATE_LIMIT);
704
+ const candidates = memories.map((memory, index) => ({
705
+ id: `personal-memory-${index}`,
706
+ kind: "memory",
707
+ description: `Personal memory: ${compactPromptLine(memory.description, JEV_MEMORY_DESCRIPTION_MAX_CHARS)}`,
708
+ metadata: { kind: "personal-memory", scope: "personal" },
709
+ name: memory.name,
710
+ scope: "personal",
711
+ path: memory.path,
712
+ content: "",
713
+ }));
714
+ const fallback = memories.find((memory) => memory.score >= 5);
715
+ const fallbackIndex = fallback ? memories.indexOf(fallback) : -1;
716
+ return {
717
+ candidates,
718
+ fallbackIds: fallbackIndex >= 0 ? [`personal-memory-${fallbackIndex}`] : [],
719
+ };
720
+ }
721
+ catch (error) {
722
+ console.warn("[agent] Jev memory context unavailable; continuing with the normal memory index.", error instanceof Error ? error.message : "unknown error");
723
+ return { candidates: [], fallbackIds: [] };
724
+ }
725
+ }
726
+ async function withinPromptBudget(work, deadlineAt) {
727
+ const remaining = deadlineAt - Date.now();
728
+ if (remaining <= 0)
729
+ return { status: "expired" };
730
+ const controller = new AbortController();
731
+ let timeout;
732
+ const result = await Promise.race([
733
+ Promise.resolve()
734
+ .then(() => work(controller.signal))
735
+ .then((value) => ({ status: "completed", value }), (error) => ({ status: "failed", error })),
736
+ new Promise((resolve) => {
737
+ timeout = setTimeout(() => {
738
+ controller.abort();
739
+ resolve({ status: "expired" });
740
+ }, remaining);
741
+ }),
742
+ ]);
743
+ if (timeout)
744
+ clearTimeout(timeout);
745
+ if (result.status === "failed") {
746
+ if (controller.signal.aborted)
747
+ return { status: "expired" };
748
+ throw result.error;
749
+ }
750
+ return result;
751
+ }
752
+ async function loadSelectedMemoryBodies(input) {
753
+ if (!input.owner || input.owner === SHARED_OWNER)
754
+ return input.candidates;
755
+ const selected = new Set(input.selectedIds);
756
+ const memories = input.candidates.filter((candidate) => selected.has(candidate.id) &&
757
+ candidate.kind === "memory" &&
758
+ Boolean(candidate.path));
759
+ if (memories.length === 0)
760
+ return input.candidates;
761
+ let loaded;
762
+ try {
763
+ loaded = await withinPromptBudget(async (signal) => {
764
+ const entries = [];
765
+ for (const candidate of memories) {
766
+ signal.throwIfAborted();
767
+ const resource = await resourceGetByPath(input.owner, candidate.path, { orgId: input.orgId });
768
+ signal.throwIfAborted();
769
+ entries.push(resource?.content.trim()
770
+ ? { id: candidate.id, content: resource.content }
771
+ : null);
772
+ }
773
+ return entries;
774
+ }, input.deadlineAt);
775
+ }
776
+ catch (error) {
777
+ console.warn("[agent] Selected memory bodies unavailable; continuing without them.", error instanceof Error ? error.message : "unknown error");
778
+ return input.candidates;
779
+ }
780
+ if (loaded.status === "expired")
781
+ return input.candidates;
782
+ const contentById = new Map(loaded.value.flatMap((entry) => (entry ? [[entry.id, entry.content]] : [])));
783
+ return input.candidates.map((candidate) => ({
784
+ ...candidate,
785
+ content: contentById.get(candidate.id) ?? candidate.content,
786
+ }));
787
+ }
788
+ function trackAnalyticsJevContext(input) {
789
+ if (input.appId !== "analytics")
790
+ return;
791
+ const selected = new Set(input.selectedIds);
792
+ const kinds = ["analytics-reference", "memory", "skill"];
793
+ const properties = {
794
+ jev_configured: input.jevConfigured,
795
+ jev_status: input.status,
796
+ selection_source: input.source,
797
+ candidate_count: input.candidates.length,
798
+ selected_count: selected.size,
799
+ };
800
+ for (const kind of kinds) {
801
+ const field = kind.replaceAll("-", "_");
802
+ properties[`candidate_${field}_count`] = input.candidates.filter((candidate) => candidate.metadata?.kind === kind || candidate.kind === kind).length;
803
+ properties[`selected_${field}_count`] = input.candidates.filter((candidate) => selected.has(candidate.id) &&
804
+ (candidate.metadata?.kind === kind || candidate.kind === kind)).length;
805
+ }
806
+ void import("../../tracking/registry.js")
807
+ .then(({ track }) => track("jev_context_prefetch", properties))
808
+ .catch(() => { });
809
+ }
810
+ function recordAnalyticsPreloadedReferenceCount(input) {
811
+ if (input.appId !== "analytics")
812
+ return;
813
+ const context = getRequestRunContext();
814
+ if (!context)
815
+ return;
816
+ context.analyticsJevPrefetch = {
817
+ preloadedReferenceCount: input.candidates.filter((candidate) => input.injectedIds.has(candidate.id) &&
818
+ (candidate.metadata?.kind === "analytics-reference" ||
819
+ candidate.kind === "analytics-reference")).length,
820
+ };
821
+ }
640
822
  /** Rank and inline a few optional context sources before the first model call. */
641
823
  export async function preloadJevContextForPrompt(options) {
642
824
  const request = options.request.trim();
643
825
  const apiKey = options.apiKey?.trim();
644
826
  const personalApiKey = options.personalApiKey?.trim();
645
- if (!request ||
646
- (!apiKey && !personalApiKey && !options.builderAuth) ||
647
- options.maxChars === 0) {
827
+ if (!request || options.maxChars === 0 || options.dispatchToBackground) {
648
828
  return "";
649
829
  }
650
- const candidates = await collectJevPromptCandidates();
651
- const selectedIds = await rankJevCandidates({
652
- request,
653
- apiKey,
654
- personalApiKey,
655
- builderAuth: options.builderAuth,
830
+ const deadlineAt = options.contextPrefetchDeadlineAt ?? Date.now() + JEV_PRELOAD_BUDGET_MS;
831
+ const hasJev = Boolean(apiKey || personalApiKey || options.builderAuth);
832
+ let runtimeCandidates = [];
833
+ let memoryContext = { candidates: [], fallbackIds: [] };
834
+ if (hasJev) {
835
+ try {
836
+ const collection = await withinPromptBudget((signal) => Promise.all([
837
+ collectJevPromptCandidates(signal),
838
+ collectJevMemoryPromptCandidates({
839
+ owner: options.owner,
840
+ orgId: options.orgId,
841
+ request,
842
+ signal,
843
+ }),
844
+ ]), deadlineAt);
845
+ if (collection.status === "completed") {
846
+ runtimeCandidates = collection.value[0];
847
+ memoryContext = collection.value[1];
848
+ }
849
+ else {
850
+ console.warn("[agent] Jev context candidates exceeded the preload budget; keeping Analytics retrieval fallback.");
851
+ }
852
+ }
853
+ catch (error) {
854
+ console.warn("[agent] Jev context candidates unavailable; keeping Analytics retrieval fallback.", error instanceof Error ? error.message : "unknown error");
855
+ }
856
+ }
857
+ const candidates = [
858
+ ...runtimeCandidates,
859
+ ...memoryContext.candidates,
860
+ ...(options.candidates ?? []),
861
+ ];
862
+ if (candidates.length === 0) {
863
+ trackAnalyticsJevContext({
864
+ appId: options.appId,
865
+ jevConfigured: hasJev,
866
+ status: "no_candidates",
867
+ source: "none",
868
+ candidates,
869
+ selectedIds: [],
870
+ });
871
+ return "";
872
+ }
873
+ const categoryFor = (candidate) => {
874
+ const kind = candidate.metadata?.kind ?? candidate.kind;
875
+ if (kind === "analytics-reference")
876
+ return "analytics-reference";
877
+ if (kind === "memory" || kind === "personal-memory")
878
+ return "memory";
879
+ return "skill";
880
+ };
881
+ const categories = ["skill", "memory", "analytics-reference"];
882
+ const candidatesByCategory = new Map(categories.map((category) => [
883
+ category,
884
+ candidates.filter((candidate) => categoryFor(candidate) === category),
885
+ ]));
886
+ const rankings = new Map();
887
+ if (hasJev) {
888
+ const rankAllCandidates = (signal) => Promise.all(categories.map(async (category) => {
889
+ const group = candidatesByCategory.get(category) ?? [];
890
+ if (group.length === 0)
891
+ return [category, null];
892
+ const rank = await rankJevCandidatesWithStatus({
893
+ request,
894
+ apiKey,
895
+ personalApiKey,
896
+ builderAuth: options.builderAuth,
897
+ candidates: group,
898
+ candidateStateKey: `candidate_${category.replaceAll("-", "_")}`,
899
+ answerKey: `best_${category.replaceAll("-", "_")}`,
900
+ signal,
901
+ timeoutMs: Math.min(JEV_TIMEOUT_MS, deadlineAt - Date.now()),
902
+ question: category === "skill"
903
+ ? "Which skills are relevant to this task? Choose at most 3."
904
+ : category === "memory"
905
+ ? "Which prior user memories are important for this task? Choose at most 2 based only on their short summaries."
906
+ : "Which Analytics data-dictionary entries or dashboard panels best match this request? Choose at most 2; references are examples, not live results.",
907
+ limit: category === "skill" ? 3 : JEV_MEMORY_SELECTION_LIMIT,
908
+ });
909
+ const groupIds = new Set(group.map((candidate) => candidate.id));
910
+ const ids = rank.ids.filter((id) => groupIds.has(id));
911
+ return [
912
+ category,
913
+ ids.length === 0 && rank.status === "selected"
914
+ ? { status: "no-match", ids: [] }
915
+ : { ...rank, ids },
916
+ ];
917
+ }));
918
+ try {
919
+ const ranked = await withinPromptBudget(rankAllCandidates, deadlineAt);
920
+ if (ranked.status === "completed") {
921
+ for (const [category, result] of ranked.value) {
922
+ if (result)
923
+ rankings.set(category, result);
924
+ }
925
+ }
926
+ else {
927
+ console.warn("[agent] Jev ranking exceeded the preload budget; using bounded retrieval fallbacks.");
928
+ }
929
+ }
930
+ catch (error) {
931
+ console.warn("[agent] Jev ranking unavailable; using bounded retrieval fallbacks.", error instanceof Error ? error.message : "unknown error");
932
+ }
933
+ }
934
+ const jevSelectedIds = [...rankings.values()]
935
+ .filter((result) => result.status === "selected")
936
+ .flatMap((result) => result.ids);
937
+ const selected = new Set(jevSelectedIds);
938
+ const analyticsCandidates = candidatesByCategory.get("analytics-reference") ?? [];
939
+ const highSimilarityReferenceIds = analyticsCandidates
940
+ .filter((candidate) => {
941
+ const similarity = Number(candidate.metadata?.similarity);
942
+ return (Number.isFinite(similarity) &&
943
+ similarity >= MIN_ANALYTICS_REFERENCE_SIMILARITY);
944
+ })
945
+ .slice(0, 1)
946
+ .map((candidate) => candidate.id);
947
+ const referenceRanking = rankings.get("analytics-reference");
948
+ if (analyticsCandidates.length > 0 &&
949
+ !analyticsCandidates.some((candidate) => selected.has(candidate.id))) {
950
+ if (!hasJev) {
951
+ for (const id of options.fallbackCandidateIds ?? [])
952
+ selected.add(id);
953
+ }
954
+ else if (highSimilarityReferenceIds.length > 0) {
955
+ for (const id of highSimilarityReferenceIds)
956
+ selected.add(id);
957
+ }
958
+ else if (!referenceRanking || referenceRanking.status === "unavailable") {
959
+ for (const id of options.fallbackCandidateIds ?? [])
960
+ selected.add(id);
961
+ }
962
+ }
963
+ const memoryRanking = rankings.get("memory");
964
+ if (hasJev &&
965
+ (!memoryRanking || memoryRanking.status === "unavailable") &&
966
+ memoryContext.fallbackIds.length > 0) {
967
+ for (const id of memoryContext.fallbackIds)
968
+ selected.add(id);
969
+ }
970
+ const selectionPriority = {
971
+ "analytics-reference": 0,
972
+ memory: 1,
973
+ skill: 2,
974
+ };
975
+ let selectedIds = candidates
976
+ .filter((candidate) => selected.has(candidate.id))
977
+ .sort((left, right) => selectionPriority[categoryFor(left)] -
978
+ selectionPriority[categoryFor(right)])
979
+ .map((candidate) => candidate.id);
980
+ const rankingStatuses = [...rankings.values()].map((result) => result.status);
981
+ const status = rankingStatuses.includes("selected")
982
+ ? "selected"
983
+ : rankings.size > 0 &&
984
+ rankingStatuses.every((value) => value === "no-match")
985
+ ? "no-match"
986
+ : "unavailable";
987
+ const selectionSource = jevSelectedIds.length
988
+ ? selectedIds.length > jevSelectedIds.length
989
+ ? "jev+fallback"
990
+ : "jev"
991
+ : selectedIds.length
992
+ ? "fallback"
993
+ : "none";
994
+ const withMemoryBodies = await loadSelectedMemoryBodies({
995
+ candidates,
996
+ selectedIds,
997
+ owner: options.owner,
998
+ orgId: options.orgId,
999
+ deadlineAt,
1000
+ });
1001
+ const bodyById = new Map(withMemoryBodies.map((candidate) => [candidate.id, candidate]));
1002
+ candidates.splice(0, candidates.length, ...withMemoryBodies);
1003
+ selectedIds = selectedIds.filter((id) => bodyById.get(id)?.content.trim());
1004
+ trackAnalyticsJevContext({
1005
+ appId: options.appId,
1006
+ jevConfigured: hasJev,
1007
+ status,
1008
+ source: selectionSource,
656
1009
  candidates,
657
- candidateStateKey: "candidate_context",
658
- answerKey: "best_context",
659
- question: "Which skills or reference resources should be loaded into the agent context first for this task? Pick the most useful source; probabilities may be used to keep a small ranked shortlist.",
660
- limit: 3,
1010
+ selectedIds,
661
1011
  });
662
- if (selectedIds.length === 0)
1012
+ if (selectedIds.length === 0) {
1013
+ recordAnalyticsPreloadedReferenceCount({
1014
+ appId: options.appId,
1015
+ candidates,
1016
+ injectedIds: new Set(),
1017
+ });
663
1018
  return "";
1019
+ }
664
1020
  const maxItemChars = options.compact ? 6_000 : JEV_CONTEXT_ITEM_MAX_CHARS;
665
1021
  const maxTotalChars = Math.min(options.compact ? 16_000 : JEV_CONTEXT_TOTAL_MAX_CHARS, Math.max(0, options.maxChars ?? Number.POSITIVE_INFINITY));
666
1022
  const contentBudget = Math.max(0, maxTotalChars - JEV_CONTEXT_WRAPPER_OVERHEAD_CHARS);
667
1023
  const blocks = [];
1024
+ const injectedIds = new Set();
668
1025
  let usedChars = 0;
669
1026
  for (const id of selectedIds) {
670
1027
  const candidate = candidates.find((item) => item.id === id);
@@ -697,8 +1054,14 @@ export async function preloadJevContextForPrompt(options) {
697
1054
  if (block.length > remaining)
698
1055
  break;
699
1056
  blocks.push(block);
1057
+ injectedIds.add(candidate.id);
700
1058
  usedChars += separatorChars + block.length;
701
1059
  }
1060
+ recordAnalyticsPreloadedReferenceCount({
1061
+ appId: options.appId,
1062
+ candidates,
1063
+ injectedIds,
1064
+ });
702
1065
  if (blocks.length === 0)
703
1066
  return "";
704
1067
  return `${JEV_CONTEXT_PREFIX}${escapeJevContextFence(blocks.join(JEV_CONTEXT_SEPARATOR))}${JEV_CONTEXT_SUFFIX}`;
@@ -1,5 +1,5 @@
1
1
  import type { Message as A2AMessage } from "../a2a/types.js";
2
- import { type ActionEntry } from "../agent/production-agent.js";
2
+ import { type ActionEntry, type AgentActionSurfaceDetails, type AgentActionSurfaceResolution } from "../agent/production-agent.js";
3
3
  import type { ActiveRun } from "../agent/run-manager.js";
4
4
  import type { AgentChatEvent, AgentChatScope } from "../agent/types.js";
5
5
  import type { ResolvedKeyReference } from "../secrets/substitution.js";
@@ -41,6 +41,7 @@ export { scheduledTriggerAvailability };
41
41
  export { shouldDisableRecurringJobsRuntime };
42
42
  export { finalizeClaimedAgentChatProcessRunFailure };
43
43
  export declare function runPostAgentTurnAutosave(callback: AgentChatPluginOptions["onAgentTurnComplete"] | undefined, scope: AgentChatScope | null | undefined, run: ActiveRun): Promise<void>;
44
+ export declare function runPostAgentRunComplete(callback: AgentChatPluginOptions["onAgentRunComplete"] | undefined, scope: AgentChatScope | null | undefined, run: ActiveRun): Promise<void>;
44
45
  export declare function runPreAgentTurnAutosave(callback: AgentChatPluginOptions["onAgentTurnStart"] | undefined, scope: AgentChatScope | null | undefined, run: Pick<ActiveRun, "threadId" | "runId">): Promise<void>;
45
46
  /**
46
47
  * The model this mount runs with, when the caller does not pass one per request.
@@ -73,6 +74,7 @@ export declare function filterRuntimeActionsToSurface(actions: Record<string, Ac
73
74
  * teaching the model names it cannot call. */
74
75
  export declare function filterFrameworkPromptToSurface(prompt: string, actions: Record<string, ActionEntry>, allowedActionNames?: readonly string[]): string;
75
76
  export declare function resolveProductionCodeExecutionForActionSurface(mode: "off" | "sandboxed" | "trusted", hasRequestScopedSurface: boolean): "off" | "sandboxed" | "trusted";
77
+ export declare function resolveObservabilityReviewSummaryActionSurface(details: AgentActionSurfaceDetails, resolveHostSurface?: (details: AgentActionSurfaceDetails) => AgentActionSurfaceResolution | Promise<AgentActionSurfaceResolution>): Promise<AgentActionSurfaceResolution>;
76
78
  /**
77
79
  * Abort reasons that mean a human asked to stop, so `/runs/:id/abort` escalates
78
80
  * to a turn-wide abort. Watchdog reasons (`no_progress`, `auto_stuck_retry`)