@agent-native/core 0.154.5 → 0.157.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/account-health/SKILL.md +76 -0
- package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +3 -0
- package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +2 -1
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +6 -5
- package/corpus/templates/analytics/AGENTS.md +3 -0
- package/corpus/templates/analytics/actions/account-deep-dive.ts +3 -2
- package/corpus/templates/analytics/actions/bigquery.ts +1 -1
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +4 -1
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyCombobox.tsx +12 -4
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyValueCombobox.tsx +5 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer/property-label.ts +32 -0
- package/corpus/templates/analytics/changelog/2026-08-13-account-health-readouts-verify-customer-scope-and-contract-metrics.md +7 -0
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +43 -17
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +17 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +3 -1
- package/corpus/templates/assets/app/i18n-data.ts +21 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +17 -13
- package/corpus/templates/calendar/AGENTS.md +2 -0
- package/corpus/templates/calendar/DEVELOPING.md +4 -4
- package/corpus/templates/calendar/actions/get-settings.ts +4 -11
- package/corpus/templates/calendar/actions/update-availability.ts +15 -4
- package/corpus/templates/calendar/actions/update-settings.ts +15 -4
- package/corpus/templates/calendar/app/components/booking/DatePicker.tsx +9 -3
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +21 -19
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +9 -6
- package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +25 -3
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +10 -3
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +9 -9
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -3
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +10 -4
- package/corpus/templates/calendar/app/i18n-data.ts +30 -0
- package/corpus/templates/calendar/app/lib/availability-schedule.ts +53 -0
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +5 -0
- package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +90 -28
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +135 -61
- package/corpus/templates/calendar/app/pages/BookingPage.tsx +2 -0
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +30 -15
- package/corpus/templates/calendar/app/pages/Settings.tsx +60 -1
- package/corpus/templates/calendar/changelog/2026-08-13-find-a-time-now-closes-from-a-clear-header-action.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +2 -1
- package/corpus/templates/calendar/server/handlers/settings.ts +12 -16
- package/corpus/templates/calendar/shared/api.ts +1 -0
- package/corpus/templates/calendar/shared/availability-schedule.ts +64 -0
- package/corpus/templates/calendar/shared/calendar-week.ts +21 -0
- package/corpus/templates/calendar/shared/settings.ts +44 -0
- package/corpus/templates/clips/AGENTS.md +2 -0
- package/corpus/templates/clips/actions/add-comment.ts +5 -2
- package/corpus/templates/clips/actions/finalize-recording.ts +31 -1
- package/corpus/templates/clips/actions/get-recording-player-data.ts +9 -0
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +21 -1
- package/corpus/templates/clips/actions/reply-to-comment.ts +5 -2
- package/corpus/templates/clips/actions/update-comment.ts +9 -2
- package/corpus/templates/clips/app/components/library/search-bar.tsx +26 -13
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +135 -3
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +5 -99
- package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +7 -3
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +102 -59
- package/corpus/templates/clips/app/components/player/video-player.tsx +84 -24
- package/corpus/templates/clips/app/components/workspace/notifications-list.tsx +11 -3
- package/corpus/templates/clips/app/i18n/en-US.ts +12 -0
- package/corpus/templates/clips/app/lib/public-meeting.ts +11 -3
- package/corpus/templates/clips/app/lib/search-focus.ts +15 -0
- package/corpus/templates/clips/app/root.tsx +2 -1
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +94 -26
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +24 -7
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +8 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +29 -8
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +24 -6
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +72 -26
- package/corpus/templates/clips/changelog/2026-08-13-inline-markdown-comments.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-13-private-meeting-agent-links.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +116 -19
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +13 -29
- package/corpus/templates/clips/desktop/src/lib/recording-request.ts +39 -0
- package/corpus/templates/clips/desktop/src/lib/settings-navigation.ts +11 -0
- package/corpus/templates/clips/desktop/src/lib/whisper-model-picker.ts +7 -0
- package/corpus/templates/clips/desktop/src/styles.css +117 -0
- package/corpus/templates/clips/server/db/index.ts +10 -0
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/recordings.ts +3 -1
- package/corpus/templates/clips/server/lib/seekable-media-state.ts +90 -0
- package/corpus/templates/clips/server/plugins/db.ts +5 -0
- package/corpus/templates/clips/server/routes/api/public-meeting.get.ts +37 -4
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +16 -5
- package/corpus/templates/clips/shared/clips-ai-prefs.ts +3 -0
- package/corpus/templates/clips/shared/meeting-agent-access.ts +5 -0
- package/corpus/templates/content/actions/add-comment.ts +2 -1
- package/corpus/templates/content/actions/update-comment.ts +1 -1
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +24 -15
- package/corpus/templates/design/actions/generate-design.ts +10 -7
- package/corpus/templates/design/actions/present-design-variants.ts +35 -6
- package/corpus/templates/design/actions/run-design-audit.ts +33 -0
- package/corpus/templates/design/changelog/2026-08-13-the-design-audit-now-catches-a-screen-that-renders-behind-an.md +6 -0
- package/corpus/templates/design/shared/design-review.ts +1 -0
- package/corpus/templates/design/shared/html-integrity.ts +66 -0
- package/corpus/templates/dispatch/.env.example +5 -0
- package/corpus/templates/dispatch/AGENTS.md +24 -19
- package/corpus/templates/dispatch/app/i18n-data.ts +20 -0
- package/corpus/templates/dispatch/server/lib/identity-sso.ts +21 -90
- package/corpus/templates/dispatch/server/plugins/identity-sso.ts +3 -12
- package/corpus/templates/dispatch/shared/feature-flags.ts +4 -0
- package/corpus/templates/factory/AGENTS.md +5 -1
- package/corpus/templates/factory/README.md +23 -0
- package/corpus/templates/factory/actions/view-screen.ts +17 -0
- package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +239 -0
- package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +2 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +130 -7
- package/corpus/templates/factory/app/i18n/en-US.ts +20 -0
- package/corpus/templates/factory/app/routes/factory.tsx +41 -0
- package/corpus/templates/factory/package.json +1 -0
- package/corpus/templates/factory/server/factory-graph/contracts.ts +2 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +9 -0
- package/corpus/templates/factory/server/plugins/dispatch-db.ts +1 -0
- package/corpus/templates/factory/server/plugins/setup-dispatch.ts +3 -0
- package/corpus/templates/mail/app/lib/native-mcp-exclusions.ts +3 -0
- package/corpus/templates/mail/vite.config.ts +7 -0
- package/corpus/templates/plan/actions/reply-to-plan-comment.ts +7 -2
- package/corpus/templates/plan/actions/resolve-plan-comment.ts +2 -2
- package/corpus/templates/plan/actions/update-visual-plan.ts +1 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +29 -20
- package/corpus/templates/slides/actions/add-slide-comment.ts +1 -1
- package/corpus/templates/slides/actions/update-slide-comment.ts +1 -1
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +9 -6
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +98 -29
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +45 -91
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +94 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +17 -29
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +42 -2
- package/corpus/templates/slides/app/global.css +7 -40
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +130 -45
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/production-agent.d.ts +30 -0
- package/dist/agent/production-agent.js +105 -9
- package/dist/agent/thread-data-builder.js +17 -1
- package/dist/agent/types.d.ts +9 -0
- package/dist/cli/skills-content/help.js +6 -4
- package/dist/cli/skills.js +17 -2
- package/dist/cli/workspacify.d.ts +5 -0
- package/dist/cli/workspacify.js +65 -8
- package/dist/client/AgentPanel.d.ts +5 -0
- package/dist/client/AgentPanel.js +32 -13
- package/dist/client/AssistantChat.d.ts +36 -1
- package/dist/client/AssistantChat.js +175 -110
- package/dist/client/MultiTabAssistantChat.js +44 -27
- package/dist/client/active-run-state.d.ts +14 -1
- package/dist/client/active-run-state.js +0 -0
- package/dist/client/agent-chat-adapter.js +107 -5
- package/dist/client/analytics.js +9 -2
- package/dist/client/chat/markdown-renderer.js +4 -2
- package/dist/client/chat/message-components.d.ts +2 -2
- package/dist/client/chat/message-components.js +69 -35
- package/dist/client/chat/run-recovery.d.ts +4 -1
- package/dist/client/chat/run-recovery.js +62 -30
- package/dist/client/chat/tool-call-display.d.ts +12 -3
- package/dist/client/chat/tool-call-display.js +79 -40
- package/dist/client/chat/widgets/DataChartRenderer.js +3 -1
- package/dist/client/chat/widgets/DataChartWidget.js +8 -2
- package/dist/client/chat/widgets/DataInsightsWidget.js +3 -1
- package/dist/client/chat/widgets/DataTableWidget.js +23 -9
- package/dist/client/chat/widgets/builtin-tool-renderers.js +3 -1
- package/dist/client/chat-first/apps-rail.js +9 -4
- package/dist/client/chat-first/primary-nav.d.ts +2 -1
- package/dist/client/chat-first/primary-nav.js +3 -3
- package/dist/client/chat-first/types.d.ts +5 -1
- package/dist/client/components/ui/message-scroller.d.ts +1 -1
- package/dist/client/components/ui/message-scroller.js +7 -3
- package/dist/client/composer/runtime-adapters.js +3 -2
- package/dist/client/context-xray/ContextMeter.js +5 -1
- package/dist/client/context-xray/ContextXRayPanel.js +5 -5
- package/dist/client/error-format.d.ts +4 -0
- package/dist/client/error-format.js +93 -5
- package/dist/client/i18n.js +83 -17
- package/dist/client/markdown/InlineMarkdown.d.ts +23 -0
- package/dist/client/markdown/InlineMarkdown.js +65 -0
- package/dist/client/markdown/index.d.ts +1 -0
- package/dist/client/markdown/index.js +1 -0
- package/dist/client/observability/ThumbsFeedback.js +10 -8
- package/dist/client/review/ReviewThreadPanel.js +2 -1
- package/dist/client/run-stream-ownership.d.ts +39 -0
- package/dist/client/run-stream-ownership.js +65 -0
- package/dist/client/sharing/ShareButton.js +160 -54
- package/dist/coding-tools/run-code.js +2 -1
- package/dist/coding-tools/sandbox/background.d.ts +1 -0
- package/dist/coding-tools/sandbox/background.js +8 -1
- package/dist/coding-tools/sandbox/executions-store.d.ts +2 -0
- package/dist/coding-tools/sandbox/executions-store.js +41 -3
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/store.d.ts +10 -0
- package/dist/feature-flags/store.js +112 -1
- package/dist/guards/no-env-credentials.js +4 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/integrations/adapters/slack.js +5 -1
- package/dist/localization/core-messages/ar-SA.d.ts +3 -0
- package/dist/localization/core-messages/ar-SA.js +541 -0
- package/dist/localization/core-messages/de-DE.d.ts +3 -0
- package/dist/localization/core-messages/de-DE.js +513 -0
- package/dist/localization/core-messages/en-US.d.ts +513 -0
- package/dist/localization/core-messages/en-US.js +513 -0
- package/dist/localization/core-messages/es-ES.d.ts +3 -0
- package/dist/localization/core-messages/es-ES.js +520 -0
- package/dist/localization/core-messages/fr-FR.d.ts +3 -0
- package/dist/localization/core-messages/fr-FR.js +520 -0
- package/dist/localization/core-messages/hi-IN.d.ts +3 -0
- package/dist/localization/core-messages/hi-IN.js +513 -0
- package/dist/localization/core-messages/ja-JP.d.ts +3 -0
- package/dist/localization/core-messages/ja-JP.js +506 -0
- package/dist/localization/core-messages/ko-KR.d.ts +3 -0
- package/dist/localization/core-messages/ko-KR.js +506 -0
- package/dist/localization/core-messages/pt-BR.d.ts +3 -0
- package/dist/localization/core-messages/pt-BR.js +520 -0
- package/dist/localization/core-messages/zh-CN.d.ts +3 -0
- package/dist/localization/core-messages/zh-CN.js +506 -0
- package/dist/localization/core-messages/zh-TW.d.ts +3 -0
- package/dist/localization/core-messages/zh-TW.js +506 -0
- package/dist/localization/core-messages.d.ts +524 -0
- package/dist/localization/core-messages.js +124 -0
- package/dist/localization/default-messages.d.ts +3 -0
- package/dist/localization/default-messages.js +3 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +2 -2
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/resources/agents.js +40 -5
- package/dist/resources/metadata.d.ts +10 -0
- package/dist/resources/metadata.js +7 -3
- package/dist/review/actions/create-review-comment.js +1 -1
- package/dist/review/actions/reply-review-comment.js +1 -1
- package/dist/review/actions/resolve-review-thread.js +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/action-routes.js +32 -6
- package/dist/server/agent-chat/plugin-options.d.ts +7 -2
- package/dist/server/agent-chat-plugin.d.ts +10 -0
- package/dist/server/agent-chat-plugin.js +144 -41
- package/dist/server/agent-discovery.js +14 -3
- package/dist/server/agent-run-context.d.ts +7 -1
- package/dist/server/agent-run-context.js +9 -2
- package/dist/server/agent-teams-run-queue.d.ts +3 -0
- package/dist/server/agent-teams.js +38 -9
- package/dist/server/core-routes-plugin.js +1 -1
- package/dist/server/identity-sso-migrations.d.ts +7 -0
- package/dist/server/identity-sso-migrations.js +36 -0
- package/dist/server/identity-sso-store.d.ts +3 -2
- package/dist/server/identity-sso-store.js +8 -3
- package/dist/server/index.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/release-migrations.js +4 -0
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.js +15 -0
- package/dist/tracking/providers.js +13 -3
- package/dist/workspace-files/tool.js +1 -1
- package/docs/content/agent-surfaces.mdx +30 -0
- package/package.json +3 -2
|
@@ -94,8 +94,24 @@ export function buildAssistantMessage(events, runId, options = {}) {
|
|
|
94
94
|
continue;
|
|
95
95
|
}
|
|
96
96
|
if (event.type === "tool_start") {
|
|
97
|
+
const explicitToolCallId = event.id?.trim();
|
|
98
|
+
// A tool_start whose id is already in this turn is a REPLAY, not a new
|
|
99
|
+
// call: the tool-call journal and zombie-ledger recovery paths re-emit
|
|
100
|
+
// tool_start/tool_done for calls that already ran in an interrupted
|
|
101
|
+
// chunk. The live client coalesces those onto the original card, so a
|
|
102
|
+
// blind push here persisted a second copy of a call the user had only
|
|
103
|
+
// ever seen once — the duplicate that appears only after a reload.
|
|
104
|
+
// Matching the tool name too, so an id reused across different tools
|
|
105
|
+
// stays two cards rather than being silently merged into one.
|
|
106
|
+
if (explicitToolCallId) {
|
|
107
|
+
const replayed = content.some((part) => part.type === "tool-call" &&
|
|
108
|
+
part.toolCallId === explicitToolCallId &&
|
|
109
|
+
part.toolName === (event.tool ?? "unknown"));
|
|
110
|
+
if (replayed)
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
97
113
|
toolCallCounter += 1;
|
|
98
|
-
const toolCallId =
|
|
114
|
+
const toolCallId = explicitToolCallId ||
|
|
99
115
|
(runId ? `${runId}:tc_${toolCallCounter}` : `tc_${toolCallCounter}`);
|
|
100
116
|
const args = (event.input ?? {});
|
|
101
117
|
content.push({
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -186,6 +186,15 @@ export interface AgentChatRequest {
|
|
|
186
186
|
*/
|
|
187
187
|
payloadRef?: boolean;
|
|
188
188
|
};
|
|
189
|
+
/**
|
|
190
|
+
* Server-resolved action authorization carried across authenticated durable
|
|
191
|
+
* background dispatches. Normal client requests must not trust this field;
|
|
192
|
+
* the foreground handler deletes and replaces it before persistence.
|
|
193
|
+
*/
|
|
194
|
+
__resolvedActionSurface?: {
|
|
195
|
+
orgId: string | null;
|
|
196
|
+
allowedActionNames: string[];
|
|
197
|
+
};
|
|
189
198
|
/**
|
|
190
199
|
* Stable identity for the logical assistant turn this request belongs to.
|
|
191
200
|
* The client sends the SAME turnId for the initial POST and every
|
|
@@ -73,7 +73,9 @@ run "npx @agent-native/core@latest recap setup" / "npx @agent-native/core@latest
|
|
|
73
73
|
verify GitHub Actions. Docs: ${docsUrl("pr-visual-recap")}.
|
|
74
74
|
|
|
75
75
|
The status/update commands inspect copied Agent Native skill folders and refresh
|
|
76
|
-
their instruction files from the current @agent-native/core package. In
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
their instruction files from the current @agent-native/core package. In a
|
|
77
|
+
standalone generated app, "skills update scaffold --project" refreshes the
|
|
78
|
+
framework skill copies. In a generated workspace, it refreshes workspace-core,
|
|
79
|
+
removes stale generic framework copies, repairs inherited .agents/skills links
|
|
80
|
+
for every app, and repairs AGENTS.md / CLAUDE.md / .claude/skills compatibility
|
|
81
|
+
links.`;
|
package/dist/cli/skills.js
CHANGED
|
@@ -20,6 +20,7 @@ import { PR_VISUAL_RECAP_SETUP, writePrVisualRecapWorkflow } from "./recap.js";
|
|
|
20
20
|
import { setupAgentSymlinks } from "./setup-agents.js";
|
|
21
21
|
import { ASSETS_SKILL_MD, CANVAS_REFERENCE_MD, CONNECTION_REFERENCE_MD, CONTENT_SKILL_MD, DESIGN_EXPLORATION_SKILL_MD, DESIGN_VISUAL_EDIT_SKILL_MD, DOCUMENT_QUALITY_REFERENCE_MD, EXEMPLAR_REFERENCE_MD, HELP, LOCAL_FILES_REFERENCE_MD, REWIND_SKILL_MD, VISUAL_PLANS_SKILL_MD, VISUAL_RECAP_SKILL_MD, VISUALIZE_REPO_SKILL_MD, WIREFRAME_REFERENCE_MD, } from "./skills-content/index.js";
|
|
22
22
|
import { createCliTelemetry } from "./telemetry.js";
|
|
23
|
+
import { linkDefaultWorkspaceSkills, removeCopiedFrameworkSkills, } from "./workspacify.js";
|
|
23
24
|
export { CANVAS_REFERENCE_MD, CONNECTION_REFERENCE_MD, DOCUMENT_QUALITY_REFERENCE_MD, EXEMPLAR_REFERENCE_MD, LOCAL_FILES_REFERENCE_MD, VISUAL_PLANS_SKILL_MD, VISUAL_RECAP_SKILL_MD, VISUALIZE_REPO_SKILL_MD, WIREFRAME_REFERENCE_MD, };
|
|
24
25
|
export const BUILT_IN_APP_SKILLS = {
|
|
25
26
|
assets: {
|
|
@@ -1401,6 +1402,17 @@ function repairScaffoldAgentLinks(states) {
|
|
|
1401
1402
|
continue;
|
|
1402
1403
|
const appDir = path.join(appsDir, entry.name);
|
|
1403
1404
|
if (fs.existsSync(path.join(appDir, "package.json"))) {
|
|
1405
|
+
const preserved = new Set([
|
|
1406
|
+
...removeCopiedFrameworkSkills(appDir, {
|
|
1407
|
+
workspaceRoot: state.workspaceRoot,
|
|
1408
|
+
}),
|
|
1409
|
+
...linkDefaultWorkspaceSkills(appDir, state.workspaceRoot),
|
|
1410
|
+
]);
|
|
1411
|
+
if (preserved.size > 0) {
|
|
1412
|
+
console.warn(`[skills] Preserved app-local framework-named skills in ${appDir}: ${[
|
|
1413
|
+
...preserved,
|
|
1414
|
+
].join(", ")}. Migrate them explicitly before inheriting workspace copies.`);
|
|
1415
|
+
}
|
|
1404
1416
|
setupAgentSymlinks(appDir);
|
|
1405
1417
|
refreshCopiedClaudeSkills(appDir);
|
|
1406
1418
|
}
|
|
@@ -3171,8 +3183,11 @@ function runSkillsStatusOrUpdate(parsed, options, update) {
|
|
|
3171
3183
|
const scaffoldChanged = update
|
|
3172
3184
|
? updateScaffoldGuidanceStates(scaffoldBefore, parsed.dryRun)
|
|
3173
3185
|
: [];
|
|
3174
|
-
if (update && !parsed.dryRun
|
|
3175
|
-
|
|
3186
|
+
if (update && !parsed.dryRun) {
|
|
3187
|
+
const workspaceStates = scaffoldBefore.filter((state) => state.workspaceRoot && state.sharedPackageDir);
|
|
3188
|
+
if (scaffoldChanged.length > 0 || workspaceStates.length > 0) {
|
|
3189
|
+
repairScaffoldAgentLinks([...scaffoldChanged, ...workspaceStates]);
|
|
3190
|
+
}
|
|
3176
3191
|
}
|
|
3177
3192
|
const skillAfter = update && !parsed.dryRun
|
|
3178
3193
|
? collectSkillInstallStates(parsed, options)
|
|
@@ -17,6 +17,11 @@ export interface WorkspacifyOptions {
|
|
|
17
17
|
toolkitDependencyVersion?: string;
|
|
18
18
|
}
|
|
19
19
|
export declare function workspacifyApp(opts: WorkspacifyOptions): void;
|
|
20
|
+
export declare function removeCopiedFrameworkSkills(appDir: string, options?: {
|
|
21
|
+
workspaceRoot?: string;
|
|
22
|
+
allowUnverified?: boolean;
|
|
23
|
+
}): string[];
|
|
24
|
+
export declare function linkDefaultWorkspaceSkills(appDir: string, workspaceRoot: string): string[];
|
|
20
25
|
/**
|
|
21
26
|
* Parse a workspace core package name into its npm scope.
|
|
22
27
|
* "@my-company/shared" → "my-company"
|
package/dist/cli/workspacify.js
CHANGED
|
@@ -144,27 +144,83 @@ export function workspacifyApp(opts) {
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
function linkInheritedWorkspaceSkills(opts) {
|
|
147
|
-
const appSkillsDir = path.join(opts.appDir, ".agents", "skills");
|
|
148
147
|
const workspaceSkillsDir = path.join(opts.workspaceRoot, ".agents", "skills");
|
|
149
148
|
if (!fs.existsSync(workspaceSkillsDir))
|
|
150
149
|
return;
|
|
151
|
-
|
|
150
|
+
removeCopiedFrameworkSkills(opts.appDir, { allowUnverified: true });
|
|
151
|
+
linkDefaultWorkspaceSkills(opts.appDir, opts.workspaceRoot);
|
|
152
|
+
}
|
|
153
|
+
function skillDirContentsMatch(sourceDir, targetDir) {
|
|
154
|
+
const sourceStat = fs.lstatSync(sourceDir, { throwIfNoEntry: false });
|
|
155
|
+
const targetStat = fs.lstatSync(targetDir, { throwIfNoEntry: false });
|
|
156
|
+
if (!sourceStat?.isDirectory() || !targetStat?.isDirectory())
|
|
157
|
+
return false;
|
|
158
|
+
const sourceEntries = fs.readdirSync(sourceDir, { withFileTypes: true });
|
|
159
|
+
const targetEntries = fs.readdirSync(targetDir, { withFileTypes: true });
|
|
160
|
+
if (sourceEntries.length !== targetEntries.length)
|
|
161
|
+
return false;
|
|
162
|
+
return sourceEntries.every((sourceEntry) => {
|
|
163
|
+
const sourcePath = path.join(sourceDir, sourceEntry.name);
|
|
164
|
+
const targetPath = path.join(targetDir, sourceEntry.name);
|
|
165
|
+
const targetEntry = targetEntries.find((entry) => entry.name === sourceEntry.name);
|
|
166
|
+
if (!targetEntry)
|
|
167
|
+
return false;
|
|
168
|
+
if (sourceEntry.isSymbolicLink()) {
|
|
169
|
+
return (targetEntry.isSymbolicLink() &&
|
|
170
|
+
fs.readlinkSync(sourcePath) === fs.readlinkSync(targetPath));
|
|
171
|
+
}
|
|
172
|
+
if (sourceEntry.isDirectory()) {
|
|
173
|
+
return (targetEntry.isDirectory() &&
|
|
174
|
+
skillDirContentsMatch(sourcePath, targetPath));
|
|
175
|
+
}
|
|
176
|
+
return (sourceEntry.isFile() &&
|
|
177
|
+
targetEntry.isFile() &&
|
|
178
|
+
fs.readFileSync(sourcePath).equals(fs.readFileSync(targetPath)));
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
export function removeCopiedFrameworkSkills(appDir, options = {}) {
|
|
182
|
+
const appSkillsDir = path.join(appDir, ".agents", "skills");
|
|
183
|
+
const workspaceSkillsDir = options.workspaceRoot
|
|
184
|
+
? path.join(options.workspaceRoot, ".agents", "skills")
|
|
185
|
+
: undefined;
|
|
186
|
+
const preserved = [];
|
|
152
187
|
for (const skill of FRAMEWORK_TEMPLATE_SHARED_SKILLS) {
|
|
153
188
|
const localPath = path.join(appSkillsDir, skill);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
189
|
+
const stat = fs.lstatSync(localPath, { throwIfNoEntry: false });
|
|
190
|
+
if (!stat || stat.isSymbolicLink())
|
|
191
|
+
continue;
|
|
192
|
+
const workspacePath = workspaceSkillsDir
|
|
193
|
+
? path.join(workspaceSkillsDir, skill)
|
|
194
|
+
: undefined;
|
|
195
|
+
if (!options.allowUnverified &&
|
|
196
|
+
(!workspacePath || !skillDirContentsMatch(workspacePath, localPath))) {
|
|
197
|
+
preserved.push(skill);
|
|
198
|
+
continue;
|
|
157
199
|
}
|
|
200
|
+
fs.rmSync(localPath, { recursive: true, force: true });
|
|
158
201
|
}
|
|
202
|
+
return preserved;
|
|
203
|
+
}
|
|
204
|
+
export function linkDefaultWorkspaceSkills(appDir, workspaceRoot) {
|
|
205
|
+
const appSkillsDir = path.join(appDir, ".agents", "skills");
|
|
206
|
+
const workspaceSkillsDir = path.join(workspaceRoot, ".agents", "skills");
|
|
207
|
+
if (!fs.existsSync(workspaceSkillsDir))
|
|
208
|
+
return [];
|
|
209
|
+
fs.mkdirSync(appSkillsDir, { recursive: true });
|
|
210
|
+
const preserved = [];
|
|
159
211
|
for (const skill of DEFAULT_WORKSPACE_SKILLS) {
|
|
160
212
|
const inheritedPath = path.join(workspaceSkillsDir, skill);
|
|
161
213
|
if (!fs.existsSync(inheritedPath))
|
|
162
214
|
continue;
|
|
163
215
|
const linkPath = path.join(appSkillsDir, skill);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
216
|
+
const existing = fs.lstatSync(linkPath, { throwIfNoEntry: false });
|
|
217
|
+
if (existing &&
|
|
218
|
+
!existing.isSymbolicLink() &&
|
|
219
|
+
!skillDirContentsMatch(inheritedPath, linkPath)) {
|
|
220
|
+
preserved.push(skill);
|
|
221
|
+
continue;
|
|
167
222
|
}
|
|
223
|
+
fs.rmSync(linkPath, { recursive: true, force: true });
|
|
168
224
|
try {
|
|
169
225
|
fs.symlinkSync(path.relative(appSkillsDir, inheritedPath), linkPath, "dir");
|
|
170
226
|
}
|
|
@@ -172,6 +228,7 @@ function linkInheritedWorkspaceSkills(opts) {
|
|
|
172
228
|
throw new Error(`Could not link inherited workspace skill ${skill} into ${appSkillsDir}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
173
229
|
}
|
|
174
230
|
}
|
|
231
|
+
return preserved;
|
|
175
232
|
}
|
|
176
233
|
/**
|
|
177
234
|
* The version an existing workspace already pins for a framework package.
|
|
@@ -29,6 +29,11 @@ export declare function normalizeAgentPanelModeForSurface(mode: PanelMode, allow
|
|
|
29
29
|
export declare function deferAgentPanelOverlayOpen(event: {
|
|
30
30
|
preventDefault: () => void;
|
|
31
31
|
}, closeMenu: () => void, openOverlay: () => void): void;
|
|
32
|
+
export declare function consumeAgentPanelOverlayFocusRestore(pendingOverlayRef: {
|
|
33
|
+
current: boolean;
|
|
34
|
+
}, event: {
|
|
35
|
+
preventDefault: () => void;
|
|
36
|
+
}): void;
|
|
32
37
|
export declare function getAgentPanelChatTabGroups(tabs: MultiTabAssistantChatHeaderProps["tabs"], activeTabId: string): {
|
|
33
38
|
activeTab: import("./MultiTabAssistantChat.js").ChatTab | undefined;
|
|
34
39
|
childTabs: import("./MultiTabAssistantChat.js").ChatTab[];
|
|
@@ -157,6 +157,12 @@ export function deferAgentPanelOverlayOpen(event, closeMenu, openOverlay) {
|
|
|
157
157
|
setTimeout(openOverlay, 0);
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
+
export function consumeAgentPanelOverlayFocusRestore(pendingOverlayRef, event) {
|
|
161
|
+
if (!pendingOverlayRef.current)
|
|
162
|
+
return;
|
|
163
|
+
pendingOverlayRef.current = false;
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
}
|
|
160
166
|
function useAvailableClis() {
|
|
161
167
|
const [clis, setClis] = useState([]);
|
|
162
168
|
useEffect(() => {
|
|
@@ -194,6 +200,7 @@ function IconTooltip({ content, children, }) {
|
|
|
194
200
|
return (_jsx(DesignSystemTooltip, { trigger: children, content: normalizeTooltipText(content), placement: "bottom", delayMs: 250, className: "z-[300] overflow-hidden rounded-md border border-border bg-popover px-2 py-1 text-[11px] text-foreground shadow-md" }));
|
|
195
201
|
}
|
|
196
202
|
function ChatLoadingSkeleton({ renderHeader, centerComposerWhenEmpty = false, composerSlot, composerAreaClassName, composerLayoutVariant = "default", }) {
|
|
203
|
+
const t = useT();
|
|
197
204
|
// Provide empty no-op implementations so renderHeader can render the real
|
|
198
205
|
// tab/mode buttons without needing actual chat state.
|
|
199
206
|
const noop = useCallback(() => { }, []);
|
|
@@ -213,7 +220,7 @@ function ChatLoadingSkeleton({ renderHeader, centerComposerWhenEmpty = false, co
|
|
|
213
220
|
toggleHistory: noop,
|
|
214
221
|
};
|
|
215
222
|
if (centerComposerWhenEmpty) {
|
|
216
|
-
return (_jsxs("div", { className: "flex flex-col flex-1 min-h-0", children: [renderHeader ? renderHeader(stubProps) : null, _jsxs("div", { "data-agent-empty-state": "centered", className: "relative flex flex-1 flex-col h-full min-h-0 text-foreground", children: [_jsx("div", { className: "agent-chat-scroll flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: _jsx("div", { className: "agent-empty-state sr-only", "aria-busy": "true", children: "
|
|
223
|
+
return (_jsxs("div", { className: "flex flex-col flex-1 min-h-0", children: [renderHeader ? renderHeader(stubProps) : null, _jsxs("div", { "data-agent-empty-state": "centered", className: "relative flex flex-1 flex-col h-full min-h-0 text-foreground", children: [_jsx("div", { className: "agent-chat-scroll flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: _jsx("div", { className: "agent-empty-state sr-only", "aria-busy": "true", children: t("agentChat.empty.loadingChat") }) }), composerSlot, _jsx("div", { className: "agent-composer-stack", children: _jsx("div", { className: cn("agent-composer-area shrink-0 px-3 py-2", composerLayoutVariant !== "default" &&
|
|
217
224
|
`agent-composer-area--${composerLayoutVariant}`, composerAreaClassName), children: _jsxs("div", { className: cn("agent-composer-root flex flex-col rounded-lg border border-input bg-muted/45 transition-colors", composerLayoutVariant !== "default" &&
|
|
218
225
|
`agent-composer-root--${composerLayoutVariant}`), children: [_jsx("div", { className: "px-3 pt-3", children: _jsx("div", { className: "h-5 w-3/5 rounded bg-muted animate-pulse motion-reduce:animate-none" }) }), _jsxs("div", { className: "mt-auto flex items-center gap-2 px-3 py-2", children: [_jsx("div", { className: "h-5 w-5 rounded bg-muted animate-pulse motion-reduce:animate-none" }), _jsx("div", { className: "ml-auto h-4 w-28 rounded bg-muted animate-pulse motion-reduce:animate-none" }), _jsx("div", { className: "h-7 w-7 rounded-md bg-muted animate-pulse motion-reduce:animate-none" })] })] }) }) })] })] }));
|
|
219
226
|
}
|
|
@@ -667,6 +674,11 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
667
674
|
const [headerMenuOpen, setHeaderMenuOpen] = useState(false);
|
|
668
675
|
const [feedbackOpen, setFeedbackOpen] = useState(false);
|
|
669
676
|
const [shareFromMenuOpen, setShareFromMenuOpen] = useState(false);
|
|
677
|
+
const preventHeaderMenuFocusRestoreRef = useRef(false);
|
|
678
|
+
const closeHeaderMenuForOverlay = useCallback(() => {
|
|
679
|
+
preventHeaderMenuFocusRestoreRef.current = true;
|
|
680
|
+
setHeaderMenuOpen(false);
|
|
681
|
+
}, []);
|
|
670
682
|
const getChatThreadShareUrl = useCallback((threadId) => {
|
|
671
683
|
if (typeof window === "undefined")
|
|
672
684
|
return undefined;
|
|
@@ -710,9 +722,13 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
710
722
|
(activeTabMessageCount <= 0 && activeTab.status === "idle")) {
|
|
711
723
|
return null;
|
|
712
724
|
}
|
|
713
|
-
return (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, allowedRoles: ["viewer", "editor", "admin"], resourceTitle: activeTab.label || "
|
|
725
|
+
return (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, allowedRoles: ["viewer", "editor", "admin"], resourceTitle: activeTab.label || t("agentPanel.chat"), shareUrl: getChatThreadShareUrl(activeTab.id), trigger: "icon", triggerClassName: "h-7 w-7", defaultOpen: onCollapse && shareFromMenuOpen, onOpenChange: onCollapse ? setShareFromMenuOpen : undefined }));
|
|
714
726
|
})(), feedbackEnabled ? (_jsx(FeedbackButton, { variant: "icon", side: "bottom", align: "end", chatSessionId: activeChatSessionId, chatStorageKey: storageKey, open: feedbackOpen, onOpenChange: setFeedbackOpen, trigger: _jsx("button", { type: "button", tabIndex: -1, "aria-hidden": "true", className: "pointer-events-none absolute end-0 top-full h-px w-px opacity-0" }) })) : null, mode === "chat" && (_jsx(IconTooltip, { content: t("agentPanel.newChat"), children: _jsx("button", { onClick: addTab, "aria-label": t("agentPanel.newChat"), className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconPlus, { size: 14 }) }) })), !onCollapse && mode === "cli" && canUseCodeTools && (_jsx(IconTooltip, { content: t("agentPanel.newTerminal"), children: _jsx("button", { onClick: addCliTab, "aria-label": t("agentPanel.newTerminal"), className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconPlus, { size: 14 }) }) })), _jsxs(DropdownMenu, { open: headerMenuOpen, onOpenChange: setHeaderMenuOpen, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { className: cn("flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", (headerMenuOpen || mode === "settings") &&
|
|
715
|
-
"bg-accent text-foreground"), "aria-label": t("agentPanel.panelOptions"), children: _jsx(IconDotsVertical, { size: 14 }) }) }), _jsxs(DropdownMenuContent, { align: "end", sideOffset: 6, className: "w-48",
|
|
727
|
+
"bg-accent text-foreground"), "aria-label": t("agentPanel.panelOptions"), children: _jsx(IconDotsVertical, { size: 14 }) }) }), _jsxs(DropdownMenuContent, { align: "end", sideOffset: 6, className: "w-48", onCloseAutoFocus: (event) => {
|
|
728
|
+
// A sibling overlay owns focus next; restoring it to the menu
|
|
729
|
+
// trigger would dismiss that overlay as an outside interaction.
|
|
730
|
+
consumeAgentPanelOverlayFocusRestore(preventHeaderMenuFocusRestoreRef, event);
|
|
731
|
+
}, children: [onCollapse && (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuItem, { onSelect: onCollapse, children: [_jsx(IconLayoutSidebarRightCollapse, { size: 14, className: "shrink-0" }), t("agentPanel.collapseSidebar"), _jsx(DropdownMenuShortcut, { children: toggleSidebarHint })] }), _jsx(DropdownMenuSeparator, {})] })), onCollapse && mode === "chat" && wideDrawerAction ? (_jsxs(DropdownMenuItem, { onSelect: wideDrawerAction, children: [_jsx(IconArrowsHorizontal, { size: 14, className: "shrink-0" }), wideDrawerLabel, _jsx(DropdownMenuShortcut, { children: widenChatHint })] })) : null, fullViewAction?.kind === "callback" && onFullViewRequest ? (_jsxs(DropdownMenuItem, { onSelect: onFullViewRequest, "aria-label": t("agentPanel.openFullView"), children: [_jsx(IconArrowsMaximize, { size: 14, className: "shrink-0" }), t("agentPanel.openFullView")] })) : fullViewAction?.kind === "link" ? (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs(Link, { to: fullViewAction.href, "aria-label": t("agentPanel.openFullView"), children: [_jsx(IconArrowsMaximize, { size: 14, className: "shrink-0" }), t("agentPanel.openFullView")] }) })) : null, (onCollapse && mode === "chat" && wideDrawerAction) ||
|
|
716
732
|
fullViewAction ? (_jsx(DropdownMenuSeparator, {})) : null, onCollapse && mode === "chat" && (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuItem, { onSelect: addTab, children: [_jsx(IconPlus, { size: 14, className: "shrink-0" }), t("agentPanel.newChat")] }), (() => {
|
|
717
733
|
const activeTab = activeChatSessionId
|
|
718
734
|
? tabs.find((tab) => tab.id === activeChatSessionId)
|
|
@@ -721,18 +737,19 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
721
737
|
(activeTabMessageCount <= 0 && activeTab.status === "idle")) {
|
|
722
738
|
return null;
|
|
723
739
|
}
|
|
724
|
-
return (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event,
|
|
725
|
-
})()] })), mode === "chat" && toggleHistory && (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event,
|
|
740
|
+
return (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event, closeHeaderMenuForOverlay, () => setShareFromMenuOpen(true)), children: [_jsx(IconShare3, { size: 14, className: "shrink-0" }), "Share"] }));
|
|
741
|
+
})()] })), mode === "chat" && toggleHistory && (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event, closeHeaderMenuForOverlay, toggleHistory), children: [_jsx(IconHistory, { size: 14, className: "shrink-0" }), showHistory
|
|
726
742
|
? t("agentPanel.hideChats")
|
|
727
743
|
: t("agentPanel.allChats")] })), mode === "chat" && (_jsx(RunsTrayMenuItem, { pollMs: 0, limit: 12, showRecent: true, onOpenThread: openRunThread })), mode === "chat" && _jsx(DropdownMenuSeparator, {}), mode === "cli" && availableClis.length > 0 && (_jsxs(_Fragment, { children: [availableClis.map((cli) => (_jsxs(DropdownMenuItem, { onSelect: () => selectCli(cli.command), className: cn(cli.command === selectedCli
|
|
728
744
|
? "font-medium"
|
|
729
|
-
: "text-muted-foreground"), children: [cli.command === selectedCli ? (_jsx(IconCheck, { size: 12, className: "shrink-0" })) : (_jsx("span", { className: "w-3" })), cli.label] }, cli.command))), _jsx(DropdownMenuSeparator, {})] })), allowSettingsMode && (_jsxs(DropdownMenuItem, { onSelect: () => switchMode("settings"), className: cn(mode === "settings" ? "font-medium" : "text-muted-foreground"), children: [_jsx(IconSettings, { size: 14, className: "shrink-0" }), t("agentPanel.settings")] })), feedbackEnabled ? (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event,
|
|
745
|
+
: "text-muted-foreground"), children: [cli.command === selectedCli ? (_jsx(IconCheck, { size: 12, className: "shrink-0" })) : (_jsx("span", { className: "w-3" })), cli.label] }, cli.command))), _jsx(DropdownMenuSeparator, {})] })), allowSettingsMode && (_jsxs(DropdownMenuItem, { onSelect: () => switchMode("settings"), className: cn(mode === "settings" ? "font-medium" : "text-muted-foreground"), children: [_jsx(IconSettings, { size: 14, className: "shrink-0" }), t("agentPanel.settings")] })), feedbackEnabled ? (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event, closeHeaderMenuForOverlay, () => setFeedbackOpen(true)), children: [_jsx(IconMessageDots, { size: 14, className: "shrink-0" }), t("agentPanel.feedback")] })) : null, ((mode === "chat" && activeTabId) ||
|
|
730
746
|
(mode === "cli" && canUseCodeTools && activeCliTab)) && (_jsxs(_Fragment, { children: [_jsx(DropdownMenuSeparator, {}), mode === "chat" ? (shouldShowAgentPanelChatTabBar(tabs, activeTabId) ? (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuItem, { onSelect: () => closeTab(activeTabId), children: [_jsx(IconX, { size: 14, className: "shrink-0" }), t("agentPanel.closeTab"), _jsx(DropdownMenuShortcut, { children: closeTabHint })] }), _jsx(DropdownMenuItem, { onSelect: () => closeOtherTabs(activeTabId), children: t("agentPanel.closeOtherTabs") }), _jsxs(DropdownMenuItem, { onSelect: () => closeAllTabs(), children: [t("agentPanel.closeAllTabs"), _jsx(DropdownMenuShortcut, { children: closeAllTabsHint })] })] })) : (_jsxs(DropdownMenuItem, { onSelect: clearActiveTab, children: [_jsx(IconX, { size: 14, className: "shrink-0" }), t("agentPanel.clearChat")] }))) : (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuItem, { onSelect: () => closeCliTab(activeCliTab), children: [_jsx(IconX, { size: 14, className: "shrink-0" }), t("agentPanel.closeTab"), _jsx(DropdownMenuShortcut, { children: closeTabHint })] }), _jsx(DropdownMenuItem, { onSelect: () => closeOtherCliTabs(activeCliTab), children: t("agentPanel.closeOtherTabs") }), _jsxs(DropdownMenuItem, { onSelect: () => closeAllCliTabs(), children: [t("agentPanel.closeAllTabs"), _jsx(DropdownMenuShortcut, { children: closeAllTabsHint })] })] }))] }))] })] }), onCollapse && (_jsx(IconTooltip, { content: t("agentPanel.collapseSidebar"), children: _jsx("button", { type: "button", onClick: onCollapse, "aria-label": t("agentPanel.collapseSidebar"), className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconX, { size: 14 }) }) }))] })), [
|
|
731
747
|
activeCliTab,
|
|
732
748
|
addCliTab,
|
|
733
749
|
allowSettingsMode,
|
|
734
750
|
availableClis,
|
|
735
751
|
canUseCodeTools,
|
|
752
|
+
closeHeaderMenuForOverlay,
|
|
736
753
|
closeAllCliTabs,
|
|
737
754
|
closeAllTabsHint,
|
|
738
755
|
closeCliTab,
|
|
@@ -769,7 +786,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
769
786
|
? tabs.find((tab) => tab.id === activeTabId)
|
|
770
787
|
: undefined;
|
|
771
788
|
const canShareActiveTab = activeTab && (activeTabMessageCount > 0 || activeTab.status !== "idle");
|
|
772
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": "true", "data-agent-page-chat-fade": "", className: "pointer-events-none absolute inset-x-0 top-0 z-50 h-16 bg-gradient-to-b from-background via-background/90 to-transparent opacity-0 transition-opacity duration-150" }), _jsx("div", { className: "pointer-events-none absolute inset-x-0 top-3 z-[60] flex justify-end px-3 sm:top-4 sm:px-4", children: _jsxs("div", { className: "pointer-events-auto flex items-center gap-1", children: [canShareActiveTab ? (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, allowedRoles: ["viewer", "editor", "admin"], resourceTitle: activeTab.label || "
|
|
789
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": "true", "data-agent-page-chat-fade": "", className: "pointer-events-none absolute inset-x-0 top-0 z-50 h-16 bg-gradient-to-b from-background via-background/90 to-transparent opacity-0 transition-opacity duration-150" }), _jsx("div", { className: "pointer-events-none absolute inset-x-0 top-3 z-[60] flex justify-end px-3 sm:top-4 sm:px-4", children: _jsxs("div", { className: "pointer-events-auto flex items-center gap-1", children: [canShareActiveTab ? (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, allowedRoles: ["viewer", "editor", "admin"], resourceTitle: activeTab.label || t("agentPanel.chat"), shareUrl: getChatThreadShareUrl(activeTab.id), trigger: "icon", triggerClassName: "h-8 w-8 border border-border bg-background/95 shadow-sm backdrop-blur hover:bg-accent" })) : null, _jsxs("button", { type: "button", "data-agent-page-new-chat": "", "aria-label": t("agentPanel.newChat"), onClick: () => {
|
|
773
790
|
addTab();
|
|
774
791
|
}, className: "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", children: [_jsx(IconPlus, { size: 14 }), _jsx("span", { children: t("agentPanel.newChat") })] })] }) })] }));
|
|
775
792
|
}, [getChatThreadShareUrl, t]);
|
|
@@ -813,7 +830,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
813
830
|
activeTab?.parentThreadId === tab.id);
|
|
814
831
|
return (_jsxs("div", { role: "button", tabIndex: 0, ref: isActive ? activeTabRefCb : undefined, onClick: () => setActiveTabId(tab.id), onKeyDown: activateOnKeyDown(() => setActiveTabId(tab.id)), className: cn("agent-tab relative flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1.5 text-[11px] font-medium cursor-pointer max-w-[150px]", isActive
|
|
815
832
|
? "bg-accent text-foreground"
|
|
816
|
-
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": "
|
|
833
|
+
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": t("agentPanel.closeTab"), onClick: (e) => {
|
|
817
834
|
e.stopPropagation();
|
|
818
835
|
closeTab(tab.id);
|
|
819
836
|
}, className: "agent-tab-close flex items-center justify-end text-muted-foreground hover:text-foreground", style: {
|
|
@@ -856,7 +873,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
856
873
|
activeTab?.parentThreadId === tab.id);
|
|
857
874
|
return (_jsxs("div", { role: "button", tabIndex: 0, ref: isActive ? activeTabRefCb : undefined, onClick: () => setActiveTabId(tab.id), onKeyDown: activateOnKeyDown(() => setActiveTabId(tab.id)), className: cn("agent-tab relative flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1.5 text-[11px] font-medium cursor-pointer max-w-[150px]", isActive
|
|
858
875
|
? "bg-accent text-foreground"
|
|
859
|
-
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": "
|
|
876
|
+
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": t("agentPanel.closeTab"), onClick: (e) => {
|
|
860
877
|
e.stopPropagation();
|
|
861
878
|
closeTab(tab.id);
|
|
862
879
|
}, className: "agent-tab-close flex items-center justify-end text-muted-foreground hover:text-foreground", style: {
|
|
@@ -874,7 +891,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
874
891
|
? activeTabRefCb
|
|
875
892
|
: undefined, onClick: () => setActiveCliTab(id), onKeyDown: activateOnKeyDown(() => setActiveCliTab(id)), className: cn("agent-tab relative flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1.5 text-[11px] font-medium cursor-pointer", id === activeCliTab
|
|
876
893
|
? "bg-accent text-foreground"
|
|
877
|
-
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsxs("span", { children: ["Terminal ", i + 1] }), _jsx("button", { type: "button", "aria-label": "
|
|
894
|
+
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsxs("span", { children: ["Terminal ", i + 1] }), _jsx("button", { type: "button", "aria-label": t("agentPanel.closeTab"), onClick: (e) => {
|
|
878
895
|
e.stopPropagation();
|
|
879
896
|
closeCliTab(id);
|
|
880
897
|
}, className: "agent-tab-close flex items-center justify-end text-muted-foreground hover:text-foreground", style: {
|
|
@@ -892,7 +909,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
892
909
|
? activeTabRefCb
|
|
893
910
|
: undefined, onClick: () => setActiveTabId(tab.id), onKeyDown: activateOnKeyDown(() => setActiveTabId(tab.id)), className: cn("agent-tab relative flex shrink-0 items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium cursor-pointer max-w-[140px]", tab.id === activeTabId
|
|
894
911
|
? "bg-accent text-foreground"
|
|
895
|
-
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.subAgentName || tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1 w-1 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": "
|
|
912
|
+
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.subAgentName || tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1 w-1 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": t("agentPanel.closeTab"), onClick: (e) => {
|
|
896
913
|
e.stopPropagation();
|
|
897
914
|
closeTab(tab.id);
|
|
898
915
|
}, className: "agent-tab-close flex items-center justify-end text-muted-foreground hover:text-foreground", style: {
|
|
@@ -921,6 +938,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
921
938
|
activeTabRefCb,
|
|
922
939
|
activateOnKeyDown,
|
|
923
940
|
closeCliTab,
|
|
941
|
+
t,
|
|
924
942
|
]);
|
|
925
943
|
return (_jsxs("div", { className: cn("agent-panel-root flex flex-1 flex-col min-h-0 h-full text-[13px] leading-[1.2] antialiased", className), style: {
|
|
926
944
|
...AGENT_PANEL_ROOT_STYLE,
|
|
@@ -956,7 +974,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
956
974
|
? mode === "cli" &&
|
|
957
975
|
cliTabs.map((id) => (_jsx("div", { className: "min-h-0 relative flex-1", style: {
|
|
958
976
|
display: id === activeCliTab ? undefined : "none",
|
|
959
|
-
}, children: _jsx(Suspense, { fallback: _jsx("div", { className: "flex items-center justify-center h-full text-muted-foreground text-sm", children: "
|
|
977
|
+
}, children: _jsx(Suspense, { fallback: _jsx("div", { className: "flex items-center justify-center h-full text-muted-foreground text-sm", children: t("agentPanel.loadingTerminal") }), children: _jsx(AgentTerminal, { command: selectedCli, hideInFrame: false, className: "h-full", style: { background: "transparent" } }) }) }, id)))
|
|
960
978
|
: mode === "cli" && (_jsx("div", { className: "flex flex-1 flex-col items-center justify-center min-h-0 px-6 gap-3", children: _jsx(CodeAccessUnavailablePanel, { title: codeAccessEnabled
|
|
961
979
|
? t("agentPanel.cliRequiresDevMode")
|
|
962
980
|
: codeUnavailableTitle, description: codeAccessEnabled
|
|
@@ -1941,6 +1959,7 @@ export function focusAgentChat() {
|
|
|
1941
1959
|
* Dispatches a custom event that AgentSidebar listens for.
|
|
1942
1960
|
*/
|
|
1943
1961
|
export function AgentToggleButton({ className }) {
|
|
1962
|
+
const t = useT();
|
|
1944
1963
|
const [open, setOpen] = useState(false);
|
|
1945
1964
|
useEffect(() => {
|
|
1946
1965
|
const handler = (event) => {
|
|
@@ -1956,5 +1975,5 @@ export function AgentToggleButton({ className }) {
|
|
|
1956
1975
|
// own close button.
|
|
1957
1976
|
if (open)
|
|
1958
1977
|
return null;
|
|
1959
|
-
return (_jsx(DesignSystemTooltip, { trigger: _jsx("button", { type: "button", "aria-label": "
|
|
1978
|
+
return (_jsx(DesignSystemTooltip, { trigger: _jsx("button", { type: "button", "aria-label": t("agentPanel.toggleAgent"), onClick: () => window.dispatchEvent(new Event("agent-panel:toggle")), className: cn("inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent/40 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", className), children: _jsx(IconMessageDots, { size: 20, "aria-hidden": true }) }), content: t("agentPanel.toggleAgent"), delayMs: 200 }));
|
|
1960
1979
|
}
|
|
@@ -90,6 +90,27 @@ export declare function settleInterruptedAssistantToolCallsInRepo<T extends {
|
|
|
90
90
|
};
|
|
91
91
|
export declare function waitForThreadRunToClear(apiUrl: string, threadId?: string): Promise<boolean>;
|
|
92
92
|
export declare function reconnectActivityFallbackContent(toolName: string | null | undefined): ContentPart[];
|
|
93
|
+
/**
|
|
94
|
+
* Whether the reconnect overlay — a SECOND fold of a run, rendered as a sibling
|
|
95
|
+
* of the message list — may appear.
|
|
96
|
+
*
|
|
97
|
+
* The adapter runtime and the reconnect reader both fold the same SSE events
|
|
98
|
+
* into their own accumulator. Whenever both are on screen the user sees the
|
|
99
|
+
* turn twice: duplicate tool cards (one spinning, one static) and the final
|
|
100
|
+
* message streaming in two places. Content-similarity dedupe cannot reliably
|
|
101
|
+
* hide the second copy, because the two readers disagree on tool-call identity
|
|
102
|
+
* (id-less activity cards get reader-local ids) and on how a turn is split
|
|
103
|
+
* across assistant messages.
|
|
104
|
+
*
|
|
105
|
+
* So ownership decides visibility, not similarity: if a runtime owns the turn,
|
|
106
|
+
* the overlay does not render. Keep this a pure function — it is the invariant
|
|
107
|
+
* the duplicate-render bug kept violating, and it must stay falsifiable.
|
|
108
|
+
*/
|
|
109
|
+
export declare function shouldShowReconnectOverlay(state: {
|
|
110
|
+
isRuntimeRunning: boolean;
|
|
111
|
+
isReconnecting: boolean;
|
|
112
|
+
reconnectFrozen: boolean;
|
|
113
|
+
}): boolean;
|
|
93
114
|
export declare function dedupeReconnectContentAgainstMessages(content: ContentPart[], messages: readonly unknown[], options?: {
|
|
94
115
|
suppressToolRepeats?: boolean;
|
|
95
116
|
trimTailTextOverlap?: boolean;
|
|
@@ -111,11 +132,22 @@ export declare function resolveAssistantChatRunningState({ forceStopped, isRunti
|
|
|
111
132
|
isRunning: boolean;
|
|
112
133
|
showRunningInUI: boolean;
|
|
113
134
|
};
|
|
114
|
-
export declare function resolveAssistantChatRunningStatusLabel({ runningActivityLabel, isAutoResuming, isReconnecting, hasReconnectContent, }: {
|
|
135
|
+
export declare function resolveAssistantChatRunningStatusLabel({ runningActivityLabel, isAutoResuming, isReconnecting, hasReconnectContent, labels, }: {
|
|
115
136
|
runningActivityLabel: string | null | undefined;
|
|
116
137
|
isAutoResuming: boolean;
|
|
117
138
|
isReconnecting: boolean;
|
|
118
139
|
hasReconnectContent: boolean;
|
|
140
|
+
labels?: {
|
|
141
|
+
thinking: string;
|
|
142
|
+
resuming: string;
|
|
143
|
+
stillWorking: string;
|
|
144
|
+
working?: string;
|
|
145
|
+
contactingModel?: string;
|
|
146
|
+
starting?: (activity: string) => string;
|
|
147
|
+
preparing?: (activity: string) => string;
|
|
148
|
+
writing?: (activity: string) => string;
|
|
149
|
+
stillGenerating?: (activity: string) => string;
|
|
150
|
+
};
|
|
119
151
|
}): string;
|
|
120
152
|
export declare function resolveAssistantChatComposerPlaceholder(composerPlaceholder: string | null | undefined): string;
|
|
121
153
|
export declare function shouldShowGlobalRunningStatus({ showRunningInUI, runningActivityLabel, runningActivityTool, latestMessage, reconnectContent, }: {
|
|
@@ -290,6 +322,8 @@ export interface AssistantChatProps {
|
|
|
290
322
|
composerToolbarSlot?: React.ReactNode;
|
|
291
323
|
/** Optional action rendered beside the voice/send controls. */
|
|
292
324
|
composerExtraActionButton?: React.ReactNode;
|
|
325
|
+
/** Show the framework model picker in the shared composer. Defaults to true. */
|
|
326
|
+
showModelSelector?: boolean;
|
|
293
327
|
/** Disable the composer for capability-gated surfaces while still showing history. */
|
|
294
328
|
composerDisabled?: boolean;
|
|
295
329
|
/** Placeholder to show while the composer is disabled by the host surface. */
|
|
@@ -389,6 +423,7 @@ export interface AssistantChatProps {
|
|
|
389
423
|
onAlwaysAllow?: (approvalKey: string) => void;
|
|
390
424
|
};
|
|
391
425
|
}
|
|
426
|
+
export declare function shouldShowAssistantChatModelSelector(showModelSelector: boolean | undefined): boolean;
|
|
392
427
|
export declare const CHAT_STORAGE_PREFIX = "agent-chat:";
|
|
393
428
|
/** Remove persisted chat for a given tabId (or "default"). */
|
|
394
429
|
export declare function clearChatStorage(tabId?: string): void;
|