@agent-native/core 0.154.4 → 0.155.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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/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 +14 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +8 -4
- 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/.agents/skills/content/SKILL.md +2 -2
- package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +20 -4
- package/corpus/templates/content/actions/_database-row-mutation.ts +1490 -0
- package/corpus/templates/content/actions/_database-utils.ts +44 -0
- package/corpus/templates/content/actions/_property-utils.ts +4 -1
- package/corpus/templates/content/actions/add-comment.ts +2 -1
- package/corpus/templates/content/actions/add-database-item.ts +62 -240
- package/corpus/templates/content/actions/configure-document-property.ts +165 -1
- package/corpus/templates/content/actions/delete-document-property.ts +18 -0
- package/corpus/templates/content/actions/set-document-property.ts +78 -1
- package/corpus/templates/content/actions/update-comment.ts +1 -1
- package/corpus/templates/content/actions/update-database-item.ts +62 -0
- package/corpus/templates/content/actions/upsert-database-item-by-key.ts +43 -796
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +24 -15
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +10 -8
- package/corpus/templates/content/app/hooks/use-content-database.ts +33 -32
- package/corpus/templates/content/changelog/2026-08-10-database-row-actions-now-validate-exact-schemas-and-safe-ret.md +6 -0
- package/corpus/templates/content/parity/matrix.md +1 -1
- package/corpus/templates/content/parity/matrix.ts +2 -0
- package/corpus/templates/content/server/db/schema.ts +39 -3
- package/corpus/templates/content/server/plugins/db.ts +30 -0
- package/corpus/templates/content/shared/api.ts +75 -2
- 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/dist/action.d.ts +22 -0
- package/dist/action.js +27 -0
- package/dist/agent/production-agent.js +5 -1
- package/dist/agent/thread-data-builder.js +17 -1
- 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 +20 -4
- package/dist/client/AssistantChat.d.ts +21 -0
- package/dist/client/AssistantChat.js +66 -68
- 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/tool-call-display.js +4 -4
- 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/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/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/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.browser.d.ts +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/integrations/adapters/slack.js +5 -1
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.js +1 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +1 -1
- 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/handlers.d.ts +1 -1
- 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/server/action-routes.js +42 -8
- package/dist/server/agent-discovery.js +14 -3
- 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/realtime-token.d.ts +1 -1
- package/dist/server/release-migrations.js +4 -0
- package/dist/tracking/providers.js +13 -3
- package/dist/workspace-files/tool.js +1 -1
- package/package.json +3 -2
|
@@ -12,6 +12,10 @@ import { emailToColor, emailToName } from "@agent-native/core/client/collab";
|
|
|
12
12
|
import { PromptComposer } from "@agent-native/core/client/composer";
|
|
13
13
|
import { useActionQuery, useSession } from "@agent-native/core/client/hooks";
|
|
14
14
|
import { useT } from "@agent-native/core/client/i18n";
|
|
15
|
+
import {
|
|
16
|
+
InlineMarkdown,
|
|
17
|
+
type InlineMarkdownProtectedSpan,
|
|
18
|
+
} from "@agent-native/core/client/markdown";
|
|
15
19
|
import {
|
|
16
20
|
useAcceptInvitation,
|
|
17
21
|
useJoinByDomain,
|
|
@@ -976,30 +980,35 @@ function safeDecodeURIComponent(value: string): string {
|
|
|
976
980
|
}
|
|
977
981
|
|
|
978
982
|
function renderCommentMessage(message: string) {
|
|
979
|
-
const
|
|
980
|
-
let lastIndex = 0;
|
|
983
|
+
const protectedSpans: InlineMarkdownProtectedSpan[] = [];
|
|
981
984
|
const pattern = /@\[([^\]]+)\]\(mailto:([^)]+)\)/g;
|
|
982
985
|
let match: RegExpExecArray | null;
|
|
983
986
|
while ((match = pattern.exec(message)) !== null) {
|
|
984
|
-
if (match.index > lastIndex) {
|
|
985
|
-
parts.push(message.slice(lastIndex, match.index));
|
|
986
|
-
}
|
|
987
987
|
const label = match[1] ?? "";
|
|
988
988
|
const email = safeDecodeURIComponent(match[2] ?? "");
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
>
|
|
995
|
-
<IconAt className="size-3" />
|
|
996
|
-
<span className="truncate">{label || email}</span>
|
|
997
|
-
</span>,
|
|
998
|
-
);
|
|
999
|
-
lastIndex = pattern.lastIndex;
|
|
989
|
+
protectedSpans.push({
|
|
990
|
+
source: match[0],
|
|
991
|
+
label: label || email,
|
|
992
|
+
title: email,
|
|
993
|
+
});
|
|
1000
994
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
995
|
+
return (
|
|
996
|
+
<InlineMarkdown
|
|
997
|
+
content={message}
|
|
998
|
+
inline
|
|
999
|
+
protectedSpans={protectedSpans}
|
|
1000
|
+
renderProtectedSpan={(span, children) => (
|
|
1001
|
+
<span
|
|
1002
|
+
key={span.source}
|
|
1003
|
+
className="mx-0.5 inline-flex max-w-[14rem] translate-y-[2px] items-center gap-1 rounded-full border border-primary/20 bg-primary/10 px-1.5 py-0.5 text-xs font-medium text-primary"
|
|
1004
|
+
title={span.title}
|
|
1005
|
+
>
|
|
1006
|
+
<IconAt className="size-3" />
|
|
1007
|
+
<span className="truncate">{children}</span>
|
|
1008
|
+
</span>
|
|
1009
|
+
)}
|
|
1010
|
+
/>
|
|
1011
|
+
);
|
|
1003
1012
|
}
|
|
1004
1013
|
|
|
1005
1014
|
function CommentAvatar({
|
|
@@ -9066,9 +9075,9 @@ function CommentThreadMessage({
|
|
|
9066
9075
|
</p>
|
|
9067
9076
|
)}
|
|
9068
9077
|
</div>
|
|
9069
|
-
<
|
|
9078
|
+
<div className="mt-1 text-sm leading-6">
|
|
9070
9079
|
{renderCommentMessage(comment.message)}
|
|
9071
|
-
</
|
|
9080
|
+
</div>
|
|
9072
9081
|
</div>
|
|
9073
9082
|
{action}
|
|
9074
9083
|
</div>
|
|
@@ -17,7 +17,7 @@ function displayNameFromEmail(email: string): string {
|
|
|
17
17
|
|
|
18
18
|
export default defineAction({
|
|
19
19
|
description:
|
|
20
|
-
"Add a comment to a slide. Omit threadId to start a new thread; provide threadId to reply.",
|
|
20
|
+
"Add a comment to a slide. Inline Markdown supports emphasis, inline code, links, and line breaks; headings are flattened. Omit threadId to start a new thread; provide threadId to reply.",
|
|
21
21
|
schema: z.object({
|
|
22
22
|
deckId: z.string().describe("Deck ID"),
|
|
23
23
|
slideId: z.string().describe("Slide ID"),
|
|
@@ -8,7 +8,7 @@ import { getDb, schema } from "../server/db/index.js";
|
|
|
8
8
|
|
|
9
9
|
export default defineAction({
|
|
10
10
|
description:
|
|
11
|
-
"Update a slide comment. Resolving or reopening a comment applies to the full thread.",
|
|
11
|
+
"Update a slide comment. Comment text supports inline Markdown without headings. Resolving or reopening a comment applies to the full thread.",
|
|
12
12
|
schema: z.object({
|
|
13
13
|
id: z.string().describe("Comment ID"),
|
|
14
14
|
deckId: z.string().optional().describe("Deck ID"),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import { InlineMarkdown } from "@agent-native/core/client/markdown";
|
|
2
3
|
import {
|
|
3
4
|
IconX,
|
|
4
5
|
IconCheck,
|
|
@@ -99,9 +100,10 @@ function CommentItem({
|
|
|
99
100
|
)}
|
|
100
101
|
</div>
|
|
101
102
|
</div>
|
|
102
|
-
<
|
|
103
|
-
{comment.content}
|
|
104
|
-
|
|
103
|
+
<InlineMarkdown
|
|
104
|
+
content={comment.content}
|
|
105
|
+
className="mt-0.5 text-[12px] text-foreground/90 leading-relaxed"
|
|
106
|
+
/>
|
|
105
107
|
</div>
|
|
106
108
|
</div>
|
|
107
109
|
);
|
|
@@ -374,9 +376,10 @@ function ThreadCard({
|
|
|
374
376
|
)}
|
|
375
377
|
</div>
|
|
376
378
|
</div>
|
|
377
|
-
<
|
|
378
|
-
{rootComment.content}
|
|
379
|
-
|
|
379
|
+
<InlineMarkdown
|
|
380
|
+
content={rootComment.content}
|
|
381
|
+
className="mt-0.5 text-[12px] text-foreground/90 leading-relaxed"
|
|
382
|
+
/>
|
|
380
383
|
</div>
|
|
381
384
|
</div>
|
|
382
385
|
|
package/dist/action.d.ts
CHANGED
|
@@ -135,6 +135,28 @@ export interface AgentActionStopOptions {
|
|
|
135
135
|
/** Optional short tool-result text. Defaults to the user-facing message. */
|
|
136
136
|
toolResult?: string;
|
|
137
137
|
}
|
|
138
|
+
export interface ActionContractErrorOptions {
|
|
139
|
+
/** Stable machine-readable code safe to expose on every action transport. */
|
|
140
|
+
errorCode: string;
|
|
141
|
+
/** Safe structured context for callers. Never include secrets or raw driver errors. */
|
|
142
|
+
details?: Record<string, unknown>;
|
|
143
|
+
/** HTTP status for the action route. Contract conflicts normally use 409. */
|
|
144
|
+
statusCode?: number;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* A deterministic, caller-correctable action contract failure.
|
|
148
|
+
*
|
|
149
|
+
* Unlike an ordinary Error, its code and explicitly safe details survive the
|
|
150
|
+
* framework HTTP transport. Internal failures remain generic 500 responses.
|
|
151
|
+
*/
|
|
152
|
+
export declare class ActionContractError extends Error {
|
|
153
|
+
readonly actionContractError = true;
|
|
154
|
+
readonly errorCode: string;
|
|
155
|
+
readonly details?: Record<string, unknown>;
|
|
156
|
+
readonly statusCode: number;
|
|
157
|
+
constructor(message: string, options: ActionContractErrorOptions);
|
|
158
|
+
}
|
|
159
|
+
export declare function isActionContractError(error: unknown): error is ActionContractError;
|
|
138
160
|
/**
|
|
139
161
|
* Throw from an action when the agent should stop the current turn instead of
|
|
140
162
|
* feeding the failure back to the model for another retry.
|
package/dist/action.js
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
import { normalizeActionChatUIConfig, } from "./action-ui.js";
|
|
2
2
|
import { normalizeAuditConfig, resolveAuditAttach } from "./audit/config.js";
|
|
3
|
+
/**
|
|
4
|
+
* A deterministic, caller-correctable action contract failure.
|
|
5
|
+
*
|
|
6
|
+
* Unlike an ordinary Error, its code and explicitly safe details survive the
|
|
7
|
+
* framework HTTP transport. Internal failures remain generic 500 responses.
|
|
8
|
+
*/
|
|
9
|
+
export class ActionContractError extends Error {
|
|
10
|
+
actionContractError = true;
|
|
11
|
+
errorCode;
|
|
12
|
+
details;
|
|
13
|
+
statusCode;
|
|
14
|
+
constructor(message, options) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "ActionContractError";
|
|
17
|
+
this.errorCode = options.errorCode;
|
|
18
|
+
this.details = options.details;
|
|
19
|
+
this.statusCode = options.statusCode ?? 409;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function isActionContractError(error) {
|
|
23
|
+
return (error instanceof ActionContractError ||
|
|
24
|
+
(!!error &&
|
|
25
|
+
typeof error === "object" &&
|
|
26
|
+
error.actionContractError ===
|
|
27
|
+
true &&
|
|
28
|
+
typeof error.errorCode === "string"));
|
|
29
|
+
}
|
|
3
30
|
/**
|
|
4
31
|
* Throw from an action when the agent should stop the current turn instead of
|
|
5
32
|
* feeding the failure back to the model for another retry.
|
|
@@ -7376,7 +7376,11 @@ export function createProductionAgentHandler(options) {
|
|
|
7376
7376
|
}
|
|
7377
7377
|
const profilePrompt = `${requestSystemPrompt}\n\n<custom-agent-profile name="${profile.name}" path="${profile.path}">\n` +
|
|
7378
7378
|
(profile.description ? `${profile.description}\n\n` : "") +
|
|
7379
|
-
`${profile.instructions}
|
|
7379
|
+
`${profile.instructions}` +
|
|
7380
|
+
(profile.workspace?.resources.length
|
|
7381
|
+
? `\n\nAgent pack resources (read these with the resources tools when relevant):\n${profile.workspace.resources.map((resource) => `- ${resource.path}${resource.name ? ` (${resource.name})` : ""}`).join("\n")}`
|
|
7382
|
+
: "") +
|
|
7383
|
+
`\n</custom-agent-profile>`;
|
|
7380
7384
|
let responseText = "";
|
|
7381
7385
|
const subUsage = await runAgentLoop({
|
|
7382
7386
|
engine,
|
|
@@ -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({
|
|
@@ -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(() => {
|
|
@@ -667,6 +673,11 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
667
673
|
const [headerMenuOpen, setHeaderMenuOpen] = useState(false);
|
|
668
674
|
const [feedbackOpen, setFeedbackOpen] = useState(false);
|
|
669
675
|
const [shareFromMenuOpen, setShareFromMenuOpen] = useState(false);
|
|
676
|
+
const preventHeaderMenuFocusRestoreRef = useRef(false);
|
|
677
|
+
const closeHeaderMenuForOverlay = useCallback(() => {
|
|
678
|
+
preventHeaderMenuFocusRestoreRef.current = true;
|
|
679
|
+
setHeaderMenuOpen(false);
|
|
680
|
+
}, []);
|
|
670
681
|
const getChatThreadShareUrl = useCallback((threadId) => {
|
|
671
682
|
if (typeof window === "undefined")
|
|
672
683
|
return undefined;
|
|
@@ -712,7 +723,11 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
712
723
|
}
|
|
713
724
|
return (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, allowedRoles: ["viewer", "editor", "admin"], resourceTitle: activeTab.label || "Chat", shareUrl: getChatThreadShareUrl(activeTab.id), trigger: "icon", triggerClassName: "h-7 w-7", defaultOpen: onCollapse && shareFromMenuOpen, onOpenChange: onCollapse ? setShareFromMenuOpen : undefined }));
|
|
714
725
|
})(), 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",
|
|
726
|
+
"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) => {
|
|
727
|
+
// A sibling overlay owns focus next; restoring it to the menu
|
|
728
|
+
// trigger would dismiss that overlay as an outside interaction.
|
|
729
|
+
consumeAgentPanelOverlayFocusRestore(preventHeaderMenuFocusRestoreRef, event);
|
|
730
|
+
}, 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
731
|
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
732
|
const activeTab = activeChatSessionId
|
|
718
733
|
? tabs.find((tab) => tab.id === activeChatSessionId)
|
|
@@ -721,18 +736,19 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
721
736
|
(activeTabMessageCount <= 0 && activeTab.status === "idle")) {
|
|
722
737
|
return null;
|
|
723
738
|
}
|
|
724
|
-
return (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event,
|
|
725
|
-
})()] })), mode === "chat" && toggleHistory && (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event,
|
|
739
|
+
return (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event, closeHeaderMenuForOverlay, () => setShareFromMenuOpen(true)), children: [_jsx(IconShare3, { size: 14, className: "shrink-0" }), "Share"] }));
|
|
740
|
+
})()] })), mode === "chat" && toggleHistory && (_jsxs(DropdownMenuItem, { onSelect: (event) => deferAgentPanelOverlayOpen(event, closeHeaderMenuForOverlay, toggleHistory), children: [_jsx(IconHistory, { size: 14, className: "shrink-0" }), showHistory
|
|
726
741
|
? t("agentPanel.hideChats")
|
|
727
742
|
: 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
743
|
? "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,
|
|
744
|
+
: "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
745
|
(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
746
|
activeCliTab,
|
|
732
747
|
addCliTab,
|
|
733
748
|
allowSettingsMode,
|
|
734
749
|
availableClis,
|
|
735
750
|
canUseCodeTools,
|
|
751
|
+
closeHeaderMenuForOverlay,
|
|
736
752
|
closeAllCliTabs,
|
|
737
753
|
closeAllTabsHint,
|
|
738
754
|
closeCliTab,
|
|
@@ -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;
|