@agent-native/core 0.120.2 → 0.120.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +3 -3
- package/corpus/core/CHANGELOG.md +20 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/context-xray-local.ts +1 -1
- package/corpus/core/src/cli/index.ts +63 -18
- package/corpus/core/src/cli/skills.ts +5 -0
- package/corpus/core/src/cli/telemetry.ts +118 -1
- package/corpus/core/src/client/AgentPanel.tsx +10 -0
- package/corpus/core/src/client/CommandMenu.tsx +13 -1
- package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +39 -4
- package/corpus/core/src/client/analytics.ts +13 -0
- package/corpus/core/src/client/error-capture.ts +6 -1
- package/corpus/core/src/client/extensions/ExtensionsListPage.tsx +12 -5
- package/corpus/core/src/client/extensions/agent-native-extension-runtime.ts +1 -1
- package/corpus/core/src/client/navigation/index.ts +2 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +14 -32
- package/corpus/core/src/client/settings/ExtensionsSettingsContent.tsx +1 -1
- package/corpus/core/src/extensions/theme.ts +1 -1
- package/corpus/core/src/localization/default-messages.ts +2 -0
- package/corpus/core/src/server/core-routes-plugin.ts +10 -1
- package/corpus/core/src/server/framework-request-handler.ts +17 -26
- package/corpus/core/src/styles/agent-native.css +13 -0
- package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +3 -0
- package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +78 -45
- package/corpus/core/src/templates/chat/app/global.css +1 -1
- package/corpus/core/src/templates/default/app/global.css +1 -1
- package/corpus/core/src/tracking/error-capture.ts +151 -0
- package/corpus/core/src/tracking/index.ts +5 -0
- package/corpus/templates/analytics/app/components/dashboard/CumulativeNetChart.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +1 -4
- package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/DataTable.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/DateRangePicker.tsx +2 -2
- package/corpus/templates/analytics/app/components/dashboard/MetricCard.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/RecentActivity.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/RevenueChart.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/RevenueComparisonChart.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +41 -9
- package/corpus/templates/analytics/app/components/dashboard/StatsCard.tsx +1 -1
- package/corpus/templates/analytics/app/components/dashboard/TimeSeriesChart.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +2 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +28 -14
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +152 -124
- package/corpus/templates/analytics/app/global.css +5 -5
- package/corpus/templates/analytics/app/lib/dashboard-report-capture.ts +42 -0
- package/corpus/templates/analytics/app/pages/adhoc/_shared/KpiChart.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/ChartTypePicker.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/DateRangePicker.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/EventRow.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/SqlPreview.tsx +2 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +3 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +2 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +162 -51
- package/corpus/templates/analytics/app/root.tsx +28 -0
- package/corpus/templates/analytics/changelog/2026-07-24-analytics-charts-now-explain-slow-loads-and-offer-a-direct-r.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-daily-dashboard-emails-now-load-signed-reports-more-reliably.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-manage-agent-is-clearly-marked-as-a-link-to-its-dedicated-pa.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +1 -1
- package/corpus/templates/analytics/server/db/schema.ts +5 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +21 -0
- package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +11 -0
- package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +54 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +235 -26
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +4 -1
- package/corpus/templates/analytics/server/plugins/db.ts +9 -0
- package/corpus/templates/analytics/shared/dashboard-report-timeouts.ts +1 -1
- package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +376 -0
- package/corpus/templates/assets/app/components/create/RecentDraftsSection.tsx +14 -4
- package/corpus/templates/assets/app/components/layout/Layout.tsx +5 -0
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +118 -74
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/assets/app/i18n-data.ts +10 -0
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +99 -10
- package/corpus/templates/assets/app/routes/library.tsx +21 -198
- package/corpus/templates/assets/changelog/2026-07-21-unified-asset-preview-click-any-asset-to-open-one-preview-wi.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/brain/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +76 -43
- package/corpus/templates/brain/app/global.css +1 -1
- package/corpus/templates/brain/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/brain/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +67 -52
- package/corpus/templates/calendar/app/global.css +1 -1
- package/corpus/templates/calendar/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/calendar/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/chat/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +78 -45
- package/corpus/templates/chat/app/global.css +1 -1
- package/corpus/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +65 -31
- package/corpus/templates/clips/app/components/library/organization-switcher.tsx +2 -2
- package/corpus/templates/clips/app/components/player/video-player.tsx +16 -1
- package/corpus/templates/clips/app/global.css +1 -1
- package/corpus/templates/clips/app/hooks/use-view-tracking.ts +55 -12
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +6 -5
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +7 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -5
- package/corpus/templates/clips/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/clips/server/plugins/db.ts +113 -68
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +66 -42
- package/corpus/templates/content/app/global.css +1 -1
- package/corpus/templates/content/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/content/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +65 -30
- package/corpus/templates/design/app/entry.client.tsx +14 -1
- package/corpus/templates/design/app/global.css +1 -1
- package/corpus/templates/design/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/design/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/dispatch/app/global.css +1 -1
- package/corpus/templates/dispatch/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/forms/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +72 -37
- package/corpus/templates/forms/app/global.css +1 -1
- package/corpus/templates/forms/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-24-forms-sidebar-actions-now-keep-search-language-feedback-and-.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/macros/app/components/DailyProgress.tsx +5 -5
- package/corpus/templates/macros/app/components/ExerciseCard.tsx +2 -2
- package/corpus/templates/macros/app/components/MealCard.tsx +2 -2
- package/corpus/templates/macros/app/components/WeightCard.tsx +2 -2
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +56 -29
- package/corpus/templates/macros/app/components/ui/button.tsx +1 -2
- package/corpus/templates/macros/app/components/ui/card.tsx +1 -1
- package/corpus/templates/macros/app/global.css +1 -1
- package/corpus/templates/macros/app/routes/_index.tsx +1 -1
- package/corpus/templates/macros/app/routes/analytics.tsx +4 -7
- package/corpus/templates/macros/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/macros/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +125 -37
- package/corpus/templates/mail/app/global.css +1 -1
- package/corpus/templates/mail/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/mail/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/plan/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +90 -60
- package/corpus/templates/plan/app/global.css +1 -1
- package/corpus/templates/plan/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +69 -32
- package/corpus/templates/slides/app/global.css +1 -1
- package/corpus/templates/slides/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/corpus/templates/tasks/app/global.css +1 -1
- package/corpus/templates/tasks/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/corpus/toolkit/CHANGELOG.md +8 -0
- package/corpus/toolkit/README.md +8 -1
- package/corpus/toolkit/agent-native.eject.json +1 -1
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/app-shell/index.ts +1 -0
- package/corpus/toolkit/src/app-shell/sidebar-footer-actions.tsx +48 -0
- package/corpus/toolkit/src/chat-history.css +52 -1
- package/corpus/toolkit/src/design-system/default-adapter.tsx +1 -1
- package/corpus/toolkit/src/ui/button.tsx +1 -2
- package/corpus/toolkit/src/ui/card.tsx +1 -1
- package/corpus/toolkit/src/ui/table.tsx +4 -11
- package/dist/cli/context-xray-local.js +1 -1
- package/dist/cli/context-xray-local.js.map +1 -1
- package/dist/cli/index.js +56 -17
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +5 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/telemetry.d.ts +7 -0
- package/dist/cli/telemetry.d.ts.map +1 -1
- package/dist/cli/telemetry.js +91 -1
- package/dist/cli/telemetry.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +7 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +2 -2
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/CommandMenu.d.ts +2 -0
- package/dist/client/CommandMenu.d.ts.map +1 -1
- package/dist/client/CommandMenu.js +12 -1
- package/dist/client/CommandMenu.js.map +1 -1
- package/dist/client/agent-page/AgentTabsPage.d.ts +4 -0
- package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
- package/dist/client/agent-page/AgentTabsPage.js +8 -4
- package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +7 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/error-capture.d.ts.map +1 -1
- package/dist/client/error-capture.js +8 -1
- package/dist/client/error-capture.js.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.js +2 -2
- package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
- package/dist/client/extensions/agent-native-extension-runtime.js +1 -1
- package/dist/client/extensions/agent-native-extension-runtime.js.map +1 -1
- package/dist/client/navigation/index.d.ts +1 -1
- package/dist/client/navigation/index.d.ts.map +1 -1
- package/dist/client/navigation/index.js +1 -1
- package/dist/client/navigation/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +9 -13
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/settings/ExtensionsSettingsContent.js +1 -1
- package/dist/client/settings/ExtensionsSettingsContent.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/extensions/theme.js +1 -1
- package/dist/extensions/theme.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/localization/default-messages.d.ts +2 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +2 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +8 -1
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +17 -27
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/styles/agent-native.css +13 -0
- package/dist/templates/chat/app/components/layout/Layout.tsx +3 -0
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +78 -45
- package/dist/templates/chat/app/global.css +1 -1
- package/dist/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/dist/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/dist/templates/default/app/global.css +1 -1
- package/dist/tracking/error-capture.d.ts +14 -0
- package/dist/tracking/error-capture.d.ts.map +1 -0
- package/dist/tracking/error-capture.js +113 -0
- package/dist/tracking/error-capture.js.map +1 -0
- package/dist/tracking/index.d.ts +1 -0
- package/dist/tracking/index.d.ts.map +1 -1
- package/dist/tracking/index.js +1 -0
- package/dist/tracking/index.js.map +1 -1
- package/package.json +2 -2
- package/src/cli/context-xray-local.ts +1 -1
- package/src/cli/index.ts +63 -18
- package/src/cli/skills.ts +5 -0
- package/src/cli/telemetry.ts +118 -1
- package/src/client/AgentPanel.tsx +10 -0
- package/src/client/CommandMenu.tsx +13 -1
- package/src/client/agent-page/AgentTabsPage.tsx +39 -4
- package/src/client/analytics.ts +13 -0
- package/src/client/error-capture.ts +6 -1
- package/src/client/extensions/ExtensionsListPage.tsx +12 -5
- package/src/client/extensions/agent-native-extension-runtime.ts +1 -1
- package/src/client/navigation/index.ts +2 -0
- package/src/client/org/OrgSwitcher.tsx +14 -32
- package/src/client/settings/ExtensionsSettingsContent.tsx +1 -1
- package/src/extensions/theme.ts +1 -1
- package/src/localization/default-messages.ts +2 -0
- package/src/server/core-routes-plugin.ts +10 -1
- package/src/server/framework-request-handler.ts +17 -26
- package/src/styles/agent-native.css +13 -0
- package/src/templates/chat/app/components/layout/Layout.tsx +3 -0
- package/src/templates/chat/app/components/layout/Sidebar.tsx +78 -45
- package/src/templates/chat/app/global.css +1 -1
- package/src/templates/chat/changelog/2026-07-24-borderless-secondary-surfaces.md +6 -0
- package/src/templates/chat/changelog/2026-07-24-sidebar-footer-controls-follow-a-consistent-order.md +6 -0
- package/src/templates/default/app/global.css +1 -1
- package/src/tracking/error-capture.ts +151 -0
- package/src/tracking/index.ts +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-capture.d.ts","sourceRoot":"","sources":["../../src/tracking/error-capture.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGtE,MAAM,MAAM,sBAAsB,GAC9B,OAAO,GACP,OAAO,GACP,SAAS,GACT,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,sBAAsB,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACzB,MAAM,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CAC3B;AA2FD,gFAAgF;AAChF,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,wBAA6B,GACrC,IAAI,CAoCN"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { trackingIdentityProperties } from "../observability/tracking-identity.js";
|
|
2
|
+
import { track } from "./registry.js";
|
|
3
|
+
const MAX_MESSAGE_LENGTH = 1000;
|
|
4
|
+
const MAX_STACK_LENGTH = 8000;
|
|
5
|
+
const MAX_TAGS = 30;
|
|
6
|
+
const MAX_EXTRA_KEYS = 30;
|
|
7
|
+
const MAX_EXTRA_VALUE_LENGTH = 1000;
|
|
8
|
+
const SECRET_RE = /\b(?:bearer|basic)\s+[^\s]+/gi;
|
|
9
|
+
const SECRET_KEY_RE = /(?:authorization|cookie|set[-_]?cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)/i;
|
|
10
|
+
function redact(value) {
|
|
11
|
+
return value
|
|
12
|
+
.replace(SECRET_RE, (match) => `${match.split(/\s+/, 1)[0]} <redacted>`)
|
|
13
|
+
.replace(/([A-Za-z0-9_$.-]*(?:authorization|cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)[A-Za-z0-9_$.-]*\s*[:=]\s*)([^\s,;}]+)/gi, "$1<redacted>");
|
|
14
|
+
}
|
|
15
|
+
function boundedText(value, max) {
|
|
16
|
+
const text = typeof value === "string" ? value : String(value ?? "");
|
|
17
|
+
const safe = redact(text);
|
|
18
|
+
return safe.length > max ? safe.slice(0, max) : safe;
|
|
19
|
+
}
|
|
20
|
+
function safeValue(value, depth = 2) {
|
|
21
|
+
if (value == null ||
|
|
22
|
+
typeof value === "boolean" ||
|
|
23
|
+
typeof value === "number") {
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
if (typeof value === "string")
|
|
27
|
+
return boundedText(value, MAX_EXTRA_VALUE_LENGTH);
|
|
28
|
+
if (depth <= 0)
|
|
29
|
+
return boundedText(value, MAX_EXTRA_VALUE_LENGTH);
|
|
30
|
+
if (Array.isArray(value)) {
|
|
31
|
+
return value.slice(0, 20).map((item) => safeValue(item, depth - 1));
|
|
32
|
+
}
|
|
33
|
+
if (typeof value === "object") {
|
|
34
|
+
const out = {};
|
|
35
|
+
for (const [key, child] of Object.entries(value)) {
|
|
36
|
+
if (Object.keys(out).length >= MAX_EXTRA_KEYS)
|
|
37
|
+
break;
|
|
38
|
+
const safeKey = boundedText(key, 100);
|
|
39
|
+
out[safeKey] = SECRET_KEY_RE.test(safeKey)
|
|
40
|
+
? "<redacted>"
|
|
41
|
+
: safeValue(child, depth - 1);
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
return boundedText(value, MAX_EXTRA_VALUE_LENGTH);
|
|
46
|
+
}
|
|
47
|
+
function exceptionParts(error) {
|
|
48
|
+
if (error instanceof Error) {
|
|
49
|
+
return {
|
|
50
|
+
type: boundedText(error.name || "Error", 200),
|
|
51
|
+
message: boundedText(error.message || error.name || "Error", MAX_MESSAGE_LENGTH),
|
|
52
|
+
...(error.stack
|
|
53
|
+
? { stack: boundedText(error.stack, MAX_STACK_LENGTH) }
|
|
54
|
+
: {}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
type: "Error",
|
|
59
|
+
message: boundedText(error, MAX_MESSAGE_LENGTH),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function safeTags(tags) {
|
|
63
|
+
const out = {};
|
|
64
|
+
for (const [key, value] of Object.entries(tags ?? {})) {
|
|
65
|
+
if (Object.keys(out).length >= MAX_TAGS || value == null)
|
|
66
|
+
break;
|
|
67
|
+
const safeKey = boundedText(key, 100);
|
|
68
|
+
out[safeKey] = SECRET_KEY_RE.test(safeKey)
|
|
69
|
+
? "<redacted>"
|
|
70
|
+
: boundedText(value, 200);
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
/** Emit a bounded, redacted Node/CLI exception through first-party tracking. */
|
|
75
|
+
export function captureException(error, context = {}) {
|
|
76
|
+
try {
|
|
77
|
+
const parts = exceptionParts(error);
|
|
78
|
+
const tags = safeTags({
|
|
79
|
+
...context.tags,
|
|
80
|
+
...(context.route ? { route: context.route } : {}),
|
|
81
|
+
...(context.method ? { method: context.method } : {}),
|
|
82
|
+
...(context.userAgent ? { userAgent: context.userAgent } : {}),
|
|
83
|
+
});
|
|
84
|
+
const extra = safeValue({
|
|
85
|
+
...context.extra,
|
|
86
|
+
...(context.contexts ? { contexts: context.contexts } : {}),
|
|
87
|
+
});
|
|
88
|
+
track("$exception", {
|
|
89
|
+
...trackingIdentityProperties(),
|
|
90
|
+
exceptionType: parts.type,
|
|
91
|
+
exceptionMessage: parts.message,
|
|
92
|
+
...(parts.stack ? { exceptionStack: parts.stack } : {}),
|
|
93
|
+
handled: context.handled ?? true,
|
|
94
|
+
level: context.level ?? "error",
|
|
95
|
+
occurredAt: new Date().toISOString(),
|
|
96
|
+
runtime: context.runtime ?? "node",
|
|
97
|
+
source: context.source ?? "server",
|
|
98
|
+
...(context.route ? { url: boundedText(context.route, 500) } : {}),
|
|
99
|
+
...(context.release
|
|
100
|
+
? { release: boundedText(context.release, 200) }
|
|
101
|
+
: {}),
|
|
102
|
+
...(context.environment
|
|
103
|
+
? { environment: boundedText(context.environment, 100) }
|
|
104
|
+
: {}),
|
|
105
|
+
...(Object.keys(tags).length ? { exceptionTags: tags } : {}),
|
|
106
|
+
...(extra && typeof extra === "object" ? { exceptionExtra: extra } : {}),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Error reporting must never mask the original failure.
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=error-capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-capture.js","sourceRoot":"","sources":["../../src/tracking/error-capture.ts"],"names":[],"mappings":"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","sourcesContent":["import { trackingIdentityProperties } from \"../observability/tracking-identity.js\";\nimport type { CaptureErrorContext } from \"../server/capture-error.js\";\nimport { track } from \"./registry.js\";\n\nexport type TrackingExceptionLevel =\n | \"fatal\"\n | \"error\"\n | \"warning\"\n | \"info\"\n | \"debug\";\n\nexport interface TrackingExceptionContext extends CaptureErrorContext {\n /** Whether the caller handled the error. Server error hooks default false. */\n handled?: boolean;\n level?: TrackingExceptionLevel;\n release?: string;\n environment?: string;\n runtime?: \"node\" | \"cli\";\n source?: \"server\" | \"cli\";\n}\n\nconst MAX_MESSAGE_LENGTH = 1000;\nconst MAX_STACK_LENGTH = 8000;\nconst MAX_TAGS = 30;\nconst MAX_EXTRA_KEYS = 30;\nconst MAX_EXTRA_VALUE_LENGTH = 1000;\nconst SECRET_RE = /\\b(?:bearer|basic)\\s+[^\\s]+/gi;\nconst SECRET_KEY_RE =\n /(?:authorization|cookie|set[-_]?cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)/i;\n\nfunction redact(value: string): string {\n return value\n .replace(SECRET_RE, (match) => `${match.split(/\\s+/, 1)[0]} <redacted>`)\n .replace(\n /([A-Za-z0-9_$.-]*(?:authorization|cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)[A-Za-z0-9_$.-]*\\s*[:=]\\s*)([^\\s,;}]+)/gi,\n \"$1<redacted>\",\n );\n}\n\nfunction boundedText(value: unknown, max: number): string {\n const text = typeof value === \"string\" ? value : String(value ?? \"\");\n const safe = redact(text);\n return safe.length > max ? safe.slice(0, max) : safe;\n}\n\nfunction safeValue(value: unknown, depth = 2): unknown {\n if (\n value == null ||\n typeof value === \"boolean\" ||\n typeof value === \"number\"\n ) {\n return value;\n }\n if (typeof value === \"string\")\n return boundedText(value, MAX_EXTRA_VALUE_LENGTH);\n if (depth <= 0) return boundedText(value, MAX_EXTRA_VALUE_LENGTH);\n if (Array.isArray(value)) {\n return value.slice(0, 20).map((item) => safeValue(item, depth - 1));\n }\n if (typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value)) {\n if (Object.keys(out).length >= MAX_EXTRA_KEYS) break;\n const safeKey = boundedText(key, 100);\n out[safeKey] = SECRET_KEY_RE.test(safeKey)\n ? \"<redacted>\"\n : safeValue(child, depth - 1);\n }\n return out;\n }\n return boundedText(value, MAX_EXTRA_VALUE_LENGTH);\n}\n\nfunction exceptionParts(error: unknown): {\n type: string;\n message: string;\n stack?: string;\n} {\n if (error instanceof Error) {\n return {\n type: boundedText(error.name || \"Error\", 200),\n message: boundedText(\n error.message || error.name || \"Error\",\n MAX_MESSAGE_LENGTH,\n ),\n ...(error.stack\n ? { stack: boundedText(error.stack, MAX_STACK_LENGTH) }\n : {}),\n };\n }\n return {\n type: \"Error\",\n message: boundedText(error, MAX_MESSAGE_LENGTH),\n };\n}\n\nfunction safeTags(\n tags: Record<string, string | undefined> | undefined,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(tags ?? {})) {\n if (Object.keys(out).length >= MAX_TAGS || value == null) break;\n const safeKey = boundedText(key, 100);\n out[safeKey] = SECRET_KEY_RE.test(safeKey)\n ? \"<redacted>\"\n : boundedText(value, 200);\n }\n return out;\n}\n\n/** Emit a bounded, redacted Node/CLI exception through first-party tracking. */\nexport function captureException(\n error: unknown,\n context: TrackingExceptionContext = {},\n): void {\n try {\n const parts = exceptionParts(error);\n const tags = safeTags({\n ...context.tags,\n ...(context.route ? { route: context.route } : {}),\n ...(context.method ? { method: context.method } : {}),\n ...(context.userAgent ? { userAgent: context.userAgent } : {}),\n });\n const extra = safeValue({\n ...context.extra,\n ...(context.contexts ? { contexts: context.contexts } : {}),\n });\n track(\"$exception\", {\n ...trackingIdentityProperties(),\n exceptionType: parts.type,\n exceptionMessage: parts.message,\n ...(parts.stack ? { exceptionStack: parts.stack } : {}),\n handled: context.handled ?? true,\n level: context.level ?? \"error\",\n occurredAt: new Date().toISOString(),\n runtime: context.runtime ?? \"node\",\n source: context.source ?? \"server\",\n ...(context.route ? { url: boundedText(context.route, 500) } : {}),\n ...(context.release\n ? { release: boundedText(context.release, 200) }\n : {}),\n ...(context.environment\n ? { environment: boundedText(context.environment, 100) }\n : {}),\n ...(Object.keys(tags).length ? { exceptionTags: tags } : {}),\n ...(extra && typeof extra === \"object\" ? { exceptionExtra: extra } : {}),\n });\n } catch {\n // Error reporting must never mask the original failure.\n }\n}\n"]}
|
package/dist/tracking/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { track, identify, flushTracking, registerTrackingProvider, unregisterTrackingProvider, listTrackingProviders, } from "./registry.js";
|
|
2
2
|
export { registerBuiltinProviders } from "./providers.js";
|
|
3
|
+
export { captureException, type TrackingExceptionContext, type TrackingExceptionLevel, } from "./error-capture.js";
|
|
3
4
|
export type { TrackingProvider, TrackingEvent } from "./types.js";
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tracking/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,QAAQ,EACR,aAAa,EACb,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tracking/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,QAAQ,EACR,aAAa,EACb,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAChB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/tracking/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { track, identify, flushTracking, registerTrackingProvider, unregisterTrackingProvider, listTrackingProviders, } from "./registry.js";
|
|
2
2
|
export { registerBuiltinProviders } from "./providers.js";
|
|
3
|
+
export { captureException, } from "./error-capture.js";
|
|
3
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tracking/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,QAAQ,EACR,aAAa,EACb,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["export {\n track,\n identify,\n flushTracking,\n registerTrackingProvider,\n unregisterTrackingProvider,\n listTrackingProviders,\n} from \"./registry.js\";\nexport { registerBuiltinProviders } from \"./providers.js\";\nexport type { TrackingProvider, TrackingEvent } from \"./types.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tracking/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,QAAQ,EACR,aAAa,EACb,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACL,gBAAgB,GAGjB,MAAM,oBAAoB,CAAC","sourcesContent":["export {\n track,\n identify,\n flushTracking,\n registerTrackingProvider,\n unregisterTrackingProvider,\n listTrackingProviders,\n} from \"./registry.js\";\nexport { registerBuiltinProviders } from \"./providers.js\";\nexport {\n captureException,\n type TrackingExceptionContext,\n type TrackingExceptionLevel,\n} from \"./error-capture.js\";\nexport type { TrackingProvider, TrackingEvent } from \"./types.js\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.120.
|
|
3
|
+
"version": "0.120.3",
|
|
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": {
|
|
@@ -390,7 +390,7 @@
|
|
|
390
390
|
"yjs": "^13.6.31",
|
|
391
391
|
"zod": "^4.3.6",
|
|
392
392
|
"@agent-native/recap-cli": "0.5.1",
|
|
393
|
-
"@agent-native/toolkit": "^0.10.
|
|
393
|
+
"@agent-native/toolkit": "^0.10.5"
|
|
394
394
|
},
|
|
395
395
|
"devDependencies": {
|
|
396
396
|
"@ai-sdk/anthropic": "^3.0.71",
|
|
@@ -1933,7 +1933,7 @@ function renderHtml(sessions, args) {
|
|
|
1933
1933
|
return "<!doctype html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>Context X-Ray</title><style>" +
|
|
1934
1934
|
"@import url(\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap\");" +
|
|
1935
1935
|
":root{--background:0 0% 100%;--foreground:220 10% 10%;--card:0 0% 100%;--muted:220 10% 95%;--muted-foreground:220 5% 45%;--accent:220 10% 92%;--border:220 10% 90%;--ring:220 10% 55%;--destructive:0 84% 60%;--radius:.5rem;--shadow:0 1px 2px rgba(16,24,40,.06);}" +
|
|
1936
|
-
"@media(prefers-color-scheme:dark){:root{--background:220 10% 7%;--foreground:220 8% 92%;--card:220 9% 9%;--muted:220 8% 15%;--muted-foreground:220 6% 64%;--accent:220 8% 17%;--border:220 8% 18%;--ring:220 8% 54%;--destructive:0
|
|
1936
|
+
"@media(prefers-color-scheme:dark){:root{--background:220 10% 7%;--foreground:220 8% 92%;--card:220 9% 9%;--muted:220 8% 15%;--muted-foreground:220 6% 64%;--accent:220 8% 17%;--border:220 8% 18%;--ring:220 8% 54%;--destructive:0 91% 71%;--shadow:none;}}" +
|
|
1937
1937
|
"*{box-sizing:border-box}html{background:hsl(var(--background))}body{margin:0;background:hsl(var(--background));color:hsl(var(--foreground));font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;font-feature-settings:\"cv02\",\"cv03\",\"cv04\",\"cv11\";line-height:1.45}button{font:inherit;color:inherit}main{max-width:1180px;margin:0 auto;padding:20px 18px 44px}.topbar{border-bottom:1px solid hsl(var(--border));background:hsl(var(--background));position:sticky;top:0;z-index:10}.topbar-inner{max-width:1180px;margin:0 auto;padding:14px 18px;display:flex;align-items:center;justify-content:space-between;gap:16px}.title-row{display:flex;align-items:center;gap:9px}.logo-dot{width:10px;height:10px;border-radius:999px;background:#38bdf8;box-shadow:0 0 0 4px rgba(56,189,248,.12)}h1{font-size:20px;line-height:1.1;margin:0;font-weight:650;letter-spacing:0}h2{font-size:15px;line-height:1.2;margin:0;font-weight:650}h3{font-size:14px;line-height:1.3;margin:0;font-weight:600}p{margin:0}.muted,.eyebrow,.meta,.empty{color:hsl(var(--muted-foreground))}.eyebrow{text-transform:uppercase;letter-spacing:.08em;font-size:11px;font-weight:650}.meta{font-size:12px}.tabs{display:inline-flex;align-items:center;gap:2px;border:1px solid hsl(var(--border));background:hsl(var(--muted)/.35);border-radius:8px;padding:2px}.tab{border:0;background:transparent;border-radius:6px;padding:6px 10px;font-size:12px;line-height:1.1;cursor:pointer}.tab:hover{background:hsl(var(--accent)/.5)}.tab.active{background:hsl(var(--background));box-shadow:var(--shadow)}.stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin:18px 0}.card{background:hsl(var(--card));border:1px solid hsl(var(--border));border-radius:8px;padding:14px;box-shadow:var(--shadow)}.stat-value{display:block;font-size:28px;line-height:1.1;font-weight:700;margin-top:6px}.panel{display:none}.panel.active{display:block}.grid{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(280px,.8fr);gap:14px;align-items:start}.grid.equal{grid-template-columns:repeat(2,minmax(0,1fr))}.section-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:12px}.bar{display:flex;overflow:hidden;height:10px;border-radius:999px;background:hsl(var(--muted));margin:10px 0 12px}.bar span{display:block;min-width:2px}.table{width:100%;border-collapse:collapse;font-size:12px}.table th{text-align:left;color:hsl(var(--muted-foreground));font-weight:600;border-bottom:1px solid hsl(var(--border));padding:7px 8px}.table td{border-bottom:1px solid hsl(var(--border));padding:8px;vertical-align:top}.table th:last-child,.table td:last-child{text-align:right}.row-button{width:100%;display:grid;grid-template-columns:minmax(0,1fr) 74px 70px;gap:10px;align-items:center;text-align:left;border:1px solid transparent;background:transparent;border-radius:6px;padding:8px;cursor:pointer}.row-button:hover,.row-button.active{border-color:hsl(var(--border));background:hsl(var(--accent)/.35)}.row-title{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row-meta{font-size:12px;color:hsl(var(--muted-foreground));text-align:right}.badge-list{display:flex;flex-wrap:wrap;gap:6px}.badge{display:inline-flex;align-items:center;gap:5px;border:1px solid hsl(var(--border));border-radius:999px;padding:3px 7px;font-size:11px;background:hsl(var(--background));max-width:100%}.badge .dot{width:7px;height:7px;border-radius:999px;flex:0 0 auto}.tips{margin:0;padding-left:20px}.tips li{margin:0 0 8px}.detail{min-height:228px}.detail-list{display:grid;gap:8px;margin-top:10px}.sample{border:1px solid hsl(var(--border));border-radius:8px;padding:10px;background:hsl(var(--muted)/.22)}.sample-top{display:flex;justify-content:space-between;gap:10px;margin-bottom:5px;font-size:11px;color:hsl(var(--muted-foreground))}.sample p{font-size:12px;color:hsl(var(--foreground));overflow-wrap:anywhere}.session-card{border:1px solid hsl(var(--border));border-radius:8px;background:hsl(var(--card));margin-bottom:10px;overflow:hidden}.session-card summary{list-style:none;display:flex;justify-content:space-between;gap:14px;cursor:pointer;padding:13px 14px}.session-card summary::-webkit-details-marker{display:none}.session-body{border-top:1px solid hsl(var(--border));padding:12px 14px}.session-title{font-size:13px;font-weight:650;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.session-path{font-size:12px;color:hsl(var(--muted-foreground));margin-top:3px;overflow-wrap:anywhere}.token-big{font-size:20px;font-weight:700;white-space:nowrap}.mini-label{margin:10px 0 6px;font-size:11px;text-transform:uppercase;letter-spacing:.08em;font-weight:650;color:hsl(var(--muted-foreground))}.footer{margin-top:20px;color:hsl(var(--muted-foreground));font-size:12px}.hidden{display:none!important}@media(max-width:840px){.topbar-inner{align-items:flex-start;flex-direction:column}.stats,.grid,.grid.equal{grid-template-columns:1fr}.tabs{width:100%;overflow:auto}.tab{white-space:nowrap}.row-button{grid-template-columns:minmax(0,1fr) 64px 58px}.session-card summary{align-items:flex-start;flex-direction:column}}" +
|
|
1938
1938
|
"</style></head><body><header class=\"topbar\"><div class=\"topbar-inner\"><div><div class=\"title-row\"><span class=\"logo-dot\"></span><h1>Context X-Ray</h1></div><p class=\"meta\">Generated " + escapeHtml(report.generatedLabel) + " · mode=" + escapeHtml(report.mode) + " · source=" + escapeHtml(report.source) + " · since=" + escapeHtml(report.since) + "</p></div><nav class=\"tabs\" aria-label=\"Report views\"><button class=\"tab active\" data-tab=\"overview\">Overview</button><button class=\"tab\" data-tab=\"tools\">Tool Calls</button><button class=\"tab\" data-tab=\"mcp\">MCP</button><button class=\"tab\" data-tab=\"metadata\">Metadata</button><button class=\"tab\" data-tab=\"sessions\">Sessions</button></nav></div></header><main><section class=\"stats\" id=\"stats\"></section><section class=\"panel active\" id=\"panel-overview\"></section><section class=\"panel\" id=\"panel-tools\"></section><section class=\"panel\" id=\"panel-mcp\"></section><section class=\"panel\" id=\"panel-metadata\"></section><section class=\"panel\" id=\"panel-sessions\"></section><p class=\"footer\">Reads local transcript and MCP config files only. No transcript content is uploaded.</p></main><script type=\"application/json\" id=\"xray-data\">" + jsonScript(report) + "</script><script>" +
|
|
1939
1939
|
"(function(){var report=JSON.parse(document.getElementById('xray-data').textContent);var cats=['user','assistant','tool_call','tool_output','reasoning','instructions','attachment','metadata','other'];var labels={user:'User asks',assistant:'Assistant text',tool_call:'Tool calls',tool_output:'Tool output',reasoning:'Reasoning',instructions:'Instructions/context',attachment:'Attachments',metadata:'Metadata',other:'Other'};var colors={user:'#8ba8ff',assistant:'#55b982',tool_call:'#f0a85b',tool_output:'#e06b73',reasoning:'#a77be8',instructions:'#6ac3d5',attachment:'#d6a85a',metadata:'#9aa3ad',other:'#c3c8ce'};function esc(v){return String(v||'').replace(/[&<>\"']/g,function(ch){return {'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[ch];});}function fmt(n){n=Number(n)||0;if(n>=1000000)return(n/1000000).toFixed(1)+'m';if(n>=1000)return(n/1000).toFixed(1)+'k';return String(n);}function tok(chars){chars=Number(chars)||0;return chars>0?Math.max(1,Math.ceil(chars/4)):0;}function pc(part,total){return total>0?Math.max(0,Math.min(100,(part/total)*100)):0;}function totalCounter(counter){return Object.keys(counter||{}).reduce(function(sum,key){return sum+(Number(counter[key])||0);},0);}function bar(counter){var total=totalCounter(counter);if(!total)return'<div class=\"bar\"></div>';return'<div class=\"bar\">'+cats.map(function(cat){var value=counter[cat]||0;if(!value)return'';return'<span title=\"'+esc(labels[cat])+'\" style=\"width:'+Math.max(1,pc(value,total)).toFixed(2)+'%;background:'+colors[cat]+'\"></span>';}).join('')+'</div>';}function metric(label,value){return'<article class=\"card\"><div class=\"eyebrow\">'+esc(label)+'</div><span class=\"stat-value\">'+esc(value)+'</span></article>';}function tableRows(entries,kind){if(!entries||!entries.length)return'<tr><td>None detected</td><td></td></tr>';return entries.map(function(entry){var value=entry[1];var shown=kind==='chars'?fmt(tok(value)):(kind==='tokens'?fmt(value):String(value));return'<tr><td>'+esc(entry[0])+'</td><td>'+esc(shown)+'</td></tr>';}).join('');}function toolToken(name){var found=(report.toolTokens||[]).filter(function(entry){return entry[0]===name;})[0];return found?found[1]:0;}function renderStats(){var counts=report.sourceCounts||{};document.getElementById('stats').innerHTML=metric('Sessions',report.sessionCount)+metric('Observed/estimated tokens',fmt(report.totalTokens))+metric('Codex',counts.codex||0)+metric('Claude',counts.claude||0);}function renderOverview(){var categoryTotal=totalCounter(report.categories);var categoryRows=cats.map(function(cat){var chars=(report.categories||{})[cat]||0;if(!chars)return'';return'<tr><td><span class=\"badge\"><span class=\"dot\" style=\"background:'+colors[cat]+'\"></span>'+esc(labels[cat])+'</span></td><td>'+fmt(tok(chars))+'</td><td>'+pc(chars,categoryTotal).toFixed(0)+'%</td></tr>';}).join('');document.getElementById('panel-overview').innerHTML='<div class=\"grid\"><section class=\"card\"><div class=\"section-head\"><div><h2>Where The Context Is Going</h2><p class=\"meta\">Approximate contribution by transcript bucket.</p></div></div>'+bar(report.categories)+'<table class=\"table\"><tbody>'+categoryRows+'</tbody></table></section><section class=\"card\"><div class=\"section-head\"><div><h2>Warnings And Optimizations</h2><p class=\"meta\">Promptable changes you control.</p></div></div><ol class=\"tips\">'+(report.recommendations||[]).map(function(tip){return'<li>'+esc(tip)+'</li>';}).join('')+'</ol></section></div><div class=\"grid equal\" style=\"margin-top:14px\"><section class=\"card\"><h2>Top Paths</h2><table class=\"table\"><tbody>'+tableRows(report.paths,'count')+'</tbody></table></section><section class=\"card\"><h2>Metadata Types</h2><table class=\"table\"><tbody>'+tableRows(report.metadata,'chars')+'</tbody></table></section></div>';}function renderTools(){var rows=(report.tools||[]).map(function(entry,index){var name=entry[0];var count=entry[1];return'<button class=\"row-button'+(index===0?' active':'')+'\" data-tool=\"'+esc(name)+'\"><span><span class=\"row-title\">'+esc(name)+'</span><span class=\"meta\">Click to inspect sampled calls</span></span><span class=\"row-meta\">x'+count+'</span><span class=\"row-meta\">'+fmt(toolToken(name))+' tok</span></button>';}).join('')||'<div class=\"empty\">No tool calls detected in these sessions.</div>';document.getElementById('panel-tools').innerHTML='<div class=\"grid\"><section class=\"card\"><div class=\"section-head\"><div><h2>Tool Calls</h2><p class=\"meta\">Calls are clickable; samples are capped so the report stays light.</p></div></div><div>'+rows+'</div></section><aside class=\"card detail\" id=\"tool-detail\"></aside></div>';Array.prototype.forEach.call(document.querySelectorAll('[data-tool]'),function(btn){btn.addEventListener('click',function(){Array.prototype.forEach.call(document.querySelectorAll('[data-tool]'),function(item){item.classList.remove('active');});btn.classList.add('active');renderToolDetail(btn.getAttribute('data-tool'));});});if((report.tools||[]).length)renderToolDetail(report.tools[0][0]);else document.getElementById('tool-detail').innerHTML='<h2>Tool Detail</h2><p class=\"empty\">Nothing to inspect yet.</p>';}function renderToolDetail(name){var events=(report.toolEvents||[]).filter(function(event){return event.tool===name;}).slice(0,30);document.getElementById('tool-detail').innerHTML='<div class=\"section-head\"><div><h2>'+esc(name)+'</h2><p class=\"meta\">'+events.length+' sampled call'+(events.length===1?'':'s')+'</p></div></div><div class=\"detail-list\">'+(events.map(function(event){return'<article class=\"sample\"><div class=\"sample-top\"><span>'+esc(event.source)+' · '+esc(event.sessionTitle||event.sessionId)+'</span><span>'+fmt(event.tokens||0)+' tok</span></div><p>'+esc(event.preview||'No preview captured.')+'</p></article>';}).join('')||'<p class=\"empty\">No sampled call payloads for this tool.</p>')+'</div>';}function renderMcp(){var servers=report.mcpServers||[];var usage=report.mcpUsage||[];var configured=servers.map(function(server){return'<button class=\"row-button\" data-mcp=\"'+esc(server.name)+'\"><span><span class=\"row-title\">'+esc(server.name)+'</span><span class=\"meta\">'+esc(server.source)+' · '+esc(server.target)+'</span></span><span class=\"row-meta\">config</span><span class=\"row-meta\"></span></button>';}).join('')||'<div class=\"empty\">No MCP server config found in the common local config files.</div>';var detected=usage.map(function(entry,index){return'<button class=\"row-button'+(!servers.length&&index===0?' active':'')+'\" data-mcp=\"'+esc(entry[0])+'\"><span><span class=\"row-title\">'+esc(entry[0])+'</span><span class=\"meta\">Detected from mcp__server__tool style names</span></span><span class=\"row-meta\">x'+entry[1]+'</span><span class=\"row-meta\"></span></button>';}).join('')||'<div class=\"empty\">No MCP-prefixed tool calls detected in the selected sessions.</div>';document.getElementById('panel-mcp').innerHTML='<div class=\"grid\"><section class=\"card\"><div class=\"section-head\"><div><h2>MCP Servers</h2><p class=\"meta\">Configured locally plus inferred calls from transcripts.</p></div></div><div class=\"mini-label\">Configured</div>'+configured+'<div class=\"mini-label\">Detected usage</div>'+detected+'</section><aside class=\"card detail\" id=\"mcp-detail\"></aside></div>';Array.prototype.forEach.call(document.querySelectorAll('[data-mcp]'),function(btn){btn.addEventListener('click',function(){Array.prototype.forEach.call(document.querySelectorAll('[data-mcp]'),function(item){item.classList.remove('active');});btn.classList.add('active');renderMcpDetail(btn.getAttribute('data-mcp'));});});if(usage.length)renderMcpDetail(usage[0][0]);else if(servers.length)renderMcpDetail(servers[0].name);else document.getElementById('mcp-detail').innerHTML='<h2>MCP Detail</h2><p class=\"empty\">Install or run sessions with MCP tools to see usage here.</p>';}function renderMcpDetail(name){var server=(report.mcpServers||[]).filter(function(item){return item.name===name;})[0];var tools=(report.mcpTools||[]).filter(function(entry){return entry[0].indexOf(name+' / ')===0;});var events=(report.toolEvents||[]).filter(function(event){return event.mcpServer===name;}).slice(0,25);document.getElementById('mcp-detail').innerHTML='<div class=\"section-head\"><div><h2>'+esc(name)+'</h2><p class=\"meta\">'+(server?esc(server.source+' · '+server.target):'Detected from tool call names')+'</p></div></div><div class=\"mini-label\">Tools</div><table class=\"table\"><tbody>'+tableRows(tools,'count')+'</tbody></table><div class=\"mini-label\">Sample calls</div><div class=\"detail-list\">'+(events.map(function(event){return'<article class=\"sample\"><div class=\"sample-top\"><span>'+esc(event.mcpTool||event.tool)+'</span><span>'+fmt(event.tokens||0)+' tok</span></div><p>'+esc(event.preview||'No preview captured.')+'</p></article>';}).join('')||'<p class=\"empty\">No sampled MCP calls for this server in the selected sessions.</p>')+'</div>';}function renderMetadata(){var rows=(report.metadata||[]).map(function(entry,index){return'<button class=\"row-button'+(index===0?' active':'')+'\" data-meta=\"'+esc(entry[0])+'\"><span><span class=\"row-title\">'+esc(entry[0])+'</span><span class=\"meta\">Click to inspect sampled records</span></span><span class=\"row-meta\">'+fmt(tok(entry[1]))+' tok</span><span class=\"row-meta\">'+fmt(entry[1])+' ch</span></button>';}).join('')||'<div class=\"empty\">No metadata-heavy records detected.</div>';document.getElementById('panel-metadata').innerHTML='<div class=\"grid\"><section class=\"card\"><div class=\"section-head\"><div><h2>Metadata</h2><p class=\"meta\">Breakdown by transcript record type.</p></div></div>'+rows+'</section><aside class=\"card detail\" id=\"metadata-detail\"></aside></div>';Array.prototype.forEach.call(document.querySelectorAll('[data-meta]'),function(btn){btn.addEventListener('click',function(){Array.prototype.forEach.call(document.querySelectorAll('[data-meta]'),function(item){item.classList.remove('active');});btn.classList.add('active');renderMetadataDetail(btn.getAttribute('data-meta'));});});if((report.metadata||[]).length)renderMetadataDetail(report.metadata[0][0]);else document.getElementById('metadata-detail').innerHTML='<h2>Metadata Detail</h2><p class=\"empty\">Nothing to inspect yet.</p>';}function renderMetadataDetail(type){var events=(report.metadataEvents||[]).filter(function(event){return event.type===type;}).slice(0,30);document.getElementById('metadata-detail').innerHTML='<div class=\"section-head\"><div><h2>'+esc(type)+'</h2><p class=\"meta\">'+events.length+' sampled record'+(events.length===1?'':'s')+'</p></div></div><div class=\"detail-list\">'+(events.map(function(event){return'<article class=\"sample\"><div class=\"sample-top\"><span>'+esc(event.source)+' · '+esc(event.sessionTitle||event.sessionId)+'</span><span>'+fmt(event.tokens||0)+' tok</span></div><p>'+esc(event.preview||'No preview captured.')+'</p></article>';}).join('')||'<p class=\"empty\">No sampled records for this metadata type.</p>')+'</div>';}function renderSessions(){document.getElementById('panel-sessions').innerHTML=(report.sessions||[]).map(function(session,index){var catRows=Object.keys(session.categories||{}).sort(function(a,b){return session.categories[b]-session.categories[a];}).map(function(cat){var chars=session.categories[cat];return'<tr><td>'+esc(labels[cat]||cat)+'</td><td>'+fmt(tok(chars))+'</td><td>'+pc(chars,session.totalChars||0).toFixed(0)+'%</td></tr>';}).join('');var tools=(session.tools?Object.keys(session.tools):[]).sort(function(a,b){return session.tools[b]-session.tools[a];}).slice(0,8).map(function(name){return'<span class=\"badge\">'+esc(name)+' x'+session.tools[name]+'</span>';}).join('')||'<span class=\"empty\">none detected</span>';var paths=(session.paths?Object.keys(session.paths):[]).sort(function(a,b){return session.paths[b]-session.paths[a];}).slice(0,8).map(function(name){return'<span class=\"badge\">'+esc(name)+' x'+session.paths[name]+'</span>';}).join('')||'<span class=\"empty\">none detected</span>';return'<details class=\"session-card\"'+(index===0?' open':'')+'><summary><span><span class=\"eyebrow\">'+esc(session.source)+' · '+esc(session.updatedAt||'unknown time')+'</span><span class=\"session-title\">'+esc(session.title||session.sessionId)+'</span><span class=\"session-path\">'+esc(session.cwd||session.path)+'</span></span><span class=\"token-big\">'+fmt(session.tokens)+'</span></summary><div class=\"session-body\">'+bar(session.categories)+'<div class=\"grid equal\"><div><div class=\"mini-label\">Buckets</div><table class=\"table\"><tbody>'+catRows+'</tbody></table></div><div><div class=\"mini-label\">Frequent tools</div><div class=\"badge-list\">'+tools+'</div><div class=\"mini-label\">Repeated paths</div><div class=\"badge-list\">'+paths+'</div></div></div></div></details>';}).join('')||'<section class=\"card\"><p class=\"empty\">No matching sessions found.</p></section>';}function activate(name){Array.prototype.forEach.call(document.querySelectorAll('.tab'),function(tab){tab.classList.toggle('active',tab.getAttribute('data-tab')===name);});Array.prototype.forEach.call(document.querySelectorAll('.panel'),function(panel){panel.classList.toggle('active',panel.id==='panel-'+name);});if(location.hash!=='#'+name)history.replaceState(null,'','#'+name);}Array.prototype.forEach.call(document.querySelectorAll('.tab'),function(tab){tab.addEventListener('click',function(){activate(tab.getAttribute('data-tab'));});});renderStats();renderOverview();renderTools();renderMcp();renderMetadata();renderSessions();var initial=(location.hash||'#overview').slice(1);if(document.getElementById('panel-'+initial))activate(initial);})();" +
|
package/src/cli/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { fileURLToPath } from "url";
|
|
|
9
9
|
import * as Sentry from "@sentry/node";
|
|
10
10
|
|
|
11
11
|
import { resolveDeployPostBuildInvocation } from "./deploy-build.js";
|
|
12
|
+
import { createCliTelemetry } from "./telemetry.js";
|
|
12
13
|
|
|
13
14
|
// Resolve version once at module scope — used by both --version and --help
|
|
14
15
|
let _version = "unknown";
|
|
@@ -170,6 +171,12 @@ const BUGS_URL = "https://github.com/BuilderIO/agent-native/issues";
|
|
|
170
171
|
const command = process.argv[2];
|
|
171
172
|
// Filter out bare "--" separators that pnpm inserts between its args and script args
|
|
172
173
|
const args = process.argv.slice(3).filter((a) => a !== "--");
|
|
174
|
+
const cliTelemetry = createCliTelemetry({
|
|
175
|
+
cli: "core",
|
|
176
|
+
cliVersion: _version,
|
|
177
|
+
command: command ?? "none",
|
|
178
|
+
interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY),
|
|
179
|
+
});
|
|
173
180
|
|
|
174
181
|
function parseScaffoldArgs(argv: string[]): {
|
|
175
182
|
name?: string;
|
|
@@ -203,25 +210,34 @@ function parseScaffoldArgs(argv: string[]): {
|
|
|
203
210
|
// Track CLI usage (best-effort, non-blocking)
|
|
204
211
|
function trackCli(event: string, props?: Record<string, unknown>): void {
|
|
205
212
|
try {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
213
|
+
cliTelemetry.track(event, { command, ...props });
|
|
214
|
+
} catch {}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function captureCliException(
|
|
218
|
+
error: unknown,
|
|
219
|
+
context?: Parameters<typeof cliTelemetry.captureException>[1],
|
|
220
|
+
): void {
|
|
221
|
+
try {
|
|
222
|
+
cliTelemetry.captureException(error, context);
|
|
212
223
|
} catch {}
|
|
213
224
|
}
|
|
214
225
|
|
|
226
|
+
function flushTelemetryAndExit(code: number): void {
|
|
227
|
+
void Promise.allSettled([cliTelemetry.flush(), Sentry.flush(2000)]).finally(
|
|
228
|
+
() => process.exit(code),
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
215
232
|
// Global error handler — show feedback link on unhandled crashes
|
|
216
233
|
process.on("uncaughtException", (err) => {
|
|
217
234
|
console.error(`\n Unexpected error: ${err.message}\n`);
|
|
218
235
|
console.error(` Report this bug: ${BUGS_URL}`);
|
|
219
236
|
console.error(` Send feedback: ${FEEDBACK_URL}\n`);
|
|
220
237
|
trackCli("cli.crash", { error: err.message });
|
|
238
|
+
captureCliException(err, { handled: false, tags: { source: "process" } });
|
|
221
239
|
Sentry.captureException(err);
|
|
222
|
-
|
|
223
|
-
.catch(() => undefined)
|
|
224
|
-
.finally(() => process.exit(1));
|
|
240
|
+
flushTelemetryAndExit(1);
|
|
225
241
|
});
|
|
226
242
|
|
|
227
243
|
process.on("unhandledRejection", (reason: any) => {
|
|
@@ -229,16 +245,18 @@ process.on("unhandledRejection", (reason: any) => {
|
|
|
229
245
|
console.error(` Report this bug: ${BUGS_URL}`);
|
|
230
246
|
console.error(` Send feedback: ${FEEDBACK_URL}\n`);
|
|
231
247
|
trackCli("cli.crash", { error: reason?.message ?? String(reason) });
|
|
248
|
+
captureCliException(reason, {
|
|
249
|
+
handled: false,
|
|
250
|
+
tags: { source: "unhandled-rejection" },
|
|
251
|
+
});
|
|
232
252
|
Sentry.captureException(reason);
|
|
233
|
-
|
|
234
|
-
.catch(() => undefined)
|
|
235
|
-
.finally(() => process.exit(1));
|
|
253
|
+
flushTelemetryAndExit(1);
|
|
236
254
|
});
|
|
237
255
|
|
|
238
256
|
// Surface a self-heal hint when an interrupted `npx @agent-native/core@latest ...`
|
|
239
257
|
// leaves a half-extracted package in the npx cache and a follow-up run fails
|
|
240
258
|
// to load one of our own sub-modules.
|
|
241
|
-
function handleScaffoldImportError(err: any):
|
|
259
|
+
function handleScaffoldImportError(err: any): void {
|
|
242
260
|
const msg = err?.message ?? String(err);
|
|
243
261
|
const looksLikeCorruptCache =
|
|
244
262
|
err?.code === "ERR_MODULE_NOT_FOUND" ||
|
|
@@ -255,9 +273,12 @@ function handleScaffoldImportError(err: any): never {
|
|
|
255
273
|
console.error(`\n Failed to load the scaffolder: ${msg}\n`);
|
|
256
274
|
}
|
|
257
275
|
trackCli("cli.scaffold.import_error", { error: msg });
|
|
276
|
+
captureCliException(err, {
|
|
277
|
+
handled: false,
|
|
278
|
+
tags: { source: "scaffold-import" },
|
|
279
|
+
});
|
|
258
280
|
Sentry.captureException(err);
|
|
259
|
-
|
|
260
|
-
throw err;
|
|
281
|
+
flushTelemetryAndExit(1);
|
|
261
282
|
}
|
|
262
283
|
|
|
263
284
|
function findBinUpwards(binName: string): string | undefined {
|
|
@@ -525,7 +546,17 @@ function runBuildStep(
|
|
|
525
546
|
stage: "spawn",
|
|
526
547
|
},
|
|
527
548
|
});
|
|
528
|
-
|
|
549
|
+
captureCliException(err, {
|
|
550
|
+
handled: false,
|
|
551
|
+
tags: {
|
|
552
|
+
source: "build-step",
|
|
553
|
+
buildStep: opts.label,
|
|
554
|
+
...(template ? { template } : {}),
|
|
555
|
+
...(app ? { app } : {}),
|
|
556
|
+
},
|
|
557
|
+
extra: { stage: "spawn" },
|
|
558
|
+
});
|
|
559
|
+
flushTelemetryAndExit(1);
|
|
529
560
|
});
|
|
530
561
|
|
|
531
562
|
child.on("exit", (code, signal) => {
|
|
@@ -557,8 +588,18 @@ function runBuildStep(
|
|
|
557
588
|
stdoutTail: stdoutBuf,
|
|
558
589
|
},
|
|
559
590
|
});
|
|
591
|
+
captureCliException(err, {
|
|
592
|
+
handled: false,
|
|
593
|
+
tags: {
|
|
594
|
+
source: "build-step",
|
|
595
|
+
buildStep: opts.label,
|
|
596
|
+
...(template ? { template } : {}),
|
|
597
|
+
...(app ? { app } : {}),
|
|
598
|
+
},
|
|
599
|
+
extra: { exitCode, signal: signal ?? null },
|
|
600
|
+
});
|
|
560
601
|
// Don't throw — see comment on runBuildStep above.
|
|
561
|
-
|
|
602
|
+
flushTelemetryAndExit(exitCode);
|
|
562
603
|
});
|
|
563
604
|
});
|
|
564
605
|
}
|
|
@@ -690,8 +731,12 @@ switch (command) {
|
|
|
690
731
|
// implies a programming error in the orchestration above. Capture
|
|
691
732
|
// and exit so the global unhandledRejection handler doesn't double-
|
|
692
733
|
// report with a generic title.
|
|
734
|
+
captureCliException(err, {
|
|
735
|
+
handled: false,
|
|
736
|
+
tags: { source: "orchestration" },
|
|
737
|
+
});
|
|
693
738
|
Sentry.captureException(err);
|
|
694
|
-
|
|
739
|
+
flushTelemetryAndExit(1);
|
|
695
740
|
});
|
|
696
741
|
break;
|
|
697
742
|
}
|
package/src/cli/skills.ts
CHANGED
|
@@ -4454,6 +4454,11 @@ export async function runSkills(
|
|
|
4454
4454
|
error: error instanceof Error ? error.message : String(error),
|
|
4455
4455
|
durationMs: Date.now() - startedAt,
|
|
4456
4456
|
});
|
|
4457
|
+
telemetry.captureException(error, {
|
|
4458
|
+
handled: false,
|
|
4459
|
+
tags: { source: "skills-command", command: parsed.command },
|
|
4460
|
+
extra: { durationMs: Date.now() - startedAt },
|
|
4461
|
+
});
|
|
4457
4462
|
throw error;
|
|
4458
4463
|
} finally {
|
|
4459
4464
|
await telemetry.flush();
|
package/src/cli/telemetry.ts
CHANGED
|
@@ -38,9 +38,17 @@ export interface CliTelemetryOptions {
|
|
|
38
38
|
|
|
39
39
|
export interface CliTelemetry {
|
|
40
40
|
track(event: string, properties?: Record<string, unknown>): void;
|
|
41
|
+
captureException(error: unknown, context?: CliExceptionContext): void;
|
|
41
42
|
flush(): Promise<void>;
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
export interface CliExceptionContext {
|
|
46
|
+
handled?: boolean;
|
|
47
|
+
level?: "fatal" | "error" | "warning" | "info" | "debug";
|
|
48
|
+
tags?: Record<string, string | number | boolean | null | undefined>;
|
|
49
|
+
extra?: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
function resolvePublicKey(): string {
|
|
45
53
|
const fromEnv = process.env.AGENT_NATIVE_ANALYTICS_PUBLIC_KEY?.trim();
|
|
46
54
|
return fromEnv || EMBEDDED_PUBLIC_KEY;
|
|
@@ -60,6 +68,110 @@ function telemetryDisabled(): boolean {
|
|
|
60
68
|
);
|
|
61
69
|
}
|
|
62
70
|
|
|
71
|
+
const MAX_EXCEPTION_MESSAGE_LENGTH = 1000;
|
|
72
|
+
const MAX_EXCEPTION_STACK_LENGTH = 8000;
|
|
73
|
+
const MAX_EXCEPTION_TAGS = 30;
|
|
74
|
+
const MAX_EXCEPTION_EXTRA_KEYS = 30;
|
|
75
|
+
const MAX_EXCEPTION_VALUE_LENGTH = 1000;
|
|
76
|
+
const SECRET_RE = /\b(?:bearer|basic)\s+[^\s]+/gi;
|
|
77
|
+
const SECRET_KEY_RE =
|
|
78
|
+
/(?:authorization|cookie|set[-_]?cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)/i;
|
|
79
|
+
|
|
80
|
+
function redactExceptionText(value: string): string {
|
|
81
|
+
return value
|
|
82
|
+
.replace(SECRET_RE, (match) => `${match.split(/\s+/, 1)[0]} <redacted>`)
|
|
83
|
+
.replace(
|
|
84
|
+
/([A-Za-z0-9_$.-]*(?:authorization|cookie|token|secret|password|passwd|pwd|api[-_]?key|apikey|credential)[A-Za-z0-9_$.-]*\s*[:=]\s*)([^\s,;}]+)/gi,
|
|
85
|
+
"$1<redacted>",
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function boundedExceptionText(value: unknown, max: number): string {
|
|
90
|
+
const text =
|
|
91
|
+
typeof value === "string" ? value : String(value ?? "Unknown error");
|
|
92
|
+
const safe = redactExceptionText(text);
|
|
93
|
+
return safe.length > max ? safe.slice(0, max) : safe;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function safeExceptionValue(value: unknown, depth = 2): unknown {
|
|
97
|
+
if (
|
|
98
|
+
value == null ||
|
|
99
|
+
typeof value === "boolean" ||
|
|
100
|
+
typeof value === "number"
|
|
101
|
+
) {
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
if (typeof value === "string") {
|
|
105
|
+
return boundedExceptionText(value, MAX_EXCEPTION_VALUE_LENGTH);
|
|
106
|
+
}
|
|
107
|
+
if (depth <= 0)
|
|
108
|
+
return boundedExceptionText(value, MAX_EXCEPTION_VALUE_LENGTH);
|
|
109
|
+
if (Array.isArray(value)) {
|
|
110
|
+
return value
|
|
111
|
+
.slice(0, 20)
|
|
112
|
+
.map((item) => safeExceptionValue(item, depth - 1));
|
|
113
|
+
}
|
|
114
|
+
if (typeof value === "object") {
|
|
115
|
+
const out: Record<string, unknown> = {};
|
|
116
|
+
for (const [key, child] of Object.entries(value)) {
|
|
117
|
+
if (Object.keys(out).length >= MAX_EXCEPTION_EXTRA_KEYS) break;
|
|
118
|
+
const safeKey = boundedExceptionText(key, 100);
|
|
119
|
+
out[safeKey] = SECRET_KEY_RE.test(safeKey)
|
|
120
|
+
? "<redacted>"
|
|
121
|
+
: safeExceptionValue(child, depth - 1);
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
return boundedExceptionText(value, MAX_EXCEPTION_VALUE_LENGTH);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function captureException(
|
|
129
|
+
error: unknown,
|
|
130
|
+
context: CliExceptionContext,
|
|
131
|
+
trackEvent: (event: string, properties?: Record<string, unknown>) => void,
|
|
132
|
+
): void {
|
|
133
|
+
const exception =
|
|
134
|
+
error instanceof Error
|
|
135
|
+
? {
|
|
136
|
+
type: boundedExceptionText(error.name || "Error", 200),
|
|
137
|
+
message: boundedExceptionText(
|
|
138
|
+
error.message || error.name || "Error",
|
|
139
|
+
MAX_EXCEPTION_MESSAGE_LENGTH,
|
|
140
|
+
),
|
|
141
|
+
stack: error.stack
|
|
142
|
+
? boundedExceptionText(error.stack, MAX_EXCEPTION_STACK_LENGTH)
|
|
143
|
+
: undefined,
|
|
144
|
+
}
|
|
145
|
+
: {
|
|
146
|
+
type: "Error",
|
|
147
|
+
message: boundedExceptionText(error, MAX_EXCEPTION_MESSAGE_LENGTH),
|
|
148
|
+
stack: undefined,
|
|
149
|
+
};
|
|
150
|
+
const tags: Record<string, string> = {};
|
|
151
|
+
for (const [key, value] of Object.entries(context.tags ?? {})) {
|
|
152
|
+
if (Object.keys(tags).length >= MAX_EXCEPTION_TAGS || value == null) break;
|
|
153
|
+
const safeKey = boundedExceptionText(key, 100);
|
|
154
|
+
tags[safeKey] = SECRET_KEY_RE.test(safeKey)
|
|
155
|
+
? "<redacted>"
|
|
156
|
+
: boundedExceptionText(value, 200);
|
|
157
|
+
}
|
|
158
|
+
const extra = safeExceptionValue(context.extra);
|
|
159
|
+
trackEvent("$exception", {
|
|
160
|
+
app: "agent-native-cli",
|
|
161
|
+
template: "cli",
|
|
162
|
+
runtime: "cli",
|
|
163
|
+
source: "cli",
|
|
164
|
+
exceptionType: exception.type,
|
|
165
|
+
exceptionMessage: exception.message,
|
|
166
|
+
...(exception.stack ? { exceptionStack: exception.stack } : {}),
|
|
167
|
+
handled: context.handled ?? false,
|
|
168
|
+
level: context.level ?? "error",
|
|
169
|
+
occurredAt: new Date().toISOString(),
|
|
170
|
+
...(Object.keys(tags).length ? { exceptionTags: tags } : {}),
|
|
171
|
+
...(extra && typeof extra === "object" ? { exceptionExtra: extra } : {}),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
63
175
|
/**
|
|
64
176
|
* Read (or lazily create) a stable per-machine install id, shared across both
|
|
65
177
|
* skills CLIs so one developer counts once. Best-effort: an unwritable home
|
|
@@ -132,5 +244,10 @@ export function createCliTelemetry(options: CliTelemetryOptions): CliTelemetry {
|
|
|
132
244
|
]);
|
|
133
245
|
}
|
|
134
246
|
|
|
135
|
-
return {
|
|
247
|
+
return {
|
|
248
|
+
track,
|
|
249
|
+
captureException: (error, context = {}) =>
|
|
250
|
+
captureException(error, context, track),
|
|
251
|
+
flush,
|
|
252
|
+
};
|
|
136
253
|
}
|
|
@@ -2745,6 +2745,12 @@ export interface AgentSidebarProps {
|
|
|
2745
2745
|
* page-level AgentChatSurface can morph into it on navigation.
|
|
2746
2746
|
*/
|
|
2747
2747
|
chatViewTransition?: boolean;
|
|
2748
|
+
/**
|
|
2749
|
+
* Mark the initial panel mount as the destination of a page-to-sidebar chat
|
|
2750
|
+
* handoff. This suppresses only the drawer's initial entry animation; normal
|
|
2751
|
+
* sidebar open/close transitions remain enabled.
|
|
2752
|
+
*/
|
|
2753
|
+
chatViewTransitionHandoff?: boolean;
|
|
2748
2754
|
/** Namespace for persisted chat state. Use the same key as AgentChatHome. */
|
|
2749
2755
|
storageKey?: string;
|
|
2750
2756
|
/** Open the sidebar when a chat run is active or reconnects. */
|
|
@@ -2784,6 +2790,7 @@ export function AgentSidebar({
|
|
|
2784
2790
|
animateMobile = true,
|
|
2785
2791
|
animateDesktop = true,
|
|
2786
2792
|
chatViewTransition = false,
|
|
2793
|
+
chatViewTransitionHandoff = false,
|
|
2787
2794
|
storageKey,
|
|
2788
2795
|
openOnChatRunning = false,
|
|
2789
2796
|
onFullscreenRequest,
|
|
@@ -3308,6 +3315,9 @@ export function AgentSidebar({
|
|
|
3308
3315
|
data-agent-sidebar-position={position}
|
|
3309
3316
|
data-agent-sidebar-state={panelOpen ? "open" : "closed"}
|
|
3310
3317
|
data-agent-sidebar-resizing={isResizing ? "true" : undefined}
|
|
3318
|
+
data-agent-sidebar-chat-handoff={
|
|
3319
|
+
chatViewTransitionHandoff ? "true" : undefined
|
|
3320
|
+
}
|
|
3311
3321
|
style={
|
|
3312
3322
|
chatViewTransition
|
|
3313
3323
|
? getAgentChatViewTransitionStyle(panelStyle)
|
|
@@ -576,6 +576,14 @@ CommandMenu.Separator = CommandSeparator;
|
|
|
576
576
|
|
|
577
577
|
// ─── Keyboard Hook ──────────────────────────────────────────────────────────
|
|
578
578
|
|
|
579
|
+
export const COMMAND_MENU_OPEN_EVENT = "agent-native:open-command-menu";
|
|
580
|
+
|
|
581
|
+
export function openCommandMenu() {
|
|
582
|
+
if (typeof window !== "undefined") {
|
|
583
|
+
window.dispatchEvent(new Event(COMMAND_MENU_OPEN_EVENT));
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
579
587
|
/**
|
|
580
588
|
* Hook to handle Cmd+K (or Ctrl+K) to open the command menu
|
|
581
589
|
*/
|
|
@@ -601,10 +609,14 @@ export function useCommandMenuShortcut(
|
|
|
601
609
|
onOpen();
|
|
602
610
|
}
|
|
603
611
|
};
|
|
612
|
+
const handleOpenRequest = () => onOpen();
|
|
604
613
|
const useCapture = Boolean(options.allowContentEditable);
|
|
605
614
|
document.addEventListener("keydown", handleKeyDown, useCapture);
|
|
606
|
-
|
|
615
|
+
window.addEventListener(COMMAND_MENU_OPEN_EVENT, handleOpenRequest);
|
|
616
|
+
return () => {
|
|
607
617
|
document.removeEventListener("keydown", handleKeyDown, useCapture);
|
|
618
|
+
window.removeEventListener(COMMAND_MENU_OPEN_EVENT, handleOpenRequest);
|
|
619
|
+
};
|
|
608
620
|
}, [onOpen, options.allowContentEditable]);
|
|
609
621
|
}
|
|
610
622
|
|