@agent-native/core 0.77.6 → 0.77.7
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 +1 -1
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +3 -3
- package/corpus/core/src/agent/thread-data-builder.ts +21 -2
- package/corpus/core/src/cli/create.ts +35 -1
- package/corpus/core/src/cli/skills.ts +8 -0
- package/corpus/core/src/client/AgentPanel.tsx +57 -25
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +31 -1
- package/corpus/core/src/client/analytics.ts +24 -2
- package/corpus/core/src/client/use-agent-engine-configured.ts +29 -15
- package/corpus/core/src/client/use-chat-threads.ts +104 -55
- package/corpus/core/src/server/analytics.ts +27 -3
- package/corpus/core/src/sharing/access.ts +35 -13
- package/corpus/core/src/sharing/actions/share-resource.ts +32 -9
- package/corpus/core/src/sharing/actions/unshare-resource.ts +25 -2
- package/corpus/core/src/sharing/registry.ts +9 -0
- package/corpus/core/src/vite/client.ts +3 -0
- package/corpus/templates/analytics/actions/data-source-status.ts +25 -14
- package/corpus/templates/analytics/app/components/layout/NewAnalysisDialog.tsx +2 -2
- package/corpus/templates/analytics/app/lib/data-source-status.ts +47 -6
- package/corpus/templates/analytics/app/lib/data-sources.ts +14 -3
- package/corpus/templates/analytics/app/pages/DataSources.tsx +24 -5
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +15 -43
- package/corpus/templates/analytics/changelog/2026-06-25-fixed-hubspot-data-source-status-so-private-app-tokens-legac.md +6 -0
- package/corpus/templates/analytics/netlify.toml +1 -0
- package/corpus/templates/analytics/server/lib/credential-keys.ts +3 -1
- package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +12 -3
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +5 -2
- package/corpus/templates/assets/changelog/2026-06-25-create-now-returns-from-agent-settings-to-the-asset-chat-eve.md +6 -0
- package/corpus/templates/assets/netlify.toml +1 -0
- package/corpus/templates/brain/netlify.toml +1 -0
- package/corpus/templates/calendar/app/i18n-data.ts +12 -0
- package/corpus/templates/calendar/app/lib/clipboard.ts +58 -0
- package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +15 -9
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +6 -2
- package/corpus/templates/calendar/changelog/2026-06-25-booking-link-copy-buttons-no-longer-fail-when-clipboard-perm.md +6 -0
- package/corpus/templates/calendar/netlify.toml +1 -0
- package/corpus/templates/chat/netlify.toml +1 -0
- package/corpus/templates/clips/AGENTS.md +9 -7
- package/corpus/templates/clips/actions/add-vocabulary-term.ts +2 -2
- package/corpus/templates/clips/actions/archive-recording.ts +5 -2
- package/corpus/templates/clips/actions/clear-edits.ts +5 -2
- package/corpus/templates/clips/actions/create-folder.ts +7 -2
- package/corpus/templates/clips/actions/delete-folder.ts +7 -4
- package/corpus/templates/clips/actions/delete-recording-permanent.ts +5 -2
- package/corpus/templates/clips/actions/finalize-recording.ts +5 -2
- package/corpus/templates/clips/actions/import-loom-recording.ts +2 -1
- package/corpus/templates/clips/actions/list-notifications.ts +9 -5
- package/corpus/templates/clips/actions/list-organization-state.ts +2 -1
- package/corpus/templates/clips/actions/list-recordings.ts +4 -1
- package/corpus/templates/clips/actions/move-recording.ts +5 -1
- package/corpus/templates/clips/actions/rename-folder.ts +6 -3
- package/corpus/templates/clips/actions/request-transcript.ts +5 -2
- package/corpus/templates/clips/actions/restore-recording.ts +5 -2
- package/corpus/templates/clips/actions/save-browser-diagnostics.ts +21 -8
- package/corpus/templates/clips/actions/set-chapters.ts +5 -2
- package/corpus/templates/clips/actions/set-thumbnail.ts +5 -2
- package/corpus/templates/clips/actions/split-recording.ts +5 -2
- package/corpus/templates/clips/actions/stitch-recordings.ts +6 -2
- package/corpus/templates/clips/actions/trash-recording.ts +5 -2
- package/corpus/templates/clips/actions/undo-edit.ts +5 -2
- package/corpus/templates/clips/actions/view-screen.ts +2 -1
- package/corpus/templates/clips/app/components/library/recording-card.tsx +24 -7
- package/corpus/templates/clips/app/lib/browser-diagnostics-capture.ts +5 -1
- package/corpus/templates/clips/changelog/2026-06-25-chrome-extension-recordings-now-upload-large-capture-bursts.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-25-console-diagnostics-keep-more-useful-non-secret-details-when.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-25-fixed-owner-recognition-so-clips-created-from-desktop-and-we.md +6 -0
- package/corpus/templates/clips/chrome-extension/package.json +3 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +85 -9
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +55 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +79 -3
- package/corpus/templates/clips/chrome-extension/src/options.ts +10 -0
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +6 -0
- package/corpus/templates/clips/chrome-extension/src/permission.ts +8 -1
- package/corpus/templates/clips/chrome-extension/src/popup.ts +65 -39
- package/corpus/templates/clips/chrome-extension/src/sentry.ts +206 -0
- package/corpus/templates/clips/chrome-extension/vite.config.ts +47 -0
- package/corpus/templates/clips/netlify.toml +1 -0
- package/corpus/templates/clips/server/db/index.ts +1 -0
- package/corpus/templates/clips/server/lib/google-calendar-oauth.ts +35 -23
- package/corpus/templates/clips/server/lib/public-agent-context.ts +8 -1
- package/corpus/templates/clips/server/lib/recordings.ts +18 -2
- package/corpus/templates/clips/server/lib/slack-oauth.ts +9 -6
- package/corpus/templates/clips/server/plugins/onboarding-calendar.ts +6 -2
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +2 -2
- package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +5 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +5 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +5 -2
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +5 -2
- package/corpus/templates/clips/shared/browser-diagnostics.ts +14 -4
- package/corpus/templates/content/netlify.toml +1 -0
- package/corpus/templates/design/netlify.toml +1 -0
- package/corpus/templates/dispatch/netlify.toml +1 -0
- package/corpus/templates/forms/netlify.toml +1 -0
- package/corpus/templates/macros/netlify.toml +1 -0
- package/corpus/templates/mail/app/components/email/EmailList.tsx +7 -3
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +4 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +10 -2
- package/corpus/templates/mail/app/hooks/use-compose-state.ts +15 -5
- package/corpus/templates/mail/app/hooks/use-google-auth.ts +47 -9
- package/corpus/templates/mail/changelog/2026-06-25-account-avatars-stay-stable-while-mail-refreshes-google-acco.md +6 -0
- package/corpus/templates/mail/changelog/2026-06-25-mail-background-draft-saves-and-thread-prefetches-no-longer.md +6 -0
- package/corpus/templates/mail/netlify.toml +1 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/references/canvas.md +8 -0
- package/corpus/templates/plan/netlify.toml +1 -0
- package/corpus/templates/slides/netlify.toml +1 -0
- package/corpus/templates/videos/netlify.toml +1 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +23 -2
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +28 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/skills.d.ts +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +8 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +8 -2
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +29 -15
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +4 -4
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +22 -2
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
- package/dist/client/use-agent-engine-configured.js +23 -13
- package/dist/client/use-agent-engine-configured.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts +4 -0
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +49 -4
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/analytics.d.ts +4 -0
- package/dist/server/analytics.d.ts.map +1 -1
- package/dist/server/analytics.js +19 -3
- package/dist/server/analytics.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +26 -12
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +20 -9
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/actions/unshare-resource.js +13 -2
- package/dist/sharing/actions/unshare-resource.js.map +1 -1
- package/dist/sharing/registry.d.ts +9 -0
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/package.json +3 -3
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.77.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e5bdcb3: Paginate the All Chats history client so older conversations can be loaded without truncating the history list.
|
|
8
|
+
- e5bdcb3: Drop benign reasonless browser AbortError events from Sentry reporting.
|
|
9
|
+
- e5bdcb3: Repair duplicate persisted chat message ids during thread normalization.
|
|
10
|
+
- e5bdcb3: Ensure hosted template apps can inject Google Analytics from Netlify build-time configuration.
|
|
11
|
+
- e5bdcb3: Normalize email casing when resolving shareable-resource ownership and user shares, and let resources opt into owner access across active-org drift.
|
|
12
|
+
- e5bdcb3: Re-check current LLM connection status before a stale missing-credentials event can keep chat locked after reconnecting Builder, and prevent page chat surfaces from rendering sidebar settings in the main content area.
|
|
13
|
+
- e5bdcb3: Allow browser Sentry initialization to build a DSN from Vite-exposed Sentry client key, project id, and ingest host env vars when runtime config injection is unavailable.
|
|
14
|
+
|
|
3
15
|
## 0.77.6
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.77.
|
|
3
|
+
"version": "0.77.7",
|
|
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": {
|
|
@@ -211,8 +211,8 @@
|
|
|
211
211
|
"@react-router/dev": "^8.0.1",
|
|
212
212
|
"@react-router/fs-routes": "^8.0.1",
|
|
213
213
|
"@resvg/resvg-js": "^2.6.2",
|
|
214
|
-
"@sentry/browser": "^10.
|
|
215
|
-
"@sentry/node": "^10.
|
|
214
|
+
"@sentry/browser": "^10.61.0",
|
|
215
|
+
"@sentry/node": "^10.61.0",
|
|
216
216
|
"@standard-schema/spec": "^1.1.0",
|
|
217
217
|
"@tanstack/react-table": "^8.21.3",
|
|
218
218
|
"@tiptap/core": "3.27.1",
|
|
@@ -482,7 +482,26 @@ function normalizeAssistantToolCallIds(message: any): any {
|
|
|
482
482
|
*/
|
|
483
483
|
export function normalizeThreadRepository(repo: any): any {
|
|
484
484
|
const normalized = repo && typeof repo === "object" ? { ...repo } : {};
|
|
485
|
-
const sourceMessages = Array.isArray(repo?.messages)
|
|
485
|
+
const sourceMessages: any[] = Array.isArray(repo?.messages)
|
|
486
|
+
? repo.messages
|
|
487
|
+
: [];
|
|
488
|
+
const firstIndexById = new Map<string, number>();
|
|
489
|
+
const lastEntryById = new Map<string, any>();
|
|
490
|
+
sourceMessages.forEach((entry, index) => {
|
|
491
|
+
const id = messageId(getStoredMessage(entry));
|
|
492
|
+
if (!id) return;
|
|
493
|
+
if (!firstIndexById.has(id)) firstIndexById.set(id, index);
|
|
494
|
+
lastEntryById.set(id, entry);
|
|
495
|
+
});
|
|
496
|
+
const uniqueSourceMessages = sourceMessages
|
|
497
|
+
.filter((entry, index) => {
|
|
498
|
+
const id = messageId(getStoredMessage(entry));
|
|
499
|
+
return id && firstIndexById.get(id) === index;
|
|
500
|
+
})
|
|
501
|
+
.map((entry) => {
|
|
502
|
+
const id = messageId(getStoredMessage(entry));
|
|
503
|
+
return (id && lastEntryById.get(id)) || entry;
|
|
504
|
+
});
|
|
486
505
|
const messages: Array<{
|
|
487
506
|
message: any;
|
|
488
507
|
parentId: string | null;
|
|
@@ -491,7 +510,7 @@ export function normalizeThreadRepository(repo: any): any {
|
|
|
491
510
|
const seenIds = new Set<string>();
|
|
492
511
|
let previousId: string | null = null;
|
|
493
512
|
|
|
494
|
-
for (const entry of
|
|
513
|
+
for (const entry of uniqueSourceMessages) {
|
|
495
514
|
const message = getStoredMessage(entry);
|
|
496
515
|
const id = messageId(message);
|
|
497
516
|
if (!id) continue;
|
|
@@ -27,6 +27,10 @@ const STANDALONE_EXACT_DEPENDENCY_OVERRIDES: Record<string, string> = {
|
|
|
27
27
|
"@react-router/fs-routes": "8.0.1",
|
|
28
28
|
"react-router": "8.0.1",
|
|
29
29
|
};
|
|
30
|
+
const SENTRY_MINIMUM_RELEASE_AGE_EXCLUDES = [
|
|
31
|
+
'"@sentry/browser"',
|
|
32
|
+
'"@sentry/node"',
|
|
33
|
+
];
|
|
30
34
|
const FIRST_PARTY_TARBALL_SYMLINK_EXCLUDES = [
|
|
31
35
|
"*/CLAUDE.md",
|
|
32
36
|
"*/.claude/skills",
|
|
@@ -1054,7 +1058,12 @@ function postProcessStandalone(
|
|
|
1054
1058
|
'"@assistant-ui/tap"': '"^0.5.14"',
|
|
1055
1059
|
};
|
|
1056
1060
|
}
|
|
1057
|
-
|
|
1061
|
+
let updated = mergeWorkspaceYamlSections(existing, sections);
|
|
1062
|
+
updated = mergeWorkspaceYamlListItems(
|
|
1063
|
+
updated,
|
|
1064
|
+
"minimumReleaseAgeExclude",
|
|
1065
|
+
SENTRY_MINIMUM_RELEASE_AGE_EXCLUDES,
|
|
1066
|
+
);
|
|
1058
1067
|
if (updated !== existing) {
|
|
1059
1068
|
fs.writeFileSync(wsPath, updated);
|
|
1060
1069
|
}
|
|
@@ -1366,6 +1375,31 @@ function mergeWorkspaceYamlSections(
|
|
|
1366
1375
|
return result;
|
|
1367
1376
|
}
|
|
1368
1377
|
|
|
1378
|
+
function mergeWorkspaceYamlListItems(
|
|
1379
|
+
yaml: string,
|
|
1380
|
+
section: string,
|
|
1381
|
+
items: string[],
|
|
1382
|
+
): string {
|
|
1383
|
+
let result = yaml;
|
|
1384
|
+
for (const item of items) {
|
|
1385
|
+
const rendered = ` - ${item}`;
|
|
1386
|
+
if (result.includes(rendered)) continue;
|
|
1387
|
+
const sectionHeader = new RegExp(`^${section}:\\s*$`, "m");
|
|
1388
|
+
const match = sectionHeader.exec(result);
|
|
1389
|
+
if (match) {
|
|
1390
|
+
const insertAt = match.index + match[0].length;
|
|
1391
|
+
result =
|
|
1392
|
+
result.slice(0, insertAt) + `\n${rendered}` + result.slice(insertAt);
|
|
1393
|
+
} else {
|
|
1394
|
+
result =
|
|
1395
|
+
result.trimEnd() +
|
|
1396
|
+
(result ? "\n" : "") +
|
|
1397
|
+
`\n${section}:\n${rendered}\n`;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
return result;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1369
1403
|
/**
|
|
1370
1404
|
* Load the pnpm workspace catalog.
|
|
1371
1405
|
* First tries the build-time snapshot at dist/catalog.json (works when
|
|
@@ -795,6 +795,14 @@ or cross either artboard, remove the label and explain the transition with a
|
|
|
795
795
|
nearby annotation instead. Before handoff, inspect the top canvas at default zoom
|
|
796
796
|
and move any frame whose label, connector, or annotation crosses another frame.
|
|
797
797
|
|
|
798
|
+
**Board-unit spacing defaults.** The canvas coordinate system uses approximately 2 board units per screen pixel. \`browser\` frames occupy roughly 700 × 600 board units; \`desktop\` frames roughly 900 × 700 board units. Apply these minimum x/y gaps when placing frames explicitly — any less and frames will touch or overlap:
|
|
799
|
+
|
|
800
|
+
- x-gap between \`browser\` frames: **≥ 1100** (700-unit frame + 400-unit gutter)
|
|
801
|
+
- x-gap between \`desktop\` frames: **≥ 1300** (900-unit frame + 400-unit gutter)
|
|
802
|
+
- y-gap between rows of any surface: **≥ 1400** (includes frame height + section header + buffer)
|
|
803
|
+
|
|
804
|
+
When in doubt, use larger values — the canvas auto-zooms to fit everything.
|
|
805
|
+
|
|
798
806
|
**Canvas annotations are designer notes on the artboard.** When a top canvas is
|
|
799
807
|
present, sprinkle Figma-style notes near the frames they explain: a short
|
|
800
808
|
heading, supporting text, and bullets — plain text layers, never bordered or
|
|
@@ -164,6 +164,12 @@ const CLI_DEFAULT = "claude";
|
|
|
164
164
|
const EXEC_MODE_KEY = "agent-native-exec-mode";
|
|
165
165
|
type ExecMode = "build" | "plan";
|
|
166
166
|
type PanelMode = "chat" | "cli" | "resources" | "settings";
|
|
167
|
+
export function normalizeAgentPanelModeForSurface(
|
|
168
|
+
mode: PanelMode,
|
|
169
|
+
allowSettingsMode: boolean,
|
|
170
|
+
): PanelMode {
|
|
171
|
+
return mode === "settings" && !allowSettingsMode ? "chat" : mode;
|
|
172
|
+
}
|
|
167
173
|
const AGENT_PANEL_FONT_FAMILY =
|
|
168
174
|
'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
169
175
|
const AGENT_PANEL_ROOT_STYLE = {
|
|
@@ -377,15 +383,11 @@ export function shouldShowAgentPanelChatTabBar(
|
|
|
377
383
|
}
|
|
378
384
|
|
|
379
385
|
export function shouldShowAgentPanelPageNewChatButton(
|
|
380
|
-
|
|
386
|
+
_tabs: MultiTabAssistantChatHeaderProps["tabs"],
|
|
381
387
|
activeTabId: string,
|
|
382
|
-
|
|
388
|
+
_activeTabMessageCount: number,
|
|
383
389
|
) {
|
|
384
|
-
|
|
385
|
-
return (
|
|
386
|
-
Boolean(activeTabId) &&
|
|
387
|
-
(activeTabMessageCount > 0 || activeTab?.status === "running")
|
|
388
|
-
);
|
|
390
|
+
return Boolean(activeTabId);
|
|
389
391
|
}
|
|
390
392
|
|
|
391
393
|
export function shouldShowAgentPanelCliTabBar(cliTabs: string[]) {
|
|
@@ -548,6 +550,8 @@ export interface AgentPanelProps extends Omit<
|
|
|
548
550
|
showTabBar?: boolean;
|
|
549
551
|
/** Show a compact New chat action in page chat when the main header is hidden. */
|
|
550
552
|
showPageNewChatButton?: boolean;
|
|
553
|
+
/** Allow the sidebar settings view to render inside this panel. Default: true. */
|
|
554
|
+
allowSettingsMode?: boolean;
|
|
551
555
|
/** Capability gate for source edits and CLI access. */
|
|
552
556
|
codeAccess?: AgentPanelCodeAccess;
|
|
553
557
|
}
|
|
@@ -666,6 +670,7 @@ function AgentPanelInner({
|
|
|
666
670
|
chatNotice,
|
|
667
671
|
showTabBar = true,
|
|
668
672
|
showPageNewChatButton = false,
|
|
673
|
+
allowSettingsMode = true,
|
|
669
674
|
codeAccess,
|
|
670
675
|
...assistantChatProps
|
|
671
676
|
}: AgentPanelProps) {
|
|
@@ -715,9 +720,9 @@ function AgentPanelInner({
|
|
|
715
720
|
saved === "resources" ||
|
|
716
721
|
saved === "settings"
|
|
717
722
|
)
|
|
718
|
-
return saved;
|
|
723
|
+
return normalizeAgentPanelModeForSurface(saved, allowSettingsMode);
|
|
719
724
|
} catch {}
|
|
720
|
-
return defaultMode;
|
|
725
|
+
return normalizeAgentPanelModeForSurface(defaultMode, allowSettingsMode);
|
|
721
726
|
});
|
|
722
727
|
useEffect(() => {
|
|
723
728
|
try {
|
|
@@ -728,9 +733,18 @@ function AgentPanelInner({
|
|
|
728
733
|
section: string | null;
|
|
729
734
|
requestKey: number;
|
|
730
735
|
}>({ section: null, requestKey: 0 });
|
|
731
|
-
const switchMode = useCallback(
|
|
732
|
-
|
|
733
|
-
|
|
736
|
+
const switchMode = useCallback(
|
|
737
|
+
(m: PanelMode) => {
|
|
738
|
+
startTransition(() =>
|
|
739
|
+
setMode(normalizeAgentPanelModeForSurface(m, allowSettingsMode)),
|
|
740
|
+
);
|
|
741
|
+
},
|
|
742
|
+
[allowSettingsMode],
|
|
743
|
+
);
|
|
744
|
+
useEffect(() => {
|
|
745
|
+
const nextMode = normalizeAgentPanelModeForSurface(mode, allowSettingsMode);
|
|
746
|
+
if (nextMode !== mode) switchMode(nextMode);
|
|
747
|
+
}, [mode, allowSettingsMode, switchMode]);
|
|
734
748
|
const openRunThread = useCallback(
|
|
735
749
|
(threadId: string, run?: AgentRun) => {
|
|
736
750
|
switchMode("chat");
|
|
@@ -794,6 +808,10 @@ function AgentPanelInner({
|
|
|
794
808
|
section: section ?? null,
|
|
795
809
|
requestKey: prev.requestKey + 1,
|
|
796
810
|
}));
|
|
811
|
+
if (!allowSettingsMode) {
|
|
812
|
+
switchMode("chat");
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
797
815
|
switchMode("settings");
|
|
798
816
|
}
|
|
799
817
|
window.addEventListener(
|
|
@@ -805,7 +823,7 @@ function AgentPanelInner({
|
|
|
805
823
|
AGENT_PANEL_OPEN_SETTINGS_EVENT,
|
|
806
824
|
handleOpenSettings,
|
|
807
825
|
);
|
|
808
|
-
}, [switchMode]);
|
|
826
|
+
}, [allowSettingsMode, switchMode]);
|
|
809
827
|
|
|
810
828
|
// CLI terminal tabs (ephemeral — not persisted to SQL)
|
|
811
829
|
const [cliTabs, setCliTabs] = useState<string[]>(["cli-1"]);
|
|
@@ -1151,15 +1169,17 @@ function AgentPanelInner({
|
|
|
1151
1169
|
<DropdownMenuSeparator />
|
|
1152
1170
|
</>
|
|
1153
1171
|
)}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1172
|
+
{allowSettingsMode && (
|
|
1173
|
+
<DropdownMenuItem
|
|
1174
|
+
onSelect={() => switchMode("settings")}
|
|
1175
|
+
className={cn(
|
|
1176
|
+
mode === "settings" ? "font-medium" : "text-muted-foreground",
|
|
1177
|
+
)}
|
|
1178
|
+
>
|
|
1179
|
+
<IconSettings size={14} className="shrink-0" />
|
|
1180
|
+
{t("agentPanel.settings")}
|
|
1181
|
+
</DropdownMenuItem>
|
|
1182
|
+
)}
|
|
1163
1183
|
<DropdownMenuItem onSelect={() => setFeedbackOpen(true)}>
|
|
1164
1184
|
<IconMessageDots size={14} className="shrink-0" />
|
|
1165
1185
|
{t("agentPanel.feedback")}
|
|
@@ -1241,6 +1261,7 @@ function AgentPanelInner({
|
|
|
1241
1261
|
[
|
|
1242
1262
|
activeCliTab,
|
|
1243
1263
|
addCliTab,
|
|
1264
|
+
allowSettingsMode,
|
|
1244
1265
|
availableClis,
|
|
1245
1266
|
canUseCodeTools,
|
|
1246
1267
|
closeAllCliTabs,
|
|
@@ -1287,7 +1308,7 @@ function AgentPanelInner({
|
|
|
1287
1308
|
data-agent-page-new-chat=""
|
|
1288
1309
|
aria-label={t("agentPanel.newChat")}
|
|
1289
1310
|
onClick={() => {
|
|
1290
|
-
addTab();
|
|
1311
|
+
void addTab();
|
|
1291
1312
|
}}
|
|
1292
1313
|
className="pointer-events-auto inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background/95 px-2.5 text-xs font-medium text-foreground shadow-sm backdrop-blur transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
1293
1314
|
>
|
|
@@ -2241,9 +2262,16 @@ export interface AgentChatSurfaceProps extends AgentPanelProps {
|
|
|
2241
2262
|
|
|
2242
2263
|
export function shouldDefaultAgentChatSurfacePageNewChatButton(
|
|
2243
2264
|
mode: AgentChatSurfaceMode | undefined,
|
|
2244
|
-
|
|
2265
|
+
_showTabBar: boolean | undefined,
|
|
2245
2266
|
): boolean {
|
|
2246
|
-
return mode === "page"
|
|
2267
|
+
return mode === "page";
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
export function shouldAllowAgentChatSurfaceSettingsMode(
|
|
2271
|
+
mode: AgentChatSurfaceMode | undefined,
|
|
2272
|
+
allowSettingsMode: boolean | undefined,
|
|
2273
|
+
): boolean {
|
|
2274
|
+
return allowSettingsMode ?? mode !== "page";
|
|
2247
2275
|
}
|
|
2248
2276
|
|
|
2249
2277
|
/**
|
|
@@ -2272,6 +2300,10 @@ export function AgentChatSurface({
|
|
|
2272
2300
|
{...props}
|
|
2273
2301
|
defaultMode={defaultMode}
|
|
2274
2302
|
isFullscreen={isFullscreen ?? pageMode}
|
|
2303
|
+
allowSettingsMode={shouldAllowAgentChatSurfaceSettingsMode(
|
|
2304
|
+
mode,
|
|
2305
|
+
props.allowSettingsMode,
|
|
2306
|
+
)}
|
|
2275
2307
|
showPageNewChatButton={
|
|
2276
2308
|
showPageNewChatButton ?? defaultShowPageNewChatButton
|
|
2277
2309
|
}
|
|
@@ -428,16 +428,24 @@ function HistoryPopover({
|
|
|
428
428
|
openTabIds,
|
|
429
429
|
activeThreadId,
|
|
430
430
|
currentScope,
|
|
431
|
+
hasMoreThreads = false,
|
|
432
|
+
isLoadingMoreThreads = false,
|
|
433
|
+
loadError,
|
|
431
434
|
onSelect,
|
|
432
435
|
onClose,
|
|
436
|
+
onLoadMore,
|
|
433
437
|
onSearch,
|
|
434
438
|
}: {
|
|
435
439
|
threads: ChatThreadSummary[];
|
|
436
440
|
openTabIds: Set<string>;
|
|
437
441
|
activeThreadId: string | null;
|
|
438
442
|
currentScope?: ChatThreadScope | null;
|
|
443
|
+
hasMoreThreads?: boolean;
|
|
444
|
+
isLoadingMoreThreads?: boolean;
|
|
445
|
+
loadError?: string | null;
|
|
439
446
|
onSelect: (id: string) => void;
|
|
440
447
|
onClose: () => void;
|
|
448
|
+
onLoadMore?: () => void;
|
|
441
449
|
onSearch?: (query: string) => Promise<ChatThreadSummary[]>;
|
|
442
450
|
}) {
|
|
443
451
|
const [search, setSearch] = useState("");
|
|
@@ -542,7 +550,11 @@ function HistoryPopover({
|
|
|
542
550
|
/>
|
|
543
551
|
</div>
|
|
544
552
|
<div className="max-h-64 overflow-y-auto py-1">
|
|
545
|
-
{
|
|
553
|
+
{loadError && !search.trim() ? (
|
|
554
|
+
<div className="px-3 py-4 text-xs text-amber-500 text-center">
|
|
555
|
+
{loadError}
|
|
556
|
+
</div>
|
|
557
|
+
) : isSearching ? (
|
|
546
558
|
<div className="px-3 py-4 text-xs text-muted-foreground text-center">
|
|
547
559
|
Searching...
|
|
548
560
|
</div>
|
|
@@ -599,6 +611,16 @@ function HistoryPopover({
|
|
|
599
611
|
),
|
|
600
612
|
)
|
|
601
613
|
)}
|
|
614
|
+
{!search.trim() && hasMoreThreads && (
|
|
615
|
+
<button
|
|
616
|
+
type="button"
|
|
617
|
+
onClick={() => onLoadMore?.()}
|
|
618
|
+
disabled={isLoadingMoreThreads}
|
|
619
|
+
className="mx-1 mt-1 flex w-[calc(100%-0.5rem)] items-center justify-center rounded-md px-3 py-2 text-xs text-muted-foreground hover:bg-accent hover:text-foreground disabled:cursor-default disabled:opacity-60"
|
|
620
|
+
>
|
|
621
|
+
{isLoadingMoreThreads ? "Loading..." : "Load older chats"}
|
|
622
|
+
</button>
|
|
623
|
+
)}
|
|
602
624
|
</div>
|
|
603
625
|
</PopoverContent>
|
|
604
626
|
</Popover>
|
|
@@ -1034,7 +1056,11 @@ export function MultiTabAssistantChat({
|
|
|
1034
1056
|
saveThreadData,
|
|
1035
1057
|
generateTitle,
|
|
1036
1058
|
searchThreads,
|
|
1059
|
+
loadMoreThreads,
|
|
1037
1060
|
refreshThreads,
|
|
1061
|
+
hasMoreThreads,
|
|
1062
|
+
isLoadingMoreThreads,
|
|
1063
|
+
threadsLoadError,
|
|
1038
1064
|
isNewThread,
|
|
1039
1065
|
} = useChatThreads(apiUrl, storageKey, scope, {
|
|
1040
1066
|
restoreActiveThread,
|
|
@@ -2649,8 +2675,12 @@ export function MultiTabAssistantChat({
|
|
|
2649
2675
|
openTabIds={new Set(openTabIds)}
|
|
2650
2676
|
activeThreadId={activeThreadId}
|
|
2651
2677
|
currentScope={scope}
|
|
2678
|
+
hasMoreThreads={hasMoreThreads}
|
|
2679
|
+
isLoadingMoreThreads={isLoadingMoreThreads}
|
|
2680
|
+
loadError={threadsLoadError}
|
|
2652
2681
|
onSelect={openFromHistory}
|
|
2653
2682
|
onClose={() => setShowHistory(false)}
|
|
2683
|
+
onLoadMore={loadMoreThreads}
|
|
2654
2684
|
onSearch={searchThreads}
|
|
2655
2685
|
/>
|
|
2656
2686
|
)}
|
|
@@ -501,9 +501,12 @@ function shouldDropBrowserSentryNoise(event: Sentry.Event): boolean {
|
|
|
501
501
|
.toLowerCase();
|
|
502
502
|
return (
|
|
503
503
|
exceptionValue === "the user aborted a request." ||
|
|
504
|
+
exceptionValue === "signal is aborted without reason" ||
|
|
504
505
|
exceptionValue === "aborterror: the user aborted a request." ||
|
|
506
|
+
exceptionValue === "aborterror: signal is aborted without reason" ||
|
|
505
507
|
(exceptionType === "aborterror" &&
|
|
506
|
-
exceptionValue.includes("the user aborted a request")
|
|
508
|
+
(exceptionValue.includes("the user aborted a request") ||
|
|
509
|
+
exceptionValue.includes("signal is aborted without reason")))
|
|
507
510
|
);
|
|
508
511
|
})
|
|
509
512
|
) {
|
|
@@ -534,12 +537,31 @@ function shouldDropBrowserSentryNoise(event: Sentry.Event): boolean {
|
|
|
534
537
|
);
|
|
535
538
|
}
|
|
536
539
|
|
|
540
|
+
function firstNonEmpty(...values: Array<string | undefined>): string {
|
|
541
|
+
for (const value of values) {
|
|
542
|
+
const trimmed = value?.trim();
|
|
543
|
+
if (trimmed) return trimmed;
|
|
544
|
+
}
|
|
545
|
+
return "";
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function resolveClientSentryDsnFromKeyProject(
|
|
549
|
+
env: Record<string, string | undefined>,
|
|
550
|
+
): string | undefined {
|
|
551
|
+
const key = firstNonEmpty(env.VITE_SENTRY_CLIENT_KEY);
|
|
552
|
+
const projectId = firstNonEmpty(env.VITE_SENTRY_PROJECT_ID);
|
|
553
|
+
const host = firstNonEmpty(env.VITE_SENTRY_INGEST_HOST);
|
|
554
|
+
if (!key || !projectId || !host) return undefined;
|
|
555
|
+
return `https://${key}@${host}/${projectId}`;
|
|
556
|
+
}
|
|
557
|
+
|
|
537
558
|
function getClientSentryDsn(): string | undefined {
|
|
538
559
|
const env = (import.meta.env as Record<string, string | undefined>) ?? {};
|
|
539
560
|
return (
|
|
540
561
|
env.VITE_SENTRY_CLIENT_DSN ||
|
|
541
562
|
env.VITE_SENTRY_DSN ||
|
|
542
|
-
window.__AGENT_NATIVE_CONFIG__?.sentryDsn
|
|
563
|
+
window.__AGENT_NATIVE_CONFIG__?.sentryDsn ||
|
|
564
|
+
resolveClientSentryDsnFromKeyProject(env)
|
|
543
565
|
);
|
|
544
566
|
}
|
|
545
567
|
|
|
@@ -26,21 +26,13 @@ export function useAgentEngineConfigured(
|
|
|
26
26
|
): UseAgentEngineConfiguredResult {
|
|
27
27
|
const [state, setState] = useState<AgentEngineConfiguredState>("unknown");
|
|
28
28
|
|
|
29
|
-
// Mid-run adapter signal that no key is usable — honored even when disabled.
|
|
30
29
|
useEffect(() => {
|
|
31
|
-
const onMissing = () => setState("missing");
|
|
32
|
-
window.addEventListener("agent-chat:missing-api-key", onMissing);
|
|
33
|
-
return () =>
|
|
34
|
-
window.removeEventListener("agent-chat:missing-api-key", onMissing);
|
|
35
|
-
}, []);
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (!enabled) {
|
|
39
|
-
setState("configured");
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
30
|
let cancelled = false;
|
|
43
|
-
const check = async () => {
|
|
31
|
+
const check = async (options?: { missingFallback?: boolean }) => {
|
|
32
|
+
if (!enabled) {
|
|
33
|
+
setState("configured");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
44
36
|
const [envKeys, builderStatus, engineStatus] = await Promise.all([
|
|
45
37
|
fetch(agentNativePath("/_agent-native/env-status"))
|
|
46
38
|
.then((r) => (r.ok ? r.json() : null))
|
|
@@ -55,6 +47,7 @@ export function useAgentEngineConfigured(
|
|
|
55
47
|
if (cancelled) return;
|
|
56
48
|
// All three failed — likely a flaky network; keep the current state.
|
|
57
49
|
if (envKeys == null && builderStatus == null && engineStatus == null) {
|
|
50
|
+
if (options?.missingFallback) setState("missing");
|
|
58
51
|
return;
|
|
59
52
|
}
|
|
60
53
|
const keys = (envKeys ?? []) as Array<{
|
|
@@ -68,11 +61,32 @@ export function useAgentEngineConfigured(
|
|
|
68
61
|
engineStatus?.configured === true;
|
|
69
62
|
setState(anyConfigured ? "configured" : "missing");
|
|
70
63
|
};
|
|
64
|
+
const onConfiguredChanged = () => {
|
|
65
|
+
void check();
|
|
66
|
+
};
|
|
67
|
+
const onMissing = () => {
|
|
68
|
+
if (!enabled) {
|
|
69
|
+
setState("configured");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
void check({ missingFallback: true });
|
|
73
|
+
};
|
|
74
|
+
|
|
71
75
|
void check();
|
|
72
|
-
window.addEventListener(
|
|
76
|
+
window.addEventListener(
|
|
77
|
+
"agent-engine:configured-changed",
|
|
78
|
+
onConfiguredChanged,
|
|
79
|
+
);
|
|
80
|
+
// A stale failed stream can arrive after a reconnect succeeds. Re-check the
|
|
81
|
+
// current status before pinning the composer in setup.
|
|
82
|
+
window.addEventListener("agent-chat:missing-api-key", onMissing);
|
|
73
83
|
return () => {
|
|
74
84
|
cancelled = true;
|
|
75
|
-
window.removeEventListener(
|
|
85
|
+
window.removeEventListener(
|
|
86
|
+
"agent-engine:configured-changed",
|
|
87
|
+
onConfiguredChanged,
|
|
88
|
+
);
|
|
89
|
+
window.removeEventListener("agent-chat:missing-api-key", onMissing);
|
|
76
90
|
};
|
|
77
91
|
}, [enabled]);
|
|
78
92
|
|